Пример #1
0
        private bool TrySetNewPath()
        {
            PawnPath pawnPath = this.GenerateNewPath();

            if (!pawnPath.Found)
            {
                this.PatherFailed();
                return(false);
            }
            if (this.curPath != null)
            {
                this.curPath.ReleaseToPool();
            }
            this.curPath = pawnPath;
            int num = 0;

            while (num < 20 && num < this.curPath.NodesLeftCount)
            {
                IntVec3 c = this.curPath.Peek(num);
                if (PawnUtility.ShouldCollideWithPawns(this.pawn) && PawnUtility.AnyPawnBlockingPathAt(c, this.pawn, false, false, false))
                {
                    this.foundPathWhichCollidesWithPawns = Find.TickManager.TicksGame;
                }
                if (PawnUtility.KnownDangerAt(c, this.pawn.Map, this.pawn))
                {
                    this.foundPathWithDanger = Find.TickManager.TicksGame;
                }
                if (this.foundPathWhichCollidesWithPawns == Find.TickManager.TicksGame && this.foundPathWithDanger == Find.TickManager.TicksGame)
                {
                    break;
                }
                num++;
            }
            return(true);
        }
 private bool WillCollideWithPawnAt(IntVec3 c)
 {
     if (!PawnUtility.ShouldCollideWithPawns(this.pawn))
     {
         return(false);
     }
     return(PawnUtility.AnyPawnBlockingPathAt(c, this.pawn, false, false));
 }
Пример #3
0
        public PawnPath findPath(Map map, IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, ByteGrid avoidGrid, Area allowedArea,
                                 int costsCardinal, int costsDiagonal)
        {
            this.map                 = map;
            this.cellIndices         = this.map.cellIndices;
            this.edificeGrid         = map.edificeGrid;
            this.traverseParms       = traverseParms;
            this.dest                = dest;
            this.peMode              = peMode;
            this.costPerMoveCardinal = costsCardinal;
            this.costPerMoveDiagonal = costsDiagonal;
            this.avoidGrid           = avoidGrid;
            this.allowedArea         = allowedArea;
            this.pathGridArray       = map.pathGrid.pathGrid;
            this.pathGrid            = map.pathGrid;
            this.topGrid             = map.terrainGrid.topGrid;
            this.pawn                = traverseParms.pawn;
            this.drafted             = pawn != null && pawn.Drafted;
            this.blueprintGrid       = map.blueprintGrid.InnerArray;

            //Only colonists and tamed animals should respect restrictions.
            //Drafted pawns move unrestricted.
            //Some job types like firefighting should exclude the restrictions.
            List <string> exceptions = QOLMod.getSettings().pfRestrictionExcemptions;

            if (this.pawn.Faction != null && this.pawn.Faction.IsPlayer && !this.pawn.Drafted && (exceptions == null || pawn.jobs.curJob == null || !exceptions.Contains(pawn.jobs.curJob.def.defName)))
            {
                this.pathfinderDirections = map.GetComponent <MapComponent_PathfinderDirections>();
            }
            else
            {
                this.pathfinderDirections = null;
            }
            this.drawPath          = DebugViewSettings.drawPaths;
            this.mapSizeX          = map.Size.x;
            this.mapSizeZ          = map.Size.z;
            this.dontPassWater     = traverseParms.mode == TraverseMode.NoPassClosedDoorsOrWater || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            this.collidesWithPawns = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);

            Step step = astar(start);

            if (step == null)
            {
                return(PawnPath.NotFound);
            }

            PawnPath emptyPawnPath = map.pawnPathPool.GetEmptyPawnPath();
            int      costs         = step.costToReachThis;

            while (step != null)
            {
                emptyPawnPath.AddNode(step.current);
                step = step.predecessor;
            }
            emptyPawnPath.SetupFound((float)costs, false);
            return(emptyPawnPath);
        }
