Directional arrow (#118)

* arrow

* yoink orginal arrow rsi

* done

* fixes

* i just learnd about ignored components

* Update Content.Client/DirectionalArrowIndicator/DirectionalArrowIndicatorComponent.cs

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>

* customArrows

* docs

* more docs

* teg and blue arrow

* misc

* fixes

* remove color

* imma dummy

* meta

* soon to obsolete

* class not partial

---------

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
This commit is contained in:
InsoPL 2026-06-20 23:45:43 +02:00 • committed by GitHub
parent f7940beb48
commit a79f85248b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 194 additions and 118 deletions

View file

@ -0,0 +1,49 @@
using Robust.Shared.Prototypes;
using System.Numerics;
namespace Content.Client.DirectionalArrowIndicator;
/// <summary>
/// Component that manages directional arrow indicators that spawn clientside when an entity is examined.
/// Handled by <see cref="DirectionalArrowIndicatorSystem"/>
/// </summary>
[RegisterComponent]
public sealed partial class DirectionalArrowIndicatorComponent : Component
{
/// <summary>
/// The lifetime of the arrow indicator in seconds.
/// </summary>
[DataField]
public float Lifetime = 2f;
/// <summary>
/// List of arrows to spawn.
/// </summary>
[DataField]
public List<ArrowSpawnData> Arrows = new();
}
/// <summary>
/// Data for spawning a single directional arrow.
/// </summary>
[DataDefinition]
public sealed partial class ArrowSpawnData
{
/// <summary>
/// Offset relative to entity's position where the arrow should appear.
/// </summary>
[DataField]
public Vector2 Offset = Vector2.Zero;
/// <summary>
/// Rotation of the arrow.
/// </summary>
[DataField]
public Angle Rotation = Angle.Zero;
/// <summary>
/// Prototype ID of the arrow entity to spawn.
/// </summary>
[DataField]
public EntProtoId ArrowType = "RedDirectionalArrowIndicator";
}

View file

@ -0,0 +1,42 @@
using Content.Shared.Examine;
using Robust.Client.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Spawners;
namespace Content.Client.DirectionalArrowIndicator;
/// <summary>
/// System responsible for handling <see cref="DirectionalArrowIndicatorComponent"/>s,
/// spawning directional arrow indicators clientside when an entity is examined.
/// </summary>
public sealed partial class DirectionalArrowIndicatorSystem : EntitySystem
{
[Dependency] private TransformSystem _transform = default!;
private const float EdgeOffset = 0.78125f; // Used for moving arrow to the edge of the tile by default.
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DirectionalArrowIndicatorComponent, ExaminedEvent>(OnExamined);
}
private void OnExamined(Entity<DirectionalArrowIndicatorComponent> ent, ref ExaminedEvent args)
{
var arrows = ent.Comp.Arrows;
var lifetime = ent.Comp.Lifetime;
if (arrows.Count == 0)
arrows.Add(new ArrowSpawnData());
foreach (var arrowData in ent.Comp.Arrows)
{
var spawnedEnt = Spawn(arrowData.ArrowType, new EntityCoordinates(ent, arrowData.Offset.X, arrowData.Offset.Y + EdgeOffset));
_transform.SetLocalRotation(spawnedEnt, arrowData.Rotation);
EnsureComp<TimedDespawnComponent>(spawnedEnt, out var timedDespawn);
timedDespawn.Lifetime = lifetime;
}
}
}

View file

@ -15,8 +15,6 @@ public sealed partial class TurnstileSystem : SharedTurnstileSystem
[Dependency] private AnimationPlayerSystem _animationPlayer = default!;
[Dependency] private SpriteSystem _sprite = default!;
private static readonly EntProtoId ExamineArrow = "TurnstileArrow";
private const string AnimationKey = "Turnstile";
public override void Initialize()
@ -24,7 +22,6 @@ public sealed partial class TurnstileSystem : SharedTurnstileSystem
base.Initialize();
SubscribeLocalEvent<TurnstileComponent, AnimationCompletedEvent>(OnAnimationCompleted);
SubscribeLocalEvent<TurnstileComponent, ExaminedEvent>(OnExamined);
}
private void OnAnimationCompleted(Entity<TurnstileComponent> ent, ref AnimationCompletedEvent args)
@ -37,11 +34,6 @@ public sealed partial class TurnstileSystem : SharedTurnstileSystem
_sprite.LayerSetRsiState((ent.Owner, sprite), TurnstileVisualLayers.Base, new RSI.StateId(ent.Comp.DefaultState));
}
private void OnExamined(Entity<TurnstileComponent> ent, ref ExaminedEvent args)
{
Spawn(ExamineArrow, new EntityCoordinates(ent, 0, 0));
}
protected override void PlayAnimation(EntityUid uid, string stateId)
{
if (!TryComp<AnimationPlayerComponent>(uid, out var animation) || !TryComp<SpriteComponent>(uid, out var sprite))

View file

@ -1,8 +0,0 @@
namespace Content.Client.Power.Generation.Teg;
/// <seealso cref="TegSystem"/>
[RegisterComponent]
public sealed partial class TegCirculatorComponent : Component
{
}

View file

@ -1,29 +0,0 @@
using Content.Client.Examine;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.Client.Power.Generation.Teg;
/// <summary>
/// Handles client-side logic for the thermo-electric generator (TEG).
/// </summary>
/// <remarks>
/// <para>
/// TEG circulators show which direction the in- and outlet port is by popping up two floating arrows when examined.
/// </para>
/// </remarks>
/// <seealso cref="TegCirculatorComponent"/>
public sealed class TegSystem : EntitySystem
{
private static readonly EntProtoId ArrowPrototype = "TegCirculatorArrow";
public override void Initialize()
{
SubscribeLocalEvent<TegCirculatorComponent, ClientExaminedEvent>(CirculatorExamined);
}
private void CirculatorExamined(EntityUid uid, TegCirculatorComponent component, ClientExaminedEvent args)
{
Spawn(ArrowPrototype, new EntityCoordinates(uid, 0, 0));
}
}

View file

@ -21,7 +21,8 @@ namespace Content.Server.Entry
"HolidayRsiSwap",
"OptionsVisualizer",
"AnomalyScannerScreen",
"MultipartMachineGhost"
"MultipartMachineGhost",
"DirectionalArrowIndicator"
};
}
}

