diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index b9c9af0..889af9c 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/BackstoryDefs/ARA_BackstoryDef.xml b/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml
index 596747c..5cecb6f 100644
--- a/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml
+++ b/1.6/1.6/Defs/BackstoryDefs/ARA_BackstoryDef.xml
@@ -91,7 +91,6 @@
工艺种
[PAWN_nameDef]是一只阿拉克涅工艺种督虫。能够产出专门用来孵化阿拉克涅武器种的孵化茧,负责阿拉克涅虫巢的基础维护。\n\n[PAWN_nameDef]在战斗中并不是一个值得正视的对手,她没有可以接入武装器官的副肢,脆弱臃肿的特性也决定了她几乎无法躲开任何攻击。
Adulthood
- Cooking
ArachnaeNode_spawnCategories_WeaponSmith
@@ -104,10 +103,6 @@
原虫种
[PAWN_nameDef]是一只阿拉克涅原虫种督虫。[PAWN_nameDef]通过独特的神经链接管伸入受害者身体来接管受害者的身体。不同于普通阿拉克涅虫族,阿拉克涅原虫种拥有自我意识,不需要女皇种的监管。
Adulthood
- Cooking
-
-
-
ArachnaeNode_spawnCategories_Facehugger
diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Possession.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Possession.xml
index 6dfe6f3..b2252d6 100644
--- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Possession.xml
+++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Possession.xml
@@ -3,15 +3,58 @@
ARA_Possession
-
- 这个生物的身体正被另一个实体所控制。
+
+ 这个生物的身体被阿拉克涅原虫所夺取了,这具身体原本的主人已经没有可能再回来了。
ArachnaeSwarm.Hediff_Possession
+ (0.6, 0.4, 0.8)
false
false
1.0
+
+
+ PawnRenderNode_AttachmentHead
+ PawnRenderNodeWorker_FlipWhenCrawling
+ ArachnaeSwarm/Things/ARA_HiveNode/Heads/Average_Normal
+ Skin
+ Head
+ true
+ true
+ Fresh, Rotting
+
+
+ 70
+
+
+
+
+ PawnRenderNode_AttachmentHead
+ PawnRenderNodeWorker_FlipWhenCrawling
+ ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Base
+ Skin
+ Head
+ true
+ true
+ Fresh, Rotting
+
+
+ 70
+
+
+
+
-
+ 0
+
+ Mood
+ Joy
+ Beauty
+ Comfort
+ Outdoors
+ Indoors
+ DrugDesire
+ RoomSize
+
diff --git a/Source/ArachnaeSwarm/Possession/CompAbilityEffect_Possess.cs b/Source/ArachnaeSwarm/Possession/CompAbilityEffect_Possess.cs
index 31cab75..f162724 100644
--- a/Source/ArachnaeSwarm/Possession/CompAbilityEffect_Possess.cs
+++ b/Source/ArachnaeSwarm/Possession/CompAbilityEffect_Possess.cs
@@ -12,34 +12,33 @@ namespace ArachnaeSwarm
Pawn caster = this.parent.pawn;
Pawn targetPawn = target.Pawn;
- if (targetPawn == null)
+ if (targetPawn == null || caster == null) return;
+
+ Log.Message($"[夺舍] 开始执行。施法者: {caster.LabelShort}, 目标: {targetPawn.LabelShort}");
+
+ // 步骤 1: 创建Hediff实例
+ Hediff_Possession hediff = (Hediff_Possession)HediffMaker.MakeHediff(HediffDef.Named("ARA_Possession"), targetPawn);
+
+ // 步骤 2: 使用SplitOff(1)将施法者的一个安全、独立的副本存入容器。
+ // 这是从地图上移除Pawn并将其存入容器的标准、原子性操作。
+ if (hediff.GetDirectlyHeldThings().TryAdd(caster.SplitOff(1), true))
{
+ Log.Message($"[夺舍] 成功将 {caster.LabelShort} 的副本存入Hediff。");
+ }
+ else
+ {
+ Log.Error($"[夺舍] 无法将 {caster.LabelShort} 的副本存入Hediff。中止操作。");
return;
}
-
- // Optional: Add checks here. E.g., cannot possess mechanical, already possessed, etc.
- // if (targetPawn.RaceProps.IsMechanoid)
- // {
- // Messages.Message("Cannot possess a mechanoid.", MessageTypeDefOf.RejectInput);
- // return;
- // }
- Log.Message("[夺舍] Apply方法开始执行。施法者: " + caster.LabelShort + ", 目标: " + targetPawn.LabelShort);
+ // 步骤 3: 使用原始施法者的数据覆盖目标Pawn。
+ // 即使caster的stackCount变为0,其数据在当前Tick中依然可读。
+ PawnDataUtility.TransferSoul(caster, targetPawn);
- Log.Message("[夺舍] 步骤1: 创建Hediff实例...");
- Hediff_Possession hediff = (Hediff_Possession)HediffMaker.MakeHediff(HediffDef.Named("ARA_Possession"), targetPawn);
-
- Log.Message("[夺舍] 步骤2: 将施法者 " + caster.LabelShort + " 安全地转移到Hediff容器中...");
- // 使用标准的游戏框架方法,将施法者从其当前的持有者(地图)转移到Hediff的内部容器中。
- // 这会自动处理施法者从地图上消失的逻辑。
- caster.holdingOwner.TryTransferToContainer(caster, hediff.GetDirectlyHeldThings(), 1);
-
- Log.Message("[夺舍] 步骤3: 调用Hediff的PostPossessionApply方法来执行数据覆盖...");
- // 我们创建一个新的方法来处理夺舍后的逻辑,而不是依赖PostAdd
- hediff.PostPossessionApply(caster, targetPawn);
-
- Log.Message("[夺舍] 步骤4: 将Hediff添加到目标Pawn身上...");
+ // 步骤 4: 将准备好的Hediff添加到目标身上。
targetPawn.health.AddHediff(hediff);
+
+ Log.Message($"[夺舍] {targetPawn.LabelShort} (原 {caster.LabelShort}) 夺舍完成。");
}
}
}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Possession/Hediff_Possession.cs b/Source/ArachnaeSwarm/Possession/Hediff_Possession.cs
index a596151..0d8903b 100644
--- a/Source/ArachnaeSwarm/Possession/Hediff_Possession.cs
+++ b/Source/ArachnaeSwarm/Possession/Hediff_Possession.cs
@@ -7,7 +7,6 @@ namespace ArachnaeSwarm
public class Hediff_Possession : HediffWithComps, IThingHolder
{
private ThingOwner innerContainer;
- private Pawn originalCaster;
public Hediff_Possession()
{
@@ -28,20 +27,8 @@ namespace ArachnaeSwarm
return innerContainer;
}
- // PostAdd在游戏加载时也会被调用,因此不适合放置一次性的夺舍逻辑。
- // 我们创建一个新的公共方法,由CompAbilityEffect在正确的时机调用。
- public void PostPossessionApply(Pawn caster, Pawn target)
- {
- Log.Message("[夺舍] Hediff.PostPossessionApply 开始执行,施法者: " + caster.LabelShort + ", 目标: " + target.LabelShort);
-
- // 将施法者的引用保存下来,用于将来的重生逻辑
- this.originalCaster = caster;
-
- Log.Message("[夺舍] 步骤5: 调用 TransferSoul 将灵魂从 " + caster.LabelShort + " 转移到 " + target.LabelShort);
- PawnDataUtility.TransferSoul(caster, target);
-
- Log.Message($"[夺舍] {target.LabelShort} 已被 {StoredCasterPawn.LabelShort} 夺舍成功!");
- }
+ // PostAdd现在只在游戏加载时起作用,我们不需要在这里做任何特殊操作。
+ // 所有的夺舍逻辑都在CompAbilityEffect_Possess中处理了。
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
{
@@ -61,24 +48,33 @@ namespace ArachnaeSwarm
this.EjectContents();
}
- public void SetCaster(Pawn caster)
- {
- this.originalCaster = caster;
- }
public void EjectContents()
{
- if (StoredCasterPawn != null)
+ if (StoredCasterPawn == null) return;
+
+ // 采用更稳健的方式获取地图和位置,防止因宿主死亡导致Map为null
+ Map map = this.pawn.MapHeld ?? Find.AnyPlayerHomeMap;
+ if (map == null)
{
- this.innerContainer.TryDropAll(this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near);
+ Log.Error("[夺舍] 无法找到一个有效的地图来重生抱脸虫。");
+ return;
}
+
+ IntVec3 cell = this.pawn.PositionHeld;
+ if (!cell.IsValid)
+ {
+ cell = map.Center;
+ }
+
+ Log.Message($"[夺舍] 准备在地图 {map.ToString()} 的位置 {cell.ToString()} 处重生 {StoredCasterPawn.LabelShort}。");
+ this.innerContainer.TryDropAll(cell, map, ThingPlaceMode.Near);
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
- Scribe_References.Look(ref originalCaster, "originalCaster", false);
}
}
}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Possession/PawnDataUtility.cs b/Source/ArachnaeSwarm/Possession/PawnDataUtility.cs
index a202dc8..62cb26a 100644
--- a/Source/ArachnaeSwarm/Possession/PawnDataUtility.cs
+++ b/Source/ArachnaeSwarm/Possession/PawnDataUtility.cs
@@ -56,9 +56,12 @@ namespace ArachnaeSwarm
{
foreach (RecordDef recordDef in DefDatabase.AllDefs)
{
+ // 根据您的指示,我们不再处理时间类型的记录,以避免警告
+ if (recordDef.type == RecordType.Time)
+ {
+ continue;
+ }
float sourceValue = soulSource.records.GetValue(recordDef);
- // For Time records, we must set them directly to avoid warnings.
- // The AddTo(delta) trick works for all types and is the standard way to "set" a value.
bodyTarget.records.AddTo(recordDef, sourceValue - bodyTarget.records.GetValue(recordDef));
}
}
@@ -81,7 +84,11 @@ namespace ArachnaeSwarm
bodyTarget.workSettings.EnableAndInitialize();
foreach (WorkTypeDef workDef in DefDatabase.AllDefs)
{
- bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
+ // 在设置优先级之前,检查目标Pawn是否禁用了该工作类型
+ if (!bodyTarget.WorkTypeIsDisabled(workDef))
+ {
+ bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
+ }
}
}