Delta-v/Content.Server/_DV/Footprints/Systems/PuddleFootPrintsSystem.cs

113 lines
4.0 KiB
C#

using System.Linq;
using Content.Server._DV.Footprints.Components;
using Content.Shared._EE.Flight;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Fluids;
using Content.Shared.Fluids.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes;
namespace Content.Server._DV.Footprints.Systems;
/// <summary>
/// Handles transferring puddle colors and reagents to entities with footprints when they step in puddles.
/// </summary>
public sealed class PuddleFootPrintsSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedFlightSystem _flight = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
private EntityQuery<FlightComponent> _flightQuery;
private static readonly ProtoId<ReagentPrototype> WaterPrototype = "Water";
public override void Initialize()
{
base.Initialize();
_flightQuery = GetEntityQuery<FlightComponent>();
SubscribeLocalEvent<PuddleFootPrintsComponent, EndCollideEvent>(OnEndCollide);
}
private void OnEndCollide(Entity<PuddleFootPrintsComponent> puddle, ref EndCollideEvent args)
{
var collidingEntity = args.OtherEntity;
// Don't process if the tripper is flying
if (_flightQuery.TryComp(collidingEntity, out var flight) && _flight.IsFlying((collidingEntity, flight)))
return;
// Only process entities that can leave footprints
if (!TryComp<FootPrintsComponent>(collidingEntity, out var footPrints))
return;
// Get puddle appearance and solution data
if (!TryComp<AppearanceComponent>(puddle, out var appearance))
return;
if (!TryComp<PuddleComponent>(puddle, out var puddleComp))
return;
if (!TryComp<SolutionContainerManagerComponent>(puddle, out var solutionManager))
return;
if (!_solutionContainer.ResolveSolution((puddle, solutionManager),
puddleComp.SolutionName,
ref puddleComp.Solution,
out var solution))
return;
// Calculate total solution quantity and water percentage
var totalSolutionQuantity = solution.Contents.Sum(sol => (float)sol.Quantity);
if (totalSolutionQuantity <= 0 || solution.Contents.Count <= 0)
return;
var waterQuantity = solution.Contents
.Where(sol => sol.Reagent.Prototype == WaterPrototype)
.Sum(sol => (float)sol.Quantity);
var waterPercent = (waterQuantity / totalSolutionQuantity) * 100f;
// If puddle is mostly water, don't transfer color
if (waterPercent > puddle.Comp.OffPercent)
return;
// Transfer color from puddle to footprints
if (_appearance.TryGetData(puddle, PuddleVisuals.SolutionColor, out var colorValue, appearance)
&& _appearance.TryGetData(puddle, PuddleVisuals.CurrentVolume, out var volumeValue, appearance))
{
if (colorValue is Color color && volumeValue is float volume)
{
AddColor(color, volume * puddle.Comp.SizeRatio, footPrints);
}
}
// Remove small amount of reagent from puddle
_solutionContainer.RemoveEachReagent(puddleComp.Solution.Value, footPrints.AmountToTransfer);
}
private void AddColor(Color color, float quantity, FootPrintsComponent component)
{
// If no color yet, use the puddle's color directly
if (component.ColorQuantity == 0f)
{
component.PrintsColor = color;
}
else
{
// Interpolate between current color and new color
component.PrintsColor = Color.InterpolateBetween(
component.PrintsColor,
color,
component.ColorInterpolationFactor);
}
component.ColorQuantity += quantity;
}
}