Beispiel #1
0
        private static bool CheckCellBasedReachability(
            IntVec3 start,
            LocalTargetInfo dest,
            PathEndMode peMode,
            TraverseParms traverseParams, RegionGrid regionGrid, Reachability __instance, List <Region> this_startingRegions,
            ReachabilityCache this_cache, List <Region> this_destRegions)
        {
            IntVec3 foundCell = IntVec3.Invalid;

            Region[]    directRegionGrid = regionGrid.DirectGrid;
            PathGrid    pathGrid         = map(__instance).pathGrid;
            CellIndices cellIndices      = map(__instance).cellIndices;

            map(__instance).floodFiller.FloodFill(start, (Predicate <IntVec3>)(c =>
            {
                int index = cellIndices.CellToIndex(c);
                if ((traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater) &&
                    c.GetTerrain(map(__instance)).IsWater)
                {
                    return(false);
                }
                if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    if (!pathGrid.WalkableFast(index))
                    {
                        Building edifice = c.GetEdifice(map(__instance));
                        if (edifice == null || !PathFinder.IsDestroyable((Thing)edifice))
                        {
                            return(false);
                        }
                    }
                }
                else if (traverseParams.mode != TraverseMode.NoPassClosedDoorsOrWater)
                {
                    Log.ErrorOnce("Do not use this method for non-cell based modes!", 938476762, false);
                    if (!pathGrid.WalkableFast(index))
                    {
                        return(false);
                    }
                }
                Region region = directRegionGrid[index];
                return(region == null || region.Allows(traverseParams, false));
            }), (Func <IntVec3, bool>)(c =>
            {
                if (!ReachabilityImmediate.CanReachImmediate(c, dest, map(__instance), peMode, traverseParams.pawn))
                {
                    return(false);
                }
                foundCell = c;
                return(true);
            }), int.MaxValue, false, (IEnumerable <IntVec3>)null);
            if (foundCell.IsValid)
            {
                if (CanUseCache(traverseParams.mode))
                {
                    Region validRegionAt = regionGrid.GetValidRegionAt(foundCell);
                    if (validRegionAt != null)
                    {
                        for (int index = 0; index < this_startingRegions.Count; ++index)
                        {
                            this_cache.AddCachedResult(this_startingRegions[index].Room, validRegionAt.Room, traverseParams, true);
                        }
                    }
                }
                return(true);
            }
            if (CanUseCache(traverseParams.mode))
            {
                for (int index1 = 0; index1 < this_startingRegions.Count; ++index1)
                {
                    for (int index2 = 0; index2 < this_destRegions.Count; ++index2)
                    {
                        this_cache.AddCachedResult(this_startingRegions[index1].Room, this_destRegions[index2].Room, traverseParams, false);
                    }
                }
            }
            return(false);
        }
        private static IAttackTarget FindBestReachableMeleeTarget(Predicate <IAttackTarget> validator, Pawn searcherPawn, float maxTargDist, bool canBash)
        {
            maxTargDist = Mathf.Min(maxTargDist, 30f);
            IAttackTarget reachableTarget = null;
            Func <IntVec3, IAttackTarget> bestTargetOnCell = delegate(IntVec3 x)
            {
                List <Thing> thingList = x.GetThingList(searcherPawn.Map);
                for (int i = 0; i < thingList.Count; i++)
                {
                    Thing         thing        = thingList[i];
                    IAttackTarget attackTarget = thing as IAttackTarget;
                    if (attackTarget != null)
                    {
                        if (validator(attackTarget))
                        {
                            if (ReachabilityImmediate.CanReachImmediate(x, thing, searcherPawn.Map, PathEndMode.Touch, searcherPawn))
                            {
                                if (searcherPawn.CanReachImmediate(thing, PathEndMode.Touch) || searcherPawn.Map.attackTargetReservationManager.CanReserve(searcherPawn, attackTarget))
                                {
                                    return(attackTarget);
                                }
                            }
                        }
                    }
                }
                return(null);
            };

            searcherPawn.Map.floodFiller.FloodFill(searcherPawn.Position, delegate(IntVec3 x)
            {
                if (!x.Walkable(searcherPawn.Map))
                {
                    return(false);
                }
                if ((float)x.DistanceToSquared(searcherPawn.Position) > maxTargDist * maxTargDist)
                {
                    return(false);
                }
                if (!canBash)
                {
                    Building_Door building_Door = x.GetEdifice(searcherPawn.Map) as Building_Door;
                    if (building_Door != null && !building_Door.CanPhysicallyPass(searcherPawn))
                    {
                        return(false);
                    }
                }
                return(!PawnUtility.AnyPawnBlockingPathAt(x, searcherPawn, true, false, false));
            }, delegate(IntVec3 x)
            {
                for (int i = 0; i < 8; i++)
                {
                    IntVec3 intVec = x + GenAdj.AdjacentCells[i];
                    if (intVec.InBounds(searcherPawn.Map))
                    {
                        IAttackTarget attackTarget = bestTargetOnCell(intVec);
                        if (attackTarget != null)
                        {
                            reachableTarget = attackTarget;
                            break;
                        }
                    }
                }
                return(reachableTarget != null);
            }, int.MaxValue, false, null);
            return(reachableTarget);
        }
