]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
TriggerOnMeleeHit and more (#39826)
authorāda <ss.adasts@gmail.com>
Sun, 31 Aug 2025 18:54:15 +0000 (13:54 -0500)
committerGitHub <noreply@github.com>
Sun, 31 Aug 2025 18:54:15 +0000 (11:54 -0700)
Co-authored-by: iaada <iaada@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeHitComponent.cs [new file with mode: 0644]
Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeMissComponent.cs [new file with mode: 0644]
Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeSwingComponent.cs [new file with mode: 0644]
Content.Shared/Trigger/Systems/MeleeTriggerSystem.cs [new file with mode: 0644]

diff --git a/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeHitComponent.cs b/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeHitComponent.cs
new file mode 100644 (file)
index 0000000..4277941
--- /dev/null
@@ -0,0 +1,25 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when this entity is swung as a melee weapon and hits at least one target.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnMeleeHitComponent : BaseTriggerOnXComponent
+{
+    /// <summary>
+    /// If true, this trigger will activate individually for each entity hit.
+    /// If false, this trigger will always activate only once.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public bool TriggerEveryHit;
+
+    /// <summary>
+    /// If true, the "user" of the trigger is the entity hit by the melee.
+    /// If false, user is the entity which attacked with the melee weapon.
+    /// </summary>
+    /// <remarks>If TriggerEveryHit is false, the user is randomly chosen from hit entities.</remarks>
+    [DataField, AutoNetworkedField]
+    public bool TargetIsUser;
+}
diff --git a/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeMissComponent.cs b/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeMissComponent.cs
new file mode 100644 (file)
index 0000000..ea175fa
--- /dev/null
@@ -0,0 +1,10 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when this entity is swung as a melee weapon and hits nothing.
+/// The user is the entity swinging the weapon.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnMeleeMissComponent : BaseTriggerOnXComponent;
diff --git a/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeSwingComponent.cs b/Content.Shared/Trigger/Components/Triggers/TriggerOnMeleeSwingComponent.cs
new file mode 100644 (file)
index 0000000..b035c20
--- /dev/null
@@ -0,0 +1,18 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Triggers;
+
+/// <summary>
+/// Triggers when this entity is swung as a melee weapon, regardless of whether it hits something.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class TriggerOnMeleeSwingComponent : BaseTriggerOnXComponent
+{
+    /// <summary>
+    /// If true, the "user" of the trigger is the entity hit by the melee. User is null if nothing is hit.
+    /// If false, user is the entity which attacked with the melee weapon.
+    /// </summary>
+    /// <remarks>If true and multiple targets are hit, the user is randomly chosen from hit entities.</remarks>
+    [DataField, AutoNetworkedField]
+    public bool TargetIsUser;
+}
diff --git a/Content.Shared/Trigger/Systems/MeleeTriggerSystem.cs b/Content.Shared/Trigger/Systems/MeleeTriggerSystem.cs
new file mode 100644 (file)
index 0000000..b7433a2
--- /dev/null
@@ -0,0 +1,58 @@
+using Content.Shared.Trigger.Components.Triggers;
+using Content.Shared.Weapons.Melee.Events;
+
+namespace Content.Shared.Trigger.Systems;
+
+/// <summary>
+/// Trigger system for melee related triggers.
+/// </summary>
+public sealed class MeleeTriggerSystem : EntitySystem
+{
+    [Dependency] private readonly TriggerSystem _trigger = default!;
+
+    /// <inheritdoc/>
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<TriggerOnMeleeMissComponent, MeleeHitEvent>(OnMissTrigger);
+        SubscribeLocalEvent<TriggerOnMeleeSwingComponent, MeleeHitEvent>(OnSwingTrigger);
+        SubscribeLocalEvent<TriggerOnMeleeHitComponent, MeleeHitEvent>(OnHitTrigger);
+    }
+
+    private void OnMissTrigger(Entity<TriggerOnMeleeMissComponent> ent, ref MeleeHitEvent args)
+    {
+        if (args.HitEntities.Count == 0)
+            _trigger.Trigger(ent.Owner, args.User, ent.Comp.KeyOut);
+    }
+
+    private void OnSwingTrigger(Entity<TriggerOnMeleeSwingComponent> ent, ref MeleeHitEvent args)
+    {
+        EntityUid? target;
+        if  (args.HitEntities.Count == 0)
+            target = ent.Comp.TargetIsUser ? null : args.User;
+        else
+            target = ent.Comp.TargetIsUser ? args.HitEntities[0] : args.User;
+
+        _trigger.Trigger(ent.Owner, target, ent.Comp.KeyOut);
+    }
+
+    private void OnHitTrigger(Entity<TriggerOnMeleeHitComponent> ent, ref MeleeHitEvent args)
+    {
+        if (args.HitEntities.Count == 0)
+            return;
+
+        if (!ent.Comp.TriggerEveryHit)
+        {
+            var target = ent.Comp.TargetIsUser ? args.HitEntities[0] : args.User;
+            _trigger.Trigger(ent.Owner, target, ent.Comp.KeyOut);
+            return;
+        }
+
+        // if TriggerEveryHit
+        foreach (var target in args.HitEntities)
+        {
+            _trigger.Trigger(ent.Owner, ent.Comp.TargetIsUser ? target : args.User, ent.Comp.KeyOut);
+        }
+    }
+}