# 26-apply · 《围猎》重构施工单(26 号文档落地) > **设计单正文见 [23-hunt.md](23-hunt.md) 附录 C**(状态×手势矩阵、等待点表、 > 首 3 分钟逐秒脚本、失败表、台词类别)。本文不重复正文,只记录实现接线、 > 偏差、台词类别映射与测试结果。交互规则权威来源: > [26-audio-interaction-playbook.md](26-audio-interaction-playbook.md)。 > 台词增量清单:`tools/voice_lines_26/hunt.md`;登记副本 [23-hunt-voice-ids.md](23-hunt-voice-ids.md)。 ## 1. 实现接线(web/hunt/) **引擎六模块**(`web/engine/`,未改动):`HuntGame` 构造并暴露 `receipts / floor / confusion / invalidHints / ladder`;`invalidHints.bind(floor)`;`confusion.onConfused → _onConfused`:有等待点走 `wp.takeover(level)`,WAVE 对局走本作三级(见 §3)。 `audio.setRateBoostEnabled(false)`(长按=帮助,不触发旁白快进)。 **发言权**(§4.1): | 场景 | Floor 状态 | |---|---| | TITLE / WAVE / TEACH 战斗 | `enterAction()`(BGM/怪 loop 即状态声) | | 波次播报 wave_bandN | `floor.speak`(可被出击打断:打断并执行),播完回 ACTION | | LOBBY / 波间休整 / END / LOST / 菜单 | `floor.speak(...)` 后 `yieldTurn(wp)` | | MATCHING | BUSY(等 joined;二周目填 intro_1/2,可跳句) | **管道**(index.html 与 playtest 同一接线):`makeInputPipeline({ floor, confusion, receipts, invalidHints, game, ladder, opts })`,`opts = { swipeCore: true, longpressCore: true }`。**双击窗口分档**:`game.DT_CORE = ladder.stage() >= 3` 快照 ——stage < 3 时 `attachGestures(..., { doubleTapWindow: 0 })`(双击不存在,键盘回车 折算 tap);stage ≥ 3 用默认窗口 + `doubletapCore: true`(游戏内分发:阶段 3 双击 = 重听威胁档 threat_*;skillUnlocked(阶段 4)= 旋风斩,冷却中仍回威胁档)。阶段 4 解锁:首次以 stage≥3 进入大厅播 `skill_teach` 一句并落盘 `progress.skillUnlocked` (「大厅全部解锁/专属教学」双口径中的专属教学路径;全项目大厅按钮走 novice.js 既有 unlockAll)。 **onGesture 收口**:`'ok' | 'hold' | 'invalid'`(本作不用 silent-ok:出击/呼喊的内容 音走 R4 队列可能延迟 >100ms,统一 ok 回执保「禁止静默」红线)。`stateName()`: title/matching/lobby/teach/wave/rest/end/lost/menu。`invalidHint(state,g)` 映射见 game.js `INVALID_LINES`。 **教学波**(§4.10):joined(teach) → T0 `sys_first_tap`(critical,首句动手)→ tap → T1 `tut_hit_full`(critical「朝叫声,滑。」+ 服务器放教学狼)→ 滑砍(错向 miss → atk_swish + `miss_side`「在另一边。」)→ 首杀(`tut_kill_ok` + ladder.onGoal = 阶段 1)→ T2 `tut_call_full` → 呼喊 → bot help_ack → `tut_callout_ok` → T3 `tut_help_full`(长按=我在哪,阶段 1 教学)→ `tut_done` → 等 ev wave 1。教学步进链 全部 critical(<3s,警报经 `_alertVoice` 排队到链尾冲刷,R1 教学不可顶)。 旧 intro_1/2/tut_rule 规则总述废除(反模式 6);无手动跳过(每步 L3 演示兜底)。 **等待点**(§4.4 三档;配置见 game.js `_introWp/_hitWp/_callWp/_helpWp/_restWp/ _endWp`):intro(tap, 6s/15s, L3 替点)、teach_hit(四向, 8s/15s, L3 替出刀)、 teach_call(tap, 8s/15s, L3 替喊)、teach_help(longpress, 8s/15s, L3 替播帮助)、 lobby(tap, 8s/12s 服务器自动开局, L3 替发 start)、rest(无 full/short——静默只给 提示音)、end(tap, 20s/45s)。**wave 等待点无 WaitPoint**:本波未出手 8s 一次 earcon (`_startWaveIdleFeed`),出手即停(「本波已出手则永不语音催」);静默信号照喂 迷茫检测(权重 1,单独不触发接管)。 **WAVE 接管**(附录 C §7 迷茫行):L1 `gd_idle`「朝最响的滑。」→ L2 只放行最近怪 弧(`_restrictArc`,其余 invalid 回执)+ `wave_only` → L3 `_demoKillNearest` 替玩家 出刀(服务端裁决;教学狼 ≤2 挡自动放过契约保留)。 **手势语义**(附录 C §3/§4 全表落地,文件头有矩阵注释): 四向滑恒出击(90° 弧;WAVE 内下滑=出击南弧不弹菜单);单击=呼喊(5s 节流,节流内 invalid + `call_cd` 一次解释);长按=我在哪(hp 档 + 波次档 + `lp_act` ≤20 字;重复 问更短,全说过则「再说一遍:」+ lp_act);菜单仅 TITLE/LOBBY/波间休整/END(左右滑 换项、单击确认、长按重听、下滑关闭、回大厅二次确认 `sys_home_check`——原则 6); 结算尾句 end_again critical(800ms 死窗由 critical 承担:ghost tap 得 busy/跳句, 不重开)。 **断点复述**(§4.12,联机豁免口径):联机局不按单机节点存档——①断线 30s 内 resume 回槽播 `net_back`「你回来了。朝叫声滑。」;②一局内被迫退出(房灭/断线超时→LOST、 菜单回大厅、对局中 stop)→ `progress.unfinished` 标记,下次进 TITLE 播 `sys_recap` 一句复述,summary 保留(`_markUnfinished` 在改 phase 前判定)。 **手势阶梯上报**:第一次击杀 `ladder.onGoal()`(阶段 1;**不播 sys_unlock_up**—— hunt 上滑=出击北弧,「我在哪」教学由 T3 tut_help_full 承担);一局 END `ladder.onGameDone()`(第 1 局 sys_unlock_down / 第 3 局 sys_unlock_dt 追加在结算 尾句后)。 **协议/拥挤/渲染全保留**:join/act/leave + joined/ev/snap/err、服务端权威怪表 对账、三源声像(loop pan + 后半平面低通、生成呼啸、bot 喊话防区 pan)、R2 bot 喊话调度、R4 one-shot 账目、断线 30s 回槽、评级双轴、进度 PUT——playtest Block 0/6/7 与 23 号 §10 验收口径逐条复测通过。 ## 2. 偏差记录(对照 23-hunt.md 附录 C) | # | 偏差 | 理由 | |---|---|---| | 1 | critical 落在 T0 `sys_first_tap` 与 T1 `tut_hit_full` 等教学指令句,而非附录 C §8 单指的开场「朝叫声,滑。」 | §8 原意「开场关键句 <3s 不可打断」;T0/T1 指令句均 <3s,critical 期间点按/滑动给 busy 回执(不打断指令),狼逼近期 ≤1.8s,代价可忽略;换来教学链不被警报/乱点打碎的确定性 | | 2 | 结算链头(end_win→grade→kill_band→end_rank)可跳句可打断;只尾句 end_again critical | §4.6「critical 必 <3s」;800ms 手势死窗由尾句 critical 承担(ghost tap 跳句/回执,不重开) | | 3 | 冷却内连滑「其后静默」→ 每下都给 invalid 回执(软「咚」),震动仍仅每窗首拦 | 「呼喊节流拒绝/挥空必须出声,禁止静默」红线 + §6.2 无声操作=0;v2 S2 要消灭的是连环 error 震,回执是 120ms 轻音不构成噪声 | | 4 | 「乱滑计入迷茫但不放技能」保真;阶段 3 双击在非 WAVE = 重听当前等待点(lobby/end),WAVE = 重听威胁档 | §4.3 阶段 3「双击=重听」通用语义与附录 C §3「重听威胁档」战斗语义并存,按语境分发 | | 5 | 死窗/吞手势一律给回执(busy/invalid),不物理静默 | 同偏差 3 红线 | | 6 | 状态链旧 4 段(hp/波次/人数/击杀)压缩为长按 3 段(hp+波次+动作);人数移 LOBBY 长按、击杀档留结算 | 附录 C §3 阶段 1 原文「耐久档。波次。一个动作」≤20 字;人数/击杀不属「我在哪」 | | 7 | 危险状态身份 = danger_low 语音 + danger 震(不再有 guide danger 签名 earcon) | Guide 层整体退役(floor/receipts/hints/confusion 接管);每局一次的语音句自带状态身份,避免新增资产 | | 8 | WAVE 期一次击杀奖励句不播(kill_wolf 音效 + pickup 震即反馈);教学首杀播 tut_kill_ok | 原则 11 肯定 ≤4 字只用于教学;对局击杀高频,内容音即回报(R5 非语音信息 <1s) | | 9 | 「冷却中双击=重听威胁」在阶段 4 之前不存在:阶段 3 双击恒重听(含就绪态),不放技能 | 附录 C §3:阶段 3「仍不放技能」;阶段 4 才有就绪/冷却分叉 | | 10 | 菜单开着时 waveclear 只延长休整窗、不播 wave_clear | E3 菜单链不可被波间播报顶掉;wave_clear 下一波照常播 | | 11 | `sys_turn_teach` 不使用 | 交接提示音(floor 风铃)+ 等待声已承担「轮到你了」教学;不额外占一句 | ## 3. 台词类别映射(§4.6;全表见 23-hunt-voice-ids.md 与 tools/voice_lines_26/hunt.md) - `critical`:sys_first_tap(T0 首句)、tut_hit_full / tut_call_full / tut_help_full (教学指令,均 <3s)、tut_kill_ok 后的步进链、tut_done、结算尾句 end_again - `content`:intro_1/2、room_wait、room_start、wave_band1-5、wave_clear、end_win/ end_lose/grade_*/end_rank、net_*(回槽/断线复述)、sys_recap、skill_teach、 sys_unlock_down/dt、sys_home_check、sys_menu - `hint`:tut_*_short、room_wait_short、sys_menu_short、end_again_short、lp_act/ lp_title、threat_*(重听威胁档)、st_wave_*/team_*(长按查询段)、wave_only、 gd_idle、skill_ready - `feedback`:atk_cd、call_cd、inv_swipe、inv_rest、miss_side、gd_invalid - 停用/删除:tut_rule、tut_attack、tut_callout、tut_skill、tut_skill_cd、 tut_status、tut_breach、tut_skip、settings_hint(详见台词清单 §3) ## 4. 测试记录 - 无头 playtest:`tools/node/bin/node web/hunt/test/playtest.mjs` —— **255 断言全绿 (退出码 0)**,覆盖:引擎 opts.pan 回归(Block 0)、教学波 §4.10(首句动手 + 首杀 ≤10s + critical 不打断 + 零规则总述)、WAVE 战斗全表(裁剪/冷却/节流/呼喊/ 突入/危险/长按状态/休整窗/wave 等待点 earcon 纪律)、双击分档(阶段 3 重听威胁、 阶段 4 旋风斩 + skill_teach)、菜单 E3 + 二次确认、结算 + ladder.onGameDone 解锁 教学 + PUT summary 双轴、断线 resume/net_back/房灭/sys_recap 断点复述、snap 收敛、 R2/R4 拥挤、设置边界、座 3 哨音、资产缺失 Floor 看门狗兜底、静态 id 审计。 - **§6.2 乱点机器人**(Block 10,157 手势跑完 lobby→两波→终局→再来一局): 无声操作 **0**、被动原句重复 **0**、打断失败 **0**(口径注记:①防连点 400ms 内 吸收的快速重点(busy 回执)算一次逻辑交互,豁免;②警报类按事件计重复——每次 突入是新信息,机器人编排按真实节奏注入)。 - 节奏检查(§4.10):教学 T0 第一句即动手(critical ≤1.8s);首杀路径实测 9.6s ≤ 10s;每 30s 有可听进展(呼啸/loop 档变化/波次播报/结算)。 - 真人冷启动:待测(§6.3,3-5 人)。 ## 5. 已知限制 / 引擎缺口 - 引擎 `InvalidHints.explainOnce` 的 onDone 只恢复等待点:ACTION 语境(无等待点) 的解释句若被打断,floor 会漏在 BUSY。本作以**实例级包装 `floor.handleInput`** 自愈(TITLE/WAVE 无合法长驻 BUSY,输入前回 ACTION),未改引擎;若后续游戏同样 需要,建议把「反馈句播完回调用语境」收进 InvalidHints(引擎侧小改)。 - `Floor.speak` 的 id 必须带 `voice/` 层前缀(裸 id 被引擎静默丢弃,靠 Floor 看门狗 3s 后推进,表现为丢句)——本作在 `_enterEnd` 踩过一次(tail 尾句),已修;静态 审计不覆盖此类问题,值得加一条「speak 前缀 lint」进 harness。 - 联机局断点复述是「一句话 + 重进匹配」口径(23 号 §9 原文),不回填对局中段; 单机式存档恢复与联机豁免冲突,维持不改。