Ports Bloodstains And Footprints from EE (#2186)

* bogos binted

* bogos binted

* Update human.yml

Signed-off-by: Lyndomen <49795619+Lyndomen@users.noreply.github.com>

* Update skeleton.yml

Signed-off-by: Lyndomen <49795619+Lyndomen@users.noreply.github.com>

* untouch

Signed-off-by: Lyndomen <49795619+Lyndomen@users.noreply.github.com>

* untouch please

Signed-off-by: Lyndomen <49795619+Lyndomen@users.noreply.github.com>

* fixed real

---------

Signed-off-by: Lyndomen <49795619+Lyndomen@users.noreply.github.com>
This commit is contained in:
Lyndomen 2024-11-19 20:00:15 -05:00 committed by GitHub
parent 4734ed41da
commit fdb26756ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 524 additions and 2 deletions

View File

@ -0,0 +1,65 @@
using Content.Shared._EE.FootPrint;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Random;
namespace Content.Client._EE.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)
|| !_appearance.TryGetData<FootPrintVisuals>(uid, FootPrintVisualState.State, out var printVisuals, appearance))
return;
sprite.LayerSetState(layer, new RSI.StateId(printVisuals switch
{
FootPrintVisuals.BareFootPrint => printsComponent.RightStep ? printsComponent.RightBarePrint : printsComponent.LeftBarePrint,
FootPrintVisuals.ShoesPrint => printsComponent.ShoesPrint,
FootPrintVisuals.SuitPrint => printsComponent.SuitPrint,
FootPrintVisuals.Dragging => _random.Pick(printsComponent.DraggingPrint),
_ => throw new ArgumentOutOfRangeException($"Unknown {printVisuals} parameter.")
}), printsComponent.RsiPath);
if (_appearance.TryGetData<Color>(uid, FootPrintVisualState.Color, out var printColor, appearance))
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);
}
}

View File

@ -0,0 +1,122 @@
using Content.Server.Atmos.Components;
using Content.Shared._EE.FootPrint;
using Content.Shared.Inventory;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared._EE.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._EE.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 component, ComponentStartup args)
{
component.StepSize = Math.Max(0f, component.StepSize + _random.NextFloat(-0.05f, 0.05f));
}
private void OnMove(EntityUid uid, FootPrintsComponent component, ref MoveEvent args)
{
if (component.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;
var distance = (transform.LocalPosition - component.StepPos).Length();
var stepSize = dragging ? component.DragSize : component.StepSize;
if (!(distance > stepSize))
return;
component.RightStep = !component.RightStep;
var entity = Spawn(component.StepProtoId, CalcCoords(gridUid, component, transform, dragging));
var footPrintComponent = EnsureComp<FootPrintComponent>(entity);
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, component.PrintsColor, appearance);
}
if (!_transformQuery.TryComp(entity, out var stepTransform))
return;
stepTransform.LocalRotation = dragging
? (transform.LocalPosition - component.StepPos).ToAngle() + Angle.FromDegrees(-90f)
: transform.LocalRotation + Angle.FromDegrees(180f);
component.PrintsColor = component.PrintsColor.WithAlpha(Math.Max(0f, component.PrintsColor.A - component.ColorReduceAlpha));
component.StepPos = transform.LocalPosition;
if (!TryComp<SolutionContainerManagerComponent>(entity, out var solutionContainer)
|| !_solution.ResolveSolution((entity, solutionContainer), footPrintComponent.SolutionName, ref footPrintComponent.Solution, out var solution)
|| string.IsNullOrWhiteSpace(component.ReagentToTransfer) || solution.Volume >= 1)
return;
_solution.TryAddReagent(footPrintComponent.Solution.Value, component.ReagentToTransfer, 1, out _);
}
private EntityCoordinates CalcCoords(EntityUid uid, FootPrintsComponent component, TransformComponent transform, bool state)
{
if (state)
return new EntityCoordinates(uid, transform.LocalPosition);
var offset = component.RightStep
? new Angle(Angle.FromDegrees(180f) + transform.LocalRotation).RotateVec(component.OffsetPrint)
: new Angle(transform.LocalRotation).RotateVec(component.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;
}
}

View File

@ -0,0 +1,52 @@
using System.Linq;
using Content.Shared._EE.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._EE.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 component, 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;
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) > component.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 * component.SizeRatio, tripper);
_solutionContainer.RemoveEachReagent(puddle.Solution.Value, 1);
}
private void AddColor(Color col, float quantity, FootPrintsComponent component)
{
component.PrintsColor = component.ColorQuantity == 0f ? col : Color.InterpolateBetween(component.PrintsColor, col, component.ColorInterpolationFactor);
component.ColorQuantity += quantity;
}
}

View File

@ -0,0 +1,23 @@
using Content.Shared.Chemistry.Components;
using Robust.Shared.GameStates;
namespace Content.Shared._EE.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;
}

View File

@ -0,0 +1,25 @@
using Robust.Shared.Serialization;
namespace Content.Shared._EE.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
}

View File

