Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompAbilityEffect_DeleteTarget.cs
ProjectKoi-Kalo\Kalo 98a0400c78 WulaFallenEmpireSettings.cs - 添加了 public bool enableDebugLogs = false; 字段和保存配置
 WulaLog.cs - 修改了DebugEnabled属性,仅检查enableDebugLogs设置(不检查DevMode)
 WulaFallenEmpireMod.cs - 在DoSettingsWindowContents中添加了UI复选框,显示"Enable Debug Logs"选项
 替换了所有848个Log.Message/Error/Warning调用为WulaLog.Debug()
2025-12-15 13:05:50 +08:00

382 lines
13 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 Verse;
using UnityEngine;
using System.Collections.Generic;
using Verse.Sound;
using System.Reflection;
namespace WulaFallenEmpire
{
public class CompAbilityEffect_DeleteTarget : CompAbilityEffect
{
public new CompProperties_AbilityDeleteTarget Props => (CompProperties_AbilityDeleteTarget)props;
// 使用反射访问私有字段
private static FieldInfo thingIDField = typeof(Thing).GetField("thingIDNumber", BindingFlags.Instance | BindingFlags.NonPublic);
private static FieldInfo mapIndexField = typeof(Thing).GetField("mapIndexOrState", BindingFlags.Instance | BindingFlags.NonPublic);
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
if (parent.pawn == null || !target.IsValid)
return;
// 尝试删除任何东西,包括地形以外的所有对象
TryDeleteEverythingAt(target.Cell);
}
private void TryDeleteEverythingAt(IntVec3 cell)
{
Map map = parent.pawn.Map;
if (map == null)
return;
bool deletedSomething = false;
int deletionCount = 0;
try
{
// 获取该位置的所有物体(创建副本,因为我们要修改集合)
List<Thing> thingsAtCell = new List<Thing>(map.thingGrid.ThingsAt(cell));
foreach (Thing thing in thingsAtCell)
{
if (thing != null && CanAffectTarget(new LocalTargetInfo(thing)))
{
if (ForceRemoveThing(thing, map))
{
deletedSomething = true;
deletionCount++;
}
}
}
// 显示效果
if (deletedSomething && Props.showEffect)
{
ShowDeleteEffect(cell);
}
// 播放音效
if (deletedSomething && Props.soundEffect != null)
{
Props.soundEffect.PlayOneShot(new TargetInfo(cell, map));
}
WulaLog.Debug($"[DeleteTarget] Processed cell {cell}, deleted {deletionCount} objects");
}
catch (System.Exception ex)
{
WulaLog.Debug($"[DeleteTarget] Error deleting objects at {cell}: {ex}");
}
}
private bool CanAffectTarget(LocalTargetInfo target)
{
Thing thing = target.Thing;
if (thing == null)
return false;
// 调试模式如果设置了affectEverything忽略所有过滤
if (Props.affectEverything)
return true;
// 根据类型过滤
if (thing is Building && !Props.affectBuildings)
return false;
if (thing is Pawn && !Props.affectPawns)
return false;
if (thing is Plant && !Props.affectPlants)
return false;
if (thing.def.EverHaulable && !Props.affectItems)
return false;
if (thing is Filth && !Props.affectFilth)
return false;
if (thing is Blueprint && !Props.affectBlueprints)
return false;
if (thing is Frame && !Props.affectFrames)
return false;
if (thing is Corpse && !Props.affectCorpses)
return false;
if (thing is Building_Trap && !Props.affectMines)
return false;
return true;
}
private bool ForceRemoveThing(Thing thing, Map map)
{
string thingInfo = $"{thing.Label} ({thing.def.defName}) at {thing.Position}";
try
{
// 方法1: 尝试使用 DeSpawn
if (thing.Spawned)
{
thing.DeSpawn(DestroyMode.Vanish);
WulaLog.Debug($"[DeleteTarget] Method1 - DeSpawn: {thingInfo}");
return true;
}
}
catch (System.Exception ex1)
{
WulaLog.Debug($"[DeleteTarget] Method1 failed for {thingInfo}: {ex1}");
}
try
{
// 方法2: 直接操作 thingGrid使用反射
if (thing.Spawned)
{
ForceRemoveFromThingGrid(thing, map);
WulaLog.Debug($"[DeleteTarget] Method2 - ForceRemoveFromThingGrid: {thingInfo}");
return true;
}
}
catch (System.Exception ex2)
{
WulaLog.Debug($"[DeleteTarget] Method2 failed for {thingInfo}: {ex2}");
}
try
{
// 方法3: 使用反射设置内部状态
if (thing.Spawned)
{
ForceDespawnViaReflection(thing, map);
WulaLog.Debug($"[DeleteTarget] Method3 - ForceDespawnViaReflection: {thingInfo}");
return true;
}
}
catch (System.Exception ex3)
{
WulaLog.Debug($"[DeleteTarget] Method3 failed for {thingInfo}: {ex3}");
}
try
{
// 方法4: 最后的尝试 - 直接调用内部清理方法
if (thing.Spawned)
{
CallInternalCleanup(thing, map);
WulaLog.Debug($"[DeleteTarget] Method4 - CallInternalCleanup: {thingInfo}");
return true;
}
}
catch (System.Exception ex4)
{
WulaLog.Debug($"[DeleteTarget] Method4 failed for {thingInfo}: {ex4}");
}
WulaLog.Debug($"[DeleteTarget] All methods failed for: {thingInfo}");
return false;
}
private void ForceRemoveFromThingGrid(Thing thing, Map map)
{
try
{
// 使用反射调用 thingGrid 的内部移除方法
MethodInfo deregisterMethod = typeof(ThingGrid).GetMethod("Deregister", BindingFlags.Instance | BindingFlags.NonPublic);
if (deregisterMethod != null)
{
deregisterMethod.Invoke(map.thingGrid, new object[] { thing });
}
else
{
// 备用方法:手动从所有相关格子中移除
ManualRemoveFromGrid(thing, map);
}
}
catch (System.Exception ex)
{
WulaLog.Debug($"[DeleteTarget] ForceRemoveFromThingGrid failed: {ex}");
throw;
}
}
private void ManualRemoveFromGrid(Thing thing, Map map)
{
// 对于多格物体
if (thing.def.size != IntVec2.One)
{
foreach (IntVec3 cell in thing.OccupiedRect())
{
RemoveThingFromCell(thing, cell, map);
}
}
else
{
// 对于单格物体
RemoveThingFromCell(thing, thing.Position, map);
}
}
private void RemoveThingFromCell(Thing thing, IntVec3 cell, Map map)
{
try
{
// 使用反射访问 thingGrid 的 grid 字段
FieldInfo gridField = typeof(ThingGrid).GetField("grid", BindingFlags.Instance | BindingFlags.NonPublic);
if (gridField != null)
{
var grid = gridField.GetValue(map.thingGrid) as List<Thing>[];
if (grid != null && cell.InBounds(map))
{
int index = map.cellIndices.CellToIndex(cell);
if (index >= 0 && index < grid.Length)
{
grid[index]?.Remove(thing);
}
}
}
}
catch (System.Exception ex)
{
WulaLog.Debug($"[DeleteTarget] RemoveThingFromCell failed: {ex}");
}
}
private void ForceDespawnViaReflection(Thing thing, Map map)
{
try
{
// 设置 mapIndexOrState 为 -1未生成状态
if (mapIndexField != null)
{
mapIndexField.SetValue(thing, -1);
}
// 设置 spawned 为 false
FieldInfo spawnedField = typeof(Thing).GetField("spawned", BindingFlags.Instance | BindingFlags.NonPublic);
if (spawnedField != null)
{
spawnedField.SetValue(thing, false);
}
// 设置 destroyed 为 true
FieldInfo destroyedField = typeof(Thing).GetField("destroyed", BindingFlags.Instance | BindingFlags.NonPublic);
if (destroyedField != null)
{
destroyedField.SetValue(thing, true);
}
// 从地图列表中移除
MethodInfo notifyMethod = typeof(Map).GetMethod("Notify_ThingDespawned", BindingFlags.Instance | BindingFlags.NonPublic);
if (notifyMethod != null)
{
notifyMethod.Invoke(map, new object[] { thing });
}
}
catch (System.Exception ex)
{
WulaLog.Debug($"[DeleteTarget] ForceDespawnViaReflection failed: {ex}");
throw;
}
}
private void CallInternalCleanup(Thing thing, Map map)
{
try
{
// 调用 DeSpawn 方法的不同重载
MethodInfo despawnMethod = typeof(Thing).GetMethod("DeSpawn", new System.Type[] { });
if (despawnMethod != null)
{
despawnMethod.Invoke(thing, null);
}
// 确保从所有管理器中移除 - 修复版本
if (thing is Pawn pawn)
{
map.mapPawns.DeRegisterPawn(pawn); // 使用 DeRegisterPawn 而不是 RemovePawn
}
// 从动态绘制列表中移除
MethodInfo notifyDespawnedMethod = typeof(Map).GetMethod("Notify_ThingDespawned", BindingFlags.Instance | BindingFlags.NonPublic);
if (notifyDespawnedMethod != null)
{
notifyDespawnedMethod.Invoke(map, new object[] { thing });
}
}
catch (System.Exception ex)
{
WulaLog.Debug($"[DeleteTarget] CallInternalCleanup failed: {ex}");
throw;
}
}
private void ShowDeleteEffect(IntVec3 cell)
{
Map map = parent.pawn.Map;
// 使用自定义效果或默认效果
if (Props.effectFleck != null)
{
FleckMaker.Static(cell, map, Props.effectFleck);
}
else
{
// 默认效果:一个明显的闪光效果
FleckMaker.Static(cell, map, FleckDefOf.PsycastAreaEffect);
FleckMaker.ThrowLightningGlow(cell.ToVector3Shifted(), map, 2f);
// 添加更多效果使其更明显
for (int i = 0; i < 3; i++)
{
FleckMaker.ThrowSmoke(cell.ToVector3Shifted() + new Vector3(Rand.Range(-0.5f, 0.5f), 0, Rand.Range(-0.5f, 0.5f)), map, 1.5f);
}
}
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
if (!base.Valid(target, throwMessages))
return false;
// 调试模式:任何位置都有效
return true;
}
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
{
return "强制擦除模式: 删除所有对象(包括不可销毁的)";
}
// 绘制预览效果 - 显示大范围区域
public override void DrawEffectPreview(LocalTargetInfo target)
{
base.DrawEffectPreview(target);
if (parent.pawn == null || parent.pawn.Map == null || !target.IsValid)
return;
try
{
// 绘制3x3的预览区域
CellRect previewRect = CellRect.CenteredOn(target.Cell, 1);
foreach (IntVec3 cell in previewRect)
{
if (cell.InBounds(parent.pawn.Map))
{
GenDraw.DrawFieldEdges(new List<IntVec3> { cell }, Color.red, 0.8f);
}
}
}
catch (System.Exception)
{
// 忽略预览绘制错误
}
}
}
}