import { Vec3 } from 'cc'; import { GridType } from '../core/Define'; import { GameManager } from '../manager/GameManager'; import { forEachLevelEntityNode } from '../level/TileLayout'; import { entityWorldPositionForRole, worldToMoverCellForRole } from '../level/EntitySpawnPlacement'; import { PlayerController } from './PlayerController'; import { VehicleController } from './VehicleController'; /** 按逻辑格查找载具(gridTypes + 当前 committedCell) */ export function findVehicleAtCell(cell: Vec3): VehicleController | null { const gm = GameManager.instance; if (!gm) return null; const fromGrid = gm.getGameObjectAtCell(cell)?.getComponent(VehicleController); if (fromGrid) return fromGrid; const level = gm.curLevel; if (!level) return null; let found: VehicleController | null = null; forEachLevelEntityNode(level, (ch) => { if (found || !ch.name.includes('Vehicle')) return; const vc = ch.getComponent(VehicleController); if (!vc || !vehicleMatchesCell(vc, cell)) return; found = vc; }); return found; } /** 双向绑定玩家与载具,并确保 Ride 格注册 */ export function linkRidePair(player: PlayerController, vehicle: VehicleController, cell: Vec3) { const gm = GameManager.instance; if (!gm) return; const config = gm.getCurLevel(); const theme = config?.theme ?? gm.uiStyle; const deck = entityWorldPositionForRole(cell, config ?? undefined, theme, 'vehicle'); player.setRideVehicle(vehicle); vehicle.setPlayer(player); vehicle.setDirection(player.direction); player.shareCommittedCell(cell); vehicle.shareCommittedCell(cell); vehicle.node.setPosition(deck); gm.addObjAtCell(cell, GridType.Ride, vehicle.node); player.setRideBaseFromVehicle(deck); } function playerLogicCell(player: PlayerController): Vec3 { const committed = player.getCommittedCell(); if (committed) return committed.clone(); const gm = GameManager.instance!; const config = gm.getCurLevel(); const theme = config?.theme ?? gm.uiStyle; return worldToMoverCellForRole( player.node.position, config ?? undefined, theme, 'player', ); } function vehicleLogicCell(vehicle: VehicleController): Vec3 | null { const committed = vehicle.getCommittedCell(); if (committed) return committed.clone(); const spawn = vehicle.getSpawnCell() ?? vehicle.getCommittedCell(); if (spawn) return spawn.clone(); const gm = GameManager.instance; if (!gm) return null; const config = gm.getCurLevel(); const theme = config?.theme ?? gm.uiStyle; return worldToMoverCellForRole(vehicle.node.position, config ?? undefined, theme, 'vehicle'); } function vehicleMatchesCell(vehicle: VehicleController, cell: Vec3): boolean { const vCell = vehicleLogicCell(vehicle); return !!vCell && vCell.x === cell.x && vCell.y === cell.y; } /** 玩家与载具占同一逻辑格时绑定(不依赖 Ride 格是否已注册) */ export function tryLinkPlayerVehicle(player: PlayerController): boolean { const gm = GameManager.instance; const level = gm?.curLevel; if (!level) return false; const pCell = playerLogicCell(player); if (!pCell) return false; const existing = player.getRideVehicle(); if (existing) { const vCell = vehicleLogicCell(existing); if (!vCell || vCell.x !== pCell.x || vCell.y !== pCell.y) { existing.setPlayer(null); player.setRideVehicle(null); return false; } linkRidePair(player, existing, pCell); return true; } let linked = false; forEachLevelEntityNode(level, (ch) => { if (linked || !ch.name.includes('Vehicle')) return; const vc = ch.getComponent(VehicleController); if (!vc || !vehicleMatchesCell(vc, pCell)) return; linkRidePair(player, vc, pCell); linked = true; }); if (linked) return true; const rideVc = findVehicleAtCell(pCell); if (rideVc) { linkRidePair(player, rideVc, pCell); return true; } return false; } /** 载具侧:同格玩家自动设为骑手 */ export function tryLinkVehicleRider(vehicle: VehicleController): boolean { const gm = GameManager.instance; const level = gm?.curLevel; if (!level) return false; const vCell = vehicleLogicCell(vehicle); if (!vCell) return false; const rider = vehicle.getPlayer(); if (rider) { const pCell = playerLogicCell(rider); if (pCell && pCell.x === vCell.x && pCell.y === vCell.y) { linkRidePair(rider, vehicle, vCell); return true; } } let matched = false; forEachLevelEntityNode(level, (ch) => { if (matched || !ch.name.includes('Player')) return; const pc = ch.getComponent(PlayerController); if (!pc) return; const pCell = playerLogicCell(pc); if (!pCell || pCell.x !== vCell.x || pCell.y !== vCell.y) return; linkRidePair(pc, vehicle, vCell); matched = true; }); return matched; } /** 移动中强制位置联动(Unity OnMoving 语义) */ export function syncRidePositions(driver: 'player' | 'vehicle', player: PlayerController, vehicle: VehicleController) { if (driver === 'player') { const p = player.node.position; vehicle.node.setPosition(p.x, p.y, p.z); } else { player.setRideBaseFromVehicle(vehicle.node.position); } } export function resolveRideBind(player: PlayerController, cell: Vec3 | null): VehicleController | null { if (!cell) return null; return findVehicleAtCell(cell); }