예제 #1
0
        // Token: 0x06000420 RID: 1056 RVA: 0x0002CD30 File Offset: 0x0002B130
        protected override IntVec3 GetWanderRoot(Pawn pawn)
        {
            if (pawn.isXenomorph())
            {
                HiveLike hivelike = pawn.mindState.duty != null && pawn.mindState.duty.focus != null ? pawn.mindState.duty.focus.Thing as HiveLike : null;
                if (hivelike != null)
                {
                    return(hivelike.Position);
                }

                /*
                 * if (hivelike==null)
                 * {
                 *  hivelike = FindClosestHiveLike(pawn);
                 * }
                 */
                if (hivelike == null || !hivelike.Spawned)
                {
                    if (XenomorphUtil.HivelikesPresent(pawn.Map))
                    {
                        return(XenomorphUtil.ClosestReachableHivelike(pawn).Position);
                    }
                    if (!XenomorphKidnapUtility.hiveslimepresent)
                    {
                        if (XenomorphKidnapUtility.TryFindGoodHiveLoc(pawn, out IntVec3 c))
                        {
                            return(c);
                        }
                    }
                    else if (!XenomorphUtil.ClosestReachableHiveSlime(pawn).DestroyedOrNull())
                    {
                        return(XenomorphUtil.ClosestReachableHiveSlime(pawn).Position);
                    }
                    return(pawn.Position);
                }
                //    Log.Message(string.Format("JobGiver_WanderHiveLike hivelike.Position: {0}", hivelike.Position));
                return(hivelike.Position);
            }
            else if (pawn.isNeomorph())
            {
                Corpse corpse = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly), 20f);
                if (corpse != null)
                {
                    return(corpse.Position);
                }
                return(pawn.Position);
            }
            else
            {
                return(pawn.Position);
            }
        }
예제 #2
0
        public static bool TryFindBestItemToSteal(IntVec3 root, Map map, float maxDist, out Thing item, Pawn thief, List <Thing> disallowed = null)
        {
            if (thief != null && !thief.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                item = null;
                return(false);
            }
            if ((thief != null && !map.reachability.CanReachMapEdge(thief.Position, TraverseParms.For(thief, Danger.Some, TraverseMode.ByPawn, false))) || (thief == null && !map.reachability.CanReachMapEdge(root, TraverseParms.For(TraverseMode.PassDoors, Danger.Some, false))))
            {
                item = null;
                return(false);
            }
            Predicate <Thing> validator = (Thing t) => (thief == null || thief.CanReserve(t, 1, -1, null, false)) && (disallowed == null || !disallowed.Contains(t)) && t.def.stealable && !t.IsBurning();

            item = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(root, map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEverOrMinifiable), PathEndMode.ClosestTouch, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Some, false), maxDist, validator, new Func <Thing, float>(StealAIUtility.GetValue), 15, 15);
            if (item != null && StealAIUtility.GetValue(item) < 320f)
            {
                item = null;
            }
            return(item != null);
        }
        private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen)
        {
            // 最終結果クリア
            chosen.Clear();

            // 中間結果クリア
            newRelevantThings.Clear();

            // そもそも材料不要
            if (bill.recipe.ingredients.Count == 0)
            {
                return(true);
            }

            // 作業位置
            var rootCell = GetBillGiverRootCell(billGiver, pawn);

            // リージョン取得
            Region rootReg = rootCell.GetRegion(pawn.Map, RegionType.Set_Passable);

            if (rootReg == null)
            {
                return(false);
            }

            // 素材を順番に並べて取得(任意材料、固定材料、その他)
            MakeIngredientsListInProcessingOrder(ingredientsOrdered, bill);

            // 中間結果クリア
            relevantThings.Clear();
            processedThings.Clear();
            bool foundAll = false;

            // 材料の基本探索条件
            Predicate <Thing> baseValidator = (t) =>
            {
                return(t.Spawned && // スポーン済み
                       !t.IsForbidden(pawn) && // 禁止されていない
                       (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && // billごとの材料探索範囲以内
                       bill.IsFixedOrAllowedIngredient(t) && // billとして許可された材料である
                       bill.recipe.ingredients.Any((ingNeed) => ingNeed.filter.Allows(t)) && // レシピとして許可された材料である
                       pawn.CanReserve(t)); // 予約可能
            };

            TraverseParms        traverseParams = TraverseParms.For(pawn);
            RegionEntryPredicate entryCondition = (from, r) => r.Allows(traverseParams, false);
            int adjacentRegionsAvailable        = rootReg.Neighbors.Count((region) => entryCondition(rootReg, region));
            int regionsProcessed = 0;

            // ???
            processedThings.AddRange(relevantThings);

            RegionProcessor regionProcessor = (r) =>
            {
                // 運搬可能な物ループ
                foreach (var thing in r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)))
                {
                    // 既に含まれている物は無視
                    if (processedThings.Contains(thing))
                    {
                        continue;
                    }

                    // そのリージョンからその物にタッチしに行けるか
                    if (!ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn))
                    {
                        continue;
                    }

                    // 基本条件を満足しない場合はダメ
                    if (!baseValidator(thing))
                    {
                        continue;
                    }

                    // リストに加える
                    newRelevantThings.Add(thing);
                    processedThings.Add(thing);
                }
                regionsProcessed++;

                if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable)
                {
                    // 二つの物の距離を比べる
                    Comparison <Thing> comparison = (t1, t2) =>
                    {
                        float t1dist = (float)(t1.Position - rootCell).LengthHorizontalSquared;
                        float t2dist = (float)(t2.Position - rootCell).LengthHorizontalSquared;
                        return(t1dist.CompareTo(t2dist));
                    };

                    // 距離の昇順?にソート
                    newRelevantThings.Sort(comparison);

                    // 探索した素材を追加
                    relevantThings.AddRange(newRelevantThings);

                    // 新しく探索した素材リストをクリア
                    newRelevantThings.Clear();

                    // 素材リストの中から最適な素材を見つける
                    if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen))
                    {
                        // 全部見つかった
                        foundAll = true;
                        return(true);
                    }
                }

                // 全部は見つからなかった
                return(false);
            };

            RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor);

            relevantThings.Clear();
            newRelevantThings.Clear();

            return(foundAll);
        }
