|
|
|
|
import type { Player } from '../game/Player';
|
|
|
|
|
import { BattleBuffCarryStore } from '../manager/battleBuff/BattleBuffCarryStore';
|
|
|
|
|
import { BattleBuffSelectService } from '../manager/battleBuff/BattleBuffSelectService';
|
|
|
|
|
import { createBattleRuntime, type ProjectBattleHandle } from './runtime/BattleRuntime';
|
|
|
|
|
import { TableBattleConfigProvider } from './config/TableBattleConfigProvider';
|
|
|
|
|
import { BattleUiPauseGate } from './BattleUiPauseGate';
|
|
|
|
|
import { installAtkDebugHooks } from './debug/AtkDebugLog';
|
|
|
|
|
import type { IBattleService } from './IBattleService';
|
|
|
|
|
import type {
|
|
|
|
|
BattleDeployParams,
|
|
|
|
|
BattleStartParams,
|
|
|
|
|
IBattleRuntimeHandle,
|
|
|
|
|
} from './types/ProjectBattleTypes';
|
|
|
|
|
|
|
|
|
|
/** 战斗模块实现:对局生命周期,由 gg.battle 持有单实例 */
|
|
|
|
|
export class BattleService implements IBattleService {
|
|
|
|
|
readonly config = new TableBattleConfigProvider();
|
|
|
|
|
|
|
|
|
|
private _match: ProjectBattleHandle | null = null;
|
|
|
|
|
|
|
|
|
|
get match(): IBattleRuntimeHandle | null {
|
|
|
|
|
return this._match;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get localPlayer() {
|
|
|
|
|
return this._match?.player;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get players(): readonly Player[] {
|
|
|
|
|
return this._match?.players ?? [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get remotePlayer() {
|
|
|
|
|
return this._match?.remotePlayer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
init(): void {
|
|
|
|
|
this.config.loadStaticTables();
|
|
|
|
|
installAtkDebugHooks();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start(params: BattleStartParams): IBattleRuntimeHandle | null {
|
|
|
|
|
installAtkDebugHooks();
|
|
|
|
|
this.end();
|
|
|
|
|
BattleBuffCarryStore.clear();
|
|
|
|
|
BattleBuffSelectService.resetAll();
|
|
|
|
|
this._seedGmCarryBuffs(params.localPlayerId ?? 0);
|
|
|
|
|
const runtime = createBattleRuntime(params);
|
|
|
|
|
if (!runtime) {
|
|
|
|
|
console.error(`[BattleService] start failed level=${params.levelId} rank=${params.playerRankId} opp=${params.opponentRankId}`);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
this._match = runtime;
|
|
|
|
|
return runtime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GM 词条:开战 clear 后按 gg.game.gmCarryBuffIds 灌入本机 CarryStore。
|
|
|
|
|
* @param localPlayerId 本机槽位
|
|
|
|
|
*/
|
|
|
|
|
private _seedGmCarryBuffs(localPlayerId: number): void {
|
|
|
|
|
const ids = gg.game.gmCarryBuffIds;
|
|
|
|
|
if (!ids?.length) return;
|
|
|
|
|
const pid = Math.max(0, Math.floor(Number(localPlayerId) || 0));
|
|
|
|
|
let ok = 0;
|
|
|
|
|
for (let i = 0; i < ids.length; i++) {
|
|
|
|
|
const parsed = BattleBuffCarryStore.appendBuffId(pid, ids[i]);
|
|
|
|
|
if (parsed) ok++;
|
|
|
|
|
else console.warn('[BattleService] GM 词条灌入失败', ids[i]);
|
|
|
|
|
}
|
|
|
|
|
console.log(`[BattleService] GM 词条灌入 player=${pid} count=${ok}/${ids.length}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
end(): void {
|
|
|
|
|
BattleUiPauseGate.clear();
|
|
|
|
|
const levelId = this._match?.levelId;
|
|
|
|
|
this._match?.destroy();
|
|
|
|
|
this._match = null;
|
|
|
|
|
if (levelId) {
|
|
|
|
|
this.config.releaseBattleSession(levelId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tick(dt: number): void {
|
|
|
|
|
this._match?.tick(dt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deploy(params: BattleDeployParams): boolean {
|
|
|
|
|
return this._match?.deploy(params) ?? false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
startCombat(): void {
|
|
|
|
|
this._match?.startCombat();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
startPrep(): void {
|
|
|
|
|
this._match?.startPrep();
|
|
|
|
|
}
|
|
|
|
|
}
|