]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Spray nozzle can suck puddles into tank directly! (#30600)
authorFildrance <fildrance@gmail.com>
Mon, 26 May 2025 03:36:16 +0000 (06:36 +0300)
committerGitHub <noreply@github.com>
Mon, 26 May 2025 03:36:16 +0000 (23:36 -0400)
* feat: now vacuum cleaner can suck solutions from floor

* refactor using AbsorbentSystem instead of separate vacuum cleaner

* refactor: remove unused vacuum cleaner files

* refactor: renamed ConnectedContainerComponent to SlotBasedConnectedContainerComponent (and system)

* fix: fix invalid comp name

* fix: no more spray nozzle messaging about water inside bottles etc.

* refactor: minor refactor in SlotBasedConnectedContainerSystem and adjustments after merge

* refactor: cleanups

* refactor: renaming

* refactor: update to use _puddleSystem.GetAbsorbentReagents

* refactor: changed interactions with SlotBasedConnectedContainerSystem into events

* refactor: new sound and action delay adjusted to sound (amount tweaked a bit accordingly, almost)

* refactor: added networking for SlotBasedConnectedContainerComponent

* fix attribution for vacuum-cleaner-fast.ogg

* trying to fix multi-license for mix sound file

* remove empty line

* refactor: remove trailing whitespace

* by ref struct, brother

---------

Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Co-authored-by: EmoGarbage404 <retron404@gmail.com>
14 files changed:
Content.IntegrationTests/Tests/Fluids/AbsorbentTest.cs
Content.Server/Chemistry/EntitySystems/InjectorSystem.cs
Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs
Content.Shared/Chemistry/Components/SlotBasedConnectedContainerComponent.cs [new file with mode: 0644]
Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs
Content.Shared/Containers/SlotBasedConnectedContainerSystem.cs [new file with mode: 0644]
Content.Shared/Fluids/AbsorbentComponent.cs
Content.Shared/Weapons/Ranged/Components/AmmoProviderComponent.cs
Content.Shared/Weapons/Ranged/Components/ClothingSlotAmmoProviderComponent.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs
Resources/Audio/Effects/Fluids/attributions.yml
Resources/Audio/Effects/Fluids/vacuum-cleaner-fast.ogg [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/spraynozzle.yml

index 87ef41fe96eda815f5690d608ea69fc779fb57e3..bf4776827437a853fb1f3480ca2720bdb2a7ea49 100644 (file)
@@ -33,6 +33,7 @@ public sealed class AbsorbentTest
   id: {AbsorbentDummyId}
   components:
   - type: Absorbent
+    useAbsorberSolution: true
   - type: SolutionContainerManager
     solutions:
       absorbed:
@@ -94,7 +95,7 @@ public sealed class AbsorbentTest
             refillable = entityManager.SpawnEntity(RefillableDummyId, coordinates);
 
             entityManager.TryGetComponent(absorbent, out component);
-            solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution);
+            solutionContainerSystem.TryGetSolution(absorbent, component.SolutionName, out var absorbentSoln, out var absorbentSolution);
             solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution);
 
             // Arrange
@@ -152,7 +153,7 @@ public sealed class AbsorbentTest
             refillable = entityManager.SpawnEntity(SmallRefillableDummyId, coordinates);
 
             entityManager.TryGetComponent(absorbent, out component);
-            solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution);
+            solutionContainerSystem.TryGetSolution(absorbent, component.SolutionName, out var absorbentSoln, out var absorbentSolution);
             solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution);
 
             // Arrange
