Skip to content

Commit

Permalink
Add slowdown to low temperatures (space-wizards#29692)
Browse files Browse the repository at this point in the history
* TemperatureSpeed component

* temperature slowdown prediction (done right)

* remove unnecessary changes

* that too

* get in line

* make it readonly

* auto pause
  • Loading branch information
EmoGarbage404 authored and themias committed Aug 9, 2024
1 parent 45459ed commit 404e95a
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
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;
Expand All @@ -11,6 +10,7 @@
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;
Expand Down
14 changes: 2 additions & 12 deletions Content.Server/Temperature/Components/TemperatureComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Content.Server.Temperature.Systems;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Damage;
Expand Down Expand Up @@ -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();

Expand All @@ -71,15 +61,15 @@ public float HeatCapacity
/// </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);

/// <summary>
/// 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";
Expand Down
14 changes: 0 additions & 14 deletions Content.Server/Temperature/Systems/TemperatureSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,17 +412,3 @@ private void RecalculateAndApplyParentThresholds(EntityUid uid,
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;
}
}
30 changes: 30 additions & 0 deletions Content.Shared/Temperature/Components/TemperatureSpeedComponent.cs
Original file line number Diff line number Diff line change
@@ -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;
}
80 changes: 80 additions & 0 deletions Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
15 changes: 15 additions & 0 deletions Content.Shared/Temperature/TemperatureEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,18 @@ public ModifyChangedTemperatureEvent(float temperature)
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;
}
}

5 changes: 5 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/moth.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions Resources/Prototypes/Entities/Mobs/Species/reptilian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 404e95a

Please sign in to comment.