]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Use nav beacon locations for announcements (#26437)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Thu, 28 Mar 2024 05:53:18 +0000 (01:53 -0400)
committerGitHub <noreply@github.com>
Thu, 28 Mar 2024 05:53:18 +0000 (16:53 +1100)
* use nav beacon locations for announcements

* :thumbs_up:

15 files changed:
Content.Server/Dragon/DragonRiftSystem.cs
Content.Server/Explosion/EntitySystems/TriggerSystem.cs
Content.Server/Nuke/NukeSystem.cs
Content.Server/Pinpointer/NavMapSystem.cs
Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs
Content.Shared/Localizations/ContentLocalizationManager.cs
Content.Shared/Pinpointer/NavMapBeaconComponent.cs
Content.Shared/Pinpointer/SharedNavMapSystem.cs
Resources/Locale/en-US/_directions.ftl [new file with mode: 0644]
Resources/Locale/en-US/dragon/rifts.ftl
Resources/Locale/en-US/implant/implant.ftl
Resources/Locale/en-US/navmap-beacons/station_map.ftl
Resources/Locale/en-US/nuke/nuke-component.ftl
Resources/Locale/en-US/shuttles/emergency.ftl
Resources/Prototypes/Entities/Objects/Devices/station_beacon.yml

index 7143280900cd92c8b74004d4338217ac1640dc76..101f030bfc10d8836b53e4cf6b196a87d96f69c5 100644 (file)
@@ -13,6 +13,7 @@ using Robust.Shared.Serialization.Manager;
 using System.Numerics;
 using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
+using Robust.Shared.Utility;
 
 namespace Content.Server.Dragon;
 
@@ -69,8 +70,9 @@ public sealed class DragonRiftSystem : EntitySystem
                 comp.State = DragonRiftState.AlmostFinished;
                 Dirty(uid, comp);
 
-                var location = xform.LocalPosition;
-                _chat.DispatchGlobalAnnouncement(Loc.GetString("carp-rift-warning", ("location", location)), playSound: false, colorOverride: Color.Red);
+                var msg = Loc.GetString("carp-rift-warning",
+                    ("location", FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString((uid, xform)))));
+                _chat.DispatchGlobalAnnouncement(msg, playSound: false, colorOverride: Color.Red);
                 _audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
                 _navMap.SetBeaconEnabled(uid, true);
             }
index e24de5a2f66fd2ab52d8d67d500c7046eac44753..94f55855362e4548240901736f04fdf52694f93c 100644 (file)
@@ -3,6 +3,7 @@ using Content.Server.Body.Systems;
 using Content.Server.Chemistry.Containers.EntitySystems;
 using Content.Server.Explosion.Components;
 using Content.Server.Flash;
+using Content.Server.Pinpointer;
 using Content.Shared.Flash.Components;
 using Content.Server.Radio.EntitySystems;
 using Content.Shared.Chemistry.Components;
@@ -31,6 +32,7 @@ using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
 using Robust.Shared.Player;
 using Content.Shared.Coordinates;