Beispiel #3
0
        public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine)
        {
            if (targ.HasThing && targ.Thing.Map != caster.Map)
            {
                resultingLine = default(ShootLine);
                return(false);
            }
            if (verbProps.range <= ShootTuning.MeleeRange) // If this verb has a MAX range up to melee range (NOT a MIN RANGE!)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(ReachabilityImmediate.CanReachImmediate(root, targ, caster.Map, PathEndMode.Touch, null));
            }
            CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect();
            float    num      = cellRect.ClosestDistSquaredTo(root);

            if (num > verbProps.range * verbProps.range || num < verbProps.minRange * verbProps.minRange)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(false);
            }
            //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile
            if (Projectile.projectile.flyOverhead)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(true);
            }

            // First check current cell for early opt-out
            IntVec3 dest;
            var     shotSource = root.ToVector3Shifted();

            shotSource.y = ShotHeight;

            // Adjust for multi-tile turrets
            if (caster.def.building?.IsTurret ?? false)
            {
                shotSource = ShotSource;
            }

            if (CanHitFromCellIgnoringRange(shotSource, targ, out dest))
            {
                resultingLine = new ShootLine(root, dest);
                return(true);
            }
            // For pawns, calculate possible lean locations
            if (CasterIsPawn)
            {
                // Next check lean sources
                ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), caster.Map, tempLeanShootSources);
                foreach (var leanLoc in tempLeanShootSources)
                {
                    var leanOffset = (leanLoc - root).ToVector3() * 0.5f;

                    if (CanHitFromCellIgnoringRange(shotSource + leanOffset, targ, out dest))
                    {
                        resultingLine = new ShootLine(leanLoc, dest);
                        return(true);
                    }
                }
            }

            resultingLine = new ShootLine(root, targ.Cell);
            return(false);
        }
