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:
metalgearsloth
2023-03-24 12:54:41 +11:00
committed by GitHub
parent 9aadc77b92
commit 448165ffda
28 changed files with 1417 additions and 747 deletions

View File

@@ -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;
}
}