Files
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

13 KiB
Raw Permalink Blame History

26-apply · 《守塔人》重构施工单(26 号文档落地)

设计单正文见 21-keeper.md 附录 C(一句话核心动作、状态×手势 矩阵、等待点配置表、首 3 分钟逐秒脚本、失败表——不在本文重复)。本文件是瘦版 施工单:只写实现接线、偏差记录、台词类别映射、测试记录。台词登记见 21-keeper-voice-ids.md R2 增量节;清单见 tools/voice_lines_26/keeper.md。交互权威: 26-audio-interaction-playbook.md。 范式对齐 26-apply-storyline.md(纯叙事主参考)、 26-apply-radio.md 与 26-apply-abyss.md (叙事型 + 双音色组同型——KEEPER/SHORE 与 HOST/PROD 同构;pendingChoice 缓存、 打断快照 _chainSpeaking、sessions 范式重点参考 abyss)。

1. 一句话核心动作

听一夜值守,单击继续;听到选项时左右滑:守灯还是救人、说出还是守住。

2. 实现接线(web/keeper/game.js + index.html)

六模块(§4.1/§4.2/§4.3/§4.4/§4.5/§4.12)全部接通,玩法核心(风暴夜时间轴 INTRO→C1→CALM→C2→CALM→C3→p9→ENDING、回忆插叙三段、trust×truth 双标量、 9 抉择 4 结局、KEEPER/SHORE 双音色 + NPC 三代声、800ms 级结算保护、底噪互斥 vinyl/storm、雾角四处兑现、存档 summary)不动,交互层整体换成 26 号模式:

  • 接线: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()(叙事类长按不占用:setRateBoostEnabled(false),新手期 longpress 由管道判 invalid)。index.html 照 storyline 同构: makeInputPipeline({ floor, confusion, receipts, invalidHints, game, ladder, opts: game.PIPELINE_OPTS }) + attachGestures(root, pipe, { doubleTapWindow: 0 }), 启动遮罩保留。doubleTapWindow: 0 → 未解锁双击由管道折算成 tap。
  • onGesture 返回值收口(§4.2):'ok'(继续/抉择/菜单/状态)|'hold' (重听、菜单换项——等待点保留)|'silent-ok' 本作无(无即时内容音手势)| 'invalid'(pipeline 给回执 + explainOnce + 迷茫信号 + settleWaitPoint(false))。
  • 语音链 = floor.speak(critical/kind):节点链全部改走 floor;拆链实现句级 critical(abyss _speakNodeVoices parts 模式)。跳句/打断由 floor 收口: tap=consumed 跳本句、滑动=打断并执行、critical=busy——旧 PROMPT_RE 门 / 锚句 空点 beat 震 / F4 恢复锁 / F5 交接尾句保护 / G5 首播锁被结构性消解。
  • 等待点(§4.4 附录 A):intro(6/15s)|continue(13/30s)|choice(25/50s, full=当前 pN 且链播即登台账)|settle(20/45s)|reopen(12/30s)|menu(20/45s)。 三档提示 + 30s 台账 + 主动重听「再说一遍:」全在 engine/hints.js。
  • 开场 §4.10:冷启动第一句 = sys_first_tap(critical 指令句,0~3s 动手); 第一下单击 → [b_open, b_rain](雾角挂 b_rain 播完)→ b_goal 极短目标 → continue 等待点;sys_turn_teach 挂 amo_a 链尾、「轮到你」状态声首现教学, sys_skip 挂 amo_b 链尾(radio z1_a/z1_b 先例)。b_rule 开场规矩念白与 gd_brief 操作念白废除;重开新夜链 = sys_new_night → b_open → b_rain(雾角) → b_goal,教学句不再播(原则 11)。
  • 手势阶梯(§4.3):第一次抉择(choose 首次)→ ladder.onGoal() 解锁上滑, 「对。」(sys_praise)挂下一段链头、教学句挂链尾;第一结局(enterEnding)→ ladder.onGameDone() 解锁下滑/第 3 局双击,教学句挂结局链尾。teachLine() 已带 voice/ 前缀,游戏侧直接引用不拼前缀。
  • 上滑「我在哪」(21 附录 C §3:时位句先行 → 信任档 → 一个动作): now 线 = prog_m{act} → tr_{tier} → tru_{truth} → 动作尾巴(choice 等待= status_choice / 其余= sys_hint_continue_full);MEMORY = prog_mem_* → tr_* → tru_* → sys_mem_back;ENDING = 结局主句 → tr_* → settle 动作句。 状态句全量 markHintSaid(原则 9);播完回原等待点(radio 口径 resumeTurn, 档位计数保留),等待点不在(旁白被打断/自动流)则按来源重建,不重播节点。 G6 顺序(prog → tr → tru)由 playtest 断言锁定;G2 的 tr_thin 附 warning 震 保留首夜首幕豁免(自然起点不是警告)。
  • 断点复述(§4.12):每抉择结算、CALM/ENDING 进入、菜单「保存并回大厅」写 soundgame.progress.keeper(含 timeline 时空位 + goalMet/turnTaught/skipHintShown 教学标志;summary 必带;MENU 落盘记回原状态)。回来:sys_continue_ask 询问 (tap=继续上次 / right=新风暴夜);MEMORY 存档恢复链 = prog_m → prog_mem → 重播当前回忆句起链(首句 critical,F4 等价),≤5s 回到可玩。
  • 迷茫检测(§4.5):confusion 信号(含管道在 invalid 时 recordInvalid、等待点 静默阈值喂 recordSilence)→ 当前等待点三级接管(L1 短句 → L2 只留期待手势 → L3 演示:intro/continue 替玩家走一步,choice 只复述方向不替选)。

