Add atmos time compression (#21954)
Add atmos.speedup which is effectively a atmos-only time compression CVar. This adjusts heat capacities and transfer rates to effectively globally speed up the time constants of atmos. This allows faster response to heating/cooling changes and faster cleanups (by buffing scrubbers, pumps, and everything else) that is tunable through one global time compression CVar. It also achieves this without any thermodynamic unsoundness.
This commit is contained in:
@@ -56,7 +56,7 @@ public sealed class AirFilterSystem : EntitySystem
|
||||
if (!GetAir(uid, out var air))
|
||||
return;
|
||||
|
||||
var ratio = MathF.Min(1f, args.dt * filter.TransferRate);
|
||||
var ratio = MathF.Min(1f, args.dt * filter.TransferRate * _atmosphere.PumpSpeedup());
|
||||
var removed = air.RemoveRatio(ratio);
|
||||
// nothing left to remove from the volume
|
||||
if (MathHelper.CloseToPercent(removed.TotalMoles, 0f))
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Content.Server.Atmos.EntitySystems
|
||||
public bool ExcitedGroupsSpaceIsAllConsuming { get; private set; }
|
||||
public float AtmosMaxProcessTime { get; private set; }
|
||||
public float AtmosTickRate { get; private set; }
|
||||
public float Speedup { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time between each atmos sub-update. If you are writing an atmos device, use AtmosDeviceUpdateEvent.dt
|
||||
@@ -49,6 +50,7 @@ namespace Content.Server.Atmos.EntitySystems
|
||||
_cfg.OnValueChanged(CCVars.Superconduction, value => Superconduction = value, true);
|
||||
_cfg.OnValueChanged(CCVars.AtmosMaxProcessTime, value => AtmosMaxProcessTime = value, true);
|
||||
_cfg.OnValueChanged(CCVars.AtmosTickRate, value => AtmosTickRate = value, true);
|
||||
_cfg.OnValueChanged(CCVars.AtmosSpeedup, value => Speedup = value, true);
|
||||
_cfg.OnValueChanged(CCVars.ExcitedGroups, value => ExcitedGroups = value, true);
|
||||
_cfg.OnValueChanged(CCVars.ExcitedGroupsSpaceIsAllConsuming, value => ExcitedGroupsSpaceIsAllConsuming = value, true);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,17 @@ namespace Content.Server.Atmos.EntitySystems
|
||||
|
||||
Span<float> tmp = stackalloc float[moles.Length];
|
||||
NumericsHelpers.Multiply(moles, GasSpecificHeats, tmp);
|
||||
return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity);
|
||||
// Adjust heat capacity by speedup, because this is primarily what
|
||||
// determines how quickly gases heat up/cool.
|
||||
return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity) / Speedup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return speedup factor for pumped or flow-based devices that depend on MaxTransferRate.
|
||||
/// </summary>
|
||||
public float PumpSpeedup()
|
||||
{
|
||||
return MathF.Sqrt(Speedup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
||||
return 0;
|
||||
}
|
||||
float overPressConst = 300; // pressure difference (in atm) to get 200 L/sec transfer rate
|
||||
float alpha = Atmospherics.MaxTransferRate / (float)Math.Sqrt(overPressConst*Atmospherics.OneAtmosphere);
|
||||
float alpha = Atmospherics.MaxTransferRate * _atmosphereSystem.PumpSpeedup() / (float)Math.Sqrt(overPressConst*Atmospherics.OneAtmosphere);
|
||||
return alpha * (float)Math.Sqrt(inlet.Pressure - outlet.Pressure);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
||||
return;
|
||||
|
||||
// We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters.
|
||||
var removed = inlet.Air.RemoveVolume(pump.TransferRate * args.dt);
|
||||
var removed = inlet.Air.RemoveVolume(pump.TransferRate * _atmosphereSystem.PumpSpeedup() * args.dt);
|
||||
|
||||
// Some of the gas from the mixture leaks when overclocked.
|
||||
if (pump.Overclocked)
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
|
||||
}
|
||||
|
||||
// We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters.
|
||||
var transferVol = filter.TransferRate * args.dt;
|
||||
var transferVol = filter.TransferRate * _atmosphereSystem.PumpSpeedup() * args.dt;
|
||||
|
||||
if (transferVol <= 0)
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
|
||||
else
|
||||
{
|
||||
comp.Enabled = true;
|
||||
transferRate = Math.Min(control * comp.Gain, comp.MaxTransferRate);
|
||||
transferRate = Math.Min(control * comp.Gain, comp.MaxTransferRate * _atmosphereSystem.PumpSpeedup());
|
||||
}
|
||||
UpdateAppearance(uid, comp);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
var timeDelta = args.dt;
|
||||
|
||||
// TODO adjust ratio so that environment does not go above MaxPressure?
|
||||
var ratio = MathF.Min(1f, timeDelta * injector.TransferRate / inlet.Air.Volume);
|
||||
var ratio = MathF.Min(1f, timeDelta * injector.TransferRate * _atmosphereSystem.PumpSpeedup() / inlet.Air.Volume);
|
||||
var removed = inlet.Air.RemoveRatio(ratio);
|
||||
|
||||
_atmosphereSystem.Merge(environment, removed);
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
|
||||
private void Scrub(float timeDelta, GasVentScrubberComponent scrubber, GasMixture? tile, PipeNode outlet)
|
||||
{
|
||||
Scrub(timeDelta, scrubber.TransferRate, scrubber.PumpDirection, scrubber.FilterGases, tile, outlet.Air);
|
||||
Scrub(timeDelta, scrubber.TransferRate*_atmosphereSystem.PumpSpeedup(), scrubber.PumpDirection, scrubber.FilterGases, tile, outlet.Air);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Content.Server.Atmos.Portable
|
||||
|
||||
private bool Scrub(float timeDelta, PortableScrubberComponent scrubber, GasMixture? tile)
|
||||
{
|
||||
return _scrubberSystem.Scrub(timeDelta, scrubber.TransferRate, ScrubberPumpDirection.Scrubbing, scrubber.FilterGases, tile, scrubber.Air);
|
||||
return _scrubberSystem.Scrub(timeDelta, scrubber.TransferRate * _atmosphereSystem.PumpSpeedup(), ScrubberPumpDirection.Scrubbing, scrubber.FilterGases, tile, scrubber.Air);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, bool isFull, bool isRunning)
|
||||
|
||||
@@ -45,6 +45,7 @@ public sealed partial class FrezonCoolantReaction : IGasReactionEffect
|
||||
energyReleased = burnRate * Atmospherics.FrezonCoolEnergyReleased * energyModifier;
|
||||
}
|
||||
|
||||
energyReleased /= atmosphereSystem.Speedup; // adjust energy to make sure speedup doesn't cause mega temperature rise
|
||||
if (energyReleased >= 0f)
|
||||
return ReactionResult.NoReaction;
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Content.Server.Atmos.Reactions
|
||||
mixture.AdjustMoles(Gas.CarbonDioxide, plasmaBurnRate * (1.0f - supersaturation));
|
||||
|
||||
energyReleased += Atmospherics.FirePlasmaEnergyReleased * plasmaBurnRate;
|
||||
energyReleased /= atmosphereSystem.Speedup; // adjust energy to make sure speedup doesn't cause mega temperature rise
|
||||
mixture.ReactionResults[GasReaction.Fire] += plasmaBurnRate * (1 + oxygenBurnRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Content.Server.Atmos.Reactions
|
||||
mixture.ReactionResults[GasReaction.Fire] += burnedFuel;
|
||||
}
|
||||
|
||||
energyReleased /= atmosphereSystem.Speedup; // adjust energy to make sure speedup doesn't cause mega temperature rise
|
||||
if (energyReleased > 0)
|
||||
{
|
||||
var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture);
|
||||
|
||||
@@ -1044,6 +1044,15 @@ namespace Content.Shared.CCVar
|
||||
public static readonly CVarDef<float> AtmosTickRate =
|
||||
CVarDef.Create("atmos.tickrate", 15f, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Scale factor for how fast things happen in our atmosphere
|
||||
/// simulation compared to real life. 1x means that a room takes as
|
||||
/// long to heat up in game as real life. Players typically expect
|
||||
/// things to happen faster in-game.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<float> AtmosSpeedup =
|
||||
CVarDef.Create("atmos.speedup", 64f, CVar.SERVERONLY);
|
||||
|
||||
/*
|
||||
* MIDI instruments
|
||||
*/
|
||||
|
||||
@@ -291,7 +291,7 @@
|
||||
True: { state: freezerOn }
|
||||
False: { state: freezerOff }
|
||||
- type: GasThermoMachine
|
||||
coefficientOfPerformance: -64
|
||||
coefficientOfPerformance: -3.9
|
||||
- type: ApcPowerReceiver
|
||||
powerDisabled: true #starts off
|
||||
- type: Machine
|
||||
@@ -334,7 +334,7 @@
|
||||
True: { state: heaterOn }
|
||||
False: { state: heaterOff }
|
||||
- type: GasThermoMachine
|
||||
coefficientOfPerformance: 32
|
||||
coefficientOfPerformance: 0.95
|
||||
- type: ApcPowerReceiver
|
||||
powerDisabled: true #starts off
|
||||
- type: Machine
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
# It fires processing on behalf of its connected circulators.
|
||||
- type: AtmosDevice
|
||||
- type: TegGenerator
|
||||
powerFactor: 0.025
|
||||
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: AtmosDevices
|
||||
|
||||
Reference in New Issue
Block a user