Beispiel #4
0
        public static bool CanReach(Reachability __instance, ref bool __result,
                                    IntVec3 start,
                                    LocalTargetInfo dest,
                                    PathEndMode peMode,
                                    TraverseParms traverseParams)
        {
            /*
             * if (working)
             * {
             *  Log.ErrorOnce("Called CanReach() while working. This should never happen. Suppressing further errors.", 7312233);
             *  return false;
             * }
             */

            Map this_map = map(__instance);

            if (traverseParams.pawn != null)
            {
                if (!traverseParams.pawn.Spawned)
                {
                    __result = false;
                    return(false);
                }
                if (traverseParams.pawn.Map != this_map)
                {
                    Log.Error("Called CanReach() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=" +
                              (object)traverseParams.pawn + " pawn.Map=" + (object)traverseParams.pawn.Map + " map=" + (object)map(__instance), false);
                    __result = false;
                    return(false);
                }
            }
            if (ReachabilityImmediate.CanReachImmediate(start, dest, this_map, peMode, traverseParams.pawn))
            {
                __result = true;
                return(false);
            }
            if (!dest.IsValid || dest.HasThing && dest.Thing.Map != this_map || (!start.InBounds(this_map) || !dest.Cell.InBounds(this_map)))
            {
                __result = false;
                return(false);
            }
            if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && (traverseParams.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater))
            {
                Room room = RegionAndRoomQuery.RoomAtFast(start, this_map, RegionType.Set_Passable);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, this_map, RegionType.Set_Passable))
                {
                    __result = true;
                    return(false);
                }
            }
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                TraverseParms traverseParams1 = traverseParams;
                traverseParams1.mode = TraverseMode.PassDoors;
                if (__instance.CanReach(start, dest, peMode, traverseParams1))
                {
                    __result = true;
                    return(false);
                }
            }
            dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(this_map), ref peMode);
            //working = true;
            try
            {
                uint this_reachedIndex;                                   //Replaced reachedIndex
                lock (reachedIndexLock)                                   //Added
                {
                    this_reachedIndex   = offsetReachedIndex;             //Added
                    offsetReachedIndex += 100000;                         //Added
                }
                HashSet <Region> regionsReached = new HashSet <Region>(); //Added
                PathGrid         pathGrid       = this_map.pathGrid;      //Replaced pathGrid
                RegionGrid       regionGrid     = this_map.regionGrid;    //Replaced regionGrid
                ++this_reachedIndex;                                      //Replaced reachedIndex

                //this_destRegions.Clear();
                List <Region> this_destRegions = new List <Region>(); //Replaced destRegions
                switch (peMode)
                {
                case PathEndMode.OnCell:
                    Region region = dest.Cell.GetRegion(this_map, RegionType.Set_Passable);
                    if (region != null && region.Allows(traverseParams, true))
                    {
                        this_destRegions.Add(region);
                        break;
                    }
                    break;

                case PathEndMode.Touch:
                    TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, this_map, this_destRegions);
                    break;
                }
                if (this_destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    //this.FinalizeCheck();
                    __result = false;
                    return(false);
                }
                this_destRegions.RemoveDuplicates <Region>();
                //this_openQueue.Clear();
                Queue <Region> this_openQueue        = new Queue <Region>(); //Replaced openQueue
                int            this_numRegionsOpened = 0;                    //Replaced numRegionsOpened
                List <Region>  this_startingRegions  = new List <Region>();
                DetermineStartRegions2(__instance, start, this_startingRegions, pathGrid, regionGrid, this_reachedIndex, this_openQueue, ref this_numRegionsOpened, regionsReached);
                if (this_openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    //this.FinalizeCheck();
                    __result = false;
                    return(false);
                }
                ReachabilityCache this_cache = cache(__instance);
                if (this_startingRegions.Any <Region>() && this_destRegions.Any <Region>() && CanUseCache(traverseParams.mode))
                {
                    switch (GetCachedResult2(traverseParams, this_startingRegions, this_destRegions, this_cache))
                    {
                    case BoolUnknown.True:
                        //this.FinalizeCheck();
                        __result = true;
                        return(false);

                    case BoolUnknown.False:
                        //this.FinalizeCheck();
                        __result = false;
                        return(false);
                    }
                }
                if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater)
                {
                    int num = CheckCellBasedReachability(start, dest, peMode, traverseParams,
                                                         regionGrid, __instance, this_startingRegions, this_cache, this_destRegions
                                                         ) ? 1 : 0;
                    //this.FinalizeCheck();
                    __result = num != 0;
                    return(false);
                }
                int num1 = CheckRegionBasedReachability(traverseParams,
                                                        this_openQueue, this_reachedIndex,
                                                        this_destRegions, this_startingRegions, this_cache, ref this_numRegionsOpened, regionsReached
                                                        ) ? 1 : 0;
                //this.FinalizeCheck();
                __result = num1 != 0;
                return(false);
            }
            finally
            {
            }
        }
        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);
        }
