618 lines
23 KiB
Markdown
618 lines
23 KiB
Markdown
# “抱脸虫夺舍”技能实现说明书 (V3 - 最终版)
|
||
|
||
## 1. 功能概述
|
||
|
||
本功能实现了一个名为“阿拉克涅寄生”的特殊技能,允许一个特定的“阿拉克涅原虫”(抱脸虫)Pawn将自己的意识(灵魂)注入另一个生物的身体,从而完全占据并控制它。
|
||
|
||
**核心玩法循环:**
|
||
1. **夺舍**: 抱脸虫使用技能后,其物理实体消失,其“灵魂”(名字、背景、技能、特性等)将完全覆盖目标的身体。
|
||
2. **成长**: 玩家将控制这个新的身体进行游戏,所有获得的经验、技能和记忆都将积累在这个身体上。
|
||
3. **重生**: 当被夺舍的身体死亡时,抱脸虫的灵魂会带着所有新的成长,从尸体中“重生”,变回一个独立的、更强大的阿拉克涅原虫Pawn,准备寻找下一个宿主。
|
||
|
||
这是一个高风险、高回报的玩法,允许玩家以一种独特的方式延续一个核心角色的“生命”和成长。
|
||
|
||
## 2. 实现流程
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[抱脸虫] -- 使用“阿拉克涅寄生”技能 --> B(目标Pawn);
|
||
B -- 添加 Hediff_Possession --> C{执行灵魂覆盖};
|
||
C -- 1. 存储抱脸虫Pawn的完整数据 --> D[Hediff容器];
|
||
C -- 2. 将抱脸虫的“灵魂”数据覆盖到目标身上 --> E[被夺舍的身体];
|
||
D -- 3. 抱脸虫物理实体消失 --> F([Vanish]);
|
||
E -- 玩家控制,积累经验和记忆 --> E;
|
||
E -- 受到致命伤害 --> G{身体死亡};
|
||
G -- 触发Hediff.Notify_PawnDied --> H{反向同步成长};
|
||
D -- 获取存储的抱脸虫数据 --> H;
|
||
E -- 获取身体上的成长数据 --> H;
|
||
H -- 将成长更新到抱脸虫数据上 --> I[更新后的抱脸虫];
|
||
I -- 从Hediff中释放 --> J(更强大的抱脸虫重生);
|
||
J -- 等待下一次夺舍 --> A;
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 代码详解
|
||
|
||
### 3.1 `CompAbilityEffect_Possess.cs` - 技能效果的起点
|
||
|
||
这是技能被使用时第一个被调用的C#文件。它的职责是创建`Hediff_Possession`并将其附加到目标身上,从而启动整个夺舍流程。
|
||
## 3. 最终数据迁移规范 (Final Data Transfer Specification)
|
||
|
||
通过对真实存档文件 (`Human.xml`) 的深度分析,我们最终确定了“灵魂”与“肉体”的数据边界。`PawnDataUtility.TransferSoul` 方法将严格遵循以下规范进行数据迁移:
|
||
|
||
### 3.1 必须复制的“灵魂”数据
|
||
|
||
这些数据定义了Pawn的身份、经历、思想和核心能力,将**完全从抱脸虫(源)复制到宿主(目标)**。
|
||
|
||
- **核心身份 (`Name`, `Story`, `Faction`)**:
|
||
- `Name`: 姓名与昵称。
|
||
- `Story`: 童年和成年背景 (`Childhood`, `Adulthood`)。
|
||
- `Traits`: 所有特性。
|
||
- `Faction`: 所属阵营。
|
||
- **成长与经历 (`Skills`, `Records`)**:
|
||
- `Skills`: 所有技能的等级、经验和热情。
|
||
- `Records`: 全部生平记录 (如击杀数、建造数等)。
|
||
- **思想与设定 (`Needs`, `WorkSettings`, etc.)**:
|
||
- `Needs`: 主要是指`thoughts.memories` (思想和记忆)。
|
||
- `WorkSettings`: 工作优先级。
|
||
- `Timetable`: 时间表。
|
||
- `PlayerSettings`: 玩家设定 (如医疗策略)。
|
||
- `Ownership`: 对床、王座等的所有权。
|
||
- `Outfits` & `Drugs`: 穿着和药物策略。
|
||
- `FoodRestriction`: 食物策略。
|
||
- **DLC核心数据 (`Ideo`, `Royalty`)**:
|
||
- `Ideo`: 完整的信仰体系。
|
||
- `Royalty`: 完整的贵族系统,包括头衔、恩惠、许可、灵能和相关技能 (`abilities`)。
|
||
- **社交 (`Relations`)**:
|
||
- 将采用**简化处理**:清空目标的旧关系,然后只复制源的**非亲属**直接关系 (如朋友、对手、爱人)。这可以避免破坏家族树。
|
||
|
||
### 3.2 必须保留的“肉体”数据
|
||
|
||
这些数据属于物理身体的范畴,在夺舍过程中将**完全保留宿主原有的数据**,不进行任何复制。
|
||
|
||
- **健康与生理 (`Health`, `Age`)**:
|
||
- `Health`: 所有伤口、疤痕、疾病和植入物。
|
||
- `Age`: 生物年龄和时间年龄。
|
||
- **外观与基因 (`Style`, `Genes`, `BodyType`)**:
|
||
- `Style`: 发型、胡须、纹身。
|
||
- `Genes`: 所有内生和异种基因。
|
||
- `BodyType`, `HeadType`, `HairColor`: 身体类型、头型和发色。
|
||
- **装备与物品 (`Apparel`, `Equipment`, `Inventory`)**:
|
||
- `Apparel`: 身上穿着的衣物。
|
||
- `Equipment`: 手中持有的装备。
|
||
- `Inventory`: 物品栏中的物品。
|
||
- **物理状态 (`Position`, `Stances`, `Pather`)**:
|
||
- Pawn在世界中的位置、姿态和寻路信息。
|
||
|
||
---
|
||
|
||
```csharp
|
||
// 路径: Source/ArachnaeSwarm/Possession/CompAbilityEffect_Possess.cs
|
||
using RimWorld;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm.Possession
|
||
{
|
||
// 继承自CompAbilityEffect,这是所有技能效果组件的基类
|
||
public class CompAbilityEffect_Possess : CompAbilityEffect
|
||
{
|
||
// 当技能成功施放时,游戏会调用这个Apply方法
|
||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||
{
|
||
base.Apply(target, dest); // 调用基类方法,确保标准流程执行
|
||
|
||
// 获取施法者 (我们的抱脸虫)
|
||
Pawn caster = this.parent.pawn;
|
||
// 获取目标Pawn
|
||
Pawn targetPawn = target.Pawn;
|
||
|
||
// 安全检查:如果目标不是一个Pawn,则直接返回
|
||
if (targetPawn == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// TODO: 在此可以添加更多的限制条件,例如:
|
||
// 1. 不能夺舍机械体
|
||
// if (targetPawn.RaceProps.IsMechanoid) { ... }
|
||
// 2. 不能夺舍已经被夺舍的目标
|
||
// if (targetPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_Possession"))) { ... }
|
||
|
||
// 步骤1: 创建Hediff实例
|
||
// HediffMaker.MakeHediff会根据XML定义创建一个新的Hediff对象
|
||
Hediff_Possession hediff = (Hediff_Possession)HediffMaker.MakeHediff(HediffDef.Named("ARA_Possession"), targetPawn);
|
||
|
||
// 步骤2: 注入施法者灵魂
|
||
// 在Hediff被正式添加到目标身上之前,将施法者的引用传递进去。
|
||
// 这是关键一步,确保Hediff在执行PostAdd逻辑时能知道谁是施法者。
|
||
hediff.SetCaster(caster);
|
||
|
||
// 步骤3: 将Hediff添加到目标身上
|
||
// 这会触发Hediff_Possession类中的PostAdd方法,从而启动真正的夺舍逻辑。
|
||
targetPawn.health.AddHediff(hediff);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 `Hediff_Possession.cs` - 夺舍与重生的核心
|
||
|
||
这个Hediff是整个功能的核心。它作为“灵魂容器”,负责存储抱脸虫的本体,并在恰当的时机执行“夺舍”和“重生”的逻辑。
|
||
|
||
```csharp
|
||
// 路径: Source/ArachnaeSwarm/Possession/Hediff_Possession.cs
|
||
using System.Collections.Generic;
|
||
using RimWorld;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm.Possession
|
||
{
|
||
// 继承HediffWithComps以支持组件,并实现IThingHolder接口来表明自己是容器
|
||
public class Hediff_Possession : HediffWithComps, IThingHolder
|
||
{
|
||
// --- 核心字段 ---
|
||
private ThingOwner innerContainer; // 实际存储灵魂(抱脸虫Pawn)的容器
|
||
private Pawn originalCaster; // 临时保存对原始施法者的引用
|
||
|
||
// --- 构造与属性 ---
|
||
public Hediff_Possession()
|
||
{
|
||
// 初始化容器。LookMode.Deep是关键,它能确保Pawn的所有数据都被完整保存。
|
||
this.innerContainer = new ThingOwner<Thing>(this, false, LookMode.Deep);
|
||
}
|
||
|
||
// 提供一个方便的只读属性来获取容器中存储的Pawn
|
||
public Pawn StoredCasterPawn => innerContainer.Count > 0 ? innerContainer[0] as Pawn : null;
|
||
|
||
// --- IThingHolder 接口实现 ---
|
||
public IThingHolder ParentHolder => this.pawn; // 容器的父级就是持有该Hediff的Pawn
|
||
|
||
public void GetChildHolders(List<IThingHolder> outChildren)
|
||
{
|
||
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, this.GetDirectlyHeldThings());
|
||
}
|
||
|
||
public ThingOwner GetDirectlyHeldThings()
|
||
{
|
||
return innerContainer;
|
||
}
|
||
|
||
// --- 核心逻辑 ---
|
||
|
||
// 当Hediff被成功添加到目标身上后,此方法被自动调用
|
||
public override void PostAdd(DamageInfo? dinfo)
|
||
{
|
||
base.PostAdd(dinfo);
|
||
|
||
if (this.originalCaster == null)
|
||
{
|
||
Log.Error("Hediff_Possession was added without an original caster.");
|
||
return;
|
||
}
|
||
|
||
// 1. 存储灵魂:将施法者的Pawn对象完整地存入容器
|
||
this.innerContainer.TryAdd(this.originalCaster);
|
||
|
||
// 2. 灵魂覆盖:调用工具类,执行数据迁移
|
||
PawnDataUtility.TransferSoul(this.originalCaster, this.pawn);
|
||
|
||
// 3. 销毁施法者的物理实体,因为它现在“活”在目标的身体里了
|
||
if (!this.originalCaster.Destroyed)
|
||
{
|
||
this.originalCaster.Destroy(DestroyMode.Vanish);
|
||
}
|
||
|
||
Log.Message($"{this.pawn.LabelShort} has been possessed by {StoredCasterPawn.LabelShort}!");
|
||
}
|
||
|
||
// 当持有此Hediff的Pawn(即宿主)死亡时,此方法被自动调用
|
||
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
|
||
{
|
||
base.Notify_PawnDied(dinfo, culprit);
|
||
|
||
Pawn deadBody = this.pawn;
|
||
Pawn storedCaster = this.StoredCasterPawn;
|
||
|
||
if (storedCaster == null)
|
||
{
|
||
Log.Error("Possessed pawn died, but no caster soul was found inside.");
|
||
return;
|
||
}
|
||
|
||
Log.Message($"Host {deadBody.LabelShort} died. Transferring experience back to {storedCaster.LabelShort} and ejecting.");
|
||
|
||
// 1. 灵魂更新:反向调用工具类,将宿主身体上的成长同步回抱脸虫的灵魂
|
||
PawnDataUtility.TransferSoul(deadBody, storedCaster);
|
||
|
||
// 2. 重生:将更新后的抱脸虫灵魂从容器中释放到地图上
|
||
this.EjectContents();
|
||
}
|
||
|
||
// --- 公共方法 ---
|
||
|
||
// 由CompAbilityEffect调用,用于在添加Hediff前设置施法者
|
||
public void SetCaster(Pawn caster)
|
||
{
|
||
this.originalCaster = caster;
|
||
}
|
||
|
||
// 将容器内的东西(抱脸虫)扔到地图上
|
||
public void EjectContents()
|
||
{
|
||
if (StoredCasterPawn != null)
|
||
{
|
||
this.innerContainer.TryDropAll(this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near);
|
||
}
|
||
}
|
||
|
||
// --- 存档/读档 ---
|
||
public override void ExposeData()
|
||
{
|
||
base.ExposeData();
|
||
// Scribe_Deep是关键,确保容器内的Pawn被深度保存
|
||
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
|
||
// 保存对原始施法者的引用(虽然它很快会被销毁,但以防万一)
|
||
Scribe_References.Look(ref originalCaster, "originalCaster");
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 `PawnDataUtility.cs` - “灵魂”数据迁移的执行者
|
||
|
||
这是一个静态工具类,集中处理所有与Pawn数据复制相关的复杂逻辑,使得其他部分的代码更整洁。
|
||
|
||
```csharp
|
||
// 路径: Source/ArachnaeSwarm/Possession/PawnDataUtility.cs
|
||
using System.Collections.Generic;
|
||
using RimWorld;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm.Possession
|
||
{
|
||
public static class PawnDataUtility
|
||
{
|
||
// 核心方法:将soulSource的“灵魂”数据转移到bodyTarget上
|
||
public static void TransferSoul(Pawn soulSource, Pawn bodyTarget)
|
||
{
|
||
if (soulSource == null || bodyTarget == null)
|
||
{
|
||
Log.Error("Cannot transfer soul: source or target is null.");
|
||
return;
|
||
}
|
||
|
||
Log.Message($"Beginning soul transfer from {soulSource.LabelShort} to {bodyTarget.LabelShort}.");
|
||
|
||
// --- 1. 核心身份数据 ---
|
||
|
||
// 姓名
|
||
bodyTarget.Name = soulSource.Name;
|
||
|
||
// 故事 (背景和特性)
|
||
bodyTarget.story.Childhood = soulSource.story.Childhood;
|
||
bodyTarget.story.Adulthood = soulSource.story.Adulthood;
|
||
// 先清空目标的所有特性,再逐一添加源的特性
|
||
bodyTarget.story.traits.allTraits.Clear();
|
||
foreach (Trait trait in soulSource.story.traits.allTraits)
|
||
{
|
||
bodyTarget.story.traits.GainTrait(trait);
|
||
}
|
||
|
||
// 技能
|
||
// 同样地,清空后逐一添加
|
||
bodyTarget.skills.skills.Clear();
|
||
foreach (SkillRecord skill in soulSource.skills.skills)
|
||
{
|
||
SkillRecord newSkill = new SkillRecord(bodyTarget, skill.def)
|
||
{
|
||
levelInt = skill.levelInt,
|
||
xpSinceLastLevel = skill.xpSinceLastLevel,
|
||
passion = skill.passion
|
||
};
|
||
bodyTarget.skills.skills.Add(newSkill);
|
||
}
|
||
|
||
// 阵营
|
||
if (bodyTarget.Faction != soulSource.Faction)
|
||
{
|
||
bodyTarget.SetFaction(soulSource.Faction, soulSource);
|
||
}
|
||
|
||
// --- 2. 思想、社交和设定 ---
|
||
|
||
// 思想和记忆
|
||
// 清空目标的记忆,然后复制源的记忆
|
||
if (bodyTarget.needs.mood?.thoughts?.memories != null)
|
||
{
|
||
bodyTarget.needs.mood.thoughts.memories.Memories.Clear();
|
||
}
|
||
if (soulSource.needs.mood?.thoughts?.memories != null)
|
||
{
|
||
foreach (Thought_Memory memory in soulSource.needs.mood.thoughts.memories.Memories)
|
||
{
|
||
bodyTarget.needs.mood.thoughts.memories.TryGainMemory(memory);
|
||
}
|
||
}
|
||
|
||
// 工作设置
|
||
if (soulSource.workSettings != null && bodyTarget.workSettings != null)
|
||
{
|
||
bodyTarget.workSettings.EnableAndInitialize();
|
||
foreach (WorkTypeDef workDef in DefDatabase<WorkTypeDef>.AllDefs)
|
||
{
|
||
bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
|
||
}
|
||
}
|
||
|
||
// 时间表
|
||
if (soulSource.timetable != null && bodyTarget.timetable != null)
|
||
{
|
||
bodyTarget.timetable.times = new List<TimeAssignmentDef>(soulSource.timetable.times);
|
||
}
|
||
|
||
// 社交关系 (简化处理)
|
||
// 警告: 直接复制关系可能很危险,这里采用清空再添加直接关系的方式
|
||
if (soulSource.relations != null && bodyTarget.relations != null)
|
||
{
|
||
bodyTarget.relations.ClearAllRelations();
|
||
foreach (DirectPawnRelation relation in soulSource.relations.DirectRelations)
|
||
{
|
||
bodyTarget.relations.AddDirectRelation(relation.def, relation.otherPawn);
|
||
}
|
||
}
|
||
|
||
// 访客/囚犯状态
|
||
if (soulSource.guest != null && bodyTarget.guest != null)
|
||
{
|
||
// 使用游戏提供的标准方法来设置,而不是直接赋值
|
||
bodyTarget.guest.SetGuestStatus(soulSource.guest.HostFaction, soulSource.guest.GuestStatus);
|
||
if (soulSource.guest.IsPrisoner)
|
||
{
|
||
bodyTarget.guest.SetExclusiveInteraction(soulSource.guest.ExclusiveInteractionMode);
|
||
}
|
||
bodyTarget.guest.joinStatus = soulSource.guest.joinStatus;
|
||
}
|
||
|
||
// --- 3. 收尾工作 ---
|
||
|
||
// 强制刷新Pawn的渲染缓存,确保外观(如名字)能立刻更新
|
||
bodyTarget.Drawer.renderer.SetAllGraphicsDirty();
|
||
|
||
Log.Message("Soul transfer complete.");
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.4 `CompProperties_AbilityPossess.cs` - 技能属性类
|
||
|
||
这是一个简单的属性类,用于将我们的技能效果组件(`CompAbilityEffect_Possess`)连接到XML定义上。
|
||
|
||
```csharp
|
||
// 路径: Source/ArachnaeSwarm/Possession/CompProperties_AbilityPossess.cs
|
||
using RimWorld;
|
||
|
||
namespace ArachnaeSwarm.Possession
|
||
{
|
||
// CompProperties类用于在XML中配置Comp组件的参数
|
||
public class CompProperties_AbilityPossess : CompProperties_AbilityEffect
|
||
{
|
||
public CompProperties_AbilityPossess()
|
||
{
|
||
// 将这个属性类与我们的技能效果实现类关联起来
|
||
this.compClass = typeof(CompAbilityEffect_Possess);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. XML 定义详解
|
||
|
||
### 4.1 `ARA_Hediffs_Possession.xml` - 定义Hediff
|
||
|
||
```xml
|
||
<!-- 路径: 1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Possession.xml -->
|
||
<?xml version="1.0" encoding="utf-8" ?>
|
||
<Defs>
|
||
|
||
<HediffDef>
|
||
<!-- 内部唯一的定义名 -->
|
||
<defName>ARA_Possession</defName>
|
||
<!-- 游戏中显示的标签 -->
|
||
<label>阿拉克涅原虫寄生</label>
|
||
<!-- 鼠标悬浮时的描述 -->
|
||
<description>这个生物的身体正被另一个实体所控制。</description>
|
||
<!-- 关键:将这个XML定义与我们的C#实现类关联起来 -->
|
||
<hediffClass>ArachnaeSwarm.Possession.Hediff_Possession</hediffClass>
|
||
<!-- 其他标准Hediff属性 -->
|
||
<isBad>false</isBad>
|
||
<scenarioCanAdd>false</scenarioCanAdd>
|
||
<maxSeverity>1.0</maxSeverity>
|
||
<stages>
|
||
<li>
|
||
<label>被寄生</label>
|
||
</li>
|
||
</stages>
|
||
</HediffDef>
|
||
|
||
</Defs>
|
||
```
|
||
|
||
### 4.2 `ARA_Possession_Defs.xml` - 定义技能、种族和身体
|
||
|
||
这个文件定义了技能本身,以及我们的“阿拉克涅原虫”作为一个完整的生物所需的一切。
|
||
|
||
```xml
|
||
<!-- 路径: 1.6/1.6/Defs/Misc/ARA_Possession_Defs.xml -->
|
||
<?xml version="1.0" encoding="utf-8" ?>
|
||
<Defs>
|
||
|
||
<!-- ==================== 技能定义 ==================== -->
|
||
<AbilityDef>
|
||
<defName>ARA_Ability_Possess</defName>
|
||
<label>阿拉克涅寄生</label>
|
||
<description>将你的意识注入另一个生物的身体,完全占据它。</description>
|
||
<iconPath>UI/Abilities/Possess</iconPath> <!-- TODO: 需要一张图标 -->
|
||
<cooldownTicks>600</cooldownTicks>
|
||
<verbProperties>
|
||
<verbClass>Verb_CastAbility</verbClass>
|
||
<warmupTime>1.5</warmupTime>
|
||
<range>5.9</range>
|
||
<targetParams>
|
||
<canTargetPawns>true</canTargetPawns>
|
||
<canTargetBuildings>false</canTargetBuildings>
|
||
<canTargetSelf>false</canTargetSelf>
|
||
<canTargetLocations>false</canTargetLocations>
|
||
</targetParams>
|
||
</verbProperties>
|
||
<comps>
|
||
<!-- 关键:将这个技能与我们的C#属性类关联起来 -->
|
||
<li Class="ArachnaeSwarm.Possession.CompProperties_AbilityPossess"/>
|
||
</comps>
|
||
</AbilityDef>
|
||
|
||
<!-- ==================== 生物AI定义 (可选) ==================== -->
|
||
<ThinkTreeDef>
|
||
<defName>ARA_Facehugger</defName>
|
||
<insertTag>Humanlike_PostMentalState</insertTag>
|
||
<insertPriority>100</insertPriority>
|
||
<thinkRoot Class="ThinkNode_Priority">
|
||
<subNodes>
|
||
<!-- 在这里可以为抱脸虫添加自定义AI,例如当它空闲时自动寻找宿主 -->
|
||
</subNodes>
|
||
</thinkRoot>
|
||
</ThinkTreeDef>
|
||
|
||
<!-- ==================== 生物类型定义 ==================== -->
|
||
<PawnKindDef>
|
||
<defName>ARA_Facehugger</defName>
|
||
<label>阿拉克涅原虫</label>
|
||
<!-- 关联下面的种族定义 -->
|
||
<race>ARA_FacehuggerRace</race>
|
||
<combatPower>25</combatPower>
|
||
<lifeStages>
|
||
<li>
|
||
<bodyGraphicData>
|
||
<texPath>Things/Pawn/Animal/ARA_Facehugger</texPath> <!-- TODO: 需要贴图 -->
|
||
<drawSize>0.8</drawSize>
|
||
</bodyGraphicData>
|
||
<dessicatedBodyGraphicData>
|
||
<texPath>Things/Pawn/Animal/Dessicated/CritterDessicated</texPath>
|
||
<drawSize>0.8</drawSize>
|
||
</dessicatedBodyGraphicData>
|
||
</li>
|
||
</lifeStages>
|
||
<aiThinkTree>ARA_Facehugger</aiThinkTree>
|
||
<abilities>
|
||
<!-- 赋予该生物我们的夺舍技能 -->
|
||
<li>ARA_Ability_Possess</li>
|
||
</abilities>
|
||
</PawnKindDef>
|
||
|
||
<!-- ==================== 种族定义 ==================== -->
|
||
<ThingDef ParentName="AnimalThingBase">
|
||
<defName>ARA_FacehuggerRace</defName>
|
||
<label>阿拉克涅原虫</label>
|
||
<description>一种小型的、脆弱的寄生生物,其唯一的生存目的就是寻找并占据一个更强大的宿主。它通过将自己的意识注入目标来完成这一过程。</description>
|
||
<statBases>
|
||
<MoveSpeed>4.0</MoveSpeed>
|
||
<MarketValue>50</MarketValue>
|
||
<ComfyTemperatureMin>-10</ComfyTemperatureMin>
|
||
<ComfyTemperatureMax>50</ComfyTemperatureMax>
|
||
</statBases>
|
||
<tools>
|
||
<li>
|
||
<label>tiny claws</label>
|
||
<capacities>
|
||
<li>Scratch</li>
|
||
</capacities>
|
||
<power>2</power>
|
||
<cooldownTime>1.5</cooldownTime>
|
||
</li>
|
||
</tools>
|
||
<race>
|
||
<thinkTreeMain>Animal</thinkTreeMain>
|
||
<!-- 关联下面的身体定义 -->
|
||
<body>ARA_FacehuggerBody</body>
|
||
<baseBodySize>0.2</baseBodySize>
|
||
<baseHealthScale>0.3</baseHealthScale>
|
||
<baseHungerRate>0.1</baseHungerRate>
|
||
<lifeStageAges>
|
||
<li>
|
||
<def>AnimalAdult</def>
|
||
<minAge>0</minAge>
|
||
</li>
|
||
</lifeStageAges>
|
||
</race>
|
||
</ThingDef>
|
||
|
||
<!-- ==================== 身体结构定义 ==================== -->
|
||
<BodyDef>
|
||
<defName>ARA_FacehuggerBody</defName>
|
||
<label>facehugger</label>
|
||
<corePart>
|
||
<def>Body</def>
|
||
<height>20</height>
|
||
<depth>20</depth>
|
||
<parts>
|
||
<li>
|
||
<def>Head</def>
|
||
<coverage>0.3</coverage>
|
||
<parts>
|
||
<li>
|
||
<def>Skull</def>
|
||
<coverage>0.2</coverage>
|
||
<depth>Inside</depth>
|
||
<parts>
|
||
<li>
|
||
<def>Brain</def>
|
||
<coverage>0.1</coverage>
|
||
<depth>Inside</depth>
|
||
</li>
|
||
</parts>
|
||
</li>
|
||
<li>
|
||
<def>Eye</def>
|
||
<customLabel>left eye</customLabel>
|
||
<coverage>0.07</coverage>
|
||
</li>
|
||
<li>
|
||
<def>Eye</def>
|
||
<customLabel>right eye</customLabel>
|
||
<coverage>0.07</coverage>
|
||
</li>
|
||
</parts>
|
||
</li>
|
||
<li>
|
||
<def>Leg</def>
|
||
<customLabel>front left leg</customLabel>
|
||
<coverage>0.1</coverage>
|
||
</li>
|
||
<li>
|
||
<def>Leg</def>
|
||
<customLabel>front right leg</customLabel>
|
||
<coverage>0.1</coverage>
|
||
</li>
|
||
<li>
|
||
<def>Leg</def>
|
||
<customLabel>rear left leg</customLabel>
|
||
<coverage>0.1</coverage>
|
||
</li>
|
||
<li>
|
||
<def>Leg</def>
|
||
<customLabel>rear right leg</customLabel>
|
||
<coverage>0.1</coverage>
|
||
</li>
|
||
</parts>
|
||
</corePart>
|
||
</BodyDef>
|
||
|
||
</Defs>
|
||
```
|
||
|
||
---
|
||
|
||
这份详尽的文档现在包含了我们所有的最终代码和XML,并附有详细的注释,解释了每一步的作用和它们之间的关联。 |