]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Revert "Add YAML gas reactions (#22803)" (#22939)
authorKara <lunarautomaton6@gmail.com>
Mon, 25 Dec 2023 06:50:42 +0000 (23:50 -0700)
committerGitHub <noreply@github.com>
Mon, 25 Dec 2023 06:50:42 +0000 (23:50 -0700)
This reverts commit 054321d2c2c17eb55a1640150131c61c29a3eb2b.

Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs
Content.Server/Atmos/EntitySystems/GenericGasReactionSystem.cs [deleted file]
Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs [new file with mode: 0644]
Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs [new file with mode: 0644]
Content.Server/Atmos/Reactions/GasReactionPrototype.cs
Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs [new file with mode: 0644]
Content.Server/Atmos/Reactions/TritiumFireReaction.cs [new file with mode: 0644]
Content.Shared/Atmos/Atmospherics.cs
Resources/Prototypes/Atmospherics/reactions.yml

index 8506b4cd32c943d97bc4f531119b6b0480e1cdf3..f8ee4f419232194a10f26b5fa72863c5daa5b809 100644 (file)
@@ -10,7 +10,6 @@ namespace Content.Server.Atmos.EntitySystems
     public sealed partial class AtmosphereSystem
     {
         [Dependency] private readonly IPrototypeManager _protoMan = default!;
-        [Dependency] private readonly GenericGasReactionSystem _reaction = default!;
 
         private GasReactionPrototype[] _gasReactions = Array.Empty<GasReactionPrototype>();
         private float[] _gasSpecificHeats = new float[Atmospherics.TotalNumberOfGases];
@@ -347,7 +346,7 @@ namespace Content.Server.Atmos.EntitySystems
                     break;
             }
 
-            return _reaction.ReactAll(GasReactions, mixture, holder);
+            return reaction;
         }
 
         public enum GasCompareResult