Beispiel #6
0
 public override bool AllowVerbCast(IntVec3 root, Map map, LocalTargetInfo targ)
 {
     return(ReachabilityImmediate.CanReachImmediate(root, targ, map, PathEndMode.Touch, null));
 }
        public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine)
        {
            if (targ.HasThing && targ.Thing.Map != this.caster.Map)
            {
                resultingLine = default(ShootLine);
                return(false);
            }
            if (this.verbProps.MeleeRange)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(ReachabilityImmediate.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null));
            }
            CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect();
            float    num      = cellRect.ClosestDistSquaredTo(root);

            if (num > this.verbProps.range * this.verbProps.range || num < this.verbProps.minRange * this.verbProps.minRange)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(false);
            }
            //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile
            if (ProjectileDef.projectile.flyOverhead)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(true);
            }
            if (this.CasterIsPawn)
            {
                IntVec3 dest;
                if (this.CanHitFromCellIgnoringRange(root, targ, out dest))
                {
                    resultingLine = new ShootLine(root, dest);
                    return(true);
                }
                ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, tempLeanShootSources);
                for (int i = 0; i < tempLeanShootSources.Count; i++)
                {
                    IntVec3 intVec = tempLeanShootSources[i];
                    if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest))
                    {
                        resultingLine = new ShootLine(intVec, dest);
                        return(true);
                    }
                }
            }
            else
            {
                CellRect.CellRectIterator iterator = this.caster.OccupiedRect().GetIterator();
                while (!iterator.Done())
                {
                    IntVec3 current = iterator.Current;
                    IntVec3 dest;
                    if (this.CanHitFromCellIgnoringRange(current, targ, out dest))
                    {
                        resultingLine = new ShootLine(current, dest);
                        return(true);
                    }
                    iterator.MoveNext();
                }
            }
            resultingLine = new ShootLine(root, targ.Cell);
            return(false);
        }
 // Token: 0x06002742 RID: 10050 RVA: 0x0012AED9 File Offset: 0x001292D9
 public override bool AllowVerbCast(IntVec3 root, Map map, LocalTargetInfo targ, Verb verb)
 {
     return(!(verb is Verb_LaunchProjectile) || ReachabilityImmediate.CanReachImmediate(root, targ, map, PathEndMode.Touch, null));
 }
