public override IEnumerable <Toil> MakeNewToils()
        {
            AddEndCondition(delegate
            {
                Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing;
                if (thing is Building && !thing.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            this.FailOnBurningImmobile(TargetIndex.A);
            this.FailOn(delegate()
            {
                IBillGiver billGiver = job.GetTarget(TargetIndex.A).Thing as IBillGiver;
                if (billGiver != null)
                {
                    if (job.bill.DeletedOrDereferenced)
                    {
                        return(true);
                    }
                    if (!billGiver.CurrentlyUsableForBills())
                    {
                        return(true);
                    }
                    if (project == null)
                    {
                        Log.Error("[HumanResources] Tried to document a null project.");
                        TryMakePreToilReservations(true);
                        return(true);
                    }
                    if (!techComp.homework.Contains(project))
                    {
                        return(true);
                    }
                }
                return(false);
            });
            Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);

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

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

            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(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, false));

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

            extract         = null;
            getToHaulTarget = null;
            findPlaceTarget = null;
            yield return(gotoBillGiver);

            yield return(MakeUnfinishedThingIfNeeded());

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

            yield return(FinishRecipeAndStartStoringProduct());

            if (!job.RecipeDef.products.NullOrEmpty <ThingDefCountClass>() || !job.RecipeDef.specialProducts.NullOrEmpty <SpecialProductType>())
            {
                yield return(Toils_Reserve.Reserve(TargetIndex.B));

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

                findPlaceTarget = Toils_Haul.CarryHauledThingToContainer();
                yield return(findPlaceTarget);

                Toil prepare = Toils_General.Wait(250);
                prepare.WithProgressBarToilDelay(TargetIndex.B, false, -0.5f);
                yield return(prepare);

                yield return(new Toil
                {
                    initAction = delegate
                    {
                        Building_BookStore shelf = (Building_BookStore)job.GetTarget(TargetIndex.B).Thing;
                        CurToil.FailOn(() => shelf == null);
                        Thing book = pawn.carryTracker.CarriedThing;
                        if (pawn.carryTracker.CarriedThing == null)
                        {
                            Log.Error($"[HumanResources] {pawn} tried to place a book on shelf but is not hauling anything.");
                            return;
                        }
                        if (shelf.Accepts(book))
                        {
                            bool flag = false;
                            if (book.holdingOwner != null)
                            {
                                book.holdingOwner.TryTransferToContainer(book, shelf.TryGetInnerInteractableThingOwner(), book.stackCount, true);
                                flag = true;
                            }
                            else
                            {
                                flag = shelf.TryGetInnerInteractableThingOwner().TryAdd(book, true);
                            }
                            pawn.carryTracker.innerContainer.Remove(book);
                        }
                        else
                        {
                            Log.Error($"[HumanResources] {pawn} tried to place a book in {shelf}, but it won't accept it.");
                            return;
                        }
                        pawn.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                    }
                });
            }
            yield break;
        }
Exemple #2
0
        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 checklist = new Toil();
                checklist.initAction = delegate()
                {
                    Pawn actor  = checklist.actor;
                    Job  curJob = actor.jobs.curJob;
                    List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B);
                    if (targetQueue.NullOrEmpty())
                    {
                        actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                    }
                    else
                    {
                        foreach (var target in (targetQueue))
                        {
                            if (target == null || target.Thing.DestroyedOrNull())
                            {
                                actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                                break;
                            }
                        }
                    }
                };

                yield return(checklist);

                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;
                List <LocalTargetInfo> L = __instance.job.GetTargetQueue(TargetIndex.B);
                if (L.Count < 2 && (L.Count == 0 || L[0].Thing.def.stackLimit < 2))
                {
                    PickUpThing = Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true);
                }
                else
                {
                    PickUpThing            = new Toil();
                    PickUpThing.initAction = delegate()
                    {
                        Pawn  actor  = PickUpThing.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;
                                        }
                                    }
                                }

                                if (splitThing != thing && actor.Map.reservationManager.ReservedBy(thing, actor, curJob))
                                {
                                    actor.Map.reservationManager.Release(thing, actor, curJob);
                                }
                            }
                        }
                    };
                }

                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() && targetQueue[0].Thing.ParentHolder != actor.carryTracker)
                    {
                        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 && !Utility.IncapableOfCleaning(__instance.pawn))
            {
                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);
                        DoCleanComp     comp;
                        if (!Settings.clean_gizmo || (comp = A.Thing?.TryGetComp <DoCleanComp>()) == null || comp.Active)
                        {
                            IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A, Settings.adv_clean_num);
                            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 = clean.actor.jobs.curJob.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 = clean.actor.jobs.curJob.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, CleanFilthList);
                clean.JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList);
                yield return(clean);

                yield return(Toils_Jump.Jump(CleanFilthList));

                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;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            // 患者の状態による失敗条件

            // 死んだりいなくなったりしたら失敗
            this.FailOnDespawnedNullOrForbidden(PatientInd);
            this.FailOn(() =>
            {
                // 寝ていない状態になったら失敗
                if (!WorkGiver_Tend.GoodLayingStatusForTend(this.Patient, this.pawn))
                {
                    return(true);
                }

                // 看護師と患者が同一人物だったら失敗
                return(this.pawn == this.Patient);
            });
            // 精神崩壊状態次第で失敗とする
            this.FailOnAggroMentalState(PatientInd);
            base.AddEndCondition(delegate
            {
                // 看病が必要な状況なら続ける
                // 免疫を得る系の病気を持っている&看病Hediffが無い
                if (Patient.health.hediffSet.GetFirstHediffOfDef(MizuDef.Hediff_Nursed) == null)
                {
                    return(JobCondition.Ongoing);
                }

                // 既に看病されていたら終了
                return(JobCondition.Succeeded);
            });

            // ツールまで移動
            yield return(Toils_Goto.GotoThing(ToolInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(ToolInd));

            // ツールを手に取る
            yield return(Toils_Haul.StartCarryThing(ToolInd));

            // 患者の元へ移動
            yield return(Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch));

            // 看病
            Toil workToil = new Toil();

            workToil.initAction = () =>
            {
                // 必要工数の計算
                this.ticksLeftThisToil = WorkTicks;
            };
            // 細々とした設定
            workToil.defaultCompleteMode = ToilCompleteMode.Delay;
            workToil.WithProgressBar(PatientInd, () => 1f - (float)this.ticksLeftThisToil / WorkTicks, true, -0.5f);
            workToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth);
            yield return(workToil);

            // 看病完了時の処理
            var finishToil = new Toil();

            finishToil.initAction = () =>
            {
                // 看病状態追加
                if (Patient.health.hediffSet.GetFirstHediffOfDef(MizuDef.Hediff_Nursed) == null)
                {
                    Patient.health.AddHediff(HediffMaker.MakeHediff(MizuDef.Hediff_Nursed, Patient));
                }

                // 水減少
                var comp = Tool.GetComp <CompWaterTool>();
                comp.StoredWaterVolume -= ConsumeWaterVolume;
            };
            finishToil.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return(finishToil);

            // ツールを片付ける場所を決める
            yield return(Toils_Mizu.TryFindStoreCell(ToolInd, ToolPlaceInd));

            // 倉庫まで移動
            yield return(Toils_Goto.GotoCell(ToolPlaceInd, PathEndMode.Touch));

            // 倉庫に置く
            yield return(Toils_Haul.PlaceHauledThingInCell(ToolPlaceInd, null, true));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOn(delegate
            {
                if (!WorkGiver_Tend.GoodLayingStatusForTend(this.$this.Deliveree, this.$this.pawn))
                {
                    return(true);
                }
                if (this.$this.MedicineUsed != null && this.$this.pawn.Faction == Faction.OfPlayer)
                {
                    if (this.$this.Deliveree.playerSettings == null)
                    {
                        return(true);
                    }
                    if (!this.$this.Deliveree.playerSettings.medCare.AllowsMedicine(this.$this.MedicineUsed.def))
                    {
                        return(true);
                    }
                }
                return(this.$this.pawn == this.$this.Deliveree && this.$this.pawn.Faction == Faction.OfPlayer && !this.$this.pawn.playerSettings.selfTend);
            });
            base.AddEndCondition(delegate
            {
                if (this.$this.pawn.Faction == Faction.OfPlayer && HealthAIUtility.ShouldBeTendedNowByPlayer(this.$this.Deliveree))
                {
                    return(JobCondition.Ongoing);
                }
                if (this.$this.pawn.Faction != Faction.OfPlayer && this.$this.Deliveree.health.HasHediffsNeedingTend(false))
                {
                    return(JobCondition.Ongoing);
                }
                return(JobCondition.Succeeded);
            });
            this.FailOnAggroMentalState(TargetIndex.A);
            Toil reserveMedicine = null;

            if (this.usesMedicine)
            {
                reserveMedicine = Toils_Tend.ReserveMedicine(TargetIndex.B, this.Deliveree).FailOnDespawnedNullOrForbidden(TargetIndex.B);
                yield return(reserveMedicine);

                yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B));

                yield return(Toils_Tend.PickupMedicine(TargetIndex.B, this.Deliveree).FailOnDestroyedOrNull(TargetIndex.B));

                yield return(Toils_Haul.CheckForGetOpportunityDuplicate(reserveMedicine, TargetIndex.B, TargetIndex.None, true, null));
            }
            PathEndMode interactionCell = (this.Deliveree != this.pawn) ? PathEndMode.InteractionCell : PathEndMode.OnCell;
            Toil        gotoToil        = Toils_Goto.GotoThing(TargetIndex.A, interactionCell);

            yield return(gotoToil);

            int duration = (int)(1f / this.pawn.GetStatValue(StatDefOf.MedicalTendSpeed, true) * 600f);

            yield return(Toils_General.Wait(duration, TargetIndex.None).FailOnCannotTouch(TargetIndex.A, interactionCell).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f).PlaySustainerOrSound(SoundDefOf.Interact_Tend));

            yield return(Toils_Tend.FinalizeTend(this.Deliveree));

            if (this.usesMedicine)
            {
                yield return(new Toil
                {
                    initAction = delegate
                    {
                        if (this.$this.MedicineUsed.DestroyedOrNull())
                        {
                            Thing thing = HealthAIUtility.FindBestMedicine(this.$this.pawn, this.$this.Deliveree);
                            if (thing != null)
                            {
                                this.$this.job.targetB = thing;
                                this.$this.JumpToToil(reserveMedicine);
                            }
                        }
                    }
                });
            }
            yield return(Toils_Jump.Jump(gotoToil));
        }
        //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

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

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

            var 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
                    var 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);
                        var   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();
                    var 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 = JobMaker.MakeJob(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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_General.Wait(10, TargetIndex.None));

            yield return(new Toil
            {
                initAction = delegate()
                {
                    if (!this.pawn.inventory.UnloadEverything)
                    {
                        base.EndJobWith(JobCondition.Succeeded);
                    }
                    else
                    {
                        ThingCount firstUnloadableThing = this.pawn.inventory.FirstUnloadableThing;
                        IntVec3 c;
                        if (!StoreUtility.TryFindStoreCellNearColonyDesperate(firstUnloadableThing.Thing, this.pawn, out c))
                        {
                            Thing thing;
                            this.pawn.inventory.innerContainer.TryDrop(firstUnloadableThing.Thing, ThingPlaceMode.Near, firstUnloadableThing.Count, out thing, null, null);
                            base.EndJobWith(JobCondition.Succeeded);
                        }
                        else
                        {
                            this.job.SetTarget(TargetIndex.A, firstUnloadableThing.Thing);
                            this.job.SetTarget(TargetIndex.B, c);
                            this.countToDrop = firstUnloadableThing.Count;
                        }
                    }
                }
            });

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

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

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

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

            yield return(carryToCell);

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

            yield break;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            if (thing == null)
            {
                pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
            }

            bool err   = false;
            Toil error = Toils_General.Do(delegate
            {
                Log.Error("Error in Toils_Haul.PlaceHauledThingInCell. Breaking job.");
                Log.Error("thing = " + thing);
                Log.Error("building = " + building);
                Log.Error("buildingCell = " + buildingCell);

                err = true;
            });

            CompProperties_TextThing textThing = thing.TryGetComp <CompTextThing>().Props;

            if (textThing != null)
            {
                float num = 0;
                //int workLeft = thing.TryGetComp<CompTextThing>().workLeft;
                CompTextThing compTextThing = thing.TryGetComp <CompTextThing>();
                if (building != null && building.GetStatValue(StatDefOf.ResearchSpeedFactor, true) > 0)
                {
                    num  = 1.1f * pawn.GetStatValue(StatDefOf.ResearchSpeed, true);    // 1.1 * 0.58 = 0.638
                    num *= building.GetStatValue(StatDefOf.ResearchSpeedFactor, true); // 0.638 * 1 = 0.638
                    ticksPerWorkPoint = ticksPerWorkPoint / num;                       // 60 / 0.638 = 94
                }
                else if (textThing.workSkill != null)
                {
                    num = (pawn.skills.GetSkill(textThing.workSkill).Level - textThing.minSkillLevel) * 2;

                    if (ticksPerWorkPoint - num > 0)
                    {
                        ticksPerWorkPoint = ticksPerWorkPoint - num;
                    }
                    else
                    {
                        ticksPerWorkPoint = 1;
                    }
                }

                this.FailOnForbidden(thingInd);

                if (building != null)
                {
                    this.FailOnDespawnedOrNull(buildingInd);
                    this.FailOnForbidden(buildingInd);
                }

                //Log.Message("num = " + num);
                //Log.Message("ticksPerWorkPoint = " + ticksPerWorkPoint);
                //Log.Message("workLeft = " + workLeft);

                yield return(Toils_Goto.GotoThing(thingInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(thingInd).FailOnSomeonePhysicallyInteracting(thingInd));

                yield return(Toils_Misc.SetForbidden(thingInd, false));

                yield return(Toils_Haul.StartCarryThing(thingInd, false, false, false));

                if (building != null)
                {
                    if (buildingCell != new IntVec3(-1000, -1000, -1000))
                    {
                        yield return(Toils_Goto.GotoThing(buildingInd, PathEndMode.InteractionCell).FailOnDespawnedOrNull(buildingInd));
                    }
                    else
                    {
                        yield return(Toils_Goto.GotoThing(buildingInd, PathEndMode.OnCell).FailOnDespawnedOrNull(buildingInd));
                    }
                }

                if (buildingCell != new IntVec3(-1000, -1000, -1000))
                {
                    //Log.Message("buildingCell = " + buildingCell);
                    yield return(Toils_Haul.PlaceHauledThingInCell(buildingCellInd, Toils_Jump.Jump(error), false));
                }

                //IntVec3 thingPosition = thing.PositionHeld;
                //IntVec3 buildingPosition = building.PositionHeld;

                float workLeftInTicks = compTextThing.workLeft * (ticksPerWorkPoint * 1.1f);
                Toil  translate       = Toils_General.Wait((int)workLeftInTicks).FailOnDespawnedNullOrForbidden(thingInd).FailOnDespawnedNullOrForbidden(buildingInd);;

                translate.tickAction = delegate
                {
                    if (textThing.workSkill != null)
                    {
                        pawn.skills.Learn(textThing.workSkill, 0.11f, false);
                    }

                    pawn.GainComfortFromCellIfPossible();

                    if (pawn.IsHashIntervalTick((int)ticksPerWorkPoint))
                    {
                        //Log.Message("workLeft = " + compTextThing.workLeft);
                        compTextThing.workLeft--;

                        if (textThing.showTranslator)
                        {
                            if (compTextThing.translator == "")
                            {
                                compTextThing.translator += pawn.Name;
                            }
                            else
                            {
                                if (!compTextThing.translator.Contains(pawn.ToString()))
                                {
                                    compTextThing.translator += pawn.Name.ToString();
                                    compTextThing.translator += ", " + pawn.Name;
                                }
                            }
                        }
                    }

                    if (compTextThing.workLeft <= 0)
                    {
                        compTextThing.workLeft    = 0;
                        thing.def.BaseMarketValue = textThing.translatedMarketValue;

                        if (textThing.taleWhenTranslated != null)
                        {
                            TaleRecorder.RecordTale(textThing.taleWhenTranslated, new object[]
                            {
                                pawn,
                                thing.def
                            });
                        }

                        if (textThing.thoughtWhenTranslated != null)
                        {
                            Thought_Memory newThought = (Thought_Memory)ThoughtMaker.MakeThought(textThing.thoughtWhenTranslated);
                            pawn.needs.mood.thoughts.memories.TryGainMemory(newThought, null);
                        }

                        pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                };

                //Log.Message("Translate");
                yield return(translate);
            }

            if (err)
            {
                yield return(error);
            }
            yield break;
        }
Exemple #8
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOn(delegate
            {
                if (!WorkGiver_Tend.GoodLayingStatusForTend(Deliveree, pawn))
                {
                    return(true);
                }
                if (MedicineUsed != null && pawn.Faction == Faction.OfPlayer)
                {
                    if (Deliveree.playerSettings == null)
                    {
                        return(true);
                    }
                    if (!Deliveree.playerSettings.medCare.AllowsMedicine(MedicineUsed.def))
                    {
                        return(true);
                    }
                }
                return((pawn == Deliveree && pawn.Faction == Faction.OfPlayer && !pawn.playerSettings.selfTend) ? true : false);
            });
            AddEndCondition(delegate
            {
                if (pawn.Faction == Faction.OfPlayer && HealthAIUtility.ShouldBeTendedNowByPlayer(Deliveree))
                {
                    return(JobCondition.Ongoing);
                }
                return((pawn.Faction != Faction.OfPlayer && Deliveree.health.HasHediffsNeedingTend()) ? JobCondition.Ongoing : JobCondition.Succeeded);
            });
            this.FailOnAggroMentalState(TargetIndex.A);
            Toil reserveMedicine = null;

            if (usesMedicine)
            {
                reserveMedicine = Toils_Tend.ReserveMedicine(TargetIndex.B, Deliveree).FailOnDespawnedNullOrForbidden(TargetIndex.B);
                yield return(reserveMedicine);

                yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B));

                yield return(Toils_Tend.PickupMedicine(TargetIndex.B, Deliveree).FailOnDestroyedOrNull(TargetIndex.B));

                yield return(Toils_Haul.CheckForGetOpportunityDuplicate(reserveMedicine, TargetIndex.B, TargetIndex.None, takeFromValidStorage: true));
            }
            PathEndMode interactionCell = (Deliveree == pawn) ? PathEndMode.OnCell : PathEndMode.InteractionCell;
            Toil        gotoToil        = Toils_Goto.GotoThing(TargetIndex.A, interactionCell);

            yield return(gotoToil);

            Toil toil = Toils_General.Wait((int)(1f / pawn.GetStatValue(StatDefOf.MedicalTendSpeed) * 600f)).FailOnCannotTouch(TargetIndex.A, interactionCell).WithProgressBarToilDelay(TargetIndex.A)
                        .PlaySustainerOrSound(SoundDefOf.Interact_Tend);

            toil.activeSkill = (() => SkillDefOf.Medicine);
            if (pawn == Deliveree && pawn.Faction != Faction.OfPlayer)
            {
                toil.tickAction = delegate
                {
                    if (pawn.IsHashIntervalTick(100) && !pawn.Position.Fogged(pawn.Map))
                    {
                        MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_HealingCross);
                    }
                };
            }
            yield return(toil);

            yield return(Toils_Tend.FinalizeTend(Deliveree));

            if (usesMedicine)
            {
                Toil toil2 = new Toil();
                toil2.initAction = delegate
                {
                    if (MedicineUsed.DestroyedOrNull())
                    {
                        Thing thing = HealthAIUtility.FindBestMedicine(pawn, Deliveree);
                        if (thing != null)
                        {
                            job.targetB = thing;
                            JumpToToil(reserveMedicine);
                        }
                    }
                };
                yield return(toil2);
            }
            yield return(Toils_Jump.Jump(gotoToil));
        }
        /// <summary>
        /// Yields all steps of restraining a person.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Hediff restrainHediff = HediffMaker.MakeHediff(KnockItOffHediffDefOf.Restrain, JobTarget);
            Hediff annoyedHediff  = HediffMaker.MakeHediff(KnockItOffHediffDefOf.Annoyed, JobTarget);


            SkillRecord meleeSkillRecordJT   = JobTarget.skills.GetSkill(SkillDefOf.Melee);
            SkillRecord meleeSkillRecordPawn = pawn.skills.GetSkill(SkillDefOf.Melee);

            bool imprisonCheck = SkillDiffCheck(meleeSkillRecordJT, meleeSkillRecordPawn);

            //If JobTarget is not violent, try to just talk him into calming down.
            if (!imprisonCheck && !JobTarget.InAggroMentalState)
            {
                SkillRecord socialSkillRecordJT   = JobTarget.skills.GetSkill(SkillDefOf.Social);
                SkillRecord socialSkillRecordPawn = pawn.skills.GetSkill(SkillDefOf.Social);

                imprisonCheck = SkillDiffCheck(socialSkillRecordJT, socialSkillRecordPawn);
            }

            // Stop the Job is the Pawn or Bed is destroyed or the Bed is no longer available for Prisoners.
            this.FailOnDestroyedOrNull(JobTargetPawnIndex);
            this.FailOnDestroyedOrNull(BedIndex);
            this.FailOn(delegate
            {
                if (job.def.makeTargetPrisoner)
                {
                    if (!DropBed.ForPrisoners)
                    {
                        return(true);
                    }
                }

                return(false);
            });

            yield return(Toils_Bed.ClaimBedIfNonMedical(BedIndex, JobTargetPawnIndex));

            //Un-claim bed once toils are done
            AddFinishAction(delegate
            {
                if (job.def.makeTargetPrisoner &&
                    JobTarget.Position != RestUtility.GetBedSleepingSlotPosFor(JobTarget, DropBed))
                {
                    JobTarget.ownership.UnclaimBed();
                }
            });

            //Goto berserk pawn
            Toil gotoTakee = new Toil
            {
                initAction          = delegate { pawn.pather.StartPath(JobTarget, PathEndMode.Touch); },
                defaultCompleteMode = ToilCompleteMode.PatherArrival
            };

            yield return(gotoTakee);

            //Restrain pawn, by removing his ability to move or handle equipment.
            //Also makes the pawn annoyed.
            Toil toilSleep = new Toil
            {
                initAction = delegate
                {
                    if (imprisonCheck)
                    {
                        Messages.Message($"Successfully restrained {JobTarget.Name}", MessageTypeDefOf.PositiveEvent);
                        JobTarget.health.AddHediff(restrainHediff, null, null);
                        JobTarget.health.AddHediff(annoyedHediff);
                    }
                    else
                    {
                        Messages.Message($"Failed to restrain {JobTarget.Name}", MessageTypeDefOf.NegativeEvent);
                        pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    }
                }
            };

            yield return(toilSleep);

            //Imprison pawn
            Toil toil = new Toil
            {
                initAction = delegate
                {
                    if (imprisonCheck)
                    {
                        CheckedMakePrisoner();
                    }
                }
            };

            yield return(toil);

            //Haul & Carry pawn to prison cell
            Toil toil2 = Toils_Haul.StartCarryThing(JobTargetPawnIndex).FailOnNonMedicalBedNotOwned(BedIndex, JobTargetPawnIndex);

            yield return(toil2);

            yield return(Toils_Goto.GotoThing(BedIndex, PathEndMode.Touch));

            //Imprison pawn again (the first one sometimes fails)
            Toil toil3 = new Toil
            {
                initAction = delegate
                {
                    if (imprisonCheck)
                    {
                        CheckedMakePrisoner();
                        if (JobTarget.playerSettings == null)
                        {
                            JobTarget.playerSettings = new Pawn_PlayerSettings(JobTarget);
                        }
                    }
                }
            };

            yield return(toil3);

            yield return(Toils_Reserve.Release(BedIndex));

            //Put Prisoner in bed & remove restrained
            Toil toil4 = new Toil
            {
                initAction = delegate
                {
                    if (imprisonCheck)
                    {
                        IntVec3 pIntVec3 = DropBed.Position;
                        pawn.carryTracker.TryDropCarriedThing(pIntVec3, ThingPlaceMode.Direct, out Thing _);
                        if (!DropBed.Destroyed && (DropBed.OwnersForReading.Contains(JobTarget) ||
                                                   DropBed.Medical && DropBed.AnyUnoccupiedSleepingSlot ||
                                                   JobTarget.ownership == null))
                        {
                            JobTarget.jobs.Notify_TuckedIntoBed(DropBed);
                            JobTarget.mindState.Notify_TuckedIntoBed();
                        }

                        if (JobTarget.IsPrisonerOfColony)
                        {
                            LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, JobTarget,
                                                                 OpportunityType.GoodToKnow);
                        }

                        JobTarget.health.RemoveHediff(restrainHediff);
                    }
                },
        // Token: 0x06000013 RID: 19 RVA: 0x00002336 File Offset: 0x00000536
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            bool flag = !base.TargetB.IsValid;

            if (flag)
            {
                base.AddFailCondition(() => this.energyNeed == null);
            }
            yield return(Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null));

            bool isValid = base.TargetB.IsValid;

            if (isValid)
            {
                yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));
            }
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(Toils_Reserve.Release(TargetIndex.A));

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

            bool isValid2 = base.TargetB.IsValid;

            if (isValid2)
            {
                yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOnForbidden(TargetIndex.B));

                yield return(Toils_General.Wait(100).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f));

                Toil rechargeToil = new Toil();
                rechargeToil.AddFinishAction(delegate
                {
                    Thing carriedThing = this.pawn.carryTracker.CarriedThing;
                    bool flag2         = carriedThing != null;
                    if (flag2)
                    {
                        EnergySourceComp energySourceComp = carriedThing.TryGetComp <EnergySourceComp>();
                        bool flag3 = energySourceComp != null;
                        if (flag3)
                        {
                            energySourceComp.RechargeEnergyNeed((Pawn)base.TargetB.Thing);
                        }
                        this.pawn.carryTracker.DestroyCarriedThing();
                    }
                });
                yield return(rechargeToil);

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

                rechargeToil = null;
            }
            else
            {
                yield return(Toils_General.Wait(100).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f));

                Toil rechargeToil2 = new Toil();
                rechargeToil2.AddFinishAction(delegate
                {
                    Thing carriedThing = this.pawn.carryTracker.CarriedThing;
                    bool flag2         = carriedThing != null;
                    if (flag2)
                    {
                        EnergySourceComp energySourceComp = carriedThing.TryGetComp <EnergySourceComp>();
                        bool flag3 = energySourceComp != null;
                        if (flag3)
                        {
                            energySourceComp.RechargeEnergyNeed(this.pawn);
                        }
                        this.pawn.carryTracker.DestroyCarriedThing();
                    }
                });
                yield return(rechargeToil2);

                rechargeToil2 = null;
            }
            yield break;
        }
