public static Toil FinishDrink(TargetIndex thingIndex) { return(Toils_Mizu.FinishDrinkSomeone(thingIndex, (toil) => { return toil.actor; })); }
protected override IEnumerable <Toil> MakeNewToils() { if (this.job.targetA.HasThing) { // ターゲットがThing=水アイテムを摂取する場合 // 水が使用不可能になったらFail ToilFailConditions.FailOnDestroyedNullOrForbidden <JobDriver_DrinkWater>(this, WaterIndex); // 水を取得 if (this.drinkingFromInventory) { // 所持品から取り出す yield return(Toils_Mizu.StartCarryFromInventory(WaterIndex)); } else { // 水の場所まで行く yield return(Toils_Goto.Goto(WaterIndex, PathEndMode.OnCell)); // 水を拾う yield return(Toils_Ingest.PickupIngestible(WaterIndex, this.pawn)); } // 飲む場所を決めてそこへ移動 yield return(Toils_Mizu.StartPathToDrinkSpot(WaterIndex)); // 水を摂取 yield return(Toils_Mizu.Drink(WaterIndex)); // 水の摂取終了(心情、水分、アイテム個数の処理) yield return(Toils_Mizu.FinishDrink(WaterIndex)); if (this.drinkingFromInventory && !this.TargetA.ThingDestroyed) { // 所持品から取り出した&まだ残っている場合は所持品に戻す yield return(Toils_Mizu.AddCarriedThingToInventory()); } } else { // ターゲットがThingではない=水アイテムを摂取しない場合=水地形を利用する場合 // 選んだ水地形が使用不可能or到達不可能になったらFail ToilFailConditions.FailOn <JobDriver_DrinkWater>(this, () => { return(this.job.targetA.Cell.IsForbidden(pawn) || !pawn.CanReach(this.job.targetA.Cell, PathEndMode.ClosestTouch, Danger.Deadly)); }); // 水地形まで移動 yield return(Toils_Goto.GotoCell(WaterIndex, PathEndMode.OnCell)); // 水地形から水分を摂取 yield return(Toils_Mizu.DrinkTerrain(WaterIndex, BaseDrinkTicksFromTerrain)); // 終了 //yield return Toils_Mizu.FinishDrinkTerrain(WaterIndex); } }
protected override IEnumerable <Toil> MakeNewToils() { var drawer = job.targetA.Thing; var peMode = drawer.def.hasInteractionCell ? PathEndMode.InteractionCell : PathEndMode.ClosestTouch; yield return(Toils_Goto.GotoThing(DrawerIndex, peMode)); yield return(Toils_Mizu.DrawWater(DrawerIndex, DrawTicks)); yield return(Toils_Mizu.FinishDrawWater(DrawerIndex)); }
public static Toil FinishDrinkPatient(TargetIndex thingIndex, TargetIndex patientIndex) { return(Toils_Mizu.FinishDrinkSomeone(thingIndex, (toil) => { if (!toil.actor.CurJob.GetTarget(patientIndex).HasThing) { return null; } return toil.actor.CurJob.GetTarget(patientIndex).Thing as Pawn; })); }
public static Toil Drink(TargetIndex thingIndex) { return(Toils_Mizu.DrinkSomeone(thingIndex, (toil) => { return () => { if (!toil.actor.CurJob.GetTarget(thingIndex).HasThing) { return null; } return toil.actor.CurJob.GetTarget(thingIndex).Thing; }; })); }
protected override IEnumerable <Toil> MakeNewToils() { var t = this.job.GetTarget(BuildingIndex).Thing; // 設備まで移動 if (t.def.hasInteractionCell) { // 使用場所がある yield return(Toils_Goto.GotoThing(BuildingIndex, PathEndMode.InteractionCell)); } else { // 使用場所がない yield return(Toils_Goto.GotoThing(BuildingIndex, PathEndMode.ClosestTouch)); } // 水を飲む yield return(Toils_Mizu.DrinkFromBuilding(BuildingIndex)); }
public static Toil FeedToPatient(TargetIndex thingIndex, TargetIndex patientIndex) { return(Toils_Mizu.DrinkSomeone(thingIndex, (toil) => { return () => { if (!toil.actor.CurJob.GetTarget(patientIndex).HasThing) { return null; } var patient = toil.actor.CurJob.GetTarget(patientIndex).Thing as Pawn; if (patient == null) { return null; } return patient; }; })); }
protected override IEnumerable <Toil> MakeNewToils() { // 水が使用不可能になったらFail ToilFailConditions.FailOnDestroyedNullOrForbidden <JobDriver_WaterDeliver>(this, WaterIndex); if (!this.pawn.CanReserveAndReach(this.TargetA, PathEndMode.Touch, Danger.Deadly, 1, this.job.count)) { // 水を予約できなかったら終了 this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); yield break; } // 予約する if (!this.pawn.Map.reservationManager.ReservedBy(this.TargetA.Thing, pawn)) { yield return(Toils_Reserve.Reserve(WaterIndex, 1, this.job.count, null)); } if (this.drinkingFromInventory) { // 水を持ち物から取り出す yield return(Toils_Mizu.StartCarryFromInventory(WaterIndex)); } else { // 水の場所まで行く yield return(Toils_Goto.Goto(WaterIndex, PathEndMode.OnCell)); // 水を拾う yield return(Toils_Ingest.PickupIngestible(WaterIndex, this.pawn)); } // スポットまで移動する yield return(Toils_Goto.GotoCell(this.TargetC.Cell, PathEndMode.OnCell)); // 置いて囚人に予約させる yield return(Toils_Mizu.DropCarriedThing(PrisonerIndex, DropSpotIndex)); }
protected override IEnumerable <Toil> MakeNewToils() { // その他の失敗条件設定 this.SetFailCondition(); PathEndMode peMode; if (this.job.GetTarget(BillGiverInd).Thing.def.hasInteractionCell) { peMode = PathEndMode.InteractionCell; } else { peMode = PathEndMode.Touch; } // 設備まで行く yield return(Toils_Goto.GotoThing(BillGiverInd, peMode)); // レシピ実行 yield return(Toils_Mizu.DoRecipeWorkDrawing(BillGiverInd)); // レシピ終了処理 yield return(Toils_Mizu.FinishRecipeAndStartStoringProduct(this.FinishAction)); // 最適な倉庫まで運ぶ場合はさらに処理をする // 持っていく yield return(Toils_Haul.CarryHauledThingToCell(TargetIndex.B)); // 置く yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.A, null, false)); // 備蓄量更新(X個になるまで作成、の場合) yield return(Toils_Mizu.UpdateResourceCounts()); }
protected override IEnumerable <Toil> MakeNewToils() { // モップまで移動 yield return(Toils_Goto.GotoThing(MopInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(MopInd)); // モップを手に取る yield return(Toils_Haul.StartCarryThing(MopInd)); // ターゲットが掃除対象として不適になっていたらリストから外す // Thing系にしか使えない var initExtractTargetFromQueue = Toils_Mizu.ClearConditionSatisfiedTargets( MoppingInd, lti => lti.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(MoppingInd)); // ターゲットキューから次のターゲットを取り出す yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(MoppingInd)); // ターゲットの元へ移動 yield return(Toils_Goto.GotoCell(MoppingInd, PathEndMode.Touch).JumpIf( () => { var target = pawn.jobs.curJob.GetTarget(MoppingInd); if (target.HasThing) { return true; } return target.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null; }, initExtractTargetFromQueue).JumpIfOutsideMopArea(MoppingInd, initExtractTargetFromQueue)); // モップ掛け作業中 var mopToil = new Toil { initAction = delegate { // 必要工数の計算 ticksLeftThisToil = MoppingTicks; }, // 細々とした設定 defaultCompleteMode = ToilCompleteMode.Delay }; mopToil.WithProgressBar(MoppingInd, () => 1f - ((float)ticksLeftThisToil / MoppingTicks), true); mopToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); // 掃除中に条件が変更されたら最初に戻る mopToil.JumpIf( () => { var target = pawn.jobs.curJob.GetTarget(MoppingInd); if (target.HasThing) { return(true); } return(target.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null); }, initExtractTargetFromQueue); mopToil.JumpIfOutsideMopArea(MoppingInd, initExtractTargetFromQueue); yield return(mopToil); // モップ掛け終了 var finishToil = new Toil { initAction = () => { // モップオブジェクト生成 var moppedThing = ThingMaker.MakeThing(MizuDef.Thing_MoppedThing); GenSpawn.Spawn(moppedThing, MoppingPos, mopToil.actor.Map); // モップから水を減らす var compTool = Mop.GetComp <CompWaterTool>(); compTool.StoredWaterVolume -= ConsumeWaterVolume; }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(finishToil); // 最初に戻る yield return(Toils_Jump.JumpIf( initExtractTargetFromQueue, () => pawn.jobs.curJob.GetTargetQueue(MoppingInd).Count > 0)); // モップを片付ける場所を決める yield return(Toils_Mizu.TryFindStoreCell(MopInd, MopPlaceInd)); // Toil startCarryToil = new Toil(); // startCarryToil.initAction = () => // { // var actor = startCarryToil.actor; // var curJob = actor.jobs.curJob; // IntVec3 c; // if (StoreUtility.TryFindBestBetterStoreCellFor(Mop, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out c)) // { // curJob.targetC = c; // curJob.count = 99999; // return; // } // }; // startCarryToil.defaultCompleteMode = ToilCompleteMode.Instant; // yield return startCarryToil; // 倉庫まで移動 yield return(Toils_Goto.GotoCell(MopPlaceInd, PathEndMode.Touch)); // 倉庫に置く yield return(Toils_Haul.PlaceHauledThingInCell(MopPlaceInd, null, true)); }
protected override IEnumerable <Toil> MakeNewToils() { // ツールまで移動 yield return(Toils_Goto.GotoThing(ToolInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(ToolInd)); // ツールを手に取る yield return(Toils_Haul.StartCarryThing(ToolInd)); // ターゲットが水やり対象として不適になっていたらリストから外す Toil initExtractTargetFromQueue = Toils_Mizu.ClearConditionSatisfiedTargets(WateringInd, (lti) => { var mapComp = this.Map.GetComponent <MapComponent_Watering>(); return(mapComp.Get(this.Map.cellIndices.CellToIndex(lti.Cell)) > 0); }); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(WateringInd)); // ターゲットキューから次のターゲットを取り出す yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(WateringInd, true)); // ターゲットの元へ移動 yield return(Toils_Goto.GotoCell(WateringInd, PathEndMode.Touch)); // 作業中 Toil workToil = new Toil(); workToil.initAction = delegate { // 必要工数の計算 this.ticksLeftThisToil = WorkingTicks; }; // 細々とした設定 workToil.defaultCompleteMode = ToilCompleteMode.Delay; workToil.WithProgressBar(WateringInd, () => 1f - (float)this.ticksLeftThisToil / WorkingTicks, true, -0.5f); workToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); yield return(workToil); // 作業終了 var finishToil = new Toil(); finishToil.initAction = () => { // 水やり更新 var mapComp = this.Map.GetComponent <MapComponent_Watering>(); mapComp.Set(this.Map.cellIndices.CellToIndex(WateringPos), MapComponent_Watering.MaxWateringValue); this.Map.mapDrawer.SectionAt(WateringPos).dirtyFlags = MapMeshFlag.Terrain; // ツールから水を減らす var compTool = Tool.GetComp <CompWaterTool>(); compTool.StoredWaterVolume -= ConsumeWaterVolume; }; finishToil.defaultCompleteMode = ToilCompleteMode.Instant; yield return(finishToil); // 最初に戻る yield return(Toils_Jump.JumpIf(initExtractTargetFromQueue, () => { return this.pawn.jobs.curJob.GetTargetQueue(WateringInd).Count > 0; })); // ツールを片付ける場所を決める 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() { // ターゲットがThing=水アイテムを摂取する場合 // 水(食事)が使用不可能になったらFail ToilFailConditions.FailOnDestroyedNullOrForbidden(this, WaterIndex); ToilFailConditions.FailOn(this, () => { if (this.Patient == null) { return(true); } // 患者がベッドに入ってなかったらFail if (!this.Patient.InBed()) { return(true); } // 到達不能になっていたらFail if (!this.pawn.CanReach(this.Patient, PathEndMode.ClosestTouch, Danger.Deadly)) { return(true); } return(false); }); // 水が予約出来ない状態なら中断 if (!ReservationUtility.CanReserveAndReach(this.pawn, this.TargetA, PathEndMode.Touch, Danger.Deadly, 1, this.job.count, null, false)) { this.GetActor().jobs.EndCurrentJob(JobCondition.Incompletable); yield break; } // 水を予約する if (!this.pawn.Map.reservationManager.ReservedBy(this.TargetA.Thing, pawn)) { yield return(Toils_Reserve.Reserve(WaterIndex, 1, this.job.count, null)); } if (this.getItemFromInventory) { // 水を持ち物から取り出す yield return(Toils_Mizu.StartCarryFromInventory(WaterIndex)); } else { // 水の場所まで行く yield return(Toils_Goto.Goto(WaterIndex, PathEndMode.OnCell)); // 水を拾う yield return(Toils_Ingest.PickupIngestible(WaterIndex, this.pawn)); } // 患者のもとへ移動 yield return(Toils_Goto.Goto(PatientIndex, PathEndMode.Touch)); // 水を飲ませる yield return(Toils_Mizu.FeedToPatient(WaterIndex, PatientIndex)); // 水の摂取終了(心情、食事の処理) yield return(Toils_Mizu.FinishDrinkPatient(WaterIndex, PatientIndex)); if (this.getItemFromInventory && !this.TargetA.ThingDestroyed) { // 所持品から取り出した&まだ残っている場合は所持品に戻す yield return(Toils_Mizu.AddCarriedThingToInventory()); } }
protected override IEnumerable <Toil> MakeNewToils() { // 水ツールを手に取る yield return(Toils_Goto.GotoThing(ToolInd, PathEndMode.Touch)); yield return(Toils_Haul.StartCarryThing(ToolInd)); // 水汲み設備へ移動 PathEndMode peMode = PathEndMode.ClosestTouch; if (SourceThing.def.hasInteractionCell) { peMode = PathEndMode.InteractionCell; } yield return(Toils_Goto.GotoThing(SourceInd, peMode)); // 水汲み Toil supplyToil = new Toil(); supplyToil.initAction = () => { var compSource = SourceThing.GetComp <CompWaterSource>(); this.needManipulate = compSource.NeedManipulate; // 水汲み速度関連はリファクタリングしたい var ticksForFull = compSource.BaseDrinkTicks; var compTool = Tool.GetComp <CompWaterTool>(); var totalTicks = (int)(ticksForFull * (1f - compTool.StoredWaterVolumePercent)); if (!needManipulate) { // 手が必要ない→水にドボンですぐに補給できる totalTicks /= 10; } // 小数の誤差を考慮して1Tick余分に多く実行する totalTicks += 1; this.maxTick = totalTicks; this.ticksLeftThisToil = totalTicks; }; supplyToil.tickAction = () => { var compSource = SourceThing.GetComp <CompWaterSource>(); var compTool = Tool.GetComp <CompWaterTool>(); var building = SourceThing as IBuilding_DrinkWater; var supplyWaterVolume = compTool.MaxWaterVolume / compSource.BaseDrinkTicks; if (!needManipulate) { supplyWaterVolume *= 10; } compTool.StoredWaterVolume += supplyWaterVolume; compTool.StoredWaterType = building.WaterType; building.DrawWater(supplyWaterVolume); if (building.IsEmpty) { this.ReadyForNextToil(); } }; supplyToil.defaultCompleteMode = ToilCompleteMode.Delay; supplyToil.WithProgressBar(SourceInd, () => 1f - (float)this.ticksLeftThisToil / this.maxTick, true, -0.5f); supplyToil.EndOnDespawnedOrNull(SourceInd); yield return(supplyToil); // 水ツールを戻す yield return(Toils_Mizu.TryFindStoreCell(ToolInd, StoreToolPosInd)); yield return(Toils_Goto.GotoCell(StoreToolPosInd, PathEndMode.OnCell)); yield return(Toils_Haul.PlaceHauledThingInCell(StoreToolPosInd, null, true)); }
protected override IEnumerable <Toil> MakeNewToils() { var ingList = job.GetTargetQueue(IngredientInd); var ingCountList = job.countQueue; // this.job.SetTarget(IngredientPlaceCellInd, this.TargetA.Thing.InteractionCell); var startToil = Toils_General.Do( () => { job.SetTarget(IngredientInd, ingList[0].Thing); job.count = ingCountList[0]; ingList.RemoveAt(0); ingCountList.RemoveAt(0); }); // 材料キューの先頭を取り出してセット yield return(startToil); // 材料の置き場所へ移動 var gotoToil = Toils_Goto.GotoThing(IngredientInd, PathEndMode.Touch); yield return(gotoToil); // 材料を運ぶ yield return(Toils_Haul.StartCarryThing(IngredientInd)); // 運ぶものリストの中に同種の材料があり、まだ物を持てる場合、設備へ持っていく前に取りに行く yield return(Toils_General.Do( () => { var actor = pawn; var curJob = actor.jobs.curJob; var targetQueue = curJob.GetTargetQueue(IngredientInd); if (targetQueue.NullOrEmpty()) { return; } if (curJob.count <= 0) { return; } if (actor.carryTracker.CarriedThing == null) { Log.Error( "JumpToAlsoCollectTargetInQueue run on " + actor + " who is not carrying something."); return; } if (actor.carryTracker.AvailableStackSpace(actor.carryTracker.CarriedThing.def) <= 0) { return; } for (var i = 0; i < targetQueue.Count; i++) { if (!GenAI.CanUseItemForWork(actor, targetQueue[i].Thing)) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } if (targetQueue[i].Thing.def != actor.carryTracker.CarriedThing.def) { continue; } curJob.SetTarget(IngredientInd, targetQueue[i].Thing); curJob.count = curJob.countQueue[i]; targetQueue.RemoveAt(i); curJob.countQueue.RemoveAt(i); actor.jobs.curDriver.JumpToToil(gotoToil); break; } })); // 運ぶ yield return(Toils_Haul.CarryHauledThingToCell(IngredientPlaceCellInd)); // 運んだものリスト(使用素材)に追加 yield return(Toils_Mizu.AddPlacedThing()); // 運んだものを置く yield return(Toils_Haul.PlaceCarriedThingInCellFacing(BillGiverInd)); // まだ材料があるならさらに運ぶ yield return(Toils_General.Do( () => { if (job.GetTargetQueue(IngredientInd).Count > 0) { pawn.jobs.curDriver.JumpToToil(startToil); } })); // レシピ実行 yield return(Toils_Recipe.DoRecipeWork()); // 水の注入完了処理 yield return(Toils_Mizu.FinishPourRecipe(BillGiverInd)); }
protected override IEnumerable <Toil> MakeNewToils() { // 患者の状態による失敗条件 // 死んだりいなくなったりしたら失敗 this.FailOnDespawnedNullOrForbidden(PatientInd); this.FailOn( () => { // 寝ていない状態になったら失敗 if (!WorkGiver_Tend.GoodLayingStatusForTend(Patient, pawn)) { return(true); } // 看護師と患者が同一人物だったら失敗 return(pawn == Patient); }); // 精神崩壊状態次第で失敗とする this.FailOnAggroMentalState(PatientInd); 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)); // 看病 var workToil = new Toil { initAction = () => // 必要工数の計算 ticksLeftThisToil = WorkTicks, // 細々とした設定 defaultCompleteMode = ToilCompleteMode.Delay }; workToil.WithProgressBar(PatientInd, () => 1f - ((float)ticksLeftThisToil / WorkTicks), true); workToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); yield return(workToil); // 看病完了時の処理 var finishToil = new Toil { 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; }, 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)); }