You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.6 KiB
108 lines
3.6 KiB
|
3 weeks ago
|
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();
|
||
|
|
}
|
||
|
|
}
|