diff --git a/Content.Server/_Sunrise/Footprints/FootPrintsSystem.cs b/Content.Server/_Sunrise/Footprints/FootPrintsSystem.cs index a9079f2c66..9db44dc1c7 100644 --- a/Content.Server/_Sunrise/Footprints/FootPrintsSystem.cs +++ b/Content.Server/_Sunrise/Footprints/FootPrintsSystem.cs @@ -1,14 +1,16 @@ using Content.Server.Atmos.Components; using Content.Shared._Sunrise.Footprints; +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.FixedPoint; using Content.Shared.Inventory; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Robust.Shared.Map; using Robust.Shared.Random; -using System.Linq; using Content.Shared.GameTicking; +using Robust.Shared.Prototypes; namespace Content.Server._Sunrise.Footprints; @@ -24,6 +26,7 @@ public sealed class FootprintSystem : EntitySystem [Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; #endregion #region Entity Queries @@ -32,6 +35,8 @@ public sealed class FootprintSystem : EntitySystem private EntityQuery _appearanceQuery; #endregion + public static readonly float FootsVolume = 5; + // Dictionary to track footprints per tile to prevent overcrowding private readonly Dictionary<(EntityUid GridId, Vector2i TilePosition), HashSet> _tileFootprints = new(); private const int MaxFootprintsPerTile = 2; // Maximum footprints allowed per tile @@ -51,6 +56,12 @@ public sealed class FootprintSystem : EntitySystem SubscribeLocalEvent(OnEmitterStartup); SubscribeLocalEvent(OnEntityMove); SubscribeNetworkEvent(Reset); + SubscribeLocalEvent(OnFootprintEmitterInit); + } + + private void OnFootprintEmitterInit(Entity entity, ref ComponentInit args) + { + _solutionSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, out _, FixedPoint2.New(FootsVolume)); } /// @@ -70,10 +81,14 @@ public sealed class FootprintSystem : EntitySystem private void OnEntityMove(EntityUid uid, FootprintEmitterComponent emitter, ref MoveEvent args) { // Check if footprints should be created - if (emitter.TrackColor.A <= 0f - || !_transformQuery.TryComp(uid, out var transform) + if (!_transformQuery.TryComp(uid, out var transform) || !_mobStateQuery.TryComp(uid, out var mobState) - || !_mapManager.TryFindGridAt(_transformSystem.GetMapCoordinates((uid, transform)), out var gridUid, out var grid)) + || !_mapManager.TryFindGridAt(_transformSystem.GetMapCoordinates((uid, transform)), out var gridUid, out var grid) + || !TryComp(uid, out var container) + || !_solutionSystem.ResolveSolution((uid, container), emitter.SolutionName, ref emitter.Solution, out var emitterSolution)) + return; + + if (emitterSolution.Volume <= 0) return; var isBeingDragged = @@ -95,7 +110,7 @@ public sealed class FootprintSystem : EntitySystem emitter.IsRightStep = !emitter.IsRightStep; // Create new footprint entity - var footprintEntity = SpawnFootprint(gridUid, emitter, uid, transform, isBeingDragged); + var footprintEntity = SpawnFootprint(gridUid, emitter, emitterSolution, uid, transform, isBeingDragged); // Add the new footprint to tile tracking if (!_tileFootprints.ContainsKey(tileKey)) @@ -104,7 +119,7 @@ public sealed class FootprintSystem : EntitySystem _tileFootprints[tileKey].Add(footprintEntity); // Update footprint and emitter state - UpdateFootprint(footprintEntity, emitter, transform, isBeingDragged); + UpdateFootprint(footprintEntity, (uid, emitter), emitterSolution, emitter.Solution.Value, transform, isBeingDragged); // Update emitter state. UpdateEmitterState(emitter, transform); @@ -124,6 +139,7 @@ public sealed class FootprintSystem : EntitySystem private EntityUid SpawnFootprint( EntityUid gridUid, FootprintEmitterComponent emitter, + Solution emitterSolution, EntityUid emitterOwner, TransformComponent transform, bool isDragging) @@ -142,9 +158,11 @@ public sealed class FootprintSystem : EntitySystem DetermineVisualState(emitterOwner, isDragging), appearance); + var alpha = Math.Clamp(emitterSolution.Volume.Float() / emitterSolution.MaxVolume.Float(), 0f, 1f); + _appearanceSystem.SetData(entity, FootprintVisualParameter.TrackColor, - emitter.TrackColor, + emitterSolution.GetColor(_prototypeManager).WithAlpha(alpha), appearance); } @@ -156,7 +174,9 @@ public sealed class FootprintSystem : EntitySystem /// private void UpdateFootprint( EntityUid footprintEntity, - FootprintEmitterComponent emitter, + Entity emitter, + Solution emitterSolution, + Entity emitterEntSolution, TransformComponent transform, bool isDragging) { @@ -164,10 +184,10 @@ public sealed class FootprintSystem : EntitySystem return; footprintTransform.LocalRotation = isDragging - ? (transform.LocalPosition - emitter.LastStepPosition).ToAngle() + Angle.FromDegrees(-90f) + ? (transform.LocalPosition - emitter.Comp.LastStepPosition).ToAngle() + Angle.FromDegrees(-90f) : transform.LocalRotation + Angle.FromDegrees(180f); - TransferReagents(footprintEntity, emitter); + TransferReagents(footprintEntity, emitter, emitterEntSolution); } #endregion @@ -177,29 +197,25 @@ public sealed class FootprintSystem : EntitySystem /// private void UpdateEmitterState(FootprintEmitterComponent emitter, TransformComponent transform) { - emitter.TrackColor = emitter.TrackColor.WithAlpha(Math.Max(0f, emitter.TrackColor.A - emitter.ColorFadeRate)); emitter.LastStepPosition = transform.LocalPosition; } /// /// Transfers reagents from emitter to footprint if applicable. /// - private void TransferReagents(EntityUid footprintEntity, FootprintEmitterComponent emitter) + private void TransferReagents(EntityUid footprintEntity, Entity emitter, Entity emitterSolution) { if (!TryComp(footprintEntity, out var container) || !TryComp(footprintEntity, out var footprint) || !_solutionSystem.ResolveSolution((footprintEntity, container), footprint.ContainerName, ref footprint.SolutionContainer, - out var solution) - || string.IsNullOrWhiteSpace(emitter.CurrentReagent) - || solution.Volume >= 1) + out var solution)) return; - _solutionSystem.TryAddReagent(footprint.SolutionContainer.Value, - emitter.CurrentReagent, - 1, - out _); + var splitSolution = _solutionSystem.SplitSolution(emitterSolution, emitter.Comp.TransferVolume); + + _solutionSystem.AddSolution(footprint.SolutionContainer.Value, splitSolution); } #endregion diff --git a/Content.Server/_Sunrise/Footprints/PuddleFootPrintsSystem.cs b/Content.Server/_Sunrise/Footprints/PuddleFootPrintsSystem.cs index 13d3dc8560..88bbe7ad18 100644 --- a/Content.Server/_Sunrise/Footprints/PuddleFootPrintsSystem.cs +++ b/Content.Server/_Sunrise/Footprints/PuddleFootPrintsSystem.cs @@ -2,7 +2,6 @@ using Content.Shared._Sunrise.Footprints; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.Fluids; using Content.Shared.Fluids.Components; using Robust.Shared.Physics.Events; @@ -27,35 +26,37 @@ public sealed class PuddleFootprintSystem : EntitySystem /// Handles puddle interaction and footprint creation when entity exits the puddle /// private void OnPuddleInteraction(EntityUid uid, PuddleFootprintComponent component, ref EndCollideEvent args) - { - if (!TryComp(uid, out var appearance) - || !TryComp(uid, out var puddle) - || !TryComp(args.OtherEntity, out var emitter) - || !TryComp(uid, out var solutionManager) - || !_solutionSystem.ResolveSolution((uid, solutionManager), puddle.SolutionName, ref puddle.Solution, out var solutions)) - return; +{ + if (!TryComp(uid, out var appearance) + || !TryComp(uid, out var puddle) + || !TryComp(args.OtherEntity, out var emitter) + || !TryComp(uid, out var solutionManager) + || !_solutionSystem.ResolveSolution((uid, solutionManager), puddle.SolutionName, ref puddle.Solution, out var puddleSolutions) + || !TryComp(args.OtherEntity, out var emitterSolutionManager) + || !_solutionSystem.ResolveSolution((args.OtherEntity, emitterSolutionManager), emitter.SolutionName, ref emitter.Solution, out var emitterSolutions)) + return; - var totalSolutionQuantity = solutions.Contents.Sum(sol => (float)sol.Quantity); - var waterQuantity = (from sol in solutions.Contents where sol.Reagent.Prototype == "Water" select (float)sol.Quantity).FirstOrDefault(); + var totalSolutionQuantity = puddleSolutions.Contents.Sum(sol => (float)sol.Quantity); + var waterQuantity = (from sol in puddleSolutions.Contents where sol.Reagent.Prototype == "Water" select (float)sol.Quantity).FirstOrDefault(); - if (waterQuantity / (totalSolutionQuantity / 100f) > component.WaterThresholdPercent || solutions.Contents.Count <= 0) - return; + if (waterQuantity / (totalSolutionQuantity / 100f) > component.WaterThresholdPercent || puddleSolutions.Contents.Count <= 0) + return; - emitter.CurrentReagent = solutions.Contents.Aggregate((l, r) => l.Quantity > r.Quantity ? l : r).Reagent.Prototype; + var availableSpace = emitterSolutions.MaxVolume.Float() - emitterSolutions.Volume.Float(); - if (_appearanceSystem.TryGetData(uid, PuddleVisuals.SolutionColor, out var color, appearance) - && _appearanceSystem.TryGetData(uid, PuddleVisuals.CurrentVolume, out var volume, appearance)) - UpdateTrackColor((Color)color, (float)volume * component.ColorTransferRatio, emitter); + if (availableSpace <= 0) + return; - _solutionSystem.RemoveEachReagent(puddle.Solution.Value, 0.5f); - } + var transferVolume = Math.Min(component.TransferVolume, availableSpace); - /// - /// Updates the color of footprints based on puddle properties - /// - private void UpdateTrackColor(Color color, float quantity, FootprintEmitterComponent emitter) - { - emitter.TrackColor = emitter.AccumulatedColor == 0f ? color : Color.InterpolateBetween(emitter.TrackColor, color, emitter.ColorBlendFactor); - emitter.AccumulatedColor += quantity; - } + if (puddleSolutions.Volume < transferVolume) + transferVolume = puddleSolutions.Volume.Float(); + + if (transferVolume <= 0) + return; + + var splitSolution = _solutionSystem.SplitSolution(puddle.Solution.Value, transferVolume); + + _solutionSystem.AddSolution(emitter.Solution.Value, splitSolution); +} } diff --git a/Content.Shared/_Sunrise/Footprints/FootprintsSerializables.cs b/Content.Shared/_Sunrise/Footprints/FootprintsSerializables.cs index 337ce8c544..640910d038 100644 --- a/Content.Shared/_Sunrise/Footprints/FootprintsSerializables.cs +++ b/Content.Shared/_Sunrise/Footprints/FootprintsSerializables.cs @@ -42,7 +42,7 @@ public sealed partial class PuddleFootprintComponent : Component /// Ratio determining how much of puddle's color transfers to footprints /// [ViewVariables(VVAccess.ReadWrite)] - public float ColorTransferRatio = 0.5f; + public float TransferVolume = 2.5f; /// /// Percentage of water content above which footprints won't be created @@ -106,12 +106,6 @@ public sealed partial class FootprintEmitterComponent : Component [ViewVariables(VVAccess.ReadOnly), DataField] public EntProtoId FootprintPrototype = "Footstep"; - /// - /// Current color of footprints - /// - [ViewVariables(VVAccess.ReadOnly), DataField] - public Color TrackColor = Color.FromHex("#00000000"); - /// /// Distance between footprints when walking /// @@ -124,11 +118,14 @@ public sealed partial class FootprintEmitterComponent : Component [DataField] public float DragMarkInterval = 0.5f; - /// - /// Amount of color accumulated from puddles - /// - [DataField] - public float AccumulatedColor; + [ViewVariables(VVAccess.ReadOnly), DataField("solution")] + public string SolutionName = "foots"; + + [ViewVariables(VVAccess.ReadOnly), DataField("solutionRef")] + public Entity? Solution; + + [ViewVariables(VVAccess.ReadWrite)] + public float TransferVolume = 0.1f; /// /// Rate at which footprint color fades @@ -136,12 +133,6 @@ public sealed partial class FootprintEmitterComponent : Component [DataField] public float ColorFadeRate = 0.05f; - /// - /// Current reagent being transferred to footprints - /// - [DataField] - public string? CurrentReagent; - /// /// Offset from entity center for footprint placement /// @@ -157,11 +148,6 @@ public sealed partial class FootprintEmitterComponent : Component /// Position of last footprint /// public Vector2 LastStepPosition = Vector2.Zero; - - /// - /// Factor for interpolating between colors when mixing - /// - public float ColorBlendFactor = 0.2f; } /// diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index d3617fa739..772a26c4bf 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -232,6 +232,9 @@ abstract: true components: - type: SolutionContainerManager + solutions: + foots: + maxVol: 5 - type: InjectableSolution solution: chemicals - type: Bloodstream