예제 #1
0
        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.JumpIf(() => ticker > duration, unequip);
            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)); });

            /*
             * carryToCell.AddEndCondition(delegate
             *  {
             *      Thing thing = carryToCell.GetActor().jobs.curJob.GetTarget(TargetIndex.B).Thing;
             *      if (thing.DestroyedOrNull() || !stillUnloadable(thing))
             *      {
             *          return JobCondition.Incompletable;
             *      }
             *      return JobCondition.Ongoing;
             *  });
             */
            yield return(carryToCell);

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

            yield break;
        }
            static IEnumerable <Toil> DoMakeToils(JobDriver_DoBill_Access __instance)
            {
                //normal scenario
                __instance.AddEndCondition(delegate
                {
                    Thing thing = __instance.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing;
                    if (thing is Building && !thing.Spawned)
                    {
                        return(JobCondition.Incompletable);
                    }
                    return(JobCondition.Ongoing);
                });
                __instance.FailOnBurningImmobile(TargetIndex.A);
                __instance.FailOn(delegate()
                {
                    if (__instance.job.GetTarget(TargetIndex.A).Thing is Filth)
                    {
                        return(false);
                    }

                    IBillGiver billGiver = __instance.job.GetTarget(TargetIndex.A).Thing as IBillGiver;
                    if (billGiver != null)
                    {
                        if (__instance.job.bill.DeletedOrDereferenced)
                        {
                            return(true);
                        }
                        if (!billGiver.CurrentlyUsableForBills())
                        {
                            return(true);
                        }
                    }
                    return(false);
                });

                Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);

                yield return(new Toil
                {
                    initAction = delegate()
                    {
                        if (__instance.job.targetQueueB != null && __instance.job.targetQueueB.Count == 1)
                        {
                            UnfinishedThing unfinishedThing = __instance.job.targetQueueB[0].Thing as UnfinishedThing;
                            if (unfinishedThing != null)
                            {
                                unfinishedThing.BoundBill = (Bill_ProductionWithUft)__instance.job.bill;
                            }
                        }
                    }
                });

                yield return(Toils_Jump.JumpIf(gotoBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.B).NullOrEmpty()));

                //hauling patch
                if (Settings.adv_haul_all_ings && __instance.pawn.Faction == Faction.OfPlayer)
                {
                    Toil extract = new Toil();
                    extract.initAction = delegate()
                    {
                        Pawn actor  = extract.actor;
                        Job  curJob = actor.jobs.curJob;
                        List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B);
                        if (!curJob.countQueue.NullOrEmpty())
                        {
                            if (curJob.countQueue[0] > targetQueue[0].Thing.stackCount)
                            {
                                actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                            }
                            else
                            {
                                curJob.SetTarget(TargetIndex.B, targetQueue[0]);
                                targetQueue.RemoveAt(0);
                                curJob.count = curJob.countQueue[0];
                                curJob.countQueue.RemoveAt(0);
                            }
                        }
                    };

                    Toil PickUpThing = new Toil();
                    PickUpThing.initAction = delegate()
                    {
                        Pawn  actor  = extract.actor;
                        Job   curJob = actor.jobs.curJob;
                        Thing thing  = curJob.GetTarget(TargetIndex.B).Thing;
                        List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B);
                        bool InventorySpawned = thing.ParentHolder == actor.inventory;
                        if (InventorySpawned || !Toils_Haul.ErrorCheckForCarry(actor, thing))
                        {
                            if (thing.stackCount < curJob.count)
                            {
                                actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                            }
                            else
                            {
                                Thing splitThing = thing.SplitOff(curJob.count);
                                if (splitThing.ParentHolder != actor.inventory && !actor.inventory.GetDirectlyHeldThings().TryAdd(splitThing, false))
                                {
                                    actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                                }


                                if (!splitThing.Destroyed && splitThing.stackCount != 0)
                                {
                                    targetQueue.Add(splitThing);

                                    if (!InventorySpawned)
                                    {
                                        CompUnloadChecker CUC = splitThing.TryGetComp <CompUnloadChecker>();
                                        if (CUC != null)
                                        {
                                            CUC.ShouldUnload = true;
                                        }
                                    }
                                }
                            }
                        }
                    };

                    Toil TakeToHands = new Toil();
                    TakeToHands.initAction = delegate()
                    {
                        Pawn actor  = TakeToHands.actor;
                        Job  curJob = actor.jobs.curJob;
                        List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B);
                        if (!targetQueue.NullOrEmpty())
                        {
                            actor.inventory.innerContainer.TryTransferToContainer(targetQueue[0].Thing, actor.carryTracker.innerContainer);
                            actor.Reserve(targetQueue[0], curJob);
                            curJob.SetTarget(TargetIndex.B, targetQueue[0]);
                            targetQueue.RemoveAt(0);
                        }
                    };

                    yield return(extract);

                    Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B);
                    yield return(Toils_Jump.JumpIf(PickUpThing, () => __instance.job.GetTarget(TargetIndex.B).Thing.ParentHolder == __instance.pawn.inventory));

                    yield return(getToHaulTarget);

                    yield return(PickUpThing);

                    yield return(Toils_Jump.JumpIf(extract, () => !__instance.job.countQueue.NullOrEmpty()));

                    yield return(TakeToHands);

                    yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B));

                    Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C);
                    yield return(findPlaceTarget);

                    yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false));

                    yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, TakeToHands));
                }
                else
                {
                    Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true);
                    yield return(extract);

                    Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B);
                    yield return(getToHaulTarget);

                    yield return(Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true));

                    yield return(JobDriver_DoBill_Access.JumpToCollectNextIntoHandsForBillCrutch(getToHaulTarget, TargetIndex.B));

                    yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B));

                    Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C);
                    yield return(findPlaceTarget);

                    yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false));

                    yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract));
                }

                yield return(gotoBillGiver); //one line from normal scenario

                //cleaning patch
                if (Settings.adv_cleaning)
                {
                    Toil returnToBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);
                    Toil FilthList         = new Toil();
                    FilthList.initAction = delegate()
                    {
                        Job curJob = FilthList.actor.jobs.curJob;
                        if (curJob.GetTargetQueue(TargetIndex.A).NullOrEmpty())
                        {
                            LocalTargetInfo     A = curJob.GetTarget(TargetIndex.A);
                            IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A);
                            Utility.AddFilthToQueue(curJob, TargetIndex.A, l, FilthList.actor);
                            FilthList.actor.ReserveAsManyAsPossible(curJob.GetTargetQueue(TargetIndex.A), curJob);
                            curJob.targetQueueA.Add(A);
                        }
                    };
                    yield return(FilthList);

                    yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty()));

                    Toil CleanFilthList = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, null);
                    yield return(CleanFilthList);

                    yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true));

                    yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty()));

                    yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, CleanFilthList).JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList));

                    Toil clean = new Toil();
                    clean.initAction = delegate()
                    {
                        Filth filth = __instance.job.GetTarget(TargetIndex.A).Thing as Filth;
                        __instance.billStartTick             = 0;
                        __instance.ticksSpentDoingRecipeWork = 0;
                        __instance.workLeft = filth.def.filth.cleaningWorkToReduceThickness * filth.thickness;
                    };
                    clean.tickAction = delegate()
                    {
                        Filth filth = __instance.job.GetTarget(TargetIndex.A).Thing as Filth;
                        __instance.billStartTick             += 1;
                        __instance.ticksSpentDoingRecipeWork += 1;
                        if (__instance.billStartTick > filth.def.filth.cleaningWorkToReduceThickness)
                        {
                            filth.ThinFilth();
                            __instance.billStartTick = 0;
                            if (filth.Destroyed)
                            {
                                clean.actor.records.Increment(RecordDefOf.MessesCleaned);
                                __instance.ReadyForNextToil();
                                return;
                            }
                        }
                    };
                    clean.defaultCompleteMode = ToilCompleteMode.Never;
                    clean.WithEffect(EffecterDefOf.Clean, TargetIndex.A);
                    clean.WithProgressBar(TargetIndex.A, () => __instance.ticksSpentDoingRecipeWork / __instance.workLeft, true, -0.5f);
                    clean.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth);
                    clean.JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, FilthList);
                    clean.JumpIfOutsideHomeArea(TargetIndex.A, FilthList);
                    yield return(clean);

                    yield return(Toils_Jump.Jump(FilthList));

                    yield return(returnToBillGiver);
                }

                //continuation of normal scenario
                yield return(Toils_Recipe.MakeUnfinishedThingIfNeeded());

                yield return(Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell));

                yield return(Toils_Recipe.FinishRecipeAndStartStoringProduct());

                if (!__instance.job.RecipeDef.products.NullOrEmpty() || !__instance.job.RecipeDef.specialProducts.NullOrEmpty())
                {
                    yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

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

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

                    Toil recount = new Toil();
                    recount.initAction = delegate()
                    {
                        Bill_Production bill_Production = recount.actor.jobs.curJob.bill as Bill_Production;
                        if (bill_Production != null && bill_Production.repeatMode == BillRepeatModeDefOf.TargetCount)
                        {
                            __instance.MapCrutch().resourceCounter.UpdateResourceCounts();
                        }
                    };
                    yield return(recount);
                }
                yield break;
            }
예제 #3
0
        static bool stillUnloadable(Thing thing)
        {
            CompUnloadChecker c = thing.TryGetComp <CompUnloadChecker>();

            return(c != null && c.ShouldUnload);
        }