Пример #4
0
        public static bool TrySetNewPath(ref Pawn_PathFollower instance, ref IntVec3 lastPathedTargetPosition, LocalTargetInfo destination, Pawn pawn, Map map, ref PathEndMode peMode)
        {
            PawnPath pawnPath = GenerateNewPath(ref lastPathedTargetPosition, destination, ref pawn, map, peMode);

            if (!pawnPath.Found)
            {
                PatherFailedHelper(ref instance, pawn);
                return(false);
            }
            if (!(instance.curPath is null))
            {
                instance.curPath.ReleaseToPool();
            }
            instance.curPath = pawnPath;
            int num = 0;
            int foundPathWhichCollidesWithPawns = Traverse.Create(instance).Field("foundPathWhichCollidesWithPawns").GetValue <int>();
            int foundPathWithDanger             = Traverse.Create(instance).Field("foundPathWithDanger").GetValue <int>();

            while (num < 20 && num < instance.curPath.NodesLeftCount)
            {
                IntVec3 c = instance.curPath.Peek(num);

                if (pawn.GetComp <CompShips>().beached)
                {
                    break;
                }
                if (PawnUtility.ShouldCollideWithPawns(pawn) && PawnUtility.AnyPawnBlockingPathAt(c, pawn, false, false, false))
                {
                    foundPathWhichCollidesWithPawns = Find.TickManager.TicksGame;
                }
                if (PawnUtility.KnownDangerAt(c, pawn.Map, pawn))
                {
                    foundPathWithDanger = Find.TickManager.TicksGame;
                }
                if (foundPathWhichCollidesWithPawns == Find.TickManager.TicksGame && foundPathWithDanger == Find.TickManager.TicksGame)
                {
                    break;
                }
                num++;
            }
            return(true);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        //public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, Pawn pawn, PathEndMode peMode = PathEndMode.OnCell)
        //{
        //    bool flag = false;
        //    if (pawn != null && pawn.CurJob != null && pawn.CurJob.canBash)
        //    {
        //        flag = true;
        //    }
        //    Danger maxDanger = Danger.Deadly;
        //    bool canBash = flag;
        //    return this.FindPath(start, dest, TraverseParms.For(pawn, maxDanger, TraverseMode.ByPawn, canBash), peMode);
        //}

        public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            //Walk through Walls Mode
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }
            //Check if there's a pawn to path for
            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 CVPathFinder should have been used, not this one. pawn=",
                    pawn,
                    " pawn.Map=",
                    pawn.Map,
                    " map=",
                    this.map
                }));
                return(PawnPath.NotFound);
            }
            //Make sure the start is valid
            if (!start.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath with invalid start ",
                    start,
                    ", pawn= ",
                    pawn
                }));
                return(PawnPath.NotFound);
            }
            //Make sure the end is valid
            if (!dest.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath with invalid dest ",
                    dest,
                    ", pawn= ",
                    pawn
                }));
                return(PawnPath.NotFound);
            }
            //Check if it's possible to get to the destination
            Log.Error(traverseParms.mode.ToString());
            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);
            }
            Log.Error("a");
            this.PfProfilerBeginSample(string.Concat(new object[]
            {
                "FindPath for ",
                pawn,
                " from ",
                start,
                " to ",
                dest,
                (!dest.HasThing) ? string.Empty : (" at " + dest.Cell)
            }));
            this.cellIndices = this.map.cellIndices;
            this.pathGrid    = this.map.pathGrid;
            this.edificeGrid = this.map.edificeGrid.InnerArray;
            int      x        = dest.Cell.x;
            int      z        = dest.Cell.z;
            int      num      = this.cellIndices.CellToIndex(start);
            int      num2     = this.cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid = (pawn == null) ? null : pawn.GetAvoidGrid();
            bool     flag     = traverseParms.mode == TraverseMode.PassAllDestroyableThings;
            bool     flag2    = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3    = !flag;
            CellRect cellRect = this.CalculateDestinationRect(dest, peMode);
            bool     flag4    = cellRect.Width == 1 && cellRect.Height == 1;

            int[]       array       = this.map.pathGrid.pathGrid;
            EdificeGrid edificeGrid = this.map.edificeGrid;
            int         num3        = 0;
            int         num4        = 0;
            Area        allowedArea = this.GetAllowedArea(pawn);
            bool        flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool        flag6       = true && DebugViewSettings.drawPaths;
            bool        flag7       = !flag && start.GetRegion(this.map, RegionType.Set_Passable) != null;
            bool        flag8       = !flag || !flag3;
            bool        flag9       = false;
            int         num5        = 0;
            int         num6        = 0;
            float       num7        = this.DetermineHeuristicStrength(pawn, start, dest);
            int         num8;
            int         num9;

            Log.Error("b");
            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)
            {
                Log.Error("c");
                this.PfProfilerBeginSample("Open cell");
                if (this.openList.Count <= 0)
                {
                    break;
                }
                num5 += this.openList.Count;
                num6++;
                CVPathFinder.CostNode costNode = this.openList.Pop();
                num = costNode.index;
                if (costNode.cost != this.calcGrid[num].costNodeCost)
                {
                    Log.Error("d");
                    this.PfProfilerEndSample();
                }
                else if (this.calcGrid[num].status == this.statusClosedValue)
                {
                    Log.Error("e");
                    this.PfProfilerEndSample();
                }
                else
                {
                    Log.Error("f");
                    IntVec3 c  = this.cellIndices.IndexToCell(num);
                    int     x2 = c.x;
                    int     z2 = c.z;
                    if (flag6)
                    {
                        this.DebugFlash(c, (float)this.calcGrid[num].knownCost / 1500f, this.calcGrid[num].knownCost.ToString());
                    }
                    if (flag4)
                    {
                        if (num == num2)
                        {
                            goto Block_27;
                        }
                    }
                    else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num))
                    {
                        goto Block_29;
                    }
                    if (num3 > 160000)
                    {
                        goto Block_30;
                    }
                    this.PfProfilerEndSample();
                    this.PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        uint num10 = (uint)(x2 + CVPathFinder.Directions[i]);
                        uint num11 = (uint)(z2 + CVPathFinder.Directions[i + 8]);
                        if ((ulong)num10 < (ulong)((long)this.mapSizeX) && (ulong)num11 < (ulong)((long)this.mapSizeZ))
                        {
                            int num12 = (int)num10;
                            int num13 = (int)num11;
                            int num14 = this.cellIndices.CellToIndex(num12, num13);
                            if (this.calcGrid[num14].status != this.statusClosedValue || flag9)
                            {
                                int  num15  = 0;
                                bool flag10 = false;
                                if (flag2 || !new IntVec3(num12, 0, num13).GetTerrain(this.map).HasTag("Water") || (pawn.GetComp <CompVehicle>() != null && pawn.GetComp <CompVehicle>().Props.vehicleType == VehicleType.Amphibious))
                                {
                                    if (!this.pathGrid.WalkableFast(num14))
                                    {
                                        if (!flag)
                                        {
                                            if (flag6)
                                            {
                                                this.DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk");
                                            }
                                            goto IL_C2E;
                                        }
                                        flag10 = true;
                                        num15 += 70;
                                        Building building = edificeGrid[num14];
                                        if (building == null)
                                        {
                                            goto IL_C2E;
                                        }
                                        if (!CVPathFinder.IsDestroyable(building))
                                        {
                                            goto IL_C2E;
                                        }
                                        num15 += (int)((float)building.HitPoints * 0.11f);
                                    }
                                    if (i > 3)
                                    {
                                        switch (i)
                                        {
                                        case 4:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 5:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 6:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 7:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;
                                        }
                                    }
                                    Log.Error("g");
                                    int num16 = (i <= 3) ? num8 : num9;
                                    num16 += num15;
                                    if (!flag10)
                                    {
                                        num16 += array[num14];
                                    }
                                    if (byteGrid != null)
                                    {
                                        num16 += (int)(byteGrid[num14] * 8);
                                    }
                                    if (allowedArea != null && !allowedArea[num14])
                                    {
                                        num16 += 600;
                                    }
                                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, false, false))
                                    {
                                        num16 += 175;
                                    }
                                    Log.Error("h");
                                    Building building2 = this.edificeGrid[num14];
                                    if (building2 != null)
                                    {
                                        this.PfProfilerBeginSample("Edifices");
                                        int buildingCost = CVPathFinder.GetBuildingCost(building2, traverseParms, pawn);
                                        if (buildingCost == 2147483647)
                                        {
                                            this.PfProfilerEndSample();
                                            goto IL_C2E;
                                        }
                                        num16 += buildingCost;
                                        this.PfProfilerEndSample();
                                    }
                                    int    num17  = num16 + this.calcGrid[num].knownCost;
                                    ushort status = this.calcGrid[num14].status;
                                    if (status == this.statusClosedValue || status == this.statusOpenValue)
                                    {
                                        int num18 = 0;
                                        if (status == this.statusClosedValue)
                                        {
                                            num18 = num8;
                                        }
                                        if (this.calcGrid[num14].knownCost <= num17 + num18)
                                        {
                                            goto IL_C2E;
                                        }
                                    }
                                    if (status != this.statusClosedValue && status != this.statusOpenValue)
                                    {
                                        if (flag9)
                                        {
                                            this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num14) * CVPathFinder.RegionHeuristicWeightByNodesOpened.Evaluate((float)num4));
                                        }
                                        else
                                        {
                                            int dx    = Math.Abs(num12 - x);
                                            int dz    = Math.Abs(num13 - z);
                                            int num19 = GenMath.OctileDistance(dx, dz, num8, num9);
                                            this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num19 * num7);
                                        }
                                    }
                                    int num20 = num17 + this.calcGrid[num14].heuristicCost;
                                    this.calcGrid[num14].parentIndex  = num;
                                    this.calcGrid[num14].knownCost    = num17;
                                    this.calcGrid[num14].status       = this.statusOpenValue;
                                    this.calcGrid[num14].costNodeCost = num20;
                                    num4++;
                                    this.openList.Push(new CVPathFinder.CostNode(num14, num20));
                                }
                            }
                        }
                        IL_C2E :;
                    }
                    this.PfProfilerEndSample();
                    num3++;
                    this.calcGrid[num].status = this.statusClosedValue;
                    if (num4 >= 2000 && flag7 && !flag9)
                    {
                        flag9 = true;
                        this.regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, this.disallowedCornerIndices);
                        this.InitStatusesAndPushStartNode(ref num, start);
                        num4 = 0;
                        num3 = 0;
                    }
                }
            }
            string text  = (pawn == null || pawn.CurJob == null) ? "null" : pawn.CurJob.ToString();
            string text2 = (pawn == null || pawn.Faction == null) ? "null" : pawn.Faction.ToString();

            Log.Warning(string.Concat(new object[]
            {
                pawn,
                " pathing from ",
                start,
                " to ",
                dest,
                " ran out of cells to process.\nJob:",
                text,
                "\nFaction: ",
                text2
            }));
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);

Block_27:
            this.PfProfilerEndSample();
            PawnPath result = this.FinalizedPath(num);

            this.PfProfilerEndSample();
            return(result);

Block_29:
            this.PfProfilerEndSample();
            PawnPath result2 = this.FinalizedPath(num);

            this.PfProfilerEndSample();
            return(result2);

