diff --git a/assets/resources/gui/element/cardlite.prefab b/assets/resources/gui/element/cardlite.prefab index 59789fc6..5f174694 100644 --- a/assets/resources/gui/element/cardlite.prefab +++ b/assets/resources/gui/element/cardlite.prefab @@ -4560,6 +4560,9 @@ "lvl_node": { "__id__": 293 }, + "canup_node": { + "__id__": 304 + }, "_id": "" }, { diff --git a/assets/script/game/common/config/heroUpSet.ts b/assets/script/game/common/config/heroUpSet.ts new file mode 100644 index 00000000..80abb28b --- /dev/null +++ b/assets/script/game/common/config/heroUpSet.ts @@ -0,0 +1,77 @@ +/** + * @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"; + +/** 英雄升级状态快照 */ +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), + }; +} diff --git a/assets/script/game/common/config/heroUpSet.ts.meta b/assets/script/game/common/config/heroUpSet.ts.meta new file mode 100644 index 00000000..d40b4960 --- /dev/null +++ b/assets/script/game/common/config/heroUpSet.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "621f3327-35b6-4b26-92f6-7f3c2abe74b7", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/script/game/map/CardLiteComp.ts b/assets/script/game/map/CardLiteComp.ts index 9326c998..727a0d0b 100644 --- a/assets/script/game/map/CardLiteComp.ts +++ b/assets/script/game/map/CardLiteComp.ts @@ -6,22 +6,28 @@ * 1. 管理英雄图鉴中单张英雄卡牌的 **显示**(名称、图标动画、卡池等级、英雄等级)。 * 2. 接收英雄 UUID 并渲染对应卡面。 * 3. 点击卡牌时通过事件通知父组件(HerosListComp)切换选中英雄详情。 + * 4. 英雄碎片满足升级条件时显示 canup 标识。 * * 关键设计: * - 轻量展示组件,仅用于英雄展示,无拖拽使用、无锁定、无费用扣除等交互。 * - 英雄卡图标加载 idle 动画剪辑并提取首帧静态展示。 * - 通过 iconVisualToken 防止异步加载竞态。 + * - canup 标识监听 HERO_GROWTH_UPDATE 事件实时刷新(碎片变动/升级后自动更新)。 * * 依赖: * - HeroInfo(heroSet)—— 用于渲染英雄卡面信息 + * - canHeroUpgrade(heroUpSet)—— 英雄升级条件判定 * - smc —— 全局单例,访问图标图集缓存与英雄局外等级 */ import { mLogger } from "../common/Logger"; import { _decorator, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteFrame, Tween, tween, UIOpacity, Vec3, resources } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; +import { oops } from "db://oops-framework/core/Oops"; import { HeroInfo } from "../common/config/heroSet"; import { getLvColor, CARD_LV_BG_COLORS } from "../common/config/GameSet"; +import { canHeroUpgrade } from "../common/config/heroUpSet"; +import { GameEvent } from "../common/config/GameEvent"; import { smc } from "../common/SingletonModuleComp"; const { ccclass, property } = _decorator; @@ -55,6 +61,10 @@ export class CardLiteComp extends CCComp { @property(Label) lvl_node: Label = null! + /** 可升级标识节点(碎片满足升级条件时显示) */ + @property(Node) + canup_node: Node = null! + // ======================== 运行时状态 ======================== card_uuid: number = 0 @@ -108,9 +118,24 @@ export class CardLiteComp extends CCComp { clear() { this.card_uuid = 0; this.applyEmptyUI(); + if (this.canup_node) this.canup_node.active = false; this.node.active = false; } + /** + * 刷新可升级标识:碎片满足升级条件时显示 canup 节点。 + * 渲染时自动调用一次;升级后由 HerosListComp 统一触发刷新。 + */ + refreshCanUp() { + if (!this.canup_node) return; + if (!this.hasCard()) { + this.canup_node.active = false; + return; + } + const growth = smc.getHeroGrowth(this.card_uuid); + this.canup_node.active = canHeroUpgrade(growth.lv, growth.fragments); + } + /** * 设置选中态:选中卡微微放大,取消选中恢复原尺寸。 * @param selected 是否选中 diff --git a/assets/script/game/map/HerosListComp.ts b/assets/script/game/map/HerosListComp.ts index 69e6a299..11ca32a2 100644 --- a/assets/script/game/map/HerosListComp.ts +++ b/assets/script/game/map/HerosListComp.ts @@ -168,6 +168,15 @@ export class HerosListComp extends CCComp { if (this.huuid) { this.updateHeroDetail(this.huuid) } + this.refreshAllCardsCanUp() + } + + /** 升级/碎片变动后统一刷新所有卡片的可升级标识(升级入口仅在本面板,无需卡片各自监听事件) */ + private refreshAllCardsCanUp() { + if (!this.cards_node) return + this.cards_node.children.forEach(cardNode => { + cardNode.getComponent(CardLiteComp)?.refreshCanUp() + }) } closeHeros() {