Files
pixelheros/assets/script/game/map/TalentItemComp.ts
panFD f4150bd33c fix(talent): 调整天赋项UI显示逻辑与样式
1.  修改天赋项锁定状态判断逻辑,不再因Lv0显示锁遮罩
2.  更新节点注释与tooltip描述
3.  调整预制体布局与精灵资源配置
2026-09-19 15:34:35 +08:00

133 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 TalentItemComp.ts
* @description 天赋迷你升级卡组件(UI 视图层,编辑器静态摆放)
*
* 职责:
* 1. 通过编辑器配置的 uuid 自查询天赋配置 + 当前等级 + 层位解锁态,渲染迷你点选卡。
* 2. 卡面自包含:图标 / 名称 / 当前已生效数值(Lv0 显示每级数值引导)/ 右下「当前/满级」角标。
* 3. 层位背景:普通背景节点下挂 blue / red / yellow 三个颜色子节点,按层位映射激活其一(L1蓝 / L2红 / L3金,L4/L5 复用金)。
* 4. 状态机:满级(MAX 金角标)/ 锁定(锁遮罩:层位未解锁或前置未满足;可加点时不显示,不做灰阶处理)。
* 5. 点击回调上抛卡体点击,加点确认弹窗与升级校验统一由 TalentsComp 处理(单一决策点)。
*
* 依赖:
* - TalentSet(TalentConfig/TalentTier/getTalentDisplayText/isTalentTierUnlocked/isTalentPrereqMet)—— 配置与校验
* - 背景三颜色子节点(blue / red / yellow,编辑器侧搭建)
* - smc —— 天赋等级表与图标图集(缺省回退资源目录)
*/
import { _decorator, CCInteger, 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 { TalentSet, TalentTier, getTalentDisplayText, isTalentPrereqMet, isTalentTierUnlocked } from "../common/config/TalentSet";
import { smc } from "../common/SingletonModuleComp";
import { oops } from "db://oops-framework/core/Oops";
const { ccclass, property } = _decorator;
/** 层位 → 背景节点下的颜色子节点名(L1蓝 / L2红 / L3金;L4/L5 复用金) */
const TIER_BG_CHILD_NAMES: Record<number, string> = {
[TalentTier.L1]: "blue",
[TalentTier.L2]: "red",
[TalentTier.L3]: "yellow",
[TalentTier.L4]: "yellow",
[TalentTier.L5]: "yellow",
};
/** TalentItemComp —— 天赋迷你升级卡组件(编辑器静态摆放,按 uuid 自驱动渲染) */
@ccclass('TalentItemComp')
@ecs.register('TalentItem', false)
export class TalentItemComp extends CCComp {
@property({ type: CCInteger, tooltip: "天赋 uuid(TalentSet key,编辑器侧配置)" })
talent_uuid: number = 0;
@property({ type: Label, tooltip: "天赋名称" })
lbl_name: Label = null!;
@property({ type: Label, tooltip: "当前已生效数值(Lv0 显示每级引导)" })
lbl_info: Label = null!;
@property({ type: Label, tooltip: "等级角标(当前/满级)" })
lbl_lv: Label = null!;
@property({ type: Sprite, tooltip: "天赋图标" })
icon: Sprite = null!;
@property({ type: Node, tooltip: "卡牌背景节点(下挂 blue / red / yellow 三颜色子节点,按层位激活其一)" })
bg: Node = null!;
@property({ type: Node, tooltip: "MAX 满级角标" })
node_max: Node = null!;
@property({ type: Node, tooltip: "锁遮罩/锁图标(层位未解锁或前置未满足时显示;可加点时隐藏)" })
node_lock: Node = null!;
/** 点击回调(卡体点击上抛),由 TalentsComp 统一校验升级 */
public onTalentTap: ((uuid: number) => void) | null = null;
protected onLoad(): void {
this.node.on(NodeEventType.TOUCH_END, this.onTap, this);
}
protected onDestroy(): void {
this.node.off(NodeEventType.TOUCH_END, this.onTap, this);
}
/** 刷新迷你卡展示:按编辑器配置的 uuid 自查询配置与等级,层位/前置校验内部完成 */
public updateItem(): void {
const cfg = TalentSet[this.talent_uuid];
if (!cfg) return;
const levels = smc.getTalentLevels();
const lv = levels[this.talent_uuid] ?? 0;
const tierUnlocked = isTalentTierUnlocked(levels, cfg.tier);
const prereqMet = isTalentPrereqMet(levels, cfg);
if (this.lbl_name) this.lbl_name.string = cfg.name;
// 卡面自包含:已加点显示当前生效数值,未加点显示每级数值引导
if (this.lbl_info) this.lbl_info.string = getTalentDisplayText(cfg, lv);
if (this.lbl_lv) this.lbl_lv.string = `${lv}/${cfg.max_lv}`;
// 锁遮罩:仅在层位未解锁或前置未满足时显示;已解锁且前置满足即可加点,不再因 Lv0 挂锁
const locked = !tierUnlocked || !prereqMet;
// 层位背景:激活对应颜色子节点(L1蓝 / L2红 / L3金)
if (this.bg) this.applyTierBg(cfg.tier);
// 图标:技能图标图集(gui/ui7)优先,资源目录回退(与 SCardComp 口径一致)
if (this.icon && cfg.icon) {
let frame: SpriteFrame | null = null;
if (smc.skillIconsAtlas) {
frame = smc.skillIconsAtlas.getSpriteFrame(cfg.icon);
}
if (!frame) {
frame = oops.res.get("game/heros/cards/" + cfg.icon, SpriteFrame) as SpriteFrame;
}
if (frame) this.icon.spriteFrame = frame;
}
// 状态角标:满级 MAX / 锁遮罩(层位未解锁或前置未满足)
if (this.node_max) this.node_max.active = lv >= cfg.max_lv;
if (this.node_lock) this.node_lock.active = locked;
}
/** 按层位激活 bg 下对应颜色子节点,其余隐藏 */
private applyTierBg(tier: TalentTier): 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;
}
}
/** 卡体点击上抛 uuid,加点确认与升级校验由 TalentsComp 处理 */
private onTap(): void {
this.onTalentTap?.(this.talent_uuid);
}
/** ECS 组件移除时销毁节点(CCComp 抽象方法实现) */
reset() {
this.node.destroy();
}
}