]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add the ability for station maps to track grids they are not on (#41248)
authorSlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Mon, 12 Jan 2026 02:47:47 +0000 (03:47 +0100)
committerGitHub <noreply@github.com>
Mon, 12 Jan 2026 02:47:47 +0000 (02:47 +0000)
* Initial commit

* Accidentally included the nukie map changes

* Fix the gridcheck

* Addressing review

* Review change

* Review comments

Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs
Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
Content.Server/Pinpointer/StationMapSystem.cs
Content.Shared/Pinpointer/NukeopsStationMapComponent.cs [new file with mode: 0644]
Content.Shared/Pinpointer/StationMapComponent.cs
Resources/Prototypes/Entities/Objects/Devices/station_map.yml
Resources/Textures/Objects/Devices/tablets.rsi/inhand-left-syndie.png [new file with mode: 0644]
Resources/Textures/Objects/Devices/tablets.rsi/inhand-right-syndie.png [new file with mode: 0644]
Resources/Textures/Objects/Devices/tablets.rsi/meta.json
Resources/Textures/Objects/Devices/tablets.rsi/syndie.png [new file with mode: 0644]

index 3d1eb1723c31ecdb5abef5271714e8dfec630d7b..49b383a7d7eb33a3be39402e50984f1ba4cdbd17 100644 (file)
@@ -17,7 +17,11 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface
         base.Open();
         EntityUid? gridUid = null;
 
-        if (EntMan.TryGetComponent<TransformComponent>(Owner, out var xform))
+        if (EntMan.TryGetComponent<StationMapComponent>(Owner, out var comp) && comp.TargetGrid != null)
+        {
+            gridUid = comp.TargetGrid;
+        }
+        else if (EntMan.TryGetComponent<TransformComponent>(Owner, out var xform))
         {
             gridUid = xform.GridUid;
         }
@@ -30,8 +34,8 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface
         {
             stationName = gridMetaData.EntityName;
         }
-        
-        if (EntMan.TryGetComponent<StationMapComponent>(Owner, out var comp) && comp.ShowLocation)
+
+        if (comp != null && comp.ShowLocation)
             _window.Set(stationName, gridUid, Owner);
         else
             _window.Set(stationName, gridUid, null);
index c669ca527888152c9df6050be86fd1f9b6c7a762..0dc906738f1411e689cb8e7fb67951449a31bb71 100644 (file)
@@ -86,6 +86,8 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
             return;
 
         component.TargetStation = RobustRandom.Pick(eligible);
+        var ev = new NukeopsTargetStationSelectedEvent(uid, component.TargetStation);
+        RaiseLocalEvent(ref ev);
     }
 
     #region Event Handlers
@@ -549,3 +551,20 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
         return null;
     }
 }
+
+/// <summary>
+/// Raised when a station has been assigned as a target for the NukeOps rule.
+/// </summary>
+[ByRefEvent]
+public readonly struct NukeopsTargetStationSelectedEvent(EntityUid ruleEntity, EntityUid? targetStation)
+{
+    /// <summary>
+    /// The entity containing the NukeOps gamerule.
+    /// </summary>
+    public readonly EntityUid RuleEntity = ruleEntity;
+
+    /// <summary>
+    /// The target station, if it exists.
+    /// </summary>
+    public readonly EntityUid? TargetStation = targetStation;
+}
index c8e5b226172ff461d717f6767ff50cb1d30455b3..bf2d2e2817fe89c1cbe1bc4e78f5559f6589c0a2 100644 (file)
@@ -1,7 +1,10 @@
+using Content.Server.GameTicking;
+using Content.Server.GameTicking.Rules;
+using Content.Server.GameTicking.Rules.Components;
 using Content.Shared.PowerCell;
 using Content.Shared.Pinpointer;
+using Content.Shared.Station;
 using Robust.Server.GameObjects;
-using Robust.Shared.Player;
 
 namespace Content.Server.Pinpointer;
 
