fix(Maintenance): 在 WorkGiver 中增加零部件消耗检查并修复注释乱码

This commit is contained in:
2025-12-14 12:50:59 +08:00
parent a608bd5586
commit 865bd922b2
3 changed files with 64 additions and 52 deletions

View File

@@ -16,24 +16,24 @@ namespace WulaFallenEmpire
public SoundDef exitSound; public SoundDef exitSound;
public EffecterDef operatingEffecter; public EffecterDef operatingEffecter;
// 时间相关 // 时间相关
public int baseDurationTicks = 60000; // 基础维护时间1天 public int baseDurationTicks = 60000; // 基础维护时间1天
public float ticksPerNeedLevel = 120000f; // 每点需求降低需要的时间 public float ticksPerNeedLevel = 120000f; // 每点需求降低需要的时间
// 电力消耗 // 电力消耗
public float powerConsumptionRunning = 250f; public float powerConsumptionRunning = 250f;
public float powerConsumptionIdle = 50f; public float powerConsumptionIdle = 50f;
// 组件消耗 // 组件消耗
public float componentCostPerNeedLevel = 2f; public float componentCostPerNeedLevel = 2f;
public int baseComponentCost = 1; public int baseComponentCost = 1;
// 维护效果 // 维护效果
public float minNeedLevelToMaintain = 0.3f; // 低于此值才需要维护 public float minNeedLevelToMaintain = 0.3f; // 低于此值才需要维护
public float needLevelAfterCycle = 1.0f; // 维护后的需求水平 public float needLevelAfterCycle = 1.0f; // 维护后的需求水平
public bool healInjuries = true; // 是否治疗损伤 public bool healInjuries = true; // 是否治疗损伤
public bool healMissingParts = true; // 是否修复缺失部位 public bool healMissingParts = true; // 是否修复缺失部位
public int maxInjuriesHealedPerCycle = 5; // 每次维护最多治疗的损伤数量 public int maxInjuriesHealedPerCycle = 5; // 每次维护最多治疗的损伤数量
public CompProperties_MaintenancePod() public CompProperties_MaintenancePod()
{ {
compClass = typeof(CompMaintenancePod); compClass = typeof(CompMaintenancePod);
@@ -57,20 +57,18 @@ namespace WulaFallenEmpire
public MaintenancePodState State => state; public MaintenancePodState State => state;
public Pawn Occupant => innerContainer.FirstOrDefault() as Pawn; public Pawn Occupant => innerContainer.FirstOrDefault() as Pawn;
public bool PowerOn => powerComp != null && powerComp.PowerOn; public bool PowerOn => powerComp != null && powerComp.PowerOn;
public float RequiredComponents public float RequiredComponents => GetRequiredComponentsFor(Occupant);
public float GetRequiredComponentsFor(Pawn pawn)
{ {
get if (pawn == null) return Props.baseComponentCost;
{
var occupant = Occupant;
if (occupant == null) return Props.baseComponentCost;
var maintenanceNeed = occupant.needs?.TryGetNeed<Need_Maintenance>(); var maintenanceNeed = pawn.needs?.TryGetNeed<Need_Maintenance>();
if (maintenanceNeed == null) return Props.baseComponentCost; if (maintenanceNeed == null) return Props.baseComponentCost;
// 计算基于当前需求水平的组件需求 // 计算基于当前需求水平的组件需求
float needDeficit = 1.0f - maintenanceNeed.CurLevel; float needDeficit = 1.0f - maintenanceNeed.CurLevel;
return Props.baseComponentCost + (needDeficit * Props.componentCostPerNeedLevel); return Props.baseComponentCost + (needDeficit * Props.componentCostPerNeedLevel);
}
} }
public int RequiredDuration public int RequiredDuration
{ {
@@ -82,7 +80,7 @@ namespace WulaFallenEmpire
var maintenanceNeed = occupant.needs?.TryGetNeed<Need_Maintenance>(); var maintenanceNeed = occupant.needs?.TryGetNeed<Need_Maintenance>();
if (maintenanceNeed == null) return Props.baseDurationTicks; if (maintenanceNeed == null) return Props.baseDurationTicks;
// 计算基于当前需求水平的维护时间 // 计算基于当前需求水平的维护时间
float needDeficit = 1.0f - maintenanceNeed.CurLevel; float needDeficit = 1.0f - maintenanceNeed.CurLevel;
return Props.baseDurationTicks + (int)(needDeficit * Props.ticksPerNeedLevel); return Props.baseDurationTicks + (int)(needDeficit * Props.ticksPerNeedLevel);
} }
@@ -127,17 +125,17 @@ namespace WulaFallenEmpire
{ {
base.CompTick(); base.CompTick();
if (!parent.Spawned) return; if (!parent.Spawned) return;
// 更新电力消耗 // 更新电力消耗
if (powerComp != null) if (powerComp != null)
{ {
powerComp.PowerOutput = -(state == MaintenancePodState.Running ? Props.powerConsumptionRunning : Props.powerConsumptionIdle); powerComp.PowerOutput = -(state == MaintenancePodState.Running ? Props.powerConsumptionRunning : Props.powerConsumptionIdle);
} }
// 运行维护周期 // 运行维护周期
if (state == MaintenancePodState.Running && PowerOn) if (state == MaintenancePodState.Running && PowerOn)
{ {
ticksRemaining--; ticksRemaining--;
// 更新效果器 // 更新效果器
if (Props.operatingEffecter != null) if (Props.operatingEffecter != null)
{ {
if (operatingEffecter == null) if (operatingEffecter == null)
@@ -160,29 +158,29 @@ namespace WulaFallenEmpire
public void StartCycle(Pawn pawn) public void StartCycle(Pawn pawn)
{ {
if (pawn == null) return; if (pawn == null) return;
// 检查组件是否足够 // 检查组件是否足够
float requiredComponents = RequiredComponents; float requiredComponents = RequiredComponents;
if (refuelableComp.Fuel < requiredComponents) if (refuelableComp.Fuel < requiredComponents)
{ {
Messages.Message("WULA_MaintenancePod_NotEnoughComponents".Translate(requiredComponents.ToString("F0")), MessageTypeDefOf.RejectInput); Messages.Message("WULA_MaintenancePod_NotEnoughComponents".Translate(requiredComponents.ToString("F0")), MessageTypeDefOf.RejectInput);
return; return;
} }
// 消耗组件 // 消耗组件
if (requiredComponents > 0) if (requiredComponents > 0)
{ {
refuelableComp.ConsumeFuel(requiredComponents); refuelableComp.ConsumeFuel(requiredComponents);
} }
// 将 pawn 放入容器 // 将 pawn 放入容器
if (pawn.Spawned) if (pawn.Spawned)
{ {
pawn.DeSpawn(DestroyMode.Vanish); pawn.DeSpawn(DestroyMode.Vanish);
} }
innerContainer.TryAddOrTransfer(pawn); innerContainer.TryAddOrTransfer(pawn);
// 开始维护周期 // 开始维护周期
state = MaintenancePodState.Running; state = MaintenancePodState.Running;
ticksRemaining = RequiredDuration; ticksRemaining = RequiredDuration;
// 播放进入音效 // 播放进入音效
if (Props.enterSound != null) if (Props.enterSound != null)
{ {
Props.enterSound.PlayOneShot(new TargetInfo(parent.Position, parent.Map)); Props.enterSound.PlayOneShot(new TargetInfo(parent.Position, parent.Map));
@@ -197,10 +195,10 @@ namespace WulaFallenEmpire
state = MaintenancePodState.Idle; state = MaintenancePodState.Idle;
return; return;
} }
// 执行维护效果 // 执行维护效果
PerformMaintenanceEffects(occupant); PerformMaintenanceEffects(occupant);
// 弹出 pawn // 弹出 pawn
EjectPawn(); EjectPawn();
Messages.Message("WULA_MaintenanceCycleComplete".Translate(occupant.LabelShortCap), MessageTypeDefOf.PositiveEvent); Messages.Message("WULA_MaintenanceCycleComplete".Translate(occupant.LabelShortCap), MessageTypeDefOf.PositiveEvent);
@@ -209,17 +207,17 @@ namespace WulaFallenEmpire
{ {
var maintenanceNeed = pawn.needs?.TryGetNeed<Need_Maintenance>(); var maintenanceNeed = pawn.needs?.TryGetNeed<Need_Maintenance>();
// 1. 恢复维护需求 // 1. 恢复维护需求
if (maintenanceNeed != null) if (maintenanceNeed != null)
{ {
maintenanceNeed.PerformMaintenance(Props.needLevelAfterCycle); maintenanceNeed.PerformMaintenance(Props.needLevelAfterCycle);
} }
// 2. 治疗损伤(如果启用) // 2. 治疗损伤(如果启用)
if (Props.healInjuries) if (Props.healInjuries)
{ {
HealInjuries(pawn); HealInjuries(pawn);
} }
// 3. 修复缺失部位(如果启用) // 3. 修复缺失部位(如果启用)
if (Props.healMissingParts) if (Props.healMissingParts)
{ {
HealMissingParts(pawn); HealMissingParts(pawn);
@@ -249,7 +247,7 @@ namespace WulaFallenEmpire
int partsHealed = 0; int partsHealed = 0;
foreach (var missingPart in missingParts) foreach (var missingPart in missingParts)
{ {
if (partsHealed >= 1) // 每次最多修复一个缺失部位 if (partsHealed >= 1) // 每次最多修复一个缺失部位
break; break;
pawn.health.RemoveHediff(missingPart); pawn.health.RemoveHediff(missingPart);
partsHealed++; partsHealed++;
@@ -264,15 +262,15 @@ namespace WulaFallenEmpire
var occupant = Occupant; var occupant = Occupant;
if (occupant != null) if (occupant != null)
{ {
// 弹出到交互单元格 // 弹出到交互单元格
innerContainer.TryDropAll(parent.InteractionCell, parent.Map, ThingPlaceMode.Near); innerContainer.TryDropAll(parent.InteractionCell, parent.Map, ThingPlaceMode.Near);
// 播放退出音效 // 播放退出音效
if (Props.exitSound != null) if (Props.exitSound != null)
{ {
Props.exitSound.PlayOneShot(new TargetInfo(parent.Position, parent.Map)); Props.exitSound.PlayOneShot(new TargetInfo(parent.Position, parent.Map));
} }
// 如果被中断,应用负面效果 // 如果被中断,应用负面效果
if (interrupted) if (interrupted)
{ {
occupant.needs?.mood?.thoughts?.memories?.TryGainMemory(ThoughtDefOf.SoakingWet); occupant.needs?.mood?.thoughts?.memories?.TryGainMemory(ThoughtDefOf.SoakingWet);
@@ -281,7 +279,7 @@ namespace WulaFallenEmpire
innerContainer.Clear(); innerContainer.Clear();
state = MaintenancePodState.Idle; state = MaintenancePodState.Idle;
// 清理效果器 // 清理效果器
if (operatingEffecter != null) if (operatingEffecter != null)
{ {
operatingEffecter.Cleanup(); operatingEffecter.Cleanup();
@@ -300,7 +298,7 @@ namespace WulaFallenEmpire
var maintenanceNeed = Occupant.needs?.TryGetNeed<Need_Maintenance>(); var maintenanceNeed = Occupant.needs?.TryGetNeed<Need_Maintenance>();
if (maintenanceNeed != null) if (maintenanceNeed != null)
{ {
// 直接显示 CurLevel确保与 Need 显示一致 // 直接显示 CurLevel确保与 Need 显示一致
sb.AppendLine("WULA_MaintenanceLevel".Translate() + ": " + maintenanceNeed.CurLevel.ToStringPercent()); sb.AppendLine("WULA_MaintenanceLevel".Translate() + ": " + maintenanceNeed.CurLevel.ToStringPercent());
} }
} }
@@ -316,7 +314,7 @@ namespace WulaFallenEmpire
{ {
yield return gizmo; yield return gizmo;
} }
// 进入维护舱的按钮 // 进入维护舱的按钮
if (state == MaintenancePodState.Idle && PowerOn) if (state == MaintenancePodState.Idle && PowerOn)
{ {
yield return new Command_Action yield return new Command_Action
@@ -327,7 +325,7 @@ namespace WulaFallenEmpire
action = () => ShowPawnSelectionMenu() action = () => ShowPawnSelectionMenu()
}; };
} }
// 取消维护的按钮 // 取消维护的按钮
if (state == MaintenancePodState.Running) if (state == MaintenancePodState.Running)
{ {
yield return new Command_Action yield return new Command_Action
@@ -362,19 +360,19 @@ namespace WulaFallenEmpire
foreach (var pawn in map.mapPawns.AllPawnsSpawned) foreach (var pawn in map.mapPawns.AllPawnsSpawned)
{ {
// 首先检查是否有维护需求 // 首先检查是否有维护需求
var maintenanceNeed = pawn.needs?.TryGetNeed<Need_Maintenance>(); var maintenanceNeed = pawn.needs?.TryGetNeed<Need_Maintenance>();
if (maintenanceNeed == null) if (maintenanceNeed == null)
{ {
// 这个Pawn没有维护需求跳过 // 这个Pawn没有维护需求跳过
continue; continue;
} }
// 检查是否真的需要维护 // 检查是否真的需要维护
if (maintenanceNeed.CurLevel > Props.minNeedLevelToMaintain && !DebugSettings.godMode) if (maintenanceNeed.CurLevel > Props.minNeedLevelToMaintain && !DebugSettings.godMode)
continue; continue;
// 创建选项 // 创建选项
var option = CreatePawnOption(pawn, maintenanceNeed); var option = CreatePawnOption(pawn, maintenanceNeed);
if (option != null) if (option != null)
options.Add(option); options.Add(option);
@@ -387,12 +385,12 @@ namespace WulaFallenEmpire
{ {
string label = $"{pawn.LabelShortCap} ({need.CurLevel.ToStringPercent()})"; string label = $"{pawn.LabelShortCap} ({need.CurLevel.ToStringPercent()})";
float requiredComponents = RequiredComponents; float requiredComponents = RequiredComponents;
// 检查组件是否足够 // 检查组件是否足够
if (refuelableComp.Fuel < requiredComponents) if (refuelableComp.Fuel < requiredComponents)
{ {
return new FloatMenuOption(label + " (" + "WULA_MaintenancePod_NotEnoughComponents".Translate(requiredComponents.ToString("F0")) + ")", null); return new FloatMenuOption(label + " (" + "WULA_MaintenancePod_NotEnoughComponents".Translate(requiredComponents.ToString("F0")) + ")", null);
} }
// 检查是否可以到达 // 检查是否可以到达
if (!pawn.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) if (!pawn.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly))
{ {
return new FloatMenuOption(label + " (" + "CannotReach".Translate() + ")", null); return new FloatMenuOption(label + " (" + "CannotReach".Translate() + ")", null);
@@ -401,7 +399,7 @@ namespace WulaFallenEmpire
{ {
if (pawn.Downed || !pawn.IsFreeColonist) if (pawn.Downed || !pawn.IsFreeColonist)
{ {
// 需要搬运 // 需要搬运
var haulJob = JobMaker.MakeJob(JobDefOf_WULA.WULA_HaulToMaintenancePod, pawn, parent); var haulJob = JobMaker.MakeJob(JobDefOf_WULA.WULA_HaulToMaintenancePod, pawn, parent);
var hauler = FindBestHauler(pawn); var hauler = FindBestHauler(pawn);
if (hauler != null) if (hauler != null)
@@ -415,7 +413,7 @@ namespace WulaFallenEmpire
} }
else else
{ {
// 自己进入 // 自己进入
var enterJob = JobMaker.MakeJob(JobDefOf_WULA.WULA_EnterMaintenancePod, parent); var enterJob = JobMaker.MakeJob(JobDefOf_WULA.WULA_EnterMaintenancePod, parent);
pawn.jobs.TryTakeOrderedJob(enterJob); pawn.jobs.TryTakeOrderedJob(enterJob);
} }

View File

@@ -22,6 +22,20 @@ namespace WulaFallenEmpire
if (podComp == null || podComp.State != MaintenancePodState.Idle || !podComp.PowerOn) if (podComp == null || podComp.State != MaintenancePodState.Idle || !podComp.PowerOn)
return false; return false;
// 检查是否有足够的燃料(零部件)
// 如果是强制工作(玩家右键),我们允许通过检查,让 JobDriver 去处理(可能会提示燃料不足)
// 这样玩家能知道为什么不能工作,而不是默默失败
if (!forced)
{
float requiredFuel = podComp.GetRequiredComponentsFor(pawn);
var refuelable = t.TryGetComp<CompRefuelable>();
if (refuelable != null && refuelable.Fuel < requiredFuel)
{
JobFailReason.Is("WULA_MaintenancePod_NotEnoughComponents".Translate(requiredFuel.ToString("F0")));
return false;
}
}
// 检查当前pawn是否有维护需求且需要维护 // 检查当前pawn是否有维护需求且需要维护
return PawnNeedsMaintenance(pawn); return PawnNeedsMaintenance(pawn);
} }