feat(talent): 重构天赋升级交互,新增确认弹窗逻辑
1. 移除天赋预制件上的+号节点和旧的背景组件,改为按阶位切换颜色背景 2. 天赋点击逻辑改为先弹出确认弹窗再执行升级 3. 简化天赋项组件的参数传递和状态判断逻辑 4. 更新注释文档与组件职责描述
This commit is contained in:
@@ -5,29 +5,29 @@
|
||||
* 职责:
|
||||
* 1. 接收 TalentsComp 下发的天赋配置 + 当前等级 + 阶位解锁态,渲染迷你点选卡。
|
||||
* 2. 卡面自包含:图标 / 名称 / 当前已生效数值(Lv0 显示每级数值引导)/ 右下「当前/满级」角标。
|
||||
* 3. 状态机:可升级(右上 + 徽标)/ 满级(MAX 金角标)/ 未激活(左上锁角标,点击锁/卡体可升级激活)。
|
||||
* 4. 点击回调上抛(含 + 徽标与卡体),升级校验与 toast 统一由 TalentsComp 处理(单一决策点)。
|
||||
* 3. 阶位背景:普通背景节点下挂 blue / red / yellow 三个颜色子节点,按阶位激活其一(Ⅰ蓝 / Ⅱ红 / Ⅲ金)。
|
||||
* 4. 状态机:满级(MAX 金角标)/ 未激活(左上锁角标 + 背景与图标灰阶 Grayscale)。
|
||||
* 5. 点击回调上抛卡体点击,加点确认弹窗与升级校验统一由 TalentsComp 处理(单一决策点)。
|
||||
*
|
||||
* 依赖:
|
||||
* - TalentSet.TalentConfig / TalentTier / getTalentDisplayText —— 配置与卡面文案
|
||||
* - CardBgComp —— 阶位品质底框(Ⅰ蓝 / Ⅱ紫 / Ⅲ金)
|
||||
* - 背景三颜色子节点(blue / red / yellow,编辑器侧搭建)
|
||||
* - smc.uiconsAtlas —— 图标解析(缺省回退资源目录)
|
||||
*/
|
||||
import { _decorator, Label, Node, NodeEventType, Sprite, SpriteFrame } 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 { TalentConfig, TalentTier, getTalentDisplayText } from "../common/config/TalentSet";
|
||||
import { CardBgComp } from "./CardBgComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 阶位 → 品质底框 card_lv(CARD_LV_BG_COLORS:2=blue、3=purple、4=yellow) */
|
||||
const TIER_TO_BG_LV: Record<number, number> = {
|
||||
[TalentTier.Basic]: 2,
|
||||
[TalentTier.Specialized]: 3,
|
||||
[TalentTier.Super]: 4,
|
||||
/** 阶位 → 背景节点下的颜色子节点名(Ⅰ蓝 / Ⅱ红 / Ⅲ金) */
|
||||
const TIER_BG_CHILD_NAMES: Record<number, string> = {
|
||||
[TalentTier.Basic]: "blue",
|
||||
[TalentTier.Specialized]: "red",
|
||||
[TalentTier.Super]: "yellow",
|
||||
};
|
||||
|
||||
/** TalentItemComp —— 天赋迷你升级卡组件 */
|
||||
@@ -47,11 +47,8 @@ export class TalentItemComp extends CCComp {
|
||||
@property({ type: Sprite, tooltip: "天赋图标" })
|
||||
icon: Sprite = null!;
|
||||
|
||||
@property({ type: CardBgComp, tooltip: "卡牌背景组件(阶位品质色)" })
|
||||
bg: CardBgComp = null!;
|
||||
|
||||
@property({ type: Node, tooltip: "右上 + 升级徽标(可升级时显示)" })
|
||||
node_plus: Node = null!;
|
||||
@property({ type: Node, tooltip: "卡牌背景节点(下挂 blue / red / yellow 三颜色子节点,按阶位激活其一)" })
|
||||
bg: Node = null!;
|
||||
|
||||
@property({ type: Node, tooltip: "MAX 满级角标" })
|
||||
node_max: Node = null!;
|
||||
@@ -78,9 +75,8 @@ export class TalentItemComp extends CCComp {
|
||||
* @param cfg 天赋配置(TalentSet 条目)
|
||||
* @param lv 当前等级
|
||||
* @param tierUnlocked 所属阶位是否已解锁
|
||||
* @param canUp 父级预判的"可升级"(阶位解锁 + 未满级 + 点数足够)
|
||||
*/
|
||||
public updateItem(cfg: TalentConfig, lv: number, tierUnlocked: boolean, canUp: boolean): void {
|
||||
public updateItem(cfg: TalentConfig, lv: number, tierUnlocked: boolean): void {
|
||||
if (!cfg) return;
|
||||
this.curUuid = cfg.uuid;
|
||||
|
||||
@@ -89,8 +85,11 @@ export class TalentItemComp extends CCComp {
|
||||
if (this.lbl_info) this.lbl_info.string = getTalentDisplayText(cfg, lv);
|
||||
if (this.lbl_lv) this.lbl_lv.string = `${lv}/${cfg.max_lv}`;
|
||||
|
||||
// 阶位品质底框:Ⅰ蓝 / Ⅱ紫 / Ⅲ金
|
||||
if (this.bg) this.bg.apply(TIER_TO_BG_LV[cfg.tier] ?? 1);
|
||||
// 未激活(Lv0 或阶位未解锁):背景与图标灰阶
|
||||
const inactive = lv <= 0 || !tierUnlocked;
|
||||
|
||||
// 阶位背景:激活对应颜色子节点(Ⅰ蓝 / Ⅱ红 / Ⅲ金)
|
||||
if (this.bg) this.applyTierBg(cfg.tier, inactive);
|
||||
|
||||
// 图标:uiconsAtlas 优先,资源目录回退(与 TalentItemComp 旧版/SCardComp 口径一致)
|
||||
if (this.icon && cfg.icon) {
|
||||
@@ -102,16 +101,28 @@ export class TalentItemComp extends CCComp {
|
||||
frame = oops.res.get("game/heros/cards/" + cfg.icon, SpriteFrame) as SpriteFrame;
|
||||
}
|
||||
if (frame) this.icon.spriteFrame = frame;
|
||||
this.icon.grayscale = inactive;
|
||||
}
|
||||
|
||||
// 状态徽标:满级 MAX / 可升级 + / 未激活锁角标(未加点或阶位未解锁,置于左上角)
|
||||
const maxed = lv >= cfg.max_lv;
|
||||
if (this.node_max) this.node_max.active = maxed;
|
||||
if (this.node_plus) this.node_plus.active = !maxed && tierUnlocked && canUp;
|
||||
if (this.node_lock) this.node_lock.active = lv <= 0 || !tierUnlocked;
|
||||
// 状态角标:满级 MAX / 未激活锁角标(未加点或阶位未解锁,置于左上角)
|
||||
if (this.node_max) this.node_max.active = lv >= cfg.max_lv;
|
||||
if (this.node_lock) this.node_lock.active = inactive;
|
||||
}
|
||||
|
||||
/** 卡体/+ 徽标/锁角标点击:触摸事件冒泡至卡体统一上抛 uuid,升级校验与提示由 TalentsComp 处理 */
|
||||
/** 按阶位激活 bg 下对应颜色子节点,其余隐藏;未激活时全部开启灰阶 */
|
||||
private applyTierBg(tier: TalentTier, inactive: boolean): void {
|
||||
const curName = TIER_BG_CHILD_NAMES[tier];
|
||||
for (const [, name] of Object.entries(TIER_BG_CHILD_NAMES)) {
|
||||
const child = this.bg.getChildByName(name);
|
||||
if (!child) continue;
|
||||
child.active = name === curName;
|
||||
// Sprite 内置灰阶材质,未激活天赋的背景置灰
|
||||
const render = child.getComponent(Sprite);
|
||||
if (render) render.grayscale = inactive;
|
||||
}
|
||||
}
|
||||
|
||||
/** 卡体点击上抛 uuid,加点确认与升级校验由 TalentsComp 处理 */
|
||||
private onTap(): void {
|
||||
this.onTalentTap?.(this.curUuid);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 职责:
|
||||
* 1. 三阶页签(Ⅰ 基础 / Ⅱ 专精 / Ⅲ 超强)状态机:单屏聚焦当前阶位的迷你天赋卡。
|
||||
* 2. 页签常显解锁进度(前阶投入 x/10),点击卡/+ 徽标升级(smc.upgradeTalent)。
|
||||
* 2. 页签常显解锁进度(前阶投入 x/10),点击天赋卡弹出 CommonPrompt 确认加点(smc.upgradeTalent)。
|
||||
* 3. 监听 GameEvent.TALENT_UPDATE 全量重渲染(23 条卡片,无需虚拟列表)。
|
||||
* 4. 看广告重置入口:CommonPrompt 二次确认后调 smc.resetTalents() 退还全部点数。
|
||||
*
|
||||
@@ -19,7 +19,7 @@ import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/modu
|
||||
import {
|
||||
TalentSet, TalentTier,
|
||||
TALENT_TIER_UNLOCK_THRESHOLD,
|
||||
getTalentLevelExp, getTalentTierInvestedPoints, getTalentUpgradeCost, isTalentTierUnlocked,
|
||||
getTalentDisplayText, getTalentLevelExp, getTalentTierInvestedPoints, getTalentUpgradeCost, isTalentTierUnlocked,
|
||||
} from "../common/config/TalentSet";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { UIID } from "../common/config/GameUIConfig";
|
||||
@@ -196,7 +196,6 @@ export class TalentsComp extends CCComp {
|
||||
private refreshGrid(levels: Record<number, number>): void {
|
||||
this.talents_content.removeAllChildren();
|
||||
const unlocked = isTalentTierUnlocked(levels, this.curTier);
|
||||
const points = smc.getTalentPoints();
|
||||
const cfgs = Object.values(TalentSet)
|
||||
.filter(cfg => cfg.tier === this.curTier)
|
||||
.sort((a, b) => a.uuid - b.uuid);
|
||||
@@ -204,15 +203,12 @@ export class TalentsComp extends CCComp {
|
||||
let cardHeight = 0;
|
||||
for (const cfg of cfgs) {
|
||||
const lv = levels[cfg.uuid] ?? 0;
|
||||
const cost = getTalentUpgradeCost(lv);
|
||||
// 可升级 = 阶位解锁 + 未满级 + 点数足够(+ 徽标显示依据)
|
||||
const canUp = unlocked && lv < cfg.max_lv && cost > 0 && points >= cost;
|
||||
|
||||
const itemNode = instantiate(this.prefab_talent_item);
|
||||
this.talents_content.addChild(itemNode);
|
||||
const comp = itemNode.getComponent(TalentItemComp);
|
||||
if (!comp) continue;
|
||||
comp.updateItem(cfg, lv, unlocked, canUp);
|
||||
comp.updateItem(cfg, lv, unlocked);
|
||||
comp.onTalentTap = (uuid: number) => this.onTalentTap(uuid);
|
||||
if (!cardHeight) cardHeight = itemNode.getComponent(UITransform)?.height ?? 0;
|
||||
}
|
||||
@@ -226,7 +222,7 @@ export class TalentsComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/** 卡片点击统一入口:阶位未解锁/已满级/点数不足分别 toast,成功升级由事件驱动刷新 */
|
||||
/** 卡片点击统一入口:未解锁/已满级直接 toast;其余弹出 CommonPrompt 确认加点,成功后事件驱动刷新 */
|
||||
private onTalentTap(uuid: number): void {
|
||||
const cfg = TalentSet[uuid];
|
||||
if (!cfg) return;
|
||||
@@ -237,13 +233,32 @@ export class TalentsComp extends CCComp {
|
||||
oops.gui.toast(`${TIER_TAB_TEXT[cfg.tier].lockName}投入 ${invested}/${TALENT_TIER_UNLOCK_THRESHOLD} 点解锁本阶`);
|
||||
return;
|
||||
}
|
||||
if (smc.getTalentLv(uuid) >= cfg.max_lv) {
|
||||
const lv = smc.getTalentLv(uuid);
|
||||
if (lv >= cfg.max_lv) {
|
||||
oops.gui.toast("该天赋已满级");
|
||||
return;
|
||||
}
|
||||
if (!smc.upgradeTalent(uuid)) {
|
||||
const cost = getTalentUpgradeCost(lv);
|
||||
if (cost <= 0) return;
|
||||
if (smc.getTalentPoints() < cost) {
|
||||
oops.gui.toast("天赋点不足");
|
||||
return;
|
||||
}
|
||||
|
||||
// CommonPrompt 确认加点(UIID.Window)
|
||||
oops.gui.open(UIID.Window, {
|
||||
title: "天赋加点",
|
||||
content: `${cfg.name} Lv.${lv} → Lv.${lv + 1}\n消耗 <color=#E0A93D>${cost}</color> 点天赋点,获得 ${getTalentDisplayText(cfg, 1)}。是否加点?`,
|
||||
okWord: "加点",
|
||||
cancelWord: "取消",
|
||||
needCancel: true,
|
||||
maskClose: true,
|
||||
okFunc: () => {
|
||||
if (!smc.upgradeTalent(uuid)) {
|
||||
oops.gui.toast("天赋点不足");
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 看广告重置入口:CommonPrompt 二次确认(广告接入前先直接确认重置) */
|
||||
|
||||
Reference in New Issue
Block a user