3 using FarseerPhysics.Dynamics;
4 using Microsoft.Xna.Framework;
6 using System.Collections.Generic;
25 private string[] idCardTags;
26 private ushort ladderId;
30 private HashSet<Identifier> tags;
40 private HashSet<Gap> openGaps;
48 openGaps ??=
new HashSet<Gap>();
74 public RuinGeneration.Ruin
Ruin;
90 public override string Name
101 get {
return idCardTags; }
105 for (
int i = 0; i < idCardTags.Length; i++)
107 idCardTags[i] = idCardTags[i].Trim().ToLowerInvariant();
112 public IEnumerable<Identifier>
Tags => tags;
117 : this(new
Rectangle((int)position.X - 3, (int)position.Y + 3, 6, 6), submarine)
160 idCardTags = Array.Empty<
string>();
161 tags =
new HashSet<Identifier>();
164 if (iconSprites ==
null)
166 iconSprites =
new Dictionary<string, Sprite>()
168 {
"Path",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(0,0,128,128)) },
169 {
"Human",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(128,0,128,128)) },
170 {
"Enemy",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(256,0,128,128)) },
171 {
"Cargo",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(384,0,128,128)) },
172 {
"Corpse",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(512,0,128,128)) },
173 {
"Ladder",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(0,128,128,128)) },
174 {
"Door",
new Sprite(
"Content/UI/MainIconsAtlas.png",
new Rectangle(128,128,128,128)) },
175 {
"Submarine",
new Sprite(
"Content/UI/CommandUIBackground.png",
new Rectangle(0,896,128,128)) },
176 {
"ExitPoint",
new Sprite(
"Content/UI/CommandUIBackground.png",
new Rectangle(0,896,128,128)) }
184 DebugConsole.Log(
"Created waypoint (" +
ID +
")");
194 idCardTags = idCardTags,
207 DebugConsole.ThrowError(
"Couldn't generate waypoints: no hulls found.");
212 foreach (
WayPoint wayPoint
in existingWaypoints)
219 List<Door> openDoors =
new List<Door>();
222 var door = item.GetComponent<
Door>();
223 if (door !=
null && !door.Body.Enabled)
229 bool isFlooded = submarine.Info.IsRuin || submarine.Info.Type ==
SubmarineType.OutpostModule && submarine.Info.OutpostModuleInfo.ModuleFlags.Contains(
"ruin".ToIdentifier());
230 float diffFromHullEdge = 50;
231 float minDist = 100.0f;
232 float heightFromFloor = 110.0f;
233 float hullMinHeight = 100;
235 var removals =
new HashSet<WayPoint>();
240 diffFromHullEdge = 75;
241 var hullWaypoints =
new List<WayPoint>();
242 float top = hull.
Rect.Y;
243 float bottom = hull.
Rect.Y - hull.
Rect.Height;
244 if (hull.
Rect.Width < 300 || hull.
Rect.Height < 300)
247 if (hull.
Rect.Width > hull.
Rect.Height)
250 float y = hull.
Rect.Y - hull.
Rect.Height / 2;
251 for (
float x = hull.
Rect.X + diffFromHullEdge; x <= hull.
Rect.Right - diffFromHullEdge; x += minDist)
259 float x = hull.
Rect.X + hull.
Rect.Width / 2;
260 for (
float y = top - diffFromHullEdge; y >= bottom + diffFromHullEdge; y -= minDist)
266 if (hullWaypoints.None())
269 for (
float x = hull.
Rect.X + diffFromHullEdge; x <= hull.
Rect.Right - diffFromHullEdge; x += minDist)
271 for (
float y = top - diffFromHullEdge; y >= bottom + diffFromHullEdge; y -= minDist)
276 if (hullWaypoints.None())
281 foreach (
WayPoint wp
in hullWaypoints)
289 rect.Inflate(10, 10);
299 foreach (var wayPoint
in hullWaypoints)
301 for (
int dir = -1; dir <= 1; dir += 2)
303 WayPoint closest = wayPoint.FindClosest(dir, horizontalSearch:
true,
new Vector2(minDist * 1.9f, minDist));
304 if (closest !=
null && closest.
CurrentHull == wayPoint.CurrentHull)
308 closest = wayPoint.FindClosest(dir, horizontalSearch:
false,
new Vector2(minDist, minDist * 1.9f));
309 if (closest !=
null && closest.
CurrentHull == wayPoint.CurrentHull)
318 if (hull.
Rect.Height < hullMinHeight) {
continue; }
321 for (
int i = 0; i < 5; i++)
323 float horizontalOffset = 0;
327 horizontalOffset = hull.
RectWidth * 0.2f;
330 horizontalOffset = hull.
RectWidth * 0.4f;
333 horizontalOffset = -hull.
RectWidth * 0.2f;
336 horizontalOffset = -hull.
RectWidth * 0.4f;
339 horizontalOffset = ConvertUnits.ToSimUnits(horizontalOffset);
340 Vector2 floorPos =
new Vector2(hull.
SimPosition.X + horizontalOffset, ConvertUnits.ToSimUnits(hull.
Rect.Y - hull.
RectHeight - 50));
342 if (floor !=
null) {
break; }
344 if (floor ==
null) {
continue; }
345 float waypointHeight = hull.
Rect.Height > heightFromFloor * 2 ? heightFromFloor : hull.
Rect.Height / 2;
346 if (hull.
Rect.Width < diffFromHullEdge * 3.0f)
353 for (
float x = hull.
Rect.X + diffFromHullEdge; x <= hull.
Rect.Right - diffFromHullEdge; x += minDist)
357 if (wayPoint.FindStairs() !=
null)
359 removals.Add(wayPoint);
362 if (previousWaypoint !=
null)
364 wayPoint.ConnectTo(previousWaypoint);
366 previousWaypoint = wayPoint;
368 if (previousWaypoint ==
null)
381 float waypointHeight = heightFromFloor;
383 for (
float x = platform.
Rect.X + diffFromHullEdge; x <= platform.
Rect.Right - diffFromHullEdge; x += minDist)
386 if (prevWaypoint !=
null)
391 if (wayPoint !=
null)
393 for (
int dir = -1; dir <= 1; dir += 2)
395 if (wayPoint.FindClosest(dir, horizontalSearch:
true, tolerance:
new Vector2(minDist, heightFromFloor), ignored: prevWaypoint.ToEnumerable()) !=
null)
403 prevWaypoint = wayPoint;
407 float outSideWaypointInterval = 100.0f;
408 if (!isFlooded && submarine.Info.Type !=
SubmarineType.OutpostModule)
413 int originalWidth = borders.Width;
414 int originalHeight = borders.Height;
415 borders.X -= Math.Min(500, originalWidth / 4);
416 borders.Y += Math.Min(500, originalHeight / 4);
417 borders.Width += Math.Min(1500, originalWidth / 2);
418 borders.Height += Math.Min(1000, originalHeight / 2);
419 borders.Location -= MathUtils.ToPoint(submarine.HiddenSubPosition);
421 if (borders.Width <= outSideWaypointInterval * 2)
423 borders.Inflate(outSideWaypointInterval * 2 - borders.Width, 0);
426 if (borders.Height <= outSideWaypointInterval * 2)
428 int inflateAmount = (int)(outSideWaypointInterval * 2) - borders.Height;
429 borders.Y += inflateAmount / 2;
430 borders.Height += inflateAmount;
434 for (
int i = 0; i < 2; i++)
436 for (
float x = borders.X + outSideWaypointInterval; x < borders.Right - outSideWaypointInterval; x += outSideWaypointInterval)
439 new Vector2(x, borders.Y - borders.Height * i) + submarine.HiddenSubPosition,
442 outsideWaypoints.Add((wayPoint, i));
444 if (x == borders.X + outSideWaypointInterval)
446 cornerWaypoint[i, 0] = wayPoint;
457 for (
int i = 0; i < 2; i++)
460 for (
float y = borders.Y - borders.Height; y < borders.Y; y += outSideWaypointInterval)
463 new Vector2(borders.X + borders.Width * i, y) + submarine.HiddenSubPosition,
466 outsideWaypoints.Add((wayPoint, i));
468 if (y == borders.Y - borders.Height)
470 wayPoint.
ConnectTo(cornerWaypoint[1, i]);
478 wayPoint.
ConnectTo(cornerWaypoint[0, i]);
481 Vector2 center = ConvertUnits.ToSimUnits(submarine.HiddenSubPosition);
482 float halfHeight = ConvertUnits.ToSimUnits(borders.Height / 2);
484 foreach (var wayPoint
in outsideWaypoints)
488 Vector2 targetPos =
new Vector2(center.X - xDiff * 0.5f, center.Y);
493 targetPos =
new Vector2(center.X - xDiff, center.Y);
498 float distanceFromWall = 1;
499 if (xDiff > 0 && !submarine.Info.HasTag(
SubmarineTag.Shuttle))
502 float yDist = Math.Abs(center.Y - wp.
SimPosition.Y);
503 distanceFromWall = MathHelper.Lerp(1, 3, MathUtils.InverseLerp(halfHeight, 0, yDist));
506 wp.
rect =
new Rectangle(ConvertUnits.ToDisplayUnits(newPos).ToPoint(), wp.
rect.Size);
512 float tooClose = outSideWaypointInterval / 2;
513 foreach (var wayPoint
in outsideWaypoints)
524 foreach (var otherWayPoint
in outsideWaypoints)
526 WayPoint otherWp = otherWayPoint.Item1;
527 if (otherWp == wp) {
continue; }
528 if (removals.Contains(otherWp)) {
continue; }
529 float sqrDist = Vector2.DistanceSquared(wp.Position, otherWp.
Position);
531 if (!removals.Contains(previous) && sqrDist < tooClose * tooClose)
540 outsideWaypoints.
RemoveAll(w => w.Item1 == wp);
542 removals.ForEach(wp => wp.
Remove());
543 for (
int i = 0; i < outsideWaypoints.Count; i++)
545 WayPoint current = outsideWaypoints[i].Item1;
546 if (current.
linkedTo.Count(l => !removals.Contains(l)) > 1) {
continue; }
548 int maxConnections = 2;
549 float tooFar = outSideWaypointInterval * 5;
550 for (
int j = 0; j < maxConnections; j++)
552 if (current.
linkedTo.Count >= maxConnections) {
break; }
553 tooFar /= current.
linkedTo.Count(l => !removals.Contains(l));
554 next = current.FindClosestOutside(outsideWaypoints, tolerance: tooFar, filter: wp => wp.Item1 != next && wp.Item1.
linkedTo.None(e => current.
linkedTo.Contains(e)) && wp.Item1.
linkedTo.Count < 2 && wp.Item2 < i);
562 removals.ForEach(wp => wp.
Remove());
567 if (!(mapEntity is
Structure structure)) {
continue; }
568 if (structure.StairDirection ==
Direction.None) {
continue; }
572 stairPoints[0] =
new WayPoint(
new Vector2(
573 structure.Rect.X + 5,
574 structure.Rect.Y - (structure.StairDirection ==
Direction.Left ? margin : structure.Rect.Height - 100)),
SpawnType.Path, submarine);
576 stairPoints[1] =
new WayPoint(
new Vector2(
577 structure.Rect.Right - 5,
578 structure.Rect.Y - (structure.StairDirection ==
Direction.Left ? structure.Rect.Height - 100 : margin)),
SpawnType.Path, submarine);
580 for (
int i = 0; i < 2; i++)
582 for (
int dir = -1; dir <= 1; dir += 2)
584 WayPoint closest = stairPoints[i].FindClosest(dir, horizontalSearch:
true,
new Vector2(minDist * 1.5f, minDist / 2));
585 if (closest ==
null) {
continue; }
591 stairPoints[0].
ConnectTo(stairPoints[2]);
592 stairPoints[2].
ConnectTo(stairPoints[1]);
593 stairPoints.ForEach(wp => wp.FindStairs());
599 var ladders = item.GetComponent<
Ladder>();
600 if (ladders ==
null) {
continue; }
602 Vector2 bottomPoint =
new Vector2(item.
Rect.Center.X, item.
Rect.Top - item.
Rect.Height + 10);
603 List<(
WayPoint wp,
bool connectHullPoints)> ladderPoints =
new List<(
WayPoint,
bool)>
608 List<Body> ignoredBodies =
new List<Body>();
611 WayPoint lowestPoint = ladderPoints[0].wp;
615 collisionCategory: Physics.CollisionWall | Physics.CollisionPlatform | Physics.CollisionStairs,
616 customPredicate: f => !(f.Body.UserData is
Submarine));
617 float startHeight = ground !=
null ? ConvertUnits.ToDisplayUnits(ground.Position.Y) : bottomPoint.Y;
618 startHeight += heightFromFloor;
620 Vector2 nextPos =
new Vector2(item.
Rect.Center.X, startHeight);
623 if (lowestPoint ==
null || Math.Abs(startPoint.
Position.Y - startHeight) > 40 &&
Hull.
FindHull(nextPos) !=
null)
626 ladderPoints.Add((startPoint,
true));
627 if (lowestPoint !=
null)
631 prevPoint = startPoint;
639 ConvertUnits.ToSimUnits(
new Vector2(startPoint.
Position.X, y)),
640 prevPos, ignoredBodies, Physics.CollisionWall,
false,
641 (Fixture f) => f.Body.UserData is
Item pickedItem && pickedItem.GetComponent<
Door>() !=
null);
643 Door pickedDoor =
null;
644 if (pickedBody !=
null)
646 pickedDoor = (pickedBody?.UserData as
Item).GetComponent<Door>();
652 ConvertUnits.ToSimUnits(
new Vector2(startPoint.
Position.X, y)), prevPos, ignoredBodies,
null,
false,
653 (Fixture f) => f.Body.UserData is
Structure);
656 if (pickedBody !=
null)
658 ignoredBodies.Add(pickedBody);
661 if (pickedDoor !=
null)
664 ladderPoints.Add((newPoint,
true));
668 prevPoint = newPoint;
669 prevPos =
new Vector2(prevPos.X, ConvertUnits.ToSimUnits(pickedDoor.
Item.
Position.Y - pickedDoor.
Item.
Rect.Height));
675 Vector2 pos = pickedBody ==
null ?
new Vector2(startPoint.
Position.X, y) :
678 ladderPoints.Add((newPoint, pickedBody !=
null));
680 prevPoint = newPoint;
681 prevPos = ConvertUnits.ToSimUnits(newPoint.
Position);
682 if (pickedBody !=
null)
685 y = Math.Max(newPoint.
Position.Y, y);
691 if (prevPoint.
rect.Y < item.
Rect.Y - 40)
694 ladderPoints.Add((wayPoint,
true));
699 var ladderWaypoints = ladderPoints.Select(lp => lp.wp);
700 foreach (var ladderPoint
in ladderPoints)
702 var wp = ladderPoint.wp;
703 wp.Ladders = ladders;
704 if (!ladderPoint.connectHullPoints) {
continue; }
705 bool isHatch = wp.ConnectedGap !=
null && !wp.ConnectedGap.IsRoomToRoom;
706 for (
int dir = -1; dir <= 1; dir += 2)
709 wp.FindClosest(dir, horizontalSearch:
true,
new Vector2(500, 1000), wp.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, filter: wp => wp.CurrentHull ==
null, ignored: ladderWaypoints) :
710 wp.FindClosest(dir, horizontalSearch:
true,
new Vector2(150, 100), wp.ConnectedGap?.ConnectedDoor?.Body.FarseerBody, ignored: ladderWaypoints);
711 if (closest ==
null) {
continue; }
720 var ladders = item.GetComponent<
Ladder>();
721 if (ladders ==
null) {
continue; }
722 var wps =
WayPointList.Where(wp => wp.Ladders == ladders).OrderByDescending(wp => wp.Rect.Y);
724 WayPoint above = cap.FindClosest(1, horizontalSearch:
false, tolerance:
new Vector2(25, 50), filter: wp => wp.Ladders !=
null && wp.Ladders != ladders);
727 WayPoint below = bottom.FindClosest(-1, horizontalSearch:
false, tolerance:
new Vector2(25, 50), filter: wp => wp.Ladders !=
null && wp.Ladders != ladders);
738 if (gap.
Rect.Height < 50) {
continue; }
743 if (gap.
Rect.Height < hullMinHeight) {
continue; }
746 Vector2 pos =
new Vector2(gap.
Rect.Center.X, gap.
Rect.Y - gap.
Rect.Height + heightFromFloor);
749 pos.Y = gap.
Rect.Y - gap.
Rect.Height / 2;
753 Vector2 tolerance = gap.
IsRoomToRoom && !isFlooded ?
new Vector2(150, 70) :
new Vector2(1000, 1000);
754 for (
int dir = -1; dir <= 1; dir += 2)
768 if (gap.
Rect.Width < 50.0f) {
continue; }
769 Vector2 pos =
new Vector2(gap.
Rect.Center.X, gap.
Rect.Y - gap.
Rect.Height / 2);
771 if (
WayPointList.Any(wp => wp.ConnectedGap == gap)) {
continue; }
775 WayPoint closest = wayPoint.FindClosest(dir, horizontalSearch:
false, isFlooded ?
new Vector2(500, 500) :
new Vector2(50, 100));
782 closest = wayPoint.FindClosest(-dir, horizontalSearch:
false, isFlooded ?
new Vector2(500, 500) :
new Vector2(50, 100));
789 for (dir = -1; dir <= 1; dir += 2)
791 closest = wayPoint.FindClosest(dir, horizontalSearch:
true,
new Vector2(500, 1000), gap.
ConnectedDoor?.
Body.
FarseerBody, filter: wp => wp.CurrentHull ==
null);
810 DebugConsole.ThrowError($
"Couldn't automatically link the waypoint {wp.ID} outside of the submarine. You should do it manually. The waypoint ID is shown in red color.");
815 foreach (
Door door
in openDoors)
823 private WayPoint FindClosestOutside(IEnumerable<(
WayPoint,
int)> waypointList,
float tolerance, Body ignoredBody =
null, IEnumerable<WayPoint> ignored =
null, Func<(
WayPoint,
int),
bool> filter =
null)
825 float closestDist = 0;
827 foreach (var wayPoint
in waypointList)
832 if (
linkedTo.Contains(wp)) {
continue; }
833 if (ignored !=
null && ignored.Contains(wp)) {
continue; }
834 if (filter !=
null && !filter(wayPoint)) {
continue; }
836 if (sqrDist > tolerance * tolerance) {
continue; }
837 if (closest ==
null || sqrDist < closestDist)
840 if (body !=
null && body != ignoredBody && !(body.UserData is
Submarine))
842 if (body.UserData is Structure || body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall))
847 closestDist = sqrDist;
854 private WayPoint FindClosest(
int dir,
bool horizontalSearch, Vector2 tolerance, Body ignoredBody =
null, IEnumerable<WayPoint> ignored =
null, Func<WayPoint, bool> filter =
null)
856 if (dir != -1 && dir != 1) {
return null; }
858 float closestDist = 0.0f;
863 if (wp.SpawnType !=
SpawnType.Path || wp ==
this) {
continue; }
866 float yDiff = wp.Position.Y -
Position.Y;
867 float xDist = Math.Abs(xDiff);
868 float yDist = Math.Abs(yDiff);
869 if (tolerance.X < xDist) {
continue; }
870 if (tolerance.Y < yDist) {
continue; }
874 if (horizontalSearch)
877 dist = xDist + yDist / 5.0f;
882 dist = yDist + xDist / 5.0f;
884 if (wp.Ladders !=
null) { dist *= 0.5f; }
887 if (Math.Sign(diff) != dir) {
continue; }
889 if (
linkedTo.Contains(wp)) {
continue; }
890 if (ignored !=
null && ignored.Contains(wp)) {
continue; }
891 if (filter !=
null && !filter(wp)) {
continue; }
893 if (closest ==
null || dist < closestDist)
896 if (body !=
null && body != ignoredBody && !(body.UserData is
Submarine))
898 if (body.UserData is Structure)
902 if (body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall) && body.UserData is Item i && i.GetComponent<
Door>() !=
null)
918 System.Diagnostics.Debug.Assert(
this != wayPoint2);
924 if (!wayPoint2.
linkedTo.Contains(
this))
934 (ignoreSubmarine || wp.Submarine == sub) &&
937 !wp.spawnType.HasFlag(
SpawnType.Disabled) &&
939 (spawnPointTag.IsNullOrEmpty() || wp.Tags.Any(t => t == spawnPointTag)) &&
940 (assignedJob ==
null || (assignedJob !=
null && wp.AssignedJob == assignedJob)),
941 useSyncedRand ? Rand.RandSync.ServerAndClient : Rand.RandSync.Unsynced);
946 List<WayPoint> subWayPoints =
WayPointList.FindAll(wp => wp.Submarine == submarine);
947 subWayPoints.Shuffle();
949 List<WayPoint> unassignedWayPoints = subWayPoints.FindAll(wp => wp.spawnType ==
SpawnType.Human);
953 for (
int i = 0; i < crew.Count; i++ )
956 for (
int n = 0; n < unassignedWayPoints.Count; n++)
958 if (crew[i].
Job.
Prefab != unassignedWayPoints[n].AssignedJob) {
continue; }
959 assignedWayPoints[i] = unassignedWayPoints[n];
960 unassignedWayPoints.RemoveAt(n);
967 for (
int i = 0; i < crew.Count; i++)
969 if (assignedWayPoints[i] !=
null) {
continue; }
972 foreach (
WayPoint wp
in subWayPoints)
976 assignedWayPoints[i] = wp;
979 if (assignedWayPoints[i] !=
null) {
continue; }
983 if (nonJobSpecificPoints.Any())
985 assignedWayPoints[i] = nonJobSpecificPoints[Rand.Int(nonJobSpecificPoints.Count, Rand.RandSync.ServerAndClient)];
988 if (assignedWayPoints[i] !=
null) {
continue; }
991 assignedWayPoints[i] =
GetRandom(
SpawnType.Human,
null, submarine, useSyncedRand:
true);
994 for (
int i = 0; i < assignedWayPoints.Length; i++)
996 if (assignedWayPoints[i] ==
null)
998 DebugConsole.AddWarning(
"Couldn't find a waypoint for " + crew[i].
Name +
"!");
1003 return assignedWayPoints;
1071 if (!
string.IsNullOrWhiteSpace(idCardDescString))
1076 if (!
string.IsNullOrWhiteSpace(idCardTagString))
1086 if (!jobIdentifier.IsEmpty)
1098 int srcId =
int.Parse(element.
GetAttribute(
"linkedto" + i).Value);
1114 public override XElement
Save(XElement parentElement)
1117 XElement element =
new XElement(
"WayPoint");
1119 element.Add(
new XAttribute(
"ID",
ID),
1123 new XAttribute(nameof(
Layer),
Layer ??
string.Empty));
1126 element.Add(
new XAttribute(
"exitpointsize", XMLExtensions.PointToString(
ExitPointSize)));
1129 if (!
string.IsNullOrWhiteSpace(
IdCardDesc)) element.Add(
new XAttribute(
"idcarddesc",
IdCardDesc));
1130 if (idCardTags.Length > 0)
1132 element.Add(
new XAttribute(
"idcardtags",
string.Join(
",", idCardTags)));
1136 element.Add(
new XAttribute(
"tags",
string.Join(
",", tags)));
1143 parentElement.Add(element);
1152 element.Add(
new XAttribute(
"linkedto" + i, e.
ID));
1162 base.ShallowRemove();
string? GetAttributeString(string key, string? def)
Identifier[] GetAttributeIdentifierArray(Identifier[] def, params string[] keys)
Point GetAttributePoint(string key, in Point def)
int GetAttributeInt(string key, int def)
XAttribute? GetAttribute(string name)
Identifier GetAttributeIdentifier(string key, string def)
virtual Vector2 WorldPosition
const ushort NullEntityID
readonly ushort ID
Unique, but non-persistent identifier. Stays the same if the entities are created in the exactly same...
static Entity FindEntityByID(ushort ID)
Find an entity based on the ID
static SubEditorScreen SubEditorScreen
static List< Gap > GapList
static Hull FindHull(Vector2 position, Hull guess=null, bool useWorldCoordinates=true, bool inclusive=true)
Returns the hull which contains the point (or null if it isn't inside any)
static Rectangle GetBorders()
static readonly List< Hull > HullList
static Hull FindHullUnoptimized(Vector2 position, Hull guess=null, bool useWorldCoordinates=true, bool inclusive=true)
Returns the hull which contains the point (or null if it isn't inside any). The difference to FindHul...
ushort GetOffsetId(XElement element)
override Vector2? Position
static readonly List< Item > ItemList
static JobPrefab Get(Identifier identifier)
static readonly List< MapEntity > MapEntityList
List< ushort > linkedToID
override Vector2 Position
List< ushort > unresolvedLinkedToID
readonly List< MapEntity > linkedTo
override Vector2 SimPosition
Prefab(ContentFile file, Identifier identifier)
readonly Identifier Identifier
static List< Structure > WallList
static void StoreCommand(Command command)
static bool IsSubEditor()
static Vector2 LastPickedNormal
static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel=false, bool ignoreSubs=false, bool ignoreSensors=true, bool ignoreDisabledWalls=true, bool ignoreBranches=true, Predicate< Fixture > blocksVisibilityPredicate=null)
Check visibility between two points (in sim units).
Vector2 HiddenSubPosition
static readonly Vector2 GridSize
static Body PickBody(Vector2 rayStart, Vector2 rayEnd, IEnumerable< Body > ignoredBodies=null, Category? collisionCategory=null, bool ignoreSensors=true, Predicate< Fixture > customPredicate=null, bool allowInsideFixture=false)
static Vector2 LastPickedPosition
static bool ShowWayPoints
const float LadderWaypointInterval
static WayPoint Load(ContentXElement element, Submarine submarine, IdRemap idRemap)
WayPoint(MapEntityPrefab prefab, Rectangle rectangle)
static List< WayPoint > WayPointList
IEnumerable< Identifier > Tags
WayPoint(Rectangle newRect, Submarine submarine)
WayPoint(Type type, Rectangle newRect, Submarine submarine, ushort id=Entity.NullEntityID)
Rectangle ExitPointWorldRect
void OnGapStateChanged(bool open, Gap gap)
Only called by a Gap when the state changes. So in practice used like an event callback,...
static WayPoint GetRandom(SpawnType spawnType=SpawnType.Human, JobPrefab assignedJob=null, Submarine sub=null, bool useSyncedRand=false, string spawnPointTag=null, bool ignoreSubmarine=false)
override void OnMapLoaded()
WayPoint(Vector2 position, SpawnType spawnType, Submarine submarine, Gap gap=null)
override void ShallowRemove()
Remove the entity from the entity list without removing links to other entities
Action< WayPoint > OnLinksChanged
override MapEntity Clone()
static bool GenerateSubWaypoints(Submarine submarine)
override XElement Save(XElement parentElement)
static WayPoint[] SelectCrewSpawnPoints(List< CharacterInfo > crew, Submarine submarine)
void ConnectTo(WayPoint wayPoint2)