Block_30:
            Log.Warning(string.Concat(new object[]
            {
                pawn,
                " pathing from ",
                start,
                " to ",
                dest,
                " hit search limit of ",
                160000,
                " cells."
            }));
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);
        }
Пример #8
0
        private static bool setup(IntVec3 s, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, Map map)
        {
            sMap  = map;
            sMapW = map.Size.x;
            sMapH = map.Size.z;

            if (s.x < 0 || s.y < 0 || s.z < 0 || s.x >= sMapW || s.z >= sMapH)
            {
#if DEBUG_LOG_ERROR
                Log.Error("Start point is out side of map:" + s);
#endif
                return(true);
            }
            IntVec3 e = dest.Cell;
            if (e.x < 0 || e.y < 0 || e.z < 0 || e.x >= sMapW || e.z >= sMapH)
            {
#if DEBUG_LOG_ERROR
                Log.Error("End point is out side of map:" + e);
#endif
                return(true);
            }

            if (dest.HasThing && dest.Thing.Map != map)
            {
#if DEBUG_LOG_ERROR
                Log.Error("Tartget thing is not this map:" + dest.Thing.ThingID);
#endif
                return(true);
            }

            int w = (sMapW + NodeSetBitMask) >> NodeSetBitShift;
            sMapW4 = w;
            int h       = (sMapH + NodeSetBitMask) >> NodeSetBitShift;
            int wh_size = w * h;
            if (sNodeSet == null || sNodeSet.Length < wh_size)
            {
                sNodeSet = new NodeSet[wh_size];
            }

            sEndX = dest.Cell.x;
            sEndY = dest.Cell.z;

            sPathGrid      = sMap.pathGrid;
            sPathGridArray = sMap.pathGrid.pathGrid;
            sEdifice       = sMap.edificeGrid.InnerArray;
            sTopGrid       = sMap.terrainGrid.topGrid;
            sBlueprint     = sMap.blueprintGrid.InnerArray;

            sTraverseParms = traverseParms;
            Pawn pawn = traverseParms.pawn;
            if (pawn != null)
            {
                if (!pawn.Spawned || pawn.Map != map)
                {
#if DEBUG_LOG_ERROR
                    Log.Error("Pawn is not spawned or diff map");
#endif
                    return(true);
                }

                sCardinal               = pawn.TicksPerMoveCardinal;
                sDiagonal               = pawn.TicksPerMoveDiagonal;
                sAvoidGrid              = pawn.GetAvoidGrid(true);
                sAllowedArea            = allowedArea(pawn);
                sDrafted                = pawn.Drafted;
                sShouldCollideWithPawns = PawnUtility.ShouldCollideWithPawns(pawn);
            }
            else
            {
                sCardinal               = DefaultMoveTicksCardinal;
                sDiagonal               = DefaultMoveTicksDiagonal;
                sAvoidGrid              = null;
                sAllowedArea            = null;
                sDrafted                = false;
                sShouldCollideWithPawns = false;
            }
            sD2C = sDiagonal - (2 * sCardinal);

            sAllowWater =
                traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater &&
                traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            sPassAllDestroyableThings =
                traverseParms.mode == TraverseMode.PassAllDestroyableThings ||
                traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;

            setupDestRect(dest, traverseParms, peMode, sMap);

            return(false);
        }
Пример #9
0
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = float.MaxValue, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe() + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0)
                {
                    if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position)))
                    {
                        return(false);
                    }
                    if (!searcherThing.CanSee(thing, losValidator))
                    {
                        if (t is Pawn)
                        {
                            if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                            {
                                return(false);
                            }
                        }
                        else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                        {
                            return(false);
                        }
                    }
                }
                if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction))
                {
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    foreach (IntVec3 item in thing.OccupiedRect())
                    {
                        if (!item.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState))
            {
                tmpTargets.Clear();
                tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator2 = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                for (int i = 0; i < tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                }
                else
                {
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(validator: ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == 0 || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)))), center: searcherThing.Position, searchSet: tmpTargets, maxDistance: maxDist);
                }
                tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = delegate(IAttackTarget t)
                {
                    if (!oldValidator(t))
                    {
                        return(false);
                    }
                    return(t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius) ? true : false);
                };
            }
            IAttackTarget attackTarget2 = (IAttackTarget)GenClosest.ClosestThingReachable(searcherThing.Position, searcherThing.Map, ThingRequest.ForGroup(ThingRequestGroup.AttackTarget), PathEndMode.Touch, TraverseParms.For(searcherPawn, Danger.Deadly, TraverseMode.ByPawn, canBash), maxDist, (Thing x) => innerValidator((IAttackTarget)x), null, 0, (maxDist > 800f) ? (-1) : 40);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
