]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Godmode refactor (#14651)
authorKara <lunarautomaton6@gmail.com>
Thu, 23 Mar 2023 18:57:15 +0000 (11:57 -0700)
committerGitHub <noreply@github.com>
Thu, 23 Mar 2023 18:57:15 +0000 (14:57 -0400)
Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs
Content.Server/Damage/Components/GodmodeComponent.cs [new file with mode: 0644]
Content.Server/Damage/Systems/GodmodeSystem.cs
Content.Shared/Damage/Systems/DamageableSystem.cs
Content.Shared/Damage/Systems/StaminaSystem.cs
Content.Shared/StatusEffect/StatusEffectsSystem.cs

index 173a0b36f422fae3e9cb57f0cac6b21549a0fb3e..1f8a25fd8545fed563f375dc827517f8e05ad09c 100644 (file)
@@ -6,6 +6,7 @@ using Content.Server.Atmos;
 using Content.Server.Atmos.Components;
 using Content.Server.Cargo.Components;
 using Content.Server.Cargo.Systems;
+using Content.Server.Damage.Components;
 using Content.Server.Doors.Components;
 using Content.Server.Doors.Systems;
 using Content.Server.Hands.Components;
@@ -123,7 +124,7 @@ public sealed partial class AdminVerbSystem
                 args.Verbs.Add(rejuvenate);
             }
 
-            if (!_godmodeSystem.HasGodmode(args.Target))
+            if (!HasComp<GodmodeComponent>(args.Target))
             {
                 Verb makeIndestructible = new()
                 {
diff --git a/Content.Server/Damage/Components/GodmodeComponent.cs b/Content.Server/Damage/Components/GodmodeComponent.cs
new file mode 100644 (file)
index 0000000..65ebec2
--- /dev/null
@@ -0,0 +1,14 @@
+using Content.Server.Damage.Systems;
+using Content.Shared.Damage;
+
+namespace Content.Server.Damage.Components;
+
+/// <summary>
+///
+/// </summary>
+[RegisterComponent, Access(typeof(GodmodeSystem))]
+public sealed class GodmodeComponent : Component
+{
+    public bool WasMovedByPressure;
+    public DamageSpecifier? OldDamage = null;
+}
index 38b06cad0bae2b8edb5433aed582e48d39879cf1..d7c6b800aeabc2b9056df195c64d43d7a6d9f769 100644 (file)
@@ -1,6 +1,10 @@
 using Content.Server.Atmos.Components;
+using Content.Server.Damage.Components;
 using Content.Shared.Damage;
-using Content.Shared.GameTicking;
+using Content.Shared.Damage.Systems;
+using Content.Shared.FixedPoint;
+using Content.Shared.Rejuvenate;
+using Content.Shared.StatusEffect;
 using JetBrains.Annotations;
 
 namespace Content.Server.Damage.Systems
@@ -8,108 +12,85 @@ namespace Content.Server.Damage.Systems
     [UsedImplicitly]
     public sealed class GodmodeSystem : EntitySystem
     {
-        private readonly Dictionary<EntityUid, OldEntityInformation> _entities = new();
-        [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+        [Dependency] private readonly DamageableSystem _damageable = default!;
 
         public override void Initialize()
         {
             base.Initialize();
 
-            SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
+            SubscribeLocalEvent<GodmodeComponent, BeforeDamageChangedEvent>(OnBeforeDamageChanged);
+            SubscribeLocalEvent<GodmodeComponent, BeforeStatusEffectAddedEvent>(OnBeforeStatusEffect);
+            SubscribeLocalEvent<GodmodeComponent, BeforeStaminaDamageEvent>(OnBeforeStaminaDamage);
         }
 
-        public void Reset(RoundRestartCleanupEvent ev)
+        private void OnBeforeDamageChanged(EntityUid uid, GodmodeComponent component, ref BeforeDamageChangedEvent args)
         {
-            _entities.Clear();
+            args.Cancelled = true;
         }
 
-        public bool EnableGodmode(EntityUid entity)
+        private void OnBeforeStatusEffect(EntityUid uid, GodmodeComponent component, ref BeforeStatusEffectAddedEvent args)
         {
-            if (_entities.ContainsKey(entity))
-            {
-                return false;
-            }
+            args.Cancelled = true;
+        }
+
+        private void OnBeforeStaminaDamage(EntityUid uid, GodmodeComponent component, ref BeforeStaminaDamageEvent args)
+        {
+            args.Cancelled = true;
+        }
 
-            _entities[entity] = new OldEntityInformation(entity, EntityManager);
+        public void EnableGodmode(EntityUid uid)
+        {
+            var godmode = EnsureComp<GodmodeComponent>(uid);
 
-            if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved))
+            if (TryComp<MovedByPressureComponent>(uid, out var moved))
             {
+                godmode.WasMovedByPressure = moved.Enabled;
                 moved.Enabled = false;
             }
 
-            if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable))
+            if (TryComp<DamageableComponent>(uid, out var damageable))
             {
-                _damageableSystem.SetDamage(entity, damageable, new DamageSpecifier());
+                godmode.OldDamage = new(damageable.Damage);
             }
 
-            return true;
+            // Rejuv to cover other stuff
+            RaiseLocalEvent(uid, new RejuvenateEvent());
         }
 