Exemple #11
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Commence fail checks!

            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);
            this.FailOnAggroMentalState(TargetIndex.A);

            yield return(Toils_Reserve.Reserve(TakeeIndex, 1));

            yield return(Toils_Reserve.Reserve(AltarIndex, Building_SacrificialAltar.LyingSlotsCount));

            yield return(new Toil
            {
                initAction = delegate
                {
                    DropAltar.ChangeState(Building_SacrificialAltar.State.sacrificing,
                                          Building_SacrificialAltar.SacrificeState.gathering);
                }
            });

            //Toil 1: Go to prisoner.
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch)
                         .FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B)
                         .FailOn(() => this.job.def == JobDefOf.Arrest && !this.Takee.CanBeArrestedBy(this.pawn))
                         .FailOn(() =>
                                 !this.pawn.CanReach(this.DropAltar, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                         .FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(new Toil
            {
                initAction = delegate
                {
                    if (this.job.def.makeTargetPrisoner)
                    {
                        Pawn pawn = (Pawn)this.job.targetA.Thing;
                        Lord lord = pawn.GetLord();
                        if (lord != null)
                        {
                            lord.Notify_PawnAttemptArrested(pawn);
                        }
                        GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm);
                        if (this.job.def == JobDefOf.Arrest && !pawn.CheckAcceptArrest(this.pawn))
                        {
                            this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                        }
                    }
                }
            });

            //Toil 2: Carry prisoner.
            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

            //Toil 3: Go to the altar.
            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.InteractionCell));

            //Toil 4: Release the prisoner.
            yield return(Toils_Reserve.Release(TargetIndex.B));

            //Toil 5: Restrain the prisoner.
            yield return(new Toil
            {
                initAction = delegate
                {
                    //In-case this fails...
                    IntVec3 position = this.DropAltar.Position;
                    Thing thing;
                    this.pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out thing, null);
                    if (!this.DropAltar.Destroyed && (this.DropAltar.AnyUnoccupiedLyingSlot))
                    {
                        this.Takee.Position = DropAltar.GetLyingSlotPos();
                        this.Takee.Notify_Teleported(false);
                        this.Takee.stances.CancelBusyStanceHard();
                        Job job = new Job(CultsDefOf.Cults_WaitTiedDown, DropAltar);
                        this.Takee.jobs.StartJob(job);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            //Toil 6: Time to chant ominously
            Toil chantingTime = new Toil();

            chantingTime.defaultCompleteMode = ToilCompleteMode.Delay;
            chantingTime.defaultDuration     = CultUtility.ritualDuration;
            chantingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f);
            chantingTime.PlaySustainerOrSound(CultsDefOf.RitualChanting);
            Texture2D deitySymbol = ((CosmicEntityDef)DropAltar.SacrificeData.Entity.def).Symbol;

            chantingTime.initAction = delegate
            {
                if (deitySymbol != null)
                {
                    MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol);
                }


                //STATE - SACRIFICING
                DropAltar.ChangeState(Building_SacrificialAltar.State.sacrificing,
                                      Building_SacrificialAltar.SacrificeState.sacrificing);
            };

            yield return(chantingTime);

            //Toil 8: Execution of Prisoner
            yield return(new Toil
            {
                initAction = delegate
                {
                    //BodyPartDamageInfo value = new BodyPartDamageInfo(this.Takee.health.hediffSet.GetBrain(), false, quiet);
                    this.Takee.TakeDamage(new DamageInfo(DamageDefOf.ExecutionCut, 99999, 0f, -1f, this.pawn,
                                                         Cthulhu.Utility.GetHeart(this.Takee.health.hediffSet)));
                    if (!this.Takee.Dead)
                    {
                        this.Takee.Kill(null);
                    }
                    //ThoughtUtility.GiveThoughtsForPawnExecuted(this.Takee, PawnExecutionKind.GenericHumane);
                    TaleRecorder.RecordTale(TaleDefOf.ExecutedPrisoner, new object[]
                    {
                        this.pawn,
                        this.Takee
                    });
                    CultUtility.SacrificeExecutionComplete(DropAltar);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            this.AddFinishAction(() =>
            {
                //It's a day to remember
                TaleDef taleToAdd = TaleDef.Named("HeldSermon");
                if ((this.pawn.IsColonist || this.pawn.HostFaction == Faction.OfPlayer) && taleToAdd != null)
                {
                    TaleRecorder.RecordTale(taleToAdd, new object[]
                    {
                        this.pawn,
                    });
                }

                //When the ritual is finished -- then let's give the thoughts

                /*
                 * if (DropAltar.currentSacrificeState == Building_SacrificialAltar.SacrificeState.finished)
                 * {
                 *  if (this.pawn == null) return;
                 *  if (DropAltar.sacrifice != null)
                 *  {
                 *      CultUtility.AttendSacrificeTickCheckEnd(this.pawn, DropAltar.sacrifice, true);
                 *  }
                 *  else
                 *  {
                 *      CultUtility.AttendSacrificeTickCheckEnd(this.pawn, null);
                 *  }
                 * }
                 */
            });
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(delegate
            {
                if (!job.ignoreDesignations)
                {
                    Pawn victim2 = Victim;
                    if (victim2 != null && !victim2.Dead && base.Map.designationManager.DesignationOn(victim2, DesignationDefOf.Hunt) == null)
                    {
                        return(true);
                    }
                }
                return(false);
            });
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                jobStartTick = Find.TickManager.TicksGame;
            };
            yield return(toil);

            yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A));

            Toil startCollectCorpseLabel = Toils_General.Label();
            Toil slaughterLabel          = Toils_General.Label();
            Toil gotoCastPos             = Toils_Combat.GotoCastPosition(TargetIndex.A, closeIfDowned: true, 0.95f).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000);

            yield return(gotoCastPos);

            Toil slaughterIfPossible = Toils_Jump.JumpIf(slaughterLabel, delegate
            {
                Pawn victim = Victim;
                if (victim.RaceProps.DeathActionWorker != null && victim.RaceProps.DeathActionWorker.DangerousInMelee)
                {
                    return(false);
                }
                return(victim.Downed ? true : false);
            });

            yield return(slaughterIfPossible);

            yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, gotoCastPos));

            yield return(Toils_Combat.CastVerb(TargetIndex.A, canHitNonTargetPawns: false).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000));

            yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel));

            yield return(Toils_Jump.Jump(slaughterIfPossible));

            yield return(slaughterLabel);

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnMobile(TargetIndex.A));

            yield return(Toils_General.WaitWith(TargetIndex.A, 180, useProgressBar: true).FailOnMobile(TargetIndex.A));

            yield return(Toils_General.Do(delegate
            {
                if (!Victim.Dead)
                {
                    ExecutionUtility.DoExecutionByCut(pawn, Victim);
                    pawn.records.Increment(RecordDefOf.AnimalsSlaughtered);
                    if (pawn.InMentalState)
                    {
                        pawn.MentalState.Notify_SlaughteredAnimal();
                    }
                }
            }));

            yield return(Toils_Jump.Jump(startCollectCorpseLabel));

            yield return(startCollectCorpseLabel);

            yield return(StartCollectCorpseToil());

            yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

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

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, storageMode: true));
        }
