예제 #1
0
        public static Thing ClosestThingReachable(IntVec3 root, Map map, ThingRequest thingReq, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null, IEnumerable <Thing> customGlobalSearchSet = null, int searchRegionsMin = 0, int searchRegionsMax = -1, bool forceGlobalSearch = false, RegionType traversableRegionTypes = RegionType.Set_Passable, bool ignoreEntirelyForbiddenRegions = false)
        {
            if (searchRegionsMax > 0 && customGlobalSearchSet != null && !forceGlobalSearch)
            {
                Log.ErrorOnce("searchRegionsMax > 0 && customGlobalSearchSet != null && !forceGlobalSearch. customGlobalSearchSet will never be used.", 634984);
            }
            if (GenClosest.EarlyOutSearch(root, map, thingReq, customGlobalSearchSet))
            {
                return(null);
            }
            Thing thing = null;

            if (!thingReq.IsUndefined)
            {
                int maxRegions = (searchRegionsMax <= 0) ? 30 : searchRegionsMax;
                thing = GenClosest.RegionwiseBFSWorker(root, map, thingReq, peMode, traverseParams, validator, null, searchRegionsMin, maxRegions, maxDistance, traversableRegionTypes, ignoreEntirelyForbiddenRegions);
            }
            if (thing == null && (searchRegionsMax < 0 || forceGlobalSearch))
            {
                if (traversableRegionTypes != RegionType.Set_Passable)
                {
                    Log.ErrorOnce("ClosestThingReachable had to do a global search, but traversableRegionTypes is not set to passable only. It's not supported, because Reachability is based on passable regions only.", 14384767);
                }
                Predicate <Thing> validator2 = delegate(Thing t)
                {
                    if (!map.reachability.CanReach(root, t, peMode, traverseParams))
                    {
                        return(false);
                    }
                    if (validator != null && !validator(t))
                    {
                        return(false);
                    }
                    return(true);
                };
                IEnumerable <Thing> searchSet = customGlobalSearchSet ?? map.listerThings.ThingsMatching(thingReq);
                thing = GenClosest.ClosestThing_Global(root, searchSet, maxDistance, validator2, null);
            }
            return(thing);
        }
예제 #2
0
        public static Thing ClosestThingReachable(IntVec3 root, Map map, ThingRequest thingReq, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null, IEnumerable <Thing> customGlobalSearchSet = null, int searchRegionsMin = 0, int searchRegionsMax = -1, bool forceGlobalSearch = false, RegionType traversableRegionTypes = RegionType.Set_Passable, bool ignoreEntirelyForbiddenRegions = false)
        {
            bool flag = searchRegionsMax < 0 || forceGlobalSearch;

            if (!flag && customGlobalSearchSet != null)
            {
                Log.ErrorOnce("searchRegionsMax >= 0 && customGlobalSearchSet != null && !forceGlobalSearch. customGlobalSearchSet will never be used.", 634984, false);
            }
            if (!flag && !thingReq.IsUndefined && !thingReq.CanBeFoundInRegion)
            {
                Log.ErrorOnce("ClosestThingReachable with thing request group " + thingReq.group + " and global search not allowed. This will never find anything because this group is never stored in regions. Either allow global search or don't call this method at all.", 518498981, false);
                return(null);
            }
            if (GenClosest.EarlyOutSearch(root, map, thingReq, customGlobalSearchSet, validator))
            {
                return(null);
            }
            Thing thing = null;
            bool  flag2 = false;

            if (!thingReq.IsUndefined && thingReq.CanBeFoundInRegion)
            {
                int num = (searchRegionsMax <= 0) ? 30 : searchRegionsMax;
                int num2;
                thing = GenClosest.RegionwiseBFSWorker(root, map, thingReq, peMode, traverseParams, validator, null, searchRegionsMin, num, maxDistance, out num2, traversableRegionTypes, ignoreEntirelyForbiddenRegions);
                flag2 = (thing == null && num2 < num);
            }
            if (thing == null && flag && !flag2)
            {
                if (traversableRegionTypes != RegionType.Set_Passable)
                {
                    Log.ErrorOnce("ClosestThingReachable had to do a global search, but traversableRegionTypes is not set to passable only. It's not supported, because Reachability is based on passable regions only.", 14384767, false);
                }
                Predicate <Thing>   validator2 = (Thing t) => map.reachability.CanReach(root, t, peMode, traverseParams) && (validator == null || validator(t));
                IEnumerable <Thing> searchSet  = customGlobalSearchSet ?? map.listerThings.ThingsMatching(thingReq);
                thing = GenClosest.ClosestThing_Global(root, searchSet, maxDistance, validator2, null);
            }
            return(thing);
        }
예제 #3
0
        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, false);
                return(null);
            }
            if (GenClosest.EarlyOutSearch(root, map, thingReq, null, validator))
            {
                return(null);
            }
            if (maxRegions < minRegions)
            {
                Log.ErrorOnce("maxRegions < minRegions", 754343, false);
            }
            Thing result = null;

            if (!thingReq.IsUndefined)
            {
                int num;
                result = GenClosest.RegionwiseBFSWorker(root, map, thingReq, peMode, traverseParams, validator, priorityGetter, minRegions, maxRegions, maxDistance, out num, RegionType.Set_Passable, false);
            }
            return(result);
        }
예제 #4
0
        /// <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
                }
            }
        }