Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/JobDriver_FeedWulaPatient.cs
2025-07-22 16:36:01 +08:00

140 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
using Verse;
using Verse.AI;
using RimWorld;
namespace WulaFallenEmpire
{
public class JobDriver_FeedWulaPatient : JobDriver
{
private const TargetIndex FoodSourceInd = TargetIndex.A;
private const TargetIndex PatientInd = TargetIndex.B;
private Thing FoodSource => job.GetTarget(FoodSourceInd).Thing;
private Pawn Patient => (Pawn)job.GetTarget(PatientInd).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
// 预留食物来源和病患
if (!pawn.Reserve(FoodSource, job, 1, -1, null, errorOnFailed))
{
return false;
}
if (!pawn.Reserve(Patient, job, 1, -1, null, errorOnFailed))
{
return false;
}
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
// 失败条件:如果病患被摧毁、为空或不在床上
this.FailOn(() => Patient.DestroyedOrNull());
this.FailOn(() => !Patient.InBed());
// Toil 0: 检查医生库存中是否有能量核心
Toil checkInventoryToil = ToilMaker.MakeToil("CheckInventory");
checkInventoryToil.initAction = delegate
{
Thing inventoryFood = null;
foreach (Thing t in pawn.inventory.innerContainer)
{
ThingDefExtension_EnergySource energySourceExt = t.def.GetModExtension<ThingDefExtension_EnergySource>();
if (energySourceExt != null && t.IngestibleNow)
{
inventoryFood = t;
break;
}
}
if (inventoryFood != null)
{
// 如果库存中有食物则将Job的目标设置为库存食物并跳过拾取步骤直接前往病患
job.SetTarget(FoodSourceInd, inventoryFood);
pawn.jobs.curDriver.JumpToToil(Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch)); // 跳转到前往病患的Toil
}
// 如果库存中没有则继续执行下一个Toil前往地图上的食物来源
};
yield return checkInventoryToil;
// Toil 1: 前往食物来源 (如果库存中没有则执行此Toil)
yield return Toils_Goto.GotoThing(FoodSourceInd, PathEndMode.ClosestTouch)
.FailOnDespawnedNullOrForbidden(FoodSourceInd)
.FailOn(() => !pawn.CanReserve(FoodSource, 1, -1, null, false)); // 在这里预留食物来源
// Toil 2: 拾取食物来源 (如果库存中没有则执行此Toil)
yield return Toils_Haul.StartCarryThing(FoodSourceInd); // 使用 StartCarryThing 拾取物品
// Toil 3: 前往病患
yield return Toils_Goto.GotoThing(PatientInd, PathEndMode.Touch)
.FailOnDespawnedOrNull(PatientInd);
// Toil 4: 喂食病患
Toil feedToil = ToilMaker.MakeToil("FeedWulaPatient");
feedToil.initAction = delegate
{
Pawn actor = feedToil.actor;
Thing food = actor.carryTracker.CarriedThing; // 医生携带的食物 (从地图拾取)
// 如果医生没有携带食物,检查是否在库存中 (从库存获取)
if (food == null)
{
food = job.GetTarget(FoodSourceInd).Thing; // 此时FoodSourceInd应该指向库存中的物品
if (food == null || !actor.inventory.innerContainer.Contains(food))
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
return;
}
}
// 获取乌拉能量需求
Need_WulaEnergy energyNeed = Patient.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 检查食物来源是否有自定义能量扩展
ThingDefExtension_EnergySource ext = food.def.GetModExtension<ThingDefExtension_EnergySource>();
if (ext == null)
{
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 补充乌拉的能量
energyNeed.CurLevel += ext.energyAmount;
// 消耗物品
if (actor.carryTracker.CarriedThing == food) // 如果是携带的物品
{
food.Destroy(DestroyMode.Vanish); // 销毁医生携带的物品
actor.carryTracker.innerContainer.ClearAndDestroyContents(); // 移除医生携带的物品
}
else if (actor.inventory.innerContainer.Contains(food)) // 如果是库存中的物品
{
food.stackCount--; // 减少库存物品数量
if (food.stackCount <= 0)
{
food.Destroy(DestroyMode.Vanish); // 如果数量为0销毁物品
}
}
else
{
// 理论上不应该发生
actor.jobs.EndCurrentJob(JobCondition.Errored);
return;
}
// 记录能量摄入 (可选)
// Patient.records.AddTo(RecordDefOf.NutritionEaten, ext.energyAmount);
};
feedToil.defaultCompleteMode = ToilCompleteMode.Instant;
yield return feedToil;
}
}
}