Beispiel #9
0
 public bool AllowVerbCast(Pawn caster, LocalTargetInfo targ, Verb verb)
 {
     return(!(verb is Verb_LaunchProjectile) || ReachabilityImmediate.CanReachImmediate(caster.Position, targ, caster.Map, PathEndMode.Touch, null));
 }
        public static bool PreFix(ref Toil __result, TargetIndex targetInd, Action hitAction)
        {
            Toil followAndAttack = new Toil();

            followAndAttack.tickAction = delegate()
            {
                Pawn      actor     = followAndAttack.actor;
                Job       curJob    = actor.jobs.curJob;
                JobDriver curDriver = actor.jobs.curDriver;
                Thing     thing     = curJob.GetTarget(targetInd).Thing;
                Pawn      pawn      = thing as Pawn;
                if (thing.Spawned && !ReachabilityImmediate.CanReachImmediate(actor, pawn, PathEndMode.Touch))
                {
                    bool flag;
                    if (actor == null)
                    {
                        flag = (null != null);
                    }
                    else
                    {
                        Pawn_MindState mindState = actor.mindState;
                        flag = ((mindState?.meleeThreat) != null);
                    }
                    if (!flag && pawn != null && pawn != null && CamoUtility.IsTargetHidden(pawn, actor))
                    {
                        CamoAIUtility.CorrectJob(actor, pawn);
                    }
                }
                if (!thing.Spawned)
                {
                    curDriver.ReadyForNextToil();
                    return;
                }
                if (thing != actor.pather.Destination.Thing || (!actor.pather.Moving && !ReachabilityImmediate.CanReachImmediate(actor, thing, PathEndMode.Touch)))
                {
                    actor.pather.StartPath(thing, PathEndMode.Touch);
                    return;
                }
                if (ReachabilityImmediate.CanReachImmediate(actor, thing, PathEndMode.Touch))
                {
                    if (pawn != null && pawn.Downed && !curJob.killIncappedTarget)
                    {
                        curDriver.ReadyForNextToil();
                        return;
                    }
                    hitAction();
                }
            };
            followAndAttack.defaultCompleteMode = ToilCompleteMode.Never;
            __result = followAndAttack;
            return(false);
        }
        public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
        {
            Job result;

            if (!t.def.mineable)
            {
                result = null;
            }
            else if (pawn.Map.designationManager.DesignationAt(t.Position, DesignationDefOf.Mine) == null)
            {
                result = null;
            }
            else if (!pawn.CanReserve(t, 1, -1, null, false))
            {
                result = null;
            }
            else
            {
                bool flag = false;
                for (int i = 0; i < 8; i++)
                {
                    IntVec3 intVec = t.Position + GenAdj.AdjacentCells[i];
                    if (intVec.InBounds(pawn.Map) && intVec.Standable(pawn.Map) && ReachabilityImmediate.CanReachImmediate(intVec, t, pawn.Map, PathEndMode.Touch, pawn))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        IntVec3 intVec2 = t.Position + GenAdj.AdjacentCells[j];
                        if (intVec2.InBounds(t.Map))
                        {
                            if (ReachabilityImmediate.CanReachImmediate(intVec2, t, pawn.Map, PathEndMode.Touch, pawn))
                            {
                                if (intVec2.Walkable(t.Map) && !intVec2.Standable(t.Map))
                                {
                                    Thing        thing     = null;
                                    List <Thing> thingList = intVec2.GetThingList(t.Map);
                                    for (int k = 0; k < thingList.Count; k++)
                                    {
                                        if (thingList[k].def.designateHaulable && thingList[k].def.passability == Traversability.PassThroughOnly)
                                        {
                                            thing = thingList[k];
                                            break;
                                        }
                                    }
                                    if (thing != null)
                                    {
                                        Job job = HaulAIUtility.HaulAsideJobFor(pawn, thing);
                                        if (job != null)
                                        {
                                            return(job);
                                        }
                                        JobFailReason.Is(WorkGiver_Miner.NoPathTrans, null);
                                        return(null);
                                    }
                                }
                            }
                        }
                    }
                    JobFailReason.Is(WorkGiver_Miner.NoPathTrans, null);
                    result = null;
                }
                else
                {
                    result = new Job(JobDefOf.Mine, t, 1500, true);
                }
            }
            return(result);
        }
