feat(map): add hero info box panel for mission scene
1. 新增HeroBoxComp组件用于展示单个已登场英雄信息 2. 实现MissionCardComp的英雄信息盒槽位管理逻辑 3. 新增英雄升级事件监听与面板同步逻辑 4. 适配英雄召唤、死亡、出售后的UI刷新
This commit is contained in:
@@ -45,6 +45,7 @@ import { drawItemCards } from "../common/config/ICardSet";
|
||||
import { drawSkillCards } from "../common/config/SCardSet";
|
||||
import { CHeroComp } from "./CHeroComp";
|
||||
import { EquipListComp } from "./EquipListComp";
|
||||
import { HeroBoxComp } from "./HeroBoxComp";
|
||||
import { SCardComp } from "./SCardComp";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
@@ -143,7 +144,7 @@ export class MissionCardComp extends CCComp {
|
||||
@property(Prefab)
|
||||
itemPrefab: Prefab = null!
|
||||
/** 卡池升级按钮节点(已废弃,保留节点引用防止 editor 报错) */
|
||||
|
||||
|
||||
@property(Node)
|
||||
cards_up: Node = null!
|
||||
/** 金币显示节点(含 icon + num 子节点) */
|
||||
@@ -173,6 +174,8 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
/** 三个槽位对应的 CHeroComp 控制器缓存(有序数组) */
|
||||
private cardComps: CHeroComp[] = [];
|
||||
/** 英雄面板 HeroBoxComp 控制器缓存(与场上英雄一一对应,最多 3 个) */
|
||||
private heroBoxComps: HeroBoxComp[] = [];
|
||||
/** 装备卡槽控制器缓存 */
|
||||
private equipCardComps: EquipListComp[] = [];
|
||||
/** 技能卡槽控制器缓存 */
|
||||
@@ -318,6 +321,9 @@ export class MissionCardComp extends CCComp {
|
||||
this.hasCalledHero = false;
|
||||
this.updatePanelButtonsInteractable();
|
||||
|
||||
// 初始化英雄信息盒(3 个空槽位)
|
||||
this.refreshHeroBoxSlots();
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "mission start");
|
||||
}
|
||||
|
||||
@@ -327,6 +333,11 @@ export class MissionCardComp extends CCComp {
|
||||
this.clearEquipments();
|
||||
this.clearSkillCards();
|
||||
this.clearShopItems();
|
||||
for (const comp of this.heroBoxComps) {
|
||||
if (comp && comp.node && comp.node.isValid) {
|
||||
comp.applyEmpty();
|
||||
}
|
||||
}
|
||||
if (this.node && this.node.isValid) {
|
||||
this.node.active = false;
|
||||
}
|
||||
@@ -368,6 +379,7 @@ export class MissionCardComp extends CCComp {
|
||||
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.on(GameEvent.HeroSell, this.onHeroSell, this);
|
||||
oops.message.on(GameEvent.HeroLvUp, this.onHeroLvUp, this);
|
||||
oops.message.on(GameEvent.UseHeroCard, this.onUseHeroCard, this);
|
||||
// 监听装备购买事件,追踪已购记录
|
||||
oops.message.on(GameEvent.UseEquipCard, this.onUseEquipCard, this);
|
||||
@@ -610,6 +622,7 @@ export class MissionCardComp extends CCComp {
|
||||
oops.message.off(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.off(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.off(GameEvent.HeroSell, this.onHeroSell, this);
|
||||
oops.message.off(GameEvent.HeroLvUp, this.onHeroLvUp, this);
|
||||
oops.message.off(GameEvent.UseHeroCard, this.onUseHeroCard, this);
|
||||
oops.message.off(GameEvent.UseEquipCard, this.onUseEquipCard, this);
|
||||
oops.message.off(GameEvent.UseItemCard, this.onUseItemCard, this);
|
||||
@@ -681,16 +694,26 @@ export class MissionCardComp extends CCComp {
|
||||
smc.finish_guides.push(3);
|
||||
oops.gui.remove(UIID.Guide3);
|
||||
}
|
||||
|
||||
// 英雄登场后同步英雄信息盒
|
||||
this.refreshHeroBoxSlots();
|
||||
}
|
||||
|
||||
/** 英雄死亡事件回调:刷新面板列表并更新英雄数量 UI */
|
||||
private onHeroDead() {
|
||||
this.updateHeroNumUI(true, false);
|
||||
this.refreshHeroBoxSlots();
|
||||
}
|
||||
|
||||
/** 英雄被出售事件回调:更新英雄数量 UI */
|
||||
/** 英雄被出售事件回调:更新英雄数量 UI 并清空对应英雄信息盒 */
|
||||
private onHeroSell() {
|
||||
this.updateHeroNumUI(true, false);
|
||||
this.refreshHeroBoxSlots();
|
||||
}
|
||||
|
||||
/** 英雄升级事件回调:刷新英雄信息盒显示 */
|
||||
private onHeroLvUp() {
|
||||
this.refreshHeroBoxSlots();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -930,6 +953,71 @@ export class MissionCardComp extends CCComp {
|
||||
this.slideToPanel(0);
|
||||
}
|
||||
|
||||
// ======================== 英雄信息盒(herosBoxNode) ========================
|
||||
|
||||
/**
|
||||
* 同步英雄信息盒槽位与场上英雄:
|
||||
* 1. 确保 herosBoxNode 下存在 3 个 HeroBoxComp 槽位(复用 + 实例化补充)。
|
||||
* 2. 查询当前存活英雄列表,按序绑定到槽位。
|
||||
* 3. 多余槽位显示空英雄信息。
|
||||
*
|
||||
* Why: 英雄召唤 / 死亡 / 卖出 / 升级后调用,保证面板与场上一一对应。
|
||||
*/
|
||||
private refreshHeroBoxSlots() {
|
||||
if (!this.herosBoxNode || !this.herosBoxNode.isValid) return;
|
||||
|
||||
this.ensureHeroBoxSlots(3);
|
||||
|
||||
// 查询场上存活英雄(含复活中的实体,按 eid 升序保证稳定顺序)
|
||||
const actors: Array<{ eid: number, model: HeroAttrsComp }> = [];
|
||||
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||
const model = entity.get(HeroAttrsComp);
|
||||
if (!model) return;
|
||||
if (model.fac !== FacSet.HERO) return;
|
||||
if (model.is_dead) return;
|
||||
actors.push({ eid: entity.eid, model });
|
||||
});
|
||||
actors.sort((a, b) => a.eid - b.eid);
|
||||
|
||||
for (let i = 0; i < this.heroBoxComps.length; i++) {
|
||||
const comp = this.heroBoxComps[i];
|
||||
if (!comp || !comp.node || !comp.node.isValid) continue;
|
||||
const actor = actors[i];
|
||||
if (actor) {
|
||||
comp.bindHero(actor.eid, actor.model);
|
||||
} else {
|
||||
comp.applyEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
this.resizeListBox(this.herosBoxNode, Math.max(actors.length, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保英雄信息盒槽位数量足够。
|
||||
* 优先复用 herosBoxNode 现有子节点,不足时从 heroPrefab 实例化补充。
|
||||
*/
|
||||
private ensureHeroBoxSlots(targetCount: number) {
|
||||
if (!this.herosBoxNode || !this.herosBoxNode.isValid) return;
|
||||
|
||||
// 刷新缓存
|
||||
this.heroBoxComps = this.herosBoxNode.children
|
||||
.map(node => node.getComponent(HeroBoxComp))
|
||||
.filter((comp): comp is HeroBoxComp => !!comp);
|
||||
|
||||
// 补充实例化不足的槽位
|
||||
while (this.heroBoxComps.length < targetCount) {
|
||||
if (!this.heroPrefab) break;
|
||||
const node = instantiate(this.heroPrefab);
|
||||
// 先禁用根节点 Widget 再挂到父节点,避免 lateUpdate 覆盖 position
|
||||
const widget = node.getComponent(Widget);
|
||||
if (widget) widget.enabled = false;
|
||||
this.herosBoxNode.addChild(node);
|
||||
const comp = node.getComponent(HeroBoxComp) || node.addComponent(HeroBoxComp);
|
||||
this.heroBoxComps.push(comp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示卡牌面板:从底部向上滑入到 Y=0
|
||||
*/
|
||||
@@ -1401,7 +1489,7 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
// 滑动到英雄面板
|
||||
this.slideToPanel(0);
|
||||
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "enterPreparePhase herosPanNode", {
|
||||
herosPanNodeActive: this.herosPanNode?.active,
|
||||
herosPanNodePos: this.herosPanNode?.position,
|
||||
@@ -1853,6 +1941,7 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
// 关键:在 reset/销毁 时将 Map 置空,彻底切断引用
|
||||
this.cardComps = [];
|
||||
this.heroBoxComps = [];
|
||||
this.skillCardComps = [];
|
||||
this.purchasedEquipUuids.clear();
|
||||
this.purchasedItemUuids.clear();
|
||||
|
||||
Reference in New Issue
Block a user