Use nav beacon locations for announcements (#26437)

* use nav beacon locations for announcements

* :thumbs_up:
This commit is contained in:
Nemanja
2024-03-28 01:53:18 -04:00
committed by GitHub
parent b064985f24
commit 766192f4b5
15 changed files with 231 additions and 98 deletions

View 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);
}

View 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));

View 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);

View 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!));
}
}

View 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.