-        public bool HasGodmode(EntityUid entity)
+        public void DisableGodmode(EntityUid uid)
         {
-            return _entities.ContainsKey(entity);
-        }
+            if (!TryComp<GodmodeComponent>(uid, out var godmode))
+                return;
 
-        public bool DisableGodmode(EntityUid entity)
-        {
-            if (!_entities.Remove(entity, out var old))
+            if (TryComp<MovedByPressureComponent>(uid, out var moved))
             {
-                return false;
+                moved.Enabled = godmode.WasMovedByPressure;
             }
 
-            if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved))
-            {
-                moved.Enabled = old.MovedByPressure;
-            }
+            if (!TryComp<DamageableComponent>(uid, out var damageable))
+                return;
 
-            if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable))
+            if (godmode.OldDamage != null)
             {
-                if (old.Damage != null)
-                {
-                    _damageableSystem.SetDamage(entity, damageable, old.Damage);
-                }
+                _damageable.SetDamage(uid, damageable, godmode.OldDamage);
             }
-
-            return true;
         }
 
         /// <summary>
         ///     Toggles godmode for a given entity.
         /// </summary>
-        /// <param name="entity">The entity to toggle godmode for.</param>
+        /// <param name="uid">The entity to toggle godmode for.</param>
         /// <returns>true if enabled, false if disabled.</returns>
-        public bool ToggleGodmode(EntityUid entity)
+        public bool ToggleGodmode(EntityUid uid)
         {
-            if (HasGodmode(entity))
+            if (HasComp<GodmodeComponent>(uid))
             {
-                DisableGodmode(entity);
+                DisableGodmode(uid);
                 return false;
             }
-            else
-            {
-                EnableGodmode(entity);
-                return true;
-            }
-        }
 
-        public sealed class OldEntityInformation
-        {
-            public OldEntityInformation(EntityUid entity, IEntityManager entityManager)
-            {
-                Entity = entity;
-                MovedByPressure = entityManager.HasComponent<MovedByPressureComponent>(entity);
-
-                if (entityManager.TryGetComponent(entity, out DamageableComponent? damageable))
-                {
-                    Damage = damageable.Damage;
-                }
-            }
-
-            public EntityUid Entity { get; }
-
-            public bool MovedByPressure { get; }
-
-            public DamageSpecifier? Damage { get; }
+            EnableGodmode(uid);
+            return true;
         }
     }
 }
index 9e7f9cb09f77adc8c4cc4dfa97ee05ca3e20ad59..e7eda3bb1b7835350ffcac19fd30c0a479d0ae0f 100644 (file)
@@ -159,6 +159,12 @@ namespace Content.Shared.Damage
                 return damage;
             }
 
+            var before = new BeforeDamageChangedEvent(damage);
+            RaiseLocalEvent(uid.Value, ref before);
+
+            if (before.Cancelled)
+                return null;
+
             // Apply resistances
             if (!ignoreResistances)
             {
@@ -283,6 +289,12 @@ namespace Content.Shared.Damage
         }
     }
 
