From 941fb50ce201a99d0358e2baac3654da81d547ad Mon Sep 17 00:00:00 2001 From: panw Date: Wed, 18 Mar 2026 09:26:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=88=B7=E6=80=AA):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=9C=BA=E4=B8=8A=E6=80=AA=E7=89=A9=E6=95=B0=E9=87=8F=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E6=8E=A7=E5=88=B6=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 `maxMonsterCount` 和 `resumeMonsterCount` 属性配置怪物数量阈值 - 添加 `stop_spawn_mon` 状态控制刷怪暂停与恢复 - 实现 `syncMonsterSpawnState` 方法周期性同步怪物数量并自动管理刷怪状态 - 在战斗准备时重置刷怪状态,确保每局开始时刷怪正常 --- assets/script/game/map/MissionComp.ts | 40 +++++++++++++++++++++++- assets/script/game/map/MissionMonComp.ts | 2 ++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index 3e0b8ed0..32d5b5a2 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -8,7 +8,7 @@ import { GameEvent } from "../common/config/GameEvent"; import { HeroViewComp } from "../hero/HeroViewComp"; import { UIID } from "../common/config/GameUIConfig"; import { SkillView } from "../skill/SkillView"; -import { FightSet } from "../common/config/GameSet"; +import { FacSet, FightSet } from "../common/config/GameSet"; import { mLogger } from "../common/Logger"; import { Monster } from "../hero/Mon"; import { Skill } from "../skill/Skill"; @@ -25,6 +25,10 @@ export class MissionComp extends CCComp { private debugMode: boolean = false; @property({ tooltip: "是否显示战斗内存观测面板" }) private showMemoryPanel: boolean = true; + @property({ tooltip: "场上怪物上限" }) + private maxMonsterCount: number = 15; + @property({ tooltip: "恢复刷怪阈值" }) + private resumeMonsterCount: number = 10; // VictoryComp:any = null; // reward:number = 0; @@ -64,8 +68,10 @@ export class MissionComp extends CCComp { private heapTrendPerMinMB: number = 0; private heapTrendTimer: number = 0; private heapTrendBaseMB: number = -1; + private monsterCountSyncTimer: number = 0; private readonly heroViewMatcher = ecs.allOf(HeroViewComp); private readonly skillViewMatcher = ecs.allOf(SkillView); + private readonly heroAttrsMatcher = ecs.allOf(HeroAttrsComp); // 记录已触发的特殊刷怪索引 @@ -81,6 +87,7 @@ export class MissionComp extends CCComp { if(!smc.mission.play) return if(smc.mission.pause) return if(smc.mission.in_fight){ + this.syncMonsterSpawnState(dt) if(smc.mission.stop_mon_action) return smc.vmdata.mission_data.fight_time+=dt this.FightTime-=dt @@ -190,9 +197,12 @@ export class MissionComp extends CCComp { smc.mission.play = true; smc.mission.pause = false; smc.mission.stop_mon_action = false; + smc.mission.stop_spawn_mon = false; smc.vmdata.mission_data.in_fight=false smc.vmdata.mission_data.fight_time=0 + smc.vmdata.mission_data.mon_num=0 smc.vmdata.mission_data.level=0 + smc.vmdata.mission_data.mon_max = Math.max(1, Math.floor(this.maxMonsterCount)) this.FightTime=FightSet.FiIGHT_TIME this.rewards=[] // 改为数组,用于存储掉落物品列表 this.revive_times = 1; // 每次任务开始重置复活次数 @@ -207,6 +217,7 @@ export class MissionComp extends CCComp { this.heapTrendPerMinMB = 0; this.heapTrendTimer = 0; this.heapTrendBaseMB = -1; + this.monsterCountSyncTimer = 0; // 重置全局属性加成和主角引用 (确保新一局数据干净) // smc.role = null; @@ -216,6 +227,33 @@ export class MissionComp extends CCComp { // mLogger.log(this.debugMode, 'MissionComp', "局内数据初始化",smc.vmdata.mission_data) } + private getMonsterThresholds(): { max: number; resume: number } { + const max = Math.max(1, Math.floor(this.maxMonsterCount)); + const resume = Math.min(max - 1, Math.max(0, Math.floor(this.resumeMonsterCount))); + return { max, resume }; + } + + private syncMonsterSpawnState(dt: number) { + this.monsterCountSyncTimer += dt; + if (dt > 0 && this.monsterCountSyncTimer < 0.2) return; + this.monsterCountSyncTimer = 0; + let monsterCount = 0; + ecs.query(this.heroAttrsMatcher).forEach(entity => { + const attrs = entity.get(HeroAttrsComp); + if (!attrs || attrs.fac !== FacSet.MON || attrs.is_dead) return; + monsterCount += 1; + }); + smc.vmdata.mission_data.mon_num = monsterCount; + const { max, resume } = this.getMonsterThresholds(); + smc.vmdata.mission_data.mon_max = max; + const stopSpawn = !!smc.mission.stop_spawn_mon; + if (stopSpawn) { + if (monsterCount <= resume) smc.mission.stop_spawn_mon = false; + return; + } + if (monsterCount >= max) smc.mission.stop_spawn_mon = true; + } + private cleanComponents() { // 优化销毁顺序:直接销毁实体,让ECS系统自动处理组件清理 // 这样可以避免在组件reset方法中访问已经被销毁的实体引用 diff --git a/assets/script/game/map/MissionMonComp.ts b/assets/script/game/map/MissionMonComp.ts index 7310c089..1996e180 100644 --- a/assets/script/game/map/MissionMonComp.ts +++ b/assets/script/game/map/MissionMonComp.ts @@ -65,6 +65,7 @@ export class MissionMonCompComp extends CCComp { fight_ready(){ // 仅重置“本组件”刷怪状态,不处理其他系统状态 smc.vmdata.mission_data.mon_num=0 + smc.mission.stop_spawn_mon = false this.globalSpawnOrder = 0 this.gameTime = 0 this.waveTimer = 0 @@ -81,6 +82,7 @@ export class MissionMonCompComp extends CCComp { if(!smc.mission.play) return if(smc.mission.pause) return if(smc.mission.stop_mon_action) return; + if(smc.mission.stop_spawn_mon) return; if(!smc.mission.in_fight) return; // 计时推进:所有“按时间驱动”的曲线都依赖 gameTime