index cc32d5a24528cb1472f82c8c082807847331da6d..62303c2e359f15714e8fce7d13d21b95d0cc23f8 100644 (file)
@@ -91,7 +91,7 @@ public sealed class InjectorSystem : SharedInjectorSystem
         // Is the target a mob? If yes, use a do-after to give them time to respond.
         if (HasComp<MobStateComponent>(target) || HasComp<BloodstreamComponent>(target))
         {
-            // Are use using an injector capible of targeting a mob?
+            // Are use using an injector capable of targeting a mob?
             if (entity.Comp.IgnoreMobs)
                 return;
 
index cb3cae10af428e97c2c3546f8b792b2d1fbd661e..1177c243042e4ed6854496ab179a8616abd4d32f 100644 (file)
@@ -19,6 +19,8 @@ namespace Content.Server.Fluids.EntitySystems;
 /// <inheritdoc/>
 public sealed class AbsorbentSystem : SharedAbsorbentSystem
 {
+    private static readonly EntProtoId Sparkles = "PuddleSparkle";
+
     [Dependency] private readonly IPrototypeManager _prototype = default!;
     [Dependency] private readonly AudioSystem _audio = default!;
     [Dependency] private readonly PopupSystem _popups = default!;
@@ -51,7 +53,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
 
     private void UpdateAbsorbent(EntityUid uid, AbsorbentComponent component)
     {
-        if (!_solutionContainerSystem.TryGetSolution(uid, AbsorbentComponent.SolutionName, out _, out var solution))
+        if (!_solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out _, out var solution))
             return;
 
         var oldProgress = component.Progress.ShallowClone();
@@ -104,7 +106,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
 
     public void Mop(EntityUid user, EntityUid target, EntityUid used, AbsorbentComponent component)
     {
-        if (!_solutionContainerSystem.TryGetSolution(used, AbsorbentComponent.SolutionName, out var absorberSoln))
+        if (!_solutionContainerSystem.TryGetSolution(used, component.SolutionName, out var absorberSoln))
             return;
 
         if (TryComp<UseDelayComponent>(used, out var useDelay)
@@ -112,7 +114,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
             return;
 
         // If it's a puddle try to grab from
-        if (!TryPuddleInteract(user, used, target, component, useDelay, absorberSoln.Value))
+        if (!TryPuddleInteract(user, used, target, component, useDelay, absorberSoln.Value) && component.UseAbsorberSolution)
         {
             // If it's refillable try to transfer
             if (!TryRefillableInteract(user, used, target, component, useDelay, absorberSoln.Value))
@@ -282,36 +284,53 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
             return true;
         }
 
-        // Check if we have any evaporative reagents on our absorber to transfer
-        var absorberSolution = absorberSoln.Comp.Solution;
-        var available = absorberSolution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(absorberSolution));
-
-        // No material
-        if (available == FixedPoint2.Zero)
+        Solution puddleSplit;
+        var isRemoved = false;
+        if (absorber.UseAbsorberSolution)
         {
-            _popups.PopupEntity(Loc.GetString("mopping-system-no-water", ("used", used)), user, user);
-            return true;
-        }
+            // Check if we have any evaporative reagents on our absorber to transfer
+            var absorberSolution = absorberSoln.Comp.Solution;
+            var available = absorberSolution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(absorberSolution));
+
+            // No material
+            if (available == FixedPoint2.Zero)
+            {
+                _popups.PopupEntity(Loc.GetString("mopping-system-no-water", ("used", used)), user, user);
+                return true;
+            }
 
-        var transferMax = absorber.PickupAmount;
-        var transferAmount = available > transferMax ? transferMax : available;
+            var transferMax = absorber.PickupAmount;
+            var transferAmount = available > transferMax ? transferMax : available;
 
-        var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution));
-        var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, _puddleSystem.GetAbsorbentReagents(absorberSolution));
+            puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution));
+            var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, _puddleSystem.GetAbsorbentReagents(absorberSolution));
 
