public static IntVec3 InteractionCellWhenAt(ThingDef def, IntVec3 center, Rot4 rot, Map map) { if (def.hasInteractionCell) { IntVec3 b = def.interactionCellOffset.RotatedBy(rot); return(center + b); } if (def.Size.x == 1 && def.Size.z == 1) { for (int i = 0; i < 8; i++) { IntVec3 intVec = center + GenAdj.AdjacentCells[i]; if (intVec.Standable(map) && intVec.GetDoor(map) == null && ReachabilityImmediate.CanReachImmediate(intVec, center, map, PathEndMode.Touch, null)) { return(intVec); } } for (int j = 0; j < 8; j++) { IntVec3 intVec2 = center + GenAdj.AdjacentCells[j]; if (intVec2.Standable(map) && ReachabilityImmediate.CanReachImmediate(intVec2, center, map, PathEndMode.Touch, null)) { return(intVec2); } } for (int k = 0; k < 8; k++) { IntVec3 intVec3 = center + GenAdj.AdjacentCells[k]; if (intVec3.Walkable(map) && ReachabilityImmediate.CanReachImmediate(intVec3, center, map, PathEndMode.Touch, null)) { return(intVec3); } } return(center); } List <IntVec3> list = GenAdjFast.AdjacentCells8Way(center, rot, def.size); CellRect rect = GenAdj.OccupiedRect(center, rot, def.size); for (int l = 0; l < list.Count; l++) { if (list[l].Standable(map) && list[l].GetDoor(map) == null && ReachabilityImmediate.CanReachImmediate(list[l], rect, map, PathEndMode.Touch, null)) { return(list[l]); } } for (int m = 0; m < list.Count; m++) { if (list[m].Standable(map) && ReachabilityImmediate.CanReachImmediate(list[m], rect, map, PathEndMode.Touch, null)) { return(list[m]); } } for (int n = 0; n < list.Count; n++) { if (list[n].Walkable(map) && ReachabilityImmediate.CanReachImmediate(list[n], rect, map, PathEndMode.Touch, null)) { return(list[n]); } } return(center); }
public 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.verbProps.range <= 1.42f) { 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 = this.verbProps.EffectiveMinRange(targ, this.caster); float num2 = cellRect.ClosestDistSquaredTo(root); if (num2 > this.verbProps.range * this.verbProps.range || 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.tempLeanShootSources); for (int i = 0; i < Verb.tempLeanShootSources.Count; i++) { IntVec3 intVec = Verb.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); }
public bool CanReach(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams) { if (this.working) { Log.ErrorOnce("Called CanReach() while working. This should never happen. Suppressing further errors.", 7312233, false); return(false); } if (traverseParams.pawn != null) { if (!traverseParams.pawn.Spawned) { return(false); } if (traverseParams.pawn.Map != this.map) { Log.Error(string.Concat(new object[] { "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=", this.map }), false); return(false); } } if (ReachabilityImmediate.CanReachImmediate(start, dest, this.map, peMode, traverseParams.pawn)) { return(true); } if (!dest.IsValid) { return(false); } if (dest.HasThing && dest.Thing.Map != this.map) { return(false); } if (!start.InBounds(this.map) || !dest.Cell.InBounds(this.map)) { 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)) { return(true); } } if (traverseParams.mode == TraverseMode.PassAllDestroyableThings) { TraverseParms traverseParams2 = traverseParams; traverseParams2.mode = TraverseMode.PassDoors; if (this.CanReach(start, dest, peMode, traverseParams2)) { return(true); } } dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(this.map), ref peMode); this.working = true; bool result; try { this.pathGrid = this.map.pathGrid; this.regionGrid = this.map.regionGrid; this.reachedIndex += 1u; this.destRegions.Clear(); if (peMode == PathEndMode.OnCell) { Region region = dest.Cell.GetRegion(this.map, RegionType.Set_Passable); if (region != null && region.Allows(traverseParams, true)) { this.destRegions.Add(region); } } else if (peMode == PathEndMode.Touch) { TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, this.map, this.destRegions); } if (this.destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater) { this.FinalizeCheck(); result = false; } else { this.destRegions.RemoveDuplicates <Region>(); this.openQueue.Clear(); this.numRegionsOpened = 0; this.DetermineStartRegions(start); if (this.openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater) { this.FinalizeCheck(); result = false; } else { if (this.startingRegions.Any <Region>() && this.destRegions.Any <Region>() && this.CanUseCache(traverseParams.mode)) { BoolUnknown cachedResult = this.GetCachedResult(traverseParams); if (cachedResult == BoolUnknown.True) { this.FinalizeCheck(); return(true); } if (cachedResult == BoolUnknown.False) { this.FinalizeCheck(); return(false); } if (cachedResult != BoolUnknown.Unknown) { } } if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater) { bool flag = this.CheckCellBasedReachability(start, dest, peMode, traverseParams); this.FinalizeCheck(); result = flag; } else { bool flag2 = this.CheckRegionBasedReachability(traverseParams); this.FinalizeCheck(); result = flag2; } } } } finally { this.working = false; } return(result); }
private bool CheckCellBasedReachability(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams) { IntVec3 foundCell = IntVec3.Invalid; Region[] directRegionGrid = this.regionGrid.DirectGrid; PathGrid pathGrid = this.map.pathGrid; CellIndices cellIndices = this.map.cellIndices; this.map.floodFiller.FloodFill(start, delegate(IntVec3 c) { int num = cellIndices.CellToIndex(c); if ((traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater) && c.GetTerrain(this.map).IsWater) { return(false); } if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater) { if (!pathGrid.WalkableFast(num)) { Building edifice = c.GetEdifice(this.map); if (edifice == null || !PathFinder.IsDestroyable(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(num)) { return(false); } } Region region = directRegionGrid[num]; return(region == null || region.Allows(traverseParams, false)); }, delegate(IntVec3 c) { if (ReachabilityImmediate.CanReachImmediate(c, dest, this.map, peMode, traverseParams.pawn)) { foundCell = c; return(true); } return(false); }, int.MaxValue, false, null); if (foundCell.IsValid) { if (this.CanUseCache(traverseParams.mode)) { Region validRegionAt = this.regionGrid.GetValidRegionAt(foundCell); if (validRegionAt != null) { for (int i = 0; i < this.startingRegions.Count; i++) { this.cache.AddCachedResult(this.startingRegions[i].Room, validRegionAt.Room, traverseParams, true); } } } return(true); } if (this.CanUseCache(traverseParams.mode)) { for (int j = 0; j < this.startingRegions.Count; j++) { for (int k = 0; k < this.destRegions.Count; k++) { this.cache.AddCachedResult(this.startingRegions[j].Room, this.destRegions[k].Room, traverseParams, false); } } } return(false); }
public static bool CanReachImmediate(IntVec3 start, CellRect rect, Map map, PathEndMode peMode, Pawn pawn) { IntVec3 c = rect.ClosestCellTo(start); return(ReachabilityImmediate.CanReachImmediate(start, c, map, peMode, pawn)); }
public static bool CanReachImmediate(this Pawn pawn, LocalTargetInfo target, PathEndMode peMode) { return(pawn.Spawned && ReachabilityImmediate.CanReachImmediate(pawn.Position, target, pawn.Map, peMode, pawn)); }
public bool CanReach(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); } if (traverseParams.pawn != null) { if (!traverseParams.pawn.Spawned) { return(false); } if (traverseParams.pawn.Map != 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=" + traverseParams.pawn + " pawn.Map=" + traverseParams.pawn.Map + " map=" + map); return(false); } } if (ReachabilityImmediate.CanReachImmediate(start, dest, map, peMode, traverseParams.pawn)) { return(true); } if (!dest.IsValid) { return(false); } if (dest.HasThing && dest.Thing.Map != map) { return(false); } if (start.InBounds(map) && dest.Cell.InBounds(map)) { 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)) { return(true); } } if (traverseParams.mode == TraverseMode.PassAllDestroyableThings) { TraverseParms traverseParams2 = traverseParams; traverseParams2.mode = TraverseMode.PassDoors; if (CanReach(start, dest, peMode, traverseParams2)) { return(true); } } dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(map), ref peMode); working = true; try { pathGrid = map.pathGrid; regionGrid = map.regionGrid; reachedIndex++; 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) { FinalizeCheck(); return(false); } destRegions.RemoveDuplicates(); openQueue.Clear(); numRegionsOpened = 0; DetermineStartRegions(start); if (openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater) { FinalizeCheck(); return(false); } if (startingRegions.Any() && destRegions.Any() && CanUseCache(traverseParams.mode)) { switch (GetCachedResult(traverseParams)) { case BoolUnknown.True: FinalizeCheck(); return(true); case BoolUnknown.False: FinalizeCheck(); return(false); } } if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater) { bool result = CheckCellBasedReachability(start, dest, peMode, traverseParams); FinalizeCheck(); return(result); } bool result2 = CheckRegionBasedReachability(traverseParams); FinalizeCheck(); return(result2); } finally { working = false; } } return(false); }