diff --git a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs
index ff050ce2cda..d45fe707ab2 100644
--- a/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs
+++ b/Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs
@@ -1,42 +1,60 @@
-using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Fluids.EntitySystems;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Fluids.Components;
using JetBrains.Annotations;
-namespace Content.Server.Destructible.Thresholds.Behaviors
+namespace Content.Server.Destructible.Thresholds.Behaviors;
+
+[UsedImplicitly]
+[DataDefinition]
+public sealed partial class SpillBehavior : IThresholdBehavior
{
- [UsedImplicitly]
- [DataDefinition]
- public sealed partial class SpillBehavior : IThresholdBehavior
- {
- [DataField]
- public string? Solution;
+ ///
+ /// Optional fallback solution name if SpillableComponent is not present.
+ ///
+ [DataField]
+ public string? Solution;
- ///
- /// If there is a SpillableComponent on EntityUidowner use it to create a puddle/smear.
- /// Or whatever solution is specified in the behavior itself.
- /// If none are available do nothing.
- ///
- /// Entity on which behavior is executed
- /// system calling the behavior
- ///
- public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
- {
- var solutionContainerSystem = system.EntityManager.System();
- var spillableSystem = system.EntityManager.System();
+ ///
+ /// When triggered, spills the entity's solution onto the ground.
+ /// Will first try to use the solution from a SpillableComponent if present,
+ /// otherwise falls back to the solution specified in the behavior's data fields.
+ /// The solution is properly drained/split before spilling to prevent double-spilling with other behaviors.
+ ///
+ /// Entity whose solution will be spilled
+ /// System calling this behavior
+ /// Optional entity that caused this behavior to trigger
+ public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
+ {
+ var solutionContainerSystem = system.EntityManager.System();
+ var spillableSystem = system.EntityManager.System();
+ var coordinates = system.EntityManager.GetComponent(owner).Coordinates;
- var coordinates = system.EntityManager.GetComponent(owner).Coordinates;
+ Solution targetSolution;
- if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
- solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out _, out var compSolution))
- {
- spillableSystem.TrySplashSpillAt(owner, coordinates, compSolution, out _, false, user: cause);
- }
- else if (Solution != null &&
- solutionContainerSystem.TryGetSolution(owner, Solution, out _, out var behaviorSolution))
- {
- spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, user: cause);
- }
+ // First try to get solution from SpillableComponent
+ if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
+ solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out var solution, out var compSolution))
+ {
+ // If entity is drainable, drain the solution. Otherwise just split it.
+ // Both methods ensure the solution is properly removed.
+ targetSolution = system.EntityManager.HasComponent(owner)
+ ? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent(owner)), solution.Value, compSolution.Volume)
+ : compSolution.SplitSolution(compSolution.Volume);
}
+ // Fallback to solution specified in behavior data
+ else if (Solution != null &&
+ solutionContainerSystem.TryGetSolution(owner, Solution, out var solutionEnt, out var behaviorSolution))
+ {
+ targetSolution = system.EntityManager.HasComponent(owner)
+ ? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent(owner)), solutionEnt.Value, behaviorSolution.Volume)
+ : behaviorSolution.SplitSolution(behaviorSolution.Volume);
+ }
+ else
+ return;
+
+ // Spill the solution that was drained/split
+ spillableSystem.TrySplashSpillAt(owner, coordinates, targetSolution, out _, false, cause);
}
}