-        // Do tile reactions first
-        var transform = Transform(target);
-        var gridUid = transform.GridUid;
-        if (TryComp(gridUid, out MapGridComponent? mapGrid))
+            // Do tile reactions first
+            var transform = Transform(target);
+            var gridUid = transform.GridUid;
+            if (TryComp(gridUid, out MapGridComponent? mapGrid))
+            {
+                var tileRef = _mapSystem.GetTileRef(gridUid.Value, mapGrid, transform.Coordinates);
+                _puddleSystem.DoTileReactions(tileRef, absorberSplit);
+            }
+            _solutionContainerSystem.AddSolution(puddle.Solution.Value, absorberSplit);
+        }
+        else
         {
-            var tileRef = _mapSystem.GetTileRef(gridUid.Value, mapGrid, transform.Coordinates);
-            _puddleSystem.DoTileReactions(tileRef, absorberSplit);
+            puddleSplit = puddleSolution.SplitSolutionWithout(absorber.PickupAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution));
+            // Despawn if we're done
+            if (puddleSolution.Volume == FixedPoint2.Zero)
+            {
+                // Spawn a *sparkle*
+                Spawn(Sparkles, GetEntityQuery<TransformComponent>().GetComponent(target).Coordinates);
+                QueueDel(target);
+                isRemoved = true;
+            }
         }
 
-        _solutionContainerSystem.AddSolution(puddle.Solution.Value, absorberSplit);
         _solutionContainerSystem.AddSolution(absorberSoln, puddleSplit);
 
-        _audio.PlayPvs(absorber.PickupSound, target);
+        _audio.PlayPvs(absorber.PickupSound, isRemoved ? used : target);
         if (useDelay != null)
             _useDelay.TryResetDelay((used, useDelay));
 