@@ -9,12 +12,18 @@ public sealed class StationMapSystem : EntitySystem
 {
     [Dependency] private readonly UserInterfaceSystem _ui = default!;
     [Dependency] private readonly PowerCellSystem _cell = default!;
+    [Dependency] private readonly SharedStationSystem _station = default!;
+    [Dependency] private readonly SharedTransformSystem _xform = default!;
+    [Dependency] private readonly GameTicker _gameTicker = default!;
 
     public override void Initialize()
     {
         base.Initialize();
+        SubscribeLocalEvent<StationMapComponent, MapInitEvent>(OnMapInit);
         SubscribeLocalEvent<StationMapUserComponent, EntParentChangedMessage>(OnUserParentChanged);
 
+        SubscribeLocalEvent<NukeopsStationMapComponent, NukeopsTargetStationSelectedEvent>(OnNukeopsStationSelected);
+
         Subs.BuiEvents<StationMapComponent>(StationMapUiKey.Key, subs =>
         {
             subs.Event<BoundUIOpenedEvent>(OnStationMapOpened);
@@ -22,6 +31,33 @@ public sealed class StationMapSystem : EntitySystem
         });
     }
 
+    private void OnMapInit(Entity<StationMapComponent> ent, ref MapInitEvent args)
+    {
+        if (!ent.Comp.InitializeWithStation)
+            return;
+
+        // If we ever find a need to make more exceptions like this, just turn this into an event.
+        if (HasComp<NukeopsStationMapComponent>(ent))
+        {
+            foreach (var rule in _gameTicker.GetActiveGameRules())
+            {
+                if (TryComp<NukeopsRuleComponent>(rule, out var nukeopsRule) && nukeopsRule.TargetStation != null)
+                {
+                    ent.Comp.TargetGrid = _station.GetLargestGrid((nukeopsRule.TargetStation.Value, null));
+                    Dirty(ent);
+                    return;
+                }
+            }
+        }
+
+        var station = _station.GetStationInMap(_xform.GetMapId(ent.Owner));
+        if (station != null)
+        {
+            ent.Comp.TargetGrid = _station.GetLargestGrid((station.Value, null));
+            Dirty(ent);
+        }
+    }
+
     private void OnStationMapClosed(EntityUid uid, StationMapComponent component, BoundUIClosedEvent args)
     {
         if (!Equals(args.UiKey, StationMapUiKey.Key))
@@ -43,4 +79,19 @@ public sealed class StationMapSystem : EntitySystem
         var comp = EnsureComp<StationMapUserComponent>(args.Actor);
         comp.Map = uid;
     }
+
+    private void OnNukeopsStationSelected(Entity<NukeopsStationMapComponent> ent, ref NukeopsTargetStationSelectedEvent args)
+    {
+        if (args.TargetStation == null)
+            return;
+
+        if (!TryComp<StationMapComponent>(ent, out var stationMap) || !TryComp<RuleGridsComponent>(args.RuleEntity, out var ruleGrids))
+            return;
+
+        if (Transform(ent).MapID != ruleGrids.Map)
+            return;
+
+        stationMap.TargetGrid = _station.GetLargestGrid((args.TargetStation.Value, null));
+        Dirty(ent);
+    }
 }
diff --git a/Content.Shared/Pinpointer/NukeopsStationMapComponent.cs b/Content.Shared/Pinpointer/NukeopsStationMapComponent.cs
new file mode 100644 (file)
index 0000000..2b57959
--- /dev/null
@@ -0,0 +1,10 @@
+namespace Content.Shared.Pinpointer;
+
+/// <summary>
+/// Used to indicate that an entity with the StationMapComponent should be updated to target the TargetStation of NukeopsRuleComponent.
+/// Uses the most recent active NukeopsRule when spawned, or the NukeopsRule which spawned the grid that the entity is on.
+/// </summary>
+[RegisterComponent]
+public sealed partial class NukeopsStationMapComponent : Component
+{
+}
index 07cc99605ed2fd629fb488080db3a227e59dcbf2..bba46215d7b924491b85f1d1b332252c54170282 100644 (file)
@@ -1,11 +1,27 @@
+using Robust.Shared.GameStates;
+
 namespace Content.Shared.Pinpointer;
 
