]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make Reactions conserve thermal energy (#16190)
authorLeon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Sat, 13 May 2023 03:10:32 +0000 (15:10 +1200)
committerGitHub <noreply@github.com>
Sat, 13 May 2023 03:10:32 +0000 (13:10 +1000)
13 files changed:
Content.Client/Chemistry/ChemicalReactionSystem.cs [deleted file]
Content.Server/Body/Systems/MetabolizerSystem.cs
Content.Server/Chemistry/EntitySystems/ChemicalReactionSystem.cs [deleted file]
Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs
Content.Server/Chemistry/ReagentEffectConditions/ReagentThreshold.cs
Content.Server/Chemistry/ReagentEffects/ChemCleanBoodstream.cs
Content.Server/Chemistry/ReagentEffects/Electrocute.cs
Content.Server/Chemistry/ReagentEffects/FlammableReaction.cs
Content.Shared/Chemistry/Components/Solution.cs
Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs [moved from Content.Shared/Chemistry/Reaction/SharedChemicalReactionSystem.cs with 85% similarity]
Content.Shared/Chemistry/Reaction/ReactionPrototype.cs
Content.Shared/Chemistry/Reagent/ReagentEffect.cs
Resources/Prototypes/Recipes/Reactions/food.yml

diff --git a/Content.Client/Chemistry/ChemicalReactionSystem.cs b/Content.Client/Chemistry/ChemicalReactionSystem.cs
deleted file mode 100644 (file)
index 96aa6db..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-using Content.Shared.Chemistry.Reaction;
-
-namespace Content.Client.Chemistry
-{
-    public sealed class ChemicalReactionSystem : SharedChemicalReactionSystem
-    {
-
-    }
-}
index 1cf9eb3e93e0c46be231a868240a69d3452ac641..34b49f0d09c24f0527dc4a5b251a2897b16e06e7 100644 (file)
@@ -181,7 +181,7 @@ namespace Content.Server.Body.Systems
                         if (effect.ShouldLog)
                         {
                             _adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
-                                $"Metabolism effect {effect.GetType().Name:effect} of reagent {args.Reagent.LocalizedName:reagent} applied on entity {actualEntity:entity} at {Transform(actualEntity).Coordinates:coordinates}");
+                                $"Metabolism effect {effect.GetType().Name:effect} of reagent {proto.LocalizedName:reagent} applied on entity {actualEntity:entity} at {Transform(actualEntity).Coordinates:coordinates}");
                         }
 
                         effect.Effect(args);