diff --git a/Content.Shared/Chemistry/Components/SlotBasedConnectedContainerComponent.cs b/Content.Shared/Chemistry/Components/SlotBasedConnectedContainerComponent.cs
new file mode 100644 (file)
index 0000000..2fde557
--- /dev/null
@@ -0,0 +1,25 @@
+using Content.Shared.Containers;
+using Content.Shared.Inventory;
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Chemistry.Components;
+
+/// <summary>
+/// Component for marking linked container in character slot, to which entity is bound.
+/// </summary>
+[RegisterComponent, Access(typeof(SlotBasedConnectedContainerSystem)), NetworkedComponent]
+public sealed partial class SlotBasedConnectedContainerComponent : Component
+{
+    /// <summary>
+    /// The slot in which target container should be.
+    /// </summary>
+    [DataField(required: true)]
+    public SlotFlags TargetSlot;
+
+    /// <summary>
+    /// A whitelist for determining whether container is valid or not .
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? ContainerWhitelist;
+}
index 99d1459340c476518d16579d04bc221965319796..f536beef2bc46410511b964a44baf7c109698ae9 100644 (file)
@@ -14,6 +14,7 @@ using System.Linq;
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Text;
+using Content.Shared.Containers;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Robust.Shared.Map;
@@ -162,6 +163,12 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
         [NotNullWhen(true)] out Entity<SolutionComponent>? entity,
         bool errorOnMissing = false)
     {
+        // use connected container instead of entity from arguments, if it exists.
+        var ev = new GetConnectedContainerEvent();
+        RaiseLocalEvent(container, ref ev);
+        if (ev.ContainerEntity.HasValue)
+            container = ev.ContainerEntity.Value;
+
         EntityUid uid;
         if (name is null)
             uid = container;
diff --git a/Content.Shared/Containers/SlotBasedConnectedContainerSystem.cs b/Content.Shared/Containers/SlotBasedConnectedContainerSystem.cs
new file mode 100644 (file)
index 0000000..4970a54
--- /dev/null
@@ -0,0 +1,86 @@
+using System.Diagnostics.CodeAnalysis;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Inventory;
+using Content.Shared.Whitelist;
+using Robust.Shared.Containers;
+
+namespace Content.Shared.Containers;
+
+/// <summary>
+/// System for getting container that is linked to subject entity. Container is supposed to be present in certain character slot.
+/// Can be used for linking ammo feeder, solution source for spray nozzle, etc.
+/// </summary>
+public sealed class SlotBasedConnectedContainerSystem : EntitySystem
+{
+    [Dependency] private readonly SharedContainerSystem _containers = default!;
+    [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
+    [Dependency] private readonly InventorySystem _inventory = default!;
+
+    /// <inheritdoc />
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<SlotBasedConnectedContainerComponent, GetConnectedContainerEvent>(OnGettingConnectedContainer);
+    }
+
+    /// <summary>
+    /// Try get connected container entity in character slots for <see cref="uid"/>.
+    /// </summary>
+    /// <param name="uid">
+    /// Entity for which connected container is required. If <see cref="SlotBasedConnectedContainerComponent"/>
+    /// is used - tries to find container in slot, returns false and null <see cref="slotEntity"/> otherwise.
+    /// </param>
+    /// <param name="slotEntity">Found connected container entity or null.</param>
+    /// <returns>True if connected container was found, false otherwise.</returns>
+    public bool TryGetConnectedContainer(EntityUid uid, [NotNullWhen(true)] out EntityUid? slotEntity)
+    {
+        if (!TryComp<SlotBasedConnectedContainerComponent>(uid, out var component))
+        {
+            slotEntity = null;
+            return false;
+        }
+
+        return TryGetConnectedContainer(uid, component.TargetSlot, component.ContainerWhitelist, out slotEntity);
+    }
+
+    private void OnGettingConnectedContainer(Entity<SlotBasedConnectedContainerComponent> ent, ref GetConnectedContainerEvent args)
+    {
+        if (TryGetConnectedContainer(ent, ent.Comp.TargetSlot, ent.Comp.ContainerWhitelist, out var val))
+            args.ContainerEntity = val;
+    }
+
+    private bool TryGetConnectedContainer(EntityUid uid, SlotFlags slotFlag, EntityWhitelist? providerWhitelist, [NotNullWhen(true)] out EntityUid? slotEntity)
+    {
+        slotEntity = null;
+
+        if (!_containers.TryGetContainingContainer((uid, null, null), out var container))
+            return false;
+
+        var user = container.Owner;
+        if (!_inventory.TryGetContainerSlotEnumerator(user, out var enumerator, slotFlag))
+            return false;
+
+        while (enumerator.NextItem(out var item))
+        {
+            if (_whitelistSystem.IsWhitelistFailOrNull(providerWhitelist, item))
+                continue;
+
+            slotEntity = item;
+            return true;
+        }
+
+        return false;
+    }
+}
+
+/// <summary>
+/// Event for an attempt of getting container, connected to entity on which event was raised.
+/// Fills <see cref="ContainerEntity"/> if connected container exists.
+/// </summary>
+[ByRefEvent]
+public struct GetConnectedContainerEvent
+{
+    /// <summary>
+    /// Container entity, if it exists, or null.
+    /// </summary>
+    public EntityUid? ContainerEntity;
+}
index 450ecc0df6d12907683e86eafd4ef024e39f1ece..2d1a9223813ee50a62e3ee8700fb174527f359ce 100644 (file)
@@ -11,23 +11,28 @@ namespace Content.Shared.Fluids;
 [RegisterComponent, NetworkedComponent]
 public sealed partial class AbsorbentComponent : Component
 {
-    public const string SolutionName = "absorbed";
-
     public Dictionary<Color, float> Progress = new();
 
+    /// <summary>
+    /// Name for solution container, that should be used for absorbed solution storage and as source of absorber solution.
+    /// Default is 'absorbed'.
+    /// </summary>
+    [DataField]
+    public string SolutionName = "absorbed";
+
     /// <summary>
     /// How much solution we can transfer in one interaction.
     /// </summary>
-    [DataField("pickupAmount")]
+    [DataField]
     public FixedPoint2 PickupAmount = FixedPoint2.New(100);
 
-    [DataField("pickupSound")]
+    [DataField]
     public SoundSpecifier PickupSound = new SoundPathSpecifier("/Audio/Effects/Fluids/watersplash.ogg")
     {
         Params = AudioParams.Default.WithVariation(SharedContentAudioSystem.DefaultVariation),
     };
 
-    [DataField("transferSound")] public SoundSpecifier TransferSound =
+    [DataField] public SoundSpecifier TransferSound =
         new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg")
         {
             Params = AudioParams.Default.WithVariation(SharedContentAudioSystem.DefaultVariation).WithVolume(-3f),
@@ -38,4 +43,11 @@ public sealed partial class AbsorbentComponent : Component
         {
             Params = AudioParams.Default.WithVariation(SharedContentAudioSystem.DefaultVariation).WithVolume(-3f),
         };
+
+    /// <summary>
+    /// Marker that absorbent component owner should try to use 'absorber solution' to replace solution to be absorbed.
+    /// Target solution will be simply consumed into container if set to false.
+    /// </summary>
+    [DataField]
+    public bool UseAbsorberSolution = true;
 }
index 9a7fdc07deb275d089d6552378a81d693dce7d2d..8e2f767f4dc32f26f682439f82b01abc687ce7ed 100644 (file)
@@ -3,4 +3,4 @@ using Robust.Shared.GameStates;
 namespace Content.Shared.Weapons.Ranged.Components;
 
 [NetworkedComponent]
-public abstract partial class AmmoProviderComponent : Component {}
+public abstract partial class AmmoProviderComponent : Component;
index e363fc9fe101e5f3e97cbb272bee7ccdea86c30e..418e712c7b8f6b575801f8fcadabf59e70839268 100644 (file)
@@ -1,6 +1,4 @@
-using Content.Shared.Inventory;
 using Content.Shared.Weapons.Ranged.Systems;
-using Content.Shared.Whitelist;
 using Robust.Shared.GameStates;
 
 namespace Content.Shared.Weapons.Ranged.Components;
@@ -10,17 +8,4 @@ namespace Content.Shared.Weapons.Ranged.Components;
 /// to an entity in the user's clothing slot.
 /// </summary>
 [RegisterComponent, NetworkedComponent, Access(typeof(SharedGunSystem))]
-public sealed partial class ClothingSlotAmmoProviderComponent : AmmoProviderComponent
-{
-    /// <summary>
-    /// The slot that the ammo provider should be located in.
-    /// </summary>
-    [DataField("targetSlot", required: true)]
-    public SlotFlags TargetSlot;
-
-    /// <summary>
-    /// A whitelist for determining whether or not an ammo provider is valid.
-    /// </summary>
-    [DataField("providerWhitelist")]
-    public EntityWhitelist? ProviderWhitelist;
-}
+public sealed partial class ClothingSlotAmmoProviderComponent : AmmoProviderComponent;
index 7ef57df53919c542bf0dfcef241b60321e4bd554..12bbe0c3123d7f544b004cceed540d396a788a41 100644 (file)
@@ -1,5 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
-using Content.Shared.Inventory;
+using Content.Shared.Containers;
 using Content.Shared.Weapons.Ranged.Components;
 using Content.Shared.Weapons.Ranged.Events;
 
@@ -7,8 +6,6 @@ namespace Content.Shared.Weapons.Ranged.Systems;
 
 public partial class SharedGunSystem
 {
-    [Dependency] private readonly InventorySystem _inventory = default!;
-
     private void InitializeClothing()
     {
         SubscribeLocalEvent<ClothingSlotAmmoProviderComponent, TakeAmmoEvent>(OnClothingTakeAmmo);
@@ -17,38 +14,21 @@ public partial class SharedGunSystem
 
     private void OnClothingTakeAmmo(EntityUid uid, ClothingSlotAmmoProviderComponent component, TakeAmmoEvent args)
     {
-        if (!TryGetClothingSlotEntity(uid, component, out var entity))
+        var getConnectedContainerEvent = new GetConnectedContainerEvent();
+        RaiseLocalEvent(uid, ref getConnectedContainerEvent);
+        if(!getConnectedContainerEvent.ContainerEntity.HasValue)
             return;
-        RaiseLocalEvent(entity.Value, args);
+
+        RaiseLocalEvent(getConnectedContainerEvent.ContainerEntity.Value, args);
     }
 
     private void OnClothingAmmoCount(EntityUid uid, ClothingSlotAmmoProviderComponent component, ref GetAmmoCountEvent args)
     {
-        if (!TryGetClothingSlotEntity(uid, component, out var entity))
+        var getConnectedContainerEvent = new GetConnectedContainerEvent();
+        RaiseLocalEvent(uid, ref getConnectedContainerEvent);
+        if (!getConnectedContainerEvent.ContainerEntity.HasValue)
             return;
-        RaiseLocalEvent(entity.Value, ref args);
-    }
-
-    private bool TryGetClothingSlotEntity(EntityUid uid, ClothingSlotAmmoProviderComponent component, [NotNullWhen(true)] out EntityUid? slotEntity)
-    {
-        slotEntity = null;
-
-        if (!Containers.TryGetContainingContainer((uid, null, null), out var container))
-            return false;
-        var user = container.Owner;
-
-        if (!_inventory.TryGetContainerSlotEnumerator(user, out var enumerator, component.TargetSlot))
-            return false;
-
-        while (enumerator.NextItem(out var item))
-        {
-            if (_whitelistSystem.IsWhitelistFailOrNull(component.ProviderWhitelist, item))
-                continue;
-
-            slotEntity = item;
-            return true;
-        }
 
-        return false;
+        RaiseLocalEvent(getConnectedContainerEvent.ContainerEntity.Value, ref args);
     }
 }
index aebe3e3c3ff0fa01a187aa8ff3604615a1492dea..c23a5f5c7f8fccaee55fbf2cbcf02ae19c41e475 100644 (file)
   license: "CC-BY-SA-3.0"
   copyright: "Created by the_toilet_guy"
   source: "https://freesound.org/people/the_toilet_guy/sounds/98770/"
+
+- files: ["vacuum-cleaner-fast.ogg"]
+  license: "CC0-1.0"
+  copyright: "Created by kyles"
+  source: "https://freesound.org/people/kyles/sounds/637927/"
+
+- files: ["vacuum-cleaner-fast.ogg"]
+  license: "CC0-1.0"
+  copyright: "Created by BrendanSound12 mixed by Fildrance"
+  source: "https://freesound.org/people/BrendanSound12/sounds/445165/"
diff --git a/Resources/Audio/Effects/Fluids/vacuum-cleaner-fast.ogg b/Resources/Audio/Effects/Fluids/vacuum-cleaner-fast.ogg
new file mode 100644 (file)
index 0000000..bf20520
Binary files /dev/null and b/Resources/Audio/Effects/Fluids/vacuum-cleaner-fast.ogg differ
index 6a7234b810bb372a8338e2864bab9027cbbb3ca8..e09ba46e1293296b074e208a02db553aeca6a336 100644 (file)
@@ -34,6 +34,7 @@
     size: Large
     sprite: Objects/Specific/Janitorial/mop.rsi
   - type: Absorbent
+    useAbsorberSolution: true
   - type: SolutionContainerManager
     solutions:
       absorbed:
@@ -89,6 +90,7 @@
       sprite: Objects/Specific/Janitorial/advmop.rsi
     - type: Absorbent
       pickupAmount: 100
+      useAbsorberSolution: true
     - type: UseDelay
       delay: 1.0
     - type: SolutionRegeneration
       sprite: Objects/Specific/Janitorial/rag.rsi
     - type: Absorbent
       pickupAmount: 15
+      useAbsorberSolution: true
     - type: Construction
       graph: Rag
       node: rag
index 616a799affe3d0baab9f8e2ca7f93052caf298c0..b6e48f701b1b9687e8ff17f073f71ea38466c70c 100644 (file)
     - FullAuto
     soundGunshot:
       path: /Audio/Weapons/Guns/Gunshots/water_spray.ogg
+  - type: Absorbent
+    pickupAmount: 35
+    solutionName: tank
+    useAbsorberSolution: false
+    pickupSound:
+      path: /Audio/Effects/Fluids/vacuum-cleaner-fast.ogg
   - type: Appearance
   - type: ClothingSlotAmmoProvider
+  - type: SlotBasedConnectedContainer
     targetSlot: BACK
-    providerWhitelist:
+    containerWhitelist:
       tags:
       - NozzleBackTank
+  - type: UseDelay
+    delay: 1.0