Files
SoundGame/docs/design/26-apply-abyss.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

143 lines
12 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 号文档落地)
> **设计单正文见 [17-abyss.md](17-abyss.md) 附录 C**(状态×手势矩阵、等待点配置、
> 首 3 分钟逐秒脚本、失败表、氧气经济与四结局判定——不在本文重复)。本文件是瘦版
> 施工单:只写实现接线、偏差记录、台词类别映射、测试记录。台词登记见
> [17-abyss-voice-ids.md](17-abyss-voice-ids.md) R3 增量节;清单见
> `tools/voice_lines_26/abyss.md`。交互权威:[26-audio-interaction-playbook.md](26-audio-interaction-playbook.md)。
> 范式对齐 [26-apply-storyline.md](26-apply-storyline.md)(叙事型主参考)与
> [26-apply-radio.md](26-apply-radio.md)(双音色组同型 + HOST/PROD 系统句归类先例)。
## 1. 一句话核心动作
**听一段深海救援:单击继续或发声呐脉冲;听到选项时左右滑做决定。**
## 2. 实现接线(web/abyss/game.js + index.html)
六模块(§4.1/§4.2/§4.3/§4.4/§4.5/§4.12)全部接通,玩法核心(节点链 + seqToken +
pendingChoice 骨架、氧气步进经济、9 抉择、4 结局 + 尾声回响、DIVER/DECK 双音色 +
NPC 平铺、存档 summary)不动:
- **接线**:`this.receipts = new Receipts(audio)`、`this.floor = new Floor(audio)`、
`this.confusion = new Confusion({ onConfused: (lvl) => waitPoint?.takeover(lvl) })`、
`this.invalidHints = new InvalidHints().bind(this.floor)`、`this.ladder = new GestureLadder()`
(构造时按 `ladder.stage() >= 3` 开旁白加速)。`index.html` 照 storyline 同构:
`makeInputPipeline({ floor, confusion, receipts, invalidHints, game, ladder,
opts: game.PIPELINE_OPTS })` + `attachGestures(root, pipe, { doubleTapWindow: 0 })`,
启动遮罩保留。
- **PIPELINE_OPTS = `{ longpressCore: true }`**:长按由游戏层裁定——新手期 invalid
(回执 + gd_invalid 首次解释),阶段 3 起 = 引擎旁白加速(`hold`,等待点保留)。
doubleTapWindow: 0 → 未解锁双击由管道折算成 tap(搜索等待=再发一枚脉冲)。
- **`onGesture` 返回值收口**(§4.2):`'ok'`(继续/抉择/菜单/状态)|`'hold'`
(重听、菜单换项——等待点保留)|`'silent-ok'`(**搜索等待单击=发脉冲**:声呐脉冲
即内容音,省 ok 回执)|`'invalid'`(pipeline 给回执 + explainOnce + 迷茫信号)。
- **打断快照 `_chainSpeaking`**(本轮新增,见偏差 5):pipeline 的
`floor.handleInput(滑动/长按)` 按 §4.1「打断并执行」先杀链把 floor 置 BUSY,游戏侧
`floor.speaking` 已为 false——`_chainSpeaking` 在 speak 置位、onDone/interrupt/
`_yieldTurn` 清零,让被掐断的旁白链按矩阵落「旁白中」分支(滑动命中抉择点 →
缓存 pendingChoice + 跳选项句;未命中/长按 → `_recoverInterrupted()` 交回 continue
等待点,零无声死锁)。
- **pendingChoice(V1 播完才生效)**:旁白链中滑动只缓存方向并跳去 p* 选项句
(`_swipePromptTarget`:本节点是抉择节点或 next 直入抉择节点);p* 整句 critical
(tap=busy 不可跳),`_armChoice` 在选项句播完的当刻让缓存生效:ui_confirm 结算音 →
结果句,零插播(W2 契约 + 盲玩公平)。
- **critical 清单**(§8 台词类别 / 结算死窗等价实现):sys_first_tap(开场第一句)、
dv1_teach(下潜链尾教学句)、p1~p9 选项句(整句)、lockFirst 节点首句(g9_in /
c_none / dry_a / dry_b——结算链首句死窗)、结局链首句、恢复链首句(F4:
`_resumeGuard` 播完即清)。**替代旧 800ms 手势死窗**:覆盖整句而非定时窗。
- **sonarGate(§5 声呐与语音互斥)保留**:信息类声呐音(echo_*/pipe_knock)只在
voice idle 时播出,否则挂队、链歇补发(`_sonar`/`_drainSonar`);玩家脉冲只在
搜索等待(voice 恒静)受理,按构造不重叠。
- **声呐步 = BUSY(`_runSteps` + `_seqBusy`)**:pre/post 信息音、危机前置(spark_flash/
landslide 前置 2s + danger 震循环 ≥1000ms 间隔)期间手势统一 busy 回执——旧
「tap 快进回波余音」废除。
- **存档(§4.12/§7)**:DIVE 进入、SURFACE 进入、每个抉择结算后、ENDING 进入、
stop() 退出、菜单「保存并回大厅」前(leaving 标记);MENU 态落盘记回原状态;ASK
态不落盘(stash 原存档才是真进度)。runs 口径 = `newRun()` 时 +1(冷启动 0 起;
ASK 右滑与结算单击同口径)。
- **手势阶梯教学句挂链尾**:第一次脉冲成功(`_firePing` → `ladder.onGoal()`)→
`sys_unlock_up` 挂本条回波链尾;一局结局(`enterEnding` → `onGameDone()`)→
`sys_unlock_down` 挂结局链尾。`teachLine()` 已带 `voice/` 前缀(novice.js 修复后
语义),游戏侧**直接引用不再拼前缀**(双前缀是曾出现过的坑,静态审计拦截
`` `voice/${` `` 模板拼接)。
- **上滑「我在哪」**(§3/§9 顺序:潜次 → 已救人数 → 氧档 → 一个动作):`interrupt` 摘
等待点(状态链期间静默 timer 清零,见偏差 6)→ 状态句全量 `markHintSaid` → 播完
**按原等待点类型重建**(搜索重挂/抉择重挂/结算/continue——radio 口径不重播节点)。
crit 档附 warning 震按档进入去重;`oxy_crit_deck` 水面变体(R2-F5)保留。
## 3. 偏差记录(与 26 号手册 / 17 号附录 C 的实现偏差)
1. **搜索等待声(17 号 §2)**:引擎 Bed 为全局统一音色,游戏层在 ping 等待点置
`floor.bedEnabled = false`——等待声由 amb_deep 常驻 + 回波余音的深海声场承担
(`_yieldTurn` 按等待点 id 翻转)。测试侧统一压 false(mock 防周期定时器不排水)。
2. **critical 粒度**:floor 的 critical 是整链一刀切,句级保护靠**拆链**实现
(`_speakNodeVoices` 按 critical 分段顺序播)。非 auto 叙事节点的尾句**不做**首播
critical——链级一刀切会把「滑动打断并执行 / 上滑我在哪」一并挡成 busy(§4.1
宪法);叙事尾句跳过的代价只是提前进等待点,由三档提示兜底复述。
3. **auto 过场链尾恒 critical**(`_tailLocked`):dv1_teach(教学句)、s_tier 档位句、
p9 结果链尾、取消链尾——「next 是 @x 过场」时链尾即过场门,不可跳。
4. **搜索等待单击恒出脉冲(silent-ok)**:包括等待声中的抢拍单击——比「轮到你提示音
后才受理」更宽(17 号 §4:再单击=再听);四潜各恰一枚玩家脉冲由 playtest 断言。
5. **打断快照为游戏层补丁**:引擎 pipeline/floor 未提供「这次手势打断了一条链」的
回执,`_chainSpeaking` 由游戏包装 floor.speak/interrupt 维护(上游修复后可撤)。
无效滑动打断旁白 → invalid 回执 + 解释句 + **交回 continue 等待点**(不重播原句,
原则 9;链末单击继续到下一节点)。
6. **引擎缺口(上报,未改引擎)**:`engine/hints.js` 的 `use()` 在 `ledgerSay(id)` 之后
才 `floor.speak`(kind hint)——静默提示到点时恰逢 SPEAKING(如上滑状态链播放中)
句子被丢弃**但台账已记**,之后 30s 内同句被动提示会错降档。游戏侧规避:上滑先
`interrupt`(清 timer,状态链期间零 fire)。建议引擎改为「speak 返回 false 时不登
台账」。同类:`InvalidHints.explainOnce` 的 ledgerSay 也在 speak 前。
7. **结算重开链**:`sys_new_dive → b_open → b_goal → b_go`(重开不念开场教学,原则
11——sys_first_tap/sys_skip 每实例一次);开场链首句 critical 指令、b_goal 极短
目标句、b_rule/gd_brief 规矩念白废除(§4.10)。
8. **状态链动作句**:search=「点一下,发脉冲。」(sys_act_ping 兼首次解释句);
choice=「正在抉择。左右滑。」(status_choice);settle=「单击,开始新救援。」
(sys_hint_settle_full);continue=「单击,继续。」——全部 DECK 组、进台账。
## 4. 台词类别映射(类别标注;增量清单见 `tools/voice_lines_26/abyss.md`)
- `critical`:sys_first_tap(开场 ≤3s 唯一指令);dv1_teach(下潜链尾教学);p1~p9
选项句(整句,含 p7_chen/p7_zheng);g9_in / c_none / dry_a / dry_b(结算链首句
死窗);结局链首句(e1~e4_a);恢复链首句(F4)。
- `content`:b_*、各潜对白(dv*/sv*/z1/bai/chen/gao/d*_e 组)、结局与尾声
(e*_b、ep_*)、prog_d1..4、prog_saved1..5、oxy_full/ok/low/crit/crit_deck/gain、
sys_turn_teach、sys_unlock_*、sys_menu、menu_help、sys_menu_*、sys_new_dive、
sys_continue_ask、sys_skip。
- `hint`:sys_hint_ping_full/short、sys_hint_continue_full/short、
sys_hint_choice_short、sys_hint_settle_full、sys_only_choice、sys_demo_continue、
sys_demo_choice、status_choice、sys_say_again(「再说一遍:」前缀,engine/hints.js
播出)。
- `feedback`:sys_act_ping(搜索等待无效滑动首次解释)、inv_nosel、inv_up_locked、
inv_down_locked、gd_invalid(通用格,保留旧句)、sys_menu_restart_confirm(重开
二次确认)。
- 音色组:系统/交互层全部 `_ABY_DECK`(母船调度=系统音,与 radio PROD 同型);
剧情潜水员 `_ABY_DIVER`、幸存者 ABYSS_NPC 平铺(不动)。通用系统句与
STORYLINE_LINES 的 sys_* 段逐字一致;键盘变体照 KEY_LINES["storyline"]。
- 完整登记(新增 23 / 修改 1 / 删除 10)见 `tools/voice_lines_26/abyss.md` 与
[17-abyss-voice-ids.md](17-abyss-voice-ids.md) R3 增量节。
## 5. 测试记录
- 无头 playtest:`web/abyss/test/playtest.mjs` **243 断言全绿**(`tools/node/bin/node
web/abyss/test/playtest.mjs` 退出码 0;`node --check web/abyss/game.js` 通过)。
覆盖:§4.10 首 3 分钟(3s 内动手、critical 指令句、规则念白零播出);剧本 A~F
六路径四结局 + 氧气逐检查点验算 + 氧气门三形态 + 干涸链 + 尾声回响差分;
pendingChoice V1 时序(缓存 → 选项句播完 → ui_confirm → 结果句);sonarGate
零重叠 + 四潜各一脉冲;结算死窗(取消链/结局链首句 critical,幽灵手势不截链);
等待点三档(ping 8/18、continue 13/30、choice 25 台账降档);迷茫接管三级
(L1 短句 → L2 缩小 → L3 替发脉冲);手势阶梯(阶段 1/2 教学句挂链尾);
§4.12 断点复述(ASK 左/右、F4 恢复首句锁、上滑状态链);菜单(左右滑换项 +
单击确认 + 二次确认重开 + 回大厅);资产缺失续链;键盘变体路由;**§6.2 乱点
机器人**:无声操作 0(0/309)、被动原句重复 0、打断失败 0、第一次操作 ≤10s
(2120ms)、第一次成功 ≤20s(2120ms)、乱按不锁死(零死锁收在合法等待态)、
关键路径手势预算 9 ≤70;静态审计(无运行时 id 拼接、11 句废止台词零引用、
19 条游戏引用新台词待生成豁免 + 引擎侧 4 条入清单)。
- 玩家感知转写:`web/harness/sessions/abyss.mjs` 已同步 26 号口径(菜单左右滑换项
+ 单击确认、结局结算后下滑逛菜单——阶段 2 解锁时机、SURFACE 签收链中段链末
单击继续、COMMS 走神触发 13s 首档提示),`tools/node/bin/node
web/harness/transcribe.mjs abyss`(含 `--session sessionStress`)两剧本零死锁
跑通(主线虚拟 279s 到 E1 海燕归钟;乱按剧本同达 E1)。
- 新语音资产(23 句 DECK 组 + 键盘变体)由主会话统一生成;playtest mock 与真实
资产解耦(缺失按可用处理,Floor 看门狗兜底)。
- 真人冷启动:待测(26 §6.3,3~5 人)。