From 39591e99922a097e53356040908eaaae183d802e Mon Sep 17 00:00:00 2001 From: Whatstone <166147148+whatston3@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:02:34 -0400 Subject: [PATCH] Cryogenics: restrict cryo pods to cryo meds, restore limited metabolism (#1533) * Cleanup, revised Solution split * French spacing * cryo pod: only extract cryogenics chems from soln * Add Cryogenic metabolism group, add to organs * Cleanup comments, "PerReagent" soln split & docs * Comment accuracy * SplitSolutionPerReagent: suggested fixes --------- Co-authored-by: Whatstone --- .../Body/Components/MetabolizerComponent.cs | 10 -- .../Body/Systems/MetabolizerSystem.cs | 17 +-- Content.Server/Medical/CryoPodSystem.cs | 13 +- .../Chemistry/Components/Solution.cs | 130 +++++++++++++----- .../SharedSolutionContainerSystem.cs | 26 +++- .../Medical/Cryogenics/CryoPodComponent.cs | 5 +- .../_NF/metabolism/metabolism-groups.ftl | 1 + .../Locale/en-US/reagents/meta/medicine.ftl | 8 +- .../Prototypes/Body/Organs/Animal/animal.yml | 1 + .../Prototypes/Body/Organs/Animal/slimes.yml | 1 + Resources/Prototypes/Body/Organs/arachnid.yml | 1 + Resources/Prototypes/Body/Organs/diona.yml | 1 + Resources/Prototypes/Body/Organs/human.yml | 1 + Resources/Prototypes/Body/Organs/moth.yml | 1 + Resources/Prototypes/Body/Organs/slime.yml | 1 + .../Entities/Mobs/NPCs/behonker.yml | 1 + .../Entities/Mobs/Player/dragon.yml | 1 + Resources/Prototypes/Reagents/medicine.yml | 14 +- .../_NF/Body/Organs/goblin_organs.yml | 1 + .../_NF/Body/Organs/synthetic_organs.yml | 1 + .../_NF/Chemistry/metabolism_groups.yml | 4 + .../_NF/Entities/Mobs/NPCs/baby_dragon.yml | 1 + .../_NF/Entities/Mobs/Player/jerma.yml | 1 + .../Prototypes/_NF/Reagents/medicine.yml | 6 +- .../Guidebook/Medical/Cryogenics.xml | 2 +- 25 files changed, 173 insertions(+), 76 deletions(-) create mode 100644 Resources/Locale/en-US/_NF/metabolism/metabolism-groups.ftl create mode 100644 Resources/Prototypes/_NF/Chemistry/metabolism_groups.yml diff --git a/Content.Server/Body/Components/MetabolizerComponent.cs b/Content.Server/Body/Components/MetabolizerComponent.cs index 9e91f9f9cbe..90c99df7db2 100644 --- a/Content.Server/Body/Components/MetabolizerComponent.cs +++ b/Content.Server/Body/Components/MetabolizerComponent.cs @@ -62,16 +62,6 @@ public sealed partial class MetabolizerComponent : Component [DataField("maxReagents")] public int MaxReagentsProcessable = 3; - /// - /// Frontier - /// - /// How many poisons can this metabolizer process at once? - /// Used to nerf 'stacked poisons' where having 5+ different poisons in a syringe, even at low - /// quantity, would be muuuuch better than just one poison acting. - /// - [DataField("maxPoisons")] - public int MaxPoisonsProcessable = 3; - /// /// A list of metabolism groups that this metabolizer will act on, in order of precedence. /// diff --git a/Content.Server/Body/Systems/MetabolizerSystem.cs b/Content.Server/Body/Systems/MetabolizerSystem.cs index 9a357d300f7..dfdbaf0edc9 100644 --- a/Content.Server/Body/Systems/MetabolizerSystem.cs +++ b/Content.Server/Body/Systems/MetabolizerSystem.cs @@ -142,7 +142,7 @@ private void TryMetabolize(Entity(reagent.Prototype, out var proto)) @@ -158,10 +158,11 @@ private void TryMetabolize(Entity= ent.Comp1.MaxPoisonsProcessable && proto.Metabolisms.ContainsKey("Poison")) + + // Frontier: all cryogenic reagents in the solution should be processed, others should be limited (buff cryo meds) + if (reagents >= ent.Comp1.MaxReagentsProcessable && !proto.Metabolisms.ContainsKey("Cryogenic")) continue; + // End Frontier // loop over all our groups and see which ones apply @@ -219,10 +220,10 @@ private void TryMetabolize(Entity FixedPoint2.Zero) { solution.RemoveReagent(reagent, mostToRemove); - // frontier modified - // We have processed a poison, so count it towards the cap - if (proto.Metabolisms.ContainsKey("Poison")) - poisons++; + // Frontier: do not count cryogenics chems against the reagent limit (to buff cryo meds) + if (!proto.Metabolisms.ContainsKey("Cryogenic")) + reagents++; + // End Frontier } } diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs index 88dc5176f18..f73b22c26f6 100644 --- a/Content.Server/Medical/CryoPodSystem.cs +++ b/Content.Server/Medical/CryoPodSystem.cs @@ -55,6 +55,9 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly NodeContainerSystem _nodeContainer = default!; + // Frontier: keep a list of cryogenics reagents. The pod will only filter these out from the provided solution. + private static readonly string[] CryogenicsReagents = ["Cryoxadone", "Aloxadone", "Doxarubixadone", "Opporozidone", "Necrosol", "Traumoxadone", "Stelloxadone"]; + public override void Initialize() { base.Initialize(); @@ -115,14 +118,14 @@ public override void Update(float frameTime) continue; } - // frontier + // Frontier // Filter out a fixed amount of each reagent from the cryo pod's beaker - var solutionToInject = _solutionContainerSystem.SplitSolutionReagentsEvenly(containerSolution.Value, cryoPod.BeakerTransferAmount); - // for every .25 units used, .5 units per second are added to the body, making cryo-pod more efficient than injections - solutionToInject.ScaleSolution(cryoPod.PotencyMultiplier); + var solutionToInject = _solutionContainerSystem.SplitSolutionPerReagentWithOnly(containerSolution.Value, cryoPod.BeakerTransferAmount, CryogenicsReagents); - // End frontier + // For every .25 units used, .5 units per second are added to the body, making cryo-pod more efficient than injections. + solutionToInject.ScaleSolution(cryoPod.PotencyMultiplier); + // End Frontier _bloodstreamSystem.TryAddToChemicals(patient.Value, solutionToInject, bloodstream); _reactiveSystem.DoEntityReaction(patient.Value, solutionToInject, ReactionMethod.Injection); diff --git a/Content.Shared/Chemistry/Components/Solution.cs b/Content.Shared/Chemistry/Components/Solution.cs index 3a3400ca591..6e2e0305e8e 100644 --- a/Content.Shared/Chemistry/Components/Solution.cs +++ b/Content.Shared/Chemistry/Components/Solution.cs @@ -606,11 +606,12 @@ public Solution SplitSolutionWithOnly(FixedPoint2 toTake, params string[] includ return sol; } + /// - /// splits the solution taking the specified amount of reagents proportionally to their quantity. + /// Splits a solution, taking the specified amount of reagents proportionally to their quantity. /// /// The total amount of solution to remove and return. - /// a new solution of equal proportions to the original solution + /// A new solution of equal proportions to the original. public Solution SplitSolution(FixedPoint2 toTake) { if (toTake <= FixedPoint2.Zero) @@ -674,58 +675,123 @@ public Solution SplitSolution(FixedPoint2 toTake) return newSolution; } + // Frontier: cryogenics per-reagent filter function (#1443, #1533) /// - /// Frontier - /// splits the solution taking up to the specified amount of each reagent from the solution. - /// If the solution has less of a reagent than the specified amount, it will take all of that reagent. + /// Splits a solution, taking the specified amount of each reagent from the solution. + /// If any reagent in the solution has less volume than specified, it will all be transferred into the new solution. /// - /// How much of each reagent to take - /// a new solution containing the reagents taken from the original solution - public Solution SplitSolutionReagentsEvenly(FixedPoint2 toTakePer) + /// How much of each reagent to take. + /// A new solution containing the reagents taken from the original solution. + public Solution SplitSolutionPerReagent(FixedPoint2 toTakePer) { - var splitSolution = new Solution(); - if (toTakePer <= FixedPoint2.Zero) - return splitSolution; - var reagentsCount = Contents.Count; - var reagentsToRemove = new List(); - for (var i = 0; i < reagentsCount; i++) + return new Solution(); + + var origVol = Volume; + Solution newSolution = new Solution(Contents.Count) { Temperature = Temperature }; + + for (var i = Contents.Count - 1; i >= 0; i--) // iterate backwards because of remove swap. { - var currentReagent = Contents[i]; + var (reagent, quantity) = Contents[i]; - if (currentReagent.Quantity <= FixedPoint2.Zero) + // If the reagent has more than enough volume to remove, no need to remove it from the list. + if (quantity > toTakePer) { - reagentsToRemove.Add(currentReagent); - continue; + Contents[i] = new ReagentQuantity(reagent, quantity - toTakePer); + newSolution.Contents.Add(new ReagentQuantity(reagent, toTakePer)); + Volume -= toTakePer; + } + else + { + Contents.RemoveSwap(i); + //Only add positive quantities to our new solution. + if (quantity > 0) + { + newSolution.Contents.Add(new ReagentQuantity(reagent, quantity)); + Volume -= quantity; + } } + } + + // If old solution is empty, invalidate old solution and transfer all volume to new. + if (Volume <= 0) + { + RemoveAllSolution(); + newSolution.Volume = origVol; + } + else + { + newSolution.Volume = origVol - Volume; + _heatCapacityDirty = true; + } + newSolution._heatCapacityDirty = true; + + ValidateSolution(); + newSolution.ValidateSolution(); + + return newSolution; + } + + /// + /// Splits a solution, taking the specified amount of each reagent specified in reagents from the solution. + /// If any reagent in the solution has less volume than specified, it will all be transferred into the new solution. + /// + /// How much of each reagent to take. + /// A new solution containing the reagents taken from the original solution. + public Solution SplitSolutionPerReagentWithOnly(FixedPoint2 toTakePer, params string[] reagents) + { + if (toTakePer <= FixedPoint2.Zero) + return new Solution(); + + var origVol = Volume; + Solution newSolution = new Solution(Contents.Count) { Temperature = Temperature }; + + for (var i = Contents.Count - 1; i >= 0; i--) // iterate backwards because of remove swap. + { + var (reagent, quantity) = Contents[i]; + + // Each reagent to split must be in the set given. + if (!reagents.Contains(reagent.Prototype)) + continue; - if (currentReagent.Quantity <= toTakePer) + // If the reagent has more than enough volume to remove, no need to remove it from the list. + if (quantity > toTakePer) { - splitSolution.AddReagent(currentReagent); - reagentsToRemove.Add(currentReagent); + Contents[i] = new ReagentQuantity(reagent, quantity - toTakePer); + newSolution.Contents.Add(new ReagentQuantity(reagent, toTakePer)); + Volume -= toTakePer; } else { - splitSolution.AddReagent(currentReagent.Reagent, toTakePer); - RemoveReagent(currentReagent.Reagent, toTakePer); + Contents.RemoveSwap(i); + //Only add positive quantities to our new solution. + if (quantity > 0) + { + newSolution.Contents.Add(new ReagentQuantity(reagent, quantity)); + Volume -= quantity; + } } } - foreach (var reagent in reagentsToRemove) + // If old solution is empty, invalidate old solution and transfer all volume to new. + if (Volume <= 0) { - RemoveReagent(reagent); - } - if (Volume == FixedPoint2.Zero) RemoveAllSolution(); - - _heatCapacityDirty = true; - splitSolution._heatCapacityDirty = true; + newSolution.Volume = origVol; + } + else + { + newSolution.Volume = origVol - Volume; + _heatCapacityDirty = true; + } + newSolution._heatCapacityDirty = true; ValidateSolution(); - splitSolution.ValidateSolution(); + newSolution.ValidateSolution(); - return splitSolution; + return newSolution; } + // End Frontier /// /// Variant of that doesn't return a new solution containing the removed reagents. diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs index c3283f1e7fb..43565c71838 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs @@ -310,22 +310,40 @@ public Solution SplitSolution(Entity soln, FixedPoint2 quanti return splitSol; } + // Frontier: cryogenics filtering functions (#1443) /// - /// Frontier /// Splits a solution removing a specified amount of each reagent, if available. /// /// The container to split the solution from. /// The amount of each reagent to split. - /// - public Solution SplitSolutionReagentsEvenly(Entity soln, FixedPoint2 quantity) + /// The solution that was removed. + public Solution SplitSolutionPerReagent(Entity soln, FixedPoint2 quantity) + { + var (uid, comp) = soln; + var solution = comp.Solution; + + var splitSol = solution.SplitSolutionPerReagent(quantity); + UpdateChemicals(soln); + return splitSol; + } + + /// + /// Splits a solution removing a specified amount of each reagent, if available. + /// + /// The container to split the solution from. + /// The amount of each reagent to split. + /// The list of reagents to split a fixed amount of, if present. + /// The solution that was removed. + public Solution SplitSolutionPerReagentWithOnly(Entity soln, FixedPoint2 quantity, params string[] reagents) { var (uid, comp) = soln; var solution = comp.Solution; - var splitSol = solution.SplitSolutionReagentsEvenly(quantity); + var splitSol = solution.SplitSolutionPerReagentWithOnly(quantity, reagents); UpdateChemicals(soln); return splitSol; } + // End Frontier public Solution SplitStackSolution(Entity soln, FixedPoint2 quantity, int stackCount) { diff --git a/Content.Shared/Medical/Cryogenics/CryoPodComponent.cs b/Content.Shared/Medical/Cryogenics/CryoPodComponent.cs index afcf072a842..f14d8e63dd5 100644 --- a/Content.Shared/Medical/Cryogenics/CryoPodComponent.cs +++ b/Content.Shared/Medical/Cryogenics/CryoPodComponent.cs @@ -38,15 +38,16 @@ public sealed partial class CryoPodComponent : Component /// [ViewVariables(VVAccess.ReadWrite)] [DataField("beakerTransferAmount")] - public float BeakerTransferAmount = .25f;// Frontier: 1<0.25 + public float BeakerTransferAmount = .25f; // Frontier: 1<0.25 (applied per reagent) + // Frontier: more efficient cryogenics (#1443) /// - /// Frontier /// How potent (multiplier) the reagents are when transferred from the beaker to the mob. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("PotencyAmount")] public float PotencyMultiplier = 2f; + // End Frontier /// /// Delay applied when inserting a mob in the pod. diff --git a/Resources/Locale/en-US/_NF/metabolism/metabolism-groups.ftl b/Resources/Locale/en-US/_NF/metabolism/metabolism-groups.ftl new file mode 100644 index 00000000000..af1fb19a2a4 --- /dev/null +++ b/Resources/Locale/en-US/_NF/metabolism/metabolism-groups.ftl @@ -0,0 +1 @@ +metabolism-group-cryogenic = Cryogenic diff --git a/Resources/Locale/en-US/reagents/meta/medicine.ftl b/Resources/Locale/en-US/reagents/meta/medicine.ftl index 08b184fcd7d..6d001253042 100644 --- a/Resources/Locale/en-US/reagents/meta/medicine.ftl +++ b/Resources/Locale/en-US/reagents/meta/medicine.ftl @@ -14,13 +14,11 @@ reagent-name-bicaridine = bicaridine reagent-desc-bicaridine = An analgesic which is highly effective at treating brute damage. It's useful for stabilizing people who have been severely beaten, as well as treating less life-threatening injuries. # Frontier: consistent cryogenics descriptors - reagent-name-cryoxadone = cryoxadone -reagent-desc-cryoxadone = Required for the proper function of cryogenics. Useful in treating asphyxiation and bloodloss, but only works in temperatures under 213K. It can treat and rejuvenate plants when applied in small doses. Works regardless of the patient being alive or dead. +reagent-desc-cryoxadone = A cryogenics chemical. Useful in treating asphyxiation and bloodloss, but only works in temperatures under 213K. It can treat and rejuvenate plants when applied in small doses. Works regardless of the patient being alive or dead. reagent-name-doxarubixadone = doxarubixadone reagent-desc-doxarubixadone = A cryogenics chemical. Heals certain types of cellular damage done by Slimes and improper use of other chemicals. Works regardless of the patient being alive or dead. - # End Frontier reagent-name-dermaline = dermaline @@ -134,8 +132,10 @@ reagent-desc-insuzine = Rapidly repairs dead tissue caused by electrocution, but reagent-name-opporozidone = opporozidone reagent-desc-opporozidone= A difficult to synthesize cryogenic drug used to regenerate rotting tissue and brain matter. +# Frontier: consistent cryogenics descriptors reagent-name-necrosol = necrosol -reagent-desc-necrosol = A necrotic substance that seems to be able to heal frozen corpses. It can treat and rejuvenate plants when applied in small doses. +reagent-desc-necrosol = A cryogenics chemical. Heals most organic damage, a true panacea. It can treat and rejuvenate plants when applied in small doses. Works regardless of the patient being alive or dead. +# End Frontier reagent-name-aloxadone = aloxadone reagent-desc-aloxadone = A cryogenics chemical. Used to treat severe third degree burns via regeneration of the burnt tissue. Works regardless of the patient being alive or dead. diff --git a/Resources/Prototypes/Body/Organs/Animal/animal.yml b/Resources/Prototypes/Body/Organs/Animal/animal.yml index 89acef82927..e7444d1c3f9 100644 --- a/Resources/Prototypes/Body/Organs/Animal/animal.yml +++ b/Resources/Prototypes/Body/Organs/Animal/animal.yml @@ -129,6 +129,7 @@ metabolizerTypes: [ Animal ] groups: - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic diff --git a/Resources/Prototypes/Body/Organs/Animal/slimes.yml b/Resources/Prototypes/Body/Organs/Animal/slimes.yml index f1a3d47e667..72578ca1c7a 100644 --- a/Resources/Prototypes/Body/Organs/Animal/slimes.yml +++ b/Resources/Prototypes/Body/Organs/Animal/slimes.yml @@ -16,6 +16,7 @@ - id: Food - id: Drink - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic - id: Alcohol diff --git a/Resources/Prototypes/Body/Organs/arachnid.yml b/Resources/Prototypes/Body/Organs/arachnid.yml index 1d0a5db996c..411b8de4e83 100644 --- a/Resources/Prototypes/Body/Organs/arachnid.yml +++ b/Resources/Prototypes/Body/Organs/arachnid.yml @@ -104,6 +104,7 @@ metabolizerTypes: [Arachnid] groups: - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic diff --git a/Resources/Prototypes/Body/Organs/diona.yml b/Resources/Prototypes/Body/Organs/diona.yml index 69fc630b9e4..a00889f4cf2 100644 --- a/Resources/Prototypes/Body/Organs/diona.yml +++ b/Resources/Prototypes/Body/Organs/diona.yml @@ -86,6 +86,7 @@ - id: Food - id: Drink - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic - id: Alcohol diff --git a/Resources/Prototypes/Body/Organs/human.yml b/Resources/Prototypes/Body/Organs/human.yml index 6cd4996926a..879cf04af27 100644 --- a/Resources/Prototypes/Body/Organs/human.yml +++ b/Resources/Prototypes/Body/Organs/human.yml @@ -159,6 +159,7 @@ metabolizerTypes: [Human] groups: - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic diff --git a/Resources/Prototypes/Body/Organs/moth.yml b/Resources/Prototypes/Body/Organs/moth.yml index 4d44dbad42f..64d7690ef24 100644 --- a/Resources/Prototypes/Body/Organs/moth.yml +++ b/Resources/Prototypes/Body/Organs/moth.yml @@ -27,6 +27,7 @@ - id: Food - id: Drink - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic - id: Alcohol diff --git a/Resources/Prototypes/Body/Organs/slime.yml b/Resources/Prototypes/Body/Organs/slime.yml index 3da76c5d4aa..74cb8fab789 100644 --- a/Resources/Prototypes/Body/Organs/slime.yml +++ b/Resources/Prototypes/Body/Organs/slime.yml @@ -16,6 +16,7 @@ - id: Food - id: Drink - id: Medicine + - id: Cryogenic # Frontier - id: Poison - id: Narcotic - id: Alcohol diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml index 6aea0e89b01..3ac8b70007f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml @@ -88,6 +88,7 @@ metabolizerTypes: [ Dragon ] groups: - id: Medicine + - id: Cryogenic # Frontier - id: Poison - type: Butcherable spawned: diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index 51e41e26077..926bbd5eead 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -101,6 +101,7 @@ metabolizerTypes: [ Dragon ] groups: - id: Medicine + - id: Cryogenic # Frontier - id: Poison - type: Butcherable spawned: diff --git a/Resources/Prototypes/Reagents/medicine.yml b/Resources/Prototypes/Reagents/medicine.yml index 4d4af6d931e..ea18fa64df0 100644 --- a/Resources/Prototypes/Reagents/medicine.yml +++ b/Resources/Prototypes/Reagents/medicine.yml @@ -168,7 +168,7 @@ physicalDesc: reagent-physical-desc-fizzy flavor: medicine color: "#0091ff" - worksOnTheDead: true # Frontier + worksOnTheDead: true # Frontier plantMetabolism: - !type:PlantAdjustToxins amount: -5 @@ -176,7 +176,7 @@ amount: 5 - !type:PlantCryoxadone {} metabolisms: - Medicine: + Cryogenic: # Frontier: Medicine