feat(hunt): 《围猎》2-4人实时联机纯音频协作守卫——纯音频MMORPG第一阶段切片

- 设计:docs/design/23-hunt.md + voice-ids(84 id,166条)+ 13号断言登记,§15记录10+1条设计裁决
- 服务器:零依赖WebSocket(ws.js)+ 房间管理/服务端权威战斗/bot AI(hunt-room.js),断线30s宽限resume回槽、超时转bot;修复package.json模块类型误判的既有破坏
- 客户端:web/hunt/ 全套(教学T0-T4/听觉视野裁剪R1-R8/结算排行榜/guide接入),playtest 211断言
- 引擎:audio.js 后向兼容 opts.pan(StereoPannerNode),web-engine-api.md 同步
- 资产:166条TTS语音(QC无离群)+ 13件合成sfx(真峰值≤-3dBFS)+ 2首Mureka BGM,终检全绿
- 平衡:bot调参至挂机局71%失守/C、3bot局71% A/B(hunt-balance-scan.mjs 24种子扫描)
- 接线:大厅卡片、profiles.js hunt桶、README/roadmap MMO路线条目

验证:hunt-sim 16/16 + api-smoke 12/12 + hunt playtest 211/211 + 既有10游戏与引擎回归零回退 + 真服务器WS端到端冒烟通过
This commit is contained in:
xsl
2026-09-13 11:08:01 +08:00
parent 31372615b2
commit 005851d01a
392 changed files with 6826 additions and 19 deletions
+39
View File
@@ -795,3 +795,42 @@ R1 起每轮的增量断言(修复回归)在各自设计文档的轮次小
结算链 800ms 手势死窗(判定出口/NIGHT/d9/e*);键盘 _k 变体 11 对按 inputMode 选播;pendingChoice/p* 不可跳/
摩尔斯首播不可跳;中断复述(含 DECODE 态恢复链 prog_t→book 档→gd_tune2);存档 schema(summary 带
暴露档名)。
---
## 24. hunt《围猎》(联机切片;设计 [23-hunt.md](23-hunt.md),台词表 23b)
> 本作是首个联机游戏:断言分两侧——**服务器侧**(`web/server/test/` 新增 hunt-room 单测,直接 import 房间模块 + 假 WS 连接,固定 seed 复现)与**客户端侧**(`web/hunt/test/playtest.mjs`,mock 引擎 + mock transport 注入 ev/snap)。协议字段以 23 号文档 §6 为唯一契约。测试钩子可读 game 实例字段与房间实例字段;手势只经引擎回调注入。
**关键路径**(首局教学房 → 5 波 → 结算 → 排行榜,≤150 次手势):
1. 启动遮罩点按 → 音频解锁(此前零播放)→ TITLE;无存档单击 → 断言客户端发出 `join { room:"quick", teach:true, ver:1 }`。
2. **教学房**:注入 `joined`(phase:'teach',slot 0,roster 含 2 bot,seed=42)→ T0(intro_1→intro_2→tut_rule 有序)→ 单击 → T1(tut_attack + 注入 spawn 狼 N eta12)→ 先错向滑 W(断言 `act attack dir:W` → 注入 `ev miss` → atk_swish + error 震 + gd_idle 重教,怪物不受伤)→ 向 N 滑 → 断言发出 `act attack dir:N` → 注入 `ev kill` → tut_kill_ok;T2 单击 → `act callout` 发出 → 注入 bot help_ack(断言 `sfx/npc_yan_help_ack` 播放且 pan=该 bot 防区中心)→ tut_callout_ok;T3 双击 → `act skill` → 注入 `ev skill cleared=[2]` → tut_skill_cd;T4 上滑 → 状态链 4 段有序(hp_band→st_wave→team_3→kill_band)→ tut_breach→tut_done → 注入 `ev wave 1` 进 WAVE。**教学狼突入零惩罚**:注入教学波 breach → dur 不变。
3. **bot 补位**:非首局(tutDone=true)→ LOBBY(room_wait 播)→ 单击发 `act start` → 开局 roster ev 断言猎人总数 = max(3, 人类数)、bot 槽 char 齐全、bot greet 逐只间隔 ≥1.5s。
4. **5 波推进**(seed=42 服务器侧快进 tick):每波 spawn 事件数/型别/逼近时长与 23 §3.4 表逐波一致;方位分配 ∈ 各座位防区;狼击杀(滑向 → act → ev kill)断言归属 slot 与 kills 账;漏一只狼 → ev breach,dur -1,`breach` 播报 + hit 震;熊漏 → dur -2 + `breach_heavy`。
5. **终局**:注入 `ev end { win:true, dur:8, grade:"A", kills }` → 结算链有序(end_win→grade_a→kill_band_*→end_rank→end_again)→ 断言 PUT `/api/progress { game:"hunt" }` 且 `data.summary` 命中生成规则(`最佳评级A · 击杀14 · 营地余8 · 共N局`)、best 按"评级>耐久>击杀"序更新;单击 → 重新进匹配。失守路径(dur 归零):end_lose 首句、无 grade_*、无 end_rank、不写 best、runs+1。
**边界断言**:
- **断线转 bot**:关连接 30s(服务器侧快进)→ roster ev 该槽 bot=true 且 char 沿用 → 该槽开始产出 act(tick 内断言);剩余人类 ≥3 时改为槽位移除(roster 缩短)。
- **重连回槽**:断开 15s 内带 `resume` 重连 → joined 同 slot/seed/char + 紧随 snap 全量 → 客户端怪表与 snap 一致、net_back 播报、战斗续接;超 30s → err `room_gone` → net_gone → LOST。
- **旋风斩冷却**:放出后 8s 内双击 → 无 act 发出、播 threat_*(按内圈只数选档);冷却完成 → skill_ready(queue:true 不顶句);伪造 `act skill` 越冷却 → 服务器 err `skill_cd`。
- **出击冷却 2.5s**:冷却内滑 → 仅 error 震、零 act;伪造连发 → 服务器只裁决首发,其余 err `cooldown`。
- **支援呼喊 bot 补位**:呼喊后 10s 内,服务器侧断言补位 bot 的下一次 act.dir ∈ 呼喊者防区(偏置 ×2 生效),且 `help_ack` 恰播一次;呼喊节流 5s(连点只出一条 callout ev)。
- **听觉裁剪上限**:eta>6s 怪零 loop;任意时刻 loop ≤3 路且为 eta 最小 3 只(注入 5 只内圈怪断言);threat_* 选档只计 eta≤4 只数;状态链/威胁句无任何逐方位枚举(台词表结构保证)。
- **拥挤控制(R1-R8)**:第 5 波峰值剧本下断言——同刻 voice ≤1;同刻 `npc_*` ≤1 且 10s 窗 ≤2 条;旁白在播时喊话延迟 ≤2s 或丢弃;one-shot 定位音同刻 ≤2;breach/danger_low/wave 播报零丢失。
- **snap 兜底**:客户端随机丢弃 50% ev,仅凭 snap(2Hz)收敛 → 怪表与服务器真值一致(id 集合 + eta 偏差 ≤0.5s 校正)。
- **菜单不暂停(E3)**:菜单开着注入 breach → dur 照扣、菜单不收;菜单 3 项固定、单击循环/双击确认/下滑关闭。
- **学期零惩罚**:教学波 breach 不扣 dur;T1 做错 2 次自动放过不卡死。
- **结算死窗**:end 到达前后 800ms 内注入 tap → 被吞(不进 TITLE/不重开);死窗后单击正常再来一局。
- **屏蔽任意 voice 资产**:结算链/警报链照走完(看门狗兜底推进),不卡死。
- **资产齐套**:voice 双性别 60 句集合一致、key 变体 11 对 ⊆ 主集、`sfx/npc_*` 24 条双格式(assetExists 口径)。
- **opts.pan 回归**:无 pan 调用路径零 panner 节点(引擎行为不变);pan=-1/0.7/1 时 panner 值正确;老 Safari 无 createStereoPanner 静默降级。
**全局通用(§7 五条全跑,另加本作条目)**:
- 启动遮罩点按前零音频播放;遮罩手势不被游戏误收(引擎双保险)。
- **guide 三档**:full=签名+语音+震;standard 无向导语音;**off=全静且零看门狗定时器**(WAVE 30s 空闲零向导播放,内容层 loop/音效除外)。
- **震动语义**:逐条对照 23 §2 表——击杀 pickup / 挥空 error / 旋风斩 success / 突入 hit / 收到呼喊 warning / 耐久 ≤2 danger / 波次 heartbeat;手势本身震动由引擎内置承担,游戏层不重复(无双震)。
- 设置边界:speed 切换下一句生效;bgm=0 全程无 bgm 加载;voice 切换下一句用对应目录。
- 服务器不可达:TITLE 单击 → net_lost → net_gone → LOST 回大厅(明示失败,不静默死屏)。
**失败即不通过**:评级与 dur 不符(归因假话);服务器接受违规 act(冷却/方位/近战窗外命中);ev 与 snap 矛盾不收敛;bot 喊话压过/打断旁白(R1/R2 破);loop >3 路;教学狼扣耐久;失守局写入 best 排行榜。