private Thing FindFood(Pawn pawn, IntVec3 partySpot)
        {
            Predicate <Thing> validator = (Thing x) => x.IngestibleNow && x.def.IsNutritionGivingIngestible && PartyUtility.InPartyArea(x.Position, partySpot, pawn.Map) && !x.def.IsDrug && x.def.ingestible.preferability > FoodPreferability.RawBad && pawn.WillEat(x, null) && !x.IsForbidden(pawn) && x.IsSociallyProper(pawn) && pawn.CanReserve(x, 1, -1, null, false);

            return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 14f, validator, null, 0, 12, false, RegionType.Set_Passable, false));
        }
Ejemplo n.º 2
0
        public static bool AddHumanlikeOrders(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            IntVec3 c = IntVec3.FromVector3(clickPos);

            foreach (Thing thing in c.GetThingList(pawn.Map))
            {
                Pawn pawn2;
                if ((pawn2 = (thing as Pawn)) != null)
                {
                    Lord lord = pawn2.GetLord();
                    if (lord != null && lord.CurLordToil != null)
                    {
                        IEnumerable <FloatMenuOption> enumerable = lord.CurLordToil.ExtraFloatMenuOptions(pawn2, pawn);
                        if (enumerable != null)
                        {
                            foreach (FloatMenuOption item8 in enumerable)
                            {
                                opts.Add(item8);
                            }
                        }
                    }
                }
            }

            if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                foreach (LocalTargetInfo item9 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForArrest(pawn), thingsOnly: true))
                {
                    bool flag = item9.HasThing && item9.Thing is Pawn && ((Pawn)item9.Thing).IsWildMan();
                    if (pawn.Drafted || flag)
                    {
                        if (item9.Thing is Pawn && (pawn.InSameExtraFaction((Pawn)item9.Thing, ExtraFactionType.HomeFaction) || pawn.InSameExtraFaction((Pawn)item9.Thing, ExtraFactionType.MiniFaction)))
                        {
                            opts.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "SameFaction".Translate((Pawn)item9.Thing), null));
                        }
                        else if (!pawn.CanReach(item9, PathEndMode.OnCell, Danger.Deadly))
                        {
                            opts.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                        }
                        else
                        {
                            Pawn   pTarg2 = (Pawn)item9.Thing;
                            Action action = delegate
                            {
                                Building_Bed building_Bed3 = RestUtility.FindBedFor(pTarg2, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false);
                                if (building_Bed3 == null)
                                {
                                    building_Bed3 = RestUtility.FindBedFor(pTarg2, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false, ignoreOtherReservations: true);
                                }

                                if (building_Bed3 == null)
                                {
                                    Messages.Message("CannotArrest".Translate() + ": " + "NoPrisonerBed".Translate(), pTarg2, MessageTypeDefOf.RejectInput, historical: false);
                                }
                                else
                                {
                                    Job job19 = JobMaker.MakeJob(JobDefOf.Arrest, pTarg2, building_Bed3);
                                    job19.count = 1;
                                    pawn.jobs.TryTakeOrderedJob(job19);
                                    if (pTarg2.Faction != null && ((pTarg2.Faction != Faction.OfPlayer && !pTarg2.Faction.Hidden) || pTarg2.IsQuestLodger()))
                                    {
                                        TutorUtility.DoModalDialogIfNotKnown(ConceptDefOf.ArrestingCreatesEnemies, pTarg2.GetAcceptArrestChance(pawn).ToStringPercent());
                                    }
                                }
                            };
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("TryToArrest".Translate(item9.Thing.LabelCap, item9.Thing, pTarg2.GetAcceptArrestChance(pawn).ToStringPercent()), action, MenuOptionPriority.High, null, item9.Thing), pawn, pTarg2));
                        }
                    }
                }
            }

            foreach (Thing thing2 in c.GetThingList(pawn.Map))
            {
                Thing t = thing2;
                if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow)
                {
                    string text = (!t.def.ingestible.ingestCommandString.NullOrEmpty()) ? string.Format(t.def.ingestible.ingestCommandString, t.LabelShort) : ((string)"ConsumeThing".Translate(t.LabelShort, t));
                    if (!t.IsSociallyProper(pawn))
                    {
                        text = text + ": " + "ReservedForPrisoners".Translate().CapitalizeFirst();
                    }

                    FloatMenuOption floatMenuOption;
                    if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler())
                    {
                        floatMenuOption = new FloatMenuOption(text + ": " + TraitDefOf.DrugDesire.DataAtDegree(-1).GetLabelCapFor(pawn), null);
                    }
                    else if (FoodUtility.InappropriateForTitle(t.def, pawn, allowIfStarving: true))
                    {
                        floatMenuOption = new FloatMenuOption(text + ": " + "FoodBelowTitleRequirements".Translate(pawn.royalty.MostSeniorTitle.def.GetLabelFor(pawn)), null);
                    }
                    else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly))
                    {
                        floatMenuOption = new FloatMenuOption(text + ": " + "NoPath".Translate().CapitalizeFirst(), null);
                    }
                    else
                    {
                        MenuOptionPriority priority = (t is Corpse) ? MenuOptionPriority.Low : MenuOptionPriority.Default;
                        int maxAmountToPickup       = FoodUtility.GetMaxAmountToPickup(t, pawn, FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition)));
                        floatMenuOption = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate
                        {
                            int maxAmountToPickup2 = FoodUtility.GetMaxAmountToPickup(t, pawn, FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition)));
                            if (maxAmountToPickup2 != 0)
                            {
                                t.SetForbidden(value: false);
                                Job job18   = JobMaker.MakeJob(JobDefOf.Ingest, t);
                                job18.count = maxAmountToPickup2;
                                pawn.jobs.TryTakeOrderedJob(job18);
                            }
                        }, priority), pawn, t);
                        if (maxAmountToPickup == 0)
                        {
                            floatMenuOption.action = null;
                        }
                    }

                    opts.Add(floatMenuOption);
                }
            }

            foreach (LocalTargetInfo item10 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForQuestPawnsWhoWillJoinColony(pawn), thingsOnly: true))
            {
                Pawn            toHelpPawn = (Pawn)item10.Thing;
                FloatMenuOption item4      = pawn.CanReach(item10, PathEndMode.Touch, Danger.Deadly) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(toHelpPawn.IsPrisoner ? "FreePrisoner".Translate() : "OfferHelp".Translate(), delegate
                {
                    pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.OfferHelp, toHelpPawn));
                }, MenuOptionPriority.RescueOrCapture, null, toHelpPawn), pawn, toHelpPawn) : new FloatMenuOption("CannotGoNoPath".Translate(), null);
                opts.Add(item4);
            }

            if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                foreach (Thing thing3 in c.GetThingList(pawn.Map))
                {
                    Corpse corpse = thing3 as Corpse;
                    if (corpse != null && corpse.IsInValidStorage())
                    {
                        StoragePriority priority2 = StoreUtility.CurrentHaulDestinationOf(corpse).GetStoreSettings().Priority;
                        if (StoreUtility.TryFindBestBetterNonSlotGroupStorageFor(corpse, pawn, pawn.Map, priority2, Faction.OfPlayer, out IHaulDestination haulDestination, acceptSamePriority: true) && haulDestination.GetStoreSettings().Priority == priority2 && haulDestination is Building_Grave)
                        {
                            Building_Grave grave = haulDestination as Building_Grave;
                            string         label = "PrioritizeGeneric".Translate("Burying".Translate(), corpse.Label);
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate
                            {
                                pawn.jobs.TryTakeOrderedJob(HaulAIUtility.HaulToContainerJob(pawn, corpse, grave));
                            }), pawn, new LocalTargetInfo(corpse)));
                        }
                    }
                }

                foreach (LocalTargetInfo item11 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true))
                {
                    Pawn victim3 = (Pawn)item11.Thing;
                    if (!victim3.InBed() && pawn.CanReserveAndReach(victim3, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && !victim3.mindState.WillJoinColonyIfRescued)
                    {
                        if (!victim3.IsPrisonerOfColony && (!victim3.InMentalState || victim3.health.hediffSet.HasHediff(HediffDefOf.Scaria)) && (victim3.Faction == Faction.OfPlayer || victim3.Faction == null || !victim3.Faction.HostileTo(Faction.OfPlayer)))
                        {
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Rescue".Translate(victim3.LabelCap, victim3), delegate
                            {
                                Building_Bed building_Bed2 = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: false, checkSocialProperness: false);
                                if (building_Bed2 == null)
                                {
                                    building_Bed2 = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: false, checkSocialProperness: false, ignoreOtherReservations: true);
                                }

                                if (building_Bed2 == null)
                                {
                                    string t3 = (!victim3.RaceProps.Animal) ? ((string)"NoNonPrisonerBed".Translate()) : ((string)"NoAnimalBed".Translate());
                                    Messages.Message("CannotRescue".Translate() + ": " + t3, victim3, MessageTypeDefOf.RejectInput, historical: false);
                                }
                                else
                                {
                                    Job job17   = JobMaker.MakeJob(JobDefOf.Rescue, victim3, building_Bed2);
                                    job17.count = 1;
                                    pawn.jobs.TryTakeOrderedJob(job17);
                                    PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total);
                                }
                            }, MenuOptionPriority.RescueOrCapture, null, victim3), pawn, victim3));
                        }

                        if (victim3.RaceProps.Humanlike && (victim3.InMentalState || victim3.Faction != Faction.OfPlayer || (victim3.Downed && (victim3.guilt.IsGuilty || victim3.IsPrisonerOfColony))))
                        {
                            TaggedString taggedString = "Capture".Translate(victim3.LabelCap, victim3);
                            if (victim3.Faction != null && victim3.Faction != Faction.OfPlayer && !victim3.Faction.Hidden && !victim3.Faction.HostileTo(Faction.OfPlayer) && !victim3.IsPrisonerOfColony)
                            {
                                taggedString += ": " + "AngersFaction".Translate().CapitalizeFirst();
                            }

                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(taggedString, delegate
                            {
                                Building_Bed building_Bed = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false);
                                if (building_Bed == null)
                                {
                                    building_Bed = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false, ignoreOtherReservations: true);
                                }

                                if (building_Bed == null)
                                {
                                    Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim3, MessageTypeDefOf.RejectInput, historical: false);
                                }
                                else
                                {
                                    Job job16   = JobMaker.MakeJob(JobDefOf.Capture, victim3, building_Bed);
                                    job16.count = 1;
                                    pawn.jobs.TryTakeOrderedJob(job16);
                                    PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total);
                                    if (victim3.Faction != null && victim3.Faction != Faction.OfPlayer && !victim3.Faction.Hidden && !victim3.Faction.HostileTo(Faction.OfPlayer) && !victim3.IsPrisonerOfColony)
                                    {
                                        Messages.Message("MessageCapturingWillAngerFaction".Translate(victim3.Named("PAWN")).AdjustedFor(victim3), victim3, MessageTypeDefOf.CautionInput, historical: false);
                                    }
                                }
                            }, MenuOptionPriority.RescueOrCapture, null, victim3), pawn, victim3));
                        }
                    }
                }

                foreach (LocalTargetInfo item12 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true))
                {
                    LocalTargetInfo localTargetInfo = item12;
                    Pawn            victim2         = (Pawn)localTargetInfo.Thing;
                    if (victim2.Downed && pawn.CanReserveAndReach(victim2, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn, ignoreOtherReservations: true) != null)
                    {
                        string text2   = "CarryToCryptosleepCasket".Translate(localTargetInfo.Thing.LabelCap, localTargetInfo.Thing);
                        JobDef jDef    = JobDefOf.CarryToCryptosleepCasket;
                        Action action2 = delegate
                        {
                            Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn);
                            if (building_CryptosleepCasket == null)
                            {
                                building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn, ignoreOtherReservations: true);
                            }

                            if (building_CryptosleepCasket == null)
                            {
                                Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim2, MessageTypeDefOf.RejectInput, historical: false);
                            }
                            else
                            {
                                Job job15 = JobMaker.MakeJob(jDef, victim2, building_CryptosleepCasket);
                                job15.count = 1;
                                pawn.jobs.TryTakeOrderedJob(job15);
                            }
                        };
                        if (victim2.IsQuestLodger())
                        {
                            text2 += " (" + "CryptosleepCasketGuestsNotAllowed".Translate() + ")";
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, null, MenuOptionPriority.Default, null, victim2), pawn, victim2));
                        }
                        else if (victim2.GetExtraHostFaction() != null)
                        {
                            text2 += " (" + "CryptosleepCasketGuestPrisonersNotAllowed".Translate() + ")";
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, null, MenuOptionPriority.Default, null, victim2), pawn, victim2));
                        }
                        else
                        {
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, action2, MenuOptionPriority.Default, null, victim2), pawn, victim2));
                        }
                    }
                }

                if (ModsConfig.RoyaltyActive)
                {
                    foreach (LocalTargetInfo item13 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForShuttle(pawn), thingsOnly: true))
                    {
                        LocalTargetInfo   localTargetInfo2 = item13;
                        Pawn              victim           = (Pawn)localTargetInfo2.Thing;
                        Predicate <Thing> validator        = (Thing thing) => thing.TryGetComp <CompShuttle>()?.IsAllowedNow(victim) ?? false;
                        Thing             shuttleThing     = GenClosest.ClosestThingReachable(victim.Position, victim.Map, ThingRequest.ForDef(ThingDefOf.Shuttle), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, validator);
                        if (shuttleThing != null && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && !pawn.WorkTypeIsDisabled(WorkTypeDefOf.Hauling))
                        {
                            string label2  = "CarryToShuttle".Translate(localTargetInfo2.Thing);
                            Action action3 = delegate
                            {
                                CompShuttle compShuttle = shuttleThing.TryGetComp <CompShuttle>();
                                if (!compShuttle.LoadingInProgressOrReadyToLaunch)
                                {
                                    TransporterUtility.InitiateLoading(Gen.YieldSingle(compShuttle.Transporter));
                                }

                                Job job14 = JobMaker.MakeJob(JobDefOf.HaulToTransporter, victim, shuttleThing);
                                job14.ignoreForbidden = true;
                                job14.count           = 1;
                                pawn.jobs.TryTakeOrderedJob(job14);
                            };
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label2, action3), pawn, victim));
                        }
                    }
                }
            }

            foreach (LocalTargetInfo item14 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForStrip(pawn), thingsOnly: true))
            {
                LocalTargetInfo stripTarg = item14;
                FloatMenuOption item5     = pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly) ? ((stripTarg.Pawn == null || !stripTarg.Pawn.HasExtraHomeFaction()) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Strip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing), delegate
                {
                    stripTarg.Thing.SetForbidden(value: false, warnOnFail: false);
                    pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.Strip, stripTarg));
                    StrippableUtility.CheckSendStrippingImpactsGoodwillMessage(stripTarg.Thing);
                }), pawn, stripTarg) : new FloatMenuOption("CannotStrip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null)) : new FloatMenuOption("CannotStrip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing) + ": " + "NoPath".Translate().CapitalizeFirst(), null);
                opts.Add(item5);
            }

            ThingWithComps equipment;

            if (pawn.equipment != null)
            {
                equipment = null;
                List <Thing> thingList = c.GetThingList(pawn.Map);
                for (int i = 0; i < thingList.Count; i++)
                {
                    if (thingList[i].TryGetComp <CompEquippable>() != null)
                    {
                        equipment = (ThingWithComps)thingList[i];
                        break;
                    }
                }

                if (equipment != null)
                {
                    string          labelShort = equipment.LabelShort;
                    FloatMenuOption item6;
                    string          cantReason;
                    if (equipment.def.IsWeapon && pawn.WorkTagIsDisabled(WorkTags.Violent))
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "IsIncapableOfViolenceLower".Translate(pawn.LabelShort, pawn), null);
                    }
                    else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly))
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "NoPath".Translate().CapitalizeFirst(), null);
                    }
                    else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "Incapable".Translate(), null);
                    }
                    else if (equipment.IsBurning())
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "BurningLower".Translate(), null);
                    }
                    else if (pawn.IsQuestLodger() && !EquipmentUtility.QuestLodgerCanEquip(equipment, pawn))
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null);
                    }
                    else if (!EquipmentUtility.CanEquip_NewTmp(equipment, pawn, out cantReason, checkBonded: false))
                    {
                        item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + cantReason.CapitalizeFirst(), null);
                    }
                    else
                    {
                        string text3 = "Equip".Translate(labelShort);
                        if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler))
                        {
                            text3 += " " + "EquipWarningBrawler".Translate();
                        }

                        if (EquipmentUtility.AlreadyBondedToWeapon(equipment, pawn))
                        {
                            text3 += " " + "BladelinkAlreadyBonded".Translate();
                            TaggedString dialogText = "BladelinkAlreadyBondedDialog".Translate(pawn.Named("PAWN"), equipment.Named("WEAPON"), pawn.equipment.bondedWeapon.Named("BONDEDWEAPON"));
                            item6 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text3, delegate
                            {
                                Find.WindowStack.Add(new Dialog_MessageBox(dialogText));
                            }, MenuOptionPriority.High), pawn, equipment);
                        }
                        else
                        {
                            item6 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text3, delegate
                            {
                                string personaWeaponConfirmationText = EquipmentUtility.GetPersonaWeaponConfirmationText(equipment, pawn);
                                if (!personaWeaponConfirmationText.NullOrEmpty())
                                {
                                    Find.WindowStack.Add(new Dialog_MessageBox(personaWeaponConfirmationText, "Yes".Translate(), delegate
                                    {
                                        Equip();
                                    }, "No".Translate()));
                                }
                                else
                                {
                                    Equip();
                                }
                            }, MenuOptionPriority.High), pawn, equipment);
                        }
                    }

                    opts.Add(item6);
                }
            }

            foreach (Pair <CompReloadable, Thing> item15 in ReloadableUtility.FindPotentiallyReloadableGear(pawn, c.GetThingList(pawn.Map)))
            {
                CompReloadable comp   = item15.First;
                Thing          second = item15.Second;
                string         text4  = "Reload".Translate(comp.parent.Named("GEAR"), NamedArgumentUtility.Named(comp.AmmoDef, "AMMO")) + " (" + comp.LabelRemaining + ")";
                List <Thing>   chosenAmmo;
                if (!pawn.CanReach(second, PathEndMode.ClosestTouch, Danger.Deadly))
                {
                    opts.Add(new FloatMenuOption(text4 + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                }
                else if (!comp.NeedsReload(allowForcedReload: true))
                {
                    opts.Add(new FloatMenuOption(text4 + ": " + "ReloadFull".Translate(), null));
                }
                else if ((chosenAmmo = ReloadableUtility.FindEnoughAmmo(pawn, second.Position, comp, forceReload: true)) == null)
                {
                    opts.Add(new FloatMenuOption(text4 + ": " + "ReloadNotEnough".Translate(), null));
                }
                else
                {
                    Action action4 = delegate
                    {
                        pawn.jobs.TryTakeOrderedJob(JobGiver_Reload.MakeReloadJob(comp, chosenAmmo));
                    };
                    opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text4, action4), pawn, second));
                }
            }

            if (pawn.apparel != null)
            {
                if (pawn.Map.thingGrid.ThingAt(c, ThingCategory.Item) is Apparel apparel)
                {
                    string key  = "CannotWear";
                    string key2 = "ForceWear";
                    if (apparel.def.apparel.LastLayer.IsUtilityLayer)
                    {
                        key  = "CannotEquipApparel";
                        key2 = "ForceEquipApparel";
                    }

                    string          cantReason2;
                    FloatMenuOption item7 = (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly)) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "NoPath".Translate().CapitalizeFirst(), null) : (apparel.IsBurning() ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "Burning".Translate(), null) : (pawn.apparel.WouldReplaceLockedApparel(apparel) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "WouldReplaceLockedApparel".Translate().CapitalizeFirst(), null) : ((!ApparelUtility.HasPartsToWear(pawn, apparel.def)) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "CannotWearBecauseOfMissingBodyParts".Translate(), null) : (EquipmentUtility.CanEquip_NewTmp(apparel, pawn, out cantReason2) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(key2.Translate(apparel.LabelShort, apparel), delegate
                    {
                        apparel.SetForbidden(value: false);
                        Job job13 = JobMaker.MakeJob(JobDefOf.Wear, apparel);
                        pawn.jobs.TryTakeOrderedJob(job13);
                    }, MenuOptionPriority.High), pawn, apparel) : new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + cantReason2, null)))));
                    opts.Add(item7);
                }
            }

            if (pawn.IsFormingCaravan())
            {
                Thing item3 = c.GetFirstItem(pawn.Map);
                if (item3 != null && item3.def.EverHaulable && item3.def.canLoadIntoCaravan)
                {
                    Pawn   packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn;
                    JobDef jobDef     = (packTarget == pawn) ? JobDefOf.TakeInventory : JobDefOf.GiveToPackAnimal;
                    if (!pawn.CanReach(item3, PathEndMode.ClosestTouch, Danger.Deadly))
                    {
                        opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(item3.Label, item3) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                    }
                    else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, item3, 1))
                    {
                        opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(item3.Label, item3) + ": " + "TooHeavy".Translate(), null));
                    }
                    else
                    {
                        LordJob_FormAndSendCaravan lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob;
                        float capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob);
                        if (item3.stackCount == 1)
                        {
                            float capacityLeft2 = capacityLeft - item3.GetStatValue(StatDefOf.Mass);
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravan".Translate(item3.Label, item3), capacityLeft2), delegate
                            {
                                item3.SetForbidden(value: false, warnOnFail: false);
                                Job job12              = JobMaker.MakeJob(jobDef, item3);
                                job12.count            = 1;
                                job12.checkEncumbrance = (packTarget == pawn);
                                pawn.jobs.TryTakeOrderedJob(job12);
                            }, MenuOptionPriority.High), pawn, item3));
                        }
                        else
                        {
                            if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, item3, item3.stackCount))
                            {
                                opts.Add(new FloatMenuOption("CannotLoadIntoCaravanAll".Translate(item3.Label, item3) + ": " + "TooHeavy".Translate(), null));
                            }
                            else
                            {
                                float capacityLeft3 = capacityLeft - (float)item3.stackCount * item3.GetStatValue(StatDefOf.Mass);
                                opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravanAll".Translate(item3.Label, item3), capacityLeft3), delegate
                                {
                                    item3.SetForbidden(value: false, warnOnFail: false);
                                    Job job11              = JobMaker.MakeJob(jobDef, item3);
                                    job11.count            = item3.stackCount;
                                    job11.checkEncumbrance = (packTarget == pawn);
                                    pawn.jobs.TryTakeOrderedJob(job11);
                                }, MenuOptionPriority.High), pawn, item3));
                            }

                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("LoadIntoCaravanSome".Translate(item3.LabelNoCount, item3), delegate
                            {
                                int to3 = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, item3), item3.stackCount);
                                Dialog_Slider window3 = new Dialog_Slider(delegate(int val)
                                {
                                    float capacityLeft4 = capacityLeft - (float)val * item3.GetStatValue(StatDefOf.Mass);
                                    return(CaravanFormingUtility.AppendOverweightInfo(string.Format("LoadIntoCaravanCount".Translate(item3.LabelNoCount, item3), val), capacityLeft4));
                                }, 1, to3, delegate(int count)
                                {
                                    item3.SetForbidden(value: false, warnOnFail: false);
                                    Job job10              = JobMaker.MakeJob(jobDef, item3);
                                    job10.count            = count;
                                    job10.checkEncumbrance = (packTarget == pawn);
                                    pawn.jobs.TryTakeOrderedJob(job10);
                                });
                                Find.WindowStack.Add(window3);
                            }, MenuOptionPriority.High), pawn, item3));
                        }
                    }
                }
            }

            if (!pawn.Map.IsPlayerHome && !pawn.IsFormingCaravan())
            {
                Thing item2 = c.GetFirstItem(pawn.Map);
                if (item2 != null && item2.def.EverHaulable)
                {
                    if (!pawn.CanReach(item2, PathEndMode.ClosestTouch, Danger.Deadly))
                    {
                        opts.Add(new FloatMenuOption("CannotPickUp".Translate(item2.Label, item2) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                    }
                    else if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item2, 1))
                    {
                        opts.Add(new FloatMenuOption("CannotPickUp".Translate(item2.Label, item2) + ": " + "TooHeavy".Translate(), null));
                    }
                    else if (item2.stackCount == 1)
                    {
                        opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUp".Translate(item2.Label, item2), delegate
                        {
                            item2.SetForbidden(value: false, warnOnFail: false);
                            Job job9              = JobMaker.MakeJob(JobDefOf.TakeInventory, item2);
                            job9.count            = 1;
                            job9.checkEncumbrance = true;
                            pawn.jobs.TryTakeOrderedJob(job9);
                        }, MenuOptionPriority.High), pawn, item2));
                    }
                    else
                    {
                        if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item2, item2.stackCount))
                        {
                            opts.Add(new FloatMenuOption("CannotPickUpAll".Translate(item2.Label, item2) + ": " + "TooHeavy".Translate(), null));
                        }
                        else
                        {
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUpAll".Translate(item2.Label, item2), delegate
                            {
                                item2.SetForbidden(value: false, warnOnFail: false);
                                Job job8              = JobMaker.MakeJob(JobDefOf.TakeInventory, item2);
                                job8.count            = item2.stackCount;
                                job8.checkEncumbrance = true;
                                pawn.jobs.TryTakeOrderedJob(job8);
                            }, MenuOptionPriority.High), pawn, item2));
                        }

                        opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUpSome".Translate(item2.LabelNoCount, item2), delegate
                        {
                            int to2 = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(pawn, item2), item2.stackCount);
                            Dialog_Slider window2 = new Dialog_Slider("PickUpCount".Translate(item2.LabelNoCount, item2), 1, to2, delegate(int count)
                            {
                                item2.SetForbidden(value: false, warnOnFail: false);
                                Job job7              = JobMaker.MakeJob(JobDefOf.TakeInventory, item2);
                                job7.count            = count;
                                job7.checkEncumbrance = true;
                                pawn.jobs.TryTakeOrderedJob(job7);
                            });
                            Find.WindowStack.Add(window2);
                        }, MenuOptionPriority.High), pawn, item2));
                    }
                }
            }

            if (!pawn.Map.IsPlayerHome && !pawn.IsFormingCaravan())
            {
                Thing item = c.GetFirstItem(pawn.Map);
                if (item != null && item.def.EverHaulable)
                {
                    Pawn bestPackAnimal = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn);
                    if (bestPackAnimal != null)
                    {
                        if (!pawn.CanReach(item, PathEndMode.ClosestTouch, Danger.Deadly))
                        {
                            opts.Add(new FloatMenuOption("CannotGiveToPackAnimal".Translate(item.Label, item) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                        }
                        else if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, 1))
                        {
                            opts.Add(new FloatMenuOption("CannotGiveToPackAnimal".Translate(item.Label, item) + ": " + "TooHeavy".Translate(), null));
                        }
                        else if (item.stackCount == 1)
                        {
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimal".Translate(item.Label, item), delegate
                            {
                                item.SetForbidden(value: false, warnOnFail: false);
                                Job job6   = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item);
                                job6.count = 1;
                                pawn.jobs.TryTakeOrderedJob(job6);
                            }, MenuOptionPriority.High), pawn, item));
                        }
                        else
                        {
                            if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, item.stackCount))
                            {
                                opts.Add(new FloatMenuOption("CannotGiveToPackAnimalAll".Translate(item.Label, item) + ": " + "TooHeavy".Translate(), null));
                            }
                            else
                            {
                                opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimalAll".Translate(item.Label, item), delegate
                                {
                                    item.SetForbidden(value: false, warnOnFail: false);
                                    Job job5   = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item);
                                    job5.count = item.stackCount;
                                    pawn.jobs.TryTakeOrderedJob(job5);
                                }, MenuOptionPriority.High), pawn, item));
                            }

                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimalSome".Translate(item.LabelNoCount, item), delegate
                            {
                                int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(bestPackAnimal, item), item.stackCount);
                                Dialog_Slider window = new Dialog_Slider("GiveToPackAnimalCount".Translate(item.LabelNoCount, item), 1, to, delegate(int count)
                                {
                                    item.SetForbidden(value: false, warnOnFail: false);
                                    Job job4   = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item);
                                    job4.count = count;
                                    pawn.jobs.TryTakeOrderedJob(job4);
                                });
                                Find.WindowStack.Add(window);
                            }, MenuOptionPriority.High), pawn, item));
                        }
                    }
                }
            }

            if (!pawn.Map.IsPlayerHome && pawn.Map.exitMapGrid.MapUsesExitGrid)
            {
                foreach (LocalTargetInfo item16 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true))
                {
                    Pawn p = (Pawn)item16.Thing;
                    if (p.Faction == Faction.OfPlayer || p.IsPrisonerOfColony || CaravanUtility.ShouldAutoCapture(p, Faction.OfPlayer))
                    {
                        IntVec3 exitSpot;
                        if (!pawn.CanReach(p, PathEndMode.ClosestTouch, Danger.Deadly))
                        {
                            opts.Add(new FloatMenuOption("CannotCarryToExit".Translate(p.Label, p) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                        }
                        else if (!RCellFinder.TryFindBestExitSpot(pawn, out exitSpot))
                        {
                            opts.Add(new FloatMenuOption("CannotCarryToExit".Translate(p.Label, p) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                        }
                        else
                        {
                            TaggedString taggedString2 = (p.Faction == Faction.OfPlayer || p.IsPrisonerOfColony) ? "CarryToExit".Translate(p.Label, p) : "CarryToExitAndCapture".Translate(p.Label, p);
                            opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(taggedString2, delegate
                            {
                                Job job3   = JobMaker.MakeJob(JobDefOf.CarryDownedPawnToExit, p, exitSpot);
                                job3.count = 1;
                                job3.failIfCantJoinOrCreateCaravan = true;
                                pawn.jobs.TryTakeOrderedJob(job3);
                            }, MenuOptionPriority.High), pawn, item16));
                        }
                    }
                }
            }

            if (pawn.equipment != null && pawn.equipment.Primary != null && GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForSelf(pawn), thingsOnly: true).Any())
            {
                if (pawn.IsQuestLodger() && !EquipmentUtility.QuestLodgerCanUnequip(pawn.equipment.Primary, pawn))
                {
                    opts.Add(new FloatMenuOption("CannotDrop".Translate(pawn.equipment.Primary.Label, pawn.equipment.Primary) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null));
                }
                else
                {
                    Action action5 = delegate
                    {
                        pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.DropEquipment, pawn.equipment.Primary));
                    };
                    opts.Add(new FloatMenuOption("Drop".Translate(pawn.equipment.Primary.Label, pawn.equipment.Primary), action5, MenuOptionPriority.Default, null, pawn));
                }
            }

            foreach (LocalTargetInfo item17 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForTrade(), thingsOnly: true))
            {
                if (!pawn.CanReach(item17, PathEndMode.OnCell, Danger.Deadly))
                {
                    opts.Add(new FloatMenuOption("CannotTrade".Translate() + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                }
                else if (pawn.skills.GetSkill(SkillDefOf.Social).TotallyDisabled)
                {
                    opts.Add(new FloatMenuOption("CannotPrioritizeWorkTypeDisabled".Translate(SkillDefOf.Social.LabelCap), null));
                }
                else if (!pawn.CanTradeWith(((Pawn)item17.Thing).Faction, ((Pawn)item17.Thing).TraderKind))
                {
                    opts.Add(new FloatMenuOption("CannotTradeMissingTitleAbility".Translate(), null));
                }
                else
                {
                    Pawn   pTarg   = (Pawn)item17.Thing;
                    Action action6 = delegate
                    {
                        Job job2 = JobMaker.MakeJob(JobDefOf.TradeWithPawn, pTarg);
                        job2.playerForced = true;
                        pawn.jobs.TryTakeOrderedJob(job2);
                        PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total);
                    };
                    string t2 = "";
                    if (pTarg.Faction != null)
                    {
                        t2 = " (" + pTarg.Faction.Name + ")";
                    }

                    opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("TradeWith".Translate(pTarg.LabelShort + ", " + pTarg.TraderKind.label) + t2, action6, MenuOptionPriority.InitiateSocial, null, item17.Thing), pawn, pTarg));
                }
            }

            foreach (LocalTargetInfo casket in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForOpen(pawn), thingsOnly: true))
            {
                if (!pawn.CanReach(casket, PathEndMode.OnCell, Danger.Deadly))
                {
                    opts.Add(new FloatMenuOption("CannotOpen".Translate(casket.Thing) + ": " + "NoPath".Translate().CapitalizeFirst(), null));
                }
                else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                {
                    opts.Add(new FloatMenuOption("CannotOpen".Translate(casket.Thing) + ": " + "Incapable".Translate(), null));
                }
                else if (casket.Thing.Map.designationManager.DesignationOn(casket.Thing, DesignationDefOf.Open) == null)
                {
                    opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Open".Translate(casket.Thing), delegate
                    {
                        Job job = JobMaker.MakeJob(JobDefOf.Open, casket.Thing);
                        job.ignoreDesignations = true;
                        pawn.jobs.TryTakeOrderedJob(job);
                    }, MenuOptionPriority.High), pawn, casket.Thing));
                }
            }

            foreach (Thing item18 in pawn.Map.thingGrid.ThingsAt(c))
            {
                foreach (FloatMenuOption floatMenuOption2 in item18.GetFloatMenuOptions(pawn))
                {
                    opts.Add(floatMenuOption2);
                }
            }

            void Equip()
            {
                equipment.SetForbidden(value: false);
                pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.Equip, equipment));
                MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip);
                PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total);
            }

            return(false);
        }
