import type { EntityId } from 'db://assets/mx/module/ecs'; import { AttributeComp, BattleEventType, BattleTeamId, TeamComp, type BattleEvent, } from 'db://assets/mx/module/battle'; import { BattleBuffCarryStore } from '../../manager/battleBuff/BattleBuffCarryStore'; import { resolveCarriedEnemySlowWan } from '../../manager/battleBuff/BattleBuffPassiveSkillUtil'; import type { ProjectBattleHandle } from '../runtime/BattleRuntime'; import { AI_PLAYER_ID } from '../ai/runtime/AiCampArea'; /** 被动敌军减速 modifier 分组 */ const ENEMY_SLOW_MOD_GROUP = 'battle_buff_enemy_slow'; /** 单玩家减速 */ type PlayerSlow = { /** 被进攻方 playerId(WaveSpawner ownerId) */ playerId: number; /** 万分比 */ slowWan: number; }; /** * 被动 functiontype=23 弱水:进攻「携带者基地」的敌军移速 ×(1-万分比/10000)。 * Team.ownerId = 被进攻方(基地所属);减速的是往该基地冲的出征兵(敌方出征)。 */ export class BattleBuffEnemySlowHost { private _battle: ProjectBattleHandle | null = null; private readonly _slows: PlayerSlow[] = []; private _onUnitSpawnedBound = false; /** 绑定本局并监听出怪 */ bind(battle: ProjectBattleHandle): void { this.unbind(); this._battle = battle; this._slows.length = 0; this._pushSlow(battle.localPlayerId); this._pushSlow(AI_PLAYER_ID); if (this._slows.length <= 0) return; battle.session.events.on(BattleEventType.UnitSpawned, this._onUnitSpawned); this._onUnitSpawnedBound = true; battle.session.world.forEachAlive((entityId) => { this._tryApply(entityId); }); } /** 解除绑定 */ unbind(): void { const battle = this._battle; if (battle && this._onUnitSpawnedBound) { battle.session.events.off(BattleEventType.UnitSpawned, this._onUnitSpawned); } this._onUnitSpawnedBound = false; this._battle = null; this._slows.length = 0; } private _pushSlow(playerId: number): void { const adjust = resolveCarriedEnemySlowWan(BattleBuffCarryStore.getPassives(playerId)); if (!adjust.active || adjust.slowWan <= 0) return; this._slows.push({ playerId, slowWan: adjust.slowWan }); } private _onUnitSpawned = (event: BattleEvent): void => { if (event.type !== BattleEventType.UnitSpawned) return; this._tryApply(event.entity); }; /** 是否已挂载弱水减速 */ isActive(): boolean { return this._slows.length > 0; } /** * 该出征怪是否受弱水减速。 * @param entityId 怪物实体 * @returns 减速万分比;不受减则 null */ resolveSlowWanForEntity(entityId: EntityId): number | null { const battle = this._battle; if (!battle || this._slows.length <= 0) return null; const world = battle.session.world; if (!world.isAlive(entityId)) return null; const team = world.getComponent(entityId, TeamComp); if (!team || !BattleTeamId.isEnemyTeam(team.team)) return null; for (let i = 0; i < this._slows.length; i++) { if (this._slows[i].playerId !== team.ownerId) continue; return this._slows[i].slowWan; } return null; } private _tryApply(entityId: EntityId): void { const battle = this._battle; if (!battle || this._slows.length <= 0) return; const world = battle.session.world; if (!world.isAlive(entityId)) return; const team = world.getComponent(entityId, TeamComp); if (!team || !BattleTeamId.isEnemyTeam(team.team)) return; for (let i = 0; i < this._slows.length; i++) { if (this._slows[i].playerId !== team.ownerId) continue; this._applySlow(battle, entityId, this._slows[i].slowWan); return; } } private _applySlow(battle: ProjectBattleHandle, entityId: EntityId, slowWan: number): void { const world = battle.session.world; if (!world.getComponent(entityId, AttributeComp)) { world.addComponent(entityId, new AttributeComp()); } const speedMul = Math.max(0, 1 - slowWan / 10000); battle.session.attributes.addModifier(entityId, { attr: 'move_speed_mul', op: 'Mul', value: speedMul, source: `${ENEMY_SLOW_MOD_GROUP}_${slowWan}`, group: ENEMY_SLOW_MOD_GROUP, }); } } let _host: BattleBuffEnemySlowHost | null = null; /** 全局敌军减速被动 Host(单局复用) */ export function getBattleBuffEnemySlowHost(): BattleBuffEnemySlowHost { if (!_host) _host = new BattleBuffEnemySlowHost(); return _host; }