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.
130 lines
4.4 KiB
130 lines
4.4 KiB
import type { BattleSession } from 'db://assets/mx/module/battle';
|
|
import { TransformComp } from 'db://assets/mx/module/battle/ecs/Components';
|
|
import type { ComposedUnit } from 'db://assets/mx/module/merge';
|
|
import type { EntityId } from 'db://assets/mx/module/ecs';
|
|
import type { MapManager } from '../map/legacy/MapManager';
|
|
import { composeKey } from './ComposeUnitKey';
|
|
|
|
/** 部署查询只需合成与已部署列表 */
|
|
export interface IDeployOwner {
|
|
/** Merge 合成单位 */
|
|
readonly compositions: readonly ComposedUnit[];
|
|
/** 已部署实体 */
|
|
readonly deployedUnits: readonly EntityId[];
|
|
}
|
|
|
|
/** 部署信息 DTO(由 Merge.compositions 查询时现算) */
|
|
export interface DeployedTowerInfo {
|
|
/** Hero.id */
|
|
weapon1Id: number;
|
|
/** 合成等级 */
|
|
level: number;
|
|
/** 合成键 */
|
|
composeKey: string;
|
|
/** 占地格 */
|
|
gridIndices: readonly number[];
|
|
/** 朝向 */
|
|
direction: ComposedUnit['direction'];
|
|
}
|
|
|
|
/** ECS 实体 → 地图格 index(TransformComp + MapManager,不读 DeploySync 缓存) */
|
|
export function findGridIndexByEntity(
|
|
entityId: EntityId,
|
|
session: BattleSession,
|
|
map: MapManager,
|
|
): number | null {
|
|
const world = session.world;
|
|
if (!world.isAlive(entityId)) return null;
|
|
const tf = world.getComponent(entityId, TransformComp);
|
|
if (!tf) return null;
|
|
const mg = map.getMapGrid(tf.row, tf.col);
|
|
return mg?.Index ?? null;
|
|
}
|
|
|
|
/** 地图格 → 与 TransformComp 格坐标精确匹配的已部署实体 */
|
|
function findEntityIdAtMapGrid(
|
|
gridIndex: number,
|
|
session: BattleSession,
|
|
map: MapManager,
|
|
player?: IDeployOwner | null,
|
|
): EntityId | null {
|
|
const g = map.getMapGridByIndex(gridIndex);
|
|
if (!g) return null;
|
|
const world = session.world;
|
|
const deployed = player?.deployedUnits ?? session.players[0]?.deployedUnits ?? [];
|
|
for (const entityId of deployed) {
|
|
if (!world.isAlive(entityId)) continue;
|
|
const tf = world.getComponent(entityId, TransformComp);
|
|
if (tf && tf.row === g.Row && tf.col === g.Col) return entityId;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 地图格 index → ECS 实体。
|
|
* 多格合成体只在 gridIndices[0] 落 Transform,其余格通过 composition 回查同一实体。
|
|
*/
|
|
export function findEntityIdByGridIndex(
|
|
gridIndex: number,
|
|
session: BattleSession,
|
|
map: MapManager,
|
|
player?: IDeployOwner | null,
|
|
): EntityId | null {
|
|
const direct = findEntityIdAtMapGrid(gridIndex, session, map, player);
|
|
if (direct != null) return direct;
|
|
|
|
// 多格合成:实体只挂在一格,其余格经 composition 回查
|
|
const comp = player?.compositions.find(c => c.gridIndices.includes(gridIndex)) ?? null;
|
|
if (!comp) return null;
|
|
for (const idx of comp.gridIndices) {
|
|
if (idx === gridIndex) continue;
|
|
const entityId = findEntityIdAtMapGrid(idx, session, map, player);
|
|
if (entityId != null) return entityId;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 实体 → 地图格 index。
|
|
* 多格合成体 Transform 只落在锚点格;锚点格对不上时,沿 composition 其它格回查。
|
|
*/
|
|
export function findGridIndexForEntity(
|
|
entityId: EntityId,
|
|
player: IDeployOwner,
|
|
session: BattleSession,
|
|
map: MapManager,
|
|
): number | null {
|
|
const direct = findGridIndexByEntity(entityId, session, map);
|
|
if (direct != null) return direct;
|
|
for (const comp of player.compositions) {
|
|
for (const idx of comp.gridIndices) {
|
|
if (findEntityIdByGridIndex(idx, session, map, player) === entityId) {
|
|
return idx;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/** MergeSession.compositions 中查找实体所属合成单位(唯一合成态来源) */
|
|
export function findCompositionForEntity(
|
|
entityId: EntityId,
|
|
player: IDeployOwner,
|
|
session: BattleSession,
|
|
map: MapManager,
|
|
): ComposedUnit | null {
|
|
const gridIndex = findGridIndexForEntity(entityId, player, session, map);
|
|
if (gridIndex == null) return null;
|
|
return player.compositions.find(c => c.gridIndices.includes(gridIndex)) ?? null;
|
|
}
|
|
|
|
/** 由 Merge 合成单位构建部署信息 DTO(查询时现算,不缓存) */
|
|
export function buildDeployedTowerInfo(comp: ComposedUnit): DeployedTowerInfo {
|
|
return {
|
|
weapon1Id: comp.weapon1Id,
|
|
level: comp.level,
|
|
composeKey: composeKey(comp),
|
|
gridIndices: comp.gridIndices,
|
|
direction: comp.direction,
|
|
};
|
|
}
|
|
|