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); }
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); }
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); }
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)); }
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); }
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); }