docs(hero-config): add hero configuration UI design documentation
新增英雄配置UI的完整设计方案文档,包含架构、数据流、JSON存储规范、生成器逻辑、UI布局与交互细节,以及实施步骤和校验规则。
This commit is contained in:
11
assets/script/game/common/config/英雄设计指引.md.meta
Normal file
11
assets/script/game/common/config/英雄设计指引.md.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"importer": "text",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "82be1e57-4be9-4315-ba27-0c2789fbd9f2",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
242
assets/script/game/common/config/英雄配置UI设计方案.md
Normal file
242
assets/script/game/common/config/英雄配置UI设计方案.md
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
# 英雄配置 UI 设计方案
|
||||||
|
|
||||||
|
> 为编辑器扩展 `extensions/hero_setup` 新增「英雄配置」功能的设计文档。
|
||||||
|
> 目标:以 [SkillSet.ts](./SkillSet.ts) / [BuffSet.ts](./BuffSet.ts) / FieldSkillSet 为只读底座,通过 UI 配置英雄(新增 + 编辑现有),落地 [英雄设计方案.md](./英雄设计方案.md) 与 [英雄设计指引.md](./英雄设计指引.md) 的能力池范式。
|
||||||
|
>
|
||||||
|
> **已确认决策**:
|
||||||
|
> - lv 档位按文档完整支持 **lv2/3/5/7/9**(数据先行),超过运行时 `HERO_MAX_LV=6` 的档给黄色警告不阻止
|
||||||
|
> - 落地方式 **JSON 外部化**:JSON 为 source of truth,单向生成 heroSet.ts 数据段
|
||||||
|
> - 功能范围:**新增英雄 + 编辑现有英雄**(不做删除)
|
||||||
|
> - 校验:uuid 存在性 + 段位规则 + lv 升序 + t_num≥1 + 形态硬约束
|
||||||
|
> - 生成器边界:**标记注释定界**(分歧裁定 1)
|
||||||
|
> - 怪物段:**全量迁移进 JSON、UI 只读**(分歧裁定 2,round-trip 门保真)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、总体架构与数据流
|
||||||
|
|
||||||
|
```
|
||||||
|
heroSet.data.json(source of truth,git 跟踪)
|
||||||
|
│ ① 扩展保存时生成(单向 JSON→TS)
|
||||||
|
▼
|
||||||
|
heroSet.ts 数据段(HeroInfo 表 + HeroList = 生成产物,其余 ~500 行类型/函数原样保留)
|
||||||
|
│ ② 下游零改动
|
||||||
|
▼
|
||||||
|
CardPoolList 自动派生 | eval-heroes 强度评估 | 游戏运行时
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
面板(Vue3,同面板双 tab:强度评估|英雄配置)
|
||||||
|
│ Editor.Message.request('hero_setup', ...)
|
||||||
|
▼
|
||||||
|
主进程 methods ──spawn──► scripts/heroes-cli.ts(复用 tsx + tsconfig.eval.json + mock-cc 链路)
|
||||||
|
│ --cmd=query-base | export | validate
|
||||||
|
├─ 读 JSON / 校验
|
||||||
|
└─ save:备份 → 写 TS → 语法自检 → round-trip 比对 → 写 JSON → refresh-asset
|
||||||
|
```
|
||||||
|
|
||||||
|
关键原则:
|
||||||
|
- **运行时零改动**:游戏代码、CardSet 派生链、eval-heroes、下游 49 个 import 方均不感知本功能存在
|
||||||
|
- **同步方向单向**:JSON → heroSet.ts,TS 数据段永远为生成产物;不一致时弹冲突对话框(含 diff),提供一次性「以 TS 反向导入」通道,禁止静默覆盖
|
||||||
|
- **CardPoolList 无需手动同步**:新英雄写入 HeroInfo + HeroList 后,CardSet 模块加载期自动生成卡池条目
|
||||||
|
|
||||||
|
## 二、JSON 存储
|
||||||
|
|
||||||
|
### 2.1 位置
|
||||||
|
|
||||||
|
`assets/script/game/common/config/heroSet.data.json`
|
||||||
|
|
||||||
|
| 候选 | 结论 | 理由 |
|
||||||
|
|---|---|---|
|
||||||
|
| assets/script/.../heroSet.data.json | **采用** | 与 heroSet.ts 同目录、随 git 入库 |
|
||||||
|
| assets/resources/ 下 | 否决 | resources 目录全量打包进游戏 |
|
||||||
|
| extensions/hero_setup/ 内 | 否决 | `.gitignore` 整体忽略 extensions/*,source of truth 会丢版本历史 |
|
||||||
|
| 项目根 config/ | 备选 | 零 asset-db 干扰,但离代码远、易被误删 |
|
||||||
|
|
||||||
|
注:JSON 不被任何运行时代码 import,Cocos 构建不会打包它;asset-db 会为其生成 .meta,代价可接受。
|
||||||
|
|
||||||
|
### 2.2 Schema 要点
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface HeroConfigFile {
|
||||||
|
schema_version: 1; // 结构性变更时递增,读取端按版本迁移
|
||||||
|
generated_at: string; // ISO 时间(人读)
|
||||||
|
gen_hash: string; // 上次生成 TS 数据段指纹,用于漂移检测
|
||||||
|
heroes: Record<number, HeroJson>; // 英雄(5001~5499 段)
|
||||||
|
monsters: Record<number, HeroJson>; // 怪物(6001~6199 段,UI 只读)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
与 `heroInfo` 接口逐字段对齐,仅三处转换:
|
||||||
|
|
||||||
|
| 转换 | JSON 存储 | 生成还原 |
|
||||||
|
|---|---|---|
|
||||||
|
| 枚举 | 语义字符串 `"type": "Melee"` | `HType.Melee`(生成端持名称→成员映射表) |
|
||||||
|
| 基准属性(英雄) | `{ ref: "HERO_ROLE_BASE", role: "Tank", delta: 1200 }` | `HERO_ROLE_BASE[HRole.Tank].hp + 1200`(delta 0 省略 `+ 0`) |
|
||||||
|
| 基准属性(怪物) | 绝对值 `hp: 3000` | 直接数值 |
|
||||||
|
| 攻速 cd | `atk_speed: "Slow"` | `AtkSpeedSet[AtkSpeedLv.Slow].cd` |
|
||||||
|
|
||||||
|
设计理由:
|
||||||
|
- 枚举存字符串:diff 友好、手改安全、枚举成员重排不破坏数据
|
||||||
|
- 属性存「基准引用+增量」:保住 `HERO_ROLE_BASE` 模板调参全局传播语义(heroSet.ts L145 注释意图);**禁止 JSON 出现已求值裸数值**,杜绝基准值改动后历史英雄静默漂移
|
||||||
|
- UI 端用底座数据实时计算绝对值预览(基准+增量双输入)
|
||||||
|
|
||||||
|
## 三、heroSet.ts 生成器(核心)
|
||||||
|
|
||||||
|
### 3.1 边界定位:标记注释定界
|
||||||
|
|
||||||
|
- 首次迁移(`--cmd=export`)时在 `export const HeroInfo` 前插入 `// @hero-setup:region-begin`,在 `HeroList` 数组 `];` 后插入 `// @hero-setup:region-end`
|
||||||
|
- 此后每次生成:读全文 → 定位两标记 → `前缀 + 生成段 + 后缀` 拼接
|
||||||
|
- **双保险**:
|
||||||
|
- 标记被手删 → 拒绝生成并提示走「重新导入」流程,绝不退化为全文件重写
|
||||||
|
- 保存前重算当前 TS 数据段指纹与 JSON 的 `gen_hash` 比对,不一致 → 弹冲突对话框(展示 diff,二选一:以 TS 反向导入一次 / 以 JSON 覆盖)
|
||||||
|
|
||||||
|
### 3.2 自研序列化器(非 JSON.stringify)
|
||||||
|
|
||||||
|
格式保真清单(与现文件逐项对齐,round-trip 门验证):
|
||||||
|
|
||||||
|
| 不变量 | 依赖方 |
|
||||||
|
|---|---|
|
||||||
|
| 4 空格缩进、双引号、行尾无分号风格跟随原文件 | 全部 diff 工具 |
|
||||||
|
| 条目头字段单行紧凑(`uuid, name, path, fac, card_lv, lv, type, grow_type, role, hp, ap, def` 一行),触发块换行展开 | 现有阅读习惯 |
|
||||||
|
| 按 uuid 段位插入注释块(`// ===== card_lv=5(5401-5499)=====`) | 段位规则 |
|
||||||
|
| **档位数组 lv 严格升序**(lv_entries / LvTriggerEntry[] / field / revive / ap_bonus / hp_bonus) | `HeroSkillDesc.ts:384` 的 `filter(e=>e.lv<=lv).pop()` |
|
||||||
|
| 数字键无引号、保持插入序 | Record 索引 |
|
||||||
|
| `ccd: 0` 占位字段不丢(HSkillInfo 必填) | Hero.ts 加载 |
|
||||||
|
| 字段顺序稳定(skills → atked/atking → dead → fstart → field → revive → info) | 减少 diff 噪音 |
|
||||||
|
| HeroList 按 card_lv 分组升序 | CardSet 卡池派生顺序 |
|
||||||
|
| `info: ""` 收尾、`path/icon/info` 字符串原样不转义变换 | 文本保真 |
|
||||||
|
| **文件头 BOM 原样保留**(读 utf-8 后首字符检测写回) | 避免整文件 diff |
|
||||||
|
|
||||||
|
### 3.3 Round-trip 门
|
||||||
|
|
||||||
|
每次保存后执行「重新生成 → 与落盘 TS 逐字节比对」,不等则回滚并报错。初始迁移同样以此门作为验收标准。
|
||||||
|
|
||||||
|
## 四、扩展模块与消息协议
|
||||||
|
|
||||||
|
### 4.1 新增文件
|
||||||
|
|
||||||
|
| 文件 | 职责 |
|
||||||
|
|---|---|
|
||||||
|
| `scripts/heroes-cli.ts` | Node 子进程脚本,承载 `--cmd=query-base / export / validate` 三命令;复用 `tsconfig.eval.json`(paths: cc → mock-cc.ts)直接 import SkillSet/BuffList/FieldSkillSet/heroSet |
|
||||||
|
| `source/heroes/generator.ts`(主进程侧) | JSON→TS 序列化器 + round-trip 校验(可被 heroes-cli 复用) |
|
||||||
|
| `source/panels/default/components/HeroConfig.ts` + `static/template/vue/hero-config.html` | 配置 UI 组件 |
|
||||||
|
|
||||||
|
### 4.2 消息协议
|
||||||
|
|
||||||
|
| 消息 | 方向 | 入参 | 出参 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `query-base` | 面板→主进程 | – | 底座快照(SkillSet/BuffList/FieldSkillSet 元数据 + 枚举名表;按文件 mtime 缓存) |
|
||||||
|
| `read-config` | 面板→主进程 | – | `{ file: HeroConfigFile, drift?: boolean }`;JSON 不存在则先跑 `--cmd=export` |
|
||||||
|
| `validate` | 面板→主进程 | HeroConfigFile | 校验报告(error[] / warning[]) |
|
||||||
|
| `save-config` | 面板→主进程 | HeroConfigFile | `{ ok, report }` |
|
||||||
|
| `config-saved` | 主进程→面板广播 | – | 强度评估 tab 重算,形成「改→看」闭环 |
|
||||||
|
|
||||||
|
`package.json` 的 `contributions.messages` 补齐上述映射。
|
||||||
|
|
||||||
|
### 4.3 保存流水线(顺序固定)
|
||||||
|
|
||||||
|
```
|
||||||
|
校验通过 → 备份当前 heroSet.ts → 生成 TS 文本 → ts 语法自检(createSourceFile 取 syntactic diagnostics)
|
||||||
|
→ 写 TS(临时文件 + rename 原子写)→ round-trip 逐字节比对 → 通过才写 JSON → asset-db refresh-asset
|
||||||
|
```
|
||||||
|
|
||||||
|
任一步失败:从备份恢复 TS、JSON 保持未写状态、返回错误报告。
|
||||||
|
|
||||||
|
## 五、校验规则分级
|
||||||
|
|
||||||
|
### 5.1 Error(阻止保存)
|
||||||
|
|
||||||
|
| 规则 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| uuid 段位匹配 | 新增时:5001-5099=card1 / 5101-5199=card2 / 5201-5299=card3 / 5301-5399=card4 / 5401-5499=card5,且不与现有重复(编辑现有英雄 uuid 不可改) |
|
||||||
|
| skills/触发组 s_uuid 存在 | 必须在 SkillSet(否则运行时静默不出手) |
|
||||||
|
| timed_buff_id 存在 | 必须在 BuffList 7001-7024 段 |
|
||||||
|
| field uuid 存在 | 必须在 FieldSkillSet 7001-7020 段(与 BuffList 同号段但互不相通) |
|
||||||
|
| t_num ≥ 1 | 0 会导致 `% 0 = NaN` 永不触发 |
|
||||||
|
| 档位 lv 升序不重复 | 保存时序列化器强制排序,重复档报错 |
|
||||||
|
| 形态硬约束 | tank/warrior→近战组(普攻 6004、大招 6103~6106/6108);assassin/射手→中距组(6001~6003/6006~6008);support/mage→远程组(6009~6019、大招 6101/6102/6107/6109~6111);辅助技能 6301/6302/6412/6501 不限形态 |
|
||||||
|
| 必填缺失 | name / path / type / role |
|
||||||
|
|
||||||
|
### 5.2 Warning(确认后可存)
|
||||||
|
|
||||||
|
| 规则 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| lv > 6 档位 | `HERO_MAX_LV=6` 封顶,lv7/9 档当前永不生效(数据先行,运行时扩展上限后自动生效) |
|
||||||
|
| card_lv 1/2/3 配了 field | 应改走 ap_bonus/hp_bonus(30/40/50% 补偿) |
|
||||||
|
| card_lv 4/5 的 lv9 未配 field | 按设计指引应有驻场光环 |
|
||||||
|
| infos 条数与实际档位不匹配 | 面板逐条展示依赖 |
|
||||||
|
|
||||||
|
## 六、UI 设计
|
||||||
|
|
||||||
|
### 6.1 布局
|
||||||
|
|
||||||
|
同面板(default,1024×600 dockable)顶部 `ui-tab`:「强度评估|英雄配置」。三栏:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌ [强度评估 | 英雄配置●] ────────────────────────── ●=有未保存改动 ┐
|
||||||
|
├────────────┬──────────────────────────────┬─────────┤
|
||||||
|
│ 🔍搜索 │ 锚点导航: 基础|技能|触发|光环|复活|加成|说明 │ 校验抽屉 │
|
||||||
|
│ ▾LV5 │ ①基础: uuid/name/path/card_lv/role/type │ ✕2 ⚠1 │
|
||||||
|
│ ●5401 刀刀│ hp/ap/def 基准+增量双输入(显示合计) │ 点击 │
|
||||||
|
│ ▾LV4 … │ ②技能: [普攻|大招] SkillPicker + 底座只读条 │ 定位 │
|
||||||
|
│ [+新建] │ + OverridesEditor + 档位矩阵 │ [保存] │
|
||||||
|
└────────────┴──────────────────────────────┴─────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 组件清单
|
||||||
|
|
||||||
|
| 组件 | 职责 | 数据源 | 校验 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| HeroListView | card_lv 分组、搜索、dirty 圆点、新建入口 | heroSet.data.json | – |
|
||||||
|
| BaseForm | 基础字段;hp/ap/def 基准+增量双输入 | HERO_ROLE_BASE | uuid 段位/重复;role→type 联动锁定 |
|
||||||
|
| SkillPicker | 自制搜索下拉选 SkillSet,显示 `6101 火球 · 远程 · AOE` | SkillSet | 普攻限 6001~6019 按 IType 过滤;大招按形态过滤;辅助技能放行 |
|
||||||
|
| SkillBasePanel | 底座关键参数只读展示(ap/cd/hit/IType/RType/DTType) | SkillSet | – |
|
||||||
|
| OverridesEditor | 分组编辑 overrides(数值 ap/hit_count/num|概率 crt/frz/stun|击退 bck|buff 注入 timed_buff_id→联动 buff_value/buff_duration|永久 buff_type|召唤 call_hero) | BuffList | timed_buff_id 存在性 |
|
||||||
|
| LvMatrix | lv 档位矩阵(技能 lv_entries / 触发档 / field / revive 复用变体):行=lv1/2/3/5/7/9、列=参数,可整行复制加档;**lv7/9 行黄色边框+⚠「运行时 HERO_MAX_LV=6 暂不生效」** | 当前英雄 | lv 升序不重复;t_num≥1 |
|
||||||
|
| TriggerGroupEditor | s_uuid 卡片嵌套档位行(外层技能组、内层档位),保存时统一升序 | SkillSet | s_uuid 存在性 |
|
||||||
|
| InfosEditor | 9 档分级说明文本 | 当前英雄 | 条数与档位对照提示 |
|
||||||
|
| BonusEditor | ap_bonus/hp_bonus 档位(lv+value) | 当前英雄 | 仅 card_lv1/2/3 提示使用 |
|
||||||
|
| ValidationPanel | 错误/警告列表(区域·字段·消息),点击 scrollIntoView + 字段红框高亮;保存按钮 error>0 时禁用 | 校验器输出 | – |
|
||||||
|
|
||||||
|
### 6.3 关键交互
|
||||||
|
|
||||||
|
- **ui- 组件与 Vue 混用**:`isCustomElement` 已配置;ui- 元素 `v-model` 不生效,须 `:value` + `@change`/`@confirm` 手动双向;属性用 kebab-case
|
||||||
|
- **自制组件**(ui- 缺失):档位矩阵表格、可搜索 SkillPicker、BuffList 分组下拉、校验列表、确认 modal
|
||||||
|
- **新建向导**:单屏 modal——选 card_lv → role →(形态按映射自动锁定为只读徽章)→ 模板预填:uuid 取段位内最小空位、职业基准属性(增量 0)、按指引 2.6 能力组合范式推荐技能(tank→6004+6301、support→6009+6302 等)、lv3/5/7 空档骨架;提供「空白模板」选项
|
||||||
|
- **状态管理**:dirty 深度 watch(加载时存 snapshot 对比),列表项与 tab 标题打点;切换英雄/切 tab 弹确认(放弃/留下);底座加载沿用 spawn 异步 + loading 态
|
||||||
|
- **保存流程**:error>0 → 保存禁用(tooltip 显示错误数);仅 warning → 自制 modal 确认后执行保存流水线
|
||||||
|
|
||||||
|
## 七、失败恢复与安全
|
||||||
|
|
||||||
|
| 项 | 方案 |
|
||||||
|
|---|---|
|
||||||
|
| 备份 | `local/hero_setup/backup/heroSet.<HHmmss>.ts`(local/ 已被 git 忽略),滚动保留 5 份;不用 git stash(不污染用户暂存区) |
|
||||||
|
| 原子写 | 同目录临时文件 + rename;Windows EPERM(编辑器占用)时 200ms 退避重试 3 次 |
|
||||||
|
| 语法自检 | `ts.createSourceFile` 取 syntactic diagnostics(typescript 已在依赖);语义级检查提示用户跑 `npx tsc --noEmit`,不阻塞 |
|
||||||
|
| 回滚 | 自检/round-trip 失败 → 从备份恢复原文件 → 返回错误报告,JSON 保持未写 |
|
||||||
|
| asset-db 刷新 | 写后 `Editor.Message.request('asset-db', 'refresh-asset', 'db://assets/script/game/common/config/heroSet.ts')`;禁止「删文件+建新文件」式写法(触发 meta 重建) |
|
||||||
|
| 并发 | 面板内保存互斥(in-flight promise 复用)+ 串行队列 |
|
||||||
|
|
||||||
|
## 八、初始迁移(一次性)
|
||||||
|
|
||||||
|
1. `--cmd=export`:tsx import 现 heroSet.ts → 导出 `heroSet.data.json`(26 英雄 + 14 怪物全量,怪物标记只读)
|
||||||
|
2. 从 JSON 重新生成 TS → **round-trip 逐字节比对必须通过**(迁移门)
|
||||||
|
3. 迁移门失败的处理:修序列化器直至通过(一次性成本);确实无法保真的字段(如怪物特有表达式)再评估局部文本透传回退
|
||||||
|
4. 迁移完成后 heroSet.ts 数据段即为生成产物,此后手改走「以 TS 反向导入」通道
|
||||||
|
|
||||||
|
## 九、实施阶段
|
||||||
|
|
||||||
|
| 阶段 | 内容 | 验收 |
|
||||||
|
|---|---|---|
|
||||||
|
| 1. 脚本核心 | heroes-cli.ts + JSON schema + 导入器 + 序列化生成器 + round-trip 门(纯 Node 可单测) | 迁移门逐字节通过 |
|
||||||
|
| 2. 主进程 | methods + 消息协议 + 备份/原子写/自检/刷新 | 手工消息调用保存成功、编辑器感知刷新 |
|
||||||
|
| 3. 面板骨架 | tab + 英雄列表 + 基础表单 + SkillPicker/OverridesEditor | 可加载、可编辑基础字段 |
|
||||||
|
| 4. 完整表单 | 触发组/光环/复活/infos/bonus + 校验抽屉 + 新建向导 | 校验规则全覆盖、按设计指引录入新英雄走通 |
|
||||||
|
| 5. 联调冒烟 | eval-heroes 验证加载链、形态约束用例、按指引落地 1 个 P0 英雄(紫电魔女 5301) | 强度评估 tab 正常评分 |
|
||||||
|
|
||||||
|
## 十、遗留事项
|
||||||
|
|
||||||
|
- heroSet.ts:297 注释「怪物5200段」与实际 6001/6101 段不符(幽灵注释),迁移时顺带修正
|
||||||
|
- UI 支持 lv7/9 档而 `HERO_MAX_LV=6`:HeroSkillDesc.ts:321-331 会向玩家展示永远无法解锁的 Lv7/Lv9 文案——超 6 档仅预录入,运行时/文案侧需按 HERO_MAX_LV 裁剪(独立任务,不在本功能范围)
|
||||||
|
- 未来扩展 `HERO_MAX_LV` 至 9 时,需同步升级碎片表 `HERO_UPGRADE_NEED_FRAGMENTS`(GameSet.ts:70)
|
||||||
11
assets/script/game/common/config/英雄配置UI设计方案.md.meta
Normal file
11
assets/script/game/common/config/英雄配置UI设计方案.md.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"importer": "text",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "52cc7e16-38f3-4e62-8e90-fc34a9b4a622",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user