/// <summary>
        /// Try to give a job to <paramref name="pawn"/>.
        /// </summary>
        /// <param name="pawn"> Pawn that will be assigned a job to. </param>
        /// <returns> A job assigned to <paramref name="pawn"/>. </returns>
        protected override Job TryGiveJob(Pawn pawn)
        {
#if DEBUG
            Log.Message(pawn.Name + "Take arm");
#endif
            if (!AwesomeInvnetoryMod.Settings.AutoEquipWeapon)
            {
                return(null);
            }

            ValidateArg.NotNull(pawn, nameof(pawn));

            if (!pawn.Faction.IsPlayer)
            {
                return(null);
            }

            if (!pawn.RaceProps.Humanlike)
            {
                return(null);
            }

            if (pawn.Drafted)
            {
                return(null);
            }

            if (pawn.equipment == null)
            {
                return(null);
            }

            if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)
                ||
                pawn.WorkTagIsDisabled(WorkTags.Violent))
            {
                return(null);
            }

            if (pawn.Map == null)
            {
                return(null);
            }

            if (_parent == null)
            {
                if (parent is JobGiver_FindItemByRadius p)
                {
                    _parent = p;
                }
                else
                {
                    throw new InvalidOperationException(ErrorText.WrongTypeParentThinkNode);
                }
            }

            bool isBrawler    = pawn.story?.traits?.HasTrait(TraitDefOf.Brawler) ?? false;
            bool preferRanged = !isBrawler && (pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level ||
                                               pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6);
            bool hasPrimary = pawn.equipment.Primary != null;

            // Switch to better suited weapon
            if (!GameComponent_AwesomeInventory_Entry.HasSimpleSidearm && pawn.inventory.innerContainer.Any())
            {
                IEnumerable <Thing> weapons = from thing in pawn.inventory.innerContainer.InnerListForReading
                                              where thing.def.IsWeapon
                                              select thing;

                ThingWithComps meleeWeapon = (ThingWithComps)weapons
                                             .Where(w => w.def.IsMeleeWeapon)
                                             .OrderBy(w => w.GetStatValue(StatDefOf.MeleeWeapon_AverageDPS))
                                             .FirstOrDefault();
                ThingWithComps rangedWeapon = (ThingWithComps)weapons.FirstOrDefault(w => w.def.IsRangedWeapon);

                if (meleeWeapon == null && rangedWeapon == null)
                {
                    return(null);
                }

                if (preferRanged)
                {
                    if (rangedWeapon != null)
                    {
                        if (!(hasPrimary && pawn.equipment.Primary.def.IsRangedWeapon))
                        {
                            TrySwitchToWeapon(rangedWeapon, pawn);
                        }
                    }
                }
                else
                {
                    if (!(hasPrimary && pawn.equipment.Primary.def.IsMeleeWeapon))
                    {
                        if (meleeWeapon != null)
                        {
                            TrySwitchToWeapon(meleeWeapon, pawn);
                        }
                    }
                }

                return(null);
            }

            // Find and equip a suitable weapon
            if (!hasPrimary)
            {
                Thing closestWeapon = _parent.FindItem(
                    pawn
                    , pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Weapon)
                    , null
                    , (Thing x) => preferRanged ? (x.def.IsRangedWeapon ? 2f : 1f) : (x.def.IsMeleeWeapon ? 2f : 1f));

                if (closestWeapon == null)
                {
                    return(null);
                }

                return(new Job(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, closestWeapon));
            }

            return(null);
        }
        /// <summary>
        /// Try to give a job to <paramref name="pawn"/> for items that needs to restock.
        /// </summary>
        /// <param name="pawn"> Pawn for the job. </param>
        /// <returns> A job to stock up items in <see cref="AwesomeInventoryLoadout"/>. </returns>
        protected override Job TryGiveJob(Pawn pawn)
        {
            ValidateArg.NotNull(pawn, nameof(pawn));

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

            Thing targetA = null;
            ThingGroupSelector groupSelector;
            int stackcount = 0;

            foreach (KeyValuePair <ThingGroupSelector, int> pair in aiLoadout.ItemsToRestock)
            {
                groupSelector = pair.Key;
                stackcount    = pair.Value;
                if (!groupSelector.AllowedThing.IsApparel && !groupSelector.AllowedThing.IsWeapon)
                {
                    if (groupSelector.AllowedThing is AIGenericDef genericDef)
                    {
                        List <List <Thing> > thingLists = new List <List <Thing> >();
                        foreach (ThingDef thingDef in genericDef.AvailableDefs)
                        {
                            List <Thing> things = pawn.Map.listerThings.ThingsOfDef(thingDef);
                            if (things.Any())
                            {
                                thingLists.Add(things);
                            }
                        }

                        Thing foundThing = null;
                        foreach (List <Thing> thingList in thingLists)
                        {
                            foundThing =
                                _parent.FindItem(
                                    pawn
                                    , thingList
                                    , (thing) =>
                            {
                                Thing innerThing = thing.GetInnerIfMinified();
                                return(groupSelector.Allows(innerThing, out _)
                                       &&
                                       !aiLoadout.Loadout.IncludedInBlacklist(innerThing));
                            });

                            if (foundThing != null)
                            {
                                break;
                            }
                        }

                        targetA = foundThing;
                    }
                    else
                    {
                        if (groupSelector.AllowedThing.Minifiable)
                        {
                            // There is a bug if add minifiedThings to searchSet by searchSet.AddRange() or searchSet.Add()
                            IEnumerable <Thing> minifiedThings = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.MinifiedThing)
                                                                 .Where(t => (t as MinifiedThing).InnerThing.def == groupSelector.AllowedThing);

                            targetA =
                                _parent.FindItem(
                                    pawn
                                    , minifiedThings
                                    , (thing) =>
                            {
                                Thing innerThing = thing.GetInnerIfMinified();
                                return(groupSelector.Allows(innerThing, out _)
                                       &&
                                       !aiLoadout.Loadout.IncludedInBlacklist(innerThing));
                            });
                        }

                        if (targetA == null)
                        {
                            targetA =
                                _parent.FindItem(
                                    pawn
                                    , pawn.Map.listerThings.ThingsOfDef(groupSelector.AllowedThing)
                                    , (thing) =>
                            {
                                Thing innerThing = thing.GetInnerIfMinified();
                                return(groupSelector.Allows(innerThing, out _)
                                       &&
                                       !aiLoadout.Loadout.IncludedInBlacklist(innerThing));
                            });
                        }
                    }

                    if (targetA != null)
                    {
                        break;
                    }
                }
            }

            if (targetA == null)
            {
                return(null);
            }
            else
            {
                Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, targetA);
                job.count = Math.Min(targetA.stackCount, stackcount * -1);
                return(job);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Try to give a job to <paramref name="pawn"/>.
        /// </summary>
        /// <param name="pawn"> Pawn that will be assigned a job to. </param>
        /// <returns> A job assigned to <paramref name="pawn"/>. </returns>
        protected override Job TryGiveJob(Pawn pawn)
        {
#if DEBUG
            ValidateArg.NotNull(pawn, nameof(pawn));
            Log.Message(pawn.Name + "Looking for weapons");
#endif
            if (CombatExtendedUtility.IsActive)
            {
                return(null);
            }

            ValidateArg.NotNull(pawn, nameof(pawn));

            if (!pawn.Faction.IsPlayer)
            {
                return(null);
            }

            if (!pawn.RaceProps.Humanlike)
            {
                return(null);
            }

            if (pawn.Drafted)
            {
                return(null);
            }

            if (pawn.equipment == null)
            {
                return(null);
            }

            if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)
                ||
                pawn.WorkTagIsDisabled(WorkTags.Violent))
            {
                return(null);
            }

            if (pawn.Map == null)
            {
                return(null);
            }

            if (_parent == null)
            {
                if (parent is JobGiver_FindItemByRadius p)
                {
                    _parent = p;
                }
                else
                {
                    throw new InvalidOperationException(ErrorText.WrongTypeParentThinkNode);
                }
            }

            if (pawn.TryGetComp <CompAwesomeInventoryLoadout>() is CompAwesomeInventoryLoadout compLoadout)
            {
                if (compLoadout.NeedRestock)
                {
                    foreach (KeyValuePair <ThingGroupSelector, int> pair in compLoadout.ItemsToRestock)
                    {
                        // Exclude beer and other drugs that are also categoried as weapon
                        ThingDef thingDef = pair.Key.AllowedThing;
                        if (thingDef.IsWeapon && !thingDef.IsDrug && !thingDef.IsStuff)
                        {
                            Thing targetThingA =
                                _parent.FindItem(
                                    pawn
                                    , pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Weapon)
                                    , (thing) => pair.Key.Allows(thing, out _)
                                    &&
                                    !compLoadout.Loadout.IncludedInBlacklist(thing)
                                    &&
                                    EquipmentUtility.CanEquip(thing, pawn));

                            if (targetThingA != null)
                            {
                                Job job = JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, targetThingA);
                                if (pawn.Reserve(targetThingA, job, errorOnFailed: false))
                                {
                                    return(job);
                                }
                                else
                                {
                                    JobMaker.ReturnToPool(job);
                                    return(null);
                                }
                            }
                        }
                    }
                }
            }

            return(null);
        }
        /// <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) => ailoadout.Loadout.filter.Allows(thing) &&
                            groupSelector.Allows(thing, out _) &&
                            !ailoadout.Loadout.IncludedInBlacklist(thing) &&
                            (thing.def.apparel.gender == Gender.None || thing.def.apparel.gender == pawn.gender) &&
                            (!thing.def.apparel.tags.Contains("Royal") || pawn.royalty.AllTitlesInEffectForReading.Count != 0));

                    if (targetA != null)
                    {
                        if (pawn.outfits?.CurrentOutfit is AwesomeInventoryCostume costume)
                        {
                            if (costume.CostumeItems.Any(c => c.Allows(targetA, out _)))
                            {
                                return(new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, targetA, false));
                            }
                            else
                            {
                                Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, targetA);
                                job.count = targetA.stackCount;
                                return(job);
                            }
                        }

                        return(new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, targetA, false));
                    }
                }
            }

            return(null);
        }