import { BATTLE_EVENT_ALL, BattleEventType, EntityTag, TagComp, UnitMetaComp, type BattleEvent, type EntityId, type UnitDefId, } from 'db://assets/mx/module/battle'; import { parseLegacyMonsterId, parseMonsterUnitDefId } from '../../battle/config/MonsterHpCalculator'; import type { ProjectBattleHandle } from '../../battle/runtime/BattleRuntime'; import { UIID } from '../../game/ConfigRes'; import { MonsterDataManager, MonsterType } from '../../manager/MonsterDataManager'; import { BattleAudio } from '../../battle/audio/BattleAudio'; import type { BattleBossPanelData } from '../BattleBoss/UIBattleBoss'; /** Boss 出场弹窗:仅敌方波次 Boss;万神幡等额外出怪不弹 */ export class BattleGameBossIntroPresenter { private _battle: ProjectBattleHandle | null = null; private _onEvent: ((e: BattleEvent) => void) | null = null; /** 绑定战斗事件 */ bind(battle: ProjectBattleHandle): void { this.unbind(); this._battle = battle; this._onEvent = (e) => this._onBattleEvent(e); battle.on(BATTLE_EVENT_ALL, this._onEvent); } /** 注销战斗事件 */ unbind(): void { if (this._battle && this._onEvent) { this._battle.off(BATTLE_EVENT_ALL, this._onEvent); } this._battle = null; this._onEvent = null; } private _onBattleEvent(event: BattleEvent): void { if (event.type !== BattleEventType.UnitSpawned) return; this._tryShowBossIntro(event.spawnPort, event.unitDefId, event.entity); } /** * 敌方出怪口波次 Boss 出场时打开 BattleBoss。 * @param spawnPort 出怪口 * @param unitDefId 单位定义 id * @param entityId 实体 id */ private _tryShowBossIntro(spawnPort: number, unitDefId: UnitDefId, entityId: EntityId): void { const battle = this._battle; if (!battle) return; if (!this._isEnemySpawnPort(spawnPort)) return; // 万神幡 / 营 / 技能召唤:meta.glowShadow=true,只出怪不出征弹窗 const meta = battle.session.world.getComponent(entityId, UnitMetaComp); if (meta?.glowShadow) return; const parsed = parseMonsterUnitDefId(unitDefId); const monsterId = parsed?.monsterId ?? parseLegacyMonsterId(unitDefId); if (!(monsterId > 0)) { console.log('[BattleGameBossIntro] unitDefId 无效', unitDefId); return; } const row = MonsterDataManager.getMonsterDataById(monsterId); if (!row) { console.log('[BattleGameBossIntro] Monster 缺失', monsterId); return; } const tags = battle.session.world.getComponent(entityId, TagComp); const isBoss = row.type === MonsterType.Boss || !!tags?.tags.includes(EntityTag.Boss); if (!isBoss) return; if (gg.ui.hasPanel(UIID.BattleBoss)) { console.log('[BattleGameBossIntro] BattleBoss 已打开,跳过', monsterId); return; } BattleAudio.playBossIntro(); const data: BattleBossPanelData = { monsterId }; void gg.ui.openPanel(UIID.BattleBoss, { data }); } /** 相对本机玩家的敌方出怪口(本机 id0→spawnPoint_1) */ private _isEnemySpawnPort(spawnPort: number): boolean { const battle = this._battle; if (!battle) return false; const localId = battle.localPlayerId; const enemyPort = localId === 0 ? 1 : 2; return spawnPort === enemyPort; } }