diff --git a/Content.Server/Atmos/EntitySystems/GenericGasReactionSystem.cs b/Content.Server/Atmos/EntitySystems/GenericGasReactionSystem.cs
deleted file mode 100644 (file)
index 15c4a33..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-using Content.Server.Atmos.Reactions;
-using Content.Shared.Atmos;
-using JetBrains.Annotations;
-using System.Collections;
-using System.Linq;
-
-namespace Content.Server.Atmos.EntitySystems;
-
-public sealed class GenericGasReactionSystem : EntitySystem
-{
-    [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
-
-    /// <summary>
-    ///     Return a reaction rate (in units reactants per second) for a given reaction. Based on the
-    ///     Arrhenius equation (https://en.wikipedia.org/wiki/Arrhenius_equation).
-    ///
-    ///     This means that most reactions scale exponentially above the MinimumTemperatureRequirement.
-    /// </summary>
-    private float ReactionRate(GasReactionPrototype reaction, GasMixture mix, float dE)
-    {
-        float temp = mix.Temperature;
-
-        // Gas reactions have a MinimumEnergyRequirement which is in spirit activiation energy (Ea),
-        // but no reactions define it. So we have to calculate one to use. One way is to assume that
-        // Ea = 10*R*MinimumTemperatureRequirement such that Ea >> RT.
-        float TScaleFactor = 10;
-        float Ea = TScaleFactor*Atmospherics.R*reaction.MinimumTemperatureRequirement + dE;
-
-        // To compute initial rate coefficient A, assume that at temp = min temp we return 1/10.
-        float RateScaleFactor = 10; // not necessarily the same as TScaleFactor! Don't get confused!
-        float A = MathF.Exp(TScaleFactor) / RateScaleFactor;
-
-        return reaction.RateMultiplier*A*MathF.Exp(-Ea/(Atmospherics.R*temp));
-    }
-
-    /// <summary>
-    ///     Run all of the reactions given on the given gas mixture located in the given container.
-    /// </summary>
-    public ReactionResult ReactAll(IEnumerable<GasReactionPrototype> reactions, GasMixture mix, IGasMixtureHolder? holder)
-    {
-        // It is possible for reactions to change the specific heat capacity, so we need to save initial
-        // internal energy so that we can conserve energy at the end
-        float initialE = _atmosphere.GetThermalEnergy(mix);
-        float reactionE = 0; // heat added by reaction enthalpy
-        foreach (var reaction in reactions)
-        {
-            float rate = 1f; // rate of this reaction
-            int reactants = 0;
-
-            // Reactions that have a maximum temperature really don't make physical sense since increasing
-            // kinetic energy always increases reaction rate. But begrudgingly implement this anyway.
-            if (mix.Temperature > reaction.MaximumTemperatureRequirement)
-                continue;
-
-            // Add concentration-dependent reaction rate
-            // For 1A + 2B -> 3C, the concentration-dependence is [A]^1 * [B]^2
-            float nTotal = mix.TotalMoles;
-            if (nTotal < Atmospherics.GasMinMoles)
-                continue;
-
-            foreach (var (reactant, num) in reaction.Reactants)
-            {
-                rate *= MathF.Pow(mix.GetMoles(reactant)/nTotal, num);
-                reactants++;
-            }
-
-            // No reactants; this is not a generic reaction.
-            if (reactants == 0)
-                continue;
-
-            // Sum catalysts
-            float catalystEnergy = 0;
-            foreach (var (catalyst, dE) in reaction.Catalysts)
-            {
-                catalystEnergy += dE;
-            }
-
-            // Now apply temperature-dependent reaction rate scaling
-            rate *= ReactionRate(reaction, mix, catalystEnergy);
-
-            // Nothing to do
-            if (rate <= 0)
-                continue;
-
-            // Pass to check the maximum rate, limited by the minimum available
-            // reactant to avoid going negative
-            float rateLim = rate;
-            foreach (var (reactant, num) in reaction.Reactants)
-            {
-                rateLim = MathF.Min(mix.GetMoles(reactant)/num, rateLim);
-            }
-            rate = rateLim;
-
-            // Go through and remove all the reactants
-            foreach (var (reactant, num) in reaction.Reactants)
-            {
-                mix.AdjustMoles(reactant, -num*rate);
-            }
-
-            // Go through and add products
-            foreach (var (product, num) in reaction.Products)
-            {
-                mix.AdjustMoles(product, num*rate);
-            }
-
-            // Add heat from the reaction
-            if (reaction.Enthalpy != 0)
-            {
-                reactionE += reaction.Enthalpy/_atmosphere.HeatScale * rate;
-                if (reaction.Enthalpy > 0)
-                    mix.ReactionResults[GasReaction.Fire] += rate;
-            }
-        }
-
-        float newHeatCapacity = _atmosphere.GetHeatCapacity(mix, true);
-        if (newHeatCapacity > Atmospherics.MinimumHeatCapacity)
-        {
-            mix.Temperature = (initialE + reactionE)/newHeatCapacity;
-        }
-        if (reactionE > 0)
-        {
-            var location = holder as TileAtmosphere;
-            if (location != null)
-            {
-                if (mix.Temperature > Atmospherics.FireMinimumTemperatureToExist)
-                {
-                    _atmosphere.HotspotExpose(location.GridIndex, location.GridIndices, mix.Temperature, mix.Volume);
-                }
-            }
-        }
-        return ReactionResult.Reacting;
-    }
-}
diff --git a/Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs b/Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs
new file mode 100644 (file)
index 0000000..197034c
--- /dev/null
@@ -0,0 +1,33 @@
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+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/FrezonCoolantReaction.cs b/Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs
new file mode 100644 (file)
index 0000000..051ee82
--- /dev/null
@@ -0,0 +1,58 @@
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+using JetBrains.Annotations;
+
+namespace Content.Server.Atmos.Reactions;
+
+/// <summary>
+///     Takes in nitrogen and frezon and cools down the surrounding area.
+/// </summary>
+[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;
+    }
+}
index b19e4c7a8859614ed8fd87a6570450796109285d..0ee29de3bf196fb7178d0496d8c2fdec310f94ef 100644 (file)
@@ -25,8 +25,7 @@ namespace Content.Server.Atmos.Reactions
         public string ID { get; private set; } = default!;
 
         /// <summary>
