Files
ArachnaeSwarm/Source/ArachnaeSwarm/Building_Comps/ARA_Building_RefuelingVat/Building_RefuelingVat.cs
ProjectKoi-Kalo\Kalo 675ac8b298 创建了 ArachnaeSwarmSettings.cs - 包含 enableDebugLogs 字段
 创建了 ArachnaeLog.cs - 中央化日志类,仅检查mod设置(不检查DevMode)
 创建了 ArachnaeSwarmMod.cs - Mod主类,提供UI设置选项
 修改了 MainHarmony.cs - 移除重复的Harmony初始化(现在由ArachnaeSwarmMod处理)
 修改了 .csproj - 添加了3个新文件到编译列表
 替换了所有582个 Log.Message/Error/Warning 调用为 ArachnaeLog.Debug()
2025-12-15 13:11:45 +08:00

773 lines
30 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 RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public class Building_RefuelingVat : Building_Enterable, IThingHolder, IThingHolderWithDrawnPawn
{
private CompRefuelable cachedRefuelableComp;
private CompRefuelingVat cachedRefuelingVatComp;
private CompAutoEjector cachedAutoEjectorComp;
private Graphic cachedTopGraphic;
// 新增字段跟踪被建筑杀死的pawn
private HashSet<Pawn> pawnsKilledByVat = new HashSet<Pawn>();
// IThingHolderWithDrawnPawn implementation
public float HeldPawnDrawPos_Y => DrawPos.y + 0.03658537f;
public float HeldPawnBodyAngle => base.Rotation.AsAngle;
public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp;
// 从 Comp 中获取属性
public float FuelProductionPerDay => RefuelingVatComp?.FuelProductionPerDay ?? 10f;
public float FuelProductionEfficiency => RefuelingVatComp?.FuelProductionEfficiency ?? 1f;
private Graphic TopGraphic
{
get
{
if (cachedTopGraphic == null)
{
var modExtension = def.GetModExtension<DefModExtension_NutrientVat>();
if (modExtension != null && !modExtension.topGraphicPath.NullOrEmpty())
{
cachedTopGraphic = GraphicDatabase.Get(modExtension.graphicClass, modExtension.topGraphicPath, ShaderDatabase.Transparent, def.graphicData.drawSize, Color.white, Color.white);
}
}
return cachedTopGraphic;
}
}
public override Vector3 PawnDrawOffset => Vector3.zero;
public CompRefuelable RefuelableComp
{
get
{
if (cachedRefuelableComp == null)
{
cachedRefuelableComp = this.TryGetComp<CompRefuelable>();
}
return cachedRefuelableComp;
}
}
public CompRefuelingVat RefuelingVatComp
{
get
{
if (cachedRefuelingVatComp == null)
{
cachedRefuelingVatComp = this.TryGetComp<CompRefuelingVat>();
}
return cachedRefuelingVatComp;
}
}
public CompAutoEjector AutoEjectorComp
{
get
{
if (cachedAutoEjectorComp == null)
{
cachedAutoEjectorComp = this.TryGetComp<CompAutoEjector>();
}
return cachedAutoEjectorComp;
}
}
public bool HasFuelCapacity => RefuelableComp != null && RefuelableComp.Fuel < RefuelableComp.Props.fuelCapacity;
public bool IsFuelFull => RefuelableComp != null && RefuelableComp.Fuel >= RefuelableComp.Props.fuelCapacity;
// 燃料生产速率每Tick
public float FuelProductionPerTick
{
get
{
if (selectedPawn != null && base.Working)
{
return (FuelProductionPerDay * FuelProductionEfficiency) / 60000f;
}
return 0f;
}
}
// 酸蚀伤害间隔每6000 tick约1/10天
private const int AcidDamageInterval = 6000;
private Dictionary<Pawn, int> pawnTickCounters = new Dictionary<Pawn, int>();
// 安全字典操作方法
private bool SafeTryGetTickCount(Pawn pawn, out int tickCount)
{
if (pawn == null || pawn.Destroyed)
{
tickCount = 0;
return false;
}
return pawnTickCounters.TryGetValue(pawn, out tickCount);
}
private void SafeSetTickCount(Pawn pawn, int tickCount)
{
if (pawn != null && !pawn.Destroyed)
{
pawnTickCounters[pawn] = tickCount;
}
}
private void SafeRemoveFromDictionaries(Pawn pawn)
{
if (pawn != null)
{
pawnTickCounters.Remove(pawn);
pawnsKilledByVat.Remove(pawn);
}
}
private void CleanupInvalidDictionaryEntries()
{
// 清理无效的pawn引用
var invalidPawns = pawnTickCounters.Keys.Where(pawn => pawn == null || pawn.Destroyed).ToList();
foreach (var invalidPawn in invalidPawns)
{
pawnTickCounters.Remove(invalidPawn);
}
pawnsKilledByVat.RemoveWhere(pawn => pawn == null || pawn.Destroyed);
}
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
cachedRefuelableComp = this.TryGetComp<CompRefuelable>();
cachedRefuelingVatComp = this.TryGetComp<CompRefuelingVat>();
cachedAutoEjectorComp = this.TryGetComp<CompAutoEjector>();
// 确保字典不为null
pawnTickCounters ??= new Dictionary<Pawn, int>();
pawnsKilledByVat ??= new HashSet<Pawn>();
CleanupInvalidDictionaryEntries();
}
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
if (mode != DestroyMode.WillReplace)
{
if (selectedPawn != null && innerContainer.Contains(selectedPawn))
{
ArachnaeLog.Debug($"RefuelingVat despawned with pawn inside, forcing ejection.");
Finish(); // 使用修改后的Finish方法
}
}
// 清理字典
CleanupInvalidDictionaryEntries();
base.DeSpawn(mode);
}
private void ApplyAcidDamage(Pawn pawn)
{
try
{
if (pawn == null || pawn.Destroyed || pawn.Dead)
return;
BodyPartRecord targetPart = GetRandomVulnerablePart(pawn);
DamageDef acidDamageDef = DefDatabase<DamageDef>.GetNamed("AcidBurn") ?? DamageDefOf.Burn;
DamageInfo acidDamage = new DamageInfo(
acidDamageDef,
1.5f, // 每次1.5点伤害
2f, // 护甲穿透
-1f, // 随机角度
instigator: this, // 将建筑设为伤害来源
hitPart: targetPart
);
// 标记这个pawn将被建筑杀死
pawnsKilledByVat.Add(pawn);
// 应用伤害
pawn.TakeDamage(acidDamage);
// 立即检查pawn是否死亡
if (pawn.Dead)
{
HandlePawnDeath(pawn);
}
}
catch (Exception ex)
{
ArachnaeLog.Debug($"Error applying acid damage to {pawn}: {ex.Message}");
}
}
// 新增方法处理pawn死亡
private void HandlePawnDeath(Pawn pawn)
{
try
{
if (pawn == null || pawn.Destroyed)
return;
// 检查是否是被建筑杀死的
if (pawnsKilledByVat.Contains(pawn))
{
ArachnaeLog.Debug($"Pawn {pawn.Label} killed by RefuelingVat, destroying corpse.");
// 从容器中移除pawn
if (innerContainer.Contains(pawn))
{
innerContainer.Remove(pawn);
}
// 销毁pawn的尸体
if (!pawn.Destroyed)
{
pawn.Destroy();
}
// 从跟踪列表中移除
SafeRemoveFromDictionaries(pawn);
// 立即调用完成逻辑
if (selectedPawn == pawn)
{
selectedPawn = null;
startTick = -1;
}
return; // 直接返回,不执行后续弹出逻辑
}
}
catch (Exception ex)
{
ArachnaeLog.Debug($"Error handling pawn death for {pawn}: {ex}");
}
}
private BodyPartRecord GetRandomVulnerablePart(Pawn pawn)
{
if (pawn == null || pawn.Destroyed)
return null;
// 优先选择外部身体部位
var vulnerableParts = pawn.health.hediffSet.GetNotMissingParts()
.Where(part => part.depth == BodyPartDepth.Outside &&
!part.def.conceptual &&
part.def.hitPoints > 0)
.ToList();
return vulnerableParts.Count > 0 ?
vulnerableParts.RandomElement() :
pawn.RaceProps.body.corePart;
}
protected override void Tick()
{
base.Tick();
// 更严格的空值检查
if (selectedPawn == null || selectedPawn.Destroyed || !innerContainer.Contains(selectedPawn))
{
OnStop();
return;
}
if (base.Working && selectedPawn != null)
{
// 检查俘虏是否死亡 - 增加更严格的检查
if (selectedPawn.Dead || selectedPawn.Destroyed)
{
// 检查是否是被建筑杀死的
if (pawnsKilledByVat.Contains(selectedPawn))
{
HandlePawnDeath(selectedPawn);
}
else
{
Finish(); // 其他原因的死亡正常弹出
}
return;
}
// 酸蚀伤害逻辑 - 使用安全的方法
if (SafeTryGetTickCount(selectedPawn, out int tickCount))
{
tickCount++;
SafeSetTickCount(selectedPawn, tickCount);
if (tickCount >= AcidDamageInterval)
{
ApplyAcidDamage(selectedPawn);
// 检查pawn是否还存在可能在ApplyAcidDamage中被销毁
if (selectedPawn != null && !selectedPawn.Destroyed)
{
SafeSetTickCount(selectedPawn, 0);
}
}
}
else
{
SafeSetTickCount(selectedPawn, 0);
}
// 燃料生产逻辑
if (selectedPawn != null && HasFuelCapacity)
{
float fuelToAdd = FuelProductionPerTick;
RefuelableComp.Refuel(fuelToAdd);
}
}
}
public override AcceptanceReport CanAcceptPawn(Pawn pawn)
{
if (pawn == null || pawn.Destroyed)
return "Invalid pawn";
if (base.Working)
{
return "Occupied".Translate();
}
if (selectedPawn != null && selectedPawn != pawn)
{
return "WaitingForPawn".Translate(selectedPawn.Named("PAWN"));
}
// 禁止置入虫群成员
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker))
{
return "PawnIsHiveMember".Translate(pawn.Named("PAWN"));
}
// 允许殖民者、囚犯和奴隶
bool isColonist = pawn.IsColonist;
bool isPrisoner = pawn.IsPrisonerOfColony;
bool isSlave = pawn.IsSlaveOfColony;
// 允许殖民者、囚犯或奴隶,但不能是任务寄宿者
return (isColonist || isPrisoner || isSlave) && !pawn.IsQuestLodger();
}
public override void TryAcceptPawn(Pawn pawn)
{
if (pawn == null || pawn.Destroyed)
return;
if (!CanAcceptPawn(pawn).Accepted)
{
return;
}
selectedPawn = pawn;
bool deselected = pawn.DeSpawnOrDeselect();
if (innerContainer.TryAddOrTransfer(pawn))
{
startTick = Find.TickManager.TicksGame;
SafeSetTickCount(pawn, 0); // 初始化伤害计数器
// 确保pawn不在死亡跟踪列表中
pawnsKilledByVat.Remove(pawn);
}
if (deselected)
{
Find.Selector.Select(pawn, playSound: false, forceDesignatorDeselect: false);
}
}
private void Finish()
{
if (selectedPawn != null)
{
try
{
// 检查pawn是否还活着如果已经死亡且是被建筑杀死的则跳过弹出
if (selectedPawn.Dead && pawnsKilledByVat.Contains(selectedPawn))
{
HandlePawnDeath(selectedPawn);
return;
}
Notify_PawnRemoved();
bool ejected = false;
string ejectionMethod = "None";
// 方法1标准弹出 - 在交互单元格附近
if (innerContainer.Contains(selectedPawn) && !selectedPawn.Dead)
{
ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _);
if (ejected) ejectionMethod = "Standard";
}
// 方法2尝试随机相邻单元格
if (!ejected && innerContainer.Contains(selectedPawn) && !selectedPawn.Dead)
{
var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList();
if (adjacentCells.Count > 0)
{
IntVec3 randomCell = adjacentCells.RandomElement();
ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _);
if (ejected) ejectionMethod = "Adjacent";
}
}
// 方法3强制移除仅对活着的pawn
if (!ejected && innerContainer.Contains(selectedPawn) && !selectedPawn.Dead)
{
ArachnaeLog.Debug($"Forcing removal of pawn {selectedPawn} from RefuelingVat");
innerContainer.Remove(selectedPawn);
GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near);
ejected = true;
ejectionMethod = "Forced";
}
if (ejected)
{
ArachnaeLog.Debug($"Successfully ejected {selectedPawn} using method: {ejectionMethod}");
}
else if (!selectedPawn.Dead) // 只有活着的pawn弹出失败才报错
{
ArachnaeLog.Debug($"Failed to eject {selectedPawn} from RefuelingVat");
}
}
catch (Exception ex)
{
ArachnaeLog.Debug($"Error during Finish() for {selectedPawn}: {ex}");
}
finally
{
OnStop();
}
}
}
private void OnStop()
{
if (selectedPawn != null)
{
// 安全地从所有字典中移除
SafeRemoveFromDictionaries(selectedPawn);
// 确保pawn不在容器中除非是被建筑杀死的
if (innerContainer.Contains(selectedPawn) && !(selectedPawn.Dead && pawnsKilledByVat.Contains(selectedPawn)))
{
ArachnaeLog.Debug($"Pawn {selectedPawn} still in container during OnStop, forcing removal.");
innerContainer.Remove(selectedPawn);
}
}
selectedPawn = null;
startTick = -1;
}
private void Notify_PawnRemoved()
{
// 可以在这里添加音效
}
public override IEnumerable<Gizmo> GetGizmos()
{
// 原有的基础Gizmos
foreach (Gizmo gizmo in base.GetGizmos())
{
yield return gizmo;
}
if (base.Working)
{
}
else
{
// 选择殖民者的操作
var command_Action = new Command_Action
{
defaultLabel = "InsertPerson".Translate() + "...",
defaultDesc = "InsertPersonRefuelingVatDesc".Translate(),
icon = Building_GrowthVat.InsertPawnIcon.Texture,
action = () =>
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
{
if (p != null && !p.Destroyed && CanAcceptPawn(p).Accepted)
{
list.Add(new FloatMenuOption(p.LabelCap, () => SelectPawn(p), p, Color.white));
}
}
if (!list.Any())
{
list.Add(new FloatMenuOption("NoViablePawns".Translate(), null));
}
Find.WindowStack.Add(new FloatMenu(list));
}
};
if (!base.AnyAcceptablePawns)
{
command_Action.Disable("NoViablePawns".Translate());
}
yield return command_Action;
// 指派搬运囚犯/奴隶的操作
var command_CarryPrisoner = new Command_Action
{
defaultLabel = "AssignCarryPrisoner".Translate() + "...",
defaultDesc = "AssignCarryPrisonerDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Attack"),
action = () =>
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
// 获取所有可接受的囚犯和奴隶
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
{
if (p != null && !p.Destroyed && CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony))
{
list.Add(new FloatMenuOption(
p.LabelCap + " (" + (p.IsPrisonerOfColony ? "Prisoner" : "Slave") + ")",
() => AssignCarrierForPrisoner(p),
p,
Color.white
));
}
}
if (!list.Any())
{
list.Add(new FloatMenuOption("NoPrisonersOrSlaves".Translate(), null));
}
Find.WindowStack.Add(new FloatMenu(list));
}
};
// 检查是否有可用的囚犯/奴隶
bool hasPrisonersOrSlaves = base.Map.mapPawns.AllPawnsSpawned
.Any(p => p != null && !p.Destroyed && CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony));
if (!hasPrisonersOrSlaves)
{
command_CarryPrisoner.Disable("NoPrisonersOrSlaves".Translate());
}
yield return command_CarryPrisoner;
}
}
public override string GetInspectString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(base.GetInspectString());
if (base.Working && selectedPawn != null && !selectedPawn.Destroyed)
{
stringBuilder.AppendLineIfNotEmpty().Append("CasketContains".Translate().ToString() + ": " + selectedPawn.NameShortColored.Resolve());
// 显示燃料生产信息
if (HasFuelCapacity)
{
stringBuilder.AppendLineIfNotEmpty().Append("FuelProduction".Translate() + ": " + FuelProductionPerDay.ToString("F1") + " per day");
stringBuilder.AppendLineIfNotEmpty().Append("ProductionEfficiency".Translate() + ": " + FuelProductionEfficiency.ToStringPercent());
// 显示当前燃料状态
if (RefuelableComp != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("CurrentFuel".Translate() + ": " + RefuelableComp.Fuel.ToString("F1") + " / " + RefuelableComp.Props.fuelCapacity);
}
}
else
{
stringBuilder.AppendLineIfNotEmpty().Append("FuelTankFull".Translate());
}
// 显示酸蚀伤害信息
if (SafeTryGetTickCount(selectedPawn, out int tickCount))
{
float damageProgress = (float)tickCount / AcidDamageInterval;
stringBuilder.AppendLineIfNotEmpty().Append("AcidDamageProgress".Translate() + ": " + damageProgress.ToStringPercent());
}
}
else if (selectedPawn != null && !selectedPawn.Destroyed)
{
stringBuilder.AppendLineIfNotEmpty().Append("WaitingForPawn".Translate(selectedPawn.Named("PAWN")).Resolve());
}
else
{
// 显示空闲状态信息
stringBuilder.AppendLineIfNotEmpty().Append("RefuelingVatIdle".Translate());
if (RefuelableComp != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("CurrentFuel".Translate() + ": " + RefuelableComp.Fuel.ToString("F1") + " / " + RefuelableComp.Props.fuelCapacity);
}
}
return stringBuilder.ToString();
}
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn selPawn)
{
foreach (FloatMenuOption floatMenuOption in base.GetFloatMenuOptions(selPawn))
{
yield return floatMenuOption;
}
if (selPawn == null || selPawn.Destroyed)
yield break;
if (!selPawn.CanReach(this, PathEndMode.InteractionCell, Danger.Deadly))
{
yield return new FloatMenuOption("CannotEnterBuilding".Translate(this) + ": " + "NoPath".Translate().CapitalizeFirst(), null);
yield break;
}
AcceptanceReport acceptanceReport = CanAcceptPawn(selPawn);
if (acceptanceReport.Accepted)
{
yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("EnterBuilding".Translate(this), () => SelectPawn(selPawn)), selPawn, this);
}
else if (!acceptanceReport.Reason.NullOrEmpty())
{
yield return new FloatMenuOption("CannotEnterBuilding".Translate(this) + ": " + acceptanceReport.Reason.CapitalizeFirst(), null);
}
}
public override void DynamicDrawPhaseAt(DrawPhase phase, Vector3 drawLoc, bool flip = false)
{
if (base.Working && selectedPawn != null && !selectedPawn.Destroyed && innerContainer.Contains(selectedPawn))
{
selectedPawn.Drawer.renderer.DynamicDrawPhaseAt(phase, drawLoc + PawnDrawOffset, null, neverAimWeapon: true);
}
base.DynamicDrawPhaseAt(phase, drawLoc, flip);
}
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
base.DrawAt(drawLoc, flip);
// 绘制顶部图形
if (TopGraphic != null)
{
TopGraphic.Draw(DrawPos + Altitudes.AltIncVect * 2f, base.Rotation, this);
}
}
public Job CreateCarryJobForPrisoner(Pawn prisoner, Pawn carrier)
{
if (prisoner == null || prisoner.Destroyed || carrier == null || carrier.Destroyed)
return null;
if (!CanAcceptPawn(prisoner).Accepted)
return null;
// 创建搬运工作定义 - 使用新的 JobDef
JobDef carryJobDef = DefDatabase<JobDef>.GetNamed("ARA_CarryPrisonerToRefuelingVat");
if (carryJobDef == null)
{
ArachnaeLog.Debug("ARA_CarryPrisonerToRefuelingVat JobDef not found!");
return null;
}
Job job = JobMaker.MakeJob(carryJobDef, prisoner, this);
job.count = 1;
return job;
}
public IEnumerable<Pawn> GetAvailableCarriers()
{
foreach (Pawn pawn in base.Map.mapPawns.AllPawnsSpawned)
{
if (pawn == null || pawn.Destroyed)
continue;
// 检查是否是虫群成员
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster))
{
// 检查是否能够工作且不是囚犯
if (pawn.workSettings != null && pawn.workSettings.WorkIsActive(WorkTypeDefOf.Hauling) &&
!pawn.Downed && !pawn.IsPrisoner && pawn.CanReach(this, PathEndMode.InteractionCell, Danger.Some))
{
yield return pawn;
}
}
}
}
public void AssignCarrierForPrisoner(Pawn prisoner)
{
if (prisoner == null || prisoner.Destroyed)
return;
// 获取可用的搬运者
var availableCarriers = GetAvailableCarriers().ToList();
if (!availableCarriers.Any())
{
Messages.Message("NoAvailableHiveCarriers".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 创建浮动菜单选择搬运者
List<FloatMenuOption> options = new List<FloatMenuOption>();
foreach (Pawn carrier in availableCarriers)
{
if (carrier == null || carrier.Destroyed)
continue;
options.Add(new FloatMenuOption(
carrier.LabelCap,
() =>
{
Job carryJob = CreateCarryJobForPrisoner(prisoner, carrier);
if (carryJob != null)
{
carrier.jobs.TryTakeOrderedJob(carryJob, JobTag.MiscWork);
Messages.Message("CarrierAssigned".Translate(carrier.LabelShort, prisoner.LabelShort), MessageTypeDefOf.NeutralEvent);
}
},
carrier,
Color.white
));
}
if (options.Any())
{
Find.WindowStack.Add(new FloatMenu(options));
}
else
{
Messages.Message("NoAvailableCarriers".Translate(), MessageTypeDefOf.RejectInput);
}
}
// 保存和加载数据
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref pawnTickCounters, "pawnTickCounters", LookMode.Reference, LookMode.Value);
Scribe_Collections.Look(ref pawnsKilledByVat, "pawnsKilledByVat", LookMode.Reference);
// 确保集合不为null
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
pawnsKilledByVat ??= new HashSet<Pawn>();
pawnTickCounters ??= new Dictionary<Pawn, int>();
// 更严格的清理可能已销毁的pawn引用
CleanupInvalidDictionaryEntries();
// 如果selectedPawn无效重置状态
if (selectedPawn != null && (selectedPawn.Destroyed || selectedPawn.Dead))
{
SafeRemoveFromDictionaries(selectedPawn);
selectedPawn = null;
startTick = -1;
}
}
}
}
}