Files
heros/assets/script/game/map/MissionMonComp.ts
walkpan 3f6b94af0e refactor(mission): 优化肉鸽关卡及怪物生成逻辑
- 将出战英雄配置由数组改为单个英雄编号,简化相关接口和数据结构
- 统一出战英雄设置和获取方法,移除冗余多英雄管理逻辑
- 增加怪物生成时的强度倍率参数,支持怪物属性随关卡进度递增调整
- 扩展肉鸽模式配置,实现关卡类型区分及怪物数量动态计算
- 新增随机事件系统,支持事件关卡随机触发宝箱、陷阱、增益、减益等事件
- 优化怪物生成流程,整合怪物配置、等级和强度倍率信息,增强游戏体验
2025-10-19 17:18:22 +08:00

240 lines
8.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator, v3, Vec3 } from "cc";
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 { MonSet } from "../common/config/heroSet";
import { smc } from "../common/SingletonModuleComp";
import { GameEvent } from "../common/config/GameEvent";
// 导入肉鸽配置
import {
getStageMonsterConfigs,
MonsterType,
getStageType,
EventType,
getRandomEvent
} from "./RogueConfig";
import { MonModelComp } from "../hero/MonModelComp";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('MissionMonCompComp')
@ecs.register('MissionMonComp', false)
export class MissionMonCompComp extends CCComp {
// 添加刷怪队列 - 使用新的RogueConfig格式
private monsterQueue: Array<{
uuid: number,
position: number,
type: MonsterType,
level: number,
strengthMultiplier: number
}> = [];
private isSpawning: boolean = false;// 是否正在生成怪物
private spawnInterval: number = 0.1; // 每个怪物生成间隔时间
private spawnTimer: number = 0; // 生成计时器
private spawnCount: number = 0; // 召唤计数器
private pauseInterval: number = 5.0; // 暂停间隔时间5秒
private isPausing: boolean = false; // 是否正在暂停
private currentEvent: EventType | null = null; // 当前关卡的随机事件
private eventProcessed: boolean = false; // 事件是否已处理
onLoad(){
this.on(GameEvent.FightReady,this.fight_ready,this)
this.on(GameEvent.NewWave,this.fight_ready,this)
}
/** 视图层逻辑代码分离演示 */
start() {
// var entity = this.ent as ecs.Entity; // ecs.Entity 可转为当前模块的具体实体对象
// this.on(ModuleEvent.Cmd, this.onHandler, this);
}
fight_ready(){
// console.log("[MissionMonComp]:fight_ready")
smc.vmdata.mission_data.mon_num=0
this.do_mon_wave()
}
protected update(dt: number): void {
if(!smc.mission.play||smc.mission.pause) return
// 处理随机事件
if (this.currentEvent && !this.eventProcessed) {
this.processRandomEvent();
this.eventProcessed = true;
}
// 处理刷怪队列
if (this.monsterQueue.length > 0 && !this.isSpawning) {
this.spawnTimer += dt;
// 检查是否需要暂停每召唤5次后暂停5秒
if (this.isPausing) {
if (this.spawnTimer >= this.pauseInterval) {
// 暂停结束,重置状态
this.isPausing = false;
this.spawnCount = 0;
this.spawnTimer = 0;
// console.log("[MissionMonComp]: 暂停结束,继续召唤怪物");
}
return; // 暂停期间不召唤怪物
}
// 正常召唤间隔
if (this.spawnTimer >= this.spawnInterval) {
this.spawnNextMonster();
this.spawnTimer = 0;
// 检查是否需要进入暂停状态
if (this.spawnCount >= 5) {
this.isPausing = true;
this.spawnTimer = 0; // 重置计时器用于暂停计时
// console.log("[MissionMonComp]: 已召唤5只怪物开始暂停5秒");
}
}
}
}
do_mon_wave(){
// 重置召唤相关状态
this.spawnCount = 0;
this.isPausing = false;
this.spawnTimer = 0;
this.eventProcessed = false;
const currentStage = smc.data.mission;
// 使用新的肉鸽关卡配置
let level=smc.vmdata.mission_data.level
const stageType = getStageType(currentStage,level);
// 检查是否为事件关卡
if (stageType === "event") {
this.currentEvent = getRandomEvent();
} else {
this.currentEvent = null;
}
const monsterConfigs = getStageMonsterConfigs(currentStage,level);
// console.log(`[MissionMonComp]:第${currentStage}关 - ${stageType}类型,怪物数量: ${monsterConfigs.length}`);
this.generateMonstersFromStageConfig(monsterConfigs);
}
// 处理随机事件
private processRandomEvent() {
if (!this.currentEvent) return;
switch (this.currentEvent) {
case EventType.TREASURE:
// 发送获得奖励事件
smc.vmdata.mission_data.gold += 50; // 增加50金币
// 可以触发UI提示
// oops.message.dispatchEvent("event_treasure");
break;
case EventType.TRAP:
// 对玩家造成伤害
// 这里可以实现对玩家英雄造成伤害的逻辑
// oops.message.dispatchEvent("event_trap");
break;
case EventType.BUFF:
// 给玩家增加临时增益效果
// oops.message.dispatchEvent("event_buff");
break;
case EventType.DEBUFF:
// 给玩家增加临时减益效果
// oops.message.dispatchEvent("event_debuff");
break;
}
}
// 根据新的关卡配置生成怪物
private generateMonstersFromStageConfig(monsterConfigs: any[]) {
const currentStage = smc.data.mission;
// 设置怪物总数
// console.log("[MissionMonComp] generateMonstersFromStageConfig",monsterConfigs)
if (!monsterConfigs || monsterConfigs.length === 0) {
console.warn(`[MissionMonComp]:关卡${currentStage}配置中没有怪物信息`);
return;
}
// 为每个怪物配置生成怪物
monsterConfigs.forEach((monsterConfig: any, index: number) => {
const { uuid, type, strengthMultiplier } = monsterConfig;
// 位置循环使用 (0-4)
const position = index % 5;
this.addToStageSpawnQueue(
uuid,
position,
type,
1, // 默认等级1
strengthMultiplier // 强度倍率
);
});
// console.log(`[MissionMonComp]:关卡${currentStage}将生成 ${monsterConfigs.length} 只怪物`);
}
// 添加到关卡刷怪队列 - 使用新的配置格式
private addToStageSpawnQueue(
uuid: number,
position: number,
type: MonsterType,
level: number = 1,
strengthMultiplier: number = 1.0
) {
this.monsterQueue.push({
uuid: uuid,
position: position,
type: type,
level: level,
strengthMultiplier: strengthMultiplier
});
}
// 从队列中生成下一个怪物 - 使用新的配置格式
private spawnNextMonster() {
if (this.monsterQueue.length === 0) return;
const monsterData = this.monsterQueue.shift();
if (monsterData) {
const isBoss = monsterData.type === MonsterType.BOSS;
this.addMonster(
monsterData.uuid,
monsterData.position,
isBoss,
false,
monsterData.level,
monsterData.strengthMultiplier
);
// 增加召唤计数
this.spawnCount++;
// console.log(`[MissionMonComp]: 召唤第${this.spawnCount}只${monsterData.type}怪物,剩余队列: ${this.monsterQueue.length}`);
}
}
private addMonster(
uuid: number = 1001,
i: number = 0,
is_boss: boolean = false,
is_call: boolean = false,
lv: number = 1,
strengthMultiplier: number = 1.0
) {
let mon = ecs.getEntity<Monster>(Monster);
let scale = -1;
let pos: Vec3 = v3(MonSet[i].pos);
// 生成怪物
mon.load(pos,scale,uuid,is_boss,is_call,strengthMultiplier);
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
// this.node.destroy();
}
}