3. 偏差记录(与 26 号手册 / 21 号附录 C 的实现偏差)

  1. 800ms 结算死窗升级为整句 critical(abyss 先例):结局链首句(e1~e4_a)、 c3_dark(灯灭差分插播,auto+@x 尾句锁)、rev_teach(时空教学)、插叙锚句首播 (rev_g1/g4、rev_f1/f5、rev_c1/c5)、恢复链首句(_resumeGuard)整句 critical ——tap/滑动给 busy 回执不截链,覆盖旧 _settleGraceUntil 800ms 定时窗且更强。 插叙入口 600ms 静默拍期间 floor=BUSY,手势同样 busy 回执(死窗语义等价)。
  2. p 选项句整句 critical*(radio 口径):p1~p7、p8_boat/p8_reef、p9a/p9b 首播 不可跳(tap=busy),链播即 markHintSaid——被动提示永不逐字复述选项。21 附录 C §8 台词表把 p* 归 content 指内容属性;矩阵 §4「p* 首播不可跳」以 critical 落地。
  3. 旁白链滑动 = 缓存抉择 + 跳选项句(abyss 模式,兑现矩阵 §4「缓存抉择,不 盲选」):旁白(含被打断快照 _chainSpeaking)中 left/right 若落在抉择点 (本节点 next 直入 p*),缓存 pendingChoice 并 playNode(p*);选项句整句 critical 播完当刻缓存生效(ui_confirm → 结果节点,W2 契约 + 盲玩公平)。非抉择点滑动 → invalid + _recoverInterrupted 交回 continue 等待点(零无声死锁)。
  4. MEMORY 打断恢复 = 重播当前回忆节点:插叙是 auto 链不设等待点;滑动打断/ 双击重听/菜单关闭/上滑播完都从「当前回忆句」(memIdx,由 audio.play 钩子实时 维护)重播起链,复播不锁锚句(G5 复播可掐);链末照常自动回返现在线。 MEMORY 中 left/right = invalid(插叙无选择,21 附录 C §4)。
  5. CALM 幕间为自动流(BUSY):链播中 tap=跳句(consumed)、空档手势=busy; 滑动打断后不重交话轮——_ensureWait CALM 分支直接挂喘息定时器推进下一幕 (radio BRIDGE 同款)。跨档 tr_* 账目在链构造时结清(radio enterBridge 口径; 不再逐句起播钩子)。
  6. 等待声:六等待点统一引擎合成「嘟—嘟」bed;插叙/幕间/危机拍为 BUSY 演出 态无等待声(原「统一 8 音词表纪律、时空不换 earcon」继续成立——本作不新增 任何 earcon,时空签名全靠内容层底噪/BGM/锚句)。
  7. 过渡音 idle 门简化:memory_in/out、static_burst 只在语音空闲时播出(原 「挂队句间补发」依赖游戏层句级钩子,floor 时代无此钩子;调用点全在链入口前, 在播即丢弃,playtest 断言成对性不受影响)。
  8. _chainSpeaking 打断快照为游戏层补丁(abyss 同款):pipeline 的 floor.handleInput 对滑动「打断并执行」先杀链置 BUSY,游戏侧 floor.speaking 已 false——快照在 speak 置位、onDone/interrupt 清零,让被掐断的旁白链按矩阵 落「旁白中」分支(上游修复后可撤)。
  9. 旧交互债务清除:双击=重听节点旧口令废止(阶段 3 起=重听当前等待点完整句 /当前回忆节点);菜单改 00 号 §5.4(左右滑换项 + 单击确认,旧「单击循环+双击 确认」= 26 §7 反模式 5);guide 层看门狗双轨/无进展轨/sys_help 帮助溢出全部 废止(三档提示 + 迷茫接管 + 手势阶梯取代)。

