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, ): 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, ): 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; }