diff --git a/Content.Server/Chemistry/EntitySystems/ChemicalReactionSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemicalReactionSystem.cs
deleted file mode 100644 (file)
index e7df6c7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.Reaction;
-using Content.Shared.Chemistry.Reagent;
-using Content.Shared.Database;
-using Content.Shared.FixedPoint;
-using Robust.Shared.Audio;
-using Robust.Shared.Player;
-
-namespace Content.Server.Chemistry.EntitySystems
-{
-    public sealed class ChemicalReactionSystem : SharedChemicalReactionSystem
-    {
-        protected override void OnReaction(Solution solution, ReactionPrototype reaction, ReagentPrototype randomReagent, EntityUid owner, FixedPoint2 unitReactions)
-        {
-            base.OnReaction(solution, reaction,  randomReagent, owner, unitReactions);
-
-            var coordinates = Transform(owner).Coordinates;
-
-            AdminLogger.Add(LogType.ChemicalReaction, reaction.Impact,
-                $"Chemical reaction {reaction.ID:reaction} occurred with strength {unitReactions:strength} on entity {ToPrettyString(owner):metabolizer} at {coordinates}");
-
-            SoundSystem.Play(reaction.Sound.GetSound(), Filter.Pvs(owner, entityManager:EntityManager), owner);
-        }
-    }
-}
index 782a1e7ec35e95fab3da7c29f101d5bd276cb3b1..bdf6a878893ac19413697b19b9f4a068bb6844be 100644 (file)
@@ -34,7 +34,7 @@ public sealed class SolutionChangedEvent : EntityEventArgs
 public sealed partial class SolutionContainerSystem : EntitySystem
 {
     [Dependency]
-    private readonly SharedChemicalReactionSystem _chemistrySystem = default!;
+    private readonly ChemicalReactionSystem _chemistrySystem = default!;
 
     [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
 
index bf18fcd54ffc892b42a6e3943f1fc0d32d3ba022..c97b29a94ca9f43dd7efdc6d74aecb5606c47202 100644 (file)
@@ -23,13 +23,14 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
 
         public override bool Condition(ReagentEffectArgs args)
         {
-            if (Reagent == null)
-                Reagent = args.Reagent.ID;
+            var reagent = Reagent ?? args.Reagent?.ID;
+            if (reagent == null)
+                return true; // No condition to apply.
 
             var quant = FixedPoint2.Zero;
-            if (args.Source != null && args.Source.ContainsReagent(Reagent))
+            if (args.Source != null && args.Source.ContainsReagent(reagent))
             {
-                quant = args.Source.GetReagentQuantity(args.Reagent.ID);
+                quant = args.Source.GetReagentQuantity(reagent);
             }
 
             return quant >= Min && quant <= Max;
index c8027ec2c5d3a48da3d92b126f99710fa2812b5a..376398d7b73a4d35888568abaab6cf261ba38a3b 100644 (file)
@@ -14,7 +14,7 @@ namespace Content.Server.Chemistry.ReactionEffects
         public float CleanseRate = 3.0f;
         public override void Effect(ReagentEffectArgs args)
         {
-            if (args.Source == null)
+            if (args.Source == null || args.Reagent == null)
                 return;
 
             var cleanseRate = CleanseRate;
index d3a5383de70cdf661d291180892392f4c81d851c..08b2df966e4f6cec2b4c9f9fce860d25e5d696ad 100644 (file)
@@ -18,9 +18,10 @@ public sealed class Electrocute : ReagentEffect
 
     public override void Effect(ReagentEffectArgs args)
     {
-        EntitySystem.Get<ElectrocutionSystem>().TryDoElectrocution(args.SolutionEntity, null,
+        args.EntityManager.System<ElectrocutionSystem>().TryDoElectrocution(args.SolutionEntity, null,
             Math.Max((args.Quantity * ElectrocuteDamageScale).Int(), 1), TimeSpan.FromSeconds(ElectrocuteTime), Refresh, ignoreInsulation: true);
 
-        args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity);
+        if (args.Reagent != null)
+            args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity);
     }
 }
index 9d0db25a1e73b96522cd1f30def54e450d908c7d..54d36891358e5a87ff767798f04dc99a9df5773b 100644 (file)
@@ -17,10 +17,13 @@ namespace Content.Server.Chemistry.ReagentEffects
 
         public override void Effect(ReagentEffectArgs args)
         {
-            if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out FlammableComponent? flammable)) return;
+            if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out FlammableComponent? flammable))
+                return;
 
-            EntitySystem.Get<FlammableSystem>().AdjustFireStacks(args.SolutionEntity, args.Quantity.Float() * Multiplier, flammable);
-            args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity);
+            args.EntityManager.System<FlammableSystem>().AdjustFireStacks(args.SolutionEntity, args.Quantity.Float() * Multiplier, flammable);
+
+            if (args.Reagent != null)
+                args.Source?.RemoveReagent(args.Reagent.ID, args.Quantity);
         }
     }
 }
index 8aaf9582fff75202d4d4b318ee7ced6302659837..cc01b8f3b17553997eea4cb9a8dc670cae321716 100644 (file)
@@ -114,6 +114,10 @@ namespace Content.Shared.Chemistry.Components
             return _heatCapacity;
         }
 
+        public float GetThermalEnergy(IPrototypeManager? protoMan)
+        {
+            return GetHeatCapacity(protoMan) * Temperature;
+        }
 
         /// <summary>
         ///     Constructs an empty solution (ex. an empty beaker).
similarity index 85%
rename from Content.Shared/Chemistry/Reaction/SharedChemicalReactionSystem.cs
rename to Content.Shared/Chemistry/Reaction/ChemicalReactionSystem.cs
index a2a4fec87a6e85944c123c126df7cab6617affa1..da8560fc5b42b48a0c34b072b02707de55b2f672 100644 (file)
@@ -1,27 +1,23 @@
 using System.Linq;