4. 台词类别映射(类别标注;增量清单见 tools/voice_lines_26/keeper.md)

  • critical:sys_first_tap(开场 ≤3s 唯一指令);p1p7、p8_boat/p8_reef、p9a/p9b 选项句(整句,首播不可跳);rev_teach(时空签名教学,全局一次);插叙锚句首播 六句(rev_g1/g4、rev_f1/f5、rev_c1/c5);c3_dark(灯灭差分);结局链首句 (e1e4_a);恢复链首句(F4 等价)。
  • content:b_、c、amo_、rev_ 中段句、e*b、ep、prog_m1..3、prog_mem_g/f、 tr_deep/half/thin、tru_zero..full、lull_1/2、sys_turn_teach、sys_skip、 sys_unlock_、sys_new_night、sys_continue_ask、sys_menu、menu_help、 sys_menu_resume/restart/lobby、sys_settings。
  • hint:sys_hint_continue_full/short、sys_hint_choice_short、sys_hint_again_full、 sys_hint_menu_short、sys_only_choice、sys_demo_continue、sys_demo_choice、 sys_mem_back、status_choice、sys_say_again(「再说一遍:」前缀,engine/hints.js 播出)、sys_first_tap_short。
  • feedback:inv_nosel、inv_mem、inv_generic、inv_up_locked、inv_down_locked、 sys_praise(「对。」首抉择链头)。
  • 音色组:系统/交互层句子全部 _SHORE(岸台值班员=系统音,与 radio PROD、 abyss DECK 同型);剧情守塔人 _KEEPER、NPC 平铺(阿澈/父/祖)不动。通用系统 句与 STORYLINE_LINES 的 sys_* 段逐字一致;键盘变体照 KEY_LINES["storyline"]; 多音字「重听」→「重新听/再听一遍」。
  • 完整登记(新增 24 / 修改 1 / 删除 8)见 tools/voice_lines_26/keeper.md 与 21-keeper-voice-ids.md R2 增量节。

5. 测试记录

  • 无头 playtest:web/keeper/test/playtest.mjs 272 断言全绿(tools/node/bin/node web/keeper/test/playtest.mjs 退出码 0;node --check web/keeper/game.js 通过; game.floor.bedEnabled = false 防周期定时器不排水)。覆盖:§4.10 首 3 分钟 (3s 内动手、critical 指令句、规则念白零播出、开局 40s 内听到阿澈);剧本 A~F 六路径 四结局 + 信任/真相逐档验算 + 尾声回响差分;时空签名(vinyl 与 storm/room/engine 播放区间零重叠、memory_in/out 成对 ×3、BGM 切换、危机拍前置 2s);上滑状态链 G6 顺序(prog → tr → tru → 动作)与 tr_thin 首夜豁免;pendingChoice 时序 (旁白滑动缓存 → 选项句播完 → ui_confirm → 结果句);锚句首播 critical / 复播可掐;结算保护(结局链/c3_dark 首句 critical,幽灵手势不截链);等待点三档 (continue 13/30、主动重听「再说一遍:」);迷茫接管三级;手势阶梯(阶段 1/2 教学句挂链头/尾);§4.12 断点复述(ASK 左/右、MEMORY 恢复链时位句先行、F4 恢复首句锁);菜单(左右滑换项 + 单击确认 + 插叙中开关菜单底噪不丢);CALM 幕间打断后喘息照走;资产缺失续链(Floor 哨兵 3s 宽限);键盘变体路由; §6.2 乱点机器人:无声操作 0、被动原句重复 0、打断失败 0、第一次操作 ≤10s、第一次成功 ≤20s、乱按不锁死(零死锁收在合法等待态或结局);静态审计 (无运行时 id 拼接、8 句废止台词零引用、20 条游戏引用新台词待生成豁免 + 引擎侧 4 条入清单一致)。
  • 玩家感知转写:web/harness/sessions/keeper.mjs 已同步 26 号口径(开场第一下 tap、floor.state 链级门控、菜单左右滑换项+单击确认、插叙中不动手——「回忆没有 选择」、CALM/危机拍 BUSY 段等它走完),tools/node/bin/node web/harness/transcribe.mjs keeper(含 --session sessionStress)两剧本零死锁 跑通(主线虚拟 290s 到 E1 灯与归人;乱按剧本 643s 同样走完结局链)。
  • 新语音资产(24 句 SHORE 组 + 键盘变体)由主会话统一生成;playtest mock 与真实 资产解耦(voice 层按可用处理,Floor 哨兵兜底缺失)。
  • 真人冷启动:待测(26 §6.3,3~5 人)。