diff --git a/assets/resources/gui/role_controller.prefab b/assets/resources/gui/role_controller.prefab index 3879baac..47e8f343 100644 --- a/assets/resources/gui/role_controller.prefab +++ b/assets/resources/gui/role_controller.prefab @@ -22,26 +22,26 @@ "__id__": 2 }, { - "__id__": 272 + "__id__": 276 }, { - "__id__": 281 + "__id__": 285 } ], "_active": true, "_components": [ - { - "__id__": 293 - }, - { - "__id__": 295 - }, { "__id__": 297 + }, + { + "__id__": 299 + }, + { + "__id__": 301 } ], "_prefab": { - "__id__": 299 + "__id__": 303 }, "_lpos": { "__type__": "cc.Vec3", @@ -93,18 +93,18 @@ ], "_active": true, "_components": [ - { - "__id__": 265 - }, - { - "__id__": 267 - }, { "__id__": 269 + }, + { + "__id__": 271 + }, + { + "__id__": 273 } ], "_prefab": { - "__id__": 271 + "__id__": 275 }, "_lpos": { "__type__": "cc.Vec3", @@ -6095,28 +6095,89 @@ "__id__": 1 }, "mountedChildren": [], - "mountedComponents": [], - "propertyOverrides": [ + "mountedComponents": [ { "__id__": 260 - }, - { - "__id__": 262 - }, - { - "__id__": 263 - }, + } + ], + "propertyOverrides": [ { "__id__": 264 + }, + { + "__id__": 266 + }, + { + "__id__": 267 + }, + { + "__id__": 268 } ], "removedComponents": [] }, { - "__type__": "CCPropertyOverrideInfo", + "__type__": "cc.MountedComponentsInfo", "targetInfo": { "__id__": 261 }, + "components": [ + { + "__id__": 262 + } + ] + }, + { + "__type__": "cc.TargetInfo", + "localID": [ + "f1ya2LoYBB547vP13Ydezp" + ] + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "__editorExtras__": { + "mountedRoot": { + "__id__": 257 + } + }, + "node": { + "__id__": 257 + }, + "_enabled": true, + "__prefab": { + "__id__": 263 + }, + "_alignFlags": 2, + "_target": null, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_horizontalCenter": 0, + "_verticalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_alignMode": 2, + "_lockFlags": 0, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "bcCrVWMRBOaLOq1wdUZD1Y" + }, + { + "__type__": "CCPropertyOverrideInfo", + "targetInfo": { + "__id__": 265 + }, "propertyPath": [ "_name" ], @@ -6131,7 +6192,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 261 + "__id__": 265 }, "propertyPath": [ "_lpos" @@ -6139,14 +6200,14 @@ "value": { "__type__": "cc.Vec3", "x": -143.895, - "y": 622.066, + "y": 640, "z": 0 } }, { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 261 + "__id__": 265 }, "propertyPath": [ "_lrot" @@ -6162,7 +6223,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 261 + "__id__": 265 }, "propertyPath": [ "_euler" @@ -6184,7 +6245,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 266 + "__id__": 270 }, "_contentSize": { "__type__": "cc.Size", @@ -6212,7 +6273,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 268 + "__id__": 272 }, "_alignFlags": 21, "_target": null, @@ -6248,7 +6309,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 270 + "__id__": 274 }, "home_btn": { "__id__": 45 @@ -6285,14 +6346,14 @@ "__id__": 1 }, "_prefab": { - "__id__": 273 + "__id__": 277 }, "__editorExtras__": {} }, { "__type__": "cc.PrefabInfo", "root": { - "__id__": 272 + "__id__": 276 }, "asset": { "__uuid__": "26bff847-cd29-48a5-bbfa-c3e2dbda688d", @@ -6300,7 +6361,7 @@ }, "fileId": "5a9CMsVQhKP5Y+UJfTKPbx", "instance": { - "__id__": 274 + "__id__": 278 }, "targetOverrides": null }, @@ -6313,20 +6374,20 @@ "mountedChildren": [], "mountedComponents": [], "propertyOverrides": [ - { - "__id__": 275 - }, - { - "__id__": 277 - }, - { - "__id__": 278 - }, { "__id__": 279 }, { - "__id__": 280 + "__id__": 281 + }, + { + "__id__": 282 + }, + { + "__id__": 283 + }, + { + "__id__": 284 } ], "removedComponents": [] @@ -6334,7 +6395,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 276 + "__id__": 280 }, "propertyPath": [ "_name" @@ -6350,7 +6411,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 276 + "__id__": 280 }, "propertyPath": [ "_lpos" @@ -6365,7 +6426,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 276 + "__id__": 280 }, "propertyPath": [ "_lrot" @@ -6381,7 +6442,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 276 + "__id__": 280 }, "propertyPath": [ "_euler" @@ -6396,7 +6457,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 276 + "__id__": 280 }, "propertyPath": [ "_active" @@ -6410,14 +6471,14 @@ "__id__": 1 }, "_prefab": { - "__id__": 282 + "__id__": 286 }, "__editorExtras__": {} }, { "__type__": "cc.PrefabInfo", "root": { - "__id__": 281 + "__id__": 285 }, "asset": { "__uuid__": "56aee962-4a5e-45ae-a779-999444d06d18", @@ -6425,7 +6486,7 @@ }, "fileId": "cboM54s0hM07XCtrpFp0/b", "instance": { - "__id__": 283 + "__id__": 287 }, "targetOverrides": null }, @@ -6438,26 +6499,26 @@ "mountedChildren": [], "mountedComponents": [], "propertyOverrides": [ - { - "__id__": 284 - }, - { - "__id__": 286 - }, - { - "__id__": 287 - }, { "__id__": 288 }, { - "__id__": 289 + "__id__": 290 }, { "__id__": 291 }, { "__id__": 292 + }, + { + "__id__": 293 + }, + { + "__id__": 295 + }, + { + "__id__": 296 } ], "removedComponents": [] @@ -6465,7 +6526,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 285 + "__id__": 289 }, "propertyPath": [ "_name" @@ -6481,7 +6542,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 285 + "__id__": 289 }, "propertyPath": [ "_lpos" @@ -6496,7 +6557,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 285 + "__id__": 289 }, "propertyPath": [ "_lrot" @@ -6512,7 +6573,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 285 + "__id__": 289 }, "propertyPath": [ "_euler" @@ -6527,7 +6588,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 290 + "__id__": 294 }, "propertyPath": [ "_top" @@ -6543,7 +6604,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 290 + "__id__": 294 }, "propertyPath": [ "_alignFlags" @@ -6553,7 +6614,7 @@ { "__type__": "CCPropertyOverrideInfo", "targetInfo": { - "__id__": 290 + "__id__": 294 }, "propertyPath": [ "_bottom" @@ -6570,7 +6631,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 294 + "__id__": 298 }, "_contentSize": { "__type__": "cc.Size", @@ -6598,7 +6659,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 296 + "__id__": 300 }, "_alignFlags": 45, "_target": null, @@ -6634,7 +6695,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 298 + "__id__": 302 }, "debugMode": false, "_id": "" @@ -6656,10 +6717,10 @@ "targetOverrides": null, "nestedPrefabInstanceRoots": [ { - "__id__": 281 + "__id__": 285 }, { - "__id__": 272 + "__id__": 276 }, { "__id__": 257 diff --git a/assets/script/game/map/MissionMonComp.ts b/assets/script/game/map/MissionMonComp.ts index 0bb5e043..9c325a9c 100644 --- a/assets/script/game/map/MissionMonComp.ts +++ b/assets/script/game/map/MissionMonComp.ts @@ -98,6 +98,14 @@ export class MissionMonCompComp extends CCComp { private pendingMonsters: GeneratedMonster[] = []; /** 增量刷怪计时器 */ private spawnTimer: number = 0; + /** 分段刷怪阶段 (1, 2, 3) */ + private currentSpawnPhase: number = 1; + /** 下一阶段刷怪的延迟计时器 */ + private phaseDelayTimer: number = 0; + /** 当前阶段目标生成的怪物总数 */ + private phaseTargetCount: number = 0; + /** 当前阶段已生成的怪物数 */ + private phaseSpawnedCount: number = 0; // ======================== 生命周期 ======================== @@ -126,21 +134,35 @@ export class MissionMonCompComp extends CCComp { if(smc.mission.stop_spawn_mon) return; - // 逐步刷怪逻辑 + // 逐步刷怪逻辑 (分 3 段刷出) if (this.pendingMonsters.length > 0) { + // 如果当前阶段的怪物已经刷完,则进入延迟等待下一阶段 + if (this.phaseSpawnedCount >= this.phaseTargetCount && this.currentSpawnPhase < 3) { + this.phaseDelayTimer -= dt; + if (this.phaseDelayTimer <= 0) { + this.currentSpawnPhase++; + this.phaseSpawnedCount = 0; + this.phaseTargetCount = this.currentSpawnPhase === 3 ? + this.pendingMonsters.length : + Math.ceil(this.pendingMonsters.length / (4 - this.currentSpawnPhase)); + } + return; + } + this.spawnTimer += dt; // 控制刷怪速率:例如每 0.2 秒刷 1-2 只 if (this.spawnTimer > 0.2) { this.spawnTimer = 0; // 一次出 2 只,加快进度 for (let i = 0; i < 2; i++) { - if (this.pendingMonsters.length === 0) break; + if (this.pendingMonsters.length === 0 || this.phaseSpawnedCount >= this.phaseTargetCount) break; const monData = this.pendingMonsters.shift()!; const lane = this.pickBalancedLane(); - console.log(`[MissionMonComp] 准备生成怪物 UUID=${monData.uuid}, 剩余数量=${this.pendingMonsters.length}`); + console.log(`[MissionMonComp] [Phase ${this.currentSpawnPhase}] 准备生成怪物 UUID=${monData.uuid}, 剩余数量=${this.pendingMonsters.length}`); this.addMonsterAt(lane, this.laneIndices[lane], monData); this.laneIndices[lane]++; this.waveSpawnedCount++; + this.phaseSpawnedCount++; } } } @@ -168,6 +190,32 @@ export class MissionMonCompComp extends CCComp { start() { } + private setupWaveData(monsters: GeneratedMonster[]) { + this.pendingMonsters = monsters; + smc.vmdata.mission_data.pending_mon_num = this.pendingMonsters.length; + this.waveTargetCount = monsters.length; + + // 初始化分段刷怪状态 + this.currentSpawnPhase = 1; + this.phaseSpawnedCount = 0; + // 第一段生成 1/3 的怪物 + this.phaseTargetCount = Math.ceil(this.pendingMonsters.length / 3); + // 每段之间的延迟时间,可以根据需要调整,例如 3 秒 + this.phaseDelayTimer = 3.0; + + let hasBoss = monsters.some(m => m.isBoss); + + console.log(`[MissionMonComp] 波次 ${this.currentWave} 生成怪物总数: ${this.waveTargetCount}`); + const uuids = monsters.map(m => m.uuid); + console.log(`[MissionMonComp] 波次 ${this.currentWave} 怪物 UUID 列表:`, uuids); + + oops.message.dispatchEvent(GameEvent.NewWave, { + wave: this.currentWave, + total: this.waveTargetCount, + bossWave: hasBoss, + }); + } + /** * 战斗准备:重置所有运行时状态并开始第一波。 */ @@ -186,20 +234,7 @@ export class MissionMonCompComp extends CCComp { // 预生成第一波数据以获取数量和 Boss 信息 const monsters = spawningEngine.generateWave(this.currentWave); - this.pendingMonsters = monsters; - smc.vmdata.mission_data.pending_mon_num = this.pendingMonsters.length; - this.waveTargetCount = monsters.length; - let hasBoss = monsters.some(m => m.isBoss); - - console.log(`[MissionMonComp] 波次 ${this.currentWave} 生成怪物总数: ${this.waveTargetCount}`); - const uuids = monsters.map(m => m.uuid); - console.log(`[MissionMonComp] 波次 ${this.currentWave} 怪物 UUID 列表:`, uuids); - - oops.message.dispatchEvent(GameEvent.NewWave, { - wave: this.currentWave, - total: this.waveTargetCount, - bossWave: hasBoss, - }); + this.setupWaveData(monsters); mLogger.log(this.debugMode, 'MissionMonComp', "[MissionMonComp] Starting Wave System"); } @@ -265,20 +300,7 @@ export class MissionMonCompComp extends CCComp { // 预生成新一波数据以获取数量和 Boss 信息 const monsters = spawningEngine.generateWave(this.currentWave); - this.pendingMonsters = monsters; - smc.vmdata.mission_data.pending_mon_num = this.pendingMonsters.length; - this.waveTargetCount = monsters.length; - let hasBoss = monsters.some(m => m.isBoss); - - console.log(`[MissionMonComp] 波次 ${this.currentWave} 生成怪物总数: ${this.waveTargetCount}`); - const uuids = monsters.map(m => m.uuid); - console.log(`[MissionMonComp] 波次 ${this.currentWave} 怪物 UUID 列表:`, uuids); - - oops.message.dispatchEvent(GameEvent.NewWave, { - wave: this.currentWave, - total: this.waveTargetCount, - bossWave: hasBoss, - }); + this.setupWaveData(monsters); } private onPhasePrepareEnd() { diff --git a/assets/script/game/map/RogueConfig.ts b/assets/script/game/map/RogueConfig.ts index 3af653bd..ef96df95 100644 --- a/assets/script/game/map/RogueConfig.ts +++ b/assets/script/game/map/RogueConfig.ts @@ -464,7 +464,7 @@ export const BlueprintTemplates: BlueprintTemplate[] = [ // ---- 教程专用 ---- { id: "TUTORIAL", type: TemplateType.NORMAL, tierMin: 1, allowAffix: false, - slots: [{ typePool: [MonType.Melee], countMin: 5, countMax: 5, weight: 1.0 }] }, + slots: [{ typePool: [MonType.Melee], countMin: 2, countMax: 2, weight: 1.0 }] }, ] // ======================== 自适应难度配置 ======================== diff --git a/assets/script/game/map/gdd/rogue-spawning.md b/assets/script/game/map/gdd/rogue-spawning.md index 1f7eacd2..1bf7eece 100644 --- a/assets/script/game/map/gdd/rogue-spawning.md +++ b/assets/script/game/map/gdd/rogue-spawning.md @@ -442,7 +442,7 @@ delta calculation per wave: ### 核心波次生成 -- **GIVEN** 游戏开始(adaptive_factor=1.0),**WHEN** 进入 W1,**THEN** 生成 5 个 Melee 怪(T1, 无词缀),HP=120, AP=12。 +- **GIVEN** 游戏开始(adaptive_factor=1.0),**WHEN** 进入 W1,**THEN** 生成 2 个 Melee 怪(T1, 无词缀),HP=120, AP=12。 - **GIVEN** 当前 Tier 1 W2(攀升波),**WHEN** 模板选取完成,**THEN** 模板类型为 NORMAL 或 MIXED,且模板的怪物槽位池中包含 Long 类型(cost=40)。运行 100 次抽取,Long 类型出现在槽位池中的比例为 100%。 - **GIVEN** W6(Boss 波),**WHEN** 模板选取完成,**THEN** 模板类型为 BOSS,mandatory_slots 包含 Boss 类型,至少生成 1 个 MeleeBoss + 10-15 个普通怪。 - **GIVEN** Tier 2 W1(REST 波),**WHEN** 模板选取完成,**THEN** 模板类型为 REST,template_modifier=0.5x。