Un-Hardcode water evaporation & mopping behavior (#33399)

* Un-harcode slipperiness

* Make it actually work

* Prettyfy

* Cleanup GetEvaporatingReagents

* Fix mopping with space lube + wrong solutions in absorbance

* Remove LINQ and rename parameters

* Change evaporation speed to fixedpoint2

* Add evaporating speed functionality

* Remove unused imports

* Swap around reagent evaporation speed and puddle evaporation speed.

---------

Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
This commit is contained in:
Jajsha
2025-04-18 20:11:28 -04:00
committed by GitHub
parent 181bb27797
commit a6741e42c1
7 changed files with 76 additions and 24 deletions

View File

@@ -57,14 +57,14 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
var oldProgress = component.Progress.ShallowClone(); var oldProgress = component.Progress.ShallowClone();
component.Progress.Clear(); component.Progress.Clear();
var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); var mopReagent = solution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(solution));
if (water > FixedPoint2.Zero) 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 otherColor = solution.GetColorWithout(_prototype, _puddleSystem.GetAbsorbentReagents(solution));
var other = (solution.Volume - water).Float(); var other = (solution.Volume - mopReagent).Float();
if (other > 0f) if (other > 0f)
{ {
@@ -180,7 +180,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
} }
// Prioritize transferring non-evaporatives if absorbent has any // 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) if (contaminants.Volume > 0)
{ {
_solutionContainerSystem.TryAddSolution(refillableSoln, contaminants); _solutionContainerSystem.TryAddSolution(refillableSoln, contaminants);
@@ -205,7 +205,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
Entity<SolutionComponent> absorbentSoln, Entity<SolutionComponent> absorbentSoln,
Entity<SolutionComponent> refillableSoln) Entity<SolutionComponent> 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; var absorbentSolution = absorbentSoln.Comp.Solution;
if (contaminantsFromAbsorbent.Volume == FixedPoint2.Zero && absorbentSolution.AvailableVolume == FixedPoint2.Zero) if (contaminantsFromAbsorbent.Volume == FixedPoint2.Zero && absorbentSolution.AvailableVolume == FixedPoint2.Zero)
@@ -222,7 +222,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
absorbentSolution.AvailableVolume; absorbentSolution.AvailableVolume;
var refillableSolution = refillableSoln.Comp.Solution; 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); _solutionContainerSystem.UpdateChemicals(refillableSoln);
if (waterFromRefillable.Volume == FixedPoint2.Zero && contaminantsFromAbsorbent.Volume == FixedPoint2.Zero) 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 // Check if we have any evaporative reagents on our absorber to transfer
var absorberSolution = absorberSoln.Comp.Solution; var absorberSolution = absorberSoln.Comp.Solution;
var available = absorberSolution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); var available = absorberSolution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(absorberSolution));
// No material // No material
if (available == FixedPoint2.Zero) if (available == FixedPoint2.Zero)
@@ -296,8 +296,8 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
var transferMax = absorber.PickupAmount; var transferMax = absorber.PickupAmount;
var transferAmount = available > transferMax ? transferMax : available; var transferAmount = available > transferMax ? transferMax : available;
var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution));
var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents); var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, _puddleSystem.GetAbsorbentReagents(absorberSolution));
// Do tile reactions first // Do tile reactions first
var transform = Transform(target); var transform = Transform(target);

View File

@@ -1,4 +1,5 @@
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint; using Content.Shared.FixedPoint;
using Content.Shared.Fluids.Components; using Content.Shared.Fluids.Components;
@@ -20,7 +21,7 @@ public sealed partial class PuddleSystem
return; return;
} }
if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) if (solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) > FixedPoint2.Zero)
{ {
var evaporation = AddComp<EvaporationComponent>(uid); var evaporation = AddComp<EvaporationComponent>(uid);
evaporation.NextTick = _timing.CurTime + EvaporationCooldown; 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)) if (!_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution, out var puddleSolution))
continue; continue;
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds; foreach ((string evaporatingReagent, FixedPoint2 evaporatingSpeed) in GetEvaporationSpeeds(puddleSolution))
puddleSolution.SplitSolutionWithOnly(reagentTick, EvaporationReagents); {
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds * evaporatingSpeed;
puddleSolution.SplitSolutionWithOnly(reagentTick, evaporatingReagent);
}
// Despawn if we're done // Despawn if we're done
if (puddleSolution.Volume == FixedPoint2.Zero) if (puddleSolution.Volume == FixedPoint2.Zero)

View File

