/// <summary> /// Gives out a job if a proper apparel is found on the map. /// </summary> /// <param name="pawn"> The pawn in question. </param> /// <returns> A 9 to 5 job. </returns> protected override Job TryGiveJob(Pawn pawn) { ValidateArg.NotNull(pawn, nameof(pawn)); #if DEBUG Log.Message(pawn.Name + "Looking for apparels"); #endif CompAwesomeInventoryLoadout ailoadout = ((ThingWithComps)pawn).TryGetComp <CompAwesomeInventoryLoadout>(); if (ailoadout == null || !ailoadout.NeedRestock) { return(null); } if (_parent == null) { if (parent is JobGiver_FindItemByRadius p) { _parent = p; } else { throw new InvalidOperationException(ErrorText.WrongTypeParentThinkNode); } } foreach (ThingGroupSelector groupSelector in ailoadout.ItemsToRestock.Select(p => p.Key)) { if (groupSelector.AllowedThing.IsApparel) { Thing targetA = _parent.FindItem( pawn , pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel) , (thing) => groupSelector.Allows(thing, out _) && !ailoadout.Loadout.IncludedInBlacklist(thing)); if (targetA != null) { Job job = new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, targetA, false); if (pawn.Reserve(targetA, job, errorOnFailed: false)) { return(job); } else { JobMaker.ReturnToPool(job); return(null); } } } } return(null); }
private static void WearApparel(Pawn pawn, Thing apparel, bool forceWear) { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = forceWear; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }
public static void Postfix(Pawn pawn, ref Job __result, JobGiver_OptimizeApparel __instance) { if (__result == null) { return; } CompAwesomeInventoryLoadout comp = pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp == null) { return; } Job job = __result; Thing targetThingA = job.targetA.Thing; if (comp.Loadout is AwesomeInventoryCostume costume) { if (__result.def == JobDefOf.Wear) { if (targetThingA != null && !costume.CostumeItems.Any(s => s.Allows(targetThingA, out _)) && !costume.CostumeItems.All(s => ApparelUtility.CanWearTogether(targetThingA.def, s.AllowedThing, BodyDefOf.Human))) { __result = null; JobMaker.ReturnToPool(job); _setNextOptimizeTick.Invoke(__instance, new[] { pawn }); return; } } } else if (comp.Loadout is AwesomeInventoryLoadout loadout) { CancellationTokenSource source = new CancellationTokenSource(); CancellationToken token = source.Token; try { bool conflict = false; if (!loadout.Any(selector => selector.Allows(targetThingA, out _))) { Parallel.ForEach( Partitioner.Create(pawn.apparel.WornApparel) , (Apparel apparel) => { if (!token.IsCancellationRequested && targetThingA != null && !ApparelUtility.CanWearTogether(apparel.def, targetThingA.def, BodyDefOf.Human)) { if (comp.Loadout.Any(selector => selector.Allows(apparel, out _))) { conflict = true; source.Cancel(); } } }); } if (conflict) { __result = new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, targetThingA, false); JobMaker.ReturnToPool(job); } } catch (Exception e) { __result = JobMaker.MakeJob(JobDefOf.Wear, targetThingA); } finally { source.Dispose(); } } }
/// <summary> /// Change getup when switch loadout. /// </summary> /// <param name="newLoadout"> New loadout pawn switch to. </param> protected void ChangeCostume(AwesomeInventoryLoadout newLoadout) { ValidateArg.NotNull(newLoadout, nameof(newLoadout)); if (newLoadout is AwesomeInventoryCostume costume) { ConcurrentBag <Apparel> wornApparels = new ConcurrentBag <Apparel>(); Parallel.ForEach( Partitioner.Create(_pawn.apparel.WornApparel) , (Apparel apparel) => { if (!costume.CostumeItems.Any(c => c.Allows(apparel, out _))) { wornApparels.Add(apparel); } }); if (wornApparels.Any()) { _pawn.jobs.StopAll(true); foreach (Apparel apparel in wornApparels) { Job job = JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_Undress, apparel); if (_pawn.CurJob == null) { _pawn.jobs.StartJob(job); } else { _pawn.jobs.jobQueue.EnqueueLast(job); } } } if (costume.CostumeItems.Any()) { ConcurrentBag <Thing> things = new ConcurrentBag <Thing>(); Parallel.ForEach( Partitioner.Create(costume.CostumeItems) , (ThingGroupSelector selector) => { Thing thing = _pawn.inventory.innerContainer.FirstOrDefault(t => selector.Allows(t, out _)); if (thing != null) { things.Add(thing); } }); if (things.Any()) { if (_pawn.jobs.curJob.def != AwesomeInventory_JobDefOf.AwesomeInventory_Undress) { _pawn.jobs.StopAll(true); } foreach (Thing thing in things.Distinct()) { if (thing.def.IsApparel) { Job job = new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, thing, false); if (_pawn.CurJob == null) { _pawn.jobs.StartJob(job); } else { _pawn.jobs.jobQueue.EnqueueLast(job); } } else if (thing.def.IsWeapon) { Job job = JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, thing); if (_pawn.CurJob == null) { _pawn.jobs.StartJob(job); } else { _pawn.jobs.jobQueue.EnqueueLast(job); } } } } } } }
public static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { IntVec3 position = IntVec3.FromVector3(clickPos); // Add options for equipment. if (pawn.equipment != null) { List <Thing> things = position.GetThingList(pawn.Map); foreach (Thing thing in things) { if (thing.TryGetComp <CompEquippable>() != null) { ThingWithComps equipment = (ThingWithComps)thing; if (equipment.def.IsWeapon && !pawn.WorkTagIsDisabled(WorkTags.Violent) && pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly) && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && !(pawn.IsQuestLodger() && (!equipment.def.IsWeapon || pawn.equipment.Primary != null)) && EquipmentUtility.CanEquip(equipment, pawn, out _)) { string text3 = UIText.AIEquip.Translate(thing.LabelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text3 += " " + UIText.EquipWarningBrawler.Translate(); } var option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( text3, () => { TaggedString equipWeaponConfirmationDialogText = ThingRequiringRoyalPermissionUtility.GetEquipWeaponConfirmationDialogText(equipment, pawn); CompBladelinkWeapon compBladelinkWeapon = equipment.TryGetComp <CompBladelinkWeapon>(); if (compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn != pawn) { if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n"; } equipWeaponConfirmationDialogText += "BladelinkEquipWarning".Translate(); } if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n" + "RoyalWeaponEquipConfirmation".Translate(); Find.WindowStack.Add( new Dialog_MessageBox( equipWeaponConfirmationDialogText, "Yes".Translate(), () => { Equip(); }, "No".Translate())); } else { Equip(); } }, MenuOptionPriority.High), pawn, equipment); opts.Add(option); } void Equip() { equipment.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, equipment)); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); } } } } // Add options for apparel. if (pawn.apparel != null) { Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(position); if (apparel != null) { if (pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly) && !apparel.IsBurning() && ApparelOptionUtility.CanWear(pawn, apparel)) { FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIForceWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = true; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = false; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); } } } }
public static void Postfix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { if (!AwesomeInventoryServiceProvider.TryGetImplementation <IInventoryHelper>(out IInventoryHelper inventoryHelper)) { Log.Error(string.Format(ErrorMessage.NotImplemented, typeof(IInventoryHelper).Name)); return; } IntVec3 position = IntVec3.FromVector3(clickPos); // Add options for equipment. if (pawn.equipment != null) { List <Thing> things = position.GetThingList(pawn.Map); foreach (Thing thing in things) { if (thing.TryGetComp <CompEquippable>() != null) { ThingWithComps equipment = (ThingWithComps)thing; if (equipment.def.IsWeapon && !pawn.WorkTagIsDisabled(WorkTags.Violent) && pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly) && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && !(pawn.IsQuestLodger() && (!equipment.def.IsWeapon || pawn.equipment.Primary != null)) && EquipmentUtility.CanEquip(equipment, pawn, out _)) { string text3 = UIText.AIEquip.Translate(thing.LabelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text3 += " " + UIText.EquipWarningBrawler.Translate(); } var option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( text3, () => { TaggedString equipWeaponConfirmationDialogText = ThingRequiringRoyalPermissionUtility.GetEquipWeaponConfirmationDialogText(equipment, pawn); CompBladelinkWeapon compBladelinkWeapon = equipment.TryGetComp <CompBladelinkWeapon>(); if (compBladelinkWeapon != null && compBladelinkWeapon.bondedPawn != pawn) { if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n"; } equipWeaponConfirmationDialogText += "BladelinkEquipWarning".Translate(); } if (!equipWeaponConfirmationDialogText.NullOrEmpty()) { equipWeaponConfirmationDialogText += "\n\n" + "RoyalWeaponEquipConfirmation".Translate(); Find.WindowStack.Add( new Dialog_MessageBox( equipWeaponConfirmationDialogText, "Yes".Translate(), () => { Equip(); }, "No".Translate())); } else { Equip(); } }, MenuOptionPriority.High), pawn, equipment); opts.Add(option); } void Equip() { equipment.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, equipment)); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); } } } } // Add options for apparel. if (pawn.apparel != null) { Apparel apparel = pawn.Map.thingGrid.ThingAt <Apparel>(position); if (apparel != null) { if (pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly) && !apparel.IsBurning() && !pawn.apparel.WouldReplaceLockedApparel(apparel) && ApparelUtility.HasPartsToWear(pawn, apparel.def)) { FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIForceWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = true; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( UIText.AIWear.Translate(apparel.LabelShort), () => { DressJob dressJob = SimplePool <DressJob> .Get(); dressJob.def = AwesomeInventory_JobDefOf.AwesomeInventory_Dress; dressJob.targetA = apparel; dressJob.ForceWear = false; apparel.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(dressJob); }, MenuOptionPriority.High), pawn, apparel); opts.Add(option); } } } List <Thing> items = position.GetThingList(pawn.Map); foreach (Thing item in items) { if (item.def.category == ThingCategory.Item) { int count = MassUtility.CountToPickUpUntilOverEncumbered(pawn, item); if (count == 0) { continue; } count = Math.Min(count, item.stackCount); string displayText = UIText.Pickup.Translate(item.LabelNoCount + " x" + count); var option = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption( displayText , () => { Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, item); job.count = count; pawn.jobs.TryTakeOrderedJob(job); }) , pawn , item); opts.Add(option); } } }