-        ///     Minimum gas amount requirements. Reactions that meet these minimum mole requirements
-        ///     have their reaction effects run. Generic gas reactions do not have minimum requirements.
+        ///     Minimum gas amount requirements.
         /// </summary>
         [DataField("minimumRequirements")]
         public float[] MinimumRequirements { get; private set; } = new float[Atmospherics.TotalNumberOfGases];
@@ -43,13 +42,6 @@ namespace Content.Server.Atmos.Reactions
         [DataField("minimumTemperature")]
         public float MinimumTemperatureRequirement { get; private set; } = Atmospherics.TCMB;
 
-        /// <summary>
-        /// If this is a generic gas reaction, multiply the initial rate by this. The default is reasonable for
-        /// synthesis reactions. Consider raising this for fires.
-        /// </summary>
-        [DataField("rateMultiplier")]
-        public float RateMultiplier = 1f;
-
         /// <summary>
         ///     Minimum energy requirement.
         /// </summary>
@@ -68,31 +60,6 @@ namespace Content.Server.Atmos.Reactions
         /// </summary>
         [DataField("effects")] private List<IGasReactionEffect> _effects = new();
 
-        /// <summary>
-        ///     Energy released by the reaction.
-        /// </summary>
-        [DataField("enthalpy")]
-        public float Enthalpy;
-
-        /// <summary>
-        /// Integer gas IDs and integer ratios required in the reaction. If this is defined, the
-        /// generic gas reaction will run.
-        /// </summary>
-        [DataField("reactants")]
-        public Dictionary<Gas, int> Reactants = new();
-
-        /// <summary>
-        /// Integer gas IDs and integer ratios of reaction products.
-        /// </summary>
-        [DataField("products")]
-        public Dictionary<Gas, int> Products = new();
-
-        /// <summary>
-        /// Integer gas IDs and how much they modify the activation energy (J/mol).
-        /// </summary>
-        [DataField("catalysts")]
-        public Dictionary<Gas, int> Catalysts = new();
-
         /// <summary>
         /// Process all reaction effects.
         /// </summary>
diff --git a/Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs b/Content.Server/Atmos/Reactions/N2ODecompositionReaction.cs
new file mode 100644 (file)
index 0000000..7fce663
--- /dev/null
@@ -0,0 +1,28 @@
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+using JetBrains.Annotations;
+
+namespace Content.Server.Atmos.Reactions;
+
+/// <summary>
+///     Decomposes Nitrous Oxide into Nitrogen and Oxygen.
+/// </summary>
+[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/TritiumFireReaction.cs b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs
new file mode 100644 (file)
index 0000000..c52b431
--- /dev/null
@@ -0,0 +1,70 @@
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+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))
+            {
+                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.GridIndex, location.GridIndices, temperature, mixture.Volume);
+                }
+            }
+
+            return mixture.ReactionResults[GasReaction.Fire] != 0 ? ReactionResult.Reacting : ReactionResult.NoReaction;
+        }
+    }
+}
index 59754220e60cf311765fc83e56de9814b0fa06ca..0f330d9dcf4e38be10e0c3b8914994ff6043f6ad 100644 (file)
@@ -204,6 +204,30 @@ namespace Content.Shared.Atmos
         public const float PlasmaOxygenFullburn = 10f;
         public const float PlasmaBurnRateDelta = 9f;
 
