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.
AdLike2048/assets/script/battle/runtime/DeployEntityQuery.ts

131 lines
4.4 KiB

13 hours ago
import type { BattleSession } from 'db://assets/mx/module/battle/core/BattleSession';
3 weeks ago
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,
};
}