Puddle Visuals: ECS/Refactor and fixes (#11941)

* Don't stop me now, cuz I'm havin' such a good time (I'm havin' a ball!)

* YEET

* No changes to intended behaviour at this point. Pretty much just a refactor + bugfixes.

* tweaks to RandomizeState, removing an error caused by setting the state after setting the RSI

* Comments cleanup and removed IsSlippery. To re-add soon for this PR.

* test

* We don't actually use this PuddleGeneric anywhere

* cheeky

* Uncheeky, and tweaks based on #8203

* Recheeky

* A small price to pay for `checks passed`

* Beauty, like ice, our footing does betray; Who can tread sure on the smooth, slippery way

* Undo Slippery Checks

* Begin smoothing. Need to fix the animation-not-playing bug again

* Cleanup

* animation bugfix

* IgnoredComponents tests fix
This commit is contained in:
Willhelm53
2022-12-19 20:40:53 -06:00
committed by GitHub
parent 3327c2998f
commit a1dcc500a8
12 changed files with 208 additions and 157 deletions

View File

@@ -0,0 +1,131 @@
using System.Linq;
using Content.Shared.Fluids;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Random;
namespace Content.Client.Fluids
{
[UsedImplicitly]
public sealed class PuddleVisualizerSystem : VisualizerSystem<PuddleVisualizerComponent>
{
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PuddleVisualizerComponent, ComponentInit>(OnComponentInit);
}
private void OnComponentInit(EntityUid uid, PuddleVisualizerComponent puddleVisuals, ComponentInit args)
{
if (!TryComp(uid, out AppearanceComponent? appearance))
{
return;
}
if (!TryComp(uid, out SpriteComponent? sprite))
{
return;
}
puddleVisuals.OriginalRsi = sprite.BaseRSI; //Back up the original RSI upon initialization
RandomizeState(sprite, puddleVisuals.OriginalRsi);
RandomizeRotation(sprite);
}
protected override void OnAppearanceChange(EntityUid uid, PuddleVisualizerComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
{
Logger.Warning($"Missing SpriteComponent for PuddleVisualizerSystem on entityUid = {uid}");
return;
}
if (args.Component.TryGetData(PuddleVisuals.VolumeScale, out float volumeScale)
&& args.Component.TryGetData(PuddleVisuals.CurrentVolume, out FixedPoint2 currentVolume)
&& args.Component.TryGetData(PuddleVisuals.SolutionColor, out Color solutionColor)
&& args.Component.TryGetData(PuddleVisuals.IsEvaporatingVisual, out bool isEvaporating))
{
// volumeScale is our opacity based on level of fullness to overflow. The lower bound is hard-capped for visibility reasons.
var cappedScale = Math.Min(1.0f, volumeScale * 0.75f + 0.25f);
Color newColor;
if (component.Recolor)
{
newColor = solutionColor.WithAlpha(cappedScale);
}
else
{
newColor = args.Sprite.Color.WithAlpha(cappedScale);
}
args.Sprite.LayerSetColor(0, newColor);
if (component.CustomPuddleSprite) //Don't consider wet floor effects if we're using a custom sprite.
{
return;
}
bool wetFloorEffectNeeded;
if (isEvaporating
&& currentVolume < component.WetFloorEffectThreshold)
{
wetFloorEffectNeeded = true;
}
else
wetFloorEffectNeeded = false;
if (wetFloorEffectNeeded)
{
if (args.Sprite.LayerGetState(0) != "sparkles") // If we need the effect but don't already have it - start it
{
StartWetFloorEffect(args.Sprite, component.WetFloorEffectAlpha);
}
}
else
{
if (args.Sprite.LayerGetState(0) == "sparkles") // If we have the effect but don't need it - end it
EndWetFloorEffect(args.Sprite, component.OriginalRsi);
}
}
else
{
return;
}
}
private void StartWetFloorEffect(SpriteComponent sprite, float alpha)
{
sprite.LayerSetState(0, "sparkles", "Fluids/wet_floor_sparkles.rsi");
sprite.Color = sprite.Color.WithAlpha(alpha);
sprite.LayerSetAutoAnimated(0, false);
sprite.LayerSetAutoAnimated(0, true); //fixes a bug where the sparkle effect would sometimes freeze on a single frame.
}
private void EndWetFloorEffect(SpriteComponent sprite, RSI? originalRSI)
{
RandomizeState(sprite, originalRSI);
sprite.LayerSetAutoAnimated(0, false);
}
private void RandomizeState(SpriteComponent sprite, RSI? rsi)
{
var maxStates = rsi?.ToArray();
if (maxStates is not { Length: > 0 }) return;
var selectedState = _random.Next(0, maxStates.Length - 1); //randomly select an index for which RSI state to use.
sprite.LayerSetState(0, maxStates[selectedState].StateId, rsi); // sets the sprite's state via our randomly selected index.
}
private void RandomizeRotation(SpriteComponent sprite)
{
float rotationDegrees = _random.Next(0, 359); // randomly select a rotation for our puddle sprite.
sprite.Rotation = Angle.FromDegrees(rotationDegrees); // sets the sprite's rotation to the one we randomly selected.
}
}
}