diff --git a/Content.Server/Atmos/GasMixture.cs b/Content.Server/Atmos/GasMixture.cs index cad0a27730..77b90d5856 100644 --- a/Content.Server/Atmos/GasMixture.cs +++ b/Content.Server/Atmos/GasMixture.cs @@ -35,6 +35,13 @@ namespace Content.Server.Atmos [ViewVariables] public float LastShare { get; private set; } = 0; + [ViewVariables] + public readonly Dictionary ReactionResults = new Dictionary() + { + // We initialize the dictionary here. + { GasReaction.Fire, 0f } + }; + [ViewVariables] public float HeatCapacity { @@ -107,8 +114,6 @@ namespace Content.Server.Atmos } } - public float ReactionResultFire { get; set; } - [ViewVariables] public float ThermalEnergy => Temperature * HeatCapacity; @@ -452,19 +457,25 @@ namespace Content.Server.Atmos temperature < prototype.MinimumTemperatureRequirement) continue; + var doReaction = true; for (var i = 0; i < prototype.MinimumRequirements.Length; i++) { if(i > Atmospherics.TotalNumberOfGases) throw new IndexOutOfRangeException("Reaction Gas Minimum Requirements Array Prototype exceeds total number of gases!"); var req = prototype.MinimumRequirements[i]; - if (GetMoles(i) < req) - continue; - reaction = prototype.React(this, holder); - if(reaction.HasFlag(ReactionResult.StopReactions)) - break; + if (!(GetMoles(i) < req)) continue; + doReaction = false; + break; } + + if (!doReaction) + continue; + + reaction = prototype.React(this, holder); + if(reaction.HasFlag(ReactionResult.StopReactions)) + break; } return reaction; diff --git a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs index d8e42bab39..e0dffe25c6 100644 --- a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs +++ b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs @@ -16,6 +16,11 @@ namespace Content.Server.Atmos.Reactions StopReactions = 2, } + public enum GasReaction : byte + { + Fire = 0, + } + [Prototype("gasReaction")] public class GasReactionPrototype : IPrototype, IIndexedPrototype { diff --git a/Content.Server/Atmos/Reactions/PhoronFireReaction.cs b/Content.Server/Atmos/Reactions/PhoronFireReaction.cs index acef249b02..f67752f906 100644 --- a/Content.Server/Atmos/Reactions/PhoronFireReaction.cs +++ b/Content.Server/Atmos/Reactions/PhoronFireReaction.cs @@ -3,6 +3,7 @@ using CannyFastMath; using Content.Server.Interfaces; using Content.Shared.Atmos; using JetBrains.Annotations; +using Robust.Shared.Log; using Robust.Shared.Serialization; namespace Content.Server.Atmos.Reactions @@ -53,7 +54,7 @@ namespace Content.Server.Atmos.Reactions energyReleased += Atmospherics.FirePhoronEnergyReleased * (phoronBurnRate); - mixture.ReactionResultFire += (phoronBurnRate) * (1 + oxygenBurnRate); + mixture.ReactionResults[GasReaction.Fire] += (phoronBurnRate) * (1 + oxygenBurnRate); } } @@ -69,15 +70,15 @@ namespace Content.Server.Atmos.Reactions temperature = mixture.Temperature; if (temperature > Atmospherics.FireMinimumTemperatureToExist) { - location.HotspotExpose(temperature, Atmospherics.CellVolume); + location.HotspotExpose(temperature, mixture.Volume); // TODO ATMOS Expose temperature all items on cell - location.TemperatureExpose(mixture, temperature, Atmospherics.CellVolume); + location.TemperatureExpose(mixture, temperature, mixture.Volume); } } - return mixture.ReactionResultFire != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction; + return mixture.ReactionResults[GasReaction.Fire] != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction; } public void ExposeData(ObjectSerializer serializer) diff --git a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs new file mode 100644 index 0000000000..8b90431253 --- /dev/null +++ b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs @@ -0,0 +1,78 @@ +#nullable enable +using Content.Server.Interfaces; +using Content.Shared.Atmos; +using JetBrains.Annotations; +using Robust.Shared.Serialization; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + public class TritiumFireReaction : IGasReactionEffect + { + public void ExposeData(ObjectSerializer serializer) + { + } + + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder) + { + var energyReleased = 0f; + var oldHeatCapacity = mixture.HeatCapacity; + var temperature = mixture.Temperature; + var location = holder as TileAtmosphere; + mixture.ReactionResults[GasReaction.Fire] = 0f; + var burnedFuel = 0f; + var initialTrit = mixture.GetMoles(Gas.Tritium); + + if (mixture.GetMoles(Gas.Oxygen) < initialTrit || + Atmospherics.MinimumTritiumOxyburnEnergy > (temperature * oldHeatCapacity)) + { + burnedFuel = mixture.GetMoles(Gas.Oxygen) / Atmospherics.TritiumBurnOxyFactor; + if (burnedFuel > initialTrit) + burnedFuel = initialTrit; + + mixture.AdjustMoles(Gas.Tritium, -burnedFuel); + } + else + { + burnedFuel = initialTrit; + mixture.SetMoles(Gas.Tritium, mixture.GetMoles(Gas.Tritium ) * (1 - 1 / Atmospherics.TritiumBurnTritFactor)); + mixture.AdjustMoles(Gas.Oxygen, -mixture.GetMoles(Gas.Tritium)); + energyReleased += (Atmospherics.FireHydrogenEnergyReleased * burnedFuel * (Atmospherics.TritiumBurnTritFactor - 1)); + } + + if (burnedFuel > 0) + { + energyReleased += (Atmospherics.FireHydrogenEnergyReleased * burnedFuel); + + // TODO ATMOS Radiation pulse here! + + // Conservation of mass is important. + mixture.AdjustMoles(Gas.WaterVapor, burnedFuel); + + mixture.ReactionResults[GasReaction.Fire] += burnedFuel; + } + + if (energyReleased > 0) + { + var newHeatCapacity = mixture.HeatCapacity; + if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) + mixture.Temperature = ((temperature * oldHeatCapacity + energyReleased) / newHeatCapacity); + } + + if (location != null) + { + temperature = mixture.Temperature; + if (temperature > Atmospherics.FireMinimumTemperatureToExist) + { + location.HotspotExpose(temperature, mixture.Volume); + + // TODO ATMOS Expose temperature all items on cell + + location.TemperatureExpose(mixture, temperature, mixture.Volume); + } + } + + return mixture.ReactionResults[GasReaction.Fire] != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction; + } + } +} diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index f92cfc3950..a40cf76d1d 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using Content.Server.Atmos.Reactions; using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces; @@ -686,7 +687,7 @@ namespace Content.Server.Atmos if (Hotspot.Bypassing) { - Hotspot.Volume = Air.ReactionResultFire * Atmospherics.FireGrowthRate; + Hotspot.Volume = Air.ReactionResults[GasReaction.Fire] * Atmospherics.FireGrowthRate; Hotspot.Temperature = Air.Temperature; } else @@ -697,7 +698,7 @@ namespace Content.Server.Atmos affected.Temperature = Hotspot.Temperature; affected.React(this); Hotspot.Temperature = affected.Temperature; - Hotspot.Volume = affected.ReactionResultFire * Atmospherics.FireGrowthRate; + Hotspot.Volume = affected.ReactionResults[GasReaction.Fire] * Atmospherics.FireGrowthRate; AssumeAir(affected); } } diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index 5cdd96327b..e5e0722069 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -143,8 +143,12 @@ namespace Content.Shared.Atmos /// /// Total number of gases. Increase this if you want to add more! /// - public const int TotalNumberOfGases = 5; + public const int TotalNumberOfGases = 6; + /// + /// Amount of heat released per mole of burnt hydrogen or tritium (hydrogen isotope) + /// + public const float FireHydrogenEnergyReleased = 560000f; public const float FireMinimumTemperatureToExist = T0C + 100f; public const float FireMinimumTemperatureToSpread = T0C + 150f; public const float FireSpreadRadiosityScale = 0.85f; @@ -159,6 +163,14 @@ namespace Content.Shared.Atmos public const float PhoronOxygenFullburn = 10f; public const float PhoronBurnRateDelta = 9f; + /// + /// This is calculated to help prevent singlecap bombs (Overpowered tritium/oxygen single tank bombs) + /// + public const float MinimumTritiumOxyburnEnergy = 2000000f; + + public const float TritiumBurnOxyFactor = 100f; + public const float TritiumBurnTritFactor = 10f; + /// /// Determines at what pressure the ultra-high pressure red icon is displayed. /// @@ -208,5 +220,6 @@ namespace Content.Shared.Atmos CarbonDioxide = 2, Phoron = 3, Tritium = 4, + WaterVapor = 5, } } diff --git a/Resources/Prototypes/Atmospherics/gases.yml b/Resources/Prototypes/Atmospherics/gases.yml index 7862919b50..0e414ec304 100644 --- a/Resources/Prototypes/Atmospherics/gases.yml +++ b/Resources/Prototypes/Atmospherics/gases.yml @@ -31,3 +31,11 @@ gasOverlaySprite: /Textures/Effects/atmospherics.rsi gasOverlayState: tritium color: 13FF4B + +- type: gas + id: 5 + name: Water Vapor + specificHeat: 40 + gasOverlaySprite: /Textures/Effects/atmospherics.rsi + gasOverlayState: water_vapor + color: bffffd diff --git a/Resources/Prototypes/Atmospherics/reactions.yml b/Resources/Prototypes/Atmospherics/reactions.yml index 9b28728a42..625b1fa2d3 100644 --- a/Resources/Prototypes/Atmospherics/reactions.yml +++ b/Resources/Prototypes/Atmospherics/reactions.yml @@ -9,3 +9,16 @@ - 0.01 # phoron effects: - !type:PhoronFireReaction {} + +- type: gasReaction + id: TritiumFire + priority: -1 + minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist + minimumRequirements: # In this case, same as minimum mole count. + - 0.01 # oxygen + - 0 # nitrogen + - 0 # carbon dioxide + - 0 # phoron + - 0.01 # tritium + effects: + - !type:TritiumFireReaction {}