public void Scan(List <Pawn> pawns, int range, int maxLinked) { rangeCache = range * range; IntVec3 parentPosition = owner.Position; linkedPawns.RemoveWhere(p => !p.Spawned || parentPosition.DistanceToSquared(p.Position) > rangeCache); if (linkedPawns.Count >= maxLinked) { return; } for (int i = 0; i < pawns.Count; i++) { Pawn pawn = pawns[i]; PawnLinkNetwork link = pawn.GetComp <CompPawnLink>()?.Link; if (link == null || network != link.network || owner == pawn) { continue; } int maxRange = Math.Max(rangeCache, link.rangeCache); if (parentPosition.DistanceToSquared(pawn.Position) <= maxRange) { if (linkedPawns.Add(pawn) && linkedPawns.Count >= maxLinked) { break; } } } }
private bool TryFindStartAndEndCells(Map map, out IntVec3 start, out IntVec3 end) { if (!RCellFinder.TryFindRandomPawnEntryCell(out start, map, CellFinder.EdgeRoadChance_Animal, (Predicate <IntVec3>)null)) { end = IntVec3.Invalid; return(false); } end = IntVec3.Invalid; int num = 0; while (num < 8) { IntVec3 startLocal = start; IntVec3 intVec = default(IntVec3); if (CellFinder.TryFindRandomEdgeCellWith((Predicate <IntVec3>)((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly)), map, CellFinder.EdgeRoadChance_Ignore, out intVec)) { if (!end.IsValid || intVec.DistanceToSquared(start) > end.DistanceToSquared(start)) { end = intVec; } num++; continue; } break; } return(end.IsValid); }
public static bool TryFindDirectFleeDestination(IntVec3 root, float dist, Pawn pawn, out IntVec3 result) { for (int i = 0; i < 30; i++) { result = root + IntVec3.FromVector3(Vector3Utility.HorizontalVectorFromAngle(Rand.Range(0, 360)) * dist); if (result.Walkable(pawn.Map) && result.DistanceToSquared(pawn.Position) < result.DistanceToSquared(root) && GenSight.LineOfSight(root, result, pawn.Map, skipFirstCell: true)) { return(true); } } Region region = pawn.GetRegion(); for (int j = 0; j < 30; j++) { IntVec3 randomCell = CellFinder.RandomRegionNear(region, 15, TraverseParms.For(pawn)).RandomCell; if (randomCell.Walkable(pawn.Map) && (float)(root - randomCell).LengthHorizontalSquared > dist * dist) { using (PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, randomCell, pawn)) { if (PawnPathUtility.TryFindCellAtIndex(path, (int)dist + 3, out result)) { return(true); } } } } result = pawn.Position; return(false); }
private bool TryFindStartAndEndCells(Map map, out IntVec3 start, out IntVec3 end) { bool result; if (!RCellFinder.TryFindRandomPawnEntryCell(out start, map, CellFinder.EdgeRoadChance_Animal, null)) { end = IntVec3.Invalid; result = false; } else { end = IntVec3.Invalid; for (int i = 0; i < 8; i++) { IntVec3 startLocal = start; IntVec3 intVec; if (!CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly), map, CellFinder.EdgeRoadChance_Ignore, out intVec)) { break; } if (!end.IsValid || intVec.DistanceToSquared(start) > end.DistanceToSquared(start)) { end = intVec; } } result = end.IsValid; } return(result); }
private int GetDistanceSquaredToExistingEdgeThing(IntVec3 cell, CellRect rect, ThingDef thingDef) { Map map = BaseGen.globalSettings.map; int num = 2147483647; foreach (IntVec3 edgeCell in rect.EdgeCells) { List <Thing> thingList = edgeCell.GetThingList(map); bool flag = false; int num2 = 0; while (num2 < thingList.Count) { if (thingList[num2].def != thingDef) { num2++; continue; } flag = true; break; } if (flag) { num = Mathf.Min(num, cell.DistanceToSquared(edgeCell)); } } return(num); }
public static bool TryFindDirectFleeDestination(IntVec3 root, float dist, Pawn pawn, out IntVec3 result) { for (int i = 0; i < 30; i++) { result = root + IntVec3.FromVector3(Vector3Utility.HorizontalVectorFromAngle((float)Rand.RangeSeeded(0, 360, Find.TickManager.TicksAbs + pawn.thingIDNumber)) * dist); if (result.Walkable(pawn.Map) && result.DistanceToSquared(pawn.Position) < result.DistanceToSquared(root) && GenSight.LineOfSight(root, result, pawn.Map, true, null, 0, 0)) { return(true); } } Region region = pawn.GetRegion(RegionType.Set_Passable); for (int j = 0; j < 30; j++) { Region region2 = CellFinder.RandomRegionNear(region, 15, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), null, null, RegionType.Set_Passable); IntVec3 randomCell = region2.RandomCell; if (randomCell.Walkable(pawn.Map) && (float)(root - randomCell).LengthHorizontalSquared > dist * dist) { using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, randomCell, pawn, PathEndMode.OnCell)) { if (PawnPathUtility.TryFindCellAtIndex(pawnPath, (int)dist + 3, out result)) { return(true); } } } } result = pawn.Position; return(false); }
private bool TryFindHiveSpawnCell(Map map, out IntVec3 spawnCell) { float num = -1f; IntVec3 intVec = IntVec3.Invalid; int num2 = 0; IntVec3 intVec2 = default(IntVec3); while (num2 < 3 && (from x in this.possibleSpawnCells where x.Standable(map) && x.GetFirstItem(map) == null && x.GetFirstBuilding(map) == null && x.GetFirstPawn(map) == null select x).TryRandomElement <IntVec3>(out intVec2)) { float num3 = -1f; for (int i = 0; i < this.spawnedHives.Count; i++) { float num4 = (float)intVec2.DistanceToSquared(this.spawnedHives[i].Position); if (num3 < 0.0 || num4 < num3) { num3 = num4; } } if (!intVec.IsValid || num3 > num) { intVec = intVec2; num = num3; } num2++; } spawnCell = intVec; return(spawnCell.IsValid); }
public static bool CheckForCollisionCallback(ProjectileCE projectile, IntVec3 cell, Thing launcher) { /* Check if an active shield can block this projectile, we don't check if the projectile flies overhead, as those projectiles don't call this function */ Map map = projectile.Map; Vector3 exactPosition = projectile.ExactPosition; IntVec3 origin = projectile.OriginIV3; getShields(map); foreach (Building building in shields) { var shield = building as Building_Shield; var generator = shield.GetComp <Comp_ShieldGenerator>(); bool isActive = generator.IsActive(); if (!isActive) { continue; } bool blockDirect = generator.BlockDirect_Active(); if (!blockDirect) { continue; } int fieldRadius = (int)generator.FieldRadius_Active(); int fieldRadiusSq = fieldRadius * fieldRadius; float DistanceSq = projectile.Position.DistanceToSquared(shield.Position) - fieldRadiusSq; float originDistanceSq = origin.DistanceToSquared(shield.Position) - fieldRadiusSq; if (DistanceSq > 0) { continue; } if (originDistanceSq < 0) { continue; } Vector3 shieldPosition2D = new Vector3(shield.Position.x, 0, shield.Position.z); Quaternion targetAngle = projectile.ExactRotation; Quaternion shieldProjAng = Quaternion.LookRotation(exactPosition - shieldPosition2D); if ((Quaternion.Angle(targetAngle, shieldProjAng) > 90)) { HitSoundDef.PlayOneShot((SoundInfo) new TargetInfo(shield.Position, map, false)); int damage = (projectile.def.projectile.GetDamageAmount(launcher)); generator.FieldIntegrity_Current -= damage; exactPosition = getExactPosition(origin.ToVector3(), projectile.ExactPosition, shield.Position.ToVector3(), (fieldRadius - 1) * (fieldRadius - 1)); MoteMaker.ThrowLightningGlow(exactPosition, map, 0.5f); projectile.ExactPosition = exactPosition; return(true); } } return(false); }
public static IntVec3 RandomWanderDestFor(Pawn pawn, IntVec3 root, float radius, Func <Pawn, IntVec3, bool> validator, Danger maxDanger) { if (radius > 12.0) { Log.Warning("wanderRadius of " + radius + " is greater than Region.GridSize of " + 12 + " and will break."); } bool flag = UnityData.isDebugBuild && DebugViewSettings.drawDestSearch; if (root.GetRegion(pawn.Map, RegionType.Set_Passable) != null) { int maxRegions = Mathf.Max((int)radius / 3, 13); CellFinder.AllRegionsNear(RCellFinder.regions, root.GetRegion(pawn.Map, RegionType.Set_Passable), maxRegions, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), (Region reg) => reg.extentsClose.ClosestDistSquaredTo(root) <= radius * radius, null, RegionType.Set_Passable); if (flag) { pawn.Map.debugDrawer.FlashCell(root, 0.6f, "root", 50); } if (RCellFinder.regions.Count > 0) { for (int i = 0; i < 35; i++) { IntVec3 randomCell = RCellFinder.regions.RandomElementByWeight((Region reg) => (float)reg.CellCount).RandomCell; if ((float)randomCell.DistanceToSquared(root) > radius * radius) { if (flag) { pawn.Map.debugDrawer.FlashCell(randomCell, 0.32f, "distance", 50); } continue; } if (!RCellFinder.CanWanderToCell(randomCell, pawn, root, validator, i, maxDanger)) { if (flag) { pawn.Map.debugDrawer.FlashCell(randomCell, 0.6f, "validation", 50); } continue; } if (flag) { pawn.Map.debugDrawer.FlashCell(randomCell, 0.9f, "go!", 50); } return(randomCell); } } } IntVec3 position = default(IntVec3); if (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 20, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 30, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position) && !CellFinder.TryFindRandomCellNear(pawn.Position, pawn.Map, 5, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position)) { position = pawn.Position; } if (flag) { pawn.Map.debugDrawer.FlashCell(position, 0.4f, "fallback", 50); } return(position); }
private List <Plant> GetValidForagingTargetsSorted() { IntVec3 position = manager.map.GetBaseCenter(); return(manager.map.listerThings.AllThings .Where(IsValidForagingTarget) // OrderBy defaults to ascending, switch sign on current yield to get descending .Select(p => p as Plant) .OrderBy(p => - p.YieldNow() / (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2)) .ToList()); }
public static IntVec3 BestCarnivalSetupPosition(IntVec3 initPos, Map map) { IntVec3 averageColPos; if (!(averageColPos = CellsUtil.ApproxClosestColonistBuilding(map, initPos, ThingDefOf.Door)).IsValid && !(averageColPos = CellsUtil.ApproxClosestColonistBuilding(map, initPos, ThingDefOf.Wall)).IsValid) { averageColPos = AverageColPos; } else { averageColPos = averageColPos.AverageWith(AverageColPos); } var distSqrdToColony = initPos.DistanceToSquared(averageColPos); if (Prefs.DevMode) { Log.Message("[Carnivale] setupSpot: initPos=" + initPos + ", averageColPos=" + averageColPos + ", distSqrdToColony=" + distSqrdToColony); } var result = initPos; if (!TryCarnivalSetupPosition_Triangular(initPos, averageColPos, distSqrdToColony, map, out result)) { if (Prefs.DevMode) { Log.Warning("\t[Carnivale] setupSpot: triangular algorithm failed. Using old random iteration algorithm."); } TryCarnivalSetupPosition_Random(initPos, averageColPos, 7, map, out result); } if (Prefs.DevMode) { if (result == initPos) { Log.Error(string.Concat(new object[] { "[Carnivale] Could not find carnival setup spot from ", initPos, ", expect more errors. Using ", initPos })); } Log.Message("[Carnivale] setupSpot: final pass: "******". distToColony=" + result.DistanceTo(averageColPos)); map.debugDrawer.FlashCell(result, 0.5f, "Setup Spot"); } return(result); }
public static bool ProcessEquidistantCells( IntVec3 center, float radius, Func <List <IntVec3>, bool> processor, Map map = null) { //if (GenRadial.working) //{ //Log.Error("Nested calls to ProcessEquidistantCells() are not allowed.", false); //} //else //{ //GenRadial.tmpCells.Clear(); List <IntVec3> tmpCells = new List <IntVec3>(); //GenRadial.working = true; try { float num1 = -1f; int num2 = GenRadial.NumCellsInRadius(radius); for (int index = 0; index < num2; ++index) { IntVec3 intVec3 = center + GenRadial.RadialPattern[index]; if (map == null || intVec3.InBounds(map)) { float squared = (float)intVec3.DistanceToSquared(center); if ((double)Mathf.Abs(squared - num1) > 9.99999974737875E-05) { if (tmpCells.Any <IntVec3>() && processor(tmpCells)) { return(false); } num1 = squared; tmpCells.Clear(); } tmpCells.Add(intVec3); } } if (!tmpCells.Any <IntVec3>()) { return(false); } int num3 = processor(tmpCells) ? 1 : 0; } finally { //GenRadial.tmpCells.Clear(); //GenRadial.working = false; } //} return(false); }
public virtual float Distance( Thing target, IntVec3 source ) { if ( PathBasedDistance ) { var path = target.Map.pathFinder.FindPath( source, target, TraverseParms.For( TraverseMode.PassDoors, Danger.Some ), PathEndMode.Touch ); var cost = path.Found ? path.TotalCost : int.MaxValue; path.ReleaseToPool(); return cost * 2; } return Mathf.Sqrt( source.DistanceToSquared( target.Position ) ) * 2; }
public static Dictionary <ThingDef, float> CalculateDistancesToNearbyClusters2(WildPlantSpawner __instance, IntVec3 c) { Map map2 = map(__instance); //nearbyClusters.Clear(); //nearbyClustersList.Clear(); Dictionary <ThingDef, List <float> > nearbyClusters = new Dictionary <ThingDef, List <float> >(); List <KeyValuePair <ThingDef, List <float> > > nearbyClustersList = new List <KeyValuePair <ThingDef, List <float> > >(); int num = GenRadial.NumCellsInRadius(map2.Biome.MaxWildAndCavePlantsClusterRadius * 2); for (int i = 0; i < num; i++) { IntVec3 intVec = c + GenRadial.RadialPattern[i]; if (!intVec.InBounds(map2)) { continue; } List <Thing> list = map2.thingGrid.ThingsListAtFast(intVec); for (int j = 0; j < list.Count; j++) { Thing thing = list[j]; if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters) { float item = intVec.DistanceToSquared(c); if (!nearbyClusters.TryGetValue(thing.def, out List <float> value)) { value = new List <float>(); //SimplePool<List<float>>.Get(); nearbyClusters.Add(thing.def, value); nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, value)); } value.Add(item); } } } //distanceSqToNearbyClusters.Clear(); Dictionary <ThingDef, float> distanceSqToNearbyClusters = new Dictionary <ThingDef, float>(); for (int k = 0; k < nearbyClustersList.Count; k++) { List <float> value2 = nearbyClustersList[k].Value; value2.Sort(); distanceSqToNearbyClusters.Add(nearbyClustersList[k].Key, value2[value2.Count / 2]); value2.Clear(); SimplePool <List <float> > .Return(value2); } return(distanceSqToNearbyClusters); }
private static void PrintAvoidGridAroundTrapLoc(Building b, ByteGrid avoidGrid) { Room room = b.Position.GetRoom(b.Map, RegionType.Set_Passable); for (int i = 0; i < AvoidGridMaker.TrapRadialCells; i++) { IntVec3 intVec = b.Position + GenRadial.RadialPattern[i]; if (intVec.InBounds(b.Map) && intVec.Walkable(b.Map) && intVec.GetRoom(b.Map, RegionType.Set_Passable) == room) { float num = (float)Mathf.Max(1, intVec.DistanceToSquared(b.Position)); int num2 = Mathf.Max(1, Mathf.RoundToInt(80f / num)); AvoidGridMaker.IncrementAvoidGrid(avoidGrid, intVec, num2); } } }
private static void PrintAvoidGridAroundTrapLoc(TrapMemory mem, ByteGrid avoidGrid) { Room room = mem.Cell.GetRoom(mem.map, RegionType.Set_Passable); for (int i = 0; i < AvoidGridMaker.TrapRadialCells; i++) { IntVec3 intVec = mem.Cell + GenRadial.RadialPattern[i]; if (intVec.InBounds(mem.map) && intVec.Walkable(mem.map) && intVec.GetRoom(mem.map, RegionType.Set_Passable) == room) { float num = (float)Mathf.Max(1, intVec.DistanceToSquared(mem.Cell)); int num2 = Mathf.Max(1, Mathf.RoundToInt((float)(32.0 * mem.PowerPercent / num))); AvoidGridMaker.IncrementAvoidGrid(avoidGrid, intVec, num2); } } }
private List <Plant> GetLoggableTreesSorted() { IntVec3 position = manager.map.GetBaseCenter(); // get a list of trees that are not designated in the logging grounds and are reachable, sorted by yield / distance * 2 List <Plant> list = manager.map.listerThings.AllThings.Where(IsValidForestryTarget) // OrderBy defaults to ascending, switch sign on current yield to get descending .Select(p => p as Plant) .OrderBy(p => - p.YieldNow() / (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2)) .ToList(); return(list); }
protected override Job TryGiveJob(Pawn pawn) { IntVec3 intVec = (IntVec3)pawn.mindState.duty.focus; if (intVec.IsValid) { if ((float)intVec.DistanceToSquared(pawn.Position) < 100f && intVec.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable)) { pawn.GetLord().Notify_ReachedDutyLocation(pawn); return(null); } } if (!intVec.IsValid) { IAttackTarget attackTarget; if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn) where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings) select x).TryRandomElement(out attackTarget)) { return(null); } intVec = attackTarget.Thing.Position; } Job result; if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)) { result = null; } else { using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell)) { IntVec3 cellBeforeBlocker; Thing thing = pawnPath.FirstBlockingBuilding(out cellBeforeBlocker, pawn); if (thing != null) { Job job = DigUtility.PassBlockerJob(pawn, thing, cellBeforeBlocker, this.canMineMineables, this.canMineNonMineables); if (job != null) { return(job); } } } result = new Job(JobDefOf.Goto, intVec, 500, true); } return(result); }
private List <Pawn> GetHuntableAnimalsSorted() { // get the 'home' position IntVec3 position = manager.map.GetBaseCenter(); // get a list of alive animals that are not designated in the hunting grounds and are reachable, sorted by meat / distance * 2 List <Pawn> list = manager.map.mapPawns.AllPawns.Where(p => IsValidHuntingTarget(p)) // OrderBy defaults to ascending, switch sign on estimated meat count to get descending .OrderBy( p => - p.EstimatedMeatCount() / (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2)).ToList(); return(list); }
private static IntVec3 TryFindEndCell(Map map, List <Pawn> generatedPawns, out IntVec3 end) { end = IntVec3.Invalid; for (int i = 0; i < 8; i++) { IntVec3 intVec3 = generatedPawns[index : i].Position; if (!CellFinder.TryFindRandomEdgeCellWith(validator: (IntVec3 x) => map.reachability.CanReach(start: intVec3, dest: x, peMode: PathEndMode.OnCell, traverseMode: TraverseMode.NoPassClosedDoors, maxDanger: Danger.Deadly), map: map, roadChance: CellFinder.EdgeRoadChance_Ignore, result: out IntVec3 intVec)) { break; } if (!end.IsValid || intVec.DistanceToSquared(b: intVec3) > end.DistanceToSquared(b: intVec3)) { end = intVec; } } return(end); }
private void CalculateDistancesToNearbyClusters(IntVec3 c) { WildPlantSpawner.nearbyClusters.Clear(); WildPlantSpawner.nearbyClustersList.Clear(); int num = GenRadial.NumCellsInRadius((float)(this.map.Biome.MaxWildAndCavePlantsClusterRadius * 2)); for (int i = 0; i < num; i++) { IntVec3 intVec = c + GenRadial.RadialPattern[i]; if (intVec.InBounds(this.map)) { List <Thing> list = this.map.thingGrid.ThingsListAtFast(intVec); for (int j = 0; j < list.Count; j++) { Thing thing = list[j]; if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters) { float item = (float)intVec.DistanceToSquared(c); List <float> list2; if (!WildPlantSpawner.nearbyClusters.TryGetValue(thing.def, out list2)) { list2 = SimplePool <List <float> > .Get(); WildPlantSpawner.nearbyClusters.Add(thing.def, list2); WildPlantSpawner.nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, list2)); } list2.Add(item); } } } } WildPlantSpawner.distanceSqToNearbyClusters.Clear(); for (int k = 0; k < WildPlantSpawner.nearbyClustersList.Count; k++) { List <float> value = WildPlantSpawner.nearbyClustersList[k].Value; value.Sort(); WildPlantSpawner.distanceSqToNearbyClusters.Add(WildPlantSpawner.nearbyClustersList[k].Key, value[value.Count / 2]); value.Clear(); SimplePool <List <float> > .Return(value); } }
private void CalculateDistancesToNearbyClusters(IntVec3 c) { nearbyClusters.Clear(); nearbyClustersList.Clear(); int num = GenRadial.NumCellsInRadius(map.Biome.MaxWildAndCavePlantsClusterRadius * 2); for (int i = 0; i < num; i++) { IntVec3 intVec = c + GenRadial.RadialPattern[i]; if (!intVec.InBounds(map)) { continue; } List <Thing> list = map.thingGrid.ThingsListAtFast(intVec); for (int j = 0; j < list.Count; j++) { Thing thing = list[j]; if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters) { float item = intVec.DistanceToSquared(c); if (!nearbyClusters.TryGetValue(thing.def, out var value)) { value = SimplePool <List <float> > .Get(); nearbyClusters.Add(thing.def, value); nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, value)); } value.Add(item); } } } distanceSqToNearbyClusters.Clear(); for (int k = 0; k < nearbyClustersList.Count; k++) { List <float> value2 = nearbyClustersList[k].Value; value2.Sort(); distanceSqToNearbyClusters.Add(nearbyClustersList[k].Key, value2[value2.Count / 2]); value2.Clear(); SimplePool <List <float> > .Return(value2); } }
protected override Job TryGiveJob(Pawn pawn) { IntVec3 vector = (IntVec3)pawn.mindState.duty.focus; if (vector.IsValid && (float)vector.DistanceToSquared(pawn.Position) < 100 && vector.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && vector.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable)) { pawn.GetLord().Notify_ReachedDutyLocation(pawn); return(null); } if (!vector.IsValid) { IAttackTarget attackTarget; if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn) where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings) select x).TryRandomElement(out attackTarget)) { return(null); } vector = attackTarget.Thing.Position; } if (!pawn.CanReach(vector, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)) { return(null); } using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, vector, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell)) { IntVec3 cellBeforeBlocker; Thing thing = pawnPath.FirstTangleweed(out cellBeforeBlocker, pawn); if (thing != null) { Job job = AttackPlantUtility.AttackPlant(pawn, thing); if (job != null) { return(job); } } } return(new Job(JobDefOf.Goto, vector, 500, true)); }
public static bool TryFindStartAndEndCells(this IncidentWorker_HerdMigration hm, Map map, PawnKindDef kind, out IntVec3 start, out IntVec3 end) { if (!RCellFinderExtended.TryFindRandomPawnEntryCell(out start, map, kind, CellFinder.EdgeRoadChance_Animal)) { end = IntVec3.Invalid; return(false); } end = IntVec3.Invalid; for (int i = 0; i < 8; i++) { IntVec3 startLocal = start; if (!CellFinderExtended.TryFindRandomEdgeCellWith((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly), map, kind, CellFinder.EdgeRoadChance_Ignore, out IntVec3 result)) { break; } if (!end.IsValid || result.DistanceToSquared(start) > end.DistanceToSquared(start)) { end = result; } } return(end.IsValid); }
protected override Job TryGiveJob(Pawn pawn) { IntVec3 intVec = pawn.mindState.duty.focus.Cell; if (intVec.IsValid && (float)intVec.DistanceToSquared(pawn.Position) < 100f && intVec.GetRoom(pawn.Map) == pawn.GetRoom() && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors)) { pawn.GetLord().Notify_ReachedDutyLocation(pawn); return(null); } if (!intVec.IsValid) { if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn) where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, canBash: false, TraverseMode.PassAllDestroyableThings) select x).TryRandomElement(out var result)) { return(null); } intVec = result.Thing.Position; } if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, canBash: false, TraverseMode.PassAllDestroyableThings)) { return(null); } using (PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings))) { IntVec3 cellBefore; Thing thing = path.FirstBlockingBuilding(out cellBefore, pawn); if (thing != null) { Job job = DigUtility.PassBlockerJob(pawn, thing, cellBefore, canMineMineables, canMineNonMineables); if (job != null) { return(job); } } } return(JobMaker.MakeJob(JobDefOf.Goto, intVec, 500, checkOverrideOnExpiry: true)); }
private static bool Distance(Thing target, IntVec3 source, out float dist) { dist = float.MaxValue; var pathFinder = target?.MapHeld?.pathFinder; if (pathFinder == null) { return(false); } if (Settings.opportunisticTakeTool_calcPath) { var path = pathFinder.FindPath(source, target, TraverseParms.For(TraverseMode.PassDoors, Danger.Some), PathEndMode.Touch); bool found = path.Found; if (found) { dist = path.TotalCost * 2; } path.ReleaseToPool(); return(found); } dist = Mathf.Sqrt(source.DistanceToSquared(target.PositionHeld)) * 2; return(true); }
private int GetDistanceSquaredToExistingEdgeThing(IntVec3 cell, CellRect rect, ThingDef thingDef) { Map map = BaseGen.globalSettings.map; int num = 2147483647; foreach (IntVec3 current in rect.EdgeCells) { List <Thing> thingList = current.GetThingList(map); bool flag = false; for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == thingDef) { flag = true; break; } } if (flag) { num = Mathf.Min(num, cell.DistanceToSquared(current)); } } return(num); }
private static bool IsSafeDropSpot(IntVec3 cell, Map map, Faction faction, IntVec2?size = null, int distToEdge = 25, int distToHostiles = 35, int distToFires = 15) { Faction factionBaseFaction = map.ParentFaction ?? Faction.OfPlayer; if (size.HasValue) { foreach (IntVec3 item in GenAdj.OccupiedRect(cell, Rot4.North, size.Value)) { if (!IsGoodDropSpot(item, map, allowFogged: false, canRoofPunch: false, allowIndoors: false)) { return(false); } } } else if (!IsGoodDropSpot(cell, map, allowFogged: false, canRoofPunch: false, allowIndoors: false)) { return(false); } if (distToEdge > 0 && cell.CloseToEdge(map, distToEdge)) { return(false); } if (faction != null) { foreach (IAttackTarget item2 in map.attackTargetsCache.TargetsHostileToFaction(faction)) { if (!item2.ThreatDisabled(null) && item2.Thing.Position.InHorDistOf(cell, distToHostiles)) { return(false); } } } if (!map.reachability.CanReachFactionBase(cell, factionBaseFaction)) { return(false); } if (size.HasValue) { foreach (IntVec3 cell2 in CellRect.CenteredOn(cell, size.Value.x, size.Value.z).Cells) { if (CellHasCrops(cell2)) { return(false); } } } else if (CellHasCrops(cell)) { return(false); } float minDistToFiresSq = distToFires * distToFires; float closestDistSq = float.MaxValue; int firesCount = 0; RegionTraverser.BreadthFirstTraverse(cell, map, (Region from, Region to) => true, delegate(Region x) { List <Thing> list = x.ListerThings.ThingsInGroup(ThingRequestGroup.Fire); for (int i = 0; i < list.Count; i++) { float num = cell.DistanceToSquared(list[i].Position); if (!(num > minDistToFiresSq)) { if (num < closestDistSq) { closestDistSq = num; } firesCount++; } } return(closestDistSq <= minDistToFiresSq && firesCount >= 5); }, 15); if (closestDistSq <= minDistToFiresSq && firesCount >= 5) { return(false); } return(true); bool CellHasCrops(IntVec3 c) { Plant plant = c.GetPlant(map); if (plant != null && plant.sown) { return(map.zoneManager.ZoneAt(c) is Zone_Growing); } return(false); } }
public static bool RandomWanderDestFor(ref IntVec3 __result, Pawn pawn, IntVec3 root, float radius, Func <Pawn, IntVec3, IntVec3, bool> validator, Danger maxDanger) { if ((double)radius > 12.0) { Log.Warning("wanderRadius of " + (object)radius + " is greater than Region.GridSize of " + (object)12 + " and will break.", false); } bool flag = false; if (root.GetRegion(pawn.Map, RegionType.Set_Passable) != null) { int maxRegions = Mathf.Max((int)radius / 3, 13); List <Region> regions = new List <Region>(); CellFinder.AllRegionsNear(regions, root.GetRegion(pawn.Map, RegionType.Set_Passable), maxRegions, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), (Predicate <Region>)(reg => (double)reg.extentsClose.ClosestDistSquaredTo(root) <= (double)radius * (double)radius), (Pawn)null, RegionType.Set_Passable); if (flag) { pawn.Map.debugDrawer.FlashCell(root, 0.6f, nameof(root), 50); } if (regions.Count > 0) { for (int tryIndex = 0; tryIndex < 35; ++tryIndex) { IntVec3 c = IntVec3.Invalid; for (int index = 0; index < 5; ++index) { IntVec3 randomCell = regions.RandomElementByWeight <Region>((Func <Region, float>)(reg => (float)reg.CellCount)).RandomCell; if ((double)randomCell.DistanceToSquared(root) <= (double)radius * (double)radius) { c = randomCell; break; } } if (!c.IsValid) { if (flag) { pawn.Map.debugDrawer.FlashCell(c, 0.32f, "distance", 50); } } else if (!(bool)CanWanderToCell.Invoke(null, new object[] { c, pawn, root, validator, tryIndex, maxDanger })) { if (flag) { pawn.Map.debugDrawer.FlashCell(c, 0.6f, "validation", 50); } } else { if (flag) { pawn.Map.debugDrawer.FlashCell(c, 0.9f, "go!", 50); } regions.Clear(); __result = c; return(false); } } } regions.Clear(); } IntVec3 result; if (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c => { if (!c.InBounds(pawn.Map) || !pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) || c.IsForbidden(pawn)) { return(false); } return(validator == null || validator(pawn, c, root)); }), out result, -1) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out result, -1) && (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 20, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out result, -1)) && (!CellFinder.TryFindRandomCellNear(root, pawn.Map, 30, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1) && !CellFinder.TryFindRandomCellNear(pawn.Position, pawn.Map, 5, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1))) { result = pawn.Position; } if (flag) { pawn.Map.debugDrawer.FlashCell(result, 0.4f, "fallback", 50); } __result = result; return(false); }
/// <summary> /// Checks whether a collision occurs along flight path within this cell. /// </summary> /// <param name="cell">Where to check for collisions in</param> /// <returns>True if collision occured, false otherwise</returns> private bool CheckCellForCollision(IntVec3 cell) { if (BlockerRegistry.CheckCellForCollisionCallback(this, cell, launcher)) { this.ticksToImpact = 0; this.landed = true; this.Impact(null); return(true); } var roofChecked = false; var justWallsRoofs = false; //Check for minimum PAWN collision distance float distFromOrigin = cell.DistanceToSquared(OriginIV3); bool skipCollision = !def.projectile.alwaysFreeIntercept && (minCollisionSqr <= 1f ? distFromOrigin < 1f : distFromOrigin <= Mathf.Min(144f, minCollisionSqr / 4)); var mainThingList = new List <Thing>(Map.thingGrid.ThingsListAtFast(cell)) .Where(t => justWallsRoofs ? t.def.Fillage == FillCategory.Full : (t is Pawn || t.def.Fillage != FillCategory.None)).ToList(); //Find pawns in adjacent cells and append them to main list if (!justWallsRoofs) { var adjList = new List <IntVec3>(); adjList.AddRange(GenAdj.CellsAdjacentCardinal(cell, Rot4.FromAngleFlat(shotRotation), new IntVec2(collisionCheckSize, 0)).ToList()); //Iterate through adjacent cells and find all the pawns foreach (var curCell in adjList) { if (curCell != cell && curCell.InBounds(Map)) { mainThingList.AddRange(Map.thingGrid.ThingsListAtFast(curCell) .Where(x => x is Pawn)); if (Controller.settings.DebugDrawInterceptChecks) { Map.debugDrawer.FlashCell(curCell, 0.7f); } } } } //If the last position is above the wallCollisionHeight, we should check for roof intersections first if (LastPos.y > CollisionVertical.WallCollisionHeight) { if (TryCollideWithRoof(cell)) { return(true); } roofChecked = true; } foreach (var thing in mainThingList.Distinct().OrderBy(x => (x.DrawPos - LastPos).sqrMagnitude)) { if ((thing == launcher || thing == mount) && !canTargetSelf) { continue; } // Check for collision if ((!skipCollision || thing == intendedTarget) && TryCollideWith(thing)) { return(true); } // Apply suppression. The height here is NOT that of the bullet in CELL, // it is the height at the END OF THE PATH. This is because SuppressionRadius // is not considered an EXACT limit. if (!justWallsRoofs && ExactPosition.y < SuppressionRadius) { var pawn = thing as Pawn; if (pawn != null) { ApplySuppression(pawn); } } } //Finally check for intersecting with a roof (again). if (!roofChecked && TryCollideWithRoof(cell)) { return(true); } return(false); }