# 技能基座重构 — 迁移计划 基于 spec: `docs/superpowers/specs/2026-05-22-skill-template-refactor-design.md` ## 迁移原则 - 每个步骤是**最小功能单元**,完成后可独立验证 - 使用**兼容层**过渡:新旧接口并存期间,代码同时读取两个位置 - 验证方式:每步完成后运行游戏,确认技能系统行为不变 --- ## Phase 1:类型定义(零风险,不改行为) ### Step 1.1:新增 SkillTemplate/SkillDefaults/HeroOverrides 接口 **文件**:`SkillSet.ts` **改动**: - 在现有 `SkillConfig` 下方新增 `SkillTemplate`、`SkillDefaults`、`HeroOverrides` 接口定义 - 新增 `TriggerSkillConf` 接口 - 更新 `BuffConf`:新增 `attr` 字段,保留旧 `buff` 字段(标注 `@deprecated`) - 不删除任何旧代码 **验证**:编译通过,游戏行为不变(新接口尚未被使用) ### Step 1.2:新增 resolveSkillParams 工具函数 **文件**:`SkillSet.ts` 或新建 `SkillResolve.ts` **改动**: ```typescript export function resolveSkillParams( template: SkillTemplate, heroSkill?: HSkillInfo, triggerConf?: TriggerSkillConf ): { kind: SkillKind } & SkillDefaults { return { kind: template.kind, ...template.defaults, ...heroSkill?.overrides, ...triggerConf?.overrides, }; } ``` **验证**:编译通过,写一个简单的测试用例验证三级覆盖逻辑 --- ## Phase 2:兼容层(数据迁移的安全网) ### Step 2.1:新增兼容读取函数 **文件**:`SkillSet.ts` **改动**:新增辅助函数,从旧 `SkillConfig` 构造 `SkillTemplate` + `SkillDefaults`: ```typescript /** 从旧 SkillConfig 提取 defaults 字段(过渡期使用) */ export function legacyDefaults(config: SkillConfig): SkillDefaults { return { TGroup: config.TGroup, ap: config.ap, t_num: 1, // 旧配置无此字段,使用默认值 hit_count: config.hit_count, hitcd: config.hitcd, crt: config.crt, frz: config.frz, bck: config.bck, buffs: config.buffs, }; } /** 从旧 SkillConfig 提取 template 字段 */ export function legacyTemplate(config: SkillConfig): SkillTemplate { return { uuid: config.uuid, name: config.name, sp_name: config.sp_name, icon: config.icon, kind: config.kind ?? SkillKind.Damage, act: config.act, readyAnm: config.readyAnm, endAnm: config.endAnm, EAnm: config.EAnm, DAnm: config.DAnm, ready: config.ready, IType: config.IType, RType: config.RType, EType: config.EType, speed: config.speed, DTType: config.DTType, with: config.with, bezier_start_y: config.bezier_start_y, bezier_mid_y: config.bezier_mid_y, bezier_arc: config.bezier_arc, time: config.time, defaults: legacyDefaults(config), info: config.info, }; } ``` **验证**:编译通过,可写测试验证提取结果与原配置一致 --- ## Phase 3:数据迁移(逐个技能类型) ### Step 3.1:迁移 buff 技能数据(6401-6406, 6501) **文件**:`SkillSet.ts` **改动**:将 6401-6406、6501 从 `SkillConfig` 格式改为 `SkillTemplate` 格式: - 顶层数值字段 → `defaults` - 显式添加 `kind: SkillKind.Support` - `buffs` 中的 `buff:` → `attr:` **存储方式**:新增 `BuffSkillTemplates: Record`,旧数据保留在 `SkillSet` 中 **验证**:游戏运行,确认卡牌释放 buff 技能效果不变 ### Step 3.2:迁移辅助技能数据(6301-6305) **文件**:`SkillSet.ts` **改动**:将护盾/治疗技能从旧格式改为 `SkillTemplate` 格式 - 护盾类:`kind: SkillKind.Shield` - 治疗类:`kind: SkillKind.Heal` **存储方式**:新增 `SupportSkillTemplates: Record`,旧数据保留 **验证**:游戏运行,确认护盾和治疗技能效果不变 ### Step 3.3:迁移必杀技数据(6104-6107) **文件**:`SkillSet.ts` **改动**:将必杀技从旧格式改为 `SkillTemplate` 格式 - 全部 `kind: SkillKind.Damage` - `crt`/`frz` 移入 defaults **验证**:游戏运行,确认必杀技伤害和特效不变 ### Step 3.4:迁移基础攻击技能数据(6001-6103) **文件**:`SkillSet.ts` **改动**:将所有攻击技能从旧格式改为 `SkillTemplate` 格式 - 全部 `kind: SkillKind.Damage` **验证**:游戏运行,确认所有英雄和怪物的普攻、远程攻击正常 ### Step 3.5:合并为新表 **文件**:`SkillSet.ts` **改动**:将分散的 `BuffSkillTemplates`、`SupportSkillTemplates` 等合并为一个: ```typescript export const SkillTemplates: Record = { ... 所有已迁移的技能 ... } ``` **验证**:通过所有新模板创建技能,确认与旧 `SkillSet` 行为一致 --- ## Phase 4:消费者适配(逐文件) ### Step 4.1:适配 Skill.ts(技能实体创建) **文件**:`assets/script/game/skill/Skill.ts` **改动**: - `skill.load()` 参数从 `config: SkillConfig` 改为 `template: SkillTemplate` - 内部读取 `template.sp_name`(表现字段,未变) - 传递给 SMoveSystem/STimeComp 的 config 改为 template - `ap`/`crt`/`frz`/`hit_count` 从 `template.defaults` 读取(通过兼容函数) **关键行**: - ~112: `config.sp_name` → `template.sp_name` - ~153: `config.EType` → `template.EType` - ~181: `config.RType` → `template.RType` - ~183-185: `config.bezier_*` → `template.bezier_*` - ~195: `config.time` → `template.time` - ~196: `config.hitcd` → `template.hitcd` - ~211-214: `config.crt`/`config.frz`/`config.ap`/`config.hit_count` → `template.defaults.*` **验证**:释放各种技能,确认弹道动画和伤害数值正确 ### Step 4.2:适配 SMoveSystem.ts(技能移动) **文件**:`assets/script/game/skill/SMoveSystem.ts` **改动**: - 类型引用 `SkillConfig` → `SkillTemplate` - 读取的字段(speed、RType、EType、bezier_*)均在模板顶层,无需改逻辑 **验证**:确认弹道轨迹(直线/贝塞尔/固定)正常 ### Step 4.3:适配 STimeComp.ts(技能时间控制) **文件**:`assets/script/game/skill/STimeComp.ts` **改动**: - 类型引用 `SkillConfig` → `SkillTemplate` - 只读 `EType`(模板顶层字段),逻辑不变 **验证**:确认技能持续时间、碰撞消失逻辑正常 ### Step 4.4:适配 SkillView.ts(技能视图) **文件**:`assets/script/game/skill/SkillView.ts` **改动**: - 类型引用 `SkillConfig` → `SkillTemplate` - 只读 `EType`(模板顶层字段),逻辑不变 **验证**:确认技能特效显示正常 ### Step 4.5:适配 HeroViewComp.ts(命中动画) **文件**:`assets/script/game/hero/HeroViewComp.ts` **改动**: - ~507: `SConf?.DAnm` → `template?.DAnm`(字段仍在顶层,只改引用名) **验证**:确认受击动画(普通/冰/火/风)显示正确 ### Step 4.6:适配 SCastSystem.ts(施法系统 — 核心) **文件**:`assets/script/game/hero/SCastSystem.ts` **改动**: - 引入 `resolveSkillParams()` 和 `legacyTemplate()` - `forceCastSkill()` 中 `SkillSet[s_uuid]` → `SkillTemplates[s_uuid]`,通过 `resolveSkillParams(template, undefined, undefined)` 获取参数 - `applyFriendlySkillEffects()` 改为接收 resolved params - `applyActualFriendlyEffect()` 中: - `config.buffs` → `resolved.buffs` - `buffConf.buff` → `buffConf.attr`(同时兼容旧 `buff` 字段) - 伤害技能路径中 `config.ap`/`config.crt`/`config.frz`/`config.hit_count` → 从 resolved params 读取 - `config.TGroup` → `resolved.TGroup` - `config.kind` → `template.kind`(模板固定) **验证**: 1. 英雄普攻伤害正确 2. 必杀技伤害和特效正确 3. 护盾/治疗/buff 效果正确 4. 卡牌技能效果正确 ### Step 4.7:适配 HeroAtkSystem.ts(伤害系统) **文件**:`assets/script/game/hero/HeroAtkSystem.ts` **改动**: - ~292: `sConf.ap` → 从 resolved defaults 读取 - ~221: `reviveSkillConf.ap` → 从 resolved defaults 读取 - ~236: `reviveSkillConf.readyAnm` → 从 template 读取(模板顶层字段) **验证**: 1. 英雄伤害数值正确 2. 复活技能恢复血量正确 ### Step 4.8:适配 SkillTriggerHelper.ts(触发技能) **文件**:`assets/script/game/hero/SkillTriggerHelper.ts` **改动**: - 触发技能时,将 `triggerConf.overrides` 传递给 `resolveSkillParams()` **验证**:确认受击触发护盾、普攻触发治疗等触发技能正常 ### Step 4.9:适配 Hero.ts + Mon.ts(初始化) **文件**:`Hero.ts`、`Mon.ts` **改动**: - 英雄/怪物初始化时,将 `heroInfo.atking`/`atked` 等配置传入 HeroAttrsComp - HeroAttrsComp 中的类型同步更新为 `TriggerSkillConf[]` **验证**:英雄和怪物的触发技能正常工作 ### Step 4.10:适配显示层文件 **文件**:`CardComp.ts`、`IBoxComp.ts`、`TooltipCom.ts`、`SIconComp.ts`、`SkillBoxComp.ts`、`HlistComp.ts` **改动**: - 仅引用名变更(`SkillConfig` → `SkillTemplate`) - 读取的字段(name、icon、IType、info)均在模板顶层,无需改逻辑 **验证**:卡牌显示、信息面板、技能图标显示正常 --- ## Phase 5:角色定制(新功能启用) ### Step 5.1:更新 heroSet.ts 触发配置类型 **文件**:`heroSet.ts` **改动**: - `atking`/`atked` 等类型从 `{s_uuid, t_num}` 内联 → `TriggerSkillConf[]` - 向后兼容:`overrides` 可选,旧配置无需修改 **验证**:编译通过,游戏行为不变(尚未添加 overrides) ### Step 5.2:为首个角色添加 overrides **文件**:`heroSet.ts` **改动**:选一个典型角色(如盾骑士 5002)作为试点,为其触发技能添加 overrides: ```typescript 5002: { ..., atked: [{ s_uuid: 6301, t_num: 2, overrides: { TGroup: TGroup.Team, ap: 2, t_num: 5, hit_count: 3 } }], }, ``` **验证**:盾骑士受击后给全队加盾,而非只给自己加。对比修改前后行为确认覆盖生效 ### Step 5.3:逐步为其他角色添加 overrides **文件**:`heroSet.ts` **改动**:逐个角色添加 overrides,每添加一个验证一次 **验证**:每个角色的技能行为符合设计意图 --- ## Phase 6:清理 ### Step 6.1:删除旧 SkillConfig 接口和 SkillSet 数据 **文件**:`SkillSet.ts` **改动**: - 删除 `SkillConfig` 接口 - 删除旧 `SkillSet` 数据(已被 `SkillTemplates` 替代) - 删除 `legacyTemplate()`/`legacyDefaults()` 兼容函数 - `SkillTemplates` 重命名回 `SkillSet`(或保持新名,全局替换引用) **验证**:全面回归测试 ### Step 6.2:BuffConf 清理 **文件**:`SkillSet.ts`、`SCastSystem.ts` **改动**: - 删除 `BuffConf.buff` 字段,只保留 `attr` - 所有配置数据中 `buff:` → `attr:` **验证**:buff 技能效果正确 ### Step 6.3:删除 kind 回退逻辑 **文件**:`SCastSystem.ts` **改动**: - 移除 `config.kind ?? SkillKind.Damage` 和 `config.kind ?? SkillKind.Support` 回退 - 全部使用 `template.kind` **验证**:所有技能类型判定正确 --- ## 验证检查清单 每个 Step 完成后,运行以下检查: | 检查项 | 方法 | |--------|------| | 编译通过 | 无 TypeScript 错误 | | 普攻正常 | 放置近战/远程英雄,观察普攻弹道和伤害 | | 必杀技正常 | 触发必杀技,确认特效和伤害 | | 护盾正常 | 触发护盾技能,确认护盾层数和显示 | | 治疗正常 | 触发治疗技能,确认血量恢复 | | Buff 正常 | 触发 buff 技能,确认属性变化 | | 卡牌技能正常 | 使用卡牌释放各种技能 | | 触发技能正常 | 受击/攻击/死亡/开始触发链正常 | | 怪物行为正常 | 怪物攻击和技能释放正常 | | 无控制台报错 | 检查浏览器控制台无 JS 错误 |