escape + kill objective changes (#17890)

* 3 space indent at start of line jumpscare

* _leftShuttles -> ShuttlesLeft

* stuff

* RequireDead override for the future

* fix 50% logic

* rouge

* pod 1984

* technically more "difficult"

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-07-09 22:00:08 +00:00
committed by GitHub
parent 53a0d1bc83
commit c346640ade
6 changed files with 441 additions and 394 deletions

View File

@@ -1,10 +1,8 @@
using Content.Server.Mind; using Content.Server.Mind;
using Content.Server.Objectives.Interfaces; using Content.Server.Objectives.Interfaces;
using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems;
using Content.Server.Station.Components;
using Content.Shared.Cuffs.Components; using Content.Shared.Cuffs.Components;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Objectives.Conditions namespace Content.Server.Objectives.Conditions
@@ -28,22 +26,6 @@ namespace Content.Server.Objectives.Conditions
public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ("Structures/Furniture/chairs.rsi"), "shuttle"); public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ("Structures/Furniture/chairs.rsi"), "shuttle");
private bool IsAgentOnShuttle(TransformComponent agentXform, EntityUid? shuttle)
{
if (shuttle == null)
return false;
var entMan = IoCManager.Resolve<IEntityManager>();
if (!entMan.TryGetComponent<MapGridComponent>(shuttle, out var shuttleGrid) ||
!entMan.TryGetComponent<TransformComponent>(shuttle, out var shuttleXform))
{
return false;
}
return shuttleXform.WorldMatrix.TransformBox(shuttleGrid.LocalAABB).Contains(agentXform.WorldPosition);
}
public float Progress public float Progress
{ {
get { get {
@@ -54,25 +36,22 @@ namespace Content.Server.Objectives.Conditions
|| !entMan.TryGetComponent<TransformComponent>(_mind.OwnedEntity, out var xform)) || !entMan.TryGetComponent<TransformComponent>(_mind.OwnedEntity, out var xform))
return 0f; return 0f;
var shuttleContainsAgent = false; if (mindSystem.IsCharacterDeadIc(_mind))
var agentIsAlive = !mindSystem.IsCharacterDeadIc(_mind); return 0f;
var agentIsEscaping = true;
if (entMan.TryGetComponent<CuffableComponent>(_mind.OwnedEntity, out var cuffed) if (entMan.TryGetComponent<CuffableComponent>(_mind.OwnedEntity, out var cuffed)
&& cuffed.CuffedHandCount > 0) && cuffed.CuffedHandCount > 0)
// You're not escaping if you're restrained!
agentIsEscaping = false;
// Any emergency shuttle counts for this objective.
foreach (var stationData in entMan.EntityQuery<StationEmergencyShuttleComponent>())
{ {
if (IsAgentOnShuttle(xform, stationData.EmergencyShuttle)) { // You're not escaping if you're restrained!
shuttleContainsAgent = true; return 0f;
break;
}
} }
return (shuttleContainsAgent && agentIsAlive && agentIsEscaping) ? 1f : 0f; // Any emergency shuttle counts for this objective, but not pods.
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
if (!emergencyShuttle.IsTargetEscaping(_mind.OwnedEntity.Value))
return 0f;
return 1f;
} }
} }

View File