Exemple #13
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //This toil is yielded later
            var gotoBillGiver = Toils_Goto.GotoThing(TI_REPBENCH, PathEndMode.InteractionCell);

            this.FailOnDestroyedNullOrForbidden(TI_REPBENCH);
            this.FailOnBurningImmobile(TI_REPBENCH);

            //Reserve the bill giver and all the ingredients
            yield return(Toils_Reserve.Reserve(TI_REPBENCH));

            yield return(Toils_Reserve.ReserveQueue(TI_ITEM));

            //these are initially set up by workgiver
            var itemTargetQueue = job.GetTargetQueue(TI_ITEM);

            if (itemTargetQueue.NullOrEmpty())
            {
                Log.Warning("RepBench: JobDriver - itemTargetQueue was null.");
                yield return(Toils_Reserve.Release(TI_REPBENCH));

                yield return(Toils_Reserve.Release(TI_ITEM));

                yield break;
            }

            var firstTargetInfo = itemTargetQueue.First();
            var item            = firstTargetInfo.Thing;

            var table = job.GetTarget(TI_REPBENCH).Thing as Building_WorkTable;

            if (table == null)
            {
                Log.Warning("RepBench: JobDriver - RepairTable was null.");
                yield return(Toils_Reserve.Release(TI_REPBENCH));

                yield return(Toils_Reserve.Release(TI_ITEM));

                yield break;
            }

            //Gather ingredients
            {
                //Extract an ingredient into TargetB
                var extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TI_ITEM);
                yield return(extract);

                //Get to ingredient and pick it up
                //Note that these fail cases must be on these toils, otherwise the recipe work fails if you stacked
                //   your targetB into another object on the bill giver square.
                var getToHaulTarget = Toils_Goto.GotoThing(TI_ITEM, PathEndMode.ClosestTouch)
                                      .FailOnDespawnedNullOrForbidden(TI_ITEM);
                yield return(getToHaulTarget);

                yield return(Toils_Haul.StartCarryThing(TI_ITEM));

                //Jump to pick up more in this run if we're collecting from multiple stacks at once
                yield return(JumpToCollectNextIntoHandsForBill(getToHaulTarget, TargetIndex.B));

                //Carry ingredient to the bill giver and put it on the square
                yield return(Toils_Goto.GotoThing(TI_REPBENCH, PathEndMode.InteractionCell)
                             .FailOnDestroyedOrNull(TI_ITEM));

                var findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TI_REPBENCH, TI_ITEM, TI_CELL);
                yield return(findPlaceTarget);

                yield return(Toils_Haul.PlaceHauledThingInCell(TI_CELL, findPlaceTarget, false));

                //Jump back if there is another ingredient needed
                //Can happen if you can't carry all the ingredients in one run
                yield return(Toils_Jump.JumpIfHaveTargetInQueue(TI_ITEM, extract));
            }

            //For it no ingredients needed, just go to the bill giver
            //This will do nothing if we took ingredients and are thus already at the bill giver
            yield return(gotoBillGiver);

            var controller = new ItemRepairProgress(pawn,
                                                    table.IngredientStackCells,
                                                    WorkGiver_Repair.CalculateTotalIngredients(item),
                                                    item.MaxHitPoints - item.HitPoints);

            float ticksToNextRepair = Settings.RepairRate;
            var   repairedAmount    = 0;
            var   repairToil        = new Toil
            {
                initAction = () =>
                {
                    Debug.PrintLine("repairToil.PreInit");
                    job.bill.Notify_DoBillStarted(pawn);
                    Debug.PrintLine("repairToil.PostInit");
                },

                tickAction = () =>
                {
//                    Debug.PrintLine("repairToil.tick.Check");
//                    pawn.jobs.CheckForJobOverride();

                    job.bill.Notify_PawnDidWork(pawn);
                    job.SetTarget(TargetIndex.B, item);

                    pawn.skills.Learn(SkillDefOf.Crafting, Settings.SkillGain);
                    pawn.GainComfortFromCellIfPossible();

                    ticksToNextRepair -= pawn.GetStatValue(StatDefOf.WorkSpeedGlobal) * table.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor);
                    if (ticksToNextRepair > 0.0)
                    {
                        return;
                    }

                    ticksToNextRepair = Settings.RepairRate;
                    item.HitPoints   += Settings.HP_GAIN;
                    repairedAmount   += Settings.HP_GAIN;

                    if (!controller.AddRepairedAmount(Settings.HP_GAIN))
                    {
                        //Technically we did not Succeed, but the job itself did not fail, we just ran out of kits.
                        EndJobWith(JobCondition.Succeeded);
                        return;
                    }

                    if (item.HitPoints < item.MaxHitPoints)
                    {
                        return;
                    }

                    // break
                    ReadyForNextToil();
                },
                defaultCompleteMode = ToilCompleteMode.Never
            };

            repairToil.WithEffect(item.def.repairEffect, TI_ITEM);
            yield return(repairToil);

            var itemRepairedToil = new Toil
            {
                initAction = () =>
                {
                    var list = new List <Thing> {
                        item
                    };
                    job.bill.Notify_IterationCompleted(pawn, list);
                    RecordsUtility.Notify_BillDone(pawn, list);
                }
            };

            yield return(itemRepairedToil);

            yield return(Toils_Haul.StartCarryThing(TI_ITEM));

            if (job.bill.GetStoreMode() == BillStoreModeDefOf.BestStockpile)
            {
                yield return(new Toil
                {
                    initAction = () =>
                    {
                        if (!StoreUtility.TryFindBestBetterStoreCellFor(item, pawn, pawn.Map, StoragePriority.Unstored,
                                                                        pawn.Faction, out var foundCell))
                        {
                            return;
                        }
                        pawn.Reserve(foundCell, job);
                        job.SetTarget(TI_CELL, foundCell);
                    }
                });
Exemple #14
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.AddFinishAction(delegate()
            {
                if (Patient.CurrentBed() == Bed && Patient.CurJobDef == JobDefOf.LayDown)
                {
                    Patient.jobs.EndCurrentJob(JobCondition.Succeeded);
                }
            });
            this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.B);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.C);
            yield return(Toils_Reserve.Reserve(TargetIndex.A));

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

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

            //Go and get the thing to carry.
            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.OnCell));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.B));

            yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch));

            yield return(Toils_Haul.PlaceCarriedThingInCellFacing(TargetIndex.C));

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

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

            yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch));

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

            yield return(Toils_Reserve.Release(TargetIndex.C));

            Toil applyBrainTemplateToil = new Toil()
            {
                defaultCompleteMode = ToilCompleteMode.Never,
                initAction          = delegate()
                {
                    Patient.pather.StopDead();
                    Patient.jobs.StartJob(new Job(JobDefOf.LayDown, TargetC)
                    {
                        forceSleep = true
                    });
                },
                tickAction = delegate()
                {
                    ticksWork -= 1f * pawn.GetStatValue(StatDefOf.ResearchSpeed);

                    if (ticksWork <= 0)
                    {
                        BrainManipUtility.ApplyBrainScanTemplateOnPawn(Patient, BrainTemplate);
                        Patient.jobs.EndCurrentJob(JobCondition.Succeeded);

                        //Give headache
                        Patient.health.AddHediff(QEHediffDefOf.QE_Headache, Patient.health.hediffSet.GetBrain());
                    }
                }
            }.WithProgressBar(TargetIndex.A, () => (workRequired - ticksWork) / workRequired).WithEffect(EffecterDefOf.Research, TargetIndex.A);

            applyBrainTemplateToil.AddPreInitAction(delegate()
            {
                ticksWork   = workRequired;
                workStarted = true;
                //Log.Message("preInitAction: ticksWork = " + ticksWork);
            });
            applyBrainTemplateToil.AddEndCondition(delegate()
            {
                if (workStarted && ticksWork <= 0)
                {
                    //Log.Message("Succeeded: ticksWork = " + ticksWork);
                    return(JobCondition.Succeeded);
                }

                //Log.Message("Ongoing: ticksWork = " + ticksWork);
                return(JobCondition.Ongoing);
            });
            applyBrainTemplateToil.AddFailCondition(() => workStarted && Patient.CurJobDef != JobDefOf.LayDown);

            yield return(applyBrainTemplateToil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(delegate
            {
                if (!CurJob.ignoreDesignations)
                {
                    Pawn victim = Victim;
                    if (victim != null && !victim.Dead && Map.designationManager.DesignationOn(victim, DesignationDefOf.Hunt) == null)
                    {
                        return(true);
                    }
                }
                return(false);
            });

            yield return(Toils_Reserve.Reserve(VictimInd, 1));

            var init = new Toil();

            init.initAction = delegate
            {
                jobStartTick = Find.TickManager.TicksGame;
            };

            yield return(init);

            yield return(Toils_Combat.TrySetJobToUseAttackVerb());

            var comp = (pawn.equipment != null && pawn.equipment.Primary != null) ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null;
            var startCollectCorpse = StartCollectCorpseToil();
            var gotoCastPos        = GotoCastPosition(VictimInd, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse).FailOn(() => Find.TickManager.TicksGame > jobStartTick + MaxHuntTicks);

            yield return(gotoCastPos);

            //var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(VictimInd, gotoCastPos);
            var moveIfCannotHit = Toils_Jump.JumpIf(gotoCastPos, delegate
            {
                var verb         = CurJob.verbToUse;
                var optimalRange = HuntRangePerBodysize(Victim.RaceProps.baseBodySize, Victim.RaceProps.executionRange, verb.verbProps.range);
                if (pawn.Position.DistanceTo(Victim.Position) > optimalRange)
                {
                    return(true);
                }
                return(!verb.CanHitTarget(Victim));
            });

            yield return(moveIfCannotHit);

            yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(VictimInd, startCollectCorpse));

            var startExecuteDowned = Toils_Goto.GotoThing(VictimInd, PathEndMode.Touch).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse);

            yield return(Toils_Jump.JumpIf(startExecuteDowned, () => Victim.Downed && Victim.RaceProps.executionRange <= 2));

            yield return(Toils_Jump.JumpIfTargetDownedDistant(VictimInd, gotoCastPos));

            yield return(Toils_Combat.CastVerb(VictimInd, false).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse)
                         .FailOn(() => {
                if (Find.TickManager.TicksGame <= jobStartTick + MaxHuntTicks)
                {
                    if (comp == null || comp.HasAndUsesAmmoOrMagazine)
                    {
                        return false;
                    }
                }
                return true;
            }));

            yield return(Toils_Jump.Jump(moveIfCannotHit));

            // Execute downed animal - adapted from JobDriver_Slaughter
            yield return(startExecuteDowned);

            yield return(Toils_General.WaitWith(VictimInd, 180, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse));

            yield return(new Toil
            {
                initAction = delegate
                {
                    ExecutionUtility.DoExecutionByCut(pawn, Victim);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            // Haul corpse to stockpile
            yield return(startCollectCorpse);

            yield return(Toils_Goto.GotoCell(VictimInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(VictimInd).FailOnSomeonePhysicallyInteracting(VictimInd));

            yield return(Toils_Haul.StartCarryThing(VictimInd));

            var carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, true));
        }
Exemple #16
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.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;
        }
            public bool MoveNext()
            {
                uint num = (uint)this.$PC;

                this.$PC = -1;
                switch (num)
                {
                case 0u:
                    this.$current = Toils_General.Wait(10, TargetIndex.None);
                    if (!this.$disposing)
                    {
                        this.$PC = 1;
                    }
                    return(true);

                case 1u:
                {
                    Toil pickItem = new Toil();
                    pickItem.initAction = delegate()
                    {
                        if (!this.pawn.inventory.UnloadEverything)
                        {
                            base.EndJobWith(JobCondition.Succeeded);
                        }
                        else
                        {
                            ThingCount firstUnloadableThing = this.pawn.inventory.FirstUnloadableThing;
                            IntVec3    c;
                            if (!StoreUtility.TryFindStoreCellNearColonyDesperate(firstUnloadableThing.Thing, this.pawn, out c))
                            {
                                Thing thing;
                                this.pawn.inventory.innerContainer.TryDrop(firstUnloadableThing.Thing, ThingPlaceMode.Near, firstUnloadableThing.Count, out thing, null, null);
                                base.EndJobWith(JobCondition.Succeeded);
                            }
                            else
                            {
                                this.job.SetTarget(TargetIndex.A, firstUnloadableThing.Thing);
                                this.job.SetTarget(TargetIndex.B, c);
                                this.countToDrop = firstUnloadableThing.Count;
                            }
                        }
                    };
                    this.$current = pickItem;
                    if (!this.$disposing)
                    {
                        this.$PC = 2;
                    }
                    return(true);
                }

                case 2u:
                    this.$current = Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null);
                    if (!this.$disposing)
                    {
                        this.$PC = 3;
                    }
                    return(true);

                case 3u:
                    this.$current = Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch);
                    if (!this.$disposing)
                    {
                        this.$PC = 4;
                    }
                    return(true);

                case 4u:
                {
                    Toil dropOrStartCarrying = new Toil();
                    dropOrStartCarrying.initAction = delegate()
                    {
                        Thing thing = this.job.GetTarget(TargetIndex.A).Thing;
                        if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing))
                        {
                            base.EndJobWith(JobCondition.Incompletable);
                        }
                        else
                        {
                            if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false))
                            {
                                this.pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, this.countToDrop, out thing, null, null);
                                base.EndJobWith(JobCondition.Succeeded);
                            }
                            else
                            {
                                this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, this.countToDrop, out thing, true);
                                this.job.count = this.countToDrop;
                                this.job.SetTarget(TargetIndex.A, thing);
                            }
                            thing.SetForbidden(false, false);
                        }
                    };
                    this.$current = dropOrStartCarrying;
                    if (!this.$disposing)
                    {
                        this.$PC = 5;
                    }
                    return(true);
                }

                case 5u:
                    carryToCell   = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);
                    this.$current = carryToCell;
                    if (!this.$disposing)
                    {
                        this.$PC = 6;
                    }
                    return(true);

                case 6u:
                    this.$current = Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true);
                    if (!this.$disposing)
                    {
                        this.$PC = 7;
                    }
                    return(true);

                case 7u:
                    this.$PC = -1;
                    break;
                }
                return(false);
            }