예제 #4
0
        static bool Prefix(Pawn eater, Pawn getter, bool allowPlant, bool allowForbidden, bool desperate, FoodPreferability maxPref, bool allowCorpse, bool allowDrug, out ThingDef foodDef, ref Thing __result)
        {
            foodDef = null;
            if (eater == null || eater.Faction == null || !eater.Faction.IsPlayer || eater.def.race.Humanlike)
            {
                return(true);
            }
            Comp_PawnMenu comp = eater.GetComp <Comp_PawnMenu>();

            if (comp == null)
            {
                return(true);
            }
            if (!comp.activated())
            {
                return(true);
            }
            FoodPreferability minPref       = FoodPreferability.NeverForNutrition;
            Predicate <Thing> foodValidator = delegate(Thing t) {
                if (!allowForbidden && t.IsForbidden(getter))
                {
                    return(false);
                }
                if (t.def.ingestible.preferability < minPref)
                {
                    return(false);
                }
                if (t.def.ingestible.preferability > maxPref)
                {
                    return(false);
                }
                if (!t.IngestibleNow || !t.def.IsNutritionGivingIngestible || (!allowCorpse && t is Corpse) || (!allowDrug && t.def.IsDrug) || (!desperate && t.IsNotFresh()) || t.IsDessicated() || !eater.RaceProps.WillAutomaticallyEat(t) || !getter.AnimalAwareOf(t) || !getter.CanReserve(t, 1, -1, null, false))
                {
                    return(false);
                }
                return(comp.contains(t.def));
            };
            ThingRequest thingRequest;

            if ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != FoodTypeFlags.None && allowPlant)
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource);
            }
            else
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            }
            int             searchRegionsMax = 100;
            HashSet <Thing> ___filtered      = new HashSet <Thing>();

            foreach (Thing thing2 in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
            {
                Pawn pawn = thing2 as Pawn;
                if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                {
                    ___filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                }
            }
            bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null;
            Predicate <Thing> predicate         = (Thing t) => foodValidator(t) && !___filtered.Contains(t) && !t.IsNotFresh();
            IntVec3           position          = getter.Position;
            Map           map            = getter.Map;
            PathEndMode   peMode         = PathEndMode.ClosestTouch;
            TraverseParms traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false);
            Thing         bestThing      = GenClosest.ClosestThingReachable(position, map, thingRequest, peMode, traverseParams, 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);

            if (bestThing != null)
            {
                if (bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false);
                }
                __result = bestThing;
                return(false);
            }
            return(true);
        }
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Log.Message("Using VEF_AttackTargetFinder");
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            Log.Message("searcher is " + searcherPawn.Label);
            Log.Message("Attack Verb is " + verb.ToString());
            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false);
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((byte)(flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Log.Message("Beginning of innerValidator - Validating for " + t.Thing.Label);
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    Log.Message("IAttackTarget is Searcher - Invalid target");
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    Log.Message("Verb has minDistance and IAttackTarget is within minimum distance - Invalid target");
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    Log.Message("Searcher cannot attack targets closer that verb.verbProps.EffectiveMinRange");
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        Log.Message("Distance between Searcher and IAttackTarget is greater than 0, but less than verb.verbProps.EffectiveMinimumRange - Invalid target");
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    Log.Message("Seacrher has limited permissable movement and IAttackTarget is outside of that distance - Invalid target");
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    Log.Message("Searcher is not hostile towards IAttackTarget - Invalid target");
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    Log.Message("Searcher has validator and validator failed. Validator checked for " + validator.GetType().ToString());
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Log.Message("Searcher is Pawn - Get Lord");
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        Log.Message("Lord is in incorrect state - Return false");
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    Log.Message("Searher needs LOS to some or all targets, but cannot see target.");
                    if (t is Pawn)
                    {
                        Log.Message("IAttackTarget is Pawn");
                        if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            Log.Message("Searcher needs LOS to Pawn - Invalid target");
                            return(false);
                        }
                    }
                    else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        Log.Message("IAttackTarget is nonPawn");
                        Log.Message("Searcher needs LOS to NonPawns - Invalid target");
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher))
                {
                    Log.Message("Searcher needs Threat, IAttackTarget is not threat - Invalid target");
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    Log.Message("Verb is EMP and target is flesh - Invalid target");
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    Log.Message("Verb is incendiary and target is already burning - Invalid target");
                    return(false);
                }
                if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike)
                {
                    Log.Message("Searcher is ToolUser - Validating use of Explosives");
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        Log.Message("Explosive is already lit - Invalid verb");
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        Log.Message("IAttackTarget is in Fog - Invalid target");
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (!iterator.Current.Fogged(thing.Map))
                        {
                            Log.Message("IAttackTarget is not in Fog - return true");
                            flag2 = true;
                            break;
                        }
                        iterator.MoveNext();
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                Log.Message("IAttackTarget is valid target");
                return(true);
            };

            if (HasRangedAttack(searcher))
            {
                Log.Message(searcher.Thing.Label + " has ranged verb.");
                tmpTargets.Clear();
                tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                Log.Message("initializing tmpTargets");
                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Log.Message("TargetScanFlags.NeedReachable");
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;

                if (tmpTargets.Count == 0)
                {
                    Log.Message("There are no tmpTargets - return null");
                    return(null);
                }
                else
                {
                    Log.Message("There are " + tmpTargets.Count + " tmpTargets");
                }

                for (int i = 0; i < tmpTargets.Count; i++)
                {
                    Log.Message("Iterating tmpTargets to check for targets that can be hit from current location. Iteration " + i);
                    IAttackTarget attackTarget = tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        Log.Message("tempTarget " + i + " can be hit from current position.");
                        flag = true;
                        break;
                    }
                    Log.Message("tempTarget " + i + " cannot be hit from current position.");
                }
                IAttackTarget result = null;
                if (flag)
                {
                    Log.Message("A target can be shot from current position. Clearing tempTargets outside of range and picking one.");
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                    Log.Message("Target that can be shot from present location is: " + result.Thing.ToString());
                }
                else
                {
                    Log.Message("No target can be hit from current position. Refining validator...");
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        Log.Message("Using validator2 where (byte)TargetScanFalgs flags are not 0");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        Log.Message("Using validator2 where (byte)TargetScanFlags flags are 0");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    Log.Message("--- MARKER ---");
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, tmpTargets, maxDist, validator2, null);
                    if (result == null)
                    {
                        Log.Message("Taregt selection complete. Clearing tmpTargets. There is no valid target");
                    }
                    else
                    {
                        Log.Message("Taregt selection complete. Clearing tmpTargets. Final target is: " + result.Thing.ToString());
                    }
                }
                tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius));
            }
            IntVec3           position         = searcherThing.Position;
            Map               map              = searcherThing.Map;
            ThingRequest      thingReq         = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode       peMode           = PathEndMode.Touch;
            Pawn              searcherPawn2    = searcherPawn;
            Danger            maxDanger        = Danger.Deadly;
            bool              canBash2         = canBash;
            TraverseParms     traverseParams   = TraverseParms.For(searcherPawn2, maxDanger, TraverseMode.ByPawn, canBash2);
            float             maxDist2         = maxDist;
            Predicate <Thing> validator3       = (Thing x) => innerValidator((IAttackTarget)x);
            int               searchRegionsMax = (maxDist <= 800f) ? 40 : -1;
            IAttackTarget     attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, maxDist2, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
예제 #6
0
        public static Building_GuestBed FindBedFor(this Pawn pawn)
        {
            Predicate <Thing> bedValidator = delegate(Thing t) {
                if (!(t is Building_GuestBed))
                {
                    return(false);
                }
                if (!pawn.CanReserveAndReach(t, PathEndMode.OnCell, Danger.Some))
                {
                    return(false);
                }
                var b = (Building_GuestBed)t;
                if (b.CurOccupant != null)
                {
                    return(false);
                }
                if (b.ForPrisoners)
                {
                    return(false);
                }
                Find.Maps.ForEach(m => m.reservationManager.ReleaseAllForTarget(b));                                 // TODO: Put this somewhere smarter
                return(!b.IsForbidden(pawn) && !b.IsBurning());
            };
            var bed = (Building_GuestBed)GenClosest.ClosestThingReachable(pawn.GetLord().CurLordToil.FlagLoc, pawn.MapHeld, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn), 500f, bedValidator);

            return(bed);
        }
예제 #7
0
        public static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd, bool takeFromValidStorage = false, Predicate <Thing> extraValidator = null)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn actor  = toil.actor;
                Job  curJob = actor.jobs.curJob;
                if (actor.carryTracker.CarriedThing.def.stackLimit != 1 && !actor.carryTracker.Full && curJob.count > 0)
                {
                    Thing             thing     = null;
                    Predicate <Thing> validator = delegate(Thing t)
                    {
                        if (!t.Spawned)
                        {
                            return(false);
                        }
                        if (t.def != actor.carryTracker.CarriedThing.def)
                        {
                            return(false);
                        }
                        if (!t.CanStackWith(actor.carryTracker.CarriedThing))
                        {
                            return(false);
                        }
                        if (t.IsForbidden(actor))
                        {
                            return(false);
                        }
                        if (!takeFromValidStorage && t.IsInValidStorage())
                        {
                            return(false);
                        }
                        if (storeCellInd != 0 && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(actor.Map, t))
                        {
                            return(false);
                        }
                        if (!actor.CanReserve(t))
                        {
                            return(false);
                        }
                        return((extraValidator == null || extraValidator(t)) ? true : false);
                    };
                    thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor), 8f, validator);
                    if (thing != null)
                    {
                        curJob.SetTarget(haulableInd, thing);
                        actor.jobs.curDriver.JumpToToil(getHaulTargetToil);
                    }
                }
            };
            return(toil);
        }
