Files
tbd-station-14/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs
Nemanja b3a64d4bcd Add slowdown to low temperatures (#29692)
* TemperatureSpeed component

* temperature slowdown prediction (done right)

* remove unnecessary changes

* that too

* get in line

* make it readonly

* auto pause
2024-08-05 18:07:02 +10:00

81 lines
3.0 KiB
C#

using System.Linq;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Temperature.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Temperature.Systems;
/// <summary>
/// This handles predicting temperature based speedup.
/// </summary>
public sealed class SharedTemperatureSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
/// <summary>
/// Band-aid for unpredicted atmos. Delays the application for a short period so that laggy clients can get the replicated temperature.
/// </summary>
private static readonly TimeSpan SlowdownApplicationDelay = TimeSpan.FromSeconds(1f);
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TemperatureSpeedComponent, OnTemperatureChangeEvent>(OnTemperatureChanged);
SubscribeLocalEvent<TemperatureSpeedComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
}
private void OnTemperatureChanged(Entity<TemperatureSpeedComponent> ent, ref OnTemperatureChangeEvent args)
{
foreach (var (threshold, modifier) in ent.Comp.Thresholds)
{
if (args.CurrentTemperature < threshold && args.LastTemperature > threshold ||
args.CurrentTemperature > threshold && args.LastTemperature < threshold)
{
ent.Comp.NextSlowdownUpdate = _timing.CurTime + SlowdownApplicationDelay;
ent.Comp.CurrentSpeedModifier = modifier;
Dirty(ent);
break;
}
}
var maxThreshold = ent.Comp.Thresholds.Max(p => p.Key);
if (args.CurrentTemperature > maxThreshold && args.LastTemperature < maxThreshold)
{
ent.Comp.NextSlowdownUpdate = _timing.CurTime + SlowdownApplicationDelay;
ent.Comp.CurrentSpeedModifier = null;
Dirty(ent);
}
}
private void OnRefreshMovementSpeedModifiers(Entity<TemperatureSpeedComponent> ent, ref RefreshMovementSpeedModifiersEvent args)
{
// Don't update speed and mispredict while we're compensating for lag.
if (ent.Comp.NextSlowdownUpdate != null || ent.Comp.CurrentSpeedModifier == null)
return;
args.ModifySpeed(ent.Comp.CurrentSpeedModifier.Value, ent.Comp.CurrentSpeedModifier.Value);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<TemperatureSpeedComponent, MovementSpeedModifierComponent>();
while (query.MoveNext(out var uid, out var temp, out var movement))
{
if (temp.NextSlowdownUpdate == null)
continue;
if (_timing.CurTime < temp.NextSlowdownUpdate)
continue;
temp.NextSlowdownUpdate = null;
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid, movement);
Dirty(uid, temp);
}
}
}