예제 #1
0
        /// <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;
                }
            }
        }
예제 #2
0
        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()));
                }
            }
        }
예제 #4
0
        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);
                    }
                }
            }
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        /// <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));
            }
        }