# CompSpawnPawnFromList 功能设计文档

## 1. 功能概述

`CompSpawnPawnFromList` 是一个 `ThingComp` 组件，它允许一个特定的 Pawn 通过右键菜单与一个物体交互，从一个可配置的列表中选择一个 Pawn，并在经过一段可配置的延迟后，生成这个 Pawn。在延迟期间，剩余时间会显示在建筑的检查面板上。可以选择在生成 Pawn 后是否摧毁建筑。

## 2. XML 配置

### 2.1. 配置属性

*   `pawnKinds` (`List<PawnKindDef>`): 一个 `PawnKindDef` 的列表，用于填充右键菜单的选项。
*   `whitelist` (`List<PawnKindDef>`): 一个 `PawnKindDef` 的白名单，只有在这个列表中的 Pawn 才能看到并使用这个右键菜单。
*   `delay` (`int`): 延迟时间，单位为 Ticks (1秒 = 60 Ticks)。
*   `destroyOnSpawn` (`bool`): (可选, 默认为 `false`) 如果为 `true`，则在生成 Pawn 后摧毁建筑。
*   `lordJob` (`Type`): (可选) 生成的 Pawn 要执行的集体任务。

### 2.2. XML 示例

```xml
<ThingDef ParentName="BuildingBase">
  <defName>ARA_PawnSpawner</defName>
  <label>Pawn Spawner</label>
  <description>A device that can be used to spawn pawns after a delay.</description>
  <!-- 其他属性 -->
  <comps>
    <li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
      <pawnKinds>
        <li>Megascarab</li>
        <li>Spelopede</li>
      </pawnKinds>
      <whitelist>
        <li>Colonist</li>
      </whitelist>
      <delay>300</delay> <!-- 5秒 -->
      <destroyOnSpawn>true</destroyOnSpawn>
      <lordJob>RimWorld.LordJob_AssaultColony</lordJob>
    </li>
  </comps>
</ThingDef>
```

## 3. 类设计

### 3.1. `CompProperties_SpawnPawnFromList.cs`

```csharp
using System;
using System.Collections.Generic;
using Verse;

namespace ArachnaeSwarm
{
    public class CompProperties_SpawnPawnFromList : CompProperties
    {
        public List<PawnKindDef> pawnKinds;
        public List<PawnKindDef> whitelist;
        public int delay = 0;
        public bool destroyOnSpawn = false;
        public Type lordJob;

        public CompProperties_SpawnPawnFromList()
        {
            compClass = typeof(CompSpawnPawnFromList);
        }

        public override IEnumerable<string> ConfigErrors(ThingDef parentDef)
        {
            foreach (string item in base.ConfigErrors(parentDef))
            {
                yield return item;
            }
            if (lordJob != null && !typeof(RimWorld.LordJob).IsAssignableFrom(lordJob))
            {
                yield return $"lordJob {lordJob} must be of type LordJob";
            }
        }
    }
}
```

### 3.2. `CompSpawnPawnFromList.cs`

```csharp
using System.Collections.Generic;
using Verse;
using RimWorld;

namespace ArachnaeSwarm
{
    public class CompSpawnPawnFromList : ThingComp
    {
        private CompProperties_SpawnPawnFromList Props => (CompProperties_SpawnPawnFromList)props;

        private int spawnUntilTick = -1;
        private PawnKindDef spawningPawnKind;
        
        public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
        {
            if (spawnUntilTick > 0)
            {
                yield break; // 正在延迟中，不显示菜单
            }

            if (Props.whitelist == null || !Props.whitelist.Contains(selPawn.kindDef))
            {
                yield break;
            }

            if (Props.pawnKinds != null)
            {
                foreach (PawnKindDef pawnKind in Props.pawnKinds)
                {
                    yield return new FloatMenuOption($"Spawn {pawnKind.label}", () =>
                    {
                        StartDelayedSpawn(pawnKind);
                    });
                }
            }
        }

        private void StartDelayedSpawn(PawnKindDef pawnKind)
        {
            spawningPawnKind = pawnKind;
            spawnUntilTick = Find.TickManager.TicksGame + Props.delay;
        }

        public override void CompTick()
        {
            base.CompTick();
            if (spawnUntilTick > 0 && Find.TickManager.TicksGame >= spawnUntilTick)
            {
                SpawnPawn(spawningPawnKind);
                spawnUntilTick = -1;
                spawningPawnKind = null;
            }
        }

        private void SpawnPawn(PawnKindDef pawnKind)
        {
            Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
            GenSpawn.Spawn(pawn, parent.Position, parent.Map);

            if (Props.lordJob != null)
            {
                Lord lord = LordMaker.MakeNewLord(parent.Faction, (LordJob)System.Activator.CreateInstance(Props.lordJob), parent.Map);
                lord.AddPawn(pawn);
            }

            if (Props.destroyOnSpawn)
            {
                parent.Destroy(DestroyMode.Vanish);
            }
        }

        public override string CompInspectStringExtra()
        {
            if (spawnUntilTick > 0)
            {
                int remainingTicks = spawnUntilTick - Find.TickManager.TicksGame;
                return $"Spawning in: {remainingTicks.ToStringTicksToPeriod()}";
            }
            return base.CompInspectStringExtra();
        }

        public override void PostExposeData()
        {
            base.PostExposeData();
            Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
            Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind");
        }
    }
}
```

## 4. 使用示例

1.  一个 `Colonist` 右键点击 `ARA_PawnSpawner`，选择 "Spawn Megascarab"。
2.  `ARA_PawnSpawner` 进入延迟状态。当玩家选中它时，检查面板会显示 "Spawning in: 5 seconds"。
3.  5 秒后，一个新的 `Megascarab` 被生成。
4.  由于 `destroyOnSpawn` 为 `true`，`ARA_PawnSpawner` 建筑被摧毁。