# 刷怪心流改造 · 实施步骤与执行方案 > 基于对 RogueConfig.ts / MissionMonComp.ts / MissionComp.ts 的多 agent 调研与方案讨论产出。 > 目标:让刷怪节奏产生"爽感"与心流(Flow),核心公式:**爽感 = 密度 × 可清性**,**心流 = 铺垫 → 峰值 → 释放循环 + 即时正反馈**。 --- ## 阶段划分总览 ``` 阶段一(P0 修复,4 项) → 安全网与曲线修正,不动体验结构 阶段二(P1 节奏与 DDA,5 项) → 核心体验重塑,依赖链严格 阶段三(P2-P3 反馈层,5 项) → 情绪反馈补全,可并行开发 ``` --- ## 阶段一:P0 修复 ### Step 1.1 — P0-3 刷怪暂停死链路(先做:泄压阀) **改动文件**:MissionMonComp.ts、MissionComp.ts | # | 操作 | 位置 | |---|---|---| | 1 | `update()` 在 pending 统计之后、批次推进之前插入 `if (smc.mission.stop_spawn_mon) return;` | MissionMonComp L106 后 | | 2 | 阈值对齐:`maxMonsterCount` 80→60,`resumeMonsterCount` 45→40 | MissionComp L86-88 | | 3 | `changePhase(PrepareEnd)` 分支补 `smc.mission.stop_spawn_mon = false;`(防开局冻结 4 秒) | MissionComp L492-495 | **验证**:临时 `maxMonsterCount=20` 进放松回合,确认到 20 只停刷、降 15 后续刷;wave 1 开局节奏无延迟。 **Commit**:`fix(mission): consume stop_spawn_mon in MissionMonComp update` --- ### Step 1.2 — P0-4 回合僵局超时(安全网) **改动文件**:RogueConfig.ts、MissionComp.ts | # | 操作 | 位置 | |---|---|---| | 1 | 新增常量 `WAVE_TIMEOUT = 75`(含 JSDoc) | RogueConfig 节奏常量区 | | 2 | MissionComp 新增字段 `skipRemainScoreOnBattleEnd`,`data_init` 复位 | MissionComp 运行时状态区 + L774 | | 3 | Battle 阶段 update 追加超时检测 `if (this.clearTime >= timeout) this.onBattleTimeout();`(timeout 取 `isBossWave ? 90 : WAVE_TIMEOUT`) | MissionComp L245-251 | | 4 | 新增 `onBattleTimeout()`:先扣 `wave_remain_monsters` → 销毁全部 MON 实体 → `mon_num=0` → 走 `TimeUpAdvanceWave` / `open_Victory` | MissionComp 回合管理区 | | 5 | BattleEnd 的 `wave_remain_monsters += mon_num` 加防重判断 | MissionComp L522-523 | **验证**:临时 `WAVE_TIMEOUT=8`,确认 8 秒准点收束、评分已扣、factor 放水;TestModeConfig 高血怪模拟僵局验证 75s 前不结束。 **Commit**:`feat(mission): add wave battle timeout fallback` --- ### Step 1.3 — P0-1 Wave 1 错位修正 **改动文件**:RogueConfig.ts(单文件) | # | 操作 | 位置 | |---|---|---| | 1 | `getWaveType`:`wave % 5 === 1` → `wave % 5 === 4` | L80 | | 2 | 同步 4 处注释:WaveType 枚举注释(L37)、文件头节奏注释(L21-23)、WaveConfigs 表头注释(L329-332)、表内"放松回合"行内注释从 wave 6/11/16 搬到 4/9/14 | 见左 | **验证**:`getWaveType(1..20)` 断言输出 `N N N R P` × 4 循环;实机确认 wave 1 = 18 只、wave 4 ≈ 40 只低强度。 **Commit**:`fix(rogue): move relax wave to pre-boss slot (wave%5==4)` --- ### Step 1.4 — P0-2 Boss 压轴 + 预警 **改动文件**:RogueConfig.ts、MissionComp.ts、GameEvent.ts | # | 操作 | 位置 | |---|---|---| | 1 | `SquadLibrary` 新增 `boss_guard`(weight:0,1 重甲+2 近战) | RogueConfig L191-198 | | 2 | `GeneratedMonster` 增加可选字段 `isBossGuard?: boolean` | RogueConfig L426-450 | | 3 | `generateWave` 重构第 3/4/8 步:Boss 不 push 首位 → 小队拼装 → 护卫队 `makeBossGuards()` → Boss 压队尾 → 批次统一分配后强制 Boss+护卫 `batch = BATCH_COUNT-1`;`remaining` 改为 `-= 4` | RogueConfig L509-554 | | 4 | `makeBoss` 的 `spawnIndex:0, batch:0` 改为占位默认值+注释 | RogueConfig L660-687 | | 5 | GameEvent 新增 `BossWarning = "BossWarning"` | GameEvent.ts | | 6 | `changePhase(BattleStart)`:`if (this.isBossWave)` 派发 `BossWarning { wave, eta: 20 }` | MissionComp L497-500 | | 7 | MissionComp 从 RogueConfig 补导入 `BATCH_INTERVAL, BATCH_COUNT` | MissionComp L51 | **验证**:wave 5 确认 0s/10s 两批纯杂兵、20s Boss 带 3 护卫进场、总怪数=21;`BossWarning` 仅在 5/10/15/20 派发。 **Commit**:`feat(rogue): spawn boss in final batch with guards and warning event` --- ## 阶段二:P1 节奏与 DDA(依赖链严格) 依赖链:**P1-5 → P1-1 → P1-2 + P1-3(同批)→ P1-4** ### Step 2.1 — P1-5 数值语义澄清(等价变换先行) **改动文件**:RogueConfig.ts(单文件) | # | 操作 | |---|---| | 1 | 删除第 5 步(乘 hp_mul/ap_mul),第 6 步改为拆分 `hpScale = targetPower × hp_mul / totalBasePower`、`apScale = targetPower × ap_mul / totalBasePower` | | 2 | 更新文件头公式注释(L12-16)与 `hp_mul/ap_mul` 字段注释 | | 3 | 17/18/19 启用 `power_adjust: 1.05 / 1.10 / 1.20` | | 4 | `validateRogueConfig` 增加 `power_adjust ∈ [0.8, 1.3]` 校验 | **验证**:改造前后固定 heroPower 打桩,逐怪 hp/ap 断言相等(等价回归);17/18/19 总强度阶梯断言。 **Commit**:`refactor(rogue): unify hp/ap mul into power scaling formula` --- ### Step 2.2 — P1-1 批次递增 + 间隔参数化 **改动文件**:RogueConfig.ts、MissionMonComp.ts | # | 操作 | |---|---| | 1 | 新增 `BATCH_RATIO = [0.25, 0.35, 0.40]`、`FINALE_SQUAD_COUNT = 2`、`SPAWN_INTERVAL_BY_TYPE`(Normal 0.18 / Pressure 0.25 / Relax 0.12) | | 2 | 批次分配从 `i % 3` 改为 `assignBatches()`:配额切分 + 第三批补 2 个最强小队(`pickStrongestSquad` 按 `calcHeroPower(样本)×count` 评分);放松回合跳过收尾加压;`totalCount` 预留收尾小队名额防 `slice` 截掉 | | 3 | MissionMonComp:`MON_SPAWN_INTERVAL` 静态常量改为实例字段 `spawnInterval`,`onPhasePrepareEnd` 按 `getWaveType(currentWave)` 查表;`releaseCurrentBatch` 末尾的 spawnTimer 初始化同步改 | **与 P0-2 的合并点**:`assignBatches` 需保留"Boss+护卫强制最后一批"逻辑。 **验证**:debugMode 日志打印每批只数与最强小队 id;放松回合 54 只应 ~6.5s 倾泻完。 **Commit**:`feat(rogue): progressive batch ratio and per-type spawn interval` --- ### Step 2.3 — P1-2 + P1-3 清场加速与 DDA 重做(**必须同 commit**) **改动文件**:RogueConfig.ts、MissionMonComp.ts、MissionComp.ts、GameSet.ts P1-2 部分(MissionMonComp): | # | 操作 | |---|---| | 1 | 新增状态:`batchReleasedCount`、`batchFastForwarded`、`aliveCheckTimer`、`waveEarlySkipTotal`(public 只读) | | 2 | `releaseCurrentBatch` 记录当批数量;update 中 0.2s 节流调 `checkBatchEarlyAdvance()` | | 3 | `checkBatchEarlyAdvance`:存活比例 ≤25% 且本批已放完 → `batchTimer += 2s`、`waveEarlySkipTotal += 2`(每批一次) | P1-3 部分(RogueConfig + MissionComp + GameSet): | # | 操作 | |---|---| | 1 | `DynamicTuner` 重写:连续映射 `desired = 1 + (0.8 - clearTime/30) × 0.5`(死亡锚定 0.8)、滞回 2 回合、指数靠拢 50%、区间 [0.7, 1.3]、新增 `streak` 字段 | | 2 | MissionComp BattleEnd:`effectiveClearTime = clearTime + MonComp.waveEarlySkipTotal` 后传入 adjust;顺手写入 `lastWaveDeathCount`/`lastWaveClearTime` 快照(供 Step 2.4) | | 3 | `FightSet.WAVE_HEAL_RATE` 0.5→0.4;修正 MissionComp L676"恢复70%"幽灵注释 | **验证**:脚本模拟三种 clearTime 曲线(恒 12s / 恒 25s / 交替)打印 20 回合 factor 轨迹;强 build 单回合时长应从 ~30s 压到 ~24-26s。 **Commit**:`feat(rogue): early batch advance and continuous DDA with hysteresis` --- ### Step 2.4 — P1-4 动态回合倒计时 **改动文件**:MissionComp.ts(单文件) | # | 操作 | |---|---| | 1 | 新增档位常量 `COUNTDOWN_FAST=2.5 / NORMAL=4.0 / FULL=5.0`,删除/降级 `WAVE_COUNTDOWN_DURATION` | | 2 | `startWaveCountdown` 改调 `computeCountdown()`:有死亡→5s,clearTime<65%→2.5s,否则 4s(读 Step 2.3 写入的快照字段) | **验证**:快清场回合倒计时显示 3→2→1;有死亡回合给满 5s。 **Commit**:`feat(mission): adaptive wave countdown based on last wave performance` --- ## 阶段三:P2-P3 反馈层 ### Step 3.1 — 事件与工具基建 + P2-2 清屏庆祝 + P2-3 Boss 演出 **改动文件**:GameEvent.ts、MissionComp.ts、MissionMonComp.ts、**新增** ScreenShake.ts、**新增** BattleBannerComp.ts、mission.prefab(编辑器) | # | 操作 | |---|---| | 1 | GameEvent 新增:`WaveClear` / `BossWarning`(Step 1.4 已加则跳过)/ `BossSpawn` / `CoinFly` / `ComboReach`,启用 `MonDead` | | 2 | 新增 `ScreenShake` 静态工具(抖 `smc.map.MapView.node`,强度/时长参数,收敛回原位) | | 3 | 新增 `BattleBannerComp`:统一横幅通道(右进 backOut → 停留 → 左出 backIn),监听 WaveClear/BossWarning/ComboReach,0.3s 去抖 | | 4 | MissionComp 清屏分支 dispatch `WaveClear { wave, clearTime, allAlive, fastClear }`(通关分支不派发) | | 5 | MissionMonComp `addMonsterAtGrid` isBoss 分支 dispatch `BossSpawn { pos }` | | 6 | 奖励规则:fastClear=1 → +2 金,=2 → +5 金,allAlive → +1 刷新石(走 MissionEconomy) | | 7 | **编辑器操作**:mission.prefab 新增 `banner` 节点(Label+背景),挂 BattleBannerComp | **Commit**:`feat(battle): wave clear banner, boss warning and screen shake` --- ### Step 3.2 — P2-1 波次 HUD + P2-4 金币飞行 **改动文件**:**新增** WaveHudComp.ts、**新增** CoinFlyComp.ts、HeroAtkSystem.ts、mission.prefab(编辑器) | # | 操作 | |---|---| | 1 | `WaveHudComp`:监听 NewWave 缓存 total;0.2s 轮询 `mon_num + pending_mon_num` 刷新进度条;静态生成 20 格旗帜(`getWaveType(i)===Pressure` 置 Boss 帧),当前回合脉动 | | 2 | HeroAtkSystem `scheduleDrop` 后 dispatch `CoinFly { worldPos, gold, isBoss }`;`onDeath` MON 分支 dispatch `MonDead` | | 3 | `CoinFlyComp`:独立 NodePool(上限 30),3-5 枚(Boss 8 枚)金币抛物线散开→加速飞向钱包;金币帧运行时取编辑器绑定的 `coinIconSrc.spriteFrame`;**账务立即结算、飞行纯表现** | | 4 | **编辑器操作**:prefab 新增 `wave_hud`(wave_lab/remain_lab/progress/flags)与 `fly_layer`(最高 sibling),挂组件并拖绑定 | **Commit**:`feat(battle): wave progress HUD and coin fly animation` --- ### Step 3.3 — P3-1 连杀 Combo **改动文件**:**新增** ComboComp.ts、mission.prefab(编辑器) | # | 操作 | |---|---| | 1 | `ComboComp`:监听 MonDead,2s 滑动窗口计数,5/10/20 阈值派发 `ComboReach { count, tier }`;MissionEnd 清零 | | 2 | BattleBannerComp 消费 ComboReach:分级文案/颜色/震屏(tier2 `shake(8,0.3)`)+ 金币爆发 2/5/10 | | 3 | **编辑器操作**:prefab 挂 ComboComp | **Commit**:`feat(battle): kill combo system with tiered rewards` --- ## 执行约束 **每次 commit 前必做**: 1. `validateRogueConfig()` 返回空数组 2. GetDiagnostics 检查改动文件无 TS 错误 3. 手动验证项按各 Step 的验证清单执行 **Commit message** 遵循项目规范(Conventional Commits、英文、祈使句、≤50 字符)。 **资源依赖**(不阻塞开发,可后期补):Boss 旗帜帧 ×1、清屏/Boss 预警/连杀音效 ×5、金币入袋音效 ×1——占位方案:flash/dun/Hit/Critical/Fire/button 复用。 **风险最高的两步**:Step 1.1(PrepareEnd 时序坑)和 Step 2.3(P1-2/P1-3 必须同批)。实施时优先单独验证这两点。 --- ## 附录:关键数值速查 | 参数 | 现值 | 目标值 | 所属 Step | |---|---|---|---| | getWaveType Relax 位 | wave%5==1 | wave%5==4 | 1.3 | | Boss 批次 | batch 0 | batch 2 + 3 护卫 | 1.4 | | maxMonsterCount / resume | 80 / 45 | 60 / 40 | 1.1 | | WAVE_TIMEOUT | 无 | 75s(Boss 90s) | 1.2 | | BATCH_RATIO | 33/33/33 | 25/35/40 + 收尾小队×2 | 2.2 | | 刷怪间隔 | 0.3s 统一 | Normal 0.18 / Pressure 0.25 / Relax 0.12 | 2.2 | | 清场加速 | 无 | 存活≤25% 时 batchTimer += 2s | 2.3 | | DynamicTuner | ±0.05 步进 [0.5, 2.0] | 连续映射+滞回 [0.7, 1.3] | 2.3 | | WAVE_HEAL_RATE | 0.5 | 0.4 | 2.3 | | 回合间倒计时 | 固定 5s | 2.5 / 4 / 5 三档 | 2.4 | | power_adjust 17/18/19 | 未使用 | 1.05 / 1.10 / 1.20 | 2.1 |