+using Robust.Shared.Utility;
 
 namespace Content.Server.Explosion.EntitySystems
 {
@@ -67,6 +69,7 @@ namespace Content.Server.Explosion.EntitySystems
         [Dependency] private readonly BodySystem _body = default!;
         [Dependency] private readonly SharedAudioSystem _audio = default!;
         [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+        [Dependency] private readonly NavMapSystem _navMap = default!;
         [Dependency] private readonly RadioSystem _radioSystem = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -185,12 +188,7 @@ namespace Content.Server.Explosion.EntitySystems
                 return;
 
             // Gets location of the implant
-            var ownerXform = Transform(uid);
-            var pos = ownerXform.MapPosition;
-            var x = (int) pos.X;
-            var y = (int) pos.Y;
-            var posText = $"({x}, {y})";
-
+            var posText = FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString(uid));
             var critMessage = Loc.GetString(component.CritMessage, ("user", implanted.ImplantedEntity.Value), ("position", posText));
             var deathMessage = Loc.GetString(component.DeathMessage, ("user", implanted.ImplantedEntity.Value), ("position", posText));
 
index 17c25d1fe9f0e1eb3fc91d9beb8e2b6d5e45eea5..c996f05ec4abbc5633baba97625365268e3e5e65 100644 (file)
@@ -21,6 +21,7 @@ using Robust.Shared.Map;
 using Robust.Shared.Map.Components;
 using Robust.Shared.Player;
 using Robust.Shared.Random;
+using Robust.Shared.Utility;
 
 namespace Content.Server.Nuke;
 
@@ -463,7 +464,8 @@ public sealed class NukeSystem : EntitySystem
 
         // warn a crew
         var announcement = Loc.GetString("nuke-component-announcement-armed",
-            ("time", (int) component.RemainingTime), ("position", posText));
+            ("time", (int) component.RemainingTime),
+            ("location", FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString((uid, nukeXform)))));
         var sender = Loc.GetString("nuke-component-announcement-sender");
         _chatSystem.DispatchStationAnnouncement(stationUid ?? uid, announcement, sender, false, null, Color.Red);
 
index 36fb39975e54d1760fa5c72af0561b15d2a10f95..2a5639886ed5654465dd237ae24f30cd37ab97c9 100644 (file)
@@ -1,12 +1,16 @@
+using System.Diagnostics.CodeAnalysis;
 using Content.Server.Administration.Logs;
 using Content.Server.Station.Systems;
 using Content.Server.Warps;
 using Content.Shared.Database;
 using Content.Shared.Examine;
+using Content.Shared.Localizations;
 using Content.Shared.Pinpointer;
 using Content.Shared.Tag;
+using JetBrains.Annotations;
 using Robust.Server.GameObjects;
 using Robust.Shared.GameStates;
+using Robust.Shared.Map;
 using Robust.Shared.Map.Components;
 using Robust.Shared.Physics;
 using Robust.Shared.Physics.Components;