예제 #8
0
        public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn              actor              = toil.actor;
                IntVec3           intVec             = IntVec3.Invalid;
                Thing             thing              = null;
                Thing             thing2             = actor.CurJob.GetTarget(ingestibleInd).Thing;
                Predicate <Thing> baseChairValidator = delegate(Thing t)
                {
                    if (t.def.building != null && t.def.building.isSittable)
                    {
                        if (t.IsForbidden(pawn))
                        {
                            return(false);
                        }
                        if (!actor.CanReserve(t, 1, -1, null, false))
                        {
                            return(false);
                        }
                        if (!t.IsSociallyProper(actor))
                        {
                            return(false);
                        }
                        if (t.IsBurning())
                        {
                            return(false);
                        }
                        if (t.HostileTo(pawn))
                        {
                            return(false);
                        }
                        bool flag = false;
                        for (int i = 0; i < 4; i++)
                        {
                            IntVec3  c       = t.Position + GenAdj.CardinalDirections[i];
                            Building edifice = c.GetEdifice(t.Map);
                            if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat)
                            {
                                flag = true;
                                break;
                            }
                        }
                        if (!flag)
                        {
                            return(false);
                        }
                        return(true);
                    }
                    return(false);
                };
                if (thing2.def.ingestible.chairSearchRadius > 0.0)
                {
                    thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None, null, 0, -1, false, RegionType.Set_Passable, false);
                }
                if (thing == null)
                {
                    intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing);
                    Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map);
                    if (chewSpotDanger != Danger.None)
                    {
                        thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger, null, 0, -1, false, RegionType.Set_Passable, false);
                    }
                }
                if (thing != null)
                {
                    intVec = thing.Position;
                    actor.Reserve(thing, actor.CurJob, 1, -1, null);
                }
                actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec);
                actor.pather.StartPath(intVec, PathEndMode.OnCell);
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            Predicate <Thing> validator = delegate(Thing t)
            {
                Pawn pawn3 = (Pawn)t;
                return((pawn3.Downed && pawn3.Faction == pawn.Faction && !pawn3.InBed() && pawn.CanReserve(pawn3) && !pawn3.IsForbidden(pawn) && !GenAI.EnemyIsNear(pawn3, 25f)) ? true : false);
            };
            Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(pawn), radius, validator);

            if (pawn2 == null)
            {
                return(null);
            }
            Building_Bed building_Bed = RestUtility.FindBedFor(pawn2, pawn, pawn2.HostFaction == pawn.Faction, checkSocialProperness: false);

            if (building_Bed == null || !pawn2.CanReserve(building_Bed))
            {
                return(null);
            }
            Job job = JobMaker.MakeJob(JobDefOf.Rescue, pawn2, building_Bed);

            job.count = 1;
            return(job);
        }
예제 #10
0
        public static Building_Bed FindPatientBedFor(Pawn pawn)
        {
            Predicate <Thing> medBedValidator = delegate(Thing t)
            {
                Building_Bed building_Bed2 = t as Building_Bed;
                if (building_Bed2 == null)
                {
                    return(false);
                }
                if (!building_Bed2.Medical && building_Bed2.def.building.bed_humanlike)
                {
                    return(false);
                }
                if (!RestUtility.IsValidBedFor(building_Bed2, pawn, pawn, pawn.IsPrisoner, false, true, false))
                {
                    return(false);
                }
                return(true);
            };

            if (pawn.InBed() && medBedValidator(pawn.CurrentBed()))
            {
                return(pawn.CurrentBed());
            }
            for (int i = 0; i < 2; i++)
            {
                Danger       maxDanger    = (Danger)((i == 0) ? 1 : 3);
                Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing b) => (int)b.Position.GetDangerFor(pawn, pawn.Map) <= (int)maxDanger && medBedValidator(b), null, 0, -1, false, RegionType.Set_Passable, false);
                if (building_Bed != null)
                {
                    return(building_Bed);
                }
            }
            return(RestUtility.FindBedFor(pawn));
        }
        // Token: 0x0600001A RID: 26 RVA: 0x0000247C File Offset: 0x0000067C
        protected override Job TryGiveJob(Pawn pawn)
        {
            bool downed = pawn.Downed;
            Job  result;

            if (downed)
            {
                result = null;
            }
            else
            {
                Need_Energy need_Energy = pawn.needs.TryGetNeed <Need_Energy>();
                bool        flag        = need_Energy == null;
                if (flag)
                {
                    result = null;
                }
                else
                {
                    bool flag2 = need_Energy.CurLevelPercentage >= Need_Energy.rechargePercentage;
                    if (flag2)
                    {
                        result = null;
                    }
                    else
                    {
                        Thing thing3 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing thing) => this.BestClosestPowerSource(pawn, thing), null, 0, -1, false, RegionType.Set_Passable, false);
                        bool  flag3  = thing3 != null;
                        if (flag3)
                        {
                            Building building = thing3 as Building;
                            bool     flag4    = thing3 != null && building != null && building.PowerComp != null && building.PowerComp.PowerNet.CurrentStoredEnergy() > 50f;
                            if (flag4)
                            {
                                IntVec3 position = thing3.Position;
                                bool    flag5    = position.Walkable(pawn.Map) && position.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(position), 1, -1, null, false) && pawn.CanReach(position, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn);
                                if (flag5)
                                {
                                    return(new Job(JobDefOf.ChJAndroidRecharge, thing3));
                                }
                                IEnumerable <IntVec3> source = GenAdj.CellsAdjacentCardinal(building);
                                Func <IntVec3, float> < > 9__1;
                                Func <IntVec3, float> keySelector;
                                if ((keySelector = < > 9__1) == null)
                                {
                                    keySelector = (< > 9__1 = ((IntVec3 selector) => selector.DistanceTo(pawn.Position)));
                                }
                                foreach (IntVec3 intVec in source.OrderByDescending(keySelector))
                                {
                                    bool flag6 = intVec.Walkable(pawn.Map) && intVec.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(intVec), 1, -1, null, false) && pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn);
                                    if (flag6)
                                    {
                                        return(new Job(JobDefOf.ChJAndroidRecharge, thing3, intVec));
                                    }
                                }
                            }
                        }
                        Thing thing2 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing thing) => thing.TryGetComp <EnergySourceComp>() != null && !thing.IsForbidden(pawn) && pawn.CanReserve(new LocalTargetInfo(thing), 1, -1, null, false) && thing.Position.InAllowedArea(pawn) && pawn.CanReach(new LocalTargetInfo(thing), PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn), null, 0, -1, false, RegionType.Set_Passable, false);
                        bool  flag7  = thing2 != null;
                        if (flag7)
                        {
                            EnergySourceComp energySourceComp = thing2.TryGetComp <EnergySourceComp>();
                            bool             flag8            = energySourceComp != null;
                            if (flag8)
                            {
                                int  num   = (int)Math.Ceiling((double)((need_Energy.MaxLevel - need_Energy.CurLevel) / energySourceComp.EnergyProps.energyWhenConsumed));
                                bool flag9 = num > 0;
                                if (flag9)
                                {
                                    return(new Job(JobDefOf.ChJAndroidRechargeEnergyComp, new LocalTargetInfo(thing2))
                                    {
                                        count = num
                                    });
                                }
                            }
                        }
                        result = null;
                    }
                }
            }
            return(result);
        }
예제 #12
0
        public void TryToTakeDownedOrDeadPawn(List <Pawn> relatedPawns)
        {
            if (pawn.CurJobDef == JobDefOf.TakeDownedOrDeadPawn ||
                pawn.IsColonist || pawn.MentalState == null || pawn.IsSlave())
            {
                return;
            }

            if (pawn.MentalStateDef == MentalStateDefOf.PanicFlee)
            {
                const float maxSearchDistance = 20;

                IntVec3 exitCell;
                if (!RCellFinder.TryFindBestExitSpot(pawn, out exitCell, TraverseMode.ByPawn))
                {
                    return;
                }

                // First priority: find any downed humanlike what is related to this pawn
                Predicate <Thing> validator = delegate(Thing t)
                {
                    Pawn pawn3 = t as Pawn;

                    return(pawn3 != null && pawn3.RaceProps.Humanlike &&
                           pawn3.PawnListed(relatedPawns) &&
                           pawn3.Downed &&
                           pawn.CanReserve(pawn3));
                };
                Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
                if (pawn2 != null)
                {
                    //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + pawn2);

                    Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn)
                    {
                        targetA = pawn2,
                        targetB = exitCell,
                        count   = 1
                    };

                    pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true);
                    return;
                }

                // Second priority: find any downed humanlike what is consists in pawn's faction
                validator = delegate(Thing t)
                {
                    Pawn pawn3 = t as Pawn;

                    return(pawn3 != null && pawn3.RaceProps.Humanlike &&
                           pawn3.Faction == pawn.Faction &&
                           pawn3.Downed &&
                           pawn.CanReserve(pawn3));
                };
                pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
                if (pawn2 != null)
                {
                    //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + pawn2);

                    Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn)
                    {
                        targetA = pawn2,
                        targetB = exitCell,
                        count   = 1
                    };

                    pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true);
                    return;
                }

                // Third priority: find any dead humanlike what was related to this pawn
                validator = delegate(Thing t)
                {
                    Corpse corpse = t as Corpse;

                    return(corpse != null && corpse.InnerPawn != null &&
                           corpse.InnerPawn.RaceProps.Humanlike &&
                           corpse.InnerPawn.PawnListed(relatedPawns) &&
                           pawn.CanReserve(corpse));
                };
                Corpse corpse2 = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
                if (corpse2 != null)
                {
                    //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + corpse2);

                    Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn)
                    {
                        targetA = corpse2,
                        targetB = exitCell,
                        count   = 1
                    };

                    pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true);
                    return;
                }

                return;
            }



