diff --git a/Content.Client/Fluids/PuddleVisualizer.cs b/Content.Client/Fluids/PuddleVisualizer.cs index 77ac584c69..dd5afc21df 100644 --- a/Content.Client/Fluids/PuddleVisualizer.cs +++ b/Content.Client/Fluids/PuddleVisualizer.cs @@ -49,12 +49,13 @@ namespace Content.Client.Fluids if (component.TryGetData(PuddleVisuals.VolumeScale, out var volumeScale) && entities.TryGetComponent(component.Owner, out var spriteComponent)) { + component.TryGetData(PuddleVisuals.ForceWetFloorSprite, out var forceWetFloorSprite); var cappedScale = Math.Min(1.0f, volumeScale * 0.75f +0.25f); - UpdateVisual(component, spriteComponent, cappedScale); + UpdateVisual(component, spriteComponent, cappedScale, forceWetFloorSprite); } } - private void UpdateVisual(AppearanceComponent component, SpriteComponent spriteComponent, float cappedScale) + private void UpdateVisual(AppearanceComponent component, SpriteComponent spriteComponent, float cappedScale, bool forceWetFloorSprite) { Color newColor; if (Recolor && component.TryGetData(PuddleVisuals.SolutionColor, out var solutionColor)) @@ -67,6 +68,20 @@ namespace Content.Client.Fluids } spriteComponent.Color = newColor; + + if (forceWetFloorSprite) + { + //Change the puddle's sprite to the wet floor sprite + spriteComponent.LayerSetRSI(0, "Fluids/wet_floor_sparkles.rsi"); + spriteComponent.LayerSetState(0, "sparkles"); + spriteComponent.Color = spriteComponent.Color.WithAlpha(0.25f); //should be mostly transparent. + } + else + { + spriteComponent.LayerSetRSI(0, "Fluids/smear.rsi"); + spriteComponent.LayerSetState(0, "smear-0"); // TODO: need a way to implement the random smears again when the mop creates new puddles. + } + } } diff --git a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs index 6cf97d696f..aa1b01e917 100644 --- a/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/CleanTileReaction.cs @@ -16,7 +16,11 @@ namespace Content.Server.Chemistry.TileReactions [DataDefinition] public class CleanTileReaction : ITileReaction { - + /// + /// Multiplier used in CleanTileReaction. + /// 1 (default) means normal consumption rate of the cleaning reagent. + /// 0 means no consumption of the cleaning reagent, i.e. the reagent is inexhaustible. + /// [DataField("cleanAmountMultiplier")] public float CleanAmountMultiplier { get; private set; } = 1.0f; @@ -29,7 +33,7 @@ namespace Content.Server.Chemistry.TileReactions { if (entMan.TryGetComponent(entity, out CleanableComponent? cleanable)) { - var next = (amount + cleanable.CleanAmount) * CleanAmountMultiplier; + var next = amount + (cleanable.CleanAmount * CleanAmountMultiplier); // Nothing left? if (reactVolume < next) break; diff --git a/Content.Server/Fluids/Components/MopComponent.cs b/Content.Server/Fluids/Components/MopComponent.cs index ca57e3955e..b5314af1c0 100644 --- a/Content.Server/Fluids/Components/MopComponent.cs +++ b/Content.Server/Fluids/Components/MopComponent.cs @@ -27,7 +27,7 @@ namespace Content.Server.Fluids.Components [Dependency] private readonly IEntityManager _entities = default!; public const string SolutionName = "mop"; - + /// /// Used to prevent do_after spam if we're currently mopping. /// @@ -71,10 +71,16 @@ namespace Content.Server.Fluids.Components public FixedPoint2 PickupAmount { get; } = FixedPoint2.New(10); /// - /// After cleaning a floor tile, leave this much reagent as a puddle. I.e., leave behind a wet floor. + /// When using the mop on an empty floor tile, leave this much reagent as a new puddle. /// [DataField("residueAmount")] - public FixedPoint2 ResidueAmount { get; } = FixedPoint2.New(5); + public FixedPoint2 ResidueAmount { get; } = FixedPoint2.New(10); // Should be higher than MopLowerLimit + + /// + /// To leave behind a wet floor, the mop will be unable to take from puddles with a volume less than this amount. + /// + [DataField("mopLowerLimit")] + public FixedPoint2 MopLowerLimit { get; } = FixedPoint2.New(5); [DataField("pickup_sound")] private SoundSpecifier _pickupSound = new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg"); @@ -117,6 +123,14 @@ namespace Content.Server.Fluids.Components !solutionSystem.TryGetSolution((puddleComponent).Owner, puddleComponent.SolutionName, out var puddleSolution)) return false; + // if the puddle is too small for the mop to effectively take any more solution + if (puddleSolution.TotalVolume <= MopLowerLimit) + { + // Transfers solution from the mop to the puddle + solutionSystem.TryAddSolution(target, puddleSolution, solutionSystem.SplitSolution(Owner, contents, FixedPoint2.Min(ResidueAmount,CurrentVolume))); + return true; + } + // if the mop is full if(AvailableVolume <= 0) { @@ -141,28 +155,28 @@ namespace Content.Server.Fluids.Components puddleComponent.Deleted) return false; - + // The volume the mop will take from the puddle FixedPoint2 transferAmount; // does the puddle actually have reagents? it might not if its a weird cosmetic entity. if (puddleSolution.TotalVolume == 0) transferAmount = FixedPoint2.Min(PickupAmount, AvailableVolume); else + { transferAmount = FixedPoint2.Min(PickupAmount, puddleSolution.TotalVolume, AvailableVolume); - - // is the puddle cleaned? - bool isCleaned = (puddleSolution.TotalVolume - transferAmount <= 0); + if ((puddleSolution.TotalVolume - transferAmount) < MopLowerLimit) // If the transferAmount would bring the puddle below the MopLowerLimit + transferAmount = puddleSolution.TotalVolume - MopLowerLimit; // Then the transferAmount should bring the puddle down to the MopLowerLimit exactly + } // Transfers solution from the puddle to the mop solutionSystem.TryAddSolution(Owner, contents, solutionSystem.SplitSolution(target, puddleSolution, transferAmount)); - - if (isCleaned) - { - // deletes the puddle - _entities.DeleteEntity(puddleComponent.Owner); - } + SoundSystem.Play(Filter.Pvs(Owner), _pickupSound.GetSound(), Owner); + // if the mop became full after that puddle, let the player know. + if(AvailableVolume <= 0) + Owner.PopupMessage(eventArgs.User, Loc.GetString("mop-component-mop-is-now-full-message")); + return true; } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index c63dfba73b..afdcfb9883 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -68,8 +68,14 @@ namespace Content.Server.Fluids.EntitySystems var volumeScale = puddleComponent.CurrentVolume.Float() / puddleComponent.OverflowVolume.Float(); var puddleSolution = _solutionContainerSystem.EnsureSolution(uid, puddleComponent.SolutionName); + // Puddles with volume below this threshold will have their sprite changed to a wet floor effect + var wetFloorEffectThreshold = FixedPoint2.New(5); + // "Does this puddle's sprite need changing to the wet floor effect sprite?" + bool changeToWetFloor = (puddleComponent.CurrentVolume <= wetFloorEffectThreshold); + appearanceComponent.SetData(PuddleVisuals.VolumeScale, volumeScale); appearanceComponent.SetData(PuddleVisuals.SolutionColor, puddleSolution.Color); + appearanceComponent.SetData(PuddleVisuals.ForceWetFloorSprite, changeToWetFloor); } private void UpdateSlip(EntityUid entityUid, PuddleComponent puddleComponent) diff --git a/Content.Shared/Fluids/PuddleVisuals.cs b/Content.Shared/Fluids/PuddleVisuals.cs index 976ef1832f..b0deefc249 100644 --- a/Content.Shared/Fluids/PuddleVisuals.cs +++ b/Content.Shared/Fluids/PuddleVisuals.cs @@ -7,6 +7,7 @@ namespace Content.Shared.Fluids public enum PuddleVisuals : byte { VolumeScale, - SolutionColor + SolutionColor, + ForceWetFloorSprite } -} \ No newline at end of file +} diff --git a/Resources/Locale/en-US/fluids/components/mop-component.ftl b/Resources/Locale/en-US/fluids/components/mop-component.ftl index 077b422fe8..ffb69e2e9a 100644 --- a/Resources/Locale/en-US/fluids/components/mop-component.ftl +++ b/Resources/Locale/en-US/fluids/components/mop-component.ftl @@ -1,2 +1,3 @@ mop-component-mop-is-dry-message = Mop needs to be wet! mop-component-mop-is-full-message = Mop is full! +mop-component-mop-is-now-full-message = Mop is now full \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Effects/puddle.yml b/Resources/Prototypes/Entities/Effects/puddle.yml index 3d65bcaa62..382ebae017 100644 --- a/Resources/Prototypes/Entities/Effects/puddle.yml +++ b/Resources/Prototypes/Entities/Effects/puddle.yml @@ -151,3 +151,4 @@ - type: Appearance visuals: - type: PuddleVisualizer + diff --git a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml index b60df3dcc8..1727103e10 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml @@ -20,7 +20,7 @@ - type: SolutionContainerManager solutions: bucket: - maxVol: 500 + maxVol: 100 - type: SolutionTransfer transferAmount: 50 maxTransferAmount: 100 diff --git a/Resources/Textures/Fluids/wet_floor_sparkles.rsi/meta.json b/Resources/Textures/Fluids/wet_floor_sparkles.rsi/meta.json new file mode 100644 index 0000000000..60daf3ca47 --- /dev/null +++ b/Resources/Textures/Fluids/wet_floor_sparkles.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "https://github.com/tgstation/tgstation/commit/505e4414959d598c0d677a9bc734067a7bb513cd", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "sparkles", + "directions": 1, + "delays": [ + [ + 0.14, + 0.14, + 0.14, + 0.14, + 0.14, + 5 + ] + ] + } + ] +} diff --git a/Resources/Textures/Fluids/wet_floor_sparkles.rsi/sparkles.png b/Resources/Textures/Fluids/wet_floor_sparkles.rsi/sparkles.png new file mode 100644 index 0000000000..d900b68b63 Binary files /dev/null and b/Resources/Textures/Fluids/wet_floor_sparkles.rsi/sparkles.png differ