@@ -22,10 +26,15 @@ public sealed class NavMapSystem : SharedNavMapSystem
     [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
     [Dependency] private readonly TagSystem _tags = default!;
     [Dependency] private readonly MapSystem _map = default!;
+    [Dependency] private readonly IMapManager _mapManager = default!;
+    [Dependency] private readonly TransformSystem _transform = default!;
 
     private EntityQuery<PhysicsComponent> _physicsQuery;
     private EntityQuery<TagComponent> _tagQuery;
 
+    public const float CloseDistance = 15f;
+    public const float FarDistance = 30f;
+
     public override void Initialize()
     {
         base.Initialize();
@@ -40,6 +49,7 @@ public sealed class NavMapSystem : SharedNavMapSystem
         SubscribeLocalEvent<NavMapComponent, ComponentGetState>(OnGetState);
         SubscribeLocalEvent<GridSplitEvent>(OnNavMapSplit);
 
+        SubscribeLocalEvent<NavMapBeaconComponent, MapInitEvent>(OnNavMapBeaconMapInit);
         SubscribeLocalEvent<NavMapBeaconComponent, ComponentStartup>(OnNavMapBeaconStartup);
         SubscribeLocalEvent<NavMapBeaconComponent, AnchorStateChangedEvent>(OnNavMapBeaconAnchor);
 
@@ -57,6 +67,16 @@ public sealed class NavMapSystem : SharedNavMapSystem
         RefreshGrid(ev.GridId, comp, Comp<MapGridComponent>(ev.GridId));
     }
 
+    private void OnNavMapBeaconMapInit(EntityUid uid, NavMapBeaconComponent component, MapInitEvent args)
+    {
+        if (component.DefaultText == null || component.Text != null)
+            return;
+
+        component.Text = Loc.GetString(component.DefaultText);
+        Dirty(uid, component);
+        RefreshNavGrid(uid);
+    }
+
     private void OnNavMapBeaconStartup(EntityUid uid, NavMapBeaconComponent component, ComponentStartup args)
     {
         RefreshNavGrid(uid);
@@ -384,4 +404,101 @@ public sealed class NavMapSystem : SharedNavMapSystem
 
         SetBeaconEnabled(uid, !comp.Enabled, comp);
     }
+
+    /// <summary>
+    /// For a given position, tries to find the nearest configurable beacon that is marked as visible.
+    /// This is used for things like announcements where you want to find the closest "landmark" to something.
+    /// </summary>
+    [PublicAPI]
+    public bool TryGetNearestBeacon(Entity<TransformComponent?> ent,
+        [NotNullWhen(true)] out Entity<NavMapBeaconComponent>? beacon,
+        [NotNullWhen(true)] out MapCoordinates? beaconCoords)
+    {
+        beacon = null;
+        beaconCoords = null;
+        if (!Resolve(ent, ref ent.Comp))
+            return false;
+
+        return TryGetNearestBeacon(_transform.GetMapCoordinates(ent, ent.Comp), out beacon, out beaconCoords);
+    }
+
+    /// <summary>
+    /// For a given position, tries to find the nearest configurable beacon that is marked as visible.
+    /// This is used for things like announcements where you want to find the closest "landmark" to something.
+    /// </summary>
+    public bool TryGetNearestBeacon(MapCoordinates coordinates,
+        [NotNullWhen(true)] out Entity<NavMapBeaconComponent>? beacon,
+        [NotNullWhen(true)] out MapCoordinates? beaconCoords)
+    {
+        beacon = null;
+        beaconCoords = null;
+        var minDistance = float.PositiveInfinity;
+
+        var query = EntityQueryEnumerator<ConfigurableNavMapBeaconComponent, NavMapBeaconComponent, TransformComponent>();
+        while (query.MoveNext(out var uid, out _, out var navBeacon, out var xform))
+        {
+            if (!navBeacon.Enabled)
+                continue;
+
+            if (navBeacon.Text == null)
+                continue;
+
+            if (coordinates.MapId != xform.MapID)
+                continue;
+
+            var coords = _transform.GetWorldPosition(xform);
+            var distanceSquared = (coordinates.Position - coords).LengthSquared();
+            if (!float.IsInfinity(minDistance) && distanceSquared >= minDistance)
+                continue;
+
+            minDistance = distanceSquared;
+            beacon = (uid, navBeacon);
+            beaconCoords = new MapCoordinates(coords, xform.MapID);
+        }
+
+        return beacon != null;
+    }
+
+    [PublicAPI]
+    public string GetNearestBeaconString(Entity<TransformComponent?> ent)
+    {
+        if (!Resolve(ent, ref ent.Comp))
+            return Loc.GetString("nav-beacon-pos-no-beacons");
+
+        return GetNearestBeaconString(_transform.GetMapCoordinates(ent, ent.Comp));
+    }
+
+    public string GetNearestBeaconString(MapCoordinates coordinates)
+    {
+        if (!TryGetNearestBeacon(coordinates, out var beacon, out var pos))
+            return Loc.GetString("nav-beacon-pos-no-beacons");
+
+        var gridOffset = Angle.Zero;
+        if (_mapManager.TryFindGridAt(pos.Value, out var grid, out _))
+            gridOffset = Transform(grid).LocalRotation;
+
+        // get the angle between the two positions, adjusted for the grid rotation so that
+        // we properly preserve north in relation to the grid.
+        var dir = (pos.Value.Position - coordinates.Position).ToWorldAngle();
+        var adjustedDir = (dir - gridOffset).GetDir();
+
+        var length = (pos.Value.Position - coordinates.Position).Length();
+        if (length < CloseDistance)
+        {
+            return Loc.GetString("nav-beacon-pos-format",
+                ("color", beacon.Value.Comp.Color),
+                ("marker", beacon.Value.Comp.Text!));
+        }
+
+        var modifier = length > FarDistance
+            ? Loc.GetString("nav-beacon-pos-format-direction-mod-far")
+            : string.Empty;
+
+        // we can null suppress the text being null because TRyGetNearestVisibleStationBeacon always gives us a beacon with not-null text.
+        return Loc.GetString("nav-beacon-pos-format-direction",
+            ("modifier", modifier),
+            ("direction", ContentLocalizationManager.FormatDirection(adjustedDir).ToLowerInvariant()),
+            ("color", beacon.Value.Comp.Color),
+            ("marker", beacon.Value.Comp.Text!));
+    }
 }
