public static void CheckIfPawnShouldUnloadInventory(Pawn pawn, bool forced = false) { Job job = JobMaker.MakeJob(PickUpAndHaulJobDefOf.UnloadYourHauledInventory, pawn); CompHauledToInventory itemsTakenToInventory = pawn.TryGetComp <CompHauledToInventory>(); if (itemsTakenToInventory == null) { return; } HashSet <Thing> carriedThing = itemsTakenToInventory.GetHashSet(); if (pawn.Faction != Faction.OfPlayer || !pawn.RaceProps.Humanlike) { return; } if (carriedThing == null || carriedThing.Count == 0 || pawn.inventory.innerContainer.Count == 0) { return; } if (forced) { if (job.TryMakePreToilReservations(pawn, false)) { pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc); return; } } if (MassUtility.EncumbrancePercent(pawn) >= 0.90f || carriedThing.Count >= 1) { if (job.TryMakePreToilReservations(pawn, false)) { pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc); return; } } if (pawn.inventory.innerContainer?.Count >= 1) { foreach (Thing rottable in pawn.inventory.innerContainer) { CompRottable compRottable = rottable.TryGetComp <CompRottable>(); if (compRottable?.TicksUntilRotAtCurrentTemp < 30000) { pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc); return; } } } if (Find.TickManager.TicksGame % 50 == 0 && pawn.inventory.innerContainer.Count < carriedThing.Count) { Verse.Log.Warning("[PickUpAndHaul] " + pawn + " inventory was found out of sync with haul index. Pawn will drop their inventory."); carriedThing.Clear(); pawn.inventory.UnloadEverything = true; } }
/// <summary> /// the workgiver checks for encumbered, this is purely extra for CE /// </summary> /// <returns></returns> public Toil CheckForOverencumberedForCombatExtended() { Toil toil = new Toil(); if (!ModCompatibilityCheck.CombatExtendedIsActive) { return(toil); } toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing nextThing = curJob.targetA.Thing; var ceOverweight = CompatHelper.CeOverweight(pawn); if (!(MassUtility.EncumbrancePercent(actor) <= 0.9f && !ceOverweight)) { Job haul = HaulAIUtility.HaulToStorageJob(actor, nextThing); if (haul?.TryMakePreToilReservations(actor, false) ?? false) { //note that HaulToStorageJob etc doesn't do opportunistic duplicate hauling for items in valid storage. REEEE actor.jobs.jobQueue.EnqueueFirst(haul, JobTag.Misc); EndJobWith(JobCondition.Succeeded); } } }; return(toil); }
public Toil CheckForOverencumbered() { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing nextThing = curJob.targetA.Thing; //float usedBulkByPct = 1f; //float usedWeightByPct = 1f; //try //{ // ((Action)(() => // { // if (ModCompatibilityCheck.CombatExtendedIsActive) // { // CompInventory ceCompInventory = actor.GetComp<CompInventory>(); // usedWeightByPct = ceCompInventory.currentWeight / ceCompInventory.capacityWeight; // usedBulkByPct = ceCompInventory.currentBulk / ceCompInventory.capacityBulk; // } // }))(); //} //catch (TypeLoadException) { } if (!(MassUtility.EncumbrancePercent(actor) <= 0.9f /*|| usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f*/)) { Job haul = HaulAIUtility.HaulToStorageJob(actor, nextThing); if (haul?.TryMakePreToilReservations(actor, false) ?? false) { //note that HaulToStorageJob etc doesn't do opportunistic duplicate hauling for items in valid storage. REEEE actor.jobs.jobQueue.EnqueueFirst(haul, JobTag.Misc); EndJobWith(JobCondition.Succeeded); } } }; return(toil); }
//regular Toils_Haul.CheckForGetOpportunityDuplicate isn't going to work for our purposes, since we're not carrying anything. //Carrying something yields weird results with unspawning errors when transfering to inventory, so we copy-past-- I mean, implement our own. public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, float distanceToOthers, Predicate <Thing> extraValidator = null) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; IntVec3 storeCell = IntVec3.Invalid; Predicate <Thing> validator = (Thing t) => t.Spawned && HaulAIUtility.PawnCanAutomaticallyHaulFast(actor, t, false) && (!t.IsInValidBestStorage()) && !t.IsForbidden(actor) && !(t is Corpse) && (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out storeCell, true)) && (extraValidator == null || extraValidator(t)) && actor.CanReserve(t, 1, -1, null, false); Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), Math.Max(distanceToOthers, 12f), validator, null, 0, -1, false, RegionType.Set_Passable, false); float usedBulkByPct = 1f; float usedWeightByPct = 1f; try { ((Action)(() => { if (ModCompatibilityCheck.CombatExtendedIsActive) { CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>(); usedWeightByPct = ceCompInventory.currentWeight / ceCompInventory.capacityWeight; usedBulkByPct = ceCompInventory.currentBulk / ceCompInventory.capacityBulk; } }))(); } catch (TypeLoadException) { } if (thing != null && (MassUtility.EncumbrancePercent(actor) <= 0.9f || usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f)) { curJob.SetTarget(haulableInd, thing); actor.Reserve(storeCell, this.job, 1, -1, null); actor.jobs.curDriver.JumpToToil(getHaulTargetToil); return; } if (thing != null) { Job haul = HaulAIUtility.HaulToStorageJob(actor, thing); if (haul?.TryMakePreToilReservations(actor) ?? false) { actor.jobs.jobQueue.EnqueueFirst(haul, new JobTag?(JobTag.Misc)); this.EndJobWith(JobCondition.Succeeded); } } if (thing == null) { Job job = new Job(PickUpAndHaulJobDefOf.UnloadYourHauledInventory); if (job.TryMakePreToilReservations(actor)) { actor.jobs.jobQueue.EnqueueFirst(job, new JobTag?(JobTag.Misc)); this.EndJobWith(JobCondition.Succeeded); } } }; return(toil); }