]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Stunned Status and Knockdown Meth fix. (#39547)
authorPrincess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com>
Sat, 27 Sep 2025 10:19:30 +0000 (03:19 -0700)
committerGitHub <noreply@github.com>
Sat, 27 Sep 2025 10:19:30 +0000 (12:19 +0200)
* Init Commit

* Remove unused code, fix stun visuals bug

* Update Content.Shared/Stunnable/SharedStunSystem.cs

* Some initial changes

* first batch of changes

* Commit

* One line cleanup

* KnockdownStatusEffect ain't worth it.

* Fix 2 bugs

* Fixes

* Remove that actually,

* Maybe this?

* Meff fix

* Meff fix

* alert cleanup and API

* I expect update loops to be at the top.

* Fix LOC

* Address review

* Address review x 2

* Merg my PR

* Fix

* Update Content.Shared/Alert/AlertsSystem.cs

webedit

Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com>
* FIX THAT TEST FAIL!!!!

* Me when I forget to actually give you alerts

* Push

* Tests are not failing locally why are they dying on github???

* Fix test fails (real)

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com>
Content.Shared/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs
Content.Shared/EntityEffects/Effects/StatusEffects/ModifyKnockdown.cs [new file with mode: 0644]
Content.Shared/EntityEffects/Effects/StatusEffects/ModifyStatusEffect.cs
Content.Shared/Stunnable/SharedStunSystem.Knockdown.cs
Resources/Locale/en-US/guidebook/chemistry/effects.ftl
Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml
Resources/Prototypes/Reagents/cleaning.yml
Resources/Prototypes/Reagents/gases.yml
Resources/Prototypes/Reagents/medicine.yml
Resources/Prototypes/Reagents/narcotics.yml
Resources/Prototypes/Reagents/toxins.yml

index b770023604074db354d82a8965bab3eebb5b523a..652c1b90a14394b5df8baa52a0e69ed4e7bb9993 100644 (file)
@@ -69,6 +69,7 @@ public sealed partial class GenericStatusEffect : EntityEffect
 
 public enum StatusEffectMetabolismType
 {
+    Update,
     Add,
     Remove,
     Set
diff --git a/Content.Shared/EntityEffects/Effects/StatusEffects/ModifyKnockdown.cs b/Content.Shared/EntityEffects/Effects/StatusEffects/ModifyKnockdown.cs
new file mode 100644 (file)
index 0000000..59ca5da
--- /dev/null
@@ -0,0 +1,99 @@
+using Content.Shared.Stunnable;
+using JetBrains.Annotations;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.EntityEffects.Effects.StatusEffects;
+
+/// <summary>
+/// Changes the knockdown timer on an entity or causes knockdown.
+/// </summary>
+[UsedImplicitly]
+public sealed partial class ModifyKnockdown : EntityEffect
+{
+    /// <summary>
+    /// Should we only affect those with crawler component? Note if this is false, it will paralyze non-crawler's instead.
+    /// </summary>
+    [DataField]
+    public bool Crawling;
+
+    /// <summary>
+    /// Should we drop items when we fall?
+    /// </summary>
+    [DataField]
+    public bool Drop;
+
+    /// <summary>
+    /// Time for which knockdown should be applied. Behaviour changes according to <see cref="StatusEffectMetabolismType"/>.
+    /// </summary>
+    [DataField]
+    public TimeSpan Time = TimeSpan.FromSeconds(0.5);
+
+    /// <summary>
+    /// Should this effect add the status effect, remove time from it, or set its cooldown?
+    /// </summary>
+    [DataField]
+    public StatusEffectMetabolismType Type = StatusEffectMetabolismType.Add;
+
+    /// <summary>
+    /// Should this effect add knockdown?, remove time from it?, or set its cooldown?
+    /// </summary>
+    [DataField]
+    public bool Refresh = true;
+
+    /// <inheritdoc />
+    public override void Effect(EntityEffectBaseArgs args)
+    {
+        var stunSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedStunSystem>();
+
+        var time = Time;
+        if (args is EntityEffectReagentArgs reagentArgs)
+            time *= reagentArgs.Scale.Float();
+
+        switch (Type)
+        {
+            case StatusEffectMetabolismType.Update:
+                if (Crawling)
+                {
+                    stunSys.TryCrawling(args.TargetEntity, time, drop: Drop);
+                }
+                else
+                {
+                    stunSys.TryKnockdown(args.TargetEntity, time, drop: Drop);
+                }
+                break;
+            case StatusEffectMetabolismType.Add:
+                if (Crawling)
+                {
+                    stunSys.TryCrawling(args.TargetEntity, time, false, drop: Drop);
+                }
+                else
+                {
+                    stunSys.TryKnockdown(args.TargetEntity, time, false, drop: Drop);
+                }
+                break;
+            case StatusEffectMetabolismType.Remove:
+                    stunSys.AddKnockdownTime(args.TargetEntity, -time);
+                break;
+            case StatusEffectMetabolismType.Set:
+                if (Crawling)
+                {
+                    stunSys.TryCrawling(args.TargetEntity, time, drop: Drop);
+                }
+                else
+                {
+                    stunSys.TryKnockdown(args.TargetEntity, time, drop: Drop);
+                }
+                stunSys.SetKnockdownTime(args.TargetEntity, time);
+                break;
+        }
+    }
+
+    /// <inheritdoc />
+    protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
+        => Loc.GetString(
+            "reagent-effect-guidebook-knockdown",
+            ("chance", Probability),
+            ("type", Type),
+            ("time", Time.TotalSeconds)
+        );
+}
index cb010b648c9932d04e5d09d7e5e3f507b866e72c..d7bf6482bd27f8f0d2373ee4d9a5183894c979ae 100644 (file)
@@ -25,12 +25,6 @@ public sealed partial class ModifyStatusEffect : EntityEffect
     [DataField]
     public float Delay = 0f;
 
-    /// <remarks>
-    /// true - refresh status effect time (update to greater value), false - accumulate status effect time.
-    /// </remarks>
-    [DataField]
-    public bool Refresh = true;
-
     /// <summary>
     /// Should this effect add the status effect, remove time from it, or set its cooldown?
     /// </summary>
@@ -49,11 +43,11 @@ public sealed partial class ModifyStatusEffect : EntityEffect
         var duration = TimeSpan.FromSeconds(time);
         switch (Type)
         {
+            case StatusEffectMetabolismType.Update:
+                statusSys.TryUpdateStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
+                break;
             case StatusEffectMetabolismType.Add:
-                if (Refresh)
-                    statusSys.TryUpdateStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
-                else
-                    statusSys.TryAddStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
+                statusSys.TryAddStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
                 break;
             case StatusEffectMetabolismType.Remove:
                 statusSys.TryAddTime(args.TargetEntity, EffectProto, -duration);
index 3646dc8f2832bd37bd2f1329c314025704ca8745..f484bd012e54f74e71386b76cd230866fa094938 100644 (file)
@@ -95,7 +95,7 @@ public abstract partial class SharedStunSystem
 
     private void OnRejuvenate(Entity<KnockedDownComponent> entity, ref RejuvenateEvent args)
     {
-        SetKnockdownTime(entity, GameTiming.CurTime);
+        SetKnockdownNextUpdate((entity, entity), GameTiming.CurTime);
 
         if (entity.Comp.AutoStand)
             RemComp<KnockedDownComponent>(entity);
@@ -156,6 +156,19 @@ public abstract partial class SharedStunSystem
         DirtyField(entity, entity.Comp, nameof(KnockedDownComponent.DoAfterId));
     }
 
+    /// <summary>
+    /// Sets the time left of the knockdown timer to the inputted value.
+    /// </summary>
+    /// <param name="entity">Entity who's knockdown time we're updating.</param>
+    /// <param name="time">The time we're updating with.</param>
+    public void SetKnockdownTime(Entity<KnockedDownComponent?> entity, TimeSpan time)
+    {
+        if (!Resolve(entity, ref entity.Comp, false))
+            return;
+
+        SetKnockdownNextUpdate(entity, GameTiming.CurTime + time);
+    }
+
     /// <summary>
     /// Updates the knockdown timer of a knocked down entity with a given inputted time, then dirties the time.
     /// </summary>
@@ -170,18 +183,6 @@ public abstract partial class SharedStunSystem
             AddKnockdownTime(entity, time);
     }
 
-    /// <summary>
-    /// Sets the next update datafield of an entity's <see cref="KnockedDownComponent"/> to a specific time.
-    /// </summary>
-    /// <param name="entity">Entity whose timer we're updating</param>
-    /// <param name="time">The exact time we're setting the next update to.</param>
-    public void SetKnockdownTime(Entity<KnockedDownComponent> entity, TimeSpan time)
-    {
-        entity.Comp.NextUpdate = time;
-        DirtyField(entity, entity.Comp, nameof(KnockedDownComponent.NextUpdate));
-        Alerts.ShowAlert(entity.Owner, KnockdownAlert, null, (GameTiming.CurTime, entity.Comp.NextUpdate));
-    }
-
     /// <summary>
     /// Refreshes the amount of time an entity is knocked down to the inputted time, if it is greater than
     /// the current time left.
@@ -195,7 +196,7 @@ public abstract partial class SharedStunSystem
 
         var knockedTime = GameTiming.CurTime + time;
         if (entity.Comp.NextUpdate < knockedTime)
-            SetKnockdownTime((entity, entity.Comp), knockedTime);
+            SetKnockdownNextUpdate((entity, entity.Comp), knockedTime);
     }
 
     /// <summary>
@@ -210,19 +211,35 @@ public abstract partial class SharedStunSystem
 
         if (entity.Comp.NextUpdate < GameTiming.CurTime)
         {
-            SetKnockdownTime((entity, entity.Comp), GameTiming.CurTime + time);
+            SetKnockdownNextUpdate((entity, entity.Comp), GameTiming.CurTime + time);
             return;
         }
 
-        entity.Comp.NextUpdate += time;
-        DirtyField(entity, entity.Comp, nameof(KnockedDownComponent.NextUpdate));
-        Alerts.ShowAlert(entity.Owner, KnockdownAlert, null, (GameTiming.CurTime, entity.Comp.NextUpdate));
+        SetKnockdownNextUpdate((entity, entity.Comp), entity.Comp.NextUpdate + time);
     }
 
     #endregion
 
     #region Knockdown Logic
 
