From 4d3a3819624f808c620286bedb7dafae1d5842d0 Mon Sep 17 00:00:00 2001 From: Willhelm53 <97707302+Willhelm53@users.noreply.github.com> Date: Fri, 4 Feb 2022 20:26:11 -0600 Subject: [PATCH] Mopping Puddle Dilution and Wet Floor Sparkles (#6273) --- Content.Client/Fluids/PuddleVisualizer.cs | 19 ++++++++- .../TileReactions/CleanTileReaction.cs | 8 +++- .../Fluids/Components/MopComponent.cs | 40 ++++++++++++------ .../Fluids/EntitySystems/PuddleSystem.cs | 6 +++ Content.Shared/Fluids/PuddleVisuals.cs | 5 ++- .../en-US/fluids/components/mop-component.ftl | 1 + .../Prototypes/Entities/Effects/puddle.yml | 1 + .../Entities/Objects/Tools/bucket.yml | 2 +- .../Fluids/wet_floor_sparkles.rsi/meta.json | 25 +++++++++++ .../wet_floor_sparkles.rsi/sparkles.png | Bin 0 -> 2025 bytes 10 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 Resources/Textures/Fluids/wet_floor_sparkles.rsi/meta.json create mode 100644 Resources/Textures/Fluids/wet_floor_sparkles.rsi/sparkles.png 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 0000000000000000000000000000000000000000..d900b68b63aec3844179dbd689f197c09654ce4b GIT binary patch literal 2025 zcma)7X*3&%8ckwps1mJ5sU_&N_O_Nx`(qtwyY+ z8r0B8EmIA`G}hRcR4pm3cq)0GXXeK{XU>^(-u$@V{c*ov_q*qQ8E!7f6XFWu007{G zy`2r}h@bopu;|gu91hVvBC)%69#{ZCviElY3$!KA0075I>}{;vV@kPYv-hV>Acz7i zikLYmx#`;~)KSQV*1listAU3F6`D2+gM|E3Rp4`i{Iq^3(0eIF;}NX_kOGC;iOFs6 z9z>aT#S3sCJBZ%G&W^pf6n!#9EQb57E}n46zi;NFS6Bgar8L;Sp6h`T5`6tM7FWp^ zDhe$(h1_ZhD0t4b<>7h49KEDkC~-bHMtH`7b`8l#9sC5syOd1iHOdbEI#Y`t1=;A{ zuip)AIFtjbR}HbdBFipYP<~-It5Nu zp8h8zjJ)pQMPSL?sk!NHL;FZGztV@g9*SO+e%;m@`g(3^13Fj3pkB{*jzAKJcT zs`fMEp)bLf%DGi?4)+!+0<;nbCCLa2Yl6Wj2;}+EIj!KiNyNVrrrr?OvFf=Yd!T$M z_D<@lk-DB>CSt+fJxa4NQNab?C|$Sv=wVz$H*~*#PrksLQCE>FeKEAR_C3PQAkYIz zVw+(YW#0{Faa83Ibdq$P`&;%JCAjyYg2y20%x6~qbdzit%tIwVK-jw}8$%LrwR^^3 zcxG}e-*7rOY}aSTXlg z1w!Lx(6%!0lul-tEuLBo$!ybTd3rI2FQxk=`f(ov75pN(GVoqoNnHc0XDp?=a~)Ps zycQt4(c-A2*nWJNvm(H9wXIAkg>H|LkI9DV650zA_I>JG4Mr9-7P_pJulsCXjHbgt zN`Oe`GZ)v5JonC!qLC8ih}3`LtdBpwktw?SI#nMNE+&ig74Wyb7O^aGumJG4&Gr|~ z*;33`(v|`RZ=3K~=wGFk0m4oT_dZeDByu7R_DBH-m!n<2qU0ArT00c#(jUS=Q7(CT zg8h2WJL`K|=?YoDSR~%4JRM(TLU34fN++MdGYc@oB3W#|9y(fc@a<8<*t_p=e;6MFpa+#fMh@=LAuN#ld zW%N6~+O-}t0%?uI;t=we+>`>h#CsH-n?6ZjO-Mg5WPnZZJnz08CV^K)-kg)cNrAGr zm$fQ?Yp&ZP1vU7!It3JJ)fxXdn@lva{_-f&)U%(vjt+->fl&D0MVE1C=7QB$okkhl zd(BDqEoAN%Y4nBV(my5@jFc2-jeRvYyXQr=Zd-Vua~js`Bc|uvysC-y=T|Fn^wVZY zsyNe#9}wca zDq9UUduv6x%6A_hTw9%d-Lgm;mrK4aqbAkm#bDYiV_vue$7hr}*D|+7ht7os5u|fx>&r<~z3fO*a~soQ$Cm!){Cv>^65mUp zTN@t7=L%5t9hWFcl?)5sbRwCBeG*kchXvBX+TEtWl2NPc%?pL%V)h>BgH6v zi=;AQU=`5Ia}xxwXt3}(08{g%Z)9M#z`5V^SeNCYAMo9p>KJqnWjVtVaGF?rSt0uVFS_=o8VBmxpW$h$QCs$LUia+pAADjkf<50*NZ?NHb_g z_MUyxf>j@e{%jVVY0ykY$0A|EV@dY(VrEuoeAp^NIceQO{dkVM^IL=G0oKI!7)Vph zU}LiU2M%IxS&;ofB<>5;|EAE;$Twu;;rOPWBpCaE2<@|_SGNr5Sow_OxHm{t$4Z+4!(Y+{EBw{3h zr-w=)1BS6z9@>EYrQ1Lsogvi&bD5o~|BM@8uJRKllHT7BC1)Jh^||oOBps xVS08^9u)?Y>nkyFk3!JSc8UT2M&0hq)vHZR=o=Ng9{p~By{(JQi>v-g{{^z~s)_&r literal 0 HcmV?d00001