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)); }
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); }
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); }
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); }
/// <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
/// <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); }
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)); }
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)); }
//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); }
// 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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); } } } } }
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)); }