diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs index 6a631858113bdc..4c3437e431e6e8 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs @@ -43,11 +43,22 @@ private void InitializeGases() /// /// Calculates the heat capacity for a gas mixture. /// - public float GetHeatCapacity(GasMixture mixture) + /// The mixture whose heat capacity should be calculated + /// Whether the internal heat capacity scaling should be applied. This should not be + /// used outside of atmospheric related heat transfer. + /// + public float GetHeatCapacity(GasMixture mixture, bool applyScaling) { - return GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable); + var scale = GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable); + + // By default GetHeatCapacityCalculation() has the heat-scale divisor pre-applied. + // So if we want the un-scaled heat capacity, we have to multiply by the scale. + return applyScaling ? scale : scale * HeatScale; } + private float GetHeatCapacity(GasMixture mixture) + => GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable); + [MethodImpl(MethodImplOptions.AggressiveInlining)] private float GetHeatCapacityCalculation(float[] moles, bool space) { @@ -320,7 +331,9 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder) var req = prototype.MinimumRequirements[i]; - if (!(mixture.GetMoles(i) < req)) continue; + if (!(mixture.GetMoles(i) < req)) + continue; + doReaction = false; break; } @@ -328,7 +341,7 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder) if (!doReaction) continue; - reaction = prototype.React(mixture, holder, this); + reaction = prototype.React(mixture, holder, this, HeatScale); if(reaction.HasFlag(ReactionResult.StopReactions)) break; } diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs index 036b64cad944b1..3eb38296f6a0ab 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs @@ -3,6 +3,7 @@ using Content.Server.Atmos.Reactions; using Content.Shared.Atmos; using Content.Shared.Atmos.Components; +using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Utility; @@ -558,4 +559,12 @@ private void GridRepopulateTiles(Entity(); - while (query.MoveNext(out var uid, out var exposed, out var transform)) + while (query.MoveNext(out var uid, out _, out var transform)) { var air = GetContainingMixture(uid, transform:transform); diff --git a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs index e8a7b089c679a9..2541d98a7efbae 100644 --- a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs +++ b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs @@ -83,7 +83,7 @@ private void OnAtmosUpdate(EntityUid uid, HeatExchangerComponent comp, AtmosDevi else xfer = outlet.Air.Remove(-n); - float CXfer = _atmosphereSystem.GetHeatCapacity(xfer); + float CXfer = _atmosphereSystem.GetHeatCapacity(xfer, true); if (CXfer < Atmospherics.MinimumHeatCapacity) return; @@ -94,7 +94,7 @@ private void OnAtmosUpdate(EntityUid uid, HeatExchangerComponent comp, AtmosDevi float CEnv = 0f; if (environment != null) { - CEnv = _atmosphereSystem.GetHeatCapacity(environment); + CEnv = _atmosphereSystem.GetHeatCapacity(environment, true); hasEnv = CEnv >= Atmospherics.MinimumHeatCapacity && environment.TotalMoles > 0f; if (hasEnv) radTemp = environment.Temperature; diff --git a/Content.Server/Atmos/IGasReactionEffect.cs b/Content.Server/Atmos/IGasReactionEffect.cs index acaef2a0719cba..bd229694bb1778 100644 --- a/Content.Server/Atmos/IGasReactionEffect.cs +++ b/Content.Server/Atmos/IGasReactionEffect.cs @@ -6,6 +6,14 @@ namespace Content.Server.Atmos [ImplicitDataDefinitionForInheritors] public partial interface IGasReactionEffect { - ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem); + /// + /// Process this reaction effect. + /// + /// The gas mixture to react + /// The container of this gas mixture + /// The atmosphere system + /// Scaling factor that should be applied to all heat input or outputs. + ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, + float heatScale); } } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs index 1b790b5cf0013e..8df1bb53658a26 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs @@ -64,7 +64,7 @@ private void OnCondenserUpdated(EntityUid uid, GasCondenserComponent component, public float NumberOfMolesToConvert(ApcPowerReceiverComponent comp, GasMixture mix, float dt) { - var hc = _atmosphereSystem.GetHeatCapacity(mix); + var hc = _atmosphereSystem.GetHeatCapacity(mix, true); var alpha = 0.8f; // tuned to give us 1-ish u/second of reagent conversion // ignores the energy needed to cool down the solution to the condensation point, but that probably adds too much difficulty and so let's not simulate that var energy = comp.Load * dt; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs index 7f5f58fe4b78d4..4140eb2a93f29d 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs @@ -80,7 +80,7 @@ private void OnThermoMachineUpdated(EntityUid uid, GasThermoMachineComponent the float dQ = thermoMachine.HeatCapacity * thermoMachine.Cp * args.dt; // Clamps the heat transferred to not overshoot - float Cin = _atmosphereSystem.GetHeatCapacity(inlet.Air); + float Cin = _atmosphereSystem.GetHeatCapacity(inlet.Air, true); float dT = targetTemp - temp; float dQLim = dT * Cin; float scale = 1f; diff --git a/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs b/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs index ddbd8a772b7808..051ee8202db2fc 100644 --- a/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs +++ b/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs @@ -10,9 +10,9 @@ namespace Content.Server.Atmos.Reactions; [UsedImplicitly] public sealed partial class FrezonCoolantReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); var temperature = mixture.Temperature; var energyModifier = 1f; @@ -45,11 +45,11 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos energyReleased = burnRate * Atmospherics.FrezonCoolEnergyReleased * energyModifier; } - energyReleased /= atmosphereSystem.HeatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise + energyReleased /= heatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise if (energyReleased >= 0f) return ReactionResult.NoReaction; - var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) mixture.Temperature = (temperature * oldHeatCapacity + energyReleased) / newHeatCapacity; diff --git a/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs b/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs index 084d939e4e0ad9..4ffd9c2f5b3e9a 100644 --- a/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs +++ b/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs @@ -11,7 +11,7 @@ namespace Content.Server.Atmos.Reactions; [UsedImplicitly] public sealed partial class FrezonProductionReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { var initialN2 = mixture.GetMoles(Gas.Nitrogen); var initialOxy = mixture.GetMoles(Gas.Oxygen); @@ -28,7 +28,6 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos // Amount of tritium & oxygen that are reacting var tritBurned = Math.Min(oxyLimit, initialTrit); var oxyBurned = tritBurned * Atmospherics.FrezonProductionTritRatio; - var burnRatio = tritBurned / initialTrit; var oxyConversion = oxyBurned / Atmospherics.FrezonProductionConversionRate; var tritConversion = tritBurned / Atmospherics.FrezonProductionConversionRate; diff --git a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs index 30f9b72f8df608..0ee29de3bf196f 100644 --- a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs +++ b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs @@ -60,13 +60,20 @@ public sealed partial class GasReactionPrototype : IPrototype /// [DataField("effects")] private List _effects = new(); - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + /// + /// Process all reaction effects. + /// + /// The gas mixture to react + /// The container of this gas mixture + /// The atmosphere system + /// Scaling factor that should be applied to all heat input or outputs. + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { var result = ReactionResult.NoReaction; foreach (var effect in _effects) { - result |= effect.React(mixture, holder, atmosphereSystem); + result |= effect.React(mixture, holder, atmosphereSystem, heatScale); } return result; diff --git a/Content.Server/Atmos/Reactions/MiasmicSubsumationReaction.cs b/Content.Server/Atmos/Reactions/MiasmicSubsumationReaction.cs index b7dd5b7eb89ec6..f9e8cbdf776af5 100644 --- a/Content.Server/Atmos/Reactions/MiasmicSubsumationReaction.cs +++ b/Content.Server/Atmos/Reactions/MiasmicSubsumationReaction.cs @@ -10,7 +10,7 @@ namespace Content.Server.Atmos.Reactions; [UsedImplicitly] public sealed partial class MiasmicSubsumationReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { var initialMiasma = mixture.GetMoles(Gas.Miasma); var initialFrezon = mixture.GetMoles(Gas.Frezon); diff --git a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs b/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs index 22a8772e6826bd..9adda3089ccbf1 100644 --- a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs +++ b/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs @@ -8,10 +8,10 @@ namespace Content.Server.Atmos.Reactions [DataDefinition] public sealed partial class PlasmaFireReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { var energyReleased = 0f; - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); var temperature = mixture.Temperature; var location = holder as TileAtmosphere; mixture.ReactionResults[GasReaction.Fire] = 0; @@ -22,8 +22,10 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos if (temperature > Atmospherics.PlasmaUpperTemperature) temperatureScale = 1f; else + { temperatureScale = (temperature - Atmospherics.PlasmaMinimumBurnTemperature) / (Atmospherics.PlasmaUpperTemperature - Atmospherics.PlasmaMinimumBurnTemperature); + } if (temperatureScale > 0) { @@ -56,14 +58,14 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos mixture.AdjustMoles(Gas.CarbonDioxide, plasmaBurnRate * (1.0f - supersaturation)); energyReleased += Atmospherics.FirePlasmaEnergyReleased * plasmaBurnRate; - energyReleased /= atmosphereSystem.HeatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise + energyReleased /= heatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise mixture.ReactionResults[GasReaction.Fire] += plasmaBurnRate * (1 + oxygenBurnRate); } } if (energyReleased > 0) { - var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) mixture.Temperature = (temperature * oldHeatCapacity + energyReleased) / newHeatCapacity; } diff --git a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs index d1459993bf80d2..c52b431fd43acf 100644 --- a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs +++ b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs @@ -8,10 +8,10 @@ namespace Content.Server.Atmos.Reactions [DataDefinition] public sealed partial class TritiumFireReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { var energyReleased = 0f; - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); var temperature = mixture.Temperature; var location = holder as TileAtmosphere; mixture.ReactionResults[GasReaction.Fire] = 0f; @@ -47,10 +47,10 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos mixture.ReactionResults[GasReaction.Fire] += burnedFuel; } - energyReleased /= atmosphereSystem.HeatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise + energyReleased /= heatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise if (energyReleased > 0) { - var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); + var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) mixture.Temperature = ((temperature * oldHeatCapacity + energyReleased) / newHeatCapacity); } diff --git a/Content.Server/Atmos/Reactions/WaterVaporReaction.cs b/Content.Server/Atmos/Reactions/WaterVaporReaction.cs index 75eb0291dfac24..8db8fdbd66d135 100644 --- a/Content.Server/Atmos/Reactions/WaterVaporReaction.cs +++ b/Content.Server/Atmos/Reactions/WaterVaporReaction.cs @@ -17,7 +17,7 @@ public sealed partial class WaterVaporReaction : IGasReactionEffect [DataField("molesPerUnit")] public float MolesPerUnit { get; private set; } = 1; - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) { // If any of the prototypes is invalid, we do nothing. if (string.IsNullOrEmpty(Reagent)) @@ -34,9 +34,8 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos // Remove the moles from the mixture... mixture.AdjustMoles(GasId, -MolesPerUnit); - var tileRef = tile.GridIndices.GetTileRef(tile.GridIndex); - EntitySystem.Get() - .TrySpillAt(tileRef, new Solution(Reagent, FixedPoint2.New(MolesPerUnit)), out _, sound: false); + var tileRef = atmosphereSystem.GetTileRef(tile); + atmosphereSystem.Puddle.TrySpillAt(tileRef, new Solution(Reagent, FixedPoint2.New(MolesPerUnit)), out _, sound: false); return ReactionResult.Reacting; } diff --git a/Content.Server/Power/Generation/Teg/TegSystem.cs b/Content.Server/Power/Generation/Teg/TegSystem.cs index 2be41f7c923d63..1fb844ac5b1c0d 100644 --- a/Content.Server/Power/Generation/Teg/TegSystem.cs +++ b/Content.Server/Power/Generation/Teg/TegSystem.cs @@ -120,8 +120,8 @@ private void GeneratorUpdate(EntityUid uid, TegGeneratorComponent component, Atm var (airA, δpA) = GetCirculatorAirTransfer(inletA.Air, outletA.Air); var (airB, δpB) = GetCirculatorAirTransfer(inletB.Air, outletB.Air); - var cA = _atmosphere.GetHeatCapacity(airA); - var cB = _atmosphere.GetHeatCapacity(airB); + var cA = _atmosphere.GetHeatCapacity(airA, true); + var cB = _atmosphere.GetHeatCapacity(airB, true); // Shift ramp position based on demand and generation from previous tick. var curRamp = component.RampPosition; diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs index 5de609d24bacd4..2ab9ce74c661a2 100644 --- a/Content.Server/Temperature/Systems/TemperatureSystem.cs +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -149,13 +149,11 @@ private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperatur if (transform.MapUid == null) return; - var position = _transform.GetGridTilePositionOrDefault((uid, transform)); var temperatureDelta = args.GasMixture.Temperature - temperature.CurrentTemperature; - var tileHeatCapacity = - _atmosphere.GetTileHeatCapacity(transform.GridUid, transform.MapUid.Value, position); + var airHeatCapacity = _atmosphere.GetHeatCapacity(args.GasMixture, false); var heatCapacity = GetHeatCapacity(uid, temperature); - var heat = temperatureDelta * (tileHeatCapacity * heatCapacity / - (tileHeatCapacity + heatCapacity)); + var heat = temperatureDelta * (airHeatCapacity * heatCapacity / + (airHeatCapacity + heatCapacity)); ChangeHeat(uid, heat * temperature.AtmosTemperatureTransferEfficiency, temperature: temperature); }