# 04 内容与数据字典

本文档定义新项目的“数据驱动内容”规范：字段含义、约束与复用策略。目标是让内容策划能够在不改代码的情况下扩展大部分内容，同时让程序具备稳定、可验证的数据接口。

## 4.1 总体约束

- 所有配置都必须有 `id`（稳定、不可随意改名），并且支持本地化 `name/desc`。
- 配置要可增量加载：按“基础数据 → 扩展包（DLC/活动）”分层，不互相覆盖时尽量追加。
- 任何“逻辑分支”都尽量用配置表达（条件表达式、标签、权重表、效果链），避免硬编码。

## 4.2 通用结构

### 4.2.1 标签（Tags）

标签用于跨系统复用与筛选，避免重复字段：

- 物品标签：`food`, `water`, `medicine`, `scrap`, `tool`, `weapon`, `armor`, `ammo`, `quest`
- 地点标签：`home`, `settlement`, `ruins`, `tunnel`, `forest`, `vault`, `radiated`, `safe`
- 事件标签：`combat`, `trade`, `moral`, `hazard`, `story`
- 敌人标签：`human`, `mutant`, `insect`, `beast`, `robot`

### 4.2.2 条件（Condition）

用于事件/任务/配方/解锁等系统的统一条件表达：

- 状态阈值：`status.hunger >= 20`
- 物品拥有：`inventory.has("water_purified", 1)`
- 科技完成：`tech.has("water_filter_1")`
- 地点/标记：`world.flag("met_mysterious_trader") == true`
- 时间：`time.day >= 5 && time.hour >= 18`

实现建议：条件采用受限表达式语言（DSL）或 JSON 结构化条件，避免 `eval`。

### 4.2.3 效果（Effect）

所有可配置结果尽量拆成原子效果并支持链式组合：

- `AddItem/RemoveItem`
- `AddStatus`（可正可负）
- `AddBuff/RemoveBuff`
- `SetFlag`（任务/世界标记）
- `UnlockRecipe/UnlockTech/UnlockPlaceService`
- `StartCombat`
- `Teleport`
- `Log`

## 4.3 物品（Item）

### 4.3.1 字段定义（建议）

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id | string | 是 | 稳定唯一 ID |
| name | string | 是 | 显示名 |
| desc | string | 否 | 描述文本 |
| type | string | 是 | `food/material/tool/weapon/armor/ammo/quest/medicine` |
| tags | string[] | 否 | 标签，用于筛选与规则复用 |
| rarity | string | 否 | `common/uncommon/rare/epic` |
| stackLimit | number | 否 | 堆叠上限，默认 1 |
| volume | number | 否 | 占用体积，默认 1 |
| durability | {max:number} | 否 | 耐久，存在则可损耗 |
| effects | Effect[] | 否 | 使用后效果链（食物/药品等） |
| equipSlot | string | 否 | `weapon/head/body/foot` 等 |
| combat | object | 否 | 武器/护甲战斗参数 |
| baseValue | number | 否 | 基础交易价值 |
| craftable | boolean | 否 | 是否可制作（方便筛选 UI） |

### 4.3.2 武器/护甲 combat 字段（建议）

- 武器：
  - `damageMin/damageMax`
  - `range`
  - `hitBonus`
  - `ammoType`（可空：近战）
  - `critChance/critMult`
- 护甲：
  - `armor`
  - `dodgeBonus`
  - `radiationResist`（可选）

### 4.3.3 物品效果（使用）

食物/药品/饮水等用 `effects` 表达，避免写死：

```json
{
  "id": "water_purified",
  "name": "净水",
  "type": "water",
  "stackLimit": 10,
  "volume": 1,
  "effects": [
    {"type": "AddStatus", "status": "thirst", "value": 25},
    {"type": "AddStatus", "status": "radiation", "value": -2}
  ]
}
```

## 4.4 状态（Status）与阈值

### 4.4.1 字段定义

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id | string | 是 | `hunger/thirst/energy/life/san/radiation` 等 |
| name | string | 是 | 显示名 |
| desc | string | 否 | 说明 |
| min/max | number | 是 | 上下限 |
| value | number | 否 | 默认初值 |
| decayPerMin | number | 否 | 每分钟自然变化（负数表示下降） |
| thresholds | Threshold[] | 否 | 阈值效果表 |

### 4.4.2 Threshold 定义

- `atOrBelow` 或 `atOrAbove`
- `applyBuff` / `removeBuff`
- `uiHint`（用于提示玩家原因）

## 4.5 Buff/Debuff（Buff）

### 4.5.1 字段定义

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id | string | 是 | 稳定唯一 ID |
| name/desc | string | 是 | 显示 |
| type | string | 是 | `good/bad/neutral` |
| durationMin | number | 否 | 持续分钟数，空表示永久直到清除 |
| stack | object | 否 | 堆叠规则（maxStacks/refreshPolicy） |
| tickIntervalMin | number | 否 | 结算间隔 |
| effects | Effect[] | 否 | 结算效果（例如每 10 分钟掉理智） |
| modifiers | object | 否 | 属性修正（命中/速度/消耗倍率） |

