diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index 9c8e840..ccf51d0 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Damage.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Damage.xml
index fabf12f..d23ca6d 100644
--- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Damage.xml
+++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Damage.xml
@@ -197,142 +197,5 @@
-
- ARA_MimicNematode
- 拟线种虫族寄生
- 被阿拉克涅拟线种虫族寄生了,如果不加以干预,拟线虫最终会杀死宿主并将其转化为没有意识的寄生体。拟线虫会通过寄生体的攻击行为感染其他躯体。
-
- ArachnaeSwarm.Hediff_NecroticVirus
- (0.6, 0.4, 0.8)
-
- true
- 1.0
- 1.0
- 0.001
- 0.001
- false
-
-
-
- 潜伏期
- false
- 5
-
-
- 活跃期
- 0.5
- 1
- 0.5
- false
-
-
- Talking
- 0
-
-
-
-
- 终末期
- 0.7
- 0.5
- 0
- true
- true
-
-
- Talking
- 0
-
-
- Consciousness
- 0.7
-
-
-
-
- 即将转化
- 0.9
- 0.5
- 2.0
- true
- true
-
-
- Talking
- 0
-
-
- Consciousness
- 0.1
-
-
-
-
- true
-
-
-
- 0.3
-
-
- -1
- 24
-
-
- 1800000~2400000
- true
-
-
-
-
- Shambler
-
-
-
-
-
-
- ARA_MimicNematode
-
-
- true
- 0.05
- ARA_MimicNematodeBite
-
-
-
-
-
-
- ARA_CureBloodRot
- 清除拟线虫感染
- 通过多种药物联合靶向治疗清除患者体内的阿拉克涅拟线种虫族感染。
- Recipe_RemoveHediff
- 清除拟线虫感染.
- 2000
- true
- false
- false
- ARA_MimicNematode
- {0} 成功清除了 {1} 体内的拟线虫感染.
-
- 5
-
-
-
-
-
- MedicineUltratech
-
-
- 10
-
-
-
-
- Medicine
-
-
-
\ No newline at end of file
diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Mutants_Configurable.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Mutants_Configurable.xml
new file mode 100644
index 0000000..4e7ec6a
--- /dev/null
+++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Mutants_Configurable.xml
@@ -0,0 +1,249 @@
+
+
+
+
+ ARA_MimicNematode
+ 拟线种虫族寄生
+ 被阿拉克涅拟线种虫族寄生了,如果不加以干预,拟线虫最终会杀死宿主并将其转化为没有意识的寄生体。拟线虫会通过寄生体的攻击行为感染其他躯体。
+
+
+ ArachnaeSwarm.Hediff_NecroticVirus
+ (0.6, 0.4, 0.8)
+
+ true
+ 1.0
+ 1.0
+ 0.001
+ 0.001
+ false
+
+
+
+ 潜伏期
+ false
+ 5
+
+
+ 活跃期
+ 0.5
+ 1
+ 0.5
+ false
+
+
+ Talking
+ 0
+
+
+
+
+ 终末期
+ 0.7
+ 0.5
+ 0
+ true
+ true
+
+
+ Talking
+ 0
+
+
+ Consciousness
+ 0.7
+
+
+ 50
+
+
+ 即将转化
+ 0.9
+ 0.5
+ 2.0
+ true
+ true
+
+
+ Talking
+ 0
+
+
+ Consciousness
+ 0.1
+
+
+ 50
+
+
+ true
+
+
+
+ 0.3
+
+
+ -1
+ 24
+
+
+ 1800000~2400000
+ true
+
+
+
+
+ ARA_MimicNematodeShambler
+ 0.7
+
+
+
+
+
+
+ ARA_MimicNematode
+
+
+ true
+ 0.05
+ ARA_MimicNematodeBite
+
+
+
+
+
+
+ ARA_CureBloodRot
+ 清除拟线虫感染
+ 通过多种药物联合靶向治疗清除患者体内的阿拉克涅拟线种虫族感染。
+ Recipe_RemoveHediff
+ 清除拟线虫感染.
+ 2000
+ true
+ false
+ false
+ ARA_MimicNematode
+ {0} 成功清除了 {1} 体内的拟线虫感染.
+
+ 5
+
+
+
+
+
+ MedicineUltratech
+
+
+ 10
+
+
+
+
+ Medicine
+
+
+
+
+
+
+ ARA_MimicNematodeShambler
+ 阿拉克涅拟线种寄生体
+ 这具尸体被一种阿拉克涅拟线虫所寄生并重新激活。被寄生的生物行动迟缓、没有心智,只会无情地攻击任何活物。在活动几天后,寄生体将因宿主新陈代谢衰竭而死亡。被捕获并固定后,寄生体无法移动,因此其生命活动会暂停。
+ ArachnaeSwarm.Hediff_ConfigurableMutant
+ (0.6, 0.4, 0.8)
+ false
+ false
+ True
+
+
+ 0
+ 0
+
+ 1.5
+ 0
+
+
+ -60
+ 30
+ 25
+ 1
+
+
+ Talking 0
+ Consciousness 0.7
+
+ 200
+
+
+
+
+
+ HediffComp_DisappearsAndKills_Shambler
+ 1800000~2400000
+ true
+
+
+
+
+
+
+
+ ARA_Rising
+ ARA_MimicNematodeShamblerShamblerCorpse
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ ARA_Rising
+ 起身中
+ 阿拉克涅拟线虫寄生赋予的强大再生能力正在复苏这具身体。
+ false
+ false
+ (0.6, 0.4, 0.8)
+
+
+ 0
+
+ Moving 0
+ Manipulation 0
+ Talking 0
+ Consciousness 0.1
+
+
+
+
+
+
+ ARA_MimicNematodeShamblerShamblerCorpse
+ 拟线种寄生体尸体
+ 这具身体刚刚被阿拉克涅拟线种寄生"复活"过。
+ true
+ (0.6, 0.4, 0.8)
+
+
+ Shambler wounds
+ PawnRenderNodeWorker_OverlayShambler
+ Body
+ 20
+ HumanlikeOnly
+
+
+ Shambler wounds
+ PawnRenderNode_AnimalPart
+ PawnRenderNodeWorker_OverlayShambler
+ Body
+ 20
+ NonHumanlikeOnly
+
+
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceMutant.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceMutant.xml
index 2b5799a..d567d28 100644
--- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceMutant.xml
+++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceMutant.xml
@@ -3,14 +3,14 @@
ARA_MimicNematodeShambler
- MimicNematode shambler
- A creature who has been raised from the dead by corrupted nano-scale archites.\n\nAbout shamblers: Shamblers are corpses which have been reanimated by archotechnology. They attack living creatures relentlessly and their immunity to pain makes them difficult to kill. However, the archites which animate them cannot sustain the rotting body for long, so shamblers expire after a few days of movement.\n\nThere are ways to raise your own shamblers and make yourself invisible to them, so they attack only outsiders.
- Shambler
+ 阿拉克涅拟线种寄生体
+ 阿拉克涅拟线种是虫群中最神秘的分支之一。它们与原虫种同源,但在进化之路上并未发展出高级智慧,而是走向了一条截然不同的道路:寄生。拟线种是无法脱离宿主独立存活的寄生虫。一旦寄生于生物体内,它们会长期潜伏,最终逐步接管宿主的神经与代谢系统,将其变为受其操控的行尸走肉——“寄生体”。得益于超凡的细胞复制与再生能力,拟线种能够模仿并替代宿主的细胞结构,这使得寄生体拥有了惊人的自我修复能力。然而,这种寄生关系也极具侵略性:拟线种的虫卵遍布寄生体体表,任何被寄生体攻击的生物都有可能被感染,最终沦为新的寄生体。尽管拟线虫将寄生体的新陈代谢维持在极低水平,但寄生体本身并不会主动觅食。因此,当能量耗尽后,它们终将迎来“死亡”。
+ ARA_MimicNematodeShambler
Shambler
ShamblerConstant
true
- shambler
- true
+ 拟线种寄生体
+ false
true
Filth_DarkBlood
Filth_DarkBloodSmear
@@ -34,7 +34,7 @@
(0.3, 0.3, 0.0, 1.0)
0
Basic
- Shambler
+
0.25
Pawn_Shambler_Call
@@ -64,7 +64,7 @@
teeth
- Bite
+ ARA_MimicNematodeShamblerBite
8.2
2
@@ -100,14 +100,32 @@
+
+ ARA_MimicNematodeShamblerBite
+ 撕咬
+
+
+ ARA_MimicNematodeShamblerBite
+ ARA_MimicNematodeShamblerBite
+
+ Verb_MeleeAttackDamage
+ ARA_MimicNematodeBite
+
+ MeleeAttack
+ Maneuver_Slash_MeleeHit
+ Maneuver_Slash_MeleeDeflect
+ Maneuver_Slash_MeleeMiss
+ Maneuver_Slash_MeleeDodge
+
+
- Shambler
+ ARA_MimicNematodeShambler
false
ARA_MimicNematodeShamblerSwarmer
- shambler swarmer
+ 阿拉克涅拟线种寄生体
40
0.2~0.4
Poor
diff --git a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
index e54884e..1fbb4db 100644
--- a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
+++ b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
@@ -564,4 +564,68 @@
+
+
+ ARA_MW_Mimic_Niddle
+ 武装器官"拟线种毒针"
+ 阿拉克涅虫群督虫使用基础近战武装器官,通过多根外露神经束与督虫的辅肢相连。这根毒针中藏有休眠中的阿拉克涅拟线种虫卵,攻击将感染受害者使其最终成为被拟线虫操控的寄生体。
+
+ ARA_Armed_Organ
+ ARA_Armed_Organ_Melee
+ ARA_Armed_Organ_T1
+
+
+ ArachnaeSwarm/Weapon/ARA_MW_Bone_Sword
+ Graphic_Single
+ CutoutComplex
+ 1
+
+ 1
+
+ Animal
+
+ 0
+
+
+ 50
+
+
+ 1000
+ 5
+
+
+
+ 割
+
+ Cut
+
+ 15
+ 1.3
+ 0.50
+
+
+ 刺
+
+ Poke
+
+ 12
+ 0.20
+ 1.5
+
+
+ ARA_MimicNematodeBite
+ 4
+
+
+
+
+
+
+
+ UnfinishedWeapon
+
+
+ RewardStandardQualitySuper
+
+
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index fc3601e..c6152d2 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -189,6 +189,7 @@
+
diff --git a/Source/ArachnaeSwarm/HediffComp_NecroticTransformation.cs b/Source/ArachnaeSwarm/HediffComp_NecroticTransformation.cs
index ac96aa0..6219903 100644
--- a/Source/ArachnaeSwarm/HediffComp_NecroticTransformation.cs
+++ b/Source/ArachnaeSwarm/HediffComp_NecroticTransformation.cs
@@ -10,6 +10,9 @@ namespace ArachnaeSwarm
{
// 在XML中需要指定的MutantDef的defName
public MutantDef mutantDef;
+
+ // 在XML中配置触发转变所需的严重性阈值
+ public float triggerSeverity = 0.7f;
public HediffCompProperties_NecroticTransformation()
{
diff --git a/Source/ArachnaeSwarm/Hediff_ConfigurableMutant.cs b/Source/ArachnaeSwarm/Hediff_ConfigurableMutant.cs
new file mode 100644
index 0000000..6498f1a
--- /dev/null
+++ b/Source/ArachnaeSwarm/Hediff_ConfigurableMutant.cs
@@ -0,0 +1,374 @@
+using System.Collections.Generic;
+using RimWorld;
+using UnityEngine;
+using Verse;
+using Verse.AI;
+using Verse.AI.Group;
+using Verse.Sound;
+
+namespace ArachnaeSwarm
+{
+ public class HediffCompProperties_ConfigurableMutant : HediffCompProperties
+ {
+ // --- 可配置的Hediff ---
+ public HediffDef risingHediff;
+ public HediffDef corpseHediff;
+
+ // --- 可配置的时间和范围 ---
+ public FloatRange resurrectionSecondsRange = new FloatRange(5f, 10f);
+ public FloatRange stunSecondsRange = new FloatRange(1f, 3f);
+ public FloatRange alertSecondsRange = new FloatRange(0.5f, 3f);
+ public IntRange selfRaiseHoursRange = new IntRange(3, 4);
+ public IntRange checkForTargetTicksInterval = new IntRange(900, 1800);
+
+ // --- 可配置的杂项值 ---
+ public float particleSpawnMTBSeconds = 1f;
+ public float extinguishFireMTB = 45f;
+ public float bioferriteOnDeathChance = 0.04f;
+ public int bioferriteAmountOnDeath = 10;
+
+ public HediffCompProperties_ConfigurableMutant()
+ {
+ this.compClass = typeof(HediffComp_ConfigurableMutant);
+ }
+ }
+
+ public class HediffComp_ConfigurableMutant : HediffComp
+ {
+ public HediffCompProperties_ConfigurableMutant Props => (HediffCompProperties_ConfigurableMutant)this.props;
+ }
+
+ public class Hediff_ConfigurableMutant : HediffWithComps
+ {
+ // 运行时状态字段,保持不变
+ public float headRotation;
+ private float resurrectTimer;
+ private float selfRaiseTimer;
+ private float alertTimer;
+ private int nextTargetCheckTick = -99999;
+ private Thing alertedTarget;
+ private Effecter riseEffecter;
+ private Sustainer riseSustainer;
+ private float corpseDamagePct = 1f;
+
+ private HediffComp_ConfigurableMutant PropsComp => this.TryGetComp();
+
+ public bool IsRising => PropsComp?.Props.risingHediff != null && pawn.health.hediffSet.HasHediff(PropsComp.Props.risingHediff);
+
+ public override void PostMake()
+ {
+ base.PostMake();
+ headRotation = Rand.RangeSeeded(-20f, 20f, pawn.thingIDNumber);
+ if (!pawn.Dead)
+ {
+ pawn.timesRaisedAsShambler++;
+ }
+ }
+
+ public override void PostAdd(DamageInfo? dinfo)
+ {
+ if (!ModLister.CheckAnomaly("Shambler"))
+ {
+ pawn.health.RemoveHediff(this);
+ }
+ else
+ {
+ base.PostAdd(dinfo);
+ }
+ }
+
+ public override void Notify_Spawned()
+ {
+ base.Notify_Spawned();
+ pawn.Map.mapPawns.RegisterShambler(pawn);
+ }
+
+ public override void TickInterval(int delta)
+ {
+ base.TickInterval(delta);
+ var compProps = PropsComp?.Props;
+ if (compProps == null) return; // 如果没有Comp,则不执行任何操作
+
+ if (IsRising)
+ {
+ if ((float)Find.TickManager.TicksGame > resurrectTimer)
+ {
+ FinishRising();
+ }
+ if (!pawn.Spawned) return;
+
+ if ((float)Find.TickManager.TicksGame > resurrectTimer - 15f)
+ {
+ riseSustainer?.End();
+ }
+ else if (IsRising)
+ {
+ if (riseSustainer == null || riseSustainer.Ended)
+ {
+ riseSustainer = SoundDefOf.Pawn_Shambler_Rise.TrySpawnSustainer(SoundInfo.InMap(pawn, MaintenanceType.PerTick));
+ }
+ if (riseEffecter == null)
+ {
+ riseEffecter = EffecterDefOf.ShamblerRaise.Spawn(pawn, pawn.Map);
+ }
+ if (pawn.Drawer.renderer.CurAnimation != AnimationDefOf.ShamblerRise)
+ {
+ pawn.Drawer.renderer.SetAnimation(AnimationDefOf.ShamblerRise);
+ }
+ riseSustainer.Maintain();
+ riseEffecter.EffectTick(pawn, TargetInfo.Invalid);
+ }
+ return;
+ }
+
+ if (Rand.MTBEventOccurs(compProps.particleSpawnMTBSeconds, 60f, 1f))
+ {
+ FleckMaker.ThrowShamblerParticles(pawn);
+ }
+ if (pawn.IsBurning() && !pawn.Downed && Rand.MTBEventOccurs(compProps.extinguishFireMTB, 60f, 1f))
+ {
+ ((Fire)pawn.GetAttachment(ThingDefOf.Fire))?.Destroy();
+ pawn.records.Increment(RecordDefOf.FiresExtinguished);
+ }
+ if (pawn.Spawned && pawn.mutant != null && !pawn.mutant.IsPassive && !pawn.Drafted)
+ {
+ if (Find.TickManager.TicksGame > nextTargetCheckTick)
+ {
+ nextTargetCheckTick = Find.TickManager.TicksGame + compProps.checkForTargetTicksInterval.RandomInRange;
+ Thing thing = MutantUtility.FindShamblerTarget(pawn);
+ if (thing != null)
+ {
+ Notify_DelayedAlert(thing);
+ MutantUtility.ActivateNearbyShamblers(pawn, thing);
+ }
+ }
+ if (alertedTarget != null && (float)Find.TickManager.TicksGame > alertTimer)
+ {
+ pawn.mindState.enemyTarget = alertedTarget;
+ pawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; // 直接给public字段赋值,绕过internal方法
+ pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
+ alertedTarget = null;
+ if (DebugViewSettings.drawShamblerAlertMote)
+ {
+ MoteMaker.MakeColonistActionOverlay(pawn, ThingDefOf.Mote_ShamblerAlert);
+ }
+ SoundDefOf.Pawn_Shambler_Alert.PlayOneShot(pawn);
+ }
+ }
+ if (ShouldSelfRaise())
+ {
+ StartRising();
+ }
+ }
+
+ private bool ShouldSelfRaise()
+ {
+ if (pawn.DevelopmentalStage == DevelopmentalStage.Baby) return false;
+ return pawn.Downed && pawn.CarriedBy == null && (float)Find.TickManager.TicksGame > selfRaiseTimer;
+ }
+
+ public void StartRising(int lifespanTicks = -1)
+ {
+ var compProps = PropsComp?.Props;
+ if (compProps?.risingHediff == null)
+ {
+ Log.Error($"[ConfigurableMutant] risingHediff is not defined in XML for {this.def.defName}");
+ return;
+ }
+
+ if (!pawn.Dead && !pawn.Downed)
+ {
+ Log.Error("Tried to raise non dead/downed pawn as shambler");
+ if(pawn.mutant != null) pawn.mutant.Turn(clearLord: true);
+ return;
+ }
+
+ MutantUtility.RestoreBodyParts(pawn);
+ pawn.Notify_DisabledWorkTypesChanged();
+
+ if (!pawn.Dead || ResurrectionUtility.TryResurrect(pawn, new ResurrectionParams { noLord = true, restoreMissingParts = false, removeDiedThoughts = false }))
+ {
+ pawn.jobs?.EndCurrentJob(JobCondition.InterruptForced);
+ resurrectTimer = Find.TickManager.TicksGame + compProps.resurrectionSecondsRange.RandomInRange.SecondsToTicks();
+ pawn.health.AddHediff(compProps.risingHediff);
+ }
+ }
+
+ private void CancelRising()
+ {
+ var risingHediff = PropsComp?.Props.risingHediff;
+ if (risingHediff == null) return;
+
+ riseSustainer?.End();
+ resurrectTimer = -99999f;
+ if (pawn.health.hediffSet.TryGetHediff(risingHediff, out var hediff))
+ {
+ pawn.health.RemoveHediff(hediff);
+ }
+ if (!pawn.Dead)
+ {
+ pawn.Kill(null, null);
+ }
+ }
+
+ private void FinishRising(bool stun = true)
+ {
+ var compProps = PropsComp?.Props;
+ if (compProps?.risingHediff != null && pawn.health.hediffSet.TryGetHediff(compProps.risingHediff, out var hediff))
+ {
+ pawn.health.RemoveHediff(hediff);
+ }
+
+ if (pawn.ParentHolder is Pawn_CarryTracker pawn_CarryTracker)
+ {
+ pawn_CarryTracker.TryDropCarriedThing(pawn_CarryTracker.pawn.Position, ThingPlaceMode.Near, out var _);
+ pawn_CarryTracker.pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
+ }
+
+ if (pawn.mutant != null && !pawn.mutant.HasTurned)
+ {
+ pawn.mutant.Turn();
+ }
+ pawn.timesRaisedAsShambler++;
+ MutantUtility.RestoreUntilNotDowned(pawn);
+
+ if (pawn.Spawned && stun)
+ {
+ pawn.Rotation = Rot4.South;
+ if(compProps != null)
+ pawn.stances.stunner.StunFor(compProps.stunSecondsRange.RandomInRange.SecondsToTicks(), pawn, addBattleLog: false, showMote: false);
+ }
+
+ pawn.Drawer.renderer.SetAnimation(null);
+ StartSelfRaiseTimer();
+ }
+
+ private void StartSelfRaiseTimer()
+ {
+ var selfRaiseHoursRange = PropsComp?.Props.selfRaiseHoursRange ?? new IntRange(3, 4);
+ selfRaiseTimer = Find.TickManager.TicksGame + 2500 * selfRaiseHoursRange.RandomInRange;
+ }
+
+ public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
+ {
+ base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
+ if (dinfo.Instigator != null && pawn.HostileTo(dinfo.Instigator))
+ {
+ if (pawn.Spawned && dinfo.Instigator is IAttackTarget && dinfo.Instigator.Spawned && pawn.CanSee(dinfo.Instigator))
+ {
+ pawn.mindState.enemyTarget = dinfo.Instigator;
+ pawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; // 直接给public字段赋值,绕过internal方法
+ pawn.jobs.EndCurrentJob(JobCondition.InterruptOptional);
+ pawn.GetLord()?.Notify_PawnAcquiredTarget(pawn, dinfo.Instigator);
+ }
+ MutantUtility.ActivateNearbyShamblers(pawn, dinfo.Instigator);
+ }
+ }
+
+ public void Notify_DelayedAlert(Thing target)
+ {
+ var alertSecondsRange = PropsComp?.Props.alertSecondsRange ?? new FloatRange(0.5f, 3f);
+ if (pawn.mutant != null && !pawn.mutant.IsPassive && !pawn.Drafted && pawn.mindState.enemyTarget == null)
+ {
+ alertTimer = Find.TickManager.TicksGame + alertSecondsRange.RandomInRange.SecondsToTicks();
+ alertedTarget = target;
+ pawn.GetLord()?.Notify_PawnAcquiredTarget(pawn, target);
+ }
+ }
+
+ public override void Notify_Downed()
+ {
+ StartSelfRaiseTimer();
+ }
+
+ public override void Notify_PawnKilled()
+ {
+ corpseDamagePct = pawn.health.summaryHealth.SummaryHealthPercent;
+ base.Notify_PawnKilled();
+ }
+
+ public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
+ {
+ if (IsRising)
+ {
+ CancelRising();
+ }
+
+ var compProps = PropsComp?.Props;
+ if (compProps != null && pawn.timesRaisedAsShambler == 1 && Rand.Chance(compProps.bioferriteOnDeathChance) && pawn.SpawnedOrAnyParentSpawned)
+ {
+ Thing thing = ThingMaker.MakeThing(ThingDefOf.Bioferrite);
+ thing.stackCount = compProps.bioferriteAmountOnDeath;
+ GenPlace.TryPlaceThing(thing, pawn.PositionHeld, pawn.MapHeld, ThingPlaceMode.Near, out var lastResultingThing);
+ lastResultingThing.SetForbidden(value: true);
+ }
+
+ if (pawn.Corpse != null)
+ {
+ pawn.Corpse.HitPoints = Mathf.Max(Mathf.RoundToInt((float)pawn.Corpse.MaxHitPoints * corpseDamagePct), 10);
+ }
+
+ if (compProps?.corpseHediff != null)
+ {
+ pawn.health.AddHediff(compProps.corpseHediff);
+ }
+
+ base.Notify_PawnDied(dinfo, culprit);
+ }
+
+ public override void PreRemoved()
+ {
+ pawn.MapHeld?.mapPawns.DeregisterShambler(pawn);
+ base.PreRemoved();
+ }
+
+ public override void PostRemoved()
+ {
+ base.PostRemoved();
+ if (pawn.Dead) return;
+ if (IsRising) CancelRising();
+ if (pawn.IsMutant)
+ {
+ if (pawn.mutant.HasTurned) pawn.mutant.Revert();
+ else pawn.mutant = null;
+ }
+ }
+
+ public override IEnumerable GetGizmos()
+ {
+ foreach (Gizmo gizmo in base.GetGizmos())
+ {
+ yield return gizmo;
+ }
+ if (DebugSettings.ShowDevGizmos && pawn.Downed && !IsRising)
+ {
+ var command_Action = new Command_Action
+ {
+ defaultLabel = "Self Raise",
+ action = () => StartRising()
+ };
+ yield return command_Action;
+ }
+ }
+
+ public override string GetInspectString()
+ {
+ if (ShouldSelfRaise()) return "ShamblerRegenerating".Translate();
+ if (IsRising) return "ShamblerRising".Translate();
+ if (pawn.CurJobDef == JobDefOf.Wait_Wander || pawn.CurJobDef == JobDefOf.Wait_MaintainPosture) return "ShamblerStanding".Translate();
+ if (pawn.CurJobDef == JobDefOf.GotoWander || pawn.CurJobDef == JobDefOf.Goto) return "ShamblerShuffling".Translate();
+ return "";
+ }
+
+ public override void ExposeData()
+ {
+ base.ExposeData();
+ Scribe_Values.Look(ref alertTimer, "alertTimer", 0f);
+ Scribe_Values.Look(ref nextTargetCheckTick, "nextTargetCheckTick", 0);
+ Scribe_References.Look(ref alertedTarget, "alertedTarget");
+ Scribe_Values.Look(ref resurrectTimer, "resurrectTimer", 0f);
+ Scribe_Values.Look(ref selfRaiseTimer, "selfRaiseTimer", 0f);
+ Scribe_Values.Look(ref headRotation, "headRotation", 0f);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Hediff_NecroticVirus_Configurable.cs b/Source/ArachnaeSwarm/Hediff_NecroticVirus_Configurable.cs
index 8192b5c..c8c151b 100644
--- a/Source/ArachnaeSwarm/Hediff_NecroticVirus_Configurable.cs
+++ b/Source/ArachnaeSwarm/Hediff_NecroticVirus_Configurable.cs
@@ -36,6 +36,12 @@ namespace ArachnaeSwarm
return;
}
+ // 检查严重性是否达到XML中配置的阈值
+ if (this.Severity < comp.Props.triggerSeverity)
+ {
+ return;
+ }
+
try
{
if (pawn.Corpse == null || pawn.Corpse.Destroyed)
@@ -46,9 +52,10 @@ namespace ArachnaeSwarm
Map map = pawn.Corpse.Map;
IntVec3 position = pawn.Corpse.Position;
- if (!MutantUtility.CanResurrectAsShambler(pawn.Corpse))
+ // 使用我们自己的、更安全的检查方法
+ if (!NecroticTransformationUtility.CanResurrect(pawn.Corpse))
{
- Log.Warning($"[NecroticVirus] Cannot resurrect {pawn.LabelShort} as a shambler-like creature.");
+ Log.Warning($"[NecroticVirus] Pawn {pawn.LabelShort} does not meet conditions for resurrection.");
return;
}
diff --git a/Source/ArachnaeSwarm/NecroticTransformationUtility.cs b/Source/ArachnaeSwarm/NecroticTransformationUtility.cs
index 2ace4c5..fefaaf1 100644
--- a/Source/ArachnaeSwarm/NecroticTransformationUtility.cs
+++ b/Source/ArachnaeSwarm/NecroticTransformationUtility.cs
@@ -5,9 +5,41 @@ namespace ArachnaeSwarm
{
public static class NecroticTransformationUtility
{
+ ///
+ /// 检查一个尸体是否可以被我们的逻辑转化为变异体。
+ /// 这是对原版 MutantUtility.CanResurrectAsShambler 的复制,但移除了对 canBecomeShambler 的检查。
+ ///
+ public static bool CanResurrect(Corpse corpse, bool ignoreIndoors = false)
+ {
+ if (corpse?.InnerPawn == null) return false;
+ if (!corpse.InnerPawn.RaceProps.IsFlesh) return false;
+ // 我们移除了对 corpse.InnerPawn.RaceProps.canBecomeShambler 的检查
+ if (corpse.InnerPawn.IsMutant) return false;
+ if (corpse is UnnaturalCorpse) return false;
+
+ Room room = corpse.PositionHeld.GetRoom(corpse.MapHeld);
+ if (room != null && !ignoreIndoors && corpse.PositionHeld.Roofed(corpse.MapHeld) && (room.ProperRoom || room.IsDoorway))
+ {
+ return false;
+ }
+
+ if (!Find.Storyteller.difficulty.childShamblersAllowed && !corpse.InnerPawn.ageTracker.Adult)
+ {
+ return false;
+ }
+
+ Hediff_DeathRefusal firstHediff = corpse.InnerPawn.health.hediffSet.GetFirstHediff();
+ if (firstHediff != null && (firstHediff.InProgress || firstHediff.UsesLeft > 0))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
///
/// 将一个Pawn复活为指定的自定义变异体.
- /// 这个方法是模仿原版 MutantUtility.ResurrectAsShambler,
+ /// 这个方法是模仿原版 MutantUtility.ResurrectAsShambler,
/// 但允许传入一个自定义的 MutantDef.
///
public static void ResurrectAsCustomMutant(Pawn pawn, MutantDef mutantDef, Faction faction = null, int lifespanTicks = -1)