- 将Logger类重命名为mLogger以符合命名规范 - 新增error方法用于统一错误输出 - 在多个组件中替换console.log/warn/error为mLogger的对应方法 - 为多个组件添加debugMode属性以控制模块级日志开关 - 新增HeroMasterComp组件框架
214 lines
6.6 KiB
TypeScript
214 lines
6.6 KiB
TypeScript
import { _decorator, v3, Vec3 } from "cc";
|
||
import { mLogger } from "../common/Logger";
|
||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||
import { Monster } from "../hero/Mon";
|
||
import { MonStart } from "../common/config/heroSet";
|
||
import { smc } from "../common/SingletonModuleComp";
|
||
import { GameEvent } from "../common/config/GameEvent";
|
||
// 导入新的肉鸽配置
|
||
import { getCurrentWave, MonType, WaveConfig } from "./RogueConfig";
|
||
import { BuffConf } from "../common/config/SkillSet";
|
||
import { IndexSet, FacSet, BoxSet } from "../common/config/GameSet";
|
||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||
import { Attrs } from "../common/config/HeroAttrs";
|
||
const { ccclass, property } = _decorator;
|
||
|
||
/** 视图层对象 */
|
||
@ccclass('MissionMonCompComp')
|
||
@ecs.register('MissionMonComp', false)
|
||
export class MissionMonCompComp extends CCComp {
|
||
@property({ tooltip: "是否启用调试日志" })
|
||
private debugMode: boolean = false;
|
||
|
||
// 刷怪队列 (主要用于特殊事件插队)
|
||
private MonQueue: Array<{
|
||
uuid: number,
|
||
position: number,
|
||
type: MonType,
|
||
level: number,
|
||
buffs: BuffConf[]
|
||
}> = [];
|
||
|
||
private spawnCount: number = 0; // 召唤计数器
|
||
|
||
/** 全局生成顺序计数器,用于层级管理 */
|
||
private globalSpawnOrder: number = 0;
|
||
|
||
/** 游戏进行时间(秒) */
|
||
private gameTime: number = 0;
|
||
|
||
/** 波次刷怪计时器 */
|
||
private waveTimer: number = 0;
|
||
|
||
/** 队列处理计时器 */
|
||
private queueTimer: number = 0;
|
||
|
||
onLoad(){
|
||
this.on(GameEvent.FightReady,this.fight_ready,this)
|
||
this.on(GameEvent.NewWave,this.fight_ready,this)
|
||
// 监听特殊刷怪事件 (精英/Boss)
|
||
this.on("SpawnSpecialMonster", this.onSpawnSpecialMonster, this);
|
||
}
|
||
|
||
/**
|
||
* 处理特殊刷怪事件
|
||
* @param event 事件名
|
||
* @param args 参数 { uuid, type, level, position?, buffs? }
|
||
*/
|
||
private onSpawnSpecialMonster(event: string, args: any) {
|
||
if (!args) return;
|
||
console.log(`[MissionMonComp] 收到特殊刷怪指令:`, args);
|
||
|
||
// 插入队列
|
||
this.MonQueue.push({
|
||
uuid: args.uuid,
|
||
position: args.position !== undefined ? args.position : 2, // 默认中间
|
||
type: args.type,
|
||
level: args.level,
|
||
buffs: args.buffs || []
|
||
});
|
||
|
||
// 立即触发一次队列检查 (可选,让 update 尽快处理)
|
||
this.queueTimer = 1.0;
|
||
}
|
||
|
||
start() {
|
||
}
|
||
|
||
fight_ready(){
|
||
smc.vmdata.mission_data.mon_num=0
|
||
// 重置生成顺序计数器
|
||
this.globalSpawnOrder = 0
|
||
this.gameTime = 0
|
||
this.waveTimer = 0
|
||
this.queueTimer = 0
|
||
this.MonQueue = []
|
||
this.spawnCount = 0
|
||
|
||
mLogger.log(this.debugMode, 'MissionMonComp', "[MissionMonComp] Starting Wave System (15-min Cycle)");
|
||
}
|
||
|
||
protected update(dt: number): void {
|
||
if(!smc.mission.play) return
|
||
if(smc.mission.pause) return
|
||
// 如果英雄死亡(停止怪物行动标志为true),则停止刷怪逻辑
|
||
if(smc.mission.stop_mon_action) return;
|
||
|
||
// 累加游戏时间
|
||
this.gameTime += dt;
|
||
|
||
// 获取当前波次配置
|
||
const currentWave = getCurrentWave(this.gameTime);
|
||
|
||
// 1. 优先处理特殊怪队列
|
||
if (this.MonQueue.length > 0) {
|
||
this.queueTimer += dt;
|
||
// 队列出怪速度快于普通波次 (0.5秒一只)
|
||
if (this.queueTimer >= 0.5) {
|
||
this.spawnNextFromQueue();
|
||
this.queueTimer = 0;
|
||
}
|
||
}
|
||
|
||
// 2. 处理波次自然刷怪
|
||
this.waveTimer += dt;
|
||
if (this.waveTimer >= currentWave.spawnInterval) {
|
||
this.waveTimer = 0;
|
||
|
||
// 检查同屏数量限制
|
||
if (smc.vmdata.mission_data.mon_num < currentWave.maxActive) {
|
||
this.spawnWaveMonster(currentWave);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 从当前波次配置生成并生成怪物
|
||
*/
|
||
private spawnWaveMonster(wave: WaveConfig) {
|
||
if (!wave.weights || wave.weights.length === 0) return;
|
||
|
||
// 权重随机算法
|
||
const totalWeight = wave.weights.reduce((sum, item) => sum + item.weight, 0);
|
||
let random = Math.random() * totalWeight;
|
||
let selectedUuid = wave.weights[0].uuid;
|
||
let selectedType = wave.weights[0].type || MonType.NORMAL;
|
||
|
||
for (const item of wave.weights) {
|
||
random -= item.weight;
|
||
if (random <= 0) {
|
||
selectedUuid = item.uuid;
|
||
selectedType = item.type || MonType.NORMAL;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 随机位置 (0-4)
|
||
const position = Math.floor(Math.random() * 5);
|
||
|
||
// 等级随时间增长 (每分钟+1级)
|
||
const level = Math.floor(this.gameTime / 60) + 1;
|
||
|
||
this.addMonster(
|
||
selectedUuid,
|
||
position,
|
||
selectedType,
|
||
level,
|
||
[],
|
||
this.gameTime
|
||
);
|
||
|
||
this.spawnCount++;
|
||
}
|
||
|
||
/**
|
||
* 从队列中生成下一个怪物
|
||
*/
|
||
private spawnNextFromQueue() {
|
||
if (this.MonQueue.length === 0) return;
|
||
|
||
const monsterData = this.MonQueue.shift();
|
||
if (monsterData) {
|
||
this.addMonster(
|
||
monsterData.uuid,
|
||
monsterData.position,
|
||
monsterData.type,
|
||
monsterData.level,
|
||
monsterData.buffs,
|
||
this.gameTime
|
||
);
|
||
this.spawnCount++;
|
||
}
|
||
}
|
||
|
||
private addMonster(
|
||
uuid: number = 1001,
|
||
i: number = 0,
|
||
monType: number = 0,
|
||
lv: number = 1,
|
||
buffs: BuffConf[] = [],
|
||
gameTime: number = 0
|
||
) {
|
||
let mon = ecs.getEntity<Monster>(Monster);
|
||
let scale = -1;
|
||
|
||
const x = MonStart.START_X + Math.floor(i / 4) * MonStart.START_I;
|
||
let y = BoxSet.GAME_LINE;
|
||
let lane = 0;
|
||
|
||
let pos: Vec3 = v3(x, y, 0);
|
||
|
||
// 递增全局生成顺序 - 溢出保护
|
||
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999;
|
||
|
||
// 生成怪物
|
||
mon.load(pos, scale, uuid, lv, monType, buffs, false, lane, this.globalSpawnOrder, gameTime);
|
||
}
|
||
|
||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||
reset() {
|
||
// this.node.destroy();
|
||
}
|
||
}
|