refactor(missionMon): 调整怪物登场排布逻辑

将怪物从按X轴均匀分布改为按类型分三排登场,匹配英雄编队镜像布局,高优先级怪物自动占据前排
This commit is contained in:
pan
2026-08-20 17:30:36 +08:00
parent 965b04094d
commit 9a24f0a9a5

View File

@@ -7,7 +7,7 @@
* 2. 战斗开始PhasePrepareEnd 时恢复怪物行动in_fight 前怪物仅原地待命,不会推进/索敌)。 * 2. 战斗开始PhasePrepareEnd 时恢复怪物行动in_fight 前怪物仅原地待命,不会推进/索敌)。
* *
* 关键设计: * 关键设计:
* - 5 只怪在 X∈[100,320] 内按登场序号均匀铺开Boss/小怪同时登场,玩家看清阵容后三选一 * - 怪物按类型落排(近战/Boss→前排、远程/刺客→中排、辅助/召唤→后排),与英雄三排镜像对应
* - 实际推进由统一 MoveComp 在战斗中向敌人移动自然形成,不再使用固定网格点。 * - 实际推进由统一 MoveComp 在战斗中向敌人移动自然形成,不再使用固定网格点。
* - 槽位索引仅用于 monGrid 寻路与 SCastSystem 索敌定位。 * - 槽位索引仅用于 monGrid 寻路与 SCastSystem 索敌定位。
*/ */
@@ -19,8 +19,9 @@ import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/O
import { Monster } from "../hero/Mon"; import { Monster } from "../hero/Mon";
import { smc } from "../common/SingletonModuleComp"; import { smc } from "../common/SingletonModuleComp";
import { GameEvent } from "../common/config/GameEvent"; import { GameEvent } from "../common/config/GameEvent";
import { BoxSet } from "../common/config/GameSet"; import { BoxSet, FightSet } from "../common/config/GameSet";
import { spawningEngine, GeneratedMonster, TestModeConfig, BOSS_COUNT, MINION_COUNT } from "./RogueConfig"; import { MonType } from "../common/config/heroSet";
import { spawningEngine, GeneratedMonster, TestModeConfig } from "./RogueConfig";
import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { MoveComp } from "../hero/MoveComp"; import { MoveComp } from "../hero/MoveComp";
@@ -33,10 +34,23 @@ export class MissionMonCompComp extends CCComp {
/** 怪物出生掉落高度 */ /** 怪物出生掉落高度 */
private static readonly MON_DROP_HEIGHT = 0; private static readonly MON_DROP_HEIGHT = 0;
/** 怪物登场 X 范围下限(靠近英雄侧) */
private static readonly SPAWN_X_MIN = 100; /**
/** 怪物登场 X 范围上限(靠近右侧) */ * 怪物类型 → 编队优先级(与英雄 HRole 枚举值升序一致):
private static readonly SPAWN_X_MAX = 320; * 近战/重型/近战Boss → 0最优先占前排
* 远程/刺客/远程Boss → 1占中排
* 辅助/召唤师 → 2占后排
*/
private static readonly MON_TYPE_PRIORITY: Record<number, number> = {
[MonType.Melee]: 0,
[MonType.Heavy]: 0,
[MonType.MeleeBoss]: 0,
[MonType.Long]: 1,
[MonType.Assassin]: 1,
[MonType.LongBoss]: 1,
[MonType.Support]: 2,
[MonType.Summoner]: 2,
};
/** 槽位基准 Y3行×4列结构仅供 monGrid 寻路与 SCastSystem 索敌定位) */ /** 槽位基准 Y3行×4列结构仅供 monGrid 寻路与 SCastSystem 索敌定位) */
public static readonly MON_POSITIONS: Vec3[] = [ public static readonly MON_POSITIONS: Vec3[] = [
@@ -104,11 +118,16 @@ export class MissionMonCompComp extends CCComp {
smc.vmdata.mission_data.pending_mon_num = this.waveTargetCount; smc.vmdata.mission_data.pending_mon_num = this.waveTargetCount;
// 怪物先行登场:玩家侦查 Boss 组合后再做英雄三选一in_fight 前怪物原地待命,不推进不索敌) // 怪物先行登场:玩家侦查 Boss 组合后再做英雄三选一in_fight 前怪物原地待命,不推进不索敌)
const squad = this.spawnQueue; // 按编队优先级排序后依次登场:近战/Boss(0) → 远程/刺客(1) → 辅助/召唤(2)
const squad = [...this.spawnQueue].sort((a, b) => {
const pa = MissionMonCompComp.MON_TYPE_PRIORITY[a.type] ?? 1;
const pb = MissionMonCompComp.MON_TYPE_PRIORITY[b.type] ?? 1;
return pa - pb;
});
this.spawnQueue = []; this.spawnQueue = [];
smc.vmdata.mission_data.pending_mon_num = 0; smc.vmdata.mission_data.pending_mon_num = 0;
for (const monData of squad) { for (let i = 0; i < squad.length; i++) {
this.addMonsterAtGrid(this.waveSpawnedCount, monData, this.currentWave); this.addMonsterAtGrid(i, squad[i], this.currentWave);
this.waveSpawnedCount++; this.waveSpawnedCount++;
} }
@@ -126,9 +145,24 @@ export class MissionMonCompComp extends CCComp {
// ======================== 怪物生成 ======================== // ======================== 怪物生成 ========================
/**
* 解析怪物出生 X按编队优先级名次映射三排锚点与英雄编队排队逻辑一致
* 名次映射rank0→前排MON_ROW_FRONT_X、rank1→中排MON_ROW_MID_X、rank≥2→后排MON_ROW_BACK_X
* 效果:高优先级类型永远占据更靠前的排;当更高优先级类型插入时,低优先级类型自动向后让位。
*
* @param index 当前怪物在排序后列表中的索引(名次)
* @returns 出生 X 坐标
*/
private resolveSpawnX(index: number): number {
if (index === 0) return FightSet.MON_ROW_FRONT_X;
if (index === 1) return FightSet.MON_ROW_MID_X;
return FightSet.MON_ROW_BACK_X;
}
/** /**
* 在指定位置索引处生成一个怪物 * 在指定位置索引处生成一个怪物
* 5 只怪在 X∈[100,320] 内按登场序号均匀铺开Boss/小怪同时登场直接开打 * 怪物按编队优先级名次落排rank0→前排、rank1→中排、rank≥2→后排
* 与英雄编队排队逻辑一致:高优先级类型永远占更靠前的排,低优先级自动让位。
*/ */
private addMonsterAtGrid( private addMonsterAtGrid(
posIndex: number, posIndex: number,
@@ -139,9 +173,7 @@ export class MissionMonCompComp extends CCComp {
let scale = -1; let scale = -1;
const basePos = MissionMonCompComp.MON_POSITIONS[posIndex % MissionMonCompComp.MON_POSITIONS.length]; const basePos = MissionMonCompComp.MON_POSITIONS[posIndex % MissionMonCompComp.MON_POSITIONS.length];
const spawnX = MissionMonCompComp.SPAWN_X_MIN const spawnX = this.resolveSpawnX(posIndex);
+ (MissionMonCompComp.SPAWN_X_MAX - MissionMonCompComp.SPAWN_X_MIN)
* (posIndex / Math.max(1, BOSS_COUNT + MINION_COUNT - 1));
const landingY = basePos.y; const landingY = basePos.y;
const spawnPos: Vec3 = v3(spawnX, landingY + MissionMonCompComp.MON_DROP_HEIGHT, 0); const spawnPos: Vec3 = v3(spawnX, landingY + MissionMonCompComp.MON_DROP_HEIGHT, 0);
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999; this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999;