import { _decorator, Component, Node } from 'cc'; import { GBundle } from '../../game/ConfigRes'; import { BattleMapSpec } from '../map/BattleMapSpec'; import { readMapGridSpec } from '../map/MapGridSpecReader'; import type { MapManager } from './legacy/MapManager'; const { ccclass, property } = _decorator; /** * 战斗地图宿主:负责加载 mapLayer 预制体并挂到场景 * 逻辑层格子规格见 BattleMapSpec(与 MapManager 字段一致) */ @ccclass('CocosBattleMapHost') export class CocosBattleMapHost extends Component { @property(Node) mapRoot: Node | null = null; private _mapNode: Node | null = null; private _mapPrefabName = ''; /** 加载关卡 map 字段指定的地图预制体 */ loadMap(mapPrefabName: string): Node | null { this.unloadMap(); const name = String(mapPrefabName ?? '').trim(); if (!name) { console.error('[CocosBattleMapHost] 地图预制体名为空'); return null; } this._mapPrefabName = name; const parent = this.mapRoot ?? this.node; const path = BattleMapSpec.PREFAB_DIR; if (typeof gg === 'undefined' || !gg.res?.getNode) { console.log('[CocosBattleMapHost] gg.res not ready'); return null; } const mapNode = gg.res.getNode(path, name, GBundle.BattleMap); if (!mapNode) { console.error('[CocosBattleMapHost] map prefab not found', name); return null; } mapNode.parent = parent; this._mapNode = mapNode; this.validateMapSize(mapNode); const mapMgr = mapNode.getComponent('MapManager') as MapManager | null; if (mapMgr) { // 动态挂载后须等节点世界变换稳定,再采集出怪口/攻击点坐标 mapMgr.scheduleOnce(() => mapMgr.initMapGrids(), 0); } else { console.error('[CocosBattleMapHost] MapManager component missing on', name); } return mapNode; } unloadMap(): void { if (this._mapNode?.isValid) { this._mapNode.destroy(); } this._mapNode = null; } get mapNode(): Node | null { return this._mapNode; } /** 当前地图预制体名(Level.map) */ get mapPrefabName(): string { return this._mapPrefabName; } /** @deprecated 请用 mapPrefabName;从 mapLayerN 解析 N,否则为 0 */ get mapId(): number { const matched = /^mapLayer(\d+)$/i.exec(this._mapPrefabName); if (!matched) return 0; const parsed = Number(matched[1]); return Number.isFinite(parsed) && parsed > 0 ? parsed : 0; } /** 校验 MapManager 与战斗 session.grid 一致(session 未创建时跳过) */ private validateMapSize(mapNode: Node): void { const mapMgr = mapNode.getComponent('MapManager') as MapManager | null; if (!mapMgr) return; const prefabSpec = readMapGridSpec(mapMgr); const session = gg.game.CurentBattle?.session; if (!session) return; const g = session.grid; if (g.rows === prefabSpec.rows && g.cols === prefabSpec.cols && g.cellSize === prefabSpec.cellSize) { return; } console.error( `[CocosBattleMapHost] ${this._mapPrefabName} 与 session.grid 不一致:`, `预制体 ${prefabSpec.rows}×${prefabSpec.cols} @ ${prefabSpec.cellSize}px,`, `session ${g.rows}×${g.cols} @ ${g.cellSize}px`, '— 请确认进战斗前已从 mapLayer 预制体探测格子规格', ); } onDestroy(): void { this.unloadMap(); } }