加key值
This commit is contained in:
158
Source/Documents/New_Component_Design.md
Normal file
158
Source/Documents/New_Component_Design.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# 开发说明书: 交互式品质生成器 (V5.1 - 最终补充版)
|
||||
|
||||
## 1. 核心概念
|
||||
|
||||
`CompInteractiveProducer` 是一个**主控制器**组件。它管理的建筑拥有一个统一的“生物质燃料”池。玩家可以通过**精确配置的燃料白/黑名单**,决定哪些物品可以作为燃料。
|
||||
|
||||
当玩家启动一个生产流程时,该流程会有一个**专属的、固定的总燃料消耗量**和**生产时间**。在生产过程中,组件会持续消耗燃料池,并根据燃料和温度的理想条件,计算最终产物的品质。
|
||||
|
||||
## 2. 架构设计
|
||||
|
||||
- **`CompInteractiveProducer` (控制器)**: 继承自 `ThingComp`,并实现 `IStoreSettingsParent`,负责所有逻辑。
|
||||
- **`CompProperties_InteractiveProducer` (数据)**: 在 XML 中定义所有生产流程及其对应的参数,以及全局的燃料接受规则。
|
||||
|
||||
---
|
||||
## 3. 依赖项说明
|
||||
|
||||
**重要**: 本组件的正常工作依赖于一个在 XML 中预先定义的 `JobDef`。交互菜单会尝试创建这个 Job 并分配给 Pawn。
|
||||
|
||||
**示例 `JobDef` 定义 (`Jobs.xml`):**
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
<JobDef>
|
||||
<defName>ARA_IncubateJob</defName>
|
||||
<driverClass>ArachnaeSwarm.JobDriver_Incubate</driverClass>
|
||||
<reportString>正在启动生产 TargetA.</reportString>
|
||||
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
|
||||
</JobDef>
|
||||
</Defs>
|
||||
```
|
||||
*注: `JobDriver_Incubate` 是一个简单的 JobDriver,其核心逻辑就是让 Pawn 走到建筑旁,然后调用 `comp.StartProduction(process)`。*
|
||||
|
||||
---
|
||||
|
||||
## 4. 实现步骤与完整代码
|
||||
|
||||
### **第 1 步: 定义支持精准配置的属性类**
|
||||
|
||||
**目的**: 创建 C# 类来映射新的、更详细的 XML 结构。
|
||||
|
||||
**产出代码 (属性类 V5):**
|
||||
```csharp
|
||||
// (代码与上一版相同,此处为简洁省略)
|
||||
```
|
||||
|
||||
### **第 2 步: 实现完整的主组件**
|
||||
|
||||
**目的**: 编写最终的、包含所有新逻辑的 `CompInteractiveProducer` 类。
|
||||
|
||||
#### **代码解析与补充说明**
|
||||
|
||||
```csharp
|
||||
// (此处为完整的 V5 版本 C# 代码)
|
||||
// ...
|
||||
|
||||
// --- 交互与生产流程 ---
|
||||
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
|
||||
{
|
||||
// ...
|
||||
// **补充说明**: 此处创建的 Job "ARA_IncubateJob" 必须在 XML 中有对应定义。
|
||||
// 该 Job 的 Driver 应包含走到 parent 旁边,然后调用 StartProduction() 的逻辑。
|
||||
// ...
|
||||
}
|
||||
|
||||
private void FinishProduction()
|
||||
{
|
||||
// ...
|
||||
// **补充说明**: 最终品质的计算公式为:
|
||||
// finalQualityScore = Clamp01( (ticksUnderOptimalConditions / totalTicks) - temperaturePenaltyPercent )
|
||||
// 这意味着温度惩罚是直接从基础品质分中扣除的。
|
||||
// ...
|
||||
}
|
||||
|
||||
private void ResetProduction()
|
||||
{
|
||||
// **补充说明**: 此方法会清空所有生产进度。
|
||||
// 如果玩家通过 Gizmo 中途取消,所有累积的“理想时间”和“温度惩罚”都会丢失。
|
||||
_selectedProcess = null;
|
||||
productionUntilTick = -1;
|
||||
ticksUnderOptimalConditions = 0;
|
||||
temperaturePenaltyPercent = 0f;
|
||||
}
|
||||
|
||||
// --- 燃料系统方法 ---
|
||||
private float GetNutritionInContainer()
|
||||
{
|
||||
// **性能备注**: 此方法会遍历容器。在绝大多数情况下性能良好。
|
||||
// 如果 Mod 允许容器内有成百上千的物品,可考虑增加缓存,不必每帧都计算。
|
||||
// ...
|
||||
}
|
||||
|
||||
// --- IStoreSettingsParent & IThingHolder 实现 ---
|
||||
// **说明**: 这些接口的实现让我们的组件能被游戏原生的运输和存储系统识别。
|
||||
// GetStoreSettings() 暴露我们的配置,让小人知道可以运什么东西过来。
|
||||
// GetDirectlyHeldThings() 暴露我们的内部容器,让游戏知道我们持有哪些物品。
|
||||
|
||||
// --- UI 与 Gizmos ---
|
||||
public override string CompInspectStringExtra()
|
||||
{
|
||||
// ...
|
||||
// **UI 设计补充**:
|
||||
// 生产中: 应清晰显示 "预计品质",其计算公式为 (当前理想 tick 数 / 已进行 tick 数) - 当前温度惩罚。
|
||||
// 空闲时: 除了显示总燃料,还可增加一行提示,如 "可由 [白名单Pawn名称] 启动"。
|
||||
// ...
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> GetGizmos()
|
||||
{
|
||||
// ...
|
||||
// **Gizmo 设计补充**:
|
||||
// 取消按钮 (Command_Action) 的 action 应直接调用 ResetProduction()。
|
||||
// 可在开发者模式下增加调试按钮,如:
|
||||
// - "DEV: +10 营养"
|
||||
// - "DEV: 立即完成生产"
|
||||
// ...
|
||||
}
|
||||
|
||||
public override void PostDestroy(DestroyMode mode, Map previousMap)
|
||||
{
|
||||
base.PostDestroy(mode, previousMap);
|
||||
// **边缘情况处理**: 建筑被摧毁或卸载时,清空内部容器,
|
||||
// 默认情况下,容器内的物品会被丢弃在地上,这符合预期。
|
||||
innerContainer.TryDropAll(parent.Position, previousMap, ThingPlaceMode.Near);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
这份 V5.1 版本的说明书,在 V5 的基础上,补充了对依赖项、UI细节、边缘情况和性能的考量,使其作为开发蓝图更加健壮和周全。这应该是我们开始编码前所需要的最终版本了。
|
||||
|
||||
## 5. 新增组件:温度损坏组件 (CompTemperatureRuinableDamage)
|
||||
|
||||
### 5.1 设计目标
|
||||
创建一个新的组件,用于在极端温度下对物品造成持续伤害,并在温度恢复正常时逐渐恢复损坏进度。
|
||||
|
||||
### 5.2 组件属性类 (CompProperties_TemperatureRuinableDamage)
|
||||
- `minSafeTemperature`: 安全温度范围的最低温度
|
||||
- `maxSafeTemperature`: 安全温度范围的最高温度(默认100)
|
||||
- `progressPerDegreePerTick`: 每度温度每tick造成的损坏进度(默认1E-05f)
|
||||
- `damagePerTick`: 每tick造成的伤害值(默认1)
|
||||
- `recoveryRate`: 温度恢复正常时的恢复速率(默认0.001f)
|
||||
|
||||
### 5.3 组件类 (CompTemperatureRuinableDamage)
|
||||
- 继承自ThingComp,实现温度监控逻辑
|
||||
- 当物品温度超出安全范围时,根据温度差值累积损坏进度,并每tick造成持续伤害
|
||||
- 当温度恢复正常时,逐渐减少损坏进度而不是立即重置
|
||||
- 支持保存和加载损坏进度状态
|
||||
|
||||
### 5.4 使用方法
|
||||
在ThingDef的comps部分添加以下配置:
|
||||
```xml
|
||||
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
|
||||
<minSafeTemperature>13</minSafeTemperature>
|
||||
<maxSafeTemperature>28</maxSafeTemperature>
|
||||
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
|
||||
<damagePerTick>1</damagePerTick>
|
||||
<recoveryRate>0.001</recoveryRate>
|
||||
</li>
|
||||
```
|
||||
180
Source/Documents/SpawnPawnFromList_Design.md
Normal file
180
Source/Documents/SpawnPawnFromList_Design.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# 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` 建筑被摧毁。
|
||||
Reference in New Issue
Block a user