diff --git a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs index 56e039a700..cb3cae10af 100644 --- a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs +++ b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs @@ -57,14 +57,14 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem var oldProgress = component.Progress.ShallowClone(); component.Progress.Clear(); - var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); - if (water > FixedPoint2.Zero) + var mopReagent = solution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(solution)); + if (mopReagent > FixedPoint2.Zero) { - component.Progress[solution.GetColorWithOnly(_prototype, PuddleSystem.EvaporationReagents)] = water.Float(); + component.Progress[solution.GetColorWithOnly(_prototype, _puddleSystem.GetAbsorbentReagents(solution))] = mopReagent.Float(); } - var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagents); - var other = (solution.Volume - water).Float(); + var otherColor = solution.GetColorWithout(_prototype, _puddleSystem.GetAbsorbentReagents(solution)); + var other = (solution.Volume - mopReagent).Float(); if (other > 0f) { @@ -180,7 +180,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem } // Prioritize transferring non-evaporatives if absorbent has any - var contaminants = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, transferAmount, PuddleSystem.EvaporationReagents); + var contaminants = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, transferAmount, _puddleSystem.GetAbsorbentReagents(absorbentSoln.Comp.Solution)); if (contaminants.Volume > 0) { _solutionContainerSystem.TryAddSolution(refillableSoln, contaminants); @@ -205,7 +205,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem Entity absorbentSoln, Entity refillableSoln) { - var contaminantsFromAbsorbent = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, component.PickupAmount, PuddleSystem.EvaporationReagents); + var contaminantsFromAbsorbent = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, component.PickupAmount, _puddleSystem.GetAbsorbentReagents(absorbentSoln.Comp.Solution)); var absorbentSolution = absorbentSoln.Comp.Solution; if (contaminantsFromAbsorbent.Volume == FixedPoint2.Zero && absorbentSolution.AvailableVolume == FixedPoint2.Zero) @@ -222,7 +222,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem absorbentSolution.AvailableVolume; var refillableSolution = refillableSoln.Comp.Solution; - var waterFromRefillable = refillableSolution.SplitSolutionWithOnly(waterPulled, PuddleSystem.EvaporationReagents); + var waterFromRefillable = refillableSolution.SplitSolutionWithOnly(waterPulled, _puddleSystem.GetAbsorbentReagents(refillableSoln.Comp.Solution)); _solutionContainerSystem.UpdateChemicals(refillableSoln); if (waterFromRefillable.Volume == FixedPoint2.Zero && contaminantsFromAbsorbent.Volume == FixedPoint2.Zero) @@ -284,7 +284,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem // Check if we have any evaporative reagents on our absorber to transfer var absorberSolution = absorberSoln.Comp.Solution; - var available = absorberSolution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); + var available = absorberSolution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(absorberSolution)); // No material if (available == FixedPoint2.Zero) @@ -296,8 +296,8 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem var transferMax = absorber.PickupAmount; var transferAmount = available > transferMax ? transferMax : available; - var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); - var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents); + var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution)); + var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, _puddleSystem.GetAbsorbentReagents(absorberSolution)); // Do tile reactions first var transform = Transform(target); diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs index d78950b1d5..f92504e74c 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs @@ -1,4 +1,5 @@ using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Fluids.Components; @@ -20,7 +21,7 @@ public sealed partial class PuddleSystem return; } - if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) + if (solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) > FixedPoint2.Zero) { var evaporation = AddComp(uid); evaporation.NextTick = _timing.CurTime + EvaporationCooldown; @@ -45,8 +46,11 @@ public sealed partial class PuddleSystem if (!_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution, out var puddleSolution)) continue; - var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds; - puddleSolution.SplitSolutionWithOnly(reagentTick, EvaporationReagents); + foreach ((string evaporatingReagent, FixedPoint2 evaporatingSpeed) in GetEvaporationSpeeds(puddleSolution)) + { + var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds * evaporatingSpeed; + puddleSolution.SplitSolutionWithOnly(reagentTick, evaporatingReagent); + } // Despawn if we're done if (puddleSolution.Volume == FixedPoint2.Zero) diff --git a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs index 84cdb47494..cfca682e9b 100644 --- a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs +++ b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs @@ -1,5 +1,6 @@ using System.Collections.Frozen; using System.Linq; +using Content.Shared.FixedPoint; using System.Text.Json.Serialization; using Content.Shared.Administration.Logs; using Content.Shared.Body.Prototypes; @@ -7,14 +8,12 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reaction; using Content.Shared.EntityEffects; using Content.Shared.Database; -using Content.Shared.FixedPoint; using Content.Shared.Nutrition; using Robust.Shared.Audio; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; using Robust.Shared.Utility; @@ -105,6 +104,18 @@ namespace Content.Shared.Chemistry.Reagent [DataField] public bool Slippery; + /// + /// The speed at which the reagent evaporates over time. + /// + [DataField] + public FixedPoint2 EvaporationSpeed = FixedPoint2.Zero; + + /// + /// If this reagent can be used to mop up other reagents. + /// + [DataField] + public bool Absorbent = false; + /// /// How easily this reagent becomes fizzy when aggitated. /// 0 - completely flat, 1 - fizzes up when nudged. @@ -206,7 +217,7 @@ namespace Content.Shared.Chemistry.Reagent .ToDictionary(x => x.Key, x => x.Item2); if (proto.PlantMetabolisms.Count > 0) { - PlantMetabolisms = new List (proto.PlantMetabolisms + PlantMetabolisms = new List(proto.PlantMetabolisms .Select(x => x.GuidebookEffectDescription(prototype, entSys)) .Where(x => x is not null) .Select(x => x!) diff --git a/Content.Shared/Fluids/Components/EvaporationComponent.cs b/Content.Shared/Fluids/Components/EvaporationComponent.cs index 5545bd7be5..9b46629439 100644 --- a/Content.Shared/Fluids/Components/EvaporationComponent.cs +++ b/Content.Shared/Fluids/Components/EvaporationComponent.cs @@ -18,8 +18,8 @@ public sealed partial class EvaporationComponent : Component public TimeSpan NextTick = TimeSpan.Zero; /// - /// How much evaporation per second. + /// Evaporation factor. Multiplied by the evaporating speed of the reagent. /// [DataField("evaporationAmount")] - public FixedPoint2 EvaporationAmount = FixedPoint2.New(0.3); + public FixedPoint2 EvaporationAmount = FixedPoint2.New(1); } diff --git a/Content.Shared/Fluids/SharedPuddleSystem.Evaporation.cs b/Content.Shared/Fluids/SharedPuddleSystem.Evaporation.cs index 023d024a05..8b937ed1a7 100644 --- a/Content.Shared/Fluids/SharedPuddleSystem.Evaporation.cs +++ b/Content.Shared/Fluids/SharedPuddleSystem.Evaporation.cs @@ -1,17 +1,52 @@ using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; namespace Content.Shared.Fluids; public abstract partial class SharedPuddleSystem { - [ValidatePrototypeId] - private const string Water = "Water"; + public string[] GetEvaporatingReagents(Solution solution) + { + var evaporatingReagents = new List(); + foreach (ReagentPrototype solProto in solution.GetReagentPrototypes(_prototypeManager).Keys) + { + if (solProto.EvaporationSpeed > FixedPoint2.Zero) + evaporatingReagents.Add(solProto.ID); + } + return evaporatingReagents.ToArray(); + } - public static readonly string[] EvaporationReagents = [Water]; + public string[] GetAbsorbentReagents(Solution solution) + { + var absorbentReagents = new List(); + foreach (ReagentPrototype solProto in solution.GetReagentPrototypes(_prototypeManager).Keys) + { + if (solProto.Absorbent) + absorbentReagents.Add(solProto.ID); + } + return absorbentReagents.ToArray(); + } public bool CanFullyEvaporate(Solution solution) { - return solution.GetTotalPrototypeQuantity(EvaporationReagents) == solution.Volume; + return solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) == solution.Volume; + } + + /// + /// Gets the evaporating speed of the reagents within a solution. + /// The speed at which a solution evaporates is the sum of the speed of all evaporating reagents in it. + /// + public Dictionary GetEvaporationSpeeds(Solution solution) + { + var evaporatingSpeeds = new Dictionary(); + foreach (ReagentPrototype solProto in solution.GetReagentPrototypes(_prototypeManager).Keys) + { + if (solProto.EvaporationSpeed > FixedPoint2.Zero) + { + evaporatingSpeeds.Add(solProto.ID, solProto.EvaporationSpeed); + } + } + return evaporatingSpeeds; } } diff --git a/Content.Shared/Fluids/SharedPuddleSystem.cs b/Content.Shared/Fluids/SharedPuddleSystem.cs index f573c042c5..34ba8ba803 100644 --- a/Content.Shared/Fluids/SharedPuddleSystem.cs +++ b/Content.Shared/Fluids/SharedPuddleSystem.cs @@ -100,7 +100,7 @@ public abstract partial class SharedPuddleSystem : EntitySystem { if (CanFullyEvaporate(solution)) args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating")); - else if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) + else if (solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) > FixedPoint2.Zero) args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-partial")); else args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-no")); diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml b/Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml index f72733d15d..c722c42162 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml @@ -436,6 +436,8 @@ parent: BaseDrink desc: reagent-desc-water slippery: true + evaporationSpeed: 0.3 + absorbent: true physicalDesc: reagent-physical-desc-translucent flavor: water color: "#75b1f0"