|
|
|
|
import type { BattleSession } from 'db://assets/mx/module/battle';
|
|
|
|
|
import { AttributeComp, CombatComp } from 'db://assets/mx/module/battle/ecs/Components';
|
|
|
|
|
import type { EntityId } from 'db://assets/mx/module/ecs';
|
|
|
|
|
import { BattleBuffCarryStore } from '../../manager/battleBuff/BattleBuffCarryStore';
|
|
|
|
|
import {
|
|
|
|
|
resolveCarriedBothAttackSpeed,
|
|
|
|
|
resolveCarriedUnitAttackSpeedWan,
|
|
|
|
|
} from '../../manager/battleBuff/BattleBuffPassiveSkillUtil';
|
|
|
|
|
import type { ProjectBattleHandle } from '../runtime/BattleRuntime';
|
|
|
|
|
import { AI_PLAYER_ID } from '../ai/runtime/AiCampArea';
|
|
|
|
|
|
|
|
|
|
/** 被动攻击单位攻速 modifier 分组 */
|
|
|
|
|
const UNIT_ASPD_MOD_GROUP = 'battle_buff_unit_aspd';
|
|
|
|
|
|
|
|
|
|
/** 单玩家攻速万分比累加 */
|
|
|
|
|
type PlayerAspd = {
|
|
|
|
|
/** playerId */
|
|
|
|
|
playerId: number;
|
|
|
|
|
/** 万分比 */
|
|
|
|
|
bonusWan: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 被动 functiontype=3 攻速符 + functiontype=7 鏖战册:携带方场上单位攻速。
|
|
|
|
|
*/
|
|
|
|
|
export class BattleBuffUnitAttackSpeedHost {
|
|
|
|
|
private _battle: ProjectBattleHandle | null = null;
|
|
|
|
|
private readonly _bonuses: PlayerAspd[] = [];
|
|
|
|
|
|
|
|
|
|
/** 绑定本局并对已有攻击单位施加攻速加成 */
|
|
|
|
|
bind(battle: ProjectBattleHandle): void {
|
|
|
|
|
this.unbind();
|
|
|
|
|
this._battle = battle;
|
|
|
|
|
this._bonuses.length = 0;
|
|
|
|
|
this._accumulateCarrier(battle.localPlayerId);
|
|
|
|
|
this._accumulateCarrier(AI_PLAYER_ID);
|
|
|
|
|
if (this._bonuses.length <= 0) return;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < this._bonuses.length; i++) {
|
|
|
|
|
const player = battle.getPlayer(this._bonuses[i].playerId);
|
|
|
|
|
if (!player) continue;
|
|
|
|
|
const deployed = player.deployedUnits;
|
|
|
|
|
for (let u = 0; u < deployed.length; u++) {
|
|
|
|
|
this.refreshEntity(battle.session, deployed[u], this._bonuses[i].playerId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 解除绑定 */
|
|
|
|
|
unbind(): void {
|
|
|
|
|
this._battle = null;
|
|
|
|
|
this._bonuses.length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 塔部署/升级后补施加被动攻速。
|
|
|
|
|
* @param session 会话
|
|
|
|
|
* @param entityId 实体
|
|
|
|
|
* @param ownerPlayerId 塔归属;缺省用本机
|
|
|
|
|
*/
|
|
|
|
|
refreshEntity(session: BattleSession, entityId: EntityId, ownerPlayerId?: number): void {
|
|
|
|
|
if (this._bonuses.length <= 0) return;
|
|
|
|
|
const pid = ownerPlayerId != null
|
|
|
|
|
? Math.max(0, Math.floor(Number(ownerPlayerId) || 0))
|
|
|
|
|
: (this._battle?.localPlayerId ?? 0);
|
|
|
|
|
for (let i = 0; i < this._bonuses.length; i++) {
|
|
|
|
|
if (this._bonuses[i].playerId !== pid) continue;
|
|
|
|
|
this._applyModifier(session, entityId, this._bonuses[i].bonusWan, pid);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 汇总携带方攻速符与鏖战册(己方/对方分量)。
|
|
|
|
|
* @param carrierPlayerId 携带方 playerId
|
|
|
|
|
*/
|
|
|
|
|
private _accumulateCarrier(carrierPlayerId: number): void {
|
|
|
|
|
const passives = BattleBuffCarryStore.getPassives(carrierPlayerId);
|
|
|
|
|
const unitAspd = resolveCarriedUnitAttackSpeedWan(passives);
|
|
|
|
|
if (unitAspd.active && unitAspd.bonusWan > 0) {
|
|
|
|
|
this._addBonusWan(carrierPlayerId, unitAspd.bonusWan);
|
|
|
|
|
}
|
|
|
|
|
const both = resolveCarriedBothAttackSpeed(passives);
|
|
|
|
|
if (!both.active) return;
|
|
|
|
|
if (both.selfWan !== 0) {
|
|
|
|
|
this._addBonusWan(carrierPlayerId, both.selfWan);
|
|
|
|
|
}
|
|
|
|
|
const opponentId = this._resolveOpponentPlayerId(carrierPlayerId);
|
|
|
|
|
if (opponentId >= 0 && both.enemyWan !== 0) {
|
|
|
|
|
this._addBonusWan(opponentId, both.enemyWan);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 双人对战对手 id。
|
|
|
|
|
* @param playerId 当前玩家
|
|
|
|
|
*/
|
|
|
|
|
private _resolveOpponentPlayerId(playerId: number): number {
|
|
|
|
|
const battle = this._battle;
|
|
|
|
|
if (!battle) return -1;
|
|
|
|
|
if (playerId === battle.localPlayerId) return AI_PLAYER_ID;
|
|
|
|
|
if (playerId === AI_PLAYER_ID) return battle.localPlayerId;
|
|
|
|
|
return playerId === 0 ? AI_PLAYER_ID : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 累加某 player 槽位攻速万分比。
|
|
|
|
|
* @param playerId 玩家
|
|
|
|
|
* @param wan 万分比
|
|
|
|
|
*/
|
|
|
|
|
private _addBonusWan(playerId: number, wan: number): void {
|
|
|
|
|
if (wan === 0) return;
|
|
|
|
|
for (let i = 0; i < this._bonuses.length; i++) {
|
|
|
|
|
if (this._bonuses[i].playerId !== playerId) continue;
|
|
|
|
|
this._bonuses[i].bonusWan += wan;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this._bonuses.push({ playerId, bonusWan: wan });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _applyModifier(session: BattleSession, entityId: EntityId, bonusWan: number, playerId: number): void {
|
|
|
|
|
if (bonusWan === 0) return;
|
|
|
|
|
const world = session.world;
|
|
|
|
|
if (!world.isAlive(entityId)) return;
|
|
|
|
|
if (!world.getComponent(entityId, CombatComp)) return;
|
|
|
|
|
|
|
|
|
|
if (!world.getComponent(entityId, AttributeComp)) {
|
|
|
|
|
world.addComponent(entityId, new AttributeComp());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
session.attributes.addModifier(entityId, {
|
|
|
|
|
attr: 'aspd_add',
|
|
|
|
|
op: 'Add',
|
|
|
|
|
value: bonusWan,
|
|
|
|
|
source: `${UNIT_ASPD_MOD_GROUP}_${playerId}`,
|
|
|
|
|
group: UNIT_ASPD_MOD_GROUP,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let _host: BattleBuffUnitAttackSpeedHost | null = null;
|
|
|
|
|
|
|
|
|
|
/** 全局攻击单位攻速被动 Host(单局复用) */
|
|
|
|
|
export function getBattleBuffUnitAttackSpeedHost(): BattleBuffUnitAttackSpeedHost {
|
|
|
|
|
if (!_host) _host = new BattleBuffUnitAttackSpeedHost();
|
|
|
|
|
return _host;
|
|
|
|
|
}
|