diff --git a/assets/script/game/map/MissionMonComp.ts b/assets/script/game/map/MissionMonComp.ts index 7ca39dd1..7310c089 100644 --- a/assets/script/game/map/MissionMonComp.ts +++ b/assets/script/game/map/MissionMonComp.ts @@ -3,12 +3,12 @@ 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 { HeroInfo, MonStart } from "../common/config/heroSet"; import { smc } from "../common/SingletonModuleComp"; import { GameEvent } from "../common/config/GameEvent"; -// 导入新的肉鸽配置 -import { BuffConf } from "../common/config/SkillSet"; import {BoxSet } from "../common/config/GameSet"; +import { BossList, BossSpawnCd, MonList, MonType, SpawnBaseCd, SpawnMinCd, SpawnPowerBias, SpawnStageReduce, StageBossGrow, StageDuration, StageGrow, UpType } from "./RogueConfig"; +import { HeroAttrsComp } from "../hero/HeroAttrsComp"; const { ccclass, property } = _decorator; /** 视图层对象 */ @@ -18,42 +18,44 @@ export class MissionMonCompComp extends CCComp { @property({ tooltip: "是否启用调试日志" }) private debugMode: boolean = false; - // 刷怪队列 (主要用于特殊事件插队) + // 刷怪队列(用于插队生成:比如运营活动怪、技能召唤怪、剧情强制怪) + // 约定:队列里的怪会优先于常规刷新处理 private MonQueue: Array<{ uuid: number, level: number, }> = []; - private spawnCount: number = 0; // 召唤计数器 - /** 全局生成顺序计数器,用于层级管理 */ + private spawnCount: number = 0; // 总生成计数,用于控制横向分布位置 + /** 全局生成顺序计数器,用于层级管理(预留) */ private globalSpawnOrder: number = 0; - /** 游戏进行时间(秒) */ + /** 局内战斗运行时间(秒) */ private gameTime: number = 0; - /** 波次刷怪计时器 */ + /** 普通怪刷新计时器 */ private waveTimer: number = 0; - /** 队列处理计时器 */ + /** 插队刷怪处理计时器 */ private queueTimer: number = 0; + /** Boss 刷新计时器 */ + private bossTimer: 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? } + * 接收特殊刷怪事件并入队 + * 事件数据最小结构:{ uuid, level } */ private onSpawnSpecialMonster(event: string, args: any) { if (!args) return; mLogger.log(this.debugMode, 'MissionMonComp', `[MissionMonComp] 收到特殊刷怪指令:`, args); - // 插入队列 this.MonQueue.push({ uuid: args.uuid, level: args.level, }); - // 立即触发一次队列检查 (可选,让 update 尽快处理) + // 让队列在下一帧附近尽快消费,提升事件响应感 this.queueTimer = 1.0; } @@ -61,12 +63,13 @@ export class MissionMonCompComp extends CCComp { } fight_ready(){ + // 仅重置“本组件”刷怪状态,不处理其他系统状态 smc.vmdata.mission_data.mon_num=0 - // 重置生成顺序计数器 this.globalSpawnOrder = 0 this.gameTime = 0 this.waveTimer = 0 this.queueTimer = 0 + this.bossTimer = 0 this.MonQueue = [] this.spawnCount = 0 @@ -74,36 +77,142 @@ export class MissionMonCompComp extends CCComp { } protected update(dt: number): void { + // 统一战斗状态门禁:未开战/暂停/角色死亡阶段均不刷怪 if(!smc.mission.play) return if(smc.mission.pause) return - // 如果英雄死亡(停止怪物行动标志为true),则停止刷怪逻辑 if(smc.mission.stop_mon_action) return; + if(!smc.mission.in_fight) return; - // 累加游戏时间 + // 计时推进:所有“按时间驱动”的曲线都依赖 gameTime this.gameTime += dt; - - + // 刷怪优先级:特殊队列 > 普通怪 > Boss(都满足条件时同帧可连续执行) + this.updateSpecialQueue(dt); + this.updateNormalSpawn(dt); + this.updateBossSpawn(dt); + } + private updateSpecialQueue(dt: number) { + if (this.MonQueue.length <= 0) return; + this.queueTimer += dt; + // 轻微节流,避免同帧内突发大量插队导致瞬间堆怪 + if (this.queueTimer < 0.15) return; + this.queueTimer = 0; + const item = this.MonQueue.shift(); + if (!item) return; + // 特殊怪同样走随机成长类型,保持局内随机性一致 + const upType = this.getRandomUpType(); + this.addMonster(item.uuid, this.spawnCount, BossList.includes(item.uuid), upType); + this.spawnCount += 1; + } + + private updateNormalSpawn(dt: number) { + this.waveTimer += dt; + // 普通怪刷新间隔会随 stage 增长而缩短 + const spawnCd = this.getCurrentSpawnCd(); + if (this.waveTimer < spawnCd) return; + this.waveTimer = 0; + // 先随机怪物类型,再在该类型池内随机具体 uuid + const uuid = this.getRandomNormalMonsterUuid(); + // 每只怪独立抽取成长方案,使同时间段怪群有轻微离散性 + const upType = this.getRandomUpType(); + this.addMonster(uuid, this.spawnCount, false, upType); + this.spawnCount += 1; + } + + private updateBossSpawn(dt: number) { + this.bossTimer += dt; + // Boss 按固定周期出现,不受普通怪 CD 影响 + if (this.bossTimer < BossSpawnCd) return; + this.bossTimer = 0; + const uuid = this.getRandomBossUuid(); + const upType = this.getRandomUpType(); + this.addMonster(uuid, this.spawnCount, true, upType); + this.spawnCount += 1; + } + + private getCurrentStage(): number { + // 每 30 秒提升 1 阶(由配置 StageDuration 控制) + return Math.floor(this.gameTime / StageDuration); + } + + private getCurrentSpawnCd(): number { + const stage = this.getCurrentStage(); + const cd = SpawnBaseCd - stage * SpawnStageReduce; + // 保护下限,避免后期刷新间隔过小打爆性能 + return Math.max(SpawnMinCd, cd); + } + + private getRandomUpType(): UpType { + // 从 StageGrow 的 key 中采样,保证新增配置无需改逻辑 + const keys = Object.keys(StageGrow).map(v => Number(v) as UpType); + const index = Math.floor(Math.random() * keys.length); + return keys[index] ?? UpType.AP1_HP1; + } + + private getRandomNormalMonsterUuid(): number { + // MonType 是常量对象,这里通过值采样拿到怪物类型 id + const typeKeys = Object.keys(MonType).map(k => (MonType as any)[k]).filter(v => typeof v === "number"); + const randomType = typeKeys[Math.floor(Math.random() * typeKeys.length)] as number; + // 如果某类型配置被清空,回退到 AP 类型,避免空池异常 + const pool = MonList[randomType] || MonList[MonType.AP]; + const index = Math.floor(Math.random() * pool.length); + return pool[index]; + } + + private getRandomBossUuid(): number { + // 目前 Boss 池可扩展为多个,先走随机抽取 + const index = Math.floor(Math.random() * BossList.length); + return BossList[index]; + } + + private resolveGrowPair(upType: UpType, isBoss: boolean): [number, number] { + // 普通怪基础成长:StageGrow + const grow = StageGrow[upType] || StageGrow[UpType.AP1_HP1]; + if (!isBoss) return [grow[0], grow[1]]; + // Boss 额外成长:StageBossGrow(在普通成长上叠加) + const bossGrow = StageBossGrow[upType] || StageBossGrow[UpType.AP1_HP1]; + return [grow[0] + bossGrow[0], grow[1] + bossGrow[1]]; + } + + private getSpawnPowerBias(): number { + // 动态难度偏差入口:当前固定读取配置,后续可切到玩家表现驱动 + return SpawnPowerBias; } private addMonster( uuid: number = 1001, i: number = 0, + isBoss: boolean = false, + upType: UpType = UpType.AP1_HP1, ) { + // 创建 ECS 怪物实体 let mon = ecs.getEntity(Monster); let scale = -1; + // 按生成序号做横向错列,减轻重叠感 const x = MonStart.START_X + Math.floor(i / 4) * MonStart.START_I; let y = BoxSet.GAME_LINE; let pos: Vec3 = v3(x, y, 0); - // 递增全局生成顺序 - 溢出保护 + // 递增全局生成顺序,做溢出保护 this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999; - // 生成怪物 - mon.load(pos, scale, uuid, false); + // 先用原始配置创建怪物,再覆盖成长后属性 + mon.load(pos, scale, uuid, isBoss); + const model = mon.get(HeroAttrsComp); + const base = HeroInfo[uuid]; + if (!model || !base) return; + const stage = this.getCurrentStage(); + const grow = this.resolveGrowPair(upType, isBoss); + // 偏差值用于整体系数缩放:1=不变,>1增强,<1减弱 + const bias = Math.max(0.1, this.getSpawnPowerBias()); + // 最终公式:基础值 + 阶段成长,再乘偏差 + model.ap = Math.max(1, Math.floor((base.ap + stage * grow[0]) * bias)); + model.hp_max = Math.max(1, Math.floor((base.hp + stage * grow[1]) * bias)); + // 满血登场,保证 hp/hp_max 一致 + model.hp = model.hp_max; } /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ diff --git a/assets/script/game/map/RogueConfig.ts b/assets/script/game/map/RogueConfig.ts index 8b137891..385ba230 100644 --- a/assets/script/game/map/RogueConfig.ts +++ b/assets/script/game/map/RogueConfig.ts @@ -1 +1,38 @@ +export enum UpType { + AP1_HP1 = 0, //平衡 + HP2 = 1, //强hp + AP2 = 2 //强ap +} +export const StageGrow = { + [UpType.AP1_HP1]: [4,10], + [UpType.HP2]: [2,20], + [UpType.AP2]: [8,0], +} +export const StageBossGrow = { + [UpType.AP1_HP1]: [3,16], + [UpType.HP2]: [1,24], + [UpType.AP2]: [10,4], +} +export const MonType = { + AP: 0, // 近战高功 + SPEED: 1, // 高速贴近 + HP: 2, // 高血皮厚 + //远程攻击 + // +} +export const MonList = { + [MonType.AP]: [5201,5401], // 近战高功 + [MonType.SPEED]: [5301], // 高速贴近 + [MonType.HP]: [5501], // 高血皮厚 + //远程攻击 + // +} +export const BossList = [5701] +export const StageDuration = 30 +export const SpawnBaseCd = 1.6 +export const SpawnMinCd = 0.5 +export const SpawnStageReduce = 0.08 +export const BossSpawnCd = 90 +export const SpawnPowerBias = 1 +