Files
pixelheros/docs/superpowers/specs/2026-08-21-hero-equip-design.md
panFD 3d2bba0cac docs(spec): 更新英雄专属武器系统设计文档
将原英雄个人装备系统设计文档重命名为英雄专属武器系统设计文档,更新了背景目标、数据结构、锻造重铸规则、局内集成、存档结构、UI交互等内容,将装备相关逻辑替换为专属武器逻辑,并完成现有光环卡改名适配。
2026-08-21 23:41:21 +08:00

12 KiB
Raw Blame History

英雄专属武器系统设计

  • 日期2026-08-21
  • 状态已评审brainstorming 阶段用户逐节确认)
  • 涉及文件:HeroWeaponSet.ts(新增)、heroSet.tsHeroAttrs.tsHeroAttrsComp.tsSingletonModuleComp.tsGameEvent.tsGameSet.tsEquipSet.ts(改名 TalentSet

1. 背景与目标

现有"装备"EquipSet.ts8701~8820 段)是全体驻场光环卡:购买后全队加属性,经 EquipBoxComp → FieldSkillHelper 全局聚合。

本设计新增英雄专属武器:每个英雄天生绑定一件专属武器,不可卸下、不可更换;词条只作用于该英雄本身;与现有光环卡并存,光环卡在表述上改名为战队天赋

核心特性:

  • 武器通过锻造成长:每次锻造 = 等级 +1并从词条池加权随机获得 1 条词条(暗黑式:数值在区间内随机)。
  • 抽中已有词条则数值累加,新词条则新增一条。
  • 等级上限 16 级特定里程碑等级必得该英雄专属词条(数值随机,合并到同 attr
  • 0 级白板武器自带 1 条初始专属词条
  • 品质按等级阶梯跃升,与词条数脱钩。
  • 重铸看广告将武器归零0 级 0 随机词条),已投入材料全部返还,初始专属词条重新 roll。
  • 武器是局外资产,随云存档持久化;局内只有战斗,不产生、不修改武器,开局快照生效。

2. 数据结构HeroWeaponSet.ts新增

位置:assets/script/game/common/config/HeroWeaponSet.ts,与 EquipSet.ts(将改名 TalentSet.ts)平级。

import { Attrs } from "./HeroAttrs";

/** 武器品质(按等级阶梯推导,不存储) */
export enum WeaponQuality {
    Fine = 1,     // 优秀绿0~3 级
    Superior = 2, // 精良4~7 级
    Epic = 3,     // 史诗8~11 级
    Legend = 4,   // 传说12~15 级
    Unique = 5,   // 唯一16 级满级
}

/** 词条池条目attr 指向 Attrs 枚举roll 时 value 在 [min, max] 内随机 */
export interface AffixPoolEntry {
    attr: Attrs;
    min: number;        // 数值型=整数下限;概率型=百分点下限
    max: number;
    weight: number;     // 抽取权重
}

/** 专属词条里程碑:到达 level 必得value 在 [min, max] 内随机后合并到同 attr */
export interface ExclusiveAffix {
    level: number;          // 0=初始自带1~16=锻造到达解锁
    attr: Attrs;
    min: number;
    max: number;
}

/** 武器底座key=英雄模板 uuid段位 9001-9099只定义规则不含实例 */
export interface HeroWeaponBase {
    hero_uuid: number;
    name: string;
    icon: string;
    affix_pool: AffixPoolEntry[];   // 随机词条池attr 白名单见第 4.4 节)
    exclusive: ExclusiveAffix[];    // 专属词条里程碑,按 level 升序,必含 1 条 level=0
    forge_cost: { item_id: number; count: number }[];  // 单次锻造材料(各级同价)
}

/** 武器状态:挂在英雄存档上,局外持久化;同 attr 词条已合并 */
export interface HeroWeaponState {
    level: number;                                 // = 已锻造次数0=未锻造白板,上限 16
    affixes: { attr: Attrs; value: number }[];     // 随机词条+专属词条,同 attr 已累加合并
    invested: { item_id: number; count: number }[]; // 累计已投入材料(重铸全量返还用)
}

品质阶梯

等级 品质 颜色
0~3 优秀Fine 绿
4~7 精良Superior
8~11 史诗Epic
12~15 传说Legend
16 唯一Unique
/** 按武器等级推导品质(不存储,实时推导) */
export function getWeaponQuality(level: number): WeaponQuality

词条口径(与现有百分比口径一致)

  • 数值型(仅 ap / hp_max / defenseFlat 数值roll 取整数
  • 概率型其余全部百分点roll 取 1 位小数
  • 词条池与专属词条仅允许出现第 4.4 节白名单中的 attr配置加载时校验。

3. 锻造与重铸

3.1 核心纯函数HeroWeaponSet.ts

/**
 * 锻造一次:等级+1 → 从 affix_pool 加权抽 1 条词条合并(已有 attr 数值累加,新 attr 新增)
 *          → 若新等级命中 exclusive 里程碑roll 专属词条数值并合并到同 attr
 * @param base 武器底座
 * @param state 当前武器状态level < 16
 * @returns 新状态base 非法或已满级返回 null 并 mLogger.warn
 */
export function forgeWeapon(base: HeroWeaponBase, state: HeroWeaponState): HeroWeaponState | null

/**
 * 初始化武器0 级白板 + roll level=0 的初始专属词条(获得英雄/懒初始化时调用)
 */
export function initWeapon(base: HeroWeaponBase): HeroWeaponState

/**
 * 重铸等级与随机词条清零invested 全量返还初始专属词条level=0重新 roll
 * @returns 新状态 + 应返还材料列表(= 原 invested 全量)
 */
export function reforgeWeapon(base: HeroWeaponBase, state: HeroWeaponState): {
    state: HeroWeaponState;
    refund: { item_id: number; count: number }[];
}

锻造流程:

  1. level+1
  2. affix_pool 按 weight 加权抽 1 条 attr[min, max] 内随机(数值型取整,概率型 1 位小数)。
  3. 该 attr 已存在于 affixes → 数值累加;否则新增一条。
  4. exclusive 中存在 level == 新等级 的条目 → 每条在 [min, max] 内随机并累加到同 attr不存在则新增
  5. invested 累加本次 forge_cost

3.2 可调参数GameSet.ts

MAX_WEAPON_LEVEL = 16,  // 武器锻造等级上限

3.3 材料与货币

  • 锻造材料为通用道具(如"精铁"),走现有道具库存;forge_cost 各级同价(递增为后续扩展,见 YAGNI
  • 重铸不消耗材料,改为看激励视频广告:广告播放完成回调成功后才执行 reforgeWeaponinvested 中材料全量返还道具库存。

4. 局内集成HeroAttrsComp

原则:局内快照,只读生效。 开战创建英雄实体时快照武器词条,局内不参与武器增删改。

4.1 快照字段

// HeroAttrsComp 新增
/** 武器词条加成缓存(局外武器在开局时快照;数值型=flat概率型=百分点) */
equip_mods: Partial<Record<Attrs, number>> = {};
  • 不存 HeroWeaponState,只存"每条属性加了多少"的聚合结果(affixes 已同 attr 合并,直接遍历即可)。
  • reset() 中清空。
  • 局内 UI 若要显示武器名,从 hero_weapons 反查,不影响战斗数据。

4.2 快照时机

英雄实体初始化(读 HeroInfo 填充属性的同一入口处)追加:

const weapon = smc.getHeroWeapon(hero_uuid);
attrsComp.equip_mods = aggregateWeaponAffixes(weapon);  // HeroWeaponSet.ts 纯函数UI 属性预览可复用

4.3 结算接入(最小侵入,每个 getFinal 加一项)

数值型:武器 flat 先进基础值,再吃驻场光环百分比(乘算放大,武器更值钱):

public getFinalAp(): number {
    const equipFlat = this.equip_mods[Attrs.ap] ?? 0;
    const runtimeAp = this.getRuntimeAp(this.ap + equipFlat);
    const mods = this.aggregateTimedMods(Attrs.ap);
    return (runtimeAp + mods.flatSum) * (1 + mods.pctSum / 100);
}

顺序:武器 flat → 驻场光环 % → 计时 buff。同理 getFinalHpMaxgetFinalDefense

概率型:百分点直接累加(base + weapon + timed

public getFinalCritical(): number {
    const base = this.getRuntimeCritical() + (this.equip_mods[Attrs.critical] ?? 0);
    const mods = this.aggregateTimedMods(Attrs.critical);
    return base + mods.flatSum + mods.pctSum;
}

4.4 接入清单(词条池 attr 白名单)

getFinal 方法 词条类型
getFinalAp / getFinalHpMax / getFinalDefense 数值型
getFinalCritical / getFinalCritDamage 概率型
getFinalFreezeChance / getFinalStunChance / getFinalParalyzeChance 概率型
getFinalPunctureChance / getFinalPunctureDmgBonus / getFinalWindFury 概率型
getFinalCriticalRes / getFinalFreezeRes / getFinalStunRes 概率型
getFinalKnockbackChance / getFinalKnockbackDistance / getFinalKnockbackRes 概率型
getFinalVulnerableRes / getFinalParalyzePower 概率型
getEffectiveSkillCdspeed 词条 → 攻速) 概率型

5. 局外数据持久化SingletonModuleComp.data

data: any = {
    // ...现有字段
    /** 英雄武器状态key=英雄模板 uuid局外资产随云存档持久化懒初始化 */
    hero_weapons: {} as Record<number, HeroWeaponState>,
}

GameDate 接口同步补充上述可选字段。

数据量评估:每件武器 JSON 约 40~60 字节(只存 level/affixes/invested50 英雄 ≈ 3KB远低于微信云存储 1MB 单记录上限。品质不存储(= getWeaponQuality(level) 实时推导)。

数据操作方法(封装在 SingletonModuleCompUI 不直改数据)

getHeroWeapon(heroUuid: number): HeroWeaponState   // 懒初始化:无记录时按底座 initWeapon 生成 0 级白板
forgeHeroWeapon(heroUuid: number): boolean         // 校验满级/材料 → 扣材料 → forgeWeapon → 累加 invested → markDataDirty + HeroWeapon_Update
reforgeHeroWeapon(heroUuid: number): boolean       // 广告成功回调内调用 → 返还 invested 全量 → reforgeWeapon → markDataDirty + HeroWeapon_Update

每个方法内部 gameDataSync.markDataDirty() + oops.message.dispatchEvent(GameEvent.HeroWeapon_Update)

新增事件GameEvent.ts

static HeroWeapon_Update = "HeroWeapon_Update";  // 武器锻造/重铸变更(英雄界面刷新)

监听方必须在 onDestroy/onDisable 注销oops 规范)。

6. UI 与交互

6.1 英雄界面 · 武器页签(唯一操作入口)

  • 英雄详情面板新增武器页签:武器图标 + 品质边框(按等级变色)+ 等级x/16+ 当前词条列表attr 名 + 数值)。
  • 【锻造】按钮显示本次材料消耗材料不足或满级16 级)置灰;点击 → 扣材料锻造 → 弹出结果浮层,高亮本次新增/累加的词条变化与品质跃升提示。
  • 【重铸】按钮:弹确认框(说明"观看广告重置武器,全部锻造材料返还")→ 调激励视频广告 → 播放完成回调成功后执行重铸并展示返还材料。

6.2 不做独立武器背包

武器与英雄强绑定,无装备网格列表、无穿戴选择层;武器信息只在英雄界面展示。

7. 现有光环卡改名"战队天赋"

  • EquipSet.tsTalentSet.ts(文件改名);EquipPoolListTalentPoolListdrawEquipCardsdrawTalentCardsfindEquipByUuidfindTalentByUuid
  • UI 文案"装备"→"战队天赋"tip_done.equip 字段名不变(避免存档兼容问题),语义指向天赋面板。
  • 局内组件 EquipBoxComp / MissEquipComp / EquipListComp逻辑不变,仅引用路径与显示文案调整。

8. 错误处理与边界

  • forgeWeapon 对未知 hero_uuid 底座或已满级16 级)返回 nullmLogger.warnforgeHeroWeapon 材料不足返回 false不扣材料。
  • 存档中 hero_weapons[hero_uuid] 存在但底座表无对应配置(云端数据异常)→ 快照时按 0 级白板处理(equip_mods = {})。
  • 词条池 / 专属词条 attr 不在白名单 → 配置加载时 mLogger.warn 并跳过该词条。
  • 旧存档无 hero_weapons 字段 → Object.assign 合并后由 getHeroWeapon 懒初始化兜底(参照 getHeroGrowth 的懒初始化模式)。
  • 重铸广告播放失败/中途关闭 → 不执行重铸,数据不变。
  • investedlevel × forge_cost 不一致(异常数据)→ 重铸以 invested 记录为准。

9. 不做的事YAGNI

  • 武器卸下/更换/交易;多武器槽位。
  • 词条锁定(洗单词条保留其他词条)。
  • 锻造材料随等级递增(初版各级同价)。
  • 词条重 roll洗练——重铸全洗已覆盖该需求。
  • 局内掉落/换武器。