Puddles & spreader refactor (#15191)
This commit is contained in:
@@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
40
Content.Shared/Fluids/Components/DrainComponent.cs
Normal file
40
Content.Shared/Fluids/Components/DrainComponent.cs
Normal 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;
|
||||
}
|
||||
21
Content.Shared/Fluids/Components/PuddleComponent.cs
Normal file
21
Content.Shared/Fluids/Components/PuddleComponent.cs
Normal 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";
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,7 @@ namespace Content.Shared.Fluids
|
||||
[Serializable, NetSerializable]
|
||||
public enum PuddleVisuals : byte
|
||||
{
|
||||
VolumeScale,
|
||||
CurrentVolume,
|
||||
SolutionColor,
|
||||
IsEvaporatingVisual
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Content.Shared/Fluids/SharedPuddleSystem.cs
Normal file
44
Content.Shared/Fluids/SharedPuddleSystem.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user