Mass Sleep rework (#4067)

* oughhh

* guuuuuh

* cleanup ops

* changeops

* changeops

* real and true
This commit is contained in:
KOTOB
2025-08-01 21:40:23 +01:00
committed by GitHub
parent 17d29b69b9
commit de2ff74b89
6 changed files with 78 additions and 24 deletions
@@ -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;
}
}
@@ -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<StatusEffectPrototype> 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<MassSleepPowerComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<MassSleepPowerComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<MassSleepPowerComponent, MassSleepPowerActionEvent>(OnPowerUsed);
SubscribeLocalEvent<MassSleepPowerComponent, MassSleepDoAfterEvent>(OnMassSleepDoAfter);
}
private void OnInit(EntityUid uid, MassSleepPowerComponent component, ComponentInit args)
private void OnInit(Entity<MassSleepPowerComponent> 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<PsionicComponent>(uid, out var psionic) && psionic.PsionicAbility == null)
psionic.PsionicAbility = component.MassSleepActionEntity;
_actions.StartUseDelay(ent.Comp.MassSleepActionEntity);
if (TryComp<PsionicComponent>(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<MassSleepPowerComponent> 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<MassSleepPowerComponent> 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<MobStateComponent>(entity) && entity != uid && !HasComp<PsionicInsulationComponent>(entity))
BreakOnDamage = true
};
foreach (var entity in _lookup.GetEntitiesInRange(args.Performer, ent.Comp.WarningRadius))
{
if (HasComp<MobStateComponent>(entity) && entity != (EntityUid)ent && !HasComp<PsionicInsulationComponent>(entity))
{
if (TryComp<DamageableComponent>(entity, out var damageable) && damageable.DamageContainerID == "Biological")
_statusEffects.TryAddStatusEffect<ForcedSleepingComponent>(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<SlowedDownComponent>(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<MassSleepPowerComponent> 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<MobStateComponent>(entity) && entity != (EntityUid)ent && !HasComp<PsionicInsulationComponent>(entity))
{
if (TryComp<DamageableComponent>(entity, out var damageable) && damageable.DamageContainerID == "Biological")
_statusEffects.TryAddStatusEffect<ForcedSleepingComponent>(entity, StatusEffectKey, TimeSpan.FromSeconds(ent.Comp.Duration), false);
}
}
ent.Comp.DoAfter = null;
}
}
}
@@ -1,2 +1,2 @@
namespace Content.Shared.Actions.Events;
public sealed partial class MassSleepPowerActionEvent : WorldTargetActionEvent {}
public sealed partial class MassSleepPowerActionEvent : InstantActionEvent {}
+3
View File
@@ -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;
@@ -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.
+1 -4
View File
@@ -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