|
|
|
|
import type { EntityId } from 'db://assets/mx/module/ecs';
|
|
|
|
|
import {
|
|
|
|
|
AttributeComp,
|
|
|
|
|
BattleEventType,
|
|
|
|
|
MovementComp,
|
|
|
|
|
type BattleEvent,
|
|
|
|
|
} from 'db://assets/mx/module/battle';
|
|
|
|
|
import { BattleBuffCarryStore } from '../../manager/battleBuff/BattleBuffCarryStore';
|
|
|
|
|
import { resolveMarchOwnerPlayerId } from '../../manager/battleBuff/BattleBuffSideResolve';
|
|
|
|
|
import { resolveCarriedOwnMarchSlowWan } from '../../manager/battleBuff/BattleBuffPassiveSkillUtil';
|
|
|
|
|
import type { ProjectBattleHandle } from '../runtime/BattleRuntime';
|
|
|
|
|
import { AI_PLAYER_ID } from '../ai/runtime/AiCampArea';
|
|
|
|
|
|
|
|
|
|
/** 被动行军速度 modifier 分组 */
|
|
|
|
|
const MOVE_SPEED_MOD_GROUP = 'battle_buff_own_march_slow';
|
|
|
|
|
|
|
|
|
|
/** 单玩家出征减速万分比 */
|
|
|
|
|
type PlayerMarchSlow = {
|
|
|
|
|
/** playerId(出征方) */
|
|
|
|
|
playerId: number;
|
|
|
|
|
/** 减速万分比 */
|
|
|
|
|
slowWan: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 被动 functiontype=13 滞行牌:携带方「己方出征兵」移速 ×(1-减速万分比/10000)。
|
|
|
|
|
*/
|
|
|
|
|
export class BattleBuffMoveSpeedHost {
|
|
|
|
|
private _battle: ProjectBattleHandle | null = null;
|
|
|
|
|
private readonly _slows: PlayerMarchSlow[] = [];
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 按携带方读滞行牌,作用于该方出征兵。
|
|
|
|
|
* @param carrierPlayerId 携带方
|
|
|
|
|
*/
|
|
|
|
|
private _pushSlow(carrierPlayerId: number): void {
|
|
|
|
|
const adjust = resolveCarriedOwnMarchSlowWan(BattleBuffCarryStore.getPassives(carrierPlayerId));
|
|
|
|
|
if (!adjust.active || adjust.slowWan <= 0) return;
|
|
|
|
|
for (let i = 0; i < this._slows.length; i++) {
|
|
|
|
|
if (this._slows[i].playerId !== carrierPlayerId) continue;
|
|
|
|
|
this._slows[i].slowWan += adjust.slowWan;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this._slows.push({ playerId: carrierPlayerId, slowWan: adjust.slowWan });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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._slows.length <= 0) return;
|
|
|
|
|
const ownerId = resolveMarchOwnerPlayerId(battle.session, entityId);
|
|
|
|
|
if (ownerId < 0) return;
|
|
|
|
|
for (let i = 0; i < this._slows.length; i++) {
|
|
|
|
|
if (this._slows[i].playerId !== ownerId) continue;
|
|
|
|
|
this._applyMarchSlow(battle, entityId, this._slows[i].slowWan);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _applyMarchSlow(battle: ProjectBattleHandle, entityId: EntityId, slowWan: number): void {
|
|
|
|
|
const clamped = Math.min(10000, Math.max(0, slowWan));
|
|
|
|
|
const mul = 1 - clamped / 10000;
|
|
|
|
|
const world = battle.session.world;
|
|
|
|
|
if (!world.getComponent(entityId, AttributeComp)) {
|
|
|
|
|
world.addComponent(entityId, new AttributeComp());
|
|
|
|
|
}
|
|
|
|
|
battle.session.attributes.addModifier(entityId, {
|
|
|
|
|
attr: 'move_speed_mul',
|
|
|
|
|
op: 'Mul',
|
|
|
|
|
value: mul,
|
|
|
|
|
source: `${MOVE_SPEED_MOD_GROUP}_${clamped}`,
|
|
|
|
|
group: MOVE_SPEED_MOD_GROUP,
|
|
|
|
|
});
|
|
|
|
|
const move = world.getComponent(entityId, MovementComp);
|
|
|
|
|
if (move) {
|
|
|
|
|
move.speed = Math.max(0, (move.baseSpeed || move.speed) * mul);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let _host: BattleBuffMoveSpeedHost | null = null;
|
|
|
|
|
|
|
|
|
|
/** 全局出征兵移速被动 Host(单局复用) */
|
|
|
|
|
export function getBattleBuffMoveSpeedHost(): BattleBuffMoveSpeedHost {
|
|
|
|
|
if (!_host) _host = new BattleBuffMoveSpeedHost();
|
|
|
|
|
return _host;
|
|
|
|
|
}
|