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/bond/BondEvaluator.ts

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;
}