@@ -1,5 +1,6 @@
using System.Collections.Frozen; using System.Collections.Frozen;
using System.Linq; using System.Linq;
using Content.Shared.FixedPoint;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Content.Shared.Administration.Logs; using Content.Shared.Administration.Logs;
using Content.Shared.Body.Prototypes; using Content.Shared.Body.Prototypes;
@@ -7,14 +8,12 @@ using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reaction;
using Content.Shared.EntityEffects; using Content.Shared.EntityEffects;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Nutrition; using Content.Shared.Nutrition;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -105,6 +104,18 @@ namespace Content.Shared.Chemistry.Reagent
[DataField] [DataField]
public bool Slippery; public bool Slippery;
/// <summary>
/// The speed at which the reagent evaporates over time.
/// </summary>
[DataField]
public FixedPoint2 EvaporationSpeed = FixedPoint2.Zero;
/// <summary>
/// If this reagent can be used to mop up other reagents.
/// </summary>
[DataField]
public bool Absorbent = false;
/// <summary> /// <summary>
/// How easily this reagent becomes fizzy when aggitated. /// How easily this reagent becomes fizzy when aggitated.
/// 0 - completely flat, 1 - fizzes up when nudged. /// 0 - completely flat, 1 - fizzes up when nudged.
@@ -206,7 +217,7 @@ namespace Content.Shared.Chemistry.Reagent
.ToDictionary(x => x.Key, x => x.Item2); .ToDictionary(x => x.Key, x => x.Item2);
if (proto.PlantMetabolisms.Count > 0) if (proto.PlantMetabolisms.Count > 0)
{ {
PlantMetabolisms = new List<string> (proto.PlantMetabolisms PlantMetabolisms = new List<string>(proto.PlantMetabolisms
.Select(x => x.GuidebookEffectDescription(prototype, entSys)) .Select(x => x.GuidebookEffectDescription(prototype, entSys))
.Where(x => x is not null) .Where(x => x is not null)
.Select(x => x!) .Select(x => x!)

View File

@@ -18,8 +18,8 @@ public sealed partial class EvaporationComponent : Component
public TimeSpan NextTick = TimeSpan.Zero; public TimeSpan NextTick = TimeSpan.Zero;
/// <summary> /// <summary>
/// How much evaporation per second. /// Evaporation factor. Multiplied by the evaporating speed of the reagent.
/// </summary> /// </summary>
[DataField("evaporationAmount")] [DataField("evaporationAmount")]
public FixedPoint2 EvaporationAmount = FixedPoint2.New(0.3); public FixedPoint2 EvaporationAmount = FixedPoint2.New(1);
} }

View File

@@ -1,17 +1,52 @@
using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent; using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
namespace Content.Shared.Fluids; namespace Content.Shared.Fluids;
public abstract partial class SharedPuddleSystem public abstract partial class SharedPuddleSystem
{ {
[ValidatePrototypeId<ReagentPrototype>] public string[] GetEvaporatingReagents(Solution solution)
private const string Water = "Water"; {
var evaporatingReagents = new List<string>();
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<string>();
foreach (ReagentPrototype solProto in solution.GetReagentPrototypes(_prototypeManager).Keys)
{
if (solProto.Absorbent)
absorbentReagents.Add(solProto.ID);
}
return absorbentReagents.ToArray();
}
public bool CanFullyEvaporate(Solution solution) public bool CanFullyEvaporate(Solution solution)
{ {
return solution.GetTotalPrototypeQuantity(EvaporationReagents) == solution.Volume; return solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) == solution.Volume;
}
/// <summary>
/// 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.
/// </summary>
public Dictionary<string, FixedPoint2> GetEvaporationSpeeds(Solution solution)
{
var evaporatingSpeeds = new Dictionary<string, FixedPoint2>();
foreach (ReagentPrototype solProto in solution.GetReagentPrototypes(_prototypeManager).Keys)
{
if (solProto.EvaporationSpeed > FixedPoint2.Zero)
{
evaporatingSpeeds.Add(solProto.ID, solProto.EvaporationSpeed);
}
}
return evaporatingSpeeds;
} }
} }

View File

@@ -100,7 +100,7 @@ public abstract partial class SharedPuddleSystem : EntitySystem
{ {
if (CanFullyEvaporate(solution)) if (CanFullyEvaporate(solution))
args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating")); 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")); args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-partial"));
else else
args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-no")); args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-no"));

View File

@@ -436,6 +436,8 @@
parent: BaseDrink parent: BaseDrink
desc: reagent-desc-water desc: reagent-desc-water
slippery: true slippery: true
evaporationSpeed: 0.3
absorbent: true
physicalDesc: reagent-physical-desc-translucent physicalDesc: reagent-physical-desc-translucent
flavor: water flavor: water
color: "#75b1f0" color: "#75b1f0"