//			if (pawn.health.HasHediffsNeedingTend())
//			{
//				float maxSearchDistance = 30 * pawn.health.capacities.GetLevel(PawnCapacityDefOf.Hearing);
//				List<Thing> allPawnsOfFactionOnMap = (List<Thing>)pawn.Map.mapPawns.FreeHumanlikesOfFaction(pawn.Faction);
//				List<Thing> allPawnsOfFactionInRange = AvaliUtility.FindAllThingsOnMapAtRange(pawn as Thing, null, typeof(Pawn), allPawnsOfFactionOnMap, maxSearchDistance, 9999, true, true);
//
//				if (allPawnsOfFactionInRange.Count == 0)
//				{
//					if (!pawn.Downed)
//					{
//
//					}
//					else return;
//				}
//
//				Pawn pawn1 = null;
//
//				for (int i = 0; i < allPawnsOfFactionInRange.Count; i++)
//				{
//					Pawn pawn2 = allPawnsOfFactionInRange[i] as Pawn;
//					if (pawn2 != null && pawn2 != pawn && pawn2.inventory.Contains(Thing))
//					{
//
//					}
//				}
//
//
//
//
////					if (pawn.inventory.Contains(ThingMaker.MakeThing(RimWorld.ThingDefOf.MedicineIndustrial)))
////					{
////
////					}
//
//				#region Выполнется только в случае если у pawn1 в инвентаре есть медикоменты и pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel
//				Predicate<Thing> validator = delegate(Thing t)
//				{
//					Pawn pawn1 = t as Pawn;
//
//					if (pawn1 != null && pawn1 != pawn &&
//					    pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction &&
//					    pawn1.inventory.Contains())
//					{
//						int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine);
//						int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine);
//
//						if (pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel)
//						{
//							return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn);
//						}
//					}
//
//					return false;
//				};
//				Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
//				if (pawn2 != null)
//				{
//					Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient)
//					{
//						targetA = pawn,
//						count = 1
//					};
//
//					pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true);
//					return;
//				}
//				#endregion
//
//				#region Выполнется только в случае если у pawn1 в инвентаре есть медикоменты
//				validator = delegate(Thing t)
//				{
//					Pawn pawn1 = t as Pawn;
//
//					if (pawn1 != null && pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction && pawn1.inventory.Contains())
//					{
//						int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine);
//						int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine);
//
//						if (pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel)
//						{
//							return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn);
//						}
//					}
//
//					return false;
//				};
//				pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
//				if (pawn2 != null)
//				{
//					Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient)
//					{
//						targetA = pawn,
//						count = 1
//					};
//
//					pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true);
//					return;
//				}
//				#endregion
//
//
//
//
//
//				validator = delegate(Thing t)
//				{
//					Pawn pawn1 = t as Pawn;
//
//					if (pawn1 != null && pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction)
//					{
//						int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine);
//						int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine);
//
//						if (pawnMedicineSkillLevel < pawn1MedicineSkillLevel)
//						{
//							return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn);
//						}
//					}
//
//					return false;
//				};
//				pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
//				if (pawn2 != null)
//				{
//					Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient)
//					{
//						targetA = pawn,
//						count = 1
//					};
//
//					pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true);
//					return;
//				}
//
//
//
//
//
//				if (pawn.Downed)
//				{
//
//				}
//				else
//				{
//
//				}
//			}
        }
예제 #13
0
        private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen)
        {
            chosen.Clear();
            newRelevantThings.Clear();
            if (bill.recipe.ingredients.Count == 0)
            {
                return(true);
            }
            IntVec3 rootCell = GetBillGiverRootCell(billGiver, pawn);
            Region  rootReg  = rootCell.GetRegion(pawn.Map);

            if (rootReg == null)
            {
                return(false);
            }
            MakeIngredientsListInProcessingOrder(ingredientsOrdered, bill);
            relevantThings.Clear();
            processedThings.Clear();
            bool foundAll = false;
            Predicate <Thing> baseValidator = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && bill.IsFixedOrAllowedIngredient(t) && bill.recipe.ingredients.Any((IngredientCount ingNeed) => ingNeed.filter.Allows(t)) && pawn.CanReserve(t);
            bool billGiverIsPawn            = billGiver is Pawn;

            if (billGiverIsPawn)
            {
                AddEveryMedicineToRelevantThings(pawn, billGiver, relevantThings, baseValidator, pawn.Map);
                if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen))
                {
                    relevantThings.Clear();
                    ingredientsOrdered.Clear();
                    return(true);
                }
            }
            TraverseParms        traverseParams = TraverseParms.For(pawn);
            RegionEntryPredicate entryCondition = (Region from, Region r) => r.Allows(traverseParams, isDestination: false);
            int adjacentRegionsAvailable        = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region));
            int regionsProcessed = 0;

            processedThings.AddRange(relevantThings);
            RegionProcessor regionProcessor = delegate(Region r)
            {
                List <Thing> list = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver));
                for (int i = 0; i < list.Count; i++)
                {
                    Thing thing = list[i];
                    if (!processedThings.Contains(thing) && ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing) && (!thing.def.IsMedicine || !billGiverIsPawn))
                    {
                        newRelevantThings.Add(thing);
                        processedThings.Add(thing);
                    }
                }
                regionsProcessed++;
                if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable)
                {
                    Comparison <Thing> comparison = delegate(Thing t1, Thing t2)
                    {
                        float num   = (t1.Position - rootCell).LengthHorizontalSquared;
                        float value = (t2.Position - rootCell).LengthHorizontalSquared;
                        return(num.CompareTo(value));
                    };
                    newRelevantThings.Sort(comparison);
                    relevantThings.AddRange(newRelevantThings);
                    newRelevantThings.Clear();
                    if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen))
                    {
                        foundAll = true;
                        return(true);
                    }
                }
                return(false);
            };

            RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999);
            relevantThings.Clear();
            newRelevantThings.Clear();
            processedThings.Clear();
            ingredientsOrdered.Clear();
            return(foundAll);
        }