index 39b76f7d324974d3eff6553560e23c36f7bea91c..a7f83f2e158be7783f582dcff7cfd77152f51fbb 100644 (file)
@@ -8,6 +8,7 @@ using Content.Server.Communications;
 using Content.Server.DeviceNetwork.Components;
 using Content.Server.DeviceNetwork.Systems;
 using Content.Server.GameTicking.Events;
+using Content.Server.Pinpointer;
 using Content.Server.Popups;
 using Content.Server.RoundEnd;
 using Content.Server.Screens.Components;
@@ -33,6 +34,7 @@ using Robust.Shared.Map.Components;
 using Robust.Shared.Player;
 using Robust.Shared.Random;
 using Robust.Shared.Timing;
+using Robust.Shared.Utility;
 
 namespace Content.Server.Shuttles.Systems;
 
@@ -55,6 +57,7 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
     [Dependency] private readonly DockingSystem _dock = default!;
     [Dependency] private readonly EntityManager _entityManager = default!;
     [Dependency] private readonly IdCardSystem _idSystem = default!;
+    [Dependency] private readonly NavMapSystem _navMap = default!;
     [Dependency] private readonly MapLoaderSystem _map = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
     [Dependency] private readonly RoundEndSystem _roundEnd = default!;
@@ -307,11 +310,8 @@ public sealed partial class EmergencyShuttleSystem : EntitySystem
         }
         else
         {
-            if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
-            {
-                var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
-                _chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
-            }
+            var location = FormattedMessage.RemoveMarkup(_navMap.GetNearestBeaconString((stationShuttle.EmergencyShuttle.Value, xform)));
+            _chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("direction", location)), playDefaultSound: false);
 
             _logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}");
             // TODO: Need filter extensions or something don't blame me.
index 0a06d9ba4f308b987693f16328ce78133e08f396..3c311f43821ca18f3f7e196d27eb0057fdf52010 100644 (file)
@@ -119,6 +119,14 @@ namespace Content.Shared.Localizations
             };
         }
 
+        /// <summary>
+        /// Formats a direction struct as a human-readable string.
+        /// </summary>
+        public static string FormatDirection(Direction dir)
+        {
+            return Loc.GetString($"zzzz-fmt-direction-{dir.ToString()}");
+        }
+
         private static ILocValue FormatLoc(LocArgs args)
         {
             var id = ((LocValueString) args.Args[0]).Value;
index c3132ee37f3ac19bf164d62e9372efb0ef5d61d9..0a86bdd9d2e4d0eea3129b3e96af1cba47657960 100644 (file)
@@ -16,6 +16,13 @@ public sealed partial class NavMapBeaconComponent : Component
     [AutoNetworkedField]
     public string? Text;
 
+    /// <summary>
+    /// A localization string that populates <see cref="Text"/> if it is null at mapinit.
+    /// Used so that mappers can still override Text while mapping.
+    /// </summary>
+    [DataField]
+    public LocId? DefaultText;
+
     [ViewVariables(VVAccess.ReadWrite), DataField]
     [AutoNetworkedField]
     public Color Color = Color.Orange;
index 7a62e6aabed53b55455f2ef72742635f25aa339f..17f86ac7e6807210a1a75d3b9e92c660114f4318 100644 (file)
@@ -8,13 +8,6 @@ public abstract class SharedNavMapSystem : EntitySystem
 {
     public const byte ChunkSize = 4;
 
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        SubscribeLocalEvent<NavMapBeaconComponent, MapInitEvent>(OnNavMapBeaconMapInit);
-    }
-
     /// <summary>
     /// Converts the chunk's tile into a bitflag for the slot.
     /// </summary>
@@ -38,13 +31,6 @@ public abstract class SharedNavMapSystem : EntitySystem
         return new Vector2i(x, y);
     }
 