Exemple #18
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            ///
            //Set fail conditions
            ///

            this.FailOnDestroyedOrNull(MountableInd);
            this.FailOnDowned(DriverInd);
            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            if (!TargetThingA.IsForbidden(pawn.Faction))
            {
                this.FailOnForbidden(MountableInd);
            }



            ///
            //Define Toil
            ///

            Toil toilMakeStandby = new Toil();

            toilMakeStandby.initAction = () =>
            {
                Pawn driver = CurJob.GetTarget(DriverInd).Thing as Pawn;
                driver.jobs.StartJob(new Job(DefDatabase <JobDef> .GetNamed("Standby"), driver.Position, 2400 + (int)((pawn.Position - driver.Position).LengthHorizontal * 120)), JobCondition.InterruptForced);
            };

            Toil toilGoto = null;

            toilGoto = Toils_Goto.GotoThing(MountableInd, PathEndMode.ClosestTouch)
                       .FailOn(() =>
            {
                //Note we don't fail on losing hauling designation
                //Because that's a special case anyway

                //While hauling to cell storage, ensure storage dest is still valid
                Pawn actor = toilGoto.actor;
                Job curJob = actor.jobs.curJob;
                if (curJob.haulMode == HaulMode.ToCellStorage)
                {
                    Thing haulThing = curJob.GetTarget(MountableInd).Thing;

                    IntVec3 destLoc = actor.jobs.curJob.GetTarget(TargetIndex.B).Cell;
                    if (!destLoc.IsValidStorageFor(haulThing))
                    {
                        return(true);
                    }
                }

                return(false);
            });

            Toil toilMountOn = new Toil();

            toilMountOn.initAction = () =>
            {
                Pawn driver = TargetB.Thing as Pawn;
                if (driver != null && TargetThingA.TryGetComp <CompMountable>() != null)
                {
                    TargetThingA.TryGetComp <CompMountable>().MountOn(driver);
                }
                else
                {
                    Log.Error(GetActor().LabelCap + ": Try make mount without target B Driver");
                    EndJobWith(JobCondition.Errored);
                }
            };

            Toil toilEnd = new Toil();

            toilEnd.initAction = () =>
            {
                Vehicle_Cart   cart   = CurJob.GetTarget(MountableInd).Thing as Vehicle_Cart;
                Vehicle_Saddle saddle = CurJob.GetTarget(MountableInd).Thing as Vehicle_Saddle;
                if (cart == null || saddle == null)
                {
                    Log.Error(GetActor().LabelCap + ": MakeMount get TargetA not cart or saddle.");
                    EndJobWith(JobCondition.Errored);
                    return;
                }
                if (cart.mountableComp.IsMounted && cart.mountableComp.Driver.CurJob.def == DefDatabase <JobDef> .GetNamed("Standby"))
                {
                    cart.mountableComp.Driver.jobs.curDriver.EndJobWith(JobCondition.Succeeded);
                }
                EndJobWith(JobCondition.Succeeded);
            };

            ///
            //Toils Start
            ///

            //Reserve thing to be stored and storage cell
            yield return(Toils_Reserve.Reserve(MountableInd));

            yield return(Toils_Reserve.Reserve(DriverInd));

            yield return(toilMakeStandby);

            yield return(toilGoto);

            yield return(Toils_Haul.StartCarryThing(MountableInd));

            yield return(Toils_Haul.CarryHauledThingToCell(DriverInd));

            yield return(toilMountOn);

            yield return(toilEnd);
        }
