feat(new8/R3): 双游戏收口修复轮 + 验证档案(radio G1-G6 / dungeon E0-1..E1-2)
- radio:帮助链去重(同等待点二次=beat震+earcon,全量口令38→20)/rep_low警告震/空点轻震/状态链重排(状态在前)/「首播必完整、复播可即掐」显式规则登记/G3核查为设计使然转断言;221→246断言 - dungeon:看门狗双轨制(无操作轨+无进展轨,30/60/90s三级升级到导航接管)/跳教学90s自动滚出(2403s→95s内)/踩楼梯到达即报贴身铁器/band1新词「带回来一点,不多」全管线重录/逃跑长按900ms+提示句;1610→1642断言 - R3 验证(进行中已入库部分):全量回归 9/9 全绿;R3 转写×4;P2/P3/P4 终审×6份(radio 满分档首评/三审,dungeon 4/4.5/3-4 全票愿意玩,无P0);两处独立定址同一残余=漫游型迷路刷不响无进展轨(R4 第一条) - 8套件+guide全绿;Mureka 累计 $0.87/$2.00
This commit is contained in:
@@ -482,3 +482,58 @@ V3(arg_muffled/brake_screech 等 11 件 SA3 资产)维持「等待 HF token
|
||||
- dungeon 款全量回归本轮 FAIL:另一 agent 并行改动 `web/engine/{audio,gesture}.js` 与
|
||||
`web/dungeon/**` 进行中(失败点为 dungeon 网格/侧墙与 tut 旁白断言,与 radio 无关);
|
||||
radio与其余 6 款全绿。
|
||||
|
||||
## R3 修复回归(round2 synthesis G1-G6 打磨轮,2026-09-02)
|
||||
|
||||
> 证据源:research/new8/radio/round2/{synthesis,live-player,p1-blind,p3-office}.md。
|
||||
> 断言全部落在 `web/radio/test/playtest.mjs`「R3 修复回归」块 + 主路径/中断复述两处顺序断言改写;
|
||||
> **playtest 断言总数 R2=221 → R3=246(+25)**,全绿。未新增台词/资产(G1 选纯音频标记方案,
|
||||
> 零 TTS 管线动作;voice_text.json / voice-ids 无改动)。
|
||||
|
||||
### G5 显式规则登记(P1 要求,F4/F5 隐式行为升格)
|
||||
|
||||
**规则语句**:radio 的跳过公平契约 = **「首播必完整、复播可即掐」**——
|
||||
|
||||
- **首播必完整**(公平底线,玩家没听过的内容不许被抢跑):
|
||||
1. 抉择提示句 p*(voice/p1..p9)首播不可跳(PROMPT_RE 门),播中左右滑仅缓存
|
||||
`pendingChoice`、句尾当刻才生效(W2 契约零插播;播中连滑取最后一次);
|
||||
2. 链末关键句(等待单击 / `@x` 过场转移 / 直入抉择提示交接前的末句,如蛋糕句、点题句)
|
||||
首播不可跳(F5 链末句保护);
|
||||
3. **ASK 恢复首句例外**:断点续玩恢复链本属局面复述(复播),但其首句仍受 F4 跳句锁
|
||||
保护——首句播完才武装跳句。锁只锁这一句、播完即释放,**不得升级为永久保护**
|
||||
(live 局 B + 会话 C 双向验证:恢复链第二句 0.2s 即可跳)。
|
||||
- **复播可即掐**(效率面,已完整交付过的内容不再强制重听):F4 锁只锁首播一句且播完即释放,
|
||||
**锁不随复播重新武装**(关菜单局面复述 / 双击重听回放同一句时单击照常跳过);F5 只护交接前
|
||||
末句本身,链中段句首播复播均可跳;复播期间播中滑动照常预缓存抉择、句尾即生效(V1 断言)。
|
||||
|
||||
注:p* 复播(双击重听/看门狗复述)仍不可跳、仍句尾生效——比 P1 建议的「复播即掐即生效」更保守;
|
||||
R2 live 已将 4 处截断全数归因玩家 tap 且 P1/P3 均接受现状,按代码实际契约登记并断言。
|
||||
|
||||
### G1-G6 逐条
|
||||
|
||||
| 项 | 选型 / 改法(web/radio/game.js) | 回归断言(✅=已断言) |
|
||||
|---|---|---|
|
||||
| G1 帮助链去重 | **选型:纯音频标记(不加新台词)**。「只震+earcon+sys_help 现有句」方案被否——sys_help 为单文件 26 字整句,无「首句」子资产,重播即逐字重复,恰是待修问题。实现:`_helpSeen`(Set,实例级,不跨实例持久化,sys_skip 每实例一次同款口径)按**等待点**键控(ONAIR/INTRO 按 nodeId、BRIDGE 整段、ENDING 按结局、菜单整段);`_helpSpokenOnce`:同键第 1 次全量口播,第 2 次起 `vibrate('beat')` + nudge earcon(复用统一 8 音词表零新增;guide 无公开单发 earcon API,经 `_playEarcon` 直用,`_startRing` 直用引擎总线同款先例;guide=off 时只震)。状态句照播(复述状态=合法帮助,P1 先例);新等待点首滑仍全量口令,非全局静默 | ✅ 同一等待点第 2 次上滑不重播 sys_help(ONAIR/ENDING 两态);✅ 状态句照播(prog/rep 各 2 次);✅ beat 轻震标记;✅ nudge earcon;✅ 新等待点(z1_a)首滑仍全量口令 |
|
||||
| G2 rep_low warning 震 | R1 P3-3 遗留。原实现 `enterBridge` 跨档分支 `vibrate('warning')` **实际不可达**(rep 唯一减分组合 p1右+p2右 从 0→-1 不跨档,`lastAnnouncedTier` 初值即 low)。修:`_tierCue()` 挂在**全部 rep_low 播报位**——RING/ONAIR/BRIDGE/ENDING 四处上滑复听,rep_low 整句出口同时手腕有感(BRIDGE 跨档分支保留不动) | ✅ RING 上滑复听 rep_low 附 warning 震(live 局 B t=198.5/497.5 证据位);✅ ONAIR 上滑同款;✅ ENDING 上滑同款 |
|
||||
| G3 k1_a/k1_b male 回退 | **核查结论:回退正常,非静默,不修。** k1_a/k1_b 为糖糖 NPC 平铺组资产(设计即单音色 Vivian 童声、不做双性别,§5.3);male 设置下引擎候选链 `voice/male/k1_a.{ogg,m4a}`(404,符合预期)→ `voice/k1_a.ogg`(200)命中平铺版播出(web-engine-api.md voice 路径解析)。**文档注记**:live 局 B 观测的「同通电话声线跳变」实为主播声部(随 settings.voice 换声)与糖糖童声(恒定)在同通内交替,属「电话音质感」设计使然;不补双性别资产(违反 NPC ≤5 音色约束与 §5.3 设计) | ✅ male 先尝试性别目录 male/k1_a、k1_b(404 属设计);✅ 平铺版播出(voicePlays 各 1);✅ 零「资产缺失」console.error(真静默则修——实测无需修) |
|
||||
| G4 空点确认轻震 | R1 P3-1 / R2 P3-4 遗留。不可跳句(p* 首播 / F5 尾句 / F4 锁)上的单击「点了但没选上」,gesture 层确认震 [20] 游戏侧无法撤销(engine/gesture.js 不在本轮改动清单)——游戏层补一记最轻 beat [8] 形成可区分签名(20→8 连击 ≠ 真确认的单记 20),消解「像点上了」误导;落点 `_onStoryGesture` / `_onEndingGesture` 两处 tap 屏蔽分支 | ✅ F4 锁内单击 beat 震;✅ F5 尾句单击 beat 震(「p9 后空点」证据位);✅ p* 不可跳句单击 beat 震(R1 P3-1 证据位) |
|
||||
| G5 显式规则 | 纯登记 + 断言,无代码改动(F4/F5/V1 现有实现即规则本体);规则语句见上节。新增断言锁「锁不随复播重新武装」(复播可即掐的反向面:保护不得扩大化) | ✅ ASK 恢复首句锁内单击不跳(例外);✅ 复播(关菜单局面复述)首句单击照常跳过;✅ 链末关键句首播不可跳(F5 引用);✅ p* 首播单击不跳(引用);(F4/F4b/F5/F5b/V1 既有断言为规则其余各半) |
|
||||
| G6 状态链重排 | P1 两次建议、纯排序改动 → 本轮做。`_withHelp()` 把帮助句接在状态链尾:「当前通号 → 口碑 → 帮助」。ONAIR/INTRO(有状态时 prog → rep → sys_help)、BRIDGE(下一通 prog → rep → sys_help)、ENDING(结局主句 → rep → sys_help);RING 本就状态在前且无帮助句(§2.3 RING 行),天然满足;MENU 链无通号/口碑状态句,G6 不适用(仅 G1 去重,帮助保持在前)。§2.3 表内「帮助+状态」措辞由本节登记更新(状态在前),正文不改 | ✅ ONAIR 顺序 prog_c1 → rep_low → sys_help;✅ BRIDGE 顺序 prog_c2 → rep_mid → sys_help(原断言改写);✅ ENDING 顺序 e4_a → rep_low → sys_help;✅ 中断复述 ONAIR 顺序 prog_c3 → rep_mid → sys_help(原断言改写) |
|
||||
|
||||
### 顺带补的 SA3 音效接线断言
|
||||
|
||||
主路径补 `sfx/onair_sting`(开场台标)/`sfx/line_drop`(幕间挂断)/`sfx/tape_static`(p9 直面)
|
||||
接线计数断言(arg_muffled ×2 / brake_screech / phone_ring 已有);静态审计
|
||||
`STABLE_AUDIO_PENDING` 注释更新为「SA3 12 件已全部补产,清单降级为守卫」。
|
||||
|
||||
### 观察项(按裁定不动代码)
|
||||
|
||||
- 复播晚点 +7.6s 一次性事件(live P3-3):一次性观测,未加断言盯防(避免为仪器怪癖加约束)。
|
||||
- mid-prompt 生效掐选项句尾(live P3-6):设计备注维持,G5 规则已按现状登记。
|
||||
- harness 丢 tap 仪器怪癖(live P3-5):记入 R3 协议(tap 后 listen 一次确认再重发),非游戏侧。
|
||||
|
||||
### 遗留
|
||||
|
||||
- 无新增遗留。G1 去重集合为实例级(重进游戏首滑仍是完整口令)——如 R3 复评希望跨实例
|
||||
记忆(localStorage 持久化「已听过口令」),列 v2 候选,本轮不加(保持与 sys_skip 每实例
|
||||
一次同口径,避免老玩家重进被静默)。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
> - male instruct 常量:`低沉醇厚的男声,像探窟向导,沉稳有力`
|
||||
> - 两常量全表统一(含教学/战斗/结算),禁止句级变体。
|
||||
> - 数字规避:层数(7 句)/血量(4 档)/金币(4 档)/面朝(4 句)/威胁(4 句)/战利(3 档)/死因(3 档)/元进度(3 档)全部分档整句,无运行时拼接。
|
||||
> - 多音字自查:全表无「血」「重(chóng/zhòng 歧义句)」「爪」「挨」「壳」「栅」;「重听」一律写「重新听」;「重新」为规范 sanctioned 常用词(sys_menu_help / sys_menu_restart)保留。「回声回来越快」已去掉助词「得」。余留风险 2 处已标注:`btl_bat` 的「蝠」(读 fú,试听异常则整句改「盲眼蝙蝠扑了过来」);`unlock_potion` 的「行囊」(xíng náng 固定词,试听确认)。
|
||||
> - 多音字自查:全表无「血」「重(chóng/zhòng 歧义句)」「爪」「挨」「壳」「栅」;「重听」一律写「重新听」;「重新」为规范 sanctioned 常用词(sys_menu_help / sys_menu_restart)保留。「回声回来越快」已去掉助词「得」。余留风险 2 处已标注:`btl_bat` 的「蝠」(读 fú,试听异常则整句改「盲眼蝙蝠扑了过来」);`unlock_potion` 的「行囊」(xíng náng 固定词,试听确认)。R3 新句自查:`gold_some`(带回来一点,不多——无多音字风险);`tut_flee_hold`(想逃跑,按住别松手——无风险)。
|
||||
> - 向导/卡关通道句(gd_*、stair_*、nav_*):trigger 见表;接线纪律按 14 号文档——watchdog/纠错句 idle-only、onceKey 同局限次、向导插播一律 queue:true;开发轮次须将本表 gd_* 条目登记进 14 号文档增补。
|
||||
> - 管线:`tools/gen_voice_dual.py` 照录(--game dungeon);生成后 `--convert` 落盘 + `tools/check_all_assets.py` 终检(双格式配对、双性别集合一致)。
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
| `sys_continue_ask` | 检测到探窟记录。单击继续,右滑重新开始。 | 有存档进游戏(TITLE) |
|
||||
| `sys_new_run` | 新的探窟,开始了。 | 新周目开始 |
|
||||
|
||||
## T 组 · 教学演练 DRILL(旁白 ×19)
|
||||
## T 组 · 教学演练 DRILL(旁白 ×20)
|
||||
|
||||
| id | 台词全文 | 触发/语境 |
|
||||
|---|---|---|
|
||||
@@ -38,12 +38,13 @@
|
||||
| `tut_parry_miss` | 没挡住也别怕,它伤不到你。 | D8 格挡失败 |
|
||||
| `tut_attack` | 现在单击,挥拳打它。 | D8 你的回合 |
|
||||
| `tut_kill` | 打中了,就是这样。 | D8 击杀 |
|
||||
| `tut_flee_hold` | 想逃跑,按住别松手。 | R3:战斗长按未满 900ms 松手(取消逃跑)时的区分提示,每场 1 次 |
|
||||
| `tut_stairs` | 铁器的回声,就是下潜的楼梯。 | D9 |
|
||||
| `tut_stairs_on` | 楼梯就在脚下。单击,下潜。 | 首次踏上楼梯格 |
|
||||
| `tut_done` | 教学完了。地窟很深,小心走。 | DRILL 完成 |
|
||||
| `tut_skip` | 已跳过教学。单击脉冲,先听听四周。 | 下滑跳过教学 |
|
||||
|
||||
## S 组 · 系统/菜单/状态(旁白 ×35)
|
||||
## S 组 · 系统/菜单/状态(旁白 ×36)
|
||||
|
||||
| id | 台词全文 | 触发/语境 |
|
||||
|---|---|---|
|
||||
@@ -67,7 +68,8 @@
|
||||
| `st_hp_2` | 你受了点伤。 | 50~75% |
|
||||
| `st_hp_3` | 你伤势不轻。 | 25~50% |
|
||||
| `st_hp_4` | 你命悬一线。 | ≤25%(danger earcon + warning 震,降档才播) |
|
||||
| `st_gold_1` | 口袋空空。 | 元进度总金币 <50 |
|
||||
| `st_gold_1` | 口袋空空。 | 元进度总金币 =0(R3 起 band0 专用:真的一枚没有) |
|
||||
| `gold_some` | 带回来一点,不多。 | R3 E1-2:金币档 1(0<金<50)真话句——上滑状态链 / SETTLE / TITLE 三处共用(修「捡到金币→口袋空空」谎报) |
|
||||
| `st_gold_2` | 有些积蓄。 | 50~200 |
|
||||
| `st_gold_3` | 收获可观。 | 200~600 |
|
||||
| `st_gold_4` | 腰包鼓鼓。 | >600 |
|
||||
@@ -80,7 +82,7 @@
|
||||
| `st_threat_right` | 右边有脚步声。 | 右侧 5 格内有怪 |
|
||||
| `st_threat_both` | 两边都有动静。 | 两侧皆有 |
|
||||
| `st_best_1` | 你还没到过第三层。 | TITLE 元进度·最深层数档 1 |
|
||||
| `st_best_2` | 你到过中层。 | 档 2(最深 3-5 层) |
|
||||
| `st_best_2` | 你最远到过中层。 | 档 2(最深 3-5 层;R3 措辞加「最远」——live P3:防误读为"本局到过",已重录) |
|
||||
| `st_best_3` | 你到过最深层。 | 档 3(最深 ≥6 层) |
|
||||
|
||||
## E 组 · 探索事件(旁白 ×9)
|
||||
@@ -172,8 +174,8 @@
|
||||
|
||||
---
|
||||
|
||||
**合计:125 句 ×2 性别 = 250 条音频**(×2 格式 = 500 文件;无 NPC 平铺件)。死亡结算链 =
|
||||
`die_intro → die_cause_X → die_adv_Y → st_floor_N(复用)→ meta_gold_X → settle_stronger → settle_again`;
|
||||
通关链 = `settle_win_1 → settle_win_2 → meta_gold_X → unlock 段 → settle_again`;
|
||||
上滑局面复述链 = `st_floor_N → st_hp_X → st_gold_X → st_face_X → st_threat_X`。
|
||||
**合计:127 句 ×2 性别 = 254 条音频**(×2 格式 = 508 文件;无 NPC 平铺件。R3:125 + `gold_some` + `tut_flee_hold`;`st_best_2` 措辞重录不加句)。
|
||||
死亡结算链 = `die_intro → die_cause_X → die_adv_Y → st_floor_N(复用)→ meta_gold_X(band1 且金>0 时为 gold_some)→ settle_stronger → settle_again`;
|
||||
通关链 = `settle_win_1 → settle_win_2 → meta_gold_X(同上)→ unlock 段 → settle_again`;
|
||||
上滑局面复述链 = `st_floor_N → st_hp_X → st_gold_X(band1 且金>0 时为 gold_some)→ st_face_X → st_threat_X`。
|
||||
主设计触发逻辑对照 [16-dungeon.md](16-dungeon.md) §4-§11;资产规模核对见其 §9。
|
||||
|
||||
@@ -575,3 +575,105 @@ choice 签名本作不使用(无抉择态;菜单是 menu)。菜单回绕
|
||||
- 场景 9:L3 带路从「整段先东西后南北 + 每步必播」改为「最短路首步 + 改向必播/同向 1.5s 节流」
|
||||
(§10.3 L3 口径的听感与保险丝友好修订)。
|
||||
- 台词/资产表:无新增 voice;新增 sfx `amb_cave`、`turn_tick`(SYN,双格式,QC 数字见上)。
|
||||
|
||||
### R3 修复回归(2026-09-02,E0-1/E0-2/E1-1/E1-2 收口轮)
|
||||
|
||||
> 证据源:research/new8/dungeon/round2/(synthesis 裁定 + live-player + p1/p2/p3/p4)。
|
||||
> 本轮**引擎零改动**(E0-1 看门狗改造全部在游戏层);radio 并行改动中,回归时全绿。
|
||||
> 回归:8 套 playtest + guide.test 全绿,dungeon 1610 → **1642** 断言(escape 140 / radio 246 /
|
||||
> rhythm 141 / rpg 188 / simon 132 / space 155 / storyline 82 / guide 122,0 失败)。
|
||||
|
||||
#### E0-1 看门狗饿死(P0,四票共识)
|
||||
|
||||
- **根因**:`_stuck.lastAct` 按 §10.3「任何有效手势重置」口径单轨计时——「一直在动手的迷路者」
|
||||
(乱按/无效手势)永远攒不满 60s,暗示→明示→带路三级链零触发。live 实证:压力局 253 对 earcon、
|
||||
最长 2223s 无语音窗、0 句提示;P1 结论「『每次手势后重挂』的口径恰好被乱按永久饿死」。
|
||||
- **修(双轨制)**:
|
||||
- ① **无操作轨**(§10.3 原样保留,仅探索态生效):任何有效手势重置,60/120/180s。
|
||||
- ② **无进展轨**(新增):只由**状态推进**重置(楼层/格位置/战斗回合/拾取,`_progressTrack()`,
|
||||
挂点在 `_walkStep` 移动、`_playerTurn` 回合推进、`_progress()` 事件与各状态进入点),30/60/90s
|
||||
三级升级:**earcon**(复用 `sfx/turn_tick`,不占台词通道、不排队)→ **短句**(`stair_hint_a/b`)→
|
||||
**导航接管**(`_navRouteVoices()` 最短路首步方向 + 楼梯指向,进入导航模式每步校正、60s 周期重报)。
|
||||
- 两轨短句内容同级(无操作轨 L1 = 无进展轨 L2)交叉登记防重复播;明示级 `stair_dir_*` 只由无操作轨
|
||||
兑现登记。站立不动(两轨同时走时)经无进展轨 30/60/90s 即升级——比 §10.3 的 180s 更早拿到带路,
|
||||
两轨并行取先到;§10.3 的 60/120/180 口径在无操作轨原样保留。
|
||||
- **断言(场景 13A/13B)**:`E0-1: 乱按 96s 全程零位移(无操作轨持续被手势重置)`、
|
||||
`E0-1: 无进展 30s 级 → earcon(复用合成回执音,乱按饿不死)`、`E0-1: 无进展 60s 级 → 短句 stair_hint_a`、
|
||||
`E0-1: 无进展 90s 级 → 导航接管(播最短路首步方向)`、`E0-1: 接管后进入导航模式`、
|
||||
`E0-1: 接管首步方向必可通行(楼梯指向,不指墙)`、`E0-1: 乱按 96s 语音总量有上界(≤4)`、
|
||||
`E0-1: 有真实进展(格位置持续推进)零卡关语音零 earcon(不误伤正常玩家)`。
|
||||
|
||||
#### E0-2 跳教学路径密度回归(P0,P3 抓获)
|
||||
|
||||
- **根因**:压力局 t=52.5 起困在教学 D9(tap=脉冲,零位移零步骤推进)39 分钟——D9 看门狗 30s 升级句
|
||||
同样被「每次手势重挂」饿死;skip 后再 79 分钟零遭遇零指向。R1 乱按局 75s 即滚出教学的逃生口在 R2
|
||||
形同虚设(2403s)。
|
||||
- **修**:① 教学态共享无进展轨(`_stuckArm` 5s 轮询扩到 DRILL;`_drillEnter` 步骤推进/格位置/战斗回合
|
||||
均重置):30s earcon → 60s 短句(仅 D9 给 `stair_hint_a`——教学句不重播 §10.2,非寻路步骤无方向话
|
||||
可给、短句级跳过登记)→ **90s 教学接管 = `_drillSkip()` 自动滚出教学**(播 `tut_skip`、drillDone 入账、
|
||||
落回探索态由导航链接手),恢复 R1「乱按 ~75s 出教学」口径并落在 P3 要求的 90-120s 内;做对了
|
||||
(步骤推进/走动)永不误触发。② 密度保底对跳教学局本就全路径生效(`_fillMainPathDensity` 在
|
||||
`_tryGenFloor` 内无条件执行),本轮补上「跳教学种子局实测 `_floor`」的直证断言;skip 后进探索即享
|
||||
E0-1 导航接管。
|
||||
- **断言(场景 13C/13D)**:`E0-2: 跳教学种子局主路径密度不变式(最长真空 ≤12 格)`、
|
||||
`E0-2: 跳教学后 Ns 内必有指向语音(≤120s;R2 压力局 skip 后 79 分钟零指向)`、
|
||||
`E0-2: 教学乱按零进展 ≤95s 内自动滚出教学(R2 压力局 2403s)`、`E0-2: 教学乱按 30s 级 earcon 先到`、
|
||||
`E0-2: D9 乱按 60s 级给方向话 stair_hint_a(看门狗长嘴)`、`E0-2: 接管播 tut_skip`。
|
||||
|
||||
#### E1-1 到达即报(P1,live)
|
||||
|
||||
- **根因**:站楼梯格 tap 被下潜模态截走(补测局 t=1288.7 实演),「铁器=楼梯」贴身回声只能靠相邻格
|
||||
脉冲兑现,教学 D9 承诺在输入层不可达(本局两次到站都靠 tut_stairs_on 而非铁器音找到楼梯)。
|
||||
- **修(产品裁定「到达即报」)**:`_onStairCell` 踏格瞬间自动播贴身铁器回声(`echo_1` 即刻 +
|
||||
`mat_stair` +120ms,编码同脉冲贴身档)+ 既有提示句(每层首达 `tut_stairs_on` / 窟主未清
|
||||
`evt_stairs_lock`)。**不占输入通道**:单击仍是下潜确认,脉冲/其他手势语义零变化。
|
||||
- **断言**:场景 2 `R3 E1-1 到达即报:踩上楼梯格瞬间自动播贴身铁器回声(echo_1+mat_stair,全程零玩家脉冲)`
|
||||
+ `R3 E1-1: 到达即报不占输入通道——tap 仍是下潜确认(照常下潜)`;场景 13E
|
||||
`E1-1: 踏上(被锁的)楼梯格自动播贴身铁器回声` + `E1-1: 到达置位 _onStairs` +
|
||||
`E1-1: 窟主未清 → 到达即报铁器 + evt_stairs_lock`。
|
||||
|
||||
#### E1-2 band1 档位账目(P1,P2/P4 共识)
|
||||
|
||||
- **根因**:`_goldBand` 把 0<金<50 与 =0 同播「口袋空空」/「这趟没带回什么」——教学拾取(蝠 3 金、
|
||||
堆 10-30 金)后即谎报(P2:49 秒自打脸,其后 6600s 里 27 次「口袋空空」)。
|
||||
- **修**:新录 band1 真话句 `gold_some`「带回来一点,不多。」(8 字,多音字自查无风险);**=0 保留
|
||||
`st_gold_1`/`meta_gold_1` 空手措辞(band0 口径不变)**。新增 `_stGoldVoice()`/`_metaGoldVoice()`
|
||||
统一出口:上滑状态链 / SETTLE / TITLE 三处共用同一条(管线单条、账本仍同一 `_goldBand`)。
|
||||
- **管线**:16-dungeon-voice-ids.md 与 gen_voice_dual.py 两表一致 → `source env.d/tts.sh` +
|
||||
`flock .gpu.lock .venv-tts/bin/python tools/gen_voice_dual.py --game dungeon --gender both
|
||||
--only gold_some,tut_flee_hold,st_best_2` 单批重录(gold_some m 1.84s / f 2.08s)→ `--convert`
|
||||
(dungeon 254 文件 ogg+m4a)→ `tools/extract_voice_text.py` 刷新 voice_text.json(8 游戏 706 句)→
|
||||
`tools/check_all_assets.py` 全过(dungeon 307+307 双格式、双性别各 127、零解码失败)。
|
||||
- **断言**:场景 4 `上滑链前 4 段有序(…gold_some band1 真话…)`(教学蝠 3 金实证)、场景 13E
|
||||
`E1-2: 上滑金币档 0<金<50 播 gold_some(不再谎报「口袋空空」)`、
|
||||
`E1-2: SETTLE band1(0<金<50)同步播 gold_some`、`E1-2: 金=0 保留 meta_gold_1 空手措辞`;
|
||||
场景 6a 死亡链序第 5 段与金币档断言改 gold_some。
|
||||
|
||||
#### 打磨(P2/P3 顺手带)
|
||||
|
||||
- **逃跑长按 ≥900ms**:`_fleeArm()`/`_battleFleeCancel()`——战斗态 longpress(引擎 450ms 判定)先武装,
|
||||
按满 `FLEE_HOLD_MS=900` 才真正 `_flee()`;未满松手 = 取消 + error 震 + 每场 1 句区分提示
|
||||
`tut_flee_hold`「想逃跑,按住别松手。」(新录)。探索态 450ms 走步不变;<450ms tap 优先判定不变
|
||||
(引擎层)。断言:场景 5 `战斗长按 ~650ms(<900ms)松手 = 不逃(R3 打磨)`、
|
||||
`短长按取消伴随 error 震`、`取消播区分提示 tut_flee_hold(每场 1 次)`;原「长按逃跑必成挨一下」
|
||||
「Boss 拒绝」断言原样通过(按住不放的路径不变,harness 短步进 longpress 配对不受影响)。
|
||||
- **st_best_2 措辞**:「你到过中层。」→「你最远到过中层。」(live P3:bestFloor 是前世纪录,防误读为
|
||||
「本局到过」;同 id 重录)。st_floor 序列经复核无缺陷(settle 链报深度正是 P3 表扬项),不动。
|
||||
- **台词账目**:125 → **127 句**(+`gold_some` +`tut_flee_hold`;`st_best_2` 重录不加句);
|
||||
playtest 资产校验同步改 127。
|
||||
|
||||
#### R3 老断言口径变更登记
|
||||
|
||||
- 场景 4 上滑链第 3 段:`st_gold_1` → `gold_some`(教学蝠 3 金落 band1 真话档)。
|
||||
- 场景 6a 死亡链序与金币档断言:`meta_gold_1` → `gold_some`(settle 金 40 = band1 且 >0)。
|
||||
- 资产校验:voice 台词总数 125 → 127。
|
||||
- 其余全部原样通过:卡关三级 60/120/180(场景 9 全链)、导航逐步校正/节流/nav_done、进展重置分级、
|
||||
队列礼仪、探索 60s 语音上界、呼吸层 20s 节奏、guide=off 30s 静默(earcon 属 sfx 内容层不违约)、
|
||||
E3/E4、屏蔽兜底、D0-D9 教学全链。
|
||||
|
||||
#### 遗留(本轮未动,沿用 R3 synthesis 悬置项)
|
||||
|
||||
- 8s nudge「earcon+首句短词」半可验改造(synthesis §2 P2/P3,未列入本轮修复清单)与 amb_cave 听感
|
||||
人测(roadmap §4)。
|
||||
- 教学跳过标志跨会话不一致、探针通道隔离:harness/仪器侧。
|
||||
- P3 建议「上滑加第 6 句最近铁器方位」「撞墙归因句」:未列入本轮清单,留终审裁定。
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# 《回声地窟》R2 全拟真复测报告 — 老陈(细心的盲盒 Roguelike 老手)+ 急躁压力局
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 身份:老陈,34 岁,Roguelike 玩家,认真跟教学、脉冲探路;另一局换急性子表弟小飞(1.7x 语速、乱按狂点)代打压力局。R1 同款人设,目标是逐条验收 R2 结构修复。
|
||||
- 设置:
|
||||
- 局 A(新手完整弧线):`voice=male, speed=normal, bgm=normal, guide=full`,主会话 `dungeon-20260902103332`(约 2.3 小时真实时间,247 段语音 100% 纯净可析),另加一个短补测会话 `dungeon-20260902131022`(教学跳过→带路→楼梯格交互补测)。
|
||||
- 局 B(急躁压力):`voice=female, speed=1.7, bgm=normal, guide=standard`,会话 `dungeon-20260902125330`(乱按 400 秒 / 273+ 手势;**未 /stop 落盘,仅 events+mix partial**——收尾时被主管催停,事件流已现场导出)。
|
||||
- 手势统计:局 A 约 400+ 次(tap/longpress/swipe×4/doubletap 全用上);局 B 随机乱按 400 秒。
|
||||
- 最深层:**第 3 层**(局 A,死于 L3 窟主石甲蟹 tel_heavy_r;L1/L2 完整走完,教学 D0-D9 全步骤)。
|
||||
- 结局:局 A 走完 **教学→探索→L2→L3→Boss 战死亡→归因链→元进度→新周目(跳教学)→再下 1 层(L2)→再死一次(全链完整收听)→TITLE 元进度复核** 全闭环,两场死亡、零死锁。
|
||||
- 报错:全程无 fetch 失败、无资产 404、无页面崩溃;**全会话 `vend reason=preempt` = 0 次**(R1:71 分钟 35,611 次)。
|
||||
- 证据落盘:`web/harness/live/out/dungeon-20260902103332/`(全量)、`out/dungeon-20260902125330/`(partial)、`out/dungeon-20260902131022/`(全量);事件流全量副本 `/tmp/sessionA_events.json`(5865 条)、`/tmp/sessionB_events.json`(1030 条)。收尾已 `POST /stop` + `fuser -k 8124/tcp`。
|
||||
|
||||
## 局 A 体验叙述(第一人称,验收视角)
|
||||
|
||||
**0:00–4:00 教学开场:每句都是完整的。** 解锁单击后 TITLE 正常;单击开局,`sys_new_run`→`intro_1`(4.8s)→`intro_2`(3.9s)→`tut_d0`(5.0s) 全长串行。D0 单击确认震干净。
|
||||
|
||||
**t=195 D1 引爆点(R1 灾难起点)——这次什么都没炸。** 脉冲照常(pulse+回声组),**且两侧第一次就报了开口**(side_open_l/r 同至,R1 全程 0 次)。`tut_echo_come` 完整播 2.24s、`tut_front_rule` 完整 2.8s,一句接一句,没有抢占。此后 D2-D9 每一步旁白、每次纠错、每条规则句全部完整入耳——我第一次「听着教学」打完了教学。
|
||||
|
||||
**4:00–5:30 D7 状态链与菜单,第一次真正听清。** 上滑状态链五段(st_floor_1→st_hp_1→st_gold_1→st_face_e→st_threat_none)逐段全长播完(R1 全是 0.2 秒渣渣)。下滑开菜单:menu 音+BGM 切换+`sys_menu`+**菜单首项名播报**(`sys_menu_resume`——复核代码确认这就是「打开即报首项」,R1 报告把它误判成「菜单被系统自动收掉」,此桩旧案当场平反);再下滑,菜单一次就关、BGM 立即切回 explore(D1-1 ✓)。教学蝠随后主动撞脸接战(脚步渐强+心跳预警),格挡练习失败两次(我手慢)、miss 句照播、ATK=0 无伤,第三刀杀之——**BGM 立即切回 explore**(D1-4 胜利路径 ✓)。D9 找楼梯时故意静置:**恰 +30.1s 播 `stair_hint_a`**(D1-2 升级兜底 ✓;8s 纯 nudge 是 earcon,探针不记事件,无法证伪)。
|
||||
|
||||
**5:30–25:00 L1→L2:靠耳朵真的能走。** 脉冲-移动循环:前方距离四档+材质尾音、左右侧墙/开口(side_open/wall 全程 76 次),撞墙 bump 与回声距离始终一致。拾金币有 `evt_coin_3` 档句。两次下潜演出全套:`stairs_down`+`evt_descend`(3.12s)+`st_floor_2`。L2 落地即被窟鼠贴脸(脚步渐强+心跳),第一次格挡成功就在这场:tel_small 后 0.7 秒双击——**parry 音+`btl_parried` 播报(R1 是死资产,R2 已接线)+减伤入账**,两格挡一击杀,`btl_loot_1`+BGM 回 explore。战斗中静置 15 秒,**turn_tick+gd_turn 恰 15.0s 到场**(D1-6③ ✓,三场战斗三次全中)。
|
||||
|
||||
**25:00–40:00 L2 全清与一次意外验证。** DFS 扫图途中把 L2 三只鼠全引了出来——**全是它们主动扑上来的**(R1 的「贴身绕圈就是不开战」彻底绝迹)。中途长按走位撞上接战瞬间变成逃跑(btl_flee+hurt),**BGM 立刻切回 explore**(D1-4 逃跑路径也验了)。菜单在探索态开/关各一次,一次即关(D1-1 主诉直证)。静默 20 秒后 `amb_cave` 垫入;L1 楼梯上静置时 **2769.0/2789.0 两次 amb_cave 严格 20s 间隔**(D0-3② ✓)。
|
||||
|
||||
**40:00–55:00 L3:蘑菇会扑了,Boss 会绕了,我死了。** L3 卡关链全 tier 实测:静置 60s→`stair_hint_b`(窟主未清的正确变体句)→120s→`stair_dir_n/w`(直线方位+警告震)→180s→**nav 带路**(最短路首步,**每走一步重报下一步**,s→s→w→n 逐步自校正,R1 的「咬死北边指墙」不复现;L2 明示说北、带路首步说南——两者坐标系不同但各自为真)。蘑菇贴身即扑(3229.1、3597.1),三只全被我正面打掉(btl_loot_2 档句+btl_lvup 升档)。HP 被放低时**自动喝药实锤**:warning 震+potion 音+`st_hp_2` 档播报(3270.6)。最后踩上 Boss 战:长按被 **`btl_flee_boss`+纠错震** 拒绝三次(Boss 禁逃 ✓),换位脚步 mob_step_heavy_r+派生前摇 tel_heavy_r、半血 `btl_half_crab` 全部到位,然后被两刀放倒——**die_intro→die_cause_2(Boss 重击,真话)**。(我脚本的手滑在 die_cause_2 播到一半点了 SETTLE=立刻重开——意外验证了「重开入口 ≤2 秒」和死后重开直接 EXPLORE 不再进教学。)
|
||||
|
||||
**55:00–75:00 第二次死亡:把归因链一个字不落听完。** 新周目一路下到 L2,用「逃跑-挨打」循环主动送死(7 次 btl_flee,鼠 ATK=1 真实放血),倒地后**全链一字不差**:die_intro→**die_cause_1**(「你被小怪拖垮了」——真话,确实是鼠群逃跑反击放死的)→**die_adv_1**(「下次前摇声响时就双击」——真话,本局 0 格挡)→st_floor_2(真死于 L2)→**meta_gold_1**→settle_stronger→settle_again。单击回 TITLE,上滑元进度:**meta_gold_1(与 SETTLE 同档!D1-5 ✓)**→st_best_2(到过 L3=中层档,正确)→**unlock_potion**(遗产购置播报,账本自洽)。元进度闭环成立。
|
||||
|
||||
**补测会话(131022)**:专程回去验「楼梯铁器回声」,结果收获一条重要边界:**站上楼梯格时单击=下潜(模态优先),脉冲永远发不出去**(t=1288.7 现场演示,直接把我送下了 L2)——详见 P1-1。
|
||||
|
||||
## 局 B 体验叙述(急躁压力:female / 1.7x / standard)
|
||||
|
||||
小飞乱按 400 秒:**136 段语音(其中 dungeon 53 段)、零死锁(无 25s+ 事件空窗)、零抢占**。乱点打死了开场蝙蝠(btl_bat→btl_kill→btl_loot_1),乱滑被 `btl_no_turn` 正确拒绝,菜单被开 12 次每次都能下滑关掉,双击砸在「保存并回大厅」上一次→sys_saved 退到大厅→乱点又开了别的游戏(88 段他家台词)——**与 R1 局 B 的大厅层乱象同款,非本轮修复范围**。注意:本局事件流混入了同机并行 radio 测试的外来语音(探针通道未按会话隔离,详见 P3-4),dungeon 侧结论均按纯 dungeon 事件清洗后得出。1.7x 语速 ASR 盲区依旧(MISMATCH 34/153:`sys_menu_save`→「否则命为大师」0.17),按协议以 events 为准。
|
||||
|
||||
## R2 修复逐条现场验证
|
||||
|
||||
| # | R2 修复 | 结论 | 现场证据(t=会话内秒) |
|
||||
|---|---|---|---|
|
||||
| D0-1 | 语音抢占死循环 | **修好(铁证)** | A 局全程 preempt=**0**(R1:35,611);**教学后 10 分钟窗口语音 38 段=3.8 段/分钟**(中位间隔 5.7s、最短 1.3s、同 id<1s 重复 0 次;R1 同期 >2000 段/分钟且 99.7% 被掐)。D1 引爆点 t=195.3:tut_echo_come 完整 2.24s→tut_front_rule 完整 2.8s,严格串行;全部 247 段语音逐句可听 |
|
||||
| D0-2 | 回声信息真实性 | **side_open 修好;mat_stair 现场仍未兑现(P1-1 挂账)** | side_open 全程 **76 次**(R1 两局 0 次),首个脉冲即双侧开口;但 **mat_stair 全程 0 次**:站楼梯格 tap 被下潜模态优先截走(补测会话 t=1288.7 实演),「楼梯前一格正对脉冲」路径被会话收尾截断未走完。铁器回声 live 缺一环 |
|
||||
| D0-3① | 主路径遭遇密度 | **修好** | L2 三鼠落地后 40-70s 内全部主动扑击(1300.5/1607.9/1849.0);L1 蝠进探索数秒即扑(281.2);探索期无 >20s 无内容体感 |
|
||||
| D0-3② | 探索呼吸层 amb_cave | **修好** | A 局静默 ~20s 垫入(2514.5);严格 20s 节奏复现(2769.0→2789.0;补测 2619.9/2639.9/2659.9);有人声时不垫 |
|
||||
| D0-3③ | 下潜演出 | **修好(本就有,转写伪影已除)** | 三次下潜全套 stairs_down→evt_descend(3.12s)→st_floor_N,无一缺失 |
|
||||
| D0-3④ | 卡关计时器 | **修好(按设计口径)** | A 局 60/120/180s 三级精确触发:hint_b(3511.5=lastAct+63.5s)→stair_dir(3215.5=+120s,警告震)→nav(3936.6=+180s);「任何有效手势重置」口径确认(拾取金币=进展,重置全链) |
|
||||
| D1-1 | 探索态菜单可关+关闭回执 | **修好** | 2526.5 探索态下滑一次即关,BGM menu→explore 立即回切;关闭签名 earcon 为引擎音、探针不单记(如实注记)。B 局菜单开 12 次全部可关 |
|
||||
| D1-2 | D9 看门狗兜底 | **修好(30s 级实锤)** | stair_hint_a 恰 lastAct+30.1s(956.5/1307.4/956.5 三次);8s 纯 nudge 为 earcon 无法从事件证实(仪器局限) |
|
||||
| D1-3① | 导航指墙 | **修好** | 带路=最短路首步且逐步自校正(nav s,s→e,e→n;1264.1/1267.4 每步重报);同向节流(全会话 nav_* 仅 14 次、最小间隔 3.21s,R1 是亚秒互掐);「L2 明示北、带路首步南」系两种坐标语义(直线 vs 路径),各自为真 |
|
||||
| D1-3② | 蘑菇/游走怪相邻即接战 | **修好** | L1 蝠秒扑(281.2)、L2 鼠全主动(1300.5/1607.9/1849.0)、L3 蘑菇扑(3229.1/3597.1);R1「35 分钟软封锁」不复现,两场 L3 战均为怪主动开 |
|
||||
| D1-4 | 战斗结束 BGM 回探索曲 | **修好(双路径)** | 胜利路径 4 次(547.0/2626.8/4040.7/7068.9 敌死即 explore)+逃跑路径 1 次(1206.4 flee 后即 explore) |
|
||||
| D1-5 | SETTLE/TITLE 金币档一致 | **修好** | SETTLE meta_gold_1(8199.3) = TITLE meta_gold_1(8257.7),同账本;后随 st_best_2+unlock_potion(购置后 meta 计提)自洽(R1 是 3 vs 2 互相打架) |
|
||||
| D1-6① | 长按 boost 闪跳 | **修好** | A 局事件流 0 次 boost on/off 窗口事件(R1 每次长按闪一对) |
|
||||
| D1-6② | D7 菜单自动收 | **结案(非 bug)** | 复核:sys_menu_resume=菜单首项名播报(MENU_ITEMS[0],openMenu 固定播),R1 误听为自动执行 |
|
||||
| D1-6③ | 回合 15s 防呆 tick | **修好** | turn_tick+gd_turn 恰 15.0s ×3 实测(477.5/2396.3/3247.9+541.6/2941.5),standard 档也有音 |
|
||||
| 整体 | 一命全弧线无死锁 | **通过** | 教学→3 层→Boss 死→结算→新周目→再下 1 层→再死→全链→TITLE,全程零死锁;B 局乱按 400s 零死锁 |
|
||||
|
||||
## 问题清单
|
||||
|
||||
### P0(破坏核心体验的系统性缺陷)
|
||||
|
||||
无。R1 的失聪循环没有复现,本轮没有任何「不听人话就玩不下去」级别的缺陷。
|
||||
|
||||
### P1(功能失效/设计违约)
|
||||
|
||||
1. **「铁器=楼梯」的贴身铁器回声在输入层不可达,mat_stair live 仍为 0 兑现**
|
||||
- 站上楼梯格时,单击被「下潜」模态优先(补测会话 t=1288.7:tap→stairs_down,脉冲根本发不出),「站楼梯格→贴身(dist1)铁器回声」这条 R2 新接的回声路径,玩家用正常手势永远听不到;
|
||||
- 唯一可听路径是楼梯恰在正前方射线(echo 距离+mat_stair),本局两次到站都因「踩格即播 tut_stairs_on→顺手单击下潜」错过,补测的「到站退一格转身脉冲」实验被收尾截断;
|
||||
- 后果:教学 D9「听到铁器回声再走过去」对新手仍是碰运气(本局老陈是靠 tut_stairs_on 踏格句而非铁器音找到楼梯的)。playtest 断言层面已全绿,但 live 端承诺未闭环。
|
||||
|
||||
### P2(不适/可疑)
|
||||
|
||||
1. **看门狗 8s 纯 nudge(earcon)仪器不可验证**:earcon 不产生独立事件,live 只能证实 30s 升级句;建议给 earcon 加轻量探针(本条是仪器欠账,不是游戏缺陷)。
|
||||
2. **连续战斗时救援链会饿着**:拾取/击杀=进展事件重置卡关链(§10.3 口径),叠加怪主动扑击后,L2 三连战期间玩家永远攒不满 60s 空闲,带路全程沉默(实测 hint_a 被拖到 lastAct+90.6s)。战斗本身是内容所以体感不空,但「打完三只鼠还没头绪」的新手要再等一整轮 60/120/180s。
|
||||
3. **教学跳过标志跨会话不一致**:B 局开局跳教学(meta.drillDone=true 生效),补测局却重进教学——同一 localStorage 键 `soundgame.progress.dungeon`、游戏内逻辑正确,根因指向 harness 会话上下文/并行测试互串(仪器侧),挂账复核。
|
||||
4. **amb_cave 听感未验**:事件层节奏全对,但 ASR 对环境垫无评判能力(全落 SFX_BGM_ONLY 行),音量/辨识度是否「像洞里的空气」待人耳。
|
||||
|
||||
### P3(建议)
|
||||
|
||||
1. **长按三义在「相邻扑击」时代更危险**:走位中被扑→下一步长按=瞬间逃跑挨打(本局实录 flee×7+扫图误逃×3)。R1 P3 原样存在且触发率变高;建议逃跑加前摇音或改绑手势。
|
||||
2. **大厅层老问题原样**:乱按双击「保存并回大厅」无确认退局(B 局 ×1),退局后无「你在大厅」定位句、乱点直接开别的游戏——dungeon 侧无责,但它是被 dungeon 菜单送进去的。
|
||||
3. **st_best 播报语义**:死于 L2 时 TITLE 播「你到过中层」(bestFloor=3 是前世纪录),句面对新玩家易误读为「本局到过」,建议加「最远」二字级别的措辞。
|
||||
4. **仪器三件**:① longpress 定长 600ms≈1 格,教学「按住走≥2 格」只能靠撞墙兜底通过(撞墙也算过,本轮实走通了这条兜底);② 1.7x+短句 ASR 盲区依旧(MISMATCH 34/153);③ /session 探针通道未按会话隔离,同机并行测试(radio-103345/110919/112548)语音互串进 B 局事件流(88 段外来),且 B 局因被催停未 /stop 仅存 partial。
|
||||
|
||||
## 做得好的地方(实话实说)
|
||||
|
||||
- **死亡归因真话律两场全对**:Boss tel_heavy_r 放倒→die_cause_2;鼠群 flee 反击放血→die_cause_1;0 格挡→die_adv_1。全游戏最严苛的承诺继续满分。
|
||||
- **格挡系统第一次完整可玩**:0.7 秒时机双击→parry+btl_parried 播报+减伤(R1 死资产已接线);格挡失败有 miss 教学句兜着。
|
||||
- **Boss 战规格全兑现**:换位脚步报位(mob_step_heavy_r)、派生前摇(tel_heavy_r)、半血句(btl_half_crab)、禁逃回执(btl_flee_boss+纠错震)。
|
||||
- **自动喝药**:HP≤25% 一瞬间 warning 震+potion 音+血量档播报(3270.6),一次不落。
|
||||
- **btl_lvup 击杀升档 ×2**、loot/coin 全部分档句正确; Economy 账本跨死亡、跨购置全部对得上。
|
||||
- **靠耳朵真的能通关 3 层**:回声距离+材质+侧向开口+怪物脚步三套信息全程零矛盾(R1 的 L3 漂移未复现);卡关三级链是真能把人带到楼梯的。
|
||||
- **节奏**:教学后每分钟都有事发生(战斗/拾取/氛围垫轮转),R1 的「350 秒真空」体感彻底消失。
|
||||
|
||||
## 玩家情绪时间线
|
||||
|
||||
- 0:00 开场四句完整清晰:「等下,这次每句都听完了?」
|
||||
- 3:15 D1 脉冲,教学句没被掐:「风暴真死了,服」
|
||||
- 6:00 状态链五段完整入耳:「原来这游戏是这么告诉状态的」
|
||||
- 20:00 菜单一次就关:「口袋终于有出口了」
|
||||
- 30:00 格挡成功叮一声+播报:「parried!这词我等了一轮」
|
||||
- 45:00 带路每步重报方向:「这导航成精了,指哪走哪」
|
||||
- 55:00 被 Boss 两刀放倒:「输得明白,死得服气」
|
||||
- 70:00 第二次死亡全链听完:「两场死法两句真话,这游戏说话算话」
|
||||
- 75:00 TITLE 上滑金币档一致:「账目都对,行,冲这个我愿意三周目」
|
||||
|
||||
## 如果只能改 3 件事
|
||||
|
||||
1. **让玩家真的听到铁器**:楼梯格上的单击下潜保留,但把「贴身铁器回声」改挂到踏格瞬间或下潜确认前播,或允许「楼梯上双击=重发脉冲」——别让唯一的新回声路径在输入层死锁(P1-1)。
|
||||
2. **战斗中的救援链别饿着**:扑击接战计入「有内容的证据」,或战斗胜利后把卡关计时从「上次手势」改从「上次进展+战斗时长折算」。
|
||||
3. **逃跑加前摇**:长按三义在主动扑击时代太容易误逃挨打,一拍前摇音就能把「撤退」变成玩家的选择而不是事故。
|
||||
|
||||
## 一句话裁决
|
||||
|
||||
**R1 那个捂着我耳朵 71 分钟的死循环真的死了——风暴 0 抢占、菜单能关、账目分毫不差、两场死亡句句真话,这游戏第一次从头到尾「说着人话」陪我走完了三层地窟;只剩「铁器回声」这一句教学承诺还差最后一口气,修掉它我就敢把「立刻再来一局」说满。**
|
||||
@@ -0,0 +1,38 @@
|
||||
# P1 视障资深玩家评审:《回声地窟》(R2 翻案复审)
|
||||
|
||||
> 评审依据:research/new8/dungeon/round2/transcript-main.md(867 行全读)+ transcript-stress.md(5996 行:前 800 行全读,另抽读蝙蝠战 t+2413-2422、收尾段 t+5950-7187,并对全文做语音清单与关键 id 全量计数)。R1 评审 research/new8/dungeon/round1/p1-blind.md 的每一条都带了回执。
|
||||
> 说明同 R1:【状态】行我只当转写器注记,不算我耳朵听到的。round2/ 目录没有 live-player.md——本轮全部结论出自转写耳证,文末注明。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4/5 —— R1 的 2 分是给「两局两个世界」的,R2 我承认主线局从头到尾是一个游戏了:两次下潜全套演出(t+152.1 stairs_down+「你顺着楼梯,往下潜」→t+156.4「这是第二层」+explore 签名;t+241.0→t+243.1「这是第三层」);BGM 纪律全对账,战曲每场都退(t+53.1/175.3/188.2/215.5/276.6/291.6 淡回 explore,boss 曲 t+319.1,结算曲 t+354.7);上滑五段链两局 60+ 次随叫随到;回声谱系四档全开(echo_1-4 = 8/7/9/6,不再是两态节拍器),侧向开口在线(main 39 次 / stress 653 次,R1 是 0)。扣的一分:撞墙归因还是哑的(stress 181 次 bump 全是裸 sfx/bump,t+67.1/154.0/272.0…零句人话);boss 死因句有一次跟我耳朵顶牛(见一致性专节);还有——压力局里我被泡在每 8 秒一对的无语义 earcon 里两小时,那不叫状态感知,那叫滴水刑。
|
||||
- 下一步明确性:3/5 —— 「铁器=楼梯」的教学承诺终于兑现,而且是一条完整因果链:t+231.6 mat_stair → t+236.3 再响 → t+240.5「楼梯就在脚下。单击,下潜。」→ t+241.0 下潜成功;L3 t+312.0/315.4 同样兑现。战斗教练依旧一流,新增的方位纠错是真好:「挥空了,它不在你面前。」(t+345.3)与 t+347.5 tel_heavy_r(右侧前摇)严丝合缝;回合发呆 15 秒有看门狗语音+turn_tick 收尾(t+345.3)。但压力局证明抢救机制对真迷路的人不开口:我在教学第 9 步被乱按困了 39 分钟,得到的是 253 对「nudge+watchdog」earcon 和 0 句提示,直到 t+2403.4 才蹦出一句「已跳过教学。单击脉冲,先听听四周。」——39 分钟才到的逃生门不叫救援,叫道歉。设计注记说 D9 看门狗「8s nudge、30s 升级播 stair_hint_a」:我的耳朵两小时一次都没等到升级句,只等到无限循环的滴滴声。
|
||||
- 愿意继续玩:是(有条件)—— 主线弧线现在值得再按下去:下潜有演出、战斗有教练、死了有对得上的账(t+363.1「这趟带回一些金币」↔ 局内 8 次入金;新周目 t+371.6「有些积蓄」)、死亡-重开循环 377 秒干净跑通。条件就一条:把看门狗的嘴装上,别拿滴水声假装在帮我。
|
||||
- P0 问题:
|
||||
1. 迷失抢救只会响、不会说:压力局自 t+75.1 起每 8 秒一对 watchdog earcon,直到 t+7187 收工共 253 对,期间 0 句导航/楼梯语音;最长无语音窗 2223 秒(t+2420.2→4643.3),另有 20 分钟级空窗(t+1189→2414)。同一套话术在主线局明明存在(t+151.6「楼梯就在脚下」),说明不是资产缺失,是触发路径对「一直在动手的迷路者」不通——「每次手势后重挂」的口径恰好被乱按永久饿死。对视障玩家,周期性无信息噪音比安静更羞辱人。
|
||||
- 建议(≤3):
|
||||
1. 看门狗升级改按「无进展时长」而非「无手势时长」计时,且升级必须落到人话:30 秒没靠近楼梯就播 stair_hint_a 或「跟着铁器声走」;earcon 节奏 8 秒封顶改 30 秒,并设总次数上限——抢救信息请用句子,别用摩斯电码逼我自己猜。
|
||||
2. 撞墙归因句接上(181 次 bump 零归因),死亡归因从真实致死前摇取材:main t+353.5 tel_heavy(正面重击前摇)1.2 秒后打死我,t+356.8 却报「你背后的偷袭,要了命。」——全程没有任何一次「背后」方位事件。R1 的归因是我点名表扬的,R2 别在这一格倒退。
|
||||
3. 远距威胁播报改口径:stress t+387.5「右边有脚步声」、t+773.2「左边有脚步声」播出时耳边没有任何 mob_step——声音没到就别宣称有脚步,改「左边有动静」或收紧触发半径到声画同达;顺带查一下无手势的 step_turn 幻影(stress t+7112.3/7132.3/7142.3,前后只有脉冲,我没转身却听见拖步转身音)。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
- R1 P0-1「不知道自己在哪」(下楼零演出×2、战曲 370s 不退、新周目无宣告)→ **已修**:下潜演出×2(t+152.1-158.5、t+241.0-243.1,stairs_down+往下潜+这是第X层+explore 签名四件套齐);每场战斗结束 explore 淡入(t+53.1/175.3/188.2/215.5/276.6/291.6,boss/settle 曲各自到位);新周目有宣告(t+365.3「新的探窟,开始了。」→t+367.4「这是第一层。」)。
|
||||
- R1 P0-2「不知道该做什么」(三级提示哑火、铁器承诺 165 脉冲 0 兑现)→ **部分修**:铁器链兑现(t+231.6/236.3→240.5→241.0;L3 t+312.0/315.4);side_open 从 0 → main 39/stress 653;350s 静默死亡——main 最长零事件窗仅 15.0s(t+330.3→345.3,且以看门狗语音收尾);呼吸层接线证实(stress t+7167.8→7187.3 静默 19.5s 后 amb_cave 恰时补上,唯一一次;main 无 ≥20s 窗故不触发,合理)。仍在的正是「说话档」:卡关提示的句子在 2 小时压力局 0 次兑现 → 升格为本轮 P0。
|
||||
- R1 P0-3「账目对不上」→ **大部分已修**:死亡结算 t+363.1「这趟带回一些金币」与局内 8 次金币事件(拾取×2 t+77.1/196.5 + 战利×6)相容;新周目 t+371.6「有些积蓄」,不再让「口袋空空」和「遗产生效」同屏打脸;SETTLE/TITLE 统一分档后,压力局标题页读账(t+0「这趟没带回什么。」+「你还没到过第三层。」)对新档自洽。R1 记的「真机伪影(剧本拾取路径)」我认——本轮 main 转写的账我逐笔能平。**仍在**:撞墙归因句 0/181。
|
||||
- R1 建议 1「让两局听起来像同一个游戏」→ **已修**:教学链/战斗链/结算链逐拍一致;D0-1 语音风暴两局 0 次复现——乱按连点只吃 error 震+完整回声组(stress t+2413.8-2414.2),语音排队不互掐(stress t+6.9 两句零间隔连播)。
|
||||
- R1 建议 2「把回声谱系喂饱」→ **部分修**:正面 echo_1-4 四档全用(8/7/9/6,R1 只剩两档横跳),侧向墙/开口语义在线,铁器在线;mat_door/mat_water 两局仍 0 次(石头地窟说得通,记着这笔)。
|
||||
- R1 建议 3「把元进度做成听得见的账 + 接撞墙归因句」→ 账**已修**(见 P0-3 回执),归因句**仍在**(见建议 2)。
|
||||
|
||||
#### 回声/脚步/播报三套信息一致性(专项更新,先对账再开骂)
|
||||
抽了 5 个移动-脉冲序列核对语义互洽,全部通过:
|
||||
1. main t+61.1:双侧 open + echo_4(远墙)→ t+69.1-77.1 持续通行无 bump,开口就是能走;
|
||||
2. main t+77.6:echo_1(贴脸墙)+ 左墙右开 → t+85.6 转身离墙,堵头就绕;
|
||||
3. main t+231.0/236.0:mat_stair 两连、echo_2→echo_1 收紧(正在接近楼梯)→ t+240.5 贴身提示 → t+241.0 下潜成功——t+53.1 的教学句至此不是谎言;
|
||||
4. main t+345.3 挥空播报 ↔ t+347.5 tel_heavy_r:我听见的方位和系统承认的方位第一次完全咬合;
|
||||
5. stress t+2413.8:乱按连点 → error 震×2 + 完整回声组 → 1.0s 后蝙蝠照样扑上来(t+2414.8)——乱按不丢信息、世界照常运转,这就是我续命的条件。
|
||||
|
||||
- 回声 vs 教学语音:**已修**。R1:165 脉冲 0 铁器、侧向开口 0 次;R2:铁器 4 次、两次直接兑现下潜,side_open 两局全程在线(含教学第一脉冲 t+8.8)。
|
||||
- 回声 vs 空间本身:**大幅改善,残留两笔**。正面四档连续谱 + 侧向两档语义与后续走位对账,「两态节拍器」解散;残留:材质谱系仍是 2/4(只有 stone/stair),以及 stress 尾段无手势的 step_turn 幻影(t+7112.3/7132.3/7142.3)——我仍无法把每一声拖步归位到「我动了」。
|
||||
- 脚步 vs 播报(威胁层):**主线局已修,两处残留**。R1 的「L2/L3 260 秒零怪步」没了:L2 窟鼠 t+160.9→164.4 脚步收敛接战、L3 蘑菇 mob_step_bug 密集可闻(t+247-319);heartbeat 仍守 ≤2 格口径(t+162.5/196.5/261.6);新增侧向威胁播报且与 pan 同侧互洽(main t+375.9「左边有脚步声」↔ mob_step_small_l 连响)。残留:远距播报空口宣言(stress t+387.5/t+773.2,说有脚步、耳边无脚步);密度下限只保主路径——压力局 L1 乱走 2 小时全场唯一遭遇是 t+2414.8 那只蝙蝠,迷路者的世界还是真空,只是现在有滴滴声伴奏。
|
||||
- 播报内部:**已修,一处新账**。settle 五句链齐整(t+356.8-365.3:死因/教训/层数/账本/鼓励);上滑五段链两局 60+ 次随叫随到;遗产账与口袋账分开表述;菜单开合有回执(main t+28.1 开 → t+30.2 关 + explore 签名,D1-1 在主线局兑现)。残留:菜单循环后三项两局仍未露脸(依旧只验证过「返回探索。」);新账一笔——boss 死因句与耳证矛盾(t+353.5 正面前摇打死我 vs t+356.8「背后的偷袭」,见建议 2)。
|
||||
|
||||
> 注:本轮 round2/ 目录无 live-player.md(仅 transcript-main.md / transcript-stress.md),以上全部为转写耳证;docs/design/16-dungeon.md「R2 修复回归」注记仅用于对照 dev 声明(如 stair_hint_a 的 30s 升级承诺),不作为我耳朵的证据。转写实际行数与任务书不符(main 867 行全读;stress 5996 行,前 800 行全读+分段抽读+全文计数),已按实际材料评审。
|
||||
@@ -0,0 +1,33 @@
|
||||
# P2 · 时间充裕的大学生 复审——《回声地窟》(R2 翻案复审)
|
||||
|
||||
> 视角:23:30,宿舍躺床,戴耳机,音量正常。R1 我给了 3/5+拒绝,理由三件事:六分钟空走廊、战斗 BGM 永不切回、「越死越强」是哑的。这次把主线转写全读、压力场全读+抽读后回来验货。
|
||||
> 说明:round2 目录下没有 live-player.md(只有两份转写),本次复审仅基于转写信息流。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4/5 —— R1 最大的传感器故障修好了:BGM 全程说真话。主线 6 场战斗每一次打完都切回探索曲(t=53.1、175.3、188.2、215.5、276.6、291.6),boss 有独立曲(t=319.1 bgm/boss),死亡进结算 menu(t=354.7)、新周目回 explore(t=367.4)——音乐再也不骗我「在打架」了。回声读数也活了:侧向空旷 side_open 从教学第一脉冲(t=8.8)起常伴全场(R1 全程 0 次),echo_1~4 四档距离真实交替,铁器回声 mat_stair 兑现了「铁器的回声就是楼梯」的教学承诺(t=231.6、236.3、312.0、315.4),还多了「左边/右边有脚步声」方向播报(t=375.9)和「附近很安静」呼吸层(压力场 ×15)。L3 虫足声铺满地界,怪物脚步带 heartbeat 震动逼近,我现在闭着眼知道「这层有什么、在哪边、多近」。扣一分:找楼梯的中距离导航还是盲的——铁器声要到贴脸 2-3 格才响(t=231.6 之后两脉冲即到),中间那一百格我依然只能靠撞(主线 L1 摸了 98 秒,t=53.1-151.6);另外看门狗每 8 秒哔一声但从不带信息(见 P0)。
|
||||
- 下一步明确性:4/5 —— R1 的「不知道自己是怎么下的楼」修稳了:两次下潜都有「楼梯就在脚下。单击,下潜。」(t=151.6、240.5),铁器回声先响、播报后到,因果链完整。死亡结算从归因到重开一句话一件事:「你背后的偷袭,要了命。」「身后有动静,先转身。」「这趟带回一些金币。」「下个周目,你会更强。」(t=356.8-365.3),单击 7 秒内进新局——我死也死得明白。扣一分:脉冲还是回答「墙多远」一流、回答「楼梯在哪」不及格,中距没有热/冷梯度;压力场里那位乱划的玩家在教学 D9 卡了 38 分钟(t=75-2403),看门狗哔了 253 次没说过一句「铁器不在这一侧」也没给过跳课出口,探索期(t=2403 之后 80 分钟)更是彻底没人管——「在动但全是无效移动」这个 R1 老毛病,指导系统两侧都没接住。
|
||||
- 愿意继续玩:是 —— 翻案。头 90 秒还是那个让我起鸡皮疙瘩的头 90 秒,而且这回后面有内容了:L2 八十三秒里三场战斗+拾取+「你的拳脚更利落了」成长播报(t=213.3),L3 一路虫足声、两场蘑菇怪、窟主带着专属 BGM 拦路,死了 7 秒重开、金币真的带进下一局(t=371.6「有些积蓄。」)——单局打完我是真的想点「再探一次」,而且这次下一局有可听的回报。
|
||||
- P0 问题:
|
||||
1. 看门狗长嘴但不长舌头:教学 D9 看门狗每 8 秒 nudge+watchdog 两连音、全程无一句人话、无跳过教学出口(压力场 t=75.1-2392.8 共 253 次,卡了 38 分钟);探索期反向失灵——主线我在 L1 边走边脉冲照样被哔了 11 次,而压力场玩家出了教学漫游 80 分钟只遇 1 场战斗(t=2414.8)却零提示零接管。迷路的新人听到的不是救援,是计时器。
|
||||
2. 压力场金币档自相矛盾:t=11.1「捡到几枚金币。」→ t=60.2 上滑「口袋空空。」,同一局内 49 秒自打脸(之后 6600 秒里 27 次口袋空空)。主线全线入账正确,所以这大概率还是「教学拾取不入包但台词照播」的边角——但对躺床的我,耳朵只认「它骗过我一次」。
|
||||
- 建议:
|
||||
1. 给看门狗装台词和梯度:卡住超阈值就升级成一句话(「铁器不在这一侧,换方向试试」「上滑可跳过教学」),把 8 秒一哔改成先静默观察、后语音介入;探索期对「活跃但无进展」也要接管,最好顺手把脉冲加上楼梯热/冷梯度或让铁器回声可远闻——这是我从「想玩到第三层」变成「想安利给室友」的最后一步。
|
||||
2. 教学拾取要么不作数就别播 coin+「捡到几枚金币」,要么一句「教学的道具不入袋」——档位一致性是我翻案的核心依据,别让它留死角。
|
||||
3. 结算报数字和遗产名:「带回一些金币」已经是好钩子,「带回 23 枚、离〈遗产名〉还差 17 枚」才是让我睡前算着一局一局刷的钩子;现在遗产只在状态行里写「遗产生效」(t=367.4),从没被念出过名字。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
| R1 原文 | R2 结果 |
|
||||
|---|---|
|
||||
| P0-1「死了金币进遗产」从未被声音兑现 | **兑现**。主线全链路可听:t=77.1「捡到一大袋金币」→ 沿途战利 → t=363.1「这趟带回一些金币」→ t=365.3「下个周目,你会更强」→ t=371.6 新周目「有些积蓄」。档位一致(一大袋→一些→有些积蓄),SETTLE 与 TITLE 不再打架。残留:压力场教学拾取谎报(建议 2) |
|
||||
| P0-2 主线中段是空的(6 分钟空层、无战斗无拾取、窟主不露面) | **兑现**。L2 82 秒 3 场窟鼠+拾取+成长播报;L3 虫足声铺底+2 场蘑菇怪;窟主石甲蟹 t=319.1 亲临,独立 boss 曲+方向性前摇(tel_heavy_r 右侧偷袭)+「挥空了,它不在你面前」位置机制。二周目 L1 出生即怪脚步+方向播报(t=369.0、375.9)。残留:压力场证明迷路玩家仍可能 80 分钟 1 战(生成器密度下限对乱走者兜不住) |
|
||||
| P0-3 战斗 BGM 永不切回 | **兑现**。6/6 战斗→探索切回(t=53.1/175.3/188.2/215.5/276.6/291.6),boss 曲、结算 menu、新周目 explore 全部正确;战斗节奏不闷了:每回合 turn 音+confirm 震、前摇 tel 带方向、15 秒停滞有 turn_tick+语音「轮到你了。单击挥击。」(t=345.3) |
|
||||
| 建议1 填层+脉冲会指路 | 前半**兑现**(侧向空旷、四档回声、铁器材质、方向播报、amb_cave/「附近很安静」呼吸层全数在场);后半**部分兑现**(铁器声近距可辨,中距热/冷梯度仍缺) |
|
||||
| 建议2 BGM 回归+楼梯播报补稳 | **全部兑现**。主线两次下潜都有「楼梯就在脚下。单击,下潜。」(t=151.6、240.5),对照 R1 的 t=142.2/273.8 缺失 |
|
||||
| 建议3 元进度可听化+遗产名播报 | **金币线兑现**(见 P0-1 回执);**遗产名未做**——「遗产」二字全转写 0 次被念出,只在状态行文字里存在 |
|
||||
|
||||
#### 元进度钩子评估(R2 更新)
|
||||
- 死后想不想立刻开下一局:想,而且这次内容上也想。R1 我夸的 7 秒重开手感原样保留(t=354.7 倒下→t=365.3 新局),归因还是真话且更具体——boss 战里 tel_heavy_r 从右侧偷了我、我确实一根筋正面输出,结算「你背后的偷袭,要了命。」「身后有动静,先转身。」骂得字字属实。R1 钝掉的钩尖这回磨尖了:结算播金币档(「带回一些金币」)、播承诺(「下个周目,你会更强」)、新周目上滑立刻验证(「有些积蓄」,且状态行明写「遗产生效,不用再上课」——新局跳过教学直落探索,这本身就是可感知的「更强」)。从「钩子形状搭好了钩尖是钝的」升级为「钩子挂得住肉」;差的最后半分在遗产名与具体数字,「更强」目前强在哪儿要我自己猜。
|
||||
- 「脉冲回声」这个核心动词:动词本体维持 5 分,读数丰富度从 R1 的 2 分修到 4 分——R1 那个「同一个动词循环十分钟没有新读数」的死局破了:side_open 真会出现(两侧空旷=岔路感回来了)、echo_1~4 梯度真实、mat_stair 把教学承诺兑了现、「左边/右边有脚步声」让耳朵第一次有了雷达扫过怪物的感觉,探索静默期还有「附近很安静」和 amb_cave 垫底。它现在的问题从「贫瘠」变成了「不指路」:读墙满分,读楼梯中距离还是空白,所以还不到 5 分——等它能在 50 格外告诉我「铁器在那头」,这就是我会发朋友圈的声呐魔法。
|
||||
|
||||
#### 一句话结论
|
||||
R1 三个拒绝理由(空走廊、BGM 骗人、金币是哑的)全部修复且经两份转写交叉验证,翻案,4/4/是;剩下的 P0 只伤迷路新人不伤核心循环——看门狗该长舌头了,然后这个游戏值得我半夜推给室友。
|
||||
@@ -0,0 +1,30 @@
|
||||
# P3 复审:《回声地窟》(dungeon)R2 — 时间紧张的白领(翻案复审)
|
||||
|
||||
> 视角不变:32 岁,地铁单程 25 分钟,站立单手持机,嘈杂车厢,只玩过消消乐。R1 我给了 2/2/否,理由是「教学后 350 秒零人声零战斗零拾取、铁器回声 0 次、下潜无声、卡关提示一次没来」。本轮依据 R2 主线转写(全程)+ 压力转写(前 800 行全读 + 菜单段/乱按段/结尾段抽读,覆盖 t=0-7187s)逐条验收。round2 目录下无 live-player.md,菜单关闭等 live 项我只能按转写验。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:3/5 —— 主线局几乎满分:两次下潜都有演出(t=152.1 stairs_down+「你顺着楼梯,往下潜」、t=241.0 同款),进层必报层(t=156.4「这是第二层」、t=243.1「这是第三层——窟主的地界」、新周目 t=367.4「这是第一层」),上滑复述从四句变五句、新增威胁行(压力局 t=387.5「右边有脚步声」、t=64.5「附近很安静」),连死亡结算都报深度(t=361.0「这是第三层」)——我在车厢里任何时候一上滑,9 秒捡回层/血/钱/朝向/威胁。扣的一分全在压力局:t=52.5 之后教学不放人,t=52.5→2403.4 整整 39 分钟我没有任何一句人话告诉我「你还卡在教学里」,状态栏(我是读转写才看得见)停在「教学演练第 9 步」,耳朵里只有每 8 秒一次的看门狗双铃——那一小时我在哪、我在什么状态,全靠猜。
|
||||
- 下一步明确性:3/5 —— 主线局这次知道该干嘛了:t=53.1 教完「铁器的回声=楼梯」,t=231.6/236.3 我真的先听到铁器回声、再 t=240.5「楼梯就在脚下。单击,下潜。」踩格即播;战斗面 t=264.0 多了「它贴着你不放,不用转身」帮我校准;t=330.3 我发呆 15 秒,t=345.3 有人开口「轮到你了。单击挥击。」+回合滴答——不闷。但压力局把短板照出来了:看门狗 t=75.1→2392.8 响了 253 次铃,一次话都没说过(「楼梯就在脚下」是踩到楼梯格才有的贴近提示,不是看门狗说的),两小时里我在第一层空转,0 楼梯、0 战斗、0 拾取,「该往哪走」这个问题两小时没人答。
|
||||
- 愿意继续玩:是(有条件)—— 主线局 6 分钟走完「教学→金币→下潜→三场窟鼠→升级→第三层→两只蘑菇怪→窟主→阵亡→新周目」,t=180 前我已经历 4 次正反馈,死一次 10.6 秒回桌不扣钱,这就是我要的通勤颗粒。条件:把「被打断乱摸」这条路径的 39 分钟教学锁和哑巴看门狗修掉,我才是无条件继续。
|
||||
- P0 问题:
|
||||
1. 不知道该做什么(中断/乱按路径):压力局 t=52.5→2403.4,教学完成判定卡死后无一句指向性语音,看门狗每 8 秒响铃 39 分钟却从不开口,教学跳过兜底(「已跳过教学」t=2403.4)比 R1 乱按局的 74.9s 滚出教学倒退了 30 多倍;skip 之后 t=2422→7187 又是约 79 分钟零遭遇、零楼梯、零金币——密度保底只在规范路径成立,乱走路径失灵。
|
||||
2. (记半条)探索态菜单:两局转写都没在纯探索态开过菜单(主线的开/关在 t=28.1/30.2,属教学态),R1 的「探索态下滑关不掉」我在转写里验不到修没修,加上 round2 没有 live 报告,此条悬置。
|
||||
- 建议:≤3 条,按对「我愿意玩下去」的影响排序
|
||||
1. 让看门狗会「说话」:同一次停顿第 3-4 次响铃(约 25-30s)必须升级成一句方向话(复用「楼梯就在脚下」句式或「西边有铁器声」);现在 nudge 和「看门狗升级」两个音每 8 秒同时响、响 39 分钟没差别,车厢里我只会读出「你卡住了」的焦躁。顺手把「已跳过教学」阈值从 2403s 压到 90-120s。
|
||||
2. 把主线的内容密度保底同样套在乱走路径:skip 后 t=2414.8 第 11 秒就来战证明生成器会做,让它每 60-90s 对任何移动路径保底一次遭遇(金币也行),别让我在 t=2422-7187 那种 79 分钟空转里耗到下车。
|
||||
3. 补两条证据+一句播报:真机或转写补验纯探索态下滑关菜单(D1-1);探索态上滑复述加第 6 句「最近的铁器声在你左边/右边」——mat_stair 已经在网格里响了,差一句播报,「找楼梯」就从撞大运变成听声辨位。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
1. 「教学后 350s 零人声零战斗零拾取」→ **已修复(主线)**。教学末句 t=53.1 → t=77.1 金币(24s)→ t=151.6 楼梯提示+下潜 → t=164.4 首场战斗;全篇最长无声空档 15s(t=330.3→345.3,且有语音救场);t=180 前正反馈 4 次,3 分钟颗粒达标。
|
||||
2. 「铁器回声 0 次」→ **已修复(主线)**。mat_stair 共 4 次(t=231.6/236.3/312.0/315.4),第二次下潜我先听铁器、再看提示句,教学承诺兑现;「楼梯就在脚下」踩格即播(t=151.6/240.5)。压力局 0 次——不是没实现,是 2 小时没走到楼梯旁,归入上面 P0。
|
||||
3. 「两次下潜无声」→ **已修复**。stairs_down 音效+「你顺着楼梯,往下潜。」+「这是第二层/第三层。」齐全,新周目还补「这是第一层」。
|
||||
4. 「卡关提示 0 触发」→ **半修复**。不再被饿死:响铃每 8s 必到,战斗发呆 15s 也有「轮到你了。单击挥击。」;但铃只响不说话、双音同响无层级差异,压力局 39 分钟零句指向。见建议 1。
|
||||
5. (R1 附带)「长按=前进在晃动车厢里易断」→ **未动**。仍是长按前进;不算翻案 blocker,记账。
|
||||
6. (R1 认知负荷)「1.2s 格挡窗口对消消乐手太苛」→ **部分缓解**。「它贴着你不放,不用转身」(t=264.0)砍掉转身判断,主线我 4 战全胜含两只蘑菇怪;窗口本身没放宽。可接受。
|
||||
|
||||
#### 通勤压力再测
|
||||
- 场景 A(正常坐车、跟着教学走):t=0-377 一条龙。25 分钟单程够跑 3-4 个周目;被打断一上滑 9 秒捡回局面+威胁行;死一次 10.6 秒(t=354.7→365.3)且归因两句不骂人、金币不清、还报「你到过第三层」。**达标,这是我愿意装着的那类游戏。**
|
||||
- 场景 B(报站分神/同事拍肩后回来乱摸,即压力局剧本):t=52.5 起教学不放人,看门狗双铃每 8 秒敲一次、39 分 11 秒后才「已跳过教学」,skip 后再 79 分钟零遭遇。真实人类 3 分钟内就杀 App;我唯一的逃生口是强退重开(约 30s 成本),但重开后乱摸还会再锁。**这正是 R1 让我拒绝的那个坑在乱按路径原样复活,而且比 R1(74.9s 滚出教学)更深——翻案是翻了,这一格别叫我再填一次。**
|
||||
- 噪音面:探索静默确实没了(好事),但代价是 8s 一次的看门狗铃;同一对铃响 38 分钟没有任何变化,在车厢里它是催促不是安抚。呼吸层环境音两局合计只出现 1 次(stress t=7187.3 amb_cave,玩家真空转 19.5s 才触发),等于没上线;主线 0 次。
|
||||
- 单手盲操:不变的好——单击/按住/左右滑全程可盲操;连点三下只吃两下 error 短震(stress t=2413.8 起)提示手滑,不罚,摸鱼怕出声也没有任何强制发声操作。
|
||||
- 菜单:教学态 t=28.1 开、t=30.2 下滑关,关时有 BGM 切回+explore 提示音,反馈清楚;纯探索态开关两局都没测到,保留疑问(见 P0 半条)。
|
||||
@@ -0,0 +1,27 @@
|
||||
# P4(疲惫的工人)R2 复审 —— 《回声地窟》
|
||||
|
||||
> 45 岁,工地收工,宿舍 21:00,外放小音量,游戏经验少。R1 我给了 3/3 拒绝,这回是来验账的。
|
||||
> 依据:research/new8/dungeon/round2/transcript-main.md(完整弧线:教学→二层→三层→窟主→死亡归因→新周目,t=0-377)+ transcript-stress.md(前 800 行全读,另抽读 t≈2400 教学脱困段、t≈4650 中段、结尾 t≈7190;全程约两小时,253 声看门狗「咚」、仅 2 场仗、没找到楼梯、没死)。
|
||||
> 注:round2/live-player.md 这回没见到,探索态菜单能不能下滑关掉(上回清单里的 D1-1),两份转写都没考到——压力局我整局没开过菜单。这条只能记「未验」。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4/5 —— 这回从下地到躺下都有人给我递话。下楼必报层(主线 t=156.4「这是第二层」、t=243.1「这是第三层」,第三层还多一句「窟主的地界」,等于提前打了预防针);怪在隔壁先有脚步声加心跳震(主线 t=247 起一路 mob_step_bug,t=261.6 心跳震),贴脸了有人报名(t=264.0「蘑菇怪拦住了你!」);血要见底有「危险」音加三连警告震(t=330.3);挥空了有人解释(t=345.3「挥空了,它不在你面前。」);死了有归因三句(t=356.8「你背后的偷袭,要了命。」)。R1 那个「命悬一线自己不知道」没了。扣的一分:心跳震和「危险」音还是没人用嘴教过,我是打到第三层血见底才咂摸出「危险」音是啥意思——要是教学里点一句,我早半层就稳了。
|
||||
- 下一步明确性:4/5 —— 该按哪永远有人教:教学一句一个动作(t=6.4 单击、t=14.8 按住走),打仗喊「轮到你了。单击挥击」(t=345.3),蘑菇贴身还补一句「它贴着你不放,不用转身」(t=266.1);楼梯一踩到就报「楼梯就在脚下。单击,下潜。」(t=151.6、t=240.5);躺了以后「单击再探一次」,一下就重开(t=365.3)。扣的一分:楼梯在踩到之前,永远没人指路。主线我第一层摸了 99 秒(t=53-152),全靠看门狗 8 秒一「咚」陪着,最后是自己撞到楼梯格上才知道;压力局我摸了俩小时、253 声「咚」,没等来一句「楼梯大概朝哪」,最后是游戏看我实在不成器,替我「跳过教学」(压力局 t=2403.4)才放我出去的。有人陪是有了,有人指路还没有。
|
||||
- 愿意继续玩:是 —— 规则一遍懂、做错不挨骂、死得明白钱还在、打完仗耳朵能歇着。上回是熬,这回是玩。
|
||||
- P0 问题:无 —— 主线这趟从头到尾,我找不出「不知自己在哪/该干嘛/为啥死」的时刻。压力局两小时上不了楼暴露的「无指路」,我知道自己在哪(第一层)、该干嘛(脉冲加走),只是不知道楼梯在哪,降成建议第一条,不算 P0。
|
||||
- 建议:
|
||||
1. 看门狗的「咚」得长嘴:同一层走上一两分钟没踩到楼梯,就把「咚」换成一句话——「楼梯大概在你东边」或者「你兜圈了」。压力局证明光「咚」没用(253 下、俩小时、零进度);这是我现在唯一还会迷路的时刻。
|
||||
2. 窟主开打前添一句「这位不好惹,打不过就顺着来路跑」;心跳震和「危险」音也在教学里各点一句(「心跳快=它近了」「听见危险音=血要见底」)。R1 提过,这回修了一半:预防针有了(「窟主的地界」)、死因明白了,就差「可以跑」这句和俩声音的出处。
|
||||
3. 「咚」的节奏调一调:8 秒一下,主线里是「有人陪着」,压力局俩小时 253 下就成了另一种单调。有话则长(报方向),无话则短(隔半分钟轻「咚」一次就行),别让它变成新的「咚……咚……」。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
- R1 建议 1(走了几十步没上楼梯,隔一会儿提一句楼梯朝哪)→ **半修**。内容真空修扎实了:主线教学后 6 秒就有怪扑(t=160.9 脚步→t=164.4 开打),金币(t=77.1、t=196.5)、连场仗、「你的拳脚更利落了」(t=213.3)一路都有,走路不再两眼一抹黑;指路也不再看「手停没停」,改成看门狗 8 秒一「咚」。但「咚」不带方向不带话——我要的「楼梯大概朝哪」到现在没人说过,压力局 253 声「咚」零指路是硬证据。未完全兑现,是我下回还愿意来的前提里最悬的一项。
|
||||
- R1 建议 2(打不过的先打招呼;心跳震和警报教学里讲一遍)→ **大半修**。窟主不再三秒突脸:第三层进门就报「窟主的地界」(t=243.1),窟主有自己的压迫 BGM(t=319.1 bgm/boss),血见底有「危险」音加警告震(t=330.3),打了 35 秒才躺,躺了有人告诉我是「背后的偷袭」、下回「先转身」(t=356.8-358.9)。没修的:窟主报名时还是只有「窟主石甲蟹,就在你面前。」(t=319.1),没有「打不过趁早跑」;心跳震、「危险」音依旧没有嘴上解释。
|
||||
- R1 建议 3(账要对上,别颗粒无收)→ **基本修好**。主线每层有拾有仗,「小有收获」(t=274.5、t=289.5)跟实际捡的对得上;死亡结算从「这趟没带回什么」改成「这趟带回一些金币」(t=363.1),新周目开局「有些积蓄」(t=371.6)——账平了。压力局标题页「这趟没带回什么。你还没到过第三层。」(t=0-2.1)是新档实话,不算撒谎。剩一处旧账:教学区捡的金币(压力局 t=11.1「捡到几枚金币」、t=48.2 打赢掉币)过后上滑还是「口袋空空」(t=60.2)——按上回裁定这是剧本伪影、真机账目核过是对的,我记一笔不再追。
|
||||
- 附带上回的 P0 两条也销账:语音抢占死循环这回一句没断过(全程每句话都放完整,主线压力局皆然);探索期四分钟纯回声翻来覆去的苦工期没了(主线最长安静约 5 秒,静快 20 秒必有两下动静垫着)。
|
||||
|
||||
#### 容错核算(R2 更新)
|
||||
- 教学跟得上吗:跟得上,还是我玩过最贴心的开头,乱按也不恼——做错就两下短震,不骂人,换个说法重教(压力局 t=36.4「没挡住也别怕,它伤不到你。」);蘑菇贴身还现场搭手「不用转身」(主线 t=266.1)。新增兜底:教学真卡死会放我出来(压力局 t=2403.4「已跳过教学。单击脉冲,先听听四周。」),就是这兜底等了 39 分钟才来,太晚了,真工人早卸手机睡觉了。
|
||||
- 死一次多惨、会不会骂我:不骂,比上回明白得多。死因、教训、到过哪层、带回多少、下局更强,五句一口气说完(主线 t=356.8-365.3);单击一下重开,重开「遗产生效,不用再上课」(t=367.4),口袋「有些积蓄」(t=371.6)——金币留住、课不重上,死了不白死,这就是俺要的账。轻轻松赢一次也有:教学怪稳赢,窟鼠蘑菇按「单击打、前摇双击挡」都能放倒,主线五场全胜。
|
||||
- 黑暗里乱走有没有惩罚过重:没有。撞墙闷响、乱按短震,压力局俩小时血一滴没掉(t=4643 上滑还是「你毫发无损」);怪靠近只提前打招呼(「右边有脚步声」,压力局 t=387.5 等七处),从不偷袭。
|
||||
- 整体玩下来累不累:主线这趟不累了。打完仗鼓点真的会收(主线 t=175.3、t=215.5、t=276.6 都切回探索曲,R1 那个绷四分钟的打仗鼓点没了);回合卡 15 秒有「咚」加一句「轮到你了。单击挥击。」(t=345.3),不像死机;快静到 20 秒就有环境音或「附近很安静」垫着(压力局结尾 t=7187.3 amb_cave 正好在约 20 秒静默末尾响,呼吸层是真的在干活)。扣分项就一条:看门狗 8 秒一「咚」,短程是陪,长程是磨——它不吵,但也不办事。
|
||||
@@ -0,0 +1,41 @@
|
||||
# R2 Synthesis —《回声地窟》(dungeon)
|
||||
|
||||
> 产品裁定 | 证据源:4 人设翻案复审(4/4 愿意玩:P4/P2 直接翻案,P1/P3 有条件翻案)+ R2 真机报告(round2/live-player.md:P0=0)+ R2 转写 ×2。live 局 B 事件流混入同机并行 radio 语音(探针通道未隔离,已定因为仪器问题,结论按纯 dungeon 事件清洗)。
|
||||
|
||||
## 1. R2 裁决:翻案轮达成
|
||||
|
||||
| 评审方 | R1 → R2 | 结论 |
|
||||
|---|---|---|
|
||||
| P1 视障评委 | 2/5→4/5、2/5→3/5 | **是**(条件:把看门狗的嘴装上) |
|
||||
| P2 大学生 | 3/5→4/5、3/5→4/5 | **是**(R1 三理由全修复经双转写交叉验证) |
|
||||
| P3 白领 | 2/5→3/5、2/5→3/5 | **是(有条件)**(主线实际 4.5;乱按路径回归必须修) |
|
||||
| P4 工人 | 3/5→4/5、3/5→4/5 | **是**(翻案成立) |
|
||||
| 真机复测 | — | **结构修复全部兑现**:风暴绝迹(10 分钟 38 段/抢占 0 vs R1 35,611 次/99.7%)、菜单可关、金币账目一致、死亡归因句句真话 |
|
||||
|
||||
**结论:从 R1 的 0/4 到 R2 的 4/4,dungeon 完成翻案。** 剩余问题收敛为一个新 P0(看门狗饿死)+ 一条 P1(贴身铁器输入层不可达)+ 打磨项,全部进 R3。
|
||||
|
||||
## 2. R3 修复清单
|
||||
|
||||
### P0 级
|
||||
- **E0-1 看门狗饿死(四票共识 + live「连续战斗饿死救援链」归并)**:抢救计时器被「每次手势后重挂」饿死(压力局 253 次 earcon、2223s 无语音窗、0 句提示)。修:区分「无操作」与「无进展」两轨——活动重置无操作轨(保留 escape §10.3 语义),但**无进展轨只由状态推进重置**(层级/位置/战斗回合变化);超阈值走三级升级:earcon → 短句提示(现有 stair_hint_a 等)→ **导航接管**(播最短路第一步方向,含楼梯指向)。断言:连续乱按 90s(无进展)必须升级到短句与接管。
|
||||
- **E0-2 跳教学路径密度回归(P3 抓获)**:skip 教学后再 79 分钟零遭遇、39 分钟零指向语音(R1 乱按局 75s 即滚出教学 → R2 倒退)。修:跳教学路径同样执行 `_fillMainPathDensity` 与导航接管;断言:跳教学种子局主路径密度不变式 + 120s 内必有指向语音或遭遇。
|
||||
|
||||
### P1 级
|
||||
- **E1-1 贴身铁器输入层不可达(live)**:站楼梯格 tap 被下潜模态截走,「铁器=楼梯」只能靠相邻格兑现。**产品裁定方案:到达即报**——踩上楼梯格的瞬间自动播贴身铁器回声 + 下行提示短句(不靠玩家脉冲,无输入冲突,教学承诺兑现)。
|
||||
- **E1-2 band1 档位账目(P2/P4 共识)**:「捡到金币→口袋空空」谎报。修:新录 band1 替代句(语义「带回来一点,不多」,走 TTS 管线单条)+ SETTLE/TITLE 同步;band0(=0)保留「空手」措辞。
|
||||
|
||||
### P2/P3 打磨(顺手带)
|
||||
- 长按三义误逃(探索态长按歧义):短按 450ms 阈值内 tap 优先判定不变,逃跑长按需 ≥900ms(降低误触),教学补一句区分。
|
||||
- `st_best` 措辞与 `st_floor` 序列微调(live P3)。
|
||||
- 8s nudge 仪器不可验:改为 earcon+首句短词(半可验);amb_cave 听感留真机人测(roadmap §4)。
|
||||
|
||||
### 关案/悬置
|
||||
- D1-1 菜单关闭:live 实锤「一次关+BGM 回切」,**关案**。
|
||||
- 教学跳过标志跨会话不一致:仪器侧(harness localStorage 语义),记协议不改游戏。
|
||||
- 大厅误开他局、探针通道未隔离:harness/大厅层,记入批次收尾清单(不属 dungeon)。
|
||||
|
||||
## 3. R3 轮次协议(= 批次验收收口轮)
|
||||
1. dev 修 E0-1/E0-2/E1-1/E1-2 + 打磨项 → playtest 全绿(含饿死/跳教学两条新断言)+ 8 套件回归。
|
||||
2. E1-2 新词 TTS 单条重录 + voice_text.json 刷新;转写重生成。
|
||||
3. 1 局 live 确认(重点:乱按 5 分钟内必被短句/接管抢救、踩楼梯到达即报铁器、band1 新词)。
|
||||
4. 4 人设终审(P1/P3 的条件是否满足)→ R3 synthesis → 达标则 dungeon 标记可交付,批次 1 收口停下等用户上手。
|
||||
@@ -0,0 +1,19 @@
|
||||
# P2 · 时间充裕的大学生 终审——《回声地窟》(R3)
|
||||
|
||||
> 视角:23:30,宿舍躺床,戴耳机,音量正常。R1 我给 3/5+拒绝(六分钟空走廊、战斗 BGM 永不切回、金币是哑的),R2 翻案到 4/4/是。这次是终审:主线转写全读,压力局前 800 行全读 + 抽读(重点抽查:band1 新词后的账目、看门狗升级证据、死亡结算、结局段)。
|
||||
> 说明:round3 目录下没有 live-player.md,本次终审仅基于转写信息流。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4.5/5 —— 比 R2 再进半步。BGM 继续全程说真话(主线 6 场战斗打完每一次都切回探索曲,boss 有专属曲 t=252.3,死亡进 menu t=287.8);「到达即报」兑现了,四个楼梯全部是踏上格子那一拍播「楼梯就在脚下。单击,下潜。」(主线 t=119.3、176.4,压力局 t=816.8、4257.5)——R2 那个「贴脸才响还要自己脉冲」的别扭没了;铁器回声第一次在远处就开口(主线 L3 从 t=198.1 起 echo_4 配 mat_stair,隔着老远就知道「这头有楼梯」),我 R2 说「等它能在 50 格外告诉我铁器在那头」,这半句兑现了;账目侧新词「带回来一点,不多。」在两局转写里落满(见钩子终评),标题页还会记着我「还没到过第三层」(压力局 t=2.1)——元进度从数字变成了记忆。扣的半分:压力局证明长距离漫游时我对「进度」仍然失明(知道自己在第 2 层、面朝哪,但不知道自己是不是在原地兜圈),看门狗哔了 77 次只说了一句人话(t=3716.5「找找铁器的回声,那是楼梯。」),导航接管一次没出现。
|
||||
- 下一步明确性:4/5 —— 和 R2 持平,但强的更强、弱的没变。强:死亡归因升级成了教学——主线 boss 战我两拳挥空(「挥空了,它不在你面前。」t=278.5、284.5,位置机制逼我转身),死了之后「你背后的偷袭,要了命。」「身后有动静,先转身。」(t=290.0-292.1)句句属实;压力局 boss 战死于重击,结算直接给下一步:「你没挡住那记重击。」「下次,前摇声响时就双击。」(t=4520.1-4522.2)——死不再是惩罚,是攻略。弱:楼梯不在脉冲锥形范围里时,我依然没有任何热/冷反馈,背对铁器时一无所知——压力局那位玩家在 L2 漫游了 57 分钟(t=939-4372)才摸到下一道楼梯,期间零战斗、零方向提示、77 声哔;真实人类在第 10 分钟就退游戏了。教学内体验没这问题(主线 119 秒下楼),这条只伤迷路的人。
|
||||
- 愿意继续玩:是 —— 终审维持,且比 R2 更硬。这一局里元循环长出了新肉:武器掉落会念名字(「捡到更快的短刃,出手更狠了。」压力局 t=4464.1)、药水进腰带(t=906.9)、打不过可以跑但会被抓一下(「你甩掉了它,被抓了一下。」t=833.3,逃跑是有代价的选择)、标题页记得我最深到过第几层。R2 我说「想安利给室友」,这次我连词都想好了(见钩子终评)。
|
||||
- P0 问题:无 —— 「不知道自己在哪/为何失败」的时刻一个都没有;「不知道该做什么」只剩漫游找楼梯一种,且目标本身始终被告知(「找找铁器的回声」),所以不判 P0,判给建议 1。
|
||||
- 建议:
|
||||
1. 把「找楼梯」变成可导航的:脉冲对不含铁器的方向给冷反馈(或楼梯热/冷梯度),看门狗那句唯一的短句升级成带方向/带接管的版本。现在压力局 77 次哔换 1 句话、57 分钟零指路——这是我从「安利」到「按头安利」之间剩下的唯一一厘米。
|
||||
2. 结算报具体数字和遗产名:「带回来一点,不多」已经是诚实的好词了,但「带回 23 枚,离下个遗产还差 17 枚」才是让我睡前算着刷的钩子;武器都有名字了(「更快的短刃」),遗产也在开局被念到了(「攒够了新的遗产。」t=4524.3),就差结算这一口报名。
|
||||
3. 漫游期的遭遇密度下限:L2 可以空 57 分钟(t=939-4372 零战斗,只剩 7 次「附近很安静」)。「附近很安静」这个呼吸层很好,但它是双刃的——安静久了它不再安抚我,而是提醒我这里什么都没有;十分钟一只能闻到味道的怪,就能保住「地窟里有东西」的底线。
|
||||
|
||||
#### 元进度钩子终评
|
||||
- **band1 新词之后,账目顺了吗:顺了,全链路验过。** 主线:教学战「战利不多。」(t=50.7)→ 死亡结算「带回来一点,不多。」(t=296.3)→ 新周目上滑复核同一档(t=304.8)。压力局更狠:教学拾取「捡到几枚金币。」之后不再有 R2 那种「口袋空空」打脸——同一局内 t=60.2 起所有上滑都是 band1 新词,探索期拾取「一小把」(t=357.1、830.4)和「几枚」(t=4320.8)入账后档位始终自洽;金币跨周目累积后档位如实升到 band2「有些积蓄」(t=1131.8 起七次),死在窟主手里后新周目开局「攒够了新的遗产。」(t=4524.3),标题页空手时也老实说「这趟没带回什么。」(t=0)。全程 75 分钟、8 个周目、四种档位词,零自相矛盾——R2 我说「耳朵只认它骗过我一次」,现在它没再骗过我。
|
||||
- **脉冲-回声这个核心动词,决策深度终评:5 分里我给 4.5。** 它现在同时读五种东西:距离(echo_1~4)、两侧(空旷/发闷)、材质(石头/铁器,且铁器在 echo_4 的远距就会开口,t=198.1)、怪物雷达(左/右/中脚步声+心跳震,还有「附近很安静」的负空间)、以及到达确认(踏上即报)。主线 L3 那段是最好的说明书:我一边听着左侧虫足声,一边从 echo_4+mat_stair 知道楼梯在正前方远处——「朝铁器推还是避开虫子」第一次成了真正的抉择。战斗侧动词也立体了:前摇听声双击格挡、位置不对会挥空、打不过按住跑(会被抓一下)、掉武器永久变强。差的半分不在读数种类,在「背对楼梯时的沉默」——锥形之外零反馈,所以它还是声呐,不是雷达。
|
||||
- **我现在怎么向室友安利它:**「有个闭着眼睛玩的下地窟游戏——你拍一下屏幕,回声告诉你墙在哪、怪在哪、楼梯的铁器在哪头;死了金币带回来,越死越强,它还记得你最深下到过第几层,第三层有个窟主在等你。」这段话里每个字都有转写背书,R1 时我一句都编不出来。室友如果追问「迷路了怎么办」,我只能如实说「它会哔哔,然后你自己摸」——这句是我安利词里唯一的虚气,也是建议 1 存在的理由。终审结论:4.5/4/是,可交付;下一轮若是打磨,请把那一厘米补上。
|
||||
@@ -0,0 +1,27 @@
|
||||
# P3 终审(R3):《回声地窟》(dungeon)— 时间紧张的白领(条件核验轮)
|
||||
|
||||
> 视角不变:32 岁,地铁单程 25 分钟,站立单手持机,嘈杂车厢,只玩过消消乐。轨迹:R1 2/5 拒(教学后 350s 空转)→ R2 3/5 有条件是,条件=「把被打断乱摸这条路径的 39 分钟教学锁和哑巴看门狗修掉,我才是无条件继续」。本轮依据 R3 主线转写(全程)+ 压力转写(前 800 行全读 + t≈1500/2500/3716/4257/4370-4524 乱按段抽读,覆盖 t=0-4524s)逐条验收。round3 目录下无 live-player.md,一切按转写验。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4/5 —— 比上轮硬了一档。进层必报(压力局 t=821.5「这是第二层」、t=4314.1「这是第三层」);楼梯「到达即报」真的来了:踩上楼梯格的瞬间 mat_stair+「楼梯就在脚下。单击,下潜。」不用我脉冲(主线 t=119.3/176.4,压力局 t=816.8/4257.5);上滑五句复述 ~9 秒捡回层/血/钱/朝向/威胁(压力局 t=348.6-357.1:第一层→毫发无损→带回来一点,不多→面朝南→右边有脚步声),血量还会照实变(「你受了点伤」×9,对应逃掉的三场「被抓了一下」);钱账诚实分三档:band1「带回来一点,不多」×11、band2「有些积蓄」×7、真零才说「口袋空空」(主线 t=25.6 教学 0 金币),标题页元进度 t=0.0「这趟没带回什么」也对得上——R2「捡到金币→口袋空空」的谎报绝迹;死亡归因句句真话还带层号和带走多少(主线 t=290.0-298.4「你背后的偷袭,要了命/身后有动静,先转身/这是第三层/带回来一点,不多」,压力局 t=4520.1「你没挡住那记重击」)。扣的一分:压力局 t=52.5→816.8 的 12.7 分钟教学锁里,没有任何一句人声告诉我「你还卡在教学第 9 步」——这个状态只写在无声的状态栏里,我只能靠上滑自己问。
|
||||
- 下一步明确性:3/5 —— 规范路径接近满分:教学句句带动作(主线 t=6.4/12.7/19.2/21.4),战斗有「轮到你了。单击挥击。」(主线 t=278.5)和「它贴着你不放,不用转身」(t=40.7),楼梯到达即报。但乱走路径「该往哪走」仍然长期没人答:教学锁 t=52.5→816.8 约 12.7 分钟里只有每 8 秒一次双铃、零指向语音,最后是我撞上楼梯才脱出(t=816.8);第二层游荡 t=925.2→4372.7 约 57 分钟零遭遇零拾取,直到 t=3716.5 才有一句「找找铁器的回声,那是楼梯。」+警告三连震——E0-1 的短句升级真实存在且开了口,但整局 75 分钟只开了这一次。
|
||||
- 愿意继续玩:是 —— 正常坐车的那条路已经是我想装进手机的通勤游戏(主线 t=0-310 一条龙:教学→金币→下潜→三战→升级→第三层→窟主→阵亡→新周目);乱按路径从 R2 的一小时酷刑降到十二分钟闷铃,不再让我拒绝,但离我开的条件还差最后一截,见下。
|
||||
- P0 问题:无 —— 「在哪/该做什么/为何失败」三个问题在任何时刻都有答案:目标句 t=52.5「铁器的回声,就是下潜的楼梯」、上滑复述全程可报、归因链不撒谎。但按 R2 协议,教学锁内「零指向语音+每 8 秒双铃」仍是 P1 头名(t=52.5-816.8),记入条件核验与建议 1。
|
||||
- 建议:≤3 条,按对「我愿意玩下去」的影响排序
|
||||
1. 把 E0-1 的 90 秒断言真跑出来:教学锁 764 秒里短句升级 0 次、导航接管 0 次;全压力局「找找铁器的回声」只开一次口(t=3716.5,距进第二层已 48 分钟)。病根在「位置变化=进展」:乱撞恰好永远在换位置,无进展轨永远被重置——要么把撞墙原地震荡从进展里摘掉,要么让锁内看门狗第 4 次响铃就升级。修好这条,我的条件才算全清。
|
||||
2. 乱走路径的遭遇保底还差一半:脱出教学后 110 秒内 3 战 1 拾(t=830.4 金币、t=830.7/837.3/843.9 三场窟鼠)证明密度保底会做,但第二层中段 46 分钟(t=925.2-3716.5)只有脚步、撞墙和脉冲——把 R2 说的「每 60-90s 对任何移动路径保底一次遭遇」真对乱走路径生效。
|
||||
3. 铃的形态没变:nudge+watchdog 双音同响(t=74.6 起,全压力局 77 对,全部发生在 t<1000s)与 R2 听感一致,说好的「earcon+首句短词」没体现;呼吸环境音 amb_cave 两局合计 0 次,探索静默期的底噪仍未上线。
|
||||
- R2 遗留回执:长按=前进在晃动车厢易断(R1 记账)**未动**;1.2s 格挡窗口**未放宽**,但「不用转身」+「没挡住也别怕,它伤不到你」(压力局 t=40.7/36.4)把判断量压住了,消消乐手可接受;乱按长按逃跑能成且只留轻伤(「你甩掉了它,被抓了一下」×5)——容错比我上轮预期的好。
|
||||
|
||||
#### 条件满足核验(我的条件=乱按路径回归修复,对应 E0-1/E0-2,附带 E1-1/E1-2)
|
||||
1. **E0-1(哑巴看门狗 + 90s 升级断言)→ 部分达成。** 升级链存在且真实开过一次口(t=3716.5 短句+警告三连震),战斗态的嘴一直是好的(主线 t=278.5「轮到你了。单击挥击。」);但教学锁 764 秒内升级 0 次,「播最短路第一步方向」的导航接管在这份 75 分钟乱按局里一次都没被观察到,8 秒双铃形态与 R2 无异。「连续乱按 90s(无进展)必须升级」的断言在转写里不成立——按「位置变化=进展」的定义,乱撞永远有进展,漏洞就在这。
|
||||
2. **E0-2(跳教学/乱走路径密度回归)→ 部分达成(间接)。** 压力局没发生主动跳教学(玩家是撞对楼梯出的教学,t=816.8,状态栏自己都写「可能跳了课,可能一路错过来的」),E0-2 的跳教学断言在这份转写里验不到;但脱出后的密度保底真实生效(t=823.7 出教学→110 秒内金币+三战),R2 那种 79 分钟死区没有复现,全程零死锁(t=4524.3「压力测试全程零死锁」收工)。残余是第二层中段 46 分钟零事件空洞。
|
||||
3. **E1-1(踩楼梯到达即报)→ 达成。** 四次楼梯抵达(主线 ×2、压力局 ×2)全是踩格瞬间 mat_stair+提示短句,不靠玩家脉冲、无输入冲突。
|
||||
4. **E1-2(band1 档位账目)→ 达成。** 「带回来一点,不多」「有些积蓄」分档如实,「口袋空空」只在真零出现,结算与新周目复述同步(主线 t=296.3/t=304.8)。
|
||||
5. **上滑 9 秒复述 → 成立。** 五句约 8.5 秒(压力局 t=348.6-357.1),内容从四句变五句、威胁行与血量会动,一句话捡回局面的承诺还在。
|
||||
6. **结论:四项 2 达成、2 部分达成——条件部分满足。** R2 让我拒绝的东西(39 分钟锁、79 分钟死区、假账、死亡不解释)全部消失或减半;但「看门狗会说话」这一半只活在断言里,75 分钟只兑现了一次、晚了 48 分钟。
|
||||
|
||||
#### 通勤压力终测
|
||||
- **场景 A(正常坐车、跟着教学走)**:达标,且比 R2 更顺。主线 t=0-310 一条龙,t=180 前 4 次正反馈照旧;到达即报(t=119.3/176.4)让我不用脉冲也能确认楼梯;升级有新句(「捡到更快的短刃,出手更狠了。」压力局 t=4464.1),死一次 ~10 秒回桌不扣钱、新周目还带「攒够了新的遗产」(t=4524.3)——给跨天通勤留了一个盼头。25 分钟单程够跑 3-4 个周目。
|
||||
- **场景 B(报站分神/同事拍肩后乱摸)**:教学锁 12.7 分钟(39→12.7,好转 3 倍),锁内每 8 秒双铃、零句话;真实车厢里我 3 分钟内就会退 App,损失可控,但体验仍是「催促不是安抚」。好消息:双铃只闹前 1000 秒,之后全程安静(R2 是 253 连响 39 分钟);坏消息:安静=没人管我,第二层走空 46 分钟无人拉我回主线。乱打 Boss 也能死个明白(t=4520.1-4522.2 归因+一句「下次,前摇声响时就双击」),这不是惩罚是教练。
|
||||
- **噪音与单手盲操**:单击/按住/左右滑全程可盲操、无强制发声(摸鱼安全);慌乱长按逃跑 5 次全成、只留轻伤,容错温和;战斗关键提示有 beat 震+turn 震双通道,车厢里丢一句语音还有手腕兜底。缺的仍是探索底噪(amb_cave 0 次)和锁内那句「你还卡在教学里」。
|
||||
@@ -0,0 +1,28 @@
|
||||
# P4(疲惫的工人)R3 终审 —— 《回声地窟》
|
||||
|
||||
> 45 岁,工地收工,宿舍 21:00,外放小音量,游戏经验少。R1 我给 3/3 拒绝,R2 翻案 4/5 愿意玩,留了一桩账:**「楼梯朝哪没人说」**。这回是终审,专程来验这桩账的。
|
||||
> 依据:round3/transcript-main.md(完整弧线:教学→二层→三层→窟主→死→新周目,t=0-310)+ round3/transcript-stress.md(前 800 行全读,另抽读 t≈2057、t≈3716 指路句窗口、t≈4377-4524 打窟主与死亡段、结尾;全程约 75 分钟,77 声看门狗「咚」、12 场仗、两次踩到楼梯、一次躺、零死锁)+ round2/p4-worker.md、round2/synthesis.md(对照验账)。
|
||||
> 注:round3/live-player.md 这回没见到,以下全按两份转写验。
|
||||
|
||||
### 回声地窟
|
||||
- 状态感知:4.5/5 —— R2 扣的那半分是「心跳震和危险音没人教」,这回教学里还是没人口头讲一句「心跳快=它近了」「危险音=血要见底」,我是靠挨过几回才咂摸出来的,这半分照扣。但这回多了两样硬货:一是踩上楼梯的当口有人当场报「楼梯就在脚下。单击,下潜。」(主线 t=119.3、t=176.4,压力局 t=816.8、t=4257.5,四次全报,一次没落);二是账改真话了,「带回来一点,不多。」(主线 t=296.3 死亡结算、t=304.8 新周目上滑)——从前「捡到金币→口袋空空」那种糊涂账没了,空手新档老实说「这趟没带回什么」(压力局 t=0)。脚下是啥、兜里有多少,都实诚了。
|
||||
- 下一步明确性:4.5/5 —— 我 R2 留的那桩账,验的结果是**半修,但修在了要紧处**。修好的:迷路熬到头有人开口了——压力局 t=3716.5,看门狗升级带警告震说了一句「找找铁器的回声,那是楼梯。」;乱按局从 R2 的俩小时上不了楼,缩到 13 分半就滚出教学踩到楼梯(t=816.8),正常主线我 70 秒就撞见楼梯、踩上即报——平时玩根本用不着等那句指路。没修透的:那句指路 75 分钟里就来了这么一回,而且只说「找铁器」、不说「朝哪走」——「楼梯大概在你东边」这种方位词,两局转写里一个字没出过声,到头来还是靠自己一格一格撞。
|
||||
- 愿意继续玩:是 —— 躺了有人告诉我为啥躺、钱一分没少带回来、单击一下就重开还不用重上课。R1 我是熬,R2 是玩,这回是收工后愿意主动摸起手机来玩。
|
||||
- P0 问题:无 —— 主线一局到头没有不明不白的时刻;压力局 75 分钟乱按零死锁、零无声死局,躺了归因句句是真话(「你没挡住那记重击。」「下次,前摇声响时就双击。」t=4520-4522)。
|
||||
- 建议:
|
||||
1. 指路句带上方位、勤快半档:「找找铁器的回声」后面跟半句「大概朝南」就齐了;同一层干转上一两分钟,这句别等 60 分钟才来一回(压力局 t=3716 那句之前,我干转了整整一个钟头)。这是 R1 到 R3 我一直在等的最后那半句。
|
||||
2. 心跳震和「危险」音,教学里各给一句:「心跳快就是它近了」「听见危险音,血就见底了」。三回了,我还是靠猜的。
|
||||
3. 逃跑这手没人教过嘴上的:状态里写着「单击挥击,按住屏幕逃跑」(压力局 t=4392),逃成了有「你甩掉了它,被抓了一下。」(t=4377.6)兜着,Boss 逃不掉也在状态里写明——但「按住」和走路那个「按住」有啥不一样,得自己试出来。开打播报时捎带半句就行。
|
||||
|
||||
#### R2 遗留专查回执
|
||||
- **迷路时有人开口指路了吗(短句+导航接管)**:短句有了——「找找铁器的回声,那是楼梯。」带警告震(压力局 t=3716.5);「播最短路第一步方向」这级没在两份转写里出过声。算修了三级里的两级半。
|
||||
- **踩楼梯自动报铁器**:修好,四次踩楼梯四次报(主线 t=119.3/176.4,压力局 t=816.8/4257.5),「楼梯就在脚下。单击,下潜。」明明白白,E1-1 兑现。
|
||||
- **「带回来一点,不多」新账目**:落地。拾取「捡到几枚金币」(主线 t=85.8)、「捡到一小把金币」(压力局 t=357.1)当场对账;结算和新周目都是「带回来一点,不多。」;遗产「有些积蓄」「攒够了新的遗产」(压力局 t=4524.3);零谎报,E1-2 兑现。
|
||||
- **逃跑按住 900ms 的提示句**:没有嘴上的教学句,「按住屏幕逃跑」只在状态行里写着;逃成功的结果句即时又诚实(甩掉了、被抓了一下),Boss 逃不掉也写明了。能摸出来,不算一遍就懂。
|
||||
- **累不累终评**:不累。仗打完鼓点两秒就收(主线 t=145.5、158.6、224.6);回合卡住有人喊「轮到你了。单击挥击。」(主线 t=278.5);死一次的代价就是听五句实话、点一下重开;75 分钟压力局血一滴没掉。剩一条老毛病:长迷路时 8 秒一「咚」还是那个节拍器,好在如今 13 分半就见着楼梯了,这「咚」是陪着等,不是干熬。
|
||||
|
||||
#### 容错核算终评
|
||||
- 教学跟得上吗:跟得上,还是我最贴心的开头。乱按不恼,做错两下短震,换个说法重教(「没挡住也别怕,它伤不到你。」压力局 t=36.4);蘑菇贴身还有人搭手「不用转身」。
|
||||
- 死一次多惨、会不会骂我:不惨、不骂。死因(「你背后的偷袭,要了命」/「你没挡住那记重击」)、教训(「身后有动静,先转身」/「前摇声响时就双击」)、到过哪层、带回多少、下局更强,一口气说完;「带回来一点,不多」进账,单击再探,遗产生效不用重上课。轻轻松赢一次也有:教学怪稳赢,窟鼠蘑菇照「单击打、前摇双击挡」都能放倒,主线五场全胜。
|
||||
- 黑暗里乱走有没有惩罚过重:没有。压力局 75 分钟乱按,血一滴没掉(直到我上头去捅窟主才躺);怪靠近只提前打招呼(「右边有脚步声」多处),从不偷袭。
|
||||
- 整体玩下来累不累:不累,终评过关。单局有头有尾五分钟上下,赢也热热闹闹(success 长震),输也明明白白(归因三问),重开一击即走。R1 那个「越玩越累」的地窟,这回我是躺下玩完还想着「再探一次」的——就差「楼梯朝哪」最后半句,我就能放心把它当收工后的保留节目了。
|
||||
@@ -0,0 +1,806 @@
|
||||
# 试玩转写:《dungeon》
|
||||
|
||||
> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文,
|
||||
> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作),
|
||||
> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。
|
||||
t+ 0.0s (玩家点开游戏,轻触屏幕开始)
|
||||
t+ 0.0s ♫ BGM 切换 → bgm/menu
|
||||
t+ 0.0s ♪ 向导音:menu(系统界面)
|
||||
t+ 0.0s 【状态】盲眼探窟者睁开了耳朵,准备下窟 标题页:单击开始探窟,上滑听元进度(BGM=bgm/menu,语速1)
|
||||
|
||||
#### 【玩家动作】单击,开始
|
||||
|
||||
t+ 0.0s ▶ 语音:「新的探窟,开始了。」
|
||||
t+ 2.1s ♫ BGM 切换 → bgm/explore
|
||||
t+ 2.1s ♪ 向导音:explore(探索/安全)
|
||||
t+ 2.1s ▶ 语音:「你在黑暗中醒来。这里是回声地窟。」
|
||||
t+ 2.1s 【状态】教学开始:三句开场白 教学演练第 0 步,跟着旁白做(语音播放中,语速1)
|
||||
t+ 4.2s ▶ 语音:「伸手不见五指,声音就是你的眼睛。」
|
||||
t+ 6.4s ▶ 语音:「先学会用耳朵看。单击,发出声波脉冲。」
|
||||
|
||||
#### 【玩家动作】单击回应「先学会用耳朵看」
|
||||
|
||||
|
||||
#### 【玩家动作】单击——人生第一声脉冲
|
||||
|
||||
t+ 8.5s ♪ 音效 sfx/pulse
|
||||
t+ 8.5s ▶ 语音:「听,回声回来了。」
|
||||
t+ 8.8s ♪ 音效 sfx/side_open_l
|
||||
t+ 8.8s ♪ 音效 sfx/side_open_r
|
||||
t+ 9.0s ♪ 音效 sfx/echo_2
|
||||
t+ 9.1s ♪ 音效 sfx/mat_stone
|
||||
t+ 10.6s ▶ 语音:「回声回来越快,墙就越近。」
|
||||
t+ 10.6s 【状态】回声回来了,听墙的距离 教学演练第 2 步,跟着旁白做(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】单击继续
|
||||
|
||||
t+ 12.7s ▶ 语音:「两侧的回声,发闷是墙,空旷是通路。」
|
||||
|
||||
#### 【玩家动作】单击继续(侧向规则听完了)
|
||||
|
||||
t+ 14.8s ♪ 音效 sfx/step_turn
|
||||
t+ 14.8s ▶ 语音:「按住屏幕不放,你就往前走。」
|
||||
|
||||
#### 【玩家动作】按住屏幕不放——脚步声起,往前走
|
||||
|
||||
t+ 14.8s ♪ 音效 sfx/step_own
|
||||
t+ 14.8s 〰 震动:swipe(滑动识别)
|
||||
t+ 15.3s ♪ 音效 sfx/step_own
|
||||
t+ 15.3s ▶ 语音:「左滑右滑,可以转身。」
|
||||
t+ 15.8s ♪ 音效 sfx/bump
|
||||
t+ 15.3s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】松开,停下
|
||||
|
||||
|
||||
#### 【玩家动作】左滑,转身
|
||||
|
||||
t+ 16.5s ♪ 音效 sfx/step_turn
|
||||
|
||||
#### 【玩家动作】右滑,转回来
|
||||
|
||||
t+ 17.1s ♪ 音效 sfx/step_turn
|
||||
t+ 17.1s ▶ 语音:「双击,再发一次脉冲,不要钱。」
|
||||
|
||||
#### 【玩家动作】双击——再发一次脉冲,不要钱
|
||||
|
||||
t+ 17.1s ♪ 音效 sfx/pulse
|
||||
t+ 17.1s ▶ 语音:「听,回声回来了。」
|
||||
t+ 17.4s ♪ 音效 sfx/echo_1
|
||||
t+ 17.5s ♪ 音效 sfx/side_open_l
|
||||
t+ 17.5s ♪ 音效 sfx/side_wall_r
|
||||
t+ 17.5s ♪ 音效 sfx/mat_stone
|
||||
t+ 19.2s ▶ 语音:「上滑,随时听自己的状态。」
|
||||
t+ 21.4s ▶ 语音:「下滑,打开菜单。」
|
||||
|
||||
#### 【玩家动作】上滑,听自己的状态
|
||||
|
||||
t+ 21.4s ▶ 语音:「这是第一层。」
|
||||
t+ 23.5s ▶ 语音:「你毫发无损。」
|
||||
t+ 25.6s ▶ 语音:「口袋空空。」
|
||||
t+ 27.7s ▶ 语音:「你面朝东。」
|
||||
|
||||
#### 【玩家动作】下滑,打开菜单
|
||||
|
||||
t+ 27.7s ♫ BGM 切换 → bgm/menu
|
||||
t+ 27.7s ♪ 向导音:menu(系统界面)
|
||||
t+ 27.7s ▶ 语音:「菜单。单击切换,双击确认。」
|
||||
t+ 29.8s ▶ 语音:「返回探索。」
|
||||
|
||||
#### 【玩家动作】再下滑,关上菜单
|
||||
|
||||
t+ 29.8s ♪ 向导音:explore(探索/安全)
|
||||
t+ 29.8s ♫ BGM 切换 → bgm/explore
|
||||
t+ 29.8s ♪ 音效 sfx/step_turn
|
||||
t+ 29.8s ♪ 音效 sfx/step_turn
|
||||
t+ 29.8s ▶ 语音:「前面有东西!放心,它伤不到你。」
|
||||
t+ 29.8s 【状态】「前面有东西!放心,它伤不到你」——等它扑上来 教学演练第 8 步,跟着旁白做(语音播放中,语速1)
|
||||
t+ 31.0s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 32.2s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 32.2s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 33.2s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 33.2s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 33.4s ♫ BGM 切换 → bgm/battle(淡入 400ms)
|
||||
t+ 33.4s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 33.4s ▶ 语音:「盲眼蝠扑了过来!」
|
||||
t+ 33.4s 【状态】教学怪扑到了面前 战斗播报中,先听着(语音播放中,语速1)
|
||||
t+ 35.6s ▶ 语音:「听到它的动静,双击格挡。」
|
||||
t+ 37.7s ♪ 音效 sfx/tel_small
|
||||
t+ 37.7s 〰 震动:beat(节拍点)
|
||||
|
||||
#### 【玩家动作】听到它的动静——双击,格挡
|
||||
|
||||
t+ 37.7s ♪ 音效 sfx/parry
|
||||
t+ 37.7s 〰 震动:confirm(轻点确认)
|
||||
t+ 38.9s ▶ 语音:「挡住了!」
|
||||
t+ 41.0s ▶ 语音:「现在单击,挥拳打它。」
|
||||
t+ 43.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 43.1s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击挥拳,两拳放倒它
|
||||
|
||||
t+ 43.1s ♪ 音效 sfx/atk_swing
|
||||
t+ 43.1s ♪ 音效 sfx/atk_hit
|
||||
t+ 43.1s ♪ 音效 sfx/tel_small
|
||||
t+ 43.1s 〰 震动:beat(节拍点)
|
||||
t+ 43.6s ♪ 音效 sfx/parry
|
||||
t+ 43.6s 〰 震动:confirm(轻点确认)
|
||||
t+ 44.3s ▶ 语音:「挡住了!」
|
||||
t+ 46.4s ▶ 语音:「现在单击,挥拳打它。」
|
||||
t+ 48.6s ♪ 向导音:turn(轮到你)
|
||||
t+ 48.6s 〰 震动:confirm(轻点确认)
|
||||
t+ 48.6s ♪ 音效 sfx/atk_swing
|
||||
t+ 48.6s ♪ 音效 sfx/atk_hit
|
||||
t+ 48.6s ♪ 音效 sfx/enemy_die
|
||||
t+ 48.6s ♪ 音效 sfx/coin
|
||||
t+ 48.6s ▶ 语音:「打中了,就是这样。」
|
||||
t+ 48.6s 〰 震动:success(成功长震)
|
||||
t+ 50.7s ▶ 语音:「战利不多。」
|
||||
t+ 52.8s ♫ BGM 切换 → bgm/explore(淡入 400ms)
|
||||
t+ 52.8s ▶ 语音:「铁器的回声,就是下潜的楼梯。」
|
||||
t+ 52.8s 【状态】教学战获胜——「打中了,就是这样」 教学演练第 9 步,跟着旁白做(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】单击,听听楼梯的铁器回声
|
||||
|
||||
t+ 52.8s ♪ 音效 sfx/pulse
|
||||
t+ 53.1s ♪ 音效 sfx/side_wall_l
|
||||
t+ 53.1s ♪ 音效 sfx/side_open_r
|
||||
t+ 53.9s ♪ 音效 sfx/echo_4
|
||||
t+ 54.0s ♪ 音效 sfx/mat_stone
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 56.3s ♪ 音效 sfx/pulse
|
||||
t+ 56.7s ♪ 音效 sfx/side_wall_l
|
||||
t+ 56.7s ♪ 音效 sfx/side_open_r
|
||||
t+ 57.4s ♪ 音效 sfx/echo_4
|
||||
t+ 57.5s ♪ 音效 sfx/mat_stone
|
||||
t+ 60.6s ♪ 音效 sfx/step_turn
|
||||
t+ 60.8s ♪ 音效 sfx/step_own
|
||||
t+ 60.8s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 61.3s ♪ 音效 sfx/pulse
|
||||
t+ 61.6s ♪ 音效 sfx/side_open_l
|
||||
t+ 61.6s ♪ 音效 sfx/side_open_r
|
||||
t+ 61.8s ♪ 音效 sfx/echo_2
|
||||
t+ 61.9s ♪ 音效 sfx/mat_stone
|
||||
t+ 69.3s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 69.3s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 69.3s ♪ 音效 sfx/step_turn
|
||||
t+ 77.3s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 77.3s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 77.3s ♪ 音效 sfx/step_own
|
||||
t+ 77.3s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 77.8s ♪ 音效 sfx/pulse
|
||||
t+ 78.2s ♪ 音效 sfx/side_open_l
|
||||
t+ 78.2s ♪ 音效 sfx/side_wall_r
|
||||
t+ 78.6s ♪ 音效 sfx/echo_3
|
||||
t+ 78.7s ♪ 音效 sfx/mat_stone
|
||||
t+ 85.8s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 85.8s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 85.8s ♪ 音效 sfx/step_own
|
||||
t+ 85.8s ♪ 音效 sfx/coin
|
||||
t+ 85.8s ▶ 语音:「捡到几枚金币。」
|
||||
t+ 85.8s 〰 震动:swipe(滑动识别)
|
||||
t+ 85.8s 〰 震动:pickup(获得)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 86.3s ♪ 音效 sfx/pulse
|
||||
t+ 86.7s ♪ 音效 sfx/side_open_l
|
||||
t+ 86.7s ♪ 音效 sfx/side_wall_r
|
||||
t+ 87.1s ♪ 音效 sfx/echo_3
|
||||
t+ 87.2s ♪ 音效 sfx/mat_stone
|
||||
t+ 94.3s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 94.3s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 94.3s ♪ 音效 sfx/step_own
|
||||
t+ 94.3s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 94.8s ♪ 音效 sfx/pulse
|
||||
t+ 95.2s ♪ 音效 sfx/side_open_l
|
||||
t+ 95.2s ♪ 音效 sfx/side_wall_r
|
||||
t+ 95.3s ♪ 音效 sfx/echo_2
|
||||
t+ 95.4s ♪ 音效 sfx/mat_stone
|
||||
t+ 102.8s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 102.8s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 102.8s ♪ 音效 sfx/step_own
|
||||
t+ 102.8s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 103.3s ♪ 音效 sfx/pulse
|
||||
t+ 103.5s ♪ 音效 sfx/echo_1
|
||||
t+ 103.7s ♪ 音效 sfx/side_open_l
|
||||
t+ 103.7s ♪ 音效 sfx/side_open_r
|
||||
t+ 103.7s ♪ 音效 sfx/mat_stone
|
||||
t+ 111.3s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 111.3s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 111.3s ♪ 音效 sfx/step_turn
|
||||
t+ 119.3s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 119.3s ♪ 向导音:watchdog(看门狗升级)
|
||||
t+ 119.3s ♪ 音效 sfx/step_own
|
||||
t+ 119.3s ♪ 音效 sfx/echo_1
|
||||
t+ 119.3s ▶ 语音:「楼梯就在脚下。单击,下潜。」
|
||||
t+ 119.3s 〰 震动:swipe(滑动识别)
|
||||
t+ 119.4s ♪ 音效 sfx/mat_stair
|
||||
|
||||
#### 【玩家动作】踏上楼梯格——「楼梯就在脚下」
|
||||
|
||||
|
||||
#### 【玩家动作】铁器就在脚下——单击,下潜
|
||||
|
||||
t+ 119.8s ♪ 音效 sfx/stairs_down
|
||||
t+ 119.8s ▶ 语音:「你顺着楼梯,往下潜。」
|
||||
t+ 121.9s ▶ 语音:「教学完了。地窟很深,小心走。」
|
||||
t+ 124.0s ▶ 语音:「这是第二层。」
|
||||
t+ 126.2s ♪ 向导音:explore(探索/安全)
|
||||
t+ 126.2s 【状态】教学完了。第二层,真正的地窟从这里开始 第 2 层黑暗里:单击发脉冲用回声看路,按住前进,左右滑转身,上滑状态,下滑菜单(BGM=bgm/explore,语速1)
|
||||
|
||||
#### 【玩家动作】单击脉冲,探一探第 2 层
|
||||
|
||||
t+ 126.2s ♪ 音效 sfx/pulse
|
||||
t+ 126.5s ♪ 音效 sfx/side_open_l
|
||||
t+ 126.5s ♪ 音效 sfx/side_wall_r
|
||||
t+ 126.7s ♪ 音效 sfx/echo_2
|
||||
t+ 126.8s ♪ 音效 sfx/mat_stone
|
||||
t+ 127.7s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 127.8s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 128.1s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 129.4s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 129.4s 〰 震动:heartbeat(心跳/倒计时)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 129.4s ♪ 音效 sfx/pulse
|
||||
t+ 129.7s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 129.8s ♪ 音效 sfx/side_open_l
|
||||
t+ 129.8s ♪ 音效 sfx/side_wall_r
|
||||
t+ 129.9s ♪ 音效 sfx/echo_2
|
||||
t+ 130.0s ♪ 音效 sfx/mat_stone
|
||||
t+ 130.2s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 131.3s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 131.8s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 131.8s ♪ 音效 sfx/step_own
|
||||
t+ 131.8s 〰 震动:swipe(滑动识别)
|
||||
t+ 132.1s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 132.1s 〰 震动:heartbeat(心跳/倒计时)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 132.1s ♪ 音效 sfx/pulse
|
||||
t+ 132.4s ♪ 音效 sfx/echo_1
|
||||
t+ 132.5s ♪ 音效 sfx/side_open_l
|
||||
t+ 132.5s ♪ 音效 sfx/side_open_r
|
||||
t+ 132.5s ♪ 音效 sfx/mat_stone
|
||||
t+ 132.8s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 133.7s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 134.1s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 134.4s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 134.4s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 134.4s ♪ 音效 sfx/step_turn
|
||||
t+ 135.4s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 135.4s ♪ 音效 sfx/step_own
|
||||
t+ 135.4s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 135.9s ♪ 音效 sfx/pulse
|
||||
t+ 136.3s ♪ 音效 sfx/side_open_l
|
||||
t+ 136.3s ♪ 音效 sfx/side_wall_r
|
||||
t+ 136.5s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 136.7s ♪ 音效 sfx/echo_3
|
||||
t+ 136.8s ♫ BGM 切换 → bgm/battle(淡入 400ms)
|
||||
t+ 136.8s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 136.8s ▶ 语音:「窟鼠窜了出来!」
|
||||
t+ 138.9s ♪ 向导音:turn(轮到你)
|
||||
t+ 138.9s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 138.9s ♪ 音效 sfx/atk_swing
|
||||
t+ 138.9s ♪ 音效 sfx/atk_hit
|
||||
t+ 138.9s ♪ 音效 sfx/tel_small
|
||||
t+ 138.9s 〰 震动:beat(节拍点)
|
||||
t+ 140.1s ♪ 音效 sfx/hurt
|
||||
t+ 140.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 140.1s 〰 震动:hit(受击重震)
|
||||
t+ 140.1s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 140.1s ♪ 音效 sfx/atk_swing
|
||||
t+ 140.1s ♪ 音效 sfx/atk_hit
|
||||
t+ 140.1s ♪ 音效 sfx/tel_small
|
||||
t+ 140.1s 〰 震动:beat(节拍点)
|
||||
t+ 141.3s ♪ 音效 sfx/hurt
|
||||
t+ 141.3s ♪ 向导音:turn(轮到你)
|
||||
t+ 141.3s 〰 震动:hit(受击重震)
|
||||
t+ 141.3s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 141.3s ♪ 音效 sfx/atk_swing
|
||||
t+ 141.3s ♪ 音效 sfx/atk_hit
|
||||
t+ 141.3s ♪ 音效 sfx/enemy_die
|
||||
t+ 141.3s ♪ 音效 sfx/coin
|
||||
t+ 141.3s ▶ 语音:「它倒下了。」
|
||||
t+ 141.3s 〰 震动:success(成功长震)
|
||||
t+ 143.4s ▶ 语音:「战利不多。」
|
||||
t+ 145.5s ♫ BGM 切换 → bgm/explore
|
||||
t+ 145.5s ♪ 向导音:explore(探索/安全)
|
||||
t+ 147.1s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 147.4s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 147.4s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 148.8s ♪ 音效 sfx/mob_step_small_c
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 148.8s ♪ 音效 sfx/pulse
|
||||
t+ 149.1s ♪ 音效 sfx/side_open_l
|
||||
t+ 149.1s ♪ 音效 sfx/side_wall_r
|
||||
t+ 149.6s ♪ 音效 sfx/echo_3
|
||||
t+ 149.7s ♪ 音效 sfx/mat_stone
|
||||
t+ 149.9s ♪ 音效 sfx/mob_step_small_l
|
||||
t+ 149.9s ♫ BGM 切换 → bgm/battle(淡入 400ms)
|
||||
t+ 149.9s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 149.9s ▶ 语音:「窟鼠窜了出来!」
|
||||
t+ 149.9s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 152.0s ♪ 向导音:turn(轮到你)
|
||||
t+ 152.0s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 152.0s ♪ 音效 sfx/atk_swing
|
||||
t+ 152.0s ♪ 音效 sfx/atk_hit
|
||||
t+ 152.0s ♪ 音效 sfx/tel_small
|
||||
t+ 152.0s 〰 震动:beat(节拍点)
|
||||
t+ 153.2s ♪ 音效 sfx/hurt
|
||||
t+ 153.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 153.2s 〰 震动:hit(受击重震)
|
||||
t+ 153.2s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 153.2s ♪ 音效 sfx/atk_swing
|
||||
t+ 153.2s ♪ 音效 sfx/atk_hit
|
||||
t+ 153.2s ♪ 音效 sfx/tel_small
|
||||
t+ 153.2s 〰 震动:beat(节拍点)
|
||||
t+ 154.4s ♪ 音效 sfx/hurt
|
||||
t+ 154.4s ♪ 向导音:turn(轮到你)
|
||||
t+ 154.4s 〰 震动:hit(受击重震)
|
||||
t+ 154.4s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 154.4s ♪ 音效 sfx/atk_swing
|
||||
t+ 154.4s ♪ 音效 sfx/atk_hit
|
||||
t+ 154.4s ♪ 音效 sfx/enemy_die
|
||||
t+ 154.4s ♪ 音效 sfx/coin
|
||||
t+ 154.4s ▶ 语音:「它倒下了。」
|
||||
t+ 154.4s 〰 震动:success(成功长震)
|
||||
t+ 156.5s ▶ 语音:「战利不多。」
|
||||
t+ 158.6s ♫ BGM 切换 → bgm/explore
|
||||
t+ 158.6s ♪ 向导音:explore(探索/安全)
|
||||
t+ 160.7s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 162.5s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 162.5s 〰 震动:heartbeat(心跳/倒计时)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 163.6s ♪ 音效 sfx/pulse
|
||||
t+ 164.0s ♪ 音效 sfx/side_open_l
|
||||
t+ 164.0s ♪ 音效 sfx/side_wall_r
|
||||
t+ 164.4s ♪ 音效 sfx/echo_3
|
||||
t+ 164.5s ♪ 音效 sfx/mat_stone
|
||||
t+ 164.9s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 167.2s ♪ 音效 sfx/mob_step_small_c
|
||||
t+ 167.2s ♪ 音效 sfx/step_turn
|
||||
t+ 168.6s ♪ 音效 sfx/step_own
|
||||
t+ 168.6s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 169.1s ♪ 音效 sfx/pulse
|
||||
t+ 169.5s ♪ 音效 sfx/side_wall_l
|
||||
t+ 169.5s ♪ 音效 sfx/side_open_r
|
||||
t+ 169.6s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 169.6s ♪ 音效 sfx/echo_2
|
||||
t+ 169.7s ♪ 音效 sfx/mat_stair
|
||||
t+ 169.6s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 171.6s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 171.6s ♪ 音效 sfx/step_own
|
||||
t+ 171.6s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 172.1s ♪ 音效 sfx/pulse
|
||||
t+ 172.3s ♪ 音效 sfx/echo_1
|
||||
t+ 172.4s ♪ 音效 sfx/side_open_l
|
||||
t+ 172.4s ♪ 音效 sfx/side_open_r
|
||||
t+ 172.5s ♪ 音效 sfx/mat_stair
|
||||
t+ 174.1s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 176.4s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 176.4s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 176.4s ♪ 音效 sfx/step_own
|
||||
t+ 176.4s ♪ 音效 sfx/echo_1
|
||||
t+ 176.4s ▶ 语音:「楼梯就在脚下。单击,下潜。」
|
||||
t+ 176.4s 〰 震动:swipe(滑动识别)
|
||||
t+ 176.5s ♪ 音效 sfx/mat_stair
|
||||
|
||||
#### 【玩家动作】铁器就在脚下——单击,下潜
|
||||
|
||||
t+ 176.9s ♪ 音效 sfx/stairs_down
|
||||
t+ 176.9s ▶ 语音:「你顺着楼梯,往下潜。」
|
||||
t+ 179.0s ▶ 语音:「这是第三层。」
|
||||
t+ 179.0s 【状态】第三层——窟主的地界 顺着楼梯,往下潜……(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】脉冲听路,朝楼梯摸过去
|
||||
|
||||
t+ 181.1s ♪ 向导音:explore(探索/安全)
|
||||
t+ 182.7s ♪ 音效 sfx/mob_step_bug_l
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 182.7s ♪ 音效 sfx/pulse
|
||||
t+ 183.0s ♪ 音效 sfx/side_open_l
|
||||
t+ 183.0s ♪ 音效 sfx/side_open_r
|
||||
t+ 183.8s ♪ 音效 sfx/echo_4
|
||||
t+ 183.9s ♪ 音效 sfx/mat_stone
|
||||
t+ 185.0s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 185.0s ♪ 音效 sfx/step_own
|
||||
t+ 185.0s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 185.5s ♪ 音效 sfx/pulse
|
||||
t+ 185.8s ♪ 音效 sfx/side_open_l
|
||||
t+ 185.8s ♪ 音效 sfx/side_open_r
|
||||
t+ 186.3s ♪ 音效 sfx/echo_3
|
||||
t+ 186.4s ♪ 音效 sfx/mat_stone
|
||||
t+ 186.5s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 188.0s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 188.0s ♪ 音效 sfx/step_own
|
||||
t+ 188.0s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 188.2s ♪ 音效 sfx/pulse
|
||||
t+ 188.6s ♪ 音效 sfx/side_open_l
|
||||
t+ 188.6s ♪ 音效 sfx/side_open_r
|
||||
t+ 189.0s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 189.0s ♪ 音效 sfx/echo_3
|
||||
t+ 189.1s ♪ 音效 sfx/mat_stone
|
||||
t+ 189.9s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 190.5s ♪ 音效 sfx/step_own
|
||||
t+ 190.5s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 191.0s ♪ 音效 sfx/pulse
|
||||
t+ 191.4s ♪ 音效 sfx/side_wall_l
|
||||
t+ 191.4s ♪ 音效 sfx/side_wall_r
|
||||
t+ 191.5s ♪ 音效 sfx/echo_2
|
||||
t+ 191.6s ♪ 音效 sfx/mat_stone
|
||||
t+ 191.8s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 192.2s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 193.0s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 193.0s ♪ 音效 sfx/step_own
|
||||
t+ 193.0s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 193.5s ♪ 音效 sfx/pulse
|
||||
t+ 193.8s ♪ 音效 sfx/echo_1
|
||||
t+ 193.9s ♪ 音效 sfx/side_open_l
|
||||
t+ 193.9s ♪ 音效 sfx/side_wall_r
|
||||
t+ 193.9s ♪ 音效 sfx/mat_stone
|
||||
t+ 194.2s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 194.5s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 195.1s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 196.1s ♪ 音效 sfx/step_turn
|
||||
t+ 196.6s ♪ 音效 sfx/step_own
|
||||
t+ 196.6s 〰 震动:swipe(滑动识别)
|
||||
t+ 196.9s ♪ 音效 sfx/mob_step_bug_c
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 196.9s ♪ 音效 sfx/pulse
|
||||
t+ 197.2s ♪ 音效 sfx/side_wall_l
|
||||
t+ 197.2s ♪ 音效 sfx/side_wall_r
|
||||
t+ 197.4s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 198.0s ♪ 音效 sfx/echo_4
|
||||
t+ 198.1s ♪ 音效 sfx/mat_stair
|
||||
t+ 198.9s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 198.9s ♪ 音效 sfx/step_own
|
||||
t+ 198.9s 〰 震动:swipe(滑动识别)
|
||||
t+ 199.2s ♪ 音效 sfx/mob_step_bug_c
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 199.2s ♪ 音效 sfx/pulse
|
||||
t+ 199.6s ♪ 音效 sfx/side_wall_l
|
||||
t+ 199.6s ♪ 音效 sfx/side_wall_r
|
||||
t+ 200.0s ♪ 音效 sfx/echo_3
|
||||
t+ 200.1s ♪ 音效 sfx/mat_stair
|
||||
t+ 200.6s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 200.7s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 201.2s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 201.2s ♪ 音效 sfx/step_own
|
||||
t+ 201.2s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 201.7s ♪ 音效 sfx/pulse
|
||||
t+ 202.1s ♪ 音效 sfx/side_wall_l
|
||||
t+ 202.1s ♪ 音效 sfx/side_wall_r
|
||||
t+ 202.3s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 202.5s ♪ 音效 sfx/echo_3
|
||||
t+ 202.6s ♪ 音效 sfx/mat_stair
|
||||
t+ 202.8s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 203.3s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 204.2s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 204.2s ♪ 音效 sfx/step_own
|
||||
t+ 204.2s 〰 震动:swipe(滑动识别)
|
||||
t+ 204.7s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 204.7s 〰 震动:heartbeat(心跳/倒计时)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 204.7s ♪ 音效 sfx/pulse
|
||||
t+ 205.1s ♪ 音效 sfx/side_wall_l
|
||||
t+ 205.1s ♪ 音效 sfx/side_wall_r
|
||||
t+ 205.2s ♪ 音效 sfx/echo_2
|
||||
t+ 205.3s ♪ 音效 sfx/mat_stair
|
||||
t+ 205.6s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 206.6s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 207.1s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 207.1s ♫ BGM 切换 → bgm/battle(淡入 400ms)
|
||||
t+ 207.1s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 207.1s ▶ 语音:「蘑菇怪拦住了你!」
|
||||
t+ 207.1s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 209.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 209.2s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 210.8s ♪ 音效 sfx/atk_swing
|
||||
t+ 210.8s ♪ 音效 sfx/atk_hit
|
||||
t+ 210.8s ♪ 音效 sfx/tel_bug
|
||||
t+ 210.8s 〰 震动:beat(节拍点)
|
||||
t+ 212.0s ♪ 音效 sfx/hurt
|
||||
t+ 212.0s ♪ 向导音:turn(轮到你)
|
||||
t+ 212.0s 〰 震动:hit(受击重震)
|
||||
t+ 212.0s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 212.0s ♪ 音效 sfx/atk_swing
|
||||
t+ 212.0s ♪ 音效 sfx/atk_hit
|
||||
t+ 212.0s ♪ 音效 sfx/tel_bug
|
||||
t+ 212.0s 〰 震动:beat(节拍点)
|
||||
|
||||
#### 【玩家动作】前摇声响——双击,格挡
|
||||
|
||||
t+ 213.0s ♪ 音效 sfx/parry
|
||||
t+ 213.0s 〰 震动:confirm(轻点确认)
|
||||
t+ 213.2s ▶ 语音:「挡下了大半!」
|
||||
t+ 215.3s ♪ 向导音:turn(轮到你)
|
||||
t+ 215.3s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 217.1s ♪ 音效 sfx/atk_swing
|
||||
t+ 217.1s ♪ 音效 sfx/atk_hit
|
||||
t+ 217.1s ♪ 音效 sfx/tel_bug
|
||||
t+ 217.1s 〰 震动:beat(节拍点)
|
||||
t+ 218.3s ♪ 音效 sfx/hurt
|
||||
t+ 218.3s ♪ 向导音:turn(轮到你)
|
||||
t+ 218.3s 〰 震动:hit(受击重震)
|
||||
t+ 218.3s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 218.3s ♪ 音效 sfx/atk_swing
|
||||
t+ 218.3s ♪ 音效 sfx/atk_hit
|
||||
t+ 218.3s ♪ 音效 sfx/enemy_die
|
||||
t+ 218.3s ♪ 音效 sfx/coin
|
||||
t+ 218.3s ▶ 语音:「它倒下了。」
|
||||
t+ 218.3s 〰 震动:success(成功长震)
|
||||
t+ 220.4s ▶ 语音:「小有收获。」
|
||||
t+ 222.5s ▶ 语音:「你的拳脚更利落了。」
|
||||
t+ 224.6s ♫ BGM 切换 → bgm/explore
|
||||
t+ 224.6s ♪ 向导音:explore(探索/安全)
|
||||
t+ 226.3s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 226.3s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 226.3s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 228.1s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 228.1s ♫ BGM 切换 → bgm/battle(淡入 400ms)
|
||||
t+ 228.1s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 228.1s ▶ 语音:「蘑菇怪拦住了你!」
|
||||
t+ 228.1s 〰 震动:heartbeat(心跳/倒计时)
|
||||
t+ 230.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 230.2s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 231.9s ♪ 音效 sfx/atk_swing
|
||||
t+ 231.9s ♪ 音效 sfx/atk_hit
|
||||
t+ 231.9s ♪ 音效 sfx/tel_bug
|
||||
t+ 231.9s 〰 震动:beat(节拍点)
|
||||
t+ 233.1s ♪ 音效 sfx/hurt
|
||||
t+ 233.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 233.1s 〰 震动:hit(受击重震)
|
||||
t+ 233.1s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 233.1s ♪ 音效 sfx/atk_swing
|
||||
t+ 233.1s ♪ 音效 sfx/atk_hit
|
||||
t+ 233.1s ♪ 音效 sfx/tel_bug
|
||||
t+ 233.1s 〰 震动:beat(节拍点)
|
||||
|
||||
#### 【玩家动作】前摇声响——双击,格挡
|
||||
|
||||
t+ 233.7s ♪ 音效 sfx/parry
|
||||
t+ 233.7s 〰 震动:confirm(轻点确认)
|
||||
t+ 234.3s ▶ 语音:「挡下了大半!」
|
||||
t+ 236.4s ♪ 向导音:turn(轮到你)
|
||||
t+ 236.4s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】单击,挥击
|
||||
|
||||
t+ 236.4s ♪ 音效 sfx/atk_swing
|
||||
t+ 236.4s ♪ 音效 sfx/atk_hit
|
||||
t+ 236.4s ♪ 音效 sfx/enemy_die
|
||||
t+ 236.4s ♪ 音效 sfx/coin
|
||||
t+ 236.4s ▶ 语音:「它倒下了。」
|
||||
t+ 236.4s 〰 震动:success(成功长震)
|
||||
t+ 238.6s ▶ 语音:「小有收获。」
|
||||
t+ 240.7s ♫ BGM 切换 → bgm/explore
|
||||
t+ 240.7s ♪ 向导音:explore(探索/安全)
|
||||
t+ 242.9s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 244.4s ♪ 音效 sfx/mob_step_bug_c
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 244.4s ♪ 音效 sfx/pulse
|
||||
t+ 244.8s ♪ 音效 sfx/side_wall_l
|
||||
t+ 244.8s ♪ 音效 sfx/side_wall_r
|
||||
t+ 244.9s ♪ 音效 sfx/echo_2
|
||||
t+ 245.1s ♪ 音效 sfx/mat_stair
|
||||
t+ 246.1s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 248.4s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 248.4s ♪ 音效 sfx/step_own
|
||||
t+ 248.4s 〰 震动:swipe(滑动识别)
|
||||
|
||||
#### 【玩家动作】单击发脉冲,听回声辨路
|
||||
|
||||
t+ 248.9s ♪ 音效 sfx/pulse
|
||||
t+ 249.2s ♪ 音效 sfx/echo_1
|
||||
t+ 249.3s ♪ 音效 sfx/side_open_l
|
||||
t+ 249.3s ♪ 音效 sfx/side_open_r
|
||||
t+ 249.3s ♪ 音效 sfx/mat_stair
|
||||
t+ 250.7s ♪ 音效 sfx/mob_step_bug_c
|
||||
t+ 252.3s ♪ 音效 sfx/mob_step_bug_l
|
||||
t+ 252.3s ♪ 音效 sfx/step_own
|
||||
t+ 252.3s ♫ BGM 切换 → bgm/boss(淡入 400ms)
|
||||
t+ 252.3s ♪ 向导音:battle(战斗/对抗)
|
||||
t+ 252.3s ▶ 语音:「窟主石甲蟹,就在你面前。」
|
||||
t+ 252.3s 〰 震动:swipe(滑动识别)
|
||||
t+ 254.4s ♪ 向导音:turn(轮到你)
|
||||
t+ 254.4s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】咬牙单击——挡不住了也要打
|
||||
|
||||
t+ 254.4s ♪ 音效 sfx/atk_swing
|
||||
t+ 254.4s ♪ 音效 sfx/atk_hit
|
||||
t+ 254.4s ♪ 音效 sfx/tel_heavy
|
||||
t+ 254.4s 〰 震动:beat(节拍点)
|
||||
t+ 255.6s ♪ 音效 sfx/hurt
|
||||
t+ 255.6s ♪ 向导音:turn(轮到你)
|
||||
t+ 255.6s 〰 震动:hit(受击重震)
|
||||
t+ 255.6s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】喘一口气,再挥
|
||||
|
||||
|
||||
#### 【玩家动作】咬牙单击——挡不住了也要打
|
||||
|
||||
t+ 262.3s ♪ 音效 sfx/atk_swing
|
||||
t+ 262.3s ♪ 音效 sfx/atk_hit
|
||||
t+ 262.3s ♪ 音效 sfx/mob_step_heavy_r
|
||||
t+ 262.3s ♪ 音效 sfx/tel_heavy_r
|
||||
t+ 262.3s 〰 震动:beat(节拍点)
|
||||
t+ 263.5s ♪ 音效 sfx/hurt
|
||||
t+ 263.5s ♪ 向导音:danger(危险)
|
||||
t+ 263.5s ♪ 向导音:turn(轮到你)
|
||||
t+ 263.5s 〰 震动:hit(受击重震)
|
||||
t+ 263.5s 〰 震动:warning(警告三连震)
|
||||
t+ 263.5s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】喘一口气,再挥
|
||||
|
||||
t+ 278.5s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 278.5s ▶ 向导语音:「轮到你了。单击挥击。」
|
||||
t+ 278.5s ♪ 音效 sfx/turn_tick
|
||||
|
||||
#### 【玩家动作】咬牙单击——挡不住了也要打
|
||||
|
||||
t+ 278.5s ♪ 音效 sfx/atk_swing
|
||||
t+ 278.5s ▶ 语音:「挥空了,它不在你面前。」
|
||||
t+ 280.6s ♪ 音效 sfx/tel_heavy_r
|
||||
t+ 280.6s 〰 震动:beat(节拍点)
|
||||
t+ 281.8s ♪ 音效 sfx/hurt
|
||||
t+ 281.8s ♪ 向导音:turn(轮到你)
|
||||
t+ 281.8s 〰 震动:hit(受击重震)
|
||||
t+ 281.8s 〰 震动:confirm(轻点确认)
|
||||
|
||||
#### 【玩家动作】喘一口气,再挥
|
||||
|
||||
|
||||
#### 【玩家动作】咬牙单击——挡不住了也要打
|
||||
|
||||
t+ 284.5s ♪ 音效 sfx/atk_swing
|
||||
t+ 284.5s ▶ 语音:「挥空了,它不在你面前。」
|
||||
t+ 286.6s ♪ 音效 sfx/mob_step_heavy_c
|
||||
t+ 286.6s ♪ 音效 sfx/tel_heavy
|
||||
t+ 286.6s 〰 震动:beat(节拍点)
|
||||
t+ 287.8s ♪ 音效 sfx/hurt
|
||||
t+ 287.8s ♫ BGM 切换 → bgm/menu
|
||||
t+ 287.8s ♪ 向导音:settle(结算)
|
||||
t+ 287.8s ▶ 语音:「你倒下了。」
|
||||
t+ 287.8s 〰 震动:hit(受击重震)
|
||||
t+ 287.8s 〰 震动:hit(受击重震)
|
||||
t+ 287.8s 【状态】倒下了。死亡归因链:死于谁、哪里没做好、带走了多少金币 结算:死亡归因与元进度入账,单击再探一次(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】听完归因三问和「下个周目,你会更强」
|
||||
|
||||
t+ 290.0s ▶ 语音:「你背后的偷袭,要了命。」
|
||||
t+ 292.1s ▶ 语音:「身后有动静,先转身。」
|
||||
t+ 294.2s ▶ 语音:「这是第三层。」
|
||||
t+ 296.3s ▶ 语音:「带回来一点,不多。」
|
||||
t+ 298.4s ▶ 语音:「下个周目,你会更强。」
|
||||
|
||||
#### 【玩家动作】单击——再探一次
|
||||
|
||||
t+ 298.4s ♪ 向导音:menu(系统界面)
|
||||
|
||||
#### 【玩家动作】单击,开始新周目
|
||||
|
||||
t+ 298.4s ▶ 语音:「新的探窟,开始了。」
|
||||
t+ 300.6s ♫ BGM 切换 → bgm/explore
|
||||
t+ 300.6s ♪ 向导音:explore(探索/安全)
|
||||
t+ 300.6s ▶ 语音:「这是第一层。」
|
||||
t+ 300.6s 【状态】新周目直落探索:遗产生效,不用再上课 第 1 层黑暗里:单击发脉冲用回声看路,按住前进,左右滑转身,上滑状态,下滑菜单(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】上滑,听新周目的局面复述
|
||||
|
||||
t+ 300.6s ▶ 语音:「这是第一层。」
|
||||
t+ 302.4s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 302.7s ▶ 语音:「你毫发无损。」
|
||||
t+ 303.0s ♪ 音效 sfx/mob_step_small_l
|
||||
t+ 304.8s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 304.8s ▶ 语音:「带回来一点,不多。」
|
||||
t+ 305.0s ♪ 音效 sfx/mob_step_small_l
|
||||
t+ 306.9s ▶ 语音:「你面朝北。」
|
||||
t+ 307.0s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 307.2s ♪ 音效 sfx/mob_step_small_l
|
||||
|
||||
#### 【玩家动作】单击脉冲,听听熟悉的回声
|
||||
|
||||
t+ 307.2s ♪ 音效 sfx/pulse
|
||||
t+ 307.6s ♪ 音效 sfx/side_open_l
|
||||
t+ 307.6s ♪ 音效 sfx/side_open_r
|
||||
t+ 307.7s ♪ 音效 sfx/echo_2
|
||||
t+ 307.8s ♪ 音效 sfx/mat_stone
|
||||
t+ 309.0s ♪ 音效 sfx/mob_step_small_l
|
||||
t+ 309.0s ▶ 语音:「左边有脚步声。」
|
||||
t+ 309.2s ♪ 音效 sfx/mob_step_small_r
|
||||
t+ 310.6s 【状态】第二周目短程收尾——死亡-重开循环跑通,收工 第 1 层黑暗里:单击发脉冲用回声看路,按住前进,左右滑转身,上滑状态,下滑菜单(语音播放中,语速1)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
# P1 视障资深玩家评审:《不眠频率》(R2 复审)
|
||||
|
||||
> 评审依据:research/new8/radio/round2/transcript-main.md(主线一局)+ transcript-stress.md(乱按压力一局,与 R1 压力局同剧本,逐拍可比:菜单同样 38 次、乱试同样 199 次、V1 签名同样落在 t+688.9)+ round2/live-player.md(真机五修验证轮)。
|
||||
> 沿用 R1 口径:两局转写 t+0.0 依旧有约 44 行「资产缺失→静默」警告块,且与后文发声自相矛盾(onair_sting 标缺却 t+2.1 照响、brake_screech 标缺却 t+223.4/t+1032.4 照响)——仍判定为转写器资产盘点附注,按实际发声行为评审。真机局 A t=0.011s phone_ring fetch 200、铃声窗 astats Peak -1.5dB/RMS -15.4dB,R1 我留的那句「真机必须先确认开场 15 秒」正式销案:开场不哑。
|
||||
|
||||
### 不眠频率
|
||||
- 状态感知:4.5/5(保持,扣分换人)—— R1 扣的 0.5 两处收回了算清了一处:rep=0 措辞(F2)全修,main t+58.8、stress t+21.2/48.8/61.3/71.8/82.2/92.6/103.1/132.1/142.5 共九处全部是「今晚的口碑,还没立起来。」,零起步就该这么说,账目与文案终于咬合。其余底盘照旧稳:每通来电报名(main t+14.8/t+97.3/t+127.6/t+161.6/t+200.4)、口碑只在跨档时开口(main t+92.2「不好不坏」→ t+122.5「立住了」;未跨档的 t+158.6/t+197.4 闭嘴)、上滑随手报「第几通+口碑」(stress t+69.6/71.8 乱流中照样报)、199 次乱按后锚没垮。新挂的 0.25 名目:一是上滑帮助链仍垫在状态前面(见建议 1,stress 里逐字重复 15 次以上);二是 F3 的铃声只活在真机(局 A t=29.65 起 loop、接听 t=169.0 即停早于人声)——离线转写里 RING 入口仍只有 turn 签名+确认震(main t+14.8),我这种只读转写的耳朵听不见它。另记一笔两口径矛盾:arg_muffled/brake_screech 在离线转写里有发声记录(main t+132.9/t+223.4,stress t+570.2/t+1032.4),真机报告却判其仍为 SA3 缺口(V3 等 HF token)——按我 R1 的规矩,信真机、从紧,维持已知遗留不重复计数。
|
||||
- 下一步明确性:5/5(保持,且证据从「转写推断」升级成「断言+真机双锁」)—— 开场 30 秒三件事照旧一次讲清(t+2.1/t+6.4/t+10.6),第一通 t+14.8 就到。R1 我只见过看门狗第一级(main t+42.0),这回 F1 真机四组实测把话堵死了:链末等待里做无效手势,看门狗以手势时刻为基准重挂,局 A t=354.7 手贱→t=380.2「单击屏幕,继续」→t=405.2 第二级,局 B 播放中手贱 t=397.3→t=410.8→t=427.8,full/standard 两档分秒不差——无效手势「零静默」重新闭环。F5 尾句保护我在转写里亲手点收:R1 被抢跑吃掉的「他们明天,会一起给我切蛋糕吗?」这回完整落在 main t+150.8,「但空着的那一秒,你说满了」t+247.2 一字不少;真机侧尾句句中/句尾单击五处全部无效化、链中段跳句三处照常生效,护尾不废跳。F4 续玩锁(真机 t=21.5 首句 1.5s 处戳不动、会话 C 验出「播完即释放」不变成永远不可跳)把我最怕的「保护变枷锁」也排了。全程没有一秒不知道该干什么。
|
||||
- 愿意继续玩:是 —— 比 R1 更硬的一票:五项修复没有一项是糊弄的复读,e1 之外我还见着了 e3「一个人的频道也是频道」,四结局已见其三。等 SA3 的 13 件声音凑齐,这是能进我推荐位的作品。
|
||||
- P0 问题:无(两局转写 + 真机报告范围内)。失败归因我照例去压力局对账:t+521.5「她走了。没上车,也没退票」(我 t+484.8 说的「把选择还给她」)、t+696.1「你许了个兑不了的现」(我 t+691.0 许的谎)、t+932.9 陈姐劝回线各自点到我的原话;尾声 t+1066.8-1075.2 五条逐人对账——老周谢歌(我 p1 陪哼歌 t+193.2)、小鹿退票(p3 右)、糖糖楼下在吵(p5 谎言)、陈姐末班车(p6 劝回)、老韩到家小红花(p8 陪聊 t+998.7);因我 p1 陪了歌,t+1044.7「头通电话那位大爷……这城市的夜,是接着的」照常接入,bond 回响一句不差。账还是真的。
|
||||
- 建议:
|
||||
1. 上滑状态链重排并截短(R1 建议 2,本轮唯一没被采纳的):状态(第几通+口碑)放最前,六秒帮助句截短或归菜单。压力局这条逐字相同的链重复了 15 次以上(t+44.5/57.1/67.5/77.9/88.4…),对 75 档语速用户是按次收取的过路费。这次把它挂成正式欠账,R3 我还来收。
|
||||
2. mid-prompt 缓存滑的契约钉死(V1 关案跟进——live 报告 P3-6 点名「人设复审可议」,我现在议):断言已锁「抉择句播完才生效、播中连滑取最后一次、零插播」(playtest.mjs L1066-1090,我亲自读了),这条我收下,盲玩公平保住了。但 live 局 A p6 复播句仍被缓存滑掐尾立即生效——复播句我已听过一遍,即掐即生效我收下,这是快手指向,我喜欢效率;请把「首播必完整、复播可即掐」写成显式规则并补一条断言,别让它停留在口头契约。离线转写里 t+688.9→691.0 又见同款签名(抉择句起 2.1 秒后结果句上账),离线时间轴是剧本步进+估算时长、断不了案,断案权在断言与真机——两处目前都站得住,所以我不升 P1,但要白纸黑字。
|
||||
3. 转写器与真机口径收敛(仪器侧,三件):离线转写 RING 无铃声、t+0.0 警告块与后文发声自相矛盾、压力局语速仍标 1(1.7 倍速只在真机局 B 真跑过)。每一件都逼读转写的评委先做一轮考古才敢下笔。R3 全员复评前对齐,别让仪器替游戏背锅,也别让仪器替游戏遮丑。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
1. 【开场 15 秒资产疑云(警告块 vs 实际发声)】→ **已解释,销案**。维持「转写器附注」判定;真机补证:局 A t=0.011s phone_ring 预载 200、铃声 30-39s 窗 astats 实测在响,R1 假设的「哑开场 P0」不存在。
|
||||
2. 【建议 1:菜单第三项存疑(V2)】→ **已解释 + 断言锁定,撤回「功能洞」指控**。「保存并回大厅」一直在循环第三格(game.js L194 `lobby`),压力局剧本每次逛菜单只点一下,38 次(t+25.4 至 t+1017.8,38 处「回到直播」逐处核对)全数停在第二格「重新开始今晚」,不是游戏藏着它,是剧本的手永远够不着第三格。playtest 断言锁死全项顺序与回绕(sys_menu→回到直播→重新开始今晚→保存并回大厅,末项单击回绕首项,playtest.mjs L646-690),登记于 docs/design/15-radio.md §9(193 条)。存档退出另有自动存档+续玩询问补位(真机局 B t=0.1「检测到你的夜班记录」→ t=19.5 续玩成功)。账算清了,这页翻过去。
|
||||
3. 【建议 2:状态链重排截短】→ **仍存在**(未采纳,不属 F/V 单)。R2 压力局逐字帮助链 15+ 次原样重现,升级为本轮建议 1,挂账。
|
||||
4. 【建议 3:rep=0 措辞(F2)】→ **已修**。九处全部「还没立起来」,用的基本是我 R1 原话——这单结得漂亮,Fx 里我唯一认领的原案,收货。
|
||||
5. 【长按快进/语速上限(R1 唯一悬而未决的「生死线」)】→ **部分验证 + 降级**。1.7 倍速真机整局负线跑通(局 B 57 手势:乱序、菜单打断复播、双击重听、长按 boost,零状态错乱、零叠音零死锁);但 harness 长按固定 600ms 只能尝 ~0.1s boost,「持续按住揉出快进」的手感仍无人真测过。从「生死线」降为「真机第一课」:最坏情况(1.7x+乱流)已过且没炸,不再一票否决,但真机上手我仍要亲手揉一次再画押。
|
||||
|
||||
附:R2 指定核验项中非我 R1 原案的两条,一并过账——F1 看门狗(证据见「下一步明确性」,修好,全场最硬);F5 链末跳过保护(main t+150.8/t+247.2 转写落点 + 真机五处无效化三处照跳,修好且没矫枉过正)。
|
||||
|
||||
#### 听觉惯例符合度(R2 逐条更新)
|
||||
- 语音可打断:过(保持)。t+6.4 口令照旧;向导纠错 idle-only 纪律未松(stress t+17.0 同句第二次仍标注跳过未播、只留 error 震)。
|
||||
- 语音可重听:过(保持)。双击原样重播(stress t+105.2→109.3);查完状态自动复述选项(main t+60.9),仍是「复述选项=合法帮助」的正确姿势。
|
||||
- 等待有无声:过(升级)。离线最长等待 25s 有看门狗兜底(main t+17.0→42.0);真机侧 F1 四组实测——无效手势后两级看门狗以手势时刻为基准准点归来,R1 那口 34 秒深坑填平,两档分秒不差。
|
||||
- 失败可归因:过(保持,见 P0)。归因句仍只挂负向结果,主线局零教学零归因,没人把我当白痴。
|
||||
- 菜单列表导航规整:过(从「半过」转正)。口令规整、关菜单必重播当前节点落位(stress t+119.7→123.8,与 R1 同拍);第三项存在且全项循环有断言看守;菜单 BGM 独立、下滑关闭回原状态(断言「下滑关闭菜单→回原状态」)。
|
||||
- 提示永不逐字重复:过(升级)。两级看门狗现场验讫(局 A t=380.2 一级→t=405.2 二级,句句不同);RING 两级不同句的规矩已写进断言(15-radio.md §9:gd_ring2 id ≠ gd_ring1,绝不逐字重播)。
|
||||
- 账目真实:过(保持)。rep 轨迹与分档句咬合(main t+92.2「不好不坏」、t+122.5 跨 5「立住了」);stress 跨档播报只在 t+1005.1 出现一次、低→低不播——账没多也没少;e1/e3 两版尾声都亲耳(转写)过目。
|
||||
- 语速上限/长按快进:半过(从「未验证」推进)。1.7x 底盘真机验讫;持续长按手感工具够不着,真机手测保留。
|
||||
- status key:过(保持)。199 次乱流之后,「第几通+口碑」随口可报(stress t+71.8/82.2/132.1 等),锚没被冲垮过。
|
||||
- 双击确认(菜单约定):过(保持)。单击循环+双击确认+上滑帮助+下滑关闭,全程无一次跳字或误确认;循环回绕行为补进了断言。
|
||||
@@ -0,0 +1,25 @@
|
||||
# P3 复审(R2):《不眠频率》(radio)— 时间紧张的白领
|
||||
|
||||
> 视角同 R1:32 岁,地铁单程 25 分钟,站立单手持机,嘈杂车厢,只玩过消消乐。R1 我给状态感知 4.5/5、愿意玩,唯一 P0 是「乱按局选项句没念完结果就出」。本轮依据 R2 主线+压力两份转写与真机复测报告(live-player.md)代入复审,专查我那条 P0 和帮助链啰嗦。
|
||||
|
||||
### 不眠频率
|
||||
- 状态感知:5/5 —— R1 扣的 0.5 两处这轮都清了。其一,乱按局那个「不知道自己选了什么」的瞬间:压力局 t=688.9-691.0 字面上还在(选项句 t=688.9 起,t=691.0 结果「睡吧。明天一睁眼」就出),但数了一遍,压力局 8 个抉择清一色 ~2.1 秒出结果,连我一点都不乱按的收播抉择(t=1054.0-1056.2)也是 2.2 秒——这是剧本每 2.1 秒塞一个手势的节拍格,不是音频真相;真机报告按引擎 vend/dur 审计,TRUNCATED 7 处全部归因玩家 tap、0 处游戏自残截断,pendingChoice「播完才生效」断言后关案。而且就算真是我手快把选项句掐了尾巴,结果句+后果句也把我做的事讲得明明白白(t=691.0「睡吧」→ t=696.1「你许了个兑不了的现。孩子睡了,谎留下了」),R1 那种迷失没有复现;真正一个字不能丢的链末点题句有 F5 护着(真机 d9_facee 两局足时、句尾单击一律无效化)。其二,铃声风险已消:R2 转写 t=0.0 缺失清单里没有 phone_ring 了,真机实测铃声循环真响(Peak -1.5 dB)、接听即停早于人声。其余照旧稳:第几通+口碑一句话报(主线 t=56.7-58.8,rep_low 新词「还没立起来」账也对上了),漏听自动重播选项(主线 t=60.9)。
|
||||
- 下一步明确性:5/5 —— 开场 14.8 秒第一声铃(主线),教学 t=2.1 讲完左右滑;压力局 199 次乱试+38 次逛菜单,收尾 t=1077.4 明写「没有任何一次手势被无声吞掉,也没有卡死在某个状态里」,结局链照样走完;链末走神有「单击屏幕,继续」(主线 t=42.0)兜底,且 R1 之后无效手势拆不掉这个兜底了(F1 真机两级提醒分秒不差);半路下车再上车,恢复链首句护住不被我条件反射戳乱(F4,锁只锁一句)。
|
||||
- 愿意继续玩:是 —— 整晚 4 分半每通都是完整小故事,最乱的一局也把我送到了结局;我这个会乱按的人都没被丢下,正经玩只会更顺。
|
||||
- P0 问题:无 —— R1 那条(t=688.9-691.0 选项没念完结果就出)经仪器伪影甄别+真机断言复核关案,详见「R1 遗留逐条回执」第 1 条。
|
||||
- 建议:≤3 条,按对「我愿意玩下去」的影响排序
|
||||
1. 帮助链收敛(R1 建议,未动,仍是最磨人的一项):压力局全量口令「单击继续,双击重新听。上滑听状态……」一字不差重播 38 次(t=44.5/57.1/67.5/77.9/88.4/98.8……),我早会了还念;更密的是上滑听状态也要先付完这 ~8 秒口令才轮到「第 N 通+口碑」(主线 t=54.6-58.8)。建议口令只在开场念,之后上滑直接报「第 N 通+口碑」两句。
|
||||
2. 关菜单别重播整句:压力局关菜单仍把当前整句来电重播(t=503.9「退不退,都是你的自由……」,t=514.5 又一遍),逛 38 次菜单等于白听几十句、还把戏往后拖。建议关菜单只「叮」一声回到等待。
|
||||
3. 快滑掐尾巴给个回执:真机上句中滑动立即生效是「零插播」契约(真机报告 P3-6),我认这笔账记在我自己手上;但建议生效时给一记区分震或半句「你选了右边」,地铁晃着的时候我不用回想刚才那下算数没有。
|
||||
|
||||
#### R1 遗留逐条回执
|
||||
1. **R1 P0「乱按局选项句没念完结果就出」(t=688.9-691.0)→ 关案。** R2 压力转写同一位置字面复现(剧本确定性、时间戳同拍):t=688.9 选项句起,t=691.0 结果句出。但三条证据把它从 P0 摘掉:(a) 仪器伪影甄别——8 个抉择全部 ~2.1s 出结果,含零乱按的收播抉择(t=1054.0-1056.2),说明 2.1s 是转写的手势节拍格而非「句被掐」的音频证据;(b) 真机引擎级审计——TRUNCATED 清单 7 处全归因玩家 tap、0 处游戏自残,pendingChoice 生效时序加断言(播完才生效)后关案;(c) 残余行为「句中快滑立即生效」被真机报告明确标为设计契约(P3-6「零插播」,玩家侧无感知损失),且 F4/F5 把恢复链首句与链末点题句护死。R1 的实际伤害「不知道自己选了什么/为什么这个结果」未复现:结果句+后果句自解释(t=691.0→696.1)。残余的体面收尾降为本轮建议 3。
|
||||
2. **R1 建议 1「教学口令只在开场念,上滑只报两句」→ 未收敛,未列入 F 类。** 压力局全量口令逐字重播 38 次(同 R1 的 t=44.5 起。
|
||||
3. **R1 建议 2「结果句前垫『你刚才选了右』回执」→ 显式回执没做,但实质被结果句+后果句承担**(压力局 t=691.0「睡吧。明天一睁眼」= 右滑「答应她明天都会好」,t=696.1 后果句点评),「不知道为什么这个结果」未复现。降级并入本轮建议 3。
|
||||
4. **R1 建议 3「关菜单不重播全句」→ 未动。** 压力局 t=503.9 与 R1 同拍同句重播「退不退,都是你的自由」。维持为本轮建议 2。
|
||||
5. **R1 扣分项「真缺铃声则接听提示只剩轻震」→ 已消。** F3 修好:R2 转写 t=0.0 缺失清单从 12 件降到 11 件且无 phone_ring(真机 fetch 200 + 程序合成循环垫 + astats Peak -1.5 dB + 接听即停早于人声)。剩余 11 件(arg_muffled/brake_screech 等)为 V3 已知资产缺口、等 HF token,本轮不重复计数。
|
||||
|
||||
#### 通勤压力再测
|
||||
- **一通电话是不是 3-4 分钟颗粒**:是。主线整晚 t=0-266.3(约 4 分半 ≈ 两个站距),五通各 25-77 秒自带起承转合(最快 C2 t=97.3-122.5,25 秒一通完整小故事),幕间垫乐只有 3-5 秒(t=92.2→97.3),全程无沉默尴尬期;被打断就当下车,损失最多半通。压力局同样成立:18 分钟纯乱按也走到了结局和五条回响(收尾 t=1077.4)。
|
||||
- **被打断后上滑复述**:够,仍是我最喜欢的设计。主线 t=54.6-63.1 全套演示——上滑→口令→「现在是今晚第一通电话」→「今晚的口碑,还没立起来」(F2 新词,账对)→自动重播卡住的选项,我一句话捡回局面;错过 C3 糖糖的关键句有 C4 带话兜底(t=177.8「四十分钟前,有个孩子问我们……」),信息不靠记性;走神 25 秒有 t=42.0 看门狗捞,且 F1 之后无效手势拆不掉它(真机 25.5s/25.0s 分秒不差);站台换乘再打开,续玩恢复链首句有 F4 护着,不会被我的条件反射单击戳乱。唯一代价是要先听完 8 秒口令(见建议 1)。
|
||||
- **单手操作全滑动**:能。全部操作就是单击/双击/左右滑/上滑/下滑,无长按依赖、全程不需要我出声(摸鱼怕出声这条满分);压力局 199 次乱试+38 次逛菜单零吞手势零卡死,1.7 倍速真机 57 个乱序手势零状态错乱。嘈杂车厢的适配也变好了:铃声现在真响(F3),吵没听清可以双击重听(教学 t=2.1 讲过);唯一遗憾还是 SA3 那 11 件资产(t=0.0 警告墙仍在)——糖糖家楼下的闷响和急刹恰恰是最能穿透地铁噪音的戏,等资产到位我再听一遍。
|
||||
@@ -0,0 +1,28 @@
|
||||
# R2 Synthesis —《不眠频率》(radio)
|
||||
|
||||
> 产品裁定 | 证据源:R2 真机复测(round2/live-player.md:五修全坐实,P0/P1/P2=0)+ P1/P3 复审(4.5/5 更硬 / 5.0 满分,均愿意玩)+ R2 转写 ×2。P2/P4 按 R1 协议本轮未复评,R3 全员收口。
|
||||
|
||||
## 1. R2 裁决
|
||||
|
||||
| 评审方 | 结果 |
|
||||
|---|---|
|
||||
| 真机复测 | **五修全部现场坐实**(F1 看门狗 25.5s 准点 / F2 新词落账 / F3 铃声可闻且接听即停 / F4 首句锁 / F5 链末保护零误伤),P0/P1/P2=0,打出 e1+e3 两结局 |
|
||||
| P1 视障评委 | 4.5/5 保持,「愿意玩」更硬;撤回 R1 两条误判(菜单功能洞/开场资产疑云销案) |
|
||||
| P3 白领 | 状态感知 **5.0/5**;R1 唯一 P0 正式关案(8 抉择同节拍=剧本仪器伪影,真机审计 0 自残截断) |
|
||||
|
||||
**结论:radio 通过 R2,R3 转入纯打磨轮。** SA3 十二件音效已在中途全部落地(真铃声/争吵闷响/刹车声),P1 的「凑齐进推荐位」条件已达成。
|
||||
|
||||
## 2. R3 修复清单(打磨级,全为 P3)
|
||||
|
||||
- **G1 帮助链去重**:帮助链被反复全量重播(压力局 38 次),违反方法论「提示永不逐字重复」公理。修:同一等待点第 2 次起播短版/纯音频标记(短版需 1-2 句新台词,走 TTS 管线;或用 sys_help 现有句 + 二次只震+earcon——以 dev 评估成本定,优先不加新台词的方案)。
|
||||
- **G2 rep_low 补 warning 震**(R1 遗留)。
|
||||
- **G3 k1_a/k1_b 缺 male 声部静默回退**:核查引擎平铺回退链,确认这两句在 male 设置下的回退行为(R2 live 新发现)。
|
||||
- **G4 ASK 态空点确认震**(R1 遗留):无选择的确认单击给轻震反馈。
|
||||
- **G5 「首播必完整、复播可即掐」写成显式规则 + 断言**(P1 要求,把 F4/F5 的隐式行为升为登记规则)。
|
||||
- **G6 状态链重排评估**(P1 建议第 1 条,两次提及):上滑状态链顺序调整为「当前通号 → 口碑 → 帮助」。若纯排序改动则做,涉台词结构则记 v2。
|
||||
- 观察项(不动代码):复播晚点 +7.6s 一次性事件;mid-prompt 生效掐选项句尾(设计备注);harness 丢 tap 仪器怪癖(记 R3 协议:tap 后 listen 一次确认再重发)。
|
||||
|
||||
## 3. R3 轮次协议(= 批次验收收口轮)
|
||||
1. dev 修 G1-G6 → playtest 全绿(含 G5 新断言)。
|
||||
2. 转写重生成(将首次携带 SA3 音效事件全集)→ 1 局 live 确认(重点:G1 帮助链行为、真铃声在局内表现)。
|
||||
3. **4 人设全员复评**(P2/P4 首次复审 + P1/P3 三审)→ R3 synthesis → 若 ≥3/4 且无 P0:**radio 达成章程验收门,标记可交付**。
|
||||
@@ -0,0 +1,19 @@
|
||||
# P2 · 时间充裕的大学生 首评——《不眠频率》(R3 终审)
|
||||
|
||||
> 视角:23:30,宿舍躺床,戴耳机,音量正常。R1/R2 我没评过这款(只有 P1/P3/真机碰过),这次是首评也是终审:主线转写全读 + 压力局全读。参照系是 R2 的背景账:P1 给 4.5、P3 给 5.0、真机五修全坐实。我的判断独立于他们,证据全部落在两份 R3 转写的时间点上。
|
||||
> 说明:round3 目录下没有 live-player.md,本次评审仅基于转写信息流与设计文档 §1/§3。
|
||||
|
||||
### 不眠频率
|
||||
- 状态感知:5/5 —— 全程没有一个时刻我不知道「现在是第几通、口碑什么档、轮到我干什么」。铃声+turn 签名=接听(t=14.8 第一声铃之前,规矩已经一句话讲完);上滑永远是「第 X 通 → 口碑 → 帮助」这个顺序(t=54.1-58.4,G6 重排落在转写里);幕间跨档播口碑(t=122.0「在听众里立住了」),不跨档就安静当喘息(t=158.2),从不啰嗦;结局把结局名、口碑和五个人的一句后续全念给我(t=248.9-263.8)。压力局 199 次乱按、38 次逛菜单,每一次手势都有回音:要么语音、要么 error 震、要么 G4 那记「20→8」的假确认轻震——我把眼睛闭上从头听到尾,地图一直在脑子里。
|
||||
- 下一步明确性:5/5 —— 每个抉择点都是「向左滑,做什么;向右滑,做什么」的整句,选项内容即教程(t=52.0);链末等我就挂看门狗(主线 t=42.0 我走了神 25 秒,回来一声「单击屏幕,继续」,雨声一直没断,局面毫发无损);菜单三项循环全念(t=62.6-68.8),关掉菜单自动重播选项(t=69.0)。压力局那位乱划的玩家全程零死锁、零被吞的手势,结局链照样走完(t=1016-1616)——我躺床上闭眼滑错了也不怕。
|
||||
- 愿意继续玩:是 —— 尾声那笔「导播账」是这个游戏的钩尖:救到的和错过的逐个点名(「糖糖后来又打来过一次。还是那句:楼下在吵。」t=1032.8,压力局我选了善意谎言,它真记着)。听完这笔账我当下的反应是想立刻重开一局去把糖糖那句话换成真话——单局结束想开下一局,这个标准它过了。
|
||||
- P0 问题:无
|
||||
- 建议:
|
||||
1. 结局收集进度请进游戏内可听:结算态和上滑状态里报一句「第 K 个结局,共四个」。现在「结局 K/4」只活在大厅存档卡片(§8.1 summary),游戏里收齐 4 个结局的驱动看不见缺口,对收集型玩家是白瞎了这个 4 结局结构。
|
||||
2. 「明晚零点,接着不眠」(t=251.0)和「红灯灭得很慢」是漂亮的伏笔,但二周目主干五通电话一模一样——对我这种吃伏笔的人,兑现不了的钩子就是空头支票。要么 v2 出第二夜内容,要么把钩子软化为「同一夜,换个说法」这类指向重玩路径的措辞。
|
||||
3. 睡前场景福利:结算态久置无操作时让 ending BGM 自动淡出收播(睡眠定时器)。现在看门狗两级之后是彻底静默没错,但垫乐会一直陪我到天亮——懂「最后一局之后直接睡着」的人,才会被当成睡前游戏。
|
||||
|
||||
#### 睡前躺床体验
|
||||
- **头 3 分钟节奏**:教科书级。t=0 开口到 t=14.8 第一声铃只有 15 秒,规矩就一句「先接住人,再接电话」;第一次动手=接听,没有比这更顺的手;第一个情绪回报在 t=77.3「他稳住了。老歌,比路牌管用。」——一通电话之内我改变了另一个人的夜晚,还教了我「这个游戏奖励倾听」;t=89.6「就这么接。记住这个手感。」是导播在给我盖首个正反馈的章。全程没有一句说教,成功路径零补救教学(主线转写验证),这点对我这种反感被当学生的人极其重要。躺床闭眼 3 分钟,我已经在「上班」了。
|
||||
- **故事钩子**:五通电话共享主干但伏笔真的接线——糖糖说的「蛋糕」在陈姐那通变成带话的素材(t=177.3「四十分钟前,有个孩子问我们」);C5 老韩那通回头点名老周的后续(t=235.3「头通电话那位大爷,就是这片被巡逻队找到的」);最后的留言机红灯是我自己的心结,替师父播晚安那句(t=244.7-246.8「带子里其实只有电流声。但空着的那一秒,你说满了。」)是全篇最好的一句台词。五个来电者五种电话音质感+各自的环境声(雨街/车站/儿童房+闷住的争吵/公车站/驾驶室),声音即世界这个立意是立住的,闭眼听就像真的在值班。
|
||||
- **4 结局想不想重玩收集**:想。两份转写正好各走一个结局(e1 天亮之前 / e2 热线常亮),e2 那句「留言机的红灯,灭得很慢」(t=1024.4)跟 e1 的「热线灯还亮着」是同一个夜晚的两种体温,这种对称结构让我好奇 e3/e4 长什么样;rep×心结的 2×2 矩阵意味着想看全结局我得故意冷一次、躲一次——「为了看坏结局而故意不接住人」本身就是一种重玩动力,而且尾声回响按每个人救没救到分叉(ep_*_ok/no),错过的版本写得有刺(小鹿「退了票。检票口的灯,记得那趟没上成的车」)。一局 20 分钟上下对睡前刚好,4 晚收齐是我愿意排的日程。扣不掉分但要说一句:重玩时五通主干台词重听率 100%,长按 1.7× 快进是有的,但「跳到下一抉择」这种二周目福利没有——收结局的第 3、4 晚,我大概率会靠快进硬压。
|
||||
@@ -0,0 +1,19 @@
|
||||
# P3 终审(R3):《不眠频率》(radio)— 时间紧张的白领
|
||||
|
||||
> 视角同 R1/R2:32 岁,地铁单程 25 分钟,站立单手持机,嘈杂车厢,只玩过消消乐。轨迹:R1 4.5/5 愿意玩(唯一 P0=乱按局选项句没念完结果就出)→ R2 5.0 满分、P0 关案。本轮依据 R3 主线+压力两份转写代入三审(round3 目录下无 live-player.md,live 项只能按转写验)。专查两件:G1 帮助链去重后,嘈杂地铁里漏听帮助第二次还能拿到什么;G6 状态链重排对被打断恢复的帮助。
|
||||
|
||||
### 不眠频率
|
||||
- 状态感知:5/5 —— R2 扣无可扣,这轮还变厚了。其一,G6 真落了:上滑状态链从「先付 8 秒口令才报状态」改成「状态在前」——主线 t=54.1「现在是今晚第一通电话。」→ t=56.3「今晚的口碑,还没立起来。」→ t=58.4 才是口令;压力局 t=17.0/19.1/21.2 同序。我要的两句(第几通+口碑)挪到了头两秒,口令成了附赠。其二,G2 的 rep_low 警告震也接上了:warning 三连震只挂在「还没立起来」的链上(压力局 t=17.0/55.0/65.4 全带,t=180.5/946.5「不好不坏」和 t=962.7「立住了」全不带)——车厢里我不听也行,手腕上就知道口碑低没低。其三,R2 那批 SA3 缺口清了:t=0.0 的缺失清单没有了,糖糖家楼下的闷响(主线 t=132.4 arg_muffled)和第五通的急刹(t=223.0 brake_screech+danger 震同拍)都真响——最穿地铁噪音的两出戏我终于听见了。其余照旧:漏听自动重播选项(主线 t=60.5)、看门狗 25 秒捞人(t=42.0)、结局五条回响逐条对账(t=255.3-265.9)。
|
||||
- 下一步明确性:5/5 —— G1 去重是这轮我最担心「反而变难」的一项,数下来不是:压力局 38 次帮助链 = 20 次全量 + 18 次短版,短版不是哑的——「通号+口碑」两句照常开口(t=65.4 震+「现在是今晚第一通电话」→ t=67.5「还没立起来」→ t=69.6 自动重播卡住的那句),只是不再重播口令。也就是说地铁里我第一遍没听清,第二遍上滑拿到的恰恰是我缺的信息,还比 R2 快了一倍多(R2 要先听完 8 秒口令才轮到状态)。全量口令从 38 次压到 20 次(每句台词第一次帮助仍念全量,t=21.2/59.2/184.7/214.2……),真忘了操作还有菜单兜底(t=62.6「菜单。单击切换选项,双击确认。」)。压力局 199 次乱试+38 次逛菜单,收尾 t=1039.2 明写「没有任何一次手势被无声吞掉,也没有卡死在某个状态里」,结局链照样走完——这条右滑收播线连回响账都记了(t=1030.7-1037.1,小鹿退票、陈姐没寄出的信,坏选择有坏结局不糊弄)。
|
||||
- 愿意继续玩:是 —— R2 满分时剩的两个毛边(帮助链啰嗦、低口碑没震)这轮都拔了,最乱的一局照样把我送到结局,正常玩只会更顺。
|
||||
- P0 问题:无
|
||||
- 建议:≤3 条,按对「我愿意玩下去」的影响排序
|
||||
1. 全量口令还能再省:20 次仍多于必要——现在去重是「同一句台词第一次帮助念全量」,等于每过一个抉择点都要重听一遍操作课(t=21.2/59.2/184.7/214.2/253.8……)。建议收成「每通电话只念一次全量,同通内一律短版」;我想要的是「第几通+口碑」,不是复习。
|
||||
2. 关菜单重播整句仍未动(R2 建议 2 原样):压力局 t=977.5/986.0 关菜单各重播一遍「说说她。开学第一天……」。逛 38 次菜单还是等于白听几十句。维持原议:关菜单「叮」一声回等待。
|
||||
3. 无效手势的提示在台词播放中只剩双短震:压力局 t=17.0「这个手势,直播间里用不上」被 idle-only 跳过,只留 error 两连短震。站立摇晃的车厢里手腕上这两下基本无感,等于白做。建议这句不被跳过,或换成一记短 earcon。
|
||||
- R2 建议回执:建议 1(口令收敛)**部分采纳**——去重落地但粒度停在「每句台词」;建议 2(关菜单不重播)**未动**;建议 3(快滑回执)**未动**(R2 已记为观察项「mid-prompt 生效掐选项句尾」,本轮压力局未见新伤,不升级)。
|
||||
|
||||
#### 通勤压力三测
|
||||
- **3 分钟颗粒**:达标。主线整晚 t=0-265.9 约 4 分半 ≈ 两个站距,五通各 25-77 秒自带起承转合,幕间垫乐 3-5 秒,无沉默尴尬期;开场 14.8 秒第一声铃,被打断就当下车、损失最多半通。压力局 17 分钟纯乱按也走到了收播结局和五条回响。
|
||||
- **被打断后一句话接上**:这轮是三测里进步最大的一项。上滑后第一句就是「第 N 通」(~2 秒)、第二句口碑(~4 秒),口令垫底——G6 的重排让我「先拿答案、后听说明」;漏听了第二遍也不怕,短版帮助照常开口报通号+口碑再自动重播卡住的句(压力局 t=65.4→69.6);低口碑另有 warning 震走手腕;走神 25 秒有 t=42.0 看门狗,半路下车再上车有首句锁。信息全程不靠记性。
|
||||
- **噪音与单手盲操**:能盲操、不用出声(单击/双击/三向滑),摸鱼安全;铃声、闷响、急刹三层「穿噪」资产都到位了。嘈杂车厢漏听帮助的最终答案:G1 去重没有让它变难,反而因为 G6 变快了——第二次帮助给我的是我缺的那两句,砍掉的只是我已经会背的口令。
|
||||
@@ -0,0 +1,21 @@
|
||||
# P4(疲惫的工人)R3 终审 —— 《不眠频率》
|
||||
|
||||
> 45 岁,工地收工,宿舍 21:00,外放小音量,游戏经验少。radio 这游戏我是头一回评——R1 那会儿我只看了 escape 他们几个老款,R2 也没轮到我,这回算初次进门的。
|
||||
> 依据:docs/design/15-radio.md §1/§3 + round3/transcript-main.md(完整一晚:五通电话、E1「天亮之前」结局,t=0-266)+ round3/transcript-stress.md(乱按局全程读到底:乱试 199 次、逛菜单 38 次、e2 收播,t=0-1619)+ round2/synthesis.md(背景:R2 五修全坐实,G1-G6 打磨轮)。
|
||||
> 注:round3/live-player.md 这回没见到,真机确认那一步我只能信转写和 synthesis 的登记。
|
||||
|
||||
### 不眠频率
|
||||
- 状态感知:5/5 —— 这一晚我从来不用猜自己干到哪儿了。每通电话进来报「第 一 通电话打进来:单击接听」(主线 t=14.8、96.9、127.1 一直到 t=200.0 第五通,一通没漏);通话里对方说完等我接话也有报(t=17.0);上滑随时问我「现在是今晚第一通电话」「今晚的口碑,还没立起来」(t=54.1-56.3),账是实时的——第二通打完立刻变「在听众里立住了」(t=122.0);幕间、收播、结局账,一段一段都报得清清楚楚。乱按局里我胡划了一百九十多下,每一次错按都有两下短震加一句解释,没一回是闷着的。
|
||||
- 下一步明确性:5/5 —— 轮到我动手的时刻,没有一次没人告诉我按啥。开场就把三件事分三句教了:「单击继续节目」「想跳过这句,单击就行」「请选择的时候,向左或向右滑」(t=2.1-6.4);电话铃一响就有 turn 震加「单击接听」;选项句自带左右说明(「向左滑,陪他哼那首老歌。向右滑,冷静问他路口的路牌」t=52.0);我发呆 25 秒,有人轻声来一句「单击屏幕,继续。」(t=42.0),不催不骂;菜单自己会念「单击切换选项,双击确认」。我全程没有一秒在想「现在该干嘛」。
|
||||
- 愿意继续玩:是 —— 它就是让我躺在铺上听一晚电台,动动手指头替几个人搭把手,规矩一条、错按不恼、通与通之间还让歇口气,21 分钟听完那笔「今晚的人都怎样了」的账,我惦记明晚。
|
||||
- P0 问题:无 —— 主线和乱按局从头到尾,我找不出不知自己在哪/该干嘛/为啥砸的时刻。乱按局连 e2 都照常收播,账还一句句念给我听(t=1028-1037),卡死都没有。
|
||||
- 建议:
|
||||
1. 开播前别给我警告震:口碑 0 档的时候上滑,「今晚的口碑,还没立起来」出口带着警告三连震(乱按局 t=17.0、44.5、55.0 一路这样)。我还没开口说一句话呢,手腕先挨了个「警告」,头一下我心里咯噔一下以为闯祸了。字是中听的,震吓人——0 档开播前建议换轻震或不震,跌回低档再震不迟。
|
||||
2. 同一个等待点反复上滑,状态三连句还是一遍遍全文重播(乱按局 t=117.2 和 t=125.6 隔 8 秒,两回都是「第一通+口碑+帮助」整串)。G1 去重已经把帮助句管住了,口碑没变的时候能不能第二次起只震一下不重念?乱按局一晚上我把「今晚的口碑,不好不坏」听了十几遍。
|
||||
3. 谎言局那句「你许了个兑不了的现。孩子睡了,谎留下了。」(乱按局 t=664.3)——归因是真的、也不挖苦,但「谎留下了」四个字对收工的我有点沉。账照记,词能不能软半分,比如「这话没法兑现了」这类。
|
||||
|
||||
#### 累了一天还能玩吗
|
||||
- 规矩一遍懂?懂。台里的规矩就一句:「先接住人,再接电话。」(t=10.6)一句完事,我记一晚上。手势也是一句教一件,不贪多。
|
||||
- 来电者语速?顶得住。来电的人说话短、逗号多,最急的一句「明天孩子生日!蛋糕都订好了,他人要今晚走!」也就一口气的长度,中间还有导播搭话垫着,我不怕跟不上。
|
||||
- 做错被骂吗?不骂。乱按局我错了将近两百回,每回就两下短震,话也是「这个手势,直播间里用不上。」这种就事论事的词,没有一句带刺。选砸了账是照实记的(小鹿退了票、糖糖家的门还摔),不哄我,但也不损我。
|
||||
- 第一通后有暖反馈吗?有,而且快。陪老周哼完歌,他自己的声音先稳了——「对,对!路口修车铺,天天放这首!」(t=73.2),通末导播再补一句「就这么接。记住这个手感。」(t=89.6)。干完活有人夸,开头三分钟就给了,这是我最吃的一套。越玩越累?不累:没有倒计时、没有死、每通电话之间有幕间歇气,结局还有人替我把今晚每个人的下落一句句念给我听。躺一局,值。
|
||||
@@ -0,0 +1,401 @@
|
||||
# 试玩转写:《radio》
|
||||
|
||||
> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文,
|
||||
> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作),
|
||||
> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。
|
||||
t+ 0.0s (玩家点开游戏,轻触屏幕开始)
|
||||
t+ 0.0s ♫ BGM 切换 → bgm/onair
|
||||
t+ 0.0s ♪ 向导音:explore(探索/安全)
|
||||
t+ 0.0s ▶ 语音:「新的夜晚,开始了。」
|
||||
t+ 2.1s ♪ 音效 sfx/onair_sting
|
||||
t+ 2.1s ▶ 向导语音:「单击继续节目。请选择的时候,向左或向右滑。」
|
||||
t+ 4.2s ▶ 语音:「午夜零点,红灯亮起。欢迎回到《今夜不眠》。」
|
||||
t+ 6.4s ▶ 语音:「想跳过这句,单击就行。」
|
||||
t+ 8.5s ▶ 语音:「雨下了一整晚。热线灯,马上就要亮了。」
|
||||
t+ 10.6s ▶ 语音:「台里的规矩就一条:先接住人,再接电话。」
|
||||
t+ 12.7s ▶ 语音:「今晚五通电话。说什么话,由你决定。」
|
||||
t+ 14.8s ♪ 向导音:turn(轮到你)
|
||||
t+ 14.8s 〰 震动:confirm(轻点确认)
|
||||
t+ 14.8s 【状态】开场口令和台标播完了,第一通电话响了 第 一 通电话打进来:单击接听(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】铃一响就接——接听是单击
|
||||
|
||||
t+ 14.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 14.8s ♪ 音效 sfx/line_connect
|
||||
t+ 14.8s ▶ 语音:「一线来电。七十多岁,雨夜,走丢了。」
|
||||
t+ 14.8s 【状态】线路接通了 第 一 通通话中,正在听对方说话(语音播放中,语速1)
|
||||
t+ 16.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 17.0s 【状态】导播报完线,老人开口了 对方说完了,等我接话(第 一 通):单击继续(BGM=bgm/onair,语速1)
|
||||
t+ 17.0s ……… 静默 25s(听到一半走了神,在想老人的老花镜) ………
|
||||
t+ 17.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 18.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 19.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 20.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 22.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 23.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 24.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 25.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 26.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 28.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 29.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 30.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 31.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 32.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 34.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 35.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 36.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 37.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 38.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 40.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 41.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 42.0s ♪ 向导音:nudge(看门狗轻提醒)
|
||||
t+ 42.0s ▶ 向导语音:「单击屏幕,继续。」
|
||||
t+ 42.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 43.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 43.6s 【状态】听到一声轻响和「单击屏幕,继续」,马上点 对方说完了,等我接话(第 一 通):单击继续(语音播放中,语速1)
|
||||
t+ 43.6s ▶ 语音:「主播……我,我找不到回家的路了。」
|
||||
t+ 44.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 46.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 47.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 47.7s ▶ 语音:「雨太大了。我本来,只想买副老花镜。」
|
||||
t+ 48.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 49.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 50.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 52.0s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 52.0s ▶ 语音:「老人在发抖。向左滑,陪他哼那首老歌。向右滑,冷静问他路口的路牌。」
|
||||
t+ 52.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 53.2s ♪ 音效 sfx/amb_rain_city
|
||||
|
||||
#### 【玩家动作】老人在发抖,我陪他哼那首老歌——但先上滑听一遍操作和进度
|
||||
|
||||
t+ 54.1s ▶ 语音:「现在是今晚第一通电话。」
|
||||
t+ 54.1s 〰 震动:warning(警告三连震)
|
||||
t+ 54.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 55.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 56.3s ▶ 语音:「今晚的口碑,还没立起来。」
|
||||
t+ 56.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 58.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 58.4s ▶ 语音:「单击继续,双击重新听。上滑听状态,下滑开菜单。请选择时,左右滑。」
|
||||
t+ 59.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 60.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 60.5s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 60.5s ▶ 语音:「老人在发抖。向左滑,陪他哼那首老歌。向右滑,冷静问他路口的路牌。」
|
||||
t+ 61.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 62.6s 【状态】听完帮助+状态链,游戏自动重播了选项 「请选择」念完了(第 一 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】下滑看看菜单有什么
|
||||
|
||||
t+ 62.6s ♪ 音效 sfx/ui_menu
|
||||
t+ 62.6s ♫ BGM 切换 → bgm/menu(淡入 500ms)
|
||||
t+ 62.6s ♪ 向导音:menu(系统界面)
|
||||
t+ 62.6s ▶ 语音:「菜单。单击切换选项,双击确认。」
|
||||
t+ 62.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 64.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 64.7s ▶ 语音:「回到直播。」
|
||||
t+ 65.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 66.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 66.9s 【状态】菜单里,切一项听听 菜单里,当前项「回到直播」:单击切换,双击确认,上滑帮助,下滑关闭(BGM=bgm/menu,语速1)
|
||||
t+ 66.9s ▶ 语音:「重新开始今晚。」
|
||||
t+ 67.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 68.8s ♪ 音效 sfx/amb_rain_city
|
||||
|
||||
#### 【玩家动作】听完了,下滑关闭菜单,回到选项
|
||||
|
||||
t+ 69.0s ♪ 音效 sfx/ui_confirm
|
||||
t+ 69.0s ♫ BGM 切换 → bgm/onair(淡入 800ms)
|
||||
t+ 69.0s ♪ 向导音:explore(探索/安全)
|
||||
t+ 69.0s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 69.0s ▶ 语音:「老人在发抖。向左滑,陪他哼那首老歌。向右滑,冷静问他路口的路牌。」
|
||||
t+ 70.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 71.1s 【状态】选项念完了,做决定 「请选择」念完了(第 一 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】老人在发抖,我陪他哼那首老歌
|
||||
|
||||
t+ 71.1s ♪ 音效 sfx/ui_confirm
|
||||
t+ 71.1s ▶ 语音:「大爷别急,这首歌我也会。咱们一句一句来。」
|
||||
t+ 71.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 72.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 73.2s ▶ 语音:「对,对!路口修车铺,天天放这首!」
|
||||
t+ 73.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 74.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 76.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 77.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 77.3s ▶ 语音:「他稳住了。老歌,比路牌管用。」
|
||||
t+ 78.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 79.4s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 79.4s ▶ 语音:「雨声更密了。向左滑,留在原地陪他等巡逻队。向右滑,转接派出所。」
|
||||
t+ 79.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 80.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 81.5s 【状态】选项念完了,做决定 「请选择」念完了(第 一 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】留在原地陪他等巡逻队
|
||||
|
||||
t+ 81.5s ♪ 音效 sfx/ui_confirm
|
||||
t+ 81.5s ▶ 语音:「哪儿也不去。我陪你,这首歌还长着呢。」
|
||||
t+ 82.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 83.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 83.6s ▶ 语音:「好,好。有人说话,我就不怕了。」
|
||||
t+ 84.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 85.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 86.8s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 87.5s ▶ 语音:「十五分钟后,巡逻灯停在路口。全城听见老人笑了。」
|
||||
t+ 88.0s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 89.2s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 89.6s ▶ 语音:「就这么接。记住这个手感。」
|
||||
t+ 90.4s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 91.6s ♪ 音效 sfx/amb_rain_city
|
||||
t+ 91.7s ♪ 向导音:settle(结算)
|
||||
t+ 91.7s ♪ 音效 sfx/line_drop
|
||||
t+ 91.7s ♫ BGM 切换 → bgm/bridge(淡入 800ms)
|
||||
t+ 91.7s ▶ 语音:「今晚的口碑,不好不坏。」
|
||||
t+ 93.9s 【状态】幕间,口碑播报和垫乐,等下一通 幕间喘息,垫乐播放中,马上接下一通(BGM=bgm/bridge,语速1)
|
||||
t+ 96.9s ♫ BGM 切换 → bgm/onair(淡入 600ms)
|
||||
t+ 96.9s ♪ 向导音:turn(轮到你)
|
||||
t+ 96.9s 〰 震动:confirm(轻点确认)
|
||||
t+ 96.9s 【状态】第 二 通电话响了,接 第 二 通电话打进来:单击接听(BGM=bgm/onair,语速1)
|
||||
t+ 96.9s ♪ 音效 sfx/amb_station
|
||||
t+ 96.9s ♪ 音效 sfx/line_connect
|
||||
t+ 96.9s ▶ 语音:「二线来电。姑娘,声音很轻,像怕吵到谁。」
|
||||
t+ 98.1s ♪ 音效 sfx/amb_station
|
||||
t+ 99.0s ▶ 语音:「主播,退票窗口十一点半就关了。我站这儿半小时了。」
|
||||
t+ 99.3s ♪ 音效 sfx/amb_station
|
||||
t+ 100.5s ♪ 音效 sfx/amb_station
|
||||
t+ 101.7s ♪ 音效 sfx/amb_station
|
||||
t+ 102.9s ♪ 音效 sfx/amb_station
|
||||
t+ 104.1s ♪ 音效 sfx/amb_station
|
||||
t+ 104.8s ▶ 语音:「票是回去看我妈的。可我试镜又黄了,两手空空……」
|
||||
t+ 105.3s ♪ 音效 sfx/amb_station
|
||||
t+ 106.5s ♪ 音效 sfx/amb_station
|
||||
t+ 107.7s ♪ 音效 sfx/amb_station
|
||||
t+ 108.9s ♪ 音效 sfx/amb_station
|
||||
t+ 110.1s ♪ 音效 sfx/amb_station
|
||||
t+ 110.5s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 110.5s ▶ 语音:「向左滑,告诉她这趟车值得上。向右滑,把选择还给她。」
|
||||
t+ 111.3s ♪ 音效 sfx/amb_station
|
||||
t+ 112.5s ♪ 音效 sfx/amb_station
|
||||
t+ 112.6s 【状态】选项念完了,做决定 「请选择」念完了(第 二 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】小鹿妈妈等的是那声「妈」,劝她上车
|
||||
|
||||
t+ 112.6s ♪ 音效 sfx/ui_confirm
|
||||
t+ 112.6s ▶ 语音:「你妈等的不是奖杯,是你进门喊的那声妈。」
|
||||
t+ 113.7s ♪ 音效 sfx/amb_station
|
||||
t+ 114.7s ▶ 语音:「呜……嗯。不退了,我现在就去检票。谢谢您。」
|
||||
t+ 114.9s ♪ 音效 sfx/amb_station
|
||||
t+ 116.1s ♪ 音效 sfx/amb_station
|
||||
t+ 117.3s ♪ 音效 sfx/amb_station
|
||||
t+ 118.5s ♪ 音效 sfx/amb_station
|
||||
t+ 119.7s ♪ 音效 sfx/amb_station
|
||||
t+ 119.9s ▶ 语音:「二线收工。这句话,值一个头条。」
|
||||
t+ 120.9s ♪ 音效 sfx/amb_station
|
||||
t+ 122.0s ♪ 向导音:settle(结算)
|
||||
t+ 122.0s ♪ 音效 sfx/line_drop
|
||||
t+ 122.0s ♫ BGM 切换 → bgm/bridge(淡入 800ms)
|
||||
t+ 122.0s ▶ 语音:「今晚的口碑,在听众里立住了。」
|
||||
t+ 124.1s 【状态】幕间,口碑播报和垫乐,等下一通 幕间喘息,垫乐播放中,马上接下一通(BGM=bgm/bridge,语速1)
|
||||
t+ 127.1s ♫ BGM 切换 → bgm/onair(淡入 600ms)
|
||||
t+ 127.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 127.1s 〰 震动:confirm(轻点确认)
|
||||
t+ 127.1s 【状态】第 三 通电话响了,接 第 三 通电话打进来:单击接听(BGM=bgm/onair,语速1)
|
||||
t+ 127.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 127.1s ♪ 音效 sfx/line_connect
|
||||
t+ 127.1s ▶ 语音:「三线来电。听呼吸,是个小孩。」
|
||||
t+ 128.3s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 129.3s ▶ 语音:「喂……有人吗?我睡不着。」
|
||||
t+ 129.5s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 130.7s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 131.9s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 132.4s ♪ 音效 sfx/arg_muffled
|
||||
t+ 132.4s ▶ 语音:「家里灯关了。可是楼下,一直有声音。」
|
||||
t+ 133.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 134.3s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 135.5s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 136.7s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 136.7s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 136.7s ▶ 语音:「向左滑,唱一段摇篮曲哄她睡。向右滑,轻轻问她怎么了。」
|
||||
t+ 137.9s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 138.9s 【状态】选项念完了,做决定 「请选择」念完了(第 三 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】糖糖像是憋着事,我轻轻问她怎么了
|
||||
|
||||
t+ 138.9s ♪ 音效 sfx/ui_confirm
|
||||
t+ 138.9s ▶ 语音:「睡不着的时候,心里是不是装着事?说给我听听。」
|
||||
t+ 139.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 140.3s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 141.0s ▶ 语音:「爸爸妈妈摔门了。是不是……我做错了什么呀。」
|
||||
t+ 141.5s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 142.7s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 143.9s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 145.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 146.2s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 146.2s ▶ 语音:「孩子的声音在抖。向左滑,告诉她这不是她的错。向右滑,答应她明天都会好。」
|
||||
t+ 146.3s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 147.5s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 148.3s 【状态】选项念完了,做决定 「请选择」念完了(第 三 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】告诉她这不是她的错——大人的事不算在孩子头上
|
||||
|
||||
t+ 148.3s ♪ 音效 sfx/ui_confirm
|
||||
t+ 148.3s ▶ 语音:「糖糖,记住,大人的事,不是小孩的错。一个字都不是。」
|
||||
t+ 148.7s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 149.9s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 150.4s ▶ 语音:「嗯……那我睡了。他们明天,会一起给我切蛋糕吗?」
|
||||
t+ 151.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 152.3s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 153.5s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 154.7s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 155.9s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 156.0s ▶ 语音:「蛋糕。记下来——四线的来电,可能跟这个家有关。」
|
||||
t+ 157.1s ♪ 音效 sfx/amb_kid_room
|
||||
t+ 158.2s ♪ 向导音:settle(结算)
|
||||
t+ 158.2s ♪ 音效 sfx/line_drop
|
||||
t+ 158.2s ♫ BGM 切换 → bgm/bridge(淡入 800ms)
|
||||
t+ 158.2s 【状态】幕间,口碑播报和垫乐,等下一通 幕间喘息,垫乐播放中,马上接下一通(BGM=bgm/bridge,语速1)
|
||||
t+ 161.2s ♫ BGM 切换 → bgm/onair(淡入 600ms)
|
||||
t+ 161.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 161.2s 〰 震动:confirm(轻点确认)
|
||||
t+ 161.2s 【状态】第 四 通电话响了,接 第 四 通电话打进来:单击接听(BGM=bgm/onair,语速1)
|
||||
t+ 161.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 161.2s ♪ 音效 sfx/line_connect
|
||||
t+ 161.2s ▶ 语音:「四线来电。户外风声大,是位大姐。」
|
||||
t+ 162.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 163.3s ▶ 语音:「主播,我就想找个人说说。我家那口子,今晚要出远门的活儿。」
|
||||
t+ 163.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 164.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 166.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 167.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 168.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 169.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 170.0s ▶ 语音:「明天孩子生日!蛋糕都订好了,他人要今晚走!」
|
||||
t+ 170.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 172.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 173.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 174.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 175.2s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 175.2s ▶ 语音:「摔门声你听见了。向左滑,替孩子给她带句话。向右滑,劝她回家把话说开。」
|
||||
t+ 175.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 176.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 177.3s 【状态】选项念完了,做决定 「请选择」念完了(第 四 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】陈姐听见孩子问话了,我把话带回去
|
||||
|
||||
t+ 177.3s ♪ 音效 sfx/ui_confirm
|
||||
t+ 177.3s ▶ 语音:「四十分钟前,有个孩子问我们:爸妈摔门,是不是她的错。」
|
||||
t+ 178.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 179.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 179.4s ▶ 语音:「什么?她还没睡?这么晚了,她还醒着?」
|
||||
t+ 180.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 181.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 182.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 184.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 184.0s ▶ 语音:「她攥着电话,很久没出声。风都停了。」
|
||||
t+ 185.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 186.1s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 186.1s ▶ 语音:「她的呼吸平了。向左滑,留在直播里,让全城等这个门铃。向右滑,换垫乐,私下陪她说完。」
|
||||
t+ 186.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 187.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 188.2s 【状态】选项念完了,做决定 「请选择」念完了(第 四 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】留在直播里,让全城等这声门铃
|
||||
|
||||
t+ 188.2s ♪ 音效 sfx/ui_confirm
|
||||
t+ 188.2s ▶ 语音:「陈姐,别挂。让他接电话——全城都在听。」
|
||||
t+ 188.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 190.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 190.3s ▶ 语音:「喂!回来吧!蛋糕要化了,孩子等着呢!」
|
||||
t+ 191.2s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 192.4s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 193.6s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 194.8s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 194.8s ▶ 语音:「电话那头,传来跑步声。今晚的高光时刻。」
|
||||
t+ 196.0s ♪ 音效 sfx/amb_street_rain
|
||||
t+ 197.0s ♪ 向导音:settle(结算)
|
||||
t+ 197.0s ♪ 音效 sfx/line_drop
|
||||
t+ 197.0s ♫ BGM 切换 → bgm/bridge(淡入 800ms)
|
||||
t+ 197.0s 【状态】幕间,口碑播报和垫乐,等下一通 幕间喘息,垫乐播放中,马上接下一通(BGM=bgm/bridge,语速1)
|
||||
t+ 200.0s ♫ BGM 切换 → bgm/onair(淡入 600ms)
|
||||
t+ 200.0s ♪ 向导音:turn(轮到你)
|
||||
t+ 200.0s 〰 震动:confirm(轻点确认)
|
||||
t+ 200.0s 【状态】第 五 通电话响了,接 第 五 通电话打进来:单击接听(BGM=bgm/onair,语速1)
|
||||
t+ 200.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 200.0s ♪ 音效 sfx/line_connect
|
||||
t+ 200.0s ▶ 语音:「五线来电。引擎声没停过——他在开车!」
|
||||
t+ 201.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 202.1s ▶ 语音:「主播,别挂。陪我说话,我的眼皮,沉得很。」
|
||||
t+ 202.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 203.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 204.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 206.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 207.0s ▶ 语音:「跑完这趟,闺女的学费就齐了。雨刷都快刮不动了。」
|
||||
t+ 207.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 208.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 209.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 210.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 212.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 212.7s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 212.7s ▶ 语音:「方向盘比话筒危险。向左滑,陪他聊聊闺女。向右滑,让他立刻进服务区。」
|
||||
t+ 213.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 214.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 214.8s 【状态】选项念完了,做决定 「请选择」念完了(第 五 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】老韩眼皮在打架,我陪他聊聊闺女
|
||||
|
||||
t+ 214.8s ♪ 音效 sfx/ui_confirm
|
||||
t+ 214.8s ▶ 语音:「说说她。开学第一天,她跟你说的头一句话,是什么?」
|
||||
t+ 215.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 216.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 216.9s ▶ 语音:「她说,爸,我在学校给你赚了朵小红花。哈哈,哈哈……」
|
||||
t+ 218.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 219.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 220.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 221.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 222.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 223.0s ♪ 向导音:danger(危险)
|
||||
t+ 223.0s ♪ 音效 sfx/brake_screech
|
||||
t+ 223.0s 〰 震动:danger(危险逼近)
|
||||
t+ 224.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 225.0s ▶ 语音:「车道偏了——听!」
|
||||
t+ 225.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 226.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 227.1s ▶ 语音:「嘶——好险!前车急刹,我擦着护栏过去了。彻底醒了!」
|
||||
t+ 227.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 228.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 230.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 231.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 232.4s ♪ 音效 sfx/amb_cab
|
||||
t+ 233.2s ▶ 语音:「吓醒的,也算醒。这一趟,聊到家。」
|
||||
t+ 233.6s ♪ 音效 sfx/amb_cab
|
||||
t+ 234.8s ♪ 音效 sfx/amb_cab
|
||||
t+ 235.3s ▶ 语音:「对了。头通电话那位大爷,就是这片被巡逻队找到的。这城市的夜,是接着的。」
|
||||
t+ 236.0s ♪ 音效 sfx/amb_cab
|
||||
t+ 237.2s ♪ 音效 sfx/amb_cab
|
||||
t+ 237.4s ♪ 向导音:settle(结算)
|
||||
t+ 237.4s ♪ 音效 sfx/line_drop
|
||||
t+ 237.4s ♫ BGM 切换 → bgm/bridge(淡入 800ms)
|
||||
t+ 237.4s 【状态】幕间,口碑播报和垫乐,等下一通 幕间喘息,垫乐播放中,马上接下一通(BGM=bgm/bridge,语速1)
|
||||
t+ 240.4s ▶ 语音:「五线收工。垫乐起——零点档,还剩最后一段。」
|
||||
t+ 242.6s ♫ BGM 切换 → bgm/onair(淡入 600ms)
|
||||
t+ 242.6s ♪ 向导音:choice(抉择/等待输入)
|
||||
t+ 242.6s ▶ 语音:「留言机红灯在闪,是老主播三年前没播完的那句晚安。向左滑,替他播出去。向右滑,照常收播。」
|
||||
t+ 244.7s 【状态】选项念完了,做决定 「请选择」念完了(第 五 通):向左或向右滑动做出你的决定(BGM=bgm/onair,语速1)
|
||||
|
||||
#### 【玩家动作】留言机红灯在闪——直面它,替老主播把晚安播出去
|
||||
|
||||
t+ 244.7s ♪ 音效 sfx/ui_confirm
|
||||
t+ 244.7s ♪ 音效 sfx/tape_static
|
||||
t+ 244.7s ▶ 语音:「师父,三年了。这句晚安,我替您播。各位,晚安。」
|
||||
t+ 246.8s ▶ 语音:「带子里其实只有电流声。但空着的那一秒,你说满了。」
|
||||
t+ 248.9s ♪ 向导音:settle(结算)
|
||||
t+ 248.9s ♫ BGM 切换 → bgm/ending(淡入 1500ms)
|
||||
t+ 248.9s ▶ 语音:「天亮了,热线灯还亮着。你们的晚安,是这座城市的心跳。」
|
||||
t+ 251.0s ▶ 语音:「这把话筒,我总算接得住了。明晚零点,接着不眠。」
|
||||
t+ 253.2s ▶ 语音:「收播了。导播间替你记了一笔账——今晚的人都怎样了。」
|
||||
t+ 255.3s ▶ 语音:「老周:孙子替他买了老花镜。回信说,谢谢那首歌。」
|
||||
t+ 257.4s ▶ 语音:「小鹿上车了。她妈后来打电话说,那声妈,比奖杯值钱。」
|
||||
t+ 259.5s ▶ 语音:「糖糖家的门,这个月没再摔过。她说这是主播魔法。」
|
||||
t+ 261.6s ▶ 语音:「陈姐家切了蛋糕。那句「回来吧」,是我这晚听过最好的声音。」
|
||||
t+ 263.8s ▶ 语音:「老韩到家了。后视镜上,多了朵小红花。」
|
||||
t+ 265.9s 【状态】结局链走完,五条回响一句句点到我今晚的每一次选择 结局和五条回响都听完了。单击再来一局,下滑开菜单(BGM=bgm/ending,语速1)
|
||||
|
||||
#### 【玩家动作】听完尾声那笔账——今晚的人都接住了,会话结束(E1 天亮之前)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -758,7 +758,8 @@ RADIO_NPC = [
|
||||
]
|
||||
|
||||
# ---------------------------------------------------------------- dungeon
|
||||
# 《回声地窟》批次 1(docs/design/16-dungeon-voice-ids.md,125 句 ×2 性别,无 NPC)。
|
||||
# 《回声地窟》批次 1(docs/design/16-dungeon-voice-ids.md,125 句 ×2 性别,无 NPC);
|
||||
# R3 起 +2(E1-2 gold_some / 打磨 tut_flee_hold)= 127 句,st_best_2 措辞重录。
|
||||
_DUN = _pair("低沉醇厚的男声,像探窟向导,沉稳有力",
|
||||
"平静清晰的女声,像探窟向导,沉稳可信")
|
||||
DUNGEON_LINES = [
|
||||
@@ -781,6 +782,7 @@ DUNGEON_LINES = [
|
||||
("tut_parry_miss", _DUN, "没挡住也别怕,它伤不到你。"),
|
||||
("tut_attack", _DUN, "现在单击,挥拳打它。"),
|
||||
("tut_kill", _DUN, "打中了,就是这样。"),
|
||||
("tut_flee_hold", _DUN, "想逃跑,按住别松手。"), # R3 打磨:战斗短长按取消逃跑时的区分提示(每场 1 次)
|
||||
("tut_stairs", _DUN, "铁器的回声,就是下潜的楼梯。"),
|
||||
("tut_stairs_on", _DUN, "楼梯就在脚下。单击,下潜。"),
|
||||
("tut_done", _DUN, "教学完了。地窟很深,小心走。"),
|
||||
@@ -809,6 +811,10 @@ DUNGEON_LINES = [
|
||||
("st_gold_2", _DUN, "有些积蓄。"),
|
||||
("st_gold_3", _DUN, "收获可观。"),
|
||||
("st_gold_4", _DUN, "腰包鼓鼓。"),
|
||||
# R3 E1-2:金币档 1(0<金<50)新真话句——修「捡到金币→口袋空空/这趟没带回什么」
|
||||
# 的档位谎报(P2/P4 共识);=0 仍播 st_gold_1/meta_gold_1 空手措辞。
|
||||
# 上滑状态链与 SETTLE/TITLE(元进度)三处共用这一条(管线单条)。
|
||||
("gold_some", _DUN, "带回来一点,不多。"),
|
||||
("st_face_e", _DUN, "你面朝东。"),
|
||||
("st_face_s", _DUN, "你面朝南。"),
|
||||
("st_face_w", _DUN, "你面朝西。"),
|
||||
@@ -818,7 +824,7 @@ DUNGEON_LINES = [
|
||||
("st_threat_right", _DUN, "右边有脚步声。"),
|
||||
("st_threat_both", _DUN, "两边都有动静。"),
|
||||
("st_best_1", _DUN, "你还没到过第三层。"),
|
||||
("st_best_2", _DUN, "你到过中层。"),
|
||||
("st_best_2", _DUN, "你最远到过中层。"), # R3 打磨措辞:加「最远」(live P3:防误读为"本局到过")
|
||||
("st_best_3", _DUN, "你到过最深层。"),
|
||||
("evt_coin_1", _DUN, "捡到几枚金币。"),
|
||||
("evt_coin_2", _DUN, "捡到一小把金币。"),
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+160
-29
@@ -12,10 +12,12 @@
|
||||
* 房间→L 型走廊(链式生成树)→起点/楼梯(BFS 最远房心)→宝物→怪(BFS≥3 安全区),
|
||||
* 教学局 L1 叠加硬约束(正前 2 格内墙 / 门怪 / 房内金币),拒绝采样保证可复现。
|
||||
* 战斗:缠斗/绕位/Boss 三档,前摇 1.2s 内双击格挡(面对 ×0.2 / 背后 ×1.0),
|
||||
* 逃跑长按必成挨一下(真话),Boss 拒绝;每 4 杀 atkLv+1。
|
||||
* 逃跑长按必成挨一下(真话;R3 打磨:需按满 900ms,探索走步 450ms 不变),Boss 拒绝;每 4 杀 atkLv+1。
|
||||
* 元进度"遗产"5 项(金币自动购置,死亡不清档):行囊药/体魄/护符/回声强化/武器。
|
||||
* 死亡归因真话律:die_cause_* / die_adv_* 按 lastHit(击杀者/背刺/未格挡)与
|
||||
* run.parries 真实选择;卡关三级提示 60/120/180s(不报答案,L3 只带方向)。
|
||||
* run.parries 真实选择;卡关双轨(R3 E0-1):无操作轨 60/120/180s(§10.3,手势重置)
|
||||
* + 无进展轨 30/60/90s(只由楼层/格位置/战斗回合/拾取重置:earcon→短句→导航接管,
|
||||
* 乱按不再饿死;教学态接管=滚出教学);踩上楼梯格到达即报贴身铁器回声(R3 E1-1)。
|
||||
*
|
||||
* 豁免 E1-E4:单击=脉冲、长按=前进/左右滑=转身(E2)、对局期
|
||||
* setRateBoostEnabled(false)(E3,EXPLORE/BATTLE/DRILL/DESCEND,TITLE/MENU/SETTLE
|
||||
@@ -39,12 +41,15 @@ const REL = { FRONT: 0, RIGHT: 1, BEHIND: 2, LEFT: 3 };
|
||||
const PULSE_CD = 1200; // 脉冲冷却(§3.1)
|
||||
const TEL_WINDOW = 1200; // 敌方攻击前摇 = 格挡窗口(§7.2)
|
||||
const WALK_STEP_MS = 500; // 长按每格耗时(§2.1)
|
||||
const STUCK_LEVELS = [60000, 120000, 180000]; // 卡关三级(§10.3)
|
||||
const STUCK_LEVELS = [60000, 120000, 180000]; // 卡关三级·无操作轨(§10.3:任何有效手势重置)
|
||||
const PROG_LEVELS = [30000, 60000, 90000]; // 无进展三级(R3 E0-1):earcon → 短句 → 导航接管
|
||||
const NAV_REPEAT_MS = 60000; // L3 带路重复周期
|
||||
const NAV_MIN_GAP_MS = 1500; // 同向导航句最小间隔(R2 D1-3:短窗不重复,保险丝友好)
|
||||
const DENSITY_STEP = 12; // 主路径内容密度下限(R2 D0-3①):每 ≤12 格必有遭遇
|
||||
const AMB_AFTER_MS = 20000; // 探索呼吸层(R2 D0-3②):静默超 20s 播环境垫
|
||||
const AMB_VOLUME = 0.35;
|
||||
const FLEE_HOLD_MS = 900; // 战斗逃跑长按最短时长(R3 打磨:探索走步 450ms 不变)
|
||||
const LONGPRESS_MS = 450; // 引擎 longpress 判定阈值(gesture.js cfg,只读参照)
|
||||
|
||||
/** 回声编码(§3.1):正前距离 4 档 → 延迟 / 音量。 */
|
||||
const ECHO_DELAY = [0, 250, 500, 800, 1100];
|
||||
@@ -141,7 +146,9 @@ export class DungeonGame extends Game {
|
||||
this._menuPause = null;
|
||||
this._menuItems = MENU_ITEMS;
|
||||
this._menuIdx = 0;
|
||||
this._stuck = { lastAct: 0, shown: new Set(), nav: false, lastFire: 0, pending: [] };
|
||||
// R3 E0-1 双轨制:lastAct=无操作轨(任何有效手势重置,§10.3 现状);
|
||||
// lastProg=无进展轨(只由状态推进重置:楼层/格位置/战斗回合/拾取)——乱按不再饿死抢救链
|
||||
this._stuck = { lastAct: 0, lastProg: 0, shown: new Set(), progShown: new Set(), nav: false, lastFire: 0, pending: [] };
|
||||
this._stuckArmed = false;
|
||||
this._lastAmbAt = 0; // 探索呼吸层上次播放时刻(R2 D0-3②)
|
||||
this._navLastDir = null; // 导航模式上次播的方向(同向短窗节流,R2 D1-3)
|
||||
@@ -168,6 +175,19 @@ export class DungeonGame extends Game {
|
||||
}
|
||||
_goldBand(gold) { return gold < 50 ? 1 : gold <= 200 ? 2 : gold <= 600 ? 3 : 4; }
|
||||
|
||||
/** R3 E1-2 金币档账目:band1(0<金<50)播新句 gold_some(「带回来一点,不多」)——
|
||||
* 修「捡到金币→口袋空空/这趟没带回什么」的档位谎报(P2/P4 共识);band0(=0)
|
||||
* 保留「空手」措辞。上滑状态链与 SETTLE/TITLE(元进度)共用同一分档与账本。 */
|
||||
_stGoldVoice() {
|
||||
if (this.meta.gold > 0 && this._goldBand(this.meta.gold) === 1) return 'voice/gold_some';
|
||||
return 'voice/st_gold_' + this._goldBand(this.meta.gold);
|
||||
}
|
||||
|
||||
_metaGoldVoice() {
|
||||
if (this.meta.gold > 0 && this._goldBand(this.meta.gold) === 1) return 'voice/gold_some';
|
||||
return 'voice/meta_gold_' + this._goldBand(this.meta.gold);
|
||||
}
|
||||
|
||||
// ================================ 地窟生成(§6) ================================
|
||||
|
||||
/** seed 派生公式(§6.1,逐字照设计):每层独立子种子。 */
|
||||
@@ -439,7 +459,7 @@ export class DungeonGame extends Game {
|
||||
}
|
||||
|
||||
_titleUpChain() {
|
||||
const ids = ['voice/meta_gold_' + this._goldBand(this.meta.gold)];
|
||||
const ids = [this._metaGoldVoice()];
|
||||
const best = this.meta.bestFloor;
|
||||
ids.push(best < 3 ? 'voice/st_best_1' : best < 6 ? 'voice/st_best_2' : 'voice/st_best_3');
|
||||
if (this.meta.unlocks.length === 0) ids.push('voice/unlock_none');
|
||||
@@ -537,6 +557,7 @@ export class DungeonGame extends Game {
|
||||
this.guide.state('explore');
|
||||
this._startMobs();
|
||||
this._stuck.lastAct = performance.now();
|
||||
this._progressTrack(); // R3 E0-1:进入探索 = 无进展轨从零起算
|
||||
this._lastAmbAt = performance.now(); // 呼吸层从进入探索起算静默(R2 D0-3②)
|
||||
this._stuckArm();
|
||||
this._armExploreWatchdog();
|
||||
@@ -547,7 +568,7 @@ export class DungeonGame extends Game {
|
||||
|
||||
onGesture(g) {
|
||||
this.guide.disarm(); // 任何手势复位向导看门狗(off 档 no-op)
|
||||
if (g === 'longpressend') { this._stopWalk(); return; } // 仅停走信号,不承载第二语义
|
||||
if (g === 'longpressend') { this._stopWalk(); this._battleFleeCancel(); return; } // 仅停走/取消逃跑,不承载第二语义
|
||||
if (this.menuOpen) { this._onMenuGesture(g); return; }
|
||||
this._stuck.pending.length = 0; // 玩家操作即作废未播的卡关提示(§10.3)
|
||||
switch (this.state) {
|
||||
@@ -691,6 +712,7 @@ export class DungeonGame extends Game {
|
||||
return;
|
||||
}
|
||||
this.run.pos = { x: nx, y: ny };
|
||||
this._progressTrack(); // 格位置变化 = 无进展轨重置(R3 E0-1:走动是真进展)
|
||||
this._walk.steps++;
|
||||
this.audio.play('sfx/step_own', { volume: 0.7 });
|
||||
vibrate('swipe');
|
||||
@@ -718,6 +740,12 @@ export class DungeonGame extends Game {
|
||||
if (!st || st.x !== x || st.y !== y) { this._onStairs = false; return; }
|
||||
this._onStairs = true;
|
||||
this._progress(); // 踏上楼梯格 = 进展事件(§10.3)
|
||||
// R3 E1-1 到达即报:踩上楼梯格瞬间自动播贴身铁器回声(编码同脉冲贴身档:
|
||||
// echo_1 +120ms 材质尾音)。live 证据——站楼梯格 tap 被下潜模态截走,「铁器=楼梯」
|
||||
// 只能靠相邻格脉冲兑现(P1-1 输入层不可达)。不占输入通道:单击仍是下潜确认。
|
||||
const s = this._session;
|
||||
this.audio.play('sfx/echo_1', { volume: ECHO_VOL[1] });
|
||||
this._after(MAT_TAIL_AT, () => { if (s === this._session) this.audio.play('sfx/mat_stair', { volume: 0.8 }); });
|
||||
const spec = FLOOR_SPECS[this.run.floor];
|
||||
if (spec.boss && !this.run.cleared.includes(this.run.floor)) {
|
||||
this._speak(['voice/evt_stairs_lock']);
|
||||
@@ -802,7 +830,7 @@ export class DungeonGame extends Game {
|
||||
if (band === 4) vibrate('warning');
|
||||
this._speak(['voice/st_floor_' + this.run.floor,
|
||||
'voice/st_hp_' + band,
|
||||
'voice/st_gold_' + this._goldBand(this.meta.gold),
|
||||
this._stGoldVoice(),
|
||||
'voice/st_face_' + DIR_KEY[this.run.face],
|
||||
'voice/st_threat_' + this._threatKey()]);
|
||||
}
|
||||
@@ -872,6 +900,7 @@ export class DungeonGame extends Game {
|
||||
cls: ms.cls, boss: !!ms.boss, mover: !!ms.mover, cell: { x: mob.x, y: mob.y },
|
||||
bearing: DIR_ORDER.indexOf(this.run.face), moveN: 0, phase2: false,
|
||||
state: 'intro', windowEnd: 0, parry: false, noTurnSaid: false,
|
||||
fleeArm: false, noFleeHintSaid: false, // R3 打磨:逃跑长按 ≥900ms(短松=取消+区分提示一句)
|
||||
drill: !!(this._drill && this._drill.step === 8),
|
||||
drillMob: !!mob.drill,
|
||||
};
|
||||
@@ -898,6 +927,8 @@ export class DungeonGame extends Game {
|
||||
if (!b) return;
|
||||
b.state = 'player';
|
||||
b.parry = false;
|
||||
b.fleeArm = false; // 新回合作废未满时的逃跑长按(R3 打磨)
|
||||
this._progressTrack(); // 战斗回合推进 = 无进展轨重置(R3 E0-1:战斗本身是内容)
|
||||
this.guide.turn({ haptic: true }); // turn earcon + confirm 震(§10.2)
|
||||
this.guide.watchdog({
|
||||
arm: true, at: [15000, 30000], say: ['gd_turn', null],
|
||||
@@ -916,7 +947,7 @@ export class DungeonGame extends Game {
|
||||
else if (g === 'doubletap') vibrate('error'); // 窗口外双击:error 震不生效(§7.2)
|
||||
else if (g === 'left') this._battleTurnG(-1);
|
||||
else if (g === 'right') this._battleTurnG(1);
|
||||
else if (g === 'longpress') this._flee();
|
||||
else if (g === 'longpress') this._fleeArm(); // R3 打磨:先武装,按满 900ms 才真逃
|
||||
else if (g === 'up') this._speakBattleStatus();
|
||||
else if (g === 'down') this._openMenu();
|
||||
} else if (b.state === 'telegraph') {
|
||||
@@ -995,6 +1026,35 @@ export class DungeonGame extends Game {
|
||||
this._speak(ids);
|
||||
}
|
||||
|
||||
/** R3 打磨:逃跑长按武装(live P3:长按三义在「相邻扑击」时代误逃率升高——
|
||||
* 走位中被扑→下一步长按=瞬间逃跑挨打,实录 flee×7+扫图误逃×3)。探索态
|
||||
* 450ms 走步不变;战斗态需按满 FLEE_HOLD_MS(900ms)才真正尝试逃跑。 */
|
||||
_fleeArm() {
|
||||
const b = this._battle;
|
||||
if (!b || b.state !== 'player' || b.fleeArm) return;
|
||||
b.fleeArm = true;
|
||||
const s = this._session;
|
||||
this._after(FLEE_HOLD_MS - LONGPRESS_MS, () => { // longpress 事件已在 450ms 到手,再等差值
|
||||
if (s !== this._session || this._battle !== b || !b.fleeArm || b.state !== 'player' || this.menuOpen) return;
|
||||
b.fleeArm = false;
|
||||
this._flee();
|
||||
});
|
||||
}
|
||||
|
||||
/** R3 打磨:长按未满 900ms 松手 = 取消逃跑(探索走步停走不受影响);
|
||||
* 每场战斗播一次区分提示(教学 D 系补课:想逃就按住别松手)。 */
|
||||
_battleFleeCancel() {
|
||||
const b = this._battle;
|
||||
if (!b || !b.fleeArm) return;
|
||||
b.fleeArm = false;
|
||||
if (this.state !== 'BATTLE' || b.state !== 'player' || this.menuOpen) return;
|
||||
vibrate('error');
|
||||
if (!b.noFleeHintSaid) {
|
||||
b.noFleeHintSaid = true;
|
||||
this._speakGuarded(['voice/tut_flee_hold'], () => {}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
/** 长按=尝试逃跑(§7.3):普通/绕位必成挨一下;Boss 拒绝。 */
|
||||
_flee() {
|
||||
const b = this._battle;
|
||||
@@ -1206,11 +1266,14 @@ export class DungeonGame extends Game {
|
||||
// R2 D1-5:金币档与 TITLE 同一分档函数、同一本账(meta.gold,遗产购置后)。
|
||||
// R1 live:SETTLE 用 run 金币自设阈值报 meta_gold_3,TITLE 用 _goldBand(meta.gold)
|
||||
// 报 meta_gold_2——同一句 id 两套口径,「这趟」的账对不上。
|
||||
const goldBand = this._goldBand(this.meta.gold);
|
||||
// R2 D1-5:金币档与 TITLE 同一分档函数、同一本账(meta.gold,遗产购置后);
|
||||
// R3 E1-2:band1(0<金<50)再换成 gold_some 真话句(经 _metaGoldVoice 统一出口)。
|
||||
// R1 live:SETTLE 用 run 金币自设阈值报 meta_gold_3,TITLE 用 _goldBand(meta.gold)
|
||||
// 报 meta_gold_2——同一句 id 两套口径,「这趟」的账对不上。
|
||||
this.run = null; // 死亡清 run 不清 meta
|
||||
this._save();
|
||||
this._settleChain = ['voice/die_intro', 'voice/die_cause_' + cause, 'voice/die_adv_' + adv,
|
||||
'voice/st_floor_' + floorN, 'voice/meta_gold_' + goldBand, 'voice/settle_stronger', 'voice/settle_again'];
|
||||
'voice/st_floor_' + floorN, this._metaGoldVoice(), 'voice/settle_stronger', 'voice/settle_again'];
|
||||
this._speakGuarded(this._settleChain, () => {}, 30000);
|
||||
}
|
||||
|
||||
@@ -1227,8 +1290,7 @@ export class DungeonGame extends Game {
|
||||
this.meta.bestFloor = Math.max(this.meta.bestFloor, 7);
|
||||
this.meta.runs++;
|
||||
const bought = this._buyUnlocks();
|
||||
const goldBand = this._goldBand(this.meta.gold); // R2 D1-5:与 TITLE 同函数同账本
|
||||
const ids = ['voice/settle_win_1', 'voice/settle_win_2', 'voice/meta_gold_' + goldBand];
|
||||
const ids = ['voice/settle_win_1', 'voice/settle_win_2', this._metaGoldVoice()]; // R2 D1-5/R3 E1-2:与 TITLE 同函数同账本
|
||||
if (bought.length) for (const u of bought) ids.push('voice/unlock_' + u);
|
||||
ids.push('voice/settle_again');
|
||||
this.run = null;
|
||||
@@ -1286,6 +1348,9 @@ export class DungeonGame extends Game {
|
||||
step: -1, fails: 0, upDone: false, menuDone: false, turnedL: false, turnedR: false,
|
||||
bat: null, stairsSpoken: false,
|
||||
};
|
||||
this._stuck.lastAct = performance.now();
|
||||
this._progressTrack(); // R3 E0-2:教学态无进展轨从零起算
|
||||
this._stuckArm(); // 教学态 5s 轮询(无进展轨接管=滚出教学)
|
||||
this._drillEnter(0);
|
||||
}
|
||||
|
||||
@@ -1300,6 +1365,7 @@ export class DungeonGame extends Game {
|
||||
const d = this._drill;
|
||||
d.step = step;
|
||||
d.fails = 0;
|
||||
this._progressTrack(); // 步骤推进 = 无进展轨重置(R3 E0-2:做对了就不会被接管)
|
||||
if (step === 0) {
|
||||
this._speakGuarded(['voice/intro_1', 'voice/intro_2', 'voice/tut_d0'], () => this._drillWatchdog(0), 20000);
|
||||
} else if (step === 1) {
|
||||
@@ -1541,6 +1607,9 @@ export class DungeonGame extends Game {
|
||||
this.state = 'DRILL';
|
||||
this.audio.play('bgm/explore');
|
||||
this.audio.setRateBoostEnabled(false);
|
||||
this._stuck.lastAct = performance.now();
|
||||
this._progressTrack(); // 菜单挂起时间不计入无进展(R3 E0-2)
|
||||
this._stuckArm();
|
||||
const d = this._drill;
|
||||
if (d.step === 7) {
|
||||
d.menuDone = true;
|
||||
@@ -1555,6 +1624,7 @@ export class DungeonGame extends Game {
|
||||
this.audio.setRateBoostEnabled(false);
|
||||
this._startMobs();
|
||||
this._stuck.lastAct = performance.now();
|
||||
this._progressTrack(); // R3 E0-1:菜单挂起时间不计入无进展
|
||||
this._lastAmbAt = performance.now();
|
||||
this._stuckArm();
|
||||
} else {
|
||||
@@ -1598,11 +1668,20 @@ export class DungeonGame extends Game {
|
||||
|
||||
// ================================ 卡关三级提示(§10.3) ================================
|
||||
|
||||
_progress() { // 进展事件:拾取/战斗胜利/踏上楼梯格/击败窟主/下潜 → 重置分级
|
||||
_progress() { // 进展事件:拾取/战斗胜利/踏上楼梯格/击败窟主/下潜 → 重置双轨分级
|
||||
this._stuck.shown.clear();
|
||||
this._stuck.progShown.clear();
|
||||
this._stuck.nav = false;
|
||||
this._navLastDir = null;
|
||||
this._stuck.lastAct = performance.now();
|
||||
this._stuck.lastProg = this._stuck.lastAct;
|
||||
}
|
||||
|
||||
/** R3 E0-1:无进展轨重置——只由状态推进调用(楼层/格位置/战斗回合/拾取)。
|
||||
* 任何手势都不重置本轨:连续乱按(无操作轨被喂饱)依旧会升级到人话与接管。 */
|
||||
_progressTrack() {
|
||||
this._stuck.lastProg = performance.now();
|
||||
this._stuck.progShown.clear();
|
||||
}
|
||||
|
||||
_stuckArm() {
|
||||
@@ -1611,10 +1690,9 @@ export class DungeonGame extends Game {
|
||||
const s = this._session;
|
||||
const loop = () => {
|
||||
if (s !== this._session) { this._stuckArmed = false; return; }
|
||||
if (this.state === 'EXPLORE' && !this.menuOpen) {
|
||||
this._stuckCheck();
|
||||
this._ambBreath();
|
||||
}
|
||||
// R3 E0-2:教学态同享无进展轨(乱按困在教学 39 分钟的解药);呼吸层仍仅探索态
|
||||
if ((this.state === 'EXPLORE' || this.state === 'DRILL') && !this.menuOpen) this._stuckCheck();
|
||||
if (this.state === 'EXPLORE' && !this.menuOpen) this._ambBreath();
|
||||
this._after(5000, loop);
|
||||
};
|
||||
this._after(5000, loop);
|
||||
@@ -1637,15 +1715,32 @@ export class DungeonGame extends Game {
|
||||
const now = performance.now();
|
||||
const idle = now - this._stuck.lastAct;
|
||||
if (this._stuck.nav) {
|
||||
// 导航模式重复带路:与无操作轨无关(R3 E0-1:乱按期间也照常重报)
|
||||
if (now - this._stuck.lastFire >= NAV_REPEAT_MS) this._stuckFire(3);
|
||||
return;
|
||||
}
|
||||
if (this._stuck.pending.length) return; // 待播中:等声道空出,不重复入队
|
||||
// R3 E0-1 无进展轨(先查,阈值更紧):只由状态推进重置——层级/格位置/战斗
|
||||
// 回合/拾取。30s earcon → 60s 短句(stair_hint_a 类)→ 90s 导航接管。
|
||||
const noprogress = now - this._stuck.lastProg;
|
||||
if (noprogress >= PROG_LEVELS[2] && !this._stuck.progShown.has('L3')) { this._stuckFire(3, true); return; }
|
||||
if (noprogress >= PROG_LEVELS[1] && !this._stuck.progShown.has('L2')) { this._stuckFire(2, true); return; }
|
||||
if (noprogress >= PROG_LEVELS[0] && !this._stuck.progShown.has('L1')) { this._stuckFire(1, true); return; }
|
||||
// §10.3 无操作轨(现状口径:任何有效手势重置;仅探索态——教学态的静止兜底
|
||||
// 是 §10.2 教学看门狗 + 上面的无进展轨,避免教学期播错内容的指路句)
|
||||
if (this.state !== 'EXPLORE') return;
|
||||
if (idle >= STUCK_LEVELS[2] && !this._stuck.shown.has('L3')) this._stuckFire(3);
|
||||
else if (idle >= STUCK_LEVELS[1] && !this._stuck.shown.has('L2')) this._stuckFire(2);
|
||||
else if (idle >= STUCK_LEVELS[0] && !this._stuck.shown.has('L1')) this._stuckFire(1);
|
||||
}
|
||||
|
||||
/** 卡关 L1 短句选句:窟主未清/终局层 → 「大东西守着」;否则 → 铁器暗示。 */
|
||||
_stairHintId() {
|
||||
const spec = FLOOR_SPECS[this.run.floor];
|
||||
const bossAlive = (spec.boss && !this.run.cleared.includes(this.run.floor)) || !!spec.final;
|
||||
return bossAlive ? 'voice/stair_hint_b' : 'voice/stair_hint_a';
|
||||
}
|
||||
|
||||
_stuckStairDir() { // 楼梯(终局层=王座)绝对方位(与上滑面朝句同坐标系,自洽)
|
||||
const st = this._floor.stairs || this._floor.throne;
|
||||
if (!st) return 'e';
|
||||
@@ -1654,15 +1749,45 @@ export class DungeonGame extends Game {
|
||||
return dy >= 0 ? 's' : 'n';
|
||||
}
|
||||
|
||||
_stuckFire(level) {
|
||||
/**
|
||||
* 卡关升级发射。fromProg=false:无操作轨(§10.3,60/120/180s:短句→明示→带路);
|
||||
* fromProg=true:R3 E0-1 无进展轨(30/60/90s:earcon → 短句 → 接管)——
|
||||
* 探索态接管=导航模式(最短路首步方向+楼梯指向);教学态接管=滚出教学
|
||||
* (E0-2:恢复 R1 乱按局 ~75s 即出教学的口径,压进 90-120s)。
|
||||
*/
|
||||
_stuckFire(level, fromProg = false) {
|
||||
if (fromProg && this.state === 'DRILL' && level === 2 && this._drill?.step !== 9) {
|
||||
// 非寻路步骤无方向话可给(教学句不重播,§10.2):短句级跳过登记,等 90s 接管
|
||||
this._stuck.progShown.add('L2');
|
||||
return;
|
||||
}
|
||||
this._stuck.lastFire = performance.now();
|
||||
vibrate('warning');
|
||||
if (fromProg && level === 1) {
|
||||
// 第 1 级 earcon:不占台词通道、不排队(语音在播也照发,sfx 不顶人声)
|
||||
this._stuck.progShown.add('L1');
|
||||
this.audio.play('sfx/turn_tick', { volume: 0.7 }); // 复用 R2 D1-6 合成回执音当注意 earcon
|
||||
return;
|
||||
}
|
||||
let ids = [];
|
||||
if (level === 1) {
|
||||
const spec = FLOOR_SPECS[this.run.floor];
|
||||
const bossAlive = (spec.boss && !this.run.cleared.includes(this.run.floor)) || !!spec.final;
|
||||
// 终局层无楼梯(目标是王座上的窟中之王)→ 用「大东西守着」句,不说铁器
|
||||
ids = [bossAlive ? 'voice/stair_hint_b' : 'voice/stair_hint_a'];
|
||||
if (fromProg) {
|
||||
if (this.state === 'DRILL') {
|
||||
if (level === 2) {
|
||||
// 教学句不重播(§10.2);唯 D9(自行寻楼梯)有现成方向话可给
|
||||
if (this._drill?.step === 9) ids = ['voice/stair_hint_a'];
|
||||
} else {
|
||||
this._drillSkip(); // 90s 零进展:教学接管=自动跳过(tut_skip → 探索态)
|
||||
return;
|
||||
}
|
||||
} else if (level === 2) {
|
||||
ids = [this._stairHintId()];
|
||||
} else {
|
||||
const st = this._floor.stairs || this._floor.throne;
|
||||
if (st && st.x === this.run.pos.x && st.y === this.run.pos.y) ids = ['voice/nav_done'];
|
||||
else ids = this._navRouteVoices();
|
||||
}
|
||||
} else if (level === 1) {
|
||||
ids = [this._stairHintId()];
|
||||
} else if (level === 2) {
|
||||
ids = ['voice/stair_dir_' + this._stuckStairDir()];
|
||||
} else {
|
||||
@@ -1674,21 +1799,27 @@ export class DungeonGame extends Game {
|
||||
ids = this._navRouteVoices();
|
||||
}
|
||||
}
|
||||
if (!ids.length) return; // 无话可播(如目标不可达的退化边):不入队不登记,下轮再查
|
||||
if (this.audio.isVoicePlaying()) {
|
||||
this._stuck.pending.push({ level, ids }); // 语音在播 → 入待播队列(escape round2 礼仪)
|
||||
this._stuck.pending.push({ level, ids, fromProg }); // 语音在播 → 入待播队列(escape round2 礼仪)
|
||||
// 未播级别不计入 shown:玩家操作作废后,下段静默期可重新触发(§10.3)
|
||||
} else {
|
||||
this._stuckSpoken(level, ids);
|
||||
this._stuckSpoken(level, ids, fromProg);
|
||||
}
|
||||
}
|
||||
|
||||
_stuckSpoken(level, ids) { // 真正播出才算"已提示"(入队被作废的不算,§10.3)
|
||||
_stuckSpoken(level, ids, fromProg = false) { // 真正播出才算"已提示"(入队被作废的不算,§10.3)
|
||||
if (!ids.length) return;
|
||||
if (level === 3) {
|
||||
if (ids[0] === 'voice/nav_done') { this._progress(); return; }
|
||||
this._stuck.nav = true; // L3 带路:进入导航模式,每步播方向,抵达播 nav_done
|
||||
this._stuck.shown.add('L3');
|
||||
this._stuck.progShown.add('L3');
|
||||
} else {
|
||||
this._stuck.shown.add('L' + level);
|
||||
// 短句两轨内容同级(无操作轨 L1 = 无进展轨 L2):交叉登记防重复播;
|
||||
// 明示级(stair_dir)只由无操作轨 L2 兑现登记,无进展轨短句不得冒领
|
||||
this._stuck.shown.add((level === 2 && !fromProg) ? 'L2' : 'L1');
|
||||
this._stuck.progShown.add('L2'); // 短句已给:无进展轨的短句级不再重复
|
||||
}
|
||||
this._speak(ids);
|
||||
}
|
||||
@@ -1744,8 +1875,8 @@ export class DungeonGame extends Game {
|
||||
_stuckFlush() {
|
||||
if (!this._stuck.pending.length) return;
|
||||
if (this.audio.isVoicePlaying()) return;
|
||||
const { level, ids } = this._stuck.pending.shift();
|
||||
this._stuckSpoken(level, ids);
|
||||
const { level, ids, fromProg } = this._stuck.pending.shift();
|
||||
this._stuckSpoken(level, ids, fromProg);
|
||||
}
|
||||
|
||||
_stuckDiscardPending() { // 玩家操作即作废未播级别(§10.3)
|
||||
|
||||
@@ -692,6 +692,8 @@ async function scenario2() {
|
||||
await walkPath(game, path);
|
||||
assert(game._onStairs === true, '踏上楼梯格');
|
||||
assert(plays(audio, mark).has('voice/tut_stairs_on'), '首次踏上楼梯格播 tut_stairs_on');
|
||||
assert(plays(audio, mark).has('sfx/echo_1') && plays(audio, mark).has('sfx/mat_stair'),
|
||||
'R3 E1-1 到达即报:踩上楼梯格瞬间自动播贴身铁器回声(echo_1+mat_stair,全程零玩家脉冲)');
|
||||
mark = audio.log.length;
|
||||
g(game, 'tap'); // 单击下潜
|
||||
await tick(6000);
|
||||
@@ -699,6 +701,7 @@ async function scenario2() {
|
||||
assert(game.meta.drillDone === true && game._drill === null, '教学标志入元进度,DRILL 收尾');
|
||||
p = plays(audio, mark);
|
||||
assert(p.has('sfx/stairs_down') && p.orderOk('voice/evt_descend', 'voice/tut_done', 'voice/st_floor_2'), '下潜演出:stairs_down → evt_descend → tut_done → st_floor_2');
|
||||
assert(p.has('sfx/stairs_down') && game.run.floor === 2, 'R3 E1-1: 到达即报不占输入通道——tap 仍是下潜确认(照常下潜)');
|
||||
const f2 = game._generateFloor(42, 2);
|
||||
assert(JSON.stringify(game._floor.grid) === JSON.stringify(f2.grid), '§12.6: 第 2 层 grid 由 floorSeed 重生成且复现');
|
||||
return { game, audio };
|
||||
@@ -715,7 +718,8 @@ async function scenario4({ game, audio }) {
|
||||
await tick(6000);
|
||||
const faceId = 'voice/st_face_' + game.run.face.toLowerCase();
|
||||
p = plays(audio, mark);
|
||||
assert(p.orderOk('voice/st_floor_2', 'voice/st_hp_1', 'voice/st_gold_1', faceId), '上滑链前 4 段有序(层/血/金/面朝)');
|
||||
// R3 E1-2:此刻 meta.gold=3(教学蝠掉落,0<金<50)→ 档 1 播 gold_some 真话句(不再「口袋空空」)
|
||||
assert(p.orderOk('voice/st_floor_2', 'voice/st_hp_1', 'voice/gold_some', faceId), '上滑链前 4 段有序(层/血/金/gold_some band1 真话/面朝)');
|
||||
assert(p.countRe(/^voice\/st_threat_/) === 1, '上滑链第 5 段威胁句恰 1 句');
|
||||
|
||||
// 探索菜单冻结:菜单打开期间怪物游走停摆,关闭恢复。
|
||||
@@ -973,6 +977,17 @@ async function scenario5() {
|
||||
assert(game.run.hp === hpP - 2, `格挡 ×0.2(atk10 → 伤 ${hpP - game.run.hp},期望 2)`);
|
||||
assert(plays(audio, mark).has('voice/btl_parried'), '格挡成功播 btl_parried(挡下了大半)');
|
||||
assert(game.run.parries === 1, 'parries 只记"面对且挡下"的格挡(1 次)');
|
||||
// R3 打磨:战斗长按未满 900ms 松手 = 取消逃跑(防走位肌肉记忆误逃)+ 区分提示一句
|
||||
mark = audio.log.length;
|
||||
vibA = vibrateLog.length;
|
||||
g(game, 'longpress');
|
||||
await tick(200);
|
||||
g(game, 'longpressend');
|
||||
await tick(600);
|
||||
assert(game.state === 'BATTLE' && game._battle === b && b.state === 'player',
|
||||
'战斗长按 ~650ms(<900ms)松手 = 不逃(R3 打磨)');
|
||||
assert(vibratedError(vibA), '短长按取消伴随 error 震');
|
||||
assert(plays(audio, mark).has('voice/tut_flee_hold'), '取消播区分提示 tut_flee_hold(每场 1 次)');
|
||||
// 长按逃跑:必成 + 撤退挨一下(真实账目)
|
||||
b.atk = 1; // 还原
|
||||
await tick(1500);
|
||||
@@ -1120,16 +1135,19 @@ async function scenario6a() {
|
||||
assert(game.state === 'SETTLE', 'HP≤0 → 死亡结算 SETTLE');
|
||||
await tick(8000); // 死亡链 7 句播完
|
||||
p = plays(audio, mark);
|
||||
// R3 E1-2:settle 金币 40(0<金<50)→ 档 1 播新真话句 gold_some(不再是「没带回什么」)
|
||||
assert(p.orderOk('voice/die_intro', 'voice/die_cause_2', 'voice/die_adv_2', 'voice/st_floor_1',
|
||||
'voice/meta_gold_1', 'voice/settle_stronger', 'voice/settle_again'),
|
||||
'死亡链序:die_intro → die_cause_2(Boss 重击未格挡)→ die_adv_2 → st_floor → meta_gold → settle_stronger → settle_again');
|
||||
'voice/gold_some', 'voice/settle_stronger', 'voice/settle_again'),
|
||||
'死亡链序:die_intro → die_cause_2(Boss 重击未格挡)→ die_adv_2 → st_floor → gold_some(E1-2 band1)→ settle_stronger → settle_again');
|
||||
assert(game._deathInfo.lastHit.type === 'crab' && game._deathInfo.cause === 2,
|
||||
`归因指认真凶:lastHit=${game._deathInfo.lastHit.type} → die_cause_2`);
|
||||
assert(game.meta.gold === 40, `遗产自动购置 90+150+220(500→${game.meta.gold})`);
|
||||
{
|
||||
// R3 E1-2:settle 档位与 TITLE 同函数同账本;band1(0<金<50)= gold_some 真话句
|
||||
const band = game._goldBand(game.meta.gold);
|
||||
assert(plays(audio, mark).has('voice/meta_gold_' + band),
|
||||
`R2 D1-5:SETTLE 金币档与 TITLE 同分档函数(_goldBand(meta.gold)=${band})`);
|
||||
const want = band === 1 ? 'voice/gold_some' : 'voice/meta_gold_' + band;
|
||||
assert(plays(audio, mark).has(want),
|
||||
`R2 D1-5/R3 E1-2:SETTLE 金币档 = TITLE 同分档出口(_goldBand=${band} → ${want})`);
|
||||
}
|
||||
assert(JSON.stringify(game.meta.unlocks) === JSON.stringify(['potion', 'vigor', 'veil']), '解锁 potion/vigor/veil');
|
||||
assert(game.meta.bestFloor === 1 && game.meta.runs === 1, 'bestFloor/runs 更新');
|
||||
@@ -1706,6 +1724,242 @@ async function scenario12() {
|
||||
}
|
||||
}
|
||||
|
||||
// ================================ 场景 13:R3 修复回归(E0-1 看门狗双轨 / E0-2 跳教学 / E1-1 / E1-2 / 打磨) ================================
|
||||
|
||||
/** 找「死胡同」格(开放邻格最少)+ 一面朝向的墙:乱按零位移的保障。 */
|
||||
function deadEndCell(floor) {
|
||||
let best = null;
|
||||
for (let y = 0; y < floor.size; y++) for (let x = 0; x < floor.size; x++) {
|
||||
if (floor.grid[y][x] !== 1) continue;
|
||||
let open = 0, wallDir = null;
|
||||
for (const [dir, d] of Object.entries(DIRS)) {
|
||||
const nx = x + d.dx, ny = y + d.dy;
|
||||
if (nx < 0 || ny < 0 || nx >= floor.size || ny >= floor.size || floor.grid[ny][nx] === 0) { wallDir = dir; continue; }
|
||||
open++;
|
||||
}
|
||||
if (!best || open < best.open) best = { x, y, open, wallDir };
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/** 连续乱按:每 ~1s 一个随机手势;reface 非空时每拍先把脸按回墙(长按只会 bump)。 */
|
||||
async function mash(game, set, ms, reface = null) {
|
||||
const t0 = vnow;
|
||||
while (vnow - t0 < ms) {
|
||||
if (reface) game.run.face = reface; // 测试钩子:钉死朝墙,保证零位移(零进展)
|
||||
g(game, set[Math.floor(Math.random() * set.length)]);
|
||||
await tick(900 + Math.floor(Math.random() * 500));
|
||||
}
|
||||
}
|
||||
|
||||
async function scenario13() {
|
||||
origConsoleLog('\n=== 场景 13:R3 修复回归(E0-1 双轨看门狗 / E0-2 跳教学 / E1-2 金币档 / E1-1 锁格到达即报) ===');
|
||||
|
||||
// ---- A. E0-1:连续乱按 96s 零进展 → earcon → 短句 → 导航接管(无操作轨被喂饱也升级) ----
|
||||
{
|
||||
storageMap.clear();
|
||||
const { game, audio } = newGame({ seed: 11 });
|
||||
game.start();
|
||||
await tick(400);
|
||||
g(game, 'tap');
|
||||
await tick(6000);
|
||||
g(game, 'down');
|
||||
await tick(2000);
|
||||
assert(game.state === 'EXPLORE', '场景13A: 跳过教学进探索');
|
||||
game._mobStep = () => {}; // 静场:乱按不被接战打断
|
||||
const de = deadEndCell(game._floor);
|
||||
assert(de && de.wallDir, '场景13A: 找到临墙格(mash 每拍钉死朝墙 → 长按只 bump,零位移保障)');
|
||||
game.run.pos = { x: de.x, y: de.y };
|
||||
const m0 = audio.log.length;
|
||||
await mash(game, ['tap', 'doubletap', 'left', 'right', 'longpress'], 96000, de.wallDir);
|
||||
const seg = plays(audio, m0);
|
||||
assert(game.state === 'EXPLORE' && game.run.pos.x === de.x && game.run.pos.y === de.y,
|
||||
'E0-1: 乱按 96s 全程零位移(无操作轨持续被手势重置——R2 压力局正是被这条饿死)');
|
||||
assert(seg.has('sfx/turn_tick'), 'E0-1: 无进展 30s 级 → earcon(复用合成回执音,乱按饿不死)');
|
||||
assert(seg.has('voice/stair_hint_a'), 'E0-1: 无进展 60s 级 → 短句 stair_hint_a(抢救落到人话)');
|
||||
assert(seg.hasRe(/^voice\/nav_[eswn]$/), 'E0-1: 无进展 90s 级 → 导航接管(播最短路首步方向)');
|
||||
assert(game._stuck.nav === true, 'E0-1: 接管后进入导航模式(每步校正 + 60s 重报直至进展)');
|
||||
{
|
||||
const dir = game._navFirstStepDir(game._floor.stairs);
|
||||
const nb = DIRS[dir];
|
||||
assert(dir && game._floor.grid[game.run.pos.y + nb.dy]?.[game.run.pos.x + nb.dx] === 1,
|
||||
'E0-1: 接管首步方向必可通行(楼梯指向,不指墙)');
|
||||
}
|
||||
const vn = seg.countRe(/^voice\//);
|
||||
assert(vn <= 4, `E0-1: 乱按 96s 语音总量有上界(${vn} 句 ≤4;R1 风暴/2223s 空窗两极都不复现)`);
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ---- B. E0-1:有真实进展(格位置持续推进)则全程不触发 ----
|
||||
{
|
||||
storageMap.clear();
|
||||
const { game, audio } = newGame({ seed: 23 });
|
||||
game.start();
|
||||
await tick(400);
|
||||
g(game, 'tap');
|
||||
await tick(6000);
|
||||
g(game, 'down');
|
||||
await tick(2000);
|
||||
assert(game.state === 'EXPLORE', '场景13B: 跳过教学进探索');
|
||||
game._mobStep = () => {};
|
||||
const fl = game._floor;
|
||||
const from = { ...fl.start };
|
||||
const nb = Object.entries(DIRS).find(([, d]) => {
|
||||
const nx = from.x + d.dx, ny = from.y + d.dy;
|
||||
return fl.grid[ny]?.[nx] === 1 && !fl.items.has(nx + ',' + ny)
|
||||
&& !(fl.stairs && nx === fl.stairs.x && ny === fl.stairs.y);
|
||||
});
|
||||
assert(nb, '场景13B: 起点有无宝无楼梯的可走邻格');
|
||||
const d0 = nb[1];
|
||||
const m0 = audio.log.length;
|
||||
const t0 = vnow;
|
||||
let legs = 0;
|
||||
while (vnow - t0 < 100000) {
|
||||
const back = legs % 2 === 1;
|
||||
const dx = back ? -d0.dx : d0.dx, dy = back ? -d0.dy : d0.dy;
|
||||
game.run.face = Object.entries(DIRS).find(([, d]) => d.dx === dx && d.dy === dy)[0];
|
||||
g(game, 'longpress'); // 起步即走 1 格(真实进展:格位置变化重置无进展轨)
|
||||
await tick(80);
|
||||
g(game, 'longpressend');
|
||||
await tick(560);
|
||||
legs++;
|
||||
}
|
||||
const seg = plays(audio, m0);
|
||||
assert(!seg.hasRe(/^voice\//) && !seg.has('sfx/turn_tick'),
|
||||
`E0-1: 有真实进展(${legs} 次格移动 / 100s)零卡关语音零 earcon(不误伤正常玩家)`);
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ---- C. E0-2:跳教学种子局主路径密度不变式 + 120s 内必有指向语音(或遭遇) ----
|
||||
{
|
||||
storageMap.clear();
|
||||
const { game, audio } = newGame({ seed: 77 });
|
||||
game.start();
|
||||
await tick(400);
|
||||
g(game, 'tap');
|
||||
await tick(6000);
|
||||
g(game, 'down'); // D0 即下滑:跳教学路径
|
||||
await tick(2000);
|
||||
assert(game.state === 'EXPLORE' && game.run, '场景13C: 跳教学直达探索(drillDone)');
|
||||
{
|
||||
// 主路径密度不变式:对实测 _floor 由测试侧独立重算(生成器对跳教学局一视同仁)
|
||||
const fl = game._floor;
|
||||
const dist = bfsDist(fl);
|
||||
const target = fl.stairs;
|
||||
const content = new Set([fl.start.x + ',' + fl.start.y, target.x + ',' + target.y,
|
||||
...fl.items.keys(), ...fl.mobs.map((m) => m.x + ',' + m.y)]);
|
||||
const path2 = [target];
|
||||
let cur = { ...target };
|
||||
while (cur.x !== fl.start.x || cur.y !== fl.start.y) {
|
||||
for (const d of Object.values(DIRS)) {
|
||||
const nx = cur.x + d.dx, ny = cur.y + d.dy;
|
||||
if (nx < 0 || ny < 0 || nx >= fl.size || ny >= fl.size || fl.grid[ny][nx] !== 1
|
||||
|| dist[ny][nx] !== dist[cur.y][cur.x] - 1) continue;
|
||||
cur = { x: nx, y: ny };
|
||||
break;
|
||||
}
|
||||
path2.push(cur);
|
||||
}
|
||||
let maxGap = 0, run = 0;
|
||||
for (const c of path2) {
|
||||
if (content.has(c.x + ',' + c.y)) { maxGap = Math.max(maxGap, run); run = 0; } else run++;
|
||||
}
|
||||
maxGap = Math.max(maxGap, run);
|
||||
assert(maxGap <= 12, `E0-2: 跳教学种子局主路径密度不变式(最长真空 ${maxGap} 格 ≤12)`);
|
||||
}
|
||||
game._mobStep = () => {}; // 静场:专验指向语音路径(遭遇路径由场景 12C 覆盖)
|
||||
const de = deadEndCell(game._floor);
|
||||
game.run.pos = { x: de.x, y: de.y };
|
||||
const m0 = audio.log.length;
|
||||
const t0 = vnow;
|
||||
await mash(game, ['tap', 'doubletap', 'left', 'right', 'longpress'], 96000, de.wallDir);
|
||||
const hit = audio.log.slice(m0).find((e) => e.id === 'voice/stair_hint_a' || /^voice\/nav_[eswn]$/.test(e.id));
|
||||
assert(hit && hit.t - t0 <= 120000,
|
||||
`E0-2: 跳教学后 ${Math.round((hit ? hit.t - t0 : 1e9) / 1000)}s 内必有指向语音(≤120s;R2 压力局 skip 后 79 分钟零指向)`);
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ---- D. E0-2:教学态乱按零进展 90s 级 → 自动滚出教学(R1 乱按局 ~75s 口径恢复) ----
|
||||
{
|
||||
storageMap.clear();
|
||||
const { game, audio } = newGame({ seed: 11 });
|
||||
game.start();
|
||||
await tick(400);
|
||||
g(game, 'tap');
|
||||
await tick(6000);
|
||||
assert(game.state === 'DRILL', '场景13D: 进教学');
|
||||
game._drill.step = 9; // 测试钩子:直落 D9(脉冲等待步——压力局 39 分钟锁点;tap=脉冲零进展)
|
||||
const m0 = audio.log.length;
|
||||
const t0 = vnow;
|
||||
await mash(game, ['tap', 'doubletap'], 98000);
|
||||
const seg = plays(audio, m0);
|
||||
assert(game.state === 'EXPLORE' && game.meta.drillDone === true,
|
||||
`E0-2: 教学乱按零进展 ${Math.round((vnow - t0) / 1000)}s 内自动滚出教学(R2 压力局 2403s → ≤95s)`);
|
||||
assert(seg.has('sfx/turn_tick'), 'E0-2: 教学乱按 30s 级 earcon 先到');
|
||||
assert(seg.has('voice/stair_hint_a'), 'E0-2: D9 乱按 60s 级给方向话 stair_hint_a(看门狗长嘴)');
|
||||
assert(seg.has('voice/tut_skip'), 'E0-2: 接管播 tut_skip(已跳过教学 → 探索态由导航链接管)');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ---- E. E1-2 金币档真话(上滑 + SETTLE + =0 保留空手)+ E1-1 锁格到达即报 ----
|
||||
{
|
||||
storageMap.clear();
|
||||
const { game, audio } = newGame({ seed: 11 });
|
||||
game.start();
|
||||
await tick(400);
|
||||
g(game, 'tap');
|
||||
await tick(6000);
|
||||
g(game, 'down');
|
||||
await tick(2000);
|
||||
game._mobStep = () => {};
|
||||
game.meta.gold = 13; // 钩子:0 < 金 < 50(教学拾取后的真实档位)
|
||||
let mark = audio.log.length;
|
||||
g(game, 'up');
|
||||
await tick(6000);
|
||||
let p = plays(audio, mark);
|
||||
assert(p.has('voice/gold_some') && !p.has('voice/st_gold_1'),
|
||||
'E1-2: 上滑金币档 0<金<50 播 gold_some(带回来一点,不多;不再谎报「口袋空空」)');
|
||||
// E1-1 锁路径:窟主未清的楼梯格,到达即报铁器 + 锁句(死亡前做,run 仍在)
|
||||
const seed13 = game.run.seed;
|
||||
game._floor = game._generateFloor(seed13, 3); // 测试钩子:L3(窟主守楼梯)
|
||||
game.run.floor = 3;
|
||||
const st3 = game._floor.stairs;
|
||||
game._onStairs = false;
|
||||
game._stairsSpokenFloor = 0;
|
||||
const e0 = audio.log.length;
|
||||
game._onStairCell(st3.x, st3.y);
|
||||
await tick(300); // echo_1 即刻、mat_stair = 到达 +120ms 材质尾音
|
||||
{
|
||||
const seg = plays(audio, e0);
|
||||
assert(seg.has('sfx/echo_1') && seg.has('sfx/mat_stair'),
|
||||
'E1-1: 踏上(被锁的)楼梯格自动播贴身铁器回声(echo_1 + mat_stair)');
|
||||
assert(game._onStairs === true, 'E1-1: 到达置位 _onStairs(tap 下潜逻辑不受影响)');
|
||||
}
|
||||
assert(plays(audio, e0).has('voice/evt_stairs_lock'), 'E1-1: 窟主未清 → 到达即报铁器 + evt_stairs_lock');
|
||||
// 还原 L1 后死于窟鼠:SETTLE band1 同步 gold_some
|
||||
game._floor = game._generateFloor(seed13, 1);
|
||||
game.run.floor = 1;
|
||||
game.run.hp = 1;
|
||||
game._encounter({ type: 'rat', x: game.run.pos.x, y: game.run.pos.y, hp: 6, maxHp: 6 });
|
||||
await tick(2500);
|
||||
mark = audio.log.length;
|
||||
g(game, 'tap'); // 挥击 → 敌前摇 → 反一刀致命
|
||||
await tick(2200);
|
||||
assert(game.state === 'SETTLE', '场景13E: 死亡进结算');
|
||||
await tick(9000);
|
||||
p = plays(audio, mark);
|
||||
assert(p.orderOk('voice/die_intro', 'voice/die_cause_1', 'voice/st_floor_1', 'voice/gold_some'),
|
||||
'E1-2: SETTLE band1(0<金<50)同步播 gold_some(真话:这趟带回了一点)');
|
||||
// =0 保留空手措辞(SETTLE 上滑重听元进度段走 _titleUpChain 同一出口)
|
||||
game.meta.gold = 0;
|
||||
g(game, 'up');
|
||||
await tick(4000);
|
||||
assert(plays(audio, mark).has('voice/meta_gold_1'),
|
||||
'E1-2: 金=0 保留 meta_gold_1 空手措辞(band0 口径不变)');
|
||||
game.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================ 资产引用校验 ================================
|
||||
|
||||
function assetAudit() {
|
||||
@@ -1725,7 +1979,7 @@ function assetAudit() {
|
||||
const male = idsOf('male');
|
||||
assert(fem.size === male.size && [...fem].every((id) => male.has(id)),
|
||||
`资产校验: voice 双性别目录集合一致(female ${fem.size} = male ${male.size})`);
|
||||
assert(fem.size === 125, `资产校验: 台词表 125 句齐全(实际 ${fem.size})`);
|
||||
assert(fem.size === 127, `资产校验: 台词表 127 句齐全(125 + R3 gold_some/tut_flee_hold,实际 ${fem.size})`);
|
||||
|
||||
// 3) game.js 静态引用 id 全量展开校验(模板 id 按数据表展开)
|
||||
const src = fs.readFileSync(path.join(DUNGEON_DIR, 'game.js'), 'utf8');
|
||||
@@ -1790,6 +2044,7 @@ try {
|
||||
await scenario10();
|
||||
await scenario11();
|
||||
await scenario12();
|
||||
await scenario13();
|
||||
} catch (e) {
|
||||
failures.push(`未捕获异常: ${e.stack}`);
|
||||
}
|
||||
|
||||
@@ -612,6 +612,7 @@
|
||||
"tut_parry_miss": "没挡住也别怕,它伤不到你。",
|
||||
"tut_attack": "现在单击,挥拳打它。",
|
||||
"tut_kill": "打中了,就是这样。",
|
||||
"tut_flee_hold": "想逃跑,按住别松手。",
|
||||
"tut_stairs": "铁器的回声,就是下潜的楼梯。",
|
||||
"tut_stairs_on": "楼梯就在脚下。单击,下潜。",
|
||||
"tut_done": "教学完了。地窟很深,小心走。",
|
||||
@@ -640,6 +641,7 @@
|
||||
"st_gold_2": "有些积蓄。",
|
||||
"st_gold_3": "收获可观。",
|
||||
"st_gold_4": "腰包鼓鼓。",
|
||||
"gold_some": "带回来一点,不多。",
|
||||
"st_face_e": "你面朝东。",
|
||||
"st_face_s": "你面朝南。",
|
||||
"st_face_w": "你面朝西。",
|
||||
@@ -649,7 +651,7 @@
|
||||
"st_threat_right": "右边有脚步声。",
|
||||
"st_threat_both": "两边都有动静。",
|
||||
"st_best_1": "你还没到过第三层。",
|
||||
"st_best_2": "你到过中层。",
|
||||
"st_best_2": "你最远到过中层。",
|
||||
"st_best_3": "你到过最深层。",
|
||||
"evt_coin_1": "捡到几枚金币。",
|
||||
"evt_coin_2": "捡到一小把金币。",
|
||||
|
||||
+96
-15
@@ -34,6 +34,16 @@
|
||||
* - F4 断点续玩恢复后的首句播完才武装跳句(_resumeGuard → _skipLockId);
|
||||
* - F5 链末句跳过保护(等待/过场/抉择提示前的末句单击不可跳)。
|
||||
*
|
||||
* R3 打磨(research/new8/radio/round2/synthesis.md G1-G6):
|
||||
* - G1 帮助链去重:同一等待点第 2 次上滑起 sys_help 口令换「纯音频标记」
|
||||
* (beat 轻震 + nudge earcon,不加新台词方案),状态句照播;
|
||||
* - G2 rep_low 整句播报处(幕间跨档 + 各态上滑复听)一律附 warning 震;
|
||||
* - G3 k1_a/k1_b(糖糖 NPC 平铺组)male 设置下经引擎「性别目录→平铺」回退链
|
||||
* 播出,非静默——确认 + 断言 + 文档注记(设计即单音色,不补双性别资产);
|
||||
* - G4 不可跳句(p* 首播 / F5 尾句 / F4 锁)上的空点单击补 beat 轻震标记;
|
||||
* - G5「首播必完整、复播可即掐」升为显式规则(15-radio.md R3 节)+ 断言;
|
||||
* - G6 上滑状态链重排:「当前通号 → 口碑 → 帮助」(状态在前、帮助垫后)。
|
||||
*
|
||||
* 确定性:铃声为无缝循环垫(无定时器重触发),测试与转写可复现。
|
||||
*/
|
||||
import { Game } from '../engine/game.js';
|
||||
@@ -281,6 +291,7 @@ export class RadioGame extends Game {
|
||||
this.sysSkipShown = false; // sys_skip 开场每实例一次(storyline skip_hint 先例)
|
||||
this.saved = null; // ASK 态暂存的存档
|
||||
this._menuQueue = []; // 菜单项报名队列(游戏侧排队,不截断当前报名)
|
||||
this._helpSeen = new Set(); // G1:已全量播过 sys_help 口令的等待点(实例级,第 2 次起纯音频标记)
|
||||
|
||||
// F4 断点续玩跳句锁:_resume 置位,恢复链首句起播时落为该句 id,播完即清
|
||||
//(首句播完才武装跳句——ASK「单击=确认」与「单击=跳句」的语义陷阱,R2 F4)
|
||||
@@ -391,10 +402,13 @@ export class RadioGame extends Game {
|
||||
});
|
||||
break;
|
||||
case 'up': {
|
||||
// 状态播报(第几通 + 口碑档),留在 RING
|
||||
// 状态播报(第几通 + 口碑档),留在 RING——本就「状态在前」且无帮助句
|
||||
//(§2.3 RING 行),G6 重排天然满足;G2:rep_low 附 warning 震
|
||||
this.seqToken++;
|
||||
this.audio.stopVoice();
|
||||
const ids = [PROG_VOICES[Math.max(0, this.callN - 1)], TIER_VOICES[tierOf(this.rep)]];
|
||||
const tier = TIER_VOICES[tierOf(this.rep)];
|
||||
this._tierCue(tier);
|
||||
const ids = [PROG_VOICES[Math.max(0, this.callN - 1)], tier];
|
||||
this._playSeq(ids, () => {
|
||||
this.voicePlaying = false;
|
||||
if (this.phase === 'RING') this._armRingWatchdog();
|
||||
@@ -441,6 +455,11 @@ export class RadioGame extends Game {
|
||||
if (!this.promptPlaying && !this._isTailSentence()
|
||||
&& this.currentVoiceId !== this._skipLockId) {
|
||||
this.audio.skipVoice();
|
||||
} else {
|
||||
// G4(R1 P3-1 / R2 P3-4 遗留):不可跳句上的单击「点了但没选上」,
|
||||
// gesture 层确认震 [20] 游戏侧无法撤销——补一记最轻 beat [8] 形成
|
||||
// 可区分签名(20→8 连击 ≠ 真确认的单记 20),消解「像点上了」误导
|
||||
vibrate('beat');
|
||||
}
|
||||
} else if (node.prompt != null && this.choiceArmed) {
|
||||
this.armChoiceHint(); // 抉择等待态空点 = 重新挂载兜底(25s 计时重置)
|
||||
@@ -519,12 +538,17 @@ export class RadioGame extends Game {
|
||||
this._bridgeChain(this._bridgeAnnounce ? [this._bridgeAnnounce] : []);
|
||||
break;
|
||||
case 'up': {
|
||||
// 帮助 + 状态,自动链继续(垫乐喘息不被打断——链尾照常进下一通)
|
||||
// G6:状态(下一通 + 口碑档)在前、帮助垫后,自动链继续(垫乐喘息不被
|
||||
// 打断——链尾照常进下一通);G2:rep_low 附 warning 震;
|
||||
// G1:同一等待点第 2 次起口令换纯音频标记
|
||||
this.seqToken++;
|
||||
this.audio.stopVoice();
|
||||
const ids = ['voice/sys_help'];
|
||||
const ids = [];
|
||||
if (this.callN < CALLS.length) ids.push(PROG_VOICES[this.callN]); // 下一通
|
||||
ids.push(TIER_VOICES[tierOf(this.rep)]);
|
||||
const tier = TIER_VOICES[tierOf(this.rep)];
|
||||
this._tierCue(tier);
|
||||
ids.push(tier);
|
||||
this._withHelp(ids, 'B');
|
||||
this._bridgeChain(ids);
|
||||
break;
|
||||
}
|
||||
@@ -546,8 +570,12 @@ export class RadioGame extends Game {
|
||||
switch (g) {
|
||||
case 'tap':
|
||||
if (this.awaitingRestart) this.newNight();
|
||||
else if (this.voicePlaying && this.currentVoiceId !== this._skipLockId) {
|
||||
this.audio.skipVoice(); // F4:续玩恢复的首句播完才武装跳句
|
||||
else if (this.voicePlaying) {
|
||||
if (this.currentVoiceId !== this._skipLockId) {
|
||||
this.audio.skipVoice(); // F4:续玩恢复的首句播完才武装跳句
|
||||
} else {
|
||||
vibrate('beat'); // G4:续玩锁首句上的空点单击同款轻震标记
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'doubletap':
|
||||
@@ -558,12 +586,16 @@ export class RadioGame extends Game {
|
||||
this._playEndingChain();
|
||||
break;
|
||||
case 'up': {
|
||||
// 帮助 + 状态(结局主句=结局名播报 + 口碑档整句,§2.3「结局名+口碑」;
|
||||
// storyline P3-2 先例),播完回结算态
|
||||
// 状态(结局主句=结局名播报 + 口碑档整句,§2.3「结局名+口碑」;
|
||||
// storyline P3-2 先例)在前 + 帮助垫后(G6),G2:rep_low 附 warning 震,
|
||||
// G1:同一等待点第 2 次起口令换纯音频标记;播完回结算态
|
||||
this.seqToken++;
|
||||
this.audio.stopVoice();
|
||||
const def = ENDINGS[this.endingId] || ENDINGS.e1;
|
||||
this._playSeq(['voice/sys_help', def.voices[0], TIER_VOICES[tierOf(this.rep)]], () => {
|
||||
const tier = TIER_VOICES[tierOf(this.rep)];
|
||||
this._tierCue(tier);
|
||||
const ids = this._withHelp([def.voices[0], tier], `E:${this.endingId}`);
|
||||
this._playSeq(ids, () => {
|
||||
this.voicePlaying = false;
|
||||
if (this.phase === 'ENDING') {
|
||||
this.awaitingRestart = true;
|
||||
@@ -605,11 +637,15 @@ export class RadioGame extends Game {
|
||||
this._execMenuItem(MENU_ITEMS[this.menuIdx].id); // 双击确认执行
|
||||
break;
|
||||
case 'up': {
|
||||
// 帮助 + 菜单内设置提示 + 复述当前项(清空报名队列:帮助链顶掉一切)
|
||||
// 帮助 + 菜单内设置提示 + 复述当前项(清空报名队列:帮助链顶掉一切)。
|
||||
// MENU 链无通号/口碑状态句,G6 重排不适用(帮助保持在前);G1 适用:
|
||||
// 同一菜单等待点第 2 次起口令换纯音频标记,设置提示与当前项照播
|
||||
this._menuQueue = [];
|
||||
this.seqToken++;
|
||||
this.audio.stopVoice();
|
||||
this._playSeq(['voice/sys_help', 'voice/sys_settings', MENU_ITEMS[this.menuIdx].voice], () => {
|
||||
const ids = this._withHelp([], 'M');
|
||||
ids.push('voice/sys_settings', MENU_ITEMS[this.menuIdx].voice);
|
||||
this._playSeq(ids, () => {
|
||||
this.voicePlaying = false;
|
||||
});
|
||||
break;
|
||||
@@ -1113,15 +1149,60 @@ export class RadioGame extends Game {
|
||||
|
||||
// ---------------------------------------------------------------- 帮助 / 复述
|
||||
|
||||
/** 上滑:帮助 + 状态(第几通 + 口碑档整句),随后重播当前节点(局面复述)。 */
|
||||
/**
|
||||
* G2(R1 P3-3 遗留):rep_low 整句播报附 warning 震——「还没立起来」出口的
|
||||
* 同时手腕有感。原实现只在 BRIDGE 跨档播报时震,各态上滑复听不震,
|
||||
* TIER_VOICES 注释与行为不符(live 局 A t=99.6-102.0 RING 上滑复现)。
|
||||
*/
|
||||
_tierCue(tierId) {
|
||||
if (tierId === TIER_VOICES.low) vibrate('warning');
|
||||
}
|
||||
|
||||
/**
|
||||
* G1 帮助链去重(R3,压力局 sys_help 口令 38 次逐字重播,违反「提示永不逐字
|
||||
* 重复」公理 §11 #9)。不加新台词方案:同一等待点第 1 次全量口播 sys_help;
|
||||
* 第 2 次起改「纯音频标记」——beat 轻震 + nudge earcon(复用统一 8 音词表,
|
||||
* 零新增),状态句照播(复述状态=合法帮助,P1 先例)。等待点键:ONAIR/INTRO
|
||||
* 按节点、BRIDGE/菜单整段、ENDING 按结局;集合实例级(不跨实例持久化,
|
||||
* sys_skip 每实例一次同款口径——重进游戏首滑仍是完整口令)。
|
||||
* @returns {boolean} true = 本次应全量口播 sys_help
|
||||
*/
|
||||
_helpSpokenOnce(waitKey) {
|
||||
if (this._helpSeen.has(waitKey)) {
|
||||
vibrate('beat'); // 轻震标记(gesture 层确认震之外的 game 层「口令省略」签名)
|
||||
if (this.guide.level() !== 'off') {
|
||||
// earcon 直用 guide 合成器(复用 nudge「轻提醒」音,零新增词表;
|
||||
// guide 无公开单发 earcon API,_startRing 直用引擎总线同款先例)
|
||||
this.guide._playEarcon('nudge');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this._helpSeen.add(waitKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** G6:状态在前、帮助垫后——把帮助句接在状态链尾(「当前通号 → 口碑 → 帮助」)。 */
|
||||
_withHelp(ids, waitKey) {
|
||||
if (this._helpSpokenOnce(waitKey)) ids.push('voice/sys_help');
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上滑:状态(第几通 + 口碑档整句)在前 + 帮助垫后(G6 重排,round2 G6/
|
||||
* P1 建议「状态放最前」),随后重播当前节点(局面复述)。
|
||||
* INTRO 开播前无通号/口碑可报,仅帮助(或标记)后重播当前段(实现取舍登记)。
|
||||
*/
|
||||
_playHelpAndResume() {
|
||||
this.seqToken++;
|
||||
this.audio.stopVoice();
|
||||
const ids = ['voice/sys_help'];
|
||||
const ids = [];
|
||||
if (this.phase === 'ONAIR' && this.callN >= 1) {
|
||||
ids.push(PROG_VOICES[this.callN - 1]);
|
||||
ids.push(TIER_VOICES[tierOf(this.rep)]);
|
||||
const tier = TIER_VOICES[tierOf(this.rep)];
|
||||
this._tierCue(tier); // G2
|
||||
ids.push(tier);
|
||||
}
|
||||
this._withHelp(ids, `S:${this.nodeId}`); // G1:同一等待点第 2 次起纯音频标记
|
||||
this._playSeq(ids, () => {
|
||||
this.voicePlaying = false;
|
||||
if (this.phase === 'ONAIR' || this.phase === 'INTRO') this.playNode(this.nodeId);
|
||||
|
||||
+191
-5
@@ -443,6 +443,9 @@ realLog('== 主路径 · 剧本 A(E1,guide=off)==');
|
||||
'voice/ep_deer_ok', 'voice/ep_kid_ok', 'voice/ep_wife_ok', 'voice/ep_han_ok']) {
|
||||
assert(voicePlays(playLog, id) === 1, `结局链播出 ${id}`);
|
||||
}
|
||||
assert(voicePlays(playLog, 'sfx/onair_sting') === 1 && voicePlays(playLog, 'sfx/line_drop') >= 1
|
||||
&& voicePlays(playLog, 'sfx/tape_static') === 1,
|
||||
'SA3 音效接线:onair_sting(开场台标)/ line_drop(幕间挂断)/ tape_static(p9 直面)各就位');
|
||||
const sd2 = saveData();
|
||||
assert(sd2 && sd2.phase === 'ENDING' && sd2.ending === 'e1' && sd2.endings.e1 === true,
|
||||
'ENDING 进入即存档,endings 收集 e1');
|
||||
@@ -635,7 +638,8 @@ realLog('== 状态播报与无效手势(guide=full)==');
|
||||
const iH = lastIndexOf(playLog, 'voice/sys_help');
|
||||
const iP2 = lastIndexOf(playLog, 'voice/prog_c2');
|
||||
const iR2 = lastIndexOf(playLog, 'voice/rep_mid');
|
||||
assert(iH < iP2 && iP2 < iR2, 'BRIDGE 上滑状态链顺序:sys_help → prog_c2(下一通)→ rep_mid');
|
||||
assert(iP2 >= 0 && iP2 < iR2 && iR2 < iH,
|
||||
'BRIDGE 上滑状态链顺序(G6):prog_c2(下一通)→ rep_mid → sys_help(状态在前、帮助垫后)');
|
||||
await advance(() => game.phase === 'RING');
|
||||
assert(game.callN === 2, 'BRIDGE 上滑后自动链继续进 RING(c2)');
|
||||
teardown(game);
|
||||
@@ -748,7 +752,7 @@ realLog('== 中断复述(guide=off,预置存档 node=k1_asko)==');
|
||||
const iH = lastIndexOf(playLog, 'voice/sys_help');
|
||||
const iP = lastIndexOf(playLog, 'voice/prog_c3');
|
||||
const iR = lastIndexOf(playLog, 'voice/rep_mid');
|
||||
assert(iH >= 0 && iH < iP && iP < iR, '上滑状态链顺序:sys_help → prog_c3 → rep_mid');
|
||||
assert(iP >= 0 && iP < iR && iR < iH, '上滑状态链顺序(G6):prog_c3 → rep_mid → sys_help');
|
||||
assert(voicePlays(playLog, 'voice/prog_c3') === 1, 'prog_c3 整句(第三通)');
|
||||
await advance(() => !game.voicePlaying);
|
||||
assert(voicePlays(playLog, 'voice/k1_asko') === 2, '状态播完重播当前节点(局面复述)');
|
||||
@@ -1128,6 +1132,189 @@ realLog('== R2 修复回归(F1 看门狗重挂 / F3 铃声垫 / F4 续玩跳
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================ R3 修复回归
|
||||
// (research/new8/radio/round2/synthesis.md G1-G6 打磨轮;断言增量登记
|
||||
// docs/design/15-radio.md 文末「R3 修复回归」小节)
|
||||
|
||||
realLog('== R3 修复回归(G1 帮助链去重 / G2 rep_low warning 震 / G3 male 回退确认 / G4 空点轻震 / G5 首播复播显式规则 / G6 状态链重排)==');
|
||||
{
|
||||
const WARN_PATTERN = JSON.stringify([30, 50, 30, 50, 30]); // warning 震型(G2)
|
||||
const BEAT_PATTERN = JSON.stringify([8]); // beat 震型(G1 标记 / G4 轻震)
|
||||
|
||||
// ---- G6+G2+G1(ONAIR):上滑状态链「prog → rep → sys_help」+ rep_low warning 震
|
||||
// + 同一等待点第 2 次起口令换纯音频标记(震 + nudge earcon),新等待点仍全量
|
||||
clearSave(); resetSettings('full');
|
||||
{
|
||||
const { audio, playLog, game } = makeRig();
|
||||
const earcons = [];
|
||||
const origEarcon = game.guide._playEarcon.bind(game.guide);
|
||||
game.guide._playEarcon = (name) => { earcons.push(name); return origEarcon(name); };
|
||||
const vib0 = vibrateLog.length;
|
||||
await audio.unlock();
|
||||
game.start(); await flush();
|
||||
await advance(() => game.phase === 'RING');
|
||||
await g(game, 'tap'); // 接听 → z1_ring_in
|
||||
await advance(() => !game.voicePlaying); // 链末等待(等待点 = S:z1_ring_in)
|
||||
await g(game, 'up'); // 该等待点第 1 次:全量口令
|
||||
await advance(() => !game.voicePlaying);
|
||||
const iP1 = lastIndexOf(playLog, 'voice/prog_c1');
|
||||
const iR1 = lastIndexOf(playLog, 'voice/rep_low');
|
||||
const iH1 = lastIndexOf(playLog, 'voice/sys_help');
|
||||
assert(iP1 >= 0 && iP1 < iR1 && iR1 < iH1,
|
||||
'G6:ONAIR 上滑状态链顺序 prog_c1 → rep_low → sys_help(状态在前、帮助垫后)');
|
||||
assert(vibrateLog.slice(vib0).some((v) => JSON.stringify(v.pattern) === WARN_PATTERN),
|
||||
'G2:ONAIR 上滑复听 rep_low(rep=0)附 warning 震');
|
||||
await advance(() => !game.voicePlaying); // 局面复述播完,回到同一链末等待
|
||||
await g(game, 'up'); // 同一等待点第 2 次:纯音频标记
|
||||
await advance(() => !game.voicePlaying);
|
||||
assert(voicePlays(playLog, 'voice/sys_help') === 1,
|
||||
'G1:同一等待点第 2 次上滑不重播 sys_help 口令(提示永不逐字重复)');
|
||||
assert(voicePlays(playLog, 'voice/prog_c1') === 2 && voicePlays(playLog, 'voice/rep_low') === 2,
|
||||
'G1:状态句照播(复述状态=合法帮助,去重只针对口令)');
|
||||
assert(vibrateLog.slice(vib0).some((v) => JSON.stringify(v.pattern) === BEAT_PATTERN),
|
||||
'G1:第 2 次帮助播 beat 轻震标记(不加新台词的纯音频方案)');
|
||||
assert(earcons.includes('nudge'),
|
||||
'G1:第 2 次帮助播 nudge earcon(复用统一 8 音词表,零新增)');
|
||||
await g(game, 'tap'); // 链末单击继续 → z1_a(新等待点)
|
||||
await advance(() => !game.voicePlaying);
|
||||
await g(game, 'up'); // 新等待点第 1 次
|
||||
await advance(() => !game.voicePlaying);
|
||||
assert(voicePlays(playLog, 'voice/sys_help') === 2,
|
||||
'G1:去重按等待点——新等待点(z1_a)首滑仍全量口令,非全局静默');
|
||||
teardown(game);
|
||||
}
|
||||
|
||||
// ---- G2(RING):上滑复听 rep_low 附 warning 震(live 局 B t=198.5/497.5 同款证据位,
|
||||
// R1 P3-3 遗留——原实现只在 BRIDGE 跨档播报时震且该分支实际不可达)
|
||||
clearSave(); resetSettings('off'); // off 档:warning 震来自游戏层,与向导档位无关
|
||||
{
|
||||
const { audio, playLog, game } = makeRig();
|
||||
const vib0 = vibrateLog.length;
|
||||
await audio.unlock();
|
||||
game.start(); await flush();
|
||||
await advance(() => game.phase === 'RING');
|
||||
await g(game, 'up'); // 状态播报:prog_c1 → rep_low(rep=0)
|
||||
await advance(() => !game.voicePlaying);
|
||||
const iP1 = lastIndexOf(playLog, 'voice/prog_c1');
|
||||
const iR1 = lastIndexOf(playLog, 'voice/rep_low');
|
||||
assert(iP1 >= 0 && iP1 < iR1, 'G2 前置:RING 上滑播 prog_c1 → rep_low(rep=0 → low 档)');
|
||||
assert(vibrateLog.slice(vib0).some((v) => JSON.stringify(v.pattern) === WARN_PATTERN),
|
||||
'G2:RING 上滑复听 rep_low 附 warning 震(R1 P3-3 遗留补齐)');
|
||||
teardown(game);
|
||||
}
|
||||
|
||||
// ---- G6+G2+G1(ENDING):上滑状态链「结局主句 → 口碑 → sys_help」+ 去重
|
||||
clearSave(); resetSettings('full');
|
||||
storageData.set(SAVE_KEY, JSON.stringify({
|
||||
schema: 1, updatedAt: new Date().toISOString(), summary: '已收播·静音 · 结局1/4',
|
||||
phase: 'ENDING', node: 'e4', call: 5, ending: 'e4',
|
||||
rep: 0, knot: false, heardArgument: false,
|
||||
bond: { zhou: 0, deer: 0, kid: 0, wife: 0, han: 0 }, endings: { e4: true }, nights: 2,
|
||||
lastCloser: null,
|
||||
}));
|
||||
{
|
||||
const { audio, playLog, game } = makeRig();
|
||||
const vib0 = vibrateLog.length;
|
||||
await audio.unlock();
|
||||
game.start(); await flush();
|
||||
await advance(() => game.phase === 'ASK' && !game.voicePlaying);
|
||||
await g(game, 'tap'); // 续玩 → 结局链重播(F4 锁只锁首句)
|
||||
await advance(() => game.awaitingRestart); // 播完回结算态
|
||||
await g(game, 'up'); // 第 1 次:e4_a → rep_low → sys_help
|
||||
await advance(() => !game.voicePlaying);
|
||||
const iE = lastIndexOf(playLog, 'voice/e4_a');
|
||||
const iR = lastIndexOf(playLog, 'voice/rep_low');
|
||||
const iH = lastIndexOf(playLog, 'voice/sys_help');
|
||||
assert(iE >= 0 && iE < iR && iR < iH,
|
||||
'G6:ENDING 上滑状态链顺序 e4_a(结局主句)→ rep_low → sys_help');
|
||||
assert(vibrateLog.slice(vib0).some((v) => JSON.stringify(v.pattern) === WARN_PATTERN),
|
||||
'G2:ENDING 上滑复听 rep_low 附 warning 震');
|
||||
const helpN = voicePlays(playLog, 'voice/sys_help');
|
||||
await g(game, 'up'); // 同一等待点(E:e4)第 2 次:纯音频标记
|
||||
await advance(() => !game.voicePlaying);
|
||||
assert(voicePlays(playLog, 'voice/sys_help') === helpN,
|
||||
'G1:ENDING 同一等待点第 2 次上滑不重播 sys_help 口令');
|
||||
teardown(game);
|
||||
}
|
||||
|
||||
// ---- G4+G5:不可跳句空点 beat 轻震(p* / F5 尾句 / F4 锁三处)+
|
||||
// 「首播必完整、复播可即掐」——F4 锁只锁首播一句,复播(局面复述)不重新武装
|
||||
clearSave(); resetSettings('off');
|
||||
storageData.set(SAVE_KEY, JSON.stringify({
|
||||
schema: 1, updatedAt: new Date().toISOString(), summary: '第4通·争吵的夫妻 · 口碑+9 · 结局0/4',
|
||||
phase: 'ONAIR', node: 'w1_say', call: 4, ending: null,
|
||||
rep: 9, knot: false, heardArgument: true,
|
||||
bond: { zhou: 1, deer: 1, kid: 1, wife: 0, han: 0 }, endings: {}, nights: 1, lastCloser: null,
|
||||
}));
|
||||
{
|
||||
const { audio, playLog, game } = makeRig();
|
||||
const vib0 = vibrateLog.length;
|
||||
await audio.unlock();
|
||||
game.start(); await flush();
|
||||
await advance(() => game.phase === 'ASK' && !game.voicePlaying);
|
||||
await g(game, 'tap'); // 恢复 w1_say 组(首句受 F4 锁)
|
||||
assert(game.currentVoiceId === 'voice/w1_say', 'G4 前置:断点续玩恢复,首句 w1_say 在播');
|
||||
await g(game, 'tap'); // 锁内单击:不跳(G5 ASK 恢复首句例外)
|
||||
assert(game.currentVoiceId === 'voice/w1_say',
|
||||
'G5:ASK 恢复链首句例外——锁内单击不跳(首播必完整,F4)');
|
||||
assert(vibrateLog.slice(vib0).filter((v) => JSON.stringify(v.pattern) === BEAT_PATTERN).length === 1,
|
||||
'G4:F4 锁内空点单击播 beat 轻震(可区分于真确认的 [20])');
|
||||
await advance(() => game.currentVoiceId === 'voice/w1_sayo'); // 首句播完,锁释放
|
||||
await g(game, 'down'); // 呼出菜单
|
||||
await advance(() => !game.voicePlaying);
|
||||
await g(game, 'down'); // 关菜单 → 局面复述(重播 w1_say 组 = 复播)
|
||||
assert(game.currentVoiceId === 'voice/w1_say', 'G5 前置:关菜单局面复述回放首句 w1_say');
|
||||
await g(game, 'tap'); // 复播的首句单击 → 可跳(锁不随复播重新武装)
|
||||
await flush();
|
||||
assert(game.currentVoiceId === 'voice/w1_sayo',
|
||||
'G5:复播可即掐——F4 锁只锁首播一句,复播(局面复述)首句单击照常跳过');
|
||||
await advance(() => game.currentVoiceId === 'voice/w1_saye');
|
||||
await g(game, 'tap'); // F5 链末句(交接 p7 前)单击不可跳
|
||||
assert(game.currentVoiceId === 'voice/w1_saye' && game.voicePlaying,
|
||||
'G5:首播必完整——链末关键句(交接抉择提示前)单击不可跳(F5)');
|
||||
assert(vibrateLog.slice(vib0).filter((v) => JSON.stringify(v.pattern) === BEAT_PATTERN).length === 2,
|
||||
'G4:F5 尾句空点单击播 beat 轻震(R2 P3-4「p9 后空点」证据位)');
|
||||
await advance(() => !game.voicePlaying); // 尾句完整播完 → 链末等待
|
||||
await g(game, 'tap'); // 链末单击继续 → p7 提示句起播
|
||||
const vibP = vibrateLog.length;
|
||||
await g(game, 'tap'); // p* 播放中单击不可跳(PROMPT_RE 门)
|
||||
assert(game.currentVoiceId === 'voice/p7' && game.promptPlaying,
|
||||
'G5:首播必完整——p* 首播单击不跳(PROMPT_RE 门)');
|
||||
assert(vibrateLog.slice(vibP).some((v) => JSON.stringify(v.pattern) === BEAT_PATTERN),
|
||||
'G4:p* 不可跳句空点单击播 beat 轻震(R1 P3-1 证据位)');
|
||||
teardown(game);
|
||||
}
|
||||
|
||||
// ---- G3:male 设置下 k1_a/k1_b(糖糖 NPC 平铺组)回退行为——性别目录 404 后
|
||||
// 平铺版照常播出(非静默),回退链工作正常 → 确认 + 断言 + 文档注记
|
||||
clearSave(); resetSettings('off');
|
||||
settings.set({ voice: 'male' });
|
||||
storageData.set(SAVE_KEY, JSON.stringify({
|
||||
schema: 1, updatedAt: new Date().toISOString(), summary: '第3通·失眠的孩子 · 口碑+2 · 结局0/4',
|
||||
phase: 'ONAIR', node: 'k1_in', call: 3, ending: null,
|
||||
rep: 2, knot: false, heardArgument: false,
|
||||
bond: { zhou: 1, deer: 1, kid: 0, wife: 0, han: 0 }, endings: {}, nights: 3, lastCloser: null,
|
||||
}));
|
||||
{
|
||||
const { audio, playLog, game } = makeRig();
|
||||
const errBefore = consoleErrs.length;
|
||||
await audio.unlock();
|
||||
game.start(); await flush();
|
||||
await advance(() => game.phase === 'ASK' && !game.voicePlaying);
|
||||
await g(game, 'tap'); // 恢复 → k1_in(链末等待)→ 单击续进 k1_a → k1_b
|
||||
await tapUntil(game, () => game.currentVoiceId === 'voice/k1_b', 6);
|
||||
await advance(() => !game.voicePlaying);
|
||||
assert(urlHits('audio/voice/male/k1_a') >= 1 && urlHits('audio/voice/male/k1_b') >= 1,
|
||||
'G3 前置:male 设置先尝试性别目录 male/k1_a、male/k1_b(无资产属设计——NPC 平铺组不做双性别)');
|
||||
assert(voicePlays(playLog, 'voice/k1_a') === 1 && voicePlays(playLog, 'voice/k1_b') === 1,
|
||||
'G3:male/k1_a、k1_b 404 后回退平铺版播出(非静默,引擎「性别目录→平铺」回退链正常)');
|
||||
assert(!consoleErrs.slice(errBefore).some((e) => e.includes('k1_a') || e.includes('k1_b')),
|
||||
'G3:回退命中平铺版 → 零「资产缺失」console.error(若真静默则修,实测确认无需修)');
|
||||
settings.set({ voice: 'female' });
|
||||
teardown(game);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================ 静态审计
|
||||
// (数字规范:分档整句字面量、无运行时 id 拼接;存档 summary 格式;资产盘点)
|
||||
|
||||
@@ -1147,9 +1334,8 @@ realLog('== 静态审计 ==');
|
||||
const ids = [...new Set([...src.matchAll(/'((?:voice|sfx|bgm)\/[A-Za-z0-9_.-]+)'/g)].map((m) => m[1]))];
|
||||
assert(ids.length > 0, `game.js 提取到 ${ids.length} 个资产 id`);
|
||||
const both = (rel) => ['.ogg', '.m4a'].every((ext) => fs.existsSync(path.join(AUDIO_DIR, rel + ext)));
|
||||
// Stable Audio 3 批次缺口(gen/gen_sfx.py 头注:HF token 未配置本轮跳过,
|
||||
// R2 F3 已移除 phone_ring(程序合成铃声循环垫落盘);剩 11 件待补;
|
||||
// 缺音效走引擎 console.error 静默降级,不阻塞玩法(§6.1 降级方案)。
|
||||
// Stable Audio 3 批次已全部补产落地(2026-09-02,research/new8/batch1-assets-report.md
|
||||
// §8:含 R2 F3 phone_ring,共 12 件);保留清单作为守卫——若未来出现新缺失必须仍属该组。
|
||||
const STABLE_AUDIO_PENDING = new Set(['sfx/onair_sting', 'sfx/line_connect',
|
||||
'sfx/line_drop', 'sfx/amb_rain_city', 'sfx/amb_station', 'sfx/amb_kid_room', 'sfx/arg_muffled',
|
||||
'sfx/amb_street_rain', 'sfx/amb_cab', 'sfx/brake_screech', 'sfx/tape_static']);
|
||||
|
||||
Reference in New Issue
Block a user