248 lines
12 KiB
Markdown
248 lines
12 KiB
Markdown
# 刷怪心流改造 · 实施步骤与执行方案
|
||
|
||
> 基于对 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 |
|