v0.12.0.2
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Barotrauma
|
||||
|
||||
public static bool ShowWayPoints = true, ShowSpawnPoints = true;
|
||||
|
||||
public const float LadderWaypointInterval = 100.0f;
|
||||
public const float LadderWaypointInterval = 70.0f;
|
||||
|
||||
protected SpawnType spawnType;
|
||||
private string[] idCardTags;
|
||||
@@ -99,6 +99,13 @@ namespace Barotrauma
|
||||
{
|
||||
SpawnType = SpawnType.Path;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (SubEditorScreen.IsSubEditor())
|
||||
{
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { this }, false));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -179,42 +186,55 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float diffFromHullEdge = 50;
|
||||
float minDist = 150.0f;
|
||||
float minDist = 100.0f;
|
||||
float heightFromFloor = 110.0f;
|
||||
float hullMinHeight = 100;
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
if (hull.Rect.Height < 150) { continue; }
|
||||
|
||||
WayPoint prevWaypoint = null;
|
||||
|
||||
// Ignore hulls that a human couldn't fit in.
|
||||
// Doesn't take multi-hull rooms into account, but it's probably best to leave them to be setup manually.
|
||||
if (hull.Rect.Height < hullMinHeight) { continue; }
|
||||
// Don't create waypoints if there's no floor.
|
||||
Vector2 floorPos = new Vector2(hull.SimPosition.X, ConvertUnits.ToSimUnits(hull.Rect.Y - hull.RectHeight - 50));
|
||||
Body floor = Submarine.PickBody(hull.SimPosition, floorPos, collisionCategory: Physics.CollisionWall | Physics.CollisionPlatform, customPredicate: f => !(f.Body.UserData is Submarine));
|
||||
if (floor == null) { continue; }
|
||||
// Make sure that the waypoints don't go higher than the halfway of the room.
|
||||
float waypointHeight = hull.Rect.Height > heightFromFloor * 2 ? heightFromFloor : hull.Rect.Height / 2;
|
||||
if (hull.Rect.Width < diffFromHullEdge * 3.0f)
|
||||
{
|
||||
new WayPoint(
|
||||
new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine);
|
||||
continue;
|
||||
new WayPoint(new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + waypointHeight), SpawnType.Path, submarine);
|
||||
}
|
||||
|
||||
for (float x = hull.Rect.X + diffFromHullEdge; x <= hull.Rect.Right - diffFromHullEdge; x += minDist)
|
||||
else
|
||||
{
|
||||
var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine);
|
||||
if (prevWaypoint != null) { wayPoint.ConnectTo(prevWaypoint); }
|
||||
prevWaypoint = wayPoint;
|
||||
WayPoint prevWaypoint = null;
|
||||
for (float x = hull.Rect.X + diffFromHullEdge; x <= hull.Rect.Right - diffFromHullEdge; x += minDist)
|
||||
{
|
||||
var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + waypointHeight), SpawnType.Path, submarine);
|
||||
if (prevWaypoint != null) { wayPoint.ConnectTo(prevWaypoint); }
|
||||
prevWaypoint = wayPoint;
|
||||
}
|
||||
if (prevWaypoint == null)
|
||||
{
|
||||
// Ensure that we always create at least one waypoint per hull.
|
||||
new WayPoint(new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + waypointHeight), SpawnType.Path, submarine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float outSideWaypointInterval = 200.0f;
|
||||
float outSideWaypointInterval = 100.0f;
|
||||
if (submarine.Info.Type != SubmarineType.OutpostModule)
|
||||
{
|
||||
int outsideWaypointDist = 100;
|
||||
List<WayPoint> outsideWaypoints = new List<WayPoint>();
|
||||
|
||||
Rectangle borders = Hull.GetBorders();
|
||||
borders.X -= outsideWaypointDist;
|
||||
borders.Y += outsideWaypointDist;
|
||||
borders.Width += outsideWaypointDist * 2;
|
||||
borders.Height += outsideWaypointDist * 2;
|
||||
int originalWidth = borders.Width;
|
||||
int originalHeight = borders.Height;
|
||||
borders.X -= Math.Min(500, originalWidth / 4);
|
||||
borders.Y += Math.Min(500, originalHeight / 4);
|
||||
borders.Width += Math.Min(1500, originalWidth / 2);
|
||||
borders.Height += Math.Min(1000, originalHeight / 2);
|
||||
borders.Location -= MathUtils.ToPoint(submarine.HiddenSubPosition);
|
||||
|
||||
if (borders.Width <= outSideWaypointInterval * 2)
|
||||
@@ -238,6 +258,8 @@ namespace Barotrauma
|
||||
new Vector2(x, borders.Y - borders.Height * i) + submarine.HiddenSubPosition,
|
||||
SpawnType.Path, submarine);
|
||||
|
||||
outsideWaypoints.Add(wayPoint);
|
||||
|
||||
if (x == borders.X + outSideWaypointInterval)
|
||||
{
|
||||
cornerWaypoint[i, 0] = wayPoint;
|
||||
@@ -260,18 +282,107 @@ namespace Barotrauma
|
||||
new Vector2(borders.X + borders.Width * i, y) + submarine.HiddenSubPosition,
|
||||
SpawnType.Path, submarine);
|
||||
|
||||
outsideWaypoints.Add(wayPoint);
|
||||
|
||||
if (y == borders.Y - borders.Height)
|
||||
{
|
||||
wayPoint.ConnectTo(cornerWaypoint[1, i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
wayPoint.ConnectTo(WayPoint.WayPointList[WayPointList.Count - 2]);
|
||||
wayPoint.ConnectTo(WayPointList[WayPointList.Count - 2]);
|
||||
}
|
||||
}
|
||||
|
||||
wayPoint.ConnectTo(cornerWaypoint[0, i]);
|
||||
}
|
||||
|
||||
Vector2 center = ConvertUnits.ToSimUnits(submarine.HiddenSubPosition);
|
||||
float halfHeight = ConvertUnits.ToSimUnits(borders.Height / 2);
|
||||
// Try to move the waypoints so that they are near the walls, roughly following the shape of the sub.
|
||||
foreach (WayPoint wp in outsideWaypoints)
|
||||
{
|
||||
float xDiff = center.X - wp.SimPosition.X;
|
||||
Vector2 targetPos = new Vector2(center.X - xDiff * 0.5f, center.Y);
|
||||
Body wall = Submarine.PickBody(wp.SimPosition, targetPos, collisionCategory: Physics.CollisionWall, customPredicate: f => !(f.Body.UserData is Submarine));
|
||||
if (wall == null)
|
||||
{
|
||||
// Try again, and shoot to the center now. It happens with some subs that the first, offset raycast don't hit the walls.
|
||||
targetPos = new Vector2(center.X - xDiff, center.Y);
|
||||
wall = Submarine.PickBody(wp.SimPosition, targetPos, collisionCategory: Physics.CollisionWall, customPredicate: f => !(f.Body.UserData is Submarine));
|
||||
}
|
||||
if (wall != null)
|
||||
{
|
||||
float distanceFromWall = 1;
|
||||
if (xDiff > 0 && !submarine.Info.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
// We don't want to move the waypoints near the tail too close to the engine.
|
||||
float yDist = Math.Abs(center.Y - wp.SimPosition.Y);
|
||||
distanceFromWall = MathHelper.Lerp(1, 3, MathUtils.InverseLerp(halfHeight, 0, yDist));
|
||||
}
|
||||
Vector2 newPos = Submarine.LastPickedPosition + Submarine.LastPickedNormal * distanceFromWall;
|
||||
wp.rect = new Rectangle(ConvertUnits.ToDisplayUnits(newPos).ToPoint(), wp.rect.Size);
|
||||
wp.FindHull();
|
||||
}
|
||||
}
|
||||
// Remove unwanted points
|
||||
var removals = new List<WayPoint>();
|
||||
WayPoint previous = null;
|
||||
float tooClose = outSideWaypointInterval / 2;
|
||||
foreach (WayPoint wp in outsideWaypoints)
|
||||
{
|
||||
if (wp.CurrentHull != null ||
|
||||
Submarine.PickBody(wp.SimPosition, wp.SimPosition + Vector2.Normalize(center - wp.SimPosition) * 0.1f, collisionCategory: Physics.CollisionWall | Physics.CollisionItem, customPredicate: f => !(f.Body.UserData is Submarine), allowInsideFixture: true) != null)
|
||||
{
|
||||
// Remove waypoints that got inside/too near the sub.
|
||||
removals.Add(wp);
|
||||
previous = wp;
|
||||
continue;
|
||||
}
|
||||
foreach (WayPoint otherWp in outsideWaypoints)
|
||||
{
|
||||
if (otherWp == wp) { continue; }
|
||||
if (removals.Contains(otherWp)) { continue; }
|
||||
float sqrDist = Vector2.DistanceSquared(wp.Position, otherWp.Position);
|
||||
// Remove waypoints that are too close to each other.
|
||||
if (!removals.Contains(previous) && sqrDist < tooClose * tooClose)
|
||||
{
|
||||
removals.Add(wp);
|
||||
}
|
||||
}
|
||||
previous = wp;
|
||||
}
|
||||
foreach (WayPoint wp in removals)
|
||||
{
|
||||
outsideWaypoints.Remove(wp);
|
||||
wp.Remove();
|
||||
}
|
||||
// Connect loose ends (TODO: this sometimes fails, creating the connection to a wrong node)
|
||||
for (int i = 0; i < outsideWaypoints.Count; i++)
|
||||
{
|
||||
WayPoint current = outsideWaypoints[i];
|
||||
if (current.linkedTo.Count > 1) { continue; }
|
||||
WayPoint next = null;
|
||||
int maxConnections = 2;
|
||||
float tooFar = outSideWaypointInterval * 5;
|
||||
for (int j = 0; j < maxConnections; j++)
|
||||
{
|
||||
if (current.linkedTo.Count >= maxConnections) { break; }
|
||||
tooFar /= current.linkedTo.Count;
|
||||
// First try to find a loose end
|
||||
next = current.FindClosestOutside(outsideWaypoints, tolerance: tooFar, filter: wp => wp != next && wp.linkedTo.None(e => current.linkedTo.Contains(e)) && wp.linkedTo.Count < 2);
|
||||
// Then accept any connection that not connected to the existing connection
|
||||
next ??= current.FindClosestOutside(outsideWaypoints, tolerance: tooFar, filter: wp => wp != next && wp.linkedTo.None(e => current.linkedTo.Contains(e)));
|
||||
if (next != null)
|
||||
{
|
||||
current.ConnectTo(next);
|
||||
}
|
||||
}
|
||||
if (current.linkedTo.Count == 1)
|
||||
{
|
||||
DebugConsole.ThrowError($"Couldn't automatically link waypoint {current.ID}. You should do it manually.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Structure> stairList = new List<Structure>();
|
||||
@@ -298,13 +409,13 @@ namespace Barotrauma
|
||||
{
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
WayPoint closest = stairPoints[i].FindClosest(dir, true, new Vector2(-30.0f, 30f));
|
||||
if (closest == null) continue;
|
||||
WayPoint closest = stairPoints[i].FindClosest(dir, horizontalSearch: true, new Vector2(100, 70));
|
||||
if (closest == null) { continue; }
|
||||
stairPoints[i].ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
|
||||
stairPoints[2] = new WayPoint((stairPoints[0].Position + stairPoints[1].Position)/2, SpawnType.Path, submarine);
|
||||
stairPoints[2] = new WayPoint((stairPoints[0].Position + stairPoints[1].Position) / 2, SpawnType.Path, submarine);
|
||||
stairPoints[0].ConnectTo(stairPoints[2]);
|
||||
stairPoints[2].ConnectTo(stairPoints[1]);
|
||||
}
|
||||
@@ -314,21 +425,44 @@ namespace Barotrauma
|
||||
var ladders = item.GetComponent<Ladder>();
|
||||
if (ladders == null) { continue; }
|
||||
|
||||
Vector2 bottomPoint = new Vector2(item.Rect.Center.X, item.Rect.Top - item.Rect.Height + 10);
|
||||
List<WayPoint> ladderPoints = new List<WayPoint>
|
||||
{
|
||||
new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height + heightFromFloor), SpawnType.Path, submarine)
|
||||
new WayPoint(bottomPoint, SpawnType.Path, submarine),
|
||||
};
|
||||
|
||||
WayPoint prevPoint = ladderPoints[0];
|
||||
Vector2 prevPos = prevPoint.SimPosition;
|
||||
List<Body> ignoredBodies = new List<Body>();
|
||||
|
||||
for (float y = ladderPoints[0].Position.Y + LadderWaypointInterval; y < item.Rect.Y - 1.0f; y += LadderWaypointInterval)
|
||||
// Lowest point is only meaningful for hanging ladders inside the sub, but it shouldn't matter in other cases either.
|
||||
// Start point is where the bots normally grasp the ladder when they stand on ground.
|
||||
WayPoint lowestPoint = ladderPoints[0];
|
||||
WayPoint prevPoint = lowestPoint;
|
||||
Vector2 prevPos = prevPoint.SimPosition;
|
||||
Body ground = Submarine.PickBody(lowestPoint.SimPosition, lowestPoint.SimPosition - Vector2.UnitY, ignoredBodies,
|
||||
collisionCategory: Physics.CollisionWall | Physics.CollisionPlatform | Physics.CollisionStairs,
|
||||
customPredicate: f => !(f.Body.UserData is Submarine));
|
||||
float startHeight = ground != null ? ConvertUnits.ToDisplayUnits(ground.Position.Y) : bottomPoint.Y;
|
||||
startHeight += heightFromFloor;
|
||||
WayPoint startPoint = lowestPoint;
|
||||
Vector2 nextPos = new Vector2(item.Rect.Center.X, startHeight);
|
||||
// Don't create the start point if it's too close to the lowest point or if it's outside of the sub.
|
||||
// If we skip creating the start point, the lowest point is used instead.
|
||||
if (lowestPoint == null || Math.Abs(startPoint.Position.Y - startHeight) > 40 && Hull.FindHull(nextPos) != null)
|
||||
{
|
||||
startPoint = new WayPoint(nextPos, SpawnType.Path, submarine);
|
||||
ladderPoints.Add(startPoint);
|
||||
if (lowestPoint != null)
|
||||
{
|
||||
startPoint.ConnectTo(lowestPoint);
|
||||
}
|
||||
prevPoint = startPoint;
|
||||
prevPos = prevPoint.SimPosition;
|
||||
}
|
||||
for (float y = startPoint.Position.Y + LadderWaypointInterval; y < item.Rect.Y - 1.0f; y += LadderWaypointInterval)
|
||||
{
|
||||
//first check if there's a door in the way
|
||||
//(we need to create a waypoint linked to the door for NPCs to open it)
|
||||
Body pickedBody = Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(new Vector2(ladderPoints[0].Position.X, y)),
|
||||
ConvertUnits.ToSimUnits(new Vector2(startPoint.Position.X, y)),
|
||||
prevPos, ignoredBodies, Physics.CollisionWall, false,
|
||||
(Fixture f) => f.Body.UserData is Item && ((Item)f.Body.UserData).GetComponent<Door>() != null);
|
||||
|
||||
@@ -341,7 +475,7 @@ namespace Barotrauma
|
||||
{
|
||||
//no door, check for walls
|
||||
pickedBody = Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(new Vector2(ladderPoints[0].Position.X, y)), prevPos, ignoredBodies, null, false,
|
||||
ConvertUnits.ToSimUnits(new Vector2(startPoint.Position.X, y)), prevPos, ignoredBodies, null, false,
|
||||
(Fixture f) => f.Body.UserData is Structure);
|
||||
}
|
||||
|
||||
@@ -374,75 +508,94 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (prevPoint.rect.Y < item.Rect.Y - 10.0f)
|
||||
// Cap
|
||||
if (prevPoint.rect.Y < item.Rect.Y - 40)
|
||||
{
|
||||
WayPoint newPoint = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - 1.0f), SpawnType.Path, submarine);
|
||||
ladderPoints.Add(newPoint);
|
||||
newPoint.ConnectTo(prevPoint);
|
||||
WayPoint wayPoint = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - 1.0f), SpawnType.Path, submarine);
|
||||
ladderPoints.Add(wayPoint);
|
||||
wayPoint.ConnectTo(prevPoint);
|
||||
}
|
||||
|
||||
//connect ladder waypoints to hull points at the right and left side
|
||||
|
||||
// Connect ladder waypoints to hull points at the right and left side
|
||||
foreach (WayPoint ladderPoint in ladderPoints)
|
||||
{
|
||||
ladderPoint.Ladders = ladders;
|
||||
//don't connect if the waypoint is at a gap (= at the boundary of hulls and/or at a hatch)
|
||||
if (ladderPoint.ConnectedGap != null) continue;
|
||||
|
||||
bool isHatch = ladderPoint.ConnectedGap != null && !ladderPoint.ConnectedGap.IsRoomToRoom;
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
WayPoint closest = ladderPoint.FindClosest(dir, true, new Vector2(-150.0f, 50f));
|
||||
if (closest == null) continue;
|
||||
WayPoint closest = null;
|
||||
if (isHatch)
|
||||
{
|
||||
closest = ladderPoint.FindClosest(dir, horizontalSearch: true, new Vector2(500, 1000), ladderPoint.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, filter: wp => wp.CurrentHull == null, ignored: ladderPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
closest = ladderPoint.FindClosest(dir, horizontalSearch: true, new Vector2(150, 70), ladderPoint.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, ignored: ladderPoints);
|
||||
}
|
||||
if (closest == null) { continue; }
|
||||
ladderPoint.ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
|
||||
// Another pass: connect cap and bottom points with other ladders when they are vertically adjacent to another (double ladders)
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!gap.IsHorizontal) continue;
|
||||
|
||||
//too small to walk through
|
||||
if (gap.Rect.Height < 150.0f) continue;
|
||||
|
||||
var wayPoint = new WayPoint(
|
||||
new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor), SpawnType.Path, submarine, gap);
|
||||
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
float tolerance = gap.IsRoomToRoom ? 50.0f : outSideWaypointInterval / 2.0f;
|
||||
|
||||
WayPoint closest = wayPoint.FindClosest(
|
||||
dir, true, new Vector2(-tolerance, tolerance),
|
||||
gap.ConnectedDoor?.Body.FarseerBody);
|
||||
|
||||
if (closest != null)
|
||||
{
|
||||
wayPoint.ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
var ladders = item.GetComponent<Ladder>();
|
||||
if (ladders == null) { continue; }
|
||||
var wps = WayPointList.Where(wp => wp.Ladders == ladders).OrderByDescending(wp => wp.Rect.Y);
|
||||
WayPoint cap = wps.First();
|
||||
WayPoint above = cap.FindClosest(1, horizontalSearch: false, tolerance: new Vector2(25, 50), filter: wp => wp.Ladders != null && wp.Ladders != ladders);
|
||||
above?.ConnectTo(cap);
|
||||
WayPoint bottom = wps.Last();
|
||||
WayPoint below = bottom.FindClosest(-1, horizontalSearch: false, tolerance: new Vector2(25, 50), filter: wp => wp.Ladders != null && wp.Ladders != ladders);
|
||||
below?.ConnectTo(bottom);
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.IsHorizontal || gap.IsRoomToRoom || !gap.linkedTo.Any(l => l is Hull)) { continue; }
|
||||
|
||||
//too small to walk through
|
||||
if (gap.Rect.Width < 100.0f) { continue; }
|
||||
|
||||
var wayPoint = new WayPoint(
|
||||
new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height / 2), SpawnType.Path, submarine, gap);
|
||||
|
||||
float tolerance = outSideWaypointInterval / 2.0f;
|
||||
Hull connectedHull = (Hull)gap.linkedTo.First(l => l is Hull);
|
||||
int dir = Math.Sign(connectedHull.Position.Y - gap.Position.Y);
|
||||
|
||||
WayPoint closest = wayPoint.FindClosest(
|
||||
dir, false, new Vector2(-tolerance, tolerance),
|
||||
gap.ConnectedDoor?.Body.FarseerBody);
|
||||
|
||||
if (closest != null)
|
||||
if (gap.IsHorizontal)
|
||||
{
|
||||
wayPoint.ConnectTo(closest);
|
||||
// Too small to walk through
|
||||
if (gap.Rect.Height < hullMinHeight) { continue; }
|
||||
Vector2 pos = new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor);
|
||||
var wayPoint = new WayPoint(pos, SpawnType.Path, submarine, gap);
|
||||
// The closest waypoint can be quite far if the gap is at an exterior door.
|
||||
Vector2 tolerance = gap.IsRoomToRoom ? new Vector2(150, 70) : new Vector2(1000, 1000);
|
||||
for (int dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
WayPoint closest = wayPoint.FindClosest(dir, horizontalSearch: true, tolerance, gap.ConnectedDoor?.Body.FarseerBody);
|
||||
if (closest != null)
|
||||
{
|
||||
wayPoint.ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create waypoints on vertical gaps on the outer walls, also hatches.
|
||||
if (gap.IsRoomToRoom || gap.linkedTo.None(l => l is Hull)) { continue; }
|
||||
// Too small to swim through
|
||||
if (gap.Rect.Width < 50.0f) { continue; }
|
||||
Vector2 pos = new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height / 2);
|
||||
// Some hatches are created in the block above where we handle the ladder waypoints. So we need to check for duplicates.
|
||||
if (WayPointList.Any(wp => wp.ConnectedGap == gap)) { continue; }
|
||||
var wayPoint = new WayPoint(pos, SpawnType.Path, submarine, gap);
|
||||
Hull connectedHull = (Hull)gap.linkedTo.First(l => l is Hull);
|
||||
int dir = Math.Sign(connectedHull.Position.Y - gap.Position.Y);
|
||||
WayPoint closest = wayPoint.FindClosest(dir, horizontalSearch: false, new Vector2(50, 100));
|
||||
if (closest != null)
|
||||
{
|
||||
wayPoint.ConnectTo(closest);
|
||||
}
|
||||
for (dir = -1; dir <= 1; dir += 2)
|
||||
{
|
||||
closest = wayPoint.FindClosest(dir, horizontalSearch: true, new Vector2(500, 1000), gap.ConnectedDoor?.Body.FarseerBody, filter: wp => wp.CurrentHull == null);
|
||||
if (closest != null)
|
||||
{
|
||||
wayPoint.ConnectTo(closest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +615,36 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private WayPoint FindClosest(int dir, bool horizontalSearch, Vector2 tolerance, Body ignoredBody = null)
|
||||
private WayPoint FindClosestOutside(IEnumerable<WayPoint> waypointList, float tolerance, Body ignoredBody = null, IEnumerable<WayPoint> ignored = null, Func<WayPoint, bool> filter = null)
|
||||
{
|
||||
float closestDist = 0;
|
||||
WayPoint closest = null;
|
||||
foreach (WayPoint wp in waypointList)
|
||||
{
|
||||
if (wp.SpawnType != SpawnType.Path || wp == this) { continue; }
|
||||
// Ignore if already linked
|
||||
if (linkedTo.Contains(wp)) { continue; }
|
||||
if (ignored != null && ignored.Contains(wp)) { continue; }
|
||||
if (filter != null && !filter(wp)) { continue; }
|
||||
float sqrDist = Vector2.DistanceSquared(Position, wp.Position);
|
||||
if (closest == null || sqrDist < closestDist)
|
||||
{
|
||||
var body = Submarine.CheckVisibility(SimPosition, wp.SimPosition, ignoreLevel: true, ignoreSubs: true, ignoreSensors: false);
|
||||
if (body != null && body != ignoredBody && !(body.UserData is Submarine))
|
||||
{
|
||||
if (body.UserData is Structure || body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
closestDist = sqrDist;
|
||||
closest = wp;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
private WayPoint FindClosest(int dir, bool horizontalSearch, Vector2 tolerance, Body ignoredBody = null, IEnumerable<WayPoint> ignored = null, Func<WayPoint, bool> filter = null)
|
||||
{
|
||||
if (dir != -1 && dir != 1) { return null; }
|
||||
|
||||
@@ -473,33 +655,45 @@ namespace Barotrauma
|
||||
{
|
||||
if (wp.SpawnType != SpawnType.Path || wp == this) { continue; }
|
||||
|
||||
float xDiff = wp.Position.X - Position.X;
|
||||
float yDiff = wp.Position.Y - Position.Y;
|
||||
float xDist = Math.Abs(xDiff);
|
||||
float yDist = Math.Abs(yDiff);
|
||||
if (tolerance.X < xDist) { continue; }
|
||||
if (tolerance.Y < yDist) { continue; }
|
||||
|
||||
float dist = 0.0f;
|
||||
float diff = 0.0f;
|
||||
if (horizontalSearch)
|
||||
{
|
||||
if ((wp.Position.Y - Position.Y) < tolerance.X || (wp.Position.Y - Position.Y) > tolerance.Y) { continue; }
|
||||
diff = wp.Position.X - Position.X;
|
||||
dist = Math.Abs(diff) + Math.Abs(wp.Position.Y - Position.Y) / 5.0f;
|
||||
diff = xDiff;
|
||||
dist = xDist + yDist / 5.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((wp.Position.X - Position.X) < tolerance.X || (wp.Position.X - Position.X) > tolerance.Y) { continue; }
|
||||
diff = wp.Position.Y - Position.Y;
|
||||
dist = Math.Abs(diff) + Math.Abs(wp.Position.X - Position.X) / 5.0f;
|
||||
diff = yDiff;
|
||||
dist = yDist + xDist / 5.0f;
|
||||
//prefer ladder waypoints when moving vertically
|
||||
if (wp.Ladders != null) { dist *= 0.5f; }
|
||||
}
|
||||
|
||||
if (Math.Sign(diff) != dir) { continue; }
|
||||
// Ignore if already linked
|
||||
if (linkedTo.Contains(wp)) { continue; }
|
||||
if (ignored != null && ignored.Contains(wp)) { continue; }
|
||||
if (filter != null && !filter(wp)) { continue; }
|
||||
|
||||
if (closest == null || dist < closestDist)
|
||||
{
|
||||
var body = Submarine.CheckVisibility(SimPosition, wp.SimPosition, true, true, false);
|
||||
var body = Submarine.CheckVisibility(SimPosition, wp.SimPosition, ignoreLevel: true, ignoreSubs: true, ignoreSensors: false);
|
||||
if (body != null && body != ignoredBody && !(body.UserData is Submarine))
|
||||
{
|
||||
if (body.UserData is Structure || body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall)) { continue; }
|
||||
if (body.UserData is Structure || body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
closestDist = dist;
|
||||
closest = wp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user