-    private void OnNavMapBeaconMapInit(EntityUid uid, NavMapBeaconComponent component, MapInitEvent args)
-    {
-        component.Text ??= string.Empty;
-        component.Text = Loc.GetString(component.Text);
-        Dirty(uid, component);
-    }
-
     [Serializable, NetSerializable]
     protected sealed class NavMapComponentState : ComponentState
     {
diff --git a/Resources/Locale/en-US/_directions.ftl b/Resources/Locale/en-US/_directions.ftl
new file mode 100644 (file)
index 0000000..7e4b82d
--- /dev/null
@@ -0,0 +1,8 @@
+zzzz-fmt-direction-North = North
+zzzz-fmt-direction-South = South
+zzzz-fmt-direction-East = East
+zzzz-fmt-direction-West = West
+zzzz-fmt-direction-NorthEast = NorthEast
+zzzz-fmt-direction-SouthEast = SouthEast
+zzzz-fmt-direction-NorthWest = NorthWest
+zzzz-fmt-direction-SouthWest = SouthWest
index 5ad061abf96efff4121f6071ee35bd86e8c24714..c182ebf10ce31e3e670362b33ea1c46d54130ed1 100644 (file)
@@ -1,4 +1,4 @@
-carp-rift-warning = A rift is causing an unnaturally large energy flux at {$location}. Stop it at all costs!
+carp-rift-warning = A rift is causing an unnaturally large energy flux {$location}. Stop it at all costs!
 carp-rift-duplicate = Cannot have 2 charging rifts at the same time!
 carp-rift-examine = It is [color=yellow]{$percentage}%[/color] charged!
 carp-rift-max = You have reached your maximum amount of rifts
index 2f6ab9e4e2f3bef99a50bea339684e8be65dd8c0..b93d43105a8374f4eaddb84d246267fd977c4220 100644 (file)
@@ -22,5 +22,5 @@ scramble-implant-activated-popup = Your appearance shifts and changes!
 
 ## Implant Messages
 
-deathrattle-implant-dead-message = {$user} has died at {$position}.
-deathrattle-implant-critical-message = {$user} life signs critical, immediate assistance required at {$position}.
+deathrattle-implant-dead-message = {$user} has died {$position}.
+deathrattle-implant-critical-message = {$user} life signs critical, immediate assistance required {$position}.
index d58d93bdb4e97b1bf359dda59f6abe4d3b2e4a43..1563e0abaf25f8bb65596602761493284c545832 100644 (file)
@@ -11,3 +11,8 @@ nav-beacon-examine-text = It is [color={$enabled ->
     [true] forestgreen]on
     *[false] crimson]off
 }[/color] and the display reads [color={$color}]"{$label}"[/color]
+
+nav-beacon-pos-no-beacons = in the middle of nowhere
+nav-beacon-pos-format = [color={$color}]near {$marker}[/color]
+nav-beacon-pos-format-direction = [color={$color}]{$modifier}{$direction} of {$marker}[/color]
+nav-beacon-pos-format-direction-mod-far = far {""}
index b2a61dfcc2cd86e285a3d7ecbb97589542ae4e7f..981dd8b6ae37bb242d7599f76886dd9543f7076c 100644 (file)
@@ -1,6 +1,6 @@
 nuke-component-cant-anchor-floor = The anchoring bolts fail to lock into the floor!
 nuke-component-announcement-sender = Nuclear Fission Explosive
-nuke-component-announcement-armed = Attention! The station's self-destruct mechanism has been engaged at global coordinates {$position}. {$time} seconds until detonation. If this was made in error, the mechanism may still be disarmed.
+nuke-component-announcement-armed = Attention! The station's self-destruct mechanism has been engaged {$location}. {$time} seconds until detonation. If this was made in error, the mechanism may still be disarmed.
 nuke-component-announcement-unarmed = The station's self-destruct was deactivated! Have a nice day!
 nuke-component-announcement-send-codes = Attention! Self-destruction codes have been sent to designated fax machines.
 nuke-component-doafter-warning = You start fiddling with wires and knobs in order to disarm the nuke.. This may take a while.
