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
This commit is contained in:
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Temperature.Systems;
|
||||
using Content.Shared.Construction;
|
||||
using Content.Shared.Construction.Components;
|
||||
using Content.Shared.Construction.EntitySystems;
|
||||
@@ -11,6 +10,7 @@ using Content.Shared.DoAfter;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Prying.Systems;
|
||||
using Content.Shared.Radio.EntitySystems;
|
||||
using Content.Shared.Temperature;
|
||||
using Content.Shared.Tools.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Content.Server.Temperature.Systems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Damage;
|
||||
@@ -51,15 +50,6 @@ public sealed partial class TemperatureComponent : Component
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float AtmosTemperatureTransferEfficiency = 0.1f;
|
||||
|
||||
[Obsolete("Use system method")]
|
||||
public float HeatCapacity
|
||||
{
|
||||
get
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().System<TemperatureSystem>().GetHeatCapacity(Owner, this);
|
||||
}
|
||||
}
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageSpecifier ColdDamage = new();
|
||||
|
||||
@@ -71,7 +61,7 @@ public sealed partial class TemperatureComponent : Component
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Okay it genuinely reaches this basically immediately for a plasma fire.
|
||||
/// </summary>
|
||||
/// </remarks>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public FixedPoint2 DamageCap = FixedPoint2.New(8);
|
||||
|
||||
@@ -79,7 +69,7 @@ public sealed partial class TemperatureComponent : Component
|
||||
/// Used to keep track of when damage starts/stops. Useful for logs.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool TakingDamage = false;
|
||||
public bool TakingDamage;
|
||||
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype> HotAlert = "Hot";
|
||||
|
||||
@@ -412,17 +412,3 @@ public sealed class TemperatureSystem : EntitySystem
|
||||
return (newHeatThreshold, newColdThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OnTemperatureChangeEvent : EntityEventArgs
|
||||
{
|
||||
public float CurrentTemperature { get; }
|
||||
public float LastTemperature { get; }
|
||||
public float TemperatureDelta { get; }
|
||||
|
||||
public OnTemperatureChangeEvent(float current, float last, float delta)
|
||||
{
|
||||
CurrentTemperature = current;
|
||||
LastTemperature = last;
|
||||
TemperatureDelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Temperature.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Temperature.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for an entity that varies in speed based on current temperature.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedTemperatureSystem)), AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
public sealed partial class TemperatureSpeedComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Pairs of temperature thresholds to applied slowdown values.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Dictionary<float, float> Thresholds = new();
|
||||
|
||||
/// <summary>
|
||||
/// The current speed modifier from <see cref="Thresholds"/> we reached.
|
||||
/// Stored and networked so that the client doesn't mispredict temperature
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public float? CurrentSpeedModifier;
|
||||
|
||||
/// <summary>
|
||||
/// The time at which the temperature slowdown is updated.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan? NextSlowdownUpdate;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,3 +13,18 @@ public sealed class ModifyChangedTemperatureEvent : EntityEventArgs, IInventoryR
|
||||
TemperatureDelta = temperature;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OnTemperatureChangeEvent : EntityEventArgs
|
||||
{
|
||||
public readonly float CurrentTemperature;
|
||||
public readonly float LastTemperature;
|
||||
public readonly float TemperatureDelta;
|
||||
|
||||
public OnTemperatureChangeEvent(float current, float last, float delta)
|
||||
{
|
||||
CurrentTemperature = current;
|
||||
LastTemperature = last;
|
||||
TemperatureDelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,11 @@
|
||||
heatDamage:
|
||||
types:
|
||||
Heat: 1.5 #per second, scales with temperature & other constants
|
||||
- type: TemperatureSpeed
|
||||
thresholds:
|
||||
293: 0.8
|
||||
280: 0.6
|
||||
260: 0.4
|
||||
- type: ThermalRegulator
|
||||
metabolismHeat: 800
|
||||
radiatedHeat: 100
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
heatDamage:
|
||||
types:
|
||||
Heat : 3 #per second, scales with temperature & other constants
|
||||
- type: TemperatureSpeed
|
||||
thresholds:
|
||||
289: 0.8
|
||||
275: 0.6
|
||||
250: 0.4
|
||||
- type: Sprite # sprite again because we want different layer ordering
|
||||
noRot: true
|
||||
drawdepth: Mobs
|
||||
|
||||
@@ -59,6 +59,11 @@
|
||||
heatDamage:
|
||||
types:
|
||||
Heat : 1.5 #per second, scales with temperature & other constants
|
||||
- type: TemperatureSpeed
|
||||
thresholds:
|
||||
301: 0.8
|
||||
295: 0.6
|
||||
285: 0.4
|
||||
- type: Wagging
|
||||
- type: Inventory
|
||||
speciesId: reptilian
|
||||
|
||||
Reference in New Issue
Block a user