@ -0,0 +1,88 @@
using System.Numerics;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared._EE.FootPrint;
[RegisterComponent]
public sealed partial class FootPrintsComponent : Component
{
[ViewVariables(VVAccess.ReadOnly), DataField]
public ResPath RsiPath = new("/Textures/_EE/Effects/footprints.rsi"); //DeltaV moved to its own space
// 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");
/// <summary>
/// The size scaling factor for footprint steps. Must be positive.
/// </summary>
[DataField]
public float StepSize = 0.7f;
/// <summary>
/// The size scaling factor for drag marks. Must be positive.
/// </summary>
[DataField]
public float DragSize = 0.5f;
/// <summary>
/// The amount of color to transfer from the source (e.g., puddle) to the footprint.
/// </summary>
[DataField]
public float ColorQuantity;
/// <summary>
/// The factor by which the alpha channel is reduced in subsequent footprints.
/// </summary>
[DataField]
public float ColorReduceAlpha = 0.1f;
[DataField]
public string? ReagentToTransfer;
[DataField]
public Vector2 OffsetPrint = new(0.1f, 0f);
/// <summary>
/// Tracks which foot should make the next print. True for right foot, false for left.
/// </summary>
public bool RightStep = true;
/// <summary>
/// The position of the last footprint in world coordinates.
/// </summary>
public Vector2 StepPos = Vector2.Zero;
/// <summary>
/// Controls how quickly the footprint color transitions between steps.
/// Value between 0 and 1, where higher values mean faster color changes.
/// </summary>
public float ColorInterpolationFactor = 0.2f;
}

View File

@ -0,0 +1,11 @@
namespace Content.Shared._EE.FootPrint;
[RegisterComponent]
public sealed partial class PuddleFootPrintsComponent : Component
{
[ViewVariables()]
public float SizeRatio = 0.2f;
[ViewVariables()]
public float OffPercent = 80f;
}

View File

@ -140,6 +140,9 @@
- CanPilot
- FootstepSound
- DoorBumpOpener
- type: FootPrints #DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-lizard" #DeltaV port from EE, blood splatter
rightBarePrint: "footprint-right-bare-lizard" #DeltaV port from EE, blood splatter
- type: entity
save: false

View File

@ -165,3 +165,47 @@
- type: Tag
tags:
- DNASolutionScannable
- type: PuddleFootPrints # DeltaV- Begin updates from EE Blood Puddle
- type: entity
name: footstep
id: Footstep
save: false
description: Trace of liquid
components:
- type: Clickable
- type: FootstepModifier
footstepSoundCollection:
collection: FootstepWater
params:
volume: 3
- type: Transform
noRot: false
- type: Sprite
drawdepth: FloorObjects
color: "#FFFFFF80"
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
slipFixture:
shape:
!type:PhysShapeAabb
bounds: "-0.4,-0.4,0.4,0.4"
mask:
- ItemMask
layer:
- SlipLayer
hard: false
- type: SolutionContainerManager
solutions:
step: { maxVol: 2 }
- type: FootPrint
- type: Puddle
solution: step
- type: Appearance
- type: SpawnOnDespawn
prototype: PuddleSparkle
- type: TimedDespawn
lifetime: 60 # DeltaV End updates from EE Blood Puddle

View File

@ -115,6 +115,9 @@
sprite: "Effects/creampie.rsi"
state: "creampie_arachnid"
visible: false
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-spider"
rightBarePrint: "footprint-right-bare-spider"
- type: Inventory
templateId: arachnid

View File

@ -219,6 +219,7 @@
- DoorBumpOpener
- AnomalyHost
- type: PotentialPsionic # DeltaV - organic species can all be psionic
- type: FootPrints # DeltaV port from EE, blood splatter
- type: entity
save: false

View File

@ -110,6 +110,9 @@
32:
sprite: Mobs/Species/Human/displacement.rsi
state: jumpsuit-female
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-diona"
rightBarePrint: "footprint-right-bare-diona"
- type: entity
parent: BaseSpeciesDummy

View File

@ -64,6 +64,9 @@
32:
sprite: Mobs/Species/Human/displacement.rsi
state: jumpsuit-female
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-dwarf"
rightBarePrint: "footprint-right-bare-dwarf"
- type: entity
parent: BaseSpeciesDummy

View File

@ -40,4 +40,4 @@
sizeMaps:
32:
sprite: Mobs/Species/Human/displacement.rsi
state: jumpsuit-female
state: jumpsuit-female

View File

@ -77,7 +77,9 @@
32:
sprite: Mobs/Species/Human/displacement.rsi
state: jumpsuit-female
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-lizard"
rightBarePrint: "footprint-right-bare-lizard"
- type: entity
parent: BaseSpeciesDummy

View File

@ -120,6 +120,9 @@
32:
sprite: Mobs/Species/Human/displacement.rsi
state: jumpsuit-female
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-slime"
rightBarePrint: "footprint-right-bare-slime"
- type: entity
parent: MobHumanDummy

View File

@ -130,6 +130,9 @@
32:
sprite: Mobs/Species/Vox/displacement.rsi
state: shoes
- type: FootPrints # DeltaV port from EE, blood splatter
leftBarePrint: "footprint-left-bare-lizard"
rightBarePrint: "footprint-right-bare-lizard"
- type: entity
parent: BaseSpeciesDummy

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

View File

@ -0,0 +1,71 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "IMPERIAL SPACE",
"states": [
{
"name": "footprint-left-bare-diona"
},
{
"name": "footprint-left-bare-dwarf"
},
{
"name": "footprint-left-bare-human"
},
{
"name": "footprint-left-bare-lizard"
},
{
"name": "footprint-left-bare-slime"
},
{
"name": "footprint-left-bare-spider"
},
{
"name": "footprint-right-bare-diona"
},
{
"name": "footprint-right-bare-dwarf"
},
{
"name": "footprint-right-bare-human"
},
{
"name": "footprint-right-bare-lizard"
},
{
"name": "footprint-right-bare-slime"
},
{
"name": "footprint-right-bare-spider"
},
{
"name": "footprint-shoes"
},
{
"name": "footprint-suit"
},
{
"name": "dragging-1"
},
{
"name": "dragging-2"
},
{
"name": "dragging-3"
},
{
"name": "dragging-4"
},
{
"name": "dragging-5"
},
{
"name": "dragging-test"
}
]
}