Files
SoundGame/docs/design/26-apply-teahouse.md
T
xsl ee5d4d2544 feat(playbook): 26 号交互手册全量落地——剩余 12 款深度重构 + 语音全量重制
storyline/escape/simon 首批之后的推广收官:15 款全部按 26 号模式运行
(发言权/回执/三档提示/迷茫接管/手势阶梯/断点复述),旧「双击重听/格挡/
菜单确认」等反模式口径全线废除,开场零规则念白(首句即动手)。

游戏层(12 款):rpg(格挡=前摇窗口内再单击)/ rhythm / space / radio /
dungeon / abyss / detective / cipher / teahouse / keeper / bridge /
hunt(联机切片):
- 每款 game.js 接引擎六模块 + makeInputPipeline(doubleTapWindow:0);
  四向玩法类 swipeCore + 长按帮助;双击是玩法的(space 护盾 / hunt
  旋风斩)按手势阶梯阶段 3 分档恢复双击窗口(doubletapCore)
- 每款 playtest 重写:玩法断言 + §6.2 乱点机器人(无声操作 / 被动
  原句重复 / 打断失败 = 0);15 款 3900+ 断言全绿
- 12 份 docs/design/26-apply-*.md 施工单 + tools/voice_lines_26/
  台词清单 + voice-ids 文档同步 + 转写会话剧本按新口径重写

引擎层(web/engine/,6 处修复):pipeline 增 doubletapCore;novice
teachLine 带 voice/ 前缀(此前教学句被静默丢弃);confusion.record
前置到新手门(锁定手势的乱点也计信号);InvalidHints 播完恢复解释前
状态(根治孤儿 BUSY);WaitPoint takeover(2) 台账去重;台账只在
speak 真正播出时登记。遗留引擎债登记 roadmap §3.1。

语音资产:台词表合并(新增 ~250 系统句 / 改 ~50 旧口径 / 删 ~110
废止句;合并器 tools/merge_voice_lines_26.py + 引用校验器
tools/validate_voice_refs.py),GPU 重录 1536 wav → 4204 ogg/m4a
落地,check_all_assets + validate_voice_refs 双绿;键盘变体同步扩表。

大厅/文档:15 款统一新交互口径(「新交互」徽标退役);README /
HANDOVER / rpg README 旧口径修正;roadmap P0-P3 置完成。
2026-10-02 12:33:20 +08:00

