Example #1
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_General.Wait(10));

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing dropThing;
                    int dropCount;
                    if (!this.pawn.inventory.UnloadEverything || !this.pawn.GetAnythingForDrop(out dropThing, out dropCount))
                    {
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                    else
                    {
                        IntVec3 c;
                        if (!StoreUtility.TryFindStoreCellNearColonyDesperate(dropThing, this.pawn, out c))
                        {
                            this.pawn.inventory.innerContainer.TryDrop(dropThing, this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near, dropCount, out dropThing);
                            this.EndJobWith(JobCondition.Succeeded);
                        }
                        else
                        {
                            pawn.CurJob.SetTarget(TargetIndex.A, dropThing);
                            pawn.CurJob.SetTarget(TargetIndex.B, c);
                            amountToDrop = dropCount;
                        }
                    }
                }
            });

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

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

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing = pawn.CurJob.GetTarget(TargetIndex.A).Thing;
                    if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing))
                    {
                        this.EndJobWith(JobCondition.Incompletable);
                        return;
                    }
                    if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStoreable)
                    {
                        this.pawn.inventory.innerContainer.TryDrop(thing, this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near, amountToDrop, out thing);
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                    else
                    {
                        this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, amountToDrop, out thing);
                        pawn.CurJob.count = amountToDrop;
                        pawn.CurJob.SetTarget(TargetIndex.A, thing);
                    }
                    thing.SetForbidden(false, false);

                    if (!this.pawn.HasAnythingForDrop())
                    {
                        this.pawn.inventory.UnloadEverything = false;
                    }
                }
            });

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

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));
        }
Example #2
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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_General.Wait(10, TargetIndex.None));

            yield return(new Toil
            {
                initAction = delegate()
                {
                    Thing MarkedThing = CompUnloadChecker.getFirstMarked(pawn);
                    if (MarkedThing == null)
                    {
                        EndJobWith(JobCondition.Succeeded);
                        return;
                    }
                    //
                    if (pawn.equipment.Contains(MarkedThing))
                    {
                        Equipment = (ThingWithComps)MarkedThing;
                        Apparel = null;
                    }
                    else
                    {
                        Apparel = pawn.apparel.Contains(MarkedThing) ? (Apparel)MarkedThing : null;
                        Equipment = null;
                    }

                    ThingCount firstUnloadableThing = MarkedThing == null ? default(ThingCount) : new ThingCount(MarkedThing, MarkedThing.stackCount);
                    IntVec3 c;
                    if (!StoreUtility.TryFindStoreCellNearColonyDesperate(firstUnloadableThing.Thing, pawn, out c))
                    {
                        Thing thing;
                        pawn.inventory.innerContainer.TryDrop(firstUnloadableThing.Thing, ThingPlaceMode.Near, firstUnloadableThing.Count, out thing, null, null);
                        EndJobWith(JobCondition.Succeeded);
                        return;
                    }

                    job.SetTarget(TargetIndex.A, firstUnloadableThing.Thing);
                    job.SetTarget(TargetIndex.B, c);
                    countToDrop = firstUnloadableThing.Count;
                }
            });

            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return !stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing); }));

            //preintiating unequip-delay
            Toil unequip = new Toil
            {
                initAction = delegate()
                {
                    if (Equipment != null)
                    {
                        pawn.equipment.TryTransferEquipmentToContainer(Equipment, pawn.inventory.innerContainer);
                    }
                    else if (Apparel != null)
                    {
                        ThingOwner <Apparel> a = Traverse.Create(pawn.apparel).Field("wornApparel").GetValue <ThingOwner <Apparel> >();
                        a.TryTransferToContainer(Apparel, pawn.inventory.innerContainer);
                    }
                }
            };
            //if equiped, wait unequipping time
            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                ticker   = 0;
                duration = Apparel != null?Apparel.GetStatValue(StatDefOf.EquipDelay, true) * 60f : Equipment != null ? 30 : 0;

                pawn.pather.StopDead();
            };
            wait.tickAction = delegate()
            {
                if (ticker >= duration)
                {
                    ReadyForNextToil();
                }
                ticker++;
            };
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => ticker / duration);
            //unequip to inventory
            yield return(wait);

            yield return(unequip);

            //hold in hands
            yield return(new Toil
            {
                initAction = delegate()
                {
                    Thing thing = job.GetTarget(TargetIndex.A).Thing;
                    CompUnloadChecker c = thing.TryGetComp <CompUnloadChecker>();
                    if (c == null || !c.ShouldUnload)
                    {
                        EndJobWith(JobCondition.Incompletable);
                        return;
                    }
                    if (thing == null || !pawn.inventory.innerContainer.Contains(thing))
                    {
                        EndJobWith(JobCondition.Incompletable);
                        return;
                    }
                    if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false))
                    {
                        pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, countToDrop, out thing, null, null);
                        EndJobWith(JobCondition.Succeeded);
                    }
                    else
                    {
                        pawn.inventory.innerContainer.TryTransferToContainer(thing, pawn.carryTracker.innerContainer, countToDrop, out thing, true);
                        job.count = countToDrop;
                        job.SetTarget(TargetIndex.A, thing);
                    }
                    thing.SetForbidden(false, false);
                }
            });

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return(!stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing)); });

            yield return(carryToCell);

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

            yield break;
        }
        //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);
        }