public bool CanReachUnfogged(IntVec3 c, TraverseParms traverseParms) { if (traverseParms.pawn != null) { if (!traverseParms.pawn.Spawned) { return(false); } if (traverseParms.pawn.Map != this.map) { Log.Error(string.Concat(new object[] { "Called CanReachUnfogged() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=", traverseParms.pawn, " pawn.Map=", traverseParms.pawn.Map, " map=", this.map }), false); return(false); } } if (!c.InBoundsShip(this.map)) { return(false); } if (!c.Fogged(this.map)) { return(true); } WaterRegion region = WaterGridsUtility.GetRegion(c, this.map, RegionType.Set_Passable); if (region == null) { return(false); } WaterRegionEntryPredicate entryCondition = (WaterRegion from, WaterRegion r) => r.Allows(traverseParms, false); bool foundReg = false; WaterRegionProcessor regionProcessor = delegate(WaterRegion r) { if (!r.AnyCell.Fogged(this.map)) { foundReg = true; return(true); } return(false); }; WaterRegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, 9999, RegionType.Set_Passable); return(foundReg); }
public void Init(CellRect end, TraverseParms traverseParms, int moveTicksCardinal, int moveTicksDiagonal, ByteGrid avoidGrid, Area allowedArea, bool drafted, List <int> disallowedCorners) { this.moveTicksCardinal = moveTicksCardinal; this.moveTicksDiagonal = moveTicksDiagonal; this.endCell = end.CenterCell; this.cachedRegion = null; this.cachedBestLink = null; this.cachedSecondBestLink = null; this.cachedBestLinkCost = 0; this.cachedSecondBestLinkCost = 0; this.cachedRegionIsDestination = false; this.regionGrid = MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionGrid.DirectGrid; this.destRegions.Clear(); if (end.Width == 1 && end.Height == 1) { WaterRegion region = WaterGridsUtility.GetRegion(this.endCell, this.map, RegionType.Set_Passable); if (region != null) { this.destRegions.Add(region); } } else { CellRect.CellRectIterator iterator = end.GetIterator(); while (!iterator.Done()) { IntVec3 intVec = iterator.Current; if (intVec.InBoundsShip(this.map) && !disallowedCorners.Contains(this.map.cellIndices.CellToIndex(intVec))) { WaterRegion region2 = WaterGridsUtility.GetRegion(intVec, this.map, RegionType.Set_Passable); if (region2 != null) { if (region2.Allows(traverseParms, true)) { this.destRegions.Add(region2); } } } iterator.MoveNext(); } } if (this.destRegions.Count == 0) { Log.Error("Couldn't find any destination regions. This shouldn't ever happen because we've checked reachability.", false); } this.regionCostCalculatorShips.Init(end, this.destRegions, traverseParms, moveTicksCardinal, moveTicksDiagonal, avoidGrid, allowedArea, drafted); }
public static void AddAllowedAdjacentRegions(LocalTargetInfo dest, TraverseParms traverseParams, Map map, List <WaterRegion> regions) { IntVec3 bl; IntVec3 tl; IntVec3 tr; IntVec3 br; GenAdj.GetAdjacentCorners(dest, out bl, out tl, out tr, out br); if (!dest.HasThing || (dest.Thing.def.size.x == 1 && dest.Thing.def.size.z == 1)) { IntVec3 cell = dest.Cell; for (int i = 0; i < 8; i++) { IntVec3 intVec = GenAdj.AdjacentCells[i] + cell; if (intVec.InBoundsShip(map) && !TouchPathEndModeUtility.IsAdjacentCornerAndNotAllowed(intVec, bl, tl, tr, br, map)) { WaterRegion region = WaterGridsUtility.GetRegion(intVec, map, RegionType.Set_Passable); if (region != null && region.Allows(traverseParams, true)) { regions.Add(region); } } } } else { List <IntVec3> list = GenAdjFast.AdjacentCells8Way(dest); for (int j = 0; j < list.Count; j++) { if (list[j].InBoundsShip(map) && !TouchPathEndModeUtility.IsAdjacentCornerAndNotAllowed(list[j], bl, tl, tr, br, map)) { WaterRegion region2 = WaterGridsUtility.GetRegion(list[j], map, RegionType.Set_Passable); if (region2 != null && region2.Allows(traverseParams, true)) { regions.Add(region2); } } } } }
public bool CanReachShip(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParms) { if (this.working) { Log.ErrorOnce("Called CanReach() while working for Ships. This should never happen. Suppressing further errors.", 7312233, false); return(false); } if (!this.map.terrainGrid.TerrainAt(dest.Cell).IsWater) { return(false); } if (!(traverseParms.pawn is null)) { if (!traverseParms.pawn.Spawned) { return(false); } if (traverseParms.pawn.Map != this.map) { Log.Error(string.Concat(new object[] { "Called CanReach() with a ship spawned not on this map. This means that we can't check its reachability here. Pawn's" + "current map should have been used instead of this one. pawn=", traverseParms.pawn, " pawn.Map=", traverseParms.pawn.Map, " map=", this.map }), false); return(false); } } if (!dest.IsValid) { return(false); } if (dest.HasThing && dest.Thing.Map != this.map) { return(false); } if (!start.InBoundsShip(this.map) || !dest.Cell.InBoundsShip(this.map)) { return(false); } if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { WaterRoom room = WaterRegionAndRoomQuery.RoomAtFast(start, this.map, RegionType.Set_Passable); if (!(room is null) && room == WaterRegionAndRoomQuery.RoomAtFast(dest.Cell, this.map, RegionType.Set_Passable)) { return(true); } } if (traverseParms.mode == TraverseMode.PassAllDestroyableThings) { TraverseParms traverseParms2 = traverseParms; traverseParms.mode = TraverseMode.PassDoors; if (this.CanReachShip(start, dest, peMode, traverseParms2)) { return(true); } } dest = (LocalTargetInfo)GenPathShip.ResolvePathMode(traverseParms.pawn, dest.ToTargetInfo(this.map), ref peMode, this.mapExt); this.working = true; bool result; try { this.pathGrid = mapExt.getShipPathGrid; this.regionGrid = this.mapExt.getWaterRegionGrid; this.reachedIndex += 1u; this.destRegions.Clear(); if (peMode == PathEndMode.OnCell) { WaterRegion region = WaterGridsUtility.GetRegion(dest.Cell, this.map, RegionType.Set_Passable); if (!(region is null) && region.Allows(traverseParms, true)) { this.destRegions.Add(region); } } else if (peMode == PathEndMode.Touch) { TouchPathEndModeUtilityShips.AddAllowedAdjacentRegions(dest, traverseParms, this.map, this.destRegions); } if (this.destRegions.Count == 0 && traverseParms.mode != TraverseMode.PassAllDestroyableThings && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { this.FinalizeCheck(); result = false; } else { this.destRegions.RemoveDuplicates <WaterRegion>(); this.openQueue.Clear(); this.numRegionsOpened = 0; this.DetermineStartRegions(start); if (this.openQueue.Count == 0 && traverseParms.mode != TraverseMode.PassAllDestroyableThings && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { this.FinalizeCheck(); result = false; } else { if (this.startingRegions.Any <WaterRegion>() && this.destRegions.Any <WaterRegion>() && this.CanUseCache(traverseParms.mode)) { BoolUnknown cachedResult = this.GetCachedResult(traverseParms); if (cachedResult == BoolUnknown.True) { this.FinalizeCheck(); return(true); } if (cachedResult == BoolUnknown.False) { this.FinalizeCheck(); return(false); } } if (traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParms.mode == TraverseMode.NoPassClosedDoorsOrWater) { bool flag = this.CheckCellBasedReachability(start, dest, peMode, traverseParms); this.FinalizeCheck(); result = flag; } else { //bool flag2 = this.CheckRegionBasedReachability(traverseParms); bool flag2 = this.CheckCellBasedReachability(start, dest, peMode, traverseParms); //Change back to region based later this.FinalizeCheck(); result = flag2; } } } } finally { this.working = false; } return(result); }
public PawnPath FindShipPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell) { if (DebugSettings.pathThroughWalls) { traverseParms.mode = TraverseMode.PassAllDestroyableThings; } Pawn pawn = traverseParms.pawn; if (!(pawn is null) && pawn.Map != this.map) { Log.Error(string.Concat(new object[] { "Tried to FindShipPath for pawn which is spawned in another map. his map ShipPathFinder 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 FindShipPath 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 (!ShipReachabilityUtility.CanReachShip(pawn, dest, peMode, Danger.Deadly, false, traverseParms.mode)) { return(PawnPath.NotFound); } } else if (!mapE.getShipReachability.CanReachShip(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.shipPathGrid = mapE.getShipPathGrid; 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 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 = this.CalculateDestinationRect(dest, peMode); bool flag4 = cellRect.Width == 1 && cellRect.Height == 1; int[] array = mapE.getShipPathGrid.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 is null) && PawnUtility.ShouldCollideWithPawns(pawn); bool flag6 = true && DebugViewSettings.drawPaths; bool flag7 = !flag && !(WaterGridsUtility.GetRegion(start, this.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.GetComp <CompShips>() is null); int num5 = (!flag11) ? NodesToOpenBeforeRegionbasedPathing_NonShip : NodesToOpenBeforeRegionBasedPathing_Ship; int num6 = 0; int num7 = 0; float num8 = this.DetermineHeuristicStrength(pawn, start, dest); int num9 = !(pawn is null) ? pawn.TicksPerMoveCardinal : DefaultMoveTicksCardinal; int num10 = !(pawn is null) ? pawn.TicksPerMoveDiagonal : DefaultMoveTicksDiagonal; this.CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect); this.InitStatusesAndPushStartNode(ref num, start); for (;;) { this.PfProfilerBeginSample("Open cell"); if (this.openList.Count <= 0) { break; } num6 += this.openList.Count; num7++; ShipPathFinder.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 > SearchLimit) { goto Block_35; } this.PfProfilerEndSample(); this.PfProfilerBeginSample("Neighbor consideration"); for (int i = 0; i < 8; i++) { uint num11 = (uint)(x2 + ShipPathFinder.Directions[i]); uint num12 = (uint)(z2 + ShipPathFinder.Directions[i + 8]); if ((ulong)num11 < ((ulong)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; Extra cost for traversing water if (flag2 || !new IntVec3(num13, 0, num14).GetTerrain(this.map).HasTag("Water")) { if (!this.shipPathGrid.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 is null) { goto IL_E3A; } if (!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, "ships"); } goto IL_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships"); } 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, "ships"); } goto IL_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num + 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships"); } 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, "ships"); } goto IL_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships"); } 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, "ships"); } goto IL_E3A; } num16 += 70; } if (this.BlocksDiagonalMovement(num - 1)) { if (flag8) { if (flag6) { this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships"); } goto IL_E3A; } num16 += 70; } break; } } int num17 = (i <= 3) ? num9 : num10; num17 += num16; /*if(!flag12) * { * //Extra Costs for traversing water * num17 += array[num15]; * num17 += flag10 ? topGrid[num15].extraDraftedPerceivedPathCost : topGrid[num15].extraNonDraftedPerceivedPathCost; * }*/ if (!(byteGrid is null)) { num17 += (int)(byteGrid[num15] * 8); } //Allowed area cost? if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num13, 0, num14), pawn, false, false, true)) { num17 += Cost_PawnCollision; } Building building2 = this.edificeGrid[num15]; if (!(building2 is null)) { //Building Costs Here } List <Blueprint> list = this.blueprintGrid[num15]; if (!(list is null)) { this.PfProfilerBeginSample("Blueprints"); int num18 = 0; foreach (Blueprint bp in list) { num18 = Mathf.Max(num18, GetBlueprintCost(bp, pawn)); } if (num18 == int.MaxValue) { this.PfProfilerEndSample(); goto IL_E3A; } num17 += num18; this.PfProfilerEndSample(); } int num19 = num17 + this.calcGrid[num].knownCost; ushort status = this.calcGrid[num15].status; if (!(pawn.GetComp <CompShips>() is null) && !this.map.terrainGrid.TerrainAt(num15).IsWater) { num19 += 10000; } 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) * ShipPathFinder.RegionheuristicWeighByNodesOpened.Evaluate((float)num4)); if (this.calcGrid[num15].heuristicCost < 0) { Log.ErrorOnce(string.Concat(new object[] { "Heuristic cost overflow for ship ", 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; //Log.Message("Num19: " + num19 + " || num22: " + num22); 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, 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 ShipPathFinder.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 is null) || pawn.CurJob is null) ? "null" : pawn.CurJob.ToString(); string text2 = ((pawn is null) || pawn.Faction is null) ? "null" : pawn.Faction.ToString(); Log.Warning(string.Concat(new object[] { "ship pawn: ", 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[] { "Ship ", pawn, " pathing from ", start, " to ", dest, " hit search limit of ", SearchLimit, " cells." }), false); this.DebugDrawRichData(); this.PfProfilerEndSample(); return(PawnPath.NotFound); }