-using Content.Shared.Administration;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Reagent;
 using Content.Shared.Database;
 using Content.Shared.FixedPoint;
-using Content.Shared.Interaction.Events;
 using Robust.Shared.Prototypes;
-using Robust.Shared.Random;
 
 namespace Content.Shared.Chemistry.Reaction
 {
-    public abstract class SharedChemicalReactionSystem : EntitySystem
+    public sealed class ChemicalReactionSystem : EntitySystem
     {
-
         /// <summary>
         ///     The maximum number of reactions that may occur when a solution is changed.
         /// </summary>
         private const int MaxReactionIterations = 20;
 
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
-        [Dependency] private readonly IRobustRandom _random = default!;
-        [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!;
+        [Dependency] private readonly SharedAudioSystem _audio = default!;
+        [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
 
         /// <summary>
         ///     A cache of all existant chemical reactions indexed by one of their
@@ -170,13 +166,12 @@ namespace Content.Shared.Chemistry.Reaction
 
         /// <summary>
         ///     Perform a reaction on a solution. This assumes all reaction criteria are met.
-        ///     Removes the reactants from the solution, then returns a solution with all products.
+        ///     Removes the reactants from the solution, adds products, and returns a list of products.
         /// </summary>
-        private Solution PerformReaction(Solution solution, EntityUid owner, ReactionPrototype reaction, FixedPoint2 unitReactions)
+        private List<string> PerformReaction(Solution solution, EntityUid owner, ReactionPrototype reaction, FixedPoint2 unitReactions)
         {
-            // We do this so that ReagentEffect can have something to work with, even if it's
-            // a little meaningless.
-            var randomReagent = _prototypeManager.Index<ReagentPrototype>(_random.Pick(reaction.Reactants).Key);
+            var energy = reaction.ConserveEnergy ? solution.GetThermalEnergy(_prototypeManager) : 0;
+
             //Remove reactants
             foreach (var reactant in reaction.Reactants)
             {
@@ -188,24 +183,35 @@ namespace Content.Shared.Chemistry.Reaction
             }
 
             //Create products
-            var products = new Solution();
+            var products = new List<string>();
             foreach (var product in reaction.Products)
             {
-                products.AddReagent(product.Key, product.Value * unitReactions);
+                products.Add(product.Key);
+                solution.AddReagent(product.Key, product.Value * unitReactions);
+            }
+
+            if (reaction.ConserveEnergy)
+            {
+                var newCap = solution.GetHeatCapacity(_prototypeManager);
+                if (newCap > 0)
+                    solution.Temperature = energy / newCap;
             }
 
-            // Trigger reaction effects
-            OnReaction(solution, reaction, randomReagent, owner, unitReactions);
+            OnReaction(solution, reaction, null, owner, unitReactions);
 
             return products;
         }
 
-        protected virtual void OnReaction(Solution solution, ReactionPrototype reaction, ReagentPrototype randomReagent, EntityUid owner, FixedPoint2 unitReactions)
+        private void OnReaction(Solution solution, ReactionPrototype reaction, ReagentPrototype? reagent, EntityUid owner, FixedPoint2 unitReactions)
         {
             var args = new ReagentEffectArgs(owner, null, solution,
-                randomReagent,
+                reagent,
                 unitReactions, EntityManager, null, 1f);
 
+            var coordinates = Transform(owner).Coordinates;
+            _adminLogger.Add(LogType.ChemicalReaction, reaction.Impact,
+                $"Chemical reaction {reaction.ID:reaction} occurred with strength {unitReactions:strength} on entity {ToPrettyString(owner):metabolizer} at {coordinates}");
+
             foreach (var effect in reaction.Effects)
             {
                 if (!effect.ShouldApply(args))
@@ -214,12 +220,14 @@ namespace Content.Shared.Chemistry.Reaction
                 if (effect.ShouldLog)
                 {
                     var entity = args.SolutionEntity;
-                    AdminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
+                    _adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
                         $"Reaction effect {effect.GetType().Name:effect} of reaction ${reaction.ID:reaction} applied on entity {ToPrettyString(entity):entity} at {Transform(entity).Coordinates:coordinates}");
                 }
 
                 effect.Effect(args);
             }
+
+            _audio.PlayPvs(reaction.Sound, owner);
         }
 
         /// <summary>
@@ -230,7 +238,7 @@ namespace Content.Shared.Chemistry.Reaction
         private bool ProcessReactions(Solution solution, EntityUid owner, FixedPoint2 maxVolume, SortedSet<ReactionPrototype> reactions, ReactionMixerComponent? mixerComponent)
         {
             HashSet<ReactionPrototype> toRemove = new();
-            Solution? products = null;
+            List<string>? products = null;
 
             // attempt to perform any applicable reaction
             foreach (var reaction in reactions)
@@ -249,30 +257,23 @@ namespace Content.Shared.Chemistry.Reaction
             if (products == null)
                 return false;
 
-            // Remove any reactions that were not applicable. Avoids re-iterating over them in future.
-            foreach (var proto in toRemove)
-            {
-                reactions.Remove(proto);
-            }
-
-            if (products.Volume <= 0)
+            if (products.Count == 0)
                 return true;
 
             // remove excess product
             // TODO spill excess?
-            var excessVolume = solution.Volume + products.Volume - maxVolume;
+            var excessVolume = solution.Volume - maxVolume;
             if (excessVolume > 0)
-                products.RemoveSolution(excessVolume);
+                solution.RemoveSolution(excessVolume);
 
             // Add any reactions associated with the new products. This may re-add reactions that were already iterated
             // over previously. The new product may mean the reactions are applicable again and need to be processed.
-            foreach (var reactant in products.Contents)
+            foreach (var product in products)
             {
-                if (_reactions.TryGetValue(reactant.ReagentId, out var reactantReactions))
+                if (_reactions.TryGetValue(product, out var reactantReactions))
                     reactions.UnionWith(reactantReactions);
             }
 
-            solution.AddSolution(products, _prototypeManager);
             return true;
         }
 
index 413c56b1f1d676b2d18b0978ec8fe4214384bbcd..ac561ccbdffa558bf0d7f7a38fdbf8df43f37206 100644 (file)
@@ -32,6 +32,12 @@ namespace Content.Shared.Chemistry.Reaction
         [DataField("minTemp")]
         public float MinimumTemperature = 0.0f;
 
+        /// <summary>
+        ///     If true, this reaction will attempt to conserve thermal energy.
+        /// </summary>
+        [DataField("conserveEnergy")]
+        public bool ConserveEnergy = true;
+
         /// <summary>
         ///     The maximum temperature the reaction can occur at.
         /// </summary>
index 5b22ae4a8a55b40c632e2e6fb65779024285cb15..9140c44f15c605f2dcbea73c51da8d91c82d08ee 100644 (file)
@@ -79,7 +79,7 @@ namespace Content.Shared.Chemistry.Reagent
         EntityUid SolutionEntity,
         EntityUid? OrganEntity,
         Solution? Source,
-        ReagentPrototype Reagent,
+        ReagentPrototype? Reagent,
         FixedPoint2 Quantity,
         IEntityManager EntityManager,
         ReactionMethod? Method,
index 5e32ab08a95d58d7416a3b5b89c34c6ce975b831..2aaf62c88b207a175c83808472ca494ae6468312 100644 (file)
@@ -2,6 +2,7 @@
   id: Curdling
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Milk:
       amount: 40
@@ -16,6 +17,7 @@
   id: CreateDough
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Flour:
       amount: 15
@@ -29,6 +31,7 @@
   id: CreateCornmealDough
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Cornmeal:
       amount: 15
@@ -44,6 +47,7 @@
   id: CreateCakeBatter
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Flour:
       amount: 15
@@ -59,6 +63,7 @@
   id: CreateButter
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Milk:
       amount: 30
@@ -73,6 +78,7 @@
   id: CreatePieDough
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Flour:
       amount: 15
@@ -91,6 +97,7 @@
   id: CreateVeganCakeBatter
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     Flour:
       amount: 15
   id: CreateTofu
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     MilkSoy:
       amount: 30
   id: CreateMeatball
   impact: Low
   quantized: true
+  conserveEnergy: false
   reactants:
     UncookedAnimalProteins:
       amount: 5