麻了先暂存
This commit is contained in:
14
.gitignore
vendored
14
.gitignore
vendored
@@ -53,8 +53,14 @@
|
|||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
# Build outputs and debug files
|
# Build outputs and debug files
|
||||||
**/obj/Debug/
|
**/obj/
|
||||||
**/obj/Release/
|
**/bin/
|
||||||
**/bin/Debug/
|
|
||||||
**/bin/Release/
|
|
||||||
*.csproj.CoreCompileInputs.cache
|
*.csproj.CoreCompileInputs.cache
|
||||||
|
*.csproj.FileListAbsolute.txt
|
||||||
|
*.pdb
|
||||||
|
*.dll.config
|
||||||
|
*.cache
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
_ReSharper.*
|
||||||
|
*.dotCover
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -10,7 +10,6 @@
|
|||||||
<aiCanUse>true</aiCanUse>
|
<aiCanUse>true</aiCanUse>
|
||||||
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
|
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
|
||||||
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
|
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
|
||||||
<jobDef>CastAbilityOnThing</jobDef>
|
|
||||||
<targetRequired>false</targetRequired>
|
<targetRequired>false</targetRequired>
|
||||||
<canUseAoeToGetTargets>false</canUseAoeToGetTargets>
|
<canUseAoeToGetTargets>false</canUseAoeToGetTargets>
|
||||||
<verbProperties>
|
<verbProperties>
|
||||||
@@ -33,4 +32,4 @@
|
|||||||
</comps>
|
</comps>
|
||||||
</AbilityDef>
|
</AbilityDef>
|
||||||
|
|
||||||
</Defs>
|
</Defs>
|
||||||
|
|||||||
@@ -146,6 +146,7 @@
|
|||||||
<aiCanUse>true</aiCanUse>
|
<aiCanUse>true</aiCanUse>
|
||||||
<ai_IsOffensive>true</ai_IsOffensive>
|
<ai_IsOffensive>true</ai_IsOffensive>
|
||||||
<targetRequired>false</targetRequired>
|
<targetRequired>false</targetRequired>
|
||||||
|
<jobDef>CastAbilityOnThing</jobDef> <!-- 添加jobDef -->
|
||||||
<statBases>
|
<statBases>
|
||||||
<Ability_Duration>15</Ability_Duration>
|
<Ability_Duration>15</Ability_Duration>
|
||||||
</statBases>
|
</statBases>
|
||||||
@@ -245,8 +246,6 @@
|
|||||||
<stages>
|
<stages>
|
||||||
<li>
|
<li>
|
||||||
<minSeverity>0</minSeverity>
|
<minSeverity>0</minSeverity>
|
||||||
<capMods>
|
|
||||||
</capMods>
|
|
||||||
<statOffsets> <!-- StatOffset 是加法偏移量,正数增加,负数减少 -->
|
<statOffsets> <!-- StatOffset 是加法偏移量,正数增加,负数减少 -->
|
||||||
<WulaEnergyMaxLevelOffset>0.5</WulaEnergyMaxLevelOffset>
|
<WulaEnergyMaxLevelOffset>0.5</WulaEnergyMaxLevelOffset>
|
||||||
</statOffsets>
|
</statOffsets>
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Defs>
|
||||||
|
|
||||||
|
<ThingDef ParentName="ApparelMakeableBase">
|
||||||
|
<defName>WULA_ShieldBelt</defName>
|
||||||
|
<label>乌拉护盾腰带</label>
|
||||||
|
<description>乌拉帝国的个人护盾装置,可以产生动量排斥场来阻挡来袭的投射物。护盾可以通过能力按钮开关,并且具有可配置的护盾值和范围。</description>
|
||||||
|
<techLevel>Ultra</techLevel>
|
||||||
|
<recipeMaker>
|
||||||
|
<researchPrerequisite>WULA_Synth_Weapon_2_Stun_Technology</researchPrerequisite>
|
||||||
|
<unfinishedThingDef>UnfinishedBelt</unfinishedThingDef>
|
||||||
|
<recipeUsers Inherit="False">
|
||||||
|
<li>WULA_Cube_Productor_Energy</li>
|
||||||
|
</recipeUsers>
|
||||||
|
<skillRequirements>
|
||||||
|
<Crafting>8</Crafting>
|
||||||
|
</skillRequirements>
|
||||||
|
</recipeMaker>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Things/Item/Equipment/WeaponMelee/Knife</texPath>
|
||||||
|
<graphicClass>Graphic_Single</graphicClass>
|
||||||
|
</graphicData>
|
||||||
|
<costList>
|
||||||
|
<Steel>50</Steel>
|
||||||
|
<Plasteel>25</Plasteel>
|
||||||
|
<ComponentSpacer>3</ComponentSpacer>
|
||||||
|
<BroadshieldCore>1</BroadshieldCore>
|
||||||
|
</costList>
|
||||||
|
<statBases>
|
||||||
|
<WorkToMake>12000</WorkToMake>
|
||||||
|
<Mass>1.2</Mass>
|
||||||
|
<Flammability>0.4</Flammability>
|
||||||
|
</statBases>
|
||||||
|
<thingCategories>
|
||||||
|
<li>Apparel</li>
|
||||||
|
</thingCategories>
|
||||||
|
<apparel>
|
||||||
|
<bodyPartGroups>
|
||||||
|
<li>Waist</li>
|
||||||
|
</bodyPartGroups>
|
||||||
|
<wornGraphicPath>Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt</wornGraphicPath>
|
||||||
|
<layers>
|
||||||
|
<li>Belt</li>
|
||||||
|
</layers>
|
||||||
|
<tags>
|
||||||
|
<li>BeltDefensePop</li>
|
||||||
|
</tags>
|
||||||
|
<defaultOutfitTags>
|
||||||
|
<li>Soldier</li>
|
||||||
|
</defaultOutfitTags>
|
||||||
|
</apparel>
|
||||||
|
<comps>
|
||||||
|
<li Class="WulaFallenEmpire.CompProperties_WulaShieldBelt">
|
||||||
|
<!-- 护盾最大生命值 - 护盾能承受的总伤害量 -->
|
||||||
|
<maxShieldHitPoints>200</maxShieldHitPoints>
|
||||||
|
<!-- 护盾半径 - 护盾保护范围的半径(以格子为单位) -->
|
||||||
|
<shieldRadius>3.0</shieldRadius>
|
||||||
|
<!-- 拦截地面投射物 - 是否拦截子弹、箭矢等地面投射物 -->
|
||||||
|
<interceptGroundProjectiles>true</interceptGroundProjectiles>
|
||||||
|
<!-- 拦截空中投射物 - 是否拦截迫击炮弹等空中投射物 -->
|
||||||
|
<interceptAirProjectiles>false</interceptAirProjectiles>
|
||||||
|
<!-- 拦截近战攻击 - 是否能够阻挡近战攻击 -->
|
||||||
|
<interceptMeleeAttacks>false</interceptMeleeAttacks>
|
||||||
|
<!-- EMP免疫 - 是否免疫电磁脉冲攻击 -->
|
||||||
|
<empImmune>false</empImmune>
|
||||||
|
<!-- 护盾颜色 - 护盾显示的颜色 (R, G, B) 值范围0-1 -->
|
||||||
|
<shieldColor>(0.2, 0.6, 1.0)</shieldColor>
|
||||||
|
<!-- 充能速率 - 护盾每秒恢复的生命值 -->
|
||||||
|
<rechargeRate>5.0</rechargeRate>
|
||||||
|
<!-- 充能冷却时间 - 护盾被破坏后开始充能前的等待时间(游戏刻数,60刻=1秒) -->
|
||||||
|
<rechargeCooldownTicks>300</rechargeCooldownTicks>
|
||||||
|
<!-- 激活音效 - 护盾运行时播放的环境音效 -->
|
||||||
|
<activeSound>BulletShield_Ambience</activeSound>
|
||||||
|
<!-- 重新激活特效 - 护盾重新启动时播放的视觉特效 -->
|
||||||
|
<reactivateEffect>BulletShieldGenerator_Reactivate</reactivateEffect>
|
||||||
|
<!-- 初始启用状态 - 护盾腰带装备后是否默认开启 -->
|
||||||
|
<startEnabled>false</startEnabled>
|
||||||
|
<!-- 护盾模式 - true=有生命值模式(可被破坏),false=无生命值模式(类似低角护盾,只偏转) -->
|
||||||
|
<useHitPointsMode>true</useHitPointsMode>
|
||||||
|
</li>
|
||||||
|
</comps>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
<!-- 高级版本 -->
|
||||||
|
<ThingDef ParentName="ApparelMakeableBase">
|
||||||
|
<defName>WULA_ShieldBelt_Advanced</defName>
|
||||||
|
<label>乌拉高级护盾腰带</label>
|
||||||
|
<description>乌拉帝国的高级个人护盾装置,具有更强的护盾值、更大的范围,并且可以抵抗近战攻击和EMP伤害。</description>
|
||||||
|
<techLevel>Ultra</techLevel>
|
||||||
|
<recipeMaker>
|
||||||
|
<researchPrerequisite>WULA_Synth_Weapon_2_Stun_Technology</researchPrerequisite>
|
||||||
|
<unfinishedThingDef>UnfinishedBelt</unfinishedThingDef>
|
||||||
|
<recipeUsers Inherit="False">
|
||||||
|
<li>WULA_Cube_Productor_Energy</li>
|
||||||
|
</recipeUsers>
|
||||||
|
<skillRequirements>
|
||||||
|
<Crafting>10</Crafting>
|
||||||
|
</skillRequirements>
|
||||||
|
</recipeMaker>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Things/Item/Equipment/WeaponMelee/Knife</texPath>
|
||||||
|
<graphicClass>Graphic_Single</graphicClass>
|
||||||
|
</graphicData>
|
||||||
|
<costList>
|
||||||
|
<Steel>100</Steel>
|
||||||
|
<Plasteel>50</Plasteel>
|
||||||
|
<ComponentSpacer>6</ComponentSpacer>
|
||||||
|
<BroadshieldCore>2</BroadshieldCore>
|
||||||
|
<Uranium>10</Uranium>
|
||||||
|
</costList>
|
||||||
|
<statBases>
|
||||||
|
<WorkToMake>20000</WorkToMake>
|
||||||
|
<Mass>2.0</Mass>
|
||||||
|
<Flammability>0.2</Flammability>
|
||||||
|
</statBases>
|
||||||
|
<thingCategories>
|
||||||
|
<li>Apparel</li>
|
||||||
|
</thingCategories>
|
||||||
|
<apparel>
|
||||||
|
<bodyPartGroups>
|
||||||
|
<li>Waist</li>
|
||||||
|
</bodyPartGroups>
|
||||||
|
<wornGraphicPath>Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt</wornGraphicPath>
|
||||||
|
<layers>
|
||||||
|
<li>Belt</li>
|
||||||
|
</layers>
|
||||||
|
<tags>
|
||||||
|
<li>BeltDefensePop</li>
|
||||||
|
</tags>
|
||||||
|
<defaultOutfitTags>
|
||||||
|
<li>Soldier</li>
|
||||||
|
</defaultOutfitTags>
|
||||||
|
</apparel>
|
||||||
|
<comps>
|
||||||
|
<li Class="WulaFallenEmpire.CompProperties_WulaShieldBelt">
|
||||||
|
<!-- 护盾最大生命值 - 护盾能承受的总伤害量 -->
|
||||||
|
<maxShieldHitPoints>400</maxShieldHitPoints>
|
||||||
|
<!-- 护盾半径 - 护盾保护范围的半径(以格子为单位) -->
|
||||||
|
<shieldRadius>4.5</shieldRadius>
|
||||||
|
<!-- 拦截地面投射物 - 是否拦截子弹、箭矢等地面投射物 -->
|
||||||
|
<interceptGroundProjectiles>true</interceptGroundProjectiles>
|
||||||
|
<!-- 拦截空中投射物 - 是否拦截迫击炮弹等空中投射物 -->
|
||||||
|
<interceptAirProjectiles>true</interceptAirProjectiles>
|
||||||
|
<!-- 拦截近战攻击 - 是否能够阻挡近战攻击 -->
|
||||||
|
<interceptMeleeAttacks>true</interceptMeleeAttacks>
|
||||||
|
<!-- EMP免疫 - 是否免疫电磁脉冲攻击 -->
|
||||||
|
<empImmune>true</empImmune>
|
||||||
|
<!-- 护盾颜色 - 护盾显示的颜色 (R, G, B) 值范围0-1 -->
|
||||||
|
<shieldColor>(1.0, 0.6, 0.2)</shieldColor>
|
||||||
|
<!-- 充能速率 - 护盾每秒恢复的生命值 -->
|
||||||
|
<rechargeRate>8.0</rechargeRate>
|
||||||
|
<!-- 充能冷却时间 - 护盾被破坏后开始充能前的等待时间(游戏刻数,60刻=1秒) -->
|
||||||
|
<rechargeCooldownTicks>180</rechargeCooldownTicks>
|
||||||
|
<!-- 激活音效 - 护盾运行时播放的环境音效 -->
|
||||||
|
<activeSound>BulletShield_Ambience</activeSound>
|
||||||
|
<!-- 重新激活特效 - 护盾重新启动时播放的视觉特效 -->
|
||||||
|
<reactivateEffect>BulletShieldGenerator_Reactivate</reactivateEffect>
|
||||||
|
<!-- 初始启用状态 - 护盾腰带装备后是否默认开启 -->
|
||||||
|
<startEnabled>false</startEnabled>
|
||||||
|
<!-- 护盾模式 - true=有生命值模式(可被破坏),false=无生命值模式(类似低角护盾,只偏转) -->
|
||||||
|
<useHitPointsMode>true</useHitPointsMode>
|
||||||
|
</li>
|
||||||
|
</comps>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
<!-- 偏转型护盾腰带 - 无生命值模式示例 -->
|
||||||
|
<ThingDef ParentName="ApparelMakeableBase">
|
||||||
|
<defName>WULA_ShieldBelt_Deflector</defName>
|
||||||
|
<label>乌拉偏转护盾腰带</label>
|
||||||
|
<description>乌拉帝国的偏转型个人护盾装置,采用低角护盾技术,不会被破坏但只能偏转投射物。这种护盾永远不会过载,但也无法完全阻挡攻击。</description>
|
||||||
|
<techLevel>Ultra</techLevel>
|
||||||
|
<recipeMaker>
|
||||||
|
<researchPrerequisite>WULA_Synth_Weapon_2_Stun_Technology</researchPrerequisite>
|
||||||
|
<unfinishedThingDef>UnfinishedBelt</unfinishedThingDef>
|
||||||
|
<recipeUsers Inherit="False">
|
||||||
|
<li>WULA_Cube_Productor_Energy</li>
|
||||||
|
</recipeUsers>
|
||||||
|
<skillRequirements>
|
||||||
|
<Crafting>6</Crafting>
|
||||||
|
</skillRequirements>
|
||||||
|
</recipeMaker>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Things/Item/Equipment/WeaponMelee/Knife</texPath>
|
||||||
|
<graphicClass>Graphic_Single</graphicClass>
|
||||||
|
</graphicData>
|
||||||
|
<costList>
|
||||||
|
<Steel>30</Steel>
|
||||||
|
<Plasteel>15</Plasteel>
|
||||||
|
<ComponentSpacer>2</ComponentSpacer>
|
||||||
|
<BroadshieldCore>1</BroadshieldCore>
|
||||||
|
</costList>
|
||||||
|
<statBases>
|
||||||
|
<WorkToMake>8000</WorkToMake>
|
||||||
|
<Mass>0.8</Mass>
|
||||||
|
<Flammability>0.4</Flammability>
|
||||||
|
</statBases>
|
||||||
|
<thingCategories>
|
||||||
|
<li>Apparel</li>
|
||||||
|
</thingCategories>
|
||||||
|
<apparel>
|
||||||
|
<bodyPartGroups>
|
||||||
|
<li>Waist</li>
|
||||||
|
</bodyPartGroups>
|
||||||
|
<wornGraphicPath>Things/Pawn/Humanlike/Apparel/ShieldBelt/ShieldBelt</wornGraphicPath>
|
||||||
|
<layers>
|
||||||
|
<li>Belt</li>
|
||||||
|
</layers>
|
||||||
|
<tags>
|
||||||
|
<li>BeltDefensePop</li>
|
||||||
|
</tags>
|
||||||
|
<defaultOutfitTags>
|
||||||
|
<li>Soldier</li>
|
||||||
|
</defaultOutfitTags>
|
||||||
|
</apparel>
|
||||||
|
<comps>
|
||||||
|
<li Class="WulaFallenEmpire.CompProperties_WulaShieldBelt">
|
||||||
|
<!-- 护盾最大生命值 - 在偏转模式下此值不重要,但仍需设置 -->
|
||||||
|
<maxShieldHitPoints>100</maxShieldHitPoints>
|
||||||
|
<!-- 护盾半径 - 护盾保护范围的半径(以格子为单位) -->
|
||||||
|
<shieldRadius>2.5</shieldRadius>
|
||||||
|
<!-- 拦截地面投射物 - 是否拦截子弹、箭矢等地面投射物 -->
|
||||||
|
<interceptGroundProjectiles>true</interceptGroundProjectiles>
|
||||||
|
<!-- 拦截空中投射物 - 是否拦截迫击炮弹等空中投射物 -->
|
||||||
|
<interceptAirProjectiles>false</interceptAirProjectiles>
|
||||||
|
<!-- 拦截近战攻击 - 是否能够阻挡近战攻击 -->
|
||||||
|
<interceptMeleeAttacks>false</interceptMeleeAttacks>
|
||||||
|
<!-- EMP免疫 - 是否免疫电磁脉冲攻击 -->
|
||||||
|
<empImmune>false</empImmune>
|
||||||
|
<!-- 护盾颜色 - 护盾显示的颜色 (R, G, B) 值范围0-1 -->
|
||||||
|
<shieldColor>(0.6, 1.0, 0.6)</shieldColor>
|
||||||
|
<!-- 充能速率 - 在偏转模式下此值不重要 -->
|
||||||
|
<rechargeRate>0</rechargeRate>
|
||||||
|
<!-- 充能冷却时间 - 在偏转模式下此值不重要 -->
|
||||||
|
<rechargeCooldownTicks>0</rechargeCooldownTicks>
|
||||||
|
<!-- 激活音效 - 护盾运行时播放的环境音效 -->
|
||||||
|
<activeSound>BulletShield_Ambience</activeSound>
|
||||||
|
<!-- 重新激活特效 - 护盾重新启动时播放的视觉特效 -->
|
||||||
|
<reactivateEffect>BulletShieldGenerator_Reactivate</reactivateEffect>
|
||||||
|
<!-- 初始启用状态 - 护盾腰带装备后是否默认开启 -->
|
||||||
|
<startEnabled>true</startEnabled>
|
||||||
|
<!-- 护盾模式 - false=无生命值模式(类似低角护盾,只偏转,永不破坏) -->
|
||||||
|
<useHitPointsMode>false</useHitPointsMode>
|
||||||
|
</li>
|
||||||
|
</comps>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
|
</Defs>
|
||||||
@@ -9,6 +9,7 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
{
|
{
|
||||||
|
Log.Message($"[EmergencyEnergyRestore] Apply method called for {parent.pawn?.LabelShort}");
|
||||||
base.Apply(target, dest);
|
base.Apply(target, dest);
|
||||||
|
|
||||||
Pawn caster = parent.pawn;
|
Pawn caster = parent.pawn;
|
||||||
@@ -45,14 +46,9 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
{
|
{
|
||||||
bool canApply = base.CanApplyOn(target, dest) && IsWulaRace(parent.pawn);
|
Log.Message($"[EmergencyEnergyRestore] CanApplyOn called. Pawn: {parent.pawn?.LabelShort}");
|
||||||
|
// 暂时强制返回true,以排除CanApplyOn的限制
|
||||||
if (Props.requireDowned)
|
return true;
|
||||||
{
|
|
||||||
canApply = canApply && parent.pawn.Downed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return canApply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsWulaRace(Pawn pawn)
|
private bool IsWulaRace(Pawn pawn)
|
||||||
@@ -61,4 +57,4 @@ namespace WulaFallenEmpire
|
|||||||
return pawn.def.defName == "WulaSpecies";
|
return pawn.def.defName == "WulaSpecies";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
Source/WulaFallenEmpire/CompProperties_WulaShieldBelt.cs
Normal file
31
Source/WulaFallenEmpire/CompProperties_WulaShieldBelt.cs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
365
Source/WulaFallenEmpire/CompWulaShieldBelt.cs
Normal file
365
Source/WulaFallenEmpire/CompWulaShieldBelt.cs
Normal file
@@ -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<Gizmo> CompGetWornGizmosExtra()
|
||||||
|
{
|
||||||
|
// 确保穿戴者存在
|
||||||
|
Pawn wearer = GetWearer();
|
||||||
|
if (wearer == null) yield break;
|
||||||
|
|
||||||
|
// 不限制只有选中时才显示
|
||||||
|
yield return new Command_Toggle
|
||||||
|
{
|
||||||
|
defaultLabel = "护盾开关",
|
||||||
|
defaultDesc = shieldEnabled ? "关闭护盾" : "激活护盾",
|
||||||
|
icon = ContentFinder<Texture2D>.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 "护盾: 已关闭";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
136
Source/WulaFallenEmpire/EmergencyAbilityPatches.cs
Normal file
136
Source/WulaFallenEmpire/EmergencyAbilityPatches.cs
Normal file
@@ -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<Ability> __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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,13 +14,15 @@
|
|||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>..\..\1.6\Assemblies\</OutputPath>
|
<OutputPath>..\..\1.6\Assemblies\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
<AllowedReferenceRelatedFileExtensions>.allowedextension</AllowedReferenceRelatedFileExtensions>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
@@ -80,6 +82,16 @@
|
|||||||
<Compile Include="Hediff_EmergencyEnergyRestore.cs" />
|
<Compile Include="Hediff_EmergencyEnergyRestore.cs" />
|
||||||
<Compile Include="CompProperties_AbilityEmergencyEnergyRestore.cs" />
|
<Compile Include="CompProperties_AbilityEmergencyEnergyRestore.cs" />
|
||||||
<Compile Include="CompAbilityEffect_EmergencyEnergyRestore.cs" />
|
<Compile Include="CompAbilityEffect_EmergencyEnergyRestore.cs" />
|
||||||
|
<Compile Include="CompProperties_WulaShieldBelt.cs" />
|
||||||
|
<Compile Include="CompWulaShieldBelt.cs" />
|
||||||
|
<Compile Include="WulaShieldBeltPatches.cs" />
|
||||||
|
<Compile Include="EmergencyAbilityPatches.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|
||||||
|
<!-- 自定义清理任务,删除obj文件夹中的临时文件 -->
|
||||||
|
<Target Name="CleanDebugFiles" AfterTargets="Build">
|
||||||
|
<RemoveDir Directories="$(ProjectDir)obj\Debug" />
|
||||||
|
<RemoveDir Directories="$(ProjectDir)obj\Release" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ namespace WulaFallenEmpire
|
|||||||
// 初始化Harmony
|
// 初始化Harmony
|
||||||
var harmony = new Harmony("tourswen.wulafallenempire"); // 替换为您的唯一Mod ID
|
var harmony = new Harmony("tourswen.wulafallenempire"); // 替换为您的唯一Mod ID
|
||||||
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
harmony.PatchAll(Assembly.GetExecutingAssembly());
|
||||||
|
|
||||||
|
// 手动应用护盾腰带的近战拦截补丁
|
||||||
|
WulaShieldBeltPatches.ApplyMeleePatch(harmony);
|
||||||
|
|
||||||
Log.Message("[WulaFallenEmpire] Harmony patches applied.");
|
Log.Message("[WulaFallenEmpire] Harmony patches applied.");
|
||||||
}
|
}
|
||||||
|
|||||||
97
Source/WulaFallenEmpire/WulaShieldBeltPatches.cs
Normal file
97
Source/WulaFallenEmpire/WulaShieldBeltPatches.cs
Normal file
@@ -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<CompWulaShieldBelt>();
|
||||||
|
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<CompWulaShieldBelt>();
|
||||||
|
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; // 如果已经被拦截了就不需要再检查
|
||||||
|
|
||||||
|
// 这个补丁确保我们的护盾系统与原版的投射物拦截系统兼容
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
Source/WulaFallenEmpire/clean.bat
Normal file
5
Source/WulaFallenEmpire/clean.bat
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@echo off
|
||||||
|
echo 清理临时文件...
|
||||||
|
if exist "obj" rmdir /s /q obj
|
||||||
|
if exist "bin" rmdir /s /q bin
|
||||||
|
echo 清理完成!
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
981fae8ea86dc7ccc506adb49b6855ce4c202ff9e230c7a6c385d9789ef4b0aa
|
|
||||||
@@ -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
|
|
||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user