From 6a18bdc023df332c769e4624ac9d71a830d1aea8 Mon Sep 17 00:00:00 2001 From: Psychpsyo <60073468+Psychpsyo@users.noreply.github.com> Date: Tue, 31 Oct 2023 21:39:12 +0100 Subject: [PATCH] Soapy Water & Edible Soap (#20364) * soap reagent and soapy water * make soapy water recognizable * Fix tile cleaning bug CleanDecalsReaction was able to take more than the reactVolume it was given. * make soapy water an evaporating reagent * Tile reactions when mopping * Fix indescribably soap flavor * Adjust soap flavours Soap and soapy water now taste clean and syndie soap tastes like punishment. * Better soap numbers & DeleteOnSolutionEmpty * Changed TrashOnEmpty to TrashOnSolutionEmpty * Last TrashOnSolutionEmpty change * Fix merged code not compiling * Requested changes. --- .../DeleteOnSolutionEmptyComponent.cs | 15 +++ .../DeleteOnSolutionEmptySystem.cs | 38 ++++++++ .../TileReactions/CleanDecalsReaction.cs | 6 +- .../Fluids/EntitySystems/AbsorbentSystem.cs | 44 +++++---- .../EntitySystems/PuddleSystem.Evaporation.cs | 13 ++- .../Fluids/EntitySystems/PuddleSystem.cs | 28 +++--- ...nt.cs => TrashOnSolutionEmptyComponent.cs} | 2 +- ...ystem.cs => TrashOnSolutionEmptySystem.cs} | 15 ++- .../Chemistry/Components/Solution.cs | 70 +++++++++++++- .../Locale/en-US/flavors/flavor-profiles.ftl | 2 + .../Locale/en-US/reagents/meta/cleaning.ftl | 6 ++ .../en-US/reagents/meta/physical-desc.ftl | 1 + .../Entities/Markers/Spawners/Random/soap.yml | 2 +- .../Consumable/Drinks/drinks_bottles.yml | 2 +- .../Objects/Consumable/Drinks/drinks_cans.yml | 2 +- .../Objects/Consumable/Drinks/drinks_cups.yml | 12 +-- .../Consumable/Drinks/drinks_flasks.yml | 2 +- .../Consumable/Food/Containers/condiments.yml | 2 +- .../Objects/Consumable/Food/ingredients.yml | 2 +- .../Objects/Specific/Janitorial/soap.yml | 87 ++++++++++++++++-- .../Objects/Specific/Janitorial/spray.yml | 2 +- .../Objects/Specific/Medical/hypospray.yml | 2 +- .../Objects/Specific/chemistry-bottles.yml | 2 +- .../Entities/Objects/Specific/chemistry.yml | 2 +- Resources/Prototypes/Flavors/flavors.yml | 14 ++- Resources/Prototypes/Reagents/cleaning.yml | 44 +++++++++ .../Prototypes/Recipes/Reactions/cleaning.yml | 10 ++ .../Specific/Janitorial/soap.rsi/deluxe-1.png | Bin 0 -> 274 bytes .../Specific/Janitorial/soap.rsi/deluxe-2.png | Bin 0 -> 312 bytes .../Specific/Janitorial/soap.rsi/deluxe-3.png | Bin 0 -> 342 bytes .../Specific/Janitorial/soap.rsi/deluxe-4.png | Bin 0 -> 357 bytes .../Specific/Janitorial/soap.rsi/deluxe.png | Bin 573 -> 0 bytes .../Specific/Janitorial/soap.rsi/gibs-1.png | Bin 0 -> 279 bytes .../Specific/Janitorial/soap.rsi/gibs-2.png | Bin 0 -> 316 bytes .../Specific/Janitorial/soap.rsi/gibs-3.png | Bin 0 -> 352 bytes .../Specific/Janitorial/soap.rsi/gibs-4.png | Bin 0 -> 372 bytes .../Specific/Janitorial/soap.rsi/gibs.png | Bin 773 -> 0 bytes .../Specific/Janitorial/soap.rsi/meta.json | 66 +++++++++++-- .../Specific/Janitorial/soap.rsi/nt-1.png | Bin 0 -> 266 bytes .../Specific/Janitorial/soap.rsi/nt-2.png | Bin 0 -> 303 bytes .../Specific/Janitorial/soap.rsi/nt-3.png | Bin 0 -> 334 bytes .../Specific/Janitorial/soap.rsi/nt-4.png | Bin 0 -> 350 bytes .../Specific/Janitorial/soap.rsi/nt.png | Bin 630 -> 0 bytes .../Specific/Janitorial/soap.rsi/omega-1.png | Bin 0 -> 267 bytes .../Specific/Janitorial/soap.rsi/omega-2.png | Bin 0 -> 356 bytes .../Specific/Janitorial/soap.rsi/omega-3.png | Bin 0 -> 415 bytes .../soap.rsi/{omega.png => omega-4.png} | Bin .../Specific/Janitorial/soap.rsi/soap-1.png | Bin 0 -> 266 bytes .../Specific/Janitorial/soap.rsi/soap-2.png | Bin 0 -> 297 bytes .../Specific/Janitorial/soap.rsi/soap-3.png | Bin 0 -> 337 bytes .../Specific/Janitorial/soap.rsi/soap-4.png | Bin 0 -> 358 bytes .../Specific/Janitorial/soap.rsi/soap.png | Bin 688 -> 0 bytes .../Specific/Janitorial/soap.rsi/syndie-1.png | Bin 0 -> 256 bytes .../Specific/Janitorial/soap.rsi/syndie-2.png | Bin 0 -> 287 bytes .../Specific/Janitorial/soap.rsi/syndie-3.png | Bin 0 -> 307 bytes .../Specific/Janitorial/soap.rsi/syndie-4.png | Bin 0 -> 317 bytes .../Specific/Janitorial/soap.rsi/syndie.png | Bin 470 -> 0 bytes 57 files changed, 415 insertions(+), 78 deletions(-) create mode 100644 Content.Server/Chemistry/Components/DeleteOnSolutionEmptyComponent.cs create mode 100644 Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs rename Content.Server/Nutrition/Components/{TrashOnEmptyComponent.cs => TrashOnSolutionEmptyComponent.cs} (86%) rename Content.Server/Nutrition/EntitySystems/{TrashOnEmptySystem.cs => TrashOnSolutionEmptySystem.cs} (65%) create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-3.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-4.png delete mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-3.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-4.png delete mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-3.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-4.png delete mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-3.png rename Resources/Textures/Objects/Specific/Janitorial/soap.rsi/{omega.png => omega-4.png} (100%) create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-3.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-4.png delete mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-1.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-2.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-3.png create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-4.png delete mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie.png diff --git a/Content.Server/Chemistry/Components/DeleteOnSolutionEmptyComponent.cs b/Content.Server/Chemistry/Components/DeleteOnSolutionEmptyComponent.cs new file mode 100644 index 0000000000..e53d10b55a --- /dev/null +++ b/Content.Server/Chemistry/Components/DeleteOnSolutionEmptyComponent.cs @@ -0,0 +1,15 @@ +namespace Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent +{ + /// + /// Component that removes an item when a specific solution in it becomes empty. + /// + [RegisterComponent] + public sealed partial class DeleteOnSolutionEmptyComponent : Component + { + /// + /// The name of the solution of which to check emptiness + /// + [DataField("solution")] + public string Solution = string.Empty; + } +} diff --git a/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs b/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs new file mode 100644 index 0000000000..fd7933e66a --- /dev/null +++ b/Content.Server/Chemistry/EntitySystems/DeleteOnSolutionEmptySystem.cs @@ -0,0 +1,38 @@ +using Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.EntitySystems; + +namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem +{ + public sealed class DeleteOnSolutionEmptySystem : EntitySystem + { + [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnSolutionChange); + } + + public void OnStartup(EntityUid uid, DeleteOnSolutionEmptyComponent component, ComponentStartup args) + { + CheckSolutions(uid, component); + } + + public void OnSolutionChange(EntityUid uid, DeleteOnSolutionEmptyComponent component, SolutionChangedEvent args) + { + CheckSolutions(uid, component); + } + + public void CheckSolutions(EntityUid uid, DeleteOnSolutionEmptyComponent component) + { + if (!EntityManager.HasComponent(uid)) + return; + + if (_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution)) + if (solution.Volume <= 0) + EntityManager.QueueDeleteEntity(uid); + } + } +} diff --git a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs index b5d5862e6c..c23956760a 100644 --- a/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanDecalsReaction.cs @@ -44,11 +44,11 @@ public sealed partial class CleanDecalsReaction : ITileReaction if (!decal.Decal.Cleanable) continue; + if (amount + CleanCost > reactVolume) + break; + decalSystem.RemoveDecal(tile.GridUid, decal.Index, decalGrid); amount += CleanCost; - - if (amount > reactVolume) - break; } return amount; diff --git a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs index facc39f146..7483199bc6 100644 --- a/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs +++ b/Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs @@ -1,7 +1,6 @@ using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using Content.Shared.Fluids; using Content.Shared.Fluids.Components; @@ -9,6 +8,7 @@ using Content.Shared.Interaction; using Content.Shared.Timing; using Content.Shared.Weapons.Melee; using Robust.Server.GameObjects; +using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -17,6 +17,7 @@ namespace Content.Server.Fluids.EntitySystems; /// public sealed class AbsorbentSystem : SharedAbsorbentSystem { + [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly PopupSystem _popups = default!; @@ -55,13 +56,13 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem var oldProgress = component.Progress.ShallowClone(); component.Progress.Clear(); - var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagent); + var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); if (water > FixedPoint2.Zero) { - component.Progress[_prototype.Index(PuddleSystem.EvaporationReagent).SubstanceColor] = water.Float(); + component.Progress[solution.GetColorWithOnly(_prototype, PuddleSystem.EvaporationReagents)] = water.Float(); } - var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagent); + var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagents); var other = (solution.Volume - water).Float(); if (other > 0f) @@ -140,7 +141,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem // Remove the non-water reagents. // Remove water on target // Then do the transfer. - var nonWater = absorberSoln.SplitSolutionWithout(component.PickupAmount, PuddleSystem.EvaporationReagent); + var nonWater = absorberSoln.SplitSolutionWithout(component.PickupAmount, PuddleSystem.EvaporationReagents); _solutionContainerSystem.UpdateChemicals(used, absorberSoln, true); if (nonWater.Volume == FixedPoint2.Zero && absorberSoln.AvailableVolume == FixedPoint2.Zero) @@ -153,18 +154,16 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem component.PickupAmount : absorberSoln.AvailableVolume; - var water = refillableSolution.RemoveReagent(PuddleSystem.EvaporationReagent, transferAmount); + var water = refillableSolution.SplitSolutionWithOnly(transferAmount, PuddleSystem.EvaporationReagents); _solutionContainerSystem.UpdateChemicals(target, refillableSolution); - if (water == FixedPoint2.Zero && nonWater.Volume == FixedPoint2.Zero) + if (water.Volume == FixedPoint2.Zero && nonWater.Volume == FixedPoint2.Zero) { _popups.PopupEntity(Loc.GetString("mopping-system-target-container-empty-water", ("target", target)), user, user); return false; } - - - if (water > 0 && !_solutionContainerSystem.TryAddReagent(used, absorberSoln, PuddleSystem.EvaporationReagent, water, - out _)) + + if (water.Volume > 0 && !_solutionContainerSystem.TryAddSolution(used, absorberSoln, water)) { _popups.PopupEntity(Loc.GetString("mopping-system-full", ("used", used)), used, user); } @@ -217,18 +216,18 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem if (!TryComp(target, out PuddleComponent? puddle)) return false; - if (!_solutionSystem.TryGetSolution(target, puddle.SolutionName, out var puddleSolution) || puddleSolution.Volume <= 0) + if (!_solutionSystem.TryGetSolution(target, puddle.SolutionName, out var puddleSoln) || puddleSoln.Volume <= 0) return false; // Check if the puddle has any non-evaporative reagents - if (_puddleSystem.CanFullyEvaporate(puddleSolution)) + if (_puddleSystem.CanFullyEvaporate(puddleSoln)) { _popups.PopupEntity(Loc.GetString("mopping-system-puddle-evaporate", ("target", target)), user, user); return true; } // Check if we have any evaporative reagents on our absorber to transfer - var available = absorberSoln.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagent); + var available = absorberSoln.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents); // No material if (available == FixedPoint2.Zero) @@ -240,14 +239,21 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem var transferMax = absorber.PickupAmount; var transferAmount = available > transferMax ? transferMax : available; - var split = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagent); + var puddleSplit = puddleSoln.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents); + var absorberSplit = absorberSoln.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents); + + // Do tile reactions first + var coordinates = Transform(target).Coordinates; + if (_mapManager.TryGetGrid(coordinates.GetGridUid(EntityManager), out var mapGrid)) + { + _puddleSystem.DoTileReactions(mapGrid.GetTileRef(coordinates), absorberSplit); + } - absorberSoln.RemoveReagent(PuddleSystem.EvaporationReagent, split.Volume); - puddleSolution.AddReagent(PuddleSystem.EvaporationReagent, split.Volume); - absorberSoln.AddSolution(split, _prototype); + puddleSoln.AddSolution(absorberSplit, _prototype); + absorberSoln.AddSolution(puddleSplit, _prototype); _solutionSystem.UpdateChemicals(used, absorberSoln); - _solutionSystem.UpdateChemicals(target, puddleSolution); + _solutionSystem.UpdateChemicals(target, puddleSoln); _audio.PlayPvs(absorber.PickupSound, target); _useDelay.BeginDelay(used); diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs index 1392a23356..d0df5e0505 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs @@ -11,7 +11,12 @@ public sealed partial class PuddleSystem private static readonly TimeSpan EvaporationCooldown = TimeSpan.FromSeconds(1); [ValidatePrototypeId] - public const string EvaporationReagent = "Water"; + private const string Water = "Water"; + + [ValidatePrototypeId] + private const string SoapyWater = "SoapyWater"; + + public static string[] EvaporationReagents = new[] { Water, SoapyWater }; private void OnEvaporationMapInit(EntityUid uid, EvaporationComponent component, MapInitEvent args) { @@ -25,7 +30,7 @@ public sealed partial class PuddleSystem return; } - if (solution.ContainsPrototype(EvaporationReagent)) + if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) { var evaporation = AddComp(uid); evaporation.NextTick = _timing.CurTime + EvaporationCooldown; @@ -51,7 +56,7 @@ public sealed partial class PuddleSystem continue; var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds; - _solutionContainerSystem.RemoveReagent(uid, puddleSolution, EvaporationReagent, reagentTick); + puddleSolution.SplitSolutionWithOnly(reagentTick, EvaporationReagents); // Despawn if we're done if (puddleSolution.Volume == FixedPoint2.Zero) @@ -65,6 +70,6 @@ public sealed partial class PuddleSystem public bool CanFullyEvaporate(Solution solution) { - return solution.Contents.Count == 1 && solution.ContainsPrototype(EvaporationReagent); + return solution.GetTotalPrototypeQuantity(EvaporationReagents) == solution.Volume; } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 886cb9eff1..9785fd8365 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -373,7 +373,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating")); } - else if (solution?.ContainsPrototype(EvaporationReagent) == true) + else if (solution?.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero) { args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-partial")); } @@ -602,16 +602,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem if (tileReact) { // First, do all tile reactions - for (var i = solution.Contents.Count - 1; i >= 0; i--) - { - var (reagent, quantity) = solution.Contents[i]; - var proto = _prototypeManager.Index(reagent.Prototype); - var removed = proto.ReactionTile(tileRef, quantity); - if (removed <= FixedPoint2.Zero) - continue; - - solution.RemoveReagent(reagent, removed); - } + DoTileReactions(tileRef, solution); } // Tile reactions used up everything. @@ -660,6 +651,21 @@ public sealed partial class PuddleSystem : SharedPuddleSystem #endregion + public void DoTileReactions(TileRef tileRef, Solution solution) + { + for (var i = solution.Contents.Count - 1; i >= 0; i--) + { + + var (reagent, quantity) = solution.Contents[i]; + var proto = _prototypeManager.Index(reagent.Prototype); + var removed = proto.ReactionTile(tileRef, quantity); + if (removed <= FixedPoint2.Zero) + continue; + + solution.RemoveReagent(reagent, removed); + } + } + /// /// Tries to get the relevant puddle entity for a tile. /// diff --git a/Content.Server/Nutrition/Components/TrashOnEmptyComponent.cs b/Content.Server/Nutrition/Components/TrashOnSolutionEmptyComponent.cs similarity index 86% rename from Content.Server/Nutrition/Components/TrashOnEmptyComponent.cs rename to Content.Server/Nutrition/Components/TrashOnSolutionEmptyComponent.cs index b36bd172bf..4fac2a362b 100644 --- a/Content.Server/Nutrition/Components/TrashOnEmptyComponent.cs +++ b/Content.Server/Nutrition/Components/TrashOnSolutionEmptyComponent.cs @@ -5,7 +5,7 @@ namespace Content.Server.Nutrition.Components /// Used for things like used ketchup packets or used syringes. /// [RegisterComponent] - public sealed partial class TrashOnEmptyComponent : Component + public sealed partial class TrashOnSolutionEmptyComponent : Component { /// /// The name of the solution of which to check emptiness diff --git a/Content.Server/Nutrition/EntitySystems/TrashOnEmptySystem.cs b/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs similarity index 65% rename from Content.Server/Nutrition/EntitySystems/TrashOnEmptySystem.cs rename to Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs index e702247900..22360b6492 100644 --- a/Content.Server/Nutrition/EntitySystems/TrashOnEmptySystem.cs +++ b/Content.Server/Nutrition/EntitySystems/TrashOnSolutionEmptySystem.cs @@ -1,4 +1,3 @@ -using Content.Server.Chemistry.EntitySystems; using Content.Server.Nutrition.Components; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; @@ -7,7 +6,7 @@ using Content.Shared.Tag; namespace Content.Server.Nutrition.EntitySystems { - public sealed class TrashOnEmptySystem : EntitySystem + public sealed class TrashOnSolutionEmptySystem : EntitySystem { [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; @@ -15,21 +14,21 @@ namespace Content.Server.Nutrition.EntitySystems public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnSolutionChange); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnSolutionChange); } - public void OnStartup(EntityUid uid, TrashOnEmptyComponent component, ComponentStartup args) + public void OnStartup(EntityUid uid, TrashOnSolutionEmptyComponent component, ComponentStartup args) { CheckSolutions(component); } - public void OnSolutionChange(EntityUid uid, TrashOnEmptyComponent component, SolutionChangedEvent args) + public void OnSolutionChange(EntityUid uid, TrashOnSolutionEmptyComponent component, SolutionChangedEvent args) { CheckSolutions(component); } - public void CheckSolutions(TrashOnEmptyComponent component) + public void CheckSolutions(TrashOnSolutionEmptyComponent component) { if (!EntityManager.HasComponent((component).Owner)) return; @@ -38,7 +37,7 @@ namespace Content.Server.Nutrition.EntitySystems UpdateTags(component, solution); } - public void UpdateTags(TrashOnEmptyComponent component, Solution solution) + public void UpdateTags(TrashOnSolutionEmptyComponent component, Solution solution) { if (solution.Volume <= 0) { diff --git a/Content.Shared/Chemistry/Components/Solution.cs b/Content.Shared/Chemistry/Components/Solution.cs index 65fdcd62dd..d793d3f70c 100644 --- a/Content.Shared/Chemistry/Components/Solution.cs +++ b/Content.Shared/Chemistry/Components/Solution.cs @@ -289,12 +289,12 @@ namespace Content.Shared.Chemistry.Components /// If you only want the volume of a single reagent, use /// [Pure] - public FixedPoint2 GetTotalPrototypeQuantity(string prototype) + public FixedPoint2 GetTotalPrototypeQuantity(params string[] prototypes) { var total = FixedPoint2.Zero; foreach (var (reagent, quantity) in Contents) { - if (reagent.Prototype == prototype) + if (prototypes.Contains(reagent.Prototype)) total += quantity; } @@ -546,6 +546,34 @@ namespace Content.Shared.Chemistry.Components return sol; } + /// + /// Splits a solution without the specified reagent prototypes. + /// + public Solution SplitSolutionWithOnly(FixedPoint2 toTake, params string[] includedPrototypes) + { + // First remove the non-included prototypes + List excluded = new(); + for (var i = Contents.Count - 1; i >= 0; i--) + { + if (includedPrototypes.Contains(Contents[i].Reagent.Prototype)) + continue; + + excluded.Add(Contents[i]); + RemoveReagent(Contents[i]); + } + + // Then split the solution + var sol = SplitSolution(toTake); + + // Then re-add the excluded reagents to the original solution. + foreach (var reagent in excluded) + { + AddReagent(reagent); + } + + return sol; + } + public Solution SplitSolution(FixedPoint2 toTake) { if (toTake <= FixedPoint2.Zero) @@ -756,6 +784,44 @@ namespace Content.Shared.Chemistry.Components return GetColorWithout(protoMan); } + public Color GetColorWithOnly(IPrototypeManager? protoMan, params string[] included) + { + if (Volume == FixedPoint2.Zero) + { + return Color.Transparent; + } + + IoCManager.Resolve(ref protoMan); + + Color mixColor = default; + var runningTotalQuantity = FixedPoint2.New(0); + bool first = true; + + foreach (var (reagent, quantity) in Contents) + { + if (!included.Contains(reagent.Prototype)) + continue; + + runningTotalQuantity += quantity; + + if (!protoMan.TryIndex(reagent.Prototype, out ReagentPrototype? proto)) + { + continue; + } + + if (first) + { + first = false; + mixColor = proto.SubstanceColor; + continue; + } + + var interpolateValue = quantity.Float() / runningTotalQuantity.Float(); + mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, interpolateValue); + } + return mixColor; + } + #region Enumeration public IEnumerator GetEnumerator() diff --git a/Resources/Locale/en-US/flavors/flavor-profiles.ftl b/Resources/Locale/en-US/flavors/flavor-profiles.ftl index 2a0c39a0e4..a17b9019d5 100644 --- a/Resources/Locale/en-US/flavors/flavor-profiles.ftl +++ b/Resources/Locale/en-US/flavors/flavor-profiles.ftl @@ -43,6 +43,7 @@ flavor-base-piquant = piquant flavor-base-sharp = sharp flavor-base-syrupy = syrupy flavor-base-spaceshroom = mysterious +flavor-base-clean = clean # lmao flavor-base-terrible = terrible @@ -213,3 +214,4 @@ flavor-complex-carpet = like a handful of fur flavor-complex-bee = unbeelievable flavor-complex-sax = like jazz flavor-complex-bottledlightning = like lightning in a bottle +flavor-complex-punishment = like punishment diff --git a/Resources/Locale/en-US/reagents/meta/cleaning.ftl b/Resources/Locale/en-US/reagents/meta/cleaning.ftl index 4c1ec87ddd..e770594956 100644 --- a/Resources/Locale/en-US/reagents/meta/cleaning.ftl +++ b/Resources/Locale/en-US/reagents/meta/cleaning.ftl @@ -4,6 +4,12 @@ reagent-desc-bleach = Heavy duty cleaner that can clean tiles the same as Space reagent-name-space-cleaner = space cleaner reagent-desc-space-cleaner = This is able to clean almost all surfaces of almost anything that may dirty them. The janitor is likely to appreciate refills. +reagent-name-soap = soap +reagent-desc-soap = Soap can be used to make soapy water. + +reagent-name-soapy-water = soapy water +reagent-desc-soapy-water = It's just soap and water. Good for cleaning gunk off of surfaces and also slippier than regular water. + reagent-name-space-lube = space lube reagent-desc-space-lube = Space Lube is a high performance lubricant intended for maintenance of extremely complex mechanical equipment (and certainly not used to make people slip). diff --git a/Resources/Locale/en-US/reagents/meta/physical-desc.ftl b/Resources/Locale/en-US/reagents/meta/physical-desc.ftl index 9093e54810..14e6e18239 100644 --- a/Resources/Locale/en-US/reagents/meta/physical-desc.ftl +++ b/Resources/Locale/en-US/reagents/meta/physical-desc.ftl @@ -63,6 +63,7 @@ reagent-physical-desc-sticky = sticky reagent-physical-desc-bubbly = bubbly reagent-physical-desc-rocky = rocky reagent-physical-desc-lemony-fresh = lemony fresh +reagent-physical-desc-soapy = soapy reagent-physical-desc-crisp = crisp reagent-physical-desc-citric = citric reagent-physical-desc-acidic = acidic diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/soap.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/soap.yml index e06a2108d8..d3283522b2 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/soap.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/soap.yml @@ -7,7 +7,7 @@ layers: - state: red - sprite: Objects/Specific/Janitorial/soap.rsi - state: soap + state: soap-4 - type: RandomSpawner prototypes: - Soap diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml index 2fa487fa2c..d6a0570e28 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml @@ -43,7 +43,7 @@ qualities: - Rolling speed: 0.75 # not as good as a rolling pin but does the job - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml index 11228d0ed6..3595d93ea0 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml @@ -54,7 +54,7 @@ speed: 0.25 # its small so takes longer to roll the entire dough flat - type: ItemCooldown - type: SpaceGarbage - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: PhysicalComposition materialComposition: diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml index f9e41054f8..828ad3cca6 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml @@ -203,7 +203,7 @@ - type: SolutionContainerVisuals maxFillLevels: 4 fillBaseName: icon- - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity @@ -221,7 +221,7 @@ - type: Sprite sprite: Objects/Consumable/Drinks/cafe_latte.rsi - type: Appearance - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity @@ -246,7 +246,7 @@ - type: SolutionContainerVisuals maxFillLevels: 4 fillBaseName: icon- - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity @@ -271,7 +271,7 @@ - type: SolutionContainerVisuals maxFillLevels: 4 fillBaseName: icon- - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity @@ -291,7 +291,7 @@ state: icon - type: Item sprite: Objects/Consumable/Drinks/lean.rsi - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity @@ -317,5 +317,5 @@ - type: SolutionContainerVisuals maxFillLevels: 1 fillBaseName: icon- - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml index c3d51b9d7e..cc8aba31e9 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml @@ -31,7 +31,7 @@ reagents: - ReagentId: Water Quantity: 50 - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml index 03118bbf28..69e96e2981 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml @@ -13,7 +13,7 @@ sprite: Objects/Consumable/Food/condiments.rsi - type: Icon sprite: Objects/Consumable/Food/condiments.rsi - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: food - type: SpaceGarbage - type: StaticPrice diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml index 166a73e43e..0acb6ac0ec 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/ingredients.yml @@ -32,7 +32,7 @@ damageContainer: Inorganic - type: Spillable solution: food - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: food - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml index 336a2a963f..07ca776207 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml @@ -9,7 +9,14 @@ - Soap - type: Sprite sprite: Objects/Specific/Janitorial/soap.rsi - state: soap + layers: + - state: soap-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + maxFillLevels: 4 + fillBaseName: soap- + changeColor: false + - type: Appearance - type: Item sprite: Objects/Specific/Janitorial/soap.rsi - type: Slippery @@ -37,6 +44,29 @@ density: 10 mask: - ItemMask + - type: SolutionContainerManager + solutions: + soap: + maxVol: 50 + reagents: + - ReagentId: SoapReagent + Quantity: 50 + - type: SolutionTransfer + transferAmount: 10 + minTransferAmount: 1 + maxTransferAmount: 25 + canReceive: false + canChangeTransferAmount: true + - type: DrainableSolution + solution: soap + - type: DeleteOnSolutionEmpty + solution: soap + - type: FlavorProfile + flavors: + - clean + - type: Food + solution: soap + - type: entity name: soap @@ -45,9 +75,20 @@ description: A Nanotrasen brand bar of soap. Smells of plasma. components: - type: Sprite - state: nt + layers: + - state: nt-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + fillBaseName: nt- - type: Item heldPrefix: nt + - type: SolutionContainerManager + solutions: + soap: + maxVol: 100 + reagents: + - ReagentId: SoapReagent + Quantity: 100 - type: entity name: soap @@ -56,7 +97,11 @@ description: A deluxe Waffle Co. brand bar of soap. Smells of condoms. components: - type: Sprite - state: deluxe + layers: + - state: deluxe-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + fillBaseName: deluxe- - type: Item heldPrefix: deluxe @@ -67,12 +112,20 @@ description: An untrustworthy bar of soap. Smells of fear. components: - type: Sprite - state: syndie + layers: + - state: syndie-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + fillBaseName: syndie- - type: Slippery paralyzeTime: 5 launchForwardsMultiplier: 2.5 - type: Item heldPrefix: syndie + - type: FlavorProfile + flavors: + - clean + - punishment - type: entity name: soap @@ -81,9 +134,20 @@ description: A homemade bar of soap. Smells of... well.... components: - type: Sprite - state: gibs + layers: + - state: gibs-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + fillBaseName: gibs- + - type: Slippery + paralyzeTime: 2 + - type: StepTrigger - type: Item heldPrefix: gibs + - type: FlavorProfile + flavors: + - clean + - meaty - type: entity name: omega soap @@ -92,9 +156,20 @@ description: The most advanced soap known to mankind. Smells of bluespace. components: - type: Sprite - state: omega + layers: + - state: omega-4 + map: ["enum.SolutionContainerLayers.Fill"] + - type: SolutionContainerVisuals + fillBaseName: omega- - type: Slippery paralyzeTime: 7 launchForwardsMultiplier: 3 - type: Item heldPrefix: omega + - type: SolutionContainerManager + solutions: + soap: + maxVol: 240 #In the Greek alphabet, Omega is the 24th letter + reagents: + - ReagentId: SoapReagent + Quantity: 240 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml index f88dc4f6b2..ed55afea1d 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml @@ -30,7 +30,7 @@ sprayVelocity: 2 spraySound: path: /Audio/Effects/spray2.ogg - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: spray - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml index 709bc751a4..47d3c77024 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml @@ -125,7 +125,7 @@ - type: SpaceGarbage - type: StaticPrice price: 75 # These are limited supply items. - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: pen - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml index b869a2008f..59bf0927aa 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml @@ -56,7 +56,7 @@ damage: types: Blunt: 0 - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: drink - type: StaticPrice price: 0 diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index f3ed4f2284..d8924895df 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -330,7 +330,7 @@ solution: injector - type: Spillable solution: injector - - type: TrashOnEmpty + - type: TrashOnSolutionEmpty solution: injector - type: Appearance - type: SolutionContainerVisuals diff --git a/Resources/Prototypes/Flavors/flavors.yml b/Resources/Prototypes/Flavors/flavors.yml index ba8f2c3476..c4c518ad89 100644 --- a/Resources/Prototypes/Flavors/flavors.yml +++ b/Resources/Prototypes/Flavors/flavors.yml @@ -169,6 +169,11 @@ flavorType: Base description: flavor-base-syrupy +- type: flavor + id: clean + flavorType: Base + description: flavor-base-clean + - type: flavor id: nothing flavorType: Complex @@ -838,7 +843,7 @@ id: spaceshroomcooked flavorType: Complex description: flavor-complex-spaceshroom-cooked - + - type: flavor id: lostfriendship flavorType: Complex @@ -847,4 +852,9 @@ - type: flavor id: pumpkin flavorType: Complex - description: flavor-complex-pumpkin \ No newline at end of file + description: flavor-complex-pumpkin + +- type: flavor + id: punishment + flavorType: Complex + description: flavor-complex-punishment diff --git a/Resources/Prototypes/Reagents/cleaning.yml b/Resources/Prototypes/Reagents/cleaning.yml index c1f8c2b352..e4ea12307d 100644 --- a/Resources/Prototypes/Reagents/cleaning.yml +++ b/Resources/Prototypes/Reagents/cleaning.yml @@ -38,6 +38,50 @@ - !type:CleanTileReaction {} - !type:CleanDecalsReaction {} +- type: reagent + id: SoapReagent + name: reagent-name-soap + desc: reagent-desc-soap + physicalDesc: reagent-physical-desc-soapy + flavor: clean + color: "#c8dfc9" + recognizable: true + boilingPoint: 100.0 + meltingPoint: 60.0 + metabolisms: + Food: + effects: + - !type:ChemVomit + Drink: + effects: + - !type:ChemVomit + +- type: reagent + id: SoapyWater + parent: Water + name: reagent-name-soapy-water + desc: reagent-desc-soapy-water + physicalDesc: reagent-physical-desc-soapy + flavor: clean + color: "#9ec8dc" + recognizable: true + metabolisms: + Drink: + effects: + - !type:SatiateThirst + factor: 3 + - !type:ChemVomit + thirstAmount: -10.0 + hungerAmount: -10.0 + plantMetabolism: + - !type:PlantAdjustWater + amount: .8 + tileReactions: + - !type:CleanDecalsReaction + cleanCost: 5 + - !type:ExtinguishTileReaction { } + - !type:SpillIfPuddlePresentTileReaction { } + - type: reagent id: SpaceLube name: reagent-name-space-lube diff --git a/Resources/Prototypes/Recipes/Reactions/cleaning.yml b/Resources/Prototypes/Recipes/Reactions/cleaning.yml index 1c68aeb2e3..b8cda27a8b 100644 --- a/Resources/Prototypes/Recipes/Reactions/cleaning.yml +++ b/Resources/Prototypes/Recipes/Reactions/cleaning.yml @@ -20,6 +20,16 @@ products: SpaceCleaner: 2 +- type: reaction + id: SoapyWater + reactants: + Water: + amount: 3 + SoapReagent: + amount: 1 + products: + SoapyWater: 4 + - type: reaction id: SpaceLube impact: Medium diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-1.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-1.png new file mode 100644 index 0000000000000000000000000000000000000000..74e3c29d2238f8eac6c830c273b3a7b7446ecf34 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijS1AIbUJF=pFe);(P{J~4>=Nz2Xx}~?`!~JW^o3iUu!;dcN1**C!@NpH8 z;w}mD3;quW3|{_>pMb)g1s;*b3=DjSK$uZf!>a)(nC$7|7-Hf7_Cg@v0ibgN7WmEm zZvUYqV^hDVenS0kCdSO!G7lCyq&YXv5@vH@G4oB9|4nJ@ErnSMo|r~2B2W0r;B5Vh5y?LoO}lq zI9MF};{N^LE4t7#+T^c;x|&=hUZ$ADq?t;r_KPy%kf7B9|4nJ@ErnSMo|r~2B6@4PZ!4!3;(whc=--1 zaI`)>ey!}@|2@?ly5~}Fvi@>vI>Fwt^#4WX9cl}7x}wX~lBPxWsR)!#*d@Fzg(+w? z$Hot8Wovc|b4Jt$rQVnk5Z<73f0pDeg(9WKWam=L+mTZ|1w9Ws3omevPh$DBCg~zm z&q0MpoXJOcj+pBIWZ589#@r~frf%)a`Nr8MI~X_h@7uN8Zok#4G}l9S^KBbeem8$C WqbkJy*JwG=sSKX3elF{r5}E*1h>2tX literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-4.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe-4.png new file mode 100644 index 0000000000000000000000000000000000000000..a67f6e50c7aa2d29b3573f48fb4009e9f31f96e6 GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCilo1AIbUJF=oa+`snx{J~4>=hUZ$Z|SW#IIH#Nmyc76o-U3d7XEK1aPu8j z;Bj{LxqQCr|L1d^H;;t*?six^#o;dpi}n8(Y)ixw!g-w+n=XGaL&e4U^TyRzras8L zc0J*=kl=w+TD%WT!~|I_depXld)G7Txbz7o#`w$kxA9DS=;gws>oC`AqD1%#WfqZz-fACTaz9YrFVdQ&MBb@02{!SP5=M^ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/deluxe.png deleted file mode 100644 index f5e0a9c9517492685c3e79420cb75635d034d1a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 573 zcmV-D0>b@?P)(Ql)lV{0xgCOD}NGS-qg^H7li|E*; zaO1gl@CL~Vp>RVRxQZDfgi;6j!k6Uhfq$S&o+;%0-uHRlC*S)9DpaUYVa>R7QLyiI zmj8?BiT_^9b@d|R?&D`9-=kbC3Il}g5QV{?YFO%olmzs>&QcN&UcOjS>qz@HNf&Hh zyP}P?+`UYQDk7&wl269R3`a-Yys-m-VHnvNQ&<4h-8SdJICEt4x?nOs24Egdv$OMP zN*u?0`8J{D?jdZ4cW>WhPLv!_EjJ7!BUDj$+w=|(0O)!i1K-b{qcF(j=<-!$4ivk; z(`;Z03t>CdoF-pKA9Cc|TN?n(e*DZmOA*Dqc{Jto_@v~*_iht~ z0bS1{Nf(@+&9G`Fr)M*gbV1ki0JM3lpdCXgMiy!8-lDOakI8SZlFJ5kdGcZwQJMld zF6up41z|f3d_PC7gZlkt?UhrYE}1xvOU2}9nZnAPkmu$5V#jJ7VLPaMq_iIUUT68> z;Ul6jU^vn*oWFstd#wN|0zeA+t@@wVaMnz56|engRG~tJ3TwwNtIrqFysn7}00000 LNkvXXu0mjfo`eo? diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-1.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1afa3da7c5a51722c97c7306cd49511a440cf411 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijS1AIbUrtp?Jp|Yo|t&8BIdTX_&!$?psN1h59MqW_)Uak-|U(OdcE%Hs#}_8rt_@A>kNL41{}#X2TKC7_)Qp00i_ I>zopr04D!tr2qf` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-2.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-2.png new file mode 100644 index 0000000000000000000000000000000000000000..782c835f847867fb7e8065811e82c348201b5f47 GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijS1AIbUrFr%o3R|8P6*VDx@#KQmW1V=s=MGh9poT{V$ z?JELpa+=cY4QdUuBAJZ-Jz+IscPRU&H~qfNs$8{+TyMTB`94o&6>)3$p;BldVSV$3 zUiyJ$vP+URwJxkRR&koHv4zP?NNBzSkNN?I_Q;STLyylN7VA6T5o5TRB=Ta<)}3i4 v){*id4=!#~ua*2Nl=96{@B5wuXC&fh`6zRRMTRQ?9me44>gTe~DWM4f6IO6P literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-3.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-3.png new file mode 100644 index 0000000000000000000000000000000000000000..8de6e87bab1bec9a74490f0d55126d98df5b4c6e GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijS1AIbUrQ}4eYo~|>9ayK`JMSdZtQE7kTw+{9 z;<_~y8ZK}&PriIGK88^vLFa49^5_#=G!6(F=j3?_XEZd6T{!T~K;V%=j#7yQ^Fy`F z*Gh`-<~(_}z(@OxVbi}uwJ#35VNd7~JE!|xW#MxJ8jCf{7ZaL;n;_GjNuuS|a! jYQ1sZ{i=p5g?kuz-Q*w5o6^n(bUcHntDnm{r-UW|L-&k& literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-4.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/gibs-4.png new file mode 100644 index 0000000000000000000000000000000000000000..5347d4d70a1c50d4595be05be9869498493e2618 GIT binary patch literal 372 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijS1AIbUr)d6mc~ujkz0L60nvYkUu5IcyeznT-)yC&$8{enB zd&suAWNvP}3o~;Hn}a&D=DFp4yYd(C%xGX<7%dn^EaJ^b ze^K1qprE?Q--l1UVP<0L?6fUDshNNmOs$22OFqkSFZ`bG^L<_p`t<43=aF&T_i}S8 zX#TH2Ye)H>v7X)+_|2!!T%Vtd=e0rskE(WDAIc_CvzL%N0yd|DrWN?>`*#lx@HZw_ zR)r9|hz>PY@XFyK=~$HKFJ1!h%;N#TRm=k5)^pUg5QY*apNtcnSpvX3-ba!o3?(eS zH!bh5^g;w&N8Q$aUE>qQv)cz2z#+8i|ZR5@t$;NZ?EfVMn`WnNequL zDfdErcdH(Hl)tr3#7R5zOgj3?+=?U|XD3ZFzxqA1$tLh&~en ztnBTKMl=94$w{hIVQxM`aAt|R7Q$7`;u}1}P{NFrPtYVM3zrv6%6^QUFSv?X+Hb=SUAv4&oQ*PdA)#{*+-L{$U9r`>MgEfmbv)|rIr_xam?d=jPY53wj-^!V<(am zy;N!UMls8f8X(^zhHzl*DDOzeqT)rh<>jhSW;CMV7@wuCg@lcJyBXx2Em8a7Kmgz1 z8CQie^3E1|qlsgDmW9g;F%@kbUQ(92LY~YHS)>07(+XE*5l?>&|F;KpjIegcjRBNoUvmqB762d z1y~{gEFs;hfjjHi`sPpT*-EB+6+imVs863heIA|P@&->C1s`j*00000NkvXXu0mjf D^a5QX diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json index c6cd1086d7..1b0c2eb436 100644 --- a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json @@ -8,22 +8,76 @@ }, "states": [ { - "name": "soap" + "name": "soap-1" }, { - "name": "deluxe" + "name": "soap-2" }, { - "name": "gibs" + "name": "soap-3" }, { - "name": "nt" + "name": "soap-4" }, { - "name": "omega" + "name": "deluxe-1" }, { - "name": "syndie" + "name": "deluxe-2" + }, + { + "name": "deluxe-3" + }, + { + "name": "deluxe-4" + }, + { + "name": "gibs-1" + }, + { + "name": "gibs-2" + }, + { + "name": "gibs-3" + }, + { + "name": "gibs-4" + }, + { + "name": "nt-1" + }, + { + "name": "nt-2" + }, + { + "name": "nt-3" + }, + { + "name": "nt-4" + }, + { + "name": "omega-1" + }, + { + "name": "omega-2" + }, + { + "name": "omega-3" + }, + { + "name": "omega-4" + }, + { + "name": "syndie-1" + }, + { + "name": "syndie-2" + }, + { + "name": "syndie-3" + }, + { + "name": "syndie-4" }, { "name": "inhand-left", diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-1.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a75d5dffab03ccb56143391c88af2cfbf0060867 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCil21AIbUvooq5+<$)l+^r4k4$PUkw!de=moMK^lS+W{|7Jy(11ZjuAiv=M zP{0uEUm*k%EbxddW?C5nk3xX8%8M9d+Aq^w!l+M`RahEagrM8eR=R!R4MVjv*HQZzlxu9X8-_?&e+d-TtFb$E+=v zws2pOpD?Z6+2WjiRpT`_8UC~T=X$XT#AKx~ZubA==OQZJaDv0_k`UXm<(;e%yYxKF z^*bw=0$3CKS`MGcNGc9EyV5~*nVOx+3#KdYmc^Oxe4$o*pD|dO>0KoIDTnYk3~kk| zvz)VE{Cam_)|#ekOTXLAzj^wmDUV*lo1NurElT3QzPV+}J-6;PtJm|NtX0yI-cyzw RP60ZZ!PC{xWt~$(695|Vg7^Rc literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-4.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/nt-4.png new file mode 100644 index 0000000000000000000000000000000000000000..bdce46f675a6706aa70344d20934ad6b66f28ea4 GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCil21AIbUvooq5+<$)l+^r4k4x}cP^!F^7Gjr{iFW-RjT_>Zr0V&RsAiv=M zP{0uEUm*k%EbxddW?=YyQOR?(|1;X`03Tr^YiC*ji-ks=Uh*cbq@`9EsfY+c||da zfj!`2C)3<%A|3n&oJw4R?H|9D9FAmRRN;tGp2jF#aPdXu!i$U#W=CHBkT11qfzY{d z1q&6einPzo=~Dz07O7eD{yrcjB7Q)#;OM!G4SHv)C5tJP)&6o$Wq;!c7%vzg6ILTFZjh{Pu_1HOUaCW|1VHV~u~6tie)pp;T*lMp0}ZVG*a z!k8zBh(cDH(2fw?s0?LxZtSAm%ZyGF0s%MkZ)UjnocaI%oO|v-h!7z{EEy{gZI%kv z*>e${U7Q4Ry?BWD^_y2Xjw{y(_7L6Be9tFf79?arK&eoj3F40*zCMM3>2yjY5((Vf zGfgSPE5fHnkas&hnwG`p=1Tyg(I^1fT!tUte*&PWamJ$w*<6Mz>zbX!7K*yYZU3HF zEQ;f}4D2D}(FE6Zxx4GLXPW4S#%1H1ti(bEyd@XpiW(wbO1KsPkfW{TwQw$Ii1X#+)#`=gF%*tOl2@4HxU^e0QUrja zuA!)LSwY><7V_Jzn?N4fg0qX0m8N9@|3*giOC-i(QJJKuaR&B~TD=0mZU3I}XyS_z z#9|UUowgjsre(<~@SOpnUf}mHTlTKo>G=-Ucr@{?DQcWV!Z07*qoM6N<$f>lu~TL1t6 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-1.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-1.png new file mode 100644 index 0000000000000000000000000000000000000000..173c995dee6c6f774b8c88849569be2e26e573a9 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCil21AIbU85m|7r=5{gotb8QCamEogYnF?v@^!WXMpmzny$|VQk*40e!>5t zfFanwLI@;S;1OBOz`%DHgc*fx+9Hw$jC^3lU+{bss(y1}B+-08=Ls3zTW4%*K{A2+I xj$N^J6N`)1$2Bl?++MM^Xj}Eg$_1OQ@tZ%8<9i$Uc@fY)22WQ%mvv4FO#l-nTcZE~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-2.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/omega-2.png new file mode 100644 index 0000000000000000000000000000000000000000..7f94298ce6d9ea5644920c82a424b9934be2d24e GIT binary patch literal 356 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCikV0(?ST85m}UH5@fgJ0qt$GtKynYtFWyvSSJ^3j-<+8XKQsFrFD)am*uo zPg>d;|B}OgMF*X;ws_?139bg2&JbtG10+RCg8YL2V*&<$|L1~0dCmfl$YKTtzQZ8Q zcszea3Q%yOr;B5Vh5y@$(R|E`9Iktnoz^bZ|Gxja(^gO6Ic3bnb|$AdnU?))cb3p; zF`2o1V{P-<4XGM|C*(V9Bw7!hDKI*?C{VysG-OVBYnh;4!#NS|g*yZO@@~~?I`H<_ zxqyvtIm~xPPqa6(aryDmH07%&%fby`BSl)~Op86EX(`9wBo&~_wAS6${?ttI4EAH6+x3bg*=r{&XS3j3^P61Og;weANDpIkmOAC2(X#^JDl zTRXhJ;dbML&fOjxlRq_x%<28bA(-^VaFxIp9`)EYhyE^f(ii=;)5&4C=oa0oPY%rc zmz-?o$`_pBE;aMzVq1yjlQl%QuoeuN^gQu&X%Q~loCIImptSa^|-%3n0Z&666>B9|9Qe zHSdiCig6ZrL>4nJ@ErnSMo|r~2B2WNr;B5Vh5y?NfqVymP6)^fd|&^#@lC$w?uM_- z!t+_S{+-ONB_we#>gjApnMFYLT&!y0oUCVVG)pXu(r|FsnV!JlIE`(|@vqC6mz^(O x*P#D?zU2Q9UKR;U=kHgi$==Hqoy%=hZC~ps6a@xm5@j!~BB*-uLKLjw` zYu+0P6yq%Lh%9Dc;5!7ujG`J|4M4#*PZ!4!3;(wh0{I#YIGhu;-~BV+c3@x2QSLQb zYTquNIrZxzYY?x3;$1)H9!?3>hoJ|iJF}TutG}yDCdPlCV9z=3^sB# zA2zYgc(vL_ea1z`0IOpUCEXc}a@*n=AM3q8?zjJ?Xlk%v0K>K^u9x}Vb8~1fvPrBz gaXnJJVC`3?xT_LZj^*Ti2D*sB)78&qol`;+0P|;VX8-^I literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-3.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-3.png new file mode 100644 index 0000000000000000000000000000000000000000..cc0c26f4ca3114f5d8fb3766a86bb7a3b0bc81e1 GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCil21AIbUgZsk#+k!s+_;}*}$t9a)(xXRPTF~q|E?F4SV!wNjkpIh(!KeCxqD{y(H zc*cT-C-fP0uFtP%>|*QaSf#Z7!djC9cNVwnyk%H%?`bvX@(PC2f-~(7T{!U}*yXi> za_EAUpMvX|`0hG|6)npuWXKUUx8_uqN-*4hEa=YVi;J22jBgfeOmRr+=kwY4aEVU3h@O1TaS?83{1ORzqg{1%h literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-4.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/soap-4.png new file mode 100644 index 0000000000000000000000000000000000000000..c97059af863aee5179bf0d6d5d9637d3d45b71bb GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCil21AIbU{o8_q`@(L&x^v?G$t9a)(xZl&oF~q|E?Sx37!v-AAtS3(Y^^alnyHr8~X3bzNeP^|G%PV_lN%I7m zg~rCk8UYUXetKyrO*y_f^xe;cpd)Bkc$!ZL3uilkf9WW*2I6H(vTpA{Nk?G z5(*g)5*;04B}%#pibDzkp_bR_J?_Ul*DUv0?%nt2=ktB<-T^LLxNz~nSX$&vmQw@( z1W_>A=d(FmTYXl{XLAUmfU}KbZZB>&ZM^gDGp6@bW*bw9oFcSw zzE+iY9kwprb)+crs8GXwyZjU=dgddiViR3{}^Vh{W;n zpp1&Ti?8p$;Cj?ULCHbYHB{7H6qKB;ASEY=0#+Wc003gXC{$fzpQ5U3>?>I2B~vuJ zEi_68P$U_je(oUT4Wij?L6Kw>lpIsPnJqDuRJ9_>*t^^Z0QR)j2RK)8x|$)h2%U%% zco&b;WyDj@B|u3S)mT|mwE>Ucv^M&zpkl07@xq@GB|_n(m;gEk|4j}|6sr%<<0B{ z6yhxKh%9Dc;5!V$jK}j=qyPmIJzX3_Ed1Y|KgfGPfrr`QIOiMtBF=?D@;h`I_S;!D z)SX}z<=h~}+2bn0@Zd}kV}FpjcE16X8sAkxSn>fgbP2j$%El~L5*>5J+ p9+|IizA3PWZDyYzGvVc5Mx8fe-Y3|KvIw>~~>ADQPl zGFh8R9An>~AjUK)rn2ht34yRx3^L~gLN;(+Je#?gt5>(_pxN;tg#!-tT{>Q87T5`W zUKDB}?Eak-;s165Bi|7P4i>?4zy8bLUzg2ia{UXl zZ1h$mhgH4oagHJf`L3-LyL9KU^2AApPBF{tKIB;@Q2Tt+M5kot?_w1@9)DNc(OMdE z?Deg)LYgJTGR8|Dp6F1DId$$JSLlWVD?eR*v&LXC&*T3akJ>!mdi3DW*>83lbN^{+ s>t@@NeWre0RcdIM!)e>~4#$2leR(9N{bo{DFVJlap00i_>zopr06719{r~^~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-4.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-4.png new file mode 100644 index 0000000000000000000000000000000000000000..a254bef8c3708cb92118cae18418fd301956ba99 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCiji0(?STCptMjIdbIA#*L?Ydb;fGw!jZ*NZOdAuxf5o4cUJ%h)yr9Ps} zG6fk*z7zSVT8rax2KKHmGke`x_64u|8#jP7m9IPRWRNaVS-*4w?pU+XoFO{3P^s)EN@Z+sL9 zbT%Oa0Wyv|D*U}#JzM|)eorU7PbSvAh;t=G7tvEg#rH*lO_t$vJ_i6yJ?~#aOpa}f zpWO}-=kORqDy4E_-~d^k2!W~ZpjNK;(QiV4Ya-L@Aw3kY$gqrKX^~g3^cKa6S4-8#HDyk>f9WnQ4P9t4I%C9qc z9%USN`Y-ue*t)k0AQ8azN|~ww44z|(x%E6#Gv-tL@;@Vo!{K;2e