import type { EntityId } from 'db://assets/mx/module/ecs'; import { BattleEventType, type BattleEvent, } from 'db://assets/mx/module/battle'; import { BattleBuffCarryStore } from '../../manager/battleBuff/BattleBuffCarryStore'; import { resolveMarchOwnerPlayerId } from '../../manager/battleBuff/BattleBuffSideResolve'; import { resolveCarriedUnitHpBonusWan } from '../../manager/battleBuff/BattleBuffPassiveSkillUtil'; import type { ProjectBattleHandle } from '../runtime/BattleRuntime'; import { SkillAtkBuffExecutor } from './SkillAtkBuffExecutor'; import { AI_PLAYER_ID } from '../ai/runtime/AiCampArea'; /** 单玩家血量加成 */ type PlayerHpBonus = { /** playerId(出征方) */ playerId: number; /** 万分比 */ bonusWan: number; }; /** * 被动 functiontype=15 补元丹:携带方「出征兵」maxHp/hp ×(1+万分比/10000)。 * 出征兵 = 进攻对面基地的行军怪(本机视角常在对面半场),不是己侧场上单位。 */ export class BattleBuffUnitHpHost { private _battle: ProjectBattleHandle | null = null; private readonly _bonuses: PlayerHpBonus[] = []; private _onUnitSpawnedBound = false; /** 绑定本局并监听出怪 */ bind(battle: ProjectBattleHandle): void { this.unbind(); this._battle = battle; this._bonuses.length = 0; this._pushBonus(battle.localPlayerId); this._pushBonus(AI_PLAYER_ID); if (this._bonuses.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._bonuses.length = 0; } private _pushBonus(playerId: number): void { const adjust = resolveCarriedUnitHpBonusWan(BattleBuffCarryStore.getPassives(playerId)); if (!adjust.active || adjust.bonusWan <= 0) return; this._bonuses.push({ playerId, bonusWan: adjust.bonusWan }); } private _onUnitSpawned = (event: BattleEvent): void => { if (event.type !== BattleEventType.UnitSpawned) return; this._tryApply(event.entity); }; private _tryApply(entityId: EntityId): void { const battle = this._battle; if (!battle || this._bonuses.length <= 0) return; const ownerId = resolveMarchOwnerPlayerId(battle.session, entityId); if (ownerId < 0) return; for (let i = 0; i < this._bonuses.length; i++) { if (this._bonuses[i].playerId !== ownerId) continue; SkillAtkBuffExecutor.applyMaxHpCoeff(battle.session.world, entityId, this._bonuses[i].bonusWan, battle); return; } } } let _host: BattleBuffUnitHpHost | null = null; /** 全局出征兵血量被动 Host(单局复用) */ export function getBattleBuffUnitHpHost(): BattleBuffUnitHpHost { if (!_host) _host = new BattleBuffUnitHpHost(); return _host; }