public static int CanFitInInventory(Pawn pawn, Thing thing) { CombatExtended.CompInventory ceCompInventory = pawn.GetComp <CombatExtended.CompInventory>(); ceCompInventory.CanFitInInventory(thing, out int countToPickUp); return(countToPickUp); }
//reserve, goto, take, check for more. Branches off to "all over the place" protected override IEnumerable <Toil> MakeNewToils() { CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>(); HashSet <Thing> carriedThings = takenToInventory.GetHashSet(); DesignationDef HaulUrgentlyDesignation = DefDatabase <DesignationDef> .GetNamed("HaulUrgentlyDesignation", false); //Thanks to AlexTD for the more dynamic search range float searchForOthersRangeFraction = 0.5f; float distanceToOthers = 0f; Toil wait = Toils_General.Wait(2); Toil reserveTargetA = Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null); Toil calculateExtraDistanceToGo = new Toil { initAction = () => { if (StoreUtility.TryFindStoreCellNearColonyDesperate(this.job.targetA.Thing, this.pawn, out IntVec3 storeLoc)) { distanceToOthers = (storeLoc - job.targetA.Thing.Position).LengthHorizontal * searchForOthersRangeFraction; } } }; yield return(calculateExtraDistanceToGo); Toil checkForOtherItemsToHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, distanceToOthers, null); Toil checkForOtherItemsToUrgentlyHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, distanceToOthers, (Thing x) => pawn.Map.designationManager.DesignationOn(x)?.def == HaulUrgentlyDesignation); yield return(reserveTargetA); Toil gotoThing = new Toil { initAction = () => { this.pawn.pather.StartPath(this.TargetThingA, PathEndMode.ClosestTouch); }, defaultCompleteMode = ToilCompleteMode.PatherArrival, }; gotoThing.FailOnDespawnedNullOrForbidden(TargetIndex.A); yield return(gotoThing); Toil takeThing = new Toil { initAction = () => { Pawn actor = this.pawn; Thing thing = actor.CurJob.GetTarget(TargetIndex.A).Thing; Toils_Haul.ErrorCheckForCarry(actor, thing); //get max we can pick up int num = Mathf.Min(thing.stackCount, MassUtility.CountToPickUpUntilOverEncumbered(actor, thing)); // yo dawg, I heard you like delegates so I put delegates in your delegate, so you can delegate your delegates. // because compilers don't respect IF statements in delegates and toils are fully iterated over as soon as the job starts. try { ((Action)(() => { if (ModCompatibilityCheck.CombatExtendedIsActive) { CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>(); ceCompInventory.CanFitInInventory(thing, out num, false, false); } }))(); } catch (TypeLoadException) { } //can't store more, so queue up hauling if we can + end the current job (smooth/instant transition) if (num <= 0) { Job haul = HaulAIUtility.HaulToStorageJob(actor, thing); if (haul?.TryMakePreToilReservations(actor) ?? false) { actor.jobs.jobQueue.EnqueueFirst(haul, new JobTag?(JobTag.Misc)); } actor.jobs.curDriver.JumpToToil(wait); } else { bool isUrgent = false; if (ModCompatibilityCheck.AllowToolIsActive) { //check BEFORE absorbing the thing, designation disappears when it's in inventory :^) if (pawn.Map.designationManager.DesignationOn(thing)?.def == HaulUrgentlyDesignation) { isUrgent = true; } } actor.inventory.GetDirectlyHeldThings().TryAdd(thing.SplitOff(num), true); takenToInventory.RegisterHauledItem(thing); try { ((Action)(() => { if (ModCompatibilityCheck.CombatExtendedIsActive) { CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>(); ceCompInventory.UpdateInventory(); } }))(); } catch (TypeLoadException) { } if (isUrgent) { actor.jobs.curDriver.JumpToToil(checkForOtherItemsToUrgentlyHaulToInventory); } } } }; yield return(takeThing); yield return(checkForOtherItemsToHaulToInventory); //we end the job in there, so only one of the checks for duplicates gets called. yield return(checkForOtherItemsToUrgentlyHaulToInventory); yield return(wait); }