Пример #1
0
        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;
            }
        }
Пример #2
0
        static ThingCount FirstUnloadableThing(Pawn pawn)
        {
            CompHauledToInventory itemsTakenToInventory = pawn.TryGetComp <CompHauledToInventory>();
            HashSet <Thing>       carriedThings         = itemsTakenToInventory.GetHashSet();

            //find the overlap.
            IEnumerable <Thing> potentialThingsToUnload =
                from t in pawn.inventory.innerContainer
                where carriedThings.Contains(t)
                select t;

            foreach (Thing thing in carriedThings.OrderBy(t => t.def.FirstThingCategory?.index))
            {
                //merged partially picked up stacks get a different thingID in inventory
                if (!potentialThingsToUnload.Contains(thing))
                {
                    ThingDef stragglerDef = thing.def;
                    //we have no method of grabbing the newly generated thingID. This is the solution to that.
                    IEnumerable <Thing> dirtyStragglers =
                        from straggler in pawn.inventory.innerContainer
                        where straggler.def == stragglerDef
                        select straggler;

                    carriedThings.Remove(thing);

                    foreach (Thing dirtyStraggler in dirtyStragglers)
                    {
                        return(new ThingCount(dirtyStraggler, dirtyStraggler.stackCount));
                    }
                }
                return(new ThingCount(thing, thing.stackCount));
            }
            return(default(ThingCount));
        }
Пример #3
0
        private static bool AllowToolHaulUrgentlyJobOnThing_PreFix(ref Job __result, Pawn pawn, Thing t, bool forced = false)
        {
            if (ModCompatibilityCheck.AllowToolIsActive)
            {
                //allowTool HaulUrgently
                CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

                if (pawn.RaceProps.Humanlike &&
                    pawn.Faction == Faction.OfPlayer &&
                    t is Corpse == false &&
                    takenToInventory != null &&
                    !(t.def.defName.Contains("Chunk"))    //most of the time we don't have space for it
                    )
                {
                    StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(t);
                    if (!StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true))
                    {
                        JobFailReason.Is("NoEmptyPlaceLower".Translate());
                        return(false);
                    }

                    WorkGiver_HaulToInventory haulWG = (WorkGiver_HaulToInventory)pawn.workSettings.WorkGiversInOrderNormal.Find(wg => wg is WorkGiver_HaulToInventory);

                    Job haul = haulWG.JobOnThing(pawn, t, forced);
                    __result = haul;
                    return(false);
                }
            }
            return(true);
        }
Пример #4
0
        private static void JobDriver_HaulToCell_PostFix(JobDriver_HaulToCell __instance)
        {
            CompHauledToInventory takenToInventory = __instance.pawn.TryGetComp <CompHauledToInventory>();

            if (takenToInventory == null)
            {
                return;
            }

            HashSet <Thing> carriedThing = takenToInventory.GetHashSet();

            if (__instance.job.haulMode == HaulMode.ToCellStorage &&
                __instance.pawn.Faction == Faction.OfPlayer &&
                __instance.pawn.RaceProps.Humanlike &&
                __instance.pawn.carryTracker.CarriedThing is Corpse == false &&
                carriedThing != null &&
                carriedThing.Count != 0)   //deliberate hauling job. Should unload.
            {
                PawnUnloadChecker.CheckIfPawnShouldUnloadInventory(__instance.pawn, true);
            }
            //else //we could politely ask
            //{
            //    PawnUnloadChecker.CheckIfPawnShouldUnloadInventory(__instance.pawn);
            //}
        }
Пример #5
0
        private static bool AllowToolHaulUrgentlyJobOnThing_PreFix(ref Job __result, Pawn pawn, Thing t, bool forced = false)
        {
            if (ModCompatibilityCheck.AllowToolIsActive)
            {
                //allowTool HaulUrgently
                CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

                if (pawn.RaceProps.Humanlike &&
                    pawn.Faction == Faction.OfPlayer &&
                    t is Corpse == false &&
                    takenToInventory != null &&
                    !(t.def.defName.Contains("Chunk"))    //most of the time we don't have space for it
                    )
                {
                    StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
                    if (!StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true))
                    {
                        JobFailReason.Is("NoEmptyPlaceLower".Translate());
                        return(false);
                    }

                    Job haul = new Job(PickUpAndHaulJobDefOf.HaulToInventory, t)
                    {
                        count = t.stackCount
                    };
                    __result = haul;
                    return(false);
                }
            }
            return(true);
        }
        public static Color GetColorForHauled(Pawn pawn, Thing thing)
        {
            CompHauledToInventory comp = pawn.GetComp <CompHauledToInventory>();

            if (comp.GetHashSet().Contains(thing))
            {
                return(Color.Lerp(Color.grey, Color.red, 0.5f));
            }
            return(Color.white);
        }