예제 #14
0
        //slightly modified version of Toils_Ingest.CarryIngestibleToChewSpot
        public static Toil CarryPuzzleToSpot(Pawn pawn, TargetIndex puzzleInd)
        {
            var toil = new Toil();

            toil.initAction = delegate
            {
                Pawn    actor  = toil.actor;
                IntVec3 intVec = IntVec3.Invalid;
                Thing   thing  = null;
                Thing   thing2 = actor.CurJob.GetTarget(puzzleInd).Thing;
                bool baseChairValidator(Thing t)
                {
                    if (t.def.building == null || !t.def.building.isSittable)
                    {
                        return(false);
                    }
                    if (t.IsForbidden(pawn))
                    {
                        return(false);
                    }
                    if (!actor.CanReserve(t, 1, -1, null, false))
                    {
                        return(false);
                    }
                    if (!t.IsSociallyProper(actor))
                    {
                        return(false);
                    }
                    if (t.IsBurning())
                    {
                        return(false);
                    }
                    if (t.HostileTo(pawn))
                    {
                        return(false);
                    }
                    var result = false;

                    for (var i = 0; i < 4; i++)
                    {
                        IntVec3  c       = t.Position + GenAdj.CardinalDirections[i];
                        Building edifice = c.GetEdifice(t.Map);
                        if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat)
                        {
                            result = true;
                            break;
                        }
                    }
                    return(result);
                }

                //if you can find a table with chair, great. If not, go to your room.

                thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map,
                                                         ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell,
                                                         TraverseParms.For(actor),
                                                         30f, //"chair search radius"
                                                         (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None);

                if (thing == null)
                {
                    if (pawn.ownership?.OwnedRoom != null)
                    {
                        (from c in pawn.ownership.OwnedRoom.Cells
                         where c.Standable(pawn.Map) && !c.IsForbidden(pawn) && pawn.CanReserveAndReach(c, PathEndMode.OnCell, Danger.None)
                         select c).TryRandomElement(out intVec);
                    }
                }
                if (thing != null)
                {
                    intVec = thing.Position;
                    actor.Reserve(thing, actor.CurJob, 1, -1, null);
                }
                if (intVec == IntVec3.Invalid)
                {
                    intVec = RCellFinder.SpotToChewStandingNear(pawn, thing2);
                }
                actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec);
                actor.pather.StartPath(intVec, PathEndMode.OnCell);
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
예제 #15
0
 public static Building_BaseMechanoidPlatform GetAvailableMechanoidPlatform(Pawn pawn, Pawn targetPawn)
 {
     return((Building_BaseMechanoidPlatform)GenClosest.ClosestThingReachable(targetPawn.Position, targetPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing b)
     {
         if (b is Building_BaseMechanoidPlatform platform &&
             !b.IsBurning() &&
             !b.IsForbidden(targetPawn) &&
             targetPawn.CanReserve(b) &&
             (targetPawn.ownership.OwnedBed == null && !platform.CompAssignableToPawn.AssignedPawns.Any() || platform.CompAssignableToPawn.AssignedPawns.Contains(targetPawn)))
         {
             CompFlickable flickable = platform.TryGetComp <CompFlickable>();
             if (flickable != null && !flickable.SwitchIsOn)
             {
                 return false;
             }
             return true;
         }
         return false;
     }));
 }
예제 #16
0
 public static bool TryMakePreToilReservations_Prefix(ThingComp __instance, Pawn selPawn, ref IEnumerable <FloatMenuOption> __result)
 {
     if (!(selPawn.WorkTypeIsDisabled(WorkTypeDefOf.Research) || selPawn.WorkTagIsDisabled(WorkTags.Intellectual)) && selPawn.CanReach(__instance.parent, PathEndMode.ClosestTouch, Danger.Some, false, TraverseMode.ByPawn) && selPawn.CanReserve(__instance.parent, 1, -1, null, false))
     {
         List <FloatMenuOption> modified = new List <FloatMenuOption>();
         Thing thing = GenClosest.ClosestThingReachable(selPawn.Position, selPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.ResearchBench), PathEndMode.InteractionCell, TraverseParms.For(selPawn, Danger.Some, TraverseMode.ByPawn, false), 9999f, (Thing t) => t is Building_WorkTable && selPawn.CanReserve(t, 1, -1, null, false), null, 0, -1, false, RegionType.Set_Passable, false);
         Job   job   = null;
         if (thing != null)
         {
             job         = JobMaker.MakeJob(JobDefOf.ApplyTechprint);
             job.targetA = thing;
             job.targetB = __instance.parent;
             job.targetC = thing.Position;
         }
         modified.Add(new FloatMenuOption("ApplyTechprint".Translate(__instance.parent.Label).CapitalizeFirst(), delegate()
         {
             if (job == null)
             {
                 Messages.Message("MessageNoResearchBenchForTechprint".Translate(), MessageTypeDefOf.RejectInput, true);
                 return;
             }
             selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
         }, MenuOptionPriority.Default, null, null, 0f, null, null));
         __result = modified.AsEnumerable();
         return(false);
     }
     return(true);
 }
예제 #17
0
        public override IEnumerable <FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
        {
            JobFailReason.Clear();
            if (this.parent.def.building != null || this.parent.def.category == ThingCategory.Building || shard == null || !Base.ThingIsPrintable(this.parent.def))
            {
                yield break;
            }

            if (this.parent.IsForbidden(selPawn))
            {
                JobFailReason.Is("CannotPrioritizeForbidden".Translate(this.parent.Label, this.parent));
            }
            else if (!selPawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                JobFailReason.Is("Incapable".Translate());
            }
            else if (selPawn.WorkTypeIsDisabled(Base.DefOf.DTechprinting) || selPawn.WorkTagIsDisabled(WorkTags.Intellectual))
            {
                JobFailReason.Is("CannotPrioritizeWorkTypeDisabled".Translate(Base.DefOf.DTechprinting.gerundLabel));
            }
            else if (selPawn.workSettings.GetPriority(Base.DefOf.DTechprinting) == 0)
            {
                JobFailReason.Is("CannotPrioritizeNotAssignedToWorkType".Translate(Base.DefOf.DTechprinting.gerundLabel));
            }
            else if (!selPawn.CanReach(this.parent, PathEndMode.ClosestTouch, Danger.Some, false, TraverseMode.ByPawn))
            {
                JobFailReason.Is("CannotReach".Translate(), null);
            }
            else if (!selPawn.CanReserve(this.parent, 1, -1, null, false))
            {
                Pawn pawn = selPawn.Map.reservationManager.FirstRespectedReserver(this.parent, selPawn);
                if (pawn == null)
                {
                    pawn = selPawn.Map.physicalInteractionReservationManager.FirstReserverOf(selPawn);
                }
                if (pawn != null)
                {
                    JobFailReason.Is("ReservedBy".Translate(pawn.LabelShort, pawn), null);
                }
                else
                {
                    JobFailReason.Is("Reserved".Translate(), null);
                }
            }
            int minAmountToGrab = Base.IsSingleAllowed(this.parent.def) ? 1 : Base.IsStackAllowed(this.parent.def, ShardMaker.stackSize) ? ShardMaker.stackSize : 0;

            if (minAmountToGrab == 0 || this.parent.stackCount < minAmountToGrab)
            {
                JobFailReason.Is("notEnoughToShard".Translate(), null);
            }

            if (JobFailReason.HaveReason)
            {
                yield return(new FloatMenuOption("CannotGenericWorkCustom".Translate("techprint") + ": " + JobFailReason.Reason.CapitalizeFirst(), null, MenuOptionPriority.Default, null, null, 0f, null, null));

                JobFailReason.Clear();
                yield break;
            }

            HaulAIUtility.PawnCanAutomaticallyHaul(selPawn, this.parent, true);
            Thing techPrinter = GenClosest.ClosestThingReachable(selPawn.Position, selPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial),
                                                                 PathEndMode.InteractionCell, TraverseParms.For(selPawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f,
                                                                 (Thing thing) => thing.def == Base.DefOf.DTechprinter && selPawn.CanReserve(thing, 1, -1, null, false));

            Job job = null;

            if (techPrinter != null)
            {
                IBillGiver billGiver = techPrinter as IBillGiver;
                if (billGiver == null)
                {
                    Log.Error("Techprinter isn't bill giver");
                    yield break;
                }
                job = MakeShardingJob(selPawn, billGiver, minAmountToGrab);
            }

            yield return(new FloatMenuOption("turnIntoShards".Translate(ShardMaker.CalcNumShardsFor(this.parent), shard.LabelCap, this.parent.LabelCap).CapitalizeFirst(), delegate()
            {
                if (job == null)
                {
                    Messages.Message("noTechprinterAvailable".Translate(), MessageTypeDefOf.RejectInput, true);
                    return;
                }
                selPawn.jobs.TryTakeOrderedJob(job, JobTag.MiscWork);
            }, MenuOptionPriority.VeryLow, null, null, 0f, null, null));

            yield break;
        }