Exemple #19
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            // Error checking/input validation.
            if (turret == null)
            {
                Log.Error(string.Concat(errorBase, "TargetThingA isn't a Building_TurretGunCE"));
                yield return(null);
            }
            if (compReloader == null)
            {
                Log.Error(string.Concat(errorBase, "TargetThingA (Building_TurretGunCE) is missing its CompAmmoUser."));
                yield return(null);
            }
            if (compReloader.UseAmmo && ammo == null)
            {
                Log.Error(string.Concat(errorBase, "TargetThingB is either null or not an AmmoThing."));
                yield return(null);
            }

            AddEndCondition(delegate
            {
                return((pawn.Downed || pawn.Dead || pawn.InMentalState || pawn.IsBurning()) ? JobCondition.Incompletable : JobCondition.Ongoing);
            });

            this.FailOnIncapable(PawnCapacityDefOf.Manipulation);

            // Set fail condition on turret.
            if (pawn.Faction != Faction.OfPlayer)
            {
                this.FailOnDestroyedOrNull(TargetIndex.A);
            }
            else
            {
                this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            }

            // Perform ammo system specific activities, failure condition and hauling
            if (compReloader.UseAmmo)
            {
                var toilGoToCell   = Toils_Goto.GotoCell(ammo.Position, PathEndMode.Touch).FailOnBurningImmobile(TargetIndex.B);
                var toilCarryThing = Toils_Haul.StartCarryThing(TargetIndex.B).FailOnBurningImmobile(TargetIndex.B);

                if (TargetThingB is AmmoThing)
                {
                    toilGoToCell.AddEndCondition(delegate { return((TargetThingB as AmmoThing).IsCookingOff ? JobCondition.Incompletable : JobCondition.Ongoing); });
                    toilCarryThing.AddEndCondition(delegate { return((TargetThingB as AmmoThing).IsCookingOff ? JobCondition.Incompletable : JobCondition.Ongoing); });
                }

                if (pawn.Faction != Faction.OfPlayer)
                {
                    ammo.SetForbidden(true, false);
                    toilGoToCell.FailOnDestroyedOrNull(TargetIndex.B);
                    toilCarryThing.FailOnDestroyedOrNull(TargetIndex.B);
                }
                else
                {
                    toilGoToCell.FailOnDestroyedNullOrForbidden(TargetIndex.B);
                    toilCarryThing.FailOnDestroyedNullOrForbidden(TargetIndex.B);
                }

                //yield return Toils_Reserve.Reserve(TargetIndex.B, Mathf.Max(1, TargetThingB.stackCount - job.count), job.count);
                yield return(toilGoToCell);

                yield return(toilCarryThing);
                //yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.A, null, false);
            }

            // If ammo system is turned off we just need to go to the turret.
            yield return(Toils_Goto.GotoCell(turret.Position, PathEndMode.Touch));

            //If pawn fails reloading from this point, reset isReloading
            this.AddFinishAction(delegate { turret.isReloading = false; });

            // Wait in place
            Toil waitToil = new Toil()
            {
                actor = pawn
            };

            waitToil.initAction = delegate
            {
                // Initial relaod process activities.
                turret.isReloading = true;
                waitToil.actor.pather.StopDead();
                if (compReloader.ShouldThrowMote)
                {
                    MoteMaker.ThrowText(turret.Position.ToVector3Shifted(), turret.Map, string.Format("CE_ReloadingTurretMote".Translate(), TargetThingA.LabelCapNoCount));
                }
                Thing newAmmo;
                compReloader.TryUnload(out newAmmo);
                if (newAmmo?.CanStackWith(ammo) ?? false)
                {
                    pawn.carryTracker.TryStartCarry(newAmmo, Mathf.Min(newAmmo.stackCount, compReloader.Props.magazineSize - ammo.stackCount));
                }
            };
            waitToil.defaultCompleteMode = ToilCompleteMode.Delay;
            waitToil.defaultDuration     = Mathf.CeilToInt(compReloader.Props.reloadTime.SecondsToTicks() / pawn.GetStatValue(CE_StatDefOf.ReloadSpeed));
            yield return(waitToil.WithProgressBarToilDelay(TargetIndex.A));

            //Actual reloader
            Toil reloadToil = new Toil();

            reloadToil.defaultCompleteMode = ToilCompleteMode.Instant;
            reloadToil.initAction          = delegate
            {
                compReloader.LoadAmmo(ammo);
                turret.isReloading = false;
            };
            //if (compReloader.useAmmo) reloadToil.EndOnDespawnedOrNull(TargetIndex.B);
            yield return(reloadToil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedNullOrForbidden(PowerDestIndex);
            if (!TargetB.IsValid)
            {
                AddFailCondition(() => energyNeed == null);
            }

            if (!isUsedFromInventory)
            {
                yield return(Toils_Reserve.Reserve(PowerDestIndex));

                if (TargetB.IsValid)
                {
                    yield return(Toils_Reserve.Reserve(OtherPawnIndex));
                }

                yield return(Toils_Goto.GotoThing(PowerDestIndex, PathEndMode.OnCell).FailOnSomeonePhysicallyInteracting(PowerDestIndex));

                yield return(Toils_Reserve.Release(PowerDestIndex));
            }
            else
            {
                yield return(new Toil()
                {
                    initAction = delegate()
                    {
                        if (!thingIsSplitOff && pawn.carryTracker.CarriedThing != TargetThingA)
                        {
                            Thing splitOffThing = TargetThingA.SplitOff(job.count);
                            thingIsSplitOff = true;
                            GenPlace.TryPlaceThing(splitOffThing, pawn.Position, pawn.Map, ThingPlaceMode.Near);

                            TargetThingA = splitOffThing;
                        }
                    }
                });
            }

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

            this.AddFinishAction(delegate()
            {
                if (pawn.carryTracker is Pawn_CarryTracker carryTracker && carryTracker.CarriedThing is Thing thing)
                {
                    if (isUsedFromInventory)
                    {
                        //Thing takenThing = carryTracker.innerContainer.Take(thing);
                        pawn.inventory.innerContainer.TryAddOrTransfer(thing, true);
                    }
                    else
                    {
                        carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Near, out Thing resultThing);
                    }
                }
            });

            if (TargetB.IsValid)
            {
                //Recharge someone else.
                yield return(Toils_Goto.GotoThing(OtherPawnIndex, PathEndMode.Touch).FailOnForbidden(OtherPawnIndex));

                yield return(Toils_General.Wait(100).WithProgressBarToilDelay(TargetIndex.A, false));

                Toil rechargeToil = new Toil();
                rechargeToil.AddFinishAction(delegate()
                {
                    //Use up the carried stack
                    Thing carriedThing = pawn.carryTracker.CarriedThing;
                    if (carriedThing != null)
                    {
                        EnergySourceComp energyComp = carriedThing.TryGetComp <EnergySourceComp>();
                        if (energyComp != null)
                        {
                            energyComp.RechargeEnergyNeed((Pawn)TargetB.Thing);
                        }

                        pawn.carryTracker.DestroyCarriedThing();
                    }
                });

                yield return(rechargeToil);

                yield return(Toils_Reserve.Release(OtherPawnIndex));
            }
            else
            {
                yield return(Toils_General.Wait(100).WithProgressBarToilDelay(TargetIndex.A, false));

                //Recharge user.
                Toil rechargeToil = new Toil();
                rechargeToil.AddFinishAction(delegate()
                {
                    //Use up the carried stack
                    Thing carriedThing = pawn.carryTracker.CarriedThing;
                    if (carriedThing != null)
                    {
                        EnergySourceComp energyComp = carriedThing.TryGetComp <EnergySourceComp>();
                        if (energyComp != null)
                        {
                            energyComp.RechargeEnergyNeed(pawn);
                        }

                        pawn.carryTracker.DestroyCarriedThing();
                    }
                });

                yield return(rechargeToil);
            }
        }
