]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
New Status Effects system: Relay events (#38579)
authorRed <96445749+TheShuEd@users.noreply.github.com>
Thu, 26 Jun 2025 20:05:58 +0000 (23:05 +0300)
committerGitHub <noreply@github.com>
Thu, 26 Jun 2025 20:05:58 +0000 (23:05 +0300)
Content.Client/Drowsiness/DrowsinessSystem.cs
Content.Shared/SSDIndicator/SSDIndicatorComponent.cs
Content.Shared/SSDIndicator/SSDIndicatorSystem.cs
Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs
Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs [moved from Content.Shared/StatusEffectNew/StatusEffectNewSystem.API.cs with 100% similarity]
Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs [new file with mode: 0644]
Resources/Prototypes/Entities/StatusEffects/misc.yml

index 152d6ebdf8c1e978a27d578477d8c43c0a7042b3..3b351014895224ff496a0e592eb06f9868aeca25 100644 (file)
@@ -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<DrowsinessStatusEffectComponent, StatusEffectAppliedEvent>(OnDrowsinessApply);
         SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRemovedEvent>(OnDrowsinessShutdown);
 
-        SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectPlayerAttachedEvent>(OnStatusEffectPlayerAttached);
-        SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectPlayerDetachedEvent>(OnStatusEffectPlayerDetached);
+        SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnStatusEffectPlayerAttached);
+        SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnStatusEffectPlayerDetached);
 
         _overlay = new();
     }
@@ -44,17 +45,14 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
         }
     }
 
-    private void OnStatusEffectPlayerAttached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectPlayerAttachedEvent args)
+    private void OnStatusEffectPlayerAttached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
     {
-        if (_player.LocalEntity != args.Target)
-            return;
-
         _overlayMan.AddOverlay(_overlay);
     }
 
-    private void OnStatusEffectPlayerDetached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectPlayerDetachedEvent args)
+    private void OnStatusEffectPlayerDetached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
     {
-        if (_player.LocalEntity != args.Target)
+        if (_player.LocalEntity is null)
             return;
 
         if (!_statusEffects.HasEffectComp<DrowsinessStatusEffectComponent>(_player.LocalEntity.Value))
index 47ac8afe720a68a979b8d85eed421e6e41b40df2..cef8bd15e358190bc81338110d37176e9212556c 100644 (file)
@@ -25,11 +25,4 @@ public sealed partial class SSDIndicatorComponent : Component
     /// </summary>
     [DataField, AutoPausedField, Access(typeof(SSDIndicatorSystem))]
     public TimeSpan FallAsleepTime = TimeSpan.Zero;
-
-    /// <summary>
-    ///     Required to don't remove forced sleep from other sources
-    /// </summary>
-    [ViewVariables(VVAccess.ReadWrite)]
-    [AutoNetworkedField]
-    public bool ForcedSleepAdded = false;
 }
index 850ea8e8da46a9bae4b28cfc48e1860794ec130a..a13b6b915c13f1e3d2a10b4e95cbc2941915f6ff 100644 (file)
@@ -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;
 /// </summary>
 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);
             }
         }
     }
index df27dca27c6c0552bf0fe860ca37256216a1ec65..c836b8205c83b3f6227ec42c81780bee74c02625 100644 (file)
@@ -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<StatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
         SubscribeLocalEvent<StatusEffectComponent, StatusEffectRemovedEvent>(OnStatusEffectRemoved);
 
-        SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(OnStatusEffectContainerAttached);
-        SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(OnStatusEffectContainerDetached);
         SubscribeLocalEvent<StatusEffectContainerComponent, ComponentGetState>(OnGetState);
 
         _containerQuery = GetEntityQuery<StatusEffectContainerComponent>();
@@ -46,24 +45,6 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
         args.State = new StatusEffectContainerComponentState(GetNetEntitySet(ent.Comp.ActiveStatusEffects));
     }
 
-    private void OnStatusEffectContainerAttached(Entity<StatusEffectContainerComponent> ent, ref LocalPlayerAttachedEvent args)
-    {
-        foreach (var effect in ent.Comp.ActiveStatusEffects)
-        {
-            var ev = new StatusEffectPlayerAttachedEvent(ent);
-            RaiseLocalEvent(effect, ref ev);
-        }
-    }
-
-    private void OnStatusEffectContainerDetached(Entity<StatusEffectContainerComponent> 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);
 
-/// <summary>
-/// Called on a status effect entity inside <see cref="StatusEffectContainerComponent"/>
-/// after a player has been <see cref="LocalPlayerAttachedEvent"/> to this container entity.
-/// </summary>
-[ByRefEvent]
-public readonly record struct StatusEffectPlayerAttachedEvent(EntityUid Target);
-
-/// <summary>
-/// Called on a status effect entity inside <see cref="StatusEffectContainerComponent"/>
-/// after a player has been <see cref="LocalPlayerDetachedEvent"/> to this container entity.
-/// </summary>
-[ByRefEvent]
-public readonly record struct StatusEffectPlayerDetachedEvent(EntityUid Target);
-
 /// <summary>
 /// Raised on an entity before a status effect is added to determine if adding it should be cancelled.
 /// </summary>
diff --git a/Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs b/Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs
new file mode 100644 (file)
index 0000000..6d97a75
--- /dev/null
@@ -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<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
+        SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
+    }
+
+    protected void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
+    {
+        RelayEvent((uid, component), ref args);
+    }
+
+    protected void RelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, T args) where T : class
+    {
+        RelayEvent((uid, component), args);
+    }
+
+    public void RelayEvent<T>(Entity<StatusEffectContainerComponent> statusEffect, ref T args) where T : struct
+    {
+        // this copies the by-ref event if it is a struct
+        var ev = new StatusEffectRelayedEvent<T>(args);
+        foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects)
+        {
+            RaiseLocalEvent(activeEffect, ref ev);
+        }
+        // and now we copy it back
+        args = ev.Args;
+    }
+
+    public void RelayEvent<T>(Entity<StatusEffectContainerComponent> statusEffect, T args) where T : class
+    {
+        // this copies the by-ref event if it is a struct
+        var ev = new StatusEffectRelayedEvent<T>(args);
+        foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects)
+        {
+            RaiseLocalEvent(activeEffect, ref ev);
+        }
+    }
+}
+
+/// <summary>
+/// Event wrapper for relayed events.
+/// </summary>
+[ByRefEvent]
+public record struct StatusEffectRelayedEvent<TEvent>(TEvent Args);
index 254d1608bd35833dff113db074fe488906c844c5..bccdea773fbc09416796d76c24bb5b7eba103900 100644 (file)
   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