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