Exemple #21
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Commence fail checks!
            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);

            yield return(Toils_Reserve.Reserve(TakeeIndex, 1));

            yield return(Toils_Reserve.Reserve(AltarIndex, 1));

            yield return(new Toil
            {
                initAction = delegate
                {
                    DropPoint.IsLoading = true;
                    customString = "BloodHaulPrisoner_Gathering".Translate();
                }
            });

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(Toils_Construct.UninstallIfMinifiable(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

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

            Toil waitingTime = new Toil();

            waitingTime.defaultCompleteMode = ToilCompleteMode.Delay;
            waitingTime.defaultDuration     = 400;
            waitingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f);
            waitingTime.initAction = delegate
            {
                customString = "BloodHaulPrisoner_Strapping".Translate(new object[]
                {
                    this.Takee.LabelShort
                });
            };
            yield return(waitingTime);

            yield return(new Toil
            {
                initAction = delegate
                {
                    customString = "BloodHaulPrisoner_Finished".Translate();
                    IntVec3 position = this.DropPoint.Position;
                    Thing thing;
                    this.pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out thing, null);
                    if (!this.DropPoint.Destroyed)
                    {
                        PrisonerHaulCompleted();
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

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

            //Toil 9: Think about that.
            yield return(new Toil
            {
                initAction = delegate
                {
                    ////It's a day to remember
                    //TaleDef taleToAdd = TaleDef.Named("HeldSermon");
                    //if ((this.pawn.IsColonist || this.pawn.HostFaction == Faction.OfPlayer) && taleToAdd != null)
                    //{
                    //    TaleRecorder.RecordTale(taleToAdd, new object[]
                    //    {
                    //       this.pawn,
                    //    });
                    //}
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            yield break;
        }
Exemple #22
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            Toil gotoTurret   = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);
            Toil loadIfNeeded = new Toil();

            loadIfNeeded.initAction = delegate()
            {
                Pawn               actor              = loadIfNeeded.actor;
                Building           building           = (Building)actor.CurJob.targetA.Thing;
                Building_TurretGun building_TurretGun = building as Building_TurretGun;
                if (!JobDriver_ManTurret.GunNeedsLoading(building))
                {
                    this.JumpToToil(gotoTurret);
                }
                else
                {
                    Thing thing = JobDriver_ManTurret.FindAmmoForTurret(this.pawn, building_TurretGun);
                    if (thing == null)
                    {
                        if (actor.Faction == Faction.OfPlayer)
                        {
                            Messages.Message("MessageOutOfNearbyShellsFor".Translate(new object[]
                            {
                                actor.LabelShort,
                                building_TurretGun.Label
                            }).CapitalizeFirst(), building_TurretGun, MessageTypeDefOf.NegativeEvent, true);
                        }
                        actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                    }
                    actor.CurJob.targetB = thing;
                    actor.CurJob.count   = 1;
                }
            };
            yield return(loadIfNeeded);

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

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.OnCell).FailOnSomeonePhysicallyInteracting(TargetIndex.B));

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

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

            yield return(new Toil
            {
                initAction = delegate()
                {
                    Pawn actor = loadIfNeeded.actor;
                    Building building = (Building)actor.CurJob.targetA.Thing;
                    Building_TurretGun building_TurretGun = building as Building_TurretGun;
                    SoundDefOf.Artillery_ShellLoaded.PlayOneShot(new TargetInfo(building_TurretGun.Position, building_TurretGun.Map, false));
                    building_TurretGun.gun.TryGetComp <CompChangeableProjectile>().LoadShell(actor.CurJob.targetB.Thing.def, 1);
                    actor.carryTracker.innerContainer.ClearAndDestroyContents(DestroyMode.Vanish);
                }
            });

            yield return(gotoTurret);

            Toil man = new Toil();

            man.tickAction = delegate()
            {
                Pawn     actor    = man.actor;
                Building building = (Building)actor.CurJob.targetA.Thing;
                if (JobDriver_ManTurret.GunNeedsLoading(building))
                {
                    this.JumpToToil(loadIfNeeded);
                }
                else
                {
                    building.GetComp <CompMannable>().ManForATick(actor);
                }
            };
            man.defaultCompleteMode = ToilCompleteMode.Never;
            man.FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell);
            yield return(man);

            yield break;
        }
Exemple #23
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Set fail conditions
            this.FailOnDestroyedOrNull(HaulableInd);
            this.FailOnBurningImmobile(StoreCellInd);

            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            //
            // TODO instead of this, just use Job.ignoreForbidden where appropriate
            //
            if (!forbiddenInitially)
            {
                this.FailOnForbidden(HaulableInd);
            }

            //Reserve thing to be stored
            //This is redundant relative to MakePreToilReservations(), but the redundancy doesn't hurt, and if we end up looping and grabbing more things, it's necessary
            var reserveTargetA = Toils_Reserve.Reserve(HaulableInd);

            yield return(reserveTargetA);

#if DEBUG
            HaulToStack.Instance.Logger.Trace("Current Job: " + pawn.CurJob.def.defName);
#endif

            //Reserve the location to store
            //Only do this if (current stack size + what pawn is currently holding + targetA stack size) >= things max stack size
            //if (HaulUtils.ShouldReserveHaulLocation(job.targetA.Thing, job.targetB.Cell, pawn, Map))
            //{
            var reserveTargetB = Toils_Reserve.Reserve(StoreCellInd);
            yield return(reserveTargetB);

            //}


            Toil toilGoto = null;
            toilGoto = Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                       .FailOnSomeonePhysicallyInteracting(HaulableInd)
                       .FailOn(() =>
            {
                //Note we don't fail on losing hauling designation
                //Because that's a special case anyway

                //While hauling to cell storage, ensure storage dest is still valid
                Pawn actor = toilGoto.actor;
                Job curJob = actor.jobs.curJob;
                if (curJob.haulMode == HaulMode.ToCellStorage)
                {
                    Thing haulThing = curJob.GetTarget(HaulableInd).Thing;

                    IntVec3 destLoc = actor.jobs.curJob.GetTarget(TargetIndex.B).Cell;
                    if (!destLoc.IsValidStorageFor(Map, haulThing))
                    {
                        return(true);
                    }
                }

                return(false);
            });
            yield return(toilGoto);

            yield return(Toils_Haul.StartCarryThing(HaulableInd, subtractNumTakenFromJobCount: true));

            if (job.haulOpportunisticDuplicates)
            {
                yield return(Toils_Haul.CheckForGetOpportunityDuplicate(reserveTargetA, HaulableInd, StoreCellInd));
                //yield return HaulUtils.CheckForGetOpportunityDuplicateReplace(reserveTargetA, HaulableInd, StoreCellInd);

                //#if DEBUG
                //                HaulToStack.Instance.Logger.Trace("Opportunistic pickup");
                //                if (getDups == null)
                //                    HaulToStack.Instance.Logger.Trace("There are no opportunistic dups");
                //#endif
                //                if (HaulUtils.ShouldReserveHaulLocation(nextJob.job.targetA.Thing, job.targetB.Cell, pawn, Map))
                //                {
                //                    var reserveTargetB = Toils_Reserve.Reserve(StoreCellInd);
                //                    yield return reserveTargetB;
                //                }
            }


            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd);
            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, true));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);
            this.FailOnAggroMentalState(TargetIndex.A);
            if (base.job.def == JobDefOf.Rescue)
            {
                this.FailOnNotDowned(TargetIndex.A);
            }
            this.FailOn(delegate
            {
                if (this.job.def.makeTargetPrisoner)
                {
                    if (!this.DropBed.ForPrisoners)
                    {
                        return(true);
                    }
                }
                else if (this.DropBed.ForPrisoners != ((Pawn)((Thing)this.TargetA)).IsPrisoner)
                {
                    return(true);
                }
                return(false);
            });
            yield return(Toils_Reserve.Reserve(TargetIndex.A, 1));

            yield return(Toils_Reserve.Reserve(TargetIndex.B, this.DropBed.SleepingSlotsCount));

            yield return(Toils_Bed.ClaimBedIfNonMedical(TargetIndex.B, TargetIndex.A));

            this.globalFinishActions.Add(delegate
            {
                if (this.job.def.makeTargetPrisoner && this.Takee.ownership.OwnedBed == this.DropBed && this.Takee.Position != RestUtility.GetBedSleepingSlotPosFor(this.Takee, this.DropBed))
                {
                    this.Takee.ownership.UnclaimBed();
                }
            });                         //Pretty sure I just changed this code to say "If(!CanBeArrestedByMyself){... See !this.Takee.CanBeArrestedBy((Pawn)base.pawn)). Previously used to be !this.CanBeArrested() but this method no longer exists.
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnNonMedicalBedNotOwned(TargetIndex.B, TargetIndex.A).FailOn(() => this.job.def == JobDefOf.Arrest && !this.Takee.CanBeArrestedBy((Pawn)base.pawn)).FailOn(() => !this.pawn.CanReach(this.DropBed, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(new Toil
            {
                initAction = delegate
                {
                    if (this.job.def.makeTargetPrisoner)
                    {
                        Pawn pawn = (Pawn)this.job.targetA.Thing;
                        Lord lord = pawn.GetLord();
                        if (lord != null)
                        {
                            lord.Notify_PawnAttemptArrested(pawn);
                        }


                        GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm);


                        if (Rand.Value < 0.1f)
                        {
                            Messages.Message("MessageRefusedArrest".Translate(new object[]
                                                                              { pawn.LabelShort }), pawn, MessageTypeDefOf.NegativeEvent);

                            pawn.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Berserk, null, false, false, null);
                            IncidentWorker_Rebellion.removeLeadership(pawn);
                            pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("LeaderArrested"));
                            this.pawn.mindState.mentalStateHandler.CurState.RecoverFromState();
                            Find.LetterStack.ReceiveLetter("LeaderEndLetter".Translate(), "LeaderEndLetterDesc".Translate(new object[] { pawn.Name.ToStringFull }), LetterDefOf.NegativeEvent, pawn, null);
                            this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                        }
                    }
                }
            });

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A, false, false));

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

            yield return(new Toil
            {
                initAction = delegate
                {
                    if (this.job.def.makeTargetPrisoner)
                    {
                        this.pawn.mindState.mentalStateHandler.CurState.RecoverFromState();
                        IncidentWorker_Rebellion.removeLeadership(this.Takee);
                        this.Takee.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("LeaderArrested"));
                        Find.LetterStack.ReceiveLetter("LeaderEndLetterArrested".Translate(), "LeaderEndLetterDescArrested".Translate(new object[] { Takee.Name.ToStringFull }), LetterDefOf.NegativeEvent, this.pawn, null);
                        foreach (Pawn p in IncidentWorker_SetLeadership.getAllColonists())
                        {
                            if (p != this.Takee)
                            {
                                p.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("LeaderArrestedColonist"), null);
                            }
                        }

                        if (this.Takee.guest.Released)
                        {
                            this.Takee.guest.Released = false;
                            this.Takee.guest.interactionMode = PrisonerInteractionModeDefOf.NoInteraction;
                        }
                        if (!this.Takee.IsPrisonerOfColony)
                        {
                            if (this.Takee.Faction != null)
                            {
                                this.Takee.Faction.Notify_MemberCaptured(this.Takee, this.pawn.Faction);
                            }
                            this.Takee.guest.SetGuestStatus(Faction.OfPlayer, true);
                            if (this.Takee.guest.IsPrisoner)
                            {
                                TaleRecorder.RecordTale(TaleDefOf.Captured, new object[]
                                {
                                    this.pawn,
                                    this.Takee
                                });
                                this.pawn.records.Increment(RecordDefOf.PeopleCaptured);
                            }
                        }
                    }
                    else if (this.Takee.Faction != Faction.OfPlayer && this.Takee.HostFaction != Faction.OfPlayer && this.Takee.guest != null)
                    {
                        this.Takee.guest.SetGuestStatus(Faction.OfPlayer, false);
                    }
                    if (this.Takee.playerSettings == null)
                    {
                        this.Takee.playerSettings = new Pawn_PlayerSettings(this.Takee);
                    }
                }
            });

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

            yield return(new Toil
            {
                initAction = delegate
                {
                    IntVec3 position = this.DropBed.Position;
                    Thing thing;
                    this.pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out thing, null);
                    if (!this.DropBed.Destroyed && (this.DropBed.OwnersForReading.Contains(this.Takee) || (this.DropBed.Medical && this.DropBed.AnyUnoccupiedSleepingSlot) || this.Takee.ownership == null))
                    {
                        this.Takee.jobs.Notify_TuckedIntoBed(this.DropBed);
                        if (this.Takee.RaceProps.Humanlike && this.job.def != JobDefOf.Arrest && !this.Takee.IsPrisonerOfColony)
                        {
                            this.Takee.relations.Notify_RescuedBy(this.pawn);
                        }
                    }
                    if (this.Takee.IsPrisonerOfColony)
                    {
                        LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, this.Takee, OpportunityType.GoodToKnow);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        }
        /// <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)
            {
                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)
                    {
                        EndJobWith(JobCondition.Succeeded);
                    }

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

            yield return(findSpot);

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

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing = job.GetTarget(TargetIndex.A).Thing;
                    if (thing == null || !pawn.inventory.innerContainer.Contains(thing))
                    {
                        carriedThing.Remove(thing);
                        pawn.jobs.curDriver.JumpToToil(wait);
                        return;
                    }
                    if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false))
                    {
                        pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, countToDrop, out thing);
                        EndJobWith(JobCondition.Succeeded);
                        carriedThing.Remove(thing);
                    }
                    else
                    {
                        pawn.inventory.innerContainer.TryTransferToContainer(thing, pawn.carryTracker.innerContainer, countToDrop, out thing);
                        job.count = countToDrop;
                        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(job.targetB, pawn, pawn.CurJob) &&
                        !ModCompatibilityCheck.HCSKIsActive)
                    {
                        pawn.Map.reservationManager.Release(job.targetB, pawn, pawn.CurJob);
                    }
                }
            };

            yield return(releaseReservation);

            yield return(Toils_Jump.Jump(wait));

            yield return(celebrate);
        }
