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 资产/开发 ▶ 进行中)
This commit is contained in:
@@ -0,0 +1,539 @@
|
||||
# 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](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'})
|
||||
|
||||
```json
|
||||
{
|
||||
"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 文末自查)。
|
||||
Reference in New Issue
Block a user