虫!
This commit is contained in:
Binary file not shown.
@@ -91,7 +91,6 @@
|
||||
<titleShort>工艺种</titleShort>
|
||||
<description>[PAWN_nameDef]是一只阿拉克涅工艺种督虫。能够产出专门用来孵化阿拉克涅武器种的孵化茧,负责阿拉克涅虫巢的基础维护。\n\n[PAWN_nameDef]在战斗中并不是一个值得正视的对手,她没有可以接入武装器官的副肢,脆弱臃肿的特性也决定了她几乎无法躲开任何攻击。</description>
|
||||
<slot>Adulthood</slot>
|
||||
<requiredWorkTags>Cooking</requiredWorkTags>
|
||||
|
||||
<spawnCategories>
|
||||
<li>ArachnaeNode_spawnCategories_WeaponSmith</li>
|
||||
@@ -104,10 +103,6 @@
|
||||
<titleShort>原虫种</titleShort>
|
||||
<description>[PAWN_nameDef]是一只阿拉克涅原虫种督虫。[PAWN_nameDef]通过独特的神经链接管伸入受害者身体来接管受害者的身体。不同于普通阿拉克涅虫族,阿拉克涅原虫种拥有自我意识,不需要女皇种的监管。</description>
|
||||
<slot>Adulthood</slot>
|
||||
<requiredWorkTags>Cooking</requiredWorkTags>
|
||||
|
||||
<forcedHediffs Insert="false">
|
||||
</forcedHediffs>
|
||||
|
||||
<spawnCategories>
|
||||
<li>ArachnaeNode_spawnCategories_Facehugger</li>
|
||||
|
||||
@@ -3,15 +3,58 @@
|
||||
|
||||
<HediffDef>
|
||||
<defName>ARA_Possession</defName>
|
||||
<label>阿拉克涅原虫寄生</label>
|
||||
<description>这个生物的身体正被另一个实体所控制。</description>
|
||||
<label>阿拉克涅原虫</label>
|
||||
<description>这个生物的身体被阿拉克涅原虫所夺取了,这具身体原本的主人已经没有可能再回来了。</description>
|
||||
<hediffClass>ArachnaeSwarm.Hediff_Possession</hediffClass>
|
||||
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
|
||||
<isBad>false</isBad>
|
||||
<scenarioCanAdd>false</scenarioCanAdd>
|
||||
<maxSeverity>1.0</maxSeverity>
|
||||
<renderNodeProperties>
|
||||
<li>
|
||||
<nodeClass>PawnRenderNode_AttachmentHead</nodeClass>
|
||||
<workerClass>PawnRenderNodeWorker_FlipWhenCrawling</workerClass>
|
||||
<texPath>ArachnaeSwarm/Things/ARA_HiveNode/Heads/Average_Normal</texPath>
|
||||
<colorType>Skin</colorType>
|
||||
<parentTagDef>Head</parentTagDef>
|
||||
<useSkinShader>true</useSkinShader>
|
||||
<useRottenColor>true</useRottenColor>
|
||||
<rotDrawMode>Fresh, Rotting</rotDrawMode>
|
||||
<drawData>
|
||||
<defaultData>
|
||||
<layer>70</layer>
|
||||
</defaultData>
|
||||
</drawData>
|
||||
</li>
|
||||
<li>
|
||||
<nodeClass>PawnRenderNode_AttachmentHead</nodeClass>
|
||||
<workerClass>PawnRenderNodeWorker_FlipWhenCrawling</workerClass>
|
||||
<texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Base</texPath>
|
||||
<colorType>Skin</colorType>
|
||||
<parentTagDef>Head</parentTagDef>
|
||||
<useSkinShader>true</useSkinShader>
|
||||
<useRottenColor>true</useRottenColor>
|
||||
<rotDrawMode>Fresh, Rotting</rotDrawMode>
|
||||
<drawData>
|
||||
<defaultData>
|
||||
<layer>70</layer>
|
||||
</defaultData>
|
||||
</drawData>
|
||||
</li>
|
||||
</renderNodeProperties>
|
||||
<stages>
|
||||
<li>
|
||||
<label>被寄生</label>
|
||||
<minSeverity>0</minSeverity>
|
||||
<disablesNeeds>
|
||||
<li>Mood</li>
|
||||
<li>Joy</li>
|
||||
<li>Beauty</li>
|
||||
<li>Comfort</li>
|
||||
<li>Outdoors</li>
|
||||
<li>Indoors</li>
|
||||
<li>DrugDesire</li>
|
||||
<li>RoomSize</li>
|
||||
</disablesNeeds>
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
@@ -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}) 夺舍完成。");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,9 +56,12 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
foreach (RecordDef recordDef in DefDatabase<RecordDef>.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<WorkTypeDef>.AllDefs)
|
||||
{
|
||||
bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
|
||||
// 在设置优先级之前,检查目标Pawn是否禁用了该工作类型
|
||||
if (!bodyTarget.WorkTypeIsDisabled(workDef))
|
||||
{
|
||||
bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user