Files
pixelheros/put/server/data/heroes.json编辑指引.md
panFD 93dc59a616 refactor(skill): 重构大招CD配置体系,统一档位管理
1. 新增大招CD档位配置ULT_CDS/ULT_CD_MAP,与普攻档位分离
2. 为职业默认值添加大招CD档配置,支持按职业类型适配
3. 改造技能编辑器与英雄向导,支持选择大招CD档位
4. 批量更新现有英雄数据与配置文件,统一使用档位化CD配置
5. 补充文档说明,规范大招CD配置规则
2026-09-14 23:00:06 +08:00

182 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# heroes.json 手动修改指引(智能体用)
> 本文件是 `put/server/data/heroes.json`(英雄编辑器数据库)的手动修改规范。
> 适用场景:不启动编辑器 UI,直接修改 JSON 新增/调整英雄。
> 规则与说明 only —— 所有底座数值请以「数据源」所列真实配置文件为准,禁止凭记忆填写。
## 0. 数据源(修改前必读,唯一事实源)
| 要什么 | 读哪里 |
|---|---|
| 技能底座(普攻/大招/辅助,含 kind/TGroup/默认数值) | `assets/script/game/common/config/SkillSet.ts` → `SkillSet` |
| 驻场光环底座(类型/图标/元数据) | 同文件 → `FieldSkillSet` |
| 计时 buff(timed_buff_id 可用值与效果) | `assets/script/game/common/config/BuffSet.ts` → `BuffList` |
| 职业属性模板 / 成长系数 | `assets/script/game/common/config/heroSet.ts` → `HERO_ROLE_BASE` / `HERO_GROW_COEF`(lv12 专项已移除,单项强化由 `bonus` 配置接管) |
| 攻速档位表达式 | 同文件 → `AtkSpeedSet` / `AtkSpeedLv` |
| 现有英雄写法样例 | 本 JSON 内 5001~5010 条目 |
| 编辑器枚举键(职业/成长/类型/底座映射) | `put/web/src/constants.js`(`HERO_ROLES` / `GROW_TYPES` / `H_TYPES` / `ROLE_ATK_SKILL` / `ROLE_ULT_SKILL` / `SUPPORT_ULT` / `OVERRIDE_KEYS`) |
服务端运行时可 `GET /api/meta` 获取底座快照(需先启动 server);修改 SkillSet 等 TS 后需 `POST /api/refresh` 或重启。
## 1. 文件角色与数据流
- 本文件是**编辑器数据库**:编辑器"保存"即全量覆盖写本文件;手动改本文件与编辑器保存等价。
- `POST /api/apply` 把本文件**全部条目**渲染成 TS,整体替换 `heroSet.ts` 中
`// @hero-setup:heroes-begin` ~ `// @hero-setup:heroes-end` 之间的英雄区。
- 推论:
- 不要手改 heroSet.ts 英雄区 —— 下次 apply 会被覆盖;
- 新增一条英雄 = 在本 JSON 数组追加一个对象,然后 apply;
- 标记区之外的 `HeroList`、`HeroComboSet`、怪物配置不受 apply 影响。
## 2. 英雄对象字段规范
| 字段 | 类型 | 规则 |
|---|---|---|
| `uuid` | number | 英雄 5000 段,全局唯一。当前已用 5001~5010,新增从 **5011** 起(修改前 grep 全库确认未占用) |
| `name` / `comment` | string | 显示名 / 设计说明(comment 可空,建议填写机制主题) |
| `path` | string | 美术资源名,必须存在 `assets/resources/game/heros/{path}.prefab`(修改前用文件系统确认) |
| `rarity` | 1~5 | 仅缩放 lv1 基础属性 ×(1+0.05×(rarity−1));卡池费用 5/10/15、抽卡权重 40/25/15/8/3 自动派生 |
| `roleKey` | string | 职业:`Tank`/`Warrior`/`Assassin`/`Archer`/`Mage`/`Support` |
| `growKey` | string | 成长曲线:`Tank`/`Warrior`/`Assassin`/`Mage`/`Support`/`Archer`,通常与 roleKey 同职业 |
| `typeKey` | string | 攻击定位:`Melee`/`Mid`/`Long`(决定默认攻击距离 100/300/450) |
| `statBase` | {hp,ap,def} | 相对 `HERO_ROLE_BASE[roleKey]` 的**偏移量**(可为负,如 5007 hp=−5);惯例量级 ±5/10/20/30 |
| `dis` / `speed` | number\|null | 英雄一般 null(走默认);显式配置才填 |
| `skills` | array | **恰好 2 个**:`[普攻, 大招]`,结构见 §3 |
| `atking`/`atked`/`fstart`/`fend`/`dead` | object | 触发组,结构见 §4 |
| `field` | array | 驻场光环档位,结构见 §5 |
| `bonus` | array | 额外属性加成 `[{lv,attrs:{...},name?,icon?,info?}]`,运行时累加所有 lv ≤ 英雄等级 的档位;`hp`/`ap`/`def` 为百分比(基数取"基础×品质+成长"快照,多档加法叠加),`crt`/`frz`/`stun`/`para` 为固定百分点;配了 `icon` 的档位在图鉴技能列表最末出图标(点击弹窗展示 name/效果,描述缺省按 attrs 自动生成,`info` 可自定义模板支持 `{lv}` 占位);常规英雄留空 |
| `info` | string | 描述文案,可空 |
| `revive` | — | **已废弃**:复活改在 `dead` 组 overrides 里配 `revive_hp`/`revive_count`,不要写独立字段 |
## 3. skills 规范
每个技能对象:`{uuid, name, cd, cdExpr, overrides, desc, lv_entries}`。
**普攻 skills[0]**
- `uuid` 必须 ∈ `ROLE_ATK_SKILL[roleKey]`;
- `cdExpr` = `"AtkSpeedSet[AtkSpeedLv.<SpeedKey>].cd"`(SpeedKey ∈ VeryFast/Fast/Normal/Slow/VerySlow),`cd` 填对应数值(0.75/0.90/1.05/1.20/1.50);
- `lv_entries` 惯例只有一档:`{lv:2, s_lv:2, overrides, desc}`。
**大招 skills[1]**
- `uuid` ∈ `ROLE_ULT_SKILL[roleKey]`;辅助类底座(`SUPPORT_ULT` 列表)任意职业可作大招;
- `cdExpr` = `"UltCdSet[UltCdLv.<Tier>].cd"`(Tier ∈ VeryFast/Fast/Normal/Slow/VerySlow),`cd` 填对应数值(6/7/8/9/10);按技能效果类型选档:单体爆发=VeryFast、群体伤害/控制=Normal、全体增益/治疗/护盾=VerySlow,Fast/Slow 为中间细分档;
- `lv_entries` 两档:`{lv:8, s_lv:2, ...}`、`{lv:16, s_lv:3, ...}`。
**通用**
- `name` 留空则回退 SkillSet 底座名;建议普攻/大招起特色名;
- `desc` 为描述模板,占位符 `{target}` `{ap}` `{dur}` `{技能字段名}` 由 HeroSkillText 渲染实时数值;空字符串等价省略;
- 档位 `overrides` 与基础 `overrides` **浅合并**(档位优先),档位只写变化键。
## 4. 触发组规范(atking / atked / fstart / fend / dead)
- 结构:`{ "<技能uuid字符串>": [条目, ...] }`,一个组可挂多个技能 uuid;
- 条目:`{lv, s_lv, name, t_num, overrides, desc}`;
- 解锁等级惯例 **lv4**(`lv:4, s_lv:1`;heroSet.ts 头部注释写的 lv6 已过时,现有英雄与编辑器默认值均为 lv4);
- `t_num`:每 n 次普攻(atking)/受击(atked)触发一次;fstart/fend 为每回合开始/结束固定触发 1 次,`t_num` 恒填 1;
- `name` 为组对外展示名(写在该组首档),留空回退底座名;
- 复活:在 `dead` 某条目 `overrides` 配 `revive_hp`(回血%)+ `revive_count`(次数上限);
- 无触发组时写空对象 `{}`,**不要省略字段**。
## 5. field 光环规范
- 结构:`[{lv:4, uuids:[{uuid, value, name}], desc?}]`;
- `uuid` 必须 ∈ `FieldSkillSet`(7001~7022 段);`value` 为实际生效数值(按光环类型:比例类为小数如 0.15,次数/固定值类为整数);
- `name` 可空(回退底座名);`desc` 可空(回退自动生成);
- 解锁等级惯例 lv4;无光环写空数组 `[]`。
## 6. overrides 白名单与特殊存储格式
可用键(对照 `SkillSet.ts` 的 `SkillOverrides` 接口;编辑器 UI 白名单 `OVERRIDE_KEYS` 是其子集,手动改 JSON 可用全集):
`ap, hit_count, hitcd, crt, frz, stun, para, bck, bck_chance, TGroup, buff_type, timed_buff_id, buff_value, buff_duration, buff_chance, buff_target, timed_debuff_id, debuff_value, debuff_duration, debuff_chance, call_hero, summon_count, is_accel, num, revive_hp, revive_count, proc_skill, icon`
特殊存储格式(导出时由 server 还原为 TS 枚举表达式):
- `TGroup`:JSON 存字符串(如 `"Team"`),导出还原 `TGroup.Team`;`null` 表示不覆写;
- `buff_target`:存数字 0~3(Hit/Self/Ally/Enemy),导出还原 `BuffTarget.X`;
- `proc_skill`:对象 `{s_uuid, chance?, overrides?}`(施法后概率触发另一技能,出手即判定,与命中/弹道数无关);
- `icon`:字符串图标帧名(uicons 图集),非数值;
- 其余一律直存数值。
引用校验:`timed_buff_id` / `timed_debuff_id` 必须 ∈ `BuffList`;`proc_skill.s_uuid` / 触发组 key / 召唤类引用必须 ∈ `SkillSet`。
### 6.1 timed_buff_id / timed_debuff_id(计时 buff / debuff 注入)
**语义划分(新规则)**:
- `timed_buff_id`:**增益语义**。释放/命中时给友方或自身挂 buff;伤害技能缺省挂**施法者自身**(如吸血、攻击后强化),辅助技能缺省挂**友方目标**。可用 `buff_target` 覆写目标。
- `timed_debuff_id`:**减益语义**。命中敌人后给**被命中者**挂 debuff(目标固定,不可覆写);仅伤害路径(HeroAtkSystem)结算,DoT 不触发。
**编辑器 UI**:overrides 添加 `timed_buff_id 计时buff` 或 `timed_debuff_id 计时debuff` 行后,值栏为 BuffList 下拉(`id 名称` + 右侧 buff 效果摘要,数据来自 `/api/meta` 的 `BuffList`);meta 未加载时可手输数字 id(allow-create,保存时自动归一化为数字)。选定 id 后编辑器自动补齐配套三行(buff 补 `buff_value`/`buff_chance`/`buff_duration`,debuff 补 `debuff_value`/`debuff_chance`/`debuff_duration`,已存在不重复),数值预填 BuffList 默认值。
**配套键**(同一 overrides 内按需添加):
| 键 | 说明 | 缺省 |
|---|---|---|
| `buff_value` | 覆写 buff 修饰数值(modifiers.value / tick.damage_or_heal,单位同 BuffList) | 回退 BuffList 默认 |
| `buff_duration` | 覆写 buff 持续时间(秒) | 回退 BuffList.duration |
| `buff_chance` | buff 触发概率 %(命中时掷骰) | 100(必触发) |
| `buff_target` | buff 施加目标:0 被命中者(Hit) / 1 施法者(Self) / 2 全体友方(Ally) / 3 全体敌方(Enemy) | 按主效果推导:伤害→施法者自身,辅助→友方目标 |
| `debuff_value` | 覆写 debuff 修饰数值 | 回退 BuffList 默认 |
| `debuff_duration` | 覆写 debuff 持续时间(秒) | 回退 BuffList.duration |
| `debuff_chance` | debuff 触发概率 %(命中时掷骰) | 100(必触发) |
**生效路径(重要)**:
- ✅ 友方/辅助技能(TGroup 为 Self/Team/Ally,或 6300/6500 段辅助底座):走 SCastSystem merged config,`timed_buff_id` 注入完整生效;`buff_target: 3`(Enemy)可把 buff 分流挂到敌方网格(如群体减甲);
- ✅ 对敌伤害技能的命中附带 debuff:用 `timed_debuff_id`(可写在 SkillSet 底座或 heroSet overrides),HeroAtkSystem 命中结算时挂被命中者;
- ✅ 对敌伤害技能的命中附带增益(吸血/自强化):用 `timed_buff_id`,缺省挂施法者自身;
- 同一 overrides 不要既配 `timed_buff_id` 又依赖永久 `buff_type` 加成:timed 路径生效后永久分支被跳过。
**语义陷阱**:`timed_buff_id` 在伤害技能上缺省挂**施法者自身**——若想"命中给敌人挂减益",必须用 `timed_debuff_id`,否则会把减益挂到自己身上。
### 6.2 proc_skill(施法后概率触发主动技能)
**定位**:施法出手后概率触发一个**主动技能**(大招/触发技底座,如 6100+/6200+ 段伤害技能),以施法者身份完整释放(含伤害/弹道/特效)。它是技能触发器,不是挂 buff 的方式——debuff 注入请用 `timed_buff_id`(见 §6.1)。
**编辑器 UI**:overrides 添加 `proc_skill 施法后概率触发技能` 行后展开结构化编辑:
1. `被触发技能 uuid`:下拉列出全部 SkillSet(`uuid 名称`);
2. `概率%`:0~100 数字输入,默认 100;
3. `被触发技能覆写`:内嵌 OverrideEditor(同套白名单),可递归覆写被触发技能的 `ap`/`TGroup`/`hit_count` 等。
选中被触发技能后自动在其内嵌 overrides 补 `TGroup` 行(取底座值,已存在不覆盖),便于直改释放对象并联动对敌断链警示。
选中 `s_uuid` 前该行不输出(防止半成品配置导出),编辑中状态会被保留。
**JSON 格式**:
```json
"proc_skill": { "s_uuid": 6201, "chance": 20, "overrides": { "ap": 150 } }
```
**运行时行为**:
- 触发链路:施法出手 → 掷 `chance` 骰(≥100 直接成功不掷骰;无 70% 封顶)→ 以施法者身份走 `forceCastTriggerSkill`(无视 CD、无施法前摇,触发类型记为 atking);
- 出手即判定:**一次施法只判定一次**,与命中次数、弹道数、召唤数均无关(多弹道技能不会按实体数重复判定);
- 不再依赖命中:即使技能落空/无目标可命中,只要施法动作出手就会判定;
- `overrides` 与被触发技能自身 heroSet overrides 叠加,本次传入优先;
- 被触发的技能不再累加普攻计数(防递归);
- 内嵌 `TGroup` 可改变被触发技能的释放对象(如触发一个友方增益)。
**选型指引**(对敌附带效果):
- 挂 debuff(冰冻/中毒/易伤等)→ `timed_buff_id`:写入 SkillSet 底座,或用友方技能 + `buff_target: 3` 分流挂敌;
- 施法后追发一个主动技能(陨石/火球等完整释放)→ `proc_skill`。
## 7. 新增英雄操作清单
1. 读 §0 数据源:选定技能/光环/buff 底座,确认 `HERO_ROLE_BASE` 模板值与攻速档位;
2. 选 uuid(≥5011 且全库唯一)、选 `path`(确认 prefab 存在);
3. 在本 JSON `heroes` 数组**末尾**追加完整英雄对象(所有字段齐全,空组写 `{}`/`[]`);
4. JSON 语法校验(如 `node -e "JSON.parse(require('fs').readFileSync('put/server/data/heroes.json','utf8'))"`);
5. 启动服务 `npm run dev`(put 目录),`POST /api/apply` 写入 heroSet.ts;
6. **手动把新 uuid 追加进 `heroSet.ts` 的 `HeroList`**(标记区之外,apply 不会代做 —— 最易漏的一步,漏了英雄不进卡池、游戏不加载);
7. 验证:编辑器 UI 重开确认渲染正常;游戏内抽卡/面板检查;必要时用 `calcHeroPowerNormalized`(基准 5001=100 分)评估强度。
## 8. 常见错误
- 手改 heroSet.ts 英雄区 → 被下次 apply 覆盖;
- 漏加 `HeroList` → 英雄存在但不可获得;
- 引用不存在的技能/光环/buff uuid 或 `path` → 编译或运行期才爆;
- 写独立 `revive` 字段 → 已废弃,复活走 dead 组;
- 触发技/光环解锁写 lv6、大招档位写 lv9 → 现行惯例 lv4 / lv8+lv16;
- 普攻/大招用数值 cd 而不给 `cdExpr` → 丢失档位语义(编辑器档位下拉失效,导出 heroSet.ts 变裸数字);
- 大招误用 `AtkSpeedSet` 作 `cdExpr` → 普攻档(0.75~1.5s)与大招档(6~10s)是两套体系,大招必须走 `UltCdSet`;
- 档位 overrides 全量复制基础档 → 浅合并下冗余且后续改基础值不生效;
- desc 与 overrides 数值脱节 → desc 模板只写 `{ap}` 等占位符,不要硬编码数字;
- 对敌技能 debuff 误用 `timed_buff_id` → buff 缺省挂施法者自身,会把减益挂到自己身上;应改用 `timed_debuff_id`(详见 §6.1);
- 想做吸血但把 buff 写到 `timed_debuff_id` → debuff 目标固定为被命中者,会奶敌人;吸血/自强化请用 `timed_buff_id`(缺省即挂自身)。