/// <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);
        }
Exemple #3
0
        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);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #5
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);
                    }
                }
            }
        }
        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);
                }
            }
        }