Exemple #26
0
            public bool MoveNext()
            {
                uint num = (uint)this.$PC;

                this.$PC = -1;
                switch (num)
                {
                case 0u:
                    this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
                    this.$current = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B);
                    if (!this.$disposing)
                    {
                        this.$PC = 1;
                    }
                    return(true);

                case 1u:
                    this.$current = Toils_Haul.StartCarryThing(TargetIndex.B, false, false, false);
                    if (!this.$disposing)
                    {
                        this.$PC = 2;
                    }
                    return(true);

                case 2u:
                    this.$current = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnDespawnedOrNull(TargetIndex.A);
                    if (!this.$disposing)
                    {
                        this.$PC = 3;
                    }
                    return(true);

                case 3u:
                    repair = Toils_General.Wait(1000, TargetIndex.None);
                    repair.FailOnDespawnedOrNull(TargetIndex.A);
                    repair.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
                    repair.WithEffect(base.Building.def.repairEffect, TargetIndex.A);
                    repair.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f);
                    this.$current = repair;
                    if (!this.$disposing)
                    {
                        this.$PC = 4;
                    }
                    return(true);

                case 4u:
                {
                    Toil finish = new Toil();
                    finish.initAction = delegate()
                    {
                        base.Components.Destroy(DestroyMode.Vanish);
                        if (Rand.Value > this.pawn.GetStatValue(StatDefOf.FixBrokenDownBuildingSuccessChance, true))
                        {
                            Vector3 loc = (this.pawn.DrawPos + base.Building.DrawPos) / 2f;
                            MoteMaker.ThrowText(loc, base.Map, "TextMote_FixBrokenDownBuildingFail".Translate(), 3.65f);
                        }
                        else
                        {
                            base.Building.GetComp <CompBreakdownable>().Notify_Repaired();
                        }
                    };
                    this.$current = finish;
                    if (!this.$disposing)
                    {
                        this.$PC = 5;
                    }
                    return(true);
                }

                case 5u:
                    this.$PC = -1;
                    break;
                }
                return(false);
            }
        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.EverStorable(true))
                    {
                        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));
        }
Exemple #28
0
        public override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            //this.FailOnBurningImmobile(TargetIndex.B);
            if (!forbiddenInitially)
            {
                this.FailOnForbidden(TargetIndex.A);
            }
            var ZTracker = ZUtils.ZTracker;

            if (pawn.Map == this.job.targetA.Thing.Map && pawn.Map == ZTracker.jobTracker[pawn].targetDest.Map)
            {
                ZLogger.Message("pawn map and thing map and dest map are same, yield breaking in JobDriver_HaulThingToDest");
                yield break;
            }
            ZLogger.Message($"JobDriver HaulThingToDestAndCell1 About to call findRouteWithStairs, with pawn {GetActor()}, dest {new TargetInfo(TargetA.Thing)}, instance {this}");
            Log.Message("1 - pawn.Map: " + pawn.Map + " - dest: " + new TargetInfo(TargetA.Thing).Map, true);
            foreach (var toil in Toils_ZLevels.GoToMap(GetActor(), new TargetInfo(TargetA.Thing).Map, this))
            {
                yield return(toil);
            }
            Toil reserveTargetA = Toils_Reserve.Reserve(TargetIndex.A);
            Toil toilGoto       = null;

            toilGoto = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnSomeonePhysicallyInteracting(TargetIndex.A).FailOn((Func <bool>) delegate
            {
                Pawn actor = toilGoto.actor;
                Job curJob = actor.jobs.curJob;
                if (curJob.haulMode == HaulMode.ToCellStorage)
                {
                    Thing thing = curJob.GetTarget(TargetIndex.A).Thing;
                    if (!actor.jobs.curJob.GetTarget(TargetIndex.B).Cell.IsValidStorageFor(base.Map, thing))
                    {
                        return(true);
                    }
                }
                return(false);
            });

            yield return(new Toil
            {
                initAction = delegate()
                {
                    ZLogger.Message("JobDriver_HaulThingToDestAndToCell 1: " + pawn + " trying to reserve: " + TargetA, true);
                }
            });

            yield return(reserveTargetA);

            yield return(toilGoto);

            yield return(new Toil
            {
                initAction = delegate()
                {
                    this.savedThing = TargetA.Thing;
                }
            });

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A, putRemainderInQueue: false, subtractNumTakenFromJobCount: true));

            if (job.haulOpportunisticDuplicates)
            {
                yield return(new Toil
                {
                    initAction = delegate()
                    {
                        ZLogger.Message("JobDriver_HaulThingToDestAndToCell 2: " + pawn + " trying to reserve other things: " + TargetA, true);
                    }
                });

                yield return(Toils_Haul.CheckForGetOpportunityDuplicate(reserveTargetA, TargetIndex.A, TargetIndex.B));
            }
            ZLogger.Message($"JobDriver HaulThingToDestAndCell2 About to call findRouteWithStairs, with pawn {GetActor()}, dest {ZTracker.jobTracker[pawn].targetDest}, instance {this}");
            Log.Message("2 - pawn.Map: " + pawn.Map + " - dest: " + ZTracker.jobTracker[pawn].targetDest.Map, true);
            foreach (var toil in Toils_ZLevels.GoToMap(GetActor(), ZTracker.jobTracker[pawn].targetDest.Map, this))
            {
                yield return(toil);
            }
            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(carryToCell);

            yield return(new Toil
            {
                initAction = delegate()
                {
                    if (TargetB.Cell.GetFirstItem(pawn.Map) != null)
                    {
                        IntVec3 newPosition = IntVec3.Invalid;

                        IntVec3 center = (from x in GenRadial.RadialCellsAround(pawn.Position, 3f, useCenter: true)
                                          where x.InBounds(pawn.Map) && x.GetFirstItem(pawn.Map) == null
                                          select x).FirstOrDefault();
                        if (center != null)
                        {
                            job.targetB = new LocalTargetInfo(center);
                        }
                        else if (CellFinder.TryFindRandomCellNear(TargetB.Cell, pawn.Map, 3,
                                                                  (IntVec3 c) => c.GetFirstItem(pawn.Map)?.def != TargetA.Thing.def, out newPosition))
                        {
                            job.targetB = new LocalTargetInfo(newPosition);
                        }
                    }
                }
            });

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, false));
        }
