Files
pixelheros/assets/script/game/map/IBoxComp.ts
panFD ae540e1232 style(map): 调整信息框Y轴偏移并简化布局代码
1. 将EquipBoxComp和SkillBoxComp的IBOX_OFFSET_Y从60改为80
2. 移除IBoxComp中冗余的布局常量和自适应布局逻辑
2026-08-03 09:10:37 +08:00

174 lines
6.0 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 IBoxComp.ts
* @description 技能/装备详情弹窗组件IBoxUI 视图层)
*
* 职责:
* 1. 作为详情弹窗,展示单个技能或装备的 **功能描述详情**。
* 2. 通过 init(args) 接收技能 UUID、装备 UUID 或运行时技能数据。
* 3. 使用单个 RichText 以 BBCode 展示名称蓝色、CD/持续时间(亮绿色)、结构化效果描述。
* 4. 点击弹窗任意区域关闭自身。
*
* 关键设计:
* - 复用 HeroSkillDesc 的结构化模板渲染,数值实时从配置读取,杜绝漂移。
* - 技能展示名称、等级、CD、效果描述SkillDescSet 模板)。
* - 装备展示名称、全部驻场光环词条FieldDescSet 模板)。
* - 不走 oops.gui由调用方手动实例化并添加到场景通过 init() 初始化。
*
* 依赖:
* - HeroSkillDescbuildSingleSkillRich / buildEquipRich—— 描述生成
* - SkillSet / FieldSkillSetSkillSet—— 技能/光环静态配置
* - EquipSetfindEquipByUuid—— 装备静态配置
*/
import { _decorator, Label, NodeEventType, RichText } 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 { SkillSet, SkillOverrides } from "../common/config/SkillSet";
import { buildEquipRich, buildSingleSkillRich } from "../common/config/HeroSkillDesc";
import { findEquipByUuid } from "../common/config/EquipSet";
const { ccclass, property } = _decorator;
/** IBox 初始化参数 */
export interface IBoxInitArgs {
/** SkillSet 技能 UUID技能详情模式 */
skillUuid?: number;
/** 技能等级(默认 1 */
skillLv?: number;
/** 技能覆写参数(如药水卡自定义档位) */
overrides?: SkillOverrides;
/** EquipSet 装备 UUID装备详情模式 */
equipUuid?: number;
/** 运行时技能数据(运行时技能详情模式,取第一个技能展示) */
skills?: Record<number, { uuid: number; lv: number; cd: number; ccd: number }>;
}
/**
* IBoxComp —— 技能/装备详情弹窗视图组件
*
* 由调用方通过 instantiate + addChild 手动实例化,然后调用 init(args) 初始化。
* 示例:
* const node = instantiate(this.iboxPrefab);
* this.node.addChild(node);
* node.getComponent(IBoxComp).init({ skillUuid: 6301, anchorPos: this.node.worldPosition });
*/
@ccclass('IBoxComp')
@ecs.register('IBoxComp', false)
export class IBoxComp extends CCComp {
// ======================== 编辑器绑定节点 ========================
@property(RichText)
massage_node: RichText = null!
/**
* 初始化并渲染弹窗内容。
* @param args 见 IBoxInitArgs
*/
public init(args: IBoxInitArgs) {
this.render(args);
}
/** 绑定点击关闭事件 */
onLoad() {
this.node.on(NodeEventType.TOUCH_END, this.onTapClose, this);
}
/** 解绑点击事件 */
onDestroy() {
super.onDestroy();
if (this.node && this.node.isValid) {
this.node.off(NodeEventType.TOUCH_END, this.onTapClose, this);
}
}
/** ECS 组件移除时销毁节点 */
reset() {
this.node.destroy();
}
// ======================== 渲染逻辑 ========================
/**
* 主渲染方法:根据 args 模式分发到技能详情或装备详情。
*/
private render(args: IBoxInitArgs) {
// 装备详情模式
if (args?.equipUuid !== undefined) {
this.renderEquip(args.equipUuid);
return;
}
// 运行时技能详情模式(取第一个技能)
if (args?.skills) {
const first = Object.values(args.skills)[0];
if (first) {
this.renderSkill(first.uuid, first.lv);
return;
}
}
// 技能详情模式
if (args?.skillUuid !== undefined) {
this.renderSkill(args.skillUuid, args.skillLv ?? 1, args.overrides);
return;
}
this.setHeroName("");
this.setRichText("暂无信息");
}
/**
* 渲染技能详情名称、等级、CD、结构化效果描述。
* @param skillUuid SkillSet 技能 UUID
* @param lv 技能等级
* @param overrides 可选覆写参数
*/
private renderSkill(skillUuid: number, lv: number, overrides?: SkillOverrides) {
const skill = SkillSet[skillUuid];
if (!skill) {
this.setHeroName("");
this.setRichText("未知技能");
return;
}
this.setHeroName(skill.name);
this.setRichText(buildSingleSkillRich(skillUuid, overrides, lv));
}
/**
* 渲染装备详情:名称、全部驻场光环词条。
* @param equipUuid EquipSet 装备 UUID
*/
private renderEquip(equipUuid: number) {
const equip = findEquipByUuid(equipUuid);
if (!equip) {
this.setHeroName("");
this.setRichText("未知装备");
return;
}
this.setHeroName(equip.name);
this.setRichText(buildEquipRich(equip.field ?? []));
}
/** 将 BBCode 文本写入 RichText */
private setRichText(text: string) {
if (this.massage_node && this.massage_node.isValid) {
this.massage_node.string = text;
}
}
/**
* 设置标题名称标签
* @param name 技能/装备名称
*/
private setHeroName(name: string) {
const bgNode = this.node.getChildByName("Bg");
const nameNode = bgNode?.getChildByName("name");
const valNode = nameNode?.getChildByName("val");
const label = valNode?.getComponent(Label) || valNode?.getComponentInChildren(Label);
if (label) {
label.string = name;
}
}
/** 点击弹窗任意区域关闭自身 */
private onTapClose() {
if (this.node && this.node.isValid) {
this.node.destroy();
}
}
}