Merge branch 'main' of https://git.ra3battle.cn/Kalospacer/WulaFallenEmpireRW
This commit is contained in:
@@ -2090,7 +2090,7 @@
|
||||
</li>
|
||||
</modExtensions>
|
||||
</ThingDef>
|
||||
<AbilityDef>
|
||||
<!-- <AbilityDef>
|
||||
<defName>WULA_RW_Auto_GL_Smoke_Ability</defName>
|
||||
<label>发射烟雾弹</label>
|
||||
<description>使用SEl-78"角砾岩"临时装填并发射一枚烟雾弹,用于遮蔽炮塔的瞄准和防止己方被流弹击中。</description>
|
||||
@@ -2124,5 +2124,46 @@
|
||||
<projectileDef>Bullet_Shell_Smoke</projectileDef>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef> -->
|
||||
<AbilityDef>
|
||||
<defName>WULA_RW_Auto_GL_Smoke_Ability</defName>
|
||||
<label>律令死亡</label>
|
||||
<description>使得目标立刻被放逐——无视一切保护措施,将其从存档中永远擦除。</description>
|
||||
<iconPath>Wula/UI/Abilities/WULA_RW_Auto_GL_Smoke_Ability</iconPath>
|
||||
<writeCombatLog>True</writeCombatLog>
|
||||
<showPsycastEffects>False</showPsycastEffects>
|
||||
<hotKey>Misc11</hotKey>
|
||||
<showOnCharacterCard>false</showOnCharacterCard>
|
||||
<charges>3</charges>
|
||||
<cooldownPerCharge>true</cooldownPerCharge>
|
||||
<cooldownTicksRange>1</cooldownTicksRange>
|
||||
<statBases>
|
||||
<Ability_EffectRadius>35</Ability_EffectRadius>
|
||||
</statBases>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<range>500</range>
|
||||
<warmupTime>0.25</warmupTime>
|
||||
<muzzleFlashScale>9</muzzleFlashScale>
|
||||
<ai_IsWeapon>true</ai_IsWeapon>
|
||||
<soundCast>Pawn_Mech_Apocriton_Death</soundCast>
|
||||
<requireLineOfSight>false</requireLineOfSight>
|
||||
|
||||
<targetParams>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
<canTargetSelf>false</canTargetSelf>
|
||||
<canTargetPawns>true</canTargetPawns>
|
||||
<canTargetBuildings>true</canTargetBuildings>
|
||||
<canTargetPlants>true</canTargetPlants>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.CompProperties_AbilityDeleteTarget">
|
||||
<affectEverything>true</affectEverything>
|
||||
<requireLineOfSight>false</requireLineOfSight>
|
||||
<!-- <showEffect>true</showEffect>
|
||||
<soundEffect>EnergyWeapon_Discharge</soundEffect> -->
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
</Defs>
|
||||
@@ -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<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));
|
||||
}
|
||||
|
||||
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<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)
|
||||
{
|
||||
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<IntVec3> { cell }, Color.red, 0.8f);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// 忽略预览绘制错误
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,8 @@
|
||||
<Compile Include="Ability\WULA_AbilityBombardment\CompProperties_AbilityBombardment.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityCircularBombardment\CompAbilityEffect_CircularBombardment.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityCircularBombardment\CompProperties_AbilityCircularBombardment.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityDeleteTarget\CompAbilityEffect_DeleteTarget.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityDeleteTarget\CompProperties_AbilityDeleteTarget.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityEnergyLance\AbilityWeaponDefExtension.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityEnergyLance\CompAbilityEffect_EnergyLance.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityEnergyLance\CompProperties_AbilityEnergyLance.cs" />
|
||||
|
||||
Reference in New Issue
Block a user