Exemple #29
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            const float baseFishingDuration = 2000f;

            int   fishingDuration            = (int)baseFishingDuration;
            float catchSomethingThreshold    = 0f;
            Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier;
            Passion     passion          = Passion.None;
            const float skillGainPerTick = 0.15f;

            this.AddEndCondition(() =>
            {
                var targ = this.pawn.jobs.curJob.GetTarget(fishingPierIndex).Thing;
                if (targ is Building && !targ.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });

            this.FailOnBurningImmobile(fishingPierIndex); // Bill giver or product burning in carry phase.

            this.rotateToFace = TargetIndex.B;

            yield return(Toils_Reserve.Reserve(fishingPierIndex));

            float fishingSkillLevel = 0f;

            fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(WorkTypeDefOf.Hunting);
            float fishingSkillDurationFactor = fishingSkillLevel / 20f;

            fishingDuration = (int)(baseFishingDuration * (1.5f - fishingSkillDurationFactor));

            yield return(Toils_Goto.GotoThing(fishingPierIndex, fishingPier.riverCell).FailOnDespawnedOrNull(fishingPierIndex));

            Toil fishToil = new Toil()
            {
                initAction = () =>
                {
                    ThingDef moteDef = null;
                    if (fishingPier.Rotation == Rot4.North)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodNorthDef;
                    }
                    else if (fishingPier.Rotation == Rot4.East)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodEastDef;
                    }
                    else if (fishingPier.Rotation == Rot4.South)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodSouthDef;
                    }
                    else
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodWestDef;
                    }
                    this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null);
                    this.fishingRodMote.exactPosition = fishingPier.fishingSpotCell.ToVector3Shifted();
                    this.fishingRodMote.Scale         = 1f;
                    GenSpawn.Spawn(this.fishingRodMote, fishingPier.fishingSpotCell, this.Map);
                },
                tickAction = () =>
                {
                    if (passion == Passion.Minor)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMinor, JoyKindDefOf.Work);
                    }
                    else if (passion == Passion.Major)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMajor, JoyKindDefOf.Work);
                    }
                    this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick);

                    if (this.ticksLeftThisToil == 1)
                    {
                        if (this.fishingRodMote != null)
                        {
                            this.fishingRodMote.Destroy();
                        }
                    }
                },
                defaultDuration     = fishingDuration,
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            yield return(fishToil.WithProgressBarToilDelay(fishingPierIndex));

            Toil computeChanceToCatchToil = new Toil()
            {
                initAction = () =>
                {
                    catchSomethingThreshold = fishingSkillLevel / 20f;
                    // Reframe min and max chance (min 5%, max 75 % chance of success).
                    Mathf.Clamp(catchSomethingThreshold, 0.05f, 0.75f);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(computeChanceToCatchToil);

            Toil catchFishToil = new Toil()
            {
                initAction = () =>
                {
                    Job   curJob       = this.pawn.jobs.curJob;
                    Thing fishingCatch = null;

                    // 90% chance to successfully catch something.
                    bool catchIsSuccessful = (Rand.Value >= 0.1f);
                    if (catchIsSuccessful == false)
                    {
                        MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon);
                        this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                        return;
                    }

                    float catchSelectorValue = Rand.Value;
                    if (catchSelectorValue > 0.04f)
                    {
                        // Catch a fish.
                        bool fishSpotIsOcean = (this.Map.terrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDefOf.WaterOceanShallow) ||
                                               (this.Map.terrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDefOf.WaterOceanDeep);
                        bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDef.Named("Marsh"));

                        PawnKindDef caugthFishDef = null;
                        if (fishSpotIsOcean)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInOcean
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else if (fishSpotIsMarshy)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInMarsh
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInRiver
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef);
                        GenSpawn.Spawn(caughtFish, this.pawn.Position, this.Map);
                        HealthUtility.DamageUntilDead(caughtFish);
                        foreach (Thing thing in this.pawn.Position.GetThingList(this.Map))
                        {
                            Corpse fishCorpse = thing as Corpse;
                            if (fishCorpse != null)
                            {
                                fishingCatch = fishCorpse;
                                fishingCatch.SetForbidden(false);
                            }
                        }
                        if (caughtFish.BodySize >= 0.1f)
                        {
                            fishingPier.fishStock--;
                            fishingPier.ComputeMaxFishStockAndRespawnPeriod();
                        }
                    }
                    else if (catchSelectorValue > 0.02)
                    {
                        fishingCatch            = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map);
                        fishingCatch.stackCount = Rand.RangeInclusive(5, 27);
                    }
                    else
                    {
                        float bonusCatchValue = Rand.Value;
                        if (bonusCatchValue < 0.01f)
                        {
                            // Really small chance to find a sunken treasure!!!
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map);
                            fishingCatch.stackCount = Rand.RangeInclusive(58, 289);
                            Thing treasureSilver = GenSpawn.Spawn(ThingDefOf.Silver, fishingPier.middleCell, this.Map);
                            treasureSilver.stackCount = Rand.RangeInclusive(237, 2154);
                            Find.LetterStack.ReceiveLetter("FishIndustry.LetterLabelSunkenTreasure".Translate(), "FishIndustry.SunkenTreasure".Translate(this.pawn.Name.ToStringShort.CapitalizeFirst()),
                                                           LetterDefOf.Good, this.pawn);
                        }
                        else if (bonusCatchValue < 0.02f)
                        {
                            // Really small chance to find a complete power armor set + sniper or charge rifle.
                            Thing powerArmor = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmor"), this.pawn.Position, this.Map);
                            fishingCatch = powerArmor; // Used to carry the power armor.
                            Thing powerArmorHelmet = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmorHelmet"), this.pawn.Position, this.Map);
                            Thing rifle            = null;
                            if (Rand.Value < 0.5f)
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_ChargeRifle"), this.pawn.Position, this.Map);
                            }
                            else
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_SniperRifle"), this.pawn.Position, this.Map);
                            }
                            CompQuality qualityComp = powerArmor.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }
                            qualityComp = powerArmorHelmet.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }
                            qualityComp = rifle.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }

                            Faction faction    = Find.FactionManager.FirstFactionOfDef(FactionDefOf.SpacerHostile);
                            Pawn    deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.SpaceSoldier, faction);
                            GenSpawn.Spawn(deadMarine, fishingPier.bankCell, this.Map);
                            HealthUtility.DamageUntilDead(deadMarine);
                            List <Thing> thingsList = deadMarine.Position.GetThingList(this.Map);
                            foreach (Thing thing in thingsList)
                            {
                                if (thing.def.defName.Contains("Corpse"))
                                {
                                    CompRottable rotComp = thing.TryGetComp <CompRottable>();
                                    if (rotComp != null)
                                    {
                                        rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated.
                                    }
                                }
                            }
                            string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has cought a dead body while fishing!\n\n'This is really disgusting but look at his gear! This guy was probably a MiningCo. security member. I wonder what happend to him...'\n";
                            Find.LetterStack.ReceiveLetter("Dead marine", eventText, LetterDefOf.Good, this.pawn);
                        }
                        else
                        {
                            // Find a small amount of gold.
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map);
                            fishingCatch.stackCount = Rand.RangeInclusive(1, 7);
                        }
                        // TODO: add chance to get hurt by a tailteeth (missing finger or even hand!).
                    }
                    IntVec3 storageCell;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true))
                    {
                        this.pawn.Reserve(fishingCatch, 1);
                        this.pawn.Reserve(storageCell, 1);
                        this.pawn.CurJob.SetTarget(TargetIndex.B, storageCell);
                        this.pawn.CurJob.SetTarget(TargetIndex.A, fishingCatch);
                        this.pawn.CurJob.count    = 1;
                        this.pawn.CurJob.haulMode = HaulMode.ToCellStorage;
                    }
                    else
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                }
            };

            yield return(catchFishToil);

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

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

            yield return(carryToCell);

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

            yield return(Toils_Reserve.Release(fishingPierIndex));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            if (fishCaught == null)
            {
                this.EndJobWith(JobCondition.Incompletable);
                fishingZone.someoneFishing = false;
            }

            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnBurningImmobile(TargetIndex.A);
            yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch));

            this.pawn.rotationTracker.FaceTarget(base.TargetA);
            Toil fishToil = new Toil();

            fishToil.tickAction = delegate()
            {
                this.pawn.skills.Learn(SkillDefOf.Animals, skillGainperTick);
                if (fishingZone != null)
                {
                    if (!fishingZone.isZoneBigEnough)
                    {
                        this.EndJobWith(JobCondition.Incompletable);
                        fishingZone.someoneFishing = false;
                    }
                }
            };

            Rot4    pawnRotation = pawn.Rotation;
            IntVec3 facingCell   = pawnRotation.FacingCell;

            if (facingCell == new IntVec3(0, 0, 1))
            {
                //Log.Message("Looking north");
                fishToil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("VCEF_FishingEffectNorth"), () => this.TargetA.Cell + new IntVec3(0, 0, 1));
            }
            else if (facingCell == new IntVec3(1, 0, 0))
            {
                // Log.Message("Looking east");

                fishToil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("VCEF_FishingEffectEast"), () => this.TargetA.Cell + new IntVec3(1, 0, 0));
            }
            else if (facingCell == new IntVec3(0, 0, -1))
            {
                // Log.Message("Looking south");
                fishToil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("VCEF_FishingEffectSouth"), () => this.TargetA.Cell + new IntVec3(0, 0, -1));
            }
            else if (facingCell == new IntVec3(-1, 0, 0))
            {
                //  Log.Message("Looking west");
                fishToil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("VCEF_FishingEffectWest"), () => this.TargetA.Cell + new IntVec3(-1, 0, 0));
            }
            fishToil.defaultCompleteMode = ToilCompleteMode.Delay;

            switch (sizeAtBeginning)
            {
            case FishSizeCategory.Small:
                fishToil.defaultDuration = (int)(-150 * fishingSkill + smallFishDurationFactor * 1.5);
                break;

            case FishSizeCategory.Medium:
                fishToil.defaultDuration = (int)(-300 * fishingSkill + mediumFishDurationFactor * 1.5);
                break;

            case FishSizeCategory.Large:
                fishToil.defaultDuration = (int)(-450 * fishingSkill + largeFishDurationFactor * 1.5);
                break;

            default:
                fishToil.defaultDuration = mediumFishDurationFactor;
                break;
            }

            //Log.Message(fishToil.defaultDuration.ToString());
            fishToil.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            yield return(fishToil.WithProgressBarToilDelay(TargetIndex.A, true));

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing newFish = ThingMaker.MakeThing(fishCaught);
                    newFish.stackCount = fishAmountWithSkill;
                    GenSpawn.Spawn(newFish, this.TargetA.Cell - GenAdj.CardinalDirections[0], this.Map);
                    StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(newFish);
                    IntVec3 c;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(newFish, this.pawn, this.Map, currentPriority, this.pawn.Faction, out c, true))
                    {
                        this.job.SetTarget(TargetIndex.C, c);
                        this.job.SetTarget(TargetIndex.B, newFish);
                        this.job.count = newFish.stackCount;
                        fishingZone.someoneFishing = false;
                    }
                    else
                    {
                        this.EndJobWith(JobCondition.Incompletable);
                        fishingZone.someoneFishing = false;
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

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

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

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch));

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

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

            yield return(carryToCell);

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



            yield break;
        }