Skip to content

Commit

Permalink
add: FootSteps
Browse files Browse the repository at this point in the history
  • Loading branch information
Spatison committed Oct 29, 2024
1 parent 63eef2d commit 391b155
Show file tree
Hide file tree
Showing 43 changed files with 541 additions and 2 deletions.
84 changes: 84 additions & 0 deletions Content.Client/_White/FootPrint/FootPrintsVisualizerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Content.Shared._White.FootPrint;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Random;

namespace Content.Client._White.FootPrint;

public sealed class FootPrintsVisualizerSystem : VisualizerSystem<FootPrintComponent>
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly IRobustRandom _random = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<FootPrintComponent, ComponentInit>(OnInitialized);
SubscribeLocalEvent<FootPrintComponent, ComponentShutdown>(OnShutdown);
}

private void OnInitialized(EntityUid uid, FootPrintComponent comp, ComponentInit args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;

sprite.LayerMapReserveBlank(FootPrintVisualLayers.Print);
UpdateAppearance(uid, comp, sprite);
}

private void OnShutdown(EntityUid uid, FootPrintComponent comp, ComponentShutdown args)
{
if (TryComp<SpriteComponent>(uid, out var sprite) &&
sprite.LayerMapTryGet(FootPrintVisualLayers.Print, out var layer))
{
sprite.RemoveLayer(layer);
}
}

private void UpdateAppearance(EntityUid uid, FootPrintComponent component, SpriteComponent sprite)
{
if (!sprite.LayerMapTryGet(FootPrintVisualLayers.Print, out var layer)
|| !TryComp<FootPrintsComponent>(component.PrintOwner, out var printsComponent)
|| !TryComp<AppearanceComponent>(uid, out var appearance))
return;

if (_appearance.TryGetData<FootPrintVisuals>(uid, FootPrintVisualState.State, out var printVisuals, appearance))
{
switch (printVisuals)
{
case FootPrintVisuals.BareFootPrint:
sprite.LayerSetState(layer,
printsComponent.RightStep
? new RSI.StateId(printsComponent.RightBarePrint)
: new RSI.StateId(printsComponent.LeftBarePrint),
printsComponent.RsiPath);
break;
case FootPrintVisuals.ShoesPrint:
sprite.LayerSetState(layer, new RSI.StateId(printsComponent.ShoesPrint), printsComponent.RsiPath);
break;
case FootPrintVisuals.SuitPrint:
sprite.LayerSetState(layer, new RSI.StateId(printsComponent.SuitPrint), printsComponent.RsiPath);
break;
case FootPrintVisuals.Dragging:
sprite.LayerSetState(layer, new RSI.StateId(_random.Pick(printsComponent.DraggingPrint)), printsComponent.RsiPath);
break;
default:
throw new ArgumentOutOfRangeException($"Unknown {printVisuals} parameter.");
}
}

if (!_appearance.TryGetData<Color>(uid, FootPrintVisualState.Color, out var printColor, appearance))
return;

sprite.LayerSetColor(layer, printColor);
}

protected override void OnAppearanceChange (EntityUid uid, FootPrintComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite is not { } sprite)
return;

UpdateAppearance(uid, component, sprite);
}
}
131 changes: 131 additions & 0 deletions Content.Server/_White/FootPrint/FootPrintsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using Content.Server.Atmos.Components;
using Content.Shared.Inventory;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared._White.FootPrint;
using Content.Shared.Standing;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Robust.Shared.Map;
using Robust.Shared.Random;

namespace Content.Server._White.FootPrint;

public sealed class FootPrintsSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly IMapManager _map = default!;

[Dependency] private readonly SharedSolutionContainerSystem _solution = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;

private EntityQuery<TransformComponent> _transformQuery;
private EntityQuery<MobThresholdsComponent> _mobThresholdQuery;
private EntityQuery<AppearanceComponent> _appearanceQuery;
private EntityQuery<LayingDownComponent> _layingQuery;

public override void Initialize()
{
base.Initialize();

_transformQuery = GetEntityQuery<TransformComponent>();
_mobThresholdQuery = GetEntityQuery<MobThresholdsComponent>();
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
_layingQuery = GetEntityQuery<LayingDownComponent>();

SubscribeLocalEvent<FootPrintsComponent, ComponentStartup>(OnStartupComponent);
SubscribeLocalEvent<FootPrintsComponent, MoveEvent>(OnMove);
}

private void OnStartupComponent(EntityUid uid, FootPrintsComponent comp, ComponentStartup args)
{
comp.StepSize += _random.NextFloat(-0.05f, 0.05f);
}

