Files
pixelheros/assets/script/game/map/MissionMonComp.ts
walkpan ffa6bbec6f feat(战斗系统): 扩展为4条战斗线路并调整相关配置
- 将战斗线路从2条扩展为4条,新增LINE3和LINE4
- 修改Monster生成逻辑以支持4条线路
- 更新英雄刘邦的技能配置
- 调整基础攻击技能消耗为0
- 更新地图预制体以包含新增线路
2026-01-02 00:03:07 +08:00

283 lines
9.8 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 { MonStart } from "../common/config/heroSet";
import { smc } from "../common/SingletonModuleComp";
import { GameEvent } from "../common/config/GameEvent";
// 导入肉鸽配置
import { getStageMonConfigs, MonType, generateMonstersFromBudget } from "./RogueConfig";
import { BuffConf } from "../common/config/SkillSet";
import { IndexSet, FacSet } 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 {
// 添加刷怪队列 - 使用新的RogueConfig格式
private MonQueue: Array<{
uuid: number,
position: number,
type: MonType,
level: number,
buffs: BuffConf[]
}> = [];
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 eventProcessed: boolean = false; // 事件是否已处理
/** 全局生成顺序计数器,用于层级管理 */
private globalSpawnOrder: number = 0;
/** 游戏进行时间(秒) */
private gameTime: number = 0;
/** 刷怪逻辑计时器(每秒执行一次) */
private spawnLogicTimer: number = 0;
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.globalSpawnOrder = 0
this.do_mon_wave()
}
protected update(dt: number): void {
if(!smc.mission.play||smc.mission.pause) return
// 累加游戏时间
this.gameTime += dt;
// ==========================================
// 新增:每秒执行一次刷怪逻辑 (Threat Budget)
// ==========================================
this.spawnLogicTimer += dt;
if (this.spawnLogicTimer >= 1.0) {
this.spawnLogicTimer = 0;
// 获取英雄血量比例
const hpRatio = this.getHeroHpRatio();
// 生成怪物
const newMonsters = generateMonstersFromBudget(this.gameTime, hpRatio);
// 添加到队列
newMonsters.forEach(mon => {
this.addToStageSpawnQueue(
mon.uuid,
mon.position !== undefined ? mon.position : 0,
mon.type,
mon.level,
mon.buffs || []
);
});
}
// 处理随机事件
// 处理刷怪队列
if (this.MonQueue.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 cStage = smc.data.mission;
// // 使用新的肉鸽关卡配置
// let level=smc.vmdata.mission_data.level
// const monsConf = getStageMonConfigs(cStage);
// // console.log(`[MissionMonComp]:第${cStage}关 - ${stageType}类型,怪物数量: ${monsConf.length}`);
// const monsConfFiltered = monsConf.filter((mon: any, index) => index === 0);
// this.generateMonsters(monsConfFiltered);
console.log("[MissionMonComp] Starting Threat Budget Wave System");
}
/**
* 获取英雄血量比例
*/
private getHeroHpRatio(): number {
// 查询带有 HeroAttrsComp 的实体
// 注意:这里假设只有一个英雄,且性能允许每秒查询一次
const entities = ecs.query(ecs.allOf(HeroAttrsComp));
for (const e of entities) {
const attrs = e.get(HeroAttrsComp);
if (attrs && attrs.fac === FacSet.HERO) {
const maxHp = attrs.Attrs[Attrs.HP_MAX] || 1;
return attrs.hp / maxHp;
}
}
return 1.0; // 默认满血
}
// 根据新的关卡配置生成怪物
private generateMonsters(monsConf: any[]) {
const cStage = smc.data.mission;
// 设置怪物总数
// console.log("[MissionMonComp] generateMonsters",monsConf)
if (!monsConf || monsConf.length === 0) {
console.warn(`[MissionMonComp]:关卡${cStage}配置中没有怪物信息`);
return;
}
// 为每个怪物配置生成怪物
monsConf.forEach((mon: any, index: number) => {
const { uuid, type, level, buffs, position } = mon;
// 使用配置中的位置,如果没有则使用索引
const spawnPosition = position !== undefined ? position : (index % 5);
this.addToStageSpawnQueue(
uuid,
spawnPosition,
type,
level,
buffs
);
});
// console.log(`[MissionMonComp]:关卡${cStage}将生成 ${monsConf.length} 只怪物`);
}
// 添加到关卡刷怪队列 - 使用新的配置格式
private addToStageSpawnQueue(
uuid: number,
position: number,
type: MonType = MonType.NORMAL,
level: number = 1,
buffs: BuffConf[] = []
) {
this.MonQueue.push({
uuid: uuid,
position: position,
type: type,
level: level,
buffs: buffs
});
}
// 从队列中生成下一个怪物 - 使用新的配置格式
private spawnNextMonster() {
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++;
// console.log(`[MissionMonComp]: 召唤第${this.spawnCount}只${monsterData.type}怪物,剩余队列: ${this.MonQueue.length}`);
}
}
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;
// 使用 MonStart 计算怪物出生位置:
// x 从 START_X 开始,按 START_I 的间隔递增;
// y 在线路之间交替0->SLINE_1, 1->SLINE_2, 2->SLINE_3, 3->SLINE_4
const x = MonStart.START_X + Math.floor(i / 4) * MonStart.START_I;
let y = MonStart.SLINE_1;
let lane = 0;
switch (i % 4) {
case 0:
y = MonStart.SLINE_1;
lane = 0;
break;
case 1:
y = MonStart.SLINE_2;
lane = 1;
break;
case 2:
y = MonStart.SLINE_3;
lane = 2;
break;
case 3:
y = MonStart.SLINE_4;
lane = 3;
break;
}
let pos: Vec3 = v3(x, y, 0);
// 递增全局生成顺序 - 🔥 添加溢出保护
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999; // 防止无限增长在999处循环重置
// 生成怪物,传递线路和生成顺序
mon.load(pos, scale, uuid, lv, monType, buffs, false, lane, this.globalSpawnOrder, gameTime);
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
// this.node.destroy();
}
}