+    /// <summary>
+    /// Sets the next update datafield of an entity's <see cref="KnockedDownComponent"/> to a specific time.
+    /// </summary>
+    /// <param name="entity">Entity whose timer we're updating</param>
+    /// <param name="time">The exact time we're setting the next update to.</param>
+    private void SetKnockdownNextUpdate(Entity<KnockedDownComponent?> entity, TimeSpan time)
+    {
+        if (!Resolve(entity, ref entity.Comp, false))
+            return;
+
+        if (GameTiming.CurTime > time)
+            time = GameTiming.CurTime;
+
+        entity.Comp.NextUpdate = time;
+        DirtyField(entity, entity.Comp, nameof(KnockedDownComponent.NextUpdate));
+        Alerts.UpdateAlert(entity.Owner, KnockdownAlert, null, entity.Comp.NextUpdate);
+    }
+
     private void HandleToggleKnockdown(ICommonSession? session)
     {
         if (session is not { } playerSession)
index 1ab89f89a34f1532eb41770f4298b3be5fc5f577..07c908c0357b971657e64ed729f7b9cb79386a21 100644 (file)
@@ -104,6 +104,10 @@ reagent-effect-guidebook-even-health-change =
 
 reagent-effect-guidebook-status-effect =
     { $type ->
+        [update]{ $chance ->
+                    [1] Causes
+                    *[other] cause
+                } {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} without accumulation
         [add]   { $chance ->
                     [1] Causes
                     *[other] cause
@@ -134,6 +138,26 @@ reagent-effect-guidebook-status-effect-delay =
                 } {NATURALFIXED($time, 3)} {MANY("second", $time)} of {LOC($key)}
     } after a {NATURALFIXED($delay, 3)} second delay
 
+reagent-effect-guidebook-knockdown =
+    { $type ->
+        [update]{ $chance ->
+                    [1] Causes
+                    *[other] cause
+                    } {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} without accumulation
+        [add]   { $chance ->
+                    [1] Causes
+                    *[other] cause
+                } knockdown for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} with accumulation
+        *[set]  { $chance ->
+                    [1] Causes
+                    *[other] cause
+                } knockdown for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} without accumulation
+        [remove]{ $chance ->
+                    [1] Removes
+                    *[other] remove
+                } {NATURALFIXED($time, 3)} {MANY("second", $time)} of knockdown
+    }
+
 reagent-effect-guidebook-set-solution-temperature-effect =
     { $chance ->
         [1] Sets
index 741108cca1e8bbf0e0889c52dfd11ddd06e2bceb..9bd5bb195fa063c2c2a33c9b4c32aac362058b98 100644 (file)
@@ -34,7 +34,6 @@
           min: 10
         type: Add
         time: 5
-        refresh: false
       - !type:PopupMessage
         type: Local
         messages:
index d03fff19410c188bac952b93fbb2e73d76ec96c3..2ebd213fec544aa44bdb6459c890b649f15f2f2b 100644 (file)
         effectProto: StatusEffectSeeingRainbow
         time: 5
         type: Add
-        refresh: false
     Drink:
       effects:
       - !type:GenericStatusEffect
index b3a533d74755aa51dd47a8bcaba023534c48b709..3d65931f19f3cfa5e2a41f722c843a3cb6c53756 100644 (file)
           shouldHave: false
         effectProto: StatusEffectForcedSleeping
         time: 3
-        type: Add
+        type: Update
       - !type:HealthChange
         conditions:
         - !type:ReagentThreshold
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 15
-        refresh: false
       - !type:Drunk
         boozePower: 15
       - !type:PopupMessage
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 500
-        refresh: false
       - !type:Drunk
         boozePower: 500
         conditions:
index bfbb8242fd45c664e8228e70150ada74e0504090..71ae11dad9a5e230bdddcfb361e3a2264e17bee4 100644 (file)
@@ -89,7 +89,6 @@
         effectProto: StatusEffectDrowsiness
         time: 1.5
         type: Add
-        refresh: false
       - !type:HealthChange
         damage:
           types:
           min: 1
         reagent: Histamine
         amount: 4
-      - !type:GenericStatusEffect
-        key: Stun
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectStunned
         time: 0.75
         type: Remove
-      - !type:GenericStatusEffect
-        key: KnockedDown
+      - !type:ModifyKnockdown
         time: 0.75
         type: Remove
       - !type:GenericStatusEffect
         damage:
           types:
             Poison: 2
-      - !type:GenericStatusEffect
-        key: Stun
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectStunned
         time: 3.0
         type: Remove
-      - !type:GenericStatusEffect
-        key: KnockedDown
+      - !type:ModifyKnockdown
         time: 3.0
         type: Remove
       - !type:ModifyStatusEffect
           min: 30
         type: Add
         time: 8
-        refresh: false
       - !type:GenericStatusEffect
         key: Jitter
         time: 2.0
         effectProto: StatusEffectDrowsiness
         time: 4
         type: Add
-        refresh: false
       - !type:GenericStatusEffect
         key: Jitter
         time: 4.0
index 3658a50f50025179cd4270eb7a4b4ea1ee85f35e..a1b1033a4b8625525b84a726793059992c43a145 100644 (file)
         key: Stutter
         component: StutteringAccent
       - !type:Jitter
-      - !type:GenericStatusEffect
-        key: Stun
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectStunned
         time: 3
         type: Remove
-      - !type:GenericStatusEffect
-        key: KnockedDown
+      - !type:ModifyKnockdown
         time: 3
         type: Remove
       - !type:ModifyStatusEffect
             Poison: 2 # this is added to the base damage of the meth.
             Asphyxiation: 2
       - !type:Jitter
-      - !type:GenericStatusEffect
-        key: Stun
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectStunned
         time: 1
         type: Remove
-      - !type:GenericStatusEffect
-        key: KnockedDown
+      - !type:ModifyKnockdown
         time: 1
         type: Remove
       - !type:ModifyStatusEffect
           min: 1
         reagent: ChloralHydrate
         amount: -10
-      - !type:GenericStatusEffect
-        key: Stun
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectStunned
         time: 3
         type: Remove
-      - !type:GenericStatusEffect
-        key: KnockedDown
+      - !type:ModifyKnockdown
         time: 3
         type: Remove
       - !type:GenericStatusEffect
         effectProto: StatusEffectSeeingRainbow
         time: 16
         type: Add
-        refresh: false
 
 - type: reagent
   id: Nicotine
         effectProto: StatusEffectSeeingRainbow
         time: 10
         type: Add
-        refresh: false
       - !type:ChemVomit # Vomiting is a symptom of brain damage
         probability: 0.05
       - !type:Drunk # Headaches and slurring are major symptoms of brain damage, this is close enough
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 5
-        refresh: false
 
 - type: reagent
   id: Bananadine
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 5
-        refresh: false
 
 # Probably replace this one with sleeping chem when putting someone in a comatose state is easier
 - type: reagent
         component: Muted
         type: Add
         time: 10
-        refresh: false
 
 - type: reagent
   id: NorepinephricAcid
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 5
-        refresh: false
index e94d13a8918a932db12d4394bbb96e7f0e90105b..33a94c079271ee1eccfd3c5d97fb5671cfbe99ee 100644 (file)
@@ -74,7 +74,6 @@
         effectProto: StatusEffectDrowsiness
         time: 4
         type: Add
-        refresh: false
       - !type:HealthChange
         conditions:
         - !type:ReagentThreshold
         effectProto: StatusEffectSeeingRainbow
         type: Add
         time: 10
-        refresh: false
   # TODO: PROPER hallucinations
 
 - type: reagent