1. 天赋总览页新增各层已投入点数展示
2. 天赋详情弹窗重构前置与层位校验UI:
- 拆分层位需求与软前置展示模块
- 优化进度显示逻辑,避免数值歧义
- 修正前置等级展示为当前/需求格式
3. 更新相关注释与文档说明
150 lines
5.9 KiB
TypeScript
150 lines
5.9 KiB
TypeScript
/**
|
||
* @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();
|
||
}
|
||
}
|