From 05ddaa6d8a0a04e4fb214a19840d0546339dcfa9 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Mon, 9 Sep 2024 04:19:55 +0100 Subject: [PATCH 1/9] start implementing soft stamina --- .../Damage/Components/StaminaComponent.cs | 19 +- .../StaminaDamageOnCollideComponent.cs | 3 + .../StaminaDamageOnEmbedComponent.cs | 3 + .../Components/StaminaDamageOnHitComponent.cs | 3 + .../Components/StaminaModifierComponent.cs | 2 +- .../Damage/Systems/StaminaSystem.cs | 214 ++++++++++++++---- 6 files changed, 197 insertions(+), 47 deletions(-) diff --git a/Content.Shared/Damage/Components/StaminaComponent.cs b/Content.Shared/Damage/Components/StaminaComponent.cs index 14c3f6d9f5..fe5b7061aa 100644 --- a/Content.Shared/Damage/Components/StaminaComponent.cs +++ b/Content.Shared/Damage/Components/StaminaComponent.cs @@ -11,6 +11,13 @@ namespace Content.Shared.Damage.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), AutoGenerateComponentPause] public sealed partial class StaminaComponent : Component { + + /// + /// Have we reached peak soft stamina damage and been forced to crawl? + /// + [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + public bool Crawling; + /// /// Have we reached peak stamina damage and been paralyzed? /// @@ -30,16 +37,22 @@ public sealed partial class StaminaComponent : Component public float Cooldown = 3f; /// - /// How much stamina damage this entity has taken. + /// How much soft (makes them crawl) stamina damage this entity has taken. + /// + [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] + public float SoftStaminaDamage; + + /// + /// How much hard (makes them static on the floor) stamina damage this entity has taken. /// [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public float StaminaDamage; + public float HardStaminaDamage; /// /// How much stamina damage is required to entire stam crit. /// [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public float CritThreshold = 100f; + public float CritThreshold = 50f; /// /// How long will this mob be stunned for? diff --git a/Content.Shared/Damage/Components/StaminaDamageOnCollideComponent.cs b/Content.Shared/Damage/Components/StaminaDamageOnCollideComponent.cs index 5ed2bb628e..a42d48c733 100644 --- a/Content.Shared/Damage/Components/StaminaDamageOnCollideComponent.cs +++ b/Content.Shared/Damage/Components/StaminaDamageOnCollideComponent.cs @@ -13,4 +13,7 @@ public sealed partial class StaminaDamageOnCollideComponent : Component [DataField("sound")] public SoundSpecifier? Sound; + + [DataField] + public bool Soft = true; } diff --git a/Content.Shared/Damage/Components/StaminaDamageOnEmbedComponent.cs b/Content.Shared/Damage/Components/StaminaDamageOnEmbedComponent.cs index 4ad4906246..0ed549c44e 100644 --- a/Content.Shared/Damage/Components/StaminaDamageOnEmbedComponent.cs +++ b/Content.Shared/Damage/Components/StaminaDamageOnEmbedComponent.cs @@ -14,4 +14,7 @@ public sealed partial class StaminaDamageOnEmbedComponent : Component { [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] public float Damage = 10f; + + [DataField] + public bool Soft = true; } diff --git a/Content.Shared/Damage/Components/StaminaDamageOnHitComponent.cs b/Content.Shared/Damage/Components/StaminaDamageOnHitComponent.cs index 7a524a0052..fbc60bf970 100644 --- a/Content.Shared/Damage/Components/StaminaDamageOnHitComponent.cs +++ b/Content.Shared/Damage/Components/StaminaDamageOnHitComponent.cs @@ -10,4 +10,7 @@ public sealed partial class StaminaDamageOnHitComponent : Component [DataField("sound")] public SoundSpecifier? Sound; + + [DataField] + public bool Soft = true; } diff --git a/Content.Shared/Damage/Components/StaminaModifierComponent.cs b/Content.Shared/Damage/Components/StaminaModifierComponent.cs index f054c77f7b..723e043f46 100644 --- a/Content.Shared/Damage/Components/StaminaModifierComponent.cs +++ b/Content.Shared/Damage/Components/StaminaModifierComponent.cs @@ -4,7 +4,7 @@ namespace Content.Shared.Damage.Components; /// -/// Multiplies the entity's by the . +/// Multiplies the entity's by the . /// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(StaminaSystem))] public sealed partial class StaminaModifierComponent : Component diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index a5c8a4b38d..87df2e995c 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Damage.Components; using Content.Shared.Damage.Events; using Content.Shared.Database; +using Content.Shared.Crawling; using Content.Shared.Effects; using Content.Shared.IdentityManagement; using Content.Shared.Popups; @@ -30,6 +31,7 @@ public sealed partial class StaminaSystem : EntitySystem [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly AlertsSystem _alerts = default!; + [Dependency] private readonly CrawlingSystem _crawling = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; [Dependency] private readonly SharedStunSystem _stunSystem = default!; @@ -63,13 +65,17 @@ public override void Initialize() private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref AfterAutoHandleStateEvent args) { if (component.Critical) - EnterStamCrit(uid, component); + EnterStamCrit(uid, component, false); else { - if (component.StaminaDamage > 0f) + + if (component.SoftStaminaDamage > 0f || component.HardStaminaDamage > 0f) EnsureComp(uid); - ExitStamCrit(uid, component); + if (component.Crawling) + EnterStamCrit(uid, component, true); + else + ExitStamCrit(uid, component, true); } } @@ -88,24 +94,43 @@ private void OnStartup(EntityUid uid, StaminaComponent component, ComponentStart } [PublicAPI] - public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null) + public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component)) return 0f; + float stamina; + + switch (soft) + { + case true: + stamina = component.SoftStaminaDamage; + break; + + case false: + stamina = component.HardStaminaDamage; + break; + } + var curTime = _timing.CurTime; var pauseTime = _metadata.GetPauseTime(uid); - return MathF.Max(0f, component.StaminaDamage - MathF.Max(0f, (float) (curTime - (component.NextUpdate + pauseTime)).TotalSeconds * component.Decay)); + return MathF.Max(0f, stamina - 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) + if (component.HardStaminaDamage >= component.CritThreshold) + { + ExitStamCrit(uid, component, false); + } + + if (component.SoftStaminaDamage >= component.CritThreshold) { - ExitStamCrit(uid, component); + ExitStamCrit(uid, component, true); } - component.StaminaDamage = 0; + component.SoftStaminaDamage = 0; + component.HardStaminaDamage = 0; RemComp(uid); SetStaminaAlert(uid, component); Dirty(uid, component); @@ -116,14 +141,17 @@ private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent if (args.Handled) return; - if (component.Critical) + if (component.Crawling) + { + args.Handled = true; return; + } var damage = args.PushProbability * component.CritThreshold; - TakeStaminaDamage(uid, damage, component, source: args.Source); + TakeStaminaDamage(uid, damage, component, source: args.Source, soft: true); args.PopupPrefix = "disarm-action-shove-"; - args.IsStunned = component.Critical; + args.IsStunned = component.Crawling; args.Handled = true; } @@ -168,7 +196,7 @@ private void OnMeleeHit(EntityUid uid, StaminaDamageOnHitComponent component, Me foreach (var (ent, comp) in toHit) { - TakeStaminaDamage(ent, damage / toHit.Count, comp, source: args.User, with: args.Weapon, sound: component.Sound); + TakeStaminaDamage(ent, damage / toHit.Count, comp, source: args.User, args.Weapon, component.Soft, sound: component.Sound); } } @@ -182,7 +210,7 @@ private void OnProjectileEmbed(EntityUid uid, StaminaDamageOnEmbedComponent comp if (!TryComp(args.Embedded, out var stamina)) return; - TakeStaminaDamage(args.Embedded, component.Damage, stamina, source: uid); + TakeStaminaDamage(args.Embedded, component.Damage, stamina, uid, soft: component.Soft); } private void OnThrowHit(EntityUid uid, StaminaDamageOnCollideComponent component, ThrowDoHitEvent args) @@ -202,7 +230,7 @@ private void OnCollide(EntityUid uid, StaminaDamageOnCollideComponent component, if (ev.Cancelled) return; - TakeStaminaDamage(target, component.Damage, source: uid, sound: component.Sound); + TakeStaminaDamage(target, component.Damage, source: uid, soft: component.Soft, sound: component.Sound); } private void SetStaminaAlert(EntityUid uid, StaminaComponent? component = null) @@ -210,30 +238,38 @@ private void SetStaminaAlert(EntityUid uid, StaminaComponent? component = null) if (!Resolve(uid, ref component, false) || component.Deleted) return; - var severity = ContentHelpers.RoundToLevels(MathF.Max(0f, component.CritThreshold - component.StaminaDamage), component.CritThreshold, 7); + double severity = ContentHelpers.RoundToLevels(MathF.Max(0f, component.CritThreshold - component.SoftStaminaDamage), component.CritThreshold, 7) / 2; + + if (component.HardStaminaDamage > 0f) + severity += ContentHelpers.RoundToLevels(MathF.Max(0f, component.CritThreshold - component.HardStaminaDamage), component.CritThreshold, 7) / 2; + + severity = Math.Round(severity); + _alerts.ShowAlert(uid, component.StaminaAlert, (short) severity); } /// /// Tries to take stamina damage without raising the entity over the crit threshold. /// - public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null) + public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null, bool soft = true) { // Something that has no Stamina component automatically passes stamina checks if (!Resolve(uid, ref component, false)) return true; - var oldStam = component.StaminaDamage; - - if (oldStam + value > component.CritThreshold || component.Critical) + if (component.HardStaminaDamage + value > component.CritThreshold || component.Critical) return false; - TakeStaminaDamage(uid, value, component, source, with, visual: false); + // start dealing hard stam now + if (component.SoftStaminaDamage + value > component.CritThreshold || component.Crawling) + soft = false; + + TakeStaminaDamage(uid, value, component, source, with, visual: false, soft); return true; } public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, - EntityUid? source = null, EntityUid? with = null, bool visual = true, SoundSpecifier? sound = null) + EntityUid? source = null, EntityUid? with = null, bool visual = true, bool soft = true, SoundSpecifier? sound = null) { if (!Resolve(uid, ref component, false)) return; @@ -247,11 +283,31 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp if (component.Critical) return; - var oldDamage = component.StaminaDamage; - component.StaminaDamage = MathF.Max(0f, component.StaminaDamage + value); + // if softstam is reached deal hard stun instead + if (soft && component.SoftStaminaDamage >= component.CritThreshold) + soft = false; + + float oldDamage; + float currentDamage; + + switch (soft) + { + case true: + oldDamage = component.SoftStaminaDamage; + component.SoftStaminaDamage = MathF.Max(0f, component.SoftStaminaDamage + value); + currentDamage = component.SoftStaminaDamage; + break; + + case false: + oldDamage = component.HardStaminaDamage; + component.HardStaminaDamage = MathF.Max(0f, component.HardStaminaDamage + value); + currentDamage = component.HardStaminaDamage; + component.SoftStaminaDamage = component.CritThreshold; + break; + } // Reset the decay cooldown upon taking damage. - if (oldDamage < component.StaminaDamage) + if (oldDamage < currentDamage) { var nextUpdate = _timing.CurTime + TimeSpan.FromSeconds(component.Cooldown); @@ -263,25 +319,41 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp // If we go above n% then apply slowdown if (oldDamage < slowdownThreshold && - component.StaminaDamage > slowdownThreshold) + component.HardStaminaDamage < 0 && + component.SoftStaminaDamage > slowdownThreshold) { _stunSystem.TrySlowdown(uid, TimeSpan.FromSeconds(3), true, 0.8f, 0.8f); } SetStaminaAlert(uid, component); + if (!component.Crawling) + { + if (component.SoftStaminaDamage >= component.CritThreshold) + { + EnterStamCrit(uid, component, true); + } + } + else + { + if (component.SoftStaminaDamage < component.CritThreshold) + { + ExitStamCrit(uid, component, true); + } + } + if (!component.Critical) { - if (component.StaminaDamage >= component.CritThreshold) + if (component.HardStaminaDamage >= component.CritThreshold) { - EnterStamCrit(uid, component); + EnterStamCrit(uid, component, false); } } else { - if (component.StaminaDamage < component.CritThreshold) + if (component.HardStaminaDamage < component.CritThreshold) { - ExitStamCrit(uid, component); + ExitStamCrit(uid, component, false); } } @@ -325,7 +397,8 @@ public override void Update(float frameTime) { // Just in case we have active but not stamina we'll check and account for it. if (!stamQuery.TryGetComponent(uid, out var comp) || - comp.StaminaDamage <= 0f && !comp.Critical) + comp.SoftStaminaDamage <= 0f && !comp.Crawling && + comp.HardStaminaDamage <= 0f && !comp.Critical) { RemComp(uid); continue; @@ -338,19 +411,27 @@ public override void Update(float frameTime) continue; // We were in crit so come out of it and continue. - if (comp.Critical) + if (comp.Critical && comp.HardStaminaDamage <= comp.CritThreshold) + { + ExitStamCrit(uid, comp, false); + continue; + } + + bool soft = comp.HardStaminaDamage <= 0; + + if (soft && comp.Crawling && comp.SoftStaminaDamage <= comp.CritThreshold) { - ExitStamCrit(uid, comp); + ExitStamCrit(uid, comp, true); continue; } comp.NextUpdate += TimeSpan.FromSeconds(1f); - TakeStaminaDamage(uid, -comp.Decay, comp); + TakeStaminaDamage(uid, comp.Decay * -1, comp, soft: soft); Dirty(uid, comp); } } - private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null) + private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || component.Critical) @@ -361,10 +442,37 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null) // To make the difference between a stun and a stamcrit clear // TODO: Mask? - component.Critical = true; - component.StaminaDamage = component.CritThreshold; - - _stunSystem.TryParalyze(uid, component.StunTime, true); + switch (soft) + { + case true: + { + if (!TryComp(uid, out var crawlerComp)) + goto case false; + + if (!HasComp(uid)) + { + _crawling.SetCrawling(uid, crawlerComp, true); + } + + component.Critical = false; + component.Crawling = true; + component.HardStaminaDamage = 0f; + break; + } + case false: + { + if (TryComp(uid, out var crawlerComp) && HasComp(uid)) + { + _crawling.SetCrawling(uid, crawlerComp, false); + } + + component.Critical = true; + component.Crawling = false; + component.HardStaminaDamage = component.CritThreshold; + _stunSystem.TryParalyze(uid, component.StunTime, true); + break; + } + } // Give them buffer before being able to be re-stunned component.NextUpdate = _timing.CurTime + component.StunTime + StamCritBufferTime; @@ -373,19 +481,39 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null) _adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} entered stamina crit"); } - private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null) + private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || - !component.Critical) + !(component.Crawling || component.Critical)) { return; } - component.Critical = false; - component.StaminaDamage = 0f; + switch (soft) + { + case true: + { + component.Crawling = false; + component.HardStaminaDamage = 0f; + RemComp(uid); + + if (TryComp(uid, out var crawlerComp) && HasComp(uid)) + { + _crawling.SetCrawling(uid, crawlerComp, false); + } + break; + } + case false: + { + component.SoftStaminaDamage = component.CritThreshold; + EnterStamCrit(uid, component, true); + break; + } + + } + component.NextUpdate = _timing.CurTime; SetStaminaAlert(uid, component); - RemComp(uid); Dirty(uid, component); _adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit"); } From a1d31a1a7bc3029671127f744c30edcfae6ba892 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Mon, 9 Sep 2024 04:50:41 +0100 Subject: [PATCH 2/9] disallow getting up when soft stunned --- Content.Shared/Crawling/CrawlingSystem.cs | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Crawling/CrawlingSystem.cs b/Content.Shared/Crawling/CrawlingSystem.cs index 4e253a677f..afd4fb0a12 100644 --- a/Content.Shared/Crawling/CrawlingSystem.cs +++ b/Content.Shared/Crawling/CrawlingSystem.cs @@ -1,4 +1,6 @@ using Content.Shared.Buckle.Components; +using Content.Shared.Damage.Components; +using Content.Shared.Damage.Systems; using Content.Shared.DoAfter; using Content.Shared.Explosion; using Content.Shared.Input; @@ -17,6 +19,8 @@ public sealed partial class CrawlingSystem : EntitySystem [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; [Dependency] private readonly AlertsSystem _alerts = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; + public override void Initialize() { base.Initialize(); @@ -39,6 +43,17 @@ public override void Initialize() .Register(); } + private bool IsSoftStunned(EntityUid uid) + { + if (!TryComp(uid, out var stamComp)) + return false; + + if (stamComp.SoftStaminaDamage >= stamComp.CritThreshold) + return true; + + return false; + } + private void ToggleCrawlingKeybind(ICommonSession? session) { if (session?.AttachedEntity == null) @@ -51,17 +66,28 @@ private void ToggleCrawling(EntityUid uid, CrawlerComponent component, CrawlingK { if (args.Cancelled) return; + + if (IsSoftStunned(uid) && _standing.IsDown(uid)) + { + args.Cancelled = true; + return; + } + SetCrawling(uid, component, !_standing.IsDown(uid)); } + public void SetCrawling(EntityUid uid, CrawlerComponent component, bool state) { - ///checks players standing state, downing player if they are standding and starts doafter with standing up if they are downed + //checks players standing state, downing player if they are standing and starts doafter with standing up if they are downed switch (state) { case true: _standing.Down(uid, dropHeldItems: false); break; case false: + if (IsSoftStunned(uid)) + return; + _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, uid, component.StandUpTime, new CrawlStandupDoAfterEvent(), uid, used: uid) { From 681452edb0a84142ccf4cd0957af502cedded930 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Mon, 9 Sep 2024 05:40:04 +0100 Subject: [PATCH 3/9] fix standing up after stun --- Content.Shared/Stunnable/SharedStunSystem.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 092da8fe5a..25c447edfe 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; +using Content.Shared.Crawling; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; @@ -106,12 +107,14 @@ private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEven private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { - _standingState.Down(uid); + if (!HasComp(uid)) + _standingState.Down(uid); } private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) { - _standingState.Stand(uid); + if (!HasComp(uid)) + _standingState.Stand(uid); } private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args) From 5b97d419b81fd43eaf657c584380a50a0f378d25 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:06:50 +0100 Subject: [PATCH 4/9] replace 2 bools with enum --- .../Damage/Components/StaminaComponent.cs | 17 +-- .../Damage/Systems/StaminaSystem.cs | 129 +++++++++--------- .../Weapons/Reflect/ReflectSystem.cs | 4 +- 3 files changed, 73 insertions(+), 77 deletions(-) diff --git a/Content.Shared/Damage/Components/StaminaComponent.cs b/Content.Shared/Damage/Components/StaminaComponent.cs index fe5b7061aa..f2006e4cea 100644 --- a/Content.Shared/Damage/Components/StaminaComponent.cs +++ b/Content.Shared/Damage/Components/StaminaComponent.cs @@ -13,16 +13,10 @@ public sealed partial class StaminaComponent : Component { /// - /// Have we reached peak soft stamina damage and been forced to crawl? + /// Have we reached peak stamina damage and been paralyzed or crawling? /// [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public bool Crawling; - - /// - /// Have we reached peak stamina damage and been paralyzed? - /// - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public bool Critical; + public StunnedState State; /// /// How much stamina reduces per second. @@ -70,3 +64,10 @@ public sealed partial class StaminaComponent : Component [DataField] public ProtoId StaminaAlert = "Stamina"; } + +public enum StunnedState +{ + None, + Crawling, + Critical +} diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 87df2e995c..1d99768517 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -64,19 +64,23 @@ public override void Initialize() private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref AfterAutoHandleStateEvent args) { - if (component.Critical) + if (component.State == StunnedState.Critical + || component.HardStaminaDamage > component.CritThreshold) + { EnterStamCrit(uid, component, false); + } + else if (component.State == StunnedState.Crawling + || component.SoftStaminaDamage > component.CritThreshold) + { + EnterStamCrit(uid, component, true); + } else { - - if (component.SoftStaminaDamage > 0f || component.HardStaminaDamage > 0f) - EnsureComp(uid); - - if (component.Crawling) - EnterStamCrit(uid, component, true); - else - ExitStamCrit(uid, component, true); + ExitStamCrit(uid, component, true); } + + if (component.SoftStaminaDamage > 0f || component.HardStaminaDamage > 0f) + EnsureComp(uid); } private void OnShutdown(EntityUid uid, StaminaComponent component, ComponentShutdown args) @@ -119,12 +123,14 @@ public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null, private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args) { - if (component.HardStaminaDamage >= component.CritThreshold) + if (component.State == StunnedState.Critical || + component.HardStaminaDamage >= component.CritThreshold) { ExitStamCrit(uid, component, false); } - if (component.SoftStaminaDamage >= component.CritThreshold) + if (component.State == StunnedState.Crawling || + component.SoftStaminaDamage>= component.CritThreshold) { ExitStamCrit(uid, component, true); } @@ -141,7 +147,7 @@ private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent if (args.Handled) return; - if (component.Crawling) + if (component.State != StunnedState.None) { args.Handled = true; return; @@ -151,7 +157,7 @@ private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent TakeStaminaDamage(uid, damage, component, source: args.Source, soft: true); args.PopupPrefix = "disarm-action-shove-"; - args.IsStunned = component.Crawling; + args.IsStunned = component.State == StunnedState.Crawling; args.Handled = true; } @@ -238,14 +244,18 @@ private void SetStaminaAlert(EntityUid uid, StaminaComponent? component = null) if (!Resolve(uid, ref component, false) || component.Deleted) return; - double severity = ContentHelpers.RoundToLevels(MathF.Max(0f, component.CritThreshold - component.SoftStaminaDamage), component.CritThreshold, 7) / 2; + float severity; + + if (component.State != StunnedState.None) + severity = component.CritThreshold - component.HardStaminaDamage; + else + severity = component.CritThreshold - component.SoftStaminaDamage; - if (component.HardStaminaDamage > 0f) - severity += ContentHelpers.RoundToLevels(MathF.Max(0f, component.CritThreshold - component.HardStaminaDamage), component.CritThreshold, 7) / 2; + double level = ContentHelpers.RoundToLevels(severity, component.CritThreshold, 7); - severity = Math.Round(severity); + level = Math.Round(level); - _alerts.ShowAlert(uid, component.StaminaAlert, (short) severity); + _alerts.ShowAlert(uid, component.StaminaAlert, (short) level); } /// @@ -257,11 +267,13 @@ public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? compone if (!Resolve(uid, ref component, false)) return true; - if (component.HardStaminaDamage + value > component.CritThreshold || component.Critical) + if (component.HardStaminaDamage + value > component.CritThreshold || + component.State == StunnedState.Critical) return false; // start dealing hard stam now - if (component.SoftStaminaDamage + value > component.CritThreshold || component.Crawling) + if (component.SoftStaminaDamage + value > component.CritThreshold || + component.State == StunnedState.Crawling) soft = false; TakeStaminaDamage(uid, value, component, source, with, visual: false, soft); @@ -279,27 +291,32 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp if (ev.Cancelled) return; - // Have we already reached the point of max stamina damage? - if (component.Critical) + bool isPositive = value > 0; + + // we want to still allow subtracting stamina so they recover + if (component.State == StunnedState.Critical && isPositive) return; + bool softModified = false; + // if softstam is reached deal hard stun instead - if (soft && component.SoftStaminaDamage >= component.CritThreshold) + // we still want to deal hard stun even when they are crit + if (soft && component.State != StunnedState.None && isPositive) + { soft = false; + softModified = true; + } - float oldDamage; float currentDamage; switch (soft) { case true: - oldDamage = component.SoftStaminaDamage; component.SoftStaminaDamage = MathF.Max(0f, component.SoftStaminaDamage + value); currentDamage = component.SoftStaminaDamage; break; case false: - oldDamage = component.HardStaminaDamage; component.HardStaminaDamage = MathF.Max(0f, component.HardStaminaDamage + value); currentDamage = component.HardStaminaDamage; component.SoftStaminaDamage = component.CritThreshold; @@ -307,7 +324,7 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp } // Reset the decay cooldown upon taking damage. - if (oldDamage < currentDamage) + if (isPositive) { var nextUpdate = _timing.CurTime + TimeSpan.FromSeconds(component.Cooldown); @@ -318,43 +335,22 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp var slowdownThreshold = component.CritThreshold / 2f; // If we go above n% then apply slowdown - if (oldDamage < slowdownThreshold && - component.HardStaminaDamage < 0 && - component.SoftStaminaDamage > slowdownThreshold) + if (currentDamage < slowdownThreshold && + component.State == StunnedState.None) { _stunSystem.TrySlowdown(uid, TimeSpan.FromSeconds(3), true, 0.8f, 0.8f); } SetStaminaAlert(uid, component); - if (!component.Crawling) - { - if (component.SoftStaminaDamage >= component.CritThreshold) - { - EnterStamCrit(uid, component, true); - } - } - else - { - if (component.SoftStaminaDamage < component.CritThreshold) - { - ExitStamCrit(uid, component, true); - } - } - - if (!component.Critical) + if (currentDamage > component.CritThreshold && component.State != StunnedState.Critical) { - if (component.HardStaminaDamage >= component.CritThreshold) - { - EnterStamCrit(uid, component, false); - } + EnterStamCrit(uid, component, soft); } - else + else if (currentDamage < component.CritThreshold && component.State != StunnedState.None + && !softModified) //wont end up putting user into crit as first hit after crawling will always pass ending immedietly { - if (component.HardStaminaDamage < component.CritThreshold) - { - ExitStamCrit(uid, component, false); - } + ExitStamCrit(uid, component, soft); } EnsureComp(uid); @@ -397,8 +393,7 @@ public override void Update(float frameTime) { // Just in case we have active but not stamina we'll check and account for it. if (!stamQuery.TryGetComponent(uid, out var comp) || - comp.SoftStaminaDamage <= 0f && !comp.Crawling && - comp.HardStaminaDamage <= 0f && !comp.Critical) + (comp.State == StunnedState.None && comp.SoftStaminaDamage <= 0)) { RemComp(uid); continue; @@ -411,15 +406,15 @@ public override void Update(float frameTime) continue; // We were in crit so come out of it and continue. - if (comp.Critical && comp.HardStaminaDamage <= comp.CritThreshold) + if (comp.State == StunnedState.Critical && comp.HardStaminaDamage <= comp.CritThreshold) { ExitStamCrit(uid, comp, false); continue; } - bool soft = comp.HardStaminaDamage <= 0; + bool soft = comp.SoftStaminaDamage < comp.CritThreshold; - if (soft && comp.Crawling && comp.SoftStaminaDamage <= comp.CritThreshold) + if (soft) { ExitStamCrit(uid, comp, true); continue; @@ -434,7 +429,7 @@ public override void Update(float frameTime) private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || - component.Critical) + component.State == StunnedState.Critical) { return; } @@ -454,8 +449,7 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo _crawling.SetCrawling(uid, crawlerComp, true); } - component.Critical = false; - component.Crawling = true; + component.State = StunnedState.Crawling; component.HardStaminaDamage = 0f; break; } @@ -466,8 +460,7 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo _crawling.SetCrawling(uid, crawlerComp, false); } - component.Critical = true; - component.Crawling = false; + component.State = StunnedState.Critical; component.HardStaminaDamage = component.CritThreshold; _stunSystem.TryParalyze(uid, component.StunTime, true); break; @@ -484,7 +477,7 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || - !(component.Crawling || component.Critical)) + component.State == StunnedState.None) { return; } @@ -493,8 +486,9 @@ private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, boo { case true: { - component.Crawling = false; + component.State = StunnedState.None; component.HardStaminaDamage = 0f; + component.SoftStaminaDamage = component.CritThreshold; RemComp(uid); if (TryComp(uid, out var crawlerComp) && HasComp(uid)) @@ -505,6 +499,7 @@ private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, boo } case false: { + component.State = StunnedState.Crawling; component.SoftStaminaDamage = component.CritThreshold; EnterStamCrit(uid, component, true); break; diff --git a/Content.Shared/Weapons/Reflect/ReflectSystem.cs b/Content.Shared/Weapons/Reflect/ReflectSystem.cs index 79fc12fd82..62b7b88e3a 100644 --- a/Content.Shared/Weapons/Reflect/ReflectSystem.cs +++ b/Content.Shared/Weapons/Reflect/ReflectSystem.cs @@ -157,7 +157,7 @@ private bool TryReflectProjectile(EntityUid user, Entity refle // Is the projectile correctly set up with physics? !TryComp(projectile, out var physics) || // If the user of the reflector is a mob with stamina, is it capable of deflecting? - TryComp(user, out var staminaComponent) && staminaComponent.Critical || + TryComp(user, out var staminaComponent) && staminaComponent.State == StunnedState.Critical || _standing.IsDown(reflector) ) return false; @@ -208,7 +208,7 @@ private bool TryReflectHitscan( // Is the reflector enabled? !_toggle.IsActivated(user) || // If the user is a mob with stamina, is it capable of deflecting? - TryComp(user, out var staminaComponent) && staminaComponent.Critical || + TryComp(user, out var staminaComponent) && staminaComponent.State == StunnedState.Critical || _standing.IsDown(user)) { newDirection = null; From e09bf4b6cb4731661feee8851cbe44183e218a4f Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:08:12 +0100 Subject: [PATCH 5/9] merge 2 damage floats --- Content.Shared/Crawling/CrawlingSystem.cs | 2 +- .../Damage/Components/StaminaComponent.cs | 10 +- .../Damage/Systems/StaminaSystem.cs | 129 ++++++++++-------- Content.Shared/Stunnable/SharedStunSystem.cs | 5 +- 4 files changed, 75 insertions(+), 71 deletions(-) diff --git a/Content.Shared/Crawling/CrawlingSystem.cs b/Content.Shared/Crawling/CrawlingSystem.cs index afd4fb0a12..729b223aaa 100644 --- a/Content.Shared/Crawling/CrawlingSystem.cs +++ b/Content.Shared/Crawling/CrawlingSystem.cs @@ -48,7 +48,7 @@ private bool IsSoftStunned(EntityUid uid) if (!TryComp(uid, out var stamComp)) return false; - if (stamComp.SoftStaminaDamage >= stamComp.CritThreshold) + if (stamComp.State != StunnedState.None) return true; return false; diff --git a/Content.Shared/Damage/Components/StaminaComponent.cs b/Content.Shared/Damage/Components/StaminaComponent.cs index f2006e4cea..953203d197 100644 --- a/Content.Shared/Damage/Components/StaminaComponent.cs +++ b/Content.Shared/Damage/Components/StaminaComponent.cs @@ -31,16 +31,10 @@ public sealed partial class StaminaComponent : Component public float Cooldown = 3f; /// - /// How much soft (makes them crawl) stamina damage this entity has taken. + /// How much stamina damage this entity has taken. /// [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public float SoftStaminaDamage; - - /// - /// How much hard (makes them static on the floor) stamina damage this entity has taken. - /// - [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] - public float HardStaminaDamage; + public float StaminaDamage; /// /// How much stamina damage is required to entire stam crit. diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 1d99768517..696d79ba77 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -25,6 +25,13 @@ namespace Content.Shared.Damage.Systems; +sealed class StaminaRecievers +{ + public EntityUid Uid { get; set; } + public StaminaComponent? Component { get; set; } + public StunnedState State { get; set; } +} + public sealed partial class StaminaSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; @@ -64,13 +71,12 @@ public override void Initialize() private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref AfterAutoHandleStateEvent args) { - if (component.State == StunnedState.Critical - || component.HardStaminaDamage > component.CritThreshold) + if (component.State == StunnedState.Critical && component.StaminaDamage > component.CritThreshold) { EnterStamCrit(uid, component, false); } else if (component.State == StunnedState.Crawling - || component.SoftStaminaDamage > component.CritThreshold) + && component.StaminaDamage > component.CritThreshold) { EnterStamCrit(uid, component, true); } @@ -79,7 +85,7 @@ private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref Af ExitStamCrit(uid, component, true); } - if (component.SoftStaminaDamage > 0f || component.HardStaminaDamage > 0f) + if (component.StaminaDamage > 0f) EnsureComp(uid); } @@ -103,18 +109,7 @@ public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null, if (!Resolve(uid, ref component)) return 0f; - float stamina; - - switch (soft) - { - case true: - stamina = component.SoftStaminaDamage; - break; - - case false: - stamina = component.HardStaminaDamage; - break; - } + float stamina = component.StaminaDamage; var curTime = _timing.CurTime; var pauseTime = _metadata.GetPauseTime(uid); @@ -123,20 +118,19 @@ public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null, private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args) { - if (component.State == StunnedState.Critical || - component.HardStaminaDamage >= component.CritThreshold) + if (component.State == StunnedState.Critical && + component.StaminaDamage >= component.CritThreshold) { ExitStamCrit(uid, component, false); } - if (component.State == StunnedState.Crawling || - component.SoftStaminaDamage>= component.CritThreshold) + if (component.State == StunnedState.Crawling && + component.StaminaDamage>= component.CritThreshold) { ExitStamCrit(uid, component, true); } - component.SoftStaminaDamage = 0; - component.HardStaminaDamage = 0; + component.StaminaDamage = 0; RemComp(uid); SetStaminaAlert(uid, component); Dirty(uid, component); @@ -244,12 +238,7 @@ private void SetStaminaAlert(EntityUid uid, StaminaComponent? component = null) if (!Resolve(uid, ref component, false) || component.Deleted) return; - float severity; - - if (component.State != StunnedState.None) - severity = component.CritThreshold - component.HardStaminaDamage; - else - severity = component.CritThreshold - component.SoftStaminaDamage; + float severity = component.CritThreshold - component.StaminaDamage; double level = ContentHelpers.RoundToLevels(severity, component.CritThreshold, 7); @@ -267,12 +256,12 @@ public bool TryTakeStamina(EntityUid uid, float value, StaminaComponent? compone if (!Resolve(uid, ref component, false)) return true; - if (component.HardStaminaDamage + value > component.CritThreshold || + if (component.StaminaDamage + value > component.CritThreshold && component.State == StunnedState.Critical) return false; // start dealing hard stam now - if (component.SoftStaminaDamage + value > component.CritThreshold || + if (component.StaminaDamage + value > component.CritThreshold && component.State == StunnedState.Crawling) soft = false; @@ -307,21 +296,7 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp softModified = true; } - float currentDamage; - - switch (soft) - { - case true: - component.SoftStaminaDamage = MathF.Max(0f, component.SoftStaminaDamage + value); - currentDamage = component.SoftStaminaDamage; - break; - - case false: - component.HardStaminaDamage = MathF.Max(0f, component.HardStaminaDamage + value); - currentDamage = component.HardStaminaDamage; - component.SoftStaminaDamage = component.CritThreshold; - break; - } + component.StaminaDamage = MathF.Max(0f, component.StaminaDamage + value); // Reset the decay cooldown upon taking damage. if (isPositive) @@ -335,7 +310,7 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp var slowdownThreshold = component.CritThreshold / 2f; // If we go above n% then apply slowdown - if (currentDamage < slowdownThreshold && + if (component.StaminaDamage < slowdownThreshold && component.State == StunnedState.None) { _stunSystem.TrySlowdown(uid, TimeSpan.FromSeconds(3), true, 0.8f, 0.8f); @@ -343,11 +318,11 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp SetStaminaAlert(uid, component); - if (currentDamage > component.CritThreshold && component.State != StunnedState.Critical) + if (component.StaminaDamage > component.CritThreshold && component.State != StunnedState.Critical) { EnterStamCrit(uid, component, soft); } - else if (currentDamage < component.CritThreshold && component.State != StunnedState.None + else if (component.StaminaDamage < component.CritThreshold && component.State != StunnedState.None && !softModified) //wont end up putting user into crit as first hit after crawling will always pass ending immedietly { ExitStamCrit(uid, component, soft); @@ -389,11 +364,13 @@ public override void Update(float frameTime) var query = EntityQueryEnumerator(); var curTime = _timing.CurTime; + List toRemove = new(); + while (query.MoveNext(out var uid, out _)) { // Just in case we have active but not stamina we'll check and account for it. if (!stamQuery.TryGetComponent(uid, out var comp) || - (comp.State == StunnedState.None && comp.SoftStaminaDamage <= 0)) + (comp.State == StunnedState.None && comp.StaminaDamage <= 0)) { RemComp(uid); continue; @@ -406,24 +383,58 @@ public override void Update(float frameTime) continue; // We were in crit so come out of it and continue. - if (comp.State == StunnedState.Critical && comp.HardStaminaDamage <= comp.CritThreshold) + if (comp.State == StunnedState.Critical && comp.StaminaDamage <= comp.CritThreshold) { - ExitStamCrit(uid, comp, false); + toRemove.Add(new StaminaRecievers + { + Uid = uid, + Component = comp, + State = StunnedState.Critical + }); + continue; } - bool soft = comp.SoftStaminaDamage < comp.CritThreshold; + bool soft = comp.State != StunnedState.None && comp.StaminaDamage < comp.CritThreshold; + + comp.NextUpdate += TimeSpan.FromSeconds(1f); + // cant modify in the for loop if (soft) { - ExitStamCrit(uid, comp, true); + toRemove.Add(new StaminaRecievers + { + Uid = uid, + Component = comp, + State = StunnedState.Crawling + }); + + Dirty(uid, comp); continue; } - comp.NextUpdate += TimeSpan.FromSeconds(1f); TakeStaminaDamage(uid, comp.Decay * -1, comp, soft: soft); + Dirty(uid, comp); } + + foreach (var i in toRemove) + { + var uid = i.Uid; + var comp = i.Component; + + if (comp == null) + continue; + + if (i.State == StunnedState.Critical) + { + ExitStamCrit(uid, comp, false); + } + else if (i.State == StunnedState.Crawling) + { + TakeStaminaDamage(uid, comp.Decay * -1, comp, soft: true); + } + } } private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) @@ -450,7 +461,7 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo } component.State = StunnedState.Crawling; - component.HardStaminaDamage = 0f; + component.StaminaDamage = 0f; break; } case false: @@ -461,7 +472,6 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo } component.State = StunnedState.Critical; - component.HardStaminaDamage = component.CritThreshold; _stunSystem.TryParalyze(uid, component.StunTime, true); break; } @@ -487,8 +497,8 @@ private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, boo case true: { component.State = StunnedState.None; - component.HardStaminaDamage = 0f; - component.SoftStaminaDamage = component.CritThreshold; + component.StaminaDamage = component.CritThreshold; + component.StaminaDamage = 0f; RemComp(uid); if (TryComp(uid, out var crawlerComp) && HasComp(uid)) @@ -500,11 +510,10 @@ private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, boo case false: { component.State = StunnedState.Crawling; - component.SoftStaminaDamage = component.CritThreshold; + component.StaminaDamage = component.CritThreshold - 1; EnterStamCrit(uid, component, true); break; } - } component.NextUpdate = _timing.CurTime; diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 25c447edfe..d5614d4968 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.ActionBlocker; using Content.Shared.Administration.Logs; using Content.Shared.Crawling; +using Content.Shared.Damage.Components; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; @@ -107,13 +108,13 @@ private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEven private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { - if (!HasComp(uid)) + if (!HasComp(uid) && HasComp(uid)) _standingState.Down(uid); } private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) { - if (!HasComp(uid)) + if (!HasComp(uid) && HasComp(uid)) _standingState.Stand(uid); } From f6942f8b409791bbc3344fff40cd0d91b14e1b2c Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:59:37 +0100 Subject: [PATCH 6/9] fix slipping --- Content.Shared/Crawling/CrawlingSystem.cs | 3 -- .../Damage/Systems/StaminaSystem.cs | 10 ++-- Content.Shared/Stunnable/SharedStunSystem.cs | 50 ++++++++++++++++++- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/Content.Shared/Crawling/CrawlingSystem.cs b/Content.Shared/Crawling/CrawlingSystem.cs index 729b223aaa..a5e4bd7182 100644 --- a/Content.Shared/Crawling/CrawlingSystem.cs +++ b/Content.Shared/Crawling/CrawlingSystem.cs @@ -85,9 +85,6 @@ public void SetCrawling(EntityUid uid, CrawlerComponent component, bool state) _standing.Down(uid, dropHeldItems: false); break; case false: - if (IsSoftStunned(uid)) - return; - _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, uid, component.StandUpTime, new CrawlStandupDoAfterEvent(), uid, used: uid) { diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 696d79ba77..966e2d5e98 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -437,7 +437,7 @@ public override void Update(float frameTime) } } - private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) + public void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || component.State == StunnedState.Critical) @@ -462,15 +462,11 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo component.State = StunnedState.Crawling; component.StaminaDamage = 0f; + _stunSystem.TryKnockdown(uid, component.StunTime / 2, true); break; } case false: { - if (TryComp(uid, out var crawlerComp) && HasComp(uid)) - { - _crawling.SetCrawling(uid, crawlerComp, false); - } - component.State = StunnedState.Critical; _stunSystem.TryParalyze(uid, component.StunTime, true); break; @@ -484,7 +480,7 @@ private void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, bo _adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} entered stamina crit"); } - private void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) + public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) { if (!Resolve(uid, ref component) || component.State == StunnedState.None) diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index d5614d4968..89b2d8f539 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -17,6 +17,7 @@ using Content.Shared.StatusEffect; using Content.Shared.Throwing; using Robust.Shared.Audio.Systems; +using Content.Shared.Damage.Systems; namespace Content.Shared.Stunnable; @@ -26,6 +27,7 @@ public abstract class SharedStunSystem : EntitySystem [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; [Dependency] private readonly StandingStateSystem _standingState = default!; [Dependency] private readonly StatusEffectsSystem _statusEffect = default!; @@ -108,14 +110,58 @@ private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEven private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { - if (!HasComp(uid) && HasComp(uid)) + bool? soft = null; + StaminaComponent? staminaComponent = null; + + if (HasComp(uid)) + (soft, staminaComponent) = IsSoftStunned(uid); + + if (soft != null) + { + _stamina.EnterStamCrit(uid, staminaComponent, soft.Value); + } + else + { _standingState.Down(uid); + } } private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) { - if (!HasComp(uid) && HasComp(uid)) + bool? soft = null; + StaminaComponent? staminaComponent = null; + + if (HasComp(uid)) + (soft, staminaComponent) = IsSoftStunned(uid); + + if (soft != null) + { + _stamina.ExitStamCrit(uid, staminaComponent, soft.Value); + } + else + { _standingState.Stand(uid); + } + } + + private (bool?, StaminaComponent?) IsSoftStunned(EntityUid uid) + { + if (HasComp(uid) && + TryComp(uid, out var staminaComponent)) + { + switch (staminaComponent.State) + { + case StunnedState.Crawling: + return (true, staminaComponent); + case StunnedState.Critical: + return (false, staminaComponent); + default: + case StunnedState.None: + return (null, staminaComponent); + } + } + + return (null, null); } private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args) From 562d62b81f2794c32ab829f23bf451438b82cef5 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:43:03 +0100 Subject: [PATCH 7/9] fix crawling mispredict --- Content.Shared/Crawling/CrawlingSystem.cs | 19 ++++++++++++------- .../Damage/Systems/StaminaSystem.cs | 7 ++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Content.Shared/Crawling/CrawlingSystem.cs b/Content.Shared/Crawling/CrawlingSystem.cs index a5e4bd7182..52155897e9 100644 --- a/Content.Shared/Crawling/CrawlingSystem.cs +++ b/Content.Shared/Crawling/CrawlingSystem.cs @@ -28,7 +28,6 @@ public override void Initialize() SubscribeLocalEvent(OnDoAfter); SubscribeLocalEvent(OnStandUp); SubscribeLocalEvent(OnFall); - SubscribeLocalEvent(OnStunned); SubscribeLocalEvent(OnBuckled); SubscribeLocalEvent(OnGetExplosionResistance); SubscribeLocalEvent(OnCrawlingAlertEvent); @@ -82,15 +81,27 @@ public void SetCrawling(EntityUid uid, CrawlerComponent component, bool state) switch (state) { case true: + { _standing.Down(uid, dropHeldItems: false); break; + } case false: + { + if (HasComp(uid) && + TryComp(uid, out var staminaComponent) && + staminaComponent.State != StunnedState.None && + staminaComponent.StaminaDamage > staminaComponent.CritThreshold) + { + break; + } + _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, uid, component.StandUpTime, new CrawlStandupDoAfterEvent(), uid, used: uid) { BreakOnDamage = true }); break; + } } } private void OnCrawlingAlertEvent(EntityUid uid, CrawlerComponent component, CrawlingAlertEvent args) @@ -120,12 +131,6 @@ private void OnFall(EntityUid uid, CrawlerComponent component, DownAttemptEvent AddComp(uid); //TODO: add hiding under table } - private void OnStunned(EntityUid uid, CrawlerComponent component, StunnedEvent args) - { - if (!HasComp(uid)) - AddComp(uid); - _alerts.ShowAlert(uid, component.CtawlingAlert); - } private void OnBuckled(EntityUid uid, CrawlerComponent component, ref BuckledEvent args) { RemCompDeferred(uid); diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 966e2d5e98..a61bf53e84 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -71,7 +71,8 @@ public override void Initialize() private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref AfterAutoHandleStateEvent args) { - if (component.State == StunnedState.Critical && component.StaminaDamage > component.CritThreshold) + if (component.State == StunnedState.Critical + && component.StaminaDamage > component.CritThreshold) { EnterStamCrit(uid, component, false); } @@ -80,10 +81,6 @@ private void OnStamHandleState(EntityUid uid, StaminaComponent component, ref Af { EnterStamCrit(uid, component, true); } - else - { - ExitStamCrit(uid, component, true); - } if (component.StaminaDamage > 0f) EnsureComp(uid); From 778521cf41e45e087851c26924886b76682b4157 Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:30:13 +0100 Subject: [PATCH 8/9] fix for noncrawlers --- .../Damage/Systems/StaminaSystem.cs | 38 ++++++++++++++++--- Content.Shared/Stunnable/SharedStunSystem.cs | 12 +----- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index a61bf53e84..7d6c4eeb7f 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -12,6 +12,7 @@ using Content.Shared.Projectiles; using Content.Shared.Rejuvenate; using Content.Shared.Rounding; +using Content.Shared.StatusEffect; using Content.Shared.Stunnable; using Content.Shared.Throwing; using Content.Shared.Weapons.Melee.Events; @@ -42,6 +43,7 @@ public sealed partial class StaminaSystem : EntitySystem [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; [Dependency] private readonly SharedStunSystem _stunSystem = default!; + [Dependency] private readonly StatusEffectsSystem _statusEffect = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; /// @@ -101,7 +103,7 @@ private void OnStartup(EntityUid uid, StaminaComponent component, ComponentStart } [PublicAPI] - public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null, bool soft = true) + public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null) { if (!Resolve(uid, ref component)) return 0f; @@ -459,12 +461,15 @@ public void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, boo component.State = StunnedState.Crawling; component.StaminaDamage = 0f; - _stunSystem.TryKnockdown(uid, component.StunTime / 2, true); + + _stunSystem.TryKnockdown(uid, component.StunTime * 2, true); break; } case false: { component.State = StunnedState.Critical; + + _statusEffect.TryRemoveStatusEffect(uid, "KnockedDown"); _stunSystem.TryParalyze(uid, component.StunTime, true); break; } @@ -502,9 +507,17 @@ public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool } case false: { - component.State = StunnedState.Crawling; - component.StaminaDamage = component.CritThreshold - 1; - EnterStamCrit(uid, component, true); + if (HasComp(uid)) + { + component.State = StunnedState.Crawling; + component.StaminaDamage = component.CritThreshold - 1; + EnterStamCrit(uid, component, true); + } + else + { + component.State = StunnedState.None; + component.StaminaDamage = 0f; + } break; } } @@ -514,6 +527,21 @@ public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool Dirty(uid, component); _adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit"); } + + //TODO: make this accurate + private TimeSpan CrawlTime(EntityUid uid, StaminaComponent stamComp, CrawlerComponent crawlComp, TimeSpan? existingTime = null) + { + TimeSpan time; + + if (existingTime == null) + time = TimeSpan.Zero; + else + time = existingTime.Value; + + time += TimeSpan.FromSeconds(stamComp.StaminaDamage * stamComp.Decay) + crawlComp.StandUpTime; + + return time; + } } /// diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 89b2d8f539..c99436a2f6 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -128,17 +128,9 @@ private void OnKnockInit(EntityUid uid, KnockedDownComponent component, Componen private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) { - bool? soft = null; - StaminaComponent? staminaComponent = null; - - if (HasComp(uid)) - (soft, staminaComponent) = IsSoftStunned(uid); + (bool? soft, _) = IsSoftStunned(uid); - if (soft != null) - { - _stamina.ExitStamCrit(uid, staminaComponent, soft.Value); - } - else + if (soft == null) { _standingState.Stand(uid); } From b565da4278a7e8af4269e04a3eeb9f386005322e Mon Sep 17 00:00:00 2001 From: Doctor-Cpu <77215380+Doctor-Cpu@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:49:16 +0100 Subject: [PATCH 9/9] fix crawling after crit --- .../Damage/Systems/StaminaSystem.cs | 61 +++++-------------- 1 file changed, 16 insertions(+), 45 deletions(-) diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 7d6c4eeb7f..39dbc473f2 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -117,16 +117,9 @@ public float GetStaminaDamage(EntityUid uid, StaminaComponent? component = null) private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args) { - if (component.State == StunnedState.Critical && - component.StaminaDamage >= component.CritThreshold) + if (component.StaminaDamage >= component.CritThreshold) { - ExitStamCrit(uid, component, false); - } - - if (component.State == StunnedState.Crawling && - component.StaminaDamage>= component.CritThreshold) - { - ExitStamCrit(uid, component, true); + ExitStamCrit(uid, component); } component.StaminaDamage = 0; @@ -324,7 +317,7 @@ public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? comp else if (component.StaminaDamage < component.CritThreshold && component.State != StunnedState.None && !softModified) //wont end up putting user into crit as first hit after crawling will always pass ending immedietly { - ExitStamCrit(uid, component, soft); + ExitStamCrit(uid, component); } EnsureComp(uid); @@ -394,7 +387,9 @@ public override void Update(float frameTime) continue; } - bool soft = comp.State != StunnedState.None && comp.StaminaDamage < comp.CritThreshold; + var decay = comp.Decay * -1; + + bool soft = comp.State != StunnedState.None && (comp.StaminaDamage + decay) < comp.CritThreshold; comp.NextUpdate += TimeSpan.FromSeconds(1f); @@ -412,7 +407,7 @@ public override void Update(float frameTime) continue; } - TakeStaminaDamage(uid, comp.Decay * -1, comp, soft: soft); + TakeStaminaDamage(uid, decay, comp, soft: soft); Dirty(uid, comp); } @@ -427,7 +422,7 @@ public override void Update(float frameTime) if (i.State == StunnedState.Critical) { - ExitStamCrit(uid, comp, false); + ExitStamCrit(uid, comp); } else if (i.State == StunnedState.Crawling) { @@ -468,7 +463,6 @@ public void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, boo case false: { component.State = StunnedState.Critical; - _statusEffect.TryRemoveStatusEffect(uid, "KnockedDown"); _stunSystem.TryParalyze(uid, component.StunTime, true); break; @@ -482,7 +476,7 @@ public void EnterStamCrit(EntityUid uid, StaminaComponent? component = null, boo _adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} entered stamina crit"); } - public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool soft = true) + public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null) { if (!Resolve(uid, ref component) || component.State == StunnedState.None) @@ -490,39 +484,16 @@ public void ExitStamCrit(EntityUid uid, StaminaComponent? component = null, bool return; } - switch (soft) - { - case true: - { - component.State = StunnedState.None; - component.StaminaDamage = component.CritThreshold; - component.StaminaDamage = 0f; - RemComp(uid); + component.State = StunnedState.None; + component.StaminaDamage = 0f; + RemComp(uid); - if (TryComp(uid, out var crawlerComp) && HasComp(uid)) - { - _crawling.SetCrawling(uid, crawlerComp, false); - } - break; - } - case false: - { - if (HasComp(uid)) - { - component.State = StunnedState.Crawling; - component.StaminaDamage = component.CritThreshold - 1; - EnterStamCrit(uid, component, true); - } - else - { - component.State = StunnedState.None; - component.StaminaDamage = 0f; - } - break; - } + if (TryComp(uid, out var crawlerComp) && HasComp(uid)) + { + _crawling.SetCrawling(uid, crawlerComp, false); } - component.NextUpdate = _timing.CurTime; + component.NextUpdate = _timing.CurTime + TimeSpan.FromMilliseconds(1); SetStaminaAlert(uid, component); Dirty(uid, component); _adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit");