/// <summary> /// Set Pawn's loadout. Called by a harmony patch, Pawn_OutfitTracker_CurrentOutfit. /// </summary> /// <param name="pawn"> Set loadout on this <paramref name="pawn"/>. </param> /// <param name="loadout"> Loadout to assign to <paramref name="pawn"/>. </param> /// <param name="delay"> If true, put jobs for changing apparel in job queue, otherwise, execute jobs immediately. </param> /// <param name="forced"> If true, update pawn's comp for <paramref name="loadout"/> even though it is the same as current loadout. </param> public static void SetLoadout(this Pawn pawn, AwesomeInventoryLoadout loadout, bool delay = false, bool forced = false) { if (pawn.TryGetComp <CompAwesomeInventoryLoadout>() is CompAwesomeInventoryLoadout comp) { if (comp.Loadout == loadout && !forced) { return; } ApparelOptionUtility.StopDressingJobs(pawn); comp.UpdateForNewLoadout(loadout, delay, forced: forced); if (loadout == pawn.outfits.CurrentOutfit) { return; } pawn.outfits.CurrentOutfit = loadout; if (!comp.HotSwapCostume?.InSameLoadoutTree(loadout) ?? true) { comp.HotSwapCostume = null; comp.LoadoutBeforeHotSwap = null; comp.HotswapState = CompAwesomeInventoryLoadout.HotSwapState.Inactive; } } }
public static void Postfix(bool value, Pawn_DraftController __instance) { ValidateArg.NotNull(__instance, nameof(__instance)); if (!value) { CompAwesomeInventoryLoadout comp = __instance.pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp != null && comp.HotswapState != CompAwesomeInventoryLoadout.HotSwapState.Inactive && comp.HotSwapCostume != null && comp.Loadout == comp.HotSwapCostume) { if (comp.LoadoutBeforeHotSwap != null && comp.LoadoutBeforeHotSwap != comp.HotSwapCostume) { ApparelOptionUtility.StopDressingJobs(__instance.pawn); __instance.pawn.SetLoadout(comp.LoadoutBeforeHotSwap); comp.LoadoutBeforeHotSwap = null; comp.HotswapState = CompAwesomeInventoryLoadout.HotSwapState.Inactive; } } } }
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 (!SimpleSidearmUtility.IsActive && equipment.def.IsWeapon && !MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, equipment, 1) && !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(); } opts.Add(ContextMenuUtility.MakeDecoratedEquipOption(pawn, equipment, text3, () => AddToLoadoutDialog(equipment))); } } } } // 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() && !MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, apparel, apparel.stackCount) && ApparelOptionUtility.CanWear(pawn, apparel)) { opts.Add( ContextMenuUtility.MakeDecoratedWearApparelOption( pawn, apparel, UIText.AIForceWear.Translate(apparel.LabelShort), true, () => AddToLoadoutDialog(apparel))); opts.Add( ContextMenuUtility.MakeDecoratedWearApparelOption( pawn, apparel, UIText.AIWear.Translate(apparel.LabelShort), false, () => AddToLoadoutDialog(apparel))); } } } void AddToLoadoutDialog(Thing thing1) { if (AwesomeInventoryMod.Settings.OpenLoadoutInContextMenu && pawn.UseLoadout(out Loadout.CompAwesomeInventoryLoadout comp)) { Find.WindowStack.Add( new Dialog_InstantMessage( UIText.AddToLoadout.Translate(comp.Loadout.label) + Environment.NewLine + $"({UIText.DisableWindowInModSetting.TranslateSimple()})" , _size , "Yes".TranslateSimple() , () => ContextMenuUtility.AddToLoadoutDialog(pawn, comp, thing1) , "No".TranslateSimple())); } } }
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); } } } }
/// <inheritdoc/> public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) { ValidateArg.NotNull(pawn, nameof(pawn)); if (Find.TickManager.TicksGame < _optimizedTick) { return(ThinkResult.NoJob); } CompAwesomeInventoryLoadout comp = pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp?.Loadout == null || comp.Loadout.GetType() == typeof(AwesomeInventoryCostume)) { return(ThinkResult.NoJob); } List <Thing> list = pawn.inventory?.innerContainer?.ToList(); if (list == null) { return(ThinkResult.NoJob); } if (!list.Any()) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } List <Apparel> wornApparels = pawn.apparel?.WornApparel; if (wornApparels == null) { return(ThinkResult.NoJob); } AwesomeInventoryCostume costume = comp.Loadout as AwesomeInventoryCostume; var thingList = list .Where(t => t is Apparel apparel && ApparelOptionUtility.CanWear(pawn, apparel)) .Select(t => new { thing = t, score = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, (Apparel)t) }) .Where(thingScore => thingScore.score > 0.05f) .OrderByDescending(s => s.score) .ToList(); if (!thingList.Any()) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } List <Apparel> wornCostume = null; if (costume != null) { wornCostume = pawn.apparel.WornApparel .AsParallel() .Where(a => costume.CostumeItems.Any(c => c.Allows(a, out _))) .ToList(); } foreach (var t in thingList) { Thing thing = null; if (costume == null) { thing = t.thing; } else { foreach (ThingGroupSelector selector in costume.CostumeItems) { if (selector.Allows(t.thing, out _)) { thing = t.thing; break; } } if (thing == null) { if (wornCostume.NullOrEmpty() || wornCostume.All(c => ApparelUtility.CanWearTogether(c.def, t.thing.def, BodyDefOf.Human))) { thing = t.thing; } } } if (thing != null) { return(new ThinkResult( new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, thing, false) , this , JobTag.ChangingApparel)); } } _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); }
/// <inheritdoc/> public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) { ValidateArg.NotNull(pawn, nameof(pawn)); if (Find.TickManager.TicksGame < _optimizedTick) { return(ThinkResult.NoJob); } CompAwesomeInventoryLoadout comp = pawn.TryGetComp <CompAwesomeInventoryLoadout>(); if (comp == null || !(comp.Loadout is AwesomeInventoryLoadout)) { return(ThinkResult.NoJob); } List <Thing> list = pawn.inventory?.innerContainer?.ToList(); if (list == null) { return(ThinkResult.NoJob); } if (!list.Any()) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } float bestScore = 0f; Thing thing = null; for (int i = 0; i < list.Count; i++) { if (list[i] is Apparel apparel && ApparelOptionUtility.CanWear(pawn, apparel)) { if (comp.Loadout is AwesomeInventoryCostume costume) { if (!costume.CostumeItems.Any(c => c.Allows(apparel, out _))) { continue; } } float score = JobGiver_OptimizeApparel.ApparelScoreGain(pawn, apparel); if (!(score < 0.05f) && !(score < bestScore)) { thing = apparel; bestScore = score; } } } if (thing == null) { _optimizedTick = _optmizedInterval + Find.TickManager.TicksGame; return(ThinkResult.NoJob); } else { return(new ThinkResult(new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, thing, false), this, JobTag.ChangingApparel)); } }