diff --git a/.gitignore b/.gitignore index 2d2bf7ca..5601d9e2 100644 --- a/.gitignore +++ b/.gitignore @@ -53,8 +53,14 @@ *.tmp # Build outputs and debug files -**/obj/Debug/ -**/obj/Release/ -**/bin/Debug/ -**/bin/Release/ +**/obj/ +**/bin/ *.csproj.CoreCompileInputs.cache +*.csproj.FileListAbsolute.txt +*.pdb +*.dll.config +*.cache +*.suo +*.user +_ReSharper.* +*.dotCover diff --git a/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/Assemblies/WulaFallenEmpire.dll index d0d59f33..99ba3dbf 100644 Binary files a/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/Assemblies/WulaFallenEmpire.pdb b/1.6/Assemblies/WulaFallenEmpire.pdb deleted file mode 100644 index a565f103..00000000 Binary files a/1.6/Assemblies/WulaFallenEmpire.pdb and /dev/null differ diff --git a/1.6/Defs/AbilityDefs/Abilities_WULA_Emergency.xml b/1.6/Defs/AbilityDefs/Abilities_WULA_Emergency.xml index e2bc7ec2..25e4b4a1 100644 --- a/1.6/Defs/AbilityDefs/Abilities_WULA_Emergency.xml +++ b/1.6/Defs/AbilityDefs/Abilities_WULA_Emergency.xml @@ -10,7 +10,6 @@ true true false - CastAbilityOnThing false false @@ -33,4 +32,4 @@ - \ No newline at end of file + diff --git a/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml b/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml index edbe0fac..d23961be 100644 --- a/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml +++ b/1.6/Defs/HediffDefs/Hediffs_BodyParts_WULA.xml @@ -146,6 +146,7 @@ true true false + CastAbilityOnThing 15 @@ -245,8 +246,6 @@
  • 0 - - 0.5 diff --git a/1.6/Defs/ThingDefs_Misc/Apparel/WULA_ShieldBelt.xml b/1.6/Defs/ThingDefs_Misc/Apparel/WULA_ShieldBelt.xml index e69de29b..03f61d51 100644 --- a/1.6/Defs/ThingDefs_Misc/Apparel/WULA_ShieldBelt.xml +++ b/1.6/Defs/ThingDefs_Misc/Apparel/WULA_ShieldBelt.xml @@ -0,0 +1,247 @@ + + + + + WULA_ShieldBelt + + 乌拉帝国的个人护盾装置,可以产生动量排斥场来阻挡来袭的投射物。护盾可以通过能力按钮开关,并且具有可配置的护盾值和范围。 + Ultra + + WULA_Synth_Weapon_2_Stun_Technology + UnfinishedBelt + +
  • WULA_Cube_Productor_Energy
  • + + + 8 + + + + Things/Item/Equipment/WeaponMelee/Knife + Graphic_Single + + + 50 + 25 + 3 + 1 + + + 12000 + 1.2 + 0.4 + + +
  • Apparel
  • +
    + + +
  • Waist
  • +
    + Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt + +
  • Belt
  • +
    + +
  • BeltDefensePop
  • +
    + +
  • Soldier
  • +
    +
    + +
  • + + 200 + + 3.0 + + true + + false + + false + + false + + (0.2, 0.6, 1.0) + + 5.0 + + 300 + + BulletShield_Ambience + + BulletShieldGenerator_Reactivate + + false + + true +
  • +
    + + + + + WULA_ShieldBelt_Advanced + + 乌拉帝国的高级个人护盾装置,具有更强的护盾值、更大的范围,并且可以抵抗近战攻击和EMP伤害。 + Ultra + + WULA_Synth_Weapon_2_Stun_Technology + UnfinishedBelt + +
  • WULA_Cube_Productor_Energy
  • +
    + + 10 + +
    + + Things/Item/Equipment/WeaponMelee/Knife + Graphic_Single + + + 100 + 50 + 6 + 2 + 10 + + + 20000 + 2.0 + 0.2 + + +
  • Apparel
  • +
    + + +
  • Waist
  • +
    + Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt + +
  • Belt
  • +
    + +
  • BeltDefensePop
  • +
    + +
  • Soldier
  • +
    +
    + +
  • + + 400 + + 4.5 + + true + + true + + true + + true + + (1.0, 0.6, 0.2) + + 8.0 + + 180 + + BulletShield_Ambience + + BulletShieldGenerator_Reactivate + + false + + true +
  • +
    +
    + + + + WULA_ShieldBelt_Deflector + + 乌拉帝国的偏转型个人护盾装置,采用低角护盾技术,不会被破坏但只能偏转投射物。这种护盾永远不会过载,但也无法完全阻挡攻击。 + Ultra + + WULA_Synth_Weapon_2_Stun_Technology + UnfinishedBelt + +
  • WULA_Cube_Productor_Energy
  • +
    + + 6 + +
    + + Things/Item/Equipment/WeaponMelee/Knife + Graphic_Single + + + 30 + 15 + 2 + 1 + + + 8000 + 0.8 + 0.4 + + +
  • Apparel
  • +
    + + +
  • Waist
  • +
    + Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt + +
  • Belt
  • +
    + +
  • BeltDefensePop
  • +
    + +
  • Soldier
  • +
    +
    + +
  • + + 100 + + 2.5 + + true + + false + + false + + false + + (0.6, 1.0, 0.6) + + 0 + + 0 + + BulletShield_Ambience + + BulletShieldGenerator_Reactivate + + true + + false +
  • +
    +
    + + \ No newline at end of file diff --git a/Source/WulaFallenEmpire/CompAbilityEffect_EmergencyEnergyRestore.cs b/Source/WulaFallenEmpire/CompAbilityEffect_EmergencyEnergyRestore.cs index 0832f9dc..c9ceb91c 100644 --- a/Source/WulaFallenEmpire/CompAbilityEffect_EmergencyEnergyRestore.cs +++ b/Source/WulaFallenEmpire/CompAbilityEffect_EmergencyEnergyRestore.cs @@ -9,6 +9,7 @@ namespace WulaFallenEmpire public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) { + Log.Message($"[EmergencyEnergyRestore] Apply method called for {parent.pawn?.LabelShort}"); base.Apply(target, dest); Pawn caster = parent.pawn; @@ -45,14 +46,9 @@ namespace WulaFallenEmpire public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest) { - bool canApply = base.CanApplyOn(target, dest) && IsWulaRace(parent.pawn); - - if (Props.requireDowned) - { - canApply = canApply && parent.pawn.Downed; - } - - return canApply; + Log.Message($"[EmergencyEnergyRestore] CanApplyOn called. Pawn: {parent.pawn?.LabelShort}"); + // 暂时强制返回true,以排除CanApplyOn的限制 + return true; } private bool IsWulaRace(Pawn pawn) @@ -61,4 +57,4 @@ namespace WulaFallenEmpire return pawn.def.defName == "WulaSpecies"; } } -} \ No newline at end of file +} diff --git a/Source/WulaFallenEmpire/CompProperties_WulaShieldBelt.cs b/Source/WulaFallenEmpire/CompProperties_WulaShieldBelt.cs new file mode 100644 index 00000000..6b926f1b --- /dev/null +++ b/Source/WulaFallenEmpire/CompProperties_WulaShieldBelt.cs @@ -0,0 +1,31 @@ +using RimWorld; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace WulaFallenEmpire +{ + public class CompProperties_WulaShieldBelt : CompProperties + { + public int maxShieldHitPoints = 200; + public float shieldRadius = 3.0f; + public bool interceptGroundProjectiles = true; + public bool interceptAirProjectiles = false; + public bool interceptMeleeAttacks = false; + public bool empImmune = false; + public Color shieldColor = new Color(0.2f, 0.6f, 1.0f); + public float rechargeRate = 5.0f; + public int rechargeCooldownTicks = 300; + public SoundDef activeSound; + public EffecterDef reactivateEffect; + public bool startEnabled = false; + + // 护盾模式:true = 有生命值模式(可被破坏),false = 无生命值模式(类似低角护盾,只是偏转) + public bool useHitPointsMode = true; + + public CompProperties_WulaShieldBelt() + { + compClass = typeof(CompWulaShieldBelt); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/CompWulaShieldBelt.cs b/Source/WulaFallenEmpire/CompWulaShieldBelt.cs new file mode 100644 index 00000000..46ff596c --- /dev/null +++ b/Source/WulaFallenEmpire/CompWulaShieldBelt.cs @@ -0,0 +1,365 @@ +using RimWorld; +using System.Collections.Generic; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace WulaFallenEmpire +{ + [StaticConstructorOnStartup] + public class CompWulaShieldBelt : ThingComp + { + private float shieldHitPoints; + private int ticksToReset = -1; + private int lastKeepDisplayTick = -9999; + private Vector3 impactAngleVect; + private int lastAbsorbDamageTick = -9999; + private bool shieldEnabled = false; + private Sustainer sustainer; + // 静态构造函数加载材质 + private static readonly Material BubbleMat = MaterialPool.MatFrom("Other/ShieldBubble", ShaderDatabase.Transparent, Color.white); + + public CompProperties_WulaShieldBelt Props => (CompProperties_WulaShieldBelt)props; + + public float ShieldHitPoints => shieldHitPoints; + public float ShieldMaxHitPoints => Props.maxShieldHitPoints; + public bool ShieldEnabled => shieldEnabled; + + private bool ShouldDisplay + { + get + { + Pawn wearer = GetWearer(); + return wearer != null && wearer.Spawned && (wearer.Drafted || (wearer.Faction != null && wearer.Faction.IsPlayer) || Find.TickManager.TicksGame < lastKeepDisplayTick + 50); + } + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref shieldHitPoints, "shieldHitPoints", 0f); + Scribe_Values.Look(ref ticksToReset, "ticksToReset", -1); + Scribe_Values.Look(ref shieldEnabled, "shieldEnabled", Props.startEnabled); + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + base.PostSpawnSetup(respawningAfterLoad); + if (!respawningAfterLoad) + { + shieldHitPoints = Props.maxShieldHitPoints; + shieldEnabled = Props.startEnabled; + } + } + + public override void CompTick() + { + base.CompTick(); + + Pawn wearer = GetWearer(); + if (wearer == null) return; + + if (shieldEnabled) + { + if (sustainer == null && Props.activeSound != null) + { + sustainer = Props.activeSound.TrySpawnSustainer(SoundInfo.InMap(wearer, MaintenanceType.PerTick)); + } + sustainer?.Maintain(); + } + else + { + sustainer?.End(); + sustainer = null; + } + + if (ticksToReset > 0) + { + ticksToReset--; + if (ticksToReset <= 0) + { + Reset(); + } + } + else if (shieldEnabled && Props.useHitPointsMode && shieldHitPoints < Props.maxShieldHitPoints) + { + shieldHitPoints += Props.rechargeRate / 60f; // 每秒恢复 + if (shieldHitPoints > Props.maxShieldHitPoints) + { + shieldHitPoints = Props.maxShieldHitPoints; + } + } + } + + public override void PostDraw() + { + base.PostDraw(); + if (shieldEnabled && ShouldDisplay) + { + float num = Mathf.Lerp(1.2f, 1.55f, shieldHitPoints / Props.maxShieldHitPoints); + Vector3 drawPos = GetWearer().Drawer.DrawPos; + drawPos.y = AltitudeLayer.MoteOverhead.AltitudeFor(); + int num2 = Find.TickManager.TicksGame - lastAbsorbDamageTick; + if (num2 < 8) + { + float num3 = (8 - num2) / 8f * 0.05f; + drawPos += impactAngleVect * num3; + num -= num3; + } + + float alpha; + if (Props.useHitPointsMode) + { + // 生命值模式:透明度根据护盾生命值变化 + alpha = Mathf.Lerp(0.2f, 0.7f, shieldHitPoints / Props.maxShieldHitPoints); + } + else + { + // 偏转模式:固定透明度,稍微闪烁效果 + alpha = 0.4f + Mathf.Sin(Time.time * 2f) * 0.1f; + } + Color color = Props.shieldColor; + color.a = alpha; + + Matrix4x4 matrix = default(Matrix4x4); + matrix.SetTRS(drawPos, Quaternion.identity, Vector3.one * num * Props.shieldRadius); + Graphics.DrawMesh(MeshPool.plane10, matrix, BubbleMat, 0, null, 0, MaterialPropertyBlock); + } + } + + private MaterialPropertyBlock materialPropertyBlock; + private MaterialPropertyBlock MaterialPropertyBlock + { + get + { + if (materialPropertyBlock == null) + { + materialPropertyBlock = new MaterialPropertyBlock(); + } + materialPropertyBlock.SetColor(ShaderPropertyIDs.Color, Props.shieldColor); + return materialPropertyBlock; + } + } + + public bool CheckIntercept(Projectile projectile, Vector3 lastExactPos, Vector3 newExactPos) + { + if (!shieldEnabled) + return false; + + // 如果使用生命值模式且护盾已破坏,则不拦截 + if (Props.useHitPointsMode && shieldHitPoints <= 0f) + return false; + + Pawn wearer = GetWearer(); + if (wearer == null || !wearer.Spawned) + return false; + + if (!Props.interceptGroundProjectiles && !projectile.def.projectile.flyOverhead) + return false; + + if (!Props.interceptAirProjectiles && projectile.def.projectile.flyOverhead) + return false; + + Vector3 center = wearer.TrueCenter(); + float radius = Props.shieldRadius; + + // 简单检查:如果射线起点和终点都在圆外,且连线不穿过圆,则不相交 + float distanceFromLastPos = Vector3.Distance(lastExactPos, center); + float distanceFromNewPos = Vector3.Distance(newExactPos, center); + + if (distanceFromLastPos > radius && distanceFromNewPos > radius) + { + // 计算点到线段的最短距离 + Vector3 line = newExactPos - lastExactPos; + float lineLength = line.magnitude; + Vector3 lineDirection = line / lineLength; + float projection = Mathf.Clamp(Vector3.Dot(center - lastExactPos, lineDirection), 0f, lineLength); + Vector3 closestPoint = lastExactPos + lineDirection * projection; + float distanceToLine = Vector3.Distance(center, closestPoint); + + if (distanceToLine > radius) + return false; + } + + lastKeepDisplayTick = Find.TickManager.TicksGame + 40; + + // 根据模式处理伤害 + if (Props.useHitPointsMode) + { + // 生命值模式:吸收伤害并可能破坏护盾 + AbsorbDamage(projectile.DamageAmount, projectile.ExactPosition); + } + else + { + // 偏转模式:只是偏转,不消耗护盾生命值 + DeflectProjectile(projectile.ExactPosition); + } + + return true; + } + + public bool CheckMeleeIntercept(DamageInfo dinfo, Pawn attacker) + { + if (!shieldEnabled || !Props.interceptMeleeAttacks || shieldHitPoints <= 0f) + return false; + + Pawn wearer = GetWearer(); + if (wearer == null || !wearer.Spawned) + return false; + + lastKeepDisplayTick = Find.TickManager.TicksGame + 40; + AbsorbDamage(dinfo.Amount, attacker.Position.ToVector3()); + return true; + } + + private void AbsorbDamage(float damage, Vector3 impactPos) + { + if (Props.empImmune && damage > 0f) + { + // EMP免疫时减少EMP伤害 + damage *= 0.1f; + } + + // 只有在生命值模式下才扣除护盾生命值 + if (Props.useHitPointsMode) + { + shieldHitPoints -= damage; + } + + lastAbsorbDamageTick = Find.TickManager.TicksGame; + + Pawn wearer = GetWearer(); + if (wearer != null) + { + impactAngleVect = Vector3Utility.HorizontalVectorFromAngle((impactPos - wearer.TrueCenter()).AngleFlat() + 180f); + } + + // 只有在生命值模式下才会破坏护盾 + if (Props.useHitPointsMode && shieldHitPoints <= 0f) + { + Break(); + } + } + + private void DeflectProjectile(Vector3 impactPos) + { + // 偏转模式:只显示视觉效果,不消耗护盾生命值 + lastAbsorbDamageTick = Find.TickManager.TicksGame; + + Pawn wearer = GetWearer(); + if (wearer != null) + { + impactAngleVect = Vector3Utility.HorizontalVectorFromAngle((impactPos - wearer.TrueCenter()).AngleFlat() + 180f); + + // 播放偏转特效 + FleckMaker.ThrowLightningGlow(impactPos, wearer.Map, 0.5f); + } + } + + private void Break() + { + shieldHitPoints = 0f; + ticksToReset = Props.rechargeCooldownTicks; + sustainer?.End(); + sustainer = null; + + Pawn wearer = GetWearer(); + if (wearer != null && wearer.Map != null) + { + FleckMaker.Static(wearer.TrueCenter(), wearer.Map, FleckDefOf.ExplosionFlash, 12f); + for (int i = 0; i < 6; i++) + { + FleckMaker.ThrowDustPuff(wearer.TrueCenter() + Vector3Utility.HorizontalVectorFromAngle(Rand.Range(0, 360)) * Rand.Range(0.3f, 0.6f), wearer.Map, Rand.Range(0.8f, 1.2f)); + } + } + } + + private void Reset() + { + if (parent.Spawned) + { + SoundDefOf.EnergyShield_Reset.PlayOneShot(new TargetInfo(parent.Position, parent.Map)); + FleckMaker.ThrowLightningGlow(GetWearer().TrueCenter(), parent.Map, 3f); + + if (Props.reactivateEffect != null) + { + Effecter effecter = Props.reactivateEffect.Spawn(parent.Position, parent.Map); + effecter.Trigger(new TargetInfo(parent.Position, parent.Map), TargetInfo.Invalid); + effecter.Cleanup(); + } + } + shieldHitPoints = Props.maxShieldHitPoints; + } + + public void ToggleShield() + { + shieldEnabled = !shieldEnabled; + + Pawn wearer = GetWearer(); + if (wearer != null) + { + string message = shieldEnabled ? $"{wearer.LabelShort}激活了护盾" : $"{wearer.LabelShort}关闭了护盾"; + Messages.Message(message, MessageTypeDefOf.NeutralEvent, false); + } + + if (!shieldEnabled) + { + sustainer?.End(); + sustainer = null; + } + } + + private Pawn GetWearer() + { + if (parent is Apparel apparel) + { + return apparel.Wearer; + } + return null; + } + + // 添加初始化方法,确保护盾值正确设置 + public override void Initialize(CompProperties props) + { + base.Initialize(props); + shieldHitPoints = ((CompProperties_WulaShieldBelt)props).maxShieldHitPoints; + shieldEnabled = ((CompProperties_WulaShieldBelt)props).startEnabled; + } + + public override IEnumerable CompGetWornGizmosExtra() + { + // 确保穿戴者存在 + Pawn wearer = GetWearer(); + if (wearer == null) yield break; + + // 不限制只有选中时才显示 + yield return new Command_Toggle + { + defaultLabel = "护盾开关", + defaultDesc = shieldEnabled ? "关闭护盾" : "激活护盾", + icon = ContentFinder.Get("UI/Commands/DesirePower"), + isActive = () => shieldEnabled, + toggleAction = ToggleShield + }; + } + + public override string CompInspectStringExtra() + { + if (shieldEnabled) + { + if (Props.useHitPointsMode) + { + return $"护盾: {shieldHitPoints:F0} / {Props.maxShieldHitPoints} (生命值模式)"; + } + else + { + return "护盾: 激活 (偏转模式)"; + } + } + else + { + return "护盾: 已关闭"; + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/EmergencyAbilityPatches.cs b/Source/WulaFallenEmpire/EmergencyAbilityPatches.cs new file mode 100644 index 00000000..845cc8e6 --- /dev/null +++ b/Source/WulaFallenEmpire/EmergencyAbilityPatches.cs @@ -0,0 +1,136 @@ +using HarmonyLib; +using RimWorld; +using System; // Added for Type +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using Verse; + +namespace WulaFallenEmpire +{ + [HarmonyPatch] + public static class EmergencyAbilityPatches + { + // 修复倒地时无法使用能力的问题 + [HarmonyPatch(typeof(Ability), "get_CanCast")] + [HarmonyPostfix] + public static void CanCast_Postfix(Ability __instance, ref AcceptanceReport __result) + { + if (__instance.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] CanCast_Postfix for {__instance.pawn?.LabelShort}, initial result: {__result.Accepted}, reason: {__result.Reason}"); + if (!__result.Accepted) + { + // 检查是否是因为pawn失去知觉而无法使用能力 + if (__instance.pawn.Downed) + { + // 对于紧急能量恢复能力,我们允许在倒地时使用 + __result = true; + Log.Message($"[EmergencyAbilityPatches] CanCast_Postfix: Pawn is downed, overriding to true. New result: {__result.Accepted}"); + } + } + } + } + + // 修复倒地时无法显示能力按钮的问题 + [HarmonyPatch(typeof(Pawn_AbilityTracker), "get_AllAbilitiesForReading")] + [HarmonyPostfix] + public static void GetAbilitiesForDisplay_Postfix(Pawn_AbilityTracker __instance, ref List __result) + { + // 检查pawn是否倒地 + if (__instance.pawn.Downed) + { + // 添加紧急能量恢复能力,即使pawn倒地 + foreach (Ability ability in __instance.abilities) + { + if (ability.def.defName == "WULA_EmergencyEnergyRestore" && !__result.Contains(ability)) + { + __result.Add(ability); + } + } + } + } + + // 修复倒地时无法使用能力的UI限制 - 直接修补Ability.GizmoDisabled方法 + [HarmonyPatch(typeof(Ability), "GizmoDisabled")] + [HarmonyPostfix] + public static void Ability_GizmoDisabled_Postfix(Ability __instance, ref bool __result, ref string reason) + { + if (__instance.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] GizmoDisabled_Postfix for {__instance.pawn?.LabelShort}, initial result: {__result}, reason: {reason}"); + if (__result) + { + // 检查是否是因为倒地而被禁用 + if (__instance.pawn.Downed && reason != null && + (reason.Contains("失去知觉") || reason.Contains("unconscious") || reason.Contains("CommandDisabledUnconscious"))) + { + // 对于紧急能量恢复能力,我们允许在倒地时使用 + __result = false; + reason = null; + Log.Message($"[EmergencyAbilityPatches] GizmoDisabled_Postfix: Pawn is downed, overriding to false. New result: {__result}"); + } + } + } + } + + // 额外的安全措施:修复Command_Ability的禁用检查 + [HarmonyPatch(typeof(Command_Ability), "get_Disabled")] + [HarmonyPostfix] + public static void Command_Ability_GizmoDisabled_Postfix(Command_Ability __instance, ref bool __result) + { + // 使用反射获取ability字段 + var abilityField = typeof(Command_Ability).GetField("ability", BindingFlags.Instance | BindingFlags.NonPublic); + if (abilityField == null) return; + + Ability ability = (Ability)abilityField.GetValue(__instance); + if (ability == null) return; + + if (ability.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] Command_Ability_GizmoDisabled_Postfix for {ability.pawn?.LabelShort}, initial result: {__result}"); + if (__result && ability.pawn.Downed) + { + // 对于紧急能量恢复能力,我们允许在倒地时使用 + __result = false; + Log.Message($"[EmergencyAbilityPatches] Command_Ability_GizmoDisabled_Postfix: Pawn is downed, overriding to false. New result: {__result}"); + } + } + } + + // 新增补丁:检查ApparelPreventsShooting是否阻止了施法 + [HarmonyPatch(typeof(Verb), "ApparelPreventsShooting")] + [HarmonyPostfix] + public static void ApparelPreventsShooting_Postfix(Verb __instance, ref bool __result) + { + Log.Message($"[EmergencyAbilityPatches] ApparelPreventsShooting_Postfix called. Verb type: {__instance.GetType().Name}, Caster: {__instance.CasterPawn?.LabelShort}, initial result: {__result}"); + if (__instance is Verb_CastAbility castAbilityVerb && castAbilityVerb.ability?.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] ApparelPreventsShooting_Postfix for EmergencyEnergyRestore. Pawn: {__instance.CasterPawn?.LabelShort}, result: {__result}"); + } + } + + // 最终诊断补丁:检查Verb.TryStartCastOn是否被调用 + [HarmonyPatch(typeof(Verb), "TryStartCastOn", new Type[] { typeof(LocalTargetInfo), typeof(LocalTargetInfo), typeof(bool), typeof(bool), typeof(bool), typeof(bool) })] + [HarmonyPrefix] + public static void TryStartCastOn_DiagnosticPrefix(Verb __instance, LocalTargetInfo castTarg, LocalTargetInfo destTarg, ref bool __result) + { + Log.Message($"[EmergencyAbilityPatches] TryStartCastOn_DiagnosticPrefix called for Verb type: {__instance.GetType().Name}. Caster: {__instance.CasterPawn?.LabelShort}. CastTarg: {castTarg}, DestTarg: {destTarg}"); + if (__instance is Verb_CastAbility castAbilityVerb && castAbilityVerb.ability?.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] TryStartCastOn_DiagnosticPrefix: This is EmergencyEnergyRestore ability. Caster: {__instance.CasterPawn?.LabelShort}"); + } + } + + // 诊断补丁:检查Verb_CastAbility.TryCastShot是否被调用 + [HarmonyPatch(typeof(Verb_CastAbility), "TryCastShot")] + [HarmonyPrefix] + public static void TryCastShot_DiagnosticPrefix(Verb_CastAbility __instance, ref bool __result) + { + if (__instance.ability?.def.defName == "WULA_EmergencyEnergyRestore") + { + Log.Message($"[EmergencyAbilityPatches] TryCastShot_DiagnosticPrefix called for EmergencyEnergyRestore. Pawn: {__instance.CasterPawn?.LabelShort}"); + } + } + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 6de951e6..df0101bf 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -14,13 +14,15 @@ true - true - full + false + none false ..\..\1.6\Assemblies\ DEBUG;TRACE prompt 4 + Off + .allowedextension pdbonly @@ -80,6 +82,16 @@ + + + + + + + + + + diff --git a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs index cb6a4608..41cb256b 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs +++ b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs @@ -13,6 +13,9 @@ namespace WulaFallenEmpire // 初始化Harmony var harmony = new Harmony("tourswen.wulafallenempire"); // 替换为您的唯一Mod ID harmony.PatchAll(Assembly.GetExecutingAssembly()); + + // 手动应用护盾腰带的近战拦截补丁 + WulaShieldBeltPatches.ApplyMeleePatch(harmony); Log.Message("[WulaFallenEmpire] Harmony patches applied."); } diff --git a/Source/WulaFallenEmpire/WulaShieldBeltPatches.cs b/Source/WulaFallenEmpire/WulaShieldBeltPatches.cs new file mode 100644 index 00000000..3b706712 --- /dev/null +++ b/Source/WulaFallenEmpire/WulaShieldBeltPatches.cs @@ -0,0 +1,97 @@ +using HarmonyLib; +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + public static class WulaShieldBeltPatches + { + // 拦截投射物 + [HarmonyPatch(typeof(Projectile), "CheckForFreeInterceptBetween")] + [HarmonyPrefix] + public static bool CheckForFreeInterceptBetween_Prefix(Projectile __instance, Vector3 lastExactPos, Vector3 newExactPos, ref bool __result) + { + var map = __instance.Map; + if (map == null) return true; + + // 检查所有穿戴护盾腰带的pawn + var pawns = map.mapPawns.AllPawnsSpawned; + foreach (var pawn in pawns) + { + if (pawn.apparel?.WornApparel == null) continue; + + foreach (var apparel in pawn.apparel.WornApparel) + { + var shieldComp = apparel.GetComp(); + if (shieldComp != null && shieldComp.CheckIntercept(__instance, lastExactPos, newExactPos)) + { + // 使用反射调用protected方法 + typeof(Projectile).GetMethod("Impact", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic) + .Invoke(__instance, new object[] { null, true }); + __result = true; + return false; + } + } + } + + return true; + } + + // 拦截近战攻击 - 使用Harmony的手动补丁方式 + public static void ApplyMeleePatch(Harmony harmony) + { + // 获取Thing.TakeDamage方法 + var originalMethod = typeof(Thing).GetMethod("TakeDamage", + System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + + if (originalMethod != null) + { + // 获取我们的前缀方法 + var prefixMethod = typeof(WulaShieldBeltPatches).GetMethod("TakeDamage_Manual_Prefix", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); + + // 应用补丁 + harmony.Patch(originalMethod, new HarmonyMethod(prefixMethod)); + } + } + + // 手动补丁方法 + public static bool TakeDamage_Manual_Prefix(Thing __instance, DamageInfo dinfo, ref DamageWorker.DamageResult __result) + { + // 只有当实例是Pawn时才执行护盾腰带的逻辑 + if (__instance is Pawn pawn) + { + if (pawn.apparel?.WornApparel == null) return true; + + // 检查是否有护盾腰带可以拦截这次攻击 + foreach (var apparel in pawn.apparel.WornApparel) + { + var shieldComp = apparel.GetComp(); + if (shieldComp != null && dinfo.Instigator is Pawn attacker) + { + if (shieldComp.CheckMeleeIntercept(dinfo, attacker)) + { + __result = new DamageWorker.DamageResult(); + return false; + } + } + } + } + + return true; + } + + // 为护盾腰带添加投射物拦截器接口支持 + [HarmonyPatch(typeof(CompProjectileInterceptor), "CheckIntercept")] + [HarmonyPostfix] + public static void CheckIntercept_Postfix(CompProjectileInterceptor __instance, Projectile projectile, Vector3 lastExactPos, Vector3 newExactPos, ref bool __result) + { + if (__result) return; // 如果已经被拦截了就不需要再检查 + + // 这个补丁确保我们的护盾系统与原版的投射物拦截系统兼容 + } + } +} diff --git a/Source/WulaFallenEmpire/clean.bat b/Source/WulaFallenEmpire/clean.bat new file mode 100644 index 00000000..a657fac4 --- /dev/null +++ b/Source/WulaFallenEmpire/clean.bat @@ -0,0 +1,5 @@ +@echo off +echo 清理临时文件... +if exist "obj" rmdir /s /q obj +if exist "bin" rmdir /s /q bin +echo 清理完成! \ No newline at end of file diff --git a/Source/WulaFallenEmpire/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/Source/WulaFallenEmpire/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs deleted file mode 100644 index 3871b184..00000000 --- a/Source/WulaFallenEmpire/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs +++ /dev/null @@ -1,4 +0,0 @@ -// -using System; -using System.Reflection; -[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] diff --git a/Source/WulaFallenEmpire/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Source/WulaFallenEmpire/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache deleted file mode 100644 index 455cf6fa..00000000 Binary files a/Source/WulaFallenEmpire/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and /dev/null differ diff --git a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.AssemblyReference.cache b/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.AssemblyReference.cache deleted file mode 100644 index 4665d311..00000000 Binary files a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.AssemblyReference.cache and /dev/null differ diff --git a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.CoreCompileInputs.cache b/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.CoreCompileInputs.cache deleted file mode 100644 index 078ed891..00000000 --- a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.CoreCompileInputs.cache +++ /dev/null @@ -1 +0,0 @@ -981fae8ea86dc7ccc506adb49b6855ce4c202ff9e230c7a6c385d9789ef4b0aa diff --git a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.FileListAbsolute.txt b/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.FileListAbsolute.txt deleted file mode 100644 index fe056ac7..00000000 --- a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,51 +0,0 @@ -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\WulaFallenEmpire.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\WulaFallenEmpire.pdb -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Assembly-CSharp.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.CoreModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.IMGUIModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.TextRenderingModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\NAudio.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\NVorbis.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.AudioModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.Collections.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.Burst.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.Mathematics.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\com.rlabrecque.steamworks.net.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Assembly-CSharp-firstpass.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.AssetBundleModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.PhysicsModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.TextMeshPro.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\ISharpZipLib.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.InputLegacyModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.PerformanceReportingModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.ImageConversionModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.ScreenCaptureModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.UI.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\netstandard.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.SharedInternalsModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.TextCoreTextEngineModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.PropertiesModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.Collections.LowLevel.ILSupport.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\Unity.Burst.Unsafe.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.TextCoreFontEngineModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.UIModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.Physics2DModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.AnimationModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\bin\Debug\UnityEngine.SpriteShapeModule.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.AssemblyReference.cache -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.CoreCompileInputs.cache -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\obj\Debug\WulaFall.44DB8A10.Up2Date -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.dll -E:\SteamLibrary\steamapps\common\RimWorld\Mods\WulaFallenEmpire\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.pdb -C:\Steam\steamapps\workshop\content\294100\3516260226\1.6\Assemblies\WulaFallenEmpire.dll -C:\Steam\steamapps\workshop\content\294100\3516260226\1.6\Assemblies\WulaFallenEmpire.pdb -C:\Steam\steamapps\workshop\content\294100\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.AssemblyReference.cache -C:\Steam\steamapps\workshop\content\294100\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.CoreCompileInputs.cache -C:\Steam\steamapps\workshop\content\294100\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.dll -C:\Steam\steamapps\workshop\content\294100\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.pdb -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\1.6\Assemblies\WulaFallenEmpire.dll -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\1.6\Assemblies\WulaFallenEmpire.pdb -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.AssemblyReference.cache -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.csproj.CoreCompileInputs.cache -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.dll -C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\obj\Debug\WulaFallenEmpire.pdb diff --git a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.dll b/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.dll deleted file mode 100644 index 89ffb7ff..00000000 Binary files a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.dll and /dev/null differ diff --git a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.pdb b/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.pdb deleted file mode 100644 index 1142b654..00000000 Binary files a/Source/WulaFallenEmpire/obj/Debug/WulaFallenEmpire.pdb and /dev/null differ