View file

@ -0,0 +1,34 @@
- type: entity
id: RedDirectionalArrowIndicator
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: Markers/directional_arrow_indicator.rsi
layers:
- state: red_arrow
- type: Tag
tags:
- HideContextMenu
- type: entity
id: BlueDirectionalArrowIndicator
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: Markers/directional_arrow_indicator.rsi
layers:
- state: blue_arrow
- type: Tag
tags:
- HideContextMenu
- type: entity
id: RedDirectionPointer
name: red direction pointer
description: Holographic arrow that points the way
components:
- type: Sprite
sprite: Markers/directional_arrow_indicator.rsi
layers:
- state: red_arrow
- type: Clickable

View file

@ -60,23 +60,7 @@
- type: Construction
graph: Turnstile
node: turnstile
- # Spawned by the client-side turnstile examine code to indicate the direction to pass through.
type: entity
id: TurnstileArrow
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: Structures/Doors/turnstile.rsi
color: "#FFFFFFBB"
layers:
- state: arrow
offset: 0, 0.78125
- type: TimedDespawn
lifetime: 2
- type: Tag
tags:
- HideContextMenu
- type: DirectionalArrowIndicator
# Genpop

View file

@ -1,4 +1,4 @@
- type: entity
- type: entity
id: Recycler
parent: BaseMachinePowered
name: recycler
@ -58,6 +58,10 @@
map: ["enum.RecyclerVisualLayers.Main"]
- type: Appearance
- type: RecyclerVisuals
- type: DirectionalArrowIndicator
arrows:
- offset: 0, -1.35
- offset: 0, 0
- type: CollideMaterialReclaimer
- type: MaterialReclaimer

View file

@ -1,4 +1,4 @@
- type: entity
- type: entity
id: TegCenter
name: thermo-electric generator
description: A high efficiency generator that uses energy transfer between hot and cold gases to produce electricity.
@ -185,22 +185,9 @@
- type: TegCirculator
- type: StealTarget
stealGroup: Teg
- # Spawned by the client-side circulator examine code to indicate the inlet/outlet direction.
type: entity
id: TegCirculatorArrow
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: Markers/teg_arrow.rsi
color: "#FFFFFFBB"
layers:
- state: arrow
offset: 0, 0.75
- state: arrow
offset: 0, -0.75
- type: TimedDespawn
lifetime: 2
- type: Tag
tags:
- HideContextMenu
- type: DirectionalArrowIndicator
arrows:
- offset: 0, -1.5
arrowType: BlueDirectionalArrowIndicator
- offset: 0, 0
arrowType: BlueDirectionalArrowIndicator

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,53 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Red arrow by EmoGarbage404 (github), Blue arrow by PJB3005",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "red_arrow",
"delays": [
[
0.5,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "blue_arrow",
"delays": [
[
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033,
0.033
]
]
}
]
}

View file

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 543 B

View file

@ -1,15 +0,0 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made by PJB3005",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "arrow",
"delays": [[0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033, 0.033]]
}
]
}

View file

@ -1,30 +1,12 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from OracleStation at https://github.com/OracleStation/OracleStation/blob/c1046bdd14674dc5a8631074aaa6650770b2937e/icons/obj/turnstile.dmi. Arrow by EmoGarbage404 (github).",
"copyright": "Taken from OracleStation at https://github.com/OracleStation/OracleStation/blob/c1046bdd14674dc5a8631074aaa6650770b2937e/icons/obj/turnstile.dmi.",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "arrow",
"delays": [
[
0.5,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "turnstile"
},