private bool NeedNewPath() { if (this.destination.IsValid && this.curPath != null && this.curPath.Found && this.curPath.NodesLeftCount != 0) { if (this.destination.HasThing && this.destination.Thing.Map != this.pawn.Map) { return(true); } if (!ReachabilityImmediate.CanReachImmediate(this.curPath.LastNode, this.destination, this.pawn.Map, this.peMode, this.pawn)) { return(true); } if (this.lastPathedTargetPosition != this.destination.Cell) { float num = (float)(this.pawn.Position - this.destination.Cell).LengthHorizontalSquared; float num2 = (float)((!(num > 900.0)) ? ((!(num > 289.0)) ? ((!(num > 100.0)) ? ((!(num > 49.0)) ? 0.5 : 2.0) : 3.0) : 5.0) : 10.0); if ((float)(this.lastPathedTargetPosition - this.destination.Cell).LengthHorizontalSquared > num2 * num2) { return(true); } } bool flag = PawnUtility.ShouldCollideWithPawns(this.pawn); bool flag2 = this.curPath.NodesLeftCount < 30; IntVec3 other = IntVec3.Invalid; int num3 = 0; while (num3 < 20 && num3 < this.curPath.NodesLeftCount) { IntVec3 intVec = this.curPath.Peek(num3); if (!intVec.Walkable(this.pawn.Map)) { return(true); } if (flag && !this.BestPathHadPawnsInTheWayRecently() && (PawnUtility.AnyPawnBlockingPathAt(intVec, this.pawn, false, true) || (flag2 && PawnUtility.AnyPawnBlockingPathAt(intVec, this.pawn, false, false)))) { return(true); } if (!this.BestPathHadDangerRecently() && PawnUtility.KnownDangerAt(intVec, this.pawn)) { return(true); } Building_Door building_Door = intVec.GetEdifice(this.pawn.Map) as Building_Door; if (building_Door != null) { if (!building_Door.CanPhysicallyPass(this.pawn) && !this.pawn.HostileTo(building_Door)) { return(true); } if (building_Door.IsForbiddenToPass(this.pawn)) { return(true); } } if (num3 != 0 && intVec.AdjacentToDiagonal(other) && (PathFinder.BlocksDiagonalMovement(intVec.x, other.z, this.pawn.Map) || PathFinder.BlocksDiagonalMovement(other.x, intVec.z, this.pawn.Map))) { return(true); } other = intVec; num3++; } return(false); } return(true); }
public int GetRegionDistance(Region region, out RegionLink minLink) { if (regionMinLink.TryGetValue(region.id, out minLink)) { return(distances[minLink]); } while (queue.Count != 0) { RegionLinkQueueEntry regionLinkQueueEntry = queue.Pop(); int num = distances[regionLinkQueueEntry.Link]; if (regionLinkQueueEntry.Cost != num) { continue; } Region otherRegion = regionLinkQueueEntry.Link.GetOtherRegion(regionLinkQueueEntry.From); if (otherRegion == null || !otherRegion.valid) { continue; } int num2 = 0; if (otherRegion.door != null) { num2 = PathFinder.GetBuildingCost(otherRegion.door, traverseParms, traverseParms.pawn); if (num2 == int.MaxValue) { continue; } num2 += OctileDistance(1, 0); } int minPathCost = RegionMedianPathCost(otherRegion); for (int i = 0; i < otherRegion.links.Count; i++) { RegionLink regionLink = otherRegion.links[i]; if (regionLink == regionLinkQueueEntry.Link || !regionLink.GetOtherRegion(otherRegion).type.Passable()) { continue; } int val = ((otherRegion.door != null) ? num2 : RegionLinkDistance(regionLinkQueueEntry.Link, regionLink, minPathCost)); val = Math.Max(val, 1); int num3 = num + val; int estimatedPathCost = MinimumRegionLinkDistance(destinationCell, regionLink) + num3; if (distances.TryGetValue(regionLink, out var value)) { if (num3 < value) { distances[regionLink] = num3; queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num3, estimatedPathCost)); } } else { distances.Add(regionLink, num3); queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num3, estimatedPathCost)); } } if (!regionMinLink.ContainsKey(otherRegion.id)) { regionMinLink.Add(otherRegion.id, regionLinkQueueEntry.Link); if (otherRegion == region) { minLink = regionLinkQueueEntry.Link; return(regionLinkQueueEntry.Cost); } } } return(10000); }
public int GetRegionDistance(Region region, out RegionLink minLink) { int result; if (this.regionMinLink.TryGetValue(region.id, out minLink)) { result = this.distances[minLink]; } else { while (this.queue.Count != 0) { RegionCostCalculator.RegionLinkQueueEntry regionLinkQueueEntry = this.queue.Pop(); int num = this.distances[regionLinkQueueEntry.Link]; if (regionLinkQueueEntry.Cost == num) { Region otherRegion = regionLinkQueueEntry.Link.GetOtherRegion(regionLinkQueueEntry.From); if (otherRegion != null && otherRegion.valid) { int num2 = 0; if (otherRegion.portal != null) { num2 = PathFinder.GetBuildingCost(otherRegion.portal, this.traverseParms, this.traverseParms.pawn); if (num2 == 2147483647) { continue; } num2 += this.OctileDistance(1, 0); } int minPathCost = this.RegionMedianPathCost(otherRegion); for (int i = 0; i < otherRegion.links.Count; i++) { RegionLink regionLink = otherRegion.links[i]; if (regionLink != regionLinkQueueEntry.Link && regionLink.GetOtherRegion(otherRegion).type.Passable()) { int num3 = (otherRegion.portal == null) ? this.RegionLinkDistance(regionLinkQueueEntry.Link, regionLink, minPathCost) : num2; num3 = Math.Max(num3, 1); int num4 = num + num3; int estimatedPathCost = this.MinimumRegionLinkDistance(this.destinationCell, regionLink) + num4; int num5; if (this.distances.TryGetValue(regionLink, out num5)) { if (num4 < num5) { this.distances[regionLink] = num4; this.queue.Push(new RegionCostCalculator.RegionLinkQueueEntry(otherRegion, regionLink, num4, estimatedPathCost)); } } else { this.distances.Add(regionLink, num4); this.queue.Push(new RegionCostCalculator.RegionLinkQueueEntry(otherRegion, regionLink, num4, estimatedPathCost)); } } } if (!this.regionMinLink.ContainsKey(otherRegion.id)) { this.regionMinLink.Add(otherRegion.id, regionLinkQueueEntry.Link); if (otherRegion == region) { minLink = regionLinkQueueEntry.Link; return(regionLinkQueueEntry.Cost); } } } } } result = 10000; } return(result); }
private void DebugFlash(IntVec3 c, float colorPct, string str) { PathFinder.DebugFlash(c, this.map, colorPct, str); }
public static bool BlocksDiagonalMovement(int x, int z, Map map) { return(PathFinder.BlocksDiagonalMovement(map.cellIndices.CellToIndex(x, z), map)); }
private bool BlocksDiagonalMovement(int index) { return(PathFinder.BlocksDiagonalMovement(index, this.map)); }
private bool BlocksDiagonalMovement(int x, int z) { return(PathFinder.BlocksDiagonalMovement(x, z, this.map)); }
public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell) { if (DebugSettings.pathThroughWalls) { traverseParms.mode = TraverseMode.PassAllDestroyableThings; } Pawn pawn = traverseParms.pawn; if (pawn != null && pawn.Map != this.map) { Log.Error(string.Concat(new object[] { "Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=", pawn, " pawn.Map=", pawn.Map, " map=", this.map })); return(PawnPath.NotFound); } if (!start.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid start ", start, ", pawn= ", pawn })); return(PawnPath.NotFound); } if (!dest.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn })); return(PawnPath.NotFound); } if (traverseParms.mode == TraverseMode.ByPawn) { if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode)) { return(PawnPath.NotFound); } } else if (!this.map.reachability.CanReach(start, dest, peMode, traverseParms)) { return(PawnPath.NotFound); } this.PfProfilerBeginSample(string.Concat(new object[] { "FindPath for ", pawn, " from ", start, " to ", dest, (!dest.HasThing) ? string.Empty : (" at " + dest.Cell) })); this.cellIndices = this.map.cellIndices; this.pathGrid = this.map.pathGrid; this.edificeGrid = this.map.edificeGrid.InnerArray; int x = dest.Cell.x; int z = dest.Cell.z; int num = this.cellIndices.CellToIndex(start); int num2 = this.cellIndices.CellToIndex(dest.Cell); ByteGrid byteGrid = (pawn == null) ? null : pawn.GetAvoidGrid(); bool flag = traverseParms.mode == TraverseMode.PassAllDestroyableThings; bool flag2 = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater; bool flag3 = !flag; CellRect cellRect = this.CalculateDestinationRect(dest, peMode); bool flag4 = cellRect.Width == 1 && cellRect.Height == 1; int[] array = this.map.pathGrid.pathGrid; EdificeGrid edificeGrid = this.map.edificeGrid; int num3 = 0; int num4 = 0; Area allowedArea = this.GetAllowedArea(pawn); bool flag5 = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn); bool flag6 = true && DebugViewSettings.drawPaths; bool flag7 = !flag && start.GetRegion(this.map, RegionType.Set_Passable) != null; bool flag8 = !flag || !flag3; bool flag9 = false; int num5 = 0; int num6 = 0; float num7 = this.DetermineHeuristicStrength(pawn, start, dest); int num8; int num9; if (pawn != null) { num8 = pawn.TicksPerMoveCardinal; num9 = pawn.TicksPerMoveDiagonal; } else { num8 = 13; num9 = 18; } this.CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); this.InitStatusesAndPushStartNode(ref num, start); while (true) { this.PfProfilerBeginSample("Open cell"); if (this.openList.Count <= 0) { break; } num5 += this.openList.Count; num6++; PathFinder.CostNode costNode = this.openList.Pop(); num = costNode.index; if (costNode.cost != this.calcGrid[num].costNodeCost) { this.PfProfilerEndSample(); } else if (this.calcGrid[num].status == this.statusClosedValue) { this.PfProfilerEndSample(); } else { IntVec3 c = this.cellIndices.IndexToCell(num); int x2 = c.x; int z2 = c.z; if (flag6) { this.DebugFlash(c, (float)this.calcGrid[num].knownCost / 1500f, this.calcGrid[num].knownCost.ToString()); } if (flag4) { if (num == num2) { goto Block_27; } } else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num)) { goto Block_29; } if (num3 > 160000) { goto Block_30; } this.PfProfilerEndSample(); this.PfProfilerBeginSample("Neighbor consideration"); for (int i = 0; i < 8; i++) { uint num10 = (uint)(x2 + PathFinder.Directions[i]); uint num11 = (uint)(z2 + PathFinder.Directions[i + 8]); if ((ulong)num10 < (ulong)((long)this.mapSizeX) && (ulong)num11 < (ulong)((long)this.mapSizeZ)) { int num12 = (int)num10; int num13 = (int)num11; int num14 = this.cellIndices.CellToIndex(num12, num13); if (this.calcGrid[num14].status != this.statusClosedValue || flag9) { int num15 = 0; bool flag10 = false; if (flag2 || !new IntVec3(num12, 0, num13).GetTerrain(this.map).HasTag("Water")) { if (!this.pathGrid.WalkableFast(num14)) { if (!flag) { if (flag6) { this.DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk"); } goto IL_C2E; } flag10 = true; num15 += 70; Building building = edificeGrid[num14]; if (building == null) { goto IL_C2E; } if (!PathFinder.IsDestroyable(building)) { goto IL_C2E; } num15 += (int)((float)building.HitPoints * 0.11f); } if (i > 3) { switch (i) { case 4: if (this.BlocksDiagonalMovement(num - this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } break; case 5: if (this.BlocksDiagonalMovement(num + this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } break; case 6: if (this.BlocksDiagonalMovement(num + this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } break; case 7: if (this.BlocksDiagonalMovement(num - this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } goto IL_C2E; } num15 += 70; } break; } } int num16 = (i <= 3) ? num8 : num9; num16 += num15; if (!flag10) { num16 += array[num14]; } if (byteGrid != null) { num16 += (int)(byteGrid[num14] * 8); } if (allowedArea != null && !allowedArea[num14]) { num16 += 600; } if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, false, false)) { num16 += 175; } Building building2 = this.edificeGrid[num14]; if (building2 != null) { this.PfProfilerBeginSample("Edifices"); int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn); if (buildingCost == 2147483647) { this.PfProfilerEndSample(); goto IL_C2E; } num16 += buildingCost; this.PfProfilerEndSample(); } int num17 = num16 + this.calcGrid[num].knownCost; ushort status = this.calcGrid[num14].status; if (status == this.statusClosedValue || status == this.statusOpenValue) { int num18 = 0; if (status == this.statusClosedValue) { num18 = num8; } if (this.calcGrid[num14].knownCost <= num17 + num18) { goto IL_C2E; } } if (status != this.statusClosedValue && status != this.statusOpenValue) { if (flag9) { this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num14) * PathFinder.RegionHeuristicWeightByNodesOpened.Evaluate((float)num4)); } else { int dx = Math.Abs(num12 - x); int dz = Math.Abs(num13 - z); int num19 = GenMath.OctileDistance(dx, dz, num8, num9); this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num19 * num7); } } int num20 = num17 + this.calcGrid[num14].heuristicCost; this.calcGrid[num14].parentIndex = num; this.calcGrid[num14].knownCost = num17; this.calcGrid[num14].status = this.statusOpenValue; this.calcGrid[num14].costNodeCost = num20; num4++; this.openList.Push(new PathFinder.CostNode(num14, num20)); } } } IL_C2E :; } this.PfProfilerEndSample(); num3++; this.calcGrid[num].status = this.statusClosedValue; if (num4 >= 2000 && flag7 && !flag9) { flag9 = true; this.regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, this.disallowedCornerIndices); this.InitStatusesAndPushStartNode(ref num, start); num4 = 0; num3 = 0; } } } string text = (pawn == null || pawn.CurJob == null) ? "null" : pawn.CurJob.ToString(); string text2 = (pawn == null || pawn.Faction == null) ? "null" : pawn.Faction.ToString(); Log.Warning(string.Concat(new object[] { pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2 })); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); Block_27: this.PfProfilerEndSample(); PawnPath result = this.FinalizedPath(num); this.PfProfilerEndSample(); return(result); Block_29: this.PfProfilerEndSample(); PawnPath result2 = this.FinalizedPath(num); this.PfProfilerEndSample(); return(result2); Block_30: Log.Warning(string.Concat(new object[] { pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells." })); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); }