private void OnMove(EntityUid uid, FootPrintsComponent comp, ref MoveEvent args)
{
if (comp.PrintsColor.A <= 0f
|| !_transformQuery.TryComp(uid, out var transform)
|| !_mobThresholdQuery.TryComp(uid, out var mobThreshHolds)
|| !_map.TryFindGridAt(_transform.GetMapCoordinates((uid, transform)), out var gridUid, out _))
return;

var dragging = mobThreshHolds.CurrentThresholdState is MobState.Critical or MobState.Dead || _layingQuery.TryComp(uid, out var laying) && laying.IsCrawlingUnder;
var distance = (transform.LocalPosition - comp.StepPos).Length();
var stepSize = dragging ? comp.DragSize : comp.StepSize;

if (!(distance > stepSize))
return;

comp.RightStep = !comp.RightStep;

var entity = Spawn(comp.StepProtoId, CalcCoords(gridUid, comp, transform, dragging));
var footPrintComponent = Comp<FootPrintComponent>(entity); // There's NO way there's no footprint commponent in a FOOTPRINT

footPrintComponent.PrintOwner = uid;
Dirty(entity, footPrintComponent);

if (_appearanceQuery.TryComp(entity, out var appearance))
{
_appearance.SetData(entity, FootPrintVisualState.State, PickState(uid, dragging), appearance);
_appearance.SetData(entity, FootPrintVisualState.Color, comp.PrintsColor, appearance);
}

if (!_transformQuery.TryComp(entity, out var stepTransform))
return;

stepTransform.LocalRotation = dragging
? (transform.LocalPosition - comp.StepPos).ToAngle() + Angle.FromDegrees(-90f)
: transform.LocalRotation + Angle.FromDegrees(180f);

comp.PrintsColor = comp.PrintsColor.WithAlpha(ReduceAlpha(comp.PrintsColor.A, comp.ColorReduceAlpha));
comp.StepPos = transform.LocalPosition;

if (!TryComp<SolutionContainerManagerComponent>(entity, out var solutionContainer)
|| !_solution.ResolveSolution((entity, solutionContainer), footPrintComponent.SolutionName, ref footPrintComponent.Solution, out var solution)
|| string.IsNullOrWhiteSpace(comp.ReagentToTransfer) || solution.Volume >= 1)
return;

_solution.TryAddReagent(footPrintComponent.Solution.Value, comp.ReagentToTransfer, 1, out _);
}

private EntityCoordinates CalcCoords(EntityUid uid, FootPrintsComponent comp, TransformComponent transform, bool state)
{
if (state)
return new EntityCoordinates(uid, transform.LocalPosition);

var offset = comp.RightStep
? new Angle(Angle.FromDegrees(180f) + transform.LocalRotation).RotateVec(comp.OffsetPrint)
: new Angle(transform.LocalRotation).RotateVec(comp.OffsetPrint);

return new EntityCoordinates(uid, transform.LocalPosition + offset);
}

private FootPrintVisuals PickState(EntityUid uid, bool dragging)
{
var state = FootPrintVisuals.BareFootPrint;

if (_inventory.TryGetSlotEntity(uid, "shoes", out _))
state = FootPrintVisuals.ShoesPrint;

if (_inventory.TryGetSlotEntity(uid, "outerClothing", out var suit) && TryComp<PressureProtectionComponent>(suit, out _))
state = FootPrintVisuals.SuitPrint;

if (dragging)
state = FootPrintVisuals.Dragging;

return state;
}

private float ReduceAlpha(float alpha, float reductionAmount)
{
if (alpha - reductionAmount > 0f)
alpha -= reductionAmount;
else
alpha = 0f;

return alpha;
}
}
53 changes: 53 additions & 0 deletions Content.Server/_White/FootPrint/PuddleFootPrintsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Linq;
using Content.Shared._White.FootPrint;
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;

namespace Content.Server._White.FootPrint;

public sealed class PuddleFootPrintsSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PuddleFootPrintsComponent, EndCollideEvent>(OnStepTrigger);
}

private void OnStepTrigger(EntityUid uid, PuddleFootPrintsComponent comp, ref EndCollideEvent args)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance)
|| !TryComp<PuddleComponent>(uid, out var puddle)
|| !TryComp<FootPrintsComponent>(args.OtherEntity, out var tripper)
|| !TryComp<SolutionContainerManagerComponent>(uid, out var solutionManager)
||!_solutionContainer.ResolveSolution((uid, solutionManager), puddle.SolutionName, ref puddle.Solution, out var solutions))
return;

