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 置完成。
137 lines
11 KiB
Markdown
137 lines
11 KiB
Markdown
# 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 修复版接线。
|