Пример #10
0
        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();
            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);
            for (;;)
            {
                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_D53;
                                        }
                                        flag12 = true;
                                        num16 += 70;
                                        Building building = edificeGrid[num15];
                                        if (building == null)
                                        {
                                            goto IL_D53;
                                        }
                                        if (!PathFinder.IsDestroyable(building))
                                        {
                                            goto IL_D53;
                                        }
                                        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_D53;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_D53;
                                                }
                                                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_D53;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_D53;
                                                }
                                                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_D53;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_D53;
                                                }
                                                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_D53;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_D53;
                                                }
                                                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_D53;
                                        }
                                        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_D53;
                                        }
                                        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_D53;
                                        }
                                    }
                                    if (status != this.statusClosedValue && status != this.statusOpenValue)
                                    {
                                        if (flag9)
                                        {
                                            this.calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num15) * PathFinder.RegionHeuristicWeightByNodesOpened.Evaluate((float)num4));
                                        }
                                        else
                                        {
                                            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;
                                    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_D53 :;
                    }
                    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);
        }
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Log.Message("Using VEF_AttackTargetFinder");
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            Log.Message("searcher is " + searcherPawn.Label);
            Log.Message("Attack Verb is " + verb.ToString());
            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false);
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((byte)(flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Log.Message("Beginning of innerValidator - Validating for " + t.Thing.Label);
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    Log.Message("IAttackTarget is Searcher - Invalid target");
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    Log.Message("Verb has minDistance and IAttackTarget is within minimum distance - Invalid target");
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    Log.Message("Searcher cannot attack targets closer that verb.verbProps.EffectiveMinRange");
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        Log.Message("Distance between Searcher and IAttackTarget is greater than 0, but less than verb.verbProps.EffectiveMinimumRange - Invalid target");
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    Log.Message("Seacrher has limited permissable movement and IAttackTarget is outside of that distance - Invalid target");
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    Log.Message("Searcher is not hostile towards IAttackTarget - Invalid target");
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    Log.Message("Searcher has validator and validator failed. Validator checked for " + validator.GetType().ToString());
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Log.Message("Searcher is Pawn - Get Lord");
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        Log.Message("Lord is in incorrect state - Return false");
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    Log.Message("Searher needs LOS to some or all targets, but cannot see target.");
                    if (t is Pawn)
                    {
                        Log.Message("IAttackTarget is Pawn");
                        if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            Log.Message("Searcher needs LOS to Pawn - Invalid target");
                            return(false);
                        }
                    }
                    else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        Log.Message("IAttackTarget is nonPawn");
                        Log.Message("Searcher needs LOS to NonPawns - Invalid target");
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher))
                {
                    Log.Message("Searcher needs Threat, IAttackTarget is not threat - Invalid target");
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    Log.Message("Verb is EMP and target is flesh - Invalid target");
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    Log.Message("Verb is incendiary and target is already burning - Invalid target");
                    return(false);
                }
                if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike)
                {
                    Log.Message("Searcher is ToolUser - Validating use of Explosives");
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        Log.Message("Explosive is already lit - Invalid verb");
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        Log.Message("IAttackTarget is in Fog - Invalid target");
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (!iterator.Current.Fogged(thing.Map))
                        {
                            Log.Message("IAttackTarget is not in Fog - return true");
                            flag2 = true;
                            break;
                        }
                        iterator.MoveNext();
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                Log.Message("IAttackTarget is valid target");
                return(true);
            };

            if (HasRangedAttack(searcher))
            {
                Log.Message(searcher.Thing.Label + " has ranged verb.");
                tmpTargets.Clear();
                tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                Log.Message("initializing tmpTargets");
                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Log.Message("TargetScanFlags.NeedReachable");
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;

                if (tmpTargets.Count == 0)
                {
                    Log.Message("There are no tmpTargets - return null");
                    return(null);
                }
                else
                {
                    Log.Message("There are " + tmpTargets.Count + " tmpTargets");
                }

                for (int i = 0; i < tmpTargets.Count; i++)
                {
                    Log.Message("Iterating tmpTargets to check for targets that can be hit from current location. Iteration " + i);
                    IAttackTarget attackTarget = tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        Log.Message("tempTarget " + i + " can be hit from current position.");
                        flag = true;
                        break;
                    }
                    Log.Message("tempTarget " + i + " cannot be hit from current position.");
                }
                IAttackTarget result = null;
                if (flag)
                {
                    Log.Message("A target can be shot from current position. Clearing tempTargets outside of range and picking one.");
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                    Log.Message("Target that can be shot from present location is: " + result.Thing.ToString());
                }
                else
                {
                    Log.Message("No target can be hit from current position. Refining validator...");
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        Log.Message("Using validator2 where (byte)TargetScanFalgs flags are not 0");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        Log.Message("Using validator2 where (byte)TargetScanFlags flags are 0");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    Log.Message("--- MARKER ---");
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, tmpTargets, maxDist, validator2, null);
                    if (result == null)
                    {
                        Log.Message("Taregt selection complete. Clearing tmpTargets. There is no valid target");
                    }
                    else
                    {
                        Log.Message("Taregt selection complete. Clearing tmpTargets. Final target is: " + result.Thing.ToString());
                    }
                }
                tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius));
            }
            IntVec3           position         = searcherThing.Position;
            Map               map              = searcherThing.Map;
            ThingRequest      thingReq         = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode       peMode           = PathEndMode.Touch;
            Pawn              searcherPawn2    = searcherPawn;
            Danger            maxDanger        = Danger.Deadly;
            bool              canBash2         = canBash;
            TraverseParms     traverseParams   = TraverseParms.For(searcherPawn2, maxDanger, TraverseMode.ByPawn, canBash2);
            float             maxDist2         = maxDist;
            Predicate <Thing> validator3       = (Thing x) => innerValidator((IAttackTarget)x);
            int               searchRegionsMax = (maxDist <= 800f) ? 40 : -1;
            IAttackTarget     attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, maxDist2, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
Пример #12
0
        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);
        }
Пример #13
0
 public override bool Applies()
 {
     return(pawn != null && PawnUtility.ShouldCollideWithPawns(pawn));
 }
Пример #14
0
        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("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) ? string.Empty : (" at " + dest.Cell)));
            cellIndices      = map.cellIndices;
            pathGrid         = map.pathGrid;
            this.edificeGrid = map.edificeGrid.InnerArray;
            blueprintGrid    = map.blueprintGrid.InnerArray;
            IntVec3  cell     = dest.Cell;
            int      x        = cell.x;
            IntVec3  cell2    = dest.Cell;
            int      z        = cell2.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       = true && DebugViewSettings.drawPaths;
            bool         flag7       = !flag && start.GetRegion(map) != null && flag2;
            bool         flag8       = !flag || !flag3;
            bool         flag9       = false;
            bool         flag10      = pawn?.Drafted ?? false;
            int          num4        = (!(pawn?.IsColonist ?? false)) ? 2000 : 100000;
            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) ? "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);
                    DebugDrawRichData();
                    PfProfilerEndSample();
                    return(PawnPath.NotFound);
                }
                num5 += openList.Count;
                num6++;
                CostNode costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    PfProfilerEndSample();
                }
                else if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                }
                else
                {
                    IntVec3 c  = cellIndices.IndexToCell(curIndex);
                    int     x2 = c.x;
                    int     z2 = c.z;
                    if (flag6)
                    {
                        DebugFlash(c, (float)calcGrid[curIndex].knownCost / 1500f, calcGrid[curIndex].knownCost.ToString());
                    }
                    if (flag4)
                    {
                        if (curIndex == num)
                        {
                            PfProfilerEndSample();
                            PawnPath result = FinalizedPath(curIndex, flag9);
                            PfProfilerEndSample();
                            return(result);
                        }
                    }
                    else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex))
                    {
                        PfProfilerEndSample();
                        PawnPath result2 = FinalizedPath(curIndex, flag9);
                        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)
                        {
                            int num12 = (int)num10;
                            int num13 = (int)num11;
                            int num14 = cellIndices.CellToIndex(num12, num13);
                            if (calcGrid[num14].status != statusClosedValue || flag9)
                            {
                                int  num15  = 0;
                                bool flag11 = false;
                                if (flag2 || !new IntVec3(num12, 0, num13).GetTerrain(map).HasTag("Water"))
                                {
                                    if (!pathGrid.WalkableFast(num14))
                                    {
                                        if (!flag)
                                        {
                                            if (flag6)
                                            {
                                                DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk");
                                            }
                                            continue;
                                        }
                                        flag11 = 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 (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex + 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 5:
                                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex + 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 6:
                                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex - 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 7:
                                        if (BlocksDiagonalMovement(curIndex - mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex - 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    default:
                                    {
                                        int num16 = (i <= 3) ? num8 : num9;
                                        num16 += num15;
                                        if (!flag11)
                                        {
                                            num16 += array[num14];
                                            num16  = ((!flag10) ? (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 == 2147483647)
                                            {
                                                PfProfilerEndSample();
                                                break;
                                            }
                                            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 == 2147483647)
                                            {
                                                PfProfilerEndSample();
                                                break;
                                            }
                                            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)
                                            {
                                                break;
                                            }
                                        }
                                        if (flag9)
                                        {
                                            calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate((float)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));
                                        break;
                                    }
                                    }
                                }
                            }
                        }
                    }
                    PfProfilerEndSample();
                    num2++;
                    calcGrid[curIndex].status = statusClosedValue;
                    if (num3 >= num4 && flag7 && !flag9)
                    {
                        flag9 = true;
                        regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, flag10, 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();
            return(PawnPath.NotFound);
        }
Пример #15
0
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb != null && verb.IsEMP();
            float minDistanceSquared = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistanceSquared > 0.0 && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistanceSquared)
                {
                    return(false);
                }
                if (maxTravelRadiusFromLocus < 9999.0 && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    if (t is Pawn)
                    {
                        if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            return(false);
                        }
                    }
                    else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled())
                {
                    return(false);
                }
                Pawn pawn2 = t as Pawn;
                if (onlyTargetMachines && pawn2 != null && pawn2.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (iterator.Current.Fogged(thing.Map))
                        {
                            iterator.MoveNext();
                            continue;
                        }
                        flag2 = true;
                        break;
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (AttackTargetFinder.HasRangedAttack(searcher))
            {
                AttackTargetFinder.tmpTargets.Clear();
                AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                if (searcherThing.Faction != Faction.OfPlayer)
                {
                    for (int i = 0; i < AttackTargetFinder.tmpTargets.Count; i++)
                    {
                        IAttackTarget attackTarget = AttackTargetFinder.tmpTargets[i];
                        if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                        {
                            flag = true;
                            break;
                        }
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = AttackTargetFinder.GetRandomShootingTargetByScore(AttackTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2 = ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == TargetScanFlags.None || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (AttackTargetFinder.CanReach(searcherThing, t, canBash) || AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))));
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, AttackTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                AttackTargetFinder.tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0.0 && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator2 = innerValidator;
                innerValidator = delegate(IAttackTarget t)
                {
                    if (!oldValidator2(t))
                    {
                        return(false);
                    }
                    if (!t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius))
                    {
                        return(false);
                    }
                    return(true);
                };
            }
            IntVec3           root             = searcherThing.Position;
            Map               map              = searcherThing.Map;
            ThingRequest      thingReq         = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode       peMode           = PathEndMode.Touch;
            Pawn              pawn             = searcherPawn;
            Danger            maxDanger        = Danger.Deadly;
            bool              canBash2         = canBash;
            TraverseParms     traverseParams   = TraverseParms.For(pawn, maxDanger, TraverseMode.ByPawn, canBash2);
            float             maxDistance      = maxDist;
            Predicate <Thing> validator3       = (Thing x) => innerValidator((IAttackTarget)x);
            int               searchRegionsMax = (!(maxDist > 800.0)) ? 40 : (-1);
            IAttackTarget     attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(root, map, thingReq, peMode, traverseParams, maxDistance, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = AttackTargetFinder.FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    root = searcherPawn.Position - attackTarget2.Thing.Position;
                    float lengthHorizontal  = root.LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50.0)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