Пример #7
0
        //pick up stuff until you can't anymore,
        //while you're up and about, pick up something and haul it
        //before you go out, empty your pockets

        public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false)
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

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

            if (thing is Corpse)
            {
                return(null);
            }

            if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced))
            {
                return(null);
            }

            if (thing.IsForbidden(pawn) || StoreUtility.IsInValidBestStorage(thing))
            {
                return(null);
            }

            //bulky gear (power armor + minigun) so don't bother.
            if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f)
            {
                return(null);
            }

            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);

            if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true))
            {
                //since we've gone through all the effort of getting the loc, might as well use it.
                //Don't multi-haul food to hoppers.
                if (thing.def.IsNutritionGivingIngestible)
                {
                    if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty)
                    {
                        List <Thing> thingList = storeCell.GetThingList(thing.Map);
                        for (int i = 0; i < thingList.Count; i++)
                        {
                            Thing thingAtCell = thingList[i];
                            if (thingAtCell.def == ThingDefOf.Hopper)
                            {
                                return(HaulAIUtility.HaulToStorageJob(pawn, thing));
                            }
                        }
                    }
                }
            }
Пример #8
0
        private static bool Drop_Prefix(Pawn pawn, Thing thing)
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

            if (takenToInventory == null)
            {
                return(true);
            }

            HashSet <Thing> carriedThing = takenToInventory.GetHashSet();

            return(!carriedThing.Contains(thing));
        }
Пример #9
0
        private static void Pawn_InventoryTracker_PostFix(Pawn_InventoryTracker __instance, Thing item)
        {
            CompHauledToInventory takenToInventory = __instance.pawn.TryGetComp <CompHauledToInventory>();

            if (takenToInventory == null)
            {
                return;
            }

            HashSet <Thing> carriedThing = takenToInventory.GetHashSet();

            if (carriedThing?.Count > 0)
            {
                if (carriedThing.Contains(item))
                {
                    carriedThing.Remove(item);
                }
            }
        }
        //get next, goto, take, check for more. Branches off to "all over the place"
        protected override IEnumerable <Toil> MakeNewToils()
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

            Toil wait = Toils_General.Wait(2);

            Toil nextTarget = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A); //also does count

            yield return(nextTarget);

            //honestly the workgiver checks for encumbered, so until CE checks are in this is unnecessary
            //yield return CheckForOverencumbered();//Probably redundant without CE checks

            Toil gotoThing = new Toil
            {
                initAction = () =>
                {
                    pawn.pather.StartPath(TargetThingA, PathEndMode.ClosestTouch);
                },
                defaultCompleteMode = ToilCompleteMode.PatherArrival
            };

            gotoThing.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            yield return(gotoThing);

            Toil takeThing = new Toil
            {
                initAction = () =>
                {
                    Pawn  actor = pawn;
                    Thing thing = actor.CurJob.GetTarget(TargetIndex.A).Thing;
                    Toils_Haul.ErrorCheckForCarry(actor, thing);

                    //get max we can pick up
                    int countToPickUp = Mathf.Min(job.count, MassUtility.CountToPickUpUntilOverEncumbered(actor, thing));
                    Log.Message($"{actor} is hauling to inventory {thing}:{countToPickUp}");

                    // 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 countToPickUp);
                            }
                        }))();
                    }
                    catch (TypeLoadException) { }

                    if (countToPickUp > 0)
                    {
                        Thing splitThing  = thing.SplitOff(countToPickUp);
                        bool  shouldMerge = takenToInventory.GetHashSet().Any(x => x.def == thing.def);
                        actor.inventory.GetDirectlyHeldThings().TryAdd(splitThing, shouldMerge);
                        takenToInventory.RegisterHauledItem(splitThing);

                        try
                        {
                            ((Action)(() =>
                            {
                                if (ModCompatibilityCheck.CombatExtendedIsActive)
                                {
                                    //CombatExtended.CompInventory ceCompInventory = actor.GetComp<CombatExtended.CompInventory>();
                                    //ceCompInventory.UpdateInventory();
                                }
                            }))();
                        }
                        catch (TypeLoadException)
                        {
                        }
                    }

                    //thing still remains, so queue up hauling if we can + end the current job (smooth/instant transition)
                    //This will technically release the reservations in the queue, but what can you do
                    if (thing.Spawned)
                    {
                        Job haul = HaulAIUtility.HaulToStorageJob(actor, thing);
                        if (haul?.TryMakePreToilReservations(actor, false) ?? false)
                        {
                            actor.jobs.jobQueue.EnqueueFirst(haul, JobTag.Misc);
                        }
                        actor.jobs.curDriver.JumpToToil(wait);
                    }
                }
            };

            yield return(takeThing);

            yield return(Toils_Jump.JumpIf(nextTarget, () => !job.targetQueueA.NullOrEmpty()));

            //Find more to haul, in case things spawned while this was in progess
            yield return(new Toil
            {
                initAction = () =>
                {
                    List <Thing> haulables = pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling();
                    WorkGiver_HaulToInventory haulMoreWork = DefDatabase <WorkGiverDef> .AllDefsListForReading.First(wg => wg.Worker is WorkGiver_HaulToInventory).Worker as WorkGiver_HaulToInventory;

                    Thing haulMoreThing = GenClosest.ClosestThing_Global(pawn.Position, haulables, 12, t => haulMoreWork.HasJobOnThing(pawn, t));

                    //WorkGiver_HaulToInventory found more work nearby
                    if (haulMoreThing != null)
                    {
                        Log.Message($"{pawn} hauling again : {haulMoreThing}");
                        Job haulMoreJob = haulMoreWork.JobOnThing(pawn, haulMoreThing);

                        if (haulMoreJob.TryMakePreToilReservations(pawn, false))
                        {
                            pawn.jobs.jobQueue.EnqueueFirst(haulMoreJob, JobTag.Misc);
                            EndJobWith(JobCondition.Succeeded);
                        }
                    }
                }
            });

            //maintain cell reservations on the trip back
            //TODO: do that when we carry things
            //I guess that means TODO: implement carrying the rest of the items in this job instead of falling back on HaulToStorageJob
            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.ClosestTouch));

            yield return(new Toil //Queue next job
            {
                initAction = () =>
                {
                    Pawn actor = pawn;
                    Job curJob = actor.jobs.curJob;
                    LocalTargetInfo storeCell = curJob.targetB;

                    Job unloadJob = new Job(PickUpAndHaulJobDefOf.UnloadYourHauledInventory, storeCell);
                    if (unloadJob.TryMakePreToilReservations(actor, false))
                    {
                        actor.jobs.jobQueue.EnqueueFirst(unloadJob, JobTag.Misc);
                        EndJobWith(JobCondition.Succeeded);
                        //This will technically release the cell reservations in the queue, but what can you do
                    }
                }
            });

            yield return(wait);
        }
