public List <Thing> ThingsOfDef(ThingDef def) { return(this.ThingsMatching(ThingRequest.ForDef(def))); }
public List <Thing> ThingsInGroup(ThingRequestGroup group) { return(this.ThingsMatching(ThingRequest.ForGroup(group))); }
public static Thing ClosestThing_Regionwise_ReachablePrioritized(IntVec3 root, Map map, ThingRequest thingReq, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null, Func <Thing, float> priorityGetter = null, int minRegions = 24, int maxRegions = 30) { if (!thingReq.IsUndefined && !thingReq.CanBeFoundInRegion) { Log.ErrorOnce("ClosestThing_Regionwise_ReachablePrioritized with thing request group " + thingReq.group + ". This will never find anything because this group is never stored in regions. Most likely a global search should have been used.", 738476712); return(null); } if (EarlyOutSearch(root, map, thingReq, null, validator)) { return(null); } if (maxRegions < minRegions) { Log.ErrorOnce("maxRegions < minRegions", 754343); } Thing result = null; if (!thingReq.IsUndefined) { result = RegionwiseBFSWorker(root, map, thingReq, peMode, traverseParams, validator, priorityGetter, minRegions, maxRegions, maxDistance, out int _); } return(result); }
public static Thing RegionwiseBFSWorker(IntVec3 root, Map map, ThingRequest req, PathEndMode peMode, TraverseParms traverseParams, Predicate <Thing> validator, Func <Thing, float> priorityGetter, int minRegions, int maxRegions, float maxDistance, out int regionsSeen, RegionType traversableRegionTypes = RegionType.Set_Passable, bool ignoreEntirelyForbiddenRegions = false) { regionsSeen = 0; if (traverseParams.mode == TraverseMode.PassAllDestroyableThings) { Log.Error("RegionwiseBFSWorker with traverseParams.mode PassAllDestroyableThings. Use ClosestThingGlobal."); return(null); } if (traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater) { Log.Error("RegionwiseBFSWorker with traverseParams.mode PassAllDestroyableThingsNotWater. Use ClosestThingGlobal."); return(null); } if (!req.IsUndefined && !req.CanBeFoundInRegion) { Log.ErrorOnce("RegionwiseBFSWorker with thing request group " + req.group + ". This group is never stored in regions. Most likely a global search should have been used.", 385766189); return(null); } Region region = root.GetRegion(map, traversableRegionTypes); if (region == null) { return(null); } float maxDistSquared = maxDistance * maxDistance; RegionEntryPredicate entryCondition = delegate(Region from, Region to) { if (!to.Allows(traverseParams, isDestination: false)) { return(false); } return(maxDistance > 5000f || to.extentsClose.ClosestDistSquaredTo(root) < maxDistSquared); }; Thing closestThing = null; float closestDistSquared = 9999999f; float bestPrio = -3.40282347E+38f; int regionsSeenScan = 0; RegionProcessor regionProcessor = delegate(Region r) { if (RegionTraverser.ShouldCountRegion(r)) { regionsSeenScan++; } if (!r.IsDoorway && !r.Allows(traverseParams, isDestination: true)) { return(false); } if (!ignoreEntirelyForbiddenRegions || !r.IsForbiddenEntirely(traverseParams.pawn)) { List <Thing> list = r.ListerThings.ThingsMatching(req); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, peMode, traverseParams.pawn)) { float num = (priorityGetter == null) ? 0f : priorityGetter(thing); if (!(num < bestPrio)) { float num2 = (float)(thing.Position - root).LengthHorizontalSquared; if ((num > bestPrio || num2 < closestDistSquared) && num2 < maxDistSquared && (validator == null || validator(thing))) { closestThing = thing; closestDistSquared = num2; bestPrio = num; } } } } } return(regionsSeenScan >= minRegions && closestThing != null); }; RegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, maxRegions, traversableRegionTypes); regionsSeen = regionsSeenScan; return(closestThing); }
public static Thing ClosestThing_Regionwise_ReachablePrioritized(IntVec3 root, Map map, ThingRequest thingReq, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null, Func <Thing, float> priorityGetter = null, int minRegions = 24, int maxRegions = 30) { if (GenClosest.EarlyOutSearch(root, map, thingReq, null)) { return(null); } if (maxRegions < minRegions) { Log.ErrorOnce("maxRegions < minRegions", 754343); } Thing result = null; if (!thingReq.IsUndefined) { result = GenClosest.RegionwiseBFSWorker(root, map, thingReq, peMode, traverseParams, validator, priorityGetter, minRegions, maxRegions, maxDistance, RegionType.Set_Passable, false); } return(result); }
/// <summary> Update the graphic if the life stage changed and swap the body graphic if moving </summary> public override void Tick() { base.Tick(); if (GenTicks.TicksAbs % Frameskip != FrameskipOffset) { return; // frameskip } if (!Spawned) { return; } if (Destroyed) { return; } if (pather == null) { return; // this can occur if the pawn leaves the map area } if (Drawer?.renderer == null) { return; } // initialize the replacement graphics (once per lifestage) if (lifeStageBefore != ageTracker.CurKindLifeStage) { SetupReplacements(); lifeStageBefore = ageTracker.CurKindLifeStage; } // avoid hunting tamed animals, accept non-ideal food instead if (Faction != Faction.OfPlayer && jobs?.curJob?.def == JobDefOf.PredatorHunt) { if ((jobs.curJob.targetA.Thing as Pawn)?.Faction == Faction.OfPlayer) { jobs.StopAll(); // stop predator hunt job if (needs.food.TicksStarving < 30000) { // find food var food = GenClosest.ClosestThingReachable(Position, Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), AI.PathEndMode.OnCell, TraverseParms.For(this, Danger.Deadly, TraverseMode.ByPawn, false), maxDistance: 100f, validator: (thing) => thing.def.category == ThingCategory.Item && thing.def.IsNutritionGivingIngestible /*&& RaceProps.CanEverEat(thing)*/, // omit food preferences customGlobalSearchSet: null, searchRegionsMax: -1, forceAllowGlobalSearch: false); if (food != null) { // try to find other food jobs.StartJob(new AI.Job(JobDefOf.Ingest, food)); } else { // wander until food is found or too starving to continue StartJobWander(); } } else // if desperate { IntVec3 exit_dest; if (RCellFinder.TryFindBestExitSpot(this, out exit_dest, TraverseMode.ByPawn)) { // exit map jobs.StartJob(new AI.Job(JobDefOf.Goto, exit_dest) { exitMapOnArrival = true }); } else { // fallback to wandering StartJobWander(); } } } } // attempt to find a replacement graphic foreach (var replacement in replacements) { if (replacement.TryReplace(Drawer.renderer)) { break; // break on first successful replacement } } }