public static ICostSymbol CreateEntry( ISymbol containingSymbol, CostNode item, DiagnosticBag diagnostics) { return(new CostSymbol(containingSymbol, item, diagnostics)); }
public static void AddCost(Cost cost, Entity entity) { CostNode node = new CostNode(cost, entity, TimeController.TimeInMinutes + 60); costs.Enqueue(node, node.TimeInMinutes); // also add to cost per hour costPerHour += cost.costPerHour; }
private void DebugDrawRichData() { if (DebugViewSettings.drawPaths) { while (this.openList.Count > 0) { CostNode costNode = this.openList.Pop(); int index = costNode.index; IntVec3 c = new IntVec3(index % this.mapSizeX, 0, index / this.mapSizeX); this.map.debugDrawer.FlashCell(c, 0f, "open", 50); } } }
/* * Update costs by going through costs items, retrieving minPriority (lowest time) * and checking if that time has arrived yet. * If so, dequeue, subtract hourly cost, and put back in queue */ void UpdateCost() { if (costs.Count > 0) { if (costs.First.TimeInMinutes <= TimeController.TimeInMinutes) { // dequeue and subtract cost CostNode costNode = costs.Dequeue(); money -= costNode.CostPerHour; // reset time in minutes for next hour and enqueue costNode.TimeInMinutes = TimeController.TimeInMinutes + 60; costs.Enqueue(costNode, costNode.TimeInMinutes); } } }
public void FloodPathsWithCost(List <int> startTiles, Func <int, int, int> costFunc, Func <int, bool> impassable = null, Func <int, float, bool> terminator = null) { if (startTiles.Count < 1 || startTiles.Contains(-1)) { Log.Error("Tried to FindPath with invalid start tiles", false); return; } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; if (impassable == null) { impassable = ((int tid) => world.Impassable(tid)); } statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } openList.Clear(); using (List <int> .Enumerator enumerator = startTiles.GetEnumerator()) { while (enumerator.MoveNext()) { int num = enumerator.Current; calcGrid[num].knownCost = 0; calcGrid[num].costNodeCost = 0; calcGrid[num].parentTile = num; calcGrid[num].status = statusOpenValue; openList.Push(new CostNode(num, 0)); } goto IL_2F2; } IL_127: CostNode costNode = openList.Pop(); if (costNode.cost == calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (calcGrid[tile].status != statusClosedValue) { int num2 = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num2; i++) { int num3 = tileIDToNeighbors_values[i]; if (calcGrid[num3].status != statusClosedValue && !impassable(num3)) { int num4 = costFunc(tile, num3) + calcGrid[tile].knownCost; ushort status = calcGrid[num3].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num3].knownCost > num4) { int num5 = num4; calcGrid[num3].parentTile = tile; calcGrid[num3].knownCost = num4; calcGrid[num3].status = this.statusOpenValue; calcGrid[num3].costNodeCost = num5; openList.Push(new CostNode(num3, num5)); } } } calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(tile, (float)calcGrid[tile].costNodeCost)) { return; } } } IL_2F2: if (openList.Count > 0) { goto IL_127; } }
public WorldPath FindPath(int startTile, int destTile, Caravan caravan, Func <float, bool> terminator = null) { if (startTile < 0) { Log.Error("Tried to FindPath with invalid start tile " + startTile + ", caravan= " + caravan); return(WorldPath.NotFound); } if (destTile < 0) { Log.Error("Tried to FindPath with invalid dest tile " + destTile + ", caravan= " + caravan); return(WorldPath.NotFound); } if (caravan != null) { if (!caravan.CanReach(destTile)) { return(WorldPath.NotFound); } } else if (!Find.WorldReachability.CanReach(startTile, destTile)) { return(WorldPath.NotFound); } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; Vector3 normalized = grid.GetTileCenter(destTile).normalized; float[] movementDifficulty = world.pathGrid.movementDifficulty; int num = 0; int num2 = caravan?.TicksPerMove ?? 3300; int num3 = CalculateHeuristicStrength(startTile, destTile); statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } calcGrid[startTile].knownCost = 0; calcGrid[startTile].heuristicCost = 0; calcGrid[startTile].costNodeCost = 0; calcGrid[startTile].parentTile = startTile; calcGrid[startTile].status = statusOpenValue; openList.Clear(); openList.Push(new CostNode(startTile, 0)); while (true) { if (openList.Count <= 0) { Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " ran out of tiles to process."); return(WorldPath.NotFound); } CostNode costNode = openList.Pop(); if (costNode.cost != calcGrid[costNode.tile].costNodeCost) { continue; } int tile = costNode.tile; if (calcGrid[tile].status == statusClosedValue) { continue; } if (tile == destTile) { return(FinalizedPath(tile)); } if (num > 500000) { Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " hit search limit of " + 500000 + " tiles."); return(WorldPath.NotFound); } int num4 = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; if (calcGrid[num5].status == statusClosedValue || world.Impassable(num5)) { continue; } int num6 = (int)((float)num2 * movementDifficulty[num5] * grid.GetRoadMovementDifficultyMultiplier(tile, num5)) + calcGrid[tile].knownCost; ushort status = calcGrid[num5].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num5].knownCost > num6) { Vector3 tileCenter = grid.GetTileCenter(num5); if (status != statusClosedValue && status != statusOpenValue) { float num7 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); calcGrid[num5].heuristicCost = Mathf.RoundToInt((float)num2 * num7 * (float)num3 * 0.5f); } int num8 = num6 + calcGrid[num5].heuristicCost; calcGrid[num5].parentTile = tile; calcGrid[num5].knownCost = num6; calcGrid[num5].status = statusOpenValue; calcGrid[num5].costNodeCost = num8; openList.Push(new CostNode(num5, num8)); } } num++; calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(calcGrid[tile].costNodeCost)) { break; } } return(WorldPath.NotFound); }
public (PawnPath path, bool found) FindVehiclePath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, CancellationToken token, PathEndMode peMode = PathEndMode.OnCell, bool waterPathing = false) { if (report) { Debug.Message($"{VehicleHarmony.LogLabel} MainPath for {traverseParms.pawn.LabelShort} - ThreadId: [{Thread.CurrentThread.ManagedThreadId}] TaskId: [{Task.CurrentId}]"); } postCalculatedCells.Clear(); VehicleMapping VehicleMapping = map.GetCachedMapComponent <VehicleMapping>(); if (DebugSettings.pathThroughWalls) { traverseParms.mode = TraverseMode.PassAllDestroyableThings; } VehiclePawn pawn = traverseParms.pawn as VehiclePawn; if (!pawn.IsBoat() && waterPathing) { Log.Error($"Set to waterPathing but {pawn.LabelShort} is not registered as a Boat. Self Correcting..."); waterPathing = false; } if (!(pawn is null) && pawn.Map != map) { Log.Error(string.Concat(new object[] { "Tried to FindVehiclePath for pawn which is spawned in another map. Their map PathFinder should have been used, not this one. " + "pawn=", pawn, " pawn.Map=", pawn.Map, " map=", map })); return(PawnPath.NotFound, false); } if (!start.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindShipPath with invalid start ", start, ", pawn=", pawn })); return(PawnPath.NotFound, false); } if (!dest.IsValid) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn })); return(PawnPath.NotFound, false); } if (traverseParms.mode == TraverseMode.ByPawn) { if (waterPathing) { if (!ShipReachabilityUtility.CanReachShip(pawn, dest, peMode, Danger.Deadly, false, traverseParms.mode)) { return(PawnPath.NotFound, false); } } else { if (!ReachabilityUtility.CanReach(pawn, dest, peMode, Danger.Deadly, false, traverseParms.mode)) { return(PawnPath.NotFound, false); } } } else { if (waterPathing) { if (!VehicleMapping.VehicleReachability.CanReachShip(start, dest, peMode, traverseParms)) { return(PawnPath.NotFound, false); } } else { if (!map.reachability.CanReach(start, dest, peMode, traverseParms)) { return(PawnPath.NotFound, false); } } } cellIndices = map.cellIndices; VehiclePathGrid = VehicleMapping.VehiclePathGrid; pathGrid = map.pathGrid; this.edificeGrid = map.edificeGrid.InnerArray; blueprintGrid = map.blueprintGrid.InnerArray; int x = dest.Cell.x; int z = dest.Cell.z; int num = cellIndices.CellToIndex(start); int num2 = cellIndices.CellToIndex(dest.Cell); ByteGrid byteGrid = (pawn is 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 = CalculateDestinationRect(dest, peMode); bool flag4 = cellRect.Width == 1 && cellRect.Height == 1; int[] boatsArray = VehiclePathGrid.pathGrid; int[] vehicleArray = pathGrid.pathGrid; TerrainDef[] topGrid = map.terrainGrid.topGrid; EdificeGrid edificeGrid = map.edificeGrid; int num3 = 0; int num4 = 0; Area allowedArea = GetAllowedArea(pawn); bool flag5 = !(pawn is null) && PawnUtility.ShouldCollideWithPawns(pawn); bool flag6 = true && DebugViewSettings.drawPaths; bool flag7 = !flag && !(VehicleGridsUtility.GetRegion(start, map, RegionType.Set_Passable) is null) && flag2; bool flag8 = !flag || !flag3; bool flag9 = false; bool flag10 = !(pawn is null) && pawn.Drafted; bool flag11 = !(pawn is null) && !(pawn is null); int num5 = (!flag11) ? NodesToOpenBeforeRegionbasedPathing_NonShip : NodesToOpenBeforeRegionBasedPathing_Ship; int num6 = 0; int num7 = 0; float num8 = DetermineHeuristicStrength(pawn, start, dest); int num9 = !(pawn is null) ? pawn.TicksPerMoveCardinal : DefaultMoveTicksCardinal; int num10 = !(pawn is null) ? pawn.TicksPerMoveDiagonal : DefaultMoveTicksDiagonal; CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); InitStatusesAndPushStartNode(ref num, start); Rot8 rot = pawn.FullRotation; int iterations = 0; for (;;) { if (token.IsCancellationRequested) { return(PawnPath.NotFound, false); } iterations++; if (openList.Count <= 0) { break; } num6 += openList.Count; num7++; CostNode costNode = openList.Pop(); num = costNode.index; if (costNode.cost == calcGrid[num].costNodeCost && calcGrid[num].status != statusClosedValue) { IntVec3 c = cellIndices.IndexToCell(num); IntVec3 prevCell = c; int x2 = c.x; int z2 = c.z; if (flag6) { DebugFlash(c, calcGrid[num].knownCost / 1500f, calcGrid[num].knownCost.ToString()); } if (flag4) { if (num == num2) { goto Block_32; } } else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(num)) { goto Block_32; } if (num3 > SearchLimit) { goto Block_33; } List <IntVec3> fullRectCells = CellRect.CenteredOn(c, pawn.def.size.x, pawn.def.size.z).Where(cl2 => cl2 != c).ToList(); for (int i = 0; i < 8; i++) { uint num11 = (uint)(x2 + Directions[i]); //x uint num12 = (uint)(z2 + Directions[i + 8]); //y if (num11 < ((ulong)mapSizeX) && num12 < (ulong)(mapSizeZ)) { int num13 = (int)num11; int num14 = (int)num12; int num15 = cellIndices.CellToIndex(num13, num14); IntVec3 cellToCheck = cellIndices.IndexToCell(num15); if (VehicleMod.settings.main.fullVehiclePathing && pawn.LocationRestrictedBySize(cellToCheck)) { goto EndPathing; } if (calcGrid[num15].status != statusClosedValue || flag9) { int num16 = 0; bool flag12 = false; //Extra cost for traversing water if (flag2 || !new IntVec3(num13, 0, num14).GetTerrain(map).HasTag("Water")) { if (waterPathing) { if (!pawn.DrivableFast(num15)) { if (!flag) { if (flag6) { DebugFlash(new IntVec3(num13, 0, num14), 0.22f, "walk"); } goto EndPathing; } num16 += 70; Building building = edificeGrid[num15]; if (building is null) { goto EndPathing; } if (!IsDestroyable(building)) { goto EndPathing; } num16 += (int)(building.HitPoints * 0.2f); } } else { if (!pawn.DrivableFast(num15)) { if (!flag) { if (flag6) { DebugFlash(new IntVec3(num13, 0, num14), 0.22f, "walk"); } goto EndPathing; } flag12 = true; num16 += 70; Building building = edificeGrid[num15]; if (building is null) { goto EndPathing; } if (!IsDestroyable(building)) { goto EndPathing; } num16 += (int)(building.HitPoints * 0.2f); } } if (i > 3) { switch (i) { case 4: if (BlocksDiagonalMovement(pawn, num - mapSizeX)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } if (BlocksDiagonalMovement(pawn, num + 1)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } break; case 5: if (BlocksDiagonalMovement(pawn, num + mapSizeX)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } if (BlocksDiagonalMovement(pawn, num + 1)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } break; case 6: if (BlocksDiagonalMovement(pawn, num + mapSizeX)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } if (BlocksDiagonalMovement(pawn, num - 1)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } break; case 7: if (BlocksDiagonalMovement(pawn, num - mapSizeX)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } if (BlocksDiagonalMovement(pawn, num - 1)) { if (flag8) { if (flag6) { DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships"); } goto EndPathing; } num16 += 70; } break; } } int num17 = (i <= 3) ? num9 : num10; num17 += num16; //if (Rot8.DirectionFromCells(prevCell, cellToCheck) != rot) //{ // Log.Message("Additional Cost"); // num17 += ChangeDirectionAdditionalCost; //} if (!flag12 && !waterPathing) { //Extra Terrain costs if (pawn.VehicleDef.properties.customTerrainCosts?.NotNullAndAny() ?? false) { TerrainDef currentTerrain = map.terrainGrid.TerrainAt(num15); if (pawn.VehicleDef.properties.customTerrainCosts.ContainsKey(currentTerrain)) { int customCost = pawn.VehicleDef.properties.customTerrainCosts[currentTerrain]; if (customCost < 0) { goto EndPathing; } num17 += customCost; } else { num17 += vehicleArray[num15]; } } else { num17 += vehicleArray[num15]; } num17 += flag10 ? topGrid[num15].extraDraftedPerceivedPathCost : topGrid[num15].extraNonDraftedPerceivedPathCost; } if (byteGrid != null) { num17 += (byteGrid[num15] * 8); } //Allowed area cost? if (flag5 && MultithreadHelper.AnyVehicleBlockingPathAt(new IntVec3(num13, 0, num14), pawn, false, false, true) != null) { num17 += Cost_PawnCollision; } Building building2 = edificeGrid[num15]; if (!(building2 is null)) { //Building Costs Here } if (blueprintGrid[num15] != null) { List <Blueprint> list = new List <Blueprint>(blueprintGrid[num15]); if (!list.NullOrEmpty()) { int num18 = 0; foreach (Blueprint bp in list) { num18 = Mathf.Max(num18, GetBlueprintCost(bp, pawn)); } if (num18 == int.MaxValue) { goto EndPathing; } num17 += num18; } } int num19 = num17 + calcGrid[num].knownCost; ushort status = calcGrid[num15].status; //if(pawn.Props.useFullHitboxPathing) //{ // foreach(IntVec3 fullRect in fullRectCells) // { // if(fullRect != cellToCheck) // { // num19 += calcGrid[cellIndices.CellToIndex(fullRect)].knownCost; // Log.Message($"Cell: {fullRect} Cost: {num19}"); // if(postCalculatedCells.ContainsKey(fullRect)) // { // postCalculatedCells[fullRect] = num19; // } // else // { // postCalculatedCells.Add(fullRect, num19); // } // } // } //} //Only generate path costs for linear non-reverse pathing check if (report) { if (postCalculatedCells.ContainsKey(cellToCheck)) { postCalculatedCells[cellToCheck] = num19; } else { postCalculatedCells.Add(cellToCheck, num19); } } if (waterPathing && !map.terrainGrid.TerrainAt(num15).IsWater) { num19 += 10000; } if (status == statusClosedValue || status == statusOpenValue) { int num20 = 0; if (status == statusClosedValue) { num20 = num9; } if (calcGrid[num15].knownCost <= num19 + num20) { goto EndPathing; } } if (flag9) { calcGrid[num15].heuristicCost = waterPathing ? Mathf.RoundToInt(regionCostCalculatorSea.GetPathCostFromDestToRegion(num15) * RegionheuristicWeighByNodesOpened.Evaluate(num4)) : Mathf.RoundToInt(regionCostCalculatorLand.GetPathCostFromDestToRegion(num15) * RegionheuristicWeighByNodesOpened.Evaluate(num4)); if (calcGrid[num15].heuristicCost < 0) { Log.ErrorOnce(string.Concat(new object[] { "Heuristic cost overflow for vehicle ", pawn.ToStringSafe <Pawn>(), " pathing from ", start, " to ", dest, "." }), pawn.GetHashCode() ^ 193840009); calcGrid[num15].heuristicCost = 0; } } else if (status != statusClosedValue && status != statusOpenValue) { int dx = Math.Abs(num13 - x); int dz = Math.Abs(num14 - z); int num21 = GenMath.OctileDistance(dx, dz, num9, num10); calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)num21 * num8); } int num22 = num19 + calcGrid[num15].heuristicCost; if (num22 < 0) { Log.ErrorOnce(string.Concat(new object[] { "Node cost overflow for ship ", pawn.ToStringSafe <Pawn>(), " pathing from ", start, " to ", dest, "." }), pawn.GetHashCode() ^ 87865822); num22 = 0; } calcGrid[num15].parentIndex = num; calcGrid[num15].knownCost = num19; calcGrid[num15].status = statusOpenValue; calcGrid[num15].costNodeCost = num22; num4++; rot = Rot8.DirectionFromCells(prevCell, cellToCheck); openList.Push(new CostNode(num15, num22)); } } } EndPathing :; } num3++; calcGrid[num].status = statusClosedValue; if (num4 >= num5 && flag7 && !flag9) { flag9 = true; if (waterPathing) { regionCostCalculatorSea.Init(cellRect, traverseParms, num9, num10, byteGrid, allowedArea, flag10, disallowedCornerIndices); } else { regionCostCalculatorLand.Init(cellRect, traverseParms, num9, num10, byteGrid, allowedArea, flag10, disallowedCornerIndices); } InitStatusesAndPushStartNode(ref num, start); num4 = 0; num3 = 0; } } } string text = ((pawn is null) || pawn.CurJob is null) ? "null" : pawn.CurJob.ToString(); string text2 = ((pawn is null) || pawn.Faction is null) ? "null" : pawn.Faction.ToString(); if (report) { Log.Warning(string.Concat(new object[] { "ship pawn: ", pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2, "\niterations: ", iterations })); } DebugDrawRichData(); return(PawnPath.NotFound, false); Block_32: PawnPath result = PawnPath.NotFound; if (report) { result = FinalizedPath(num, flag9); } DebugDrawPathCost(); return(result, true); Block_33: Log.Warning(string.Concat(new object[] { "Ship ", pawn, " pathing from ", start, " to ", dest, " hit search limit of ", SearchLimit, " cells." })); DebugDrawRichData(); return(PawnPath.NotFound, false); }
public WorldPath FindPath(int startTile, int destTile, VehicleCaravan caravan, Func <float, bool> terminator = null) { if (startTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid start tile ", startTile, ", caravan= ", caravan })); return(WorldPath.NotFound); } if (destTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest tile ", destTile, ", caravan= ", caravan })); return(WorldPath.NotFound); } if (!WorldVehicleReachability.Instance.CanReach(caravan, destTile)) { return(WorldPath.NotFound); } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; Vector3 normalized = grid.GetTileCenter(destTile).normalized; Dictionary <VehicleDef, float[]> movementDifficulty = WorldVehiclePathGrid.Instance.movementDifficulty; int num = 0; int num2 = (caravan != null) ? caravan.TicksPerMove : 3300; int num3 = CalculateHeuristicStrength(startTile, destTile); statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } calcGrid[startTile].knownCost = 0; calcGrid[startTile].heuristicCost = 0; calcGrid[startTile].costNodeCost = 0; calcGrid[startTile].parentTile = startTile; calcGrid[startTile].status = statusOpenValue; openList.Clear(); openList.Push(new CostNode(startTile, 0)); while (openList.Count > 0) { CostNode costNode = openList.Pop(); if (costNode.cost == calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (calcGrid[tile].status != statusClosedValue) { if (tile == destTile) { return(FinalizedPath(tile)); } if (num > SearchLimit) { Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " hit search limit of ", SearchLimit, " tiles." })); return(WorldPath.NotFound); } int num4 = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; if (calcGrid[num5].status != statusClosedValue && caravan.UniqueVehicleDefsInCaravan().All(v => WorldVehiclePathGrid.Instance.Passable(num5, v)) && (!caravan.HasBoat() || !(Find.World.CoastDirectionAt(num5).IsValid&& num5 != destTile))) { float highestTerrainCost = caravan.UniqueVehicleDefsInCaravan().Max(v => movementDifficulty[v][num5]); int num6 = (int)(num2 * highestTerrainCost * VehicleCaravan_PathFollower.GetRoadMovementDifficultyMultiplier(caravan, tile, num5, null)) + calcGrid[tile].knownCost; ushort status = calcGrid[num5].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num5].knownCost > num6) { Vector3 tileCenter = grid.GetTileCenter(num5); if (status != statusClosedValue && status != statusOpenValue) { float num7 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); calcGrid[num5].heuristicCost = Mathf.RoundToInt(num2 * num7 * num3 * BestRoadDiscount); } int num8 = num6 + calcGrid[num5].heuristicCost; calcGrid[num5].parentTile = tile; calcGrid[num5].knownCost = num6; calcGrid[num5].status = statusOpenValue; calcGrid[num5].costNodeCost = num8; openList.Push(new CostNode(num5, num8)); } } } num++; calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(calcGrid[tile].costNodeCost)) { return(WorldPath.NotFound); } } } } Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " ran out of tiles to process." })); return(WorldPath.NotFound); }
public void FloodPathsWithCost(List <int> startTiles, Func <int, int, int> costFunc, Func <int, bool> impassable = null, Func <int, float, bool> terminator = null) { if (startTiles.Count < 1 || startTiles.Contains(-1)) { Log.Error("Tried to FindPath with invalid start tiles"); return; } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; if (impassable == null) { impassable = ((int tid) => world.Impassable(tid)); } statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } openList.Clear(); foreach (int startTile in startTiles) { calcGrid[startTile].knownCost = 0; calcGrid[startTile].costNodeCost = 0; calcGrid[startTile].parentTile = startTile; calcGrid[startTile].status = statusOpenValue; openList.Push(new CostNode(startTile, 0)); } while (openList.Count > 0) { CostNode costNode = openList.Pop(); if (costNode.cost != calcGrid[costNode.tile].costNodeCost) { continue; } int tile = costNode.tile; if (calcGrid[tile].status == statusClosedValue) { continue; } int num = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num; i++) { int num2 = tileIDToNeighbors_values[i]; if (calcGrid[num2].status != statusClosedValue && !impassable(num2)) { int num3 = costFunc(tile, num2) + calcGrid[tile].knownCost; ushort status = calcGrid[num2].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num2].knownCost > num3) { int num4 = num3; calcGrid[num2].parentTile = tile; calcGrid[num2].knownCost = num3; calcGrid[num2].status = statusOpenValue; calcGrid[num2].costNodeCost = num4; openList.Push(new CostNode(num2, num4)); } } } calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(tile, calcGrid[tile].costNodeCost)) { break; } } }
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); }
/// <summary> /// Find route which contains target node. /// </summary> /// <param name="targetNode">Node to find.</param> /// <returns>NodeRoute.</returns> public NodeRoute FindRoute(CostNode targetNode) { foreach (NodeRoute route in _nodeRoutes) { foreach (CostNode node in route.CostNodes) { if (node == targetNode) { return route; } } } return null; }
public void FloodPathsWithCost(List <int> startTiles, Func <int, int, int> costFunc, Func <int, bool> impassable = null, Func <int, float, bool> terminator = null) { if (startTiles.Count < 1 || startTiles.Contains(-1)) { Log.Error("Tried to FindPath with invalid start tiles"); } else { World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; if (impassable == null) { impassable = ((int tid) => world.Impassable(tid)); } this.statusOpenValue += 2; this.statusClosedValue += 2; if (this.statusClosedValue >= 65435) { this.ResetStatuses(); } this.openList.Clear(); foreach (int startTile in startTiles) { this.calcGrid[startTile].knownCost = 0; this.calcGrid[startTile].costNodeCost = 0; this.calcGrid[startTile].parentTile = startTile; this.calcGrid[startTile].status = this.statusOpenValue; this.openList.Push(new CostNode(startTile, 0)); } while (this.openList.Count > 0) { CostNode costNode = this.openList.Pop(); if (costNode.cost == this.calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (this.calcGrid[tile].status != this.statusClosedValue) { int num = (tile + 1 >= tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_values.Count : tileIDToNeighbors_offsets[tile + 1]; for (int i = tileIDToNeighbors_offsets[tile]; i < num; i++) { int num2 = tileIDToNeighbors_values[i]; int num4; if (this.calcGrid[num2].status != this.statusClosedValue && !impassable(num2)) { int num3 = costFunc(tile, num2); num4 = num3 + this.calcGrid[tile].knownCost; ushort status = this.calcGrid[num2].status; if (status != this.statusClosedValue && status != this.statusOpenValue) { goto IL_0282; } if (this.calcGrid[num2].knownCost > num4) { goto IL_0282; } } continue; IL_0282: int num5 = num4; this.calcGrid[num2].parentTile = tile; this.calcGrid[num2].knownCost = num4; this.calcGrid[num2].status = this.statusOpenValue; this.calcGrid[num2].costNodeCost = num5; this.openList.Push(new CostNode(num2, num5)); } this.calcGrid[tile].status = this.statusClosedValue; if (terminator != null && terminator(tile, (float)this.calcGrid[tile].costNodeCost)) { break; } } } } } }
public WorldPath FindPath(int startTile, int destTile, Caravan caravan, Func <float, bool> terminator = null) { if (startTile < 0) { Log.Error("Tried to FindPath with invalid start tile " + startTile + ", caravan= " + caravan); return(WorldPath.NotFound); } if (destTile < 0) { Log.Error("Tried to FindPath with invalid dest tile " + destTile + ", caravan= " + caravan); return(WorldPath.NotFound); } if (caravan != null) { if (!caravan.CanReach(destTile)) { return(WorldPath.NotFound); } } else if (!Find.WorldReachability.CanReach(startTile, destTile)) { return(WorldPath.NotFound); } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; Vector3 normalized = grid.GetTileCenter(destTile).normalized; int[] pathGrid = world.pathGrid.pathGrid; int num = 0; int num2 = (caravan == null) ? 2500 : caravan.TicksPerMove; int num3 = this.CalculateHeuristicStrength(startTile, destTile); this.statusOpenValue += 2; this.statusClosedValue += 2; if (this.statusClosedValue >= 65435) { this.ResetStatuses(); } this.calcGrid[startTile].knownCost = 0; this.calcGrid[startTile].heuristicCost = 0; this.calcGrid[startTile].costNodeCost = 0; this.calcGrid[startTile].parentTile = startTile; this.calcGrid[startTile].status = this.statusOpenValue; this.openList.Clear(); this.openList.Push(new CostNode(startTile, 0)); while (true) { if (this.openList.Count <= 0) { Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " ran out of tiles to process."); return(WorldPath.NotFound); } CostNode costNode = this.openList.Pop(); if (costNode.cost == this.calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (this.calcGrid[tile].status != this.statusClosedValue) { if (DebugViewSettings.drawPaths) { Find.WorldDebugDrawer.FlashTile(tile, (float)((float)this.calcGrid[tile].knownCost / 375000.0), this.calcGrid[tile].knownCost.ToString(), 50); } if (tile == destTile) { return(this.FinalizedPath(tile)); } if (num > 500000) { Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " hit search limit of " + 500000 + " tiles."); return(WorldPath.NotFound); } int num4 = (tile + 1 >= tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_values.Count : tileIDToNeighbors_offsets[tile + 1]; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; int num7; ushort status; if (this.calcGrid[num5].status != this.statusClosedValue && !world.Impassable(num5)) { int num6 = num2; num6 += pathGrid[num5]; num6 = (int)((float)num6 * grid.GetRoadMovementMultiplierFast(tile, num5)); num7 = num6 + this.calcGrid[tile].knownCost; status = this.calcGrid[num5].status; if (status != this.statusClosedValue && status != this.statusOpenValue) { goto IL_041e; } if (this.calcGrid[num5].knownCost > num7) { goto IL_041e; } } continue; IL_041e: Vector3 tileCenter = grid.GetTileCenter(num5); if (status != this.statusClosedValue && status != this.statusOpenValue) { float num8 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); this.calcGrid[num5].heuristicCost = Mathf.RoundToInt((float)((float)num2 * num8 * (float)num3 * 0.5)); } int num9 = num7 + this.calcGrid[num5].heuristicCost; this.calcGrid[num5].parentTile = tile; this.calcGrid[num5].knownCost = num7; this.calcGrid[num5].status = this.statusOpenValue; this.calcGrid[num5].costNodeCost = num9; this.openList.Push(new CostNode(num5, num9)); } num++; this.calcGrid[tile].status = this.statusClosedValue; if (terminator != null && terminator((float)this.calcGrid[tile].costNodeCost)) { break; } } } } return(WorldPath.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 != map) { Log.Error(string.Concat("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=", map)); return(PawnPath.NotFound); } if (!start.IsValid) { Log.Error(string.Concat("Tried to FindPath with invalid start ", start, ", pawn= ", pawn)); return(PawnPath.NotFound); } if (!dest.IsValid) { Log.Error(string.Concat("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 (!map.reachability.CanReach(start, dest, peMode, traverseParms)) { return(PawnPath.NotFound); } PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, dest.HasThing ? (" at " + dest.Cell) : "")); cellIndices = map.cellIndices; pathGrid = map.pathGrid; this.edificeGrid = map.edificeGrid.InnerArray; blueprintGrid = map.blueprintGrid.InnerArray; int x = dest.Cell.x; int z = dest.Cell.z; int curIndex = cellIndices.CellToIndex(start); int num = cellIndices.CellToIndex(dest.Cell); ByteGrid byteGrid = pawn?.GetAvoidGrid(); 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 = CalculateDestinationRect(dest, peMode); bool flag4 = cellRect.Width == 1 && cellRect.Height == 1; int[] array = map.pathGrid.pathGrid; TerrainDef[] topGrid = map.terrainGrid.topGrid; EdificeGrid edificeGrid = map.edificeGrid; int num2 = 0; int num3 = 0; Area allowedArea = GetAllowedArea(pawn); bool flag5 = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn); bool flag6 = !flag && start.GetRegion(map) != null && flag2; bool flag7 = !flag || !flag3; bool flag8 = false; bool flag9 = pawn?.Drafted ?? false; int num4 = ((pawn?.IsColonist ?? false) ? 100000 : 2000); int num5 = 0; int num6 = 0; float num7 = DetermineHeuristicStrength(pawn, start, dest); int num8; int num9; if (pawn != null) { num8 = pawn.TicksPerMoveCardinal; num9 = pawn.TicksPerMoveDiagonal; } else { num8 = 13; num9 = 18; } CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); InitStatusesAndPushStartNode(ref curIndex, start); while (true) { PfProfilerBeginSample("Open cell"); if (openList.Count <= 0) { string text = ((pawn != null && pawn.CurJob != null) ? pawn.CurJob.ToString() : "null"); string text2 = ((pawn != null && pawn.Faction != null) ? pawn.Faction.ToString() : "null"); Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2)); DebugDrawRichData(); PfProfilerEndSample(); PfProfilerEndSample(); return(PawnPath.NotFound); } num5 += openList.Count; num6++; CostNode costNode = openList.Pop(); curIndex = costNode.index; if (costNode.cost != calcGrid[curIndex].costNodeCost) { PfProfilerEndSample(); continue; } if (calcGrid[curIndex].status == statusClosedValue) { PfProfilerEndSample(); continue; } IntVec3 c = cellIndices.IndexToCell(curIndex); int x2 = c.x; int z2 = c.z; if (flag4) { if (curIndex == num) { PfProfilerEndSample(); PawnPath result = FinalizedPath(curIndex, flag8); PfProfilerEndSample(); return(result); } } else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex)) { PfProfilerEndSample(); PawnPath result2 = FinalizedPath(curIndex, flag8); PfProfilerEndSample(); return(result2); } if (num2 > 160000) { break; } PfProfilerEndSample(); PfProfilerBeginSample("Neighbor consideration"); for (int i = 0; i < 8; i++) { uint num10 = (uint)(x2 + Directions[i]); uint num11 = (uint)(z2 + Directions[i + 8]); if (num10 >= mapSizeX || num11 >= mapSizeZ) { continue; } int num12 = (int)num10; int num13 = (int)num11; int num14 = cellIndices.CellToIndex(num12, num13); if (calcGrid[num14].status == statusClosedValue && !flag8) { continue; } int num15 = 0; bool flag10 = false; if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(map).HasTag("Water")) { continue; } if (!pathGrid.WalkableFast(num14)) { if (!flag) { continue; } flag10 = true; num15 += 70; Building building = edificeGrid[num14]; if (building == null || !IsDestroyable(building)) { continue; } num15 += (int)((float)building.HitPoints * 0.2f); } switch (i) { case 4: if (BlocksDiagonalMovement(curIndex - mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex + 1)) { if (flag7) { continue; } num15 += 70; } break; case 5: if (BlocksDiagonalMovement(curIndex + mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex + 1)) { if (flag7) { continue; } num15 += 70; } break; case 6: if (BlocksDiagonalMovement(curIndex + mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex - 1)) { if (flag7) { continue; } num15 += 70; } break; case 7: if (BlocksDiagonalMovement(curIndex - mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex - 1)) { if (flag7) { continue; } num15 += 70; } break; } int num16 = ((i > 3) ? num9 : num8); num16 += num15; if (!flag10) { num16 += array[num14]; num16 = ((!flag9) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost)); } if (byteGrid != null) { num16 += byteGrid[num14] * 8; } if (allowedArea != null && !allowedArea[num14]) { num16 += 600; } if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true)) { num16 += 175; } Building building2 = this.edificeGrid[num14]; if (building2 != null) { PfProfilerBeginSample("Edifices"); int buildingCost = GetBuildingCost(building2, traverseParms, pawn); if (buildingCost == int.MaxValue) { PfProfilerEndSample(); continue; } num16 += buildingCost; PfProfilerEndSample(); } List <Blueprint> list = blueprintGrid[num14]; if (list != null) { PfProfilerBeginSample("Blueprints"); int num17 = 0; for (int j = 0; j < list.Count; j++) { num17 = Mathf.Max(num17, GetBlueprintCost(list[j], pawn)); } if (num17 == int.MaxValue) { PfProfilerEndSample(); continue; } num16 += num17; PfProfilerEndSample(); } int num18 = num16 + calcGrid[curIndex].knownCost; ushort status = calcGrid[num14].status; if (status == statusClosedValue || status == statusOpenValue) { int num19 = 0; if (status == statusClosedValue) { num19 = num8; } if (calcGrid[num14].knownCost <= num18 + num19) { continue; } } if (flag8) { calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate(num3)); if (calcGrid[num14].heuristicCost < 0) { Log.ErrorOnce(string.Concat("Heuristic cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0xB8DC389); calcGrid[num14].heuristicCost = 0; } } else if (status != statusClosedValue && status != statusOpenValue) { int dx = Math.Abs(num12 - x); int dz = Math.Abs(num13 - z); int num20 = GenMath.OctileDistance(dx, dz, num8, num9); calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num20 * num7); } int num21 = num18 + calcGrid[num14].heuristicCost; if (num21 < 0) { Log.ErrorOnce(string.Concat("Node cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0x53CB9DE); num21 = 0; } calcGrid[num14].parentIndex = curIndex; calcGrid[num14].knownCost = num18; calcGrid[num14].status = statusOpenValue; calcGrid[num14].costNodeCost = num21; num3++; openList.Push(new CostNode(num14, num21)); } PfProfilerEndSample(); num2++; calcGrid[curIndex].status = statusClosedValue; if (num3 >= num4 && flag6 && !flag8) { flag8 = true; regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndices); InitStatusesAndPushStartNode(ref curIndex, start); num3 = 0; num2 = 0; } } Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells.")); DebugDrawRichData(); PfProfilerEndSample(); PfProfilerEndSample(); return(PawnPath.NotFound); }
/// <summary> /// Test this cost node is preceding of the given node. /// </summary> /// <param name="node">Cost node to test with.</param> /// <returns>True for yes, otherwise false.</returns> internal bool IsPreceed(CostNode node) { return this.CostNode.WaveUnit.SampleOffset + this.CostNode.WaveUnit.SampleLength == node.WaveUnit.SampleOffset; }
/// <summary> /// Find a NodeRoute which is shown and includes the cost node. /// </summary> /// <param name="costNode">Cost noe to find route on.</param> /// <returns>Found node route.</returns> public NodeRoute FindRoute(CostNode costNode) { if (Utterance == null || Utterance.Viterbi == null) { return null; } foreach (NodeRoute route in Utterance.Viterbi.NodeRoutes) { if (route.Visible && route.CostNodes.Contains(costNode)) { return route; } } return null; }
private static CostNode ParseCostNode(string line) { CostNode node = new CostNode(); string[] items = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); System.Diagnostics.Debug.Assert(items.Length == 14 || items.Length == 5 || items.Length == 3); node.Index = int.Parse(items[1], CultureInfo.InvariantCulture); node.WaveUnit = ParseWaveUnitForViterbi(items); if (items.Length > 3) { node.TargetCost = float.Parse(items[items.Length - 2], CultureInfo.InvariantCulture); node.RouteCost = float.Parse(items[items.Length - 1], CultureInfo.InvariantCulture); } return node; }
/// <summary> /// Save information of one unit into log file. /// </summary> /// <param name="writer">Stream writer to save the information.</param> /// <param name="index">Index of the unit to save.</param> /// <param name="expectedUnit">Expected unit from front-end.</param> /// <param name="selectedNode">Selected node through unit selection.</param> /// <returns>Next unit index.</returns> private static int SaveUnit(StreamWriter writer, int index, TtsUnit expectedUnit, CostNode selectedNode) { writer.Write(index.ToString(CultureInfo.InvariantCulture) + " "); ++index; writer.Write(index.ToString(CultureInfo.InvariantCulture) + " "); writer.Write(expectedUnit.MetaUnit.Id.ToString(CultureInfo.InvariantCulture) + " "); writer.Write(selectedNode.WaveUnit.SampleOffset.ToString(CultureInfo.InvariantCulture) + " "); writer.Write(selectedNode.WaveUnit.SampleLength.ToString(CultureInfo.InvariantCulture) + " "); TtsUnitFeature selFea = selectedNode.WaveUnit.Features; if (selFea != null) { StringBuilder builder = new StringBuilder(); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/ {1} ", (int)selFea.PosInSentence, (int)expectedUnit.Feature.PosInSentence); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.PosInWord, (int)expectedUnit.Feature.PosInWord); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.PosInSyllable, (int)expectedUnit.Feature.PosInSyllable); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.LeftContextPhone, (int)expectedUnit.Feature.LeftContextPhone); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.RightContextPhone, (int)expectedUnit.Feature.RightContextPhone); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.LeftContextTone, (int)expectedUnit.Feature.LeftContextTone); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.RightContextTone, (int)expectedUnit.Feature.RightContextTone); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/ {1} ", (int)selFea.TtsStress, (int)expectedUnit.Feature.TtsStress); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.TtsEmphasis, (int)expectedUnit.Feature.TtsEmphasis); builder.AppendFormat(CultureInfo.InvariantCulture, "{0}/{1} ", (int)selFea.TtsWordTone, (int)expectedUnit.Feature.TtsWordTone); writer.Write(builder.ToString()); } writer.Write("\r\n"); return index; }
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 != map) { Log.Warning(String.Format("Map object was rebuilt, but new pather was not assigned to new map (new {0}) (old {1})", pawn.Map.uniqueID, map.uniqueID)); 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=" + 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 (!map.reachability.CanReach(start, dest, peMode, traverseParms)) { return(PawnPath.NotFound); } PfProfilerBeginSample("FindPath for " + pawn + " from " + start + " to " + dest + (dest.HasThing ? (" at " + dest.Cell) : "")); cellIndices = map.cellIndices; pathGrid = map.pathGrid; this.edificeGrid = map.edificeGrid.InnerArray; blueprintGrid = map.blueprintGrid.InnerArray; int x = dest.Cell.x; int z = dest.Cell.z; int curIndex = cellIndices.CellToIndex(start); int num = cellIndices.CellToIndex(dest.Cell); ByteGrid byteGrid = pawn?.GetAvoidGrid(); 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 = CalculateDestinationRect(dest, peMode); bool flag4 = cellRect.Width == 1 && cellRect.Height == 1; int[] array = map.pathGrid.pathGrid; TerrainDef[] topGrid = map.terrainGrid.topGrid; EdificeGrid edificeGrid = map.edificeGrid; int num2 = 0; int num3 = 0; Area allowedArea = GetAllowedArea(pawn); bool flag5 = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn); bool flag6 = (!flag && start.GetRegion(map) != null) & flag2; bool flag7 = !flag || !flag3; bool flag8 = false; bool flag9 = pawn?.Drafted ?? false; int num4 = (pawn?.IsColonist ?? false) ? 100000 : 2000; int num5 = 0; int num6 = 0; float num7 = DetermineHeuristicStrength(pawn, start, dest); // BEGIN CHANGED SECTION // In case pawn is null int num8 = 13; int num9 = 18; Dictionary <TerrainDef, int> pawnTerrainCacheCardinal = new Dictionary <TerrainDef, int>(); Dictionary <TerrainDef, int> pawnTerrainCacheDiagonal = new Dictionary <TerrainDef, int>(); Dictionary <TerrainDef, bool> pawnSpecialMovementCache = new Dictionary <TerrainDef, bool>(); Dictionary <TerrainDef, bool> pawnImpassibleMovementCache = new Dictionary <TerrainDef, bool>(); Dictionary <TerrainDef, int> pawnTerrainMovementCache = new Dictionary <TerrainDef, int>(); // END CHANGED SECTION CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); InitStatusesAndPushStartNode(ref curIndex, start); while (true) { PfProfilerBeginSample("Open cell"); if (openList.Count <= 0) { string text = (pawn != null && pawn.CurJob != null) ? pawn.CurJob.ToString() : "null"; string text2 = (pawn != null && pawn.Faction != null) ? pawn.Faction.ToString() : "null"; Log.Warning(pawn + " pathing from " + start + " to " + dest + " ran out of cells to process.\nJob:" + text + "\nFaction: " + text2); DebugDrawRichData(); PfProfilerEndSample(); PfProfilerEndSample(); return(PawnPath.NotFound); } num5 += openList.Count; num6++; CostNode costNode = openList.Pop(); curIndex = costNode.index; if (costNode.cost != calcGrid[curIndex].costNodeCost) { PfProfilerEndSample(); continue; } if (calcGrid[curIndex].status == statusClosedValue) { PfProfilerEndSample(); continue; } IntVec3 c = cellIndices.IndexToCell(curIndex); int x2 = c.x; int z2 = c.z; if (flag4) { if (curIndex == num) { PfProfilerEndSample(); PawnPath result = FinalizedPath(curIndex, flag8); PfProfilerEndSample(); return(result); } } else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex)) { PfProfilerEndSample(); PawnPath result2 = FinalizedPath(curIndex, flag8); PfProfilerEndSample(); return(result2); } if (num2 > 160000) { break; } PfProfilerEndSample(); PfProfilerBeginSample("Neighbor consideration"); for (int i = 0; i < 8; i++) { uint num10 = (uint)(x2 + Directions[i]); uint num11 = (uint)(z2 + Directions[i + 8]); if (num10 >= mapSizeX || num11 >= mapSizeZ) { continue; } int num12 = (int)num10; int num13 = (int)num11; int num14 = cellIndices.CellToIndex(num12, num13); if (calcGrid[num14].status == statusClosedValue && !flag8) { continue; } // BEGIN CHANGED SECTION IntVec3 targetCell = new IntVec3(num12, 0, num13); TerrainDef targetTerrain = topGrid[num14]; if (pawn != null) { // Use cache of terrain movement indicators to avoid a lot of repeated computation if (!pawnImpassibleMovementCache.TryGetValue(targetTerrain, out bool impassible)) { impassible = pawn.kindDef.UnreachableTerrainCheck(targetTerrain); pawnImpassibleMovementCache[targetTerrain] = impassible; } if (impassible) { // Skip this cell for pathing calculations calcGrid[num14].status = statusClosedValue; continue; } // Overwrite directional move costs if (!pawnTerrainCacheCardinal.TryGetValue(targetTerrain, out num8)) { num8 = pawn.TerrainAwareTicksPerMoveCardinal(targetTerrain); pawnTerrainCacheCardinal[targetTerrain] = num8; } if (!pawnTerrainCacheDiagonal.TryGetValue(targetTerrain, out num9)) { num9 = pawn.TerrainAwareTicksPerMoveDiagonal(targetTerrain); pawnTerrainCacheDiagonal[targetTerrain] = num9; } } // END CHANGED SECTION int num15 = 0; bool flag10 = false; //if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(map).HasTag("Water")) if (!flag2 && targetTerrain.HasTag("Water")) { continue; } if (!pathGrid.WalkableFast(num14)) { if (!flag) { continue; } flag10 = true; num15 += 70; Building building = edificeGrid[num14]; if (building == null || !IsDestroyable(building)) { continue; } num15 += (int)((float)building.HitPoints * 0.2f); } switch (i) { case 4: if (BlocksDiagonalMovement(curIndex - mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex + 1)) { if (flag7) { continue; } num15 += 70; } break; case 5: if (BlocksDiagonalMovement(curIndex + mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex + 1)) { if (flag7) { continue; } num15 += 70; } break; case 6: if (BlocksDiagonalMovement(curIndex + mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex - 1)) { if (flag7) { continue; } num15 += 70; } break; case 7: if (BlocksDiagonalMovement(curIndex - mapSizeX)) { if (flag7) { continue; } num15 += 70; } if (BlocksDiagonalMovement(curIndex - 1)) { if (flag7) { continue; } num15 += 70; } break; } int num16 = (i > 3) ? num9 : num8; num16 += num15; if (!flag10) { // BEGIN CHANGED SECTION //num16 += array[num14]; //num16 = ((!flag9) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost)); if (pawn == null) { num16 += array[num14]; if (flag9) { num16 += targetTerrain.extraDraftedPerceivedPathCost; } else { num16 += targetTerrain.extraNonDraftedPerceivedPathCost; } } else { // Use cache of terrain perceived cost instead of fixed pathCost grid to avoid a lot of repeated computation while maintaining accuracy if (!pawnTerrainMovementCache.TryGetValue(targetTerrain, out int terrainMoveCost)) { terrainMoveCost = pawn.TerrainMoveCost(targetTerrain); pawnTerrainMovementCache[targetTerrain] = terrainMoveCost; } // This was really really expensive, so we opted to mod this pre-calced value //num16 += pathGrid.TerrainCalculatedCostAt(map, pawn, targetCell, true, IntVec3.Invalid, terrainMoveCost); num16 += pathGrid.ApplyTerrainModToCalculatedCost(targetTerrain, array[num14], terrainMoveCost); // Use cache of terrain movement indicators to avoid a lot of repeated computation if (!pawnSpecialMovementCache.TryGetValue(targetTerrain, out bool specialMovement)) { specialMovement = pawn.TerrainMoveStat(targetTerrain) != StatDefOf.MoveSpeed; pawnSpecialMovementCache[targetTerrain] = specialMovement; } // Skip applying the PerceivedPathCost hack if we've got a specialized speed stat for this terrain if (!specialMovement) { if (flag9) { num16 += targetTerrain.extraDraftedPerceivedPathCost; } else { num16 += targetTerrain.extraNonDraftedPerceivedPathCost; } } } // END CHANGED SECTION } if (byteGrid != null) { num16 += byteGrid[num14] * 8; } if (allowedArea != null && !allowedArea[num14]) { num16 += 600; } //new IntVec3(num12, 0, num13) -> targetCell if (flag5 && PawnUtility.AnyPawnBlockingPathAt(targetCell, pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true)) { num16 += 175; } Building building2 = this.edificeGrid[num14]; if (building2 != null) { PfProfilerBeginSample("Edifices"); int buildingCost = GetBuildingCost(building2, traverseParms, pawn); if (buildingCost == int.MaxValue) { PfProfilerEndSample(); continue; } num16 += buildingCost; PfProfilerEndSample(); } List <Blueprint> list = blueprintGrid[num14]; if (list != null) { PfProfilerBeginSample("Blueprints"); int num17 = 0; for (int j = 0; j < list.Count; j++) { num17 = Mathf.Max(num17, GetBlueprintCost(list[j], pawn)); } if (num17 == int.MaxValue) { PfProfilerEndSample(); continue; } num16 += num17; PfProfilerEndSample(); } int num18 = num16 + calcGrid[curIndex].knownCost; ushort status = calcGrid[num14].status; if (status == statusClosedValue || status == statusOpenValue) { int num19 = 0; if (status == statusClosedValue) { num19 = num8; } if (calcGrid[num14].knownCost <= num18 + num19) { continue; } } if (flag8) { calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate(num3)); if (calcGrid[num14].heuristicCost < 0) { Log.ErrorOnce("Heuristic cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0xB8DC389); calcGrid[num14].heuristicCost = 0; } } else if (status != statusClosedValue && status != statusOpenValue) { int dx = Math.Abs(num12 - x); int dz = Math.Abs(num13 - z); int num20 = GenMath.OctileDistance(dx, dz, num8, num9); calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num20 * num7); } int num21 = num18 + calcGrid[num14].heuristicCost; if (num21 < 0) { Log.ErrorOnce("Node cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0x53CB9DE); num21 = 0; } calcGrid[num14].parentIndex = curIndex; calcGrid[num14].knownCost = num18; calcGrid[num14].status = statusOpenValue; calcGrid[num14].costNodeCost = num21; num3++; openList.Push(new CostNode(num14, num21)); } PfProfilerEndSample(); num2++; calcGrid[curIndex].status = statusClosedValue; if (num3 >= num4 && flag6 && !flag8) { flag8 = true; regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndices); InitStatusesAndPushStartNode(ref curIndex, start); num3 = 0; num2 = 0; } } Log.Warning(pawn + " pathing from " + start + " to " + dest + " hit search limit of " + 160000 + " cells."); DebugDrawRichData(); PfProfilerEndSample(); PfProfilerEndSample(); return(PawnPath.NotFound); }
internal ICostTypeSymbol BindCostTypeSymbol(CostNode node, DiagnosticBag diagnostics) => BindSimple <ICostTypeSymbol, ErrorSymbols.ErrorCostTypeSymbol>( node, diagnostics, node.TypeId, LookupOptions.CostTypeOnly);