Beispiel #12
0
        public static bool CanReach(Reachability __instance, ref bool __result, IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams)
        {
            Map map = mapFieldRef(__instance);

            //if (working)
            //{
            //Log.ErrorOnce("Called CanReach() while working. This should never happen. Suppressing further errors.", 7312233);
            //return false;
            //}

            if (traverseParams.pawn != null)
            {
                if (!traverseParams.pawn.Spawned)
                {
                    __result = false;
                    return(false);
                }

                if (traverseParams.pawn.Map != map)
                {
                    Log.Error(string.Concat("Called CanReach() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=", traverseParams.pawn, " pawn.Map=", traverseParams.pawn.Map, " map=", map));
                    __result = false;
                    return(false);
                }
            }

            if (ReachabilityImmediate.CanReachImmediate(start, dest, map, peMode, traverseParams.pawn))
            {
                __result = true;
                return(false);
            }

            if (!dest.IsValid)
            {
                __result = false;
                return(false);
            }

            if (dest.HasThing && dest.Thing.Map != map)
            {
                __result = false;
                return(false);
            }

            if (!start.InBounds(map) || !dest.Cell.InBounds(map))
            {
                __result = false;
                return(false);
            }

            if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && traverseParams.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
            {
                Room room = RegionAndRoomQuery.RoomAtFast(start, map);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, map))
                {
                    __result = true;
                    return(false);
                }
            }

            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                TraverseParms traverseParams2 = traverseParams;
                traverseParams2.mode = TraverseMode.PassDoors;
                bool canReachResult = false;
                CanReach(__instance, ref canReachResult, start, dest, peMode, traverseParams2);
                if (canReachResult)
                {
                    __result = true;
                    return(false);
                }
            }

            dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(map), ref peMode);
            try
            {
                PathGrid   pathGrid   = map.pathGrid;
                RegionGrid regionGrid = map.regionGrid;

                destRegions.Clear();

                switch (peMode)
                {
                case PathEndMode.OnCell:
                {
                    Region region = dest.Cell.GetRegion(map);
                    if (region != null && region.Allows(traverseParams, isDestination: true))
                    {
                        destRegions.Add(region);
                    }
                    break;
                }

                case PathEndMode.Touch:
                    TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, map, destRegions);
                    break;
                }

                if (destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    __result = false;
                    return(false);
                }

                destRegions.RemoveDuplicates();
                regionsReached.Clear();
                openQueue.Clear();
                startingRegions.Clear();

                DetermineStartRegions(map, start, startingRegions, pathGrid, regionGrid, openQueue, regionsReached);
                if (openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    __result = false;
                    return(false);
                }

                if (startingRegions.Any() && destRegions.Any() && funcCanUseCache(__instance, traverseParams.mode))
                {
                    switch (GetCachedResult(__instance, traverseParams, startingRegions, destRegions))
                    {
                    case BoolUnknown.True:
                        __result = true;
                        return(false);

                    case BoolUnknown.False:
                        __result = false;
                        return(false);
                    }
                }
                if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater)
                {
                    bool result = funcCheckCellBasedReachability(__instance, start, dest, peMode, traverseParams);
                    __result = result;
                    return(false);
                }

                bool result2 = CheckRegionBasedReachability(__instance, traverseParams, openQueue, regionsReached, startingRegions, destRegions);
                __result = result2;
                return(false);
            }
            finally
            {
            }
        }
        // Verse.Verb
        // Token: 0x060022E2 RID: 8930 RVA: 0x000D4A4C File Offset: 0x000D2C4C
        public new bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine)
        {
            if (targ.HasThing && targ.Thing.Map != this.Caster.Map)
            {
                resultingLine = default(ShootLine);
                return(false);
            }
            if (this.verbProps.IsMeleeAttack || this.EffectiveRange <= 1.42f)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(ReachabilityImmediate.CanReachImmediate(root, targ, this.Caster.Map, PathEndMode.Touch, null));
            }
            CellRect cellRect = targ.HasThing ? targ.Thing.OccupiedRect() : CellRect.SingleCell(targ.Cell);
            float    num      = this.verbProps.EffectiveMinRange(targ, this.Caster);
            float    num2     = cellRect.ClosestDistSquaredTo(root);

            if (num2 > this.EffectiveRange * this.EffectiveRange || num2 < num * num)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(false);
            }
            if (!this.verbProps.requireLineOfSight)
            {
                resultingLine = new ShootLine(root, targ.Cell);
                return(true);
            }
            if (this.CasterIsPawn)
            {
                IntVec3 dest;
                if (this.CanHitFromCellIgnoringRange(root, targ, out dest))
                {
                    resultingLine = new ShootLine(root, dest);
                    return(true);
                }
                ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.Caster.Map, Verb_ShootCompMounted.tempLeanShootSources);
                for (int i = 0; i < Verb_ShootCompMounted.tempLeanShootSources.Count; i++)
                {
                    IntVec3 intVec = Verb_ShootCompMounted.tempLeanShootSources[i];
                    if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest))
                    {
                        resultingLine = new ShootLine(intVec, dest);
                        return(true);
                    }
                }
            }
            else
            {
                IntVec2 size = new IntVec2(Caster.def.size.x + 1, Caster.def.size.z + 1);
                foreach (IntVec3 intVec2 in GenAdj.OccupiedRect(Caster.Position, Caster.Rotation, size))
                {
                    IntVec3 dest;
                    if (this.CanHitFromCellIgnoringRange(intVec2, targ, out dest))
                    {
                        resultingLine = new ShootLine(intVec2, dest);
                        return(true);
                    }
                }
            }
            resultingLine = new ShootLine(root, targ.Cell);
            return(false);
        }