137 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 26-apply · 《深夜茶馆》重构设计单(26 号文档落地)
> **设计单正文见 [20-teahouse.md](20-teahouse.md) 附录 C**(一句话核心动作 / 三态 /
> 手势表 / 状态×手势矩阵 / 等待点表 / 首 3 分钟 / 失败表——本文件不重复,两处冲突
> 以本文「偏差记录」节为准)。本文是 26 号深度重构的**施工单**:实现接线、偏差记录、
> 台词类别映射、测试记录。台词登记见 [20-teahouse-voice-ids.md](20-teahouse-voice-ids.md)
> R2 增量节;清单见 `tools/voice_lines_26/teahouse.md`。
> 交互权威:[26-audio-interaction-playbook.md](26-audio-interaction-playbook.md)、[00-global-ux.md](00-global-ux.md)。
> 范式对齐 [26-apply-radio.md](26-apply-radio.md)(叙事型接线参考)与
> [26-apply-storyline.md](26-apply-storyline.md)。
## 1. 实现接线
- **输入管道(§4.2/§4.3)**:`web/teahouse/index.html` 与 storyline 同构——
`makeInputPipeline({ floor, confusion, receipts, invalidHints, game, ladder })`
+ `attachGestures(root, pipe, { doubleTapWindow: 0 })`(关双击窗口:时机步单击
即时生效,无 300ms 延迟;键盘回车发的 doubletap 由管道折算 tap)。
- **game.js 暴露**:`this.receipts / this.floor / this.confusion / this.invalidHints`
(`bind(floor)`)/ `this.ladder`;`onGesture(g)` 返回 `'ok'|'hold'|'invalid'|'silent-ok'`;
`stateName()`(TITLE/OPENING/SERVE/CLOSE + BREW 细分 TEA/WATER/STEEP + MENU/SHOP);
`invalidHint(state, g)`(原则 7 每格一句;WATER/STEEP 返回 null=只回执)。
- **发言权层(§4.1)**:营业态自动链全部走 `_speakFlow` 包装(floor.speak + 续接点
`_flow`)。管道对滑动统一「杀链后交给游戏」——floor.speaking 在 onGesture 入口
已为 false,所以**打断续接一律无条件 `_popFlow()`**(有自动流=刚被打断),这是
teahouse 改造的关键接线(被杀链的「迎下一位客人/进灶/反应链收尾」立即续上,
流程不失速)。
- **CONFUSION 接管**:`confusion.onConfused(lvl) → floor.waitPoint.takeover(lvl)`;
`record` 在管道新手门之前(引擎 2026-10 修复版)。L3 替打口径见附录 C §5:
intro 替点 / tea 替选点单那罐 / water 替提壶(拨到将沸窗中点)/ steep 替出汤 /
close 与 reopen 只提示音。
- **等待点(§4.4)**:`SILENCE` 表 + `_introWp/_reopenWp/_teaWp/_timingWp/_closeWp/
_menuWp/_shopWp/_drillWp`;三档与 30s 台账由 `engine/hints.js` 统一实现。
- **手势阶梯(§4.3)**:`ladder.onGoal()`(第一盏茶送出,D4 反应链尾)→ 阶段 1
教学句挂 D5 链首;`ladder.onGameDone()`(第一晚睡下)→ 阶段 2 教学句挂下一晚
开场链首;阶段 3(累计 3 局)解锁双击=重听(点单/茶名/开工问询),未解锁由管道
折算 tap。`teachLine()` 返回带 `voice/` 前缀 id 直接进链。
- **E3 加速**:进 BREW `audio.setRateBoostEnabled(false)`(全态关加速,长按不快进、
时机窗不许倍速听);出灶(结算/堂前)恢复 true。
- **教学寄生首晚(§5 单击版)**:D0 左右滑看柜(换罐即教选定,做中学)→ D1 单击
选定 → tut_water 说完才起水声(听觉分层:注水/教学时间上串行)→ D2 窗内单击
提壶 → D3 窗内单击出汤 → D4 单击端茶(反应链前停住等玩家)→ D5 上滑状态链 →
tut_done,drillDone 落盘。偏手真话归因重教,2 次后替打,90s 无进展自动替打。
已 drillDone 玩家开场 `sys_tap_start`(不念教学、不念 intro)。
- **断点复述(§4.12)**:每位客人结算后 `_saveAuto()`(PUT /api/progress,summary
必带:第 N 晚 · 客人 x/4 · 口碑档 · 存款/欠账);回来 `sys_continue_ask` →
单击 = 复述链(客人序 → 口碑档 → [BREW 中断:sig+点单句] → recap_go)→ 当前
客人从进门链重放;右滑两次 = 重开确认(sys_reset_ask)。
- **菜单(00 §5.4)**:左右滑切项每项报名 + 单击确认 + 上滑重听说明 + 下滑关闭;
BREW 内开菜单冻结水声/滴答时间线(elapsed 停表),关闭恢复并播一句复述
(hint_water / 茶名)。打烊后菜单多一项「打烊置办」(二级列表,置办真话门
upg_none/upg_lock)。
## 2. 偏差记录(对 20 号附录 C)
1. **timing 等待点 full/short 置空**(附录 C §5 water/steep full 写了
「听到细密泡,点一下。」):实现取 null——分层铁律(26 §3.3 / 20 §3.3
「时机窗内禁止向导语音」)优先,被动档与迷茫 L1 只剩交接提示音;那句教学职责
由 tut_water/ tut_steep 承担(critical,播完才起水声/滴答时间线,时间上串行)。
playtest 断言「WATER/STEEP 时机窗内 voice 播放事件 = 0」。
2. **堂前链播中左/右滑 = 打断并推进**(附录 C §4 写 invalid):26 §4.1 管道统一
裁定「滑动=打断并执行」优先于旧格;只有堂前链间空档的滑动才 invalid
(inv_serve_swipe 首次解释)。被打断的迎客/进灶调度立即续上,不杀流程。
3. **上滑状态链第一段(重播点单)覆盖堂前与灶上**:附录 C 只写 BREW;实现里
只要客人未走(堂前点单链播中/空档、BREW 全程)上滑都先「再说一遍:」+ 点单句
(sig 音随行),需求随时可查(原则 3)。
4. **菜单关闭重播被停链 = 从链首重播**(非「从被停句续播」):下滑先经管道
`floor.handleInput` 杀链,此后 `floor.currentId()` 不可查(引擎缺口,见 §5);
盲玩语义「节点不丢」按完整重听算(被停链整条重播,玩家不丢任何一句话)。
5. **教学跳过入口裁定为「无入口」**:附录 C §3「教学跳过仅 TITLE/OPENING 未入
泡茶前用帮助长句」——实际形态下 sys_help 仅从菜单(阶段 2 解锁,时点必已
drillDone)可达,且教学七步有 90s 自动替打保送、已 drillDone 玩家开场直接
sys_tap_start 不进教学,「跳过教学」不再有真实需求。sys_help 保留为菜单帮助项
(动作词全部换「点一下」口径重录)。
6. CLOSE 800ms 死窗 + 结算链锁(critical 整链手势一律 busy)+ `settle_night`
链尾交出睡下等待点——与附录 C §4 一致,无偏差;死窗内 ghost 手势不算输入。
## 3. 台词类别映射
增量清单(新增 14 / 修改 10 / 删除 5)见 `tools/voice_lines_26/teahouse.md`,
登记副本见 [20-teahouse-voice-ids.md](20-teahouse-voice-ids.md) R2 增量节。类别口径:
- `critical`(不可打断,busy 回执):sys_first_tap、sys_tap_start(开场指令);
tut_d0/tut_tea/tut_water/tut_steep/tut_serve(教学指令 = 规则唯一一次说明);
brew_start(单句短链,防滑动打断后预览失联);res_good/plain/wrong(结果关键句);
rent_due/rent_short(账目关键句);sys_continue_ask/sys_reset_ask(问询句);
打烊结算链整链(close_open → close_coin_* → [debt/rent/chapter] → settle_night)。
- `content`:night_*、intro_1/2、serve_link/bridge_*、amb_*(氛围客转述)、
st_guest/rep/purse(状态链)、tea_*(口诀随身)、settle_night、upg_*、
sys_turn_teach、sys_unlock_up/down/dt(阶梯教学句)、hint_water(菜单回灶复述)、
recap_go、反应链 NPC 句(sig_* 为 sfx 不占)。
- `hint`:wp_tap_short(intro/reopen/close/drill 的 _short 档)、wp_tea_full/
wp_tea_short、wp_up_short(D5)、gd_close(close 等待点 full 档复用)、
sys_say_again(主动重听前缀,全项目一句,资产每游戏各存一份)。
- `feedback`(idle-only,原则 7 每格一次):water_early/ok/late、steep_early/ok/late
(判定即归因,2 秒内真话)、inv_up_locked/inv_down_locked/inv_serve_swipe、
gd_invalid(TITLE/OPENING/CLOSE 滑动、长按)。
- 引擎播出(`engine/novice.js teachLine` / `engine/hints.js requestReplay`):
sys_unlock_up/down/dt、sys_say_again——资产照常落 `web/teahouse/audio/voice/
{female,male}/`。
- 废止口径(26 §7 反模式 5 / §4.10):「双击提壶/双击出汤」(tut_water/tut_steep
旧文)、「双击动手」(tut_skip)、「单击切换,双击确认」菜单(sys_menu 旧文)、
intro_3 规则念白、tut_status/gd_serve/gd_brew 旧看门狗——全部停用或重录。
## 4. 测试记录
- **无头 playtest**:`web/teahouse/test/playtest.mjs` **216 断言全绿**
(`tools/node/bin/node web/teahouse/test/playtest.mjs` 退出码 0)。覆盖:
§4.10 开场链与教学七步(D0–D6,单击版)+ 二周目 drillDone 开场;§4.1/§4.2
交互矩阵(跳句 ok/防连点 busy/滑动打断并推进/关键句 busy);手势阶梯三解锁
(含链播中下滑开菜单);判定三元组 9 组合 + 水声 700/350ms 与滴答时间线 +
超时自动过老/自动出汤;分层铁律(WATER/STEEP 窗内 voice=0);剧本 A 五晚逐晚
对账(27/35/31/56/49 文 + 口碑跨档双向 + 置办三件 + chapter_end)与剧本 B
贴钱营业(debt 20→9→clear→17,无 game over);CLOSE 800ms 死窗 + 链锁;
三档提示 12s/30s 与迷茫接管 L1/L2/L3(替提壶拨将沸);断点复述(BREW 中断
存档带 inBrew、复述链序、summary 规则);菜单/置办真话门/E3;键盘变体候选链;
**§6.2 乱点机器人**(无声操作 0 / 被动原句重复 0 / 打断失败 0 / 首操作 ≤10s /
首成功 ≤20s,走完第一晚打烊);资产缺失 Floor 哨兵兜底;静态审计(全部播放
id 在台词表内、无未捕获异常)。
- **玩家感知转写**:`web/harness/sessions/teahouse.mjs` 已同步 26 号口径
(单击提壶/出汤、菜单左右滑+单击确认、教学不可跳、`floor.state` 链级门控、
打烊段等待态收束),`tools/node/bin/node web/harness/transcribe.mjs teahouse`
(含 `--session sessionStress`)两剧本零死锁跑通:主线虚拟 243s(教学零替打、
三客全 good、上滑对账、睡下进 N2);乱按 276s(标题乱划、教学乱试探、心急
提前提壶被真话归因、菜单乱逛、照样走到打烊睡下)。
- 真人冷启动:待测(26 §6.3,3~5 人)。
## 5. 引擎缺口(报主会话)
- **floor.killChain 后不暴露被杀链进度**:`Floor.handleInput` 对滑动先
`_killChain()`(`_chain = null`),游戏侧随后 `currentId()` 恒 null,菜单
「从被停句续播」无法实现(本次按「从链首重播」落地,见偏差 4)。建议 floor
保留 `_lastKilled = { ids, i }` 并暴露 `lastKilledChain()`——所有走「下滑开
菜单停链」语义的游戏受益。
- 其余六模块(floor/receipts/hints/confusion/novice/pipeline)本轮无缺口:
pipeline `doubletapCore` 选项、novice `teachLine` 带 voice/ 前缀、confusion
record 前置新手门,均已按 2026-10 修复版接线。