Ejemplo n.º 3
0
        public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
        {
            var need = pawn.needs.TryGetNeed <Need_Motivation>();

            if (pawn.timetable == null)
            {
                WorkSettings.InitWorkSettings(pawn);
            }
            if (HealthAIUtility.ShouldHaveSurgeryDoneNow(pawn))
            {
                return(ThinkResult.NoJob);
            }

            if (PrisonLaborPrefs.EnableFullHealRest && (HealthAIUtility.ShouldBeTendedNowByPlayer(pawn) || HealthAIUtility.ShouldSeekMedicalRest(pawn)))
            {
                return(ThinkResult.NoJob);
            }
            //Check medical assistance, fed, and rest if not override
            if (!PrisonLaborUtility.WorkTime(pawn))
            {
                Other.Tutorials.Timetable();
                if (need != null)
                {
                    need.IsPrisonerWorking = false;
                }
                return(ThinkResult.NoJob);
            }
            //Check motivation
            if (PrisonLaborPrefs.EnableMotivationMechanics && (need == null || need.IsLazy))
            {
                return(ThinkResult.NoJob);
            }
            //Work prisoners will do
            WorkSettings.InitWorkSettings(pawn);
            var workList = pawn.workSettings.WorkGiversInOrderNormal;

            //TODO check this
            //workList.RemoveAll(workGiver => workGiver.def.defName == "GrowerSow");
            if (need != null)
            {
                need.IsPrisonerWorking = false;
            }

            var num        = -999;
            var targetInfo = TargetInfo.Invalid;
            WorkGiver_Scanner workGiver_Scanner = null;

            for (var j = 0; j < workList.Count; j++)
            {
                var workGiver = workList[j];
                if (workGiver.def.priorityInType != num && targetInfo.IsValid)
                {
                    break;
                }
                if (PawnCanUseWorkGiver(pawn, workGiver))
                {
                    try
                    {
                        var job2 = workGiver.NonScanJob(pawn);
                        if (job2 != null)
                        {
                            if (need != null)
                            {
                                need.IsPrisonerWorking = true;
                            }
                            return(new ThinkResult(job2, this, workList[j].def.tagToGive));
                        }
                        var scanner = workGiver as WorkGiver_Scanner;
                        if (scanner != null)
                        {
                            if (workGiver.def.scanThings)
                            {
                                Predicate <Thing> predicate = t =>
                                                              !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t, false);
                                var   enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                                Thing thing;
                                if (scanner.Prioritized)
                                {
                                    var enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 =
                                            pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    var validator = predicate;
                                    thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map,
                                                                                     enumerable2, scanner.PathEndMode,
                                                                                     TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f,
                                                                                     validator, x => scanner.GetPriority(pawn, x));
                                }
                                else
                                {
                                    var validator         = predicate;
                                    var forceGlobalSearch = enumerable != null;
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                             scanner.PotentialWorkThingRequest, scanner.PathEndMode,
                                                                             TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f,
                                                                             validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, forceGlobalSearch,
                                                                             RegionType.Set_Passable, false);
                                }
                                if (thing != null)
                                {
                                    targetInfo        = thing;
                                    workGiver_Scanner = scanner;
                                }
                            }
                            if (workGiver.def.scanCells)
                            {
                                var position    = pawn.Position;
                                var num2        = 99999f;
                                var num3        = -3.40282347E+38f;
                                var prioritized = scanner.Prioritized;
                                foreach (var current in scanner.PotentialWorkCellsGlobal(pawn))
                                {
                                    var   flag = false;
                                    float num4 = (current - position).LengthHorizontalSquared;
                                    if (prioritized)
                                    {
                                        if (!current.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, current))
                                        {
                                            var priority = scanner.GetPriority(pawn, current);
                                            if (priority > num3 || priority == num3 && num4 < num2)
                                            {
                                                flag = true;
                                                num3 = priority;
                                            }
                                        }
                                    }
                                    else if (num4 < num2 && !current.IsForbidden(pawn) &&
                                             scanner.HasJobOnCell(pawn, current))
                                    {
                                        flag = true;
                                    }
                                    if (flag)
                                    {
                                        targetInfo        = new TargetInfo(current, pawn.Map, false);
                                        workGiver_Scanner = scanner;
                                        num2 = num4;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ",
                                                ex.ToString()));
                    }
                    finally
                    {
                    }
                    if (targetInfo.IsValid)
                    {
                        Job job3;
                        if (targetInfo.HasThing)
                        {
                            job3 = workGiver_Scanner.JobOnThing(pawn, targetInfo.Thing, false);
                        }
                        else
                        {
                            job3 = workGiver_Scanner.JobOnCell(pawn, targetInfo.Cell);
                        }
                        if (job3 != null)
                        {
                            job3.workGiverDef = workGiver.def;
                            if (need != null)
                            {
                                need.IsPrisonerWorking = true;
                            }
                            return(new ThinkResult(job3, this, workList[j].def.tagToGive));
                        }
                        Log.ErrorOnce(
                            string.Concat(workGiver_Scanner, " provided target ", targetInfo,
                                          " but yielded no actual job for pawn ", pawn,
                                          ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    }
                    num = workGiver.def.priorityInType;
                }
            }
            return(ThinkResult.NoJob);
        }
Ejemplo n.º 4
0
        public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false, bool ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined)
        {
            foodDef = null;
            bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

            if (!getterCanManipulate && getter != eater)
            {
                Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation."));
                return(null);
            }
            FoodPreferability minPref;

            if (minPrefOverride == FoodPreferability.Undefined)
            {
                if (eater.NonHumanlikeOrWildMan())
                {
                    minPref = FoodPreferability.NeverForNutrition;
                }
                else if (desperate)
                {
                    minPref = FoodPreferability.DesperateOnly;
                }
                else
                {
                    minPref = (((int)eater.needs.food.CurCategory >= 2) ? FoodPreferability.RawBad : FoodPreferability.MealAwful);
                }
            }
            else
            {
                minPref = minPrefOverride;
            }
            Predicate <Thing> foodValidator = delegate(Thing t)
            {
                Building_NutrientPasteDispenser building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser;
                if (building_NutrientPasteDispenser != null)
                {
                    if (!allowDispenserFull || !getterCanManipulate || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability < (int)minPref || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability > (int)maxPref || !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) || (t.Faction != getter.Faction && t.Faction != getter.HostFaction) || (!allowForbidden && t.IsForbidden(getter)) || !building_NutrientPasteDispenser.powerComp.PowerOn || (!allowDispenserEmpty && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers()) || !t.InteractionCell.Standable(t.Map) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some)))
                    {
                        return(false);
                    }
                }
                else
                {
                    int stackCount = 1;
                    if (bestFoodSourceOnMap_minNutrition_NewTemp.HasValue)
                    {
                        float statValue = t.GetStatValue(StatDefOf.Nutrition);
                        stackCount = StackCountForNutrition(bestFoodSourceOnMap_minNutrition_NewTemp.Value, statValue);
                    }
                    if ((int)t.def.ingestible.preferability < (int)minPref || (int)t.def.ingestible.preferability > (int)maxPref || !eater.WillEat(t, getter) || !t.def.IsNutritionGivingIngestible || !t.IngestibleNow || (!allowCorpse && t is Corpse) || (!allowDrug && t.def.IsDrug) || (!allowForbidden && t.IsForbidden(getter)) || (!desperate && t.IsNotFresh()) || t.IsDessicated() || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || (!getter.AnimalAwareOf(t) && !forceScanWholeMap) || (!ignoreReservations && !getter.CanReserve(t, 10, stackCount)))
                    {
                        return(false);
                    }
                }
                return(true);
            };
            ThingRequest thingRequest = ((!((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != 0 && allowPlant)) ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource));
            Thing        bestThing;

            if (getter.RaceProps.Humanlike)
            {
                bestThing = SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, foodValidator);
                if (allowHarvest && getterCanManipulate)
                {
                    Thing thing = GenClosest.ClosestThingReachable(searchRegionsMax : (!forceScanWholeMap || bestThing != null) ? 30 : (-1), root : getter.Position, map : getter.Map, thingReq : ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), peMode : PathEndMode.Touch, traverseParams : TraverseParms.For(getter), maxDistance : 9999f, validator : delegate(Thing x)
                    {
                        Plant plant = (Plant)x;
                        if (!plant.HarvestableNow)
                        {
                            return(false);
                        }
                        ThingDef harvestedThingDef = plant.def.plant.harvestedThingDef;
                        if (!harvestedThingDef.IsNutritionGivingIngestible)
                        {
                            return(false);
                        }
                        if (!eater.WillEat(harvestedThingDef, getter))
                        {
                            return(false);
                        }
                        if (!getter.CanReserve(plant))
                        {
                            return(false);
                        }
                        if (!allowForbidden && plant.IsForbidden(getter))
                        {
                            return(false);
                        }
                        return((bestThing == null || (int)GetFinalIngestibleDef(bestThing).ingestible.preferability < (int)harvestedThingDef.ingestible.preferability) ? true : false);
                    });
                    if (thing != null)
                    {
                        bestThing = thing;
                        foodDef   = GetFinalIngestibleDef(thing, harvest: true);
                    }
                }
                if (foodDef == null && bestThing != null)
                {
                    foodDef = GetFinalIngestibleDef(bestThing);
                }
            }
            else
            {
                int maxRegionsToScan = GetMaxRegionsToScan(getter, forceScanWholeMap);
                filtered.Clear();
                foreach (Thing item in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, useCenter: true))
                {
                    Pawn pawn = item 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, cellTarget: true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null;
                Predicate <Thing> validator         = delegate(Thing t)
                {
                    if (!foodValidator(t))
                    {
                        return(false);
                    }
                    if (filtered.Contains(t))
                    {
                        return(false);
                    }
                    if (!(t is Building_NutrientPasteDispenser) && (int)t.def.ingestible.preferability <= 2)
                    {
                        return(false);
                    }
                    return((!t.IsNotFresh()) ? true : false);
                };
                bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, validator, null, 0, maxRegionsToScan, forceAllowGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                filtered.Clear();
                if (bestThing == null)
                {
                    desperate = true;
                    bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, foodValidator, null, 0, maxRegionsToScan, forceAllowGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                }
                if (bestThing != null)
                {
                    foodDef = GetFinalIngestibleDef(bestThing);
                }
            }
            return(bestThing);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Finds the closest Thing on the map to a pawn that matches the ThingDef needed by the Bill.
        /// The available ingredients are cached in the BillProcessor variable in Building_GrowerBase_WorkTable.
        /// If the cached ThingDef is no longer available, it will look for another ThingDef that's needed.
        /// </summary>
        /// <param name="theBill"></param>
        /// <param name="finder"></param>
        /// <param name="countForVat"></param>
        /// <returns></returns>
        public static Thing ThingPawnShouldRetrieveForBill(Bill theBill, Pawn finder, ref int countForVat)
        {
            Building_GrowerBase_WorkTable vat = theBill.billStack.billGiver as Building_GrowerBase_WorkTable;
            ThingOwner vatStoredIngredients   = vat.GetDirectlyHeldThings();

            Thing cachedThing     = null;
            bool  ingAreAvailable = vat.billProc.ingredientsAvailableNow.TryGetValue(theBill.GetUniqueLoadID(), out cachedThing);

            if (cachedThing == null)
            {
                QEEMod.TryLog("ThingPawnShouldRetrieveForBill() returning null. Reason - cachedThing is null");
                return(null);
            }

            if (ingAreAvailable == false)
            {
                QEEMod.TryLog("ThingPawnShouldRetrieveForBill() returning null. Reason - ingAreAvailable is false");
                return(null);
            }

            ThingRequest      tRequest;
            ThingOrderRequest desiredRequest;

            vat.billProc.desiredRequests.TryGetValue(cachedThing.def.defName, out desiredRequest);

            //check that the vat still needs the cached ingredient before searching the map for the same ThingDef
            if (desiredRequest == null || desiredRequest.amount <= 0)
            {
                QEEMod.TryLog("Cached ingredient " + cachedThing.LabelShort + " is already fulfilled in vat. Looking for next ingredient in recipe");

                //this ingredient isn't in desiredIngredients or the vat has the full amount. Refresh desiredIngredients and try once more
                vat.billProc.UpdateDesiredRequests();

                //now get a random item in the dictionary of desired requests
                foreach (ThingOrderRequest value in vat.billProc.desiredRequests.Values)
                {
                    desiredRequest = value;
                }

                //return if there's no thingDef or desiredRequest is null
                if (desiredRequest == null)
                {
                    QEEMod.TryLog("ThingPawnShouldRetrieveForBill() returning null. Reason - Desired ThingOrderRequest is null");
                    return(null);
                }

                //return if the amount for this request is 0
                if (desiredRequest.amount <= 0)
                {
                    QEEMod.TryLog("ThingPawnShouldRetrieveForBill() returning null. Reason - Desired Thing " + desiredRequest.Label + " has 0 amount");
                    return(null);
                }
            }

            tRequest = desiredRequest.GetThingRequest();

            if (tRequest.IsUndefined)
            {
                QEEMod.TryLog("ThingPawnShouldRetrieveForBill() returning null. Reason - ThingRequest for " + desiredRequest.Label +
                              " returned undefined ThingRequest");
                return(null);
            }

            countForVat = desiredRequest.amount;


            QEEMod.TryLog("Searching map for closest " + desiredRequest.Label + " to " + finder.LabelShort);

            //search the map for the closest Thing to the pawn that matches the ThingDef in 'tRequest'
            Thing result = GenClosest.ClosestThingReachable(finder.Position, finder.Map, tRequest,
                                                            PathEndMode.OnCell, TraverseParms.For(finder),
                                                            validator :
                                                            delegate(Thing testThing)
            {
                if (tRequest.Accepts(testThing))
                {
                    if (testThing.IsForbidden(finder))
                    {
                        return(false);
                    }

                    if (!finder.CanReserve(testThing))
                    {
                        return(false);
                    }
                    return(true);
                }

                return(false);
            });

            if (result != null)
            {
                QEEMod.TryLog(finder.LabelShort + " should retrieve: " + result.Label + " | stackCount: " + result.stackCount +
                              " | countForVat: " + countForVat);
            }

            return(result);
        } //end FindClosestIngForBill
Ejemplo n.º 6
0
        /// <summary>
        ///     Gets the best food source on the map for the given getter and eater pawns
        /// </summary>
        /// this function gets the best food source on the map for the given pawns, making sure to optimize for the case where
        /// a humanoid pawn can eat plants
        /// <param name="getter">The getter.</param>
        /// <param name="eater">The eater.</param>
        /// <param name="desperate">if set to <c>true</c> [desperate].</param>
        /// <param name="foodDef">The food definition.</param>
        /// <param name="maxPref">The maximum preference.</param>
        /// <param name="allowPlant">if set to <c>true</c> [allow plant].</param>
        /// <param name="allowDrug">if set to <c>true</c> [allow drug].</param>
        /// <param name="allowCorpse">if set to <c>true</c> [allow corpse].</param>
        /// <param name="allowDispenserFull">if set to <c>true</c> [allow dispenser full].</param>
        /// <param name="allowDispenserEmpty">if set to <c>true</c> [allow dispenser empty].</param>
        /// <param name="allowForbidden">if set to <c>true</c> [allow forbidden].</param>
        /// <param name="allowSociallyImproper">if set to <c>true</c> [allow socially improper].</param>
        /// <param name="allowHarvest">if set to <c>true</c> [allow harvest].</param>
        /// <param name="forceScanWholeMap">if set to <c>true</c> [force scan whole map].</param>
        /// <param name="ignoreReservations">if set to <c>true</c> [ignore reservations].</param>
        /// <param name="minPrefOverride">The minimum preference override.</param>
        /// <returns></returns>
        public static Thing BestFoodSourceOnMapOptimized(
            [NotNull] Pawn getter,
            [NotNull] Pawn eater,
            bool desperate,
            out ThingDef foodDef,
            FoodPreferability maxPref         = FoodPreferability.MealLavish,
            bool allowPlant                   = true,
            bool allowDrug                    = true,
            bool allowCorpse                  = true,
            bool allowDispenserFull           = true,
            bool allowDispenserEmpty          = true,
            bool allowForbidden               = false,
            bool allowSociallyImproper        = false,
            bool allowHarvest                 = false,
            bool forceScanWholeMap            = false,
            bool ignoreReservations           = false,
            FoodPreferability minPrefOverride = FoodPreferability.Undefined)
        {
            foodDef = null;
            HungerCategory foodCurCategory     = eater.needs.food.CurCategory;
            bool           getterCanManipulate = getter.IsToolUser() && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

            if (!getterCanManipulate && getter != eater)
            {
                Log.Error(getter
                          + " tried to find food to bring to "
                          + eater
                          + " but "
                          + getter
                          + " is incapable of Manipulation.");
                return(null);
            }

            FoodPreferability minPref;

            if (minPrefOverride != FoodPreferability.Undefined)
            {
                minPref = minPrefOverride;
            }
            else if (!eater.NonHumanlikeOrWildMan()) //with the new patch, to 'recruit' sapient former humans pawns will need
            {
                if (!desperate)
                {
                    if (foodCurCategory >= HungerCategory.UrgentlyHungry)
                    {
                        minPref = FoodPreferability.RawBad;
                    }
                    else
                    {
                        minPref = FoodPreferability.MealAwful;
                    }
                }
                else
                {
                    minPref = FoodPreferability.DesperateOnly;
                }
            }
            else
            {
                minPref = FoodPreferability.NeverForNutrition;
            }

            bool FoodValidator(Thing t)
            {
                if (allowDispenserFull && getterCanManipulate && t is Building_NutrientPasteDispenser nutrientPDispenser)
                {
                    if (ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref ||
                        ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref ||
                        !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) ||
                        t.Faction != getter.Faction && t.Faction != getter.HostFaction ||
                        !allowForbidden && t.IsForbidden(getter) ||
                        !nutrientPDispenser.powerComp.PowerOn ||
                        !allowDispenserEmpty && !nutrientPDispenser.HasEnoughFeedstockInHoppers() ||
                        !t.InteractionCell.Standable(t.Map) ||
                        !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) ||
                        !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map),
                                                                  PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some)))
                    {
                        return(false);
                    }
                }
                else
                {
                    FoodPreferability pref = GetAdjustedPreferability(eater, t);
                    if (pref < minPref ||
                        pref > maxPref)
                    {
                        return(false);
                    }

                    if (!eater.WillEat(t, getter))
                    {
                        return(false);
                    }

                    if (!t.def.IsNutritionGivingIngestible || !t.IngestibleNow)
                    {
                        return(false);
                    }

                    if (!allowCorpse && t is Corpse ||
                        !allowDrug && t.def.IsDrug ||
                        !allowForbidden && t.IsForbidden(getter) ||
                        !desperate && t.IsNotFresh() ||
                        t.IsDessicated() ||
                        !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) ||
                        !getter.AnimalAwareOf(t) && !forceScanWholeMap ||
                        !ignoreReservations && !getter.CanReserve((LocalTargetInfo)t, 10, 1))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            ThingRequest thingRequest;

            if (!CanEatPlants(eater, allowPlant, foodCurCategory))
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            }
            else
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource);
            }
            Thing bestThing;

            if (getter.IsHumanlike())
            {
                //TODO split up search for hungry humanlike into 2 phases
                //whole map search for good food
                //small search for good plants
                bestThing = SpawnedFoodSearchInnerScan(eater, getter.Position,
                                                       getter.Map.listerThings.ThingsMatching(thingRequest),
                                                       PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, FoodValidator);



                if (allowHarvest & getterCanManipulate)
                {
                    int searchRegionsMax = !forceScanWholeMap || bestThing != null ? 30 : -1;

                    bool HarvestValidator(Thing x)
                    {
                        var t = (Plant)x;

                        if (!t.HarvestableNow)
                        {
                            return(false);
                        }
                        ThingDef harvestedThingDef = t.def.plant.harvestedThingDef;

                        return(harvestedThingDef.IsNutritionGivingIngestible &&
                               eater.WillEat(harvestedThingDef, getter) &&
                               getter.CanReserve((LocalTargetInfo)t) &&
                               (allowForbidden || !t.IsForbidden(getter)) &&
                               (bestThing == null ||
                                FoodUtility.GetFinalIngestibleDef(bestThing)
                                .ingestible.preferability
                                < harvestedThingDef.ingestible.preferability));
                    }

                    Thing foodSource = GenClosest.ClosestThingReachable(getter.Position, getter.Map,
                                                                        ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant),
                                                                        PathEndMode.Touch, TraverseParms.For(getter), 9999f,
                                                                        HarvestValidator, null, 0, searchRegionsMax);
                    if (foodSource != null)
                    {
                        bestThing = foodSource;
                        foodDef   = FoodUtility.GetFinalIngestibleDef(foodSource, true);
                    }
                }

                if (foodDef == null && bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing);
                }
            }
            else
            {
                int maxRegionsToScan =
                    GetMaxRegionsToScan(getter, forceScanWholeMap, foodCurCategory); //this is where the lag comes from
                //humanlikes alwayse scan the whole map
                filtered.Clear();
                foreach (Thing thing in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
                {
                    var pawn = thing 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?.EffectiveAreaRestrictionInPawnCurrentMap != null;
                var validator = (Predicate <Thing>)(t => FoodValidator(t) &&
                                                    !filtered.Contains(t) &&
                                                    (t is Building_NutrientPasteDispenser ||
                                                     t.def.ingestible.preferability > FoodPreferability.DesperateOnly) &&
                                                    !t.IsNotFresh());
                bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch,
                                                             TraverseParms.For(getter), 9999f, validator, null, 0,
                                                             maxRegionsToScan, false, RegionType.Set_Passable,
                                                             ignoreEntirelyForbiddenRegions);
                filtered.Clear();
                if (bestThing == null)
                {
                    desperate = true;
                    bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest,
                                                                 PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f,
                                                                 FoodValidator, null, 0, maxRegionsToScan, false,
                                                                 RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
                }

                if (bestThing != null)
                {
                    foodDef = FoodUtility.GetFinalIngestibleDef(bestThing);
                }
            }

            return(bestThing);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (!Controller.settings.EnableAmmoSystem || !Controller.settings.AutoTakeAmmo)
            {
                return(null);
            }

            if (pawn.Faction == null) //Wild man (b19 incident added) Faction is null
            {
                return(null);
            }

            if (!pawn.RaceProps.Humanlike || (pawn.story != null && pawn.WorkTagIsDisabled(WorkTags.Violent)))
            {
                return(null);
            }
            if (pawn.Faction.IsPlayer && pawn.Drafted)
            {
                return(null);
            }

            if (!Rand.MTBEventOccurs(60, 5, 30))
            {
                return(null);
            }

            if (!pawn.Faction.IsPlayer && FindBattleWorthyEnemyPawnsCount(Find.CurrentMap, pawn) > 25)
            {
                return(null);
            }
            if (pawn.IsPrisoner && (pawn.HostFaction != Faction.OfPlayer || pawn.guest.interactionMode == PrisonerInteractionModeDefOf.Release))
            {
                return(null);
            }

            //Log.Message(pawn.ThingID +  " - priority:" + (GetPriorityWork(pawn)).ToString() + " capacityWeight: " + pawn.TryGetComp<CompInventory>().capacityWeight.ToString() + " currentWeight: " + pawn.TryGetComp<CompInventory>().currentWeight.ToString() + " capacityBulk: " + pawn.TryGetComp<CompInventory>().capacityBulk.ToString() + " currentBulk: " + pawn.TryGetComp<CompInventory>().currentBulk.ToString());

            var           brawler         = (pawn.story != null && pawn.story.traits != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler));
            CompInventory inventory       = pawn.TryGetComp <CompInventory>();
            bool          hasPrimary      = (pawn.equipment != null && pawn.equipment.Primary != null);
            CompAmmoUser  primaryAmmoUser = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null;
            CompAmmoUser  primaryAmmoUserWithInventoryCheck = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : hasWeaponInInventory(pawn) ? weaponInInventory(pawn) : null;

            if (inventory != null)
            {
                // Prefer ranged weapon in inventory
                if (!pawn.Faction.IsPlayer && hasPrimary && pawn.equipment.Primary.def.IsMeleeWeapon && !brawler)
                {
                    if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level ||
                         pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6))
                    {
                        ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine);
                        if (InvListGun3 != null)
                        {
                            inventory.TrySwitchToWeapon(InvListGun3);
                        }
                    }
                }

                // Equip weapon if no any weapon
                if (!pawn.Faction.IsPlayer && !hasPrimary)
                {
                    // For ranged weapon
                    if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level ||
                         pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6) && !brawler)
                    {
                        ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine);
                        if (InvListGun3 != null)
                        {
                            inventory.TrySwitchToWeapon(InvListGun3);
                        }
                    }
                    else
                    {
                        // For melee weapon
                        ThingWithComps InvListMeleeWeapon = inventory.meleeWeaponList.Find(thing => thing.def.IsMeleeWeapon);
                        if (InvListMeleeWeapon != null)
                        {
                            inventory.TrySwitchToWeapon(InvListMeleeWeapon);
                        }
                    }
                }

                var priority = GetPriorityWork(pawn);

                // Drop excess ranged weapon
                if (!pawn.Faction.IsPlayer && primaryAmmoUser != null && priority == WorkPriority.Unloading && inventory.rangedWeaponList.Count >= 1)
                {
                    Thing ListGun = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def);
                    if (ListGun != null)
                    {
                        Thing ammoListGun = null;
                        if (!ListGun.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine)
                        {
                            foreach (AmmoLink link in ListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                            {
                                if (inventory.ammoList.Find(thing => thing.def == link.ammo) == null)
                                {
                                    ammoListGun = ListGun;
                                    break;
                                }
                            }
                        }
                        if (ammoListGun != null)
                        {
                            Thing droppedWeapon;
                            if (inventory.container.TryDrop(ListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ListGun.stackCount, out droppedWeapon))
                            {
                                pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, droppedWeapon, 30, true));
                            }
                        }
                    }
                }

                // Find and drop not need ammo from inventory
                if (!pawn.Faction.IsPlayer && hasPrimary && inventory.ammoList.Count > 1 && priority == WorkPriority.Unloading)
                {
                    Thing WrongammoThing = null;
                    WrongammoThing = primaryAmmoUser != null
                        ? inventory.ammoList.Find(thing => !primaryAmmoUser.Props.ammoSet.ammoTypes.Any(a => a.ammo == thing.def))
                        : inventory.ammoList.RandomElement <Thing>();

                    if (WrongammoThing != null)
                    {
                        Thing InvListGun = inventory.rangedWeaponList.Find(thing => hasPrimary && thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def);
                        if (InvListGun != null)
                        {
                            Thing ammoInvListGun = null;
                            foreach (AmmoLink link in InvListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                            {
                                ammoInvListGun = inventory.ammoList.Find(thing => thing.def == link.ammo);
                                break;
                            }
                            if (ammoInvListGun != null && ammoInvListGun != WrongammoThing)
                            {
                                Thing droppedThingAmmo;
                                if (inventory.container.TryDrop(ammoInvListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ammoInvListGun.stackCount, out droppedThingAmmo))
                                {
                                    pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                    pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, 30, true));
                                }
                            }
                        }
                        else
                        {
                            Thing droppedThing;
                            if (inventory.container.TryDrop(WrongammoThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, WrongammoThing.stackCount, out droppedThing))
                            {
                                pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, 30, true));
                            }
                        }
                    }
                }

                Room room = RegionAndRoomQuery.RoomAtFast(pawn.Position, pawn.Map);

                // Find weapon in inventory and try to switch if any ammo in inventory.
                if (priority == WorkPriority.Weapon && !hasPrimary)
                {
                    ThingWithComps InvListGun2 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null);

                    if (InvListGun2 != null)
                    {
                        Thing ammoInvListGun2 = null;
                        foreach (AmmoLink link in InvListGun2.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                        {
                            ammoInvListGun2 = inventory.ammoList.Find(thing => thing.def == link.ammo);
                            break;
                        }
                        if (ammoInvListGun2 != null)
                        {
                            inventory.TrySwitchToWeapon(InvListGun2);
                        }
                    }

                    // Find weapon with near ammo for ai.
                    if (!pawn.Faction.IsPlayer)
                    {
                        Predicate <Thing> validatorWS = (Thing w) => w.def.IsWeapon &&
                                                        w.MarketValue > 500 && pawn.CanReserve(w, 1) &&
                                                        pawn.Position.InHorDistOf(w.Position, 25f) &&
                                                        pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) &&
                                                        (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[w.Position]);

                        // generate a list of all weapons (this includes melee weapons)
                        List <Thing> allWeapons = (
                            from w in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                            where validatorWS(w)
                            orderby w.MarketValue - w.Position.DistanceToSquared(pawn.Position) * 2f descending
                            select w
                            ).ToList();

                        // now just get the ranged weapons out...
                        List <Thing> rangedWeapons = allWeapons.Where(w => w.def.IsRangedWeapon).ToList();

                        if (!rangedWeapons.NullOrEmpty())
                        {
                            foreach (Thing thing in rangedWeapons)
                            {
                                if (thing.TryGetComp <CompAmmoUser>() == null)
                                {
                                    // pickup a non-CE ranged weapon...
                                    int numToThing = 0;
                                    if (inventory.CanFitInInventory(thing, out numToThing))
                                    {
                                        return(new Job(JobDefOf.Equip, thing));
                                    }
                                }
                                else
                                {
                                    // pickup a CE ranged weapon...
                                    List <ThingDef> thingDefAmmoList = thing.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes.Select(g => g.ammo as ThingDef).ToList();

                                    Predicate <Thing> validatorA = (Thing t) => t.def.category == ThingCategory.Item &&
                                                                   t is AmmoThing && pawn.CanReserve(t, 1) &&
                                                                   pawn.Position.InHorDistOf(t.Position, 25f) &&
                                                                   pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) &&
                                                                   (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]);

                                    List <Thing> thingAmmoList = (
                                        from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                                        where validatorA(t)
                                        select t
                                        ).ToList();

                                    if (thingAmmoList.Count > 0 && thingDefAmmoList.Count > 0)
                                    {
                                        int   desiredStackSize = thing.TryGetComp <CompAmmoUser>().Props.magazineSize * 2;
                                        Thing th = thingAmmoList.FirstOrDefault(x => thingDefAmmoList.Contains(x.def) && x.stackCount > desiredStackSize);
                                        if (th != null)
                                        {
                                            int numToThing = 0;
                                            if (inventory.CanFitInInventory(thing, out numToThing))
                                            {
                                                return(new Job(JobDefOf.Equip, thing));
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // else if no ranged weapons with nearby ammo was found, lets consider a melee weapon.
                        if (allWeapons != null && allWeapons.Count > 0)
                        {
                            // since we don't need to worry about ammo, just pick one.
                            Thing meleeWeapon = allWeapons.FirstOrDefault(w => !w.def.IsRangedWeapon && w.def.IsMeleeWeapon);

                            if (meleeWeapon != null)
                            {
                                return(new Job(JobDefOf.Equip, meleeWeapon));
                            }
                        }
                    }
                }

                // Find ammo
                if ((priority == WorkPriority.Ammo || priority == WorkPriority.LowAmmo) &&
                    primaryAmmoUserWithInventoryCheck != null)
                {
                    List <ThingDef> curAmmoList = (from AmmoLink g in primaryAmmoUserWithInventoryCheck.Props.ammoSet.ammoTypes
                                                   select g.ammo as ThingDef).ToList();

                    if (curAmmoList.Count > 0)
                    {
                        Predicate <Thing> validator = (Thing t) => t is AmmoThing && pawn.CanReserve(t, 1) &&
                                                      pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) &&
                                                      ((pawn.Faction.IsPlayer && !ForbidUtility.IsForbidden(t, pawn)) || (!pawn.Faction.IsPlayer && pawn.Position.InHorDistOf(t.Position, 35f))) &&
                                                      (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]);
                        List <Thing> curThingList = (
                            from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                            where validator(t)
                            select t
                            ).ToList();
                        foreach (Thing th in curThingList)
                        {
                            foreach (ThingDef thd in curAmmoList)
                            {
                                if (thd == th.def)
                                {
                                    //Defence from low count loot spam
                                    float thw = (th.GetStatValue(CE_StatDefOf.Bulk)) * th.stackCount;
                                    if (thw > 0.5f)
                                    {
                                        if (pawn.Faction.IsPlayer)
                                        {
                                            int SearchRadius = 0;
                                            if (priority == WorkPriority.LowAmmo)
                                            {
                                                SearchRadius = 70;
                                            }
                                            else
                                            {
                                                SearchRadius = 30;
                                            }

                                            Thing closestThing = GenClosest.ClosestThingReachable(
                                                pawn.Position,
                                                pawn.Map,
                                                ThingRequest.ForDef(th.def),
                                                PathEndMode.ClosestTouch,
                                                TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                                                SearchRadius,
                                                x => !x.IsForbidden(pawn) && pawn.CanReserve(x));

                                            if (closestThing != null)
                                            {
                                                int numToCarry = 0;
                                                if (inventory.CanFitInInventory(th, out numToCarry))
                                                {
                                                    return(new Job(JobDefOf.TakeInventory, th)
                                                    {
                                                        count = numToCarry
                                                    });
                                                }
                                            }
                                        }
                                        else
                                        {
                                            int numToCarry = 0;
                                            if (inventory.CanFitInInventory(th, out numToCarry))
                                            {
                                                return(new Job(JobDefOf.TakeInventory, th)
                                                {
                                                    count = Mathf.RoundToInt(numToCarry * 0.8f)
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                /*
                 * if (!pawn.Faction.IsPlayer && pawn.apparel != null && priority == WorkPriority.Apparel)
                 * {
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso))
                 *  {
                 *      Apparel apparel = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Torso);
                 *      if (apparel != null)
                 *      {
                 *          int numToapparel = 0;
                 *          if (inventory.CanFitInInventory(apparel, out numToapparel))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel)
                 *              {
                 *                  ignoreForbidden = true
                 *              };
                 *          }
                 *      }
                 *  }
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Legs))
                 *  {
                 *      Apparel apparel2 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Legs);
                 *      if (apparel2 != null)
                 *      {
                 *          int numToapparel2 = 0;
                 *          if (inventory.CanFitInInventory(apparel2, out numToapparel2))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel2)
                 *              {
                 *                  ignoreForbidden = true
                 *              };
                 *          }
                 *      }
                 *  }
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.FullHead))
                 *  {
                 *      Apparel apparel3 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.FullHead);
                 *      if (apparel3 != null)
                 *      {
                 *          int numToapparel3 = 0;
                 *          if (inventory.CanFitInInventory(apparel3, out numToapparel3))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel3)
                 *              {
                 *                  ignoreForbidden = true,
                 *                  locomotionUrgency = LocomotionUrgency.Sprint
                 *              };
                 *          }
                 *      }
                 *  }
                 * }
                 */
                return(null);
            }
            return(null);
        }
Ejemplo n.º 8
0
 private Thing FindClosestComponent(Pawn pawn)
 {
     return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(ThingDefOf.ComponentIndustrial), PathEndMode.InteractionCell, TraverseParms.For(pawn, pawn.NormalMaxDanger(), TraverseMode.ByPawn, false), 9999f, (Thing x) => !x.IsForbidden(pawn) && pawn.CanReserve(x, 1, -1, null, false), null, 0, -1, false, RegionType.Set_Passable, false));
 }
Ejemplo n.º 9
0
        public static Thing ClosestReachableEgg(Pawn pawn)
        {
            Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(XenomorphDefOf.RRY_EggXenomorphFertilized), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 9999f, null, null, 0, -1, false, RegionType.Set_Passable, false);

            return(thing);
        }
 private Thing FindDrugFor(Pawn pawn, ThingDef drugDef)
 {
     return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(drugDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, (Thing x) => DrugValidator(pawn, x)));
 }
        public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
        {
            X2_AIRobot robot = pawn as X2_AIRobot;

            if (robot == null || !robot.Spawned || robot.Destroyed || robot.GetWorkGivers(false) == null)
            {
                return(ThinkResult.NoJob);
            }

            //Profiler.BeginSample("JobGiver_Work");

            //if (this.emergency && pawn.mindState.priorityWork.IsPrioritized)
            //{
            //    List<WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkType.workGiversByPriority;
            //    for (int i = 0; i < workGiversByPriority.Count; i++)
            //    {
            //        WorkGiver worker = workGiversByPriority[i].Worker;
            //        Job job = this.GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
            //        if (job != null)
            //        {
            //            job.playerForced = true;
            //            return new ThinkResult(job, this, new JobTag?(workGiversByPriority[i].tagToGive), false);
            //        }
            //    }
            //    pawn.mindState.priorityWork.Clear();
            //}


            List <WorkGiver> list               = robot.GetWorkGivers(false); // Get Non-Emergency WorkGivers
            int               num               = -999;
            TargetInfo        targetInfo        = TargetInfo.Invalid;
            WorkGiver_Scanner workGiver_Scanner = null;
            WorkGiver_Scanner scanner;

            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && targetInfo.IsValid)
                {
                    break;
                }
                if (PawnCanUseWorkGiver(pawn, workGiver))
                {
                    //Profiler.BeginSample("WorkGiver: " + workGiver.def.defName);
                    try
                    {
                        Job job2 = workGiver.NonScanJob(pawn);
                        if (job2 != null)
                        {
                            return(new ThinkResult(job2, this, list[j].def.tagToGive, false));
                        }
                        scanner = (workGiver as WorkGiver_Scanner);
                        if (scanner != null)
                        {
                            IntVec3 intVec;
                            if (scanner.def.scanThings)
                            {
                                Predicate <Thing>   predicate  = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t, false);
                                IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                                Thing thing;
                                if (scanner.Prioritized)
                                {
                                    IEnumerable <Thing> enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    if (scanner.AllowUnreachable)
                                    {
                                        intVec = pawn.Position;
                                        IEnumerable <Thing> searchSet = enumerable2;
                                        Predicate <Thing>   validator = predicate;
                                        try
                                        {
                                            thing = GenClosest.ClosestThing_Global(intVec, searchSet, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x));
                                        }
                                        catch //(Exception ex)
                                        {
                                            //Log.Warning(string.Concat(new object[]
                                            //{
                                            //    pawn,
                                            //    " threw exception in WorkGiver ",
                                            //    workGiver.def.defName,
                                            //    ": ",
                                            //    ex.ToString()
                                            //}));

                                            thing = null;
                                        }
                                    }
                                    else
                                    {
                                        intVec = pawn.Position;
                                        Map map = pawn.Map;
                                        IEnumerable <Thing> searchSet      = enumerable2;
                                        PathEndMode         pathEndMode    = scanner.PathEndMode;
                                        TraverseParms       traverseParams = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn), TraverseMode.ByPawn, false);
                                        Predicate <Thing>   validator      = predicate;
                                        try
                                        {
                                            thing = GenClosest.ClosestThing_Global_Reachable(intVec, map, searchSet, pathEndMode, traverseParams, 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x));
                                        }
                                        catch //(Exception ex)
                                        {
                                            //Log.Warning(string.Concat(new object[]
                                            //{
                                            //    pawn,
                                            //    " threw exception in WorkGiver ",
                                            //    workGiver.def.defName,
                                            //    ": ",
                                            //    ex.ToString()
                                            //}));

                                            thing = null;
                                        }
                                    }
                                }
                                else if (scanner.AllowUnreachable)
                                {
                                    IEnumerable <Thing> enumerable3 = enumerable;
                                    if (enumerable3 == null)
                                    {
                                        enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    intVec = pawn.Position;
                                    IEnumerable <Thing> searchSet = enumerable3;
                                    Predicate <Thing>   validator = predicate;
                                    try
                                    {
                                        thing = GenClosest.ClosestThing_Global(intVec, searchSet, 99999f, validator, null);
                                    }
                                    catch //(Exception ex)
                                    {
                                        //Log.Warning(string.Concat(new object[]
                                        //{
                                        //    pawn,
                                        //    " threw exception in WorkGiver ",
                                        //    workGiver.def.defName,
                                        //    ": ",
                                        //    ex.ToString()
                                        //}));

                                        thing = null;
                                    }
                                }
                                else
                                {
                                    intVec = pawn.Position;
                                    Map               map = pawn.Map;
                                    ThingRequest      potentialWorkThingRequest = scanner.PotentialWorkThingRequest;
                                    PathEndMode       pathEndMode       = scanner.PathEndMode;
                                    TraverseParms     traverseParams    = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn), TraverseMode.ByPawn, false);
                                    Predicate <Thing> validator         = predicate;
                                    bool              forceGlobalSearch = enumerable != null;
                                    try
                                    {
                                        thing = GenClosest.ClosestThingReachable(intVec, map, potentialWorkThingRequest, pathEndMode, traverseParams, 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, forceGlobalSearch, RegionType.Set_Passable, false);
                                    }
                                    catch //(Exception ex)
                                    {
                                        //Log.Warning(string.Concat(new object[]
                                        //{
                                        //    pawn,
                                        //    " threw exception in WorkGiver ",
                                        //    workGiver.def.defName,
                                        //    ": ",
                                        //    ex.ToString()
                                        //}));

                                        thing = null;
                                    }
                                }
                                if (thing != null)
                                {
                                    targetInfo        = thing;
                                    workGiver_Scanner = scanner;
                                }
                            }
                            if (scanner.def.scanCells)
                            {
                                IntVec3 position         = pawn.Position;
                                float   num2             = 99999f;
                                float   num3             = -3.40282347E+38f;
                                bool    prioritized      = scanner.Prioritized;
                                bool    allowUnreachable = scanner.AllowUnreachable;
                                Danger  maxDanger        = scanner.MaxPathDanger(pawn);
                                foreach (IntVec3 item in scanner.PotentialWorkCellsGlobal(pawn))
                                {
                                    bool flag = false;
                                    intVec = item - position;
                                    float num4 = (float)intVec.LengthHorizontalSquared;
                                    float num5 = 0f;
                                    if (prioritized)
                                    {
                                        if (!item.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, item, false))
                                        {
                                            if (!allowUnreachable && !pawn.CanReach(item, scanner.PathEndMode, maxDanger, false, TraverseMode.ByPawn))
                                            {
                                                continue;
                                            }
                                            num5 = scanner.GetPriority(pawn, item);
                                            if (num5 > num3 || (num5 == num3 && num4 < num2))
                                            {
                                                flag = true;
                                            }
                                        }
                                    }
                                    else if (num4 < num2 && !item.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, item, false))
                                    {
                                        if (!allowUnreachable && !pawn.CanReach(item, scanner.PathEndMode, maxDanger, false, TraverseMode.ByPawn))
                                        {
                                            continue;
                                        }
                                        flag = true;
                                    }
                                    if (flag)
                                    {
                                        targetInfo        = new TargetInfo(item, pawn.Map, false);
                                        workGiver_Scanner = scanner;
                                        num2 = num4;
                                        num3 = num5;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(pawn + " threw exception in WorkGiver " + workGiver.def.defName + ": " + ex.ToString(), false);
                    }
                    finally
                    {
                        //Profiler.EndSample();
                    }
                    if (targetInfo.IsValid)
                    {
                        //Profiler.EndSample();
                        Job job3 = null;
                        try
                        {
                            //pawn.mindState.lastGivenWorkType = workGiver.def.workType;
                            job3 = (!targetInfo.HasThing) ? workGiver_Scanner.JobOnCell(pawn, targetInfo.Cell, false) : workGiver_Scanner.JobOnThing(pawn, targetInfo.Thing, false);
                        }
                        catch //(Exception ex)
                        {
                            //Log.Warning(string.Concat(new object[]
                            //{
                            //    pawn,
                            //    " threw exception in WorkGiver ",
                            //    workGiver.def.defName,
                            //    " in JobOnX: ",
                            //    ex.ToString()
                            //}));

                            // Error --> Force NoJob
                            return(ThinkResult.NoJob);
                        }
                        if (job3 != null)
                        {
                            return(new ThinkResult(job3, this, list[j].def.tagToGive, false));
                        }
                        Log.ErrorOnce(workGiver_Scanner + " provided target " + targetInfo + " but yielded no actual job for pawn " + pawn + ". The CanGiveJob and JobOnX methods may not be synchronized.", 6112651, false);
                    }
                    num = workGiver.def.priorityInType;
                }
            }
            return(ThinkResult.NoJob);
        }
        public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
        {
            X2_AIRobot robot = pawn as X2_AIRobot;

            if (robot == null || !robot.Spawned || robot.Destroyed || robot.GetWorkGivers(false) == null)
            {
                return(ThinkResult.NoJob);
            }

            //Profiler.BeginSample("JobGiver_Work");

            //if (emergency && pawn.mindState.priorityWork.IsPrioritized)
            //{
            //	List<WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
            //	for (int i = 0; i < workGiversByPriority.Count; i++)
            //	{
            //		WorkGiver worker = workGiversByPriority[i].Worker;
            //		if (WorkGiversRelated(pawn.mindState.priorityWork.WorkGiver, worker.def))
            //		{
            //			Job job = GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
            //			if (job != null)
            //			{
            //				job.playerForced = true;
            //				return new ThinkResult(job, this, workGiversByPriority[i].tagToGive);
            //			}
            //		}
            //	}
            //	pawn.mindState.priorityWork.Clear();
            //}



            List <WorkGiver> list = robot.GetWorkGivers(false); // Get Non-Emergency WorkGivers
            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            WorkGiver_Scanner scanner;
            IntVec3           pawnPosition;
            bool              prioritized;
            bool              allowUnreachable;
            Danger            maxPathDanger;

            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }
                if (!PawnCanUseWorkGiver(pawn, workGiver))
                {
                    continue;
                }
                try
                {
                    Job job2 = workGiver.NonScanJob(pawn);
                    if (job2 != null)
                    {
                        return(new ThinkResult(job2, this, list[j].def.tagToGive));
                    }
                    scanner = (workGiver as WorkGiver_Scanner);
                    float closestDistSquared;
                    float bestPriority;
                    if (scanner != null)
                    {
                        if (scanner.def.scanThings)
                        {
                            Predicate <Thing>   validator  = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);
                            IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                            Thing thing;
                            try
                            {
                                if (scanner.Prioritized)
                                {
                                    IEnumerable <Thing> enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    thing = ((!scanner.AllowUnreachable) ? GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)) : GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)));
                                }
                                else if (scanner.AllowUnreachable)
                                {
                                    IEnumerable <Thing> enumerable3 = enumerable;
                                    if (enumerable3 == null)
                                    {
                                        enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, validator);
                                }
                                else
                                {
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Error("Error in WorkGiver: " + ex.Message);

                                thing = null;
                            }
                            if (thing != null)
                            {
                                bestTargetOfLastPriority = thing;
                                scannerWhoProvidedTarget = scanner;
                            }
                        }

                        if (scanner.def.scanCells)
                        {
                            pawnPosition       = pawn.Position;
                            closestDistSquared = 99999f;
                            bestPriority       = float.MinValue;
                            prioritized        = scanner.Prioritized;
                            allowUnreachable   = scanner.AllowUnreachable;
                            maxPathDanger      = scanner.MaxPathDanger(pawn);
                            IEnumerable <IntVec3> allWork4Pawn = scanner.PotentialWorkCellsGlobal(pawn);
                            IList <IntVec3>       currWork4Pawn;

                            int maxCheck = 100; // check max work types for possible work
                            if ((currWork4Pawn = (allWork4Pawn as IList <IntVec3>)) != null)
                            {
                                for (int k = 0; k < currWork4Pawn.Count; k++)
                                {
                                    ProcessCell(currWork4Pawn[k], pawn, scanner, pawnPosition, prioritized, allowUnreachable, maxPathDanger,
                                                ref bestTargetOfLastPriority, ref scannerWhoProvidedTarget, ref closestDistSquared, ref bestPriority);

                                    maxCheck = maxCheck - 1;
                                    if (maxCheck <= 0 && bestTargetOfLastPriority != TargetInfo.Invalid)
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                foreach (IntVec3 item in allWork4Pawn)
                                {
                                    ProcessCell(item, pawn, scanner, pawnPosition, prioritized, allowUnreachable, maxPathDanger,
                                                ref bestTargetOfLastPriority, ref scannerWhoProvidedTarget, ref closestDistSquared, ref bestPriority);

                                    maxCheck = maxCheck - 1;
                                    if (maxCheck <= 0 && bestTargetOfLastPriority != TargetInfo.Invalid)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(pawn + " threw exception in WorkGiver " + workGiver.def.defName + ": " + ex.ToString());
                }
                finally
                {
                }
                if (bestTargetOfLastPriority.IsValid)
                {
                    Job job3 = (!bestTargetOfLastPriority.HasThing) ? scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell) : scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                    if (job3 != null)
                    {
                        job3.workGiverDef = scannerWhoProvidedTarget.def;
                        return(new ThinkResult(job3, this, list[j].def.tagToGive));
                    }
                    Log.ErrorOnce(scannerWhoProvidedTarget + " provided target " + bestTargetOfLastPriority + " but yielded no actual job for pawn " + pawn + ". The CanGiveJob and JobOnX methods may not be synchronized.", 6112651);
                }
                num = workGiver.def.priorityInType;
            }
            return(ThinkResult.NoJob);
        }
 // Token: 0x06000029 RID: 41 RVA: 0x00002F0C File Offset: 0x0000110C
 public Thing TryFindBestEnergySource(Pawn pawn)
 {
     return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing searchThing) => searchThing.TryGetComp <EnergySourceComp>() != null && !searchThing.IsForbidden(pawn) && pawn.CanReserve(searchThing, 1, -1, null, false) && searchThing.Position.InAllowedArea(pawn) && pawn.CanReach(new LocalTargetInfo(searchThing), PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn), null, 0, -1, false, RegionType.Set_Passable, false));
 }
Ejemplo n.º 14
0
        //slightly modified version of Toils_Ingest.CarryIngestibleToChewSpot
        public static Toil CarryPuzzleToSpot(Pawn pawn, TargetIndex puzzleInd)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn              actor              = toil.actor;
                IntVec3           intVec             = IntVec3.Invalid;
                Thing             thing              = null;
                Thing             thing2             = actor.CurJob.GetTarget(puzzleInd).Thing;
                Predicate <Thing> baseChairValidator = delegate(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);
                    }
                    bool result = 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)
                        {
                            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);
        }
Ejemplo n.º 15
0
        // Token: 0x0600002B RID: 43 RVA: 0x000034D4 File Offset: 0x000016D4
        protected override Job TryGiveJob(Pawn pawn)
        {
            bool flag = pawn.Downed || pawn.CurJob != null;
            Job  result;

            if (flag)
            {
                result = null;
            }
            else
            {
                bool flag2 = pawn.RaceProps.Humanlike && pawn.WorkTagIsDisabled(WorkTags.Violent);
                if (flag2)
                {
                    result = null;
                }
                else
                {
                    bool flag3 = !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);
                    if (flag3)
                    {
                        result = null;
                    }
                    else
                    {
                        bool flag4 = pawn.GetRegion(RegionType.Set_Passable) == null;
                        if (flag4)
                        {
                            result = null;
                        }
                        else
                        {
                            bool flag5 = pawn.equipment.HasAnything();
                            if (flag5)
                            {
                                Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Weapon), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 15f, (Thing x) => pawn.CanReserve(x, 1, -1, null, false), null, 0, 15, false, RegionType.Set_Passable, false);
                                bool  flag6 = thing == null;
                                if (flag6)
                                {
                                    return(null);
                                }
                                bool flag7 = pawn.equipment.Primary.def != null;
                                if (flag7)
                                {
                                    ThingDef def   = pawn.equipment.Primary.def;
                                    bool     flag8 = thing.def.BaseMarketValue <= def.BaseMarketValue;
                                    if (flag8)
                                    {
                                        return(null);
                                    }
                                    bool flag9 = thing != null && !thing.IsBurning() && !thing.IsForbidden(pawn) && thing.def.BaseMarketValue > def.BaseMarketValue && pawn.CurJob == null;
                                    if (flag9)
                                    {
                                        pawn.equipment.DropAllEquipment(pawn.Position, false);
                                        return(new Job(JobGiver_WPAutoWeapon.WPAnimalJobDefOf.AnimalWeaponEquip, thing));
                                    }
                                }
                            }
                            bool flag10 = !pawn.equipment.HasAnything();
                            if (flag10)
                            {
                                Thing thing2 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Weapon), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 8f, (Thing x) => pawn.CanReserve(x, 1, -1, null, false), null, 0, 15, false, RegionType.Set_Passable, false);
                                bool  flag11 = thing2 != null && !thing2.IsBurning() && !thing2.IsForbidden(pawn) && pawn.CurJob == null;
                                if (flag11)
                                {
                                    return(new Job(JobGiver_WPAutoWeapon.WPAnimalJobDefOf.AnimalWeaponEquip, thing2));
                                }
                            }
                            result = null;
                        }
                    }
                }
            }
            return(result);
        }
Ejemplo n.º 16
0
        public static Thing ClosestReachableCocoonToEgg(Thing egg, ThingDef t)
        {
            Thing thing = GenClosest.ClosestThingReachable(egg.Position, egg.Map, ThingRequest.ForDef(XenomorphDefOf.RRY_Xenomorph_Cocoon_Humanoid), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 10f, null, null, 0, -1, false, RegionType.Set_Passable, false);

            return(thing);
        }
Ejemplo n.º 17
0
        public static Building_CryptosleepCasket FindCryptosleepCasketFor(Pawn p, Pawn traveler, bool ignoreOtherReservations = false)
        {
            IEnumerable <ThingDef> enumerable = from def in DefDatabase <ThingDef> .AllDefs
                                                where typeof(Building_CryptosleepCasket).IsAssignableFrom(def.thingClass)
                                                select def;

            foreach (ThingDef current in enumerable)
            {
                Building_CryptosleepCasket building_CryptosleepCasket = (Building_CryptosleepCasket)GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForDef(current), PathEndMode.InteractionCell, TraverseParms.For(traveler, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x)
                {
                    bool arg_33_0;
                    if (!((Building_CryptosleepCasket)x).HasAnyContents)
                    {
                        Pawn traveler2                = traveler;
                        LocalTargetInfo target        = x;
                        bool ignoreOtherReservations2 = ignoreOtherReservations;
                        arg_33_0 = traveler2.CanReserve(target, 1, -1, null, ignoreOtherReservations2);
                    }
                    else
                    {
                        arg_33_0 = false;
                    }
                    return(arg_33_0);
                }, null, 0, -1, false, RegionType.Set_Passable, false);
                if (building_CryptosleepCasket != null)
                {
                    return(building_CryptosleepCasket);
                }
            }
            return(null);
        }
Ejemplo n.º 18
0
        public static Thing ClosestReachableEmptyCocoonToEgg(Thing egg, ThingDef t)
        {
            Thing thing = GenClosest.ClosestThingReachable(egg.Position, egg.Map, ThingRequest.ForDef(XenomorphDefOf.RRY_Xenomorph_Cocoon_Humanoid), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 10f, (x => (x is Building_XenomorphCocoon XC && XC.AnyUnoccupiedSleepingSlot && XC.OwnersForReading.NullOrEmpty())), null, 0, -1, false, RegionType.Set_Passable, false);

            return(thing);
        }
Ejemplo n.º 19
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, CombatSearchMode combatSearchMode = CombatSearchMode.Default)
        {
            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))
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != 0)
                {
                    RoofDef roof = thing.Position.GetRoof(thing.Map);
                    if (roof != null && roof.isThickRoof)
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0)
                {
                    if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position)))
                    {
                        return(false);
                    }
                    if (!searcherThing.CanSee(thing, losValidator))
                    {
                        if (t is Pawn)
                        {
                            if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                            {
                                return(false);
                            }
                        }
                        else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                        {
                            return(false);
                        }
                    }
                }
                if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction))
                {
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    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;
                    foreach (IntVec3 item in thing.OccupiedRect())
                    {
                        if (!item.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState))
            {
                tmpTargets.Clear();
                var targets = searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher);

                if (combatSearchMode == CombatSearchMode.Default)
                {
                    tmpTargets.AddRange(targets);
                }
                else if (combatSearchMode == CombatSearchMode.Strongest)
                {
                    tmpTargets.AddRange(targets.OrderByDescending(x => (x.Thing as Pawn)?.kindDef.combatPower));
                }
                else if (combatSearchMode == CombatSearchMode.Weakest)
                {
                    tmpTargets.AddRange(targets.OrderBy(x => (x.Thing as Pawn)?.kindDef.combatPower));
                }
                else if (combatSearchMode == CombatSearchMode.PursueFleeing)
                {
                    tmpTargets.AddRange(targets.Where(x => (x.Thing as Pawn)?.CurJobDef == JobDefOf.Flee || (x.Thing as Pawn)?.CurJobDef == JobDefOf.FleeAndCower));
                }
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator2 = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash));
                }
                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;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                }
                else
                {
                    result = (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);
                }
                tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = delegate(IAttackTarget t)
                {
                    if (!oldValidator(t))
                    {
                        return(false);
                    }
                    return(t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius) ? true : false);
                };
            }
            IAttackTarget attackTarget2 = (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 (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);
        }
Ejemplo n.º 20
0
        public static Thing ClosestReachableChildHivelike(Pawn pawn, List <Thing> Hivelikes)
        {
            Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 9999f, (x => Hivelikes.Contains(x)), null, 0, -1, false, RegionType.Set_Passable, false);

            return(thing);
        }
Ejemplo n.º 21
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)
                    {
                        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);
                    }
                    bool result = 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)
                        {
                            result = true;
                            break;
                        }
                    }
                    return(result);
                };
                if (thing2.def.ingestible.chairSearchRadius > 0f)
                {
                    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) && t.Position.GetDangerFor(pawn, t.Map) <= 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);
        }
Ejemplo n.º 22
0
        private static Thing BestWaterSourceOnMap(Pawn getter, Pawn eater, bool priorQuality, WaterPreferability maxPref = WaterPreferability.ClearWater, bool allowDrug = false, bool allowForbidden = false, bool allowSociallyImproper = false)
        {
            if (!getter.CanManipulate() && getter != eater)
            {
                // 取得者は操作不可、取得者と摂取者が違う
                // →マップから取得して持ち運ぶことができない
                // →エラー
                Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation."));
                return(null);
            }

            bool waterValidator(Thing t)
            {
                // 禁止されている&禁止を無視して取得してはいけない
                if (!allowForbidden && t.IsForbidden(getter))
                {
                    return(false);
                }

                // ドラッグ禁止&対象はドラッグ
                if (!allowDrug && t.def.IsDrug)
                {
                    return(false);
                }

                // 取得者が予約できない
                if (!getter.CanReserve(t))
                {
                    return(false);
                }

                var comp = t.TryGetComp <CompWaterSource>();

                // 水源として使用できない
                if (comp == null || !comp.IsWaterSource)
                {
                    return(false);
                }

                // 食べられるものは飲み物としては選ばれない
                if (t.def.IsIngestible)
                {
                    return(false);
                }

                // 操作が必要なのに操作できない
                if (comp.NeedManipulate && !getter.CanManipulate())
                {
                    return(false);
                }

                var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType];

                if (comp.SourceType == CompProperties_WaterSource.SourceType.Item)
                {
                    // 水分がない
                    if (!t.CanGetWater())
                    {
                        return(false);
                    }

                    // 水分を持っている=水アイテムである
                    var waterPreferability = t.GetWaterPreferability();

                    // 水の品質が範囲外
                    if (waterPreferability < WaterPreferability.SeaWater || waterPreferability > maxPref)
                    {
                        return(false);
                    }

                    // 現在飲める状態には無い
                    if (!t.CanDrinkWaterNow())
                    {
                        return(false);
                    }

                    // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse
                    if (!IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper))
                    {
                        return(false);
                    }

                    // 取得者がそれに気づいていない
                    if (!getter.AnimalAwareOf(t))
                    {
                        return(false);
                    }

                    return(true);
                }

                if (comp.SourceType != CompProperties_WaterSource.SourceType.Building)
                {
                    return(false);
                }

                // 取得者と摂取者が異なる(自分で飲みに行く必要がある)
                if (getter != eater)
                {
                    return(false);
                }

                // 水汲みに使えない
                if (!(t is IBuilding_DrinkWater drinkWaterBuilding))
                {
                    return(false);
                }

                // 水を飲む人が飲めない(能力が無い、水の量がない)
                if (!drinkWaterBuilding.CanDrinkFor(eater))
                {
                    return(false);
                }

                // 最大水質を超えていたらダメ
                if (waterTypeDef.waterPreferability > maxPref)
                {
                    return(false);
                }

                // 野生人?(派閥所属なし?)はダメ
                if (eater.IsWildMan())
                {
                    return(false);
                }

                // 自陣営or自陣営のホストの設備でなければダメ
                // 動物でない場合は、という条件を追加
                if (!eater.RaceProps.Animal && t.Faction != eater.Faction && t.Faction != eater.HostFaction)
                {
                    return(false);
                }

                // 使えない状態はダメ
                if (!drinkWaterBuilding.IsActivated)
                {
                    return(false);
                }

                // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse
                if (!IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper))
                {
                    return(false);
                }

                if (t.def.hasInteractionCell)
                {
                    // 使用場所がある
                    if (!t.InteractionCell.Standable(t.Map) || !eater.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some)))
                    {
                        // 使用場所に立てない or 使用場所まで行けない
                        return(false);
                    }
                }
                else
                {
                    // 使用場所が無い
                    if (!getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.Position, t.Map), PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Some)))
                    {
                        // その設備にタッチできない
                        return(false);
                    }
                }

                return(true);

                // それ以外
            }

            if (getter.RaceProps.Humanlike)
            {
                // 取得者はHumanlikeである
                // →条件を満たすものの中から最適な物を探す
                return(SpawnedWaterSearchInnerScan(
                           eater,
                           getter.Position,
                           getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.Everything).FindAll(
                               t =>
                {
                    if (t.CanDrinkWaterNow())
                    {
                        return true;
                    }

                    if (t is IBuilding_DrinkWater building && building.CanDrinkFor(eater))
                    {
                        return true;
                    }

                    return false;
                }),
                           PathEndMode.ClosestTouch,
                           TraverseParms.For(getter),
                           priorQuality,
                           9999f,
                           waterValidator));
            }

            // 取得者はHumanlikeではない

            // プレイヤー派閥に所属しているかどうかでリージョン?数を変える
            var searchRegionsMax = 30;

            if (getter.Faction == Faction.OfPlayer)
            {
                searchRegionsMax = 100;
            }

            var filtered = new HashSet <Thing>();

            foreach (var current in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
            {
                // 自分を中心に半径2以内の物をチェック
                if (current is Pawn pawn && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == MizuDef.Job_DrinkWater && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                {
                    // 自分ではない動物が現在水アイテムを摂取している
                    // →今まさに摂取している物は探索対象から除外
                    filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                }
            }

            var ignoreEntirelyForbiddenRegions = !allowForbidden && // 禁止物のアクセスは許可されていない
                                                 ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings?.EffectiveAreaRestrictionInPawnCurrentMap != null;    // 有効な制限エリアなし

            bool predicate(Thing t)
            {
                // アイテムが条件を満たしていない
                if (!waterValidator(t))
                {
                    return(false);
                }

                // すぐ近くで他の動物が飲んでいる水のリストに入っていない
                if (filtered.Contains(t))
                {
                    return(false);
                }

                // 水の品質が最低値未満
                if (t.GetWaterPreferability() < WaterPreferability.SeaWater)
                {
                    return(false);
                }

                return(true);
            }

            // 指定の条件下でアクセスできるものを探す

            // 水アイテムから
            var thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);

            if (thing != null)
            {
                return(thing);
            }

            // 水汲み設備
            thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
            if (thing != null)
            {
                return(thing);
            }

            // 条件を変えて再探索
            // 水アイテム
            thing = GenClosest.ClosestThingReachable(
                getter.Position,
                getter.Map,
                ThingRequest.ForGroup(ThingRequestGroup.HaulableEver),
                PathEndMode.ClosestTouch,
                TraverseParms.For(getter),
                9999f,
                waterValidator, // ここが変わった
                null,
                0,
                searchRegionsMax,
                false,
                RegionType.Set_Passable,
                ignoreEntirelyForbiddenRegions);
            if (thing != null)
            {
                return(thing);
            }

            // 水汲み設備
            thing = GenClosest.ClosestThingReachable(
                getter.Position,
                getter.Map,
                ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial),
                PathEndMode.ClosestTouch,
                TraverseParms.For(getter),
                9999f,
                waterValidator, // ここが変わった
                null,
                0,
                searchRegionsMax,
                false,
                RegionType.Set_Passable,
                ignoreEntirelyForbiddenRegions);
            return(thing);
        }
Ejemplo n.º 23
0
        private Thing TryFindHaulableOfDef(Pawn pawn, ThingDef haulableDef)
        {
            bool SearchPredicate(Thing thing) => !thing.IsForbidden(pawn) && pawn.CanReserve(thing);

            return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(haulableDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn), maxIngredientSearchDist, SearchPredicate));
        }
        // RimWorld.FloatMenuMakerMap

        /*
         *  PostFix
         *
         *  This code adds to the float menu list.
         *
         *  Adds:
         *    + Force straitjacket on _____
         *    + Help _____ out of straitjacket
         *
         */
        public static void AddHumanlikeOrdersPostFix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            IntVec3 c = IntVec3.FromVector3(clickPos);

            foreach (Thing current in c.GetThingList(pawn.Map))
            {
                if (current is Pawn target && pawn != null && pawn != target && !pawn.Dead && !pawn.Downed)
                {
                    //We sadly can't handle aggro mental states or non-humanoids.
                    if ((target?.RaceProps?.Humanlike ?? false) && !target.InAggroMentalState)
                    {
                        //Let's proceed if our 'actor' is capable of manipulation
                        if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                        {
                            //Does the target have a straitjacket?
                            //We can help them remove the straitjacket.
                            if (target?.apparel?.WornApparel?.FirstOrDefault(x => x.def == StraitjacketDefOf.ROM_Straitjacket) != null)
                            {
                                if (!pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                                {
                                    opts.Add(new FloatMenuOption("CannotRemoveStraitjacket".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null));
                                }
                                else if (!pawn.CanReserve(target, 1))
                                {
                                    opts.Add(new FloatMenuOption("CannotRemoveStraitjacket".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null));
                                }
                                else
                                {
                                    Action action = delegate
                                    {
                                        Job job = new Job(StraitjacketDefOf.ROM_TakeOffStraitjacket, target);
                                        job.count = 1;
                                        pawn.jobs.TryTakeOrderedJob(job);
                                    };
                                    opts.Add(new FloatMenuOption("RemoveStraitjacket".Translate(new object[]
                                    {
                                        target.LabelCap
                                    }), action, MenuOptionPriority.High, null, target, 0f, null, null));
                                }
                            }
                            //We can put one on!
                            else
                            {
                                if (pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel).FirstOrDefault((Thing x) => x.def == StraitjacketDefOf.ROM_Straitjacket) != null)
                                {
                                    if (!pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                                    {
                                        opts.Add(new FloatMenuOption("CannotForceStraitjacket".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null));
                                    }
                                    else if (!pawn.CanReserve(target, 1))
                                    {
                                        opts.Add(new FloatMenuOption("CannotForceStraitjacket".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null));
                                    }
                                    else
                                    {
                                        Action action = delegate
                                        {
                                            Thing straitjacket = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(StraitjacketDefOf.ROM_Straitjacket), PathEndMode.Touch, TraverseParms.For(pawn));
                                            Job   job          = new Job(StraitjacketDefOf.ROM_ForceIntoStraitjacket, target, straitjacket);
                                            job.count             = 1;
                                            job.locomotionUrgency = LocomotionUrgency.Sprint;
                                            pawn.jobs.TryTakeOrderedJob(job);
                                        };
                                        opts.Add(new FloatMenuOption("ForceStraitjacketUpon".Translate(new object[]
                                        {
                                            target.LabelCap
                                        }), action, MenuOptionPriority.High, null, target, 0f, null, null));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        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 (AttackTargetFinder.HasRangedAttack(searcher))
            {
                AttackTargetFinder.tmpTargets.Clear();
                AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((byte)(flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                for (int i = 0; i < AttackTargetFinder.tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = AttackTargetFinder.tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = AttackTargetFinder.GetRandomShootingTargetByScore(AttackTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2;
                    if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0)
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (AttackTargetFinder.CanReach(searcherThing, t, canBash) || AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)));
                    }
                    else
                    {
                        validator2 = ((Thing t) => innerValidator((IAttackTarget)t));
                    }
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, AttackTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                AttackTargetFinder.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 = AttackTargetFinder.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);
        }
Ejemplo n.º 26
0
        private LoadoutSlot GetPrioritySlot(Pawn pawn, out ItemPriority priority, out Thing closestThing, out int count)
        {
            priority = ItemPriority.None;
            LoadoutSlot slot = null;

            closestThing = null;
            count        = 0;

            CompInventory inventory = pawn.TryGetComp <CompInventory>();

            if (inventory != null && inventory.container != null)
            {
                Loadout loadout = pawn.GetLoadout();
                if (loadout != null && !loadout.Slots.NullOrEmpty())
                {
                    foreach (LoadoutSlot curSlot in loadout.Slots)
                    {
                        ItemPriority curPriority = ItemPriority.None;
                        Thing        curThing    = null;
                        int          numCarried  = inventory.container.TotalStackCountOfDef(curSlot.Def);

                        // Add currently equipped gun
                        if (pawn.equipment != null && pawn.equipment.Primary != null)
                        {
                            if (pawn.equipment.Primary.def == curSlot.Def)
                            {
                                numCarried++;
                            }
                        }
                        if (numCarried < curSlot.Count)
                        {
                            curThing = GenClosest.ClosestThingReachable(
                                pawn.Position,
                                pawn.Map,
                                ThingRequest.ForDef(curSlot.Def),
                                PathEndMode.ClosestTouch,
                                TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                                proximitySearchRadius,
                                x => !x.IsForbidden(pawn) && pawn.CanReserve(x));
                            if (curThing != null)
                            {
                                curPriority = ItemPriority.Proximity;
                            }
                            else
                            {
                                curThing = GenClosest.ClosestThingReachable(
                                    pawn.Position,
                                    pawn.Map,
                                    ThingRequest.ForDef(curSlot.Def),
                                    PathEndMode.ClosestTouch,
                                    TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                                    maximumSearchRadius,
                                    x => !x.IsForbidden(pawn) && pawn.CanReserve(x));
                                if (curThing != null)
                                {
                                    if (!curSlot.Def.IsNutritionGivingIngestible && numCarried / curSlot.Count <= 0.5f)
                                    {
                                        curPriority = ItemPriority.LowStock;
                                    }
                                    else
                                    {
                                        curPriority = ItemPriority.Low;
                                    }
                                }
                            }
                        }
                        if (curPriority > priority && curThing != null && inventory.CanFitInInventory(curThing, out count))
                        {
                            priority     = curPriority;
                            slot         = curSlot;
                            closestThing = curThing;
                        }
                        if (priority >= ItemPriority.LowStock)
                        {
                            break;
                        }
                    }
                }
            }

            return(slot);
        }
        public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
        {
            int               num               = -999;
            TargetInfo        targetInfo        = TargetInfo.Invalid;
            WorkGiver_Scanner workGiver_Scanner = null;

            if (workGiverDef != null)
            {
                WorkGiver workGiver = workGiverDef.Worker;
                if (workGiver.def.priorityInType != num && targetInfo.IsValid)
                {
                    return(ThinkResult.NoJob);
                }

                if (this.PawnCanUseWorkGiver(pawn, workGiver))
                {
                    try
                    {
                        Job job2 = workGiver.NonScanJob(pawn);
                        if (job2 != null)
                        {
                            return(new ThinkResult(job2, this, new JobTag?(workGiverDef.tagToGive)));
                        }
                        WorkGiver_Scanner scanner = workGiver as WorkGiver_Scanner;
                        if (scanner != null)
                        {
                            if (workGiver.def.scanThings)
                            {
                                Predicate <Thing>   predicate  = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t, false);
                                IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                                Thing thing;
                                if (scanner.Prioritized)
                                {
                                    IEnumerable <Thing> enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }
                                    Predicate <Thing> validator = predicate;
                                    thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x));
                                }
                                else
                                {
                                    Predicate <Thing> validator = predicate;
                                    bool forceGlobalSearch      = enumerable != null;
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, enumerable, 0, scanner.LocalRegionsToScanFirst, forceGlobalSearch, RegionType.Set_Passable, false);
                                }
                                if (thing != null)
                                {
                                    targetInfo        = thing;
                                    workGiver_Scanner = scanner;
                                }
                            }
                            if (workGiver.def.scanCells)
                            {
                                IntVec3 position    = pawn.Position;
                                float   num2        = 99999f;
                                float   num3        = -3.40282347E+38f;
                                bool    prioritized = scanner.Prioritized;
                                foreach (IntVec3 current in scanner.PotentialWorkCellsGlobal(pawn))
                                {
                                    bool  flag = false;
                                    float num4 = (float)(current - position).LengthHorizontalSquared;
                                    if (prioritized)
                                    {
                                        if (!current.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, current))
                                        {
                                            float priority = scanner.GetPriority(pawn, current);
                                            if (priority > num3 || (priority == num3 && num4 < num2))
                                            {
                                                flag = true;
                                                num3 = priority;
                                            }
                                        }
                                    }
                                    else if (num4 < num2 && !current.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, current))
                                    {
                                        flag = true;
                                    }
                                    if (flag)
                                    {
                                        targetInfo        = new TargetInfo(current, pawn.Map, false);
                                        workGiver_Scanner = scanner;
                                        num2 = num4;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Concat(new object[]
                        {
                            pawn,
                            " threw exception in WorkGiver ",
                            workGiver.def.defName,
                            ": ",
                            ex.ToString()
                        }));
                    }
                    finally
                    {
                    }
                    if (targetInfo.IsValid)
                    {
                        pawn.mindState.lastGivenWorkType = workGiver.def.workType;
                        Job job3;
                        if (targetInfo.HasThing)
                        {
                            job3 = workGiver_Scanner.JobOnThing(pawn, targetInfo.Thing, false);
                        }
                        else
                        {
                            job3 = workGiver_Scanner.JobOnCell(pawn, targetInfo.Cell);
                        }
                        if (job3 != null)
                        {
                            return(new ThinkResult(job3, this, new JobTag?(workGiverDef.tagToGive)));
                        }
                        Log.ErrorOnce(string.Concat(new object[]
                        {
                            workGiver_Scanner,
                            " provided target ",
                            targetInfo,
                            " but yielded no actual job for pawn ",
                            pawn,
                            ". The CanGiveJob and JobOnX methods may not be synchronized."
                        }), 6112651);
                    }
                    num = workGiver.def.priorityInType;
                }
            }

            return(ThinkResult.NoJob);
        }
        public static Thing FindSilver(Pawn pawn)
        {
            Predicate <Thing> predicate = (Thing x) => !x.IsForbidden(pawn) && pawn.CanReserve(x, 1, -1, null, false) && x.def == ThingDefOf.Silver;

            return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(ThingDefOf.Silver), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, predicate, null, 0, -1, false, RegionType.Set_Passable, false));
        }
Ejemplo n.º 29
0
        public override void TickLong()
        {
            base.TickLong();
            bool selected = Find.Selector.SingleSelectedThing == this;

            if (!this.IsBurning() && !this.Destroyed && this.Map != null)
            {
                Thing thing = GenClosest.ClosestThingReachable(this.Position, this.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 6f, x => XenomorphUtil.isInfectablePawn(((Pawn)x)), null, 0, -1, false, RegionType.Set_Passable, false);
                if (thing != null && this.Growth > 0.95f && !thing.Destroyed && !((Pawn)thing).Dead)
                {
                    List <Thing> thingList = GridsUtility.GetThingList(thing.Position, this.Map);
                    Thing        thing2;
                    if (this.def == XenomorphDefOf.RRY_Plant_Neomorph_Fungus)
                    {
                        thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Neomorph_Spores);
                    }
                    else
                    {
                        thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Neomorph_Spores_Hidden);
                    }
                    float Chance = ((0.5f * Growth) * ((Pawn)thing).BodySize) / DistanceBetween(this.Position, thing.Position);
                    if (selected)
                    {
                        Log.Message(string.Format("Chance: {0}", Chance));
                    }
                    if (Rand.Chance(Chance) && !thingList.Exists(x => x.def == XenomorphDefOf.RRY_Neomorph_Spores))
                    {
                        if (thing.Faction == Faction.OfPlayer)
                        {
                            string text = TranslatorFormattedStringExtensions.Translate("Xeno_Neospores_Trigger", thing.LabelShortCap, this.Label);
                            Log.Message(text);
                            MoteMaker.ThrowText(this.Position.ToVector3(), this.Map, text, 5f);
                        }
                        GenSpawn.Spawn(thing2, thing.Position, this.Map);
                    }
                }
                else
                {
                    Plant plant = (Plant)GenClosest.ClosestThingReachable(this.Position, this.Map, ThingRequest.ForGroup(ThingRequestGroup.Plant), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 3f, x => ((Plant)x).Growth > 0.65f && x.def != XenomorphDefOf.RRY_Plant_Neomorph_Fungus && x.def != XenomorphDefOf.RRY_Plant_Neomorph_Fungus_Hidden && (x.def.defName.Contains("Grass") || x.def.defName.Contains("Moss")), null, 0, -1, false, RegionType.Set_Passable, false);
                    if (plant != null && !plant.Destroyed && !plant.IsBurning() && this.Growth > 0.95f)
                    {
                        if (selected)
                        {
                            Log.Message(string.Format("plant: {0}", plant));
                        }
                        float Chance2 = ((0.5f * Growth) * plant.Growth / DistanceBetween(this.Position, plant.Position));
                        if (selected)
                        {
                            Log.Message(string.Format("Chance2: {0}", Chance2));
                        }
                        if (Rand.Chance(Chance2))
                        {
                            Thing thing2;
                            if (this.def == XenomorphDefOf.RRY_Plant_Neomorph_Fungus)
                            {
                                thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Neomorph_Spores);
                            }
                            else
                            {
                                thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Neomorph_Spores_Hidden);
                            }
                            if (selected)
                            {
                                Log.Message(string.Format("was: {0}", plant));
                            }
                            IntVec3 vec3 = plant.Position;
                            GenSpawn.Spawn(thing2, vec3, this.Map);
                            plant.Destroy();
                            GenSpawn.Spawn(ThingMaker.MakeThing(this.def), vec3, this.Map);
                        }
                    }
                }
            }
        }
Ejemplo n.º 30
0
 private Hive FindClosestHive(Pawn pawn)
 {
     return((Hive)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(ThingDefOf.Hive), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 30f, (Thing x) => x.Faction == pawn.Faction, null, 0, 30, false, RegionType.Set_Passable, false));
 }