Puddles & spreader refactor (#15191)

This commit is contained in:
metalgearsloth
2023-04-10 15:37:03 +10:00
committed by GitHub
parent 3178ab83f6
commit 317a4013eb
141 changed files with 3046 additions and 3201 deletions

View File

@@ -10,48 +10,31 @@ namespace Content.Shared.Fluids;
[RegisterComponent, NetworkedComponent]
public sealed class AbsorbentComponent : Component
{
// TODO: Predicted solutions my beloved.
public float Progress;
public const string SolutionName = "absorbed";
public Dictionary<Color, float> Progress = new();
/// <summary>
/// How much solution we can transfer in one interaction.
/// </summary>
[DataField("pickupAmount")]
public FixedPoint2 PickupAmount = FixedPoint2.New(10);
/// <summary>
/// When using this tool on an empty floor tile, leave this much reagent as a new puddle.
/// </summary>
[DataField("residueAmount")]
public FixedPoint2 ResidueAmount = FixedPoint2.New(10); // Should be higher than MopLowerLimit
/// <summary>
/// To leave behind a wet floor, this tool will be unable to take from puddles with a volume less than this
/// amount. This limit is ignored if the target puddle does not evaporate.
/// </summary>
[DataField("lowerLimit")]
public FixedPoint2 LowerLimit = FixedPoint2.New(5);
public FixedPoint2 PickupAmount = FixedPoint2.New(60);
[DataField("pickupSound")]
public SoundSpecifier PickupSound = new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg");
public SoundSpecifier PickupSound = new SoundPathSpecifier("/Audio/Effects/Fluids/watersplash.ogg")
{
Params = AudioParams.Default.WithVariation(0.05f),
};
[DataField("transferSound")]
public SoundSpecifier TransferSound = new SoundPathSpecifier("/Audio/Effects/Fluids/watersplash.ogg");
/// <summary>
/// Quantity of reagent that this mop can pick up per second. Determines the length of the do-after.
/// </summary>
[DataField("speed")] public float Speed = 10;
/// <summary>
/// How many entities can this tool interact with at once?
/// </summary>
[DataField("maxEntities")]
public int MaxInteractingEntities = 1;
/// <summary>
/// What entities is this tool interacting with right now?
/// </summary>
[ViewVariables]
public HashSet<EntityUid> InteractingEntities = new();
[DataField("transferSound")] public SoundSpecifier TransferSound =
new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg")
{
Params = AudioParams.Default.WithVariation(0.05f).WithVolume(-3f),
};
public static readonly SoundSpecifier DefaultTransferSound =
new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg")
{
Params = AudioParams.Default.WithVariation(0.05f).WithVolume(-3f),
};
}

View File

@@ -0,0 +1,40 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Fluids.Components;
[RegisterComponent, NetworkedComponent]
public sealed class DrainComponent : Component
{
public const string SolutionName = "drainBuffer";
[DataField("accumulator")]
public float Accumulator = 0f;
/// <summary>
/// How many units per second the drain can absorb from the surrounding puddles.
/// Divided by puddles, so if there are 5 puddles this will take 1/5 from each puddle.
/// This will stay fixed to 1 second no matter what DrainFrequency is.
/// </summary>
[DataField("unitsPerSecond")]
public float UnitsPerSecond = 6f;
/// <summary>
/// How many units are ejected from the buffer per second.
/// </summary>
[DataField("unitsDestroyedPerSecond")]
public float UnitsDestroyedPerSecond = 1f;
/// <summary>
/// How many (unobstructed) tiles away the drain will
/// drain puddles from.
/// </summary>
[DataField("range")]
public float Range = 2f;
/// <summary>
/// How often in seconds the drain checks for puddles around it.
/// If the EntityQuery seems a bit unperformant this can be increased.
/// </summary>
[DataField("drainFrequency")]
public float DrainFrequency = 1f;
}

View File

@@ -0,0 +1,21 @@
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Fluids.Components
{
/// <summary>
/// Puddle on a floor
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedPuddleSystem))]
public sealed class PuddleComponent : Component
{
[DataField("spillSound")]
public SoundSpecifier SpillSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg");
[DataField("overflowVolume")]
public FixedPoint2 OverflowVolume = FixedPoint2.New(20);
[DataField("solution")] public string SolutionName = "puddle";
}
}

View File

@@ -5,9 +5,7 @@ namespace Content.Shared.Fluids
[Serializable, NetSerializable]
public enum PuddleVisuals : byte
{
VolumeScale,
CurrentVolume,
SolutionColor,
IsEvaporatingVisual
}
}

View File

@@ -1,9 +1,13 @@
using System.Linq;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Fluids;
public abstract class SharedMoppingSystem : EntitySystem
/// <summary>
/// Mopping logic for interacting with puddle components.
/// </summary>
public abstract class SharedAbsorbentSystem : EntitySystem
{
public override void Initialize()
{
@@ -17,23 +21,29 @@ public abstract class SharedMoppingSystem : EntitySystem
if (args.Current is not AbsorbentComponentState state)
return;
if (component.Progress.Equals(state.Progress))
if (component.Progress.OrderBy(x => x.Key.ToArgb()).SequenceEqual(state.Progress))
return;
component.Progress = state.Progress;
component.Progress.Clear();
foreach (var item in state.Progress)
{
component.Progress.Add(item.Key, item.Value);
}
}
private void OnAbsorbentGetState(EntityUid uid, AbsorbentComponent component, ref ComponentGetState args)
{
args.State = new AbsorbentComponentState()
{
Progress = component.Progress,
};
args.State = new AbsorbentComponentState(component.Progress);
}
[Serializable, NetSerializable]
protected sealed class AbsorbentComponentState : ComponentState
{
public float Progress;
public Dictionary<Color, float> Progress;
public AbsorbentComponentState(Dictionary<Color, float> progress)
{
Progress = progress;
}
}
}

View File

@@ -0,0 +1,44 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.DragDrop;
using Content.Shared.Fluids.Components;
namespace Content.Shared.Fluids;
public abstract class SharedPuddleSystem : EntitySystem
{
/// <summary>
/// The lowest threshold to be considered for puddle sprite states as well as slipperiness of a puddle.
/// </summary>
public const float LowThreshold = 0.3f;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RefillableSolutionComponent, CanDragEvent>(OnRefillableCanDrag);
SubscribeLocalEvent<RefillableSolutionComponent, CanDropDraggedEvent>(OnRefillableCanDropDragged);
SubscribeLocalEvent<DrainableSolutionComponent, CanDropTargetEvent>(OnDrainCanDropTarget);
}
private void OnRefillableCanDrag(EntityUid uid, RefillableSolutionComponent component, ref CanDragEvent args)
{
args.Handled = true;
}
private void OnDrainCanDropTarget(EntityUid uid, DrainableSolutionComponent component, ref CanDropTargetEvent args)
{
if (HasComp<RefillableSolutionComponent>(args.Dragged))
{
args.CanDrop = true;
args.Handled = true;
}
}
private void OnRefillableCanDropDragged(EntityUid uid, RefillableSolutionComponent component, ref CanDropDraggedEvent args)
{
if (!HasComp<DrainableSolutionComponent>(args.Target) && !HasComp<DrainComponent>(args.Target))
return;
args.CanDrop = true;
args.Handled = true;
}
}