Пример #16
0
        private bool NeedNewPath()
        {
            if (!this.destination.IsValid || this.curPath == null || !this.curPath.Found || this.curPath.NodesLeftCount == 0)
            {
                return(true);
            }
            if (this.destination.HasThing && this.destination.Thing.Map != this.pawn.Map)
            {
                return(true);
            }
            if ((this.pawn.Position.InHorDistOf(this.curPath.LastNode, 15f) || this.pawn.Position.InHorDistOf(this.destination.Cell, 15f)) && !ReachabilityImmediate.CanReachImmediate(this.curPath.LastNode, this.destination, this.pawn.Map, this.peMode, this.pawn))
            {
                return(true);
            }
            if (this.curPath.UsedRegionHeuristics && this.curPath.NodesConsumedCount >= 75)
            {
                return(true);
            }
            if (this.lastPathedTargetPosition != this.destination.Cell)
            {
                float num = (float)(this.pawn.Position - this.destination.Cell).LengthHorizontalSquared;
                float num2;
                if (num > 900f)
                {
                    num2 = 10f;
                }
                else if (num > 289f)
                {
                    num2 = 5f;
                }
                else if (num > 100f)
                {
                    num2 = 3f;
                }
                else if (num > 49f)
                {
                    num2 = 2f;
                }
                else
                {
                    num2 = 0.5f;
                }
                if ((float)(this.lastPathedTargetPosition - this.destination.Cell).LengthHorizontalSquared > num2 * num2)
                {
                    return(true);
                }
            }
            bool    flag  = PawnUtility.ShouldCollideWithPawns(this.pawn);
            bool    flag2 = this.curPath.NodesLeftCount < 30;
            IntVec3 other = IntVec3.Invalid;
            int     num3  = 0;

            while (num3 < 20 && num3 < this.curPath.NodesLeftCount)
            {
                IntVec3 intVec = this.curPath.Peek(num3);
                if (!intVec.Walkable(this.pawn.Map))
                {
                    return(true);
                }
                if (flag && !this.BestPathHadPawnsInTheWayRecently() && (PawnUtility.AnyPawnBlockingPathAt(intVec, this.pawn, false, true, false) || (flag2 && PawnUtility.AnyPawnBlockingPathAt(intVec, this.pawn, false, false, false))))
                {
                    return(true);
                }
                if (!this.BestPathHadDangerRecently() && PawnUtility.KnownDangerAt(intVec, this.pawn.Map, this.pawn))
                {
                    return(true);
                }
                Building_Door building_Door = intVec.GetEdifice(this.pawn.Map) as Building_Door;
                if (building_Door != null)
                {
                    if (!building_Door.CanPhysicallyPass(this.pawn) && !this.pawn.HostileTo(building_Door))
                    {
                        return(true);
                    }
                    if (building_Door.IsForbiddenToPass(this.pawn))
                    {
                        return(true);
                    }
                }
                if (num3 != 0 && intVec.AdjacentToDiagonal(other) && (PathFinder.BlocksDiagonalMovement(intVec.x, other.z, this.pawn.Map) || PathFinder.BlocksDiagonalMovement(other.x, intVec.z, this.pawn.Map)))
                {
                    return(true);
                }
                other = intVec;
                num3++;
            }
            return(false);
        }
