Mopping Puddle Dilution and Wet Floor Sparkles (#6273)

This commit is contained in:
Willhelm53
2022-02-04 20:26:11 -06:00
committed by GitHub
parent 3d3a3c857b
commit 4d3a381962
10 changed files with 87 additions and 20 deletions

View File

@@ -49,12 +49,13 @@ namespace Content.Client.Fluids
if (component.TryGetData<float>(PuddleVisuals.VolumeScale, out var volumeScale) && if (component.TryGetData<float>(PuddleVisuals.VolumeScale, out var volumeScale) &&
entities.TryGetComponent<SpriteComponent>(component.Owner, out var spriteComponent)) entities.TryGetComponent<SpriteComponent>(component.Owner, out var spriteComponent))
{ {
component.TryGetData<bool>(PuddleVisuals.ForceWetFloorSprite, out var forceWetFloorSprite);
var cappedScale = Math.Min(1.0f, volumeScale * 0.75f +0.25f); 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; Color newColor;
if (Recolor && component.TryGetData<Color>(PuddleVisuals.SolutionColor, out var solutionColor)) if (Recolor && component.TryGetData<Color>(PuddleVisuals.SolutionColor, out var solutionColor))
@@ -67,6 +68,20 @@ namespace Content.Client.Fluids
} }
spriteComponent.Color = newColor; 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.
}
} }
} }

View File

@@ -16,7 +16,11 @@ namespace Content.Server.Chemistry.TileReactions
[DataDefinition] [DataDefinition]
public class CleanTileReaction : ITileReaction public class CleanTileReaction : ITileReaction
{ {
/// <summary>
/// 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.
/// </summary>
[DataField("cleanAmountMultiplier")] [DataField("cleanAmountMultiplier")]
public float CleanAmountMultiplier { get; private set; } = 1.0f; public float CleanAmountMultiplier { get; private set; } = 1.0f;
@@ -29,7 +33,7 @@ namespace Content.Server.Chemistry.TileReactions
{ {
if (entMan.TryGetComponent(entity, out CleanableComponent? cleanable)) if (entMan.TryGetComponent(entity, out CleanableComponent? cleanable))
{ {
var next = (amount + cleanable.CleanAmount) * CleanAmountMultiplier; var next = amount + (cleanable.CleanAmount * CleanAmountMultiplier);
// Nothing left? // Nothing left?
if (reactVolume < next) if (reactVolume < next)
break; break;

View File

@@ -27,7 +27,7 @@ namespace Content.Server.Fluids.Components
[Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IEntityManager _entities = default!;
public const string SolutionName = "mop"; public const string SolutionName = "mop";
/// <summary> /// <summary>
/// Used to prevent do_after spam if we're currently mopping. /// Used to prevent do_after spam if we're currently mopping.
/// </summary> /// </summary>
@@ -71,10 +71,16 @@ namespace Content.Server.Fluids.Components
public FixedPoint2 PickupAmount { get; } = FixedPoint2.New(10); public FixedPoint2 PickupAmount { get; } = FixedPoint2.New(10);
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
[DataField("residueAmount")] [DataField("residueAmount")]
public FixedPoint2 ResidueAmount { get; } = FixedPoint2.New(5); public FixedPoint2 ResidueAmount { get; } = FixedPoint2.New(10); // Should be higher than MopLowerLimit
/// <summary>
/// To leave behind a wet floor, the mop will be unable to take from puddles with a volume less than this amount.
/// </summary>
[DataField("mopLowerLimit")]
public FixedPoint2 MopLowerLimit { get; } = FixedPoint2.New(5);
[DataField("pickup_sound")] [DataField("pickup_sound")]
private SoundSpecifier _pickupSound = new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg"); 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)) !solutionSystem.TryGetSolution((puddleComponent).Owner, puddleComponent.SolutionName, out var puddleSolution))
return false; 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 the mop is full
if(AvailableVolume <= 0) if(AvailableVolume <= 0)
{ {
@@ -141,28 +155,28 @@ namespace Content.Server.Fluids.Components
puddleComponent.Deleted) puddleComponent.Deleted)
return false; return false;
// The volume the mop will take from the puddle
FixedPoint2 transferAmount; FixedPoint2 transferAmount;
// does the puddle actually have reagents? it might not if its a weird cosmetic entity. // does the puddle actually have reagents? it might not if its a weird cosmetic entity.
if (puddleSolution.TotalVolume == 0) if (puddleSolution.TotalVolume == 0)
transferAmount = FixedPoint2.Min(PickupAmount, AvailableVolume); transferAmount = FixedPoint2.Min(PickupAmount, AvailableVolume);
else else
{
transferAmount = FixedPoint2.Min(PickupAmount, puddleSolution.TotalVolume, AvailableVolume); transferAmount = FixedPoint2.Min(PickupAmount, puddleSolution.TotalVolume, AvailableVolume);
if ((puddleSolution.TotalVolume - transferAmount) < MopLowerLimit) // If the transferAmount would bring the puddle below the MopLowerLimit
// is the puddle cleaned? transferAmount = puddleSolution.TotalVolume - MopLowerLimit; // Then the transferAmount should bring the puddle down to the MopLowerLimit exactly
bool isCleaned = (puddleSolution.TotalVolume - transferAmount <= 0); }
// Transfers solution from the puddle to the mop // Transfers solution from the puddle to the mop
solutionSystem.TryAddSolution(Owner, contents, solutionSystem.SplitSolution(target, puddleSolution, transferAmount)); 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); 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; return true;
} }
} }

View File

@@ -68,8 +68,14 @@ namespace Content.Server.Fluids.EntitySystems
var volumeScale = puddleComponent.CurrentVolume.Float() / puddleComponent.OverflowVolume.Float(); var volumeScale = puddleComponent.CurrentVolume.Float() / puddleComponent.OverflowVolume.Float();
var puddleSolution = _solutionContainerSystem.EnsureSolution(uid, puddleComponent.SolutionName); 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.VolumeScale, volumeScale);
appearanceComponent.SetData(PuddleVisuals.SolutionColor, puddleSolution.Color); appearanceComponent.SetData(PuddleVisuals.SolutionColor, puddleSolution.Color);
appearanceComponent.SetData(PuddleVisuals.ForceWetFloorSprite, changeToWetFloor);
} }
private void UpdateSlip(EntityUid entityUid, PuddleComponent puddleComponent) private void UpdateSlip(EntityUid entityUid, PuddleComponent puddleComponent)

View File

@@ -7,6 +7,7 @@ namespace Content.Shared.Fluids
public enum PuddleVisuals : byte public enum PuddleVisuals : byte
{ {
VolumeScale, VolumeScale,
SolutionColor SolutionColor,
ForceWetFloorSprite
} }
} }

View File

@@ -1,2 +1,3 @@
mop-component-mop-is-dry-message = Mop needs to be wet! mop-component-mop-is-dry-message = Mop needs to be wet!
mop-component-mop-is-full-message = Mop is full! mop-component-mop-is-full-message = Mop is full!
mop-component-mop-is-now-full-message = Mop is now full

View File

@@ -151,3 +151,4 @@
- type: Appearance - type: Appearance
visuals: visuals:
- type: PuddleVisualizer - type: PuddleVisualizer

View File

@@ -20,7 +20,7 @@
- type: SolutionContainerManager - type: SolutionContainerManager
solutions: solutions:
bucket: bucket:
maxVol: 500 maxVol: 100
- type: SolutionTransfer - type: SolutionTransfer
transferAmount: 50 transferAmount: 50
maxTransferAmount: 100 maxTransferAmount: 100

View File

@@ -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
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB