This commit is contained in:
2025-10-15 14:03:08 +08:00
parent 4d743c74e0
commit 601d20b6a1
8 changed files with 12 additions and 325 deletions

Binary file not shown.

View File

@@ -1,112 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- 首先是冷冻效果的定义 -->
<HediffDef>
<defName>ARA_Hediff_Frozen</defName>
<label>冷冻中</label>
<description>这个身体部位正在被冷冻。移动会因此减慢。如果该部位被完全冷冻,它将在下一次受到冲击时碎裂。</description>
<hediffClass>ArachnaeSwarm.Hediff_Frozen</hediffClass>
<isBad>true</isBad>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-6</severityPerDay>
</li>
<li Class="ArachnaeSwarm.HediffCompProperties_GlobalFreeze">
<stunThreshold>0.3</stunThreshold> <!-- 全身30%的健康值被转化为冷冻值时,目标将被眩晕 -->
</li>
<li Class="HediffCompProperties_DisappearsOnDeath"/>
</comps>
<injuryProps>
<painPerSeverity>0</painPerSeverity>
<canMerge>true</canMerge>
<destroyedLabel>已碎裂</destroyedLabel>
</injuryProps>
<stages>
<li>
<label>轻微</label>
<becomeVisible>true</becomeVisible>
</li>
<li>
<label>轻微</label>
<minSeverity>0.2</minSeverity>
<statOffsets>
<ComfyTemperatureMin>40</ComfyTemperatureMin>
</statOffsets>
<capMods>
</capMods>
</li>
<li>
<label>中等</label>
<minSeverity>0.35</minSeverity>
<statOffsets>
<ComfyTemperatureMin>80</ComfyTemperatureMin>
</statOffsets>
<capMods>
<li>
<capacity>Moving</capacity>
<offset>-0.1</offset>
</li>
<li>
<capacity>Manipulation</capacity>
<offset>-0.2</offset>
</li>
</capMods>
</li>
<li>
<label>严重</label>
<minSeverity>0.5</minSeverity>
<statOffsets>
<ComfyTemperatureMin>120</ComfyTemperatureMin>
</statOffsets>
<capMods>
<li>
<capacity>Moving</capacity>
<offset>-0.3</offset>
</li>
<li>
<capacity>Manipulation</capacity>
<offset>-0.4</offset>
</li>
</capMods>
</li>
<li>
<label>极度</label>
<minSeverity>0.65</minSeverity>
<statOffsets>
<ComfyTemperatureMin>160</ComfyTemperatureMin>
</statOffsets>
<capMods>
<li>
<capacity>Moving</capacity>
<offset>-0.5</offset>
</li>
<li>
<capacity>Manipulation</capacity>
<offset>-0.6</offset>
</li>
</capMods>
</li>
<li>
<label>完全</label>
<minSeverity>0.85</minSeverity>
<statOffsets>
<ComfyTemperatureMin>200</ComfyTemperatureMin>
</statOffsets>
<capMods>
<li>
<capacity>Moving</capacity>
<setMax>0.2</setMax>
</li>
<li>
<capacity>Manipulation</capacity>
<setMax>0.2</setMax>
</li>
</capMods>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_Hediff_FrostCoverd_after</defName>
<label>霜冻覆盖</label>
@@ -230,14 +124,13 @@
</HediffDef>
<!-- 然后是冷冻伤害本身的定义 -->
<DamageDef>
<DamageDef Name="ARA_Damage_Freeze">
<defName>ARA_Damage_Freeze</defName>
<label>冷冻</label>
<workerClass>DamageWorker_AddInjury</workerClass> <!-- 使用原版的伤害工人 -->
<workerClass>DamageWorker_Frostbite</workerClass> <!-- 使用原版的伤害工人 -->
<externalViolence>true</externalViolence>
<deathMessage>{0}的身体在极寒中化为了冰雕,随后碎裂四散。</deathMessage>
<hediff>ARA_Hediff_Frozen</hediff> <!-- 核心将伤害转化为这个Hediff的严重性 -->
<hediffSolid>ARA_Hediff_Frozen</hediffSolid> <!-- 对非血肉生物也使用这个Hediff -->
<hediff>Frostbite</hediff> <!-- 核心将伤害转化为这个Hediff的严重性 -->
<harmsHealth>false</harmsHealth> <!-- 核心!不造成常规生命值伤害 -->
<armorCategory>Heat</armorCategory> <!-- 可以被抗热/冷的护甲减免 -->
<overkillPctToDestroyPart>0</overkillPctToDestroyPart> <!-- 伤害足够时直接摧毁我们的C#代码会处理这个) -->
@@ -245,29 +138,21 @@
<defaultArmorPenetration>0</defaultArmorPenetration>
<buildingDamageFactorImpassable>0</buildingDamageFactorImpassable>
<buildingDamageFactorPassable>0</buildingDamageFactorPassable>
<explosionHeatEnergyPerCell>-15</explosionHeatEnergyPerCell>
<explosionCellFleck>BlastFlame</explosionCellFleck>
<explosionColorCenter>(0.52, 0.7, 0.95,0.5)</explosionColorCenter>
<explosionColorEdge>(0.52, 1, 0.95,0.5)</explosionColorEdge>
<soundExplosion>Explosion_Flame</soundExplosion>
</DamageDef>
<!-- 然后是冷冻伤害本身的定义 -->
<DamageDef>
<DamageDef ParentName="ARA_Damage_Freeze">
<defName>ARA_Damage_Freeze_ex</defName>
<label>冷冻</label>
<workerClass>DamageWorker_AddInjury</workerClass> <!-- 使用原版的伤害工人 -->
<externalViolence>true</externalViolence>
<deathMessage>{0}的身体在极寒中化为了冰雕,随后碎裂四散。</deathMessage>
<hediff>ARA_Hediff_Frozen</hediff> <!-- 核心将伤害转化为这个Hediff的严重性 -->
<hediffSolid>ARA_Hediff_Frozen</hediffSolid> <!-- 对非血肉生物也使用这个Hediff -->
<harmsHealth>false</harmsHealth> <!-- 核心!不造成常规生命值伤害 -->
<armorCategory>Heat</armorCategory> <!-- 可以被抗热/冷的护甲减免 -->
<overkillPctToDestroyPart>0</overkillPctToDestroyPart> <!-- 伤害足够时直接摧毁我们的C#代码会处理这个) -->
<defaultDamage>3</defaultDamage>
<defaultArmorPenetration>0</defaultArmorPenetration>
<buildingDamageFactorImpassable>0</buildingDamageFactorImpassable>
<buildingDamageFactorPassable>0</buildingDamageFactorPassable>
<additionalHediffs>
<li>
<hediff>ARA_CryoShock</hediff>
<severityPerDamageDealt>0.01</severityPerDamageDealt>
</li>
<hediff>ARA_CryoShock</hediff>
<severityPerDamageDealt>0.01</severityPerDamageDealt>
</li>
<li>
<hediff>ARA_Hediff_FrostCoverd_after</hediff>
<severityPerDamageDealt>0.01</severityPerDamageDealt>

View File

@@ -108,7 +108,6 @@
<postExplosionSpawnChance>1</postExplosionSpawnChance>
<postExplosionSpawnThingCount>1</postExplosionSpawnThingCount>
<soundExplode>Explosion_Stun</soundExplode>
<doExplosionVFX>false</doExplosionVFX>
</projectile>
<comps>
<li Class="CompProperties_ProjectileEffecter">

View File

@@ -6,9 +6,6 @@ namespace ArachnaeSwarm
[DefOf]
public static class ARA_HediffDefOf
{
public static HediffDef ARA_Hediff_Frozen;
public static HediffDef ARA_Hediff_FrostCoverd_after;
public static HediffDef ARA_CryoShock;
public static HediffDef ARA_HiveMindMaster;
public static HediffDef ARA_HiveMindDrone;
public static HediffDef ARA_HiveMindWorker; // 如果存在这个Def

View File

@@ -193,8 +193,6 @@
<Compile Include="Hediffs\MoharHediffs\Tools.cs" />
<Compile Include="Hediffs\ProphecyGearEffect.cs" />
<Compile Include="HediffComp_TimedExplosion.cs" />
<Compile Include="Hediff_Frozen.cs" />
<Compile Include="HediffComp_GlobalFreeze.cs" />
<Compile Include="Hediffs\WULA_HediffDamgeShield\DRMDamageShield.cs" />
<Compile Include="Hediffs\WULA_HediffDamgeShield\Hediff_DamageShield.cs" />
<Compile Include="Thing_Comps\ARA_ThingComp_GuardianPsyField\Hediff_DynamicInterceptor.cs" />
@@ -275,7 +273,6 @@
<Compile Include="Buildings\Building_CatastropheMissileSilo\Building_CatastropheMissileSilo.cs" />
<Compile Include="Buildings\Building_CatastropheMissileSilo\WorldObject_CatastropheMissile.cs" />
<Compile Include="HarmonyPatches\Patch_ForceTargetable.cs" />
<Compile Include="HarmonyPatch_Pawn_HealthTracker_PreApplyDamage.cs" />
<Compile Include="Building_Comps\CompForceTargetable.cs" />
<Compile Include="PowerArmor\ARA_PowerArmor.cs" />
<Compile Include="PowerArmor\CompPowerArmorStation.cs" />

View File

@@ -1,73 +0,0 @@
using HarmonyLib;
using RimWorld;
using Verse;
using System.Linq;
using UnityEngine; // For FleckMaker
namespace ArachnaeSwarm
{
// Harmony 入口点,将在 Mod 加载时自动初始化
[StaticConstructorOnStartup]
public static class HarmonyPatches
{
static HarmonyPatches()
{
var harmony = new Harmony("ArachnaeSwarm.FreezeMod");
harmony.PatchAll();
}
}
// 补丁目标Pawn_HealthTracker 类的 PreApplyDamage 方法
[HarmonyPatch(typeof(Pawn_HealthTracker), "PreApplyDamage")]
public static class HarmonyPatch_Pawn_HealthTracker_PreApplyDamage
{
// Postfix 补丁:在原方法执行后运行
// __instance 是 Pawn_HealthTracker 的实例
// dinfo 是 DamageInfo 的引用
// absorbed 是 out bool 参数的引用
public static void Postfix(Pawn_HealthTracker __instance, ref DamageInfo dinfo, ref bool absorbed)
{
// 如果伤害已经被吸收,或者没有击中任何部位,则不处理
if (absorbed || dinfo.HitPart == null)
{
return;
}
Pawn pawn = (Pawn)AccessTools.Field(typeof(Pawn_HealthTracker), "pawn").GetValue(__instance);
if (pawn == null)
{
return;
}
// 复制一份 dinfo避免 ref 参数在 lambda 中使用的问题
DamageInfo currentDinfo = dinfo;
// 获取被击中部位上的 Hediff_Frozen
Hediff_Frozen frozenHediff = pawn.health.hediffSet.hediffs.OfType<Hediff_Frozen>()
.FirstOrDefault(h => h.Part == currentDinfo.HitPart);
// 如果该部位存在 Hediff_Frozen 并且已经完全冷冻
if (frozenHediff != null && frozenHediff.Severity >= currentDinfo.HitPart.def.GetMaxHealth(pawn))
{
// 检查伤害是否是我们的冷冻伤害(防止循环触发)
if (currentDinfo.Def.hediff == ARA_HediffDefOf.ARA_Hediff_Frozen)
{
return; // 忽略我们自己的冷冻伤害
}
// 检查伤害是否是会造成生命值损伤的普通伤害
if (currentDinfo.Def.harmsHealth && currentDinfo.Amount > 0.01f)
{
// 施加一个巨大的、足以摧毁该部位的伤害
DamageInfo fatalDamage = new DamageInfo(DamageDefOf.Crush, 99999f, 999f, -1f, currentDinfo.Instigator, currentDinfo.HitPart);
pawn.TakeDamage(fatalDamage);
// 播放一个破碎的特效
FleckMaker.Static(pawn.Position, pawn.Map, FleckDefOf.ExplosionFlash, 2f);
absorbed = true; // 标记原伤害已被处理,阻止其继续执行
}
}
}
}
}

View File

@@ -1,72 +0,0 @@
using RimWorld;
using Verse;
using System.Linq;
namespace ArachnaeSwarm
{
public class HediffComp_GlobalFreeze : HediffComp
{
private const int CheckInterval = 60; // 每60 ticks检查一次 (1秒)
private bool isStunnedByFreeze = false; // 用于追踪是否是由我们这个组件造成的眩晕
public HediffCompProperties_GlobalFreeze Props => (HediffCompProperties_GlobalFreeze)props;
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
// 每隔一段时间才执行一次,避免性能问题
if (Pawn.IsHashIntervalTick(CheckInterval))
{
// 计算全身所有Hediff_Frozen的总严重性
float totalFreezeSeverity = Pawn.health.hediffSet.hediffs
.OfType<Hediff_Frozen>()
.Sum(h => h.Severity);
// 获取Pawn的总生命值作为参考
float totalBodyHealth = Pawn.health.summaryHealth.SummaryHealthPercent * Pawn.MaxHitPoints;
// 计算冷冻阈值
float stunThreshold = totalBodyHealth * Props.stunThreshold;
// 如果总冷冻值超过阈值
if (totalFreezeSeverity >= stunThreshold)
{
// 如果Pawn当前没有被眩晕则施加一个“永久”的眩晕
// StunFor会取最大值所以我们给一个足够长的时间5秒它会在下一轮检查时被刷新
if (!Pawn.stances.stunner.Stunned)
{
Pawn.stances.stunner.StunFor(300, Pawn, false, true);
isStunnedByFreeze = true;
}
}
// 如果总冷冻值低于阈值,并且之前是由我们造成的眩晕
else if (isStunnedByFreeze)
{
// 立即停止眩晕
// 我们通过将stunTicksLeft设置为0来直接唤醒它
Pawn.stances.stunner.StunFor(0, Pawn, false, false);
isStunnedByFreeze = false;
}
}
}
// 保存和加载我们的状态,确保读档后逻辑正确
public override void CompExposeData()
{
base.CompExposeData();
Scribe_Values.Look(ref isStunnedByFreeze, "isStunnedByFreeze", false);
}
}
public class HediffCompProperties_GlobalFreeze : HediffCompProperties
{
// XML中可配置的阈值默认为全身健康的30%
public float stunThreshold = 0.3f;
public HediffCompProperties_GlobalFreeze()
{
compClass = typeof(HediffComp_GlobalFreeze);
}
}
}

View File

@@ -1,46 +0,0 @@
using RimWorld;
using Verse;
using UnityEngine;
namespace ArachnaeSwarm
{
public class Hediff_Frozen : Hediff_Injury
{
// 我们需要覆盖这个方法来改变在健康面板上显示的标签
public override string LabelInBrackets
{
get
{
// 如果严重性达到了部位的满生命值,就显示“完全冷冻”
if (Severity >= Part.def.GetMaxHealth(pawn))
{
return "Fully Frozen";
}
return base.LabelInBrackets;
}
}
// 当部位的疼痛感,可以根据严重性调整
public override float PainOffset
{
get
{
// 冷冻不造成额外疼痛
return 0f;
}
}
// 当一个部位的伤害被治疗(在这里就是冷冻值减少)时调用
public override void Heal(float amount)
{
// 减少严重性但不让它低于0
Severity -= amount;
if (Severity < 0)
{
Severity = 0;
}
}
// 伤害拦截逻辑将通过 Harmony 补丁实现,不在 Hediff 内部处理
}
}