Пример #17
0
        //public static FastPriorityQueue<CostNode2> openList = new FastPriorityQueue<CostNode2>(new CostNodeComparer2());
        //public static PathFinderNodeFast[] calcGrid = new PathFinderNodeFast[40000];
        //public static ushort statusOpenValue = 1;
        //public static ushort statusClosedValue = 2;
        public static bool FindPath(PathFinder __instance, ref PawnPath __result, IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            FastPriorityQueue <CostNode2> openList = getOpenList();
            ushort statusOpenValue   = getOpenValue();
            ushort statusClosedValue = getClosedValue();

            PathFinderNodeFast[]        calcGrid             = getCalcGrid(__instance);
            RegionCostCalculatorWrapper regionCostCalculator = getRegionCostCalculatorWrapper(__instance);

            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }

            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != mapField(__instance))
            {
                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=", mapField(__instance)));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!start.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid start ", start, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!dest.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
                {
                    __result = PawnPath.NotFound;
                    return(false);
                }
            }
            else if (!mapField(__instance).reachability.CanReach(start, dest, peMode, traverseParms))
            {
                __result = PawnPath.NotFound;
                return(false);
            }

            PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, dest.HasThing ? (" at " + dest.Cell) : ""));
            cellIndicesField(__instance)   = mapField(__instance).cellIndices;
            pathGridField(__instance)      = mapField(__instance).pathGrid;
            edificeGridField(__instance)   = mapField(__instance).edificeGrid.InnerArray;
            blueprintGridField(__instance) = mapField(__instance).blueprintGrid.InnerArray;
            int      x               = dest.Cell.x;
            int      z               = dest.Cell.z;
            int      curIndex        = cellIndicesField(__instance).CellToIndex(start);
            int      num             = cellIndicesField(__instance).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 destinationRect = CalculateDestinationRect(dest, peMode);
            bool     flag4           = destinationRect.Width == 1 && destinationRect.Height == 1;

            int[]        array       = mapField(__instance).pathGrid.pathGrid;
            TerrainDef[] topGrid     = mapField(__instance).terrainGrid.topGrid;
            EdificeGrid  edificeGrid = mapField(__instance).edificeGrid;
            int          num2        = 0;
            int          num3        = 0;
            Area         allowedArea = GetAllowedArea(pawn);
            bool         flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = !flag && start.GetRegion(mapField(__instance)) != 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;
            }

            CalculateAndAddDisallowedCorners2(disallowedCornerIndicesField(__instance), mapField(__instance), peMode, destinationRect);
            InitStatusesAndPushStartNode3(ref curIndex, start, cellIndicesField(__instance), calcGrid, ref statusOpenValue, ref statusClosedValue);
            openList.Clear();
            openList.Push(new CostNode2(curIndex, 0));
            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();
                    __result = PawnPath.NotFound;
                    return(false);
                }

                num5 += openList.Count;
                num6++;
                CostNode2 costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    PfProfilerEndSample();
                    continue;
                }

                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                    continue;
                }

                IntVec3 c  = cellIndicesField(__instance).IndexToCell(curIndex);
                int     x2 = c.x;
                int     z2 = c.z;
                if (flag4)
                {
                    if (curIndex == num)
                    {
                        PfProfilerEndSample();
                        PawnPath result = FinalizedPath2(curIndex, flag8, cellIndicesField(__instance), calcGrid);
                        PfProfilerEndSample();
                        __result = result;
                        return(false);
                    }
                }
                else if (destinationRect.Contains(c) && !disallowedCornerIndicesField(__instance).Contains(curIndex))
                {
                    PfProfilerEndSample();
                    PawnPath result2 = FinalizedPath2(curIndex, flag8, cellIndicesField(__instance), calcGrid);
                    PfProfilerEndSample();
                    __result = result2;
                    return(false);
                }

                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 >= mapSizeXField(__instance) || num11 >= mapSizeZField(__instance))
                    {
                        continue;
                    }

                    int num12 = (int)num10;
                    int num13 = (int)num11;
                    int num14 = cellIndicesField(__instance).CellToIndex(num12, num13);
                    if (calcGrid[num14].status == statusClosedValue && !flag8)
                    {
                        continue;
                    }

                    int  num15  = 0;
                    bool flag10 = false;
                    if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(mapField(__instance)).HasTag("Water"))
                    {
                        continue;
                    }

                    if (!pathGridField(__instance).WalkableFast(num14))
                    {
                        if (!flag)
                        {
                            continue;
                        }

                        flag10 = true;
                        num15 += 70;
                        Building building = edificeGrid[num14];
                        if (building == null || !PathFinder.IsDestroyable(building))
                        {
                            continue;
                        }

                        num15 += (int)(building.HitPoints * 0.2f);
                    }

                    switch (i)
                    {
                    case 4:
                        if (PathFinder.BlocksDiagonalMovement(curIndex - mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex + 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 5:
                        if (PathFinder.BlocksDiagonalMovement(curIndex + mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex + 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 6:
                        if (PathFinder.BlocksDiagonalMovement(curIndex + mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex - 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 7:
                        if (PathFinder.BlocksDiagonalMovement(curIndex - mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex - 1, mapField(__instance)))
                        {
                            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 = edificeGridField(__instance)[num14];
                    if (building2 != null)
                    {
                        PfProfilerBeginSample("Edifices");
                        int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn);
                        if (buildingCost == int.MaxValue)
                        {
                            PfProfilerEndSample();
                            continue;
                        }

                        num16 += buildingCost;
                        PfProfilerEndSample();
                    }

                    List <Blueprint> list = blueprintGridField(__instance)[num14];
                    if (list != null)
                    {
                        PfProfilerBeginSample("Blueprints");
                        int num17 = 0;
                        for (int j = 0; j < list.Count; j++)
                        {
                            num17 = Mathf.Max(num17, PathFinder.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 CostNode2(num14, num21));
                }

                PfProfilerEndSample();
                num2++;
                calcGrid[curIndex].status = statusClosedValue;
                if (num3 >= num4 && flag6 && !flag8)
                {
                    flag8 = true;
                    regionCostCalculator.Init(destinationRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndicesField(__instance));
                    InitStatusesAndPushStartNode3(ref curIndex, start, cellIndicesField(__instance), calcGrid, ref statusOpenValue, ref statusClosedValue);
                    openList.Clear();
                    openList.Push(new CostNode2(curIndex, 0));
                    num3 = 0;
                    num2 = 0;
                }
            }

            Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells."));
            DebugDrawRichData();
            PfProfilerEndSample();
            PfProfilerEndSample();
            __result = PawnPath.NotFound;
            return(false);
        }
Пример #18
0
        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);
        }
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, Verb verb, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false);
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((byte)(flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    if (t is Pawn)
                    {
                        if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            return(false);
                        }
                    }
                    else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                if (onlyTargetMachines && t is Pawn pawn && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    foreach (IntVec3 cellRect in thing.OccupiedRect())
                    {
                        if (cellRect.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (PCF_AttackTargetFinder.HasRangedAttack(searcher, verb))
            {
                PCF_AttackTargetFinder.tmpTargets.Clear();
                PCF_AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && PCF_AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                for (int i = 0; i < PCF_AttackTargetFinder.tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = PCF_AttackTargetFinder.tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && PCF_AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    PCF_AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = PCF_AttackTargetFinder.GetRandomShootingTargetByScore(PCF_AttackTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (PCF_AttackTargetFinder.CanReach(searcherThing, t, canBash) || PCF_AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, PCF_AttackTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                PCF_AttackTargetFinder.tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius));
            }
            IntVec3       position       = searcherThing.Position;
            Map           map            = searcherThing.Map;
            ThingRequest  thingReq       = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode   peMode         = PathEndMode.Touch;
            Pawn          searcherPawn2  = searcherPawn;
            Danger        maxDanger      = Danger.Deadly;
            bool          canBash2       = canBash;
            TraverseParms traverseParams = TraverseParms.For(searcherPawn2, maxDanger, TraverseMode.ByPawn, canBash2);
            float         maxDist2       = maxDist;

            bool validator3(Thing x) => innerValidator((IAttackTarget)x);

            int           searchRegionsMax = (maxDist <= 800f) ? 40 : -1;
            IAttackTarget attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, maxDist2, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = PCF_AttackTargetFinder.FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
Пример #20
0
        //The standard A* search algorithm has been modified to implement the bidirectional pathmax algorithm
        //("Inconsistent heuristics in theory and practice" Felner et al.) http://web.cs.du.edu/~sturtevant/papers/incnew.pdf
        internal PawnPath FindPathInner(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, HeuristicMode mode = HeuristicMode.Better)
        {
            //The initialization is largely unchanged from Core, aside from coding style in some spots
            #region initialization
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAnything;
            }
            Pawn pawn            = traverseParms.pawn;
            bool canPassAnything = traverseParms.mode == TraverseMode.PassAnything;

            if (!ValidateFindPathParameters(pawn, start, dest, traverseParms, peMode, canPassAnything))
            {
                return(PawnPath.NotFound);
            }

            PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, (!dest.HasThing) ? string.Empty : (" at " + dest.Cell)));
            destinationX = dest.Cell.x;
            destinationZ = dest.Cell.z;
            var cellIndices = this.map.cellIndices;
            curIndex         = cellIndices.CellToIndex(start);
            destinationIndex = cellIndices.CellToIndex(dest.Cell);
            if (!dest.HasThing || peMode == PathEndMode.OnCell)
            {
                destinationRect = CellRect.SingleCell(dest.Cell);
            }
            else
            {
                destinationRect = dest.Thing.OccupiedRect();
            }
            if (peMode == PathEndMode.Touch)
            {
                destinationRect = destinationRect.ExpandedBy(1);
            }
            destinationRect = destinationRect.ClipInsideMap(map);
            var regions = destinationRect.Cells.Select(c => this.map.regionGrid.GetValidRegionAt_NoRebuild(c)).Where(r => r != null);
            //Pretty sure this shouldn't be able to happen...
            if (mode == HeuristicMode.Better && !canPassAnything && !regions.Any())
            {
                mode = HeuristicMode.Vanilla;
                Log.Warning("Pathfinding destination not in region, must fall back to vanilla!");
            }
            destinationIsOneCell = (destinationRect.Width == 1 && destinationRect.Height == 1);
            this.pathGridDirect  = this.map.pathGrid.pathGrid;
            this.edificeGrid     = this.map.edificeGrid.InnerArray;
            statusOpenValue     += 2;
            statusClosedValue   += 2;
            if (statusClosedValue >= 65435)
            {
                ResetStatuses();
            }
            if (pawn?.RaceProps.Animal == true)
            {
                heuristicStrength = 30;
            }
            else
            {
                float lengthHorizontal = (start - dest.Cell).LengthHorizontal;
                heuristicStrength = (int)Math.Round(HeuristicStrengthHuman_DistanceCurve.Evaluate(lengthHorizontal));
            }
            closedCellCount = 0;
            openList.Clear();
            debug_pathFailMessaged   = false;
            debug_totalOpenListCount = 0;
            debug_openCellsPopped    = 0;

            PawnPathCostSettings pawnPathCosts = GetPawnPathCostSettings(traverseParms.pawn);

            moveTicksCardinal = pawnPathCosts.moveTicksCardinal;
            moveTicksDiagonal = pawnPathCosts.moveTicksDiagonal;

            //Where the magic happens
            RegionPathCostHeuristic regionCost = new RegionPathCostHeuristic(map, start, destinationRect, regions, traverseParms, pawnPathCosts);

            if (mode == HeuristicMode.Better)
            {
                if (canPassAnything)
                {
                    //Roughly preserves the Vanilla behavior of increasing path accuracy for shorter paths and slower pawns, though not as smoothly. Only applies to sappers.
                    heuristicStrength = Math.Max(1, (int)Math.Round(heuristicStrength / (float)moveTicksCardinal));
                }
                else
                {
                    var totalCostEst = (debug_totalHeuristicCostEstimate = regionCost.GetPathCostToRegion(curIndex)) + (moveTicksCardinal * 50);                     //Add constant cost so it tries harder on short paths
                    regionHeuristicWeightReal[1].x = totalCostEst / 2;
                    regionHeuristicWeightReal[2].x = totalCostEst;
                }
                regionHeuristicWeight = weightEnabled ? regionHeuristicWeightReal : regionHeuristicWeightNone;
            }
            else
            {
                regionHeuristicWeight = regionHeuristicWeightNone;
            }
            calcGrid[curIndex].knownCost     = 0;
            calcGrid[curIndex].heuristicCost = 0;
            calcGrid[curIndex].parentIndex   = curIndex;
            calcGrid[curIndex].status        = statusOpenValue;
            openList.Push(new CostNode(curIndex, 0));


            bool shouldCollideWithPawns = false;
            if (pawn != null)
            {
                shouldCollideWithPawns = PawnUtility.ShouldCollideWithPawns(pawn);
            }
            #endregion

            while (true)
            {
                PfProfilerBeginSample("Open cell pop");
                if (openList.Count <= 0)
                {
                    break;
                }
                debug_openCellsPopped++;
                var thisNode = openList.Pop();
                curIndex = thisNode.gridIndex;
                PfProfilerEndSample();
                PfProfilerBeginSample("Open cell");
                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                }
                else
                {
#if DEBUG
                    calcGrid[curIndex].timesPopped++;
#endif
                    curIntVec3 = cellIndices.IndexToCell(curIndex);
                    if (DebugViewSettings.drawPaths && !disableDebugFlash && debug_openCellsPopped < 20000)
                    {
                        //draw backpointer
                        var    arrow    = GetBackPointerArrow(cellIndices.IndexToCell(calcGrid[curIndex].parentIndex), curIntVec3);
                        string leading  = "";
                        string trailing = "";

#if DEBUG
                        switch (calcGrid[curIndex].timesPopped)
                        {
                        case 1:
                            trailing = "\n\n";                                     // $"\n\n\n{thisNode.totalCostEstimate}({calcGrid[curIndex].knownCost + calcGrid[curIndex].originalHeuristicCost})";
                            break;

                        case 2:
                            trailing = "\n"; break;

                        case 3: break;

                        case 4:
                            leading = "\n"; break;

                        default:
                            leading = "\n\n"; break;
                        }
#endif
                        DebugFlash(curIntVec3, calcGrid[curIndex].knownCost / 1500f, leading + calcGrid[curIndex].knownCost + " " + arrow + " " + debug_openCellsPopped + trailing);
                    }
                    if (curIndex == destinationIndex || (!destinationIsOneCell && destinationRect.Contains(curIntVec3)))
                    {
                        PfProfilerEndSample();
                        PfProfilerBeginSample("Finalize Path");
                        var ret = FinalizedPath(curIndex);
                        PfProfilerEndSample();
                        return(ret);
                    }
                    //With reopening closed nodes, this limit can be reached a lot more easily. I've left it as is because it gets users to report bad paths.
                    if (closedCellCount > 160000)
                    {
                        Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells."));
                        PfProfilerEndSample();
                        return(PawnPath.NotFound);
                    }
                    PfProfilerEndSample();
                    PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        neighIndexes[i] = -1;

                        neighX = (ushort)(curIntVec3.x + Directions[i]);
                        neighZ = (ushort)(curIntVec3.z + Directions[i + 8]);
                        if (neighX >= mapSizeX || neighZ >= mapSizeZ)
                        {
                            continue;
                        }

                        switch (i)
                        {
                        case 4:     //Northeast
                            if (!pathGridDirect.WalkableExtraFast(curIndex - mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex + 1))
                            {
                                continue;
                            }
                            break;

                        case 5:     //Southeast
                            if (!pathGridDirect.WalkableExtraFast(curIndex + mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex + 1))
                            {
                                continue;
                            }
                            break;

                        case 6:     //Southwest
                            if (!pathGridDirect.WalkableExtraFast(curIndex + mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex - 1))
                            {
                                continue;
                            }
                            break;

                        case 7:     //Northwest
                            if (!pathGridDirect.WalkableExtraFast(curIndex - mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex - 1))
                            {
                                continue;
                            }
                            break;
                        }

                        neighIndex = cellIndices.CellToIndex(neighX, neighZ);

                        if ((calcGrid[neighIndex].status != statusClosedValue) && (calcGrid[neighIndex].status != statusOpenValue))
                        {
                            if (10000 <= (calcGrid[neighIndex].perceivedPathCost = GetTotalPerceivedPathCost(traverseParms, canPassAnything, shouldCollideWithPawns, pawn, pawnPathCosts)))
                            {
                                continue;
                            }
#if DEBUG
                            calcGrid[neighIndex].timesPopped = 0;
#endif
                            #region heuristic
                            PfProfilerBeginSample("Heuristic");
                            switch (mode)
                            {
                            case HeuristicMode.Vanilla:
                                h = heuristicStrength * (Math.Abs(neighX - destinationX) + Math.Abs(neighZ - destinationZ));
                                break;

                            case HeuristicMode.AdmissableOctile:
                            {
                                var dx = Math.Abs(neighX - destinationX);
                                var dy = Math.Abs(neighZ - destinationZ);
                                h = moveTicksCardinal * (dx + dy) + (moveTicksDiagonal - 2 * moveTicksCardinal) * Math.Min(dx, dy);
                            }
                            break;

                            case HeuristicMode.Better:
                                if (canPassAnything)
                                {
                                    var dx = Math.Abs(neighX - destinationX);
                                    var dy = Math.Abs(neighZ - destinationZ);
                                    h = heuristicStrength * (moveTicksCardinal * (dx + dy) + (moveTicksDiagonal - 2 * moveTicksCardinal) * Math.Min(dx, dy));
                                }
                                else
                                {
                                    h = regionCost.GetPathCostToRegion(neighIndex);
                                }
                                break;
                            }
                            calcGrid[neighIndex].heuristicCost = h;
#if PATHMAX
                            calcGrid[neighIndex].originalHeuristicCost = h;
#endif
                            PfProfilerEndSample();
                            #endregion
                        }


                        if (calcGrid[neighIndex].perceivedPathCost < 10000)
                        {
                            neighIndexes[i] = neighIndex;
                        }
                        if (mode == HeuristicMode.Better && (calcGrid[neighIndex].status == statusOpenValue &&
                                                             Math.Max(i > 3 ? (int)(calcGrid[curIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[curIndex].perceivedPathCost + moveTicksCardinal, 1) + calcGrid[neighIndex].knownCost < calcGrid[curIndex].knownCost))
                        {
                            calcGrid[curIndex].parentIndex = neighIndex;
                            calcGrid[curIndex].knownCost   = Math.Max(i > 3 ? (int)(calcGrid[curIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[curIndex].perceivedPathCost + moveTicksCardinal, 1) + calcGrid[neighIndex].knownCost;
                        }
                    }
                    #region BPMX Best H
#if PATHMAX
                    PfProfilerBeginSample("BPMX Best H");
                    int bestH = calcGrid[curIndex].heuristicCost;
                    if (mode == HeuristicMode.Better && pathmaxEnabled)
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            neighIndex = neighIndexes[i];
                            if (neighIndex < 0)
                            {
                                continue;
                            }
                            bestH = Math.Max(bestH, calcGrid[neighIndex].heuristicCost - (calcGrid[curIndex].perceivedPathCost + (i > 3 ? moveTicksDiagonal : moveTicksCardinal)));
                        }
                    }

                    //Pathmax Rule 3: set the current node heuristic to the best value of all connected nodes
                    calcGrid[curIndex].heuristicCost = bestH;
                    PfProfilerEndSample();
#endif
                    #endregion

                    #region Updating open list
                    for (int i = 0; i < 8; i++)
                    {
                        neighIndex = neighIndexes[i];
                        if (neighIndex < 0)
                        {
                            continue;
                        }
                        if (calcGrid[neighIndex].status == statusClosedValue && (canPassAnything || mode != HeuristicMode.Better))
                        {
                            continue;
                        }

                        //When path costs are significantly higher than move costs (e.g. snowy ice, or outside of allowed areas),
                        //small differences in the weighted heuristic overwhelm the added cost of diagonal movement, so nodes
                        //can often be visited in unnecessary zig-zags, causing lots of nodes to be reopened later, and weird looking
                        //paths if they are not revisited. Weighting the diagonal path cost slightly counteracts this behavior, and
                        //should result in natural looking paths when it does cause suboptimal behavior
                        var thisDirEdgeCost = (i > 3 ? (int)(calcGrid[neighIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[neighIndex].perceivedPathCost + moveTicksCardinal);

                        //var thisDirEdgeCost = calcGrid[neighIndex].perceivedPathCost + (i > 3 ? moveTicksDiagonal : moveTicksCardinal);
                        //Some mods can result in negative path costs. That works well enough with Vanilla, since it won't revisit closed nodes, but when we do, it's an infinite loop.
                        thisDirEdgeCost     = (ushort)Math.Max(thisDirEdgeCost, 1);
                        neighCostThroughCur = thisDirEdgeCost + calcGrid[curIndex].knownCost;
#if PATHMAX
                        //Pathmax Rule 1
                        int nodeH = (mode == HeuristicMode.Better && pathmaxEnabled) ? Math.Max(calcGrid[neighIndex].heuristicCost, bestH - thisDirEdgeCost) : calcGrid[neighIndex].heuristicCost;
#endif
                        if (calcGrid[neighIndex].status == statusClosedValue || calcGrid[neighIndex].status == statusOpenValue)
                        {
#if PATHMAX
                            bool needsUpdate = false;
#endif
                            int minReopenGain = 0;
                            if (calcGrid[neighIndex].status == statusOpenValue)
                            {
#if PATHMAX
                                needsUpdate = nodeH > calcGrid[neighIndex].heuristicCost;
#endif
                            }
                            else
                            {                                   //Don't reopen closed nodes if the path cost difference isn't large enough to justify it; otherwise there can be cascades of revisiting the same nodes over and over for tiny path improvements each time
                                                                //Increasing the threshold as more cells get reopened further helps prevent cascades
                                minReopenGain = moveTicksCardinal + closedCellsReopened / 5;
                                if (pawnPathCosts.area?[neighIndex] == false)
                                {
                                    minReopenGain *= 10;
                                }
                            }
#if PATHMAX
                            calcGrid[neighIndex].heuristicCost = nodeH;
#endif
                            if (!(neighCostThroughCur + minReopenGain < calcGrid[neighIndex].knownCost))
                            {
#if PATHMAX
                                if (needsUpdate)                                 //if the heuristic cost was increased for an open node, we need to adjust its spot in the queue
                                {
                                    var neighCell = cellIndices.IndexToCell(neighIndex);
                                    var edgeCost  = Math.Max(calcGrid[neighIndex].parentX != neighCell.x && calcGrid[neighIndex].parentZ != neighCell.z ? (int)(calcGrid[neighIndex].perceivedPathCost * diagonalPercievedCostWeight) + moveTicksDiagonal : calcGrid[neighIndex].perceivedPathCost + moveTicksCardinal, 1);
                                    openList.PushOrUpdate(new CostNode(neighIndex, calcGrid[neighIndex].knownCost - edgeCost
                                                                       + (int)Math.Ceiling((edgeCost + nodeH) * regionHeuristicWeight.Evaluate(calcGrid[neighIndex].knownCost))));
                                }
#endif
                                continue;
                            }
                            if (calcGrid[neighIndex].status == statusClosedValue)
                            {
                                closedCellsReopened++;
                            }
                        }
                        //else
                        //{
                        //	DebugFlash(cellIndices.IndexToCell(neighIndex), 0.2f, $"\n\n{neighCostThroughCur} | {nodeH}\n{calcGrid[curIndex].knownCost + (int)Math.Ceiling((nodeH + thisDirEdgeCost) * regionHeuristicWeight.Evaluate(calcGrid[curIndex].knownCost))}");
                        //}

                        calcGrid[neighIndex].parentIndex = curIndex;
                        calcGrid[neighIndex].knownCost   = neighCostThroughCur;
                        calcGrid[neighIndex].status      = statusOpenValue;
#if PATHMAX
                        calcGrid[neighIndex].heuristicCost = nodeH;
#endif
                        PfProfilerBeginSample("Push Open");
                        openList.PushOrUpdate(new CostNode(neighIndex, calcGrid[curIndex].knownCost
                                                           + (int)Math.Ceiling((calcGrid[neighIndex].heuristicCost + thisDirEdgeCost) * regionHeuristicWeight.Evaluate(calcGrid[curIndex].knownCost))));
                        debug_totalOpenListCount++;
                        PfProfilerEndSample();
                    }
                    #endregion
                    PfProfilerEndSample();
                    closedCellCount++;
                    calcGrid[curIndex].status = statusClosedValue;
                }
            }
            if (!debug_pathFailMessaged)
            {
                string text  = pawn?.CurJob?.ToString() ?? "null";
                string text2 = pawn?.Faction?.ToString() ?? "null";
                Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2));
                debug_pathFailMessaged = true;
            }
            PfProfilerEndSample();
            return(PawnPath.NotFound);
        }