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.
81 lines
3.2 KiB
81 lines
3.2 KiB
|
3 weeks ago
|
import type { EntityId } from 'db://assets/mx/module/ecs';
|
||
|
|
import { AbilitySetComp } from 'db://assets/mx/module/battle/ecs/Components';
|
||
|
|
import type { ComposedUnit } from 'db://assets/mx/module/merge';
|
||
|
|
import type { Node } from 'cc';
|
||
|
|
import type { IBattleRuntimeHandle } from '../types/ProjectBattleTypes';
|
||
|
|
import { WeaponComposeConfigProvider } from '../bag/WeaponComposeConfigProvider';
|
||
|
|
|
||
|
|
/** 羁绊读地图字块(不 import TextGrid,避免经 Skill 绕回) */
|
||
|
|
interface IBondMapGrid {
|
||
|
|
/** 节点是否有效 */
|
||
|
|
readonly isValid: boolean;
|
||
|
|
/** 所在区域 */
|
||
|
|
readonly location?: { kind: string };
|
||
|
|
/** 皮肤根 */
|
||
|
|
getSkinNode(): Node | null;
|
||
|
|
}
|
||
|
|
import { resolveTowerHeroId } from '../config/BattleHeroTable';
|
||
|
|
import { findEntityIdByGridIndex } from '../runtime/DeployEntityQuery';
|
||
|
|
import { isHeroActorWeapon1 } from '../heros/HeroActorRes';
|
||
|
|
|
||
|
|
function isActivatedAttackComposition(comp: ComposedUnit): boolean {
|
||
|
|
if (comp.weapon1Id <= 0) return false;
|
||
|
|
WeaponComposeConfigProvider.instance.load();
|
||
|
|
const provider = WeaponComposeConfigProvider.instance;
|
||
|
|
if (provider.isSingleCellWeapon1(comp.weapon1Id)) return true;
|
||
|
|
return comp.gridIndices.length >= 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isCompositionAttackActive(
|
||
|
|
comp: ComposedUnit,
|
||
|
|
mapGrids: ReadonlyMap<number, IBondMapGrid>,
|
||
|
|
): boolean {
|
||
|
|
let onMap = false;
|
||
|
|
let active = false;
|
||
|
|
for (const idx of comp.gridIndices) {
|
||
|
|
const grid = mapGrids.get(idx);
|
||
|
|
if (!grid?.isValid || grid.location?.kind !== 'map') continue;
|
||
|
|
onMap = true;
|
||
|
|
const skin = grid.getSkinNode();
|
||
|
|
const skill = skin?.getComponent('Skill') ?? skin?.getComponentInChildren('Skill');
|
||
|
|
if ((skill as { isActive?: boolean } | null)?.isActive) active = true;
|
||
|
|
}
|
||
|
|
if (isHeroActorWeapon1(comp.weapon1Id)) return onMap;
|
||
|
|
return onMap && active;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 局内羁绊:伙伴英雄是否在地图上处于攻击激活态 */
|
||
|
|
export function isPartnerWeaponActiveOnMap(
|
||
|
|
runtime: IBattleRuntimeHandle,
|
||
|
|
partnerWeapon1Id: number,
|
||
|
|
mapGrids?: ReadonlyMap<number, IBondMapGrid>,
|
||
|
|
): boolean {
|
||
|
|
const player = runtime.player;
|
||
|
|
const session = runtime.session;
|
||
|
|
if (!player || !session) return false;
|
||
|
|
|
||
|
|
const compositions = runtime.bagSession?.compositions ?? player.compositions ?? [];
|
||
|
|
|
||
|
|
for (const comp of compositions) {
|
||
|
|
if (comp.weapon1Id !== partnerWeapon1Id) continue;
|
||
|
|
if (!isActivatedAttackComposition(comp)) continue;
|
||
|
|
|
||
|
|
if (mapGrids?.size && isCompositionAttackActive(comp, mapGrids)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const idx of comp.gridIndices) {
|
||
|
|
const entityId: EntityId | null = findEntityIdByGridIndex(
|
||
|
|
idx, session, runtime.Map, player,
|
||
|
|
);
|
||
|
|
if (entityId == null || !session.world.isAlive(entityId)) continue;
|
||
|
|
if (resolveTowerHeroId(session.world, entityId) !== partnerWeapon1Id) continue;
|
||
|
|
// 已部署到地图的塔实体即在场。表现层 group2 不传 mapGrids,不能用 !!mapGrids 把判定打成 false。
|
||
|
|
if (isHeroActorWeapon1(partnerWeapon1Id)) return true;
|
||
|
|
const abilities = session.world.getComponent(entityId, AbilitySetComp);
|
||
|
|
if (abilities?.abilityIds.length) return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|