今天一整天的调试,最终让我们看清了一个核心结论:定义域与值域必须彻底分离。 以下是把今天所有混乱和修复整理成的一套规则,可以作为新项目的“装备系统设计文档”直接使用。
这些数据在游戏运行期间不会发生变化,它们只存在于 JSON 文件中,作为“模板”。
| 文件 | 内容 | 字段示例 |
|------|------|----------|
| `items.json` | 装备模板 | `id`, `name`, `type`, `stats`, `price`, `quality`(仅限模板默认品质) |
| `effects.json` | 效果模板 | `id`, `name`, `description`, `template`, `stacking`, `maxStack` |
| `loot.json` | 掉落策略 | `chance`, `range`, `quality`分布, `rareEffects`池, `jumpPoint`配置 |
关键原则:
这些数据在游戏运行期间会变化、会被生成、会被玩家操作,存储在 `gameState` 中。
| 数据结构 | 存储位置 | 字段示例 |
|----------|----------|----------|
| 装备实例 | `gameState.inventory[]` | `instanceId`, `templateId`, `quality`, `effects`, `bonusStats` |
| 装备槽 | `gameState.player.equipment` | `weapon: instanceId`, `armor: instanceId` |
| 玩家最终属性 | `gameState.player.finalStats` | `attackMin`, `attackMax`, `defensePhysical`, `defenseMagical`, `hp` |
关键原则:
- 每件装备都是独立实例(`instanceId` 唯一),不合并、不覆盖
- 装备槽只存实例 ID,不存模板 ID,不存完整对象
- 最终属性由 模板 + 实例 合并计算得出,战斗系统只读取 `finalStats`
当一件装备被创建时(掉落、购买、奖励),系统执行以下流程:
1. 从定义域读取模板(items.json) 2. 从掉落策略读取品质分布,roll 出一个品质 3. 如果模板有固定品质,覆盖品质(如:布衣→普通,炼狱→特殊) 4. 如果品质为 rare,从 effects.json 中抽取 1~2 个效果,附加到实例 5. 如果品质为 special 或 rare,执行跳点判定(连续尝试,一次失败即停止) 6. 生成独立 instanceId,存入 inventory
跳点规则(今日已确认可用):
recalculateCombatStats()
├── 重置 finalStats 为 0
├── 遍历装备槽(weapon, armor, helmet, necklace, bracelet, ring)
│ ├── 通过 instanceId 从 inventory 找到装备实例
│ ├── 通过 templateId 从 items.json 找到装备模板
│ ├── 基础属性 = 模板.stats
│ ├── 跳点加成 = 实例.bonusStats
│ ├── 效果 = 实例.effects(用于 combatStats.modifiers)
│ └── 最终属性 = 基础属性 + 跳点加成
├── 写入 player.finalStats
└── 战斗系统只读取 player.finalStats
关键原则:
- 属性计算是纯函数,无副作用
- 计算结果缓存在 `finalStats` 中,不实时计算
- 装备变化时重新计算,不是每次战斗都计算
效果是数据驱动的,不硬编码:
| 品质 | 颜色 | 显示 | 效果 |
|------|------|------|------|
| normal | 灰色 | "普通" | 无跳点,无额外效果 |
| special | 蓝色 | "特殊" | 可触发跳点,不自动附加效果 |
| rare | 金色 | "稀有" | 可触发跳点,自动附加 1~2 个效果 |
关键原则:
- 品质是运行时属性,不是定义域属性(但模板可以指定默认品质)
- 品质决定了颜色显示和机制行为(是否跳点、是否附加效果)
| 坑 | 后果 | 正确做法 |
|----|------|----------|
| 装备槽存 `itemId` 字符串 | 丢失实例信息,无法区分同名装备 | 存 `instanceId` |
| 背包中同名装备合并 | 属性丢失,品质丢失 | 每件装备独立实例,不合并 |
| 战斗函数直接读取 `items.json` | 跳点、品质、效果全部失效 | 战斗函数只读取 `player.finalStats` |
| 效果用 `if` 枚举 | 每个新效果都要改战斗代码 | 数据驱动 + `modifiers` 对象 |
| 属性计算散落在各处 | 逻辑不一致,难以追踪 | 统一在 `recalculateCombatStats()` 中完成 |
| 跳点作为临时补丁 | 代码混乱,难以维护 | 跳点是装备实例的属性,是定义域的一部分 |
data/definitions/ ├── items.json # 装备模板(不变) ├── effects.json # 效果模板(不变) ├── loot.json # 掉落策略(不变) └── monsters.json # 怪物模板(不变) data/runtime/ ├── inventory.json # 装备实例列表(可变) ├── equipment.json # 装备槽引用(可变) └── player.json # 最终属性 + 状态(可变) 计算层(纯函数): └── recalculateCombatStats() # 模板 + 实例 → 最终属性 战斗层(只读): └── 只读取 player.finalStats
你提到的三个阶段——单人 RPG、组队协作、组织运营——对装备系统的要求会逐级变化:
第一阶段(单人 RPG):
第二阶段(组队协作):
第三阶段(组织运营):
今天完善的装备系统,已经为第一阶段做好了准备。第二阶段和第三阶段,是在这个基础上做扩展,而不是推翻重来。
---
明天要讨论的问题:
—— 人与AI协作记录 ——