index 57d4d09effdfaca8911959a4b66337b95750cdf3..c71629113514bf12d47b26bf56d5a671471fcec3 100644 (file)
@@ -15,7 +15,7 @@ emergency-shuttle-left = The Emergency Shuttle has left the station. Estimate {$
 emergency-shuttle-launch-time = The emergency shuttle will launch in {$consoleAccumulator} seconds.
 emergency-shuttle-docked = The Emergency Shuttle has docked with the station on the {$direction} side. It will leave in {$time} seconds.
 emergency-shuttle-good-luck = The Emergency Shuttle is unable to find a station. Good luck.
-emergency-shuttle-nearby = The Emergency Shuttle is unable to find a valid docking port. It has warped in {$direction} of the station.
+emergency-shuttle-nearby = The Emergency Shuttle is unable to find a valid docking port. It has warped {$direction}.
 
 # Emergency shuttle console popup / announcement
 emergency-shuttle-console-no-early-launches = Early launch is disabled
index 6cf66ba04211e7f829efa2da187e71b9af8a4d2f..fa9071d3e9f58d653ff329ba00cadd14625a3bbd 100644 (file)
@@ -22,7 +22,7 @@
           False: {state: icon}
   - type: ConfigurableNavMapBeacon
   - type: NavMapBeacon
-    text: station-beacon-general
+    defaultText: station-beacon-general
     color: "#D4D4D496"
   - type: WarpPoint
   - type: ActivatableUI
   suffix: Command
   components:
   - type: NavMapBeacon
-    text: station-beacon-command
+    defaultText: station-beacon-command
     color: "#FFFF00"
 
 - type: entity
   suffix: Bridge
   components:
   - type: NavMapBeacon
-    text: station-beacon-bridge
+    defaultText: station-beacon-bridge
 
 - type: entity
   parent: DefaultStationBeaconCommand
   suffix: Vault
   components:
   - type: NavMapBeacon
-    text: station-beacon-vault
+    defaultText: station-beacon-vault
 
 - type: entity
   parent: DefaultStationBeaconCommand
   suffix: Captain's Quarters
   components:
   - type: NavMapBeacon
-    text: station-beacon-captain
+    defaultText: station-beacon-captain
 
 - type: entity
   parent: DefaultStationBeaconCommand
   suffix: HOP's Office
   components:
   - type: NavMapBeacon
-    text: station-beacon-hop
+    defaultText: station-beacon-hop
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Security
   components:
   - type: NavMapBeacon
-    text: station-beacon-security
+    defaultText: station-beacon-security
     color: "#DE3A3A"
 
 - type: entity
   suffix: Brig
   components:
   - type: NavMapBeacon
-    text: station-beacon-brig
+    defaultText: station-beacon-brig
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Warden's Office
   components:
   - type: NavMapBeacon
-    text: station-beacon-warden
+    defaultText: station-beacon-warden
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: HOS’s Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-hos
+    defaultText: station-beacon-hos
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Armory
   components:
   - type: NavMapBeacon
-    text: station-beacon-armory
+    defaultText: station-beacon-armory
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Perma Brig
   components:
   - type: NavMapBeacon
-    text: station-beacon-perma-brig
+    defaultText: station-beacon-perma-brig
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Detective's Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-detective
+    defaultText: station-beacon-detective
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Courtroom
   components:
   - type: NavMapBeacon
-    text: station-beacon-courtroom
+    defaultText: station-beacon-courtroom
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Law Office
   components:
   - type: NavMapBeacon
-    text: station-beacon-law
+    defaultText: station-beacon-law
 
 - type: entity
   parent: DefaultStationBeaconSecurity
   suffix: Sec Checkpoint
   components:
   - type: NavMapBeacon
-    text: station-beacon-security-checkpoint
+    defaultText: station-beacon-security-checkpoint
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Medical
   components:
   - type: NavMapBeacon
-    text: station-beacon-medical
+    defaultText: station-beacon-medical
     color: "#52B4E9"
 
 - type: entity
   suffix: Medbay
   components:
   - type: NavMapBeacon
-    text: station-beacon-medbay
+    defaultText: station-beacon-medbay
 
 - type: entity
   parent: DefaultStationBeaconMedical
   suffix: Chemistry
   components:
   - type: NavMapBeacon
-    text: station-beacon-chemistry
+    defaultText: station-beacon-chemistry
 
 - type: entity
   parent: DefaultStationBeaconMedical
   suffix: Cryonics
   components:
   - type: NavMapBeacon
-    text: station-beacon-cryonics
+    defaultText: station-beacon-cryonics
 
 - type: entity
   parent: DefaultStationBeaconMedical
   suffix: CMO's room
   components:
   - type: NavMapBeacon
-    text: station-beacon-cmo
+    defaultText: station-beacon-cmo
 
 - type: entity
   parent: DefaultStationBeaconMedical
   suffix: Morgue
   components:
   - type: NavMapBeacon
-    text: station-beacon-morgue
+    defaultText: station-beacon-morgue
 
 - type: entity
   parent: DefaultStationBeaconMedical
   suffix: Surgery
   components:
   - type: NavMapBeacon
-    text: station-beacon-surgery
+    defaultText: station-beacon-surgery
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Science
   components:
   - type: NavMapBeacon
-    text: station-beacon-science
+    defaultText: station-beacon-science
     color: "#D381C9"
 
 - type: entity
   suffix: Research and Development
   components:
   - type: NavMapBeacon
-    text: station-beacon-research-and-development
+    defaultText: station-beacon-research-and-development
 
 - type: entity
   parent: DefaultStationBeaconScience
   suffix: Research Server Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-research-server
+    defaultText: station-beacon-research-server
 
 - type: entity
   parent: DefaultStationBeaconScience
   suffix: RD's Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-research-director
+    defaultText: station-beacon-research-director
 
 - type: entity
   parent: DefaultStationBeaconScience
   suffix: Robotics
   components:
   - type: NavMapBeacon
-    text: station-beacon-robotics
+    defaultText: station-beacon-robotics
 
 - type: entity
   parent: DefaultStationBeaconScience
   suffix: Artifact Lab
   components:
   - type: NavMapBeacon
-    text: station-beacon-artifact-lab
+    defaultText: station-beacon-artifact-lab
 
 - type: entity
   parent: DefaultStationBeaconScience
   suffix: Anomaly Generator
   components:
   - type: NavMapBeacon
-    text: station-beacon-anomaly-gen
+    defaultText: station-beacon-anomaly-gen
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Supply
   components:
   - type: NavMapBeacon
-    text: station-beacon-supply
+    defaultText: station-beacon-supply
     color: "#A46106"
 
 - type: entity
   suffix: Cargo Reception
   components:
   - type: NavMapBeacon
-    text: station-beacon-cargo
+    defaultText: station-beacon-cargo
 
 - type: entity
   parent: DefaultStationBeaconSupply
   suffix: Cargo Bay
   components:
   - type: NavMapBeacon
-    text: station-beacon-cargo-bay
+    defaultText: station-beacon-cargo-bay
 
 - type: entity
   parent: DefaultStationBeaconSupply
   suffix: QM's Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-qm
+    defaultText: station-beacon-qm
 
 - type: entity
   parent: DefaultStationBeaconSupply
   suffix: Salvage
   components:
   - type: NavMapBeacon
-    text: station-beacon-salvage
+    defaultText: station-beacon-salvage
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Engineering
   components:
   - type: NavMapBeacon
-    text: station-beacon-engineering
+    defaultText: station-beacon-engineering
     color: "#EFB341"
 
 - type: entity
   suffix: CE's Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-ce
+    defaultText: station-beacon-ce
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: AME
   components:
   - type: NavMapBeacon
-    text: station-beacon-ame
+    defaultText: station-beacon-ame
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: Solars
   components:
   - type: NavMapBeacon
-    text: station-beacon-solars
+    defaultText: station-beacon-solars
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: Grav Gen
   components:
   - type: NavMapBeacon
-    text: station-beacon-gravgen
+    defaultText: station-beacon-gravgen
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: PA Control
   components:
   - type: NavMapBeacon
-    text: station-beacon-pa
+    defaultText: station-beacon-pa
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: SMES Power Bank
   components:
   - type: NavMapBeacon
-    text: station-beacon-smes
+    defaultText: station-beacon-smes
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: Telecoms
   components:
   - type: NavMapBeacon
-    text: station-beacon-telecoms
+    defaultText: station-beacon-telecoms
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: Atmospherics
   components:
   - type: NavMapBeacon
-    text: station-beacon-atmos
+    defaultText: station-beacon-atmos
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: TEG
   components:
   - type: NavMapBeacon
-    text: station-beacon-teg
+    defaultText: station-beacon-teg
 
 - type: entity
   parent: DefaultStationBeaconEngineering
   suffix: Tech Vault
   components:
   - type: NavMapBeacon
-    text: station-beacon-tech-vault
+    defaultText: station-beacon-tech-vault
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Service
   components:
   - type: NavMapBeacon
-    text: station-beacon-service
+    defaultText: station-beacon-service
     color: "#9FED58"
 
 - type: entity
   suffix: Kitchen
   components:
   - type: NavMapBeacon
-    text: station-beacon-kitchen
+    defaultText: station-beacon-kitchen
 
 - type: entity
   parent: DefaultStationBeaconService
   suffix: Bar
   components:
   - type: NavMapBeacon
-    text: station-beacon-bar
+    defaultText: station-beacon-bar
 
 - type: entity
   parent: DefaultStationBeaconService
   suffix: Botany
   components:
   - type: NavMapBeacon
-    text: station-beacon-botany
+    defaultText: station-beacon-botany
 
 - type: entity
   parent: DefaultStationBeaconService
   suffix: Janitor's Closet
   components:
   - type: NavMapBeacon
-    text: station-beacon-janitor
+    defaultText: station-beacon-janitor
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: AI
   components:
   - type: NavMapBeacon
-    text: station-beacon-ai
+    defaultText: station-beacon-ai
     color: "#2ed2fd"
 
 - type: entity
   suffix: AI Satellite
   components:
   - type: NavMapBeacon
-    text: station-beacon-ai-sat
+    defaultText: station-beacon-ai-sat
 
 - type: entity
   parent: DefaultStationBeaconAI
   suffix: AI Core
   components:
   - type: NavMapBeacon
-    text: station-beacon-ai-core
+    defaultText: station-beacon-ai-core
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Arrivals
   components:
   - type: NavMapBeacon
-    text: station-beacon-arrivals
+    defaultText: station-beacon-arrivals
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Evac
   components:
   - type: NavMapBeacon
-    text: station-beacon-evac
+    defaultText: station-beacon-evac
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: EVA Storage
   components:
   - type: NavMapBeacon
-    text: station-beacon-eva-storage
+    defaultText: station-beacon-eva-storage
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Chapel
   components:
   - type: NavMapBeacon
-    text: station-beacon-chapel
+    defaultText: station-beacon-chapel
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Library
   components:
   - type: NavMapBeacon
-    text: station-beacon-library
+    defaultText: station-beacon-library
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Theater
   components:
   - type: NavMapBeacon
-    text: station-beacon-theater
+    defaultText: station-beacon-theater
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Dorms
   components:
   - type: NavMapBeacon
-    text: station-beacon-dorms
+    defaultText: station-beacon-dorms
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Tool Room
   components:
   - type: NavMapBeacon
-    text: station-beacon-tools
+    defaultText: station-beacon-tools
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Disposals
   components:
   - type: NavMapBeacon
-    text: station-beacon-disposals
+    defaultText: station-beacon-disposals
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Cryosleep
   components:
   - type: NavMapBeacon
-    text: station-beacon-cryosleep
+    defaultText: station-beacon-cryosleep
 
 - type: entity
   parent: DefaultStationBeacon
   suffix: Escape Pod
   components:
   - type: NavMapBeacon
-    text: station-beacon-escape-pod
+    defaultText: station-beacon-escape-pod