@@ -1,6 +1,9 @@
using Content.Server.Mind; using Content.Server.Mind;
using Content.Server.Objectives.Interfaces; using Content.Server.Objectives.Interfaces;
using Content.Server.Shuttles.Systems;
using Content.Shared.CCVar;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Server.Objectives.Conditions namespace Content.Server.Objectives.Conditions
@@ -12,6 +15,11 @@ namespace Content.Server.Objectives.Conditions
protected Mind.Mind? Target; protected Mind.Mind? Target;
public abstract IObjectiveCondition GetAssigned(Mind.Mind mind); public abstract IObjectiveCondition GetAssigned(Mind.Mind mind);
/// <summary>
/// Whether the target must be truly dead, ignores missing evac.
/// </summary>
protected bool RequireDead = false;
public string Title public string Title
{ {
get get
@@ -37,13 +45,37 @@ namespace Content.Server.Objectives.Conditions
{ {
get get
{ {
var entityManager = IoCManager.Resolve<EntityManager>(); if (Target == null || Target.OwnedEntity == null)
var mindSystem = entityManager.System<MindSystem>(); return 1f;
return Target == null || mindSystem.IsCharacterDeadIc(Target) ? 1f : 0f;
var entMan = IoCManager.Resolve<EntityManager>();
var mindSystem = entMan.System<MindSystem>();
if (mindSystem.IsCharacterDeadIc(Target))
return 1f;
if (RequireDead)
return 0f;
// if evac is disabled then they really do have to be dead
var configMan = IoCManager.Resolve<IConfigurationManager>();
if (!configMan.GetCVar(CCVars.EmergencyShuttleEnabled))
return 0f;
// target is escaping so you fail
var emergencyShuttle = entMan.System<EmergencyShuttleSystem>();
if (emergencyShuttle.IsTargetEscaping(Target.OwnedEntity.Value))
return 0f;
// evac has left without the target, greentext since the target is afk in space with a full oxygen tank and coordinates off.
if (emergencyShuttle.ShuttlesLeft)
return 1f;
// if evac is still here and target hasn't boarded, show 50% to give you an indicator that you are doing good
return emergencyShuttle.EmergencyShuttleArrived ? 0f : 0.5f;
} }
} }
public float Difficulty => 2f; public float Difficulty => 1.75f;
public bool Equals(IObjectiveCondition? other) public bool Equals(IObjectiveCondition? other)
{ {

View File

@@ -71,7 +71,10 @@ public sealed partial class EmergencyShuttleSystem
/// </summary> /// </summary>
private bool _launchedShuttles; private bool _launchedShuttles;
private bool _leftShuttles; /// <summary>
/// Have the emergency shuttles left for CentCom?
/// </summary>
public bool ShuttlesLeft;
/// <summary> /// <summary>
/// Have we announced the launch? /// Have we announced the launch?
@@ -209,9 +212,9 @@ public sealed partial class EmergencyShuttleSystem
} }
// Departed // Departed
if (!_leftShuttles && _consoleAccumulator <= 0f) if (!ShuttlesLeft && _consoleAccumulator <= 0f)
{ {
_leftShuttles = true; ShuttlesLeft = true;
_chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}"))); _chatSystem.DispatchGlobalAnnouncement(Loc.GetString("emergency-shuttle-left", ("transitTime", $"{TransitTime:0}")));
Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken?.Token ?? default); Timer.Spawn((int) (TransitTime * 1000) + _bufferTime.Milliseconds, () => _roundEnd.EndRound(), _roundEndCancelToken?.Token ?? default);
@@ -309,7 +312,7 @@ public sealed partial class EmergencyShuttleSystem
{ {
_announced = false; _announced = false;
_roundEndCancelToken = null; _roundEndCancelToken = null;
_leftShuttles = false; ShuttlesLeft = false;
_launchedShuttles = false; _launchedShuttles = false;
_consoleAccumulator = float.MinValue; _consoleAccumulator = float.MinValue;
EarlyLaunchAuthorized = false; EarlyLaunchAuthorized = false;

View File

@@ -31,355 +31,388 @@ namespace Content.Server.Shuttles.Systems;
public sealed partial class EmergencyShuttleSystem : EntitySystem public sealed partial class EmergencyShuttleSystem : EntitySystem
{ {
/* /*
* Handles the escape shuttle + CentCom. * Handles the escape shuttle + CentCom.
*/ */
[Dependency] private readonly IAdminLogManager _logger = default!; [Dependency] private readonly IAdminLogManager _logger = default!;
[Dependency] private readonly IAdminManager _admin = default!; [Dependency] private readonly IAdminManager _admin = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly AccessReaderSystem _reader = default!; [Dependency] private readonly AccessReaderSystem _reader = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly CommunicationsConsoleSystem _commsConsole = default!; [Dependency] private readonly CommunicationsConsoleSystem _commsConsole = default!;
[Dependency] private readonly DockingSystem _dock = default!; [Dependency] private readonly DockingSystem _dock = default!;
[Dependency] private readonly IdCardSystem _idSystem = default!; [Dependency] private readonly IdCardSystem _idSystem = default!;
[Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly MapLoaderSystem _map = default!;
[Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly RoundEndSystem _roundEnd = default!; [Dependency] private readonly RoundEndSystem _roundEnd = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ShuttleSystem _shuttle = default!; [Dependency] private readonly ShuttleSystem _shuttle = default!;
[Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
private ISawmill _sawmill = default!; private ISawmill _sawmill = default!;
private const float ShuttleSpawnBuffer = 1f; private const float ShuttleSpawnBuffer = 1f;
private bool _emergencyShuttleEnabled; private bool _emergencyShuttleEnabled;
private const string DockTag = "DockEmergency"; private const string DockTag = "DockEmergency";
public override void Initialize() public override void Initialize()
{ {
_sawmill = Logger.GetSawmill("shuttle.emergency"); _sawmill = Logger.GetSawmill("shuttle.emergency");
_emergencyShuttleEnabled = _configManager.GetCVar(CCVars.EmergencyShuttleEnabled); _emergencyShuttleEnabled = _configManager.GetCVar(CCVars.EmergencyShuttleEnabled);
// Don't immediately invoke as roundstart will just handle it. // Don't immediately invoke as roundstart will just handle it.
_configManager.OnValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled); _configManager.OnValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart); SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
SubscribeLocalEvent<StationEmergencyShuttleComponent, ComponentStartup>(OnStationStartup); SubscribeLocalEvent<StationEmergencyShuttleComponent, ComponentStartup>(OnStationStartup);
SubscribeLocalEvent<StationCentcommComponent, ComponentShutdown>(OnCentcommShutdown); SubscribeLocalEvent<StationCentcommComponent, ComponentShutdown>(OnCentcommShutdown);
SubscribeLocalEvent<StationCentcommComponent, ComponentInit>(OnCentcommInit); SubscribeLocalEvent<StationCentcommComponent, ComponentInit>(OnCentcommInit);
SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition); SubscribeNetworkEvent<EmergencyShuttleRequestPositionMessage>(OnShuttleRequestPosition);
InitializeEmergencyConsole(); InitializeEmergencyConsole();
} }
private void OnRoundStart(RoundStartingEvent ev) private void OnRoundStart(RoundStartingEvent ev)
{ {
CleanupEmergencyConsole(); CleanupEmergencyConsole();
_roundEndCancelToken?.Cancel(); _roundEndCancelToken?.Cancel();
_roundEndCancelToken = new CancellationTokenSource(); _roundEndCancelToken = new CancellationTokenSource();
} }
private void OnCentcommShutdown(EntityUid uid, StationCentcommComponent component, ComponentShutdown args) private void OnCentcommShutdown(EntityUid uid, StationCentcommComponent component, ComponentShutdown args)
{ {
QueueDel(component.Entity); QueueDel(component.Entity);
component.Entity = EntityUid.Invalid; component.Entity = EntityUid.Invalid;
if (_mapManager.MapExists(component.MapId)) if (_mapManager.MapExists(component.MapId))
_mapManager.DeleteMap(component.MapId); _mapManager.DeleteMap(component.MapId);
component.MapId = MapId.Nullspace; component.MapId = MapId.Nullspace;
} }
private void SetEmergencyShuttleEnabled(bool value) private void SetEmergencyShuttleEnabled(bool value)
{ {
if (_emergencyShuttleEnabled == value) if (_emergencyShuttleEnabled == value)
return; return;
_emergencyShuttleEnabled = value; _emergencyShuttleEnabled = value;
if (value) if (value)
{ {
SetupEmergencyShuttle(); SetupEmergencyShuttle();
} }
else else
{ {
CleanupEmergencyShuttle(); CleanupEmergencyShuttle();
} }
} }
private void CleanupEmergencyShuttle() private void CleanupEmergencyShuttle()
{ {
var query = AllEntityQuery<StationCentcommComponent>(); var query = AllEntityQuery<StationCentcommComponent>();
while (query.MoveNext(out var uid, out _)) while (query.MoveNext(out var uid, out _))
{ {
RemCompDeferred<StationCentcommComponent>(uid); RemCompDeferred<StationCentcommComponent>(uid);
} }
} }
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);
UpdateEmergencyConsole(frameTime); UpdateEmergencyConsole(frameTime);
} }
public override void Shutdown() public override void Shutdown()
{ {
_configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled); _configManager.UnsubValueChanged(CCVars.EmergencyShuttleEnabled, SetEmergencyShuttleEnabled);
ShutdownEmergencyConsole(); ShutdownEmergencyConsole();
} }
/// <summary> /// <summary>
/// If the client is requesting debug info on where an emergency shuttle would dock. /// If the client is requesting debug info on where an emergency shuttle would dock.
/// </summary> /// </summary>
private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args) private void OnShuttleRequestPosition(EmergencyShuttleRequestPositionMessage msg, EntitySessionEventArgs args)
{ {
if (!_admin.IsAdmin((IPlayerSession) args.SenderSession)) if (!_admin.IsAdmin((IPlayerSession) args.SenderSession))
return; return;
var player = args.SenderSession.AttachedEntity; var player = args.SenderSession.AttachedEntity;
if (player is null) if (player is null)
return; return;
var station = _station.GetOwningStation(player.Value); var station = _station.GetOwningStation(player.Value);
if (!TryComp<StationEmergencyShuttleComponent>(station, out var stationShuttle) || if (!TryComp<StationEmergencyShuttleComponent>(station, out var stationShuttle) ||
!HasComp<ShuttleComponent>(stationShuttle.EmergencyShuttle)) !HasComp<ShuttleComponent>(stationShuttle.EmergencyShuttle))
{ {
return; return;
} }
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(station.Value)); var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(station.Value));
if (targetGrid == null) if (targetGrid == null)
return; return;
var config = _dock.GetDockingConfig(stationShuttle.EmergencyShuttle.Value, targetGrid.Value, DockTag); var config = _dock.GetDockingConfig(stationShuttle.EmergencyShuttle.Value, targetGrid.Value, DockTag);
if (config == null) if (config == null)
return; return;
RaiseNetworkEvent(new EmergencyShuttlePositionMessage() RaiseNetworkEvent(new EmergencyShuttlePositionMessage()
{ {
StationUid = targetGrid, StationUid = targetGrid,
Position = config.Area, Position = config.Area,
}); });
} }
/// <summary> /// <summary>
/// Calls the emergency shuttle for the station. /// Calls the emergency shuttle for the station.
/// </summary> /// </summary>
public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null) public void CallEmergencyShuttle(EntityUid stationUid, StationEmergencyShuttleComponent? stationShuttle = null)
{ {
if (!Resolve(stationUid, ref stationShuttle) || if (!Resolve(stationUid, ref stationShuttle) ||
!TryComp<TransformComponent>(stationShuttle.EmergencyShuttle, out var xform) || !TryComp<TransformComponent>(stationShuttle.EmergencyShuttle, out var xform) ||
!TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle)) !TryComp<ShuttleComponent>(stationShuttle.EmergencyShuttle, out var shuttle))
{ {
return; return;
} }
var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid)); var targetGrid = _station.GetLargestGrid(Comp<StationDataComponent>(stationUid));
// UHH GOOD LUCK // UHH GOOD LUCK
if (targetGrid == null) if (targetGrid == null)
{ {
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}"); _logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to dock with station {ToPrettyString(stationUid)}");
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false); _chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-good-luck"), playDefaultSound: false);
// TODO: Need filter extensions or something don't blame me. // TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true); _audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
return; return;
} }
var xformQuery = GetEntityQuery<TransformComponent>(); var xformQuery = GetEntityQuery<TransformComponent>();
if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag)) if (_shuttle.TryFTLDock(stationShuttle.EmergencyShuttle.Value, shuttle, targetGrid.Value, DockTag))
{ {
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform)) if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
{ {
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery); var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery);
_chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false); _chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-docked", ("time", $"{_consoleAccumulator:0}"), ("direction", angle.GetDir())), playDefaultSound: false);
} }
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} docked with stations"); _logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} docked with stations");
// TODO: Need filter extensions or something don't blame me. // TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true); _audio.PlayGlobal("/Audio/Announcements/shuttle_dock.ogg", Filter.Broadcast(), true);
} }
else else
{ {
if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform)) if (TryComp<TransformComponent>(targetGrid.Value, out var targetXform))
{ {
var angle = _dock.GetAngle(stationShuttle.EmergencyShuttle.Value, xform, targetGrid.Value, targetXform, xformQuery); 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); _chatSystem.DispatchStationAnnouncement(stationUid, Loc.GetString("emergency-shuttle-nearby", ("direction", angle.GetDir())), playDefaultSound: false);
} }
_logger.Add(LogType.EmergencyShuttle, LogImpact.High, $"Emergency shuttle {ToPrettyString(stationUid)} unable to find a valid docking port for {ToPrettyString(stationUid)}"); _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. // TODO: Need filter extensions or something don't blame me.
_audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true); _audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
} }
} }
private void OnCentcommInit(EntityUid uid, StationCentcommComponent component, ComponentInit args) private void OnCentcommInit(EntityUid uid, StationCentcommComponent component, ComponentInit args)
{ {
if (!_emergencyShuttleEnabled) if (!_emergencyShuttleEnabled)
return; return;
// Post mapinit? fancy // Post mapinit? fancy
if (TryComp<TransformComponent>(component.Entity, out var xform)) if (TryComp<TransformComponent>(component.Entity, out var xform))
{ {
component.MapId = xform.MapID; component.MapId = xform.MapID;
return; return;
} }
AddCentcomm(component); AddCentcomm(component);
} }
private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args) private void OnStationStartup(EntityUid uid, StationEmergencyShuttleComponent component, ComponentStartup args)
{ {
AddEmergencyShuttle(uid, component); AddEmergencyShuttle(uid, component);
} }
/// <summary> /// <summary>
/// Spawns the emergency shuttle for each station and starts the countdown until controls unlock. /// Spawns the emergency shuttle for each station and starts the countdown until controls unlock.
/// </summary> /// </summary>
public void CallEmergencyShuttle() public void CallEmergencyShuttle()
{ {
if (EmergencyShuttleArrived) if (EmergencyShuttleArrived)
return; return;
if (!_emergencyShuttleEnabled) if (!_emergencyShuttleEnabled)
{ {
_roundEnd.EndRound(); _roundEnd.EndRound();
return; return;
} }
_consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime); _consoleAccumulator = _configManager.GetCVar(CCVars.EmergencyShuttleDockTime);
EmergencyShuttleArrived = true; EmergencyShuttleArrived = true;
var query = AllEntityQuery<StationEmergencyShuttleComponent>(); var query = AllEntityQuery<StationEmergencyShuttleComponent>();
while (query.MoveNext(out var uid, out var comp)) while (query.MoveNext(out var uid, out var comp))
{ {
CallEmergencyShuttle(uid, comp); CallEmergencyShuttle(uid, comp);
} }
_commsConsole.UpdateCommsConsoleInterface(); _commsConsole.UpdateCommsConsoleInterface();
} }
private void SetupEmergencyShuttle() private void SetupEmergencyShuttle()
{ {
if (!_emergencyShuttleEnabled) if (!_emergencyShuttleEnabled)
return; return;
var centcommQuery = AllEntityQuery<StationCentcommComponent>(); var centcommQuery = AllEntityQuery<StationCentcommComponent>();
while (centcommQuery.MoveNext(out var centcomm)) while (centcommQuery.MoveNext(out var centcomm))
{ {
AddCentcomm(centcomm); AddCentcomm(centcomm);
} }
var query = AllEntityQuery<StationEmergencyShuttleComponent>(); var query = AllEntityQuery<StationEmergencyShuttleComponent>();
while (query.MoveNext(out var uid, out var comp)) while (query.MoveNext(out var uid, out var comp))
{ {
AddEmergencyShuttle(uid, comp); AddEmergencyShuttle(uid, comp);
} }
} }
private void AddCentcomm(StationCentcommComponent component) private void AddCentcomm(StationCentcommComponent component)
{ {
// Check for existing centcomms and just point to that // Check for existing centcomms and just point to that
var query = AllEntityQuery<StationCentcommComponent>(); var query = AllEntityQuery<StationCentcommComponent>();
while (query.MoveNext(out var otherComp)) while (query.MoveNext(out var otherComp))
{ {
if (otherComp == component) if (otherComp == component)
continue; continue;
component.MapId = otherComp.MapId; component.MapId = otherComp.MapId;
component.ShuttleIndex = otherComp.ShuttleIndex; component.ShuttleIndex = otherComp.ShuttleIndex;
return; return;
} }
var mapId = _mapManager.CreateMap(); var mapId = _mapManager.CreateMap();
component.MapId = mapId; component.MapId = mapId;
if (!string.IsNullOrEmpty(component.Map.ToString())) if (!string.IsNullOrEmpty(component.Map.ToString()))
{ {
var ent = _map.LoadGrid(mapId, component.Map.ToString()); var ent = _map.LoadGrid(mapId, component.Map.ToString());
if (ent != null) if (ent != null)
{ {
component.Entity = ent.Value; component.Entity = ent.Value;
_shuttle.AddFTLDestination(ent.Value, false); _shuttle.AddFTLDestination(ent.Value, false);
} }
} }
else else
{ {
_sawmill.Warning("No CentComm map found, skipping setup."); _sawmill.Warning("No CentComm map found, skipping setup.");
} }
} }
public HashSet<MapId> GetCentcommMaps() public HashSet<MapId> GetCentcommMaps()
{ {
var query = AllEntityQuery<StationCentcommComponent>(); var query = AllEntityQuery<StationCentcommComponent>();
var maps = new HashSet<MapId>(Count<StationCentcommComponent>()); var maps = new HashSet<MapId>(Count<StationCentcommComponent>());
while (query.MoveNext(out var comp)) while (query.MoveNext(out var comp))
{ {
maps.Add(comp.MapId); maps.Add(comp.MapId);
} }
return maps; return maps;
} }
private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component) private void AddEmergencyShuttle(EntityUid uid, StationEmergencyShuttleComponent component)
{ {
if (!_emergencyShuttleEnabled if (!_emergencyShuttleEnabled
|| component.EmergencyShuttle != null || || component.EmergencyShuttle != null ||
!TryComp<StationCentcommComponent>(uid, out var centcomm)) !TryComp<StationCentcommComponent>(uid, out var centcomm))
{ {
return; return;
} }
// Load escape shuttle // Load escape shuttle
var shuttlePath = component.EmergencyShuttlePath; var shuttlePath = component.EmergencyShuttlePath;
var shuttle = _map.LoadGrid(centcomm.MapId, shuttlePath.ToString(), new MapLoadOptions() var shuttle = _map.LoadGrid(centcomm.MapId, shuttlePath.ToString(), new MapLoadOptions()
{ {
// Should be far enough... right? I'm too lazy to bounds check CentCom rn. // Should be far enough... right? I'm too lazy to bounds check CentCom rn.
Offset = new Vector2(500f + centcomm.ShuttleIndex, 0f) Offset = new Vector2(500f + centcomm.ShuttleIndex, 0f)
}); });
if (shuttle == null) if (shuttle == null)
{ {
_sawmill.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(uid)}"); _sawmill.Error($"Unable to spawn emergency shuttle {shuttlePath} for {ToPrettyString(uid)}");
return; return;
} }
centcomm.ShuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer; centcomm.ShuttleIndex += _mapManager.GetGrid(shuttle.Value).LocalAABB.Width + ShuttleSpawnBuffer;
// Update indices for all centcomm comps pointing to same map // Update indices for all centcomm comps pointing to same map
var query = AllEntityQuery<StationCentcommComponent>(); var query = AllEntityQuery<StationCentcommComponent>();
while (query.MoveNext(out var comp)) while (query.MoveNext(out var comp))
{ {
if (comp == centcomm || comp.MapId != centcomm.MapId) if (comp == centcomm || comp.MapId != centcomm.MapId)
continue; continue;
comp.ShuttleIndex = centcomm.ShuttleIndex; comp.ShuttleIndex = centcomm.ShuttleIndex;
} }
component.EmergencyShuttle = shuttle; component.EmergencyShuttle = shuttle;
EnsureComp<ProtectedGridComponent>(shuttle.Value); EnsureComp<ProtectedGridComponent>(shuttle.Value);
EnsureComp<PreventPilotComponent>(shuttle.Value); EnsureComp<PreventPilotComponent>(shuttle.Value);
} }
private void OnEscapeUnpaused(EntityUid uid, EscapePodComponent component, ref EntityUnpausedEvent args) private void OnEscapeUnpaused(EntityUid uid, EscapePodComponent component, ref EntityUnpausedEvent args)
{ {
if (component.LaunchTime == null) if (component.LaunchTime == null)
return; return;
component.LaunchTime = component.LaunchTime.Value + args.PausedTime; component.LaunchTime = component.LaunchTime.Value + args.PausedTime;
} }
/// <summary>
/// Returns whether a target is escaping on the emergency shuttle, but only if evac has arrived.
/// </summary>
public bool IsTargetEscaping(EntityUid target)
{
// if evac isn't here then sitting in a pod doesn't return true
if (!EmergencyShuttleArrived)
return false;
// check each emergency shuttle
var xform = Transform(target);
foreach (var stationData in EntityQuery<StationEmergencyShuttleComponent>())
{
if (stationData.EmergencyShuttle == null)
continue;
if (IsOnGrid(xform, stationData.EmergencyShuttle.Value))
{
return true;
}
}
return false;
}
private bool IsOnGrid(TransformComponent xform, EntityUid shuttle, MapGridComponent? grid = null, TransformComponent? shuttleXform = null)
{
if (!Resolve(shuttle, ref grid, ref shuttleXform))
return false;
return shuttleXform.WorldMatrix.TransformBox(grid.LocalAABB).Contains(xform.WorldPosition);
}
} }

View File

@@ -1,2 +1,2 @@
objective-condition-escape-shuttle-title = Escape on the emergency shuttle alive and unrestrained. objective-condition-escape-shuttle-title = Escape to centcom alive and unrestrained.
objective-condition-escape-shuttle-description = One of our undercover agents will debrief you when you arrive. Don't show up in cuffs. objective-condition-escape-shuttle-description = One of our undercover agents will debrief you when you arrive. Don't show up in cuffs.

View File

@@ -1,2 +1,2 @@
objective-condition-kill-person-title = Kill {$targetName}, {CAPITALIZE($job)} objective-condition-kill-person-title = Kill or maroon {$targetName}, {CAPITALIZE($job)}
objective-condition-kill-person-description = Do it however you like, just make sure they don't last the shift. objective-condition-kill-person-description = Do it however you like, just make sure they don't make it to centcom.