refactor(map): 重构装备卡槽管理与节点挂载逻辑

1.  移除HeroBoxComp中未使用的ebars_node属性
2.  重构EBox.load方法,支持自定义父节点并更新注释
3.  重构MissEquipComp:
    - 移除无用的BoxSet导入和硬编码槽位坐标
    - 使用ebars_node子节点动态生成槽位
    - 修改装备挂载逻辑,将装备挂载到对应ebar子节点而非直接设置位置
    - 更新相关注释与日志提示
4.  调整mission.prefab的UI布局参数与绑定节点
This commit is contained in:
pan
2026-08-06 16:52:32 +08:00
parent 369817d304
commit 0b579f695c
4 changed files with 54 additions and 51 deletions

View File

@@ -1906,7 +1906,7 @@
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": 306.634, "x": 306.634,
"y": 651.253, "y": 216.64,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -2425,7 +2425,7 @@
"_left": -8.317000000000007, "_left": -8.317000000000007,
"_right": -6.6340000000000146, "_right": -6.6340000000000146,
"_top": 89.63, "_top": 89.63,
"_bottom": 596.253, "_bottom": 161.64,
"_horizontalCenter": 0, "_horizontalCenter": 0,
"_verticalCenter": 0, "_verticalCenter": 0,
"_isAbsLeft": true, "_isAbsLeft": true,
@@ -7013,7 +7013,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -315, "x": -310,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -7292,7 +7292,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -235, "x": -220,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -7571,7 +7571,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -155, "x": -130,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -7850,7 +7850,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -75, "x": -40,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -8129,7 +8129,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": 5, "x": 50,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -8408,7 +8408,7 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": 85, "x": 140,
"y": 0, "y": 0,
"z": 0 "z": 0
}, },
@@ -8744,11 +8744,11 @@
"height": 40 "height": 40
}, },
"_startAxis": 0, "_startAxis": 0,
"_paddingLeft": 5, "_paddingLeft": 10,
"_paddingRight": 0, "_paddingRight": 0,
"_paddingTop": 0, "_paddingTop": 0,
"_paddingBottom": 0, "_paddingBottom": 0,
"_spacingX": 0, "_spacingX": 10,
"_spacingY": 0, "_spacingY": 0,
"_verticalDirection": 1, "_verticalDirection": 1,
"_horizontalDirection": 0, "_horizontalDirection": 0,
@@ -23937,6 +23937,7 @@
"refresh_stone_num_node": { "refresh_stone_num_node": {
"__id__": 209 "__id__": 209
}, },
"ebars_node": null,
"_id": "" "_id": ""
}, },
{ {
@@ -24018,6 +24019,9 @@
"__uuid__": "66d7902d-2a85-43d5-8cbb-671cc7dbb275", "__uuid__": "66d7902d-2a85-43d5-8cbb-671cc7dbb275",
"__expectedType__": "cc.Prefab" "__expectedType__": "cc.Prefab"
}, },
"ebars_node": {
"__id__": 421
},
"_id": "" "_id": ""
}, },
{ {

View File

@@ -26,15 +26,17 @@ export class EBox extends ecs.Entity {
/** /**
* 加载并初始化技能盒子 * 加载并初始化技能盒子
* 1) 创建节点并挂到 SKILL 层 * 1) 创建节点并挂到 parent 下(未传时默认 SKILL 层
* 2) 初始化表现与属性数据 * 2) 初始化表现与属性数据
*/ */
load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab): Node { load(uuid: number, card_lv: number, pos: Vec3, prefab: Prefab, parent?: Node): Node {
let node = instantiate(prefab); let node = instantiate(prefab);
let scene = smc.map.MapView.scene;
// 统一挂到实体显示层 SKILL 节点下 // 默认挂到实体显示层 SKILL 节点下
let parent = scene.entityLayer!.node!.getChildByName("SKILL"); if (!parent) {
let scene = smc.map.MapView.scene;
parent = scene.entityLayer!.node!.getChildByName("SKILL") ?? undefined;
}
if (parent) { if (parent) {
node.parent = parent; node.parent = parent;
} }

View File

@@ -44,9 +44,7 @@ export class HeroBoxComp extends CCComp {
// ======================== 编辑器绑定节点 ======================== // ======================== 编辑器绑定节点 ========================
/** 装备图标节点 */
@property({ type: Node })
private ebars_node: Node = null;
/** 英雄图标节点 */ /** 英雄图标节点 */
@property({ type: Node }) @property({ type: Node })

View File

@@ -22,21 +22,16 @@
* - smc.map.MapView.scene.entityLayer —— 装备节点的父容器EQUIP 节点) * - smc.map.MapView.scene.entityLayer —— 装备节点的父容器EQUIP 节点)
*/ */
import { mLogger } from "../common/Logger"; import { mLogger } from "../common/Logger";
import { _decorator, Node, Prefab, instantiate, Vec3 } from "cc"; import { _decorator, Node, Prefab, Vec3 } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { EBox } from "./EBox"; import { EBox } from "./EBox";
import { oops } from "db://oops-framework/core/Oops"; import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent"; import { GameEvent } from "../common/config/GameEvent";
import { BoxSet } from "../common/config/GameSet";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
/** 技能槽位数据结构 */ /** 装备槽位占用状态 */
interface SkillBoxSlot { interface EquipSlot {
/** 该槽位的固定 X 坐标 */
x: number;
/** 该槽位的固定 Y 坐标 */
y: number;
/** 是否已被占用 */ /** 是否已被占用 */
used: boolean; used: boolean;
/** 占用该槽位的节点引用 */ /** 占用该槽位的节点引用 */
@@ -47,7 +42,7 @@ interface SkillBoxSlot {
* MissEquipComp —— 场上装备卡槽位管理器 * MissEquipComp —— 场上装备卡槽位管理器
* *
* 在战斗场景中管理已激活的装备卡显示位置。 * 在战斗场景中管理已激活的装备卡显示位置。
* 2 行 × 5 列 = 10 个槽位,不足时提示已满。 * 最多 6 个槽位(由外部传入的 ebars_node 子节点 ebar 提供),不足时提示已满。
*/ */
@ccclass('MissEquipComp') @ccclass('MissEquipComp')
@ecs.register('MissEquipComp', false) @ecs.register('MissEquipComp', false)
@@ -68,24 +63,24 @@ export class MissEquipComp extends CCComp {
return inst.slots.every(slot => slot.used); return inst.slots.every(slot => slot.used);
} }
/** 技能卡 Prefab在编辑器中赋值 */ /** 装备卡 Prefab在编辑器中赋值 */
@property({ type: Prefab }) @property({ type: Prefab })
private equip_box: Prefab = null; private equip_box: Prefab = null;
/**
* 预定义的 6 个槽位坐标(单行): /** 装备槽位容器(子节点为 6 个 ebar每个装备实例化为一个 ebar 的子节点) */
*/ @property({ type: Node })
private slots: SkillBoxSlot[] = [ private ebars_node: Node = null;
{ x: -310, y: BoxSet.GAME_LINE - 70, used: false, node: null },
{ x: -230, y: BoxSet.GAME_LINE - 70, used: false, node: null }, /** 槽位占用状态(与 ebars_node 子节点一一对应,最多 6 个) */
{ x: -150, y: BoxSet.GAME_LINE - 70, used: false, node: null }, private slots: EquipSlot[] = [];
{ x: -70, y: BoxSet.GAME_LINE - 70, used: false, node: null },
{ x: 10, y: BoxSet.GAME_LINE - 70, used: false, node: null },
{ x: 90, y: BoxSet.GAME_LINE - 70, used: false, node: null },
];
/** 注册事件监听 */ /** 注册事件监听 */
onLoad() { onLoad() {
MissEquipComp.instance = this; MissEquipComp.instance = this;
// 初始化槽位占用状态(与 ebars_node 子节点一一对应)
if (this.ebars_node) {
this.slots = this.ebars_node.children.map(() => ({ used: false, node: null }));
}
oops.message.on(GameEvent.UseEquipCard, this.onUseEquipCard, this); oops.message.on(GameEvent.UseEquipCard, this.onUseEquipCard, this);
oops.message.on(GameEvent.RemoveEquipBox, this.onRemoveEquipBox, this); oops.message.on(GameEvent.RemoveEquipBox, this.onRemoveEquipBox, this);
} }
@@ -125,10 +120,12 @@ export class MissEquipComp extends CCComp {
} }
/** /**
* 紧凑重排:将所有有效节点按顺序移到前置槽位。 * 紧凑重排:将所有有效节点按顺序移到前置 ebar 槽位。
* 确保视觉上不会出现中间空洞。 * 确保视觉上不会出现中间空洞。
*/ */
private rearrangeSlots() { private rearrangeSlots() {
if (!this.ebars_node || !this.ebars_node.isValid) return;
// 收集所有有效节点 // 收集所有有效节点
const validNodes: Node[] = []; const validNodes: Node[] = [];
for (let i = 0; i < this.slots.length; i++) { for (let i = 0; i < this.slots.length; i++) {
@@ -138,13 +135,12 @@ export class MissEquipComp extends CCComp {
this.slots[i].used = false; this.slots[i].used = false;
this.slots[i].node = null; this.slots[i].node = null;
} }
// 按顺序重新分配 // 按顺序重新挂载到前置 ebar
for (let i = 0; i < validNodes.length; i++) { for (let i = 0; i < validNodes.length && i < this.slots.length; i++) {
if (i < this.slots.length) { this.slots[i].used = true;
this.slots[i].used = true; this.slots[i].node = validNodes[i];
this.slots[i].node = validNodes[i]; validNodes[i].parent = this.ebars_node.children[i];
validNodes[i].setPosition(new Vec3(this.slots[i].x, this.slots[i].y, 0)); validNodes[i].setPosition(Vec3.ZERO);
}
} }
} }
@@ -168,7 +164,7 @@ export class MissEquipComp extends CCComp {
/** /**
* 在场上添加一个装备卡: * 在场上添加一个装备卡:
* 1. 在 slots 中查找空闲位。 * 1. 在 slots 中查找空闲位。
* 2. 实例化 equip_box Prefab 并放置在空闲位坐标 * 2. 实例化 equip_box Prefab 并挂载到对应 ebar 子节点下
* 3. 获取或添加 EquipBoxComp 并初始化。 * 3. 获取或添加 EquipBoxComp 并初始化。
* *
* @param uuid 装备 UUID * @param uuid 装备 UUID
@@ -179,6 +175,10 @@ export class MissEquipComp extends CCComp {
mLogger.error(this.debugMode, "MissEquipComp", "equip_box prefab not set"); mLogger.error(this.debugMode, "MissEquipComp", "equip_box prefab not set");
return; return;
} }
if (!this.ebars_node || !this.ebars_node.isValid || this.slots.length === 0) {
mLogger.error(this.debugMode, "MissEquipComp", "ebars node not bound");
return;
}
// 查找空闲槽位 // 查找空闲槽位
const emptyIndex = this.slots.findIndex(slot => !slot.used); const emptyIndex = this.slots.findIndex(slot => !slot.used);
@@ -188,10 +188,9 @@ export class MissEquipComp extends CCComp {
return; return;
} }
// 使用 ECS 实体创建装备节点 // 使用 ECS 实体创建装备节点,挂载到对应 ebar 子节点下
let ebox = ecs.getEntity<EBox>(EBox); let ebox = ecs.getEntity<EBox>(EBox);
let pos = new Vec3(this.slots[emptyIndex].x, this.slots[emptyIndex].y, 0); let node = ebox.load(uuid, card_lv, Vec3.ZERO, this.equip_box, this.ebars_node.children[emptyIndex]);
let node = ebox.load(uuid, card_lv, pos, this.equip_box);
this.slots[emptyIndex].used = true; this.slots[emptyIndex].used = true;
this.slots[emptyIndex].node = node; this.slots[emptyIndex].node = node;