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; }
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; }
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; }
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)); }
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); } });
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)); }
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); }
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); }
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); } }
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; }
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; }
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); }
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)); }
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)); }
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; }