diff --git a/Content.Client/Drowsiness/DrowsinessSystem.cs b/Content.Client/Drowsiness/DrowsinessSystem.cs index 152d6ebdf8..3b35101489 100644 --- a/Content.Client/Drowsiness/DrowsinessSystem.cs +++ b/Content.Client/Drowsiness/DrowsinessSystem.cs @@ -2,6 +2,7 @@ using Content.Shared.Drowsiness; using Content.Shared.StatusEffectNew; using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Player; namespace Content.Client.Drowsiness; @@ -20,8 +21,8 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem SubscribeLocalEvent(OnDrowsinessApply); SubscribeLocalEvent(OnDrowsinessShutdown); - SubscribeLocalEvent(OnStatusEffectPlayerAttached); - SubscribeLocalEvent(OnStatusEffectPlayerDetached); + SubscribeLocalEvent>(OnStatusEffectPlayerAttached); + SubscribeLocalEvent>(OnStatusEffectPlayerDetached); _overlay = new(); } @@ -44,17 +45,14 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem } } - private void OnStatusEffectPlayerAttached(Entity ent, ref StatusEffectPlayerAttachedEvent args) + private void OnStatusEffectPlayerAttached(Entity ent, ref StatusEffectRelayedEvent args) { - if (_player.LocalEntity != args.Target) - return; - _overlayMan.AddOverlay(_overlay); } - private void OnStatusEffectPlayerDetached(Entity ent, ref StatusEffectPlayerDetachedEvent args) + private void OnStatusEffectPlayerDetached(Entity ent, ref StatusEffectRelayedEvent args) { - if (_player.LocalEntity != args.Target) + if (_player.LocalEntity is null) return; if (!_statusEffects.HasEffectComp(_player.LocalEntity.Value)) diff --git a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs index 47ac8afe72..cef8bd15e3 100644 --- a/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs +++ b/Content.Shared/SSDIndicator/SSDIndicatorComponent.cs @@ -25,11 +25,4 @@ public sealed partial class SSDIndicatorComponent : Component /// [DataField, AutoPausedField, Access(typeof(SSDIndicatorSystem))] public TimeSpan FallAsleepTime = TimeSpan.Zero; - - /// - /// Required to don't remove forced sleep from other sources - /// - [ViewVariables(VVAccess.ReadWrite)] - [AutoNetworkedField] - public bool ForcedSleepAdded = false; } diff --git a/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs b/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs index 850ea8e8da..a13b6b915c 100644 --- a/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs +++ b/Content.Shared/SSDIndicator/SSDIndicatorSystem.cs @@ -1,8 +1,8 @@ -using Content.Shared.Bed.Sleep; using Content.Shared.CCVar; using Content.Shared.StatusEffectNew; using Robust.Shared.Configuration; using Robust.Shared.Player; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Shared.SSDIndicator; @@ -12,6 +12,8 @@ namespace Content.Shared.SSDIndicator; /// public sealed class SSDIndicatorSystem : EntitySystem { + public static readonly EntProtoId StatusEffectSSDSleeping = "StatusEffectSSDSleeping"; + [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SharedStatusEffectsSystem _statusEffects = default!; @@ -37,11 +39,7 @@ public sealed class SSDIndicatorSystem : EntitySystem if (_icSsdSleep) { component.FallAsleepTime = TimeSpan.Zero; - if (component.ForcedSleepAdded) // Remove component only if it has been added by this system - { - _statusEffects.TryRemoveStatusEffect(uid, SleepingSystem.StatusEffectForcedSleeping); - component.ForcedSleepAdded = false; - } + _statusEffects.TryRemoveStatusEffect(uid, StatusEffectSSDSleeping); } Dirty(uid, component); @@ -87,8 +85,7 @@ public sealed class SSDIndicatorSystem : EntitySystem ssd.FallAsleepTime <= _timing.CurTime && !TerminatingOrDeleted(uid)) { - _statusEffects.TryAddStatusEffect(uid, SleepingSystem.StatusEffectForcedSleeping); - ssd.ForcedSleepAdded = true; + _statusEffects.TryAddStatusEffect(uid, StatusEffectSSDSleeping); } } } diff --git a/Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs b/Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs index df27dca27c..c836b8205c 100644 --- a/Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs +++ b/Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs @@ -3,7 +3,6 @@ using Content.Shared.StatusEffectNew.Components; using Content.Shared.Whitelist; using Robust.Shared.GameStates; using Robust.Shared.Network; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -30,11 +29,11 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem { base.Initialize(); + InitializeRelay(); + SubscribeLocalEvent(OnStatusEffectApplied); SubscribeLocalEvent(OnStatusEffectRemoved); - SubscribeLocalEvent(OnStatusEffectContainerAttached); - SubscribeLocalEvent(OnStatusEffectContainerDetached); SubscribeLocalEvent(OnGetState); _containerQuery = GetEntityQuery(); @@ -46,24 +45,6 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem args.State = new StatusEffectContainerComponentState(GetNetEntitySet(ent.Comp.ActiveStatusEffects)); } - private void OnStatusEffectContainerAttached(Entity ent, ref LocalPlayerAttachedEvent args) - { - foreach (var effect in ent.Comp.ActiveStatusEffects) - { - var ev = new StatusEffectPlayerAttachedEvent(ent); - RaiseLocalEvent(effect, ref ev); - } - } - - private void OnStatusEffectContainerDetached(Entity ent, ref LocalPlayerDetachedEvent args) - { - foreach (var effect in ent.Comp.ActiveStatusEffects) - { - var ev = new StatusEffectPlayerDetachedEvent(ent); - RaiseLocalEvent(effect, ref ev); - } - } - public override void Update(float frameTime) { base.Update(frameTime); @@ -187,20 +168,6 @@ public readonly record struct StatusEffectAppliedEvent(EntityUid Target); [ByRefEvent] public readonly record struct StatusEffectRemovedEvent(EntityUid Target); -/// -/// Called on a status effect entity inside -/// after a player has been to this container entity. -/// -[ByRefEvent] -public readonly record struct StatusEffectPlayerAttachedEvent(EntityUid Target); - -/// -/// Called on a status effect entity inside -/// after a player has been to this container entity. -/// -[ByRefEvent] -public readonly record struct StatusEffectPlayerDetachedEvent(EntityUid Target); - /// /// Raised on an entity before a status effect is added to determine if adding it should be cancelled. /// diff --git a/Content.Shared/StatusEffectNew/StatusEffectNewSystem.API.cs b/Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs similarity index 100% rename from Content.Shared/StatusEffectNew/StatusEffectNewSystem.API.cs rename to Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs diff --git a/Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs b/Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs new file mode 100644 index 0000000000..6d97a75edd --- /dev/null +++ b/Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs @@ -0,0 +1,51 @@ +using Content.Shared.StatusEffectNew.Components; +using Robust.Shared.Player; + +namespace Content.Shared.StatusEffectNew; + +public abstract partial class SharedStatusEffectsSystem +{ + protected void InitializeRelay() + { + SubscribeLocalEvent(RelayStatusEffectEvent); + SubscribeLocalEvent(RelayStatusEffectEvent); + } + + protected void RefRelayStatusEffectEvent(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct + { + RelayEvent((uid, component), ref args); + } + + protected void RelayStatusEffectEvent(EntityUid uid, StatusEffectContainerComponent component, T args) where T : class + { + RelayEvent((uid, component), args); + } + + public void RelayEvent(Entity statusEffect, ref T args) where T : struct + { + // this copies the by-ref event if it is a struct + var ev = new StatusEffectRelayedEvent(args); + foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects) + { + RaiseLocalEvent(activeEffect, ref ev); + } + // and now we copy it back + args = ev.Args; + } + + public void RelayEvent(Entity statusEffect, T args) where T : class + { + // this copies the by-ref event if it is a struct + var ev = new StatusEffectRelayedEvent(args); + foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects) + { + RaiseLocalEvent(activeEffect, ref ev); + } + } +} + +/// +/// Event wrapper for relayed events. +/// +[ByRefEvent] +public record struct StatusEffectRelayedEvent(TEvent Args); diff --git a/Resources/Prototypes/Entities/StatusEffects/misc.yml b/Resources/Prototypes/Entities/StatusEffects/misc.yml index 254d1608bd..bccdea773f 100644 --- a/Resources/Prototypes/Entities/StatusEffects/misc.yml +++ b/Resources/Prototypes/Entities/StatusEffects/misc.yml @@ -27,6 +27,14 @@ components: - type: ForcedSleepingStatusEffect +# This creature is asleep because it's disconnected from the game. +- type: entity + parent: MobStatusEffectBase + id: StatusEffectSSDSleeping + name: forced sleep + components: + - type: ForcedSleepingStatusEffect + # Blurs your vision and makes you randomly fall asleep - type: entity parent: MobStatusEffectBase