+        /// <summary>
+        ///     This is calculated to help prevent singlecap bombs (Overpowered tritium/oxygen single tank bombs)
+        /// </summary>
+        public const float MinimumTritiumOxyburnEnergy = 143000f;
+
+        public const float TritiumBurnOxyFactor = 100f;
+        public const float TritiumBurnTritFactor = 10f;
+
+        public const float FrezonCoolLowerTemperature = 23.15f;
+
+        /// <summary>
+        ///     Frezon cools better at higher temperatures.
+        /// </summary>
+        public const float FrezonCoolMidTemperature = 373.15f;
+
+        public const float FrezonCoolMaximumEnergyModifier = 10f;
+
+        /// <summary>
+        ///     Remove X mol of nitrogen for each mol of frezon.
+        /// </summary>
+        public const float FrezonNitrogenCoolRatio = 5;
+        public const float FrezonCoolEnergyReleased = -600e3f;
+        public const float FrezonCoolRateModifier = 20f;
+
         public const float FrezonProductionMaxEfficiencyTemperature = 73.15f;
 
         /// <summary>
@@ -221,6 +245,16 @@ namespace Content.Shared.Atmos
         /// </summary>
         public const float FrezonProductionConversionRate = 50f;
 
+        /// <summary>
+        ///     The maximum portion of the N2O that can decompose each reaction tick. (50%)
+        /// </summary>
+        public const float N2ODecompositionRate = 2f;
+
+        /// <summary>
+        ///     Divisor for Ammonia Oxygen reaction so that it doesn't happen instantaneously.
+        /// </summary>
+        public const float AmmoniaOxygenReactionRate = 10f;
+
         /// <summary>
         ///     Determines at what pressure the ultra-high pressure red icon is displayed.
         /// </summary>
index 03c563b125c2a58f5d8dfb45e444ee7a48e1e805..d226c81f6cc5fef04616cace99ee47089c5d6f9c 100644 (file)
   id: TritiumFire
   priority: -1
   minimumTemperature: 373.149 # Same as Atmospherics.FireMinimumTemperatureToExist
-  enthalpy: 284000
-  reactants:
-    Tritium: 2
-    Oxygen: 1
-  products:
-    WaterVapor: 2
+  minimumRequirements: # In this case, same as minimum mole count.
+    - 0.01  # oxygen
+    - 0     # nitrogen
+    - 0     # carbon dioxide
+    - 0     # plasma
+    - 0.01  # tritium
+  effects:
+    - !type:TritiumFireReaction {}
 
 - type: gasReaction
   id: FrezonCoolant
   priority: 1
   minimumTemperature: 23.15
-  enthalpy: -600000
-  reactants:
-    Frezon: 1
-    Nitrogen: 5
-  products:
-    NitrousOxide: 6
+  minimumRequirements:
+  - 0     # oxygen
+  - 0.01  # nitrogen
+  - 0     # carbon dioxide
+  - 0     # plasma
+  - 0     # tritium
+  - 0     # vapor
+  - 0     # ammonia
+  - 0     # n2o
+  - 0.01  # frezon
+  effects:
+  - !type:FrezonCoolantReaction {}
 
 - type: gasReaction
   id: FrezonProduction
   id: AmmoniaOxygenReaction
   priority: 2
   minimumTemperature: 323.149
-  reactants:
-    Ammonia: 2
-    Oxygen: 2
-  products:
-    NitrousOxide: 1
-    WaterVapor: 3
+  minimumRequirements:
+  - 0.01  # oxygen
+  - 0     # nitrogen
+  - 0     # carbon dioxide
+  - 0     # plasma
+  - 0     # tritium
+  - 0     # vapor
+  - 0.01  # ammonia
+  - 0     # n2o
+  - 0     # frezon
+  effects:
+  - !type:AmmoniaOxygenReaction {}
 
 - type: gasReaction
   id: N2ODecomposition
   priority: 0
   minimumTemperature: 850
-  reactants:
-    NitrousOxide: 2
-  products:
-    Nitrogen: 2
-    Oxygen: 1
+  minimumRequirements:
+  - 0     # oxygen
+  - 0     # nitrogen
+  - 0     # carbon dioxide
+  - 0     # plasma
+  - 0     # tritium
+  - 0     # vapor
+  - 0     # ammonia
+  - 0.01  # n2o
+  - 0     # frezon
+  effects:
+  - !type:N2ODecompositionReaction {}
 
 #- type: gasReaction
 #  id: WaterVaporPuddle