Overhauled stamina slowdown behavior (#36336)

This commit is contained in:
nikitosych
2025-05-02 00:01:17 +01:00
committed by GitHub
parent 52062dcfad
commit 72d2d8ab0f
3 changed files with 116 additions and 22 deletions

View File

@@ -7,8 +7,7 @@ using Content.Shared.Damage.Components;
using Content.Shared.Damage.Events;
using Content.Shared.Database;
using Content.Shared.Effects;
using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
using Content.Shared.FixedPoint;
using Content.Shared.Projectiles;
using Content.Shared.Rejuvenate;
using Content.Shared.Rounding;
@@ -21,7 +20,6 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared.Damage.Systems;
@@ -114,6 +112,7 @@ public sealed partial class StaminaSystem : EntitySystem
}
component.StaminaDamage = 0;
AdjustSlowdown(uid);
RemComp<ActiveStaminaComponent>(uid);
SetStaminaAlert(uid, component);
Dirty(uid, component);
@@ -275,17 +274,16 @@ public sealed partial class StaminaSystem : EntitySystem
component.NextUpdate = nextUpdate;
}
var slowdownThreshold = component.CritThreshold / 2f;
// If we go above n% then apply slowdown
if (oldDamage < slowdownThreshold &&
component.StaminaDamage > slowdownThreshold)
{
_stunSystem.TrySlowdown(uid, TimeSpan.FromSeconds(3), true, 0.8f, 0.8f);
}
AdjustSlowdown(uid);
SetStaminaAlert(uid, component);
// Checking if the stamina damage has decreased to zero after exiting the stamcrit
if (component.AfterCritical && oldDamage > component.StaminaDamage && component.StaminaDamage <= 0f)
{
component.AfterCritical = false; // Since the recovery from the crit has been completed, we are no longer 'after crit'
}
if (!component.Critical)
{
if (component.StaminaDamage >= component.CritThreshold)
@@ -330,9 +328,6 @@ public sealed partial class StaminaSystem : EntitySystem
{
base.Update(frameTime);
if (!_timing.IsFirstTimePredicted)
return;
var stamQuery = GetEntityQuery<StaminaComponent>();
var query = EntityQueryEnumerator<ActiveStaminaComponent>();
var curTime = _timing.CurTime;
@@ -353,15 +348,17 @@ public sealed partial class StaminaSystem : EntitySystem
if (nextUpdate > curTime)
continue;
// We were in crit so come out of it and continue.
// Handle exiting critical condition and restoring stamina damage
if (comp.Critical)
{
ExitStamCrit(uid, comp);
continue;
}
comp.NextUpdate += TimeSpan.FromSeconds(1f);
TakeStaminaDamage(uid, -comp.Decay, comp);
TakeStaminaDamage(
uid,
comp.AfterCritical ? -comp.Decay * comp.AfterCritDecayMultiplier : -comp.Decay, // Recover faster after crit
comp);
Dirty(uid, comp);
}
}
@@ -398,11 +395,38 @@ public sealed partial class StaminaSystem : EntitySystem
}
component.Critical = false;
component.StaminaDamage = 0f;
component.AfterCritical = true; // Set to true to indicate that stamina will be restored after exiting stamcrit
component.NextUpdate = _timing.CurTime;
SetStaminaAlert(uid, component);
RemComp<ActiveStaminaComponent>(uid);
Dirty(uid, component);
_adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit");
}
/// <summary>
/// Adjusts the movement speed of an entity based on its current <see cref="StaminaComponent.StaminaDamage"/> value.
/// If the entity has a <see cref="SlowOnDamageComponent"/>, its custom damage-to-speed thresholds are used,
/// otherwise, a default set of thresholds is applied.
/// The method determines the closest applicable damage threshold below the crit limit and applies the corresponding
/// speed modifier using the stun system. If no threshold is met then the entity's speed is restored to normal.
/// </summary>
/// <param name="ent">Entity to update</param>
private void AdjustSlowdown(Entity<StaminaComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
var closest = FixedPoint2.Zero;
// Iterate through the dictionary in the similar way as in Damage.SlowOnDamageSystem.OnRefreshMovespeed
foreach (var thres in ent.Comp.StunModifierThresholds)
{
var key = thres.Key.Float();
if (ent.Comp.StaminaDamage >= key && key > closest && closest < ent.Comp.CritThreshold)
closest = thres.Key;
}
_stunSystem.UpdateStunModifiers(ent, ent.Comp.StunModifierThresholds[closest]);
}
}