185 lines
15 KiB
Markdown
185 lines
15 KiB
Markdown
# 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, t_chance?, pity_add?, overrides, desc}`;
|
||
- 解锁等级惯例 **lv4**(`lv:4, s_lv:1`;heroSet.ts 头部注释写的 lv6 已过时,现有英雄与编辑器默认值均为 lv4);
|
||
- `t_num`:每 n 次普攻(atking)/受击(atked)触发一次;fstart/fend 为每回合开始/结束固定触发 1 次,`t_num` 恒填 1;
|
||
- `t_chance`:触发概率(百分点 0~100,**仅 atking/atked 生效**,其余组忽略);缺省/100 = 必触发。示例 30 表示次数条件达成后掷骰 30%;
|
||
- `pity_add`:保底叠加(百分点,仅 atking/atked 生效);未触发时为该技能累积下次概率增量,触发成功后清零、封顶 100。示例 `t_chance:30, pity_add:20` → 30/50/70/90/100 递进;
|
||
- 触发组 `desc` 模板可额外使用 `{t_chance}`(触发概率,缺省渲染 100)与 `{pity_add}`(保底叠加,缺省渲染 0)占位符;模板显式使用 `{t_chance}` 时触发语境不再自动追加"(N%概率)"后缀,避免重复;
|
||
- `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`(缺省即挂自身)。
|