+    /// <summary>
+    ///     Raised before damage is done, so stuff can cancel it if necessary.
+    /// </summary>
+    [ByRefEvent]
+    public record struct BeforeDamageChangedEvent(DamageSpecifier Delta, bool Cancelled=false);
+
     /// <summary>
     ///     Raised on an entity when damage is about to be dealt,
     ///     in case anything else needs to modify it other than the base
index 561f94545854adcc917ba63f9df86abfe29c1bf3..332bc65e60b9da6310473baa87e709502b002397 100644 (file)
@@ -7,6 +7,7 @@ using Content.Shared.Damage.Events;
 using Content.Shared.Database;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Popups;
+using Content.Shared.Rejuvenate;
 using Content.Shared.Rounding;
 using Content.Shared.Stunnable;
 using Content.Shared.Weapons.Melee.Events;
@@ -45,6 +46,7 @@ public sealed class StaminaSystem : EntitySystem
         SubscribeLocalEvent<StaminaComponent, ComponentGetState>(OnStamGetState);
         SubscribeLocalEvent<StaminaComponent, ComponentHandleState>(OnStamHandleState);
         SubscribeLocalEvent<StaminaComponent, DisarmedEvent>(OnDisarmed);
+        SubscribeLocalEvent<StaminaComponent, RejuvenateEvent>(OnRejuvenate);
         SubscribeLocalEvent<StaminaDamageOnCollideComponent, StartCollideEvent>(OnCollide);
         SubscribeLocalEvent<StaminaDamageOnHitComponent, MeleeHitEvent>(OnHit);
     }
@@ -111,6 +113,18 @@ public sealed class StaminaSystem : EntitySystem
         return MathF.Max(0f, component.StaminaDamage - MathF.Max(0f, (float) (curTime - (component.NextUpdate + pauseTime)).TotalSeconds * component.Decay));
     }
 
+    private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args)
+    {
+        if (component.StaminaDamage >= component.CritThreshold)
+        {
+            ExitStamCrit(uid, component);
+        }
+
+        component.StaminaDamage = 0;
+        RemComp<ActiveStaminaComponent>(uid);
+        Dirty(component);
+    }
+
     private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent args)
     {
         if (args.Handled || !_random.Prob(args.PushProbability))
@@ -209,7 +223,16 @@ public sealed class StaminaSystem : EntitySystem
 
     public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null)
     {
-        if (!Resolve(uid, ref component, false) || component.Critical)
+        if (!Resolve(uid, ref component, false))
+            return;
+
+        var ev = new BeforeStaminaDamageEvent(value);
+        RaiseLocalEvent(uid, ref ev);
+        if (ev.Cancelled)
+            return;
+
+        // Have we already reached the point of max stamina damage?
+        if (component.Critical)
             return;
 
         var oldDamage = component.StaminaDamage;
@@ -356,4 +379,11 @@ public sealed class StaminaSystem : EntitySystem
         public float CritThreshold;
         public TimeSpan LastUpdate;
     }
+
 }
+
+/// <summary>
+///     Raised before stamina damage is dealt to allow other systems to cancel it.
+/// </summary>
+[ByRefEvent]
+public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled=false);
index 0cab536e19a1749fe2d1eec345d9e59cc4af13de..23d18eb903d84292bbbecdaa52e1b8a2f978dc52 100644 (file)
@@ -346,6 +346,12 @@ namespace Content.Shared.StatusEffect
             // don't log since stuff calling this prolly doesn't care if we don't actually have it
             if (!Resolve(uid, ref status, false))
                 return false;
+
+            var ev = new BeforeStatusEffectAddedEvent(key);
+            RaiseLocalEvent(uid, ref ev);
+            if (ev.Cancelled)
+                return false;
+
             if (!_prototypeManager.TryIndex<StatusEffectPrototype>(key, out var proto))
                 return false;
             if (!status.AllowedEffects.Contains(key) && !proto.AlwaysAllowed)
@@ -465,6 +471,12 @@ namespace Content.Shared.StatusEffect
         }
     }
 
+    /// <summary>
+    ///     Raised on an entity before a status effect is added to determine if adding it should be cancelled.
+    /// </summary>
+    [ByRefEvent]
+    public record struct BeforeStatusEffectAddedEvent(string Key, bool Cancelled=false);
+
     public readonly struct StatusEffectAddedEvent
     {
         public readonly EntityUid Uid;