import { Node } from 'cc'; import { aiLog } from './AiLog'; import type { ProjectBattleHandle } from '../../runtime/BattleRuntime'; import type { MapManager } from '../../map/legacy/MapManager'; import { SkillController } from '../../skill/SkillController'; import { AiHeadlessBagHost } from './AiHeadlessBagHost'; import type { TextGrid } from '../../view/TextGrid'; /** * AI 技能表现宿主:独立 SkillController,承接 AI 塔 PresentationCue。 * 缺绑则 PlayPresentation 上锁后无人 finish,AI 塔永不攻击。 */ export class AiSkillHost { private _hostNode: Node | null = null; private _controller: SkillController | null = null; /** * 绑定 AI 玩家的 SkillController。 * @param battle 战斗 * @param map 地图 * @param parent UI 节点(挂载组件) * @param mapGrids AI 地图 TextGrid */ bind(battle: ProjectBattleHandle, map: MapManager, parent: Node, mapGrids?: ReadonlyMap): boolean { this.dispose(); const aiPlayer = battle.getPlayer(AiHeadlessBagHost.AI_PLAYER_ID); if (!aiPlayer) { aiLog('[AiSkillHost] bind failed: AI player missing'); return false; } if (!parent?.isValid) { aiLog('[AiSkillHost] bind failed: parent invalid'); return false; } let host = parent.getChildByName('aiSkillHost'); if (!host?.isValid) { host = new Node('aiSkillHost'); parent.addChild(host); } let sc = host.getComponent(SkillController); if (!sc) sc = host.addComponent(SkillController); sc.bind(aiPlayer, battle); sc.refreshEntitySkillBindings(map, mapGrids); aiPlayer.skillController = sc; this._hostNode = host; this._controller = sc; aiLog('[AiSkillHost] bound AI SkillController'); return true; } /** * 部署变化后刷新 entity→Skill 映射。 * @param map 地图 * @param mapGrids AI 地图 TextGrid */ refresh(map: MapManager, mapGrids?: ReadonlyMap): void { this._controller?.refreshEntitySkillBindings(map, mapGrids); } /** 解除绑定 */ dispose(): void { if (this._controller) { this._controller.unbind(); this._controller = null; } if (this._hostNode?.isValid) { this._hostNode.destroy(); } this._hostNode = null; } }