5.7 KiB
5.7 KiB
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 示例
<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
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
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. 使用示例
- 一个
Colonist右键点击ARA_PawnSpawner,选择 "Spawn Megascarab"。 ARA_PawnSpawner进入延迟状态。当玩家选中它时,检查面板会显示 "Spawning in: 5 seconds"。- 5 秒后,一个新的
Megascarab被生成。 - 由于
destroyOnSpawn为true,ARA_PawnSpawner建筑被摧毁。