Пример #11
0
        /// <summary>
        /// Find spot, reserve spot, pull thing out of inventory, go to spot, drop stuff, repeat.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable <Toil> MakeNewToils()
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();
            HashSet <Thing>       carriedThing     = takenToInventory.GetHashSet();

            if (ModCompatibilityCheck.ExtendedStorageIsActive)
            {
                //ES takes at least ~10 ticks to move from the feeder to the stockpile, so workaround ahoy
                UnloadDuration = 20;
            }

            Toil wait      = Toils_General.Wait(UnloadDuration);
            Toil celebrate = Toils_General.Wait(UnloadDuration);

            yield return(wait);

            Toil findSpot = new Toil
            {
                initAction = () =>
                {
                    ThingCount unloadableThing = FirstUnloadableThing(pawn);

                    if (unloadableThing.Count == 0 && carriedThing.Count == 0)
                    {
                        this.EndJobWith(JobCondition.Succeeded);
                    }

                    if (unloadableThing.Count != 0)
                    {
                        //StoragePriority currentPriority = StoreUtility.StoragePriorityAtFor(pawn.Position, unloadableThing.Thing);
                        if (!StoreUtility.TryFindStoreCellNearColonyDesperate(unloadableThing.Thing, this.pawn, out IntVec3 c))
                        {
                            this.pawn.inventory.innerContainer.TryDrop(unloadableThing.Thing, ThingPlaceMode.Near, unloadableThing.Thing.stackCount, out Thing thing);
                            this.EndJobWith(JobCondition.Succeeded);
                        }
                        else
                        {
                            this.job.SetTarget(TargetIndex.A, unloadableThing.Thing);
                            this.job.SetTarget(TargetIndex.B, c);
                            this.countToDrop = unloadableThing.Thing.stackCount;
                        }
                    }
                }
            };

            yield return(findSpot);

            yield return(Toils_Reserve.Reserve(TargetIndex.B));

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing = this.job.GetTarget(TargetIndex.A).Thing;
                    if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing))
                    {
                        carriedThing.Remove(thing);
                        pawn.jobs.curDriver.JumpToToil(wait);
                        return;
                    }
                    if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false))
                    {
                        this.pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, this.countToDrop, out thing);
                        this.EndJobWith(JobCondition.Succeeded);
                        carriedThing.Remove(thing);
                    }
                    else
                    {
                        this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, this.countToDrop, out thing);
                        this.job.count = this.countToDrop;
                        this.job.SetTarget(TargetIndex.A, thing);
                        carriedThing.Remove(thing);
                    }
                    try
                    {
                        ((Action)(() =>
                        {
                            if (ModCompatibilityCheck.CombatExtendedIsActive)
                            {
                                //CombatExtended.CompInventory ceCompInventory = pawn.GetComp<CombatExtended.CompInventory>();
                                //ceCompInventory.UpdateInventory();
                            }
                        }))();
                    }
                    catch (TypeLoadException) { }
                    thing.SetForbidden(false, false);
                }
            });

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch));

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));

            //If the original cell is full, PlaceHauledThingInCell will set a different TargetIndex resulting in errors on yield return Toils_Reserve.Release.
            //We still gotta release though, mostly because of Extended Storage.
            Toil releaseReservation = new Toil
            {
                initAction = () =>
                {
                    if (pawn.Map.reservationManager.ReservedBy(this.job.targetB, pawn, pawn.CurJob) && !ModCompatibilityCheck.HCSKIsActive)
                    {
                        pawn.Map.reservationManager.Release(this.job.targetB, pawn, pawn.CurJob);
                    }
                }
            };

            yield return(releaseReservation);

            yield return(Toils_Jump.Jump(wait));

            yield return(celebrate);
        }
        //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);
        }