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("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("Tried to FindPath with invalid start " + start + ", pawn= " + pawn); return(PawnPath.NotFound); } if (!dest.IsValid) { Log.Error("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("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; IntVec3 cell = dest.Cell; int x = cell.x; IntVec3 cell2 = dest.Cell; int z = cell2.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) { string text = (pawn == null || pawn.CurJob == null) ? "null" : pawn.CurJob.ToString(); string text2 = (pawn == null || pawn.Faction == null) ? "null" : pawn.Faction.ToString(); Log.Warning(pawn + " pathing from " + start + " to " + dest + " ran out of cells to process.\nJob:" + text + "\nFaction: " + text2); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); } num5 += this.openList.Count; num6++; CostNode costNode = this.openList.Pop(); num = costNode.index; if (costNode.cost != this.calcGrid[num].costNodeCost) { this.PfProfilerEndSample(); continue; } if (this.calcGrid[num].status == this.statusClosedValue) { this.PfProfilerEndSample(); continue; } IntVec3 c = this.cellIndices.IndexToCell(num); int x2 = c.x; int z2 = c.z; if (flag6) { this.DebugFlash(c, (float)((float)this.calcGrid[num].knownCost / 1500.0), this.calcGrid[num].knownCost.ToString()); } if (flag4) { if (num == num2) { this.PfProfilerEndSample(); PawnPath result = this.FinalizedPath(num); this.PfProfilerEndSample(); return(result); } } else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num)) { this.PfProfilerEndSample(); PawnPath result2 = this.FinalizedPath(num); this.PfProfilerEndSample(); return(result2); } if (num3 <= 160000) { 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]); int num12; int num13; int num14; bool flag10; int num15; if (num10 < this.mapSizeX && num11 < this.mapSizeZ) { num12 = (int)num10; num13 = (int)num11; num14 = this.cellIndices.CellToIndex(num12, num13); if (this.calcGrid[num14].status == this.statusClosedValue && !flag9) { continue; } num15 = 0; flag10 = false; if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(this.map).HasTag("Water")) { continue; } if (!this.pathGrid.WalkableFast(num14)) { if (!flag) { if (flag6) { this.DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk"); } } else { flag10 = true; num15 += 70; Building building = edificeGrid[num14]; if (building != null && PathFinder.IsDestroyable(building)) { num15 += (int)((float)building.HitPoints * 0.10999999940395355); goto IL_0749; } } continue; } goto IL_0749; } continue; IL_092b: if (this.BlocksDiagonalMovement(num - this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn"); } continue; } num15 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } continue; } num15 += 70; } goto IL_09bf; IL_0b0e: ushort status; 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 num16 = GenMath.OctileDistance(dx, dz, num8, num9); this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num16 * num7); } } int num17; int num18 = 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 = num18; num4++; this.openList.Push(new CostNode(num14, num18)); continue; IL_0803: if (this.BlocksDiagonalMovement(num + this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn"); } continue; } num15 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } continue; } num15 += 70; } goto IL_09bf; IL_09bf: int num19 = (i <= 3) ? num8 : num9; num19 += num15; if (!flag10) { num19 += array[num14]; } if (byteGrid != null) { num19 += byteGrid[num14] * 8; } if (allowedArea != null && !allowedArea[num14]) { num19 += 600; } if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, false, false)) { num19 += 175; } Building building2 = this.edificeGrid[num14]; if (building2 != null) { this.PfProfilerBeginSample("Edifices"); int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn); if (buildingCost == 2147483647) { this.PfProfilerEndSample(); continue; } num19 += buildingCost; this.PfProfilerEndSample(); } num17 = num19 + this.calcGrid[num].knownCost; status = this.calcGrid[num14].status; if (status != this.statusClosedValue && status != this.statusOpenValue) { goto IL_0b0e; } int num20 = 0; if (status == this.statusClosedValue) { num20 = num8; } if (this.calcGrid[num14].knownCost > num17 + num20) { goto IL_0b0e; } continue; IL_0897: if (this.BlocksDiagonalMovement(num + this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn"); } continue; } num15 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } continue; } num15 += 70; } goto IL_09bf; IL_0749: switch (i) { case 4: break; case 5: goto IL_0803; case 6: goto IL_0897; case 7: goto IL_092b; default: goto IL_09bf; } if (this.BlocksDiagonalMovement(num - this.mapSizeX)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn"); } continue; } num15 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } continue; } num15 += 70; } goto IL_09bf; } 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; } continue; } break; } Log.Warning(pawn + " pathing from " + start + " to " + dest + " hit search limit of " + 160000 + " cells."); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); }
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 }), false); return(PawnPath.NotFound); } if (!start.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid start ", start, ", pawn= ", pawn }), false); return(PawnPath.NotFound); } if (!dest.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn }), false); 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; this.blueprintGrid = this.map.blueprintGrid.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(true); bool flag = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater; 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; TerrainDef[] topGrid = this.map.terrainGrid.topGrid; 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 && flag2; bool flag8 = !flag || !flag3; bool flag9 = false; bool flag10 = pawn != null && pawn.Drafted; bool flag11 = pawn != null && pawn.IsColonist; int num5 = (!flag11) ? 2000 : 100000; int num6 = 0; int num7 = 0; float num8 = this.DetermineHeuristicStrength(pawn, start, dest); int num9; int num10; if (pawn != null) { num9 = pawn.TicksPerMoveCardinal; num10 = pawn.TicksPerMoveDiagonal; } else { num9 = 13; num10 = 18; } this.CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); this.InitStatusesAndPushStartNode(ref num, start); while (true) { this.PfProfilerBeginSample("Open cell"); if (this.openList.Count <= 0) { break; } num6 += this.openList.Count; num7++; 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_32; } } else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num)) { goto Block_34; } if (num3 > 160000) { goto Block_35; } this.PfProfilerEndSample(); this.PfProfilerBeginSample("Neighbor consideration"); for (int i = 0; i < 8; i++) { uint num11 = (uint)(x2 + PathFinder.Directions[i]); uint num12 = (uint)(z2 + PathFinder.Directions[i + 8]); if ((ulong)num11 < (ulong)((long)this.mapSizeX) && (ulong)num12 < (ulong)((long)this.mapSizeZ)) { int num13 = (int)num11; int num14 = (int)num12; int num15 = this.cellIndices.CellToIndex(num13, num14); if (this.calcGrid[num15].status != this.statusClosedValue || flag9) { int num16 = 0; bool flag12 = false; if (flag2 || !new IntVec3(num13, 0, num14).GetTerrain(this.map).HasTag("Water")) { if (!this.pathGrid.WalkableFast(num15)) { if (!flag) { if (flag6) { this.DebugFlash(new IntVec3(num13, 0, num14), 0.22f, "walk"); } goto IL_E3A; } flag12 = true; num16 += 70; Building building = edificeGrid[num15]; if (building == null) { goto IL_E3A; } if (!PathFinder.IsDestroyable(building)) { goto IL_E3A; } num16 += (int)((float)building.HitPoints * 0.2f); } 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_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } goto IL_E3A; } num16 += 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_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn"); } goto IL_E3A; } num16 += 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_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } goto IL_E3A; } num16 += 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_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn"); } goto IL_E3A; } num16 += 70; } break; } } int num17 = (i <= 3) ? num9 : num10; num17 += num16; if (!flag12) { num17 += array[num15]; if (flag10) { num17 += topGrid[num15].extraDraftedPerceivedPathCost; } else { num17 += topGrid[num15].extraNonDraftedPerceivedPathCost; } } if (byteGrid != null) { num17 += (int)(byteGrid[num15] * 8); } if (allowedArea != null && !allowedArea[num15]) { num17 += 600; } if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num13, 0, num14), pawn, false, false, true)) { num17 += 175; } Building building2 = this.edificeGrid[num15]; if (building2 != null) { this.PfProfilerBeginSample("Edifices"); int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn); if (buildingCost == 2147483647) { this.PfProfilerEndSample(); goto IL_E3A; } num17 += buildingCost; this.PfProfilerEndSample(); } List <Blueprint> list = this.blueprintGrid[num15]; if (list != null) { this.PfProfilerBeginSample("Blueprints"); int num18 = 0; for (int j = 0; j < list.Count; j++) { num18 = Mathf.Max(num18, PathFinder.GetBlueprintCost(list[j], pawn)); } if (num18 == 2147483647) { this.PfProfilerEndSample(); goto IL_E3A; } num17 += num18; this.PfProfilerEndSample(); } int num19 = num17 + this.calcGrid[num].knownCost; ushort status = this.calcGrid[num15].status; if (status == this.statusClosedValue || status == this.statusOpenValue) { int num20 = 0; if (status == this.statusClosedValue) { num20 = num9; } if (this.calcGrid[num15].knownCost <= num19 + num20) { goto IL_E3A; } } if (flag9) { this.calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num15) * PathFinder.RegionHeuristicWeightByNodesOpened.Evaluate((float)num4)); if (this.calcGrid[num15].heuristicCost < 0) { Log.ErrorOnce(string.Concat(new object[] { "Heuristic cost overflow for ", pawn.ToStringSafe <Pawn>(), " pathing from ", start, " to ", dest, "." }), pawn.GetHashCode() ^ 193840009, false); this.calcGrid[num15].heuristicCost = 0; } } else if (status != this.statusClosedValue && status != this.statusOpenValue) { int dx = Math.Abs(num13 - x); int dz = Math.Abs(num14 - z); int num21 = GenMath.OctileDistance(dx, dz, num9, num10); this.calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)num21 * num8); } int num22 = num19 + this.calcGrid[num15].heuristicCost; if (num22 < 0) { Log.ErrorOnce(string.Concat(new object[] { "Node cost overflow for ", pawn.ToStringSafe <Pawn>(), " pathing from ", start, " to ", dest, "." }), pawn.GetHashCode() ^ 87865822, false); num22 = 0; } this.calcGrid[num15].parentIndex = num; this.calcGrid[num15].knownCost = num19; this.calcGrid[num15].status = this.statusOpenValue; this.calcGrid[num15].costNodeCost = num22; num4++; this.openList.Push(new PathFinder.CostNode(num15, num22)); } } } IL_E3A :; } this.PfProfilerEndSample(); num3++; this.calcGrid[num].status = this.statusClosedValue; if (num4 >= num5 && flag7 && !flag9) { flag9 = true; this.regionCostCalculator.Init(cellRect, traverseParms, num9, num10, byteGrid, allowedArea, flag10, 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 }), false); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); Block_32: this.PfProfilerEndSample(); PawnPath result = this.FinalizedPath(num, flag9); this.PfProfilerEndSample(); return(result); Block_34: this.PfProfilerEndSample(); PawnPath result2 = this.FinalizedPath(num, flag9); this.PfProfilerEndSample(); return(result2); Block_35: Log.Warning(string.Concat(new object[] { pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells." }), false); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); }