You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
5.1 KiB
123 lines
5.1 KiB
import { BattlePhase } from 'db://assets/mx/module/battle';
|
|
import { LevelWaveParser, NO_BOSS } from '../../battle/config/LevelWaveParser';
|
|
import { parseMonsterUnitDefId } from '../../battle/config/MonsterHpCalculator';
|
|
import { TableBattleConfigProvider } from '../../battle/config/TableBattleConfigProvider';
|
|
import type { ProjectBattleHandle } from '../../battle/runtime/BattleRuntime';
|
|
import { TableNames } from '../../game/ConfigTableData';
|
|
import { MonsterDataManager, MonsterType } from '../../manager/MonsterDataManager';
|
|
|
|
/** 万神幡:从己方出怪口额外召唤关卡 Boss */
|
|
export class BattleGameExtraBossSkill {
|
|
/**
|
|
* 万神幡动画播完后:从当前关卡 boss 池随机 1 个 Boss,经己方出怪口额外出兵。
|
|
* @param battle 战斗
|
|
* @param ownerPlayerId 施放方;省略则用 battle.player
|
|
* @returns 是否已成功创建实体
|
|
*/
|
|
static trySummon(battle: ProjectBattleHandle, ownerPlayerId?: number): boolean {
|
|
if (NO_BOSS) {
|
|
console.log('[BattleGameExtraBossSkill] 调试屏蔽 Boss');
|
|
return false;
|
|
}
|
|
if (battle.session.phase !== BattlePhase.COMBAT) {
|
|
console.log('[BattleGameExtraBossSkill] 仅战斗阶段可召唤 Boss');
|
|
return false;
|
|
}
|
|
|
|
const levelRow = gg.data.table.getTableData<ITableLevel>(TableNames.Level, battle.LevelConfigId);
|
|
if (!levelRow) {
|
|
console.log('[BattleGameExtraBossSkill] Level 缺失', battle.LevelConfigId);
|
|
return false;
|
|
}
|
|
|
|
const bossIds = LevelWaveParser.collectUniqueBossMonsterIds(levelRow.boss);
|
|
if (bossIds.length <= 0) {
|
|
console.log('[BattleGameExtraBossSkill] 关卡无 Boss 配置', battle.LevelConfigId);
|
|
return false;
|
|
}
|
|
|
|
const pickIdx = battle.session.rng.int(0, bossIds.length - 1);
|
|
const monsterId = bossIds[pickIdx];
|
|
const row = MonsterDataManager.getMonsterDataById(monsterId);
|
|
if (!row) {
|
|
console.log('[BattleGameExtraBossSkill] Monster 缺失', monsterId);
|
|
return false;
|
|
}
|
|
if (row.type !== MonsterType.Boss) {
|
|
console.log('[BattleGameExtraBossSkill] 非 Boss 类型,仍尝试召唤', monsterId, row.type);
|
|
}
|
|
|
|
const ownerId = ownerPlayerId != null
|
|
? Math.max(0, Math.floor(Number(ownerPlayerId) || 0))
|
|
: (battle.player?.playerId ?? 0);
|
|
const route = BattleGameExtraBossSkill._resolveSpawnRoute(ownerId);
|
|
const difficultyRow = BattleGameExtraBossSkill._resolveCurrentWaveDifficultyRow(battle, route.spawnPort);
|
|
const config = gg.battle.config as TableBattleConfigProvider;
|
|
const unitDefId = config.ensureSpawnMonsterDef(monsterId, route.spawnPort, difficultyRow);
|
|
|
|
const skin = MonsterDataManager.resolveBattleSpineSkin(row, route.enemyCamp);
|
|
const entity = battle.session.spawner.spawnExtraEnemy(
|
|
unitDefId,
|
|
route.spawnPort,
|
|
route.targetPlayerId,
|
|
skin || undefined,
|
|
);
|
|
if (entity == null) return false;
|
|
|
|
console.log(
|
|
`[BattleGameExtraBossSkill] 召唤 Boss id=${monsterId} port=${route.spawnPort}`
|
|
+ ` target=${route.targetPlayerId} unitDef=${unitDefId}`,
|
|
);
|
|
return true;
|
|
}
|
|
|
|
/** 本机从 spawnPoint_2 攻 AI;AI 从 spawnPoint_1 攻本机 */
|
|
private static _resolveSpawnRoute(ownerPlayerId: number): {
|
|
spawnPort: number;
|
|
targetPlayerId: number;
|
|
enemyCamp: boolean;
|
|
} {
|
|
if (ownerPlayerId === 0) {
|
|
return { spawnPort: 2, targetPlayerId: 1, enemyCamp: false };
|
|
}
|
|
return { spawnPort: 1, targetPlayerId: 0, enemyCamp: true };
|
|
}
|
|
|
|
/** 当前波次对应难度行(与营召唤一致,取本出口首段) */
|
|
private static _resolveCurrentWaveDifficultyRow(battle: ProjectBattleHandle, spawnPort: number): number {
|
|
const waves = battle.session.levelDef?.waves;
|
|
if (!waves?.length) {
|
|
console.log('[BattleGameExtraBossSkill] 无波次配置,难度行兜底 1');
|
|
return 1;
|
|
}
|
|
|
|
let wi = battle.session.spawner.waveIndex;
|
|
if (wi < 0) wi = 0;
|
|
if (wi >= waves.length) wi = waves.length - 1;
|
|
|
|
const wave = waves[wi];
|
|
let portPlan: (typeof waves)[number]['ports'][number] | null = null;
|
|
for (let i = 0; i < (wave.ports?.length ?? 0); i++) {
|
|
if (wave.ports[i].port === spawnPort) {
|
|
portPlan = wave.ports[i];
|
|
break;
|
|
}
|
|
}
|
|
if (!portPlan?.segments?.length) {
|
|
portPlan = wave.ports?.[0] ?? null;
|
|
}
|
|
const seg = portPlan?.segments?.[0];
|
|
if (!seg) {
|
|
console.log('[BattleGameExtraBossSkill] 波次无出怪段,难度行兜底', wi + 1);
|
|
return wi + 1;
|
|
}
|
|
|
|
const fromSeg = Math.max(1, Math.floor(Number(seg.difficultyRow) || 0));
|
|
if (fromSeg > 0) return fromSeg;
|
|
|
|
const parsed = parseMonsterUnitDefId(seg.unitDefId);
|
|
if (parsed?.difficultyRow) return Math.max(1, parsed.difficultyRow);
|
|
|
|
return wi + 1;
|
|
}
|
|
}
|
|
|