diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs b/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs index 7d611c63dac..5858c9f2114 100644 --- a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs +++ b/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.Actions; +using Content.Shared.DoAfter; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -14,5 +14,17 @@ namespace Content.Shared.Abilities.Psionics [DataField("massSleepActionEntity")] public EntityUid? MassSleepActionEntity; + + [DataField] + public DoAfterId? DoAfter; + + [DataField] + public TimeSpan UseDelay = TimeSpan.FromSeconds(4); + + [DataField] + public float Duration = 5f; + + [DataField] + public float WarningRadius = 6f; } } diff --git a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs b/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs index e8ad6bed299..952e0969588 100644 --- a/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs +++ b/Content.Shared/Nyanotrasen/Abilities/Psionics/Abilities/MassSleep/MassSleepPowerSystem.cs @@ -1,21 +1,24 @@ using Content.Shared.Actions; +using Content.Shared.DoAfter; using Content.Shared.Bed.Sleep; -using Content.Shared.Magic.Events; using Content.Shared.Damage; using Content.Shared.Mobs.Components; using Robust.Shared.Prototypes; -using Robust.Shared.Timing; -using Content.Shared.Mind; using Content.Shared.Actions.Events; +using Content.Shared.Popups; +using Content.Shared.Psionics.Events; using Content.Shared.StatusEffect; +using Content.Shared.Stunnable; namespace Content.Shared.Abilities.Psionics { public sealed class MassSleepPowerSystem : EntitySystem { public ProtoId StatusEffectKey = "ForcedSleep"; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!; [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; @@ -25,36 +28,73 @@ namespace Content.Shared.Abilities.Psionics SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnMassSleepDoAfter); } - private void OnInit(EntityUid uid, MassSleepPowerComponent component, ComponentInit args) + private void OnInit(Entity ent, ref ComponentInit args) { - _actions.AddAction(uid, ref component.MassSleepActionEntity, component.MassSleepActionId ); - _actions.TryGetActionData( component.MassSleepActionEntity, out var actionData ); + _actions.AddAction(ent, ref ent.Comp.MassSleepActionEntity, ent.Comp.MassSleepActionId ); + _actions.TryGetActionData( ent.Comp.MassSleepActionEntity, out var actionData ); if (actionData is { UseDelay: not null }) - _actions.StartUseDelay(component.MassSleepActionEntity); - if (TryComp(uid, out var psionic) && psionic.PsionicAbility == null) - psionic.PsionicAbility = component.MassSleepActionEntity; + _actions.StartUseDelay(ent.Comp.MassSleepActionEntity); + if (TryComp(ent, out var psionic) && psionic.PsionicAbility == null) + psionic.PsionicAbility = ent.Comp.MassSleepActionEntity; } - private void OnShutdown(EntityUid uid, MassSleepPowerComponent component, ComponentShutdown args) + private void OnShutdown(Entity ent, ref ComponentShutdown args) { - _actions.RemoveAction(uid, component.MassSleepActionEntity); + _actions.RemoveAction(ent, ent.Comp.MassSleepActionEntity); } - private void OnPowerUsed(EntityUid uid, MassSleepPowerComponent component, MassSleepPowerActionEvent args) + private void OnPowerUsed(Entity ent, ref MassSleepPowerActionEvent args) { - var duration = 5; // Duration of the mass sleep - foreach (var entity in _lookup.GetEntitiesInRange(args.Target, component.Radius)) + var ev = new MassSleepDoAfterEvent(); + var doAfterArgs = new DoAfterArgs(EntityManager, ent, ent.Comp.UseDelay, ev, ent) { - if (HasComp(entity) && entity != uid && !HasComp(entity)) + BreakOnDamage = true + }; + + foreach (var entity in _lookup.GetEntitiesInRange(args.Performer, ent.Comp.WarningRadius)) + { + if (HasComp(entity) && entity != (EntityUid)ent && !HasComp(entity)) { - if (TryComp(entity, out var damageable) && damageable.DamageContainerID == "Biological") - _statusEffects.TryAddStatusEffect(entity, StatusEffectKey, TimeSpan.FromSeconds(duration), false); + _popup.PopupEntity(Loc.GetString("psionic-power-mass-sleep-warning"), + entity, + entity, + PopupType.LargeCaution); } } - _psionics.LogPowerUsed(uid, "mass sleep"); + + _statusEffects.TryAddStatusEffect(ent, "SlowedDown", ent.Comp.UseDelay, true); + + _doAfter.TryStartDoAfter(doAfterArgs, out var doAfterId); + ent.Comp.DoAfter = doAfterId; + + _psionics.LogPowerUsed(ent, "mass sleep"); args.Handled = true; } + + private void OnMassSleepDoAfter(Entity ent, ref MassSleepDoAfterEvent args) + { + if (args.Handled) + return; + + if (args.Cancelled) + { + _statusEffects.TryRemoveStatusEffect(ent, "SlowedDown"); + return; + } + + foreach (var entity in _lookup.GetEntitiesInRange(args.User, ent.Comp.Radius)) + { + if (HasComp(entity) && entity != (EntityUid)ent && !HasComp(entity)) + { + if (TryComp(entity, out var damageable) && damageable.DamageContainerID == "Biological") + _statusEffects.TryAddStatusEffect(entity, StatusEffectKey, TimeSpan.FromSeconds(ent.Comp.Duration), false); + } + } + + ent.Comp.DoAfter = null; + } } } diff --git a/Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs b/Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs index 6666ee48d6c..5d775c2cc37 100644 --- a/Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs +++ b/Content.Shared/Nyanotrasen/Actions/Events/MassSleepPowerActionEvent.cs @@ -1,2 +1,2 @@ namespace Content.Shared.Actions.Events; -public sealed partial class MassSleepPowerActionEvent : WorldTargetActionEvent {} +public sealed partial class MassSleepPowerActionEvent : InstantActionEvent {} diff --git a/Content.Shared/_DV/Psionics/Events.cs b/Content.Shared/_DV/Psionics/Events.cs index 1e1bcb1833a..8ff9db2053c 100644 --- a/Content.Shared/_DV/Psionics/Events.cs +++ b/Content.Shared/_DV/Psionics/Events.cs @@ -9,5 +9,8 @@ public sealed partial class PrecognitionDoAfterEvent : SimpleDoAfterEvent; [Serializable, NetSerializable] public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent; +[Serializable, NetSerializable] +public sealed partial class MassSleepDoAfterEvent : SimpleDoAfterEvent; + [Serializable, NetSerializable] public sealed partial class PsionicEruptionDoAfterEvent : SimpleDoAfterEvent; diff --git a/Resources/Locale/en-US/_DV/abilities/psionic.ftl b/Resources/Locale/en-US/_DV/abilities/psionic.ftl index d9215e7e496..b96e7567c2f 100644 --- a/Resources/Locale/en-US/_DV/abilities/psionic.ftl +++ b/Resources/Locale/en-US/_DV/abilities/psionic.ftl @@ -1,5 +1,7 @@ psionic-nosebleed-message = Your nose starts gushing blood! +psionic-power-mass-sleep-warning = Your eyelids begin to droop... + psionic-power-precognition-failure-by-damage = Your concentration was broken! You fail to decipher anything of use. psionic-power-precognition-no-event-result-message = You see a vision of an undisturbed lake. diff --git a/Resources/Prototypes/_DV/Actions/psionic.yml b/Resources/Prototypes/_DV/Actions/psionic.yml index d4c9379844e..a70c3c476c7 100644 --- a/Resources/Prototypes/_DV/Actions/psionic.yml +++ b/Resources/Prototypes/_DV/Actions/psionic.yml @@ -20,14 +20,11 @@ name: Mass Sleep description: Put targets in a small area to sleep. components: - - type: WorldTargetAction + - type: InstantAction icon: sprite: _DV/Interface/Actions/actions_psionics.rsi state: mass_sleep useDelay: 60 - checkCanAccess: false - checkCanInteract: false - range: 8 itemIconStyle: BigAction event: !type:MassSleepPowerActionEvent