public void EquipIntoSlot(GearData gear, LoadoutSlots slot) { if (!CanEquipIntoSlot(gear, slot)) { throw new ArgumentException("Cannot equip " + gear + " into " + slot.ToString()); } LoadoutSlot slotcontainer = slots[slot]; slotcontainer.contains = gear; }
public bool CanEquipIntoSlot(GearData gear, LoadoutSlots slot) { if (!SlotIsFree(slot)) { return(false); } LoadoutSlot slotcontainer = slots[slot]; if (slotcontainer.type != gear.requiredSlot) { return(false); } return(true); }
/// <summary> /// This starts the work of finding something lacking that the pawn should pickup. /// </summary> /// <param name="pawn">Pawn who's inventory and loadout should be considered.</param> /// <param name="priority">Priority value for how important doing this job is.</param> /// <param name="closestThing">The thing found to be picked up.</param> /// <param name="count">The amount of closestThing to pickup. Already checked if inventory can hold it.</param> /// <param name="carriedBy">If unable to find something on the ground to pickup, the pawn (pack animal/prisoner) which has the item to take.</param> /// <returns>LoadoutSlot which has something that can be picked up.</returns> private LoadoutSlot GetPrioritySlot(Pawn pawn, out ItemPriority priority, out Thing closestThing, out int count, out Pawn carriedBy) { priority = ItemPriority.None; LoadoutSlot slot = null; closestThing = null; count = 0; carriedBy = null; CompInventory inventory = pawn.TryGetComp <CompInventory>(); if (inventory?.container != null) { } return(slot); }
/// <summary> /// Similar to GetExcessThing though narrower in scope. If there is NOT a loadout which covers the equipped item, it should be dropped. /// </summary> /// <param name="pawn"></param> /// <param name="dropEquipment">Thing which should be unequiped.</param> /// <returns>bool, true if there is equipment that should be unequipped.</returns> static public bool GetExcessEquipment(this Pawn pawn, out ThingWithComps dropEquipment) { Loadout loadout = pawn.GetLoadout(); dropEquipment = null; if (loadout == null || (loadout != null && loadout.Slots.NullOrEmpty()) || pawn.equipment?.Primary == null) { return(false); } LoadoutSlot eqSlot = loadout.Slots.FirstOrDefault(s => s.count >= 1 && ((s.thingDef != null && s.thingDef == pawn.equipment.Primary.def) || (s.genericDef != null && s.genericDef.lambda(pawn.equipment.Primary.def)))); if (eqSlot == null) { dropEquipment = pawn.equipment.Primary; return(true); } return(false); }
/// <summary> /// Tries to give the pawn a job related to picking up or dropping an item from their inventory. /// </summary> /// <param name="pawn">Pawn to which the job is given.</param> /// <returns>Job that the pawn was instructed to do, be it hauling a dropped Thing or going and getting a Thing.</returns> protected override Job TryGiveJob(Pawn pawn) { // Get inventory CompInventory inventory = pawn.TryGetComp <CompInventory>(); if (inventory == null) { return(null); } RPGILoadout loadout = pawn.GetLoadout(); if (loadout != null) { ThingWithComps dropEq; ThingWithComps droppedEq; if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out droppedEq, pawn.Position, false)) { if (droppedEq != null) { return(HaulAIUtility.HaulToStorageJob(pawn, droppedEq)); } } Thing dropThing = new Thing(); int dropCount = 0; Thing droppedThing; if (inventory.container.TryDrop(dropThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, dropCount, out droppedThing)) { if (droppedThing != null) { return(HaulAIUtility.HaulToStorageJob(pawn, droppedThing)); } Log.Error(string.Concat(pawn, " tried dropping ", dropThing, " from loadout but resulting thing is null")); } // Find missing items ItemPriority priority; Thing closestThing; int count; Pawn carriedBy; bool doEquip = false; LoadoutSlot prioritySlot = GetPrioritySlot(pawn, out priority, out closestThing, out count, out carriedBy); // moved logic to detect if should equip vs put in inventory here... if (closestThing != null) { if (closestThing.TryGetComp <CompEquippable>() != null && !(pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) && (pawn.health != null && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) && (pawn.equipment == null || pawn.equipment.Primary == null || !loadout.Any(s => s.def == pawn.equipment.Primary.def))) { doEquip = true; } if (carriedBy == null) { // Equip gun if unarmed or current gun is not in loadout if (doEquip) { return(new Job(JobDefOf.Equip, closestThing)); } return(new Job(JobDefOf.TakeInventory, closestThing) { count = Mathf.Min(closestThing.stackCount, count) }); } else { // TODO Implement Take from Others //return new Job(CE_JobDefOf.TakeFromOther, closestThing, carriedBy, doEquip ? pawn : null) //{ // count = doEquip ? 1 : Mathf.Min(closestThing.stackCount, count) //}; return(null); } } } return(null); }
/// <summary> /// Used by GetPrioritySlot, actually finds a requested thing. /// </summary> /// <param name="pawn">Pawn to be considered. Used in checking equipment and position when looking for nearby things.</param> /// <param name="curSlot">Pawn's LoadoutSlot being considered.</param> /// <param name="findCount">Amount of Thing of ThingDef to try and pickup.</param> /// <param name="curPriority">Priority of the job.</param> /// <param name="curThing">Thing found near pawn for potential pickup.</param> /// <param name="curCarrier">Pawn that is holding the curThing that 'pawn' wants.</param> /// <remarks>Was split off into a sepearate method so the code could be run from multiple places in caller but that is no longer needed.</remarks> private void FindPickup(Pawn pawn, LoadoutSlot curSlot, int findCount, out ItemPriority curPriority, out Thing curThing, out Pawn curCarrier) { curPriority = ItemPriority.None; curThing = null; curCarrier = null; Predicate <Thing> isFoodInPrison = (Thing t) => (t.GetRoom()?.isPrisonCell ?? false) && t.def.IsNutritionGivingIngestible && pawn.Faction.IsPlayer; // Hint: The following block defines how to find items... pay special attention to the Predicates below. ThingRequest req; if (curSlot.genericDef != null) { req = ThingRequest.ForGroup(curSlot.genericDef.thingRequestGroup); } else { req = curSlot.thingDef.Minifiable ? ThingRequest.ForGroup(ThingRequestGroup.MinifiedThing) : ThingRequest.ForDef(curSlot.thingDef); } Predicate <Thing> findItem; if (curSlot.genericDef != null) { findItem = t => curSlot.genericDef.lambda(t.GetInnerIfMinified().def); } else { findItem = t => t.GetInnerIfMinified().def == curSlot.thingDef; } Predicate <Thing> search = t => findItem(t) && !t.IsForbidden(pawn) && pawn.CanReserve(t) && !isFoodInPrison(t); // look for a thing near the pawn. curThing = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, req, PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), ProximitySearchRadius, search); if (curThing != null) { curPriority = ItemPriority.Proximity; } else { // look for a thing basically anywhere on the map. curThing = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, req, PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), MaximumSearchRadius, search); if (curThing == null && pawn.Map != null) { // look for a thing inside caravan pack animals and prisoners. EXCLUDE other colonists to avoid looping state. List <Pawn> carriers = pawn.Map.mapPawns.AllPawns.Where( p => (p.inventory?.innerContainer?.InnerListForReading?.Any() ?? false) && (p.RaceProps.packAnimal && p.Faction == pawn.Faction || p.IsPrisoner && p.HostFaction == pawn.Faction) && pawn.CanReserveAndReach(p, PathEndMode.ClosestTouch, Danger.Deadly, int.MaxValue, 0)).ToList(); foreach (Pawn carrier in carriers) { Thing thing = carrier.inventory.innerContainer.FirstOrDefault(t => findItem(t)); if (thing != null) { curThing = thing; curCarrier = carrier; break; } } } if (curThing != null) { if (!curThing.def.IsNutritionGivingIngestible && (float)findCount / curSlot.count >= 0.5f) { curPriority = ItemPriority.LowStock; } else { curPriority = ItemPriority.Low; } } } }
public bool SlotIsFree(LoadoutSlots slot) { LoadoutSlot slotcontainer = slots[slot]; return(!slotcontainer.hidden && slotcontainer.contains == null); }
public void UnequipFromSlot(LoadoutSlots slot) { LoadoutSlot slotcontainer = slots[slot]; slotcontainer.contains = null; }