Files
pixelheros/assets/script/game/map/TalentsComp.ts
panFD 45e3e8712b feat(ui): 新增天赋详情弹窗功能
重构天赋加点逻辑:将卡片点击校验与加点弹窗逻辑内聚到TIBoxComp中,TalentsComp仅负责打开弹窗。新增天赋详情弹窗,支持展示天赋信息、前置条件校验,并根据玩家状态动态控制加点按钮显隐。
2026-09-19 22:19:12 +08:00

139 lines
5.4 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: 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}`;
}
// 天赋等级(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();
}
}