-[RegisterComponent]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
 public sealed partial class StationMapComponent : Component
 {
     /// <summary>
     /// Whether or not to show the user's location on the map.
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public bool ShowLocation = true;
+
+    /// <summary>
+    /// If true, when this entity initializes it will target and remember the station grid of the map the entity is in.
+    /// If there is no station, the entity will target a random station in the current session.
+    /// </summary>
+    [DataField]
+    public bool InitializeWithStation = false;
+
+    /// <summary>
+    /// The target grid that the map will display.
+    /// If null, it will display the user's current grid.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityUid? TargetGrid;
 }
index e440cec09ae9cfdcf5505b2f6380d4a2301cca26..8724a4060b8571865622f9b577c342b4083e019d 100644 (file)
   id: HandheldStationMapUnpowered
   parent: BaseHandheldStationMap
   suffix: Handheld, Always Powered
+
+- type: entity
+  parent: HandheldStationMap
+  id: HandheldStationMapStatic
+  suffix: Handheld, Works Off-Station
+  components:
+  - type: StationMap
+    initializeWithStation: true
+
+- type: entity
+  parent: HandheldStationMap
+  id: HandheldStationMapNukeops
+  name: target station map
+  suffix: Handheld, NukeOps
+  description: Displays a readout of the target station.
+  components:
+  - type: Sprite
+    sprite: Objects/Devices/tablets.rsi
+    layers:
+    - state: tablet
+    - state: syndie
+      shader: unshaded
+  - type: Item
+    sprite: Objects/Devices/tablets.rsi
+    inhandVisuals:
+      left:
+      - state: inhand-left-syndie
+      right:
+      - state: inhand-right-syndie
+  - type: StationMap
+    showLocation: false
+    initializeWithStation: true
+  - type: NukeopsStationMap
+
diff --git a/Resources/Textures/Objects/Devices/tablets.rsi/inhand-left-syndie.png b/Resources/Textures/Objects/Devices/tablets.rsi/inhand-left-syndie.png
new file mode 100644 (file)
index 0000000..2bff152
Binary files /dev/null and b/Resources/Textures/Objects/Devices/tablets.rsi/inhand-left-syndie.png differ
diff --git a/Resources/Textures/Objects/Devices/tablets.rsi/inhand-right-syndie.png b/Resources/Textures/Objects/Devices/tablets.rsi/inhand-right-syndie.png
new file mode 100644 (file)
index 0000000..89e389c
Binary files /dev/null and b/Resources/Textures/Objects/Devices/tablets.rsi/inhand-right-syndie.png differ
index 5c572d32e45836c6588e2d776761f618bc69f504..224ccf739c74ce5295d7166aca48b3f31057bc60 100644 (file)
@@ -1,7 +1,7 @@
 {
     "version": 1,
     "license": "CC-BY-SA-3.0",
-    "copyright": "Taken from Baystation12 at https://github.com/Baystation12/Baystation12/tree/17e84546562b97d775cb26790a08e6d87e7f8077 and heavily modified by Flareguy for Space Station 14. Inhands by carousel",
+    "copyright": "Taken from Baystation12 at https://github.com/Baystation12/Baystation12/tree/17e84546562b97d775cb26790a08e6d87e7f8077 and heavily modified by Flareguy for Space Station 14. Inhands by carousel. Syndie versions modified from generic by SlamBamActionman",
     "size": {
         "x": 32,
         "y": 32
         {
             "name": "inhand-right",
             "directions": 4
+        },
+        {
+            "name": "syndie",
+        "delays": [
+            [
+            0.3,
+            0.3
+            ]
+        ]
+        },
+        {
+            "name": "inhand-left-syndie",
+            "directions": 4
+        },
+        {
+            "name": "inhand-right-syndie",
+            "directions": 4
         }
     ]
 }
diff --git a/Resources/Textures/Objects/Devices/tablets.rsi/syndie.png b/Resources/Textures/Objects/Devices/tablets.rsi/syndie.png
new file mode 100644 (file)
index 0000000..1c288c8
Binary files /dev/null and b/Resources/Textures/Objects/Devices/tablets.rsi/syndie.png differ