Files
pixelheros/assets/script/game/map/TalentItemComp.ts
pan df519fdc4e feat(talent): 重构天赋系统为三阶结构并实现全新UI
1.  重构天赋系统为一阶基础/二阶专精/三阶超强三阶结构,移除前置天赋要求改为阶位累计点数解锁
2.  新增阶位解锁校验逻辑与天赋点投入统计
3.  重做天赋UI为三阶Tab页签+迷你升级卡样式,支持状态展示与一键升级
4.  补充新的天赋配置与属性加成,更新天赋系统文档
5.  修复属性计算问题,新增暴击伤害与穿刺伤害加成支持
2026-08-25 16:29:11 +08:00

128 lines
5.2 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. 接收 TalentsComp 下发的天赋配置 + 当前等级 + 阶位解锁态,渲染迷你点选卡。
* 2. 卡面自包含:图标 / 名称 / 当前已生效数值(Lv0 显示每级数值引导)/ 右下「当前/满级」角标。
* 3. 状态机:可升级(右上 + 徽标,绿光呼吸)/ 满级(MAX 金角标)/ 阶未解锁(半透明 + 锁)。
* 4. 点击回调上抛(含 + 徽标与卡体),升级校验与 toast 统一由 TalentsComp 处理(单一决策点)。
*
* 依赖:
* - TalentSet.TalentConfig / TalentTier / getTalentDisplayText —— 配置与卡面文案
* - CardBgComp —— 阶位品质底框(Ⅰ蓝 / Ⅱ紫 / Ⅲ金)
* - smc.uiconsAtlas —— 图标解析(缺省回退资源目录)
*/
import { _decorator, Label, Node, NodeEventType, Sprite, SpriteFrame, UIOpacity } 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,
};
/** TalentItemComp —— 天赋迷你升级卡组件 */
@ccclass('TalentItemComp')
@ecs.register('TalentItem', false)
export class TalentItemComp extends CCComp {
@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: CardBgComp, tooltip: "卡牌背景组件(阶位品质色)" })
bg: CardBgComp = null!;
@property({ type: Node, tooltip: "右上 + 升级徽标(可升级时显示)" })
node_plus: Node = null!;
@property({ type: Node, tooltip: "MAX 满级角标" })
node_max: Node = null!;
@property({ type: Node, tooltip: "阶位未解锁遮罩/锁图标" })
node_lock: Node = null!;
/** 点击回调(卡体与 + 徽标同源上抛),由父级统一校验升级 */
public onTalentTap: ((uuid: number) => void) | null = null;
/** 当前展示的天赋 uuid(回调携带) */
private curUuid: number = 0;
protected onLoad(): void {
this.node.on(NodeEventType.TOUCH_END, this.onTap, this);
}
protected onDestroy(): void {
this.node.off(NodeEventType.TOUCH_END, this.onTap, this);
}
/**
* 刷新迷你卡展示
* @param cfg 天赋配置(TalentSet 条目)
* @param lv 当前等级
* @param tierUnlocked 所属阶位是否已解锁
* @param canUp 父级预判的"可升级"(阶位解锁 + 未满级 + 点数足够)
*/
public updateItem(cfg: TalentConfig, lv: number, tierUnlocked: boolean, canUp: boolean): void {
if (!cfg) return;
this.curUuid = cfg.uuid;
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}`;
// 阶位品质底框:Ⅰ蓝 / Ⅱ紫 / Ⅲ金
if (this.bg) this.bg.apply(TIER_TO_BG_LV[cfg.tier] ?? 1);
// 图标:uiconsAtlas 优先,资源目录回退(与 TalentItemComp 旧版/SCardComp 口径一致)
if (this.icon && cfg.icon) {
let frame: SpriteFrame | null = null;
if (smc.uiconsAtlas) {
frame = smc.uiconsAtlas.getSpriteFrame(cfg.icon);
}
if (!frame) {
frame = oops.res.get("game/heros/cards/" + cfg.icon, SpriteFrame) as SpriteFrame;
}
if (frame) this.icon.spriteFrame = frame;
}
// 状态徽标:满级 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 = !tierUnlocked;
// 阶位锁定整卡压暗(UIOpacity:Cocos 3.x 节点透明度组件)
const uo = this.node.getComponent(UIOpacity) ?? this.node.addComponent(UIOpacity);
uo.opacity = tierUnlocked ? 255 : 110;
}
/** 卡体/+ 徽标点击:上抛 uuid,升级校验与提示由 TalentsComp 统一处理 */
private onTap(): void {
this.onTalentTap?.(this.curUuid);
}
/** ECS 组件移除时销毁节点(CCComp 抽象方法实现) */
reset() {
this.node.destroy();
}
}