// alles gut!
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();

if (waterQuantity / (totalSolutionQuantity / 100f) > comp.OffPercent || solutions.Contents.Count <= 0)
return;

tripper.ReagentToTransfer =
solutions.Contents.Aggregate((l, r) => l.Quantity > r.Quantity ? l : r).Reagent.Prototype;

if (_appearance.TryGetData(uid, PuddleVisuals.SolutionColor, out var color, appearance)
&& _appearance.TryGetData(uid, PuddleVisuals.CurrentVolume, out var volume, appearance))
AddColor((Color)color, (float)volume * comp.SizeRatio, tripper);

_solutionContainer.RemoveEachReagent(puddle.Solution.Value, 1);
}

private void AddColor(Color col, float quantity, FootPrintsComponent comp)
{
comp.PrintsColor = comp.ColorQuantity == 0f ? col : Color.InterpolateBetween(comp.PrintsColor, col, 0.2f);
comp.ColorQuantity += quantity;
}
}
23 changes: 23 additions & 0 deletions Content.Shared/_White/Footprint/FootPrintComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Content.Shared.Chemistry.Components;
using Robust.Shared.GameStates;

namespace Content.Shared._White.FootPrint;

/// <summary>
/// This is used for marking footsteps, handling footprint drawing.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class FootPrintComponent : Component
{
/// <summary>
/// Owner (with <see cref="FootPrintsComponent"/>) of a print (this component).
/// </summary>
[AutoNetworkedField]
public EntityUid PrintOwner;

[DataField]
public string SolutionName = "step";

[DataField]
public Entity<SolutionComponent>? Solution;
}
25 changes: 25 additions & 0 deletions Content.Shared/_White/Footprint/FootPrintVisuals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Robust.Shared.Serialization;

namespace Content.Shared._White.FootPrint;

[Serializable, NetSerializable]
public enum FootPrintVisuals : byte
{
BareFootPrint,
ShoesPrint,
SuitPrint,
Dragging
}

[Serializable, NetSerializable]
public enum FootPrintVisualState : byte
{
State,
Color
}

[Serializable, NetSerializable]
public enum FootPrintVisualLayers : byte
{
Print
}
64 changes: 64 additions & 0 deletions Content.Shared/_White/Footprint/FootPrintsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Numerics;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;

namespace Content.Shared._White.FootPrint;

[RegisterComponent]
public sealed partial class FootPrintsComponent : Component
{
[ViewVariables(VVAccess.ReadOnly), DataField]
public ResPath RsiPath = new("/Textures/_White/Effects/footprints.rsi");

// all of those are set as a layer
[ViewVariables(VVAccess.ReadOnly), DataField]
public string LeftBarePrint = "footprint-left-bare-human";

[ViewVariables(VVAccess.ReadOnly), DataField]
public string RightBarePrint = "footprint-right-bare-human";

[ViewVariables(VVAccess.ReadOnly), DataField]
public string ShoesPrint = "footprint-shoes";

[ViewVariables(VVAccess.ReadOnly), DataField]
public string SuitPrint = "footprint-suit";

[ViewVariables(VVAccess.ReadOnly), DataField]
public string[] DraggingPrint =
[
"dragging-1",
"dragging-2",
"dragging-3",
"dragging-4",
"dragging-5",
];
// yea, those

[ViewVariables(VVAccess.ReadOnly), DataField]
public EntProtoId<FootPrintComponent> StepProtoId = "Footstep";

[ViewVariables(VVAccess.ReadOnly), DataField]
public Color PrintsColor = Color.FromHex("#00000000");

[DataField]
public float StepSize = 0.7f;

[DataField]
public float DragSize = 0.5f;

[DataField]
public float ColorQuantity;

[DataField]
public float ColorReduceAlpha = 0.1f;

[DataField]
public string? ReagentToTransfer;

[DataField]
public Vector2 OffsetPrint = new(0.1f, 0f);

public bool RightStep = true;

public Vector2 StepPos = Vector2.Zero;
}
11 changes: 11 additions & 0 deletions Content.Shared/_White/Footprint/PuddleFootPrintsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Content.Shared._White.FootPrint;

[RegisterComponent]
public sealed partial class PuddleFootPrintsComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public float SizeRatio = 0.2f;

[ViewVariables(VVAccess.ReadWrite)]
public float OffPercent = 80f;
}
Loading

0 comments on commit 391b155

Please sign in to comment.