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.
 
 
 
 
AdLike2048/assets/script/ui/BattleGame/BattleGameExtraBossSkill.ts

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;
}
}