예제 #18
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            //if (pawn.def != ThingDefOf.Avali) return null;

            if (pawn.IsColonist || pawn.MentalState == null)
            {
                return(null);
            }

            if (pawn.MentalState.def == null || pawn.MentalState.def != MentalStateDefOf.PanicFlee)
            {
                return(null);
            }

            IntVec3 exitCell;

            if (!RCellFinder.TryFindBestExitSpot(pawn, out exitCell, TraverseMode.ByPawn))
            {
                return(null);
            }

            Hediff_AvaliBiology avaliBiologyHediff = pawn.health.hediffSet.GetHediffs <Hediff_AvaliBiology>().First();

            Predicate <Thing> validator = null;
            Pawn pawn2 = null;

            if (avaliBiologyHediff != null)
            {
                // First priority: find any downed humanlike what is related to this pawn
                validator = delegate(Thing t)
                {
                    Pawn pawn3 = t as Pawn;

                    return(pawn3.RaceProps.Humanlike &&
                           pawn3.PawnListed(avaliBiologyHediff.packPawns) &&
                           pawn3.Downed &&
                           pawn.CanReserve(pawn3));
                };
                pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
                if (pawn2 != null)
                {
                    return(new Job(JobDefOf.TakeDownedOrDeadPawn)
                    {
                        targetA = pawn2,
                        targetB = exitCell,
                        count = 1
                    });
                }
            }

            // Second priority: find any downed humanlike what is consist in pawn faction
            validator = delegate(Thing t)
            {
                Pawn pawn3 = t as Pawn;

                return(pawn3.RaceProps.Humanlike &&
                       pawn3.Faction == pawn.Faction &&
                       pawn3.Downed &&
                       pawn.CanReserve(pawn3));
            };
            pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);
            if (pawn2 != null)
            {
                return(new Job(JobDefOf.TakeDownedOrDeadPawn)
                {
                    targetA = pawn2,
                    targetB = exitCell,
                    count = 1
                });
            }

            // Third priority: find any dead humanlike what was related to this pawn
            validator = delegate(Thing t)
            {
                Corpse corpse = t as Corpse;

                return(corpse != null && corpse.InnerPawn != null &&
                       corpse.InnerPawn.RaceProps.Humanlike &&
                       corpse.InnerPawn.PawnListed(avaliBiologyHediff.packPawns) &&
                       pawn.CanReserve(corpse));
            };
            Corpse corpse2 = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false);

            if (corpse2 != null)
            {
                //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + corpse2);

                Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn)
                {
                    targetA = corpse2,
                    targetB = exitCell,
                    count   = 1
                };
            }

            return(null);
        }
예제 #19
0
        /**
         * Move few stepf srom dispenser to avoid clustering in a single cell
         */
        public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn    actor  = toil.actor;
                IntVec3 intVec = IntVec3.Invalid;
                Thing   thing  = null;
                Thing   thing2 = actor.CurJob.GetTarget(ingestibleInd).Thing;

                intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing);
                Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map);
                if (chewSpotDanger != Danger.None)
                {
                    thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.def.ingestible.chairSearchRadius, (Thing t) => (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger);
                }
                if (thing != null)
                {
                    intVec = thing.Position;
                    actor.Reserve(thing, actor.CurJob);
                }

                actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec);
                actor.pather.StartPath(intVec, PathEndMode.OnCell);
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
예제 #20
0
        /// <summary>
        ///     Grab all viable target candidates.
        /// </summary>
        /// <param name="abilityDef">Ability Def to take in account.</param>
        /// <param name="pawn">Caster Pawn.</param>
        /// <param name="customPredicate">If set it overrides the default predicate.</param>
        /// <param name="pawnsToTest">How many pawns to test at max before stopping. Default is 30.</param>
        /// <returns>Things that are viable.</returns>
        public virtual IEnumerable <Thing> GrabTargets(AbilityAIDef abilityDef, Pawn pawn,
                                                       Predicate <Thing> customPredicate = null, int pawnsToTest = 30)
        {
            //Make a list of candidates.
            var potentionalTargets          = new List <Thing>();
            Predicate <Thing> pawnPredicate = null;

            if (customPredicate != null)
            {
                pawnPredicate = customPredicate;
            }
            else if (abilityDef.canTargetAlly)
            {
                pawnPredicate = delegate(Thing thing)
                {
                    //Count own faction and faction whose goodwill they got above 50% as allies.
                    if (AbilityUtility.AreAllies(pawn, thing))
                    {
                        return(true);
                    }
                    return(false);
                }
            }
            ;
            else
            {
                pawnPredicate = delegate(Thing thing)
                {
                    var thingPawn = thing as Pawn;

                    //Count anything hostile as a target.
                    if (thingPawn != null)
                    {
                        if (!thingPawn.Downed && thing.HostileTo(pawn))
                        {
                            return(true);
                        }
                        else if (thing.HostileTo(pawn))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }
            };

            //Max 'pawnsToTest' shall we grab.
            for (var i = 0; i < pawnsToTest; i++)
            {
                var grabResult = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                  ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell,
                                                                  TraverseParms.For(TraverseMode.NoPassClosedDoors),
                                                                  abilityDef.maxRange,
                                                                  thing => pawn != thing && !potentionalTargets.Contains(thing) &&
                                                                  (thing.Position - pawn.Position).LengthHorizontal >= abilityDef.minRange &&
                                                                  pawnPredicate(thing));

                //If found nothing, then break.
                if (grabResult == null)
                {
                    break;
                }

                potentionalTargets.Add(grabResult);

                yield return(grabResult);
            }
        }
    }
        /// <summary>
        /// Used by GetPrioritySlot, actually finds a requested thing.
        /// </summary>
        /// <param name="pawn">Pawn to be considered.  Used in checking equipment and position when looking for nearby things.</param>
        /// <param name="curSlot">Pawn's LoadoutSlot being considered.</param>
        /// <param name="findCount">Amount of Thing of ThingDef to try and pickup.</param>
        /// <param name="curPriority">Priority of the job.</param>
        /// <param name="curThing">Thing found near pawn for potential pickup.</param>
        /// <param name="curCarrier">Pawn that is holding the curThing that 'pawn' wants.</param>
        /// <remarks>Was split off into a sepearate method so the code could be run from multiple places in caller but that is no longer needed.</remarks>
        private void FindPickup(Pawn pawn, LoadoutSlot curSlot, int findCount, out ItemPriority curPriority, out Thing curThing, out Pawn curCarrier)
        {
            curPriority = ItemPriority.None;
            curThing    = null;
            curCarrier  = null;

            Predicate <Thing> isFoodInPrison = (Thing t) => t.GetRoom().isPrisonCell&& t.def.IsNutritionGivingIngestible && pawn.Faction.IsPlayer;
            // Hint: The following block defines how to find items... pay special attention to the Predicates below.
            ThingRequest req;

            if (curSlot.genericDef != null)
            {
                req = ThingRequest.ForGroup(ThingRequestGroup.HaulableEver);
            }
            else
            {
                req = curSlot.thingDef.Minifiable ? ThingRequest.ForGroup(ThingRequestGroup.MinifiedThing) : ThingRequest.ForDef(curSlot.thingDef);
            }
            Predicate <Thing> findItem;

            if (curSlot.genericDef != null)
            {
                findItem = t => curSlot.genericDef.lambda(t.GetInnerIfMinified().def);
            }
            else
            {
                findItem = t => t.GetInnerIfMinified().def == curSlot.thingDef;
            }
            Predicate <Thing> search = t => findItem(t) && !t.IsForbidden(pawn) && pawn.CanReserve(t) && !isFoodInPrison(t);

            // look for a thing near the pawn.
            curThing = GenClosest.ClosestThingReachable(
                pawn.Position,
                pawn.Map,
                req,
                PathEndMode.ClosestTouch,
                TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                ProximitySearchRadius,
                search);
            if (curThing != null)
            {
                curPriority = ItemPriority.Proximity;
            }
            else
            {
                // look for a thing basically anywhere on the map.
                curThing = GenClosest.ClosestThingReachable(
                    pawn.Position,
                    pawn.Map,
                    req,
                    PathEndMode.ClosestTouch,
                    TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                    MaximumSearchRadius,
                    search);
                if (curThing == null && pawn.Map != null)
                {
                    // look for a thing inside caravan pack animals and prisoners.  EXCLUDE other colonists to avoid looping state.
                    List <Pawn> carriers = pawn.Map.mapPawns.AllPawns.Where(
                        p => p.inventory.innerContainer.Count > 0 && (p.RaceProps.packAnimal && p.Faction == pawn.Faction || p.IsPrisoner && p.HostFaction == pawn.Faction) &&
                        pawn.CanReserveAndReach(p, PathEndMode.ClosestTouch, Danger.Deadly, int.MaxValue, 0)).ToList();
                    foreach (Pawn carrier in carriers)
                    {
                        Thing thing = carrier.inventory.innerContainer.FirstOrDefault(t => findItem(t));
                        if (thing != null)
                        {
                            curThing   = thing;
                            curCarrier = carrier;
                            break;
                        }
                    }
                }
                if (curThing != null)
                {
                    if (!curThing.def.IsNutritionGivingIngestible && findCount / curSlot.count <= 0.5f)
                    {
                        curPriority = ItemPriority.LowStock;
                    }
                    else
                    {
                        curPriority = ItemPriority.Low;
                    }
                }
            }
        }
예제 #22
0
        //public float y=0f;
        public override IEnumerable <Gizmo> CompGetGizmosExtra()
        {
            foreach (var g in base.CompGetGizmosExtra())
            {
                yield return(g);
            }
            yield return(new Command_Action
            {
                icon = ContentFinder <Texture2D> .Get("UI/Commands/RenameZone"),
                defaultLabel = "CommandRenameZoneLabel".Translate(),
                action = delegate { Find.WindowStack.Add(new Dialog_RenameDSU(this)); },
                hotKey = KeyBindingDefOf.Misc1
            });

#if DEBUG
            yield return(new Command_Action
            {
                defaultLabel = "Items in Region",
                action = delegate
                {
                    Log.Warning("ListerThings for " + parent + " (at region at position " + parent.Position + ")");
                    foreach (var t in parent.Position.GetRegion(parent.Map).ListerThings
                             .ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)))
                    {
                        Log.Message("  " + t);
                    }
                }
            });
#endif

#if false
            yield return(new Command_Action {
                defaultLabel = "Y-=.1",
                action = delegate() {
                    y -= 0.1f;
                    Messages.Message("Offset: " + y, MessageTypeDefOf.NeutralEvent);
                }
            });

            yield return(new Command_Action {
                defaultLabel = "Y+=.1",
                action = delegate() {
                    y += 0.1f;
                    Messages.Message("Offset: " + y, MessageTypeDefOf.NeutralEvent);
                }
            });
#endif

            // I left this lovely testing code in - oops.
            //yield return new Command_Action
            //{
            //    defaultLabel = "Minus One",
            //    action=delegate ()
            //    {
            //        foreach (var cl in parent.GetSlotGroup().CellsList)
            //        {
            //            foreach (Thing t in parent.Map.thingGrid.ThingsAt(cl))
            //            {
            //                if (t.def.category == ThingCategory.Item)
            //                {
            //                    if (t.stackCount > 1)
            //                    {
            //                        Log.Warning("Lowering " + t.ToString());
            //                        t.stackCount--;
            //                    }
            //                }// item
            //            }// each thing
            //        }// each cell
            //    },// end action
            //};
        }
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                //Log.Error("BestAttackTarget with " + searcher + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb != null && verb.IsEMP();
            float minDistanceSquared = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((byte)(flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistanceSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistanceSquared)
                {
                    return(false);
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    if (t is Pawn)
                    {
                        if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            return(false);
                        }
                    }
                    else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (!iterator.Current.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                        iterator.MoveNext();
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (ARA_AttackTargetFinder.HasRangedAttack(searcher))
            {
                //Log.Warning("Finder: Range detected. Verb is " + verb);
                //Log.Warning("Finder: Pawn " + searcherPawn.Faction);
                ARA_AttackTargetFinder.tmpTargets.Clear();

                //This needs to be fixed. Can't use searcherThing. Doing this the hard way.
                //Set request for all attackable.
                ThingRequest        thingReq  = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
                IEnumerable <Thing> searchSet = searcherThing.Map.listerThings.ThingsMatching(thingReq);

                foreach (IAttackTarget iTarget in searchSet)
                {
                    ARA_AttackTargetFinder.tmpTargets.Add(iTarget);
                }

                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && ARA_AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                if (searcherThing.Faction != Faction.OfPlayer)
                {
                    //Log.Warning("Finder: Target available : " + ARA_AttackTargetFinder.tmpTargets.Count);
                    for (int i = 0; i < ARA_AttackTargetFinder.tmpTargets.Count; i++)
                    {
                        IAttackTarget attackTarget = ARA_AttackTargetFinder.tmpTargets[i];
                        if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && ARA_AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                        {
                            //Log.Warning("Finder: flag is true");
                            flag = true;
                            break;
                        }
                    }
                }

                IAttackTarget result;
                if (flag)
                {
                    //Log.Warning("Finder: FlagTrue result");
                    ARA_AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    //Log.Warning("Finder: Target Avaliable : " + ARA_AttackTargetFinder.tmpTargets.Count);
                    result = ARA_AttackTargetFinder.GetRandomShootingTargetByScore(ARA_AttackTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        //Log.Warning("Finder: Needs reachable");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (ARA_AttackTargetFinder.CanReach(searcherThing, t, canBash) || ARA_AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        //Log.Warning("Finder: Running normal validator");
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, ARA_AttackTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                ARA_AttackTargetFinder.tmpTargets.Clear();
                //Log.Warning("Trying to return result " + result);
                return(result);
            }
            //Log.Warning("Returning Null");
            return(null);
        }
        // Token: 0x06003F17 RID: 16151 RVA: 0x001D8758 File Offset: 0x001D6B58
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false);
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((byte)(flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }

                /*
                 * if (!searcherThing.HostileTo(thing))
                 * {
                 *  return false;
                 * }
                 */
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    if (t is Pawn)
                    {
                        if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            return(false);
                        }
                    }
                    else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        return(false);
                    }
                }
                if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (!iterator.Current.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                        iterator.MoveNext();
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (XenomorphTargetFinder.HasRangedAttack(searcher))
            {
                XenomorphTargetFinder.tmpTargets.Clear();
                XenomorphTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && XenomorphTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                for (int i = 0; i < XenomorphTargetFinder.tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = XenomorphTargetFinder.tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && XenomorphTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    XenomorphTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = XenomorphTargetFinder.GetRandomShootingTargetByScore(XenomorphTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (XenomorphTargetFinder.CanReach(searcherThing, t, canBash) || XenomorphTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, XenomorphTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                XenomorphTargetFinder.tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius));
            }
            IntVec3           position         = searcherThing.Position;
            Map               map              = searcherThing.Map;
            ThingRequest      thingReq         = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode       peMode           = PathEndMode.Touch;
            Pawn              searcherPawn2    = searcherPawn;
            Danger            maxDanger        = Danger.Deadly;
            bool              canBash2         = canBash;
            TraverseParms     traverseParams   = TraverseParms.For(searcherPawn2, maxDanger, TraverseMode.ByPawn, canBash2);
            float             maxDist2         = maxDist;
            Predicate <Thing> validator3       = (Thing x) => innerValidator((IAttackTarget)x);
            int               searchRegionsMax = (maxDist <= 800f) ? 40 : -1;
            IAttackTarget     attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, maxDist2, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = XenomorphTargetFinder.FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
        //regular Toils_Haul.CheckForGetOpportunityDuplicate isn't going to work for our purposes, since we're not carrying anything.
        //Carrying something yields weird results with unspawning errors when transfering to inventory, so we copy-past-- I mean, implement our own.
        public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, float distanceToOthers, Predicate <Thing> extraValidator = null)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn    actor     = toil.actor;
                Job     curJob    = actor.jobs.curJob;
                IntVec3 storeCell = IntVec3.Invalid;

                Predicate <Thing> validator = (Thing t) => t.Spawned &&
                                              HaulAIUtility.PawnCanAutomaticallyHaulFast(actor, t, false) &&
                                              (!t.IsInValidBestStorage()) &&
                                              !t.IsForbidden(actor) &&
                                              !(t is Corpse) &&
                                              (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out storeCell, true)) &&
                                              (extraValidator == null || extraValidator(t)) &&
                                              actor.CanReserve(t, 1, -1, null, false);

                Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch,
                                                               TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), Math.Max(distanceToOthers, 12f), validator, null, 0, -1, false, RegionType.Set_Passable, false);

                float usedBulkByPct   = 1f;
                float usedWeightByPct = 1f;

                try
                {
                    ((Action)(() =>
                    {
                        if (ModCompatibilityCheck.CombatExtendedIsActive)
                        {
                            CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>();
                            usedWeightByPct = ceCompInventory.currentWeight / ceCompInventory.capacityWeight;
                            usedBulkByPct = ceCompInventory.currentBulk / ceCompInventory.capacityBulk;
                        }
                    }))();
                }
                catch (TypeLoadException) { }


                if (thing != null && (MassUtility.EncumbrancePercent(actor) <= 0.9f || usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f))
                {
                    curJob.SetTarget(haulableInd, thing);
                    actor.Reserve(storeCell, this.job, 1, -1, null);
                    actor.jobs.curDriver.JumpToToil(getHaulTargetToil);
                    return;
                }
                if (thing != null)
                {
                    Job haul = HaulAIUtility.HaulToStorageJob(actor, thing);
                    if (haul?.TryMakePreToilReservations(actor) ?? false)
                    {
                        actor.jobs.jobQueue.EnqueueFirst(haul, new JobTag?(JobTag.Misc));
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                }
                if (thing == null)
                {
                    Job job = new Job(PickUpAndHaulJobDefOf.UnloadYourHauledInventory);
                    if (job.TryMakePreToilReservations(actor))
                    {
                        actor.jobs.jobQueue.EnqueueFirst(job, new JobTag?(JobTag.Misc));
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                }
            };
            return(toil);
        }
예제 #26
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.Downed)
            {
                return(null);
            }
            Predicate <Thing> validator = (Thing t) => t.def.category == ThingCategory.Item && t.IngestibleNow && pawn.RaceProps.CanEverEat(t) && pawn.CanReserve(t, 1, -1, null, false);
            Thing             thing     = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 10f, validator, null, 0, -1, false, RegionType.Set_Passable, false);

            if (thing == null)
            {
                return(null);
            }
            return(new Job(JobDefOf.Ingest, thing));
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (ShouldSkip(pawn))
            {
                return(null);
            }

            Predicate <Thing> predicate = (Thing x) => HasJobOnThing(pawn, x);
            Thing             t         = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn),
                                                                           PathEndMode, TraverseParms.For(pawn, Danger.Some, TraverseMode.ByPawn), 100f, predicate, PotentialWorkThingsGlobal(pawn));

            if (t is null)
            {
                return(null);
            }
            return(JobMaker.MakeJob(JobDefOf.Slaughter, t));
        }
예제 #28
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.inventory == null)
            {
                return(null);
            }
            float invNutrition = this.GetInventoryPackableFoodNutrition(pawn);

            if (invNutrition > 0.4f)
            {
                return(null);
            }
            if (pawn.Map.resourceCounter.TotalHumanEdibleNutrition < (float)pawn.Map.mapPawns.ColonistsSpawnedCount * 1.5f)
            {
                return(null);
            }
            Thing thing = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 20f, delegate(Thing t)
            {
                if (!this.IsGoodPackableFoodFor(t, pawn) || t.IsForbidden(pawn) || !pawn.CanReserve(t, 1, -1, null, false) || !t.IsSociallyProper(pawn))
                {
                    return(false);
                }
                float num3 = invNutrition + t.GetStatValue(StatDefOf.Nutrition, true) * (float)t.stackCount;
                if (num3 < 0.8f)
                {
                    return(false);
                }
                List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(pawn, t, FoodUtility.GetFinalIngestibleDef(t, false));
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i].stages[0].baseMoodEffect < 0f)
                    {
                        return(false);
                    }
                }
                return(true);
            }, (Thing x) => FoodUtility.FoodOptimality(pawn, x, FoodUtility.GetFinalIngestibleDef(x, false), 0f, false), 24, 30);

            if (thing == null)
            {
                return(null);
            }
            float num  = pawn.needs.food.MaxLevel - invNutrition;
            int   num2 = Mathf.FloorToInt(num / thing.GetStatValue(StatDefOf.Nutrition, true));

            num2 = Mathf.Min(num2, thing.stackCount);
            num2 = Mathf.Max(num2, 1);
            return(new Job(JobDefOf.TakeInventory, thing)
            {
                count = num2
            });
        }
        public override void CompTickRare()
        {
            base.CompTickRare();
            Predicate <Thing> predicate = null;

            if (Props.onlyHumanlike)
            {
                predicate = (Thing t) => (t as Pawn)?.RaceProps.Humanlike ?? false;
            }
            Thing thing = null;

            if (Props.triggerOnPawnInRoom)
            {
                foreach (Thing containedAndAdjacentThing in parent.GetRoom().ContainedAndAdjacentThings)
                {
                    if (predicate(containedAndAdjacentThing))
                    {
                        thing = containedAndAdjacentThing;
                        break;
                    }
                }
            }
            if (thing == null && Props.radius > 0f)
            {
                thing = GenClosest.ClosestThingReachable(parent.Position, parent.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors), Props.radius, predicate);
            }
            if (thing != null)
            {
                Effecter effecter = new Effecter(EffecterDefOf.ActivatorProximityTriggered);
                effecter.Trigger(parent, TargetInfo.Invalid);
                effecter.Cleanup();
                Messages.Message("MessageActivatorProximityTriggered".Translate(thing), parent, MessageTypeDefOf.ThreatBig);
                Find.SignalManager.SendSignal(new Signal(signalTag, parent.Named("SUBJECT")));
                SoundDefOf.MechanoidsWakeUp.PlayOneShot(new TargetInfo(parent.Position, parent.Map));
                sent = true;
            }
        }
예제 #30
0
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = float.MaxValue, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe() + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        //	Log.Messageage(thing + " lord ValidateAttackTarget: false");
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != 0)
                {
                    RoofDef roof = thing.Position.GetRoof(thing.Map);
                    if (roof != null && roof.isThickRoof)
                    {
                        //	Log.Messageage(thing + " isThickRoof: false");
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0)
                {
                    if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position)))
                    {
                        //	Log.Messageage(thing + " LOSToAll: false");
                        return(false);
                    }
                    if (!searcherThing.CanSee(thing, losValidator))
                    {
                        if (t is Pawn)
                        {
                            if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                            {
                                //	Log.Messageage(thing + " LOSToPawns: false");
                                return(false);
                            }
                        }
                        else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                        {
                            //	Log.Messageage(thing + " LOSToNonPawns: false");
                            return(false);
                        }
                    }
                }
                if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher))
                {
                    //	Log.Messageage(thing + " NeedThreat: false");
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t))
                {
                    //	Log.Messageage(thing + " NeedAutoTargetable: false");
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction))
                {
                    //	Log.Messageage(thing + " NeedActiveThreat: false");
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    //	Log.Messageage(thing + " onlyTargetMachines: false");
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    //	Log.Messageage(thing + " NeedNonBurning: false");
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        //	Log.Messageage(thing + " wickStarted: false");
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        //	Log.Messageage(thing + " Fogged: false");
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    foreach (IntVec3 item in thing.OccupiedRect())
                    {
                        if (!item.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        //	Log.Messageage(thing + " Fogged: false");
                        return(false);
                    }
                }
                //	Log.Messageage(thing + " valid: true");
                return(true);
            };

            if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState))
            {
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  0");
                tmpTargets.Clear();
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  1");
                tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  2 tmpTargets: " + tmpTargets.Count);
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator2 = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash));
                }
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  3");
                bool flag = false;
                for (int i = 0; i < tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 4 ");
                IAttackTarget attackTarget2;
                if (flag)
                {
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    attackTarget2 = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                }
                else
                {
                    attackTarget2 = (IAttackTarget)GenClosest.ClosestThing_Global(validator: ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == 0 || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)))), center: searcherThing.Position, searchSet: tmpTargets, maxDistance: maxDist);
                }
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  5");
                tmpTargets.Clear();
                //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack tgt found: " + (attackTarget2 != null).ToString());
                return(attackTarget2);
            }
            //	Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack  no ranged attack found");
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius));
            }
            IAttackTarget attackTarget3 = (IAttackTarget)GenClosest.ClosestThingReachable(searcherThing.Position, searcherThing.Map, ThingRequest.ForGroup(ThingRequestGroup.AttackTarget), PathEndMode.Touch, TraverseParms.For(searcherPawn, Danger.Deadly, TraverseMode.ByPawn, canBash), maxDist, (Thing x) => innerValidator((IAttackTarget)x), null, 0, (maxDist > 800f) ? (-1) : 40);

            if (attackTarget3 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget4 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget4 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget4.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget3 = attackTarget4;
                    }
                }
            }
            return(attackTarget3);
        }