Files
SoundGame/docs/design/21-keeper.md
T
xsl cd4c5ec65a docs(new8): 批次 4 策划落地(21-keeper/22-bridge)——8 款设计文档全部齐备
- keeper:时空双线(风暴/老唱片签名+锚句)、回忆插叙固定时序、trust×truth 双标量、148 句
- bridge:四象限系统状态音(2.0s±50ms 逐毫秒可断言)、告警仲裁 R1-R8+双危机 7 场景穷举、危机事件卡、忠诚账本、154 句
- 13 号文档 §23 六款断言指针;README new8 索引补齐;章程进度账 8 款设计 ☑(批次 2 资产/开发 ▶ 进行中)
2026-09-10 01:02:49 +08:00

51 KiB
Raw Blame History

21 · 《守塔人》(keeper) — 孤岛灯塔叙事 RPG 设计文档

给开发的实现要点摘要

  1. 叙事模式(声命线范式,radio/abyss/cipher 同骨架):节点链 onComplete 串行 + seqToken 打断作废 + pendingChoice 缓存;复制 web/radio/ 结构起步,状态机 6 宏状态(INTRO/WATCH/MEMORY/CALM/ENDING + MENU 覆盖层)。
  2. 手势零豁免:全部走全局默认映射(单击=继续/跳句、双击=重听、左右滑=抉择、上滑=状态、下滑=模态菜单 §5.2 约定、长按=引擎快进)。
  3. 台词依据 21-keeper-voice-ids.md(148 句:双性别 121 + 平铺 NPC 27);NPC 电台/老唱片滤波在资产侧 ffmpeg 带通(radio 先例),引擎零改动。
  4. 本作核心差异层=时空双线(§6):现在(风暴+电台静电)/回忆(老唱片底噪+唱片滤波)全靠音色+底噪签名区分;插叙=节点链 auto(≤6 句/≤90s),进入/回返有固定过渡音时序;不新增 guide earcon(统一 8 音词表纪律),时空签名住内容层(sfx+底噪+BGM+锚句)。
  5. 信任/真相双轻量标量(radio rep 同款纪律,档位措辞逐值为真);软失败=「灯灭过一刻钟/他自己冲滩」叙事差分,零死亡零倒计时(P4);结算链 800ms 手势死窗(abyss/地下城 H1 同款)。
  6. 章程任务 N4(research/new8/00-program.md §2):单局 15-25 分钟、9 抉择点(实选 8-9)、4 结局、分支局部化。
  7. 断言清单住本文档 §9(abyss §21 先例;13 号文档 §23 指针待批次测试轮同步登记)。

1. 概述

  • 一句话:风暴夜,孤岛灯塔的电台里,一声比一声近的求救,牵出你家三代守塔人的秘密——守灯,还是救人;说出真相,还是守住秘密。
  • 题材(声音即世界):黑暗风暴里视觉归零,电台人声=另一条命、风暴与雾角=你的处境、老唱片底噪=过去——「用耳朵守一夜」与纯音频载体天然同构。两个时空只靠音色与底噪区分,声音本身就是叙事本体。
  • 单局:一个完整风暴夜(一条抉择路径)21-24 分钟;风暴从起到歇=天然三幕,分歧局部化在每幕内部;9 个抉择点(实选 8-9 个),4 结局。
  • 核心循环:值守(塔内叙事链)→ 电台(阿澈对白+抉择点)→ 抉择结果 →(关键抉择触发回忆插叙:唱针落下→父辈/祖辈片段→风声回来)→ 回到现在继续值守 → 幕间喘息。跨幕积累「信任」(阿澈信你有几分)与「真相度」(三代秘密翻开几层),风歇前 p9 决定秘密的归宿。
  • 与 radio/abyss 的差异点(骨架同、差异层不同):radio 靠电话音质立「声音即存在」,abyss 靠声呐双通道立「用耳朵找人」;keeper 靠时空音频签名立「回忆会开口说话」——插叙不是过场动画,是给现在抉择供货的信息与重量(发条知识=插叙2 兑现 p7 生死细节;祖父忏悔=插叙3 给 p9 完整真相可说)。
  • 风险预防(本作特有,策划期显式设计):① 时空误认=剧情混乱——签名规格显式教学一次(rev_teach)+上滑时位句+中断复述带时空位(§6.4/§6.5);② 家族人物多音色——三代人+求救者共 3 个 NPC 音色 ≤5,区分度逐人标注(§5.3/voice-ids 头表)。

2. 状态机

2.1 状态列表

状态 内容 BGM guide.state
INTRO 开场链:塔名口播 + 一句规矩 + 今晚目标 bgm/storm explore
WATCH 值守叙事:现在线对白链 + 抉择点 + 结果 bgm/storm explore;抉择点=choice
MEMORY 回忆插叙:auto 链 ≤6 句,首尾锚句,链末自动回 WATCH bgm/memory explore(不新增签名)
CALM 幕间:风暴进度通报(+跨档信任播报),自动链 ≤12s bgm/storm(不切) settle
ENDING 结局链 + 尾声回响(epilogue),结算态 bgm/dawn settle
MENU 模态覆盖层(任意叙事态下滑呼出,暂停一切链) bgm/storm(低响度淡入) menu
  • CALM 自动链 ≤12s:foghorn → lull_N(风暴进度整句)→(跨档才播)信任档位句 → 自动进下一幕;不切 BGM(风暴进程靠 amb_storm 游戏层 gain 分幕:幕一 0.5 / 幕二 1.0 / 幕三 0.7)。
  • 结局链/c3_dark/插叙链入口处盖 _settleGraceUntil = now+800ms 手势死窗(abyss §2.2 同款),窗内手势一律吞掉,关键叙事完整播出。
  • MENU 打开时 guide.disarm() + 取消一切看门狗/自动链;关闭后重播当前节点(局面复述;MEMORY 中关闭=重播当前回忆节点,底噪仍 vinyl)。

2.2 转移图(文本)

                ┌───────────── 结算单击=新风暴夜 ─────────────┐
                ▼                                             │
 INTRO ──链完单击──> WATCH(C1) ──幕一链完──> CALM(1) ──────────┤→ WATCH(C2)
                       │                                        …CALM(2) 同型)…
                       │  p2左/p3左|p4左/p6左 触发:
                       ▼
                    MEMORY ──插叙链 auto──> 回 WATCH(原 now 线续走)
                                                              │
                                    WATCH(C3) ──高潮链完──> CALM-lite(g9) ──> ◆p9
                                                                              │
                                    d9 结果链 ──> ENDING(e1..e4 + ep 回响链) ──┘

 任意叙事态(INTRO/WATCH/MEMORY/CALM/ENDING):下滑 → MENU(模态)
   MENU:单击=循环切换选项 → 双击=确认执行 → 上滑=帮助 → 下滑/「回到值守」项=关闭回原状态(重播当前节点)
  • 全部叙事态为节点链驱动(radio playNode 模式);CALM 与插叙链 auto:true,WATCH 叙事节点链末等待单击(radio 实现核对 #1 同口径)。
  • MEMORY 是显式宏状态(BGM/底噪/存档 timeline 都按它切换),但没有独立等待点:链 auto 完成即回 WATCH;插叙期间开菜单=暂停,关闭=重播当前回忆节点。

2.3 每状态手势映射(6+2 全覆盖,零豁免)

手势 INTRO WATCH MEMORY CALM ENDING MENU
上滑 帮助+状态,随后重播当前段 帮助+状态(时位句+信任/真相档),随后重播当前节点 帮助+状态(prog_mem_g/f 时位句先行),随后重播当前回忆节点 帮助+状态,自动链继续 帮助+状态(结局名+信任档) 帮助(sys_help)
下滑 模态菜单 模态菜单 模态菜单(停插叙链) 模态菜单 模态菜单 关闭菜单
左滑 无效 → error 震+gd_invalid 无效 → gd_invalid(喂无进展轨) 无效 → gd_invalid 无效 → gd_invalid 无效 → gd_invalid 无效 → error 震
右滑 无效 → gd_invalid 无效 → gd_invalid;ASK 态=新风暴夜 无效 → gd_invalid 无效 → gd_invalid 无效 → gd_invalid 无效 → error 震
单击 播放中=跳过本句;链末=进 C1 播放中=跳过本句(p* 与锚句首播不可跳);链末=继续 播放中=跳过本句(锚入/锚出句首播不可跳);无链末等待(auto 回返) 跳过本句(自动链) 再来一夜(新风暴夜) 循环切换选项
双击 重听当前段 重听当前节点台词(含抉择提示) 重听当前回忆节点 重听幕间链 重听结局链 确认执行(菜单约定覆盖重听)
长按 引擎接管:旁白临时 1.7×(12 号 §2.2,叙事类不豁免) 同左 同左 同左 同左 同左(快进菜单语音)
长按松开 引擎接管:恢复 settings.speed 同左 同左 同左 同左 同左
  • 豁免登记:无。六个基础手势全部符合全局宪法默认语义;菜单走 §5.2 R3 模态约定(单击循环+双击确认)。
  • ASK(存档询问态,radio 同款):单击=继续上次 / 右滑=新风暴夜(两者 runs 均 +1,cipher §8 统一口径);上滑/下滑/左滑/双击=无效(error 震+gd_invalid)。
  • 抉择 prompt(voice/p1..p9 及 p8_boat/p8_reef/p9a/p9b 变体)播放中单击不可跳(PROMPT_RE 门)、左右滑缓存 pendingChoice 播完即生效(radio W2 契约照抄)。
  • 继承 radio G5 跳过公平契约:首播必完整(p 首播不可跳 / 插叙首尾锚句与链末关键句保护 / ASK 恢复首句锁)、复播可即掐(锁不随复播重新武装、插叙中段句可跳、复播滑动照常预缓存)*。
  • 无效手势零静默:所有「无效」格均有 error 震 + gd_invalid(onceKey 同局限次,F1.4 idle-only);longpress/longpressend/tapcancel 全状态合法(radio 实现修复 #2 教训)。
  • 键盘通道:三通道并行,游戏代码零改动;操作提示句按 gesture.inputMode() 选 _k 变体资产(§7.3、voice-ids 集中分组)。

3. 抉择树

3.1 全局骨架(三幕共享主干,分歧局部化)

INTRO: gd_brief → b_open → b_rain → b_rule → b_goal ──链完单击──> C1
【C1 幕一·风暴起】教学幕 · 2 抉择(p1/p2)+插叙1 ──> CALM(1) ──> C2
【C2 幕二·风暴顶】2 抉择(p3/p4)+插叙2 +危机拍1 + p5 ──> CALM(2) ──> C3
【C3 幕三·风歇前】p6(+插叙3) + p7 核心 + 危机拍2 + p8 双形态 ──> 签收 ◆p9 ──> ENDING

分支纪律:每幕内部分支、幕末收敛到 CALM/签收句;跨幕只传标量(trust、rev1/rev2/rev3、p7/p9 派生枚举),不生成组合节点。最坏路径与最好路径节点数同型。

3.2 分幕结构(◆=抉择点,〔〕=条件差分,【插叙】=MEMORY auto 链)

【C1 幕一·风暴起】
c1_tune → amo_a → amo_b → ◆p1
   ├左 接住人: c1_hold → c1_holdo → c1_holde(trust+1)─┐
   └右 要船位: c1_ask → c1_asko → c1_aske(即时纠偏)───┤
                                                        ▼
amo_c(回澜号伏笔)→ ◆p2
   ├左 翻暗格: c1_open → rev_teach(全局一次) →【插叙1】→ c1_diary(truth+1)─┐
   └右 守灯:   c1_focus → c1_focuse ──────────────────────────────────────────┤
                                                                              ▼
                          CALM(1): foghorn → lull_1 →〔跨档才播 tr_*〕→ C2

【插叙1·祖父的年代】memory_in → rev_g1(锚入) → rev_g2 → rev_g3 → rev_g4(锚出) → memory_out

【C2 幕二·风暴顶】
c2_back → amo_d → ◆p3
   ├左 口诀: c2_song → c2_songo →【插叙2】→ c2_key(truth+1)─┐
   └右 岸台: c2_shore → c2_shoreo ─────────────────────────────┤
                                                                 ▼
amo_e → ◆p4
   ├左 真话: c4_true →〔插叙2 未触发 ?【插叙2兜底】+c2_key : 直进〕→ c4_trueo(trust+1)─┐
   └右 带过: c4_pass → c4_passo ───────────────────────────────────────────────────────────┤
                                                                                            ▼
【危机拍1】hull_crack 前置2s 渐强 + danger 签名/震 → c2_crack → amo_f → ◆p5
   ├左 堵漏: c5_patch → c5_patcho(trust+1)─┐
   └右 救生衣: c5_suit → c5_suito ────────────┤
                                               ▼
                          CALM(2): foghorn → lull_2 →〔跨档才播 tr_*〕→ C3

【插叙2·父亲的最后一晚】memory_in → rev_f1(锚入) → rev_f2 → rev_f3 → rev_f4 → rev_f5(锚出) → memory_out

【C3 幕三·风歇前】
c3_eye →〔rev2 ? c3_page → ◆p6 : m6_seal 封锁句(播后自动走右,不摆假选项)〕
   ├左 读完:【插叙3】→ c6_reade(truth+1)─┐
   └右 合上: c6_shut ────────────────────────┤
                                              ▼
◆p7(核心:守灯还是救人;提示句全表最长)
   ├左 离塔救人:〔rev2 ? c7_go(满发条,配 lamp_mech): c7_go2(半卷)〕
   │     →【危机拍2】wave_wall 前置2s+danger → c3_wall → ◆p8_boat
   │       ├左 循渔歌: c8_song → c8_songo ─┐
   │       └右 推坐标: c8_math → c8_matho ─┤
   │                                        ▼
   │     c9_return →〔rev2 ? — : c3_dark(灯灭过一刻钟,800ms 死窗)〕─┐
   └右 守灯引渡: c7_hold →【危机拍2】c3_wall → ◆p8_reef                │
           ├左 老航道: c8_old → c8_oldo ─┐                            │
           └右 新礁缝: c8_new → c8_newo ─┤                            │
                                           ▼                           ▼
                     〔trust≥3 ? c9_land : c9_found〕──────────┴→ 签收(两路通用,电台或塔内对谈)

【签收】g9_in → g9_knot → ◆p9〔truth=3 ? p9a : p9b〕
   ├左 说出:〔truth=3 ? d9_tell_a : d9_tell_b〕→ amo_g → d9_telle ─┐
   └右 守住: d9_keep → amo_h → d9_keepe ────────────────────────────┤
                                                                     ▼
ENDING: e*_a → e*_b(trust 档 × p9 四选一)→ ep_lead → ep_*(条件选播)→ ep_shore

【插叙3·祖父的忏悔】memory_in → rev_c1(锚入) → rev_c2 → rev_c3 → rev_c4 → rev_c5(锚出) → memory_out

3.3 分支局部化说明

  • 跨幕状态全部是标量:trust(int 0-4)、rev1/rev2/rev3(bool,插叙完成数=truth)、p7('boat'|'lamp')、p9(bool)。没有任何「幕 i 分支 × 幕 j 分支」组合节点。
  • 条件差分全部是节点内选播(radio w1_say/w1_say2、abyss p7 双形态先例):插叙2 兜底(p4 左)、c7_go/c7_go2(rev2)、c9_land/c9_found(trust)、c9_return 后 c3_dark 插播(rev2=false)、p9a/p9b 与 d9_tell_a/b(truth)、ep_* 选播。树形不变。
  • 树规模:148 句台词、约 75 个节点;任一路径到达全部 9 个抉择点,p6 在 rev2=false 时被 m6_seal 自动走右(实选 8-9 个)。

3.4 四结局达成条件

结局 条件 主题 开环钩子
e1 灯与归人 trust ≥ 3 且 p9=左 人接住了,真相也说全了 「回澜号的账,翻开了第一页」
e2 守夜人 trust ≥ 3 且 p9=右 人救了,秘密再压一代 「有些东西,再压一代人」
e3 半明半暗 trust < 3 且 p9=左 你说了,他半信半疑 「碎片也是真话」
e4 各自的塔 trust < 3 且 p9=右 隔海两塔,各自沉默 「谁也没再提那晚」
  • 尾声回响(P2 回响感):epilogue 逐项点名——阿澈(接回塔/自渡/天亮被找到,按 p7×trust)、灯的记录簿(满发条自转/灭过一刻钟/整夜未眨眼,按 p7×rev2)、祖父日志(见光/压回黑暗,按 p9×truth≥1)、父亲的班次(rev2=true 替他签字);岸台晨报恒播收尾(b_goal 货轮承诺闭环)。玩家每一层翻开的与守住的都被点名。

4. 数值设计

4.1 变量

变量 类型 初值 说明
trust(信任) int 0 阿澈对你的信任,幕一/二积累,幕三不动
rev1/rev2/rev3 bool false 插叙1/2/3 完成位;truth = 三者之和
p7 str null 'boat'(离塔救人)/'lamp'(守灯引渡),核心抉择派生
endings{} / runs map/int — 结局收集与重玩计数(存档展示用)

4.2 抉择计分表(左=走心·翻开/说出 / 右=克制·程序/守秘)

抉择 左(走心) 右(克制) 备注
p1 接住人/要船位 trust+1 0 左路阿澈声音稳住(首个正反馈);右路 c1_aske 即时纠偏不扣分
p2 翻暗格/守灯 truth+1(rev1=true) 0 左路=插叙1(日志残篇到手,缺最后一页)
p3 口诀/岸台 trust+1,truth+1(rev2=true) 0 左路=插叙2 主触发(发条知识+缺页线索 c2_key)
p4 真话/带过 trust+1;rev2=false 时兜底插叙2(truth+1) 0 插叙2 的第二把钥匙(p3 右的补偿路)
p5 堵漏/救生衣 trust+1 0 双活路(两路都活着,差分在反应句与尾声心境)
p6 读完/合上 truth+1(rev3=true) 0 左路=插叙3(祖父忏悔全量);rev2=false 时左路封锁(m6_seal 播出后自动走右,abyss g9_dry 先例——不摆假选项)
p7 离塔救人/守灯引渡 0(p7='boat') 0(p7='lamp') 核心宿命抉择:不动 trust;后果走 rev2(发条)与 trust(引渡)差分
p8_boat 循渔歌/推坐标 0 0 双活路差分(海上找人方式)
p8_reef 老航道/新礁缝 0 0 双活路差分(引渡路线)
p9 说出/守住 真相出口 秘密出口 不动 trust;提示句按 truth 选 p9a/p9b

4.3 信任档位表(账目真实:每档句义对每个取值皆为真)

档 trust 区间 整句 真实性核验
tr_deep 3-4 「他把命,交给了你的声音。」 ≥3 时 p7 右他完全照做(c9_land)✓;p7 左他海上应答配合 ✓
tr_half 1-2 「他信一半,疑一半。」 1-2 时 p7 右他半路改主意(c9_found)✓
tr_thin 0 「今晚,他只信自己的手。」 0 = 四个信任点全失,p7 右必自渡 ✓(附 warning 震,radio G2 同款)
  • 阈值 3 = 「多数走心 + 容忍 1-2 次克制」落在高信任档——把「他是否把命交给你」压在玩家自己的累计上,而非单点(radio rep ≥5 同款纪律)。
  • 跨档被动播报(挂 CALM 链尾,跨档才播);上滑 status 随时可查。

真相度逐值表(truth=插叙完成数,每值一句、逐值为真)

truth 整句 核验
0 「旧账压在灯底,你一页没翻。」 rev1/2/3 全 false ✓(暗格未开)
1 「灯下的旧账,你翻开了一角。」 仅插叙1(日志残篇)✓
2 「祖父和父亲的事,你都翻到了。」 插叙1+2 ✓(缺页在手未读)
3 「三代人的账,今夜见底了。」 插叙1+2+3 ✓(忏悔全文,p9a 解锁)

4.4 结局与差分验算(设计期穷举,playtest 剧本 A-F 引用)

  • trust ∈ {0..4} 全档可达(四个独立 ±1 抉择 p1/p3/p4/p5);e1/e2 ⟺ trust≥3(如 p1左 p3左 p4左 p5右=3),e3/e4 ⟺ trust≤2(全右=0)。
  • truth ∈ {0..3} 全档可达:rev1=p2左;rev2=p3左∨p4左;rev3=p6左∧rev2。0(p2右p3右p4右)、1(p2左+双右)、2(p2左+p3左)、3(再 p6左)。
  • p6 封锁与 p9 变体联动:rev2=false → m6_seal 自动右;truth=3 → p9a/d9_tell_a(全真相),truth<3 → p9b/d9_tell_b(碎片:只确认「那晚守塔的是我爷爷、灯灭过一下」——前者是家族常识、后者来自阿澈自己的话,truth=0 也句句为真,归因真话律)。
  • 灯三态(p7×rev2):p7 左+rev2 → ep_lamp_full(满发条自转,rev_f4 知识兑现);p7 左+¬rev2 → c3_dark+ep_lamp_dark(半卷发条走到头,复刻祖父之夜,归因指向「没听完父亲那一晚」的实际选择);p7 右 → ep_lamp_hold(整夜未停)。
  • 阿澈三态(p7×trust):p7 左 → 恒被接回(c9_return,人已上艇不失去);p7 右+trust≥3 → 自渡成功(c9_land);p7 右+trust<3 → 天亮被渔队找到(c9_found,活着,措辞克制——零死亡红线)。
  • 最坏路径完整性:剧本 C(全右)仍走完全部 9 抉择点、3 结局分支可差分(ep_amo_dawn/ep_lamp_hold/ep_log 不播)——树深固定,无死路。
  • 纸面承诺安全性:trust≥3 ⟹ p3/p4 至少一左 ⟹ rev2=true ⟹ 缺页在手(c2_key)——e1_a「那页纸攥在手里」/e2_b「缺页放回灯底」对 trust≥3 两结局恒为真;e3/e4(trust<3)文案零纸面引用,truth 任意取值皆不穿帮(归因真话律在结局文案侧的落点)。

4.5 家族秘密 gating 顺序(秘密揭示的三把钥匙与三道门)

层 秘密 钥匙(抉择) 门(插叙) 兑现(现在线收益)
层1 灯下藏着东西 p2 左(翻暗格) 插叙1(祖父:「灯下压着的东西,比灯重」) 日志残篇 + 缺页悬念(tru_one)
层2 父亲的最后一次值守 p3 左(口诀)或 p4 左(真话,兜底) 插叙2(父亲电台:「上满发条能自己转一夜」) 手电缺页线索(c2_key)+ 发条知识(c7_go 差分)
层3 祖父的忏悔(回澜号真相) p6 左(前置=层2 已开) 插叙3(祖父:「我离灯三刻,回澜号,七个人」) p9a 完整真相可说 + e1/e2 重量
  • 顺序不可跳:层3 的门只认层2 的钥匙(m6_seal 封锁);层2 有两把钥匙(p3/p4)保证「错过 p3 仍可全真相」(补偿路,abyss hasLog 双入口同型)。
  • 阿澈的回环:amo_c(幕一伏笔「我爷爷……白角的灯灭过一下」)→ amo_g(p9 左揭晓「我爷爷,就在那七个人里」)——玩家的抉择把两条家族线缝上。

5. 音频三层映射

5.1 BGM(状态→曲目,Mureka instrumental,3 首 ≈ $0.09;台账 tools/mureka_log.md)

状态 曲目 切换 Mureka prompt 草稿(英文,seamless loop)
INTRO/WATCH/CALM bgm/storm 开局淡入 800ms,全夜不切;语音 duck 引擎自理 "Storm night lighthouse vigil, tense low piano motif over dark strings, restrained and lonely, distant thunder and wind, no vocals, seamless loop, 60-90 seconds"
MEMORY bgm/memory 插叙进入 crossfade 800ms;回返淡回 storm 800ms "Old phonograph memory waltz, music box and muted strings with vintage vinyl warmth, fragile nostalgia, slightly out-of-time, no vocals, seamless loop, 60-90 seconds"
ENDING bgm/dawn d9 结果链播完后淡入 1500ms "Calm grey dawn after a storm at sea, soft piano and warm strings, gulls far away, quiet relief, no vocals, seamless loop, 60-90 seconds"
MENU bgm/storm(低响度) 呼出低响度淡入 500ms;关闭淡回 800ms 同 storm(省 1 首,塔内场景同构;abyss menu 用 deck 先例)
  • bgm=0 时全部静默(引擎约定);幕的推进不靠切曲——靠 amb_storm 游戏层 gain 分幕(0.5/1.0/0.7)+ lull_N 进度整句(账目在语音不在音乐)。

5.2 SFX 清单(SA3=Stable Audio 3 / SYN=程序合成;one-shot 真峰值 ≤-3dBFS;amb 循环由游戏层 buffer.loop 实现,radio phone_ring 先例)

id 用途 来源 prompt(英文)/ 合成参数
sfx/amb_storm 风暴底噪 loop(现在时签名①;分幕 gain 0.5/1.0/0.7) SA3 "Storm wind and heavy waves hitting a lighthouse rock, sustained gale, night, seamless loop"
sfx/amb_room 塔内底噪 loop(炉火+木构+雨打玻璃) SA3 "Inside a lighthouse room at night, oil stove crackle, wooden beams creak, rain on glass, seamless loop"
sfx/amb_vinyl 老唱片底噪 loop(回忆时签名②;插叙期间唯一底噪) SA3 "Vintage 78 rpm phonograph record surface noise, warm crackle and hiss, no music, seamless loop"
sfx/memory_in 插叙进入过渡音:唱针落下+转速走稳 SA3 "Phonograph needle dropping onto a record, brief run-in groove then steady rotation, 1 second"
sfx/memory_out 插叙回返过渡音:唱针抬起+轻划 SA3 "Phonograph needle lifting off a record with a short scratch, 0.6 seconds"
sfx/radio_tune 调频找台(C1 首通/信号重连) SA3 "Turning an old shortwave radio dial through static, settling on a weak signal, 3 seconds"
sfx/static_burst 阿澈信号断续气口(信息音,idle-only) SA3 "Shortwave radio static burst with faint ghost of a distant voice, 2 seconds"
sfx/radio_beep 电台接通确认 SYN 双音上行 0.3s(abyss link_beep 同款)
sfx/amb_engine 阿澈侧渔船引擎 loop(通话期对侧 amb,voice 在播时 -6dB) SA3 "Small fishing boat engine running rough in a storm, water sloshing in bilge, seamless loop"
sfx/hull_crack 危机拍1:船板开裂(前置 2s 渐强) SA3 "Wooden boat hull cracking under stress, splintering and groaning, 3 seconds"
sfx/wave_wall 危机拍2:浪墙(前置 2s 渐强) SA3 "Massive wave wall rising and crashing, deep roar, 4 seconds"
sfx/lamp_mech 灯座机械上发条(c7_go;rev_f4 兑现音) SA3 "Clockwork lighthouse rotation mechanism being wound, heavy ratchet clicks, 3 seconds"
sfx/hatch_open 灯座暗格开启(c1_open) SA3 "Old hidden compartment sliding open, metal and wood scrape, 2 seconds"
sfx/flash_click 手电尾盖旋开两响(c3_page) SYN 两次短金属 click(120ms 间隔)
sfx/foghorn 雾角两长一短(b_rain 承诺音:开场/幕间×2/ep_shore) SA3 "Lighthouse foghorn, two long and one short blast, deep brass, distant storm behind, 4 seconds"
sfx/ui_confirm / ui_menu 菜单/确认(程序合成兜底) SYN 同全局先例
  • 预警窗纪律:hull_crack/wave_wall 均前置 2s 起渐强(L2),danger 签名与 danger 震同窗(radio C5/abyss D2-D4 先例);全游戏仅此两处 danger。
  • 承诺兑现绑定:foghorn 在 b_rain 口播「两长一短」后,开场/CALM(1)/CALM(2)/ep_shore 四处必播(§6.5 清单 + §9 断言计数)。

5.3 Voice 划分(详见 21-keeper-voice-ids.md)

组 声部 落位 数量
守塔人(你)KEEPER 双性别(female=Serena / male=Uncle_Fu + KEEPER instruct 常量) voice/female|male/ 42 句
岸台/系统/向导 SHORE 双性别(female=Vivian / male=Dylan + SHORE instruct 常量) voice/female|male/ 79 句
NPC 平铺 ×3 阿澈=Dylan(电台滤波)/ 父亲=Uncle_Fu(唱片滤波)/ 祖父=Eric(唱片滤波),不做双性别 voice/ 根(平铺回退命中)+ 滤波转码 27 句
  • NPC ≤5 约束满足(3 人);玩家自己的声音跟随全局 settings.voice;岸台值班员是向导人设(L4 角色化系统声,radio 导播/abyss 调度同型)。
  • 合计 148 句(≤160 预算 ✓,含 _k 键盘变体 8 对);音频文件 = 121×2 + 27 = 269 条(×2 格式 = 538 文件)。

6. 时空双线设计(本作核心差异层)

6.1 引擎能力边界(对照 web-engine-api.md)

能力 引擎现状 方案
voice 运行时 EQ/滤波 ❌ voice 链无滤波插入点 资产侧转码滤波(radio §6.2 先例):ffmpeg highpass+lowpass+压缩器 逐 NPC 定档(§5.3/voice-ids)
BGM crossfade ✅ fadeMs 800ms 内置 插叙进入/回返直接 play('bgm/...') 切换
sfx 循环 ❌ 即发即弃 游戏层 buffer.loop=true 持句柄(amb_storm/amb_room/amb_vinyl/amb_engine),插叙切换时淡入淡出(radio _ringSrc 先例)
sfx vs voice 互让 ❌ sfx 总线独立无 duck 游戏层 idle 门(§6.6 R1):memory_in/out、static_burst 只在 !audio.isVoicePlaying() 时放行,否则挂队列表句间补发
语音 duck 垫乐 ✅ 内置(duck 20%,300ms) 直接依赖
变速不变调 ✅ SoundTouch 直接依赖(长按 1.7× / 2.2× 视障档)

6.2 时空签名规格(误认=剧情混乱,规格逐维度显式)

维度 现在(风暴夜) 回忆(老唱片)
BGM bgm/storm(低音钢琴+暗弦+远雷) bgm/memory(八音盒+老唱片暖染圆舞)
底噪 amb_storm(分幕 gain)+ amb_room amb_vinyl(唯一底噪:storm/room 双双淡出)
过渡音 回返:memory_out + storm 渐起 进入:memory_in(唱针落下)
语音音质 KEEPER/SHORE 不滤波(塔内近讲);阿澈=电台滤波 祖父/父亲=唱片滤波;KEEPER 锚句不滤波(「现在的你」在回忆里旁白——干净人声 vs 唱片人声,强化「你在看回忆」)
时位句 prog_m1/m2/m3(上滑链首段) prog_mem_g / prog_mem_f(上滑链首段 + 恢复链首段)
台词锚 (now 句自然在场) 锚入 rev_g1/rev_f1/rev_c1 + 锚出 rev_g4/rev_f5/rev_c5
  • earcon 纪律:时空切换零新增 guide earcon——统一 8 音词表中 MEMORY/WATCH 同用 explore 签名;时空签名住内容层(sfx 过渡音+底噪+BGM+台词锚),语义靠语音(L2 铁律:earcon 只做粗标记,训练 8.5 轮结论不赌)。
  • 底噪互斥是硬约束:任意时刻 amb_vinyl 与 amb_storm/amb_room 零重叠(§9 转写断言);插叙期间阿澈的 amb_engine 也停(叙事自洽:插叙都发生在塔内独处拍,电台此刻静默)。

6.3 插叙触发与回返时序(精确到步骤)

步 事件 时序
1 now 结果句播完 → 静默一拍 600ms
2 memory_in(1.0s,idle 门放行)+ BGM crossfade storm→memory 800ms + amb 切换(storm/room 淡出 400ms / vinyl 淡入 400ms) 与步 2 同时起
3 插叙链 auto:锚入(KEEPER,不可跳首播)→ NPC 2-3 句(中段可跳)→ 锚出(KEEPER,不可跳首播) ≤6 句 ≤90s
4 memory_out(0.6s)+ crossfade memory→storm 800ms + amb 回切 链末即起
5 回返后 now 句接播(c1_diary / c2_key 或 c4_trueo / c6_reade) memory_out 播完接
  • 插叙链入口 800ms 手势死窗(§2.2);链末不设等待(auto 回返——回忆不是关卡,是信息颗粒);「停下来回味」由双击重听当前回忆节点承接(叙事类等待点合法回味 + 可重听,A2/P1)。
  • 插叙触发点全集(3 处):p2 左→插叙1;p3 左或 p4 左→插叙2(兜底);p6 左→插叙3(前置 rev2=true)。

6.4 「我在哪」复述机制(P3 打断回来说得清)

层 机制
被动 底噪+BGM 时空签名 2s 可辨(A1:有无唱片底噪/风声)
主动 上滑 status 链首段=时位句:now → prog_m1..3;memory → prog_mem_g(祖父年代)/ prog_mem_f(父亲最后一晚)——「现在是回忆」可随时重听确认
台词锚 每段插叙首尾锚句 = 台词级时空位(「唱针落下。四十年前……」「风声回来了……」)
中断恢复 存档带 timeline('now'/'mem_g'/'mem_f');恢复链 = timeline=mem* 时先播 prog_mem_* 再重播当前回忆节点(§9 断言:恢复首句=时位句, ≤5s 回到可玩)
菜单复述 MEMORY 中开菜单关闭后重播当前回忆节点,底噪仍 vinyl(timeline 不丢)

6.5 教学承诺清单(dungeon「铁器=楼梯」教训:每句承诺必须真实存在且可感知)

教学句 承诺 兑现点(断言锁定)
rev_teach「听到唱针落下、风声退后,是回忆。风声回来,就是现在」(全局一次,首插叙前) 时空签名四要素 每次插叙必有 memory_in+vinyl+锚入 / memory_out+storm+锚出;全剧本零漏(§9)
b_rain「雾角两长一短——塔在,我也在」 雾角=塔的报平安音 foghorn 播点=开场/CALM(1)/CALM(2)/ep_shore 恰四处
b_rule「风暴夜,灯不能灭」 灯=规矩本体 灯三态兑现:ep_lamp_full/dark/hold + c3_dark 差分归因(§4.4)
b_goal「今夜两艘货轮过境。守住灯,也守住频道」 货轮/频道双目标 c3_dark「过境的货轮,平安」+ ep_shore 晨报「航道平安」闭环
rev_f4「塔上的机械上满发条,能自己转一夜」 发条知识 p7 左 rev2 差分:c7_go/c7_go2、ep_lamp_full/ep_lamp_dark(剧本 A/E 对照)
prog_m1..3 幕句=风暴三进程 「风暴起/到顶/在退」 CALM 切幕+amb_storm gain 分幕(0.5/1.0/0.7)一致

6.6 通道仲裁规则(并发声流 ≤2)

  • R1 过渡音不叠语音:memory_in/out、static_burst 与任何 voice 播放区间零重叠——idle 门只在 voice 空闲放行,在播则排队到句间空隙(abyss sonarGate 同型)。
  • R2 插叙主导段:前景=插叙链人声+vinyl 底噪,BGM=memory 曲;电台(阿澈)此刻静默,叙事自洽。
  • R3 通话期底噪退位:阿澈通话期间 amb_engine 常驻低响度、voice 在播时游戏层降 -6dB(abyss R3 先例);amb_storm 同步 -4dB——「海况让给人声」。
  • R4 危机拍优先:hull_crack/wave_wall 即发即弃可叠底噪;danger 签名+danger 震同窗;当前 voice 句播完后危机链才插续。
  • R5 回忆可重听:MEMORY 双击=重听当前回忆节点(关键线索可重听,P1);插叙中段句可跳、首尾锚句首播不可跳(G5)。
  • 声流账:任意时刻 ≤2 条前景流(voice 串行 1 + 信息音/底噪 1),BGM/amb 为背景层——ASA ≤2 约束。

7. 向导层接入

7.1 状态签名 earcon / turn cue

时机 向导动作 说明
INTRO 进入 guide.state('explore') 叙事态签名
WATCH/MEMORY 进入 guide.state('explore') 同一枚签名(时空不换 earcon,§6.2 纪律)
每个抉择点 p* 起播 guide.state('choice') 选项句本身即 turn cue(W2 契约零插播)
CALM 进入 guide.state('settle') 喘息/结算签名
ENDING 进入 guide.state('settle') 同上
MENU 打开 guide.state('menu') 菜单签名
危机拍1/2 guide.state('danger') 音效前置 2s 渐强同窗(全游戏仅两处)
无效手势 guide.error({voice:'gd_invalid', onceKey}) error 震 + full 档语音,idle-only(F1.4)
  • earcon 词表:只用全项目统一 8 音(menu/explore/battle/choice/settle/danger/turn/nudge),零新增;battle 不用。

7.2 看门狗双轨(radio F1 + dungeon E0-1 教训:乱按也要被抢救)

无操作轨(guide watchdog,任何手势复位;两级不同句、用尽即停、永不惩罚):

等待点 full 档 standard 档 级别内容
INTRO/WATCH/CALM 链末等待 [25, 50] [13, 30] ① gd_continue ② gd_again(storyline F1.1 同款)
抉择点 p* 播完无操作 [25, 50] [25, 50] 重播当前 p* 提示句(13 号 §16 先例;空点单击=重挂计时)
ENDING 结算等待 [25, 50] [13, 30] gd_continue / gd_again
MEMORY 链末 不挂(auto 回返) 不挂 资产缺失兜底:30s 单句看门狗且 isVoicePlaying()===false 才续(radio N1 先例)

无进展轨(游戏层计时,dungeon E0-1 ②同型;挂 WATCH 链末与 p* 等待两个可饿死点):

项 规则
进展定义 节点推进 / 抉择结算 / 重听。无效手势(滑错、空点)不计进展——无操作轨被它们复位、无进展轨不被复位,乱按 96s 必被抢救
阈值 60s → gd_prog1;120s → gd_prog2;用尽即停(每等待点一轮)
有真实进展 全程零 prog 播出(不误伤正常玩家)
双轨去重 两轨短句内容同级交叉登记;同一等待点先播过 gd_* 同义级则无进展轨跳过
  • 向导插播一律 queue:true,绝不顶掉在播对白;error/watchdog 类语音 idle-only(在播则跳过且过期丢弃,F1.4)。

7.3 键盘变体机制(PC 键盘玩家)

  • 运行时按 gesture.inputMode()(settings.input auto/touch/key)选 _k 变体资产:key → voice/<gender>/<id>_k.*,touch → 无后缀版;auto 跟随最近使用通道。_k 缺失回退无后缀版(check_all_assets 校验配对)。
  • 变体清单(8 对,集中分组见 voice-ids §G0.a 与 C1 首个抉择):gd_brief / gd_continue / gd_again / sys_help / sys_menu / sys_skip / sys_continue_ask / p1(首个抉择的键位绑定)。
  • 抉择提示 p2..p9 措辞统一「向左滑/向右滑」;键盘玩家由 p1_k 与 sys_help_k 完成首次绑定(左=←,右=→),后续语义不变。启动遮罩文案引擎自理(游戏零改动)。

7.4 继承 radio 三轮验证机制(照抄不重设计)

机制 来源 落点
帮助链去重(同等待点第 2 次上滑只震+nudge) radio G1 _helpSeen 按等待点键控(MEMORY 按插叙段键控)
状态链顺序「状态在前、帮助在后」 radio G6 prog_m* →〔mem: prog_mem_〕→ tr_ → tru_* → sys_help
空点确认轻震(不可跳句上单击补 beat [8]) radio G4 p*/锚句/F4 锁各 tap 屏蔽分支
tr_thin 播报位附 warning 震 radio G2 全部 tr_thin 出口(含上滑复听)
菜单报名游戏侧排队零截断 radio 实现修复 #3 _menuQueue 排水
stop() 先 seqToken++ 作废在途链 radio 实现修复 #6 同款
新局清 choiceArmed/pendingChoice radio 实现修复 #7 newNight()
长按误报无效(longpress 全状态合法) radio 实现修复 #2 仅 left/right(ASK 另含 up/down/doubletap)报无效

8. 存档设计

8.1 进度 data 结构(PUT /api/progress {game:'keeper'})

{
  "schema": 1,
  "updatedAt": "2026-09-09T12:00:00Z",
  "summary": "第2幕·风暴顶 · 信任:信一半 · 结局2/4",
  "phase": "WATCH",
  "node": "amo_e",
  "act": 2,
  "timeline": "now",
  "trust": 2,
  "flags": { "rev1": true, "rev2": true, "rev3": false },
  "p7": null,
  "endings": { "e2": true },
  "runs": 3
}
  • 写入时机:每幕 CALM 进入、每个抉择结算后、ENDING 进入、菜单「保存并回大厅」。
  • 断点续玩:读档 → sys_continue_ask(_k)(单击=继续上次 / 右滑=新风暴夜,runs 均 +1 统一口径);继续 = 恢复 phase+node+timeline+全部数值并局面复述:timeline=mem* 时恢复链 = prog_m* → prog_mem_g/f → 重播当前回忆节点(时位句先行,「我在哪个时空」一句话说清);now 则直接重播当前节点链;重进 ≤5s 可玩(L5);恢复首句受 F4 跳句锁(radio G5 例外条款)。
  • summary 格式:进行中 第N幕·<幕名> · 信任<档名> · 结局X/4(幕名=风暴起/风暴顶/风歇前);已收夜 风暴夜已过·<结局名> · 结局X/4(大厅卡片直接显示)。

9. playtest 断言清单(登记 13 号文档 keeper 节,格式同 §21;settings.set({guide:'off'}) 纯玩法验证,向导行为住 guide.test)

关键路径(剧本 A:信任满·全真相·出海接人·说出 → e1,≤60 次手势):

  1. 遮罩点按 → INTRO 链(gd_brief → b_open → b_rain → b_rule → b_goal,voice 层有播放记录)→ 链末单击 → C1:c1_tune → amo_a → amo_b → ◆p1。
  2. p1 左 → c1_hold(o)(e)(trust=1,首个正反馈)→ amo_c → p2 左 → c1_open(配 hatch_open)→ rev_teach(全局一次)→ 插叙1 时序断言:memory_in → bgm 切 memory → rev_g1..g4 → memory_out → storm 回 → c1_diary(truth=1)→ CALM(1):foghorn+lull_1+tr_half(跨档)→ C2。
  3. C2:c2_back → amo_d → p3 左 → c2_song(o) → 插叙2(rev_f1..f5,同款时序)→ c2_key(truth=2)→ amo_e → p4 左 → c4_true →〔插叙2 已完成:兜底不播〕→ c4_trueo(trust=3)→ 危机拍1(hull_crack 前置 2s 与 danger 同窗)→ c2_crack → amo_f → p5 左(trust=4)→ CALM(2)。
  4. C3:c3_eye → c3_page → p6 左 → 插叙3(rev_c1..c5)→ c6_reade(truth=3)→ p7 左 → c7_go(配 lamp_mech,满发条版)→ 危机拍2(wave_wall+danger+danger 震)→ c3_wall → p8_boat 左 → c8_song(o) → c9_return → g9_in → g9_knot → p9a(truth=3 变体)→ 左 → d9_tell_a → amo_g → d9_telle → ENDING(e1):e1_a/b + ep_lead + ep_amo_home + ep_lamp_full + ep_log_told + ep_dad + ep_shore → 结算单击重开回 INTRO。

边界断言:

  • 四结局可达(含信任逐点验算):剧本 B(p1左 p2左 p3左 p4左 p5左 p6右 p7右 p8_reef右 p9右,trust=4/truth=2)→ e2:c9_land + p9b + ep_amo_solo/ep_lamp_hold/ep_log_kept/ep_dad;剧本 C(p1右 p2右 p3右 p4右 p5右 → m6_seal 自动右 → p7右 p8_reef左 p9左,trust=0/truth=0)→ e3:c9_found + p9b/d9_tell_b + ep_amo_dawn/ep_lamp_hold,ep_log_ 两句皆不播*(truth=0 日志未出场)、ep_dad 不播(rev2=false);剧本 D(同 C 但 p9 右)→ e4。各局 trust/truth 逐检查点与 §4.2 一致。
  • 插叙触发与回返:p2 左→插叙1、p3 左→插叙2、p6 左→插叙3 的节点顺序断言;剧本 F(p1左 p2左 p3右 p4左 p5左)断言插叙2 兜底在 c4_true 与 c4_trueo 之间播出且 c2_key 随后播出;回返后 now 线下一节点正确(c1_diary / c2_key 或 c4_trueo / c6_reade);插叙链 auto 完成即回 WATCH(无链末等待)。
  • 时空签名断言(核心):全剧本转写断言——amb_vinyl 与 amb_storm/amb_room 播放区间零重叠;每次插叙 memory_in/memory_out 成对出现且计数=插叙完成数;锚入句(rev_g1/rev_f1/rev_c1)与锚出句(rev_g4/rev_f5/rev_c5)在位且首播不可跳(单击=beat 轻震不跳句);插叙期间 bgm=memory、回返后 bgm=storm;插叙期间 amb_engine 停播。
  • 教学承诺兑现(§6.5 清单逐条):rev_teach 全局恰一次(第二次插叙前不重播);foghorn 计数=开场+CALM(1)+CALM(2)+ep_shore 恰四处;rev_f4→剧本 A 播 c7_go/剧本 E 播 c7_go2(发条差分);b_goal→c3_dark 与 ep_shore 货轮闭环;prog_m1..3 与三幕 amb gain 档一致。
  • p6 封锁不摆假选项:rev2=false 时 p6 提示句不播、m6_seal 播出后自动走 c6_shut,该点左右滑无效果(不丢不误触)。
  • 信任/真相账目真实:上滑链顺序 prog_m* →〔mem: prog_mem_g/f〕→ tr_* → tru_* → sys_help(G6);档位句与当前值一一对应(tr_deep≥3 / tr_half=1-2 / tr_thin=0;tru 四值逐句);tr_thin 各播报位附 warning 震。
  • 看门狗双轨:WATCH 链末 25s/50s → gd_continue/gd_again;p* 播完 25s/50s → 当前 p* 重播两次后静默;乱按 96s(每 2s 注入一个无效滑动):无操作轨零播出 + 无进展轨 60s→gd_prog1、120s→gd_prog2;有真实进展全程零 prog;MEMORY 链末不挂看门狗;guide=off 全程零定时器零向导事件。
  • 键盘变体:settings.input='key' 会话播出 gd_brief_k/sys_help_k/p1_k 且对应无后缀版零播出;'touch' 反之;'auto':keydown 后下一句用 _k。
  • 中断复述含时空位:杀进程重进(存档 timeline='mem_f'、node=rev_f3)→ sys_continue_ask → 单击 → 恢复链首句=prog_m2 → prog_mem_f → 重播 rev_f3 起链(恢复首句不可跳,第二句起可跳);now 态存档(node=amo_e)恢复=重播该节点链。
  • pendingChoice:p* 播放中左右滑 → 播完立即生效(不丢、不重复、连滑取最后一次)。
  • p 不可跳*:p* 播放中单击 → 不跳句(PROMPT_RE 门)+ beat 轻震(G4)。
  • idle-only:向导 gd_* 在对白在播时跳过且不占 onceKey(F1.4);queue 句排在当前句后零截断。
  • 菜单:下滑开菜单 → 上滑帮助 → 双击「回到值守」→ phase/node 不变、当前节点重播;插叙中开关菜单后底噪仍 vinyl、重播当前回忆节点;单击循环顺序 = [回到值守, 重新开始今夜, 保存并回大厅];确认回大厅 → sys_menu_lobby 播出且 PUT/localStorage 有最新 data。
  • 结算链死窗:e* 结局链/c3_dark/插叙链开播后 800ms 内注入在途 tap → 手势被吞、链完整有序播出。
  • 危机拍:hull_crack/wave_wall 前置 2s 渐强、danger 签名与音效同窗、danger 震遍间隔 ≥400ms;当前 voice 句播完危机链才插续。
  • 资产缺失:屏蔽任意 voice 资产 → 30s 看门狗自动续链到结局不卡死;NPC 滤波资产缺失回退原声可播。
  • 数字规范:prog_/tr_/tru_/gd_ 全部整句字面量,静态审计无运行时拼接碎片。

失败即不通过:任何等待 >5s 无声(静默死局);无效手势零反馈;vinyl 与 storm/room 底噪重叠;插叙缺过渡音或缺锚句;结局计数与 §3.4 不符;档位句与 trust/truth 值不符。

10. 节奏曲线(风暴三幕)

段 内容 目标时长 设计目标
开场 塔名+规矩+目标+第一声呼救 1-1.5 min 首输入 ~30s(INTRO 链 ~30s 链末单击);规矩一句讲完(P4);雾角承诺音埋下
幕一 风暴起 p1/p2 + 插叙1 + CALM(1) 4-5 min 首个正反馈 ≤3min(~2.5min p1 左阿澈声音稳住);时空签名教学+首次兑现(rev_teach→插叙1 四要素全播);两抉择条条有出路
幕二 风暴顶 p3/p4 + 插叙2 + 危机拍1 + p5 6-7 min 情感段(父亲真相 p4);第一危机拍(前置 2s 预警);插叙2 供货发条知识(p7 兑现预告)
幕三 风歇前 p6+插叙3 + p7 核心 + 危机拍2 + p8 7-8 min 紧张峰值:三代秘密见底→「守灯还是救人」宿命抉择→浪墙下的执行差分;复刻祖父之夜的暗线(剧本 E 灯灭)
签收+结局 p9 + 结局链 + 尾声回响 2.5-3 min 心结抉择(说/瞒×全/碎片)+ ep 逐项点名(P2 回响);开环钩子拉下一夜
  • 合计 ≈ 21-24 min(15-25 达标);每 30-60s 一个反馈颗粒(阿澈反应句/结果句/档位句/插叙锚句),无沉默尴尬期(P3)。
  • 难度曲线 = 情感与信息复杂度(接住人→翻开过去→宿命抉择→秘密归宿),操作复杂度恒定(永远二选一)——P4「规则一遍听懂」由恒定操作面保证;风暴强度=氛围曲线(amb gain 三档),不构成玩法压力(无倒计时无死亡)。

11. 自检清单(策划交付自验;☐ = 待开发/测试轮填)

# 硬约束/教训 落地 ✓
1 FTUE 首输入 <60s INTRO 链 ~30s 链末单击(§10) ☑
2 FTUE 首个正反馈 ≤3min ~2.5min p1 左阿澈稳住(c1_holdo+c1_holde) ☑
3 学习期零惩罚 幕一全组合不扣资源;右路只即时纠偏(c1_aske);无超时惩罚 ☑
4 失败三问归因+归因真话律 c1_aske/c3_dark/c9_found 指向实际选择;d9_tell_b 在 truth=0 仍句句为真;§4.4 无假归因 ☑
5 资源账目真实(radio rep_low 教训) tr_* 三档逐区间为真;tru_* 四值逐值为真;跨档才播 ☑
6 手势宪法 6 手势默认语义零豁免 §2.3 全覆盖;菜单 §5.2 模态约定 ☑
7 长按显式登记 无豁免:长按=引擎快进(12 号叙事类不豁免),§2.3 在案 ☑
8 向导:签名/turn cue/看门狗两级不同句 §7.1/§7.2;gd_continue→gd_again;MEMORY 链末不挂 ☑
9 看门狗双轨(dungeon E0-1/radio F1 教训) 无操作轨+无进展轨(§7.2);乱按 96s 必被抢救 ☑
10 插播 queue 不顶对白;纠错 idle-only 过期丢弃 §7.2(F1.4 契约);过渡音 idle 门(§6.6 R1) ☑
11 死亡/失败结算链完整(dungeon H1 教训) e* 链/c3_dark/插叙链 800ms 手势死窗;阿澈恒活着(零死亡红线) ☑
12 教学承诺兑现(dungeon「铁器=楼梯」教训) §6.5 承诺清单 6 条逐条绑兑现点+断言 ☑
13 单次播报 ≤3 选项 全部抉择恒 2 选项;菜单 3 项循环 ☑
14 并发声流 ≤2 + 通道仲裁 voice 串行+底噪/信息音互斥(R1-R5,§6.6);断言零重叠 ☑
15 earcon ≤7、统一词表、语义靠语音 只用统一 8 音中 7 个(battle 不用),零新增;时空签名住内容层 ☑
16 台词一句一文件 ≤40 字、数字分档整句、无运行时拼接 voice-ids 全表 ≤35 字(最长 p7);prog/tr/tru 分档整句;句内数字写死 ☑
17 多音字规避/同 instruct 常量/无语速词 voice-ids 头部+文末自查(落/数/缝/卷/转/重 试听项) ☑
18 PC 键盘变体(提示句集中+标注) 8 对 _k 变体集中分组(voice-ids §G0.a);inputMode() 运行时选择 ☑
19 P1:可打断/重听(含回忆节点)/status key/不当白痴 跳句+双击(MEMORY 重听 R5)+上滑时位句链+成功零补救教学 ☑
20 P2:3 分钟见效/结局回响 ~2.5min 阿澈声音稳住;ep 逐项点名(阿澈/灯/日志/父亲班次) ☑
21 P3:3 分钟颗粒/中断复述含时空位/单手 一幕=4-8min 段落+边界存档;恢复链 prog_mem_* 时位句先行;全手势免视单手 ☑
22 P4:一遍懂/容错/无高压倒计时/不骂人 一句规矩;零死亡零倒计时;NPC 句 ≤27 字+逗号停顿 ☑
23 抉择树 4 结局可走通验算 §4.4 穷举+§9 剧本 A-D(e1-e4 各一条实路径)+E/F 差分剧本 ☑
24 单局 15-25 min §10 曲线 ≈21-24 min ☑
25 分支不爆炸(radio 纪律) 跨幕仅 trust+3 bool+p7/p9 派生;~75 节点固定深度(§3.3) ☑
26 台词 ≤160、NPC ≤5 单音色 148 句(双 121+NPC 27)/3 个 NPC 音色(voice-ids 账目) ☑
27 引擎边界诚实 §6.1 能力表:滤波/loop/互让全写明资产侧或降级方案 ☑
28 存档带 summary、断点续玩 §8:data+summary 格式、timeline 恢复链、≤5s、局面复述 ☑

批 1 教训内化确认(5 条全落地)

教训 本作机制 断言
教学承诺必须兑现 §6.5 六条承诺清单(时空签名/雾角/灯/货轮/发条/三幕) §9「教学承诺兑现」块
看门狗双轨 §7.2 无操作轨+无进展轨;无效手势不复位进展轨 §9「看门狗双轨」块
档位措辞真实 §4.3 tr 三档逐区间+tru 四值逐值为真 §9「信任/真相账目真实」块
失败结算链完整不被打断 800ms 手势死窗盖 e* 链/c3_dark/插叙链;seqToken 作废在途链 §9「结算链死窗」块
PC 键盘操作提示 8 对 _k 变体+inputMode() 选择+集中分组标注 §9「键盘变体」块

时空签名教学-兑现验算(本作特有自检)

承诺(rev_teach 四要素) 教学点 兑现次数(剧本 A) 断言位
唱针落下(memory_in) rev_teach 全局一次(首插叙前) 插叙 1/2/3 各一,共 3 §9 插叙触发与回返
风声退后(vinyl 底噪、storm/room 淡出) 同上 3 段插叙全程,零重叠 §9 时空签名断言
唱针抬起+划针(memory_out) 同上 3 次,与 in 成对 §9 时空签名断言
风声回来(storm 回切+锚出句) 同上 3 次(锚句 rev_g4/rev_f5/rev_c5) §9 时空签名断言
「我在哪」三层兜底 上滑时位句(prog_m*/prog_mem_*)+恢复链时位句先行+菜单关闭底噪不丢 全程可查;§8/§9 §9 中断复述含时空位

结局验算(3-4 结局条款 → 定 4)

e1=trust≥3∧p9左(剧本 A:trust4/truth3);e2=trust≥3∧p9右(剧本 B:trust4/truth2,p9b);e3=trust<3∧p9左(剧本 C:trust0/truth0,p9b+d9_tell_b);e4=trust<3∧p9右(剧本 D)。四格互斥完备、各有一条实路径、trust/truth 全档可达(§4.4)。

台词 ≤40 字验算

voice-ids 全表最长 = p7(35 字),次长 p9a/p9b(各 32 字)、d9_tell_a(31 字);NPC 句最长 amo_c(25 字)——全部 ≤40 ✓(逐句账见 voice-ids 文末自查)。