/// <summary> /// Give a haul job to <paramref name="pawn"/>. /// </summary> /// <param name="pawn"> Pawm that looks for a job. </param> /// <returns> A potential job for <paramref name="pawn"/>. </returns> protected override Job TryGiveJob(Pawn pawn) { #if DEBUG Log.Message(pawn.Name + "Looking for things to haul"); #endif if (_parent == null) { if (parent is JobGiver_FindItemByRadius p) { _parent = p; } else { throw new InvalidOperationException(ErrorText.WrongTypeParentThinkNode); } } if (_parent.Itemfound) { ValidateArg.NotNull(pawn, nameof(pawn)); List <WorkGiverDef> workGivers = WorkTypeDefOf.Hauling.workGiversByPriority; if (workGivers[0].Worker is WorkGiver_Scanner scanner) { IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn); if (enumerable == null || enumerable.Any()) { return(null); } Thing thing = GenClosest.ClosestThing_Global_Reachable( pawn.Position , pawn.Map , enumerable , scanner.PathEndMode , TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)) , _parent.Radius[0] , t => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t)); if (thing != null) { return(scanner.JobOnThing(pawn, thing)); } } } return(null); }
/// <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"/>. /// </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> /// 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); } }
/// <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); }