Exemple #1
0
 public static Toil FinishDrink(TargetIndex thingIndex)
 {
     return(Toils_Mizu.FinishDrinkSomeone(thingIndex, (toil) =>
     {
         return toil.actor;
     }));
 }
Exemple #2
0
        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));
        }
Exemple #4
0
        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;
            }));
        }
Exemple #5
0
 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));
        }
Exemple #7
0
        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;
                };
            }));
        }
Exemple #8
0
        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));
        }
Exemple #9
0
        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));
        }
Exemple #11
0
        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));
        }
Exemple #14
0
        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));
        }