From 9b8b76fb086544ccbaeb7f5c77c3dc219b6ef3b7 Mon Sep 17 00:00:00 2001 From: CrazyAmphibian <0crazyamphibian@gmail.com> Date: Sun, 22 Dec 2024 00:34:51 -0800 Subject: [PATCH 1/4] a bunch of changes --- .../EntitySystems/AtmosphereSystem.Hotspot.cs | 37 +++-- Content.Server/Atmos/IGasReactionEffect.cs | 2 +- .../Atmos/Reactions/AmmoniaOxygenReaction.cs | 34 ---- .../Atmos/Reactions/AmoniaOxygen_fire.cs | 71 +++++++++ .../Atmos/Reactions/FrezonCoolantReaction.cs | 59 ------- .../Reactions/FrezonOxygen_dissapation.cs | 56 +++++++ .../Atmos/Reactions/FrezonPlasma_cooldown.cs | 55 +++++++ .../Reactions/FrezonProductionReaction.cs | 44 ------ .../Atmos/Reactions/Frezon_decompose.cs | 43 ++++++ .../Reactions/N2ODecompositionReaction.cs | 29 ---- .../Atmos/Reactions/N2O_hightemp_decompose.cs | 45 ++++++ .../Atmos/Reactions/PlasmaFireReaction.cs | 86 ----------- .../PlasmaOxygen_to_fire_reaction.cs | 71 +++++++++ .../Atmos/Reactions/PlasmaSteam_to_Tritium.cs | 59 +++++++ .../Atmos/Reactions/TritiumFireReaction.cs | 71 --------- .../Atmos/Reactions/TritiumOxygen_fire.cs | 66 ++++++++ .../Reactions/_reaction_helper_functions.cs | 104 +++++++++++++ .../IgnitionSource/IgnitionSourceComponent.cs | 2 +- .../Light/EntitySystems/MatchstickSystem.cs | 3 +- .../StationEvents/Events/GasLeakRule.cs | 3 +- Content.Server/Tools/ToolSystem.cs | 3 +- .../Prototypes/Atmospherics/reactions.yml | 145 ++++++++++++------ 22 files changed, 704 insertions(+), 384 deletions(-) delete mode 100644 Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs create mode 100644 Content.Server/Atmos/Reactions/AmoniaOxygen_fire.cs delete mode 100644 Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs create mode 100644 Content.Server/Atmos/Reactions/FrezonOxygen_dissapation.cs create mode 100644 Content.Server/Atmos/Reactions/FrezonPlasma_cooldown.cs delete mode 100644 Content.Server/Atmos/Reactions/FrezonProductionReaction.cs create mode 100644 Content.Server/Atmos/Reactions/Frezon_decompose.cs delete mode 100644 Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs create mode 100644 Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs delete mode 100644 Content.Server/Atmos/Reactions/PlasmaFireReaction.cs create mode 100644 Content.Server/Atmos/Reactions/PlasmaOxygen_to_fire_reaction.cs create mode 100644 Content.Server/Atmos/Reactions/PlasmaSteam_to_Tritium.cs delete mode 100644 Content.Server/Atmos/Reactions/TritiumFireReaction.cs create mode 100644 Content.Server/Atmos/Reactions/TritiumOxygen_fire.cs create mode 100644 Content.Server/Atmos/Reactions/_reaction_helper_functions.cs diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs index a03f27b561ae..a0d6802a48fa 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs @@ -23,6 +23,19 @@ public sealed partial class AtmosphereSystem [ViewVariables(VVAccess.ReadWrite)] public string? HotspotSound { get; private set; } = "/Audio/Effects/fire.ogg"; + private const float min_moles_for_hotspot=.5f; //min moles of fuel+ox to allow combustion + + private float GetHotspotTotalFuel(TileAtmosphere tile){ + if (tile==null || tile.Air==null) return 0f; + return tile.Air.GetMoles(Gas.Plasma)+tile.Air.GetMoles(Gas.Ammonia)+tile.Air.GetMoles(Gas.Tritium); + } + private float GetHotspotTotalOxidizer(TileAtmosphere tile){ + if (tile==null || tile.Air==null) return 0f; + //nitro is .5 because of how it breaks down. (into 1 mole of n2, .5 mole of o2) + return tile.Air.GetMoles(Gas.Oxygen)+tile.Air.GetMoles(Gas.NitrousOxide)*.5f; + } + + private void ProcessHotspot( Entity ent, TileAtmosphere tile) @@ -46,9 +59,9 @@ private void ProcessHotspot( ExcitedGroupResetCooldowns(tile.ExcitedGroup); if ((tile.Hotspot.Temperature < Atmospherics.FireMinimumTemperatureToExist) || (tile.Hotspot.Volume <= 1f) - || tile.Air == null || tile.Air.GetMoles(Gas.Oxygen) < 0.5f || (tile.Air.GetMoles(Gas.Plasma) < 0.5f && tile.Air.GetMoles(Gas.Tritium) < 0.5f)) + || tile.Air == null || GetHotspotTotalFuel(tile)=min_moles_for_hotspot && GetHotspotTotalOxidizer(tile)>=min_moles_for_hotspot; if (tile.Hotspot.Valid) { if (soh) { - if (plasma > 0.5f || tritium > 0.5f) + if (allowhotspotignite) { if (tile.Hotspot.Temperature < exposedTemperature) tile.Hotspot.Temperature = exposedTemperature; @@ -151,7 +170,7 @@ private void HotspotExpose(GridAtmosphereComponent gridAtmosphere, TileAtmospher return; } - if ((exposedTemperature > Atmospherics.PlasmaMinimumBurnTemperature) && (plasma > 0.5f || tritium > 0.5f)) + if ((exposedTemperature > Atmospherics.PlasmaMinimumBurnTemperature) && allowhotspotignite) { if (sparkSourceUid.HasValue) _adminLog.Add(LogType.Flammable, LogImpact.High, $"Heat/spark of {ToPrettyString(sparkSourceUid.Value)} caused atmos ignition of gas: {tile.Air.Temperature.ToString():temperature}K - {oxygen}mol Oxygen, {plasma}mol Plasma, {tritium}mol Tritium"); diff --git a/Content.Server/Atmos/IGasReactionEffect.cs b/Content.Server/Atmos/IGasReactionEffect.cs index 9fc9231908c2..0b3703d4d9e6 100644 --- a/Content.Server/Atmos/IGasReactionEffect.cs +++ b/Content.Server/Atmos/IGasReactionEffect.cs @@ -16,5 +16,5 @@ public partial interface IGasReactionEffect /// 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/Reactions/AmmoniaOxygenReaction.cs b/Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs deleted file mode 100644 index 2c071afab1e9..000000000000 --- a/Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions; - -[UsedImplicitly] -public sealed partial class AmmoniaOxygenReaction : IGasReactionEffect -{ - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var nAmmonia = mixture.GetMoles(Gas.Ammonia); - var nOxygen = mixture.GetMoles(Gas.Oxygen); - var nTotal = mixture.TotalMoles; - - // Concentration-dependent reaction rate - var fAmmonia = nAmmonia/nTotal; - var fOxygen = nOxygen/nTotal; - var rate = MathF.Pow(fAmmonia, 2) * MathF.Pow(fOxygen, 2); - - var deltaMoles = nAmmonia / Atmospherics.AmmoniaOxygenReactionRate * 2 * rate; - - if (deltaMoles <= 0 || nAmmonia - deltaMoles < 0) - return ReactionResult.NoReaction; - - mixture.AdjustMoles(Gas.Ammonia, -deltaMoles); - mixture.AdjustMoles(Gas.Oxygen, -deltaMoles); - mixture.AdjustMoles(Gas.NitrousOxide, deltaMoles / 2); - mixture.AdjustMoles(Gas.WaterVapor, deltaMoles * 1.5f); - - return ReactionResult.Reacting; - } -} diff --git a/Content.Server/Atmos/Reactions/AmoniaOxygen_fire.cs b/Content.Server/Atmos/Reactions/AmoniaOxygen_fire.cs new file mode 100644 index 000000000000..e6245edb85eb --- /dev/null +++ b/Content.Server/Atmos/Reactions/AmoniaOxygen_fire.cs @@ -0,0 +1,71 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class AmoniaOxygen_fire : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + mixture.ReactionResults[GasReaction.Fire]=0f; + // 2(O2) + 2(NH3) -> N2O + 3(H2O) + const float energy_per_mole = 46e3f; //46 kJ/mol. + const float minimum_temp = Atmospherics.T0C+250f; // 275C. this number is pure make-believe. + const float halfstep_temp = 150f; // 150C. what temp past min it will be at half speed. + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float oxy = mixture.GetMoles(Gas.Oxygen); + float amonia = mixture.GetMoles(Gas.Ammonia); + float nitrox = mixture.GetMoles(Gas.NitrousOxide); + float stm = mixture.GetMoles(Gas.NitrousOxide); + float conversionratio=1.0f; + + if(oxy<=0.0f || amonia<=0.0f){ + return ReactionResult.NoReaction; + } + + conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.5f,oxy,amonia); // equal parts. + conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp ); + conversionratio*=(oxy+amonia)/(mixture.TotalMoles-(nitrox+stm)); + + + + if (conversionratio>0.0f){ + float molesconv=MathF.Min(oxy,amonia)*conversionratio; + + totalsystemenergy+= energy_per_mole*.5f*molesconv/heatScale; //half it because that is for a complete reaction, whereas we just use half moles. + + mixture.AdjustMoles(Gas.Ammonia, -molesconv ); + mixture.AdjustMoles(Gas.Oxygen, -molesconv ); + mixture.AdjustMoles(Gas.NitrousOxide, molesconv*.5f ); + mixture.AdjustMoles(Gas.WaterVapor, molesconv*1.5f ); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + if (molesconv>.01f){ + mixture.ReactionResults[GasReaction.Fire] += molesconv; + var location = holder as TileAtmosphere; //start fires + if (location!=null && mixture.Temperature > Atmospherics.FireMinimumTemperatureToExist){ + atmosphereSystem.HotspotExpose(location, mixture.Temperature, mixture.Volume); + } + } + + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs b/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs deleted file mode 100644 index 475c149cf373..000000000000 --- a/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions; - -/// -/// Takes in nitrogen and frezon and cools down the surrounding area. -/// -[UsedImplicitly] -public sealed partial class FrezonCoolantReaction : IGasReactionEffect -{ - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); - var temperature = mixture.Temperature; - - var energyModifier = 1f; - var scale = (temperature - Atmospherics.FrezonCoolLowerTemperature) / - (Atmospherics.FrezonCoolMidTemperature - Atmospherics.FrezonCoolLowerTemperature); - - if (scale > 1f) - { - // Scale energy but not frezon usage if we're in a very, very hot place - energyModifier = Math.Min(scale, Atmospherics.FrezonCoolMaximumEnergyModifier); - scale = 1f; - } - - if (scale <= 0) - return ReactionResult.NoReaction; - - var initialNit = mixture.GetMoles(Gas.Nitrogen); - var initialFrezon = mixture.GetMoles(Gas.Frezon); - - var burnRate = initialFrezon * scale / Atmospherics.FrezonCoolRateModifier; - - var energyReleased = 0f; - if (burnRate > Atmospherics.MinimumHeatCapacity) - { - var nitAmt = Math.Min(burnRate * Atmospherics.FrezonNitrogenCoolRatio, initialNit); - var frezonAmt = Math.Min(burnRate, initialFrezon); - mixture.AdjustMoles(Gas.Nitrogen, -nitAmt); - mixture.AdjustMoles(Gas.Frezon, -frezonAmt); - mixture.AdjustMoles(Gas.NitrousOxide, nitAmt + frezonAmt); - energyReleased = burnRate * Atmospherics.FrezonCoolEnergyReleased * energyModifier; - } - - 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, true); - if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) - mixture.Temperature = (temperature * oldHeatCapacity + energyReleased) / newHeatCapacity; - - return ReactionResult.Reacting; - } -} diff --git a/Content.Server/Atmos/Reactions/FrezonOxygen_dissapation.cs b/Content.Server/Atmos/Reactions/FrezonOxygen_dissapation.cs new file mode 100644 index 000000000000..b57d170ca81f --- /dev/null +++ b/Content.Server/Atmos/Reactions/FrezonOxygen_dissapation.cs @@ -0,0 +1,56 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class FrezonOxygenReaction : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + const float energy_per_mole = 250e3f; //250 kJ/mol. endothermic. this has to be high because we are deleting moles which messes with the total energy quite a bit. + const float minimum_temp = Atmospherics.T0C-30f; // -40C + const float halfstep_temp = 80f; + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float oxy = mixture.GetMoles(Gas.Oxygen); + float frez = mixture.GetMoles(Gas.Frezon); + float conversionratio=1.0f; + + + + if(oxy<=0f || frez<=0f){ + return ReactionResult.NoReaction; + } + + conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp ); + conversionratio*=(frez+oxy)/(mixture.TotalMoles); + + if (conversionratio>0f){ + float molestoreact=MathF.Min(oxy,frez)*conversionratio; + + totalsystemenergy-=molestoreact*energy_per_mole/heatScale; + + mixture.AdjustMoles(Gas.Frezon, -molestoreact); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + + + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/FrezonPlasma_cooldown.cs b/Content.Server/Atmos/Reactions/FrezonPlasma_cooldown.cs new file mode 100644 index 000000000000..02ace0903d2b --- /dev/null +++ b/Content.Server/Atmos/Reactions/FrezonPlasma_cooldown.cs @@ -0,0 +1,55 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class FrezonPlasmaReaction : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + const float energy_per_mole = 1000e3f; //900 kJ/mol. endothermic. + const float minimum_temp = 0f; // 0K. ice cold. + const float halfstep_temp = Atmospherics.T0C; //0C + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float plas = mixture.GetMoles(Gas.Plasma); + float frez = mixture.GetMoles(Gas.Frezon); + float conversionratio=1.0f; + + if(plas<=0f || frez<=0f){ + return ReactionResult.NoReaction; + } + + conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.5f,plas,frez); + conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp ); + conversionratio*=(frez+plas)/(mixture.TotalMoles); + + if (conversionratio>0f){ + float molestoreact=MathF.Min(plas,frez)*conversionratio; + + totalsystemenergy-=molestoreact*energy_per_mole/heatScale; + + mixture.AdjustMoles(Gas.Frezon, -molestoreact); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + + + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs b/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs deleted file mode 100644 index e3d3ece6b6af..000000000000 --- a/Content.Server/Atmos/Reactions/FrezonProductionReaction.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions; - -/// -/// Produces frezon from oxygen and tritium, with nitrogen as a catalyst that also acts as a stopper if too much is present. -/// Has a max temperature, but paradoxically gets more efficient the hotter it is. -/// -[UsedImplicitly] -public sealed partial class FrezonProductionReaction : IGasReactionEffect -{ - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var initialN2 = mixture.GetMoles(Gas.Nitrogen); - var initialOxy = mixture.GetMoles(Gas.Oxygen); - var initialTrit = mixture.GetMoles(Gas.Tritium); - - var efficiency = mixture.Temperature / Atmospherics.FrezonProductionMaxEfficiencyTemperature; - var loss = 1 - efficiency; - - // How much the catalyst (N2) will allow us to produce - // Less N2 is required the more efficient it is. - var catalystLimit = initialN2 * (Atmospherics.FrezonProductionNitrogenRatio / efficiency); - var oxyLimit = Math.Min(initialOxy, catalystLimit) / Atmospherics.FrezonProductionTritRatio; - - // Amount of tritium & oxygen that are reacting - var tritBurned = Math.Min(oxyLimit, initialTrit); - var oxyBurned = tritBurned * Atmospherics.FrezonProductionTritRatio; - - var oxyConversion = oxyBurned / Atmospherics.FrezonProductionConversionRate; - var tritConversion = tritBurned / Atmospherics.FrezonProductionConversionRate; - var total = oxyConversion + tritConversion; - - mixture.AdjustMoles(Gas.Oxygen, -oxyConversion); - mixture.AdjustMoles(Gas.Tritium, -tritConversion); - mixture.AdjustMoles(Gas.Frezon, total * efficiency); - mixture.AdjustMoles(Gas.Nitrogen, total * loss); - - return ReactionResult.Reacting; - } -} diff --git a/Content.Server/Atmos/Reactions/Frezon_decompose.cs b/Content.Server/Atmos/Reactions/Frezon_decompose.cs new file mode 100644 index 000000000000..682d4c6784bc --- /dev/null +++ b/Content.Server/Atmos/Reactions/Frezon_decompose.cs @@ -0,0 +1,43 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class FrezonDecomposition : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + const float minimum_temp = Atmospherics.T0C; // will break down above 0C + const float halfstep_temp = 1000f; + + float currenttemp=mixture.Temperature; + float frez = mixture.GetMoles(Gas.Frezon); + + if(frez<=0f){ + return ReactionResult.NoReaction; + } + + float conversionratio=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp ); + + if (conversionratio>0f){ + float molestoreact=frez*conversionratio; + + mixture.AdjustMoles(Gas.Frezon, -molestoreact); //break down into oxy. this is done because it's its originating gas + mixture.AdjustMoles(Gas.Oxygen, molestoreact); //but also, because it makes it so that frezon cans don't just evaporate into nothing. + + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + + + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs b/Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs deleted file mode 100644 index 367c0eb7b9cf..000000000000 --- a/Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions; - -/// -/// Decomposes Nitrous Oxide into Nitrogen and Oxygen. -/// -[UsedImplicitly] -public sealed partial class N2ODecompositionReaction : IGasReactionEffect -{ - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var cacheN2O = mixture.GetMoles(Gas.NitrousOxide); - - var burnedFuel = cacheN2O / Atmospherics.N2ODecompositionRate; - - if (burnedFuel <= 0 || cacheN2O - burnedFuel < 0) - return ReactionResult.NoReaction; - - mixture.AdjustMoles(Gas.NitrousOxide, -burnedFuel); - mixture.AdjustMoles(Gas.Nitrogen, burnedFuel); - mixture.AdjustMoles(Gas.Oxygen, burnedFuel / 2); - - return ReactionResult.Reacting; - } -} diff --git a/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs new file mode 100644 index 000000000000..fdb305602b26 --- /dev/null +++ b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs @@ -0,0 +1,45 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class N2O_decompose_Reaction : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + //source: http://vias.org/genchem/standard_enthalpies_table.html + const float energy_per_mole_decomposed = 81.55e3f; //81.55 kJ/mole. + const float min_temp_to_decompose = Atmospherics.T0C+300f; //starts to decompose at 300C + const float decomposition_halfmark = 2925f; // at this many degrees more than the min, half will decompose in a cycle. (1250C total) + //these numbers were eyeballed, honestly. finding a source for this is hard. + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float n2o = mixture.GetMoles(Gas.NitrousOxide); + + float conversionratio=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, min_temp_to_decompose ,decomposition_halfmark ); + + float totalmolesdecomp=n2o*conversionratio; + + if (totalmolesdecomp>0.0f){ + totalsystemenergy+=totalmolesdecomp*energy_per_mole_decomposed/heatScale; + mixture.AdjustMoles(Gas.NitrousOxide, -totalmolesdecomp ); + mixture.AdjustMoles(Gas.Nitrogen, totalmolesdecomp ); + mixture.AdjustMoles(Gas.Oxygen, totalmolesdecomp*0.5f ); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs b/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs deleted file mode 100644 index 98d567d4ed52..000000000000 --- a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions -{ - [UsedImplicitly] - [DataDefinition] - public sealed partial class PlasmaFireReaction : IGasReactionEffect - { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var energyReleased = 0f; - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); - var temperature = mixture.Temperature; - var location = holder as TileAtmosphere; - mixture.ReactionResults[GasReaction.Fire] = 0; - - // More plasma released at higher temperatures. - var temperatureScale = 0f; - - if (temperature > Atmospherics.PlasmaUpperTemperature) - temperatureScale = 1f; - else - { - temperatureScale = (temperature - Atmospherics.PlasmaMinimumBurnTemperature) / - (Atmospherics.PlasmaUpperTemperature - Atmospherics.PlasmaMinimumBurnTemperature); - } - - if (temperatureScale > 0) - { - var oxygenBurnRate = Atmospherics.OxygenBurnRateBase - temperatureScale; - var plasmaBurnRate = 0f; - - var initialOxygenMoles = mixture.GetMoles(Gas.Oxygen); - var initialPlasmaMoles = mixture.GetMoles(Gas.Plasma); - - // Supersaturation makes tritium. - var oxyRatio = initialOxygenMoles / initialPlasmaMoles; - // Efficiency of reaction decreases from 1% Plasma to 3% plasma: - var supersaturation = Math.Clamp((oxyRatio - Atmospherics.SuperSaturationEnds) / - (Atmospherics.SuperSaturationThreshold - - Atmospherics.SuperSaturationEnds), 0.0f, 1.0f); - - if (initialOxygenMoles > initialPlasmaMoles * Atmospherics.PlasmaOxygenFullburn) - plasmaBurnRate = initialPlasmaMoles * temperatureScale / Atmospherics.PlasmaBurnRateDelta; - else - plasmaBurnRate = temperatureScale * (initialOxygenMoles / Atmospherics.PlasmaOxygenFullburn) / Atmospherics.PlasmaBurnRateDelta; - - if (plasmaBurnRate > Atmospherics.MinimumHeatCapacity) - { - plasmaBurnRate = MathF.Min(plasmaBurnRate, MathF.Min(initialPlasmaMoles, initialOxygenMoles / oxygenBurnRate)); - mixture.SetMoles(Gas.Plasma, initialPlasmaMoles - plasmaBurnRate); - mixture.SetMoles(Gas.Oxygen, initialOxygenMoles - plasmaBurnRate * oxygenBurnRate); - - // supersaturation adjusts the ratio of produced tritium to unwanted CO2 - mixture.AdjustMoles(Gas.Tritium, plasmaBurnRate * supersaturation); - mixture.AdjustMoles(Gas.CarbonDioxide, plasmaBurnRate * (1.0f - supersaturation)); - - energyReleased += Atmospherics.FirePlasmaEnergyReleased * plasmaBurnRate; - 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, true); - if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) - mixture.Temperature = (temperature * oldHeatCapacity + energyReleased) / newHeatCapacity; - } - - if (location != null) - { - var mixTemperature = mixture.Temperature; - if (mixTemperature > Atmospherics.FireMinimumTemperatureToExist) - { - atmosphereSystem.HotspotExpose(location, mixTemperature, mixture.Volume); - } - } - - return mixture.ReactionResults[GasReaction.Fire] != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction; - } - } -} diff --git a/Content.Server/Atmos/Reactions/PlasmaOxygen_to_fire_reaction.cs b/Content.Server/Atmos/Reactions/PlasmaOxygen_to_fire_reaction.cs new file mode 100644 index 000000000000..7030a88d2d99 --- /dev/null +++ b/Content.Server/Atmos/Reactions/PlasmaOxygen_to_fire_reaction.cs @@ -0,0 +1,71 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class PlasmaOxygen_Reaction : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + mixture.ReactionResults[GasReaction.Fire]=0f; + + const float plasmafire_energy_per_mole = 2000e3f; //2 MJ/mol. blasma. + const float plasmafire_minimum_temp = Atmospherics.T0C+200f; // 250C. below this it will not react. + const float plasmafire_halfstep_temp = 1750f; // 1750C. what temp past min it will be at half speed. + const float plasmafire_oxygenratio = .4f; //40-60 ratio of oxygen to plasma. + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float heatgenerated=0.0f; + float oxy = mixture.GetMoles(Gas.Oxygen); + float plas = mixture.GetMoles(Gas.Plasma); + float carb = mixture.GetMoles(Gas.CarbonDioxide); + float conversionratio=1.0f; //multiply it by the factors to get the final. + + conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(plasmafire_oxygenratio,oxy,plas); // 40-60 ratio + conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, plasmafire_minimum_temp ,plasmafire_halfstep_temp ); + conversionratio*=(oxy+plas)/(mixture.TotalMoles-carb); //adjust by total amount of gas that is not this. do not penalize waste products. + + if (conversionratio>0.0f){ //if we are burning + //this ensures that the output will be clamped to 0-1 for any ratio. + float oxyfactor=plasmafire_oxygenratio/MathF.Max(plasmafire_oxygenratio,1.0f-plasmafire_oxygenratio); + float plasmafactor=(1.0f-plasmafire_oxygenratio)/MathF.Max(plasmafire_oxygenratio,1.0f-plasmafire_oxygenratio); + + + + totalsystemenergy+=plasmafire_energy_per_mole*plas*plasmafactor*conversionratio/heatScale; + + mixture.AdjustMoles(Gas.Plasma, -plas*(conversionratio)*plasmafactor ); + mixture.AdjustMoles(Gas.Oxygen, -oxy*(conversionratio)*oxyfactor ); + + float pmc=plas*(conversionratio)*plasmafactor; + float omc=oxy*(conversionratio) *oxyfactor; + + mixture.AdjustMoles(Gas.CarbonDioxide, plas*(conversionratio)*plasmafactor ); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add nwe heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + if (plas*conversionratio*plasmafactor + oxy*conversionratio*oxyfactor >.01f){ + mixture.ReactionResults[GasReaction.Fire]+=plas*conversionratio*plasmafactor + oxy*conversionratio*oxyfactor; + var location = holder as TileAtmosphere; //start fires + if (location!=null && mixture.Temperature > Atmospherics.FireMinimumTemperatureToExist){ + atmosphereSystem.HotspotExpose(location, mixture.Temperature, mixture.Volume); + } + } + + return ReactionResult.Reacting; + } + //if we are not... + return ReactionResult.NoReaction; //just end calcs. + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/PlasmaSteam_to_Tritium.cs b/Content.Server/Atmos/Reactions/PlasmaSteam_to_Tritium.cs new file mode 100644 index 000000000000..f1ca6825e9dd --- /dev/null +++ b/Content.Server/Atmos/Reactions/PlasmaSteam_to_Tritium.cs @@ -0,0 +1,59 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class TritiumProduction : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + const float minimum_temp = Atmospherics.T0C+100f; //min temp for the reaction to occur + const float peak_temp = Atmospherics.T0C+250f; // the temp where the reaction peaks in speed. + const float maximum_temp = Atmospherics.T0C+500f; //max temp for it to occur + const float energy_per_mole_transmuted=-50e3f; // 50 kJ per mole. endothermic. + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float plas = mixture.GetMoles(Gas.Plasma); + float steam = mixture.GetMoles(Gas.WaterVapor); + float trt = mixture.GetMoles(Gas.Tritium); + float ox = mixture.GetMoles(Gas.Oxygen); + + if (plas<=0.0f || steam<=0.0f){ + return ReactionResult.NoReaction; + } + + float conversionratio=1.0f; + + + conversionratio*=GasReactionHelperFunctions.reaction_mult_finite_band(currenttemp, minimum_temp, peak_temp, maximum_temp); + conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.1f, steam,plas); //10-90. this is to slow it. + conversionratio*= (plas+steam)/(mixture.TotalMoles-(ox+trt)*.5f); + + if(conversionratio>0.0f){ + float molesconvert = MathF.Min(steam,plas/9.0f); + + totalsystemenergy-=molesconvert*energy_per_mole_transmuted/heatScale; + + mixture.AdjustMoles(Gas.WaterVapor, -molesconvert ); //H2O + mixture.AdjustMoles(Gas.Oxygen, molesconvert*.5f ); //O + mixture.AdjustMoles(Gas.Tritium, molesconvert ); //H2 + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //adjust for new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs deleted file mode 100644 index 3ad0a4b04de1..000000000000 --- a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Atmos.Reactions; -using JetBrains.Annotations; - -namespace Content.Server.Atmos.Reactions -{ - [UsedImplicitly] - [DataDefinition] - public sealed partial class TritiumFireReaction : IGasReactionEffect - { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) - { - var energyReleased = 0f; - var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); - 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 * heatScale)) - { - 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; - } - - energyReleased /= heatScale; // adjust energy to make sure speedup doesn't cause mega temperature rise - if (energyReleased > 0) - { - var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture, true); - if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) - mixture.Temperature = ((temperature * oldHeatCapacity + energyReleased) / newHeatCapacity); - } - - if (location != null) - { - temperature = mixture.Temperature; - if (temperature > Atmospherics.FireMinimumTemperatureToExist) - { - atmosphereSystem.HotspotExpose(location, temperature, mixture.Volume); - } - } - - return mixture.ReactionResults[GasReaction.Fire] != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction; - } - } -} diff --git a/Content.Server/Atmos/Reactions/TritiumOxygen_fire.cs b/Content.Server/Atmos/Reactions/TritiumOxygen_fire.cs new file mode 100644 index 000000000000..a11a7611cf92 --- /dev/null +++ b/Content.Server/Atmos/Reactions/TritiumOxygen_fire.cs @@ -0,0 +1,66 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Reactions; +using JetBrains.Annotations; + +using Content.Server.Atmos.GasReactionHelpers; + +namespace Content.Server.Atmos.Reactions +{ + [UsedImplicitly] + [DataDefinition] + public sealed partial class TritiumOxygenFire : IGasReactionEffect + { + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale) + { + mixture.ReactionResults[GasReaction.Fire]=0f; + // 2(H2) + O2 -> 2(H2O) + const float energy_per_mole = 482e3f; //482 kJ/mol. this will be halved later because 2 mols in the H2 to H2O + const float minimum_temp = Atmospherics.T0C+225f; // 200C. this number is pure make-believe. + const float halfstep_temp = 100f; // 500C. what temp past min it will be at half speed. + + float currenttemp=mixture.Temperature; + float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp; + float oxy = mixture.GetMoles(Gas.Oxygen); + float trit = mixture.GetMoles(Gas.Tritium); + float stm = mixture.GetMoles(Gas.Tritium); + float conversionratio=1.0f; + + if (oxy<=0.0f || trit<=0.0f){ + return ReactionResult.NoReaction; + } + + conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.33333333333f,oxy,trit); // 1:2 + conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp ); + conversionratio*=(oxy+trit)/(mixture.TotalMoles-stm); + + if(conversionratio>0.0f){ + float molesconv=MathF.Min(oxy*.5f,trit)*conversionratio; + + totalsystemenergy+= energy_per_mole*.5f*molesconv/heatScale; //half it because that is for a complete reaction, whereas we just use half moles. + + mixture.AdjustMoles(Gas.Tritium, -molesconv ); + mixture.AdjustMoles(Gas.Oxygen, -molesconv*.5f ); + mixture.AdjustMoles(Gas.WaterVapor, molesconv ); + + float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat + if (newheatcap > Atmospherics.MinimumHeatCapacity){ + mixture.Temperature=totalsystemenergy/newheatcap; + } + + if (molesconv>.01f){ + mixture.ReactionResults[GasReaction.Fire] += molesconv; + var location = holder as TileAtmosphere; //start fires + if (location!=null && mixture.Temperature > Atmospherics.FireMinimumTemperatureToExist){ + atmosphereSystem.HotspotExpose(location, mixture.Temperature, mixture.Volume); + } + } + return ReactionResult.Reacting; + } + return ReactionResult.NoReaction; + + + + } + } +} \ No newline at end of file diff --git a/Content.Server/Atmos/Reactions/_reaction_helper_functions.cs b/Content.Server/Atmos/Reactions/_reaction_helper_functions.cs new file mode 100644 index 000000000000..452c423e00bd --- /dev/null +++ b/Content.Server/Atmos/Reactions/_reaction_helper_functions.cs @@ -0,0 +1,104 @@ +namespace Content.Server.Atmos.GasReactionHelpers +{ + public static class GasReactionHelperFunctions{ + + + + /* + this is to simulate an under/oversaturated mixture. closer to the ideal mix means more reaction. + do NOT set the idealratio to 1.0 or 0.0, as that may cause a div 0 - so do that at your own risk. + 0.0 <-> 1.0 ; 0.0 = all gas2, 1.0 = all gas 1, 0.5 = same of both. you get the idea. + here's the function in math format, you can paste it into desmos and move the var around to see how it works. + \max\left(0,\left\{x>R_{ideal}:\frac{\left(x-1\right)\left(-x+2R_{ideal}-1\right)}{\left(1-R_{ideal}\right)^{2}},\frac{\left(x\right)\left(2R_{ideal}-x\right)}{R_{ideal}^{2}}\right\}\right) + */ + public static float reaction_mult_2gas_idealratio(float idealratio, float molesgas1,float molesgas2){ + if(molesgas1<=0.0f || molesgas2 <=0.0f){ + return 0.0f; + } + float reactionmultiplier=0.0f; + float currentratio=molesgas1/(molesgas1+molesgas2); + + //this function uses a fancy parabolic interpolation. results in less effect harshness. + if (currentratio>idealratio){ + reactionmultiplier= (currentratio-1)*(-currentratio+2f*idealratio-1f)/((1f-idealratio)*(1f-idealratio)); + }else{ + reactionmultiplier= (idealratio)*(2f*idealratio-currentratio)/(idealratio*idealratio); + } + + reactionmultiplier=MathF.Max(0.0f,reactionmultiplier); //clamp to 0.0 to 1.0. we don't have to call min because that's already done for us in the previous if check. + + return reactionmultiplier; + } + + /* + this was used before, however the linear results act almost as a band-pass and result in undesirable behavior (really slow rates) when off-ratio. still here if you want to use it for whatever reason + formula: + \max\left(0,\left\{x>R_{ideal}:\frac{\left(1-x\right)}{1-R_{ideal}},\frac{x}{R_{ideal}}\right\}\right) + */ + public static float reaction_mult_2gas_idealratio_linear(float idealratio, float molesgas1,float molesgas2){ + if(molesgas1<=0.0f || molesgas2 <=0.0f){ + return 0.0f; + } + float reactionmultiplier=0.0f; + float currentratio=molesgas1/(molesgas1+molesgas2); + + //this function is essentially a linear interpolation between the point (0,0) -> (idealratio,1) and (idealratio,1) -> (1,0) + if (currentratio>idealratio){ + reactionmultiplier=(1.0f-currentratio)/(1.0f-idealratio); + }else{ + reactionmultiplier= currentratio/idealratio; + } + + reactionmultiplier=MathF.Max(0.0f,reactionmultiplier); //clamp to 0.0 to 1.0. we don't have to call min because that's already done for us in the previous if check. + + return reactionmultiplier; + } + + + /* + this function makes higher temps increase. + function characteristics: x-> +inf, y-> 1 ; x->[mintemp], y->0 + any temp below mintemp returns 0. above this, it increases with diminishing returns. the variable temphalfpoint determines the steepness. when the temp beyond the minimum temp is equal to this value, the output will be 0.5 + temphalfpoint should be above 0. + math format function: + 1-\frac{t_{half}}{\max\left(0.0,x-t_{min}\right)+t_{half}} + */ + public static float reaction_mult_mintemp_higher_asymptote(float actualtemp, float mintemp,float temphalfpoint){ + float tf= 1.0f- temphalfpoint/(MathF.Max(0.0f,actualtemp-mintemp)+temphalfpoint ); + return tf*tf; //square the result to make it a bit less abrupt. + } + + /* + essentially the same as above, except the direction is reversed. + math format function: + 1+\frac{t_{half}}{\min\left(0.0,x-t_{min}\right)-t_{half}} + */ + public static float reaction_mult_maxtemp_lower_asymptote(float actualtemp, float mintemp,float temphalfpoint){ + float tf= 1.0f+ temphalfpoint/(MathF.Min(0.0f,actualtemp-mintemp)-temphalfpoint ); + return tf*tf; + } + + /* + gives a finite band in which the value is above 0. the value peaks at peaktemp. this doesn't use linear interpolation, but rather creates a piecewise parabola to make a silky smooth curve. + it's a bit more complex, though. + peaktemp should be between mintemp and maxtemp, and maxtemp should be greater than mintemp. duh. + math formula: + \max\left(0,\left\{x>m:1-\frac{\left(x-m\right)}{\left(b-m\right)}^{2},1-\frac{\left(x-m\right)}{\left(m-a\right)}^{2}\right\}\right) + */ + public static float reaction_mult_finite_band(float actualtemp, float mintemp,float peaktemp,float maxtemp){ + float reactionmultiplier=1.0f; + float tempval = (actualtemp-peaktemp); + if(actualtemp>peaktemp){ + tempval/=maxtemp-peaktemp; + reactionmultiplier-= tempval*tempval; + }else{ + tempval/=peaktemp-mintemp; + reactionmultiplier-= tempval*tempval; + } + + reactionmultiplier=MathF.Max(0.0f,reactionmultiplier); + return reactionmultiplier; + } + + } +} \ No newline at end of file diff --git a/Content.Server/IgnitionSource/IgnitionSourceComponent.cs b/Content.Server/IgnitionSource/IgnitionSourceComponent.cs index d6e0ab9407dc..d4b2755aded6 100644 --- a/Content.Server/IgnitionSource/IgnitionSourceComponent.cs +++ b/Content.Server/IgnitionSource/IgnitionSourceComponent.cs @@ -10,5 +10,5 @@ public sealed partial class IgnitionSourceComponent : Component public bool Ignited; [DataField, ViewVariables(VVAccess.ReadWrite)] - public int Temperature = 700; + public int Temperature = 973; } diff --git a/Content.Server/Light/EntitySystems/MatchstickSystem.cs b/Content.Server/Light/EntitySystems/MatchstickSystem.cs index 96e4695784dd..6b937805a584 100644 --- a/Content.Server/Light/EntitySystems/MatchstickSystem.cs +++ b/Content.Server/Light/EntitySystems/MatchstickSystem.cs @@ -52,7 +52,8 @@ public override void Update(float frameTime) var position = _transformSystem.GetGridOrMapTilePosition(match, xform); - _atmosphereSystem.HotspotExpose(gridUid, position, 400, 50, match, true); + //400C + _atmosphereSystem.HotspotExpose(gridUid, position, 673.15f, 50, match, true); } } diff --git a/Content.Server/StationEvents/Events/GasLeakRule.cs b/Content.Server/StationEvents/Events/GasLeakRule.cs index 9e1f70474c1b..53d594ccb171 100644 --- a/Content.Server/StationEvents/Events/GasLeakRule.cs +++ b/Content.Server/StationEvents/Events/GasLeakRule.cs @@ -82,7 +82,8 @@ private void Spark(EntityUid uid, GasLeakRuleComponent component) // Don't want it to be so obnoxious as to instantly murder anyone in the area but enough that // it COULD start potentially start a bigger fire. - _atmosphere.HotspotExpose(component.TargetGrid, component.TargetTile, 700f, 50f, null, true); + //700C + _atmosphere.HotspotExpose(component.TargetGrid, component.TargetTile, 973.15f, 50f, null, true); Audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/sparks4.ogg"), component.TargetCoords); } } diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs index 7738a6398fad..8106647562fc 100644 --- a/Content.Server/Tools/ToolSystem.cs +++ b/Content.Server/Tools/ToolSystem.cs @@ -20,7 +20,8 @@ public override void TurnOn(Entity entity, EntityUid? user) if (xform.GridUid is { } gridUid) { var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, xform); - _atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, entity.Owner, true); + //700C + _atmosphereSystem.HotspotExpose(gridUid, position, 973.15f, 50, entity.Owner, true); } } diff --git a/Resources/Prototypes/Atmospherics/reactions.yml b/Resources/Prototypes/Atmospherics/reactions.yml index d226c81f6cc5..73e8cef1dbaf 100644 --- a/Resources/Prototypes/Atmospherics/reactions.yml +++ b/Resources/Prototypes/Atmospherics/reactions.yml @@ -3,82 +3,131 @@ priority: -2 minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist minimumRequirements: # In this case, same as minimum mole count. - - 0.01 # oxygen + - 0.1 # oxygen - 0 # nitrogen - 0 # carbon dioxide - - 0.01 # plasma + - 0.1 # plasma effects: - - !type:PlasmaFireReaction {} + - !type:PlasmaOxygen_Reaction {} - type: gasReaction - id: TritiumFire + id: AmoniaFire priority: -1 - minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist + minimumTemperature: 398.15 minimumRequirements: # In this case, same as minimum mole count. - - 0.01 # oxygen - - 0 # nitrogen - - 0 # carbon dioxide - - 0 # plasma - - 0.01 # tritium + - 0.1 # oxygen + - 0 # nitrogen + - 0 # carbon dioxide + - 0 # plasma + - 0 # tritium + - 0 # vapor + - 0.1 # ammonia + - 0 # n2o + - 0 # frezon effects: - - !type:TritiumFireReaction {} + - !type:AmoniaOxygen_fire {} + - type: gasReaction - id: FrezonCoolant + id: TritiumFire + priority: 0 + minimumTemperature: 398.15 + minimumRequirements: # In this case, same as minimum mole count. + - 0.1 # oxygen + - 0 # nitrogen + - 0 # carbon dioxide + - 0 # plasma + - 0.1 # tritium + - 0 # vapor + - 0 # ammonia + - 0 # n2o + - 0 # frezon + effects: + - !type:TritiumOxygenFire {} + + + + + + +- type: gasReaction + id: TritiumProd priority: 1 - minimumTemperature: 23.15 - minimumRequirements: + minimumTemperature: 373.149 + minimumRequirements: # In this case, same as minimum mole count. - 0 # oxygen - - 0.01 # nitrogen + - 0 # nitrogen - 0 # carbon dioxide - - 0 # plasma + - 0.1 # plasma - 0 # tritium - - 0 # vapor + - 0.1 # vapor - 0 # ammonia - 0 # n2o - - 0.01 # frezon + - 0 # frezon effects: - - !type:FrezonCoolantReaction {} + - !type:TritiumProduction {} + + - type: gasReaction - id: FrezonProduction + id: NitrousDecompose priority: 2 - maximumTemperature: 73.15 # Cold tritium fire, basically. - minimumRequirements: - - 0.01 # oxygen - - 0.01 # nitrogen + minimumTemperature: 573.15 + minimumRequirements: # In this case, same as minimum mole count. + - 0 # oxygen + - 0 # nitrogen - 0 # carbon dioxide - 0 # plasma - - 0.01 # tritium + - 0 # tritium - 0 # vapor - 0 # ammonia - - 0 # n2o + - 0.05 # n2o - 0 # frezon effects: - - !type:FrezonProductionReaction {} - + - !type:N2O_decompose_Reaction {} + + - type: gasReaction - id: AmmoniaOxygenReaction - priority: 2 - minimumTemperature: 323.149 - minimumRequirements: - - 0.01 # oxygen + id: FrezonPlasCool + priority: 3 + minimumTemperature: 0.0 + minimumRequirements: # In this case, same as minimum mole count. + - 0 # oxygen + - 0 # nitrogen + - 0 # carbon dioxide + - 0.05 # plasma + - 0 # tritium + - 0 # vapor + - 0 # ammonia + - 0 # n2o + - 0.05 # frezon + effects: + - !type:FrezonPlasmaReaction {} + + +- type: gasReaction + id: FrezonOxyCool + priority: 4 + minimumTemperature: 233.15 + minimumRequirements: # In this case, same as minimum mole count. + - 0.05 # oxygen - 0 # nitrogen - 0 # carbon dioxide - 0 # plasma - 0 # tritium - 0 # vapor - - 0.01 # ammonia + - 0 # ammonia - 0 # n2o - - 0 # frezon + - 0.05 # frezon effects: - - !type:AmmoniaOxygenReaction {} - + - !type:FrezonOxygenReaction {} + + - type: gasReaction - id: N2ODecomposition - priority: 0 - minimumTemperature: 850 - minimumRequirements: + id: FrezonDecomp + priority: 5 + minimumTemperature: 273.15 + minimumRequirements: # In this case, same as minimum mole count. - 0 # oxygen - 0 # nitrogen - 0 # carbon dioxide @@ -86,14 +135,16 @@ - 0 # tritium - 0 # vapor - 0 # ammonia - - 0.01 # n2o - - 0 # frezon + - 0 # n2o + - 0.01 # frezon effects: - - !type:N2ODecompositionReaction {} - + - !type:FrezonDecomposition {} + + + #- type: gasReaction # id: WaterVaporPuddle -# priority: 1 +# priority: 6 # maximumTemperature: 373.13 # Boiling point of water. # minimumRequirements: # In this case, same as minimum mole count. # - 0 # oxygen @@ -105,4 +156,4 @@ # effects: # - !type:WaterVaporReaction # gas: 5 -# reagent: Water +# reagent: Water \ No newline at end of file From 3239363e2e463ee73a35924703ce335f7eefd31d Mon Sep 17 00:00:00 2001 From: CrazyAmphibian <0crazyamphibian@gmail.com> Date: Sun, 22 Dec 2024 00:46:09 -0800 Subject: [PATCH 2/4] Update N2O_hightemp_decompose.cs --- Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs index fdb305602b26..89b22f1996f5 100644 --- a/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs +++ b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs @@ -16,7 +16,7 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos //source: http://vias.org/genchem/standard_enthalpies_table.html const float energy_per_mole_decomposed = 81.55e3f; //81.55 kJ/mole. const float min_temp_to_decompose = Atmospherics.T0C+300f; //starts to decompose at 300C - const float decomposition_halfmark = 2925f; // at this many degrees more than the min, half will decompose in a cycle. (1250C total) + const float decomposition_halfmark = 1500f; // at this many degrees more than the min, half will decompose in a cycle. (1250C total) //these numbers were eyeballed, honestly. finding a source for this is hard. float currenttemp=mixture.Temperature; From d093bf5b664408250e5d0b495f16bde8837bfe48 Mon Sep 17 00:00:00 2001 From: CrazyAmphibian <0crazyamphibian@gmail.com> Date: Sun, 22 Dec 2024 00:46:23 -0800 Subject: [PATCH 3/4] Update N2O_hightemp_decompose.cs --- Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs index 89b22f1996f5..8a9221f58790 100644 --- a/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs +++ b/Content.Server/Atmos/Reactions/N2O_hightemp_decompose.cs @@ -16,7 +16,7 @@ public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, Atmos //source: http://vias.org/genchem/standard_enthalpies_table.html const float energy_per_mole_decomposed = 81.55e3f; //81.55 kJ/mole. const float min_temp_to_decompose = Atmospherics.T0C+300f; //starts to decompose at 300C - const float decomposition_halfmark = 1500f; // at this many degrees more than the min, half will decompose in a cycle. (1250C total) + const float decomposition_halfmark = 1250f; // at this many degrees more than the min, half will decompose in a cycle. (1250C total) //these numbers were eyeballed, honestly. finding a source for this is hard. float currenttemp=mixture.Temperature; From 6ff0e382b46bb8eb1e7b9a3514d7f523800ca9a7 Mon Sep 17 00:00:00 2001 From: CrazyAmphibian <0crazyamphibian@gmail.com> Date: Sun, 22 Dec 2024 01:11:03 -0800 Subject: [PATCH 4/4] remove redundant oldcode --- .../EntitySystems/AtmosphereSystem.Hotspot.cs | 2 +- Content.Shared/Atmos/Atmospherics.cs | 65 ------------------- 2 files changed, 1 insertion(+), 66 deletions(-) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs index a0d6802a48fa..fbae746662ae 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs @@ -170,7 +170,7 @@ private void HotspotExpose(GridAtmosphereComponent gridAtmosphere, TileAtmospher return; } - if ((exposedTemperature > Atmospherics.PlasmaMinimumBurnTemperature) && allowhotspotignite) + if ((exposedTemperature > Atmospherics.FireMinimumTemperatureToExist) && allowhotspotignite) { if (sparkSourceUid.HasValue) _adminLog.Add(LogType.Flammable, LogImpact.High, $"Heat/spark of {ToPrettyString(sparkSourceUid.Value)} caused atmos ignition of gas: {tile.Air.Temperature.ToString():temperature}K - {oxygen}mol Oxygen, {plasma}mol Plasma, {tritium}mol Tritium"); diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index cb89f6c19920..86ff0f8acbad 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -196,76 +196,11 @@ public static class Atmospherics /// public const int AdjustedNumberOfGases = ((TotalNumberOfGases + 3) / 4) * 4; - /// - /// Amount of heat released per mole of burnt hydrogen or tritium (hydrogen isotope) - /// - public const float FireHydrogenEnergyReleased = 284e3f; // hydrogen is 284 kJ/mol public const float FireMinimumTemperatureToExist = T0C + 100f; public const float FireMinimumTemperatureToSpread = T0C + 150f; public const float FireSpreadRadiosityScale = 0.85f; - public const float FirePlasmaEnergyReleased = 160e3f; // methane is 16 kJ/mol, plus plasma's spark of magic public const float FireGrowthRate = 40000f; - public const float SuperSaturationThreshold = 96f; - public const float SuperSaturationEnds = SuperSaturationThreshold / 3; - - public const float OxygenBurnRateBase = 1.4f; - public const float PlasmaMinimumBurnTemperature = (100f+T0C); - public const float PlasmaUpperTemperature = (1370f+T0C); - public const float PlasmaOxygenFullburn = 10f; - public const float PlasmaBurnRateDelta = 9f; - - /// - /// This is calculated to help prevent singlecap bombs (Overpowered tritium/oxygen single tank bombs) - /// - public const float MinimumTritiumOxyburnEnergy = 143000f; - - public const float TritiumBurnOxyFactor = 100f; - public const float TritiumBurnTritFactor = 10f; - - public const float FrezonCoolLowerTemperature = 23.15f; - - /// - /// Frezon cools better at higher temperatures. - /// - public const float FrezonCoolMidTemperature = 373.15f; - - public const float FrezonCoolMaximumEnergyModifier = 10f; - - /// - /// Remove X mol of nitrogen for each mol of frezon. - /// - public const float FrezonNitrogenCoolRatio = 5; - public const float FrezonCoolEnergyReleased = -600e3f; - public const float FrezonCoolRateModifier = 20f; - - public const float FrezonProductionMaxEfficiencyTemperature = 73.15f; - - /// - /// 1 mol of N2 is required per X mol of tritium and oxygen. - /// - public const float FrezonProductionNitrogenRatio = 10f; - - /// - /// 1 mol of Tritium is required per X mol of oxygen. - /// - public const float FrezonProductionTritRatio = 8.0f; - - /// - /// 1 / X of the tritium is converted into Frezon each tick - /// - public const float FrezonProductionConversionRate = 50f; - - /// - /// The maximum portion of the N2O that can decompose each reaction tick. (50%) - /// - public const float N2ODecompositionRate = 2f; - - /// - /// Divisor for Ammonia Oxygen reaction so that it doesn't happen instantaneously. - /// - public const float AmmoniaOxygenReactionRate = 10f; - /// /// Determines at what pressure the ultra-high pressure red icon is displayed. ///