Files
pixelheros/docs/superpowers/specs/2026-05-22-skill-migration-plan.md
walkpan eae62f245a docs: add skill template refactor design and migration plan docs
新增技能基座重构的设计文档和完整迁移计划文档,包含新的接口定义、配置结构、运行时参数解析逻辑以及分步迁移验证方案,为后续技能系统重构提供完整的设计指导。
2026-05-22 10:22:33 +08:00

12 KiB
Raw Blame History

技能基座重构 — 迁移计划

基于 spec: docs/superpowers/specs/2026-05-22-skill-template-refactor-design.md

迁移原则

  • 每个步骤是最小功能单元,完成后可独立验证
  • 使用兼容层过渡:新旧接口并存期间,代码同时读取两个位置
  • 验证方式:每步完成后运行游戏,确认技能系统行为不变

Phase 1类型定义零风险不改行为

Step 1.1:新增 SkillTemplate/SkillDefaults/HeroOverrides 接口

文件SkillSet.ts

改动

  • 在现有 SkillConfig 下方新增 SkillTemplateSkillDefaultsHeroOverrides 接口定义
  • 新增 TriggerSkillConf 接口
  • 更新 BuffConf:新增 attr 字段,保留旧 buff 字段(标注 @deprecated
  • 不删除任何旧代码

验证:编译通过,游戏行为不变(新接口尚未被使用)

Step 1.2:新增 resolveSkillParams 工具函数

文件SkillSet.ts 或新建 SkillResolve.ts

改动

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

/** 从旧 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<number, SkillTemplate>,旧数据保留在 SkillSet

验证:游戏运行,确认卡牌释放 buff 技能效果不变

Step 3.2迁移辅助技能数据6301-6305

文件SkillSet.ts

改动:将护盾/治疗技能从旧格式改为 SkillTemplate 格式

  • 护盾类:kind: SkillKind.Shield
  • 治疗类:kind: SkillKind.Heal

存储方式:新增 SupportSkillTemplates: Record<number, SkillTemplate>,旧数据保留

验证:游戏运行,确认护盾和治疗技能效果不变

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

改动:将分散的 BuffSkillTemplatesSupportSkillTemplates 等合并为一个:

export const SkillTemplates: Record<number, SkillTemplate> = { ... 所有已迁移的技能 ... }

验证:通过所有新模板创建技能,确认与旧 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_counttemplate.defaults 读取(通过兼容函数)

关键行

  • ~112: config.sp_nametemplate.sp_name
  • ~153: config.ETypetemplate.EType
  • ~181: config.RTypetemplate.RType
  • ~183-185: config.bezier_*template.bezier_*
  • ~195: config.timetemplate.time
  • ~196: config.hitcdtemplate.hitcd
  • ~211-214: config.crt/config.frz/config.ap/config.hit_counttemplate.defaults.*

验证:释放各种技能,确认弹道动画和伤害数值正确

Step 4.2:适配 SMoveSystem.ts技能移动

文件assets/script/game/skill/SMoveSystem.ts

改动

  • 类型引用 SkillConfigSkillTemplate
  • 读取的字段speed、RType、EType、bezier_*)均在模板顶层,无需改逻辑

验证:确认弹道轨迹(直线/贝塞尔/固定)正常

Step 4.3:适配 STimeComp.ts技能时间控制

文件assets/script/game/skill/STimeComp.ts

改动

  • 类型引用 SkillConfigSkillTemplate
  • 只读 EType(模板顶层字段),逻辑不变

验证:确认技能持续时间、碰撞消失逻辑正常

Step 4.4:适配 SkillView.ts技能视图

文件assets/script/game/skill/SkillView.ts

改动

  • 类型引用 SkillConfigSkillTemplate
  • 只读 EType(模板顶层字段),逻辑不变

验证:确认技能特效显示正常

Step 4.5:适配 HeroViewComp.ts命中动画

文件assets/script/game/hero/HeroViewComp.ts

改动

  • ~507: SConf?.DAnmtemplate?.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.buffsresolved.buffs
    • buffConf.buffbuffConf.attr(同时兼容旧 buff 字段)
  • 伤害技能路径中 config.ap/config.crt/config.frz/config.hit_count → 从 resolved params 读取
  • config.TGroupresolved.TGroup
  • config.kindtemplate.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.tsMon.ts

改动

  • 英雄/怪物初始化时,将 heroInfo.atking/atked 等配置传入 HeroAttrsComp
  • HeroAttrsComp 中的类型同步更新为 TriggerSkillConf[]

验证:英雄和怪物的触发技能正常工作

Step 4.10:适配显示层文件

文件CardComp.tsIBoxComp.tsTooltipCom.tsSIconComp.tsSkillBoxComp.tsHlistComp.ts

改动

  • 仅引用名变更(SkillConfigSkillTemplate
  • 读取的字段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

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.2BuffConf 清理

文件SkillSet.tsSCastSystem.ts

改动

  • 删除 BuffConf.buff 字段,只保留 attr
  • 所有配置数据中 buff:attr:

验证buff 技能效果正确

Step 6.3:删除 kind 回退逻辑

文件SCastSystem.ts

改动

  • 移除 config.kind ?? SkillKind.Damageconfig.kind ?? SkillKind.Support 回退
  • 全部使用 template.kind

验证:所有技能类型判定正确


验证检查清单

每个 Step 完成后,运行以下检查:

检查项 方法
编译通过 无 TypeScript 错误
普攻正常 放置近战/远程英雄,观察普攻弹道和伤害
必杀技正常 触发必杀技,确认特效和伤害
护盾正常 触发护盾技能,确认护盾层数和显示
治疗正常 触发治疗技能,确认血量恢复
Buff 正常 触发 buff 技能,确认属性变化
卡牌技能正常 使用卡牌释放各种技能
触发技能正常 受击/攻击/死亡/开始触发链正常
怪物行为正常 怪物攻击和技能释放正常
无控制台报错 检查浏览器控制台无 JS 错误