## 4.6 配方与科技（Recipe / Tech）

### 4.6.1 配方（Recipe）

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id/name | string | 是 | 标识 |
| workbenchType | string | 是 | `hand/workshop/forge/cook/filter/med/lab` |
| requirements | Condition[] | 否 | 条件集合 |
| inputs | {itemId:string,count:number}[] | 是 | 消耗 |
| outputs | {itemId:string,count:number,weight?:number}[] | 是 | 产出（可做权重表） |
| timeCostMin | number | 是 | 耗时 |
| energyCost | number | 否 | 精力消耗 |
| sideEffects | Effect[] | 否 | 副作用（辐射、疲劳等） |

### 4.6.2 科技（Tech）

科技节点建议用“解锁能力”表达：

- 解锁配方：`unlockRecipes`
- 解锁地点服务：`unlockServices`
- 永久修正：`modifiers`（例如制作耗时倍率 -10%）
- 前置：`requires`（其他科技、状态阈值、完成任务）

## 4.7 地图与地点（Map / Place）

### 4.7.1 地点 Place

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id/name | string | 是 | 标识 |
| tags | string[] | 否 | `home/ruins/vault` 等 |
| dangerLevel | number | 是 | 0–10 |
| services | string[] | 否 | `trade/rest/craft/heal/info` |
| resourceNodes | ResourceNode[] | 否 | 可采集资源 |
| trashNodes | TrashNode[] | 否 | 垃圾池 |
| encounterTable | EncounterEntry[] | 否 | 遭遇权重表 |
| eventPools | string[] | 否 | 事件池 ID（通用+地点专属） |
| questHooks | QuestHook[] | 否 | 任务触发钩子 |

### 4.7.2 路径 Edge

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| from/to | string | 是 | 起终点地点 ID |
| travelTimeMin | number | 是 | 基础耗时 |
| risk | number | 否 | 途中风险修正（影响遭遇概率） |
| conditions | Condition[] | 否 | 需要某工具/科技才能通行 |

### 4.7.3 资源节点 ResourceNode

- `id/name`
- `refreshMin`：刷新/生长间隔
- `maxStock`：最大存量
- `growsPerRefresh`：每次生长数量
- `harvestCost`：时间/精力/工具
- `outputs`：产出物品权重表

### 4.7.4 垃圾节点 TrashNode

- `refreshMin`
- `risk`：触发负面事件概率加成
- `lootTable`：掉落权重表

## 4.8 敌人（Enemy）

### 4.8.1 字段定义

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id/name | string | 是 | 标识 |
| tags | string[] | 否 | 类别标签 |
| level | number | 否 | 用于难度缩放 |
| life | number | 是 | 生命 |
| attack | {min:number,max:number} | 是 | 攻击 |
| armor | number | 否 | 护甲 |
| range | number | 否 | 射程 |
| hitRate | number | 否 | 命中 |
| skills | string[] | 否 | 技能 ID 列表 |
| lootTable | LootEntry[] | 否 | 掉落表 |

## 4.9 事件（Event）

### 4.9.1 字段定义

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id | string | 是 | 事件 ID |
| tags | string[] | 否 | `combat/story/hazard` 等 |
| conditions | Condition[] | 否 | 触发条件 |
| weight | number | 否 | 权重，默认 1 |
| text | string | 是 | 主文本 |
| options | Option[] | 否 | 选项列表（0–4） |

Option：

- `text`
- `conditions`
- `check`（属性检定配置，可选）
- `effects`（成功/失败效果链）

## 4.10 任务（Quest）

### 4.10.1 字段定义

| 字段 | 类型 | 必填 | 说明 |
|---|---:|:---:|---|
| id/title | string | 是 | 标识 |
| type | string | 是 | `main/side/dynamic` |
| desc | string | 否 | 描述 |
| prereq | Condition[] | 否 | 前置条件 |
| steps | QuestStep[] | 是 | 阶段目标 |
| rewards | Effect[] | 否 | 完成奖励 |
| failConditions | Condition[] | 否 | 失败条件（可选） |

QuestStep 支持目标：

- `ReachPlace`
- `CollectItem`
- `DefeatEnemy`
- `CraftRecipe`
- `TriggerEvent`
- `SurviveDays`

## 4.11 日志（Log）与可观测性

为了让系统可解释、可测试、可回放：

- 所有关键变化都写日志：
  - 状态变化（原因、数值）
  - 战斗结果（命中/伤害/距离）
  - 事件结果（选项、成功/失败、消耗/获得）
  - 任务推进（步骤变化）
- 日志结构化，支持筛选与上报：
  - `timestamp`
  - `category`
  - `message`
  - `payload`（可选）

