1. 新增HeroInfoComp英雄详情弹窗,支持英雄属性展示、升级操作、前后切换功能 2. 重构HerosListComp图鉴页面,将详情面板逻辑剥离至弹窗,点击卡片直接打开详情页 3. 新增英雄列表排序工具函数,统一图鉴与弹窗切换的排序逻辑 4. 优化战斗渲染排序逻辑,移除无关的Y轴渲染权重计算 5. 新增英雄详情弹窗UI配置与预制体资源
101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
/**
|
||
* @file heroUpSet.ts
|
||
* @description 英雄局外升级规则与判定逻辑(纯逻辑模块,无 UI / 无单例依赖)
|
||
*
|
||
* 职责:
|
||
* 1. 封装 HERO_UPGRADE_NEED_FRAGMENTS 升级消耗表的查询口径(满级判定)。
|
||
* 2. 提供"是否可升级"的统一判定,供 smc.upgradeHero / HerosListComp / CardLiteComp 复用。
|
||
*
|
||
* 关键设计:
|
||
* - 不直接引用 smc 单例,由调用方传入成长数据(lv / fragments),保持纯函数可测试。
|
||
* - 升级表 key 为目标等级:need = HERO_UPGRADE_NEED_FRAGMENTS[lv + 1],查不到即满级。
|
||
*/
|
||
import { HERO_UPGRADE_NEED_FRAGMENTS } from "./GameSet";
|
||
import { HeroInfo, HeroList } from "./heroSet";
|
||
|
||
/** 英雄升级状态快照 */
|
||
export interface HeroUpgradeState {
|
||
/** 当前局外等级 */
|
||
lv: number;
|
||
/** 下一级(满级时为当前等级) */
|
||
nextLv: number;
|
||
/** 当前拥有碎片数 */
|
||
fragments: number;
|
||
/** 升到下一级所需碎片数(满级为 0) */
|
||
needFragments: number;
|
||
/** 是否已满级 */
|
||
isMaxLv: boolean;
|
||
/** 是否满足升级条件(未满级且碎片充足) */
|
||
canUpgrade: boolean;
|
||
}
|
||
|
||
/** 英雄最高局外等级(升级表最大 key - 1) */
|
||
export const HERO_MAX_LV: number = Math.max(...Object.keys(HERO_UPGRADE_NEED_FRAGMENTS).map(Number)) - 1;
|
||
|
||
/**
|
||
* 查询从当前等级升到下一级所需的碎片数。
|
||
* @param lv 当前局外等级
|
||
* @returns 所需碎片数;已满级返回 undefined
|
||
*/
|
||
export function getHeroUpgradeNeedFragments(lv: number): number | undefined {
|
||
return HERO_UPGRADE_NEED_FRAGMENTS[lv + 1];
|
||
}
|
||
|
||
/**
|
||
* 判断英雄当前等级是否已满级。
|
||
* @param lv 当前局外等级
|
||
*/
|
||
export function isHeroMaxLv(lv: number): boolean {
|
||
return getHeroUpgradeNeedFragments(lv) === undefined;
|
||
}
|
||
|
||
/**
|
||
* 判断英雄是否满足升级条件(未满级且碎片充足)。
|
||
* @param lv 当前局外等级
|
||
* @param fragments 当前拥有碎片数
|
||
*/
|
||
export function canHeroUpgrade(lv: number, fragments: number): boolean {
|
||
const need = getHeroUpgradeNeedFragments(lv);
|
||
return need !== undefined && fragments >= need;
|
||
}
|
||
|
||
/**
|
||
* 汇总英雄升级状态快照(供 UI 一次性取用,避免重复查表)。
|
||
* @param lv 当前局外等级
|
||
* @param fragments 当前拥有碎片数
|
||
*/
|
||
export function getHeroUpgradeState(lv: number, fragments: number): HeroUpgradeState {
|
||
const need = getHeroUpgradeNeedFragments(lv);
|
||
const isMax = need === undefined;
|
||
return {
|
||
lv,
|
||
nextLv: isMax ? lv : lv + 1,
|
||
fragments,
|
||
needFragments: need ?? 0,
|
||
isMaxLv: isMax,
|
||
canUpgrade: !isMax && fragments >= (need as number),
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 图鉴展示排序:可升级优先 → 现有等级降序 → 品质降序。
|
||
* Why: 图鉴(HerosListComp)与英雄详情(HeroInfoComp)共用同一排序口径,
|
||
* 保证图鉴中的卡片顺序与详情面板"前后切换"顺序一致。
|
||
* @param getGrowth 查询英雄成长数据(lv / fragments)的回调,通常由 smc.getHeroGrowth 注入
|
||
* @returns 排序后的英雄 uuid 数组(新数组,不修改 HeroList)
|
||
*/
|
||
export function getSortedHeroList(getGrowth: (uuid: number) => { lv: number; fragments: number }): number[] {
|
||
return [...HeroList].sort((a, b) => {
|
||
const ga = getGrowth(a);
|
||
const gb = getGrowth(b);
|
||
// 可升级的一批排在最左
|
||
const ca = canHeroUpgrade(ga.lv, ga.fragments) ? 0 : 1;
|
||
const cb = canHeroUpgrade(gb.lv, gb.fragments) ? 0 : 1;
|
||
if (ca !== cb) return ca - cb;
|
||
// 同批内:现有等级降序优先
|
||
if (ga.lv !== gb.lv) return gb.lv - ga.lv;
|
||
// 等级相同:品质降序(rarity 越大品质越高)
|
||
return (HeroInfo[b]?.rarity ?? 1) - (HeroInfo[a]?.rarity ?? 1);
|
||
});
|
||
}
|