Files
pixelheros/assets/script/game/map/TalentsComp.ts
pan 1634f6a528 feat(talent-ui): 优化天赋界面展示逻辑与数据显示
1.  天赋总览页新增各层已投入点数展示
2.  天赋详情弹窗重构前置与层位校验UI:
    - 拆分层位需求与软前置展示模块
    - 优化进度显示逻辑,避免数值歧义
    - 修正前置等级展示为当前/需求格式
3.  更新相关注释与文档说明
2026-09-20 16:04:09 +08:00

150 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file TalentsComp.ts
* @description 天赋加点页组件(UI 视图层,最小容器)
*
* 职责:
* 1. 页头展示:可用天赋点 / 天赋等级(Lv.x)/ 当前等级经验进度 / 各层已投入点数。
* 2. 收集子树内全部 TalentItemComp(编辑器静态摆放),TALENT_UPDATE 事件驱动全量刷新。
* 3. 卡片点击统一打开 TIBox 天赋详情弹窗;加点校验(层位/前置/满级/点数)由 TIBoxComp 内聚,
* 不满足条件时弹窗隐藏加点按钮,仅作详情查看。
* 4. 看广告重置入口:CommonPrompt 二次确认后调 smc.resetTalents() 退还全部点数。
*
* 依赖:
* - TalentSet(getTalentTierInvestedPoints/getTalentLevelExp)—— 配置与统计
* - TalentItemComp —— 单张迷你升级卡(编辑器静态摆放,按 uuid 自驱动渲染)
* - TIBoxComp —— 天赋详情弹窗(UIID.TIBox)
* - smc —— 天赋等级表/点数/升级/重置
*/
import { _decorator, Label, Node, NodeEventType, ProgressBar } 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 {
getTalentLevelExp, getTalentTierInvestedPoints,
} from "../common/config/TalentSet";
import { GameEvent } from "../common/config/GameEvent";
import { UIID } from "../common/config/GameUIConfig";
import { TalentItemComp } from "./TalentItemComp";
import { smc } from "../common/SingletonModuleComp";
import { oops } from "db://oops-framework/core/Oops";
const { ccclass, property } = _decorator;
/** TalentsComp —— 天赋加点页组件(最小容器:页头 + 编辑器静态卡片收集) */
@ccclass('TalentsComp')
@ecs.register('Talents', false)
export class TalentsComp extends CCComp {
@property({ type: Label, tooltip: "页头可用天赋点" })
lbl_points: Label = null!;
@property({ type: Label, tooltip: "天赋等级文案(Lv.x 样式)" })
lbl_lv: Label = null!;
@property({ type: ProgressBar, tooltip: "当前等级经验进度条" })
progress_exp: ProgressBar = null!;
@property({ type: Label, tooltip: "当前等级经验数值(当前经验/升级所需经验)" })
lbl_exp: Label = null!;
@property({ type: [Label], tooltip: "各层已投入点数 Label(数组索引对应第 1~5 层)" })
lbl_tier_points: Label[] = [];
@property({ type: Node, tooltip: "看广告重置按钮" })
btn_reset: Node = null!;
/** 页内全部天赋卡(onLoad 时自动收集子树内所有 TalentItemComp,无需编辑器拖引) */
private talent_items: TalentItemComp[] = [];
protected onLoad(): void {
this.talent_items = this.node.getComponentsInChildren(TalentItemComp);
for (const item of this.talent_items) {
item.onTalentTap = (uuid: number) => this.onTalentTap(uuid);
}
this.btn_reset?.on(NodeEventType.TOUCH_END, this.onResetTap, this);
}
protected onEnable(): void {
// 升级/重置/加点变动统一走 TALENT_UPDATE 事件驱动全量刷新
oops.message.on(GameEvent.TALENT_UPDATE, this.refreshUI, this);
this.refreshUI();
}
protected onDisable(): void {
oops.message.off(GameEvent.TALENT_UPDATE, this.refreshUI, this);
}
protected onDestroy(): void {
this.btn_reset?.targetOff(this);
}
/** 全量刷新:页头点数 + 天赋等级/经验 + 全部静态卡片 */
public refreshUI(): void {
const levels = smc.getTalentLevels();
if (this.lbl_points) {
// 剩余/总点数:总点数 = 剩余 + 各层已投入
const remaining = smc.getTalentPoints();
let invested = 0;
for (let tier = 1; tier <= 5; tier++) {
invested += getTalentTierInvestedPoints(levels, tier);
}
this.lbl_points.string = `${remaining}/${remaining + invested}`;
}
// 各层已投入点数(数组索引对应层 1~5)
for (let tier = 1; tier <= this.lbl_tier_points.length; tier++) {
const lbl = this.lbl_tier_points[tier - 1];
if (lbl) {
lbl.string = `${getTalentTierInvestedPoints(levels, tier)}`;
}
}
// 天赋等级(Lv.x)与当前等级经验进度
const talentLv = smc.getTalentLevel();
if (this.lbl_lv) this.lbl_lv.string = `Lv.${talentLv}`;
if (this.progress_exp) {
const needExp = getTalentLevelExp(talentLv);
// 满级后进度条显示为满
this.progress_exp.progress = needExp > 0
? Math.min(1, smc.getTalentExp() / needExp)
: 1;
}
if (this.lbl_exp) {
const needExp = getTalentLevelExp(talentLv);
// 满级后显示为 0/0,避免分母为 0
this.lbl_exp.string = needExp > 0
? `${smc.getTalentExp()}/${needExp}`
: `0/0`;
}
for (const item of this.talent_items) {
item.updateItem();
}
}
/**
* 卡片点击统一入口:任何状态均打开 TIBox 天赋详情弹窗,加点按钮显隐由 TIBoxComp 校验
* @param uuid 天赋 uuid
*/
private onTalentTap(uuid: number): void {
oops.gui.open(UIID.TIBox, { uuid });
}
/** 看广告重置入口:CommonPrompt 二次确认(广告接入前先直接确认重置) */
private onResetTap(): void {
oops.gui.open(UIID.Window, {
title: "重置天赋",
content: "观看广告后重置所有天赋等级,并全额退还已消耗的天赋点。是否继续?",
okWord: "重置",
cancelWord: "取消",
needCancel: true,
okFunc: () => smc.resetTalents(),
});
}
/** ECS 组件移除时销毁节点 */
reset() {
this.node.destroy();
}
}