diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Manpack_Weapon.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Manpack_Weapon.xml index d5ed7e33..64726bb6 100644 --- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Manpack_Weapon.xml +++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Manpack_Weapon.xml @@ -2090,7 +2090,7 @@ - + + + WULA_RW_Auto_GL_Smoke_Ability + + 使得目标立刻被放逐——无视一切保护措施,将其从存档中永远擦除。 + Wula/UI/Abilities/WULA_RW_Auto_GL_Smoke_Ability + True + False + Misc11 + false + 3 + true + 1 + + 35 + + + Verb_CastAbility + 500 + 0.25 + 9 + true + Pawn_Mech_Apocriton_Death + false + + + true + false + true + true + true + + + +
  • + true + false + +
  • +
    \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompAbilityEffect_DeleteTarget.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompAbilityEffect_DeleteTarget.cs new file mode 100644 index 00000000..2b16dabf --- /dev/null +++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompAbilityEffect_DeleteTarget.cs @@ -0,0 +1,381 @@ +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 thingsAtCell = new List(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)); + } + + Log.Message($"[DeleteTarget] Processed cell {cell}, deleted {deletionCount} objects"); + } + catch (System.Exception ex) + { + Log.Error($"[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); + Log.Message($"[DeleteTarget] Method1 - DeSpawn: {thingInfo}"); + return true; + } + } + catch (System.Exception ex1) + { + Log.Warning($"[DeleteTarget] Method1 failed for {thingInfo}: {ex1}"); + } + + try + { + // 方法2: 直接操作 thingGrid(使用反射) + if (thing.Spawned) + { + ForceRemoveFromThingGrid(thing, map); + Log.Message($"[DeleteTarget] Method2 - ForceRemoveFromThingGrid: {thingInfo}"); + return true; + } + } + catch (System.Exception ex2) + { + Log.Warning($"[DeleteTarget] Method2 failed for {thingInfo}: {ex2}"); + } + + try + { + // 方法3: 使用反射设置内部状态 + if (thing.Spawned) + { + ForceDespawnViaReflection(thing, map); + Log.Message($"[DeleteTarget] Method3 - ForceDespawnViaReflection: {thingInfo}"); + return true; + } + } + catch (System.Exception ex3) + { + Log.Warning($"[DeleteTarget] Method3 failed for {thingInfo}: {ex3}"); + } + + try + { + // 方法4: 最后的尝试 - 直接调用内部清理方法 + if (thing.Spawned) + { + CallInternalCleanup(thing, map); + Log.Message($"[DeleteTarget] Method4 - CallInternalCleanup: {thingInfo}"); + return true; + } + } + catch (System.Exception ex4) + { + Log.Warning($"[DeleteTarget] Method4 failed for {thingInfo}: {ex4}"); + } + + Log.Error($"[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) + { + Log.Warning($"[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[]; + 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) + { + Log.Warning($"[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) + { + Log.Warning($"[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) + { + Log.Warning($"[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 { cell }, Color.red, 0.8f); + } + } + } + catch (System.Exception) + { + // 忽略预览绘制错误 + } + } + } +} diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompProperties_AbilityDeleteTarget.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompProperties_AbilityDeleteTarget.cs new file mode 100644 index 00000000..879e46e6 --- /dev/null +++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityDeleteTarget/CompProperties_AbilityDeleteTarget.cs @@ -0,0 +1,28 @@ +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + public class CompProperties_AbilityDeleteTarget : CompProperties_AbilityEffect + { + public bool affectBuildings = true; + public bool affectPawns = true; + public bool affectItems = true; + public bool affectPlants = true; + public bool affectFilth = true; + public bool affectBlueprints = true; + public bool affectFrames = true; + public bool affectCorpses = true; + public bool affectMines = true; + public bool affectEverything = true; // 覆盖所有其他设置 + public bool requireLineOfSight = false; // 调试模式不需要视线 + public bool showEffect = true; + public FleckDef effectFleck; + public SoundDef soundEffect; + + public CompProperties_AbilityDeleteTarget() + { + this.compClass = typeof(CompAbilityEffect_DeleteTarget); + } + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index fa688d23..a4149d50 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -78,6 +78,8 @@ + +