diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index 219727fac0..bd2cb3219b 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -24,6 +24,7 @@ public sealed partial class ShuttleSystem [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!; @@ -57,6 +58,11 @@ public sealed partial class ShuttleSystem /// private const float Buffer = 5f; + /// + /// How many times we try to proximity warp close to something before falling back to map-wideAABB. + /// + private const int FTLProximityIterations = 3; + private void InitializeFTL() { SubscribeLocalEvent(OnStationGridAdd); @@ -429,20 +435,58 @@ public sealed partial class ShuttleSystem { if (!Resolve(targetUid, ref targetXform) || targetXform.MapUid == null || !Resolve(component.Owner, ref xform)) return false; - var shuttleAABB = Comp(component.Owner).Grid.WorldAABB; + var xformQuery = GetEntityQuery(); + var shuttleAABB = Comp(component.Owner).Grid.LocalAABB; Box2? aabb = null; // Spawn nearby. - foreach (var grid in _mapManager.GetAllMapGrids(targetXform.MapID)) + // We essentially expand the Box2 of the target area until nothing else is added then we know it's valid. + // Can't just get an AABB of every grid as we may spawn very far away. + var targetAABB = _transform.GetWorldMatrix(targetXform, xformQuery) + .TransformBox(Comp(targetUid).Grid.LocalAABB).Enlarged(shuttleAABB.Size.Length); + + var nearbyGrids = new HashSet(1) { targetUid }; + var iteration = 0; + var lastCount = 1; + var mapId = targetXform.MapID; + + while (iteration < 3) { - var gridAABB = grid.WorldAABB; - aabb = aabb?.Union(gridAABB) ?? gridAABB; + foreach (var grid in _mapManager.FindGridsIntersecting(mapId, targetAABB)) + { + if (!nearbyGrids.Add(grid.GridEntityId)) continue; + + targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.GridEntityId, xformQuery) + .TransformBox(Comp(grid.GridEntityId).Grid.LocalAABB)); + } + + // Can do proximity + if (nearbyGrids.Count == lastCount) + { + break; + } + + targetAABB = targetAABB.Enlarged(shuttleAABB.Size.Length / 2f); + iteration++; + lastCount = nearbyGrids.Count; + + // Mishap moment, dense asteroid field or whatever + if (iteration != 3) continue; + + 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.GridEntityId)) continue; + + targetAABB = targetAABB.Union(_transform.GetWorldMatrix(grid.GridEntityId, xformQuery) + .TransformBox(Comp(grid.GridEntityId).Grid.LocalAABB)); + } + + break; } - aabb ??= new Box2(); - - var minRadius = MathF.Max(aabb.Value.Width, aabb.Value.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height); - var spawnPos = aabb.Value.Center + _random.NextVector2(minRadius, minRadius + 256f); + var minRadius = (MathF.Max(targetAABB.Width, targetAABB.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height)) / 2f; + var spawnPos = targetAABB.Center + _random.NextVector2(minRadius, minRadius + 64f); if (TryComp(component.Owner, out var shuttleBody)) { @@ -452,6 +496,6 @@ public sealed partial class ShuttleSystem xform.Coordinates = new EntityCoordinates(targetXform.MapUid.Value, spawnPos); xform.WorldRotation = _random.NextAngle(); - return false; + return true; } }