Escape pods (#14809)
* Namespace adjustments for days * pod * thanks rider * Fix the oop launch * Fixes * Fix stuff * eeeeeeeee * Fix * access * map * forgor * thing * Genericise escape pod fill
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using Content.Server.Doors.Systems;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared.Parallax;
|
||||
using Content.Shared.Shuttles.Systems;
|
||||
using Content.Shared.StatusEffect;
|
||||
@@ -29,18 +28,11 @@ public sealed partial class ShuttleSystem
|
||||
* This is a way to move a shuttle from one location to another, via an intermediate map for fanciness.
|
||||
*/
|
||||
|
||||
[Dependency] private readonly AirlockSystem _airlock = default!;
|
||||
[Dependency] private readonly DoorSystem _doors = default!;
|
||||
[Dependency] private readonly ShuttleConsoleSystem _console = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly StunSystem _stuns = default!;
|
||||
[Dependency] private readonly ThrusterSystem _thruster = default!;
|
||||
|
||||
private MapId? _hyperSpaceMap;
|
||||
|
||||
private const float DefaultStartupTime = 5.5f;
|
||||
private const float DefaultTravelTime = 30f;
|
||||
private const float DefaultArrivalTime = 5f;
|
||||
public const float DefaultStartupTime = 5.5f;
|
||||
public const float DefaultTravelTime = 30f;
|
||||
public const float DefaultArrivalTime = 5f;
|
||||
private const float FTLCooldown = 30f;
|
||||
private const float ShuttleFTLRange = 100f;
|
||||
|
||||
@@ -106,14 +98,17 @@ public sealed partial class ShuttleSystem
|
||||
return true;
|
||||
}
|
||||
|
||||
var bounds = xform.WorldMatrix.TransformBox(grid.LocalAABB).Enlarged(ShuttleFTLRange);
|
||||
var bounds = _transform.GetWorldMatrix(xform).TransformBox(grid.LocalAABB).Enlarged(ShuttleFTLRange);
|
||||
var bodyQuery = GetEntityQuery<PhysicsComponent>();
|
||||
|
||||
foreach (var other in _mapManager.FindGridsIntersecting(xform.MapID, bounds))
|
||||
{
|
||||
if (grid.Owner == other.Owner ||
|
||||
if (uid == other.Owner ||
|
||||
!bodyQuery.TryGetComponent(other.Owner, out var body) ||
|
||||
body.Mass < ShuttleFTLMassThreshold) continue;
|
||||
body.Mass < ShuttleFTLMassThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
reason = Loc.GetString("shuttle-console-proximity");
|
||||
return false;
|
||||
@@ -127,7 +122,8 @@ public sealed partial class ShuttleSystem
|
||||
/// </summary>
|
||||
public FTLDestinationComponent AddFTLDestination(EntityUid uid, bool enabled)
|
||||
{
|
||||
if (TryComp<FTLDestinationComponent>(uid, out var destination) && destination.Enabled == enabled) return destination;
|
||||
if (TryComp<FTLDestinationComponent>(uid, out var destination) && destination.Enabled == enabled)
|
||||
return destination;
|
||||
|
||||
destination = EnsureComp<FTLDestinationComponent>(uid);
|
||||
|
||||
@@ -146,19 +142,22 @@ public sealed partial class ShuttleSystem
|
||||
{
|
||||
if (!RemComp<FTLDestinationComponent>(uid))
|
||||
return;
|
||||
|
||||
_console.RefreshShuttleConsoles();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves a shuttle from its current position to the target one. Goes through the hyperspace map while the timer is running.
|
||||
/// </summary>
|
||||
public void FTLTravel(ShuttleComponent component,
|
||||
public void FTLTravel(
|
||||
EntityUid shuttleUid,
|
||||
ShuttleComponent component,
|
||||
EntityCoordinates coordinates,
|
||||
float startupTime = DefaultStartupTime,
|
||||
float hyperspaceTime = DefaultTravelTime,
|
||||
string? priorityTag = null)
|
||||
{
|
||||
if (!TrySetupFTL(component, out var hyperspace))
|
||||
if (!TrySetupFTL(shuttleUid, component, out var hyperspace))
|
||||
return;
|
||||
|
||||
hyperspace.StartupTime = startupTime;
|
||||
@@ -173,14 +172,16 @@ public sealed partial class ShuttleSystem
|
||||
/// <summary>
|
||||
/// Moves a shuttle from its current position to docked on the target one. Goes through the hyperspace map while the timer is running.
|
||||
/// </summary>
|
||||
public void FTLTravel(ShuttleComponent component,
|
||||
public void FTLTravel(
|
||||
EntityUid shuttleUid,
|
||||
ShuttleComponent component,
|
||||
EntityUid target,
|
||||
float startupTime = DefaultStartupTime,
|
||||
float hyperspaceTime = DefaultTravelTime,
|
||||
bool dock = false,
|
||||
string? priorityTag = null)
|
||||
{
|
||||
if (!TrySetupFTL(component, out var hyperspace))
|
||||
if (!TrySetupFTL(shuttleUid, component, out var hyperspace))
|
||||
return;
|
||||
|
||||
hyperspace.StartupTime = startupTime;
|
||||
@@ -192,9 +193,8 @@ public sealed partial class ShuttleSystem
|
||||
_console.RefreshShuttleConsoles();
|
||||
}
|
||||
|
||||
private bool TrySetupFTL(ShuttleComponent shuttle, [NotNullWhen(true)] out FTLComponent? component)
|
||||
private bool TrySetupFTL(EntityUid uid, ShuttleComponent shuttle, [NotNullWhen(true)] out FTLComponent? component)
|
||||
{
|
||||
var uid = shuttle.Owner;
|
||||
component = null;
|
||||
|
||||
if (HasComp<FTLComponent>(uid))
|
||||
@@ -310,9 +310,9 @@ public sealed partial class ShuttleSystem
|
||||
if (comp.TargetUid != null && shuttle != null)
|
||||
{
|
||||
if (comp.Dock)
|
||||
TryFTLDock(shuttle, comp.TargetUid.Value, comp.PriorityTag);
|
||||
TryFTLDock(uid, shuttle, comp.TargetUid.Value, comp.PriorityTag);
|
||||
else
|
||||
TryFTLProximity(shuttle, comp.TargetUid.Value);
|
||||
TryFTLProximity(uid, shuttle, comp.TargetUid.Value);
|
||||
|
||||
mapId = Transform(comp.TargetUid.Value).MapID;
|
||||
}
|
||||
@@ -350,7 +350,7 @@ public sealed partial class ShuttleSystem
|
||||
comp.TravelStream = null;
|
||||
}
|
||||
|
||||
SoundSystem.Play(_arrivalSound.GetSound(), Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(uid)), _arrivalSound.Params);
|
||||
_audio.PlayGlobal(_arrivalSound, Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(uid)), true);
|
||||
|
||||
if (TryComp<FTLDestinationComponent>(uid, out var dest))
|
||||
{
|
||||
@@ -380,7 +380,9 @@ public sealed partial class ShuttleSystem
|
||||
{
|
||||
foreach (var (dock, xform) in EntityQuery<DockingComponent, TransformComponent>(true))
|
||||
{
|
||||
if (xform.ParentUid != uid || dock.Enabled == enabled) continue;
|
||||
if (xform.ParentUid != uid || dock.Enabled == enabled)
|
||||
continue;
|
||||
|
||||
_dockSystem.Undock(dock);
|
||||
dock.Enabled = enabled;
|
||||
}
|
||||
@@ -388,25 +390,30 @@ public sealed partial class ShuttleSystem
|
||||
|
||||
private void SetDockBolts(EntityUid uid, bool enabled)
|
||||
{
|
||||
foreach (var (_, door, xform) in EntityQuery<DockingComponent, AirlockComponent, TransformComponent>(true))
|
||||
{
|
||||
if (xform.ParentUid != uid) continue;
|
||||
var query = AllEntityQuery<DockingComponent, AirlockComponent, TransformComponent>();
|
||||
|
||||
_doors.TryClose(door.Owner);
|
||||
_airlock.SetBoltsWithAudio(door.Owner, door, enabled);
|
||||
while (query.MoveNext(out var doorUid, out _, out var door, out var xform))
|
||||
{
|
||||
if (xform.ParentUid != uid)
|
||||
continue;
|
||||
|
||||
_doors.TryClose(doorUid);
|
||||
_airlock.SetBoltsWithAudio(doorUid, door, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetSoundRange(EntityUid uid)
|
||||
{
|
||||
if (!_mapManager.TryGetGrid(uid, out var grid)) return 4f;
|
||||
if (!_mapManager.TryGetGrid(uid, out var grid))
|
||||
return 4f;
|
||||
|
||||
return MathF.Max(grid.LocalAABB.Width, grid.LocalAABB.Height) + 12.5f;
|
||||
}
|
||||
|
||||
private void SetupHyperspace()
|
||||
{
|
||||
if (_hyperSpaceMap != null) return;
|
||||
if (_hyperSpaceMap != null)
|
||||
return;
|
||||
|
||||
_hyperSpaceMap = _mapManager.CreateMap();
|
||||
_sawmill.Info($"Setup hyperspace map at {_hyperSpaceMap.Value}");
|
||||
@@ -453,7 +460,8 @@ public sealed partial class ShuttleSystem
|
||||
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
if (!buckleQuery.TryGetComponent(child.Value, out var buckle) || buckle.Buckled) continue;
|
||||
if (!buckleQuery.TryGetComponent(child.Value, out var buckle) || buckle.Buckled)
|
||||
continue;
|
||||
|
||||
toKnock.Add(child.Value);
|
||||
}
|
||||
@@ -462,10 +470,9 @@ public sealed partial class ShuttleSystem
|
||||
/// <summary>
|
||||
/// Tries to dock with the target grid, otherwise falls back to proximity.
|
||||
/// </summary>
|
||||
/// <param name="priorityTag">Priority docking tag to prefer, e.g. for emergency shuttle</param>
|
||||
public bool TryFTLDock(ShuttleComponent component, EntityUid targetUid, string? priorityTag = null)
|
||||
public bool TryFTLDock(EntityUid shuttleUid, ShuttleComponent component, EntityUid targetUid, string? priorityTag = null)
|
||||
{
|
||||
if (!TryComp<TransformComponent>(component.Owner, out var xform) ||
|
||||
if (!TryComp<TransformComponent>(shuttleUid, out var shuttleXform) ||
|
||||
!TryComp<TransformComponent>(targetUid, out var targetXform) ||
|
||||
targetXform.MapUid == null ||
|
||||
!targetXform.MapUid.Value.IsValid())
|
||||
@@ -473,42 +480,49 @@ public sealed partial class ShuttleSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var config = GetDockingConfig(component, targetUid, priorityTag);
|
||||
var config = _dockSystem.GetDockingConfig(shuttleUid, targetUid, priorityTag);
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
// Set position
|
||||
xform.Coordinates = config.Coordinates;
|
||||
xform.WorldRotation = config.Angle;
|
||||
|
||||
// Connect everything
|
||||
foreach (var (dockA, dockB) in config.Docks)
|
||||
{
|
||||
_dockSystem.Dock(dockA.Owner, dockA, dockB.Owner, dockB);
|
||||
}
|
||||
|
||||
return true;
|
||||
FTLDock(config, shuttleXform);
|
||||
return true;
|
||||
}
|
||||
|
||||
TryFTLProximity(component, targetUid, xform, targetXform);
|
||||
TryFTLProximity(shuttleUid, component, targetUid, shuttleXform, targetXform);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces an FTL dock.
|
||||
/// </summary>
|
||||
public void FTLDock(DockingConfig config, TransformComponent shuttleXform)
|
||||
{
|
||||
// Set position
|
||||
shuttleXform.Coordinates = config.Coordinates;
|
||||
_transform.SetWorldRotation(shuttleXform, config.Angle);
|
||||
|
||||
// Connect everything
|
||||
foreach (var (dockAUid, dockBUid, dockA, dockB) in config.Docks)
|
||||
{
|
||||
_dockSystem.Dock(dockAUid, dockA, dockBUid, dockB);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to arrive nearby without overlapping with other grids.
|
||||
/// </summary>
|
||||
public bool TryFTLProximity(ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null)
|
||||
public bool TryFTLProximity(EntityUid shuttleUid, ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null)
|
||||
{
|
||||
if (!Resolve(targetUid, ref targetXform) ||
|
||||
targetXform.MapUid == null ||
|
||||
!targetXform.MapUid.Value.IsValid() ||
|
||||
!Resolve(component.Owner, ref xform))
|
||||
!Resolve(shuttleUid, ref xform))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var shuttleAABB = Comp<MapGridComponent>(component.Owner).LocalAABB;
|
||||
var shuttleAABB = Comp<MapGridComponent>(shuttleUid).LocalAABB;
|
||||
Box2 targetLocalAABB;
|
||||
|
||||
// Spawn nearby.
|
||||
@@ -534,7 +548,8 @@ public sealed partial class ShuttleSystem
|
||||
{
|
||||
foreach (var grid in _mapManager.FindGridsIntersecting(mapId, targetAABB))
|
||||
{
|
||||
if (!nearbyGrids.Add(grid.Owner)) continue;
|
||||
if (!nearbyGrids.Add(grid.Owner))
|
||||
continue;
|
||||
|
||||
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
||||
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
||||
@@ -557,7 +572,8 @@ public sealed partial class ShuttleSystem
|
||||
foreach (var grid in _mapManager.GetAllGrids())
|
||||
{
|
||||
// Don't add anymore as it is irrelevant, but that doesn't mean we need to re-do existing work.
|
||||
if (nearbyGrids.Contains(grid.Owner)) continue;
|
||||
if (nearbyGrids.Contains(grid.Owner))
|
||||
continue;
|
||||
|
||||
targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.Owner, xformQuery)
|
||||
.TransformBox(Comp<MapGridComponent>(grid.Owner).LocalAABB));
|
||||
@@ -568,10 +584,10 @@ public sealed partial class ShuttleSystem
|
||||
|
||||
Vector2 spawnPos;
|
||||
|
||||
if (TryComp<PhysicsComponent>(component.Owner, out var shuttleBody))
|
||||
if (TryComp<PhysicsComponent>(shuttleUid, out var shuttleBody))
|
||||
{
|
||||
_physics.SetLinearVelocity(component.Owner, Vector2.Zero, body: shuttleBody);
|
||||
_physics.SetAngularVelocity(component.Owner, 0f, body: shuttleBody);
|
||||
_physics.SetLinearVelocity(shuttleUid, Vector2.Zero, body: shuttleBody);
|
||||
_physics.SetAngularVelocity(shuttleUid, 0f, body: shuttleBody);
|
||||
}
|
||||
|
||||
// TODO: This is pretty crude for multiple landings.
|
||||
@@ -604,138 +620,4 @@ public sealed partial class ShuttleSystem
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the emergency shuttle can warp to the specified position.
|
||||
/// </summary>
|
||||
private bool ValidSpawn(EntityUid gridUid, MapGridComponent grid, Box2 area)
|
||||
{
|
||||
// If the target is a map then any tile is valid.
|
||||
// TODO: We already need the entities-under check
|
||||
if (HasComp<MapComponent>(gridUid))
|
||||
return true;
|
||||
|
||||
return !grid.GetLocalTilesIntersecting(area).Any();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a valid docking configuration for the shuttle to the target grid.
|
||||
/// </summary>
|
||||
/// <param name="priorityTag">Priority docking tag to prefer, e.g. for emergency shuttle</param>
|
||||
private DockingConfig? GetDockingConfig(ShuttleComponent component, EntityUid targetGrid, string? priorityTag = null)
|
||||
{
|
||||
var gridDocks = GetDocks(targetGrid);
|
||||
|
||||
if (gridDocks.Count <= 0)
|
||||
return null;
|
||||
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var targetGridGrid = Comp<MapGridComponent>(targetGrid);
|
||||
var targetGridXform = xformQuery.GetComponent(targetGrid);
|
||||
var targetGridAngle = targetGridXform.WorldRotation.Reduced();
|
||||
|
||||
var shuttleDocks = GetDocks(component.Owner);
|
||||
var shuttleAABB = Comp<MapGridComponent>(component.Owner).LocalAABB;
|
||||
|
||||
var validDockConfigs = new List<DockingConfig>();
|
||||
|
||||
if (shuttleDocks.Count > 0)
|
||||
{
|
||||
// We'll try all combinations of shuttle docks and see which one is most suitable
|
||||
foreach (var shuttleDock in shuttleDocks)
|
||||
{
|
||||
var shuttleDockXform = xformQuery.GetComponent(shuttleDock.Owner);
|
||||
|
||||
foreach (var gridDock in gridDocks)
|
||||
{
|
||||
var gridXform = xformQuery.GetComponent(gridDock.Owner);
|
||||
|
||||
if (!CanDock(
|
||||
shuttleDock, shuttleDockXform,
|
||||
gridDock, gridXform,
|
||||
targetGridAngle,
|
||||
shuttleAABB,
|
||||
targetGrid,
|
||||
targetGridGrid,
|
||||
out var dockedAABB,
|
||||
out var matty,
|
||||
out var targetAngle)) continue;
|
||||
|
||||
// Can't just use the AABB as we want to get bounds as tight as possible.
|
||||
var spawnPosition = new EntityCoordinates(targetGrid, matty.Transform(Vector2.Zero));
|
||||
spawnPosition = new EntityCoordinates(targetGridXform.MapUid!.Value, spawnPosition.ToMapPos(EntityManager));
|
||||
|
||||
var dockedBounds = new Box2Rotated(shuttleAABB.Translated(spawnPosition.Position), targetGridAngle, spawnPosition.Position);
|
||||
|
||||
// Check if there's no intersecting grids (AKA oh god it's docking at cargo).
|
||||
if (_mapManager.FindGridsIntersecting(targetGridXform.MapID,
|
||||
dockedBounds).Any(o => o.Owner != targetGrid))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Alright well the spawn is valid now to check how many we can connect
|
||||
// Get the matrix for each shuttle dock and test it against the grid docks to see
|
||||
// if the connected position / direction matches.
|
||||
|
||||
var dockedPorts = new List<(DockingComponent DockA, DockingComponent DockB)>()
|
||||
{
|
||||
(shuttleDock, gridDock),
|
||||
};
|
||||
|
||||
foreach (var other in shuttleDocks)
|
||||
{
|
||||
if (other == shuttleDock) continue;
|
||||
|
||||
foreach (var otherGrid in gridDocks)
|
||||
{
|
||||
if (otherGrid == gridDock) continue;
|
||||
|
||||
if (!CanDock(
|
||||
other,
|
||||
xformQuery.GetComponent(other.Owner),
|
||||
otherGrid,
|
||||
xformQuery.GetComponent(otherGrid.Owner),
|
||||
targetGridAngle,
|
||||
shuttleAABB,
|
||||
targetGrid,
|
||||
targetGridGrid,
|
||||
out var otherDockedAABB,
|
||||
out _,
|
||||
out var otherTargetAngle) ||
|
||||
!otherDockedAABB.Equals(dockedAABB) ||
|
||||
!targetAngle.Equals(otherTargetAngle)) continue;
|
||||
|
||||
dockedPorts.Add((other, otherGrid));
|
||||
}
|
||||
}
|
||||
|
||||
validDockConfigs.Add(new DockingConfig()
|
||||
{
|
||||
Docks = dockedPorts,
|
||||
Area = dockedAABB.Value,
|
||||
Coordinates = spawnPosition,
|
||||
Angle = targetAngle,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validDockConfigs.Count <= 0)
|
||||
return null;
|
||||
|
||||
// Prioritise by priority docks, then by maximum connected ports, then by most similar angle.
|
||||
validDockConfigs = validDockConfigs
|
||||
.OrderByDescending(x => x.Docks.Any(docks =>
|
||||
TryComp<PriorityDockComponent>(docks.DockB.Owner, out var priority) &&
|
||||
priority.Tag?.Equals(priorityTag) == true))
|
||||
.ThenByDescending(x => x.Docks.Count)
|
||||
.ThenBy(x => Math.Abs(Angle.ShortestDistance(x.Angle.Reduced(), targetGridAngle).Theta)).ToList();
|
||||
|
||||
var location = validDockConfigs.First();
|
||||
location.TargetGrid = targetGrid;
|
||||
// TODO: Ideally do a hyperspace warpin, just have it run on like a 10 second timer.
|
||||
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user