fish-station/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs
TemporalOroboros 6f38eed9d9
Splits temperature damage processing into its own component (#30515)
* Creates TemperatureDamageThresholdsComponent

* Obsolete TemperatureComponent fields

* Use TemperatureDamageThresholdsComponent
Moves all the uses of the relocated TemperatureComponent fields to use the TDTC versions

* Removes the obsolete TemperatureComponent fields

* Update YAML definitions

* Update doc comments

* Split TemperatureSystem
Creates TemperatureDamageSystem and moves the damage handling from TemperatureSystem

* Cull unused using statements

* Use component-based damage tick scheduling

* Fix temperature damage processing
Check was inverted resulting in things never starting to take temperature damage

* Poke tests

* Add TemperatureDamageThresholds to new prototypes

* Move TemperatureDamageThresholdsComponent to Shared
Parity with TemperatureComponent

* While I'm here
Fixes warning regarding obsolete ProtoId validator attribute

* Fix YAML errors

* Fix merge errors

* Rename TemperatureDamageThresholdsComponent -> TemperatureDamageComponent

* Use ContentHelpers.RoundToLevels for temperature alerts

* Fix YML

* A fuckton of cleanup

* working cleanup

* fix

* misc additions

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
2025-12-24 06:37:11 +00:00

101 lines
3.8 KiB
C#

using System.Linq;
using Content.Shared.Atmos;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Temperature.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
namespace Content.Shared.Temperature.Systems;
/// <summary>
/// This handles predicting temperature based speedup.
/// </summary>
public abstract class SharedTemperatureSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
protected EntityQuery<TemperatureComponent> TemperatureQuery;
/// <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);
TemperatureQuery = GetEntityQuery<TemperatureComponent>();
}
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);
}
}
public virtual void ChangeHeat(EntityUid uid, float heatAmount, bool ignoreHeatResistance = false, TemperatureComponent? temperature = null)
{
}
public float GetHeatCapacity(EntityUid uid, TemperatureComponent? comp = null, PhysicsComponent? physics = null)
{
if (!TemperatureQuery.Resolve(uid, ref comp) || !Resolve(uid, ref physics, false) || physics.FixturesMass <= 0)
{
return Atmospherics.MinimumHeatCapacity;
}
return comp.SpecificHeat * physics.FixturesMass;
}
}