# 蜂巢意识（Hive Mind）系统设计文档 - v2

## 1. 需求概述

本设计旨在为 `ArachnaeSwarm` Mod 实现一个“蜂巢意识”系统。该系统包含两种角色：

-   **主节点 (Master)**：蜂巢的中心。
-   **子节点 (Drone)**：蜂巢的工蜂，可以有多个。

它们之间通过 `Hediff`（健康状态）进行链接，实现以下核心功能：

1.  **自动绑定**：子节点在生成时，会自动在地图上寻找携带 `ARA_HiveMindMaster` Hediff 的Pawn作为主节点。如果找到多个，则选择第一个进行绑定。如果找不到主节点，子节点会立即死亡。
2.  **主从死亡联动**：当主节点死亡时，所有与之链接的子节点也会立即死亡。
3.  **链接增益**：主节点的力量会随着链接的子节点数量增加而增强。具体表现为主节点的 `Hediff` 严重性（Severity）会随着子节点数量的增加而提升，为后续添加属性加成提供基础。

## 2. 技术方案

为了实现上述功能，我们将创建以下组件：

### 2.1. XML 定义 (使用 ARA_ 前缀)

我们将定义两个新的 `HediffDef`:

-   `HediffDef: ARA_HiveMindMaster`
    -   **hediffClass**: `ArachnaeSwarm.Hediff_HiveMindMaster`
    -   **描述**: 应用于主节点，用于管理子节点链接并根据数量调整严重性。
-   `HediffDef: ARA_HiveMindDrone`
    -   **hediffClass**: `ArachnaeSwarm.Hediff_HiveMindDrone`
    -   **描述**: 应用于子节点，继承自 `HediffWithTarget`，其 `target` 字段将指向主节点。

### 2.2. C# 类定义 (命名空间: ArachnaeSwarm)

我们将实现两个新的C#类：

-   `Hediff_HiveMindMaster`
    -   继承自 `Hediff`。
    -   包含一个 `List<Pawn>` 类型的字段 `drones`，用于存储所有已链接的子节点。
    -   提供 `RegisterDrone(Pawn drone)` 和 `DeregisterDrone(Pawn drone)` 方法，用于添加和移除子节点。
    -   在每次注册/反注册后，更新自身的 `Severity` 属性，其值等于 `drones.Count`。
    -   重写 `PostRemoved()` 方法，在主节点死亡或Hediff被移除时，杀死所有已注册的子节点。

-   `Hediff_HiveMindDrone`
    -   继承自 `HediffWithTarget`。
    -   重写 `PostAdd(DamageInfo? dinfo)` 方法。在此方法中：
        1.  在当前地图上扫描所有Pawn，查找携带 `ARA_HiveMindMaster` Hediff 的单位。
        2.  如果找到至少一个，则选择第一个作为 `target`，并调用其 `RegisterDrone` 方法将自己注册进去。
        3.  如果找不到任何主节点，立即杀死自己 (`pawn.Kill(null, null)`)。
    -   重写 `PostRemoved()` 方法，在自身被移除时，如果 `target` 仍然有效，则调用其 `DeregisterDrone` 方法将自己从中移除。
    -   在 `PostTick()` 或类似方法中周期性检查 `target`（主节点）是否已死亡或 Hediff 已被移除。如果是，则立即杀死自己。

## 3. 开发步骤 (TODO List)

-   [ ] **步骤 1: 创建 XML 定义**
    -   在 `ArachnaeSwarm/1.6/Defs/HediffDefs/` 目录下创建 `ARA_Hediffs_HiveMind.xml` 文件。
-   [ ] **步骤 2: 实现 C# 类 `Hediff_HiveMindMaster`**
    -   在 `ArachnaeSwarm/Source/ArachnaeSwarm/` 目录下创建 `Hediff_HiveMindMaster.cs` 文件并编写代码。
-   [ ] **步骤 3: 实现 C# 类 `Hediff_HiveMindDrone`**
    -   在 `ArachnaeSwarm/Source/ArachnaeSwarm/` 目录下创建 `Hediff_HiveMindDrone.cs` 文件并编写代码。
-   [ ] **步骤 4: 更新项目文件**
    -   将新创建的 `.cs` 文件添加到 `ArachnaeSwarm.csproj` 项目文件中。
-   [ ] **步骤 5: 编译和测试**
    -   运行 `dotnet build` 编译项目，修复所有编译错误。
    -   进入游戏进行功能测试。

## 4. 参考代码

### `HediffWithTarget.cs`

```csharp
using Verse;

namespace RimWorld
{
    public class HediffWithTarget : HediffWithComps
    {
        public Thing target;

        public override bool ShouldRemove
        {
            get
            {
                if (target != null && !(target is Pawn { Dead: not false }))
                {
                    return base.ShouldRemove;
                }
                return true;
            }
        }

        public override void ExposeData()
        {
            base.ExposeData();
            Scribe_References.Look(ref target, "target");
        }
    }
}
```

### `Hediff_PsychicBond.cs`

```csharp
using Verse;

namespace RimWorld
{
    public class Hediff_PsychicBond : HediffWithTarget
    {
        private const int HediffCheckInterval = 65;

        public override string LabelBase => base.LabelBase + " (" + target?.LabelShortCap + ")";

        public override bool ShouldRemove
        {
            get
            {
                if (!base.ShouldRemove)
                {
                    return pawn.Dead;
                }
                return true;
            }
        }

        public override void PostRemoved()
        {
            base.PostRemoved();
            Gene_PsychicBonding gene_PsychicBonding = base.pawn.genes?.GetFirstGeneOfType<Gene_PsychicBonding>();
            if (gene_PsychicBonding != null)
            {
                gene_PsychicBonding.RemoveBond();
            }
            else if (target != null && target is Pawn pawn)
            {
                pawn.genes?.GetFirstGeneOfType<Gene_PsychicBonding>()?.RemoveBond();
            }
        }

        public override void PostTickInterval(int delta)
        {
            base.PostTickInterval(delta);
            if (pawn.IsHashIntervalTick(65, delta))
            {
                Severity = (ThoughtWorker_PsychicBondProximity.NearPsychicBondedPerson(pawn, this) ? 0.5f : 1.5f);
            }
        }
    }
}