fix(escape): 暗室状态引导方案落地(25号策划文档 B1-B8 → F1-F9 实施)
策划轮:25-escape-map-flow.md as-built地图/玩家流程/信息账本+盲区清单(S1-S7)+方案B1-B8 实施(玩法零改动,只加状态引导层): - F1 撞墙方位句「左边是墙」(wall_dir_*×4,同向10s限频) - F2 目标句并入方位「铁柜,在右面的房间」(gd_*_dir×3) - F3 无进展150s活跃计时器+gd_prog_1..3进度重述(只重述不泄题,专治活跃迷路玩家——修卡关计时从「无进展」退化为「无操作」的既定偏差) - F4 双击兜底直通L2降级L1(不再白送答案) - F5 空房首访描述(4空房可区分) - F7 busy窗口手势缓存补判(原静默吞手势) - F8 结算链单击守卫(time_band/again完整到达) - F9 跳过引导补播目标句 - F6 空房方位特征句按25号裁定留档后续轮 新增语音10句×2性别(flock串行QC无离群,ASR逐字正确) 验证:escape playtest 235/235(+85新断言)+ guide 132/132 + 终检全绿 + 14游戏回归零回退 live复跑10.4分钟通关:零截断,S1-S7盲区逐条核销 档案 research/escape-state/round1-2;01号文档追加修订记录R1
This commit is contained in:
@@ -103,3 +103,46 @@ start → GUIDE(可下滑跳过)→ PLAY(自由探索 + 三级提示计时
|
||||
```
|
||||
|
||||
PLAY 阶段手势:四向滑=移动 / 单击=重播环境音+检查 / 双击=使用物品(无目标→背包+L2 明示)。ENDING:单击=重开,下滑=菜单(回大厅)。
|
||||
|
||||
---
|
||||
|
||||
## 修订记录(追加不改旧文,编号自 R1 起)
|
||||
|
||||
### R1 · escape-state round2 状态引导改进(2026-09-15,方案见 25 号文档 §4.1)
|
||||
|
||||
按 25 号文档 §4.3 实施清单 F1-F9 落地(F6/B5b 按方案"可分期"留档):
|
||||
|
||||
1. **撞墙报方位(B1/F1)**:§2.1 G2 表格的撞墙反馈在 PLAY 阶段升级为
|
||||
`wall` 播完接播陈述式方位句 `wall_dir_<dir>`「左边是墙。」等 4 句
|
||||
(同向 10s 限频、被打断作废)。这是对 round1-live"回退教学腔方位句"的
|
||||
部分再修订——回退掉的是措辞,方位信息以世界内陈述句回归。
|
||||
2. **目标句带目标名(B2/F2)**:三处进展链尾方位句由「右面的房间。」升级为
|
||||
"目标名+方位"一体句(`gd_cabinet_dir`/`gd_box_dir`/`gd_gate_dir`),
|
||||
原 `gd_room_*` 保留作异常路径回落。
|
||||
3. **无进展计时器回收(B3/F3)**:§3.1"以上一次进展事件起算"的原始意图以
|
||||
**平行通道**部分回收——无进展 150s 且期间 ≥5 次有效手势(活跃迷路)播
|
||||
不泄题的进度重述 `gd_prog_1/2/3`(每进展段限 1 次);现行"无操作 60/120/
|
||||
180s"三级提示骨架不动(round1-live 修订继续有效)。
|
||||
4. **§3.2 末条修订(B4/F4)**:「主动求提示保留:先播背包,再播 L2 级明示」
|
||||
修订为「先播背包/use_fail,再播 **L1 级意象暗示**」——live 两次实录没卡关
|
||||
的玩家被白送 L2 答案(泄漏 > 帮助),L2/L3 仍锁在计时器里(修订留痕于此,
|
||||
25 号文档 §4.1 B4 有完整证据链)。
|
||||
5. **空房首访描述(B5a/F5)**:§4 房间声音去重补一条——空房首访一次性补播
|
||||
现有 `empty_*`(不算进展事件;B5b 含方位特征的改词重录留后续轮)。
|
||||
6. **引导 busy 手势缓存(B6/F7)**:§2.1 补——步骤推进语音播放中(busy)
|
||||
的首个非跳过分手势被缓存,解锁后按新步骤补判(合法=作答,不合法=答错
|
||||
路径;缓存手势不触发下滑跳过),符合 00 文档 §5.4"做了手势 3 秒内必须有
|
||||
反馈"。
|
||||
7. **结算链单击守卫(B7/F8)**:§7 流程图 ENDING 补——结算链播完前单击不
|
||||
立即重开(`_settleBusy`,链完/30s 兜底解除),保障用时播报与操作指引的
|
||||
完整到达权。
|
||||
8. **目标句全局可达(B8/F9)**:§2.1"跳过引导直达 PLAY"修订——跳过确认句
|
||||
后与 REOPEN 直进路径都补播一次 `g7_goal`(任何路径进 PLAY 都至少听过
|
||||
一次目标句;二周目可单击跳过)。
|
||||
|
||||
新断言登记(13 号文档不动):escape playtest 场景 G-N(B1/B2/B3/B4/B5a/
|
||||
B6/B7/B8 各场景,含边界:B3 进展复位、B4 降级后 L2 仍可达、B6 缓存按序
|
||||
补判、B7 结算链完整到达)共 +85 条至 235 全绿;guide.test ⑩c 换线 +
|
||||
⑩d B6 full 档共 132 全绿;逐条勾账与既有断言变更登记见 25 号文档
|
||||
「阶段四 · 实施勾账」。新语音 10 句台词表见 01-escape-voice-ids.md
|
||||
「escape-state round2 新增主表句」。
|
||||
|
||||
@@ -53,3 +53,26 @@ web/engine/gesture.js inputMode())时,引擎 voice 候选链前置加载
|
||||
| `again` | 按空格,再来一次。按下方向键,打开菜单。 |
|
||||
| `help_ops` | 方向键,在房间之间移动。按空格,检查房间,或者重听房间的声音。按回车,使用物品,或者查看背包。 |
|
||||
| `skip_hint` | 按空格可跳过旁白。 |
|
||||
|
||||
---
|
||||
|
||||
## escape-state round2 新增主表句(10 句,25 号文档 §4.1 方案 B1/B2/B3)
|
||||
|
||||
> 状态引导改进方案([25-escape-map-flow.md](25-escape-map-flow.md) §4.1 B1/B2/B3、§4.3
|
||||
> 实施清单 F1/F2/F3)的新增语音,台词与 25 号文档草案**逐字一致**。全部不含操作词,
|
||||
> 无键盘变体(变体只覆盖含操作词的句子,id 集合 ⊆ 主表的既有约定不变)。
|
||||
> 管线:`gen_voice_dual.py --game escape --only <ids>` → `--check` → `--convert` →
|
||||
> `check_all_assets.py` 终检。
|
||||
|
||||
| id | 台词全文 | 方案 |
|
||||
|---|---|---|
|
||||
| `wall_dir_l` | 左边是墙。 | B1 撞墙方位(陈述式) |
|
||||
| `wall_dir_r` | 右边是墙。 | B1 |
|
||||
| `wall_dir_u` | 上边是墙。 | B1 |
|
||||
| `wall_dir_d` | 下边是墙。 | B1 |
|
||||
| `gd_cabinet_dir` | 铁柜,在右面的房间。 | B2 目标名+方位一体句(found_key 链尾) |
|
||||
| `gd_box_dir` | 电箱,在左面的房间。 | B2(gd_next_fuse 链尾) |
|
||||
| `gd_gate_dir` | 大门,在右面的房间。 | B2(fix_box 链尾) |
|
||||
| `gd_prog_1` | 钥匙已经到手。找到能用它的锁。 | B3 无进展进度重述(stage=cabinet) |
|
||||
| `gd_prog_2` | 铁柜已经打开。电还没有通。 | B3(stage=box) |
|
||||
| `gd_prog_3` | 电已经通了。去找那扇大门。 | B3(stage=gate) |
|
||||
|
||||
@@ -0,0 +1,645 @@
|
||||
# 25 · 《暗室》地图与玩家流程文档 + 状态引导改进方案
|
||||
|
||||
> **as-built 声明**:本文档为「以代码为准」的现行实现文档化,权威来源是
|
||||
> `web/escape/game.js`(837 行,R2 重设计 + round1~round4 历次 live 修复),
|
||||
> 与 01 号设计文档(01-escape-redesign.md)对账,**凡不一致处以代码为准**,
|
||||
> 差异全录于 §1.5。语音 id 全集与全文以 `tools/gen_voice_dual.py` 的
|
||||
> `ESCAPE_LINES`(80 句)为准。
|
||||
>
|
||||
> 阶段三「状态引导改进方案」的取证材料在 `research/escape-state/round1/`
|
||||
> (mock 转写 + live 真机一局 + P1/P3 人设评审)。方案只产出设计,未实施。
|
||||
>
|
||||
> 轮次:escape-state round1(2026-09-14)。靶问题(用户真机反馈):
|
||||
> **玩家不知道自己的状态**——不知道自己在哪、不知道目标、不知道进度。
|
||||
|
||||
---
|
||||
|
||||
# 阶段一 · as-built 文档化
|
||||
|
||||
## 1. 地图章
|
||||
|
||||
### 1.1 房间总图(3x3,坐标 x 0西→2东,y 0北→2南)
|
||||
|
||||
```
|
||||
x=0(西) x=1 x=2(东)
|
||||
y=0 ┌───────────┬───────────┬───────────┐
|
||||
(北) │ (0,0) │ (1,0) │ (2,0) │
|
||||
│ 电箱房 │ 空房·风 │ 空房·嗡鸣 │
|
||||
│ amb_power │ amb_wind │ amb_hum │
|
||||
├───────────┼───────────┼───────────┤
|
||||
y=1 │ (0,1) │ (1,1) │ (2,1) │
|
||||
│ 空房·嗡鸣 │ 起点 │ 铁柜房 │
|
||||
│ amb_hum │ amb_drip │ amb_cabinet│
|
||||
├───────────┼───────────┼───────────┤
|
||||
y=2 │ (0,2) │ (1,2) │ (2,2) │
|
||||
(南) │ 储物间 │ 空房·风 │ 大门 │
|
||||
│ amb_storage│ amb_wind │ amb_gate │
|
||||
└───────────┴───────────┴───────────┘
|
||||
(通电后 amb_gate → amb_gate_live)
|
||||
```
|
||||
|
||||
- **连通关系**:全部相邻房间四向连通——`_move()` 只做 0..2 边界检查
|
||||
(game.js:394-417),内部 12 条边全部可走。**全图无锁门、无单向通道**,
|
||||
唯一"锁"是动作门(双击使用物品的前置条件),不是空间门。
|
||||
- **撞墙边界**:仅外圈 12 段墙。撞墙 = 目标坐标出界 → `sfx/wall` 闷响 +
|
||||
`error` 震 + `voice/wall`「那边是墙,换个方向。」(每次撞都播,
|
||||
game.js:397-404)。
|
||||
- **起点**:(1,1) 正中央,检查语音 `start_room`「你站在设施中央的房间里」
|
||||
——"中央"是全图**唯一一次**给出的绝对方位锚点(见 §3 盲区 S1)。
|
||||
|
||||
### 1.2 每房间资产与点位表
|
||||
|
||||
| 房间 | 坐标 | 环境音 id | 进入描述(仅首到) | 单击检查语音(状态相关) | 双击使用 |
|
||||
|---|---|---|---|---|---|
|
||||
| 电箱房 | (0,0) | `sfx/amb_power` | `room_power`「这个房间的墙上,有一只电箱。」 | 未修 `inspect_box_dead` / 已修 `box_fixed` | hasFuse → `fix_box`(修电) |
|
||||
| 空房 | (1,0) | `sfx/amb_wind` | 无 | `empty_1`「空空荡荡,只有你自己的回声。」 | 兜底 |
|
||||
| 空房 | (2,0) | `sfx/amb_hum` | 无 | `empty_3`「除了远处的水滴声,这里什么都没有。」 | 兜底 |
|
||||
| 空房 | (0,1) | `sfx/amb_hum` | 无 | `empty_2`「摸到的只有冰冷粗糙的墙壁。」 | 兜底 |
|
||||
| 起点 | (1,1) | `sfx/amb_drip` | 无 | `start_room`(中央房间+操作总览) | 兜底 |
|
||||
| 铁柜房 | (2,1) | `sfx/amb_cabinet` | `room_cabinet`「这个房间里,立着一个铁柜。」 | 未开 `inspect_cabinet_locked` / 已开 `empty_1` | hasKey → `unlock_cabinet`(得保险丝) |
|
||||
| 储物间 | (0,2) | `sfx/amb_storage` | `room_storage`「货架上堆满杂物,角落里传来水滴声。」 | 有钥匙且柜未开 → **拾取钥匙** `found_key`;否则 `empty_2` | 兜底 |
|
||||
| 空房 | (1,2) | `sfx/amb_wind` | 无 | `empty_3` | 兜底 |
|
||||
| 大门 | (2,2) | `sfx/amb_gate`(通电后 `amb_gate_live`) | `room_gate`「面前,是一扇沉重的铁门。」 | 未通电 `inspect_gate` / 已通电 `inspect_gate_ready` | powerOn → 逃脱结算 |
|
||||
|
||||
要点:
|
||||
- **环境音 6 类铺 9 房**:4 间空房只有 2 种音(wind×2、hum×2)且成对角分布
|
||||
((1,0)/(1,2) 风、(0,1)/(2,0) 嗡鸣)——**空房之间声学不可区分**(盲区 S5)。
|
||||
- **首到描述只播一次**(`visited` 集合,game.js:112,412-416);重访关键房间
|
||||
零语音,只换环境音。
|
||||
- **进房间自动播环境音**(每次移动都播,game.js:429-431),单击检查也先重播
|
||||
环境音再播描述(800ms 间隔让环境音先进耳朵,game.js:446-448)。
|
||||
- 大门通电后环境音切换 `amb_gate_live` 是**唯一**一条"谜题状态改变可听觉感知"
|
||||
的环境通道(01 号文档 §4.4 的设计意图,代码兑现)。
|
||||
|
||||
### 1.3 解谜链依赖图
|
||||
|
||||
```
|
||||
[储物间 (0,2) 单击] ──得钥匙──▶ [铁柜房 (2,1) 双击] ──得保险丝──▶
|
||||
[电箱房 (0,0) 双击] ──通电──▶ [大门 (2,2) 双击] ──▶ 逃脱结算
|
||||
hasKey=true cabinetOpen=true powerOn=true
|
||||
hasFuse=true
|
||||
```
|
||||
|
||||
- 链上 4 个动作,每个都是"在对的房间双击",前置 = 上一环的物品/状态。
|
||||
- 物品即进度:`hasKey`/`hasFuse` 为真即代表链推进到对应环;`cabinetOpen`/
|
||||
`powerOn` 为真代表该环完成。`_stage()`(game.js:538-543)按此回退链判定
|
||||
当前阶段:`key → cabinet → box → gate`。
|
||||
- **最短通关路径**(11 次移动 + 1 单击 + 3 双击,约 2-3 分钟):
|
||||
(1,1)→左(0,1)→下(0,2)【单击拾钥匙】→右(1,2)→右(2,2)→上(2,1)【双击开柜】
|
||||
→左(1,1)→左(0,1)→上(0,0)【双击修电箱】→右(1,0)→右(2,0)→下(2,2)【双击逃脱】。
|
||||
注意这条最短路径**恰好绕过所有空房**,且铁柜房/电箱房的方位句
|
||||
(H1)在这条路径上分别给出"右面的房间"(储物间→铁柜房)与
|
||||
"左面的房间"(铁柜房→电箱房)。
|
||||
|
||||
### 1.4 房间 → 谜题 → 状态映射表
|
||||
|
||||
| 阶段 `_stage()` | 判定条件 | 目标房间(L3 带路 STAGES) | L1 暗示 | L2 明示 | 进展事件(清已播级别) |
|
||||
|---|---|---|---|---|---|
|
||||
| `key` | `!hasKey && !cabinetOpen` | (0,2) 储物间 | `stuck_key_1` 铁锈味意象 | `stuck_key_2` 西南角储物间单击 | 拾钥匙、**首到储物间** |
|
||||
| `cabinet` | `hasKey` | (2,1) 铁柜房 | `stuck_cabinet_1` 钥匙在你身上 | `stuck_cabinet_2` 东边铁柜房双击 | 开柜(得保险丝) |
|
||||
| `box` | `cabinetOpen && !powerOn` | (0,0) 电箱房 | `stuck_box_1` 电流声意象 | `stuck_box_2` 西北角电箱房双击 | 修电箱 |
|
||||
| `gate` | `powerOn` | (2,2) 大门 | `stuck_gate_1` 电已通 | `stuck_gate_2` 东南角大门双击 | 逃脱 |
|
||||
|
||||
- 进展事件调 `_progressEvent()`:清空 `_stuckShown`,下段静默期从 L1 重新分级
|
||||
(game.js:578-582)。
|
||||
- 代码把**首到储物间**也算进展事件(KEY_ROOMS 含 (0,2)),01 号文档 §3.1
|
||||
只列了铁柜房/电箱房/大门——差异见 §1.5-③。
|
||||
|
||||
### 1.5 代码 vs 设计文档差异清单(以代码为准)
|
||||
|
||||
| # | 01 号设计文档 | 现行代码 | 性质 |
|
||||
|---|---|---|---|
|
||||
| ① | §3.1/§3.2 卡关计时"以上一次**进展事件**起算"(无进展 60/120/180s) | 按"**无操作时长**"计时:PLAY 阶段任何有效手势重置计时(game.js:26-31,160-164,589-612) | round1-live 修复(原机关枪式报答案+顶语音),设计意图被反向修订 |
|
||||
| ② | §2.1 G0「单击继续」+ CONFIRM 震 | intro 播完 **1.2s 无操作自动推进 G1**(game.js:205-211);G0 单击仍有效 | round2-live 修复(intro 后死寂 17~91s) |
|
||||
| ③ | §3.1 进展事件列"首到铁柜房/电箱房/大门" | 首到**储物间**同样计进展(KEY_ROOMS 四房间统一处理) | 代码超集 |
|
||||
| ④ | §2.1「引导期间任何步骤可下滑跳过」 | 仅 G0/G3/G5/G6 可下滑跳过;G1/G2/G4 下滑=作答(game.js:239-245) | 13 号文档裁定,round2-live 修复教学链断裂 |
|
||||
| ⑤ | §3.2「双击无目标兜底:先播背包,再播 L2」 | 在**关键房间**内播 `use_fail` 而非背包;非关键房才播背包(game.js:519-527) | 代码细化 |
|
||||
| ⑥ | 14 号文档 v1 裁定 5/§2:「连续撞墙 ≥2 次 → full 档卡关三级阈值提前一级」 | **未落地**:game.js 无任何撞墙连击/阈值提前逻辑(已核实无 wallStreak 类状态) | 文档先行、代码缺失,以代码为准(=无此功能) |
|
||||
| ⑦ | §2.1 G2 反馈含"未撞墙:脚步 + SWIPE_OK"分支 | 引导期位置固定,**滑动即撞墙反馈**(每滑必 wall 闷响+error 震+wall 语音),无"未撞墙"分支(game.js:264-272) | 设计草案分支不存在 |
|
||||
| ⑧ | §2.1 G6 反馈「兜底播报背包 + CONFIRM 震」 | G6 双击答对播 `inv_key`+`g6_done`+`g7_goal` 链(无单独 confirm 震,靠引擎双击内置 confirm) | 等价 |
|
||||
| ⑨ | (01 号文档无 REOPEN 相) | 存在 REOPEN 二周目阶段:上滑重听引导/单击直接开始(game.js:54-55,143-151) | 01 号文档 §2.1 末段提到过一次,代码为完整实现 |
|
||||
| ⑩ | §3.2 L1 附"语音提示前播'需要帮助吗?'" | `stuck_ask` 仅 L1 前插播,L2/L3 无(game.js:607-611) | 一致(此处列出防误扩) |
|
||||
| ⑪ | 01 号文档 §4.2「环境音扩到 6 种」 | 实际 8 个环境音资产 6 类(含 `amb_gate_live` 通电变体) | 一致(超集) |
|
||||
|
||||
另注:14 号文档 round2 F2.3「撞墙接播 guide_blunt_<dir> 方位句」曾被落地、
|
||||
后被 round1-live **回退**为只播 `voice/wall` 极简句(game.js:400-403 注释),
|
||||
教学腔方位句仅限引导期 G3 纠错路径——这条历史是阶段三 B1 方案的前车之鉴
|
||||
(方位信息要给,但措辞不能再走教学腔)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 玩家流程章
|
||||
|
||||
### 2.1 全局状态机
|
||||
|
||||
```
|
||||
┌────────────── 首次开局 ──────────────┐
|
||||
▼ │
|
||||
start ─▶ REOPEN(二周目才有:上滑重听引导/单击直接开始)
|
||||
│ 首局自动
|
||||
▼
|
||||
GUIDE(脚本化教学,玩家手势推进,G0→G7)
|
||||
│ G6 双击答对 → g7_goal 链播完 _finishGuide
|
||||
│ G0/G3/G5/G6 下滑跳过 → guide_skip → PLAY
|
||||
▼
|
||||
PLAY(自由探索 + 卡关三级提示计时器;谜题链阶段 key→cabinet→box→gate)
|
||||
│ 大门双击(powerOn)→ _escape()
|
||||
▼
|
||||
ENDING(结算链 escape→time_band→again;单击重开 / 下滑菜单)
|
||||
│ 下滑
|
||||
▼
|
||||
MENU(模态:单击循环选项 / 双击执行 / 上滑帮助 / 下滑关闭)
|
||||
```
|
||||
|
||||
- **会话令牌** `_session`:重开/跳过/回大厅时递增,使旧计时器与语音链回调
|
||||
全部失效(game.js:98,826-831)。
|
||||
- **语音纪律基础设施**:待播队列 `_pendingVoice`(kind=`stuck` 卡关提示 /
|
||||
`describe` 补发检查),只在当前语音自然播完后播出,**绝不顶句**;待播期间
|
||||
玩家任何操作即作废卡关提示(未播级别不计入已播,game.js:125,783-810)。
|
||||
- 单击跳句(12 号文档):可跳句播放中单击 = `skipVoice()` 跳过本句 + 补发检查
|
||||
(环境音即时重播、描述进待播队列);不可跳句(引导 G0-G7、关键获得链、
|
||||
L3 带路)单击 = 忽略(game.js:377-388,445)。
|
||||
|
||||
### 2.2 引导子状态 G0-G7(GUIDE 阶段)
|
||||
|
||||
| 步 | 语音(全文见 §3 账本) | 等待手势 | 答对反馈 | 答错(3 次给 blunt+warning 震) |
|
||||
|---|---|---|---|---|
|
||||
| G0 | `g0_intro`(剧情) | 单击;**1.2s 无操作自动推进** | g1_move+skip_hint | intro 播放中滑动=忽略;空档滑动=`guide_offpath`「先跟我走。」 |
|
||||
| G1 | `g1_move`「朝任意方向滑一下」 | 任意滑动(下滑也算作答,不可跳过) | step + `g1_done` + `g2_wall` | `guide_wrong_gesture` |
|
||||
| G2 | `g2_wall`「再滑两下,试试碰碰墙」 | 滑动×2(每滑必播 wall 闷响+error 震+`wall`) | 满 2 次 → `wall`+`g3_left` | 非滑动 = wrong_gesture |
|
||||
| G3 | `g3_left`「向左滑。」 | 左滑(→(0,1)) | step + `g4_down` | 其他滑动 = `guide_wrong_left` |
|
||||
| G4 | `g4_down`「再向下滑。」 | 下滑(→(0,2) 储物间) | step + `amb_storage` + `g5_inspect` | 其他滑动 = `guide_wrong_down` |
|
||||
| G5 | `g5_inspect`「单击检查」 | 单击 → **拾钥匙** | pickup + `g5_key` | 非单击 = wrong_gesture |
|
||||
| G6 | `g6_doubletap`「双击试试」 | 双击 | `inv_key`+`g6_done`+`g7_goal` | 非双击 = wrong_gesture |
|
||||
| G7 | `g7_goal`「找到能用这把钥匙打开的东西…」 | (无,链播完自动进 PLAY) | — | 手势忽略 |
|
||||
|
||||
- 引导期位置是脚本写死的:(1,1)→(0,1)→(0,2),与真实地图一致;G2 的"撞墙"
|
||||
是伪撞墙(位置并未移动)。
|
||||
- `_guideBusy` 推进语音播放中**忽略一切非跳过分手势**——这是阶段四 live 局
|
||||
抓到的事故点(盲区 S6):G3 答案在 busy 窗口内被吞,玩家紧接着的下滑被
|
||||
当成"跳过引导"。
|
||||
|
||||
### 2.3 手势语义总表(逐阶段)
|
||||
|
||||
| 手势 | REOPEN | GUIDE | PLAY | ENDING | MENU |
|
||||
|---|---|---|---|---|---|
|
||||
| 上滑 | 重听引导 | 下滑跳过仅限 G0/G3/G5/G6,**上滑无跳过语义**;其余步上滑=答错/忽略 | **移动(dy=-1)** | 忽略 | 播 `help_ops` 操作说明 |
|
||||
| 下滑 | 忽略 | G0/G3/G5/G6=跳过引导;G1/G2/G4=作答 | **移动(dy=+1)** | 打开菜单 | 关闭菜单 |
|
||||
| 左/右滑 | 忽略 | 按步骤判定(G3 左滑=答案) | **移动(dx=∓1)** | 忽略 | 忽略 |
|
||||
| 单击 | 直接开始(stopVoice+进 PLAY) | 按步骤判定(G0/G5=推进/拾取) | voice 播放中=跳句+补检查;无 voice=检查 | **重开一局** | 循环切换菜单项(播选项名) |
|
||||
| 双击 | 忽略 | 按步骤判定(G6=答案) | 使用物品:有目标=解谜动作;无目标=**兜底**(背包或 use_fail + `stuck_<stage>_2` L2 明示) | 忽略 | 执行当前项 |
|
||||
| 长按 | 引擎:旁白快进(后松开) | 同左 | 同左 | 同左 | 同左 |
|
||||
|
||||
- escape 的手势映射**全面偏离全局默认**(四向滑=移动、双击=使用而非重听),
|
||||
00 号文档 §5.3 豁免表已备案;偏离内容在引导 G1/G2/G5/G6 逐一手把手教过。
|
||||
- **PLAY 阶段没有菜单、没有上滑帮助**(00 §5.3:帮助入口 = 双击兜底 +
|
||||
卡关计时器)——"主动查状态"在 escape 里只有双击兜底一个口子,而它直通
|
||||
L2 明示(盲区 S4)。
|
||||
|
||||
### 2.4 卡关三级提示(PLAY 阶段自动触发)
|
||||
|
||||
| 级别 | 触发(现行代码:无操作时长) | 内容 | 附带 | 重复规则 |
|
||||
|---|---|---|---|---|
|
||||
| L1 暗示 | 60s 无任何手势 | `stuck_ask`「需要帮助吗?」+ `stuck_<stage>_1` 意象句 | warning 震 | 每进展段 1 次 |
|
||||
| L2 明示 | 120s | `stuck_<stage>_2` 直接点明房间+动作 | warning 震 | 每进展段 1 次 |
|
||||
| L3 带路 | 180s | `stuck_<stage>_3` + `nav_*` 按当前坐标算路(每轴一句,最多两句,先东西后南北) | warning 震 | 此后每 60s 无操作重复,按当时坐标重算 |
|
||||
|
||||
- **队列与作废**:提示只进待播队列,等当前语音播完;待播期间玩家任何操作
|
||||
即作废(`_dropPendingStuck`,game.js:803-810)。→ 活跃玩家可能连 L1 都
|
||||
听不到,但它本来就不该听到(计时按无操作)。
|
||||
- **双击兜底 = 另一条 L2 通道**(game.js:519-527):在关键房间播 use_fail、
|
||||
在非关键房播背包,**都接 `stuck_<stage>_2`**——玩家主动探状态会被直接
|
||||
喂答案(阶段四 live 两次实录,见盲区 S4)。
|
||||
- 14 号文档裁定的"连续撞墙 ≥2 次阈值提前一级"未落地(§1.5-⑥)。
|
||||
|
||||
### 2.5 关键路径与分支
|
||||
|
||||
**主路径(引导完整走)**:REOPEN(跳过)→ G0 intro → G1 滑一步 → G2 撞墙×2
|
||||
→ G3 左滑 → G4 下滑进储物间 → G5 单击拾钥匙 → G6 双击 → G7 目标陈述 →
|
||||
PLAY(已持钥匙,阶段=cabinet)→ 自由探索开柜→修电箱→开门。
|
||||
引导结束瞬间玩家已知:移动方式、撞墙反馈、检查、双击、背包里有钥匙、
|
||||
下一步目标 = 找锁。**这是全游戏信息最充裕的时刻。**
|
||||
|
||||
**分支与边界路径**:
|
||||
1. **跳过引导**(G0/G3/G5/G6 下滑):`guide_skip`「跳过引导,直接开始自由
|
||||
探索。」→ 直接 PLAY,**不持钥匙、没听过 g7_goal**——开局只有
|
||||
`start_room` 一句操作总览,目标维度完全空白(盲区 S4,live 实录)。
|
||||
2. **二周目** REOPEN:上滑=重听引导;单击=直接开始(播 start_room)。
|
||||
3. **撞墙**:外圈 12 段;反馈 wall 闷响+error 震+`wall` 极简句。无方位
|
||||
信息(教学腔方位句已被 round1-live 回退,§1.5 注)。
|
||||
4. **双击兜底**:非关键房 = 背包句 + L2;关键房 = use_fail + L2。
|
||||
(live 实录:柜已开后再双击铁柜房,听到 use_fail + `stuck_box_2`——
|
||||
玩家并没有卡关,答案句白送。)
|
||||
5. **空房**:进入只播环境音(与邻房可能同音),单击才播 empty_*。
|
||||
6. **重访关键房间**:零语音(首到描述只一次)。
|
||||
7. **结算**:escape 链(不可跳)播完淡入 bgm/menu;单击=立即重开
|
||||
(`_restart` 不管结算链是否播完——live 实录结算链被单击截断,
|
||||
time_band/again 未播,见盲区 S7);下滑=菜单(重开/回大厅/返回)。
|
||||
8. **菜单**:暂停一切(escape 无局内计时器,影响仅限语音队列)。
|
||||
|
||||
### 2.6 各阶段玩家可获得的信息渠道
|
||||
|
||||
| 阶段 | 语音 | earcon/音效 | 震动 | 环境音 | BGM |
|
||||
|---|---|---|---|---|---|
|
||||
| REOPEN | reopen_prompt | turn cue | —(等抉择) | — | bgm/drone |
|
||||
| GUIDE | 逐句指令+纠错(不可跳) | step/wall/pickup | error(答错)/warning(3 连错)/pickup(拾钥匙)/引擎内置 swipe/confirm | amb_storage(G4 到储物间) | bgm/drone |
|
||||
| PLAY | 首到房间描述/检查句/进展链(found_key→gd_room_*)/卡关三级/双击兜底 | step/wall/pickup/unlock/door_creak/spark/power_on/gate_open/win_chime | error(撞墙/无效使用)/success(开柜修电/逃脱)/pickup(拾钥匙)/warning(卡关提示)/引擎 swipe | 每房进来自动播,单击可重听 | bgm/drone |
|
||||
| ENDING | escape+time_band+again(不可跳) | gate_open(后移 2.6s)+win_chime | success | — | drone 淡出→bgm/menu 淡入 |
|
||||
| MENU | menu_open+选项名/help_ops | — | confirm(双击执行) | — | bgm/menu |
|
||||
|
||||
信息渠道的四division 铁律(14 号裁定 7):语音说"你要做什么"、earcon 说
|
||||
"哪类事/哪个状态"、BGM 说"宏观状态"、震动说"刚才那下对不对"。escape 的
|
||||
earcon 仅向导层 8 签名(explore/menu/settle/turn)+ 内容音效;**游戏层没有
|
||||
任何自研 earcon**——方位/进度类信息目前没有 earcon 通道可用(新增需走
|
||||
14 号文档的引擎词表修订,或改用语音/环境音通道)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 信息账本(语音 id 全集三类归档 + 盲区清单)
|
||||
|
||||
### 3.1 语音 id 全集(80 句,按「状态告知 / 操作反馈 / 叙事·教学」三类)
|
||||
|
||||
**A 类 · 状态告知**(回答"我在哪/我有什么/进展如何/系统处于什么状态"):
|
||||
|
||||
| id | 全文(摘要) | 覆盖的状态维度 |
|
||||
|---|---|---|
|
||||
| `start_room` | 你站在设施中央的房间里。滑动移动,单击检查,双击使用物品。 | 绝对方位(唯一一次)+ 操作总览 |
|
||||
| `room_storage` / `room_cabinet` / `room_power` / `room_gate` | 储物间/铁柜/电箱/大门 首到描述 | 房间身份(仅首到) |
|
||||
| `empty_1/2/3` | 空空荡荡/冰冷墙壁/远处水滴 | 空房身份(仅单击检查时) |
|
||||
| `inspect_cabinet_locked` / `inspect_box_dead` / `box_fixed` / `inspect_gate` / `inspect_gate_ready` | 各互动物状态描述 | 谜题对象状态 |
|
||||
| `inv_empty/key/fuse/both` | 背包四档 | 物品持有 |
|
||||
| `wall` | 那边是墙,换个方向。 | 边界负信息(无方位) |
|
||||
| `stuck_ask` + `stuck_<stage>_1` ×4 | 需要帮助吗?+ 意象暗示 | 目标(L1 级,意象) |
|
||||
| `stuck_<stage>_2` ×4 | 点明房间+动作 | 目标(L2 级,明示) |
|
||||
| `stuck_<stage>_3` ×4 + `nav_udlr` ×4 | 带路 | 目标+路线(L3 级) |
|
||||
| `gd_next_fuse` | 保险丝到手。接下来,去找电箱。 | 目标(进展事件当下) |
|
||||
| `gd_room_l/r/u/d` | 左/右/上/下面的房间。 | 目标相对方位(无目标名) |
|
||||
| `time_band1-4` | 用时四档整句 | 结算用时 |
|
||||
| `use_fail` | 这里没有用得上东西的地方。 | 无效使用(状态否定) |
|
||||
| `menu_open/restart/home/back` + `help_ops` + `reopen_prompt` | 菜单与帮助 | 系统状态 |
|
||||
| `box_fixed`(重复列出处归入检查) | — | — |
|
||||
|
||||
**B 类 · 操作反馈**(回答"刚才那下对不对/成了没"):
|
||||
|
||||
| id | 全文(摘要) | 触发 |
|
||||
|---|---|---|
|
||||
| `g1_done` / `g5_key` / `g6_done` | 引导答对确认 | 引导 G1/G5/G6 |
|
||||
| `found_key` | 摸到钥匙(长句,不可跳) | 拾取 |
|
||||
| `unlock_cabinet` | 开柜得保险丝(不可跳) | 解谜成功 1 |
|
||||
| `fix_box` | 装保险丝通电(不可跳) | 解谜成功 2 |
|
||||
| `escape` | 逃脱结算(不可跳) | 通关 |
|
||||
| `replay` | 黑暗再次合拢(重开) | 重开 |
|
||||
| `again` | 单击再来一次(结算链尾) | 结算 |
|
||||
| `use_fail`(兼 A 类) | 无效使用 | 双击无目标 |
|
||||
| `guide_wrong_up/down/left/right/gesture` ×5 | 不是这个方向/操作 | 引导答错 |
|
||||
| `guide_blunt_up/down/left/right` ×4 | 直白重述(3 连错) | 引导连续答错 |
|
||||
| `guide_offpath` | 先跟我走。 | 引导期越轨滑动 |
|
||||
|
||||
**C 类 · 叙事·教学**(铺氛围/教手势,不承担状态):
|
||||
|
||||
| id | 全文(摘要) |
|
||||
|---|---|
|
||||
| `g0_intro` | 黑暗。你在废弃的地下设施里醒来…… |
|
||||
| `g1_move` / `g2_wall` / `g3_left` / `g4_down` / `g5_inspect` / `g6_doubletap` / `g7_goal` | 引导指令六步 + 目标陈述 |
|
||||
| `skip_hint` / `guide_skip` | 跳过旁白提示 / 跳过确认 |
|
||||
| `reopen_prompt`(兼 A) | 二周目抉择 |
|
||||
|
||||
### 3.2 状态维度 × 信息渠道矩阵(空白格 = 盲区)
|
||||
|
||||
| 状态维度 | 语音 | 环境音 | 震动 | earcon/BGM | 结论 |
|
||||
|---|---|---|---|---|---|
|
||||
| 绝对方位(我在图上的哪格) | 仅开局 `start_room` 一句"中央";L2 角落词 | 无 | 无 | 无 | **盲区 S1** |
|
||||
| 相对方位(目标在我哪边) | 仅进展链当下(gd_room)+ L3 带路 | 无 | 无 | 无 | 半盲区(时机太窄) |
|
||||
| 撞墙方位(哪面不通) | 无(教学腔已被回退) | 无 | 无(撞墙=error 通式) | 无 | **盲区 S1b** |
|
||||
| 已探索地图(我来过这吗) | 无(首到描述不重复,重访零语音) | 无 | 无 | 无 | **盲区 S2** |
|
||||
| 空房身份(这屋是哪间) | 仅单击检查时 empty_*,且文本无方位 | 2 种音铺 4 房,不可区分 | 无 | 无 | **盲区 S5** |
|
||||
| 谜题链全局进度(几环完成/还剩几环) | 无主动渠道;inv_* 只报物品 | 仅大门通电有 amb_gate_live | 无 | 无 | **盲区 S3** |
|
||||
| 当前目标(L0 轻量重述) | 仅引导尾 g7_goal(跳过即永久丢失)+ 进展链当下一句 | 无 | 无 | 无 | **盲区 S4** |
|
||||
| 主动查询入口 | 双击兜底 = 直通 L2 明示(泄漏) | — | — | — | **盲区 S4b(机制错配)** |
|
||||
| 物品持有 | inv_* ✓(双击兜底时) | 无 | 拾取时 pickup ✓ | 无 | 基本覆盖 |
|
||||
| 互动物状态(锁/电/门) | 检查语音 ✓ | 大门通电 ✓ | 解谜 success ✓ | 无 | 覆盖(需玩家记得检查) |
|
||||
| 卡关计时器状态 | 无(提示到点才出现) | — | — | — | 设计内,不动 |
|
||||
| 引导 busy 窗口(我手势算数吗) | 无 | 无 | 仅引擎 [10] | 无 | **盲区 S6**(事故级) |
|
||||
| 结算完整性(我通关用时/重开确认) | 结算链可被单击无条件截断 | — | — | — | **盲区 S7** |
|
||||
|
||||
> S1/S2/S3/S4/S5 是用户真机反馈"不知道自己在哪/目标/进度"的精确落点;
|
||||
> S6/S7 是 live 局新抓到的机制级盲区。S1b(撞墙无方位)是 P1 评审的死线项。
|
||||
|
||||
---
|
||||
|
||||
# 阶段三 · 状态引导改进方案(escape-state round1)
|
||||
|
||||
## 4.0 取证摘要
|
||||
|
||||
- **mock 转写**(`research/escape-state/round1/transcript-mock.md`):引导完整
|
||||
路径(G0-G7 全覆盖),证明"引导结束时信息最充裕";此后唯一信息增量来自
|
||||
进展链(mock 行 107-108、126:gd_next_fuse + 方位句)。
|
||||
- **live 真机一局**(`research/escape-state/round1/live-transcript.md`,女声响
|
||||
full 档,约 14 分钟,打到通关并重开):52 个语音段,55 条判定行
|
||||
(OK 35 / SFX_BGM_ONLY 18 / TRUNCATED 2;两条 TRUNCATED 均有玩家手势
|
||||
归因,非资产缺陷)。
|
||||
关键事件:引导期 busy 吞手势(行 30-35)、误触下滑跳过引导(行 61-74)、
|
||||
双击兜底两次直通 L2 明示(行 161-178、230-243)、结算链被单击截断
|
||||
(行 253-275)、L1/L2/L3 三级按时触发且 L3 每 60s 按坐标重算重播
|
||||
(行 75-86、288-294、295-346)。
|
||||
- **人设评审**:P1 视障(`p1-blind.md`)+ P3 白领(`p3-office.md`),双席对
|
||||
盲区清单达成一致。
|
||||
|
||||
设计约束(本方案全部条目的共同红线):
|
||||
- **00 号宪法**:整句预生成、禁运行时拼接;数字信息分档整句;震动语义按
|
||||
00 §2.2 既有 10 震型、不新增语义震;手势映射零改动(上滑仍是移动)。
|
||||
- **14 号向导层**:三档语义(full=earcon+语音+震 / standard=耳标+震 / off=
|
||||
全静);新 earcon 不进本方案(引擎 8 签名词表修订成本过高,方位与进度信息
|
||||
一律走语音通道,游戏反馈层全档位,与 gd_next_fuse/gd_room 先例同级)。
|
||||
- **归因真话律**:进度句报的完成数必须等于真实状态机(hasKey/cabinetOpen/
|
||||
powerOn 派生),不许多报少报。
|
||||
- **难度不降低**:所有新语音只报"状态与方向",不报"做法";L2/L3 的到达不因
|
||||
新通道提前或变频繁。
|
||||
- **节奏不破**:单局 15-30 分钟的宏观节奏由谜题链决定,新播报全部挂在
|
||||
"进展事件 / 首次 / 限频"上,不给活跃玩家增加语音负担。
|
||||
|
||||
## 4.1 方案条目
|
||||
|
||||
### B1 · 撞墙报方位(陈述式,非教学腔)
|
||||
|
||||
- **问题(证据)**:撞墙反馈只有 `wall`「那边是墙,换个方向。」——无方位。
|
||||
live 行 40-55 连撞两次地图零增量;P1「每次错都学不到东西」、P3「盲操的
|
||||
试错成本全是沉没成本」。14 号 F2.3 曾用 `guide_blunt_*`「手指贴着屏幕,向
|
||||
X 推一下」补方位,被 round1-live 以"教学腔中后期出戏"回退——回退掉的是
|
||||
措辞,方位信息本身没有错杀的理由。
|
||||
- **目标状态**:玩家每次撞墙都能建立一个"此方向不通"的地图标记,措辞是
|
||||
世界内陈述句而非操作教学。
|
||||
- **方案**:新增 4 句整句(游戏反馈层全档位,撞墙既有链路 `sfx/wall`+error
|
||||
震+`wall` 播完后接播,被下一次移动打断则自然作废——复用 F2.3 原接线模式):
|
||||
- `wall_dir_l`「左边是墙。」 / `wall_dir_r`「右边是墙。」 /
|
||||
`wall_dir_u`「上边是墙。」 / `wall_dir_d`「下边是墙。」
|
||||
- 触发:PLAY 阶段撞墙、`voice/wall` 播完后、同方向 10s 内限频 1 次
|
||||
(防贴墙连撞连播)。**仅报方位事实,不说"换个方向/推一下"**——后半句
|
||||
现有 `wall` 已覆盖。
|
||||
- 方位 = 滑动方向(escape 移动坐标系),按真实撞墙方向取句,归因真话。
|
||||
- 震动:沿用 error,不新增。
|
||||
- **宪法条款**:00 §2.2(既有 error 震型);00 §3.2(整句预生成);14 裁定 7
|
||||
(语音报事实、耳标报类别——本句是纯语音通道);14 F2.3 先例(接线模式)。
|
||||
- **拥挤评估**:撞墙在 3x3 图中的理论上限是外圈 12 段;限频后一局新增语音
|
||||
≤6-8 句短句(各 ≤5 字),对 15-30 分钟单局节奏影响可忽略。风险:贴墙探索
|
||||
型玩家会听到成串方位句——10s 同向限频 + 移动即作废已把上限压住。
|
||||
|
||||
### B2 · 目标方位句并入目标名(H1 的措辞升级)
|
||||
|
||||
- **问题(证据)**:H1 方位句只有方向词无目标名:「右面的房间。」(live 行
|
||||
112-116、156-160、201-208)。P3:嘈杂环境 1.3s 短句被吃掉后只剩"……的
|
||||
房间"(行 206-208 ASR sim 0.75 实证);P1:"右面是哪?我赌不起"。三处
|
||||
触发点(found_key / gd_next_fuse / fix_box)在谜题链正常路径上位置固定,
|
||||
方位可枚举。
|
||||
- **目标状态**:进展链尾玩家听到"目标名 + 方位"一体句,单句即可行动。
|
||||
- **方案**:新增 3 句整句替换三处 `gd_room_*` 接播(接线点不变,全档位):
|
||||
- found_key 链尾 → `gd_cabinet_dir`「铁柜,在右面的房间。」(储物间 (0,2)
|
||||
→ 铁柜房 (2,1),轴序先东西,dx=+2 固定为右)
|
||||
- unlock_cabinet/gd_next_fuse 链尾 → `gd_box_dir`「电箱,在左面的房间。」
|
||||
(铁柜房 (2,1) → 电箱房 (0,0),dx=−2 固定为左)
|
||||
- fix_box 链尾 → `gd_gate_dir`「大门,在右面的房间。」(电箱房 (0,0) →
|
||||
大门 (2,2),dx=+2 固定为右)
|
||||
- 原 `gd_room_l/r/u/d` 4 句保留不删(guide.test.mjs 的 H1 方向映射断言与
|
||||
playtest 断言引用它们,删除触碰断言零改动红线);新句并行接线,仅替换
|
||||
三处触发点。方位若在异常路径上计算结果与枚举不符(理论上不存在——三处
|
||||
触发点坐标固定),兜底回落 `gd_room_*`。
|
||||
- **宪法条款**:00 §3.2(整句);归因真话(方位按房间图枚举核对过:三处
|
||||
触发点→目标均同排/跨排但轴序先东西,方向唯一);14 H1 裁定(接线模式
|
||||
原样,只改词)。
|
||||
- **拥挤评估**:3 处替换、0 处新增播出次数;句长 +4 字。对节奏零影响。
|
||||
附带收益:修了 P3 的"关键信息听不清"——信息密度翻倍,重听价值也翻倍。
|
||||
|
||||
### B3 · 无进展计时器 + L0 进度重述(活跃迷路通道)
|
||||
|
||||
- **问题(证据)**:卡关计时按"无操作"(§1.5-①,round1-live 修订),**活跃
|
||||
但无进展的玩家永远不会收到任何状态输入**——live 局我在解谜链外探路时
|
||||
(行 87-94、179-220 各段 transit)游戏只给我脚步和环境音。01 号文档原始
|
||||
设计是"无进展起算",代码把"无进展"改成"无操作"后,"活跃迷路"这个状态
|
||||
从提示体系里消失了。用户反馈"不知道进度"正是这个空洞。
|
||||
- **目标状态**:玩家长时间有操作但零进展时,收到一条**不泄题**的进度重述,
|
||||
知道自己已完成几环、目标仍是什么,而不是答案。
|
||||
- **方案**:
|
||||
- 新增独立计时:以 `_progressEvent()` 起算的"无进展时长"(与现有无操作
|
||||
计时器并存,互不复位)。触发点:无进展 ≥150s 且期间有 ≥5 次有效手势
|
||||
(=活跃探索,排除挂机——挂机交给现有 60s L1 体系)→ 每进展段限 1 次。
|
||||
- 播报内容(整句分档,不拼接,归因真话——完成数由 `_stage()` 反推):
|
||||
- `gd_prog_1`「钥匙已经到手。找到能用它的锁。」(stage=cabinet)
|
||||
- `gd_prog_2`「铁柜已经打开。电还没有通。」(stage=box)
|
||||
- `gd_prog_3`「电已经通了。去找那扇大门。」(stage=gate)
|
||||
- key 阶段无进展 150s 不走本通道(现有 L1/L2/L3 已覆盖"找不到钥匙",
|
||||
避免双计时器对同一阶段轰炸)。
|
||||
- 队列语义沿用 `_pendingVoice`(绝不顶句,待播期间有操作即作废);warning
|
||||
震与 L1-L3 同款。
|
||||
- **宪法条款**:00 §3.2(整句分档);归因真话律;14 裁定 5(escape 卡关
|
||||
骨架保留,本通道是**新增平行通道**,不动既有 60/120/180 任何一级);01 号
|
||||
文档 §3.1 原始意图的部分回收。
|
||||
- **拥挤评估**:触发频率 = 每进展段最多 1 次 × 最多 3 段(cabinet/box/gate)
|
||||
= 全局限 3 句;且要求 150s 活跃零进展,正常通关(2-3 分钟/环节)永远触发
|
||||
不到。只补"该响没响"的洞,不给顺畅玩家加噪。
|
||||
|
||||
### B4 · 双击兜底降级:背包 + L1 意象,不再直通 L2
|
||||
|
||||
- **问题(证据)**:双击无目标 = 玩家**主动查询**的唯一入口,现状直通
|
||||
L2 明示:live 行 161-178(柜已开后再双击铁柜房 → use_fail + `stuck_box_2`
|
||||
把电箱房和动作全报出来)、行 230-243(同理 `stuck_gate_2`)。P1 定为 P0
|
||||
"谜题被白送"——没卡关的人收到卡关 120s 才该有的答案,既是泄漏也稀释 L2
|
||||
的稀缺性(难度变相降低)。
|
||||
- **目标状态**:主动查询返回"背包 + 当前目标的 L1 级暗示",答案仍锁在
|
||||
计时器 L2/L3 与进展链里。
|
||||
- **方案**:`_useItem()` 兜底链第二句由 `voice/stuck_<stage>_2` 改为
|
||||
`voice/stuck_<stage>_1`(资产现成,4 句意象暗示:铁锈味/钥匙在身上/
|
||||
电流声/电已通——全部不点明房间与动作,零新资产)。`use_fail` 与背包句
|
||||
不动。已在 `_stuckShown` 里记过 L1 的进展段不重复播(沿用既有去重)。
|
||||
- **宪法条款**:00 §5.3(escape 帮助入口语义不变,只是档位归位);01 号
|
||||
§3.2「主动求提示保留:先播背包,再播 L2」——本条是对 01 的**有意修订**
|
||||
(泄漏 > 帮助,证据双实录),在本文档留痕;归因真话(L1 句无答案可泄漏)。
|
||||
- **拥挤评估**:播出次数不变(一次兜底两句);内容变轻。L2 触发总量下降
|
||||
(对非卡关玩家),L3 不受影响。对卡关玩家:60s L1 → 120s L2 → 180s L3
|
||||
的阶梯完整保留,难度不降。
|
||||
|
||||
### B5 · 空房首访描述(复用现有资产)+ 方位线索句(新词,二选一落地)
|
||||
|
||||
- **问题(证据)**:进入空房零语音(live 行 87-94、179-186、209-220),
|
||||
4 间空房 2 种环境音不可区分(amb_hum 行 90/182;amb_wind 行 120/212)。
|
||||
玩家对 5/9 的地图面积永远建不起模型——用户反馈"不知道自己在哪"的大头。
|
||||
- **目标状态**:每间空房至少有一个可建立心智地图的听觉锚(首访一次性,
|
||||
之后可单击复核)。
|
||||
- **方案**(两档,按实施预算二选一,建议 a 先行):
|
||||
- **a(零新资产)**:空房**首访**时补播现有 `empty_1/2/3`(现只在单击
|
||||
检查时播;进入时播、单击时不再重复首访句)。三个 id 恰好够分给
|
||||
(1,0)/(0,1)/(1,2)+(2,0)…4 房 3 句,需把 (1,2)/(2,0) 拆开:建议
|
||||
(1,0)→empty_1、(0,1)→empty_2、(1,2)→empty_3、(2,0)→复用 empty_3 或
|
||||
保持沉默(两间"远处水滴"空房对称分布也是合法的记忆点)。
|
||||
- **b(3-4 句新词,推荐终态)**:empty_* 改词重录为**含固定方位特征**的
|
||||
句子(房间特征是固定的,方位词不随玩家状态变,归因真话):
|
||||
`empty_1`→「北面墙缝透进一丝风。这里什么都没有。」((1,0) 北外墙)、
|
||||
`empty_2`→「回声从东面的墙折回来。这里空空荡荡。」((0,1) 东侧内墙——
|
||||
内墙方位特征需与地图核对后定稿)、`empty_3a/3b` 同理。每句给一个方向
|
||||
锚 + 一个可分辨特征,四间空房从此声学可区分。
|
||||
- 触发:进入空房首访(visited 集合扩到空房坐标);震动/earcon 不动。
|
||||
- **宪法条款**:00 §3.2(整句);归因真话(方位特征写死前按房间图逐间核对);
|
||||
14 裁定 7(描述句走语音通道)。
|
||||
- **拥挤评估**:每房一生一次,全局 +≤4 句;单击检查路径不变。对节奏零影响。
|
||||
风险:empty_* 改词会动既有资产文本(playtest 断言若引用文本需同步登记)——
|
||||
方案 a 完全绕开此风险。
|
||||
|
||||
### B6 · 引导 busy 窗口手势缓存(逻辑修复)
|
||||
|
||||
- **问题(证据)**:live 行 30-35:`g2_wall` 播放中(37.60-43.28)我滑了一下
|
||||
(41.57),只有引擎 [10] 轻震——墙没响、G2 计数没走,**静默吞手势**。若玩家
|
||||
信了这一下、只再补一滑,G2 永远不满足"滑两下",引导卡死(虽有 20s 看门狗
|
||||
兜底推进,但那是防资产缺失的,不是交互语义)。P1 特别检查项"失败可否归因"
|
||||
判半不过。
|
||||
- **目标状态**:busy 窗口内的首个手势在窗口结束后被补判(或明确拒绝并给
|
||||
反馈)。
|
||||
- **方案**:`_guideBusy` 期间缓存首个非跳过分手势,推进语音播完(done())
|
||||
后立即按新步骤判定:若缓存手势对新步骤合法则直接作答(玩家体验为"我的
|
||||
输入没丢");不合法则按新步骤的答错路径处理(有纠正语音,可归因)。缓存
|
||||
仅 1 个、只存活到本步骤解锁,杜绝跨步幽灵输入。
|
||||
- **宪法条款**:00 §5.4「做了一个手势 3 秒内必须有反馈」(当前 busy 吞手势
|
||||
违反此条,本条是合规修复);14 裁定 5(引导链结构不动)。
|
||||
- **拥挤评估**:零资产、零新增语音;只改引导期手势时序。引导链被 playtest
|
||||
断言冻结的部分(finishVoices(3)→PLAY 等)不受影响——缓存只在 busy 窗口
|
||||
内生效,脚本化玩家的手势本就在 turn cue 后送达。
|
||||
|
||||
### B7 · 结算链单击守卫(逻辑修复)
|
||||
|
||||
- **问题(证据)**:live 行 253-275:`inspect_gate_ready` 被随后的逃脱双击
|
||||
截断(行 256-257,属正常链式替换);更严重的是我的习惯性单击(369.22)在
|
||||
结算链 escape 播到 10.7/15.3s 时直接触发重开——`time_band1`(用时)与
|
||||
`again` 两句被永久吞掉(行 263-275)。P3 定为 P0:"结算是我唯一确认打完了/
|
||||
打得如何的窗口,一碰就碎"。
|
||||
- **目标状态**:结算链播完前,ENDING 单击不立即重开。
|
||||
- **方案**:`_escape()` 起设 `_settleBusy=true`(结算链 onDone/30s 兜底处
|
||||
复位);ENDING 单击在 `_settleBusy` 期间忽略(或在 full 档播一句既有
|
||||
`again` 前句?—— 不新增语音,直接忽略+引擎 confirm 震已有)。`again` 句
|
||||
本身已含操作指引,链播完后再单击重开的原语义不变。30s 资产缺失兜底保留
|
||||
(防静默死锁)。
|
||||
- **宪法条款**:00 §5.4(单击 3s 内反馈——忽略路径有引擎 confirm 震兜底,
|
||||
合规);00 §3.2(结算整句分档的完整到达权);14 裁定 4(不顶句、不丢句)。
|
||||
- **拥挤评估**:零资产;只影响结算后前 ~15s 的重开时序。结算链播完 → 单击
|
||||
重开 → replay 的既有闭环在转写里完整存在(mock 行 144-149),本条只是
|
||||
把闭环的起点从"escape 第一句"推迟到"again 播完"。
|
||||
|
||||
### B8 · 跳过引导后补播目标句(零资产)
|
||||
|
||||
- **问题(证据)**:`guide_skip` 路径(live 行 61-74)与 REOPEN 单击直进
|
||||
路径都只播 `start_room`(手势总览)——**目标陈述 g7_goal 只在引导 G7 链尾
|
||||
出现一次**,跳过的玩家(恰是最需要目标的一群,P1/P3 共识)永远听不到
|
||||
"找到能用这把钥匙打开的东西"。且跳过后阶段=key、身上无物品,60s 内只有
|
||||
意象级 L1(行 75-86)。
|
||||
- **目标状态**:任何路径进入 PLAY 时,玩家都至少听过一次目标句。
|
||||
- **方案**:`guide_skip` 确认句后、`_enterPlay` 前补播 `g7_goal`(资产现成,
|
||||
链式 `_speak`);REOPEN 单击直进路径同样在 `start_room` 后接 `g7_goal`。
|
||||
二周目老手可单击跳过该句(skippable 默认 true,符合 12 号文档——教学
|
||||
义务句已随首局完成,此处是状态告知不是教学)。
|
||||
- **宪法条款**:00 §3.2;14 H1 注(g7_goal 不接方位句的红线仅冻结于**引导
|
||||
链内**——本方案接在跳过确认链后,不触碰被冻结的引导链断言);01 号 §2.1
|
||||
设计意图(G7 目标陈述的全局可达)。
|
||||
- **拥挤评估**:两句短链、每会话最多一次;二周目玩家 1 次单击即可跳过。
|
||||
对节奏影响 ≤5s,且只发生在"信息最空白"的路径上。
|
||||
|
||||
### B9 · L2 台词顺带修订(不推荐本轮做,留档)
|
||||
|
||||
live 行 288-294 可见 L2/L3 句仍用"西南角/西北角/东南角"绝对方位词——对
|
||||
从未建立坐标系的玩家,绝对角落词不如相对方向可用(L3 带路已经改用相对
|
||||
滑动方向)。但 L2 明示句的改词会动 12 句资产与全部相关断言,且 L3 已兜底
|
||||
带路,**收益/成本比低,列为后续轮候选**,不在本轮实施清单内。
|
||||
|
||||
## 4.2 盲区 → 方案对照表
|
||||
|
||||
| 盲区 | 方案 | 新语音资产 | 逻辑改动 | 证据 |
|
||||
|---|---|---|---|---|
|
||||
| S1/S1b 方位(撞墙/平时) | B1 | +4 句 | 撞墙链路接播+限频 | live 行 40-55;P1/P3 P0 |
|
||||
| 相对方位半盲区(无目标名) | B2 | +3 句 | 三处接线点换 id | live 行 112-116/156-160/201-208 |
|
||||
| S3 全局进度无渠道 | B3 | +3 句 | 新计时器+触发 | 用户反馈;live transit 段 |
|
||||
| S4/S4b 目标重述/查询泄漏 | B4 + B8 | 0(复用) | 兜底换 id;跳过链补播 | live 行 61-74/161-178/230-243 |
|
||||
| S5 空房不可区分 | B5a/b | 0 或 +3~4 句 | 首访描述接线 | live 行 90/182/120/212 |
|
||||
| S6 busy 吞手势 | B6 | 0 | 缓存补判 | live 行 30-35 |
|
||||
| S7 结算链截断 | B7 | 0 | 守卫 | live 行 253-275 |
|
||||
|
||||
## 4.3 实施清单(F 类编号,**仅登记,未实施**)
|
||||
|
||||
| # | 内容 | 资产管线步骤 | 断言登记建议 |
|
||||
|---|---|---|---|
|
||||
| F1(B1) | 撞墙方位句 `wall_dir_l/r/u/d` ×4,撞墙链路接播 + 同向 10s 限频 | `tools/gen_voice_dual.py --game escape --only wall_dir_l,wall_dir_r,wall_dir_u,wall_dir_d` → `--convert` → `check_all_assets.py` → `extract_voice_text.py` 刷新 | escape playtest:撞墙后方位句到达/限频生效/移动打断作废;guide.test 不受影(PLAY 期行为) |
|
||||
| F2(B2) | `gd_cabinet_dir` / `gd_box_dir` / `gd_gate_dir` ×3,替换三处 gd_room_* 接播(原句保留) | 同 F1 管线,3 句 | playtest:三处进展链尾新句到达且方位正确;原 H1 断言(gd_room_* 映射表)保留不动 |
|
||||
| F3(B3) | `gd_prog_1/2/3` ×3 + 无进展 150s 活跃计时器(≥5 手势闸门、每段限 1 次、队列语义) | 同 F1 管线,3 句 | playtest(guide=off):计时器不误触(挂机不触、进展后清零、限 1 次);guide.test:队列不顶句、作废语义 |
|
||||
| F4(B4) | 双击兜底第二句 stuck_*_2 → stuck_*_1 | **零资产** | playtest:兜底链内容变更需逐条同步(现有断言若期望 stuck_*_2 必改);L2 计时器触发路径断言不动 |
|
||||
| F5(B5a) | 空房首访补播 empty_*(零资产先行版) | 零资产 | playtest:首访到达/重访不重复/单击检查语义不变 |
|
||||
| F6(B5b,可分期) | empty_* 改词带方位特征 ×3~4 | 同 F1 管线;**改词前逐间核对房间图方位特征(归因真话)** | 文本断言同步;双耳一致性 |
|
||||
| F7(B6) | 引导 busy 手势缓存补判 | 零资产 | guide.test:busy 窗口手势缓存→解锁后补判/答错路径;既有引导推进断言零改动红线 |
|
||||
| F8(B7) | 结算链单击守卫 `_settleBusy` | 零资产 | playtest:结算链完整播完(time_band/again 到达)后才可重开;30s 兜底仍生效 |
|
||||
| F9(B8) | 跳过引导/REOPEN 直进补播 g7_goal | 零资产 | playtest:两条路径 start_room 后 g7_goal 到达;二周目单击可跳过 |
|
||||
|
||||
统一收尾(每轮 F 实施完必做):`check_all_assets.py` 全绿 → 6 playtest
|
||||
(guide=off)断言对账(escape 现有 103 条,F4/F5/F7/F9 会改其中若干,
|
||||
须逐条登记变更原因)→ `guide.test.mjs` 增补 → live 复跑一局验证新句在
|
||||
真实混音中可闻(B2/B3 短句尤其要做 ASR 层判定)。
|
||||
|
||||
---
|
||||
|
||||
# 阶段四 · 实施勾账(escape-state round2,2026-09-15)
|
||||
|
||||
> §4.3 清单已从"仅登记,未实施"转为**已实施**(除 F6 按方案"可分期"留档,
|
||||
> 见实施裁定 1)。验证档案:`research/escape-state/round2/`(mock 转写 +
|
||||
> live 真机一局 38 段 OK 37 / SFX_BGM_ONLY 19 / 零截断,S1-S7 逐条核对)。
|
||||
> 新断言全部登记在 `web/escape/test/playtest.mjs`(103 → 235 条全绿)与
|
||||
> `web/harness/guide.test.mjs`(120 → 132 条全绿);既有断言变更 3 处,
|
||||
> 逐条登记于下表"断言变更"列。
|
||||
|
||||
| # | 落地 | 断言登记(场景.条数) | 断言变更 | live 证据(round2/live-transcript.md 行号) |
|
||||
|---|---|---|---|---|
|
||||
| F1(B1) | ✅ `wall_dir_l/r/u/d` ×4 双性别已生成落盘;`_move` 撞墙链路 `wall` 播完接播、同向 10s 限频、被打断作废(game.js `_move`) | playtest G×13(引导期不播/接播顺序/打断作废/限频与恢复)+ 资产校验 F 段扩 wall_dir 族 | 无 | 行 141-143 wall_dir_u、行 166-168 wall_dir_l、199.5s 限频 |
|
||||
| F2(B2) | ✅ `gd_cabinet_dir/gd_box_dir/gd_gate_dir` ×3 替换三处接播;`_playGoalDir(target, namedId, expectedId)` 异常路径回落 `gd_room_*`(原句保留) | playtest H×12(三处到达+顺序+不再播 gd_room_*+回落+同房间不播);guide.test ⑩c 换线 + 回落断言 | guide.test ⑩c 三处接线断言由 gd_room_* 改为 gd_*_dir(映射表单元断言保留不动) | 行 231-233 gd_box_dir、行 306-312 gd_gate_dir |
|
||||
| F3(B3) | ✅ `gd_prog_1/2/3` ×3 + `_checkStuck` 平行通道(150s 无进展 ∧ ≥5 手势 ∧ stage≠key,每段限 1 次,队列/作废语义同卡关提示) | playtest I×11(key 不走/闸门/触发/限 1 次/进展复位/box 段再触/入队不顶句/作废计入不重发) | 无 | 行 265-268 gd_prog_2(活跃 154s 触发,期间 L1-L3 零误触) |
|
||||
| F4(B4) | ✅ `_useItem` 兜底第二句 `stuck_*_2`→`stuck_*_1`,L1 播了即记账沿用 `_stuckShown` 去重 | playtest J×8(背包+L1/不直通 L2/记账/再兜底不重复/60s 不重复 L1/120s L2 仍到达) | playtest 场景 A 兜底断言 stuck_key_2→stuck_key_1(+不播 _2 反向断言) | 行 180-182 use_fail+stuck_cabinet_1 |
|
||||
| F5(B5a) | ✅ 空房首访补播 `empty_*`((1,0)→1/(0,1)→2/(1,2)→3/(2,0)→3 复用),`_freshEmpty` 实现"本房间内单击不重复首访句";不算进展事件 | playtest K×9(首访到达/非进展事件/房内单击不重复/重访零语音/重访单击照常/四房映射) | 无(单击检查语义不变) | 行 115-118/189-192/199-202 三间首访 |
|
||||
| F6(B5b) | ⏸ **留档**(实施裁定 1) | — | — | — |
|
||||
| F7(B6) | ✅ `_guidePending` 缓存首个非跳过分手势,`_advance` done() 解锁后按新步骤补判(fromCache 绕过下滑跳过检查);跳过分手势不缓存;G6 链尾离 GUIDE 缓存作废 | playtest L×15(不当场判定/补判作答/答错路径/不触发跳过/仅 1 个/跳过分手势不缓存/引导链完整);guide.test ⑩d×7(full 档同款) | 无(既有引导推进断言零改动) | live-events 82.3s 缓存→87.9s 补判 |
|
||||
| F8(B7) | ✅ `_settleBusy` 守卫:`_escape` 挂载,`_startEndingBgm`(链完/30s 兜底汇合点)解除;ENDING 单击守卫期忽略 | playtest M×10(守卫期不重开/链完整 time_band+again/解除后重开/again 缺失 30s 兜底) | 无 | 行 336-347 习惯性单击被守卫挡下,time_band3+again 完整到达 |
|
||||
| F9(B8) | ✅ `_skipGuide` 链 guide_skip→g7_goal→_enterPlay;REOPEN 单击 `_enterPlay(true, true)` start_room→g7_goal;`_skipGuide` 期间 guideStep=7(裁定 4) | playtest N×6(直进顺序/可单击跳过)+ A2/B 场景跳过链更新(g7_goal 到达、顺序、两句后再进 PLAY) | playtest A2/B 跳过断言由"一句后 PLAY"改为"guide_skip→g7_goal 两句后 PLAY" | g7_goal OK sim=1(行 149.5s) |
|
||||
|
||||
统一收尾执行记录:`check_all_assets.py` 全项目 15 游戏全绿(escape voice 各 90
|
||||
id 双性别一致);escape playtest 235/0、guide.test 132/0、其余 14 款 playtest
|
||||
回归全绿、engine-voice 19/0 与 engine-input 72/0 无连带;live 复跑一局
|
||||
(端口 8145,打完杀净)S1-S7 每个时刻现在都有落点(round2/README.md 对照表)。
|
||||
|
||||
## 实施裁定记录(编号自本轮起,接续追加不改旧文)
|
||||
|
||||
1. **F6(B5b)分期留档**:B5b 草案台词未定稿——`empty_2` 东侧内墙方位特征
|
||||
原文标注"需与地图核对后定稿"、`empty_3a/3b` 无台词草案,无法按"台词与
|
||||
草案逐字一致"的管线铁律生成;且 B5 原文即"建议 a 先行"、F6 标注"可分期"。
|
||||
本轮只落地 F5(B5a 零资产版),B5b 连同 B9(L2 角落词改词)一并列为
|
||||
后续轮候选。
|
||||
2. **B4 去重双向化**:方案只规定"已在 `_stuckShown` 记过 L1 的进展段不重复
|
||||
播";实施把兜底播出 L1 也**记账**(播了即加入 `_stuckShown`),否则 60s
|
||||
计时器会把玩家刚听过的同一句意象暗示再播一遍(去重只做单向等于没做)。
|
||||
附带效果:L1 整级(含 `stuck_ask`)跳过,L2/L3 阶梯与触发时点不变
|
||||
(playtest J 冻结)。
|
||||
3. **B3 作废计入已播**:待播 `gd_prog` 在排队期间被玩家操作作废后仍计入
|
||||
"每进展段限 1 次"(触发即记账)。方案"每进展段限 1 次"若按播出记账,
|
||||
5s 轮询会在条件持续成立时立即重发,形成骚扰循环;按触发记账与该条
|
||||
"全局限 3 句"的拥挤评估一致(playtest I⑧ 冻结)。
|
||||
4. **B8 跳过链期间 guideStep=7**:`_skipGuide` 的两句链(guide_skip→g7_goal)
|
||||
播放期间相位仍是 GUIDE,原 guideStep 下单击/滑动会被当成引导作答(既有
|
||||
竞态:skip 链中单击可误推 G1)。落地把 guideStep 置 7(G7 等待语义:
|
||||
手势全忽略),链中输入 robustness 与 G7 自然链尾对齐;语音缺失兜底计时
|
||||
5s→9s(覆盖两句链)。
|
||||
5. **B5a 两个二选一**:(2,0) 选"复用 empty_3"(方案原文认可"两间'远处水滴'
|
||||
空房对称分布也是合法的记忆点");"单击时不再重复首访句"以 `_freshEmpty`
|
||||
实现——仅首访句刚播过的那个房间内抑制同句,离开即恢复单击播句,
|
||||
重访后单击检查语义完全不变(playtest K 冻结)。
|
||||
6. **B6 缓存手势绕过下滑跳过**:方案"不合法则按新步骤的答错路径处理"
|
||||
意味着缓存的下滑在可跳过步骤上也不再触发 `_skipGuide`(fromCache 绕过
|
||||
skip 检查)——这正是 live round1 S6 事故(答案被吞后下滑被当成跳过)的
|
||||
修复点;实时注入的下滑跳过语义不变(playtest L⑤/guide.test ⑩d 冻结)。
|
||||
7. **B1 限频记账点**:同向 10s 限频按**方位句实际开播时刻**记账;仅调度
|
||||
(wall 接播注册)未播出即被打断的不占额度(playtest G③"被作废的方向
|
||||
补撞后正常接播"冻结)。
|
||||
|
||||
## 盲区清单核销(§3.2 → round2)
|
||||
|
||||
S1/S1b(B1)、相对方位半盲区(B2)、S2(B5a)、S3(B3)、S4/S4b(B4+B8)、
|
||||
S5(B5a,B5b 留档)、S6(B6)、S7(B7)——live round2 逐条核对证据见
|
||||
`research/escape-state/round2/README.md`,每个盲区时刻现在都有落点。
|
||||
@@ -0,0 +1,271 @@
|
||||
{"ev":"probe_ready","t":50.099999994039536,"ta":null}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":30065,"ta":null}
|
||||
{"ev":"recstart","mime":"audio/webm;codecs=opus","t":30170.90000000596,"ta":0}
|
||||
{"ev":"fetch","url":"audio/sfx/step.ogg","status":200,"ok":true,"ms":14,"t":30185.29999998212,"ta":0.014}
|
||||
{"ev":"fetch","url":"audio/sfx/wall.ogg","status":200,"ok":true,"ms":14,"t":30185.40000000596,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/pickup.ogg","status":200,"ok":true,"ms":14,"t":30185.5,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/unlock.ogg","status":200,"ok":true,"ms":14,"t":30185.5,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/door_creak.ogg","status":200,"ok":true,"ms":14,"t":30185.5,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/spark.ogg","status":200,"ok":true,"ms":14,"t":30185.5,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/power_on.ogg","status":200,"ok":true,"ms":14,"t":30185.69999998808,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/gate_open.ogg","status":200,"ok":true,"ms":15,"t":30186.40000000596,"ta":0.016}
|
||||
{"ev":"fetch","url":"audio/sfx/win_chime.ogg","status":200,"ok":true,"ms":16,"t":30187.79999998212,"ta":0.017}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_storage.ogg","status":200,"ok":true,"ms":18,"t":30189.69999998808,"ta":0.019}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_cabinet.ogg","status":200,"ok":true,"ms":18,"t":30190.40000000596,"ta":0.02}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_power.ogg","status":200,"ok":true,"ms":20,"t":30192.40000000596,"ta":0.022}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_gate.ogg","status":200,"ok":true,"ms":22,"t":30194,"ta":0.023}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_gate_live.ogg","status":200,"ok":true,"ms":28,"t":30200.19999998808,"ta":0.029}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_drip.ogg","status":200,"ok":true,"ms":28,"t":30200.29999998212,"ta":0.029}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_wind.ogg","status":200,"ok":true,"ms":29,"t":30201.19999998808,"ta":0.03}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_hum.ogg","status":200,"ok":true,"ms":29,"t":30201.29999998212,"ta":0.03}
|
||||
{"ev":"fetch","url":"audio/voice/female/g0_intro.ogg","status":200,"ok":true,"ms":30,"t":30202.59999999404,"ta":0.032}
|
||||
{"ev":"fetch","url":"audio/voice/female/skip_hint.ogg","status":200,"ok":true,"ms":33,"t":30205.29999998212,"ta":0.034}
|
||||
{"ev":"fetch","url":"audio/voice/female/g1_move.ogg","status":200,"ok":true,"ms":34,"t":30206.69999998808,"ta":0.036}
|
||||
{"ev":"fetch","url":"audio/voice/female/reopen_prompt.ogg","status":200,"ok":true,"ms":35,"t":30207.90000000596,"ta":0.037}
|
||||
{"ev":"fetch","url":"audio/voice/female/start_room.ogg","status":200,"ok":true,"ms":36,"t":30208.5,"ta":0.038}
|
||||
{"ev":"fetch","url":"audio/bgm/menu.ogg","status":200,"ok":true,"ms":36,"t":30209,"ta":0.038}
|
||||
{"ev":"fetch","url":"audio/bgm/drone.ogg","status":200,"ok":true,"ms":37,"t":30209.69999998808,"ta":0.039}
|
||||
{"ev":"vstart","url":"audio/voice/female/g0_intro.ogg","t":30259.19999998808,"dur":6.64,"ta":0.088}
|
||||
{"ev":"start","t":30453.69999998808,"sid":1,"url":"audio/bgm/drone.ogg","layer":"bgm","dur":117,"rate":1,"loop":true,"when":0,"ta":0.283}
|
||||
{"ev":"vend","url":"audio/voice/female/g0_intro.ogg","t":37066.59999999404,"reason":"kill","ta":6.896}
|
||||
{"ev":"vstart","url":"audio/voice/female/g1_move.ogg","t":38267.09999999404,"dur":4.56,"ta":8.096}
|
||||
{"ev":"vend","url":"audio/voice/female/g1_move.ogg","t":42847.59999999404,"reason":"kill","ta":12.677}
|
||||
{"ev":"vstart","url":"audio/voice/female/skip_hint.ogg","t":42847.90000000596,"dur":1.6,"ta":12.677}
|
||||
{"ev":"vend","url":"audio/voice/female/skip_hint.ogg","t":44449.5,"reason":"kill","ta":14.279}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":64687.79999998212,"ta":34.517}
|
||||
{"ev":"vibrate","pattern":"[10]","t":65048.29999998212,"ta":34.877}
|
||||
{"ev":"start","t":65049.09999999404,"sid":2,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":34.878}
|
||||
{"ev":"fetch","url":"audio/voice/female/g1_done.ogg","status":200,"ok":true,"ms":3,"t":65051.40000000596,"ta":34.881}
|
||||
{"ev":"vstart","url":"audio/voice/female/g1_done.ogg","t":65055.59999999404,"dur":2.72,"ta":34.885}
|
||||
{"ev":"vend","url":"audio/voice/female/g1_done.ogg","t":67760.29999998212,"reason":"kill","ta":37.589}
|
||||
{"ev":"fetch","url":"audio/voice/female/g2_wall.ogg","status":200,"ok":true,"ms":3,"t":67763.09999999404,"ta":37.592}
|
||||
{"ev":"vstart","url":"audio/voice/female/g2_wall.ogg","t":67768.69999998808,"dur":5.68,"ta":37.598}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":71744.59999999404,"ta":41.574}
|
||||
{"ev":"vibrate","pattern":"[10]","t":72097.79999998212,"ta":41.927}
|
||||
{"ev":"vend","url":"audio/voice/female/g2_wall.ogg","t":73448.79999998212,"reason":"kill","ta":43.278}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":76509.09999999404,"ta":46.338}
|
||||
{"ev":"vibrate","pattern":"[10]","t":76864.19999998808,"ta":46.693}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":76864.40000000596,"ta":46.694}
|
||||
{"ev":"start","t":76864.69999998808,"sid":3,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":46.694}
|
||||
{"ev":"fetch","url":"audio/voice/female/wall.ogg","status":200,"ok":true,"ms":2,"t":76866.79999998212,"ta":46.696}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":76870.29999998212,"dur":2.08,"ta":46.699}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":79207.09999999404,"reason":"kill","ta":49.036}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":83826.69999998808,"ta":53.656}
|
||||
{"ev":"vibrate","pattern":"[10]","t":84180.59999999404,"ta":54.01}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":84180.79999998212,"ta":54.01}
|
||||
{"ev":"start","t":84180.90000000596,"sid":4,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":54.01}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":84181,"dur":2.08,"ta":54.01}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":86520.40000000596,"reason":"kill","ta":56.35}
|
||||
{"ev":"fetch","url":"audio/voice/female/g3_left.ogg","status":200,"ok":true,"ms":3,"t":86523.29999998212,"ta":56.352}
|
||||
{"ev":"vstart","url":"audio/voice/female/g3_left.ogg","t":86526.79999998212,"dur":2.96,"ta":56.356}
|
||||
{"ev":"vend","url":"audio/voice/female/g3_left.ogg","t":89515.59999999404,"reason":"kill","ta":59.345}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":91087.40000000596,"ta":60.917}
|
||||
{"ev":"vibrate","pattern":"[10]","t":91447,"ta":61.276}
|
||||
{"ev":"fetch","url":"audio/voice/female/guide_skip.ogg","status":200,"ok":true,"ms":2,"t":91449.69999998808,"ta":61.279}
|
||||
{"ev":"vstart","url":"audio/voice/female/guide_skip.ogg","t":91453.79999998212,"dur":2.88,"ta":61.283}
|
||||
{"ev":"vend","url":"audio/voice/female/guide_skip.ogg","t":94437.79999998212,"reason":"kill","ta":64.267}
|
||||
{"ev":"vstart","url":"audio/voice/female/start_room.ogg","t":94438.09999999404,"dur":7.2,"ta":64.267}
|
||||
{"ev":"start","t":94438.90000000596,"sid":5,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":64.268}
|
||||
{"ev":"vend","url":"audio/voice/female/start_room.ogg","t":101983.69999998808,"reason":"kill","ta":71.813}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":155172.90000000596,"ta":125.002}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_ask.ogg","status":200,"ok":true,"ms":3,"t":155176.09999999404,"ta":125.005}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_ask.ogg","t":155179.29999998212,"dur":1.28,"ta":125.008}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_ask.ogg","t":156778.09999999404,"reason":"kill","ta":126.607}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_key_1.ogg","status":200,"ok":true,"ms":2,"t":156780.59999999404,"ta":126.61}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_1.ogg","t":156784.29999998212,"dur":2.88,"ta":126.613}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_1.ogg","t":159773.19999998808,"reason":"kill","ta":129.602}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":161038.69999998808,"ta":130.868}
|
||||
{"ev":"vibrate","pattern":"[10]","t":161394.19999998808,"ta":131.223}
|
||||
{"ev":"start","t":161394.5,"sid":6,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":131.224}
|
||||
{"ev":"start","t":161394.59999999404,"sid":7,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":131.224}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":167817.79999998212,"ta":137.647}
|
||||
{"ev":"vibrate","pattern":"[10]","t":168177.69999998808,"ta":138.007}
|
||||
{"ev":"start","t":168178.29999998212,"sid":8,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":138.007}
|
||||
{"ev":"start","t":168178.29999998212,"sid":9,"url":"audio/sfx/amb_storage.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":138.007}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_storage.ogg","status":200,"ok":true,"ms":3,"t":168180.79999998212,"ta":138.01}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_storage.ogg","t":168186.90000000596,"dur":5.36,"ta":138.016}
|
||||
{"ev":"vend","url":"audio/voice/female/room_storage.ogg","t":173866.79999998212,"reason":"kill","ta":143.696}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":175088.19999998808,"ta":144.917}
|
||||
{"ev":"vibrate","pattern":"[20]","t":175453.29999998212,"ta":145.282}
|
||||
{"ev":"vibrate","pattern":"[15]","t":175453.59999999404,"ta":145.283}
|
||||
{"ev":"start","t":175453.69999998808,"sid":10,"url":"audio/sfx/amb_storage.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":145.283}
|
||||
{"ev":"start","t":175453.69999998808,"sid":11,"url":"audio/sfx/pickup.ogg","layer":"sfx","dur":0.3470748299319728,"rate":1,"loop":false,"when":0,"ta":145.283}
|
||||
{"ev":"fetch","url":"audio/voice/female/found_key.ogg","status":200,"ok":true,"ms":3,"t":176256.69999998808,"ta":146.086}
|
||||
{"ev":"vstart","url":"audio/voice/female/found_key.ogg","t":176266.69999998808,"dur":9.96,"ta":146.096}
|
||||
{"ev":"vend","url":"audio/voice/female/found_key.ogg","t":186404.29999998212,"reason":"kill","ta":156.233}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_room_r.ogg","status":200,"ok":true,"ms":3,"t":186407.40000000596,"ta":156.237}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_room_r.ogg","t":186410.29999998212,"dur":1.28,"ta":156.239}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_room_r.ogg","t":188006.40000000596,"reason":"kill","ta":157.836}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":205702,"ta":175.531}
|
||||
{"ev":"vibrate","pattern":"[10]","t":206059.29999998212,"ta":175.888}
|
||||
{"ev":"start","t":206059.59999999404,"sid":12,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":175.889}
|
||||
{"ev":"start","t":206059.59999999404,"sid":13,"url":"audio/sfx/amb_wind.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":175.889}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":209469.5,"ta":179.299}
|
||||
{"ev":"vibrate","pattern":"[10]","t":209825.5,"ta":179.655}
|
||||
{"ev":"start","t":209825.90000000596,"sid":14,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":179.655}
|
||||
{"ev":"start","t":209825.90000000596,"sid":15,"url":"audio/sfx/amb_gate.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":179.655}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_gate.ogg","status":200,"ok":true,"ms":2,"t":209828,"ta":179.657}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_gate.ogg","t":209833,"dur":3.52,"ta":179.662}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":213236.40000000596,"ta":183.066}
|
||||
{"ev":"vibrate","pattern":"[10]","t":213592.19999998808,"ta":183.421}
|
||||
{"ev":"vend","url":"audio/voice/female/room_gate.ogg","t":213592.40000000596,"reason":"kill","ta":183.422}
|
||||
{"ev":"start","t":213592.59999999404,"sid":16,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":183.422}
|
||||
{"ev":"start","t":213592.59999999404,"sid":17,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":183.422}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_cabinet.ogg","status":200,"ok":true,"ms":3,"t":213595.19999998808,"ta":183.424}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_cabinet.ogg","t":213599.19999998808,"dur":2.64,"ta":183.428}
|
||||
{"ev":"vend","url":"audio/voice/female/room_cabinet.ogg","t":216309.29999998212,"reason":"kill","ta":186.138}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":222734.5,"ta":192.564}
|
||||
{"ev":"vibrate","pattern":"[20]","t":222982.59999999404,"ta":192.812}
|
||||
{"ev":"vibrate","pattern":"[100]","t":222982.90000000596,"ta":192.812}
|
||||
{"ev":"start","t":222983.29999998212,"sid":18,"url":"audio/sfx/unlock.ogg","layer":"sfx","dur":0.49777777777777776,"rate":1,"loop":false,"when":0,"ta":192.812}
|
||||
{"ev":"start","t":222983.29999998212,"sid":19,"url":"audio/sfx/door_creak.ogg","layer":"sfx","dur":1.3999773242630384,"rate":1,"loop":false,"when":0,"ta":192.812}
|
||||
{"ev":"fetch","url":"audio/voice/female/unlock_cabinet.ogg","status":200,"ok":true,"ms":3,"t":222985.59999999404,"ta":192.815}
|
||||
{"ev":"vstart","url":"audio/voice/female/unlock_cabinet.ogg","t":222997.40000000596,"dur":11.48,"ta":192.827}
|
||||
{"ev":"vend","url":"audio/voice/female/unlock_cabinet.ogg","t":234628.09999999404,"reason":"kill","ta":204.457}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_next_fuse.ogg","status":200,"ok":true,"ms":3,"t":234630.79999998212,"ta":204.46}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_next_fuse.ogg","t":234635.5,"dur":3.28,"ta":204.465}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_next_fuse.ogg","t":238087.59999999404,"reason":"kill","ta":207.917}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_room_l.ogg","status":200,"ok":true,"ms":3,"t":238090.40000000596,"ta":207.92}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_room_l.ogg","t":238093.5,"dur":1.68,"ta":207.923}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_room_l.ogg","t":239968.19999998808,"reason":"kill","ta":209.797}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":252754.09999999404,"ta":222.583}
|
||||
{"ev":"vibrate","pattern":"[20]","t":253003,"ta":222.832}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":253003.09999999404,"ta":222.832}
|
||||
{"ev":"fetch","url":"audio/voice/female/use_fail.ogg","status":200,"ok":true,"ms":3,"t":253005.69999998808,"ta":222.835}
|
||||
{"ev":"vstart","url":"audio/voice/female/use_fail.ogg","t":253013.29999998212,"dur":7.36,"ta":222.842}
|
||||
{"ev":"vend","url":"audio/voice/female/use_fail.ogg","t":260562.69999998808,"reason":"kill","ta":230.392}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_box_2.ogg","status":200,"ok":true,"ms":3,"t":260565.59999999404,"ta":230.395}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_box_2.ogg","t":260571.29999998212,"dur":4.88,"ta":230.4}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":263135.90000000596,"ta":232.965}
|
||||
{"ev":"vibrate","pattern":"[10]","t":263489.90000000596,"ta":233.319}
|
||||
{"ev":"start","t":263490.09999999404,"sid":20,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":233.319}
|
||||
{"ev":"start","t":263490.09999999404,"sid":21,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":233.319}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_box_2.ogg","t":265508.09999999404,"reason":"kill","ta":235.337}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":266899.09999999404,"ta":236.728}
|
||||
{"ev":"vibrate","pattern":"[10]","t":267256.7999999821,"ta":237.086}
|
||||
{"ev":"start","t":267257.09999999404,"sid":22,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":237.086}
|
||||
{"ev":"start","t":267257.09999999404,"sid":23,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":237.086}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":270667.09999999404,"ta":240.496}
|
||||
{"ev":"vibrate","pattern":"[10]","t":271023.40000000596,"ta":240.853}
|
||||
{"ev":"start","t":271023.7999999821,"sid":24,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":240.853}
|
||||
{"ev":"start","t":271023.7999999821,"sid":25,"url":"audio/sfx/amb_power.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":240.853}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_power.ogg","status":200,"ok":true,"ms":2,"t":271026,"ta":240.855}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_power.ogg","t":271030.2999999821,"dur":2.64,"ta":240.859}
|
||||
{"ev":"vend","url":"audio/voice/female/room_power.ogg","t":273750.5,"reason":"kill","ta":243.58}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":297793,"ta":267.622}
|
||||
{"ev":"vibrate","pattern":"[20]","t":298041.1999999881,"ta":267.87}
|
||||
{"ev":"vibrate","pattern":"[100]","t":298041.40000000596,"ta":267.871}
|
||||
{"ev":"start","t":298041.6999999881,"sid":26,"url":"audio/sfx/spark.ogg","layer":"sfx","dur":0.8970975056689342,"rate":1,"loop":false,"when":0,"ta":267.871}
|
||||
{"ev":"start","t":298041.6999999881,"sid":27,"url":"audio/sfx/power_on.ogg","layer":"sfx","dur":2.2,"rate":1,"loop":false,"when":0,"ta":267.871}
|
||||
{"ev":"fetch","url":"audio/voice/female/fix_box.ogg","status":200,"ok":true,"ms":2,"t":298043.90000000596,"ta":267.873}
|
||||
{"ev":"vstart","url":"audio/voice/female/fix_box.ogg","t":298051.7999999821,"dur":7.52,"ta":267.881}
|
||||
{"ev":"vend","url":"audio/voice/female/fix_box.ogg","t":305605.40000000596,"reason":"kill","ta":275.435}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_room_r.ogg","t":305605.59999999404,"dur":1.28,"ta":275.435}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_room_r.ogg","t":307207.59999999404,"reason":"kill","ta":277.037}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":308359.2999999821,"ta":278.188}
|
||||
{"ev":"vibrate","pattern":"[10]","t":308721.90000000596,"ta":278.551}
|
||||
{"ev":"start","t":308722.09999999404,"sid":28,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":278.551}
|
||||
{"ev":"start","t":308722.09999999404,"sid":29,"url":"audio/sfx/amb_wind.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":278.551}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":312131.6999999881,"ta":281.961}
|
||||
{"ev":"vibrate","pattern":"[10]","t":312488,"ta":282.317}
|
||||
{"ev":"start","t":312488.2999999821,"sid":30,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":282.317}
|
||||
{"ev":"start","t":312488.2999999821,"sid":31,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":282.317}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":315896.1999999881,"ta":285.725}
|
||||
{"ev":"vibrate","pattern":"[10]","t":316254.90000000596,"ta":286.084}
|
||||
{"ev":"start","t":316255.1999999881,"sid":32,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":286.084}
|
||||
{"ev":"start","t":316255.1999999881,"sid":33,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":286.084}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":325678.09999999404,"ta":295.507}
|
||||
{"ev":"vibrate","pattern":"[20]","t":326040.59999999404,"ta":295.87}
|
||||
{"ev":"start","t":326041,"sid":34,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":295.87}
|
||||
{"ev":"fetch","url":"audio/voice/female/empty_1.ogg","status":200,"ok":true,"ms":3,"t":326844.5,"ta":296.674}
|
||||
{"ev":"vstart","url":"audio/voice/female/empty_1.ogg","t":326851.2999999821,"dur":5.2,"ta":296.68}
|
||||
{"ev":"vend","url":"audio/voice/female/empty_1.ogg","t":332074,"reason":"kill","ta":301.903}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":335912.40000000596,"ta":305.742}
|
||||
{"ev":"vibrate","pattern":"[20]","t":336160,"ta":305.989}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":336160.1999999881,"ta":305.989}
|
||||
{"ev":"vstart","url":"audio/voice/female/use_fail.ogg","t":336160.2999999821,"dur":7.36,"ta":305.989}
|
||||
{"ev":"vend","url":"audio/voice/female/use_fail.ogg","t":343706.1999999881,"reason":"kill","ta":313.535}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_gate_2.ogg","status":200,"ok":true,"ms":3,"t":343708.90000000596,"ta":313.538}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_gate_2.ogg","t":343715.2999999821,"dur":5.44,"ta":313.544}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_gate_2.ogg","t":349394.6999999881,"reason":"kill","ta":319.224}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":369477.2999999821,"ta":339.306}
|
||||
{"ev":"vibrate","pattern":"[10]","t":369835.6999999881,"ta":339.665}
|
||||
{"ev":"start","t":369836,"sid":35,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":339.665}
|
||||
{"ev":"start","t":369836,"sid":36,"url":"audio/sfx/amb_gate_live.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":339.665}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":379260.40000000596,"ta":349.09}
|
||||
{"ev":"vibrate","pattern":"[20]","t":379623.90000000596,"ta":349.453}
|
||||
{"ev":"start","t":379624.2999999821,"sid":37,"url":"audio/sfx/amb_gate_live.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":349.453}
|
||||
{"ev":"fetch","url":"audio/voice/female/inspect_gate_ready.ogg","status":200,"ok":true,"ms":3,"t":380427.1999999881,"ta":350.256}
|
||||
{"ev":"vstart","url":"audio/voice/female/inspect_gate_ready.ogg","t":380436,"dur":8.72,"ta":350.265}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":388748.40000000596,"ta":358.578}
|
||||
{"ev":"vibrate","pattern":"[20]","t":388997.1999999881,"ta":358.826}
|
||||
{"ev":"vibrate","pattern":"[100]","t":388997.5,"ta":358.827}
|
||||
{"ev":"vend","url":"audio/voice/female/inspect_gate_ready.ogg","t":388998.09999999404,"reason":"kill","ta":358.827}
|
||||
{"ev":"fetch","url":"audio/voice/female/escape.ogg","status":200,"ok":true,"ms":3,"t":389000.59999999404,"ta":358.83}
|
||||
{"ev":"vstart","url":"audio/voice/female/escape.ogg","t":389013.90000000596,"dur":15.32,"ta":358.843}
|
||||
{"ev":"stop","t":391557.7999999821,"sid":1,"when":0,"ta":361.387}
|
||||
{"ev":"start","t":391599.09999999404,"sid":38,"url":"audio/sfx/gate_open.ogg","layer":"sfx","dur":2.7999773242630384,"rate":1,"loop":false,"when":0,"ta":361.428}
|
||||
{"ev":"start","t":391599.09999999404,"sid":39,"url":"audio/sfx/win_chime.ogg","layer":"sfx","dur":1.6,"rate":1,"loop":false,"when":0,"ta":361.428}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":399386.7999999821,"ta":369.216}
|
||||
{"ev":"vibrate","pattern":"[20]","t":399751,"ta":369.58}
|
||||
{"ev":"vend","url":"audio/voice/female/escape.ogg","t":399751.2999999821,"reason":"kill","ta":369.58}
|
||||
{"ev":"start","t":399751.59999999404,"sid":40,"url":"audio/bgm/drone.ogg","layer":"bgm","dur":117,"rate":1,"loop":true,"when":0,"ta":369.581}
|
||||
{"ev":"start","t":399751.59999999404,"sid":41,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":369.581}
|
||||
{"ev":"fetch","url":"audio/voice/female/replay.ogg","status":200,"ok":true,"ms":3,"t":399754.1999999881,"ta":369.583}
|
||||
{"ev":"vstart","url":"audio/voice/female/replay.ogg","t":399762.90000000596,"dur":8.24,"ta":369.592}
|
||||
{"ev":"vend","url":"audio/voice/female/replay.ogg","t":407950.6999999881,"reason":"kill","ta":377.78}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":460172.90000000596,"ta":430.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_ask.ogg","t":460173.1999999881,"dur":1.28,"ta":430.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_ask.ogg","t":461769.7999999821,"reason":"kill","ta":431.599}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_1.ogg","t":461769.7999999821,"dur":2.88,"ta":431.599}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_1.ogg","t":464764.90000000596,"reason":"kill","ta":434.594}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":520173,"ta":490.002}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_key_2.ogg","status":200,"ok":true,"ms":3,"t":520176.09999999404,"ta":490.005}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_2.ogg","t":520182.5,"dur":4.48,"ta":490.012}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_2.ogg","t":524760.099999994,"reason":"kill","ta":494.589}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":580172.900000006,"ta":550.002}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_key_3.ogg","status":200,"ok":true,"ms":3,"t":580175.7999999821,"ta":550.005}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":580180.099999994,"dur":3.12,"ta":550.009}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":583641,"reason":"kill","ta":553.47}
|
||||
{"ev":"fetch","url":"audio/voice/female/nav_left.ogg","status":200,"ok":true,"ms":3,"t":583643.6999999881,"ta":553.473}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":583646.7999999821,"dur":1.28,"ta":553.476}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":585243.099999994,"reason":"kill","ta":555.072}
|
||||
{"ev":"fetch","url":"audio/voice/female/nav_down.ogg","status":200,"ok":true,"ms":3,"t":585245.6999999881,"ta":555.075}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":585248.599999994,"dur":0.9570975056689343,"ta":555.078}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":586380.7999999821,"reason":"kill","ta":556.21}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":640172.900000006,"ta":610.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":640173.099999994,"dur":3.12,"ta":610.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":643636.5,"reason":"kill","ta":613.466}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":643636.599999994,"dur":1.28,"ta":613.466}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":645238.6999999881,"reason":"kill","ta":615.068}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":645238.6999999881,"dur":0.9570975056689343,"ta":615.068}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":646376,"reason":"kill","ta":616.205}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":700173,"ta":670.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":700173.099999994,"dur":3.12,"ta":670.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":703631.6999999881,"reason":"kill","ta":673.461}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":703631.7999999821,"dur":1.28,"ta":673.461}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":705233.6999999881,"reason":"kill","ta":675.063}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":705233.7999999821,"dur":0.9570975056689343,"ta":675.063}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":706371.2999999821,"reason":"kill","ta":676.2}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":760173,"ta":730.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":760173.099999994,"dur":3.12,"ta":730.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":763627,"reason":"kill","ta":733.456}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":763627,"dur":1.28,"ta":733.456}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":765228.900000006,"reason":"kill","ta":735.058}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":765229,"dur":0.9570975056689343,"ta":735.058}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":766366.6999999881,"reason":"kill","ta":736.196}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":820172.900000006,"ta":790.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":820173.1999999881,"dur":3.12,"ta":790.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":823622.2999999821,"reason":"kill","ta":793.451}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":823622.400000006,"dur":1.28,"ta":793.452}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":825224.5,"reason":"kill","ta":795.054}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":825224.5,"dur":0.9570975056689343,"ta":795.054}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":826362,"reason":"kill","ta":796.191}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":880173.099999994,"ta":850.002}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_key_3.ogg","t":880173.2999999821,"dur":3.12,"ta":850.002}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_key_3.ogg","t":883617.6999999881,"reason":"kill","ta":853.447}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_left.ogg","t":883617.7999999821,"dur":1.28,"ta":853.447}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_left.ogg","t":885219.900000006,"reason":"kill","ta":855.049}
|
||||
{"ev":"vstart","url":"audio/voice/female/nav_down.ogg","t":885220,"dur":0.9570975056689343,"ta":855.049}
|
||||
{"ev":"vend","url":"audio/voice/female/nav_down.ogg","t":886357.2999999821,"reason":"kill","ta":856.186}
|
||||
{"ev":"recstop","t":918408.5,"ta":888.238}
|
||||
@@ -0,0 +1,346 @@
|
||||
# escape 实时会话 transcript
|
||||
|
||||
- `[ 0.00s]` REC 开始 (audio/webm;codecs=opus)
|
||||
- `[ 0.09s]` VOICE ▶ g0_intro (dur 6.64s)
|
||||
- `[ 0.28s]` BGM ♪ drone (loop)
|
||||
- `[ 6.90s]` VOICE ■ g0_intro (kill)
|
||||
- `[ 6.90s]` VERDICT g0_intro: **OK** sim=1
|
||||
- 期望: 黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。
|
||||
- 听到: 黑暗,你在废弃的地下设施里醒来,什么都想不起来,你必须找到出路。
|
||||
- `[ 8.10s]` VOICE ▶ g1_move (dur 4.56s)
|
||||
- `[ 12.68s]` VOICE ■ g1_move (kill)
|
||||
- `[ 12.68s]` VOICE ▶ skip_hint (dur 1.6s)
|
||||
- `[ 12.68s]` VERDICT g1_move: **OK** sim=0.9697
|
||||
- 期望: 先活动一下。朝任意方向滑一下,走一小步。
|
||||
- 听到: 先活动一下,朝任意方向滑一下,走一小。
|
||||
- `[ 14.28s]` VOICE ■ skip_hint (kill)
|
||||
- `[ 14.28s]` VERDICT skip_hint: **OK** sim=0.7143
|
||||
- 期望: 单击可跳过旁白。
|
||||
- 听到: 单机可跳过旁本。
|
||||
- `[ 34.52s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 34.88s]` VIBRATE [10]
|
||||
- `[ 34.88s]` SFX ♪ step
|
||||
- `[ 34.88s]` VOICE ▶ g1_done (dur 2.72s)
|
||||
- `[ 34.88s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 37.59s]` VOICE ■ g1_done (kill)
|
||||
- `[ 37.59s]` VERDICT g1_done: **OK** sim=0.9412
|
||||
- 期望: 很好,你迈出了第一步。
|
||||
- 听到: 很好,你迈出了第一。
|
||||
- `[ 37.60s]` VOICE ▶ g2_wall (dur 5.68s)
|
||||
- `[ 41.57s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 41.93s]` VIBRATE [10]
|
||||
- `[ 43.28s]` VOICE ■ g2_wall (kill)
|
||||
- `[ 43.28s]` VERDICT g2_wall: **OK** sim=0.9268
|
||||
- 期望: 这个房间不大,四面都是墙。再滑两下,试试碰碰墙。
|
||||
- 听到: 一、这个房间不大,四面都是墙,再划两下试试碰碰墙。
|
||||
- `[ 46.34s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 46.69s]` VIBRATE [10]
|
||||
- `[ 46.69s]` VIBRATE [60,40,60]
|
||||
- `[ 46.69s]` SFX ♪ wall
|
||||
- `[ 46.70s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 46.70s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 49.04s]` VOICE ■ wall (kill)
|
||||
- `[ 49.04s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 53.66s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 54.01s]` VIBRATE [10]
|
||||
- `[ 54.01s]` VIBRATE [60,40,60]
|
||||
- `[ 54.01s]` SFX ♪ wall
|
||||
- `[ 54.01s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 54.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 56.35s]` VOICE ■ wall (kill)
|
||||
- `[ 56.35s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 56.36s]` VOICE ▶ g3_left (dur 2.96s)
|
||||
- `[ 59.34s]` VOICE ■ g3_left (kill)
|
||||
- `[ 59.34s]` VERDICT g3_left: **OK** sim=0.9
|
||||
- 期望: 跟着我指的路走。向左滑。
|
||||
- 听到: 跟着我指的路走向左画。
|
||||
- `[ 60.92s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 61.28s]` VIBRATE [10]
|
||||
- `[ 61.28s]` VOICE ▶ guide_skip (dur 2.88s)
|
||||
- `[ 61.28s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 64.27s]` VOICE ■ guide_skip (kill)
|
||||
- `[ 64.27s]` VOICE ▶ start_room (dur 7.2s)
|
||||
- `[ 64.27s]` VERDICT guide_skip: **OK** sim=1
|
||||
- 期望: 跳过引导,直接开始自由探索。
|
||||
- 听到: 跳过引导,直接开始自由探索。
|
||||
- `[ 64.27s]` SFX ♪ amb_drip
|
||||
- `[ 71.81s]` VOICE ■ start_room (kill)
|
||||
- `[ 71.81s]` VERDICT start_room: **OK** sim=1
|
||||
- 期望: 你站在设施中央的房间里。滑动移动,单击检查,双击使用物品。
|
||||
- 听到: 你站在设施中央的房间里滑动移动,单击检查,双击使用物品。
|
||||
- `[ 125.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 125.01s]` VOICE ▶ stuck_ask (dur 1.28s)
|
||||
- `[ 125.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 126.61s]` VOICE ■ stuck_ask (kill)
|
||||
- `[ 126.61s]` VERDICT stuck_ask: **OK** sim=0.9091
|
||||
- 期望: 需要帮助吗?
|
||||
- 听到: 需要我帮助吗?
|
||||
- `[ 126.61s]` VOICE ▶ stuck_key_1 (dur 2.88s)
|
||||
- `[ 129.60s]` VOICE ■ stuck_key_1 (kill)
|
||||
- `[ 129.60s]` VERDICT stuck_key_1: **OK** sim=0.9231
|
||||
- 期望: 铁锈味最重的地方,值得仔细看看。
|
||||
- 听到: 铁锈味最重的地方值得仔细。
|
||||
- `[ 130.87s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 131.22s]` VIBRATE [10]
|
||||
- `[ 131.22s]` SFX ♪ step
|
||||
- `[ 131.22s]` SFX ♪ amb_hum
|
||||
- `[ 137.65s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 138.01s]` VIBRATE [10]
|
||||
- `[ 138.01s]` SFX ♪ step
|
||||
- `[ 138.01s]` SFX ♪ amb_storage
|
||||
- `[ 138.02s]` VOICE ▶ room_storage (dur 5.36s)
|
||||
- `[ 138.02s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 143.70s]` VOICE ■ room_storage (kill)
|
||||
- `[ 143.70s]` VERDICT room_storage: **OK** sim=1
|
||||
- 期望: 一间储物间。货架上堆满杂物,角落里传来水滴声。
|
||||
- 听到: 一间储物间货架上堆满杂物,角落里传来水滴声。
|
||||
- `[ 144.92s]` **GESTURE** tap @(195,422)
|
||||
- `[ 145.28s]` VIBRATE [20]
|
||||
- `[ 145.28s]` VIBRATE [15]
|
||||
- `[ 145.28s]` SFX ♪ amb_storage
|
||||
- `[ 145.28s]` SFX ♪ pickup
|
||||
- `[ 146.10s]` VOICE ▶ found_key (dur 9.96s)
|
||||
- `[ 146.10s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 156.23s]` VOICE ■ found_key (kill)
|
||||
- `[ 156.23s]` VERDICT found_key: **OK** sim=1
|
||||
- 期望: 你蹲下身在储物架的角落里摸索,指尖碰到一个冰凉的金属物件——是一把钥匙!钥匙到手了。
|
||||
- 听到: 你蹲下身,在储物架的角落里摸索,指尖碰到一个冰凉的金属物件,是一把钥匙,钥匙到手了。
|
||||
- `[ 156.24s]` VOICE ▶ gd_room_r (dur 1.28s)
|
||||
- `[ 157.84s]` VOICE ■ gd_room_r (kill)
|
||||
- `[ 157.84s]` VERDICT gd_room_r: **OK** sim=1
|
||||
- 期望: 右面的房间。
|
||||
- 听到: 右面的房间。
|
||||
- `[ 175.53s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 175.89s]` VIBRATE [10]
|
||||
- `[ 175.89s]` SFX ♪ step
|
||||
- `[ 175.89s]` SFX ♪ amb_wind
|
||||
- `[ 179.30s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 179.66s]` VIBRATE [10]
|
||||
- `[ 179.66s]` SFX ♪ step
|
||||
- `[ 179.66s]` SFX ♪ amb_gate
|
||||
- `[ 179.66s]` VOICE ▶ room_gate (dur 3.52s)
|
||||
- `[ 179.66s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 183.07s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 183.42s]` VIBRATE [10]
|
||||
- `[ 183.42s]` VOICE ■ room_gate (kill)
|
||||
- `[ 183.42s]` SFX ♪ step
|
||||
- `[ 183.42s]` SFX ♪ amb_cabinet
|
||||
- `[ 183.42s]` VERDICT room_gate: **OK** sim=1
|
||||
- 期望: 面前,是一扇沉重的铁门。
|
||||
- 听到: 面前是一扇沉重的铁门。
|
||||
- `[ 183.43s]` VOICE ▶ room_cabinet (dur 2.64s)
|
||||
- `[ 186.14s]` VOICE ■ room_cabinet (kill)
|
||||
- `[ 186.14s]` VERDICT room_cabinet: **OK** sim=1
|
||||
- 期望: 这个房间里,立着一个铁柜。
|
||||
- 听到: 这个房间里立着一个铁柜。
|
||||
- `[ 192.56s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 192.81s]` VIBRATE [20]
|
||||
- `[ 192.81s]` VIBRATE [100]
|
||||
- `[ 192.81s]` SFX ♪ unlock
|
||||
- `[ 192.81s]` SFX ♪ door_creak
|
||||
- `[ 192.83s]` VOICE ▶ unlock_cabinet (dur 11.48s)
|
||||
- `[ 192.83s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 204.46s]` VOICE ■ unlock_cabinet (kill)
|
||||
- `[ 204.46s]` VERDICT unlock_cabinet: **OK** sim=0.9714
|
||||
- 期望: 钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。
|
||||
- 听到: 钥匙插进锁孔,缓缓转动,咔嗒一声,柜门开了,柜子深处躺着一枚保险丝,保险丝到手了。
|
||||
- `[ 204.47s]` VOICE ▶ gd_next_fuse (dur 3.28s)
|
||||
- `[ 207.92s]` VOICE ■ gd_next_fuse (kill)
|
||||
- `[ 207.92s]` VERDICT gd_next_fuse: **OK** sim=1
|
||||
- 期望: 保险丝到手。接下来,去找电箱。
|
||||
- 听到: 保险丝到手,接下来去找电箱。
|
||||
- `[ 207.92s]` VOICE ▶ gd_room_l (dur 1.68s)
|
||||
- `[ 209.80s]` VOICE ■ gd_room_l (kill)
|
||||
- `[ 209.80s]` VERDICT gd_room_l: **OK** sim=1
|
||||
- 期望: 左面的房间。
|
||||
- 听到: 左面的房间。
|
||||
- `[ 222.58s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 222.83s]` VIBRATE [20]
|
||||
- `[ 222.83s]` VIBRATE [60,40,60]
|
||||
- `[ 222.84s]` VOICE ▶ use_fail (dur 7.36s)
|
||||
- `[ 222.84s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 230.39s]` VOICE ■ use_fail (kill)
|
||||
- `[ 230.39s]` VERDICT use_fail: **OK** sim=0.9655
|
||||
- 期望: 这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。
|
||||
- 听到: 这里没有用得上东西的地方,换个房间试试,或者先单机检查一下周围。
|
||||
- `[ 230.40s]` VOICE ▶ stuck_box_2 (dur 4.88s)
|
||||
- `[ 232.97s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 233.32s]` VIBRATE [10]
|
||||
- `[ 233.32s]` SFX ♪ step
|
||||
- `[ 233.32s]` SFX ♪ amb_drip
|
||||
- `[ 235.34s]` VOICE ■ stuck_box_2 (kill)
|
||||
- `[ 235.34s]` VERDICT stuck_box_2: **OK** sim=1
|
||||
- 期望: 去西北角的电箱房,双击,把保险丝装进电箱。
|
||||
- 听到: 去西北角的电箱房,双击把保险丝装进电箱。
|
||||
- `[ 236.73s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 237.09s]` VIBRATE [10]
|
||||
- `[ 237.09s]` SFX ♪ step
|
||||
- `[ 237.09s]` SFX ♪ amb_hum
|
||||
- `[ 240.50s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 240.85s]` VIBRATE [10]
|
||||
- `[ 240.85s]` SFX ♪ step
|
||||
- `[ 240.85s]` SFX ♪ amb_power
|
||||
- `[ 240.86s]` VOICE ▶ room_power (dur 2.64s)
|
||||
- `[ 240.86s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 243.58s]` VOICE ■ room_power (kill)
|
||||
- `[ 243.58s]` VERDICT room_power: **OK** sim=1
|
||||
- 期望: 这个房间的墙上,有一只电箱。
|
||||
- 听到: 这个房间的墙上有一只电箱。
|
||||
- `[ 267.62s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 267.87s]` VIBRATE [20]
|
||||
- `[ 267.87s]` VIBRATE [100]
|
||||
- `[ 267.87s]` SFX ♪ spark
|
||||
- `[ 267.87s]` SFX ♪ power_on
|
||||
- `[ 267.88s]` VOICE ▶ fix_box (dur 7.52s)
|
||||
- `[ 267.88s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 275.44s]` VOICE ■ fix_box (kill)
|
||||
- `[ 275.44s]` VOICE ▶ gd_room_r (dur 1.28s)
|
||||
- `[ 275.44s]` VERDICT fix_box: **OK** sim=0.9492
|
||||
- 期望: 你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了!
|
||||
- 听到: 你把保险丝用力按静卡座,火花一闪,嗡鸣声响起,头顶的线路恢复供电。
|
||||
- `[ 277.04s]` VOICE ■ gd_room_r (kill)
|
||||
- `[ 277.04s]` VERDICT gd_room_r: **OK** sim=0.75
|
||||
- 期望: 右面的房间。
|
||||
- 听到: 右面的。
|
||||
- `[ 278.19s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 278.55s]` VIBRATE [10]
|
||||
- `[ 278.55s]` SFX ♪ step
|
||||
- `[ 278.55s]` SFX ♪ amb_wind
|
||||
- `[ 281.96s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 282.32s]` VIBRATE [10]
|
||||
- `[ 282.32s]` SFX ♪ step
|
||||
- `[ 282.32s]` SFX ♪ amb_hum
|
||||
- `[ 285.73s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 286.08s]` VIBRATE [10]
|
||||
- `[ 286.08s]` SFX ♪ step
|
||||
- `[ 286.08s]` SFX ♪ amb_cabinet
|
||||
- `[ 295.51s]` **GESTURE** tap @(195,422)
|
||||
- `[ 295.87s]` VIBRATE [20]
|
||||
- `[ 295.87s]` SFX ♪ amb_cabinet
|
||||
- `[ 296.68s]` VOICE ▶ empty_1 (dur 5.2s)
|
||||
- `[ 296.68s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 301.90s]` VOICE ■ empty_1 (kill)
|
||||
- `[ 301.90s]` VERDICT empty_1: **OK** sim=1
|
||||
- 期望: 房间里空空荡荡,只有你自己的回声。
|
||||
- 听到: 房间里空空荡荡,只有你自己的回声。
|
||||
- `[ 305.74s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 305.99s]` VIBRATE [20]
|
||||
- `[ 305.99s]` VIBRATE [60,40,60]
|
||||
- `[ 305.99s]` VOICE ▶ use_fail (dur 7.36s)
|
||||
- `[ 305.99s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 313.54s]` VOICE ■ use_fail (kill)
|
||||
- `[ 313.54s]` VERDICT use_fail: **OK** sim=0.9655
|
||||
- 期望: 这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。
|
||||
- 听到: 这里没有用得上东西的地方,换个房间试试,或者先单机检查一下周围。
|
||||
- `[ 313.54s]` VOICE ▶ stuck_gate_2 (dur 5.44s)
|
||||
- `[ 319.22s]` VOICE ■ stuck_gate_2 (kill)
|
||||
- `[ 319.22s]` VERDICT stuck_gate_2: **OK** sim=1
|
||||
- 期望: 去东南角的大门,双击,打开它,离开这里。
|
||||
- 听到: 去东南角的大门,双击打开它,离开这里。
|
||||
- `[ 339.31s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 339.67s]` VIBRATE [10]
|
||||
- `[ 339.67s]` SFX ♪ step
|
||||
- `[ 339.67s]` SFX ♪ amb_gate_live
|
||||
- `[ 349.09s]` **GESTURE** tap @(195,422)
|
||||
- `[ 349.45s]` VIBRATE [20]
|
||||
- `[ 349.45s]` SFX ♪ amb_gate_live
|
||||
- `[ 350.26s]` VOICE ▶ inspect_gate_ready (dur 8.72s)
|
||||
- `[ 350.26s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 358.58s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 358.83s]` VIBRATE [20]
|
||||
- `[ 358.83s]` VIBRATE [100]
|
||||
- `[ 358.83s]` VOICE ■ inspect_gate_ready (kill)
|
||||
- `[ 358.83s]` VERDICT inspect_gate_ready: **TRUNCATED** sim=0.9667
|
||||
- 期望: 电子锁的指示灯亮了,发出微弱的绿光。大门已经通电。双击,打开它,离开这里。
|
||||
- 听到: 电子锁的指示灯亮了,发出微弱的绿光,大门已经通电,双击打开它,离开。
|
||||
- `[ 358.84s]` VOICE ▶ escape (dur 15.32s)
|
||||
- `[ 361.43s]` SFX ♪ gate_open
|
||||
- `[ 361.43s]` SFX ♪ win_chime
|
||||
- `[ 369.22s]` **GESTURE** tap @(195,422)
|
||||
- `[ 369.58s]` VIBRATE [20]
|
||||
- `[ 369.58s]` VOICE ■ escape (kill)
|
||||
- `[ 369.58s]` VERDICT escape: **TRUNCATED** sim=0.7711
|
||||
- 期望: 你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。
|
||||
- 听到: 开你搬动开关,电击轰,沉重的铁门缓缓升起,刺眼的光线涌了进来,你眯起眼睛向前迈。
|
||||
- `[ 369.58s]` BGM ♪ drone (loop)
|
||||
- `[ 369.58s]` SFX ♪ amb_drip
|
||||
- `[ 369.59s]` VOICE ▶ replay (dur 8.24s)
|
||||
- `[ 377.78s]` VOICE ■ replay (kill)
|
||||
- `[ 377.78s]` VERDICT replay: **OK** sim=0.9545
|
||||
- 期望: 黑暗再次合拢。你回到了中央的房间。这一次,你会更快。
|
||||
- 听到: 前黑暗再次合拢,你回到了中央的房间,这一次你会更。
|
||||
- `[ 430.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 430.00s]` VOICE ▶ stuck_ask (dur 1.28s)
|
||||
- `[ 430.00s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 431.60s]` VOICE ■ stuck_ask (kill)
|
||||
- `[ 431.60s]` VOICE ▶ stuck_key_1 (dur 2.88s)
|
||||
- `[ 431.60s]` VERDICT stuck_ask: **OK** sim=0.9091
|
||||
- 期望: 需要帮助吗?
|
||||
- 听到: 需要我帮助吗?
|
||||
- `[ 434.59s]` VOICE ■ stuck_key_1 (kill)
|
||||
- `[ 434.59s]` VERDICT stuck_key_1: **OK** sim=0.9286
|
||||
- 期望: 铁锈味最重的地方,值得仔细看看。
|
||||
- 听到: 铁修味最重的地方,值得仔细看看。
|
||||
- `[ 490.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 490.01s]` VOICE ▶ stuck_key_2 (dur 4.48s)
|
||||
- `[ 490.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 494.59s]` VOICE ■ stuck_key_2 (kill)
|
||||
- `[ 494.59s]` VERDICT stuck_key_2: **OK** sim=1
|
||||
- 期望: 去西南角的储物间,单击检查,找到钥匙。
|
||||
- 听到: 去西南角的储物间单击检查,找到钥匙。
|
||||
- `[ 550.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 550.01s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 550.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 553.47s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 553.47s]` VERDICT stuck_key_3: **OK** sim=1
|
||||
- 期望: 跟我说的方向走,去西南角的储物间。
|
||||
- 听到: 跟我说的方向走,去西南角的储物间。
|
||||
- `[ 553.48s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 555.07s]` VOICE ■ nav_left (kill)
|
||||
- `[ 555.07s]` VERDICT nav_left: **OK** sim=1
|
||||
- 期望: 向左滑。
|
||||
- 听到: 向左滑。
|
||||
- `[ 555.08s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 556.21s]` VOICE ■ nav_down (kill)
|
||||
- `[ 556.21s]` VERDICT nav_down: **OK** sim=1
|
||||
- 期望: 向下滑。
|
||||
- 听到: 向下滑。
|
||||
- `[ 610.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 610.00s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 613.47s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 613.47s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 615.07s]` VOICE ■ nav_left (kill)
|
||||
- `[ 615.07s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 616.21s]` VOICE ■ nav_down (kill)
|
||||
- `[ 670.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 670.00s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 673.46s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 673.46s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 675.06s]` VOICE ■ nav_left (kill)
|
||||
- `[ 675.06s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 676.20s]` VOICE ■ nav_down (kill)
|
||||
- `[ 730.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 730.00s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 733.46s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 733.46s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 735.06s]` VOICE ■ nav_left (kill)
|
||||
- `[ 735.06s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 736.20s]` VOICE ■ nav_down (kill)
|
||||
- `[ 790.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 790.00s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 793.45s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 793.45s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 795.05s]` VOICE ■ nav_left (kill)
|
||||
- `[ 795.05s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 796.19s]` VOICE ■ nav_down (kill)
|
||||
- `[ 850.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 850.00s]` VOICE ▶ stuck_key_3 (dur 3.12s)
|
||||
- `[ 853.45s]` VOICE ■ stuck_key_3 (kill)
|
||||
- `[ 853.45s]` VOICE ▶ nav_left (dur 1.28s)
|
||||
- `[ 855.05s]` VOICE ■ nav_left (kill)
|
||||
- `[ 855.05s]` VOICE ▶ nav_down (dur 0.9570975056689343s)
|
||||
- `[ 856.19s]` VOICE ■ nav_down (kill)
|
||||
@@ -0,0 +1,64 @@
|
||||
# P1 视障资深玩家评审:《暗室》(escape-state 取证轮 R1)
|
||||
|
||||
> 评审依据:`live-transcript.md`(真机 live 一局,SenseVoice 转写,行号即该文件行)+
|
||||
> `transcript-mock.md`(mock 新手局转写)。本轮只聚焦一个问题:**哪些时刻我
|
||||
> 不知道自己在哪 / 该干嘛 / 进展到哪**。我读的是转写,按"如果是我戴着耳机在
|
||||
> 75 档语速下听到这些"代入;ASR 近失(如"单机"→"单击")不计入缺陷。
|
||||
|
||||
### 暗室
|
||||
- 状态感知:2/5 —— 引导期每秒都有指令带路,状态满格;一进自由探索就开始
|
||||
失聪。**①撞墙只有"那边是墙",没有方位**(live 行 40-55):我在 (0,0) 连撞
|
||||
两次,听到的句子一字不差,但我的地图上一个标记都没增加——我不知道刚才是
|
||||
哪面墙,只知道"此路不通"。**②空房声学 identical**:(0,1) 是 amb_hum(行 90),
|
||||
后来 (2,0) 也是 amb_hum(行 182);(1,2) amb_wind(行 120),(1,0) 也是
|
||||
amb_wind(行 212)。四间空房两种音,我对着转写都对不出哪间是哪间,耳朵更
|
||||
不可能。**③重访已探索房间零语音**:我重返铁柜房时(行 220、223)只听到
|
||||
环境音,"这个房间里立着一个铁柜"是首到专属——我作为记图全靠耳朵的人,
|
||||
第二次经过没有任何"我来过这"的锚。
|
||||
- 下一步明确性:3/5 —— 进展事件当下很明确:found_key 后接"右面的房间。"
|
||||
(行 112-116),unlock 后"左面的房间。"(行 156-160),修电箱后"右面的房间。"
|
||||
(行 201-208)——链条本身做得好。但有两个洞:**①方向句没有目标名**:
|
||||
"右面的房间。"——右面是哪?我下一秒要干什么?我手里钥匙对应的是铁柜,
|
||||
句子不说,得我赌。**②引导期手势被静默吞掉**(行 30-35):g2_wall 还没播完
|
||||
我滑了一下,只收到引擎一声 [10] 轻震,墙没响、计数没走——我这一滑到底算数
|
||||
吗?教科书式的无声失败。如果我信了这一下、只再补一滑,就永远卡在 G2。
|
||||
- 愿意继续玩:是 —— 解谜链手感对(双击使用、震动脉络清楚),但我要先能
|
||||
建出自己的地图才谈得上"探索",现在建图材料不够。
|
||||
- P0 问题(不知道自己在哪/该干嘛/进展到哪的具体时刻):
|
||||
1. **跳过引导后目标全丢**(行 61-74):swipedown 被当成跳过(G3 下滑=跳过
|
||||
是设计,但我是在引导语音刚说完"向左滑"之后、还没作答时滑错的),然后
|
||||
`guide_skip` + `start_room` 两句了事——**"找到能用钥匙打开的东西"这句
|
||||
目标陈述我一辈子没听到**(g7_goal 只存在于引导链尾)。开局 64s 起我站
|
||||
在 (1,1),知道三个手势,不知道要干什么。
|
||||
2. **主动查状态被直接喂答案**(行 161-178、230-243):我双击铁柜房(柜已开、
|
||||
手里是保险丝),只是想知道"我现在该干嘛",游戏播 use_fail 之后直接上
|
||||
`stuck_box_2`「去西北角的电箱房,双击,把保险丝装进电箱」——L2 明示是
|
||||
给卡关 120 秒的人的,我没卡关,谜题被白送。这是提示泄漏,也是唯一一个
|
||||
"主动查询"入口被做成答案分发口。
|
||||
3. **地图进度无账本**:全 9 房走了 7 房,没有任何一句告诉我"钥匙✓、铁柜✓、
|
||||
电✓、还差大门"——进展播报只在进展事件当下播一次(found_key 链等),
|
||||
中途无法回查(escape 连上滑状态键都没有,00 §5.3 豁免表)。
|
||||
- 建议(按对"我愿意玩下去"的影响排序):
|
||||
1. 给 escape 一个 L0 级进度重述通道(不泄题:报"已完成几环/还差几环"),
|
||||
取代双击兜底直通 L2 的现状(见 25 号文档 B3/B5)。
|
||||
2. 撞墙报方位但用陈述句(「左边是墙。」),别再走"手指贴着屏幕推"教学腔
|
||||
(round1-live 回退原因我同意,但方位本身是该给的,见 B1)。
|
||||
3. 目标方位句并入目标名(「铁柜,在右面的房间。」),并给四间空房各自
|
||||
可分辨的声学签名或首访方位线索句(见 B4/B6)。
|
||||
|
||||
#### 听觉惯例符合度(逐条核对特别检查项)
|
||||
- 语音可打断:过。单击跳句机制干净,关键获得链(found_key/unlock/fix_box)
|
||||
不可跳有事件层兜住(行 106-116 链完整)。
|
||||
- 语音可重听:过。单击检查=重播环境音+描述,空房也可重听。
|
||||
- 等待有无声:**半不过**。行 72 的 3s 静默是设计内的"辨方向",可以;但自由
|
||||
探索期最长的静默段(行 87-94 我在空房之间移动)只有脚步声和环境音——
|
||||
这不是"死寂",是"零信息",比死寂更糟:我一直在动,游戏一直说话(环境音),
|
||||
可我什么也学不到。
|
||||
- 失败可否归因:半过。撞墙可归因(有闷响+error 震+短句),但**被吞手势不可
|
||||
归因**(行 30-35)——引导 busy 窗口是静默 return,震都没有第二声。
|
||||
- 菜单列表导航:未验证(结算后我直接重开,没进菜单)。
|
||||
- status key:**缺席**。PLAY 期上滑=移动,全游戏无任何时刻查询"我在哪/我
|
||||
有什么/还剩几环"——这是我这个人设最依赖的锚,本作没有。双击兜底本可补位,
|
||||
现状是答案泄漏口(见 P0-2)。
|
||||
- 提示永不逐字重复:过。L3 带路每 60s 重算重播但坐标若没变内容相同属合理
|
||||
(行 295-346 从 (1,1) 重复带路,玩家没动当然重复同一路线)。
|
||||
@@ -0,0 +1,51 @@
|
||||
# P3 时间紧张的白领评审:《暗室》(escape-state 取证轮 R1)
|
||||
|
||||
> 评审依据:`live-transcript.md`(真机 live 一局)+ `transcript-mock.md`(mock
|
||||
> 新手局)。本轮只聚焦一个问题:**哪些时刻我不知道自己在哪 / 该干嘛 / 进展
|
||||
> 到哪**。我代入的场景是地铁单程 25 分钟、站立单手持机、随时可能被打断——
|
||||
> 被打断后能不能一句话接上,是我的生死线。
|
||||
|
||||
### 暗室
|
||||
- 状态感知:2/5 —— 我被 put off 的第一个时刻是**空房 transit**:行 87-94
|
||||
我从起点滑到储物间,中间经过 (0,1) 只有脚步+嗡鸣,两行事件、零句话;
|
||||
行 179-186、209-220 同理((0,1)→(0,0)、(1,0)→(2,0)→(2,1) 全是静默移动)。
|
||||
地铁里听不清环境音细节,这几段对我来说就是"盲滑"。**撞了墙也不知道方位**
|
||||
(行 40-55):"那边是墙"告诉我此路不通,不告诉我我刚才想去哪——单手持机
|
||||
滑错方向太常见了,每次错都学不到东西。
|
||||
- 下一步明确性:3/5 —— 好消息是**进展链很会带路**:拿到钥匙接"右面的房间。"
|
||||
(行 112-116)、开柜接"左面的房间。"(行 156-160)、修电箱接"右面的房间。"
|
||||
(行 201-208),只要我在解谜链上,永远不迷路。坏消息有二:**①方向句无
|
||||
目标名**:地铁里"右面的房间。"(1.3s 短句)极易被车厢噪音盖住前半句,
|
||||
我只听到"……的房间",不知道去找什么(行 206-208 的 ASR sim 只有 0.75,
|
||||
正是短句被环境吃掉的实证)。**②被打断恢复无锚**:行 253-275 我双击大门
|
||||
之后结算链 escape 刚播 10 秒,我一个习惯性单击(想确认是不是要操作)直接
|
||||
重开——time_band 和 again 都没播,我连自己通关用时多少都不知道就进下一局
|
||||
了。25 分钟通勤被打断 3 次就会这样 3 次。
|
||||
- 愿意继续玩:否 —— 单局 6 分钟节奏其实合适,但我每次被打断回来都要重新
|
||||
摸一遍地图,"一句话接上"做不到。
|
||||
- P0 问题(不知道自己在哪/该干嘛/进展到哪的具体时刻):
|
||||
1. **结算链无保护**(行 253-275):ENDING 单击无条件重开,结算语音播一半
|
||||
就没了(行 266 TRUNCATED sim 0.77)——我作为"随时被打断"的人,结算
|
||||
是我唯一确认"我打完了/打得如何"的窗口,这个窗口一碰就碎。
|
||||
2. **目标句短且无名**(行 112-116):嘈杂环境下 1.3s 的"右面的房间。"承载
|
||||
不了关键导航信息;该把目标名并进整句("铁柜在右面的房间"信息量翻倍、
|
||||
时长只多 1 秒)。
|
||||
3. **跳过引导=目标全丢**(行 61-74):误触下滑跳过之后只有 start_room 的
|
||||
手势总览,没有任何目标提示;我这种没耐心的玩家正是最容易跳过引导的人,
|
||||
跳过之后 60 秒(行 75-86)才等到第一句 L1 暗示。开局一分钟是纯摸黑。
|
||||
- 建议(按对"我愿意玩下去"的影响排序):
|
||||
1. 结算链播完前单击重开加守卫(或单击=跳过下一不可跳句的确认):我要听完
|
||||
用时播报(见 25 号文档 B8)。
|
||||
2. 目标方位句并入目标名并重录(「铁柜,在右面的房间。」,见 B4)。
|
||||
3. 跳过引导的确认句后补播 g7_goal 目标句(资产现成,见 B9);撞墙给陈述式
|
||||
方位句(见 B1),让我每次失误都变成地图信息。
|
||||
|
||||
#### 通勤场景符合度(逐条核对特别检查项)
|
||||
- 3 分钟内有没有一次完整乐趣:有——mock 局 35s 就到电箱房、2 分钟内通关的
|
||||
关键路径存在(mock 行 144-149),链式解谜本身爽点密。
|
||||
- 被打断后能不能一句话接上:**不能**(见 P0-1/P0-3),这是唯一硬伤。
|
||||
- 会不会太吵:不会,语音密度低、无高频刺耳件(转写无声频谱数据,此项不评)。
|
||||
- 操作能不能单手盲操:能,四向滑+单击+双击单手成立;但盲操的代价是撞墙
|
||||
频繁,而撞墙不给方位(行 40-55),盲操的试错成本全是沉没成本。
|
||||
- 关键信息听不清怎么办:**无解**——没有重听上一句的通道(单击只重播环境音),
|
||||
短方位句被噪音吃掉就永久丢失,直到下一次进展事件(可能就是 60-180s 后)。
|
||||
@@ -0,0 +1,151 @@
|
||||
# 试玩转写:《escape》
|
||||
|
||||
> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文,
|
||||
> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作),
|
||||
> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。
|
||||
t+ 0.0s (玩家点开游戏,轻触屏幕开始)
|
||||
t+ 0.0s ♫ BGM 切换 → bgm/drone
|
||||
t+ 0.0s ♪ 向导音:explore(探索/安全)
|
||||
t+ 0.0s ▶ 语音:「黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。」
|
||||
t+ 0.0s 【状态】黑屏,只有引子的声音,先听完 引导第 1/8 步,等我做手势(语音播放中,语速1)
|
||||
t+ 0.0s 【状态】引导第 1/8 步 引导第 1/8 步,等我做手势(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】照引导单击了一下
|
||||
|
||||
t+ 0.0s ▶ 语音:「先活动一下。朝任意方向滑一下,走一小步。」
|
||||
t+ 2.1s ▶ 语音:「单击可跳过旁白。」
|
||||
t+ 4.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 4.2s 【状态】引导第 2/8 步 引导第 2/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】随便滑了一步,有脚步声
|
||||
|
||||
t+ 4.2s ♪ 音效 sfx/step
|
||||
t+ 4.2s ▶ 语音:「很好,你迈出了第一步。」
|
||||
t+ 6.4s ▶ 语音:「这个房间不大,四面都是墙。再滑两下,试试碰碰墙。」
|
||||
t+ 8.5s ♪ 向导音:turn(轮到你)
|
||||
t+ 8.5s 【状态】引导第 3/8 步 引导第 3/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
t+ 8.5s ♪ 音效 sfx/wall
|
||||
t+ 8.5s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 8.5s 〰 震动:error(做错了:两连短震)
|
||||
|
||||
#### 【玩家动作】又滑一步,又撞墙了——墙的方位听出来了
|
||||
|
||||
t+ 10.6s ♪ 音效 sfx/wall
|
||||
t+ 10.6s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 10.6s 〰 震动:error(做错了:两连短震)
|
||||
t+ 12.7s ▶ 语音:「跟着我指的路走。向左滑。」
|
||||
t+ 14.8s ♪ 向导音:turn(轮到你)
|
||||
t+ 14.8s 【状态】引导第 4/8 步 引导第 4/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】这回往左,走通了一步
|
||||
|
||||
t+ 14.8s ♪ 音效 sfx/step
|
||||
t+ 14.8s ▶ 语音:「对。再向下滑。」
|
||||
t+ 17.0s ♪ 向导音:turn(轮到你)
|
||||
t+ 17.0s 【状态】引导第 5/8 步 引导第 5/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】往下滑,进了储物间
|
||||
|
||||
t+ 17.0s ♪ 音效 sfx/step
|
||||
t+ 17.0s ♪ 音效 sfx/amb_storage
|
||||
t+ 17.0s ▶ 语音:「听到水声了吗?单击一下,仔细检查这个房间。」
|
||||
t+ 19.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 19.1s 【状态】引导第 6/8 步 引导第 6/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】单击摸一遍房间,摸到钥匙了
|
||||
|
||||
t+ 19.1s ♪ 音效 sfx/pickup
|
||||
t+ 19.1s ▶ 语音:「你摸到了一把钥匙!」
|
||||
t+ 19.1s 〰 震动:pickup(获得)
|
||||
t+ 21.2s ▶ 语音:「钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。」
|
||||
t+ 23.3s ♪ 向导音:turn(轮到你)
|
||||
t+ 23.3s 【状态】引导第 7/8 步 引导第 7/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】双击看了看背包
|
||||
|
||||
t+ 23.3s ▶ 语音:「你身上带着一把钥匙。」
|
||||
t+ 25.4s ▶ 语音:「对,就是这样。接下来,靠你自己了。」
|
||||
t+ 27.6s ▶ 语音:「找到能用这把钥匙打开的东西。需要帮助时,在原地双击。」
|
||||
t+ 29.7s ♪ 向导音:turn(轮到你)
|
||||
t+ 29.7s ♪ 音效 sfx/amb_storage
|
||||
t+ 29.7s 【状态】引导完毕,正式开始。我在储物间 探索中,我在 (0,2)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 29.7s ……… 静默 3s(辨了辨方向) ………
|
||||
t+ 29.7s ♪ 音效 sfx/step
|
||||
t+ 29.7s ♪ 音效 sfx/amb_hum
|
||||
t+ 35.0s ♪ 音效 sfx/step
|
||||
t+ 35.0s ♪ 音效 sfx/amb_power
|
||||
t+ 35.0s ▶ 语音:「这个房间的墙上,有一只电箱。」
|
||||
t+ 37.1s ♪ 音效 sfx/wall
|
||||
t+ 37.1s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 37.1s 〰 震动:error(做错了:两连短震)
|
||||
|
||||
#### 【玩家动作】北边是墙,撞了一下——「那边是墙」后面还跟了句方向(向上推的是北墙)
|
||||
|
||||
t+ 39.2s ♪ 音效 sfx/wall
|
||||
t+ 39.2s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 39.2s 〰 震动:error(做错了:两连短震)
|
||||
|
||||
#### 【玩家动作】又撞了一下——听到游戏主动来问我了
|
||||
|
||||
t+ 50.0s ♪ 音效 sfx/step
|
||||
t+ 50.0s ♪ 音效 sfx/amb_wind
|
||||
|
||||
#### 【玩家动作】往东走,风声换了个方向
|
||||
|
||||
t+ 55.0s ♪ 音效 sfx/step
|
||||
t+ 55.0s ♪ 音效 sfx/amb_hum
|
||||
t+ 60.0s ♪ 音效 sfx/step
|
||||
t+ 60.0s ♪ 音效 sfx/amb_cabinet
|
||||
t+ 60.0s ▶ 语音:「这个房间里,立着一个铁柜。」
|
||||
|
||||
#### 【玩家动作】到了铁柜房,柜子锁着
|
||||
|
||||
t+ 62.1s ♪ 音效 sfx/unlock
|
||||
t+ 62.1s ♪ 音效 sfx/door_creak
|
||||
t+ 62.1s ▶ 语音:「钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。」
|
||||
t+ 62.1s 〰 震动:success(成功长震)
|
||||
t+ 64.2s ▶ 向导语音:「保险丝到手。接下来,去找电箱。」
|
||||
t+ 66.4s ▶ 向导语音:「左面的房间。」
|
||||
t+ 68.5s 【状态】柜子开了。「保险丝到手。接下来,去找电箱。」后面还跟了一句「左面的房间。」——这回知道该往哪边摸了 探索中,我在 (2,1)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 68.5s ♪ 音效 sfx/step
|
||||
t+ 68.5s ♪ 音效 sfx/amb_drip
|
||||
|
||||
#### 【玩家动作】照方位句往左(西)摸
|
||||
|
||||
t+ 75.0s ♪ 音效 sfx/step
|
||||
t+ 75.0s ♪ 音效 sfx/amb_hum
|
||||
t+ 80.0s ♪ 音效 sfx/step
|
||||
t+ 80.0s ♪ 音效 sfx/amb_power
|
||||
|
||||
#### 【玩家动作】电流声越来越清晰——电箱房到了
|
||||
|
||||
t+ 85.0s ♪ 音效 sfx/spark
|
||||
t+ 85.0s ♪ 音效 sfx/power_on
|
||||
t+ 85.0s ▶ 语音:「你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了!」
|
||||
t+ 85.0s 〰 震动:success(成功长震)
|
||||
t+ 87.1s ▶ 向导语音:「右面的房间。」
|
||||
t+ 95.0s 【状态】电箱修好了。目标句后面照样跟着方位——「右面的房间。」大门在东边 探索中,我在 (0,0)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 95.0s ♪ 音效 sfx/step
|
||||
t+ 95.0s ♪ 音效 sfx/amb_wind
|
||||
|
||||
#### 【玩家动作】照方位句往右(东)摸
|
||||
|
||||
t+ 100.0s ♪ 音效 sfx/step
|
||||
t+ 100.0s ♪ 音效 sfx/amb_hum
|
||||
t+ 105.0s ♪ 音效 sfx/step
|
||||
t+ 105.0s ♪ 音效 sfx/amb_cabinet
|
||||
t+ 110.0s ♪ 音效 sfx/step
|
||||
t+ 110.0s ♪ 音效 sfx/amb_gate_live
|
||||
t+ 110.0s ▶ 语音:「面前,是一扇沉重的铁门。」
|
||||
|
||||
#### 【玩家动作】脚步声停下来——面前这间就是大门
|
||||
|
||||
t+ 112.1s ♪ 向导音:settle(结算)
|
||||
t+ 112.1s ▶ 语音:「你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。」
|
||||
t+ 112.1s 〰 震动:success(成功长震)
|
||||
t+ 114.2s ▶ 语音:「你逃出来了,用时不到两分钟。了不起!」
|
||||
t+ 114.7s ♪ 音效 sfx/gate_open
|
||||
t+ 114.7s ♪ 音效 sfx/win_chime
|
||||
t+ 116.4s ▶ 语音:「单击屏幕,再来一次。下滑,打开菜单。」
|
||||
t+ 118.5s ♫ BGM 切换 → bgm/menu(淡入 1500ms)
|
||||
t+ 118.5s 【状态】钥匙插进锁孔,门开了——结算播报来了,这局是完整的赢 逃脱了,结算播报中。播完单击再来,下滑开菜单(BGM=bgm/menu,语速1)
|
||||
@@ -0,0 +1,44 @@
|
||||
# escape-state round2 · 状态引导改进方案(25 号文档 B1-B8)修复验证档案
|
||||
|
||||
> 轮次:escape-state round2(2026-09-14/15)。对象:25 号文档 §4.3 实施清单
|
||||
> F1-F9(F6/B5b 按方案"可分期"留档,见 25 号文档实施裁定 1)。
|
||||
> 档案格式对齐 round1:mock 转写 + live 真机一局 + 事件/判定原件。
|
||||
> round1 的 P1/P3 人设评审不重做(方案条目即由双席评审产出,本轮验证落地效果)。
|
||||
|
||||
## 产物
|
||||
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `transcript-mock.md` | mock 转写(`transcribe.mjs escape`,sessions/escape.mjs 已按新行为微调):新手完整一局,覆盖 B1 撞墙方位句+限频、B5a 空房首访、B2 一体句 ×2、结算链完整到达 |
|
||||
| `live-transcript.md` / `live-events.jsonl` / `verdicts.json` / `mix.webm` | live 真机一局(control.mjs 端口 8145,女声响 full 档,约 10.4 分钟,引导→探索→通关→重开),认真新手人设 |
|
||||
| `README.md` | 本文件(盲区清单 S1-S7 逐条核对) |
|
||||
|
||||
## live 一局总览
|
||||
|
||||
- 38 个语音段,56 条判定行:**OK 37 / SFX_BGM_ONLY 19 / TRUNCATED 0 / MISMATCH 0**
|
||||
(round1 为 OK 35 / SFX_BGM_ONLY 18 / TRUNCATED 2——两条截断均有手势归因;
|
||||
本轮零截断,含 B7 守卫挡下的那一次习惯性单击)。
|
||||
- 新语音 10 句在真实混音中全部到达且 ASR sim≥0.93:wall_dir_u/l、empty_2/1/3(首访)、
|
||||
stuck_cabinet_1(B4 降级)、gd_box_dir/gd_gate_dir(B2 一体句)、gd_prog_2(B3)。
|
||||
|
||||
## 盲区清单 S1-S7 逐条核对(25 号文档 §3.2)
|
||||
|
||||
| 盲区 | 修复 | live 证据(行号 = live-transcript.md) | 结论 |
|
||||
|---|---|---|---|
|
||||
| S1/S1b 方位(撞墙无方位) | B1 wall_dir_* | 行 141-143:wall 后接播「上边是墙。」OK sim=1;行 166-168:「左边是墙。」OK;同向 10s 限频生效(199.5s 第二次撞北墙只有 wall 无 wall_dir_u) | ✅ 每次撞墙建立"此方向不通"地图标记 |
|
||||
| 相对方位半盲区(无目标名) | B2 gd_*_dir 一体句 | 行 231-233:「电箱,在左面的房间。」OK sim=1;行 306-312:「大门,在右面的房间。」OK sim=1 | ✅ 单句即可行动,不再是"……的房间" |
|
||||
| S2 已探索地图 | B5a 空房首访描述 | 行 115-118 (0,1) empty_2、行 189-192 (1,0) empty_1、行 199-202 (2,0) empty_3,均首访一次性 OK | ✅ 空房进入即有听觉锚 |
|
||||
| S3 全局进度无渠道 | B3 gd_prog_* | 行 265-268:开柜后活跃探路 ~154s(10 次手势零进展、避开 (2,2) 防进展重置)→ gd_prog_2「铁柜已经打开。电还没有通。」OK sim=1;期间 L1/L2/L3 零误触 | ✅ 活跃迷路通道补洞,不泄题 |
|
||||
| S4/S4b 目标重述/查询泄漏 | B4 + B8 | B4:行 180-182 双击兜底播 use_fail + stuck_cabinet_1(L1 意象,OK 0.93),**不再直通 stuck_*_2**;B8:g7_goal 在引导链尾 OK sim=1(跳过/REOPEN 路径补播由 playtest A2/B/N 断言覆盖) | ✅ 主动查询不再白送答案 |
|
||||
| S5 空房不可区分 | B5a(B5b 留档) | 三间首访空房文本各异(回声/墙壁/水滴),live 中与环境音叠加可分辨 | ✅(B5b 方位特征改词留后续轮) |
|
||||
| S6 busy 吞手势 | B6 缓存补判 | 行 79-87(live-events.jsonl):82.3s swipeleft 落在 g2_wall busy 窗口(82.2-87.9)只有 [10] 震——87.9s 解锁瞬间补判:error 震 + wall 语音 + G2 计数 1(对照 round1 行 30-35 同场景静默吞手势) | ✅ "我的输入没丢",可归因 |
|
||||
| S7 结算链截断 | B7 _settleBusy | 行 336-347:587.46s 习惯性单击落在 escape 播到 4.4/15.3s——只发引擎 confirm 震,链继续;time_band3(行 346)、again 完整到达 OK;链播完后单击正常重开(replay 起播) | ✅ 结算完整到达权 + 重开闭环 |
|
||||
|
||||
## 附带观察
|
||||
|
||||
- escape 长句 live 实测 15.32s(dur 探针值),结算链全长 ~24s(escape+time_band3+again),
|
||||
B7 守卫窗口即此区间;30s 资产缺失兜底由 playtest 场景 M 第二条路径冻结。
|
||||
- time_band3「用时不到十分钟」与本局 ~9.7 分钟一致(归因真话)。
|
||||
- female/wall_dir_r 为 3.04s 慢速 take(同句 male 1.04s,ratio 2.92 未触 3x 离群线),
|
||||
QC:ASR 双性别内容均「右边是墙。」逐字正确,慢速贴合"沉稳平静"instruct,留档备查;
|
||||
本局 female 档未触发该句(撞的是北/西墙),male 档或未限频路径如有听感问题再重录。
|
||||
@@ -0,0 +1,289 @@
|
||||
{"ev":"probe_ready","t":61.10000002384186,"ta":null}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":2065.4000000059605,"ta":-5.104}
|
||||
{"ev":"recstart","mime":"audio/webm;codecs=opus","t":7169.100000023842,"ta":0}
|
||||
{"ev":"fetch","url":"audio/sfx/step.ogg","status":200,"ok":true,"ms":15,"t":7184.100000023842,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/wall.ogg","status":200,"ok":true,"ms":15,"t":7184.200000017881,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/pickup.ogg","status":200,"ok":true,"ms":15,"t":7184.300000011921,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/unlock.ogg","status":200,"ok":true,"ms":15,"t":7184.300000011921,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/door_creak.ogg","status":200,"ok":true,"ms":15,"t":7184.300000011921,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/spark.ogg","status":200,"ok":true,"ms":14,"t":7184.300000011921,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/power_on.ogg","status":200,"ok":true,"ms":14,"t":7184.4000000059605,"ta":0.015}
|
||||
{"ev":"fetch","url":"audio/sfx/gate_open.ogg","status":200,"ok":true,"ms":16,"t":7186.100000023842,"ta":0.017}
|
||||
{"ev":"fetch","url":"audio/sfx/win_chime.ogg","status":200,"ok":true,"ms":16,"t":7186.300000011921,"ta":0.017}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_storage.ogg","status":200,"ok":true,"ms":18,"t":7187.600000023842,"ta":0.019}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_cabinet.ogg","status":200,"ok":true,"ms":18,"t":7188.5,"ta":0.019}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_power.ogg","status":200,"ok":true,"ms":19,"t":7189.4000000059605,"ta":0.02}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_gate.ogg","status":200,"ok":true,"ms":25,"t":7195.700000017881,"ta":0.027}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_gate_live.ogg","status":200,"ok":true,"ms":25,"t":7195.700000017881,"ta":0.027}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_drip.ogg","status":200,"ok":true,"ms":27,"t":7196.800000011921,"ta":0.028}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_wind.ogg","status":200,"ok":true,"ms":27,"t":7197.600000023842,"ta":0.029}
|
||||
{"ev":"fetch","url":"audio/sfx/amb_hum.ogg","status":200,"ok":true,"ms":28,"t":7198.700000017881,"ta":0.03}
|
||||
{"ev":"fetch","url":"audio/voice/female/g0_intro.ogg","status":200,"ok":true,"ms":30,"t":7200.100000023842,"ta":0.031}
|
||||
{"ev":"fetch","url":"audio/voice/female/g1_move.ogg","status":200,"ok":true,"ms":34,"t":7204.5,"ta":0.035}
|
||||
{"ev":"fetch","url":"audio/voice/female/skip_hint.ogg","status":200,"ok":true,"ms":36,"t":7206.600000023842,"ta":0.038}
|
||||
{"ev":"fetch","url":"audio/voice/female/reopen_prompt.ogg","status":200,"ok":true,"ms":38,"t":7208.4000000059605,"ta":0.039}
|
||||
{"ev":"fetch","url":"audio/voice/female/start_room.ogg","status":200,"ok":true,"ms":38,"t":7209,"ta":0.04}
|
||||
{"ev":"fetch","url":"audio/bgm/menu.ogg","status":200,"ok":true,"ms":38,"t":7209.100000023842,"ta":0.04}
|
||||
{"ev":"fetch","url":"audio/bgm/drone.ogg","status":200,"ok":true,"ms":39,"t":7209.800000011921,"ta":0.041}
|
||||
{"ev":"vstart","url":"audio/voice/female/g0_intro.ogg","t":7245.700000017881,"dur":6.64,"ta":0.077}
|
||||
{"ev":"start","t":7439.800000011921,"sid":1,"url":"audio/bgm/drone.ogg","layer":"bgm","dur":117,"rate":1,"loop":true,"when":0,"ta":0.271}
|
||||
{"ev":"vend","url":"audio/voice/female/g0_intro.ogg","t":14100.40000000596,"reason":"kill","ta":6.931}
|
||||
{"ev":"vstart","url":"audio/voice/female/g1_move.ogg","t":15300.90000000596,"dur":4.56,"ta":8.132}
|
||||
{"ev":"vend","url":"audio/voice/female/g1_move.ogg","t":19910.20000001788,"reason":"kill","ta":12.741}
|
||||
{"ev":"vstart","url":"audio/voice/female/skip_hint.ogg","t":19910.30000001192,"dur":1.6,"ta":12.741}
|
||||
{"ev":"vend","url":"audio/voice/female/skip_hint.ogg","t":21530.100000023842,"reason":"kill","ta":14.361}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":86221.70000001788,"ta":79.053}
|
||||
{"ev":"vibrate","pattern":"[10]","t":86578.60000002384,"ta":79.41}
|
||||
{"ev":"start","t":86579.60000002384,"sid":2,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":79.411}
|
||||
{"ev":"fetch","url":"audio/voice/female/g1_done.ogg","status":200,"ok":true,"ms":3,"t":86582,"ta":79.413}
|
||||
{"ev":"vstart","url":"audio/voice/female/g1_done.ogg","t":86586.30000001192,"dur":2.72,"ta":79.417}
|
||||
{"ev":"vend","url":"audio/voice/female/g1_done.ogg","t":89320.20000001788,"reason":"kill","ta":82.151}
|
||||
{"ev":"fetch","url":"audio/voice/female/g2_wall.ogg","status":200,"ok":true,"ms":3,"t":89322.80000001192,"ta":82.154}
|
||||
{"ev":"vstart","url":"audio/voice/female/g2_wall.ogg","t":89328.30000001192,"dur":5.68,"ta":82.159}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":89490,"ta":82.321}
|
||||
{"ev":"vibrate","pattern":"[10]","t":89844.70000001788,"ta":82.676}
|
||||
{"ev":"vend","url":"audio/voice/female/g2_wall.ogg","t":95050.10000002384,"reason":"kill","ta":87.881}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":95050.30000001192,"ta":87.881}
|
||||
{"ev":"start","t":95050.70000001788,"sid":3,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":87.882}
|
||||
{"ev":"fetch","url":"audio/voice/female/wall.ogg","status":200,"ok":true,"ms":2,"t":95052.70000001788,"ta":87.884}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":95056.40000000596,"dur":2.08,"ta":87.887}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":97410.10000002384,"reason":"kill","ta":90.241}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":116300.20000001788,"ta":109.131}
|
||||
{"ev":"vibrate","pattern":"[10]","t":116660.10000002384,"ta":109.491}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":116660.20000001788,"ta":109.491}
|
||||
{"ev":"start","t":116660.40000000596,"sid":4,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":109.491}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":116660.5,"dur":2.08,"ta":109.491}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":119030.30000001192,"reason":"kill","ta":111.861}
|
||||
{"ev":"fetch","url":"audio/voice/female/g3_left.ogg","status":200,"ok":true,"ms":2,"t":119032.80000001192,"ta":111.864}
|
||||
{"ev":"vstart","url":"audio/voice/female/g3_left.ogg","t":119037.10000002384,"dur":2.96,"ta":111.868}
|
||||
{"ev":"vend","url":"audio/voice/female/g3_left.ogg","t":122050.10000002384,"reason":"kill","ta":114.881}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":124070.30000001192,"ta":116.901}
|
||||
{"ev":"vibrate","pattern":"[10]","t":124426.70000001788,"ta":117.258}
|
||||
{"ev":"start","t":124427.20000001788,"sid":5,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":117.258}
|
||||
{"ev":"fetch","url":"audio/voice/female/g4_down.ogg","status":200,"ok":true,"ms":2,"t":124429.20000001788,"ta":117.26}
|
||||
{"ev":"vstart","url":"audio/voice/female/g4_down.ogg","t":124432.80000001192,"dur":1.84,"ta":117.264}
|
||||
{"ev":"vend","url":"audio/voice/female/g4_down.ogg","t":126340.20000001788,"reason":"kill","ta":119.171}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":129835.90000000596,"ta":122.667}
|
||||
{"ev":"vibrate","pattern":"[10]","t":130192.90000000596,"ta":123.024}
|
||||
{"ev":"start","t":130193.30000001192,"sid":6,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":123.024}
|
||||
{"ev":"start","t":130193.40000000596,"sid":7,"url":"audio/sfx/amb_storage.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":123.024}
|
||||
{"ev":"fetch","url":"audio/voice/female/g5_inspect.ogg","status":200,"ok":true,"ms":2,"t":130195.5,"ta":123.026}
|
||||
{"ev":"vstart","url":"audio/voice/female/g5_inspect.ogg","t":130200.90000000596,"dur":3.92,"ta":123.032}
|
||||
{"ev":"vend","url":"audio/voice/female/g5_inspect.ogg","t":134340.10000002384,"reason":"kill","ta":127.171}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":137604.80000001192,"ta":130.436}
|
||||
{"ev":"vibrate","pattern":"[20]","t":137970.20000001788,"ta":130.801}
|
||||
{"ev":"vibrate","pattern":"[15]","t":137970.40000000596,"ta":130.801}
|
||||
{"ev":"start","t":137970.70000001788,"sid":8,"url":"audio/sfx/pickup.ogg","layer":"sfx","dur":0.3470748299319728,"rate":1,"loop":false,"when":0,"ta":130.802}
|
||||
{"ev":"fetch","url":"audio/voice/female/g5_key.ogg","status":200,"ok":true,"ms":3,"t":137973.10000002384,"ta":130.804}
|
||||
{"ev":"vstart","url":"audio/voice/female/g5_key.ogg","t":137976.80000001192,"dur":1.52,"ta":130.808}
|
||||
{"ev":"vend","url":"audio/voice/female/g5_key.ogg","t":139590.20000001788,"reason":"kill","ta":132.421}
|
||||
{"ev":"fetch","url":"audio/voice/female/g6_doubletap.ogg","status":200,"ok":true,"ms":2,"t":139592.60000002384,"ta":132.424}
|
||||
{"ev":"vstart","url":"audio/voice/female/g6_doubletap.ogg","t":139602.40000000596,"dur":10.64,"ta":132.433}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":148080.20000001788,"ta":140.911}
|
||||
{"ev":"vibrate","pattern":"[20]","t":148329.60000002384,"ta":141.161}
|
||||
{"ev":"vend","url":"audio/voice/female/g6_doubletap.ogg","t":150560.10000002384,"reason":"kill","ta":143.391}
|
||||
{"ev":"fetch","url":"audio/voice/female/inv_key.ogg","status":200,"ok":true,"ms":3,"t":150563,"ta":143.394}
|
||||
{"ev":"vstart","url":"audio/voice/female/inv_key.ogg","t":150566.70000001788,"dur":1.68,"ta":143.398}
|
||||
{"ev":"vend","url":"audio/voice/female/inv_key.ogg","t":152460.10000002384,"reason":"kill","ta":145.291}
|
||||
{"ev":"fetch","url":"audio/voice/female/g6_done.ogg","status":200,"ok":true,"ms":3,"t":152462.70000001788,"ta":145.294}
|
||||
{"ev":"vstart","url":"audio/voice/female/g6_done.ogg","t":152468,"dur":3.92,"ta":145.299}
|
||||
{"ev":"vend","url":"audio/voice/female/g6_done.ogg","t":156620.20000001788,"reason":"kill","ta":149.451}
|
||||
{"ev":"fetch","url":"audio/voice/female/g7_goal.ogg","status":200,"ok":true,"ms":3,"t":156622.80000001192,"ta":149.454}
|
||||
{"ev":"vstart","url":"audio/voice/female/g7_goal.ogg","t":156629.40000000596,"dur":6.88,"ta":149.46}
|
||||
{"ev":"vend","url":"audio/voice/female/g7_goal.ogg","t":163760.30000001192,"reason":"kill","ta":156.591}
|
||||
{"ev":"start","t":163760.70000001788,"sid":9,"url":"audio/sfx/amb_storage.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":156.592}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":185967.10000002384,"ta":178.798}
|
||||
{"ev":"vibrate","pattern":"[10]","t":186324.30000001192,"ta":179.155}
|
||||
{"ev":"start","t":186324.90000000596,"sid":10,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":179.156}
|
||||
{"ev":"start","t":186324.90000000596,"sid":11,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":179.156}
|
||||
{"ev":"fetch","url":"audio/voice/female/empty_2.ogg","status":200,"ok":true,"ms":3,"t":186327.30000001192,"ta":179.158}
|
||||
{"ev":"vstart","url":"audio/voice/female/empty_2.ogg","t":186333.30000001192,"dur":4.88,"ta":179.164}
|
||||
{"ev":"vend","url":"audio/voice/female/empty_2.ogg","t":191320.30000001192,"reason":"kill","ta":184.151}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":192735.70000001788,"ta":185.567}
|
||||
{"ev":"vibrate","pattern":"[10]","t":193090.80000001192,"ta":185.922}
|
||||
{"ev":"start","t":193091.20000001788,"sid":12,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":185.922}
|
||||
{"ev":"start","t":193091.20000001788,"sid":13,"url":"audio/sfx/amb_power.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":185.922}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_power.ogg","status":200,"ok":true,"ms":3,"t":193093.70000001788,"ta":185.925}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_power.ogg","t":193097.70000001788,"dur":2.64,"ta":185.929}
|
||||
{"ev":"vend","url":"audio/voice/female/room_power.ogg","t":195840,"reason":"kill","ta":188.671}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":199501.40000000596,"ta":192.332}
|
||||
{"ev":"vibrate","pattern":"[10]","t":199856.80000001192,"ta":192.688}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":199856.90000000596,"ta":192.688}
|
||||
{"ev":"start","t":199857,"sid":14,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":192.688}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":199857,"dur":2.08,"ta":192.688}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":202220.20000001788,"reason":"kill","ta":195.051}
|
||||
{"ev":"fetch","url":"audio/voice/female/wall_dir_u.ogg","status":200,"ok":true,"ms":3,"t":202223.60000002384,"ta":195.055}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall_dir_u.ogg","t":202227.10000002384,"dur":1.36,"ta":195.058}
|
||||
{"ev":"vend","url":"audio/voice/female/wall_dir_u.ogg","t":203840.10000002384,"reason":"kill","ta":196.671}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":206268,"ta":199.099}
|
||||
{"ev":"vibrate","pattern":"[10]","t":206623.40000000596,"ta":199.454}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":206623.70000001788,"ta":199.455}
|
||||
{"ev":"start","t":206623.80000001192,"sid":15,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":199.455}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":206623.90000000596,"dur":2.08,"ta":199.455}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":208990.20000001788,"reason":"kill","ta":201.821}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":211033.30000001192,"ta":203.864}
|
||||
{"ev":"vibrate","pattern":"[10]","t":211390,"ta":204.221}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":211390.10000002384,"ta":204.221}
|
||||
{"ev":"start","t":211390.30000001192,"sid":16,"url":"audio/sfx/wall.ogg","layer":"sfx","dur":0.44709750566893425,"rate":1,"loop":false,"when":0,"ta":204.221}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall.ogg","t":211390.30000001192,"dur":2.08,"ta":204.221}
|
||||
{"ev":"vend","url":"audio/voice/female/wall.ogg","t":213760.10000002384,"reason":"kill","ta":206.591}
|
||||
{"ev":"fetch","url":"audio/voice/female/wall_dir_l.ogg","status":200,"ok":true,"ms":3,"t":213762.70000001788,"ta":206.594}
|
||||
{"ev":"vstart","url":"audio/voice/female/wall_dir_l.ogg","t":213766.10000002384,"dur":1.04,"ta":206.597}
|
||||
{"ev":"vend","url":"audio/voice/female/wall_dir_l.ogg","t":214920.10000002384,"reason":"kill","ta":207.751}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":217799.90000000596,"ta":210.631}
|
||||
{"ev":"vibrate","pattern":"[20]","t":218046.80000001192,"ta":210.878}
|
||||
{"ev":"vibrate","pattern":"[60,40,60]","t":218047.20000001788,"ta":210.878}
|
||||
{"ev":"fetch","url":"audio/voice/female/use_fail.ogg","status":200,"ok":true,"ms":3,"t":218049.80000001192,"ta":210.881}
|
||||
{"ev":"vstart","url":"audio/voice/female/use_fail.ogg","t":218057.40000000596,"dur":7.36,"ta":210.888}
|
||||
{"ev":"vend","url":"audio/voice/female/use_fail.ogg","t":225650.10000002384,"reason":"kill","ta":218.481}
|
||||
{"ev":"fetch","url":"audio/voice/female/stuck_cabinet_1.ogg","status":200,"ok":true,"ms":3,"t":225653.20000001788,"ta":218.484}
|
||||
{"ev":"vstart","url":"audio/voice/female/stuck_cabinet_1.ogg","t":225659,"dur":3.84,"ta":218.49}
|
||||
{"ev":"vend","url":"audio/voice/female/stuck_cabinet_1.ogg","t":229790.20000001788,"reason":"kill","ta":222.621}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":263046.3000000119,"ta":255.877}
|
||||
{"ev":"vibrate","pattern":"[10]","t":263404.2000000179,"ta":256.235}
|
||||
{"ev":"start","t":263404.60000002384,"sid":17,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":256.236}
|
||||
{"ev":"start","t":263404.60000002384,"sid":18,"url":"audio/sfx/amb_wind.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":256.236}
|
||||
{"ev":"fetch","url":"audio/voice/female/empty_1.ogg","status":200,"ok":true,"ms":3,"t":263407.2000000179,"ta":256.238}
|
||||
{"ev":"vstart","url":"audio/voice/female/empty_1.ogg","t":263413.60000002384,"dur":5.2,"ta":256.245}
|
||||
{"ev":"vend","url":"audio/voice/female/empty_1.ogg","t":268670.10000002384,"reason":"kill","ta":261.501}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":269814.3000000119,"ta":262.645}
|
||||
{"ev":"vibrate","pattern":"[10]","t":270170.5,"ta":263.001}
|
||||
{"ev":"start","t":270171,"sid":19,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":263.002}
|
||||
{"ev":"start","t":270171,"sid":20,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":263.002}
|
||||
{"ev":"fetch","url":"audio/voice/female/empty_3.ogg","status":200,"ok":true,"ms":3,"t":270173.3000000119,"ta":263.004}
|
||||
{"ev":"vstart","url":"audio/voice/female/empty_3.ogg","t":270178.60000002384,"dur":3.68,"ta":263.01}
|
||||
{"ev":"vend","url":"audio/voice/female/empty_3.ogg","t":274030.2000000179,"reason":"kill","ta":266.861}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":276579.5,"ta":269.41}
|
||||
{"ev":"vibrate","pattern":"[10]","t":276937.5,"ta":269.768}
|
||||
{"ev":"start","t":276937.90000000596,"sid":21,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":269.769}
|
||||
{"ev":"start","t":276937.90000000596,"sid":22,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":269.769}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_cabinet.ogg","status":200,"ok":true,"ms":3,"t":276940.40000000596,"ta":269.771}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_cabinet.ogg","t":276944.7000000179,"dur":2.64,"ta":269.776}
|
||||
{"ev":"vend","url":"audio/voice/female/room_cabinet.ogg","t":279690.10000002384,"reason":"kill","ta":272.521}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":283348,"ta":276.179}
|
||||
{"ev":"vibrate","pattern":"[20]","t":283593.90000000596,"ta":276.425}
|
||||
{"ev":"vibrate","pattern":"[100]","t":283594.10000002384,"ta":276.425}
|
||||
{"ev":"start","t":283594.3000000119,"sid":23,"url":"audio/sfx/unlock.ogg","layer":"sfx","dur":0.49777777777777776,"rate":1,"loop":false,"when":0,"ta":276.425}
|
||||
{"ev":"start","t":283594.3000000119,"sid":24,"url":"audio/sfx/door_creak.ogg","layer":"sfx","dur":1.3999773242630384,"rate":1,"loop":false,"when":0,"ta":276.425}
|
||||
{"ev":"fetch","url":"audio/voice/female/unlock_cabinet.ogg","status":200,"ok":true,"ms":2,"t":283596.60000002384,"ta":276.428}
|
||||
{"ev":"vstart","url":"audio/voice/female/unlock_cabinet.ogg","t":283607,"dur":11.48,"ta":276.438}
|
||||
{"ev":"vend","url":"audio/voice/female/unlock_cabinet.ogg","t":295320.10000002384,"reason":"kill","ta":288.151}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_next_fuse.ogg","status":200,"ok":true,"ms":3,"t":295323.10000002384,"ta":288.154}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_next_fuse.ogg","t":295328.10000002384,"dur":3.28,"ta":288.159}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_next_fuse.ogg","t":298800.40000000596,"reason":"kill","ta":291.631}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_box_dir.ogg","status":200,"ok":true,"ms":3,"t":298803.5,"ta":291.634}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_box_dir.ogg","t":298807.3000000119,"dur":2.16,"ta":291.638}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_box_dir.ogg","t":301180.10000002384,"reason":"kill","ta":294.011}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":317593.90000000596,"ta":310.425}
|
||||
{"ev":"vibrate","pattern":"[10]","t":317952.10000002384,"ta":310.783}
|
||||
{"ev":"start","t":317952.3000000119,"sid":25,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":310.783}
|
||||
{"ev":"start","t":317952.3000000119,"sid":26,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":310.783}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":334362.90000000596,"ta":327.194}
|
||||
{"ev":"vibrate","pattern":"[10]","t":334718.3000000119,"ta":327.549}
|
||||
{"ev":"start","t":334718.60000002384,"sid":27,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":327.55}
|
||||
{"ev":"start","t":334718.7000000179,"sid":28,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":327.55}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":351128.5,"ta":343.959}
|
||||
{"ev":"vibrate","pattern":"[10]","t":351484.2000000179,"ta":344.315}
|
||||
{"ev":"start","t":351484.40000000596,"sid":29,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":344.315}
|
||||
{"ev":"start","t":351484.5,"sid":30,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":344.315}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":367894.40000000596,"ta":360.725}
|
||||
{"ev":"vibrate","pattern":"[10]","t":368250.40000000596,"ta":361.081}
|
||||
{"ev":"start","t":368250.7000000179,"sid":31,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":361.082}
|
||||
{"ev":"start","t":368250.7000000179,"sid":32,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":361.082}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":384660.10000002384,"ta":377.491}
|
||||
{"ev":"vibrate","pattern":"[10]","t":385016,"ta":377.847}
|
||||
{"ev":"start","t":385016.2000000179,"sid":33,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":377.847}
|
||||
{"ev":"start","t":385016.2000000179,"sid":34,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":377.847}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":416051.60000002384,"ta":408.883}
|
||||
{"ev":"vibrate","pattern":"[10]","t":416414.8000000119,"ta":409.246}
|
||||
{"ev":"start","t":416415.10000002384,"sid":35,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":409.246}
|
||||
{"ev":"start","t":416415.10000002384,"sid":36,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":409.246}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":432824.8000000119,"ta":425.656}
|
||||
{"ev":"vibrate","pattern":"[10]","t":433180.7000000179,"ta":426.012}
|
||||
{"ev":"start","t":433181,"sid":37,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":426.012}
|
||||
{"ev":"start","t":433181,"sid":38,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":426.012}
|
||||
{"ev":"vibrate","pattern":"[30,50,30,50,30]","t":437170.90000000596,"ta":430.002}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_prog_2.ogg","status":200,"ok":true,"ms":3,"t":437173.90000000596,"ta":430.005}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_prog_2.ogg","t":437178.10000002384,"dur":2.56,"ta":430.009}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_prog_2.ogg","t":439920.2000000179,"reason":"kill","ta":432.751}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":449589.90000000596,"ta":442.421}
|
||||
{"ev":"vibrate","pattern":"[10]","t":449947,"ta":442.778}
|
||||
{"ev":"start","t":449947.3000000119,"sid":39,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":442.778}
|
||||
{"ev":"start","t":449947.40000000596,"sid":40,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":442.778}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":466357.10000002384,"ta":459.188}
|
||||
{"ev":"vibrate","pattern":"[10]","t":466713.2000000179,"ta":459.544}
|
||||
{"ev":"start","t":466713.3000000119,"sid":41,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":459.544}
|
||||
{"ev":"start","t":466713.5,"sid":42,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":459.544}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":483123.3000000119,"ta":475.954}
|
||||
{"ev":"vibrate","pattern":"[10]","t":483478.8000000119,"ta":476.31}
|
||||
{"ev":"start","t":483479.10000002384,"sid":43,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":476.31}
|
||||
{"ev":"start","t":483479.10000002384,"sid":44,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":476.31}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":534004.3000000119,"ta":526.835}
|
||||
{"ev":"vibrate","pattern":"[10]","t":534360.1000000238,"ta":527.191}
|
||||
{"ev":"start","t":534360.3000000119,"sid":45,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":527.191}
|
||||
{"ev":"start","t":534360.400000006,"sid":46,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":527.191}
|
||||
{"ev":"gesture","type":"swipeleft","x":195,"y":422,"t":538768.8000000119,"ta":531.6}
|
||||
{"ev":"vibrate","pattern":"[10]","t":539126.8000000119,"ta":531.958}
|
||||
{"ev":"start","t":539127.1000000238,"sid":47,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":531.958}
|
||||
{"ev":"start","t":539127.1000000238,"sid":48,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":531.958}
|
||||
{"ev":"gesture","type":"swipeup","x":195,"y":422,"t":543536.400000006,"ta":536.367}
|
||||
{"ev":"vibrate","pattern":"[10]","t":543893.6000000238,"ta":536.725}
|
||||
{"ev":"start","t":543893.900000006,"sid":49,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":536.725}
|
||||
{"ev":"start","t":543893.900000006,"sid":50,"url":"audio/sfx/amb_power.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":536.725}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":548303.3000000119,"ta":541.134}
|
||||
{"ev":"vibrate","pattern":"[20]","t":548551.1000000238,"ta":541.382}
|
||||
{"ev":"vibrate","pattern":"[100]","t":548551.400000006,"ta":541.382}
|
||||
{"ev":"start","t":548551.7000000179,"sid":51,"url":"audio/sfx/spark.ogg","layer":"sfx","dur":0.8970975056689342,"rate":1,"loop":false,"when":0,"ta":541.383}
|
||||
{"ev":"start","t":548551.7000000179,"sid":52,"url":"audio/sfx/power_on.ogg","layer":"sfx","dur":2.2,"rate":1,"loop":false,"when":0,"ta":541.383}
|
||||
{"ev":"fetch","url":"audio/voice/female/fix_box.ogg","status":200,"ok":true,"ms":3,"t":548554.3000000119,"ta":541.385}
|
||||
{"ev":"vstart","url":"audio/voice/female/fix_box.ogg","t":548562.400000006,"dur":7.52,"ta":541.393}
|
||||
{"ev":"vend","url":"audio/voice/female/fix_box.ogg","t":556150.1000000238,"reason":"kill","ta":548.981}
|
||||
{"ev":"fetch","url":"audio/voice/female/gd_gate_dir.ogg","status":200,"ok":true,"ms":3,"t":556153.3000000119,"ta":548.984}
|
||||
{"ev":"vstart","url":"audio/voice/female/gd_gate_dir.ogg","t":556157.3000000119,"dur":2.32,"ta":548.988}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":557962.3000000119,"ta":550.793}
|
||||
{"ev":"vibrate","pattern":"[10]","t":558326.1000000238,"ta":551.157}
|
||||
{"ev":"start","t":558326.400000006,"sid":53,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":551.157}
|
||||
{"ev":"start","t":558326.400000006,"sid":54,"url":"audio/sfx/amb_wind.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":551.157}
|
||||
{"ev":"vend","url":"audio/voice/female/gd_gate_dir.ogg","t":558530,"reason":"kill","ta":551.361}
|
||||
{"ev":"gesture","type":"swiperight","x":195,"y":422,"t":562736.3000000119,"ta":555.567}
|
||||
{"ev":"vibrate","pattern":"[10]","t":563092.3000000119,"ta":555.923}
|
||||
{"ev":"start","t":563092.5,"sid":55,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":555.923}
|
||||
{"ev":"start","t":563092.5,"sid":56,"url":"audio/sfx/amb_hum.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":555.923}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":567502.3000000119,"ta":560.333}
|
||||
{"ev":"vibrate","pattern":"[10]","t":567859.3000000119,"ta":560.69}
|
||||
{"ev":"start","t":567859.5,"sid":57,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":560.69}
|
||||
{"ev":"start","t":567859.5,"sid":58,"url":"audio/sfx/amb_cabinet.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":560.69}
|
||||
{"ev":"gesture","type":"swipedown","x":195,"y":422,"t":572269.900000006,"ta":565.101}
|
||||
{"ev":"vibrate","pattern":"[10]","t":572625.3000000119,"ta":565.456}
|
||||
{"ev":"start","t":572625.8000000119,"sid":59,"url":"audio/sfx/step.ogg","layer":"sfx","dur":0.27709750566893426,"rate":1,"loop":false,"when":0,"ta":565.457}
|
||||
{"ev":"start","t":572625.8000000119,"sid":60,"url":"audio/sfx/amb_gate_live.ogg","layer":"sfx","dur":6,"rate":1,"loop":false,"when":0,"ta":565.457}
|
||||
{"ev":"fetch","url":"audio/voice/female/room_gate.ogg","status":200,"ok":true,"ms":3,"t":572628.3000000119,"ta":565.459}
|
||||
{"ev":"vstart","url":"audio/voice/female/room_gate.ogg","t":572633.400000006,"dur":3.52,"ta":565.464}
|
||||
{"ev":"vend","url":"audio/voice/female/room_gate.ogg","t":576480.2000000179,"reason":"kill","ta":569.311}
|
||||
{"ev":"gesture","type":"doubletap","x":195,"y":422,"t":589967.5,"ta":582.798}
|
||||
{"ev":"vibrate","pattern":"[20]","t":590216.2000000179,"ta":583.047}
|
||||
{"ev":"vibrate","pattern":"[100]","t":590216.5,"ta":583.047}
|
||||
{"ev":"fetch","url":"audio/voice/female/escape.ogg","status":200,"ok":true,"ms":3,"t":590219.5,"ta":583.05}
|
||||
{"ev":"vstart","url":"audio/voice/female/escape.ogg","t":590232.7000000179,"dur":15.32,"ta":583.064}
|
||||
{"ev":"stop","t":592776.8000000119,"sid":1,"when":0,"ta":585.608}
|
||||
{"ev":"start","t":592817.400000006,"sid":61,"url":"audio/sfx/gate_open.ogg","layer":"sfx","dur":2.7999773242630384,"rate":1,"loop":false,"when":0,"ta":585.648}
|
||||
{"ev":"start","t":592817.400000006,"sid":62,"url":"audio/sfx/win_chime.ogg","layer":"sfx","dur":1.6,"rate":1,"loop":false,"when":0,"ta":585.648}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":594627.5,"ta":587.458}
|
||||
{"ev":"vibrate","pattern":"[20]","t":594990.8000000119,"ta":587.822}
|
||||
{"ev":"vend","url":"audio/voice/female/escape.ogg","t":605660.1000000238,"reason":"kill","ta":598.491}
|
||||
{"ev":"fetch","url":"audio/voice/female/time_band3.ogg","status":200,"ok":true,"ms":3,"t":605663.2000000179,"ta":598.494}
|
||||
{"ev":"vstart","url":"audio/voice/female/time_band3.ogg","t":605667.8000000119,"dur":3.2,"ta":598.499}
|
||||
{"ev":"vend","url":"audio/voice/female/time_band3.ogg","t":609140.2000000179,"reason":"kill","ta":601.971}
|
||||
{"ev":"fetch","url":"audio/voice/female/again.ogg","status":200,"ok":true,"ms":2,"t":609142.6000000238,"ta":601.974}
|
||||
{"ev":"vstart","url":"audio/voice/female/again.ogg","t":609148.400000006,"dur":4.96,"ta":601.979}
|
||||
{"ev":"vend","url":"audio/voice/female/again.ogg","t":614410.1000000238,"reason":"kill","ta":607.241}
|
||||
{"ev":"start","t":614410.400000006,"sid":63,"url":"audio/bgm/menu.ogg","layer":"bgm","dur":90,"rate":1,"loop":true,"when":0,"ta":607.241}
|
||||
{"ev":"gesture","type":"tap","x":195,"y":422,"t":630374.6000000238,"ta":623.206}
|
||||
{"ev":"vibrate","pattern":"[20]","t":630739.2000000179,"ta":623.57}
|
||||
{"ev":"start","t":630740,"sid":64,"url":"audio/bgm/drone.ogg","layer":"bgm","dur":117,"rate":1,"loop":true,"when":0,"ta":623.571}
|
||||
{"ev":"start","t":630740.1000000238,"sid":65,"url":"audio/sfx/amb_drip.ogg","layer":"sfx","dur":5,"rate":1,"loop":false,"when":0,"ta":623.571}
|
||||
{"ev":"fetch","url":"audio/voice/female/replay.ogg","status":200,"ok":true,"ms":3,"t":630742.5,"ta":623.573}
|
||||
{"ev":"vstart","url":"audio/voice/female/replay.ogg","t":630751.2000000179,"dur":8.24,"ta":623.582}
|
||||
{"ev":"stop","t":631600.2000000179,"sid":63,"when":0,"ta":624.431}
|
||||
{"ev":"vend","url":"audio/voice/female/replay.ogg","t":639000.2000000179,"reason":"kill","ta":631.831}
|
||||
{"ev":"recstop","t":646344.7000000179,"ta":639.176}
|
||||
@@ -0,0 +1,362 @@
|
||||
# escape 实时会话 transcript
|
||||
|
||||
- `[ -5.10s]` **GESTURE** tap @(195,422)
|
||||
- `[ 0.00s]` REC 开始 (audio/webm;codecs=opus)
|
||||
- `[ 0.08s]` VOICE ▶ g0_intro (dur 6.64s)
|
||||
- `[ 0.27s]` BGM ♪ drone (loop)
|
||||
- `[ 6.93s]` VOICE ■ g0_intro (kill)
|
||||
- `[ 6.93s]` VERDICT g0_intro: **OK** sim=1
|
||||
- 期望: 黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。
|
||||
- 听到: 黑暗,你在废弃的地下设施里醒来,什么都想不起来,你必须找到出路。
|
||||
- `[ 8.13s]` VOICE ▶ g1_move (dur 4.56s)
|
||||
- `[ 12.74s]` VOICE ■ g1_move (kill)
|
||||
- `[ 12.74s]` VOICE ▶ skip_hint (dur 1.6s)
|
||||
- `[ 12.74s]` VERDICT g1_move: **OK** sim=0.9697
|
||||
- 期望: 先活动一下。朝任意方向滑一下,走一小步。
|
||||
- 听到: 先活动一下,朝任意方向滑一下,走一小。
|
||||
- `[ 14.36s]` VOICE ■ skip_hint (kill)
|
||||
- `[ 14.36s]` VERDICT skip_hint: **OK** sim=0.8571
|
||||
- 期望: 单击可跳过旁白。
|
||||
- 听到: 单击可跳过旁板。
|
||||
- `[ 79.05s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 79.41s]` VIBRATE [10]
|
||||
- `[ 79.41s]` SFX ♪ step
|
||||
- `[ 79.42s]` VOICE ▶ g1_done (dur 2.72s)
|
||||
- `[ 79.42s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 82.15s]` VOICE ■ g1_done (kill)
|
||||
- `[ 82.15s]` VERDICT g1_done: **OK** sim=0.9412
|
||||
- 期望: 很好,你迈出了第一步。
|
||||
- 听到: 很好,你迈出了第一。
|
||||
- `[ 82.16s]` VOICE ▶ g2_wall (dur 5.68s)
|
||||
- `[ 82.32s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 82.68s]` VIBRATE [10]
|
||||
- `[ 87.88s]` VOICE ■ g2_wall (kill)
|
||||
- `[ 87.88s]` VIBRATE [60,40,60]
|
||||
- `[ 87.88s]` VERDICT g2_wall: **OK** sim=1
|
||||
- 期望: 这个房间不大,四面都是墙。再滑两下,试试碰碰墙。
|
||||
- 听到: 这个房间不大,四面都是墙,再滑两下试试碰碰墙。
|
||||
- `[ 87.88s]` SFX ♪ wall
|
||||
- `[ 87.89s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 90.24s]` VOICE ■ wall (kill)
|
||||
- `[ 90.24s]` VERDICT wall: **OK** sim=0.9412
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 墙那边是墙,换个方向。
|
||||
- `[ 109.13s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 109.49s]` VIBRATE [10]
|
||||
- `[ 109.49s]` VIBRATE [60,40,60]
|
||||
- `[ 109.49s]` SFX ♪ wall
|
||||
- `[ 109.49s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 109.49s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 111.86s]` VOICE ■ wall (kill)
|
||||
- `[ 111.86s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 111.87s]` VOICE ▶ g3_left (dur 2.96s)
|
||||
- `[ 114.88s]` VOICE ■ g3_left (kill)
|
||||
- `[ 114.88s]` VERDICT g3_left: **OK** sim=0.9
|
||||
- 期望: 跟着我指的路走。向左滑。
|
||||
- 听到: 跟着我指的路走,向左画。
|
||||
- `[ 116.90s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 117.26s]` VIBRATE [10]
|
||||
- `[ 117.26s]` SFX ♪ step
|
||||
- `[ 117.26s]` VOICE ▶ g4_down (dur 1.84s)
|
||||
- `[ 117.26s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 119.17s]` VOICE ■ g4_down (kill)
|
||||
- `[ 119.17s]` VERDICT g4_down: **OK** sim=1
|
||||
- 期望: 对。再向下滑。
|
||||
- 听到: 对,再向下滑。
|
||||
- `[ 122.67s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 123.02s]` VIBRATE [10]
|
||||
- `[ 123.02s]` SFX ♪ step
|
||||
- `[ 123.02s]` SFX ♪ amb_storage
|
||||
- `[ 123.03s]` VOICE ▶ g5_inspect (dur 3.92s)
|
||||
- `[ 123.03s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 127.17s]` VOICE ■ g5_inspect (kill)
|
||||
- `[ 127.17s]` VERDICT g5_inspect: **OK** sim=1
|
||||
- 期望: 听到水声了吗?单击一下,仔细检查这个房间。
|
||||
- 听到: 听到水声了吗?单击一下,仔细检查这个房间。
|
||||
- `[ 130.44s]` **GESTURE** tap @(195,422)
|
||||
- `[ 130.80s]` VIBRATE [20]
|
||||
- `[ 130.80s]` VIBRATE [15]
|
||||
- `[ 130.80s]` SFX ♪ pickup
|
||||
- `[ 130.81s]` VOICE ▶ g5_key (dur 1.52s)
|
||||
- `[ 130.81s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 132.42s]` VOICE ■ g5_key (kill)
|
||||
- `[ 132.42s]` VERDICT g5_key: **OK** sim=1
|
||||
- 期望: 你摸到了一把钥匙!
|
||||
- 听到: 你摸到了一把钥匙。
|
||||
- `[ 132.43s]` VOICE ▶ g6_doubletap (dur 10.64s)
|
||||
- `[ 140.91s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 141.16s]` VIBRATE [20]
|
||||
- `[ 143.39s]` VOICE ■ g6_doubletap (kill)
|
||||
- `[ 143.39s]` VERDICT g6_doubletap: **OK** sim=0.9787
|
||||
- 期望: 钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。
|
||||
- 听到: 匙钥匙能开锁,双击是把物品用出去的用法。现在双击试试。
|
||||
- `[ 143.40s]` VOICE ▶ inv_key (dur 1.68s)
|
||||
- `[ 145.29s]` VOICE ■ inv_key (kill)
|
||||
- `[ 145.29s]` VERDICT inv_key: **OK** sim=1
|
||||
- 期望: 你身上带着一把钥匙。
|
||||
- 听到: 你身上带着一把钥匙。
|
||||
- `[ 145.30s]` VOICE ▶ g6_done (dur 3.92s)
|
||||
- `[ 149.45s]` VOICE ■ g6_done (kill)
|
||||
- `[ 149.45s]` VERDICT g6_done: **OK** sim=1
|
||||
- 期望: 对,就是这样。接下来,靠你自己了。
|
||||
- 听到: 对,就是这样,接下来靠你自己了。
|
||||
- `[ 149.46s]` VOICE ▶ g7_goal (dur 6.88s)
|
||||
- `[ 156.59s]` VOICE ■ g7_goal (kill)
|
||||
- `[ 156.59s]` VERDICT g7_goal: **OK** sim=1
|
||||
- 期望: 找到能用这把钥匙打开的东西。需要帮助时,在原地双击。
|
||||
- 听到: 找到能用这把钥匙打开的东西,需要帮助时在原地双击。
|
||||
- `[ 156.59s]` SFX ♪ amb_storage
|
||||
- `[ 178.80s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 179.16s]` VIBRATE [10]
|
||||
- `[ 179.16s]` SFX ♪ step
|
||||
- `[ 179.16s]` SFX ♪ amb_hum
|
||||
- `[ 179.16s]` VOICE ▶ empty_2 (dur 4.88s)
|
||||
- `[ 179.16s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 184.15s]` VOICE ■ empty_2 (kill)
|
||||
- `[ 184.15s]` VERDICT empty_2: **OK** sim=1
|
||||
- 期望: 你伸出手,摸到的只有冰冷粗糙的墙壁。
|
||||
- 听到: 你伸出手摸到的只有冰冷粗糙的墙壁。
|
||||
- `[ 185.57s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 185.92s]` VIBRATE [10]
|
||||
- `[ 185.92s]` SFX ♪ step
|
||||
- `[ 185.92s]` SFX ♪ amb_power
|
||||
- `[ 185.93s]` VOICE ▶ room_power (dur 2.64s)
|
||||
- `[ 185.93s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 188.67s]` VOICE ■ room_power (kill)
|
||||
- `[ 188.67s]` VERDICT room_power: **OK** sim=1
|
||||
- 期望: 这个房间的墙上,有一只电箱。
|
||||
- 听到: 这个房间的墙上有一只电箱。
|
||||
- `[ 192.33s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 192.69s]` VIBRATE [10]
|
||||
- `[ 192.69s]` VIBRATE [60,40,60]
|
||||
- `[ 192.69s]` SFX ♪ wall
|
||||
- `[ 192.69s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 192.69s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 195.05s]` VOICE ■ wall (kill)
|
||||
- `[ 195.05s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 195.06s]` VOICE ▶ wall_dir_u (dur 1.36s)
|
||||
- `[ 196.67s]` VOICE ■ wall_dir_u (kill)
|
||||
- `[ 196.67s]` VERDICT wall_dir_u: **OK** sim=1
|
||||
- 期望: 上边是墙。
|
||||
- 听到: 上边是墙。
|
||||
- `[ 199.10s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 199.45s]` VIBRATE [10]
|
||||
- `[ 199.46s]` VIBRATE [60,40,60]
|
||||
- `[ 199.46s]` SFX ♪ wall
|
||||
- `[ 199.46s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 199.46s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 201.82s]` VOICE ■ wall (kill)
|
||||
- `[ 201.82s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 203.86s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 204.22s]` VIBRATE [10]
|
||||
- `[ 204.22s]` VIBRATE [60,40,60]
|
||||
- `[ 204.22s]` SFX ♪ wall
|
||||
- `[ 204.22s]` VOICE ▶ wall (dur 2.08s)
|
||||
- `[ 204.22s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 206.59s]` VOICE ■ wall (kill)
|
||||
- `[ 206.59s]` VERDICT wall: **OK** sim=1
|
||||
- 期望: 那边是墙,换个方向。
|
||||
- 听到: 那边是墙,换个方向。
|
||||
- `[ 206.60s]` VOICE ▶ wall_dir_l (dur 1.04s)
|
||||
- `[ 207.75s]` VOICE ■ wall_dir_l (kill)
|
||||
- `[ 207.75s]` VERDICT wall_dir_l: **OK** sim=1
|
||||
- 期望: 左边是墙。
|
||||
- 听到: 左边是墙。
|
||||
- `[ 210.63s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 210.88s]` VIBRATE [20]
|
||||
- `[ 210.88s]` VIBRATE [60,40,60]
|
||||
- `[ 210.89s]` VOICE ▶ use_fail (dur 7.36s)
|
||||
- `[ 210.89s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 218.48s]` VOICE ■ use_fail (kill)
|
||||
- `[ 218.48s]` VERDICT use_fail: **OK** sim=0.9655
|
||||
- 期望: 这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。
|
||||
- 听到: 这里没有用得上东西的地方,换个房间试试,或者先单机检查一下周围。
|
||||
- `[ 218.49s]` VOICE ▶ stuck_cabinet_1 (dur 3.84s)
|
||||
- `[ 222.62s]` VOICE ■ stuck_cabinet_1 (kill)
|
||||
- `[ 222.62s]` VERDICT stuck_cabinet_1: **OK** sim=0.9333
|
||||
- 期望: 钥匙就在你身上。它能打开某一把锁。
|
||||
- 听到: 钥匙就在你身上,他能打开某一把锁。
|
||||
- `[ 255.88s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 256.24s]` VIBRATE [10]
|
||||
- `[ 256.24s]` SFX ♪ step
|
||||
- `[ 256.24s]` SFX ♪ amb_wind
|
||||
- `[ 256.25s]` VOICE ▶ empty_1 (dur 5.2s)
|
||||
- `[ 256.25s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 261.50s]` VOICE ■ empty_1 (kill)
|
||||
- `[ 261.50s]` VERDICT empty_1: **OK** sim=1
|
||||
- 期望: 房间里空空荡荡,只有你自己的回声。
|
||||
- 听到: 房间里空空荡荡,只有你自己的回声。
|
||||
- `[ 262.64s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 263.00s]` VIBRATE [10]
|
||||
- `[ 263.00s]` SFX ♪ step
|
||||
- `[ 263.00s]` SFX ♪ amb_hum
|
||||
- `[ 263.01s]` VOICE ▶ empty_3 (dur 3.68s)
|
||||
- `[ 263.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 266.86s]` VOICE ■ empty_3 (kill)
|
||||
- `[ 266.86s]` VERDICT empty_3: **OK** sim=1
|
||||
- 期望: 除了远处的水滴声,这里什么都没有。
|
||||
- 听到: 除了远处的水滴声,这里什么都没有。
|
||||
- `[ 269.41s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 269.77s]` VIBRATE [10]
|
||||
- `[ 269.77s]` SFX ♪ step
|
||||
- `[ 269.77s]` SFX ♪ amb_cabinet
|
||||
- `[ 269.78s]` VOICE ▶ room_cabinet (dur 2.64s)
|
||||
- `[ 269.78s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 272.52s]` VOICE ■ room_cabinet (kill)
|
||||
- `[ 272.52s]` VERDICT room_cabinet: **OK** sim=1
|
||||
- 期望: 这个房间里,立着一个铁柜。
|
||||
- 听到: 这个房间里立着一个铁柜。
|
||||
- `[ 276.18s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 276.43s]` VIBRATE [20]
|
||||
- `[ 276.43s]` VIBRATE [100]
|
||||
- `[ 276.43s]` SFX ♪ unlock
|
||||
- `[ 276.43s]` SFX ♪ door_creak
|
||||
- `[ 276.44s]` VOICE ▶ unlock_cabinet (dur 11.48s)
|
||||
- `[ 276.44s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 288.15s]` VOICE ■ unlock_cabinet (kill)
|
||||
- `[ 288.15s]` VERDICT unlock_cabinet: **OK** sim=0.9714
|
||||
- 期望: 钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。
|
||||
- 听到: 钥匙插进锁孔,缓缓转动,咔嗒一声,柜门开了,柜子深处躺着一枚保险丝,保险丝到手了。
|
||||
- `[ 288.16s]` VOICE ▶ gd_next_fuse (dur 3.28s)
|
||||
- `[ 291.63s]` VOICE ■ gd_next_fuse (kill)
|
||||
- `[ 291.63s]` VERDICT gd_next_fuse: **OK** sim=1
|
||||
- 期望: 保险丝到手。接下来,去找电箱。
|
||||
- 听到: 保险丝到手,接下来去找电箱。
|
||||
- `[ 291.64s]` VOICE ▶ gd_box_dir (dur 2.16s)
|
||||
- `[ 294.01s]` VOICE ■ gd_box_dir (kill)
|
||||
- `[ 294.01s]` VERDICT gd_box_dir: **OK** sim=1
|
||||
- 期望: 电箱,在左面的房间。
|
||||
- 听到: 电箱在左面的房间。
|
||||
- `[ 310.43s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 310.78s]` VIBRATE [10]
|
||||
- `[ 310.78s]` SFX ♪ step
|
||||
- `[ 310.78s]` SFX ♪ amb_drip
|
||||
- `[ 327.19s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 327.55s]` VIBRATE [10]
|
||||
- `[ 327.55s]` SFX ♪ step
|
||||
- `[ 327.55s]` SFX ♪ amb_hum
|
||||
- `[ 343.96s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 344.31s]` VIBRATE [10]
|
||||
- `[ 344.31s]` SFX ♪ step
|
||||
- `[ 344.31s]` SFX ♪ amb_drip
|
||||
- `[ 360.73s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 361.08s]` VIBRATE [10]
|
||||
- `[ 361.08s]` SFX ♪ step
|
||||
- `[ 361.08s]` SFX ♪ amb_cabinet
|
||||
- `[ 377.49s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 377.85s]` VIBRATE [10]
|
||||
- `[ 377.85s]` SFX ♪ step
|
||||
- `[ 377.85s]` SFX ♪ amb_hum
|
||||
- `[ 408.88s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 409.25s]` VIBRATE [10]
|
||||
- `[ 409.25s]` SFX ♪ step
|
||||
- `[ 409.25s]` SFX ♪ amb_cabinet
|
||||
- `[ 425.66s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 426.01s]` VIBRATE [10]
|
||||
- `[ 426.01s]` SFX ♪ step
|
||||
- `[ 426.01s]` SFX ♪ amb_drip
|
||||
- `[ 430.00s]` VIBRATE [30,50,30,50,30]
|
||||
- `[ 430.01s]` VOICE ▶ gd_prog_2 (dur 2.56s)
|
||||
- `[ 430.01s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 432.75s]` VOICE ■ gd_prog_2 (kill)
|
||||
- `[ 432.75s]` VERDICT gd_prog_2: **OK** sim=1
|
||||
- 期望: 铁柜已经打开。电还没有通。
|
||||
- 听到: 铁柜已经打开,电还没有通。
|
||||
- `[ 442.42s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 442.78s]` VIBRATE [10]
|
||||
- `[ 442.78s]` SFX ♪ step
|
||||
- `[ 442.78s]` SFX ♪ amb_hum
|
||||
- `[ 459.19s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 459.54s]` VIBRATE [10]
|
||||
- `[ 459.54s]` SFX ♪ step
|
||||
- `[ 459.54s]` SFX ♪ amb_drip
|
||||
- `[ 475.95s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 476.31s]` VIBRATE [10]
|
||||
- `[ 476.31s]` SFX ♪ step
|
||||
- `[ 476.31s]` SFX ♪ amb_cabinet
|
||||
- `[ 526.84s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 527.19s]` VIBRATE [10]
|
||||
- `[ 527.19s]` SFX ♪ step
|
||||
- `[ 527.19s]` SFX ♪ amb_drip
|
||||
- `[ 531.60s]` **GESTURE** swipeleft @(195,422)
|
||||
- `[ 531.96s]` VIBRATE [10]
|
||||
- `[ 531.96s]` SFX ♪ step
|
||||
- `[ 531.96s]` SFX ♪ amb_hum
|
||||
- `[ 536.37s]` **GESTURE** swipeup @(195,422)
|
||||
- `[ 536.73s]` VIBRATE [10]
|
||||
- `[ 536.73s]` SFX ♪ step
|
||||
- `[ 536.73s]` SFX ♪ amb_power
|
||||
- `[ 541.13s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 541.38s]` VIBRATE [20]
|
||||
- `[ 541.38s]` VIBRATE [100]
|
||||
- `[ 541.38s]` SFX ♪ spark
|
||||
- `[ 541.38s]` SFX ♪ power_on
|
||||
- `[ 541.39s]` VOICE ▶ fix_box (dur 7.52s)
|
||||
- `[ 541.39s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 548.98s]` VOICE ■ fix_box (kill)
|
||||
- `[ 548.98s]` VERDICT fix_box: **OK** sim=0.9153
|
||||
- 期望: 你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了!
|
||||
- 听到: 你把保险丝用力安静卡座,火花一闪,嗡鸣声响起,头顶的线路恢复供电。
|
||||
- `[ 548.99s]` VOICE ▶ gd_gate_dir (dur 2.32s)
|
||||
- `[ 550.79s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 551.16s]` VIBRATE [10]
|
||||
- `[ 551.16s]` SFX ♪ step
|
||||
- `[ 551.16s]` SFX ♪ amb_wind
|
||||
- `[ 551.36s]` VOICE ■ gd_gate_dir (kill)
|
||||
- `[ 551.36s]` VERDICT gd_gate_dir: **OK** sim=1
|
||||
- 期望: 大门,在右面的房间。
|
||||
- 听到: 大门在右面的房间。
|
||||
- `[ 555.57s]` **GESTURE** swiperight @(195,422)
|
||||
- `[ 555.92s]` VIBRATE [10]
|
||||
- `[ 555.92s]` SFX ♪ step
|
||||
- `[ 555.92s]` SFX ♪ amb_hum
|
||||
- `[ 560.33s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 560.69s]` VIBRATE [10]
|
||||
- `[ 560.69s]` SFX ♪ step
|
||||
- `[ 560.69s]` SFX ♪ amb_cabinet
|
||||
- `[ 565.10s]` **GESTURE** swipedown @(195,422)
|
||||
- `[ 565.46s]` VIBRATE [10]
|
||||
- `[ 565.46s]` SFX ♪ step
|
||||
- `[ 565.46s]` SFX ♪ amb_gate_live
|
||||
- `[ 565.46s]` VOICE ▶ room_gate (dur 3.52s)
|
||||
- `[ 565.46s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 569.31s]` VOICE ■ room_gate (kill)
|
||||
- `[ 569.31s]` VERDICT room_gate: **OK** sim=1
|
||||
- 期望: 面前,是一扇沉重的铁门。
|
||||
- 听到: 面前是一扇沉重的铁门。
|
||||
- `[ 582.80s]` **GESTURE** doubletap @(195,422)
|
||||
- `[ 583.05s]` VIBRATE [20]
|
||||
- `[ 583.05s]` VIBRATE [100]
|
||||
- `[ 583.06s]` VOICE ▶ escape (dur 15.32s)
|
||||
- `[ 583.06s]` VERDICT (无语音区间): **SFX_BGM_ONLY**
|
||||
- `[ 585.65s]` SFX ♪ gate_open
|
||||
- `[ 585.65s]` SFX ♪ win_chime
|
||||
- `[ 587.46s]` **GESTURE** tap @(195,422)
|
||||
- `[ 587.82s]` VIBRATE [20]
|
||||
- `[ 598.49s]` VOICE ■ escape (kill)
|
||||
- `[ 598.49s]` VERDICT escape: **OK** sim=0.9053
|
||||
- 期望: 你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。
|
||||
- 听到: 你搬动开关,电击轰,沉重的体能缓缓升起,刺眼的光线涌了进来,你眯起眼睛向前迈出了第一步,自由了,你逃出来了。
|
||||
- `[ 598.50s]` VOICE ▶ time_band3 (dur 3.2s)
|
||||
- `[ 601.97s]` VOICE ■ time_band3 (kill)
|
||||
- `[ 601.97s]` VERDICT time_band3: **OK** sim=0.88
|
||||
- 期望: 你逃出来了,用时不到十分钟。
|
||||
- 听到: 你逃出来了,用时不到10分钟。
|
||||
- `[ 601.98s]` VOICE ▶ again (dur 4.96s)
|
||||
- `[ 607.24s]` VOICE ■ again (kill)
|
||||
- `[ 607.24s]` BGM ♪ menu (loop)
|
||||
- `[ 607.24s]` VERDICT again: **OK** sim=1
|
||||
- 期望: 单击屏幕,再来一次。下滑,打开菜单。
|
||||
- 听到: 单击屏幕再来一次下滑打开菜单。
|
||||
- `[ 623.21s]` **GESTURE** tap @(195,422)
|
||||
- `[ 623.57s]` VIBRATE [20]
|
||||
- `[ 623.57s]` BGM ♪ drone (loop)
|
||||
- `[ 623.57s]` SFX ♪ amb_drip
|
||||
- `[ 623.58s]` VOICE ▶ replay (dur 8.24s)
|
||||
- `[ 631.83s]` VOICE ■ replay (kill)
|
||||
Binary file not shown.
@@ -0,0 +1,164 @@
|
||||
# 试玩转写:《escape》
|
||||
|
||||
> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文,
|
||||
> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作),
|
||||
> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。
|
||||
t+ 0.0s (玩家点开游戏,轻触屏幕开始)
|
||||
t+ 0.0s ♫ BGM 切换 → bgm/drone
|
||||
t+ 0.0s ♪ 向导音:explore(探索/安全)
|
||||
t+ 0.0s ▶ 语音:「黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。」
|
||||
t+ 0.0s 【状态】黑屏,只有引子的声音,先听完 引导第 1/8 步,等我做手势(语音播放中,语速1)
|
||||
t+ 0.0s 【状态】引导第 1/8 步 引导第 1/8 步,等我做手势(语音播放中,语速1)
|
||||
|
||||
#### 【玩家动作】照引导单击了一下
|
||||
|
||||
t+ 0.0s ▶ 语音:「先活动一下。朝任意方向滑一下,走一小步。」
|
||||
t+ 2.1s ▶ 语音:「单击可跳过旁白。」
|
||||
t+ 4.2s ♪ 向导音:turn(轮到你)
|
||||
t+ 4.2s 【状态】引导第 2/8 步 引导第 2/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】随便滑了一步,有脚步声
|
||||
|
||||
t+ 4.2s ♪ 音效 sfx/step
|
||||
t+ 4.2s ▶ 语音:「很好,你迈出了第一步。」
|
||||
t+ 6.4s ▶ 语音:「这个房间不大,四面都是墙。再滑两下,试试碰碰墙。」
|
||||
t+ 8.5s ♪ 向导音:turn(轮到你)
|
||||
t+ 8.5s 【状态】引导第 3/8 步 引导第 3/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
t+ 8.5s ♪ 音效 sfx/wall
|
||||
t+ 8.5s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 8.5s 〰 震动:error(做错了:两连短震)
|
||||
|
||||
#### 【玩家动作】又滑一步,又撞墙了——墙的方位听出来了
|
||||
|
||||
t+ 10.6s ♪ 音效 sfx/wall
|
||||
t+ 10.6s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 10.6s 〰 震动:error(做错了:两连短震)
|
||||
t+ 12.7s ▶ 语音:「跟着我指的路走。向左滑。」
|
||||
t+ 14.8s ♪ 向导音:turn(轮到你)
|
||||
t+ 14.8s 【状态】引导第 4/8 步 引导第 4/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】这回往左,走通了一步
|
||||
|
||||
t+ 14.8s ♪ 音效 sfx/step
|
||||
t+ 14.8s ▶ 语音:「对。再向下滑。」
|
||||
t+ 17.0s ♪ 向导音:turn(轮到你)
|
||||
t+ 17.0s 【状态】引导第 5/8 步 引导第 5/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】往下滑,进了储物间
|
||||
|
||||
t+ 17.0s ♪ 音效 sfx/step
|
||||
t+ 17.0s ♪ 音效 sfx/amb_storage
|
||||
t+ 17.0s ▶ 语音:「听到水声了吗?单击一下,仔细检查这个房间。」
|
||||
t+ 19.1s ♪ 向导音:turn(轮到你)
|
||||
t+ 19.1s 【状态】引导第 6/8 步 引导第 6/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】单击摸一遍房间,摸到钥匙了
|
||||
|
||||
t+ 19.1s ♪ 音效 sfx/pickup
|
||||
t+ 19.1s ▶ 语音:「你摸到了一把钥匙!」
|
||||
t+ 19.1s 〰 震动:pickup(获得)
|
||||
t+ 21.2s ▶ 语音:「钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。」
|
||||
t+ 23.3s ♪ 向导音:turn(轮到你)
|
||||
t+ 23.3s 【状态】引导第 7/8 步 引导第 7/8 步,等我做手势(BGM=bgm/drone,语速1)
|
||||
|
||||
#### 【玩家动作】双击看了看背包
|
||||
|
||||
t+ 23.3s ▶ 语音:「你身上带着一把钥匙。」
|
||||
t+ 25.4s ▶ 语音:「对,就是这样。接下来,靠你自己了。」
|
||||
t+ 27.6s ▶ 语音:「找到能用这把钥匙打开的东西。需要帮助时,在原地双击。」
|
||||
t+ 29.7s ♪ 向导音:turn(轮到你)
|
||||
t+ 29.7s ♪ 音效 sfx/amb_storage
|
||||
t+ 29.7s 【状态】引导完毕,正式开始。我在储物间 探索中,我在 (0,2)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 29.7s ……… 静默 3s(辨了辨方向) ………
|
||||
t+ 29.7s ♪ 音效 sfx/step
|
||||
t+ 29.7s ♪ 音效 sfx/amb_hum
|
||||
t+ 29.7s ▶ 语音:「你伸出手,摸到的只有冰冷粗糙的墙壁。」
|
||||
|
||||
#### 【玩家动作】路过一间空房,它自己开口了:摸到的只有冰冷粗糙的墙壁
|
||||
|
||||
t+ 31.8s ♪ 音效 sfx/step
|
||||
t+ 31.8s ♪ 音效 sfx/amb_power
|
||||
t+ 31.8s ▶ 语音:「这个房间的墙上,有一只电箱。」
|
||||
|
||||
#### 【玩家动作】电流声——电箱房到了
|
||||
|
||||
t+ 33.9s ♪ 音效 sfx/wall
|
||||
t+ 33.9s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 33.9s 〰 震动:error(做错了:两连短震)
|
||||
t+ 36.0s ▶ 语音:「上边是墙。」
|
||||
|
||||
#### 【玩家动作】北边是墙,撞了一下——「那边是墙」后面跟了句「上边是墙。」,这面不通记住了
|
||||
|
||||
t+ 36.0s ♪ 音效 sfx/wall
|
||||
t+ 36.0s ▶ 语音:「那边是墙,换个方向。」
|
||||
t+ 36.0s 〰 震动:error(做错了:两连短震)
|
||||
|
||||
#### 【玩家动作】又撞了一下——同方向 10 秒内不重复报方位,游戏不啰嗦
|
||||
|
||||
t+ 45.0s ♪ 音效 sfx/step
|
||||
t+ 45.0s ♪ 音效 sfx/amb_wind
|
||||
t+ 45.0s ▶ 语音:「房间里空空荡荡,只有你自己的回声。」
|
||||
|
||||
#### 【玩家动作】往东走,一间空房自报家门:空空荡荡只有回声
|
||||
|
||||
t+ 47.1s ♪ 音效 sfx/step
|
||||
t+ 47.1s ♪ 音效 sfx/amb_hum
|
||||
t+ 47.1s ▶ 语音:「除了远处的水滴声,这里什么都没有。」
|
||||
|
||||
#### 【玩家动作】又一间空房:除了远处的水滴声什么都没有
|
||||
|
||||
t+ 49.2s ♪ 音效 sfx/step
|
||||
t+ 49.2s ♪ 音效 sfx/amb_cabinet
|
||||
t+ 49.2s ▶ 语音:「这个房间里,立着一个铁柜。」
|
||||
|
||||
#### 【玩家动作】到了铁柜房,柜子锁着
|
||||
|
||||
t+ 51.4s ♪ 音效 sfx/unlock
|
||||
t+ 51.4s ♪ 音效 sfx/door_creak
|
||||
t+ 51.4s ▶ 语音:「钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。」
|
||||
t+ 51.4s 〰 震动:success(成功长震)
|
||||
t+ 53.5s ▶ 向导语音:「保险丝到手。接下来,去找电箱。」
|
||||
t+ 55.6s ▶ 向导语音:「电箱,在左面的房间。」
|
||||
t+ 57.7s 【状态】柜子开了。「保险丝到手。接下来,去找电箱。」后面跟的是「电箱,在左面的房间。」——目标名和方位一句话说全了 探索中,我在 (2,1)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 57.7s ♪ 音效 sfx/step
|
||||
t+ 57.7s ♪ 音效 sfx/amb_drip
|
||||
|
||||
#### 【玩家动作】照方位句往左(西)摸
|
||||
|
||||
t+ 60.0s ♪ 音效 sfx/step
|
||||
t+ 60.0s ♪ 音效 sfx/amb_hum
|
||||
t+ 65.0s ♪ 音效 sfx/step
|
||||
t+ 65.0s ♪ 音效 sfx/amb_power
|
||||
|
||||
#### 【玩家动作】电流声越来越清晰——电箱房到了
|
||||
|
||||
t+ 70.0s ♪ 音效 sfx/spark
|
||||
t+ 70.0s ♪ 音效 sfx/power_on
|
||||
t+ 70.0s ▶ 语音:「你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了!」
|
||||
t+ 70.0s 〰 震动:success(成功长震)
|
||||
t+ 72.1s ▶ 向导语音:「大门,在右面的房间。」
|
||||
t+ 80.0s 【状态】电箱修好了。目标句后面照样是目标名+方位——「大门,在右面的房间。」 探索中,我在 (0,0)。四向滑挪步,单击摸一遍房间,双击用物品(BGM=bgm/drone,语速1)
|
||||
t+ 80.0s ♪ 音效 sfx/step
|
||||
t+ 80.0s ♪ 音效 sfx/amb_wind
|
||||
|
||||
#### 【玩家动作】照方位句往右(东)摸
|
||||
|
||||
t+ 85.0s ♪ 音效 sfx/step
|
||||
t+ 85.0s ♪ 音效 sfx/amb_hum
|
||||
t+ 90.0s ♪ 音效 sfx/step
|
||||
t+ 90.0s ♪ 音效 sfx/amb_cabinet
|
||||
t+ 95.0s ♪ 音效 sfx/step
|
||||
t+ 95.0s ♪ 音效 sfx/amb_gate_live
|
||||
t+ 95.0s ▶ 语音:「面前,是一扇沉重的铁门。」
|
||||
|
||||
#### 【玩家动作】脚步声停下来——面前这间就是大门
|
||||
|
||||
t+ 97.1s ♪ 向导音:settle(结算)
|
||||
t+ 97.1s ▶ 语音:「你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。」
|
||||
t+ 97.1s 〰 震动:success(成功长震)
|
||||
t+ 99.2s ▶ 语音:「你逃出来了,用时不到两分钟。了不起!」
|
||||
t+ 99.7s ♪ 音效 sfx/gate_open
|
||||
t+ 99.7s ♪ 音效 sfx/win_chime
|
||||
t+ 101.4s ▶ 语音:「单击屏幕,再来一次。下滑,打开菜单。」
|
||||
t+ 103.5s ♫ BGM 切换 → bgm/menu(淡入 1500ms)
|
||||
t+ 103.5s 【状态】钥匙插进锁孔,门开了——结算播报来了,这局是完整的赢 逃脱了,结算播报中。播完单击再来,下滑开菜单(BGM=bgm/menu,语速1)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -237,6 +237,20 @@ ESCAPE_LINES = [
|
||||
("gd_room_r", _ESC, "右面的房间。"),
|
||||
("gd_room_u", _ESC, "上面的房间。"),
|
||||
("gd_room_d", _ESC, "下面的房间。"),
|
||||
# ---- escape-state round2(docs/design/25-escape-map-flow.md §4.1 B1/B2/B3,台词与草案逐字一致)----
|
||||
# B1(F1):撞墙方位句(陈述式非教学腔),wall 播完后接播,同向 10s 限频。
|
||||
("wall_dir_l", _ESC, "左边是墙。"),
|
||||
("wall_dir_r", _ESC, "右边是墙。"),
|
||||
("wall_dir_u", _ESC, "上边是墙。"),
|
||||
("wall_dir_d", _ESC, "下边是墙。"),
|
||||
# B2(F2):目标名+方位一体句,替换三处 gd_room_* 接播(原句保留作异常路径兜底)。
|
||||
("gd_cabinet_dir", _ESC, "铁柜,在右面的房间。"),
|
||||
("gd_box_dir", _ESC, "电箱,在左面的房间。"),
|
||||
("gd_gate_dir", _ESC, "大门,在右面的房间。"),
|
||||
# B3(F3):无进展 150s 活跃计时器的进度重述(stage=cabinet/box/gate,key 阶段不走本通道)。
|
||||
("gd_prog_1", _ESC, "钥匙已经到手。找到能用它的锁。"),
|
||||
("gd_prog_2", _ESC, "铁柜已经打开。电还没有通。"),
|
||||
("gd_prog_3", _ESC, "电已经通了。去找那扇大门。"),
|
||||
|
||||
]
|
||||
|
||||
|
||||
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.
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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+163
-40
@@ -8,14 +8,17 @@
|
||||
*
|
||||
* 手势映射(偏离全局默认,引导中讲清):
|
||||
* - 四向滑动:在相邻房间间移动,撞墙播闷响 + ERROR 震动 + wall 语音(每次都播;
|
||||
* PLAY 阶段只播「那边是墙」,教学腔方位句 guide_blunt_* 仅限引导期)
|
||||
* PLAY 阶段 wall 播完接播陈述式方位句 wall_dir_<dir>「左边是墙。」(escape-state
|
||||
* round2 B1,同向 10s 限频,被打断自然作废);教学腔 guide_blunt_* 仅限引导期)
|
||||
* - 单击:重播当前房间环境音 + 检查描述(储物间拾钥匙);
|
||||
* voice 播放中单击 = 跳过本句(audio.skipVoice(),链播继续,12 号文档)
|
||||
* 并补发检查——环境音即时重播、描述进待播队列等链播播完(不顶句)。
|
||||
* 不可跳:引导 G0-G7(引导期单击是答题)、关键获得(found_key/
|
||||
* unlock_cabinet/fix_box/escape 结算链)、L3 带路(stuck_*_3 + nav_*)
|
||||
* - 双击:使用物品(钥匙开柜 / 保险丝修电箱 / 通电后开大门);
|
||||
* 无可用目标时播报背包 + L2 级明示提示
|
||||
* 无可用目标时播报背包/use_fail + L1 级意象暗示(escape-state round2 B4:
|
||||
* 原直通 L2 明示把答案白送给没卡关的玩家,降级为 L1;答案仍锁在计时器
|
||||
* L2/L3 与进展链里)
|
||||
* - 引导阶段下滑:跳过引导(仅限答案不含滑动的步骤 G0/G3/G5/G6;G1/G2 任意
|
||||
* 滑动即答案、G4 的答案就是下滑——这些步骤下滑 = 作答,不可跳过);
|
||||
* ENDING 下滑:菜单
|
||||
@@ -31,12 +34,23 @@
|
||||
* 修电箱/首到关键房间/逃脱)清空已播级别,下段静默期从 L1 重新分级。
|
||||
* 提示到点只进待播队列:等当前语音自然播完再播、绝不顶掉进行中的语音;
|
||||
* 待播期间玩家任何操作即作废该提示(未播级别不计入已播)。
|
||||
* escape-state round2 新增平行通道(B3):无进展 150s 且期间 ≥5 次有效手势
|
||||
* (活跃但零进展,挂机仍走 60s L1 体系)→ 播不泄题的进度重述 gd_prog_1/2/3
|
||||
* (stage=cabinet/box/gate,key 阶段不走本通道),每进展段限 1 次,
|
||||
* 队列语义与卡关提示同款(不顶句、待播期间有操作即作废)。
|
||||
*
|
||||
* round4 H1(docs/design/14-guide-layer.md「round4 v1.3」):阶段目标句
|
||||
* (found_key / gd_next_fuse / fix_box)播完后,按房间图计算目标房间相对当前
|
||||
* 房间的真实方位,接播 gd_room_l/r/u/d 之一(游戏反馈层全档位;目标在同一
|
||||
* 房间不播;方向 = escape 移动坐标系,up/down/left/right 滑动方向即方位)。
|
||||
* 引导期 g7_goal 不接(引导本身逐句带路,且引导链被 playtest 断言冻结)。
|
||||
* 房间的真实方位接播方位句;escape-state round2 B2 把三处固定接线点升级为
|
||||
* "目标名+方位"一体句(gd_cabinet_dir/gd_box_dir/gd_gate_dir),异常路径方位
|
||||
* 与枚举不符时回落 gd_room_l/r/u/d(原句保留)。引导期 g7_goal 不接(引导链
|
||||
* 被 playtest 断言冻结);但跳过引导/REOPEN 直进路径补播 g7_goal(round2 B8:
|
||||
* 任何路径进 PLAY 都至少听过一次目标句)。
|
||||
*
|
||||
* escape-state round2 逻辑修复:B6 引导 busy 窗口缓存首个非跳过分手势、步骤
|
||||
* 解锁后按新步骤补判(合法=作答/不合法=答错路径,缓存手势不触发下滑跳过);
|
||||
* B7 结算链播完前 ENDING 单击不重开(_settleBusy 守卫,链完/30s 兜底解除);
|
||||
* B5a 空房首访补播 empty_* 一次性听觉锚(不算进展事件)。
|
||||
*
|
||||
* 语音 id 权威清单:docs/audio/round2-voice-ids.md(已删除的 n0–n9 数字拼接链、
|
||||
* hint_ 四级提示、intro/tutorial 旧开场不再引用)。震动分工:滑动/点按的识别反馈由 gesture.js 内置,本层只发语义震动
|
||||
@@ -80,6 +94,16 @@ const KEY_ROOMS = {
|
||||
// 空房环境音轮换(弱化版风声/嗡鸣)
|
||||
const EMPTY_AMB = { '1,0': 'sfx/amb_wind', '0,1': 'sfx/amb_hum', '1,2': 'sfx/amb_wind', '2,0': 'sfx/amb_hum' };
|
||||
|
||||
// 空房首访描述(escape-state round2 B5a:复用现有 empty_*,进入时一次性播;
|
||||
// 与 _inspect 单击检查映射一致——两间"远处水滴"空房 (1,2)/(2,0) 对称分布,
|
||||
// 共用 empty_3 也是合法的记忆点)
|
||||
const EMPTY_FIRST_VOICE = {
|
||||
'1,0': 'voice/empty_1', '0,1': 'voice/empty_2', '1,2': 'voice/empty_3', '2,0': 'voice/empty_3',
|
||||
};
|
||||
|
||||
// B3 无进展进度重述:stage → gd_prog id(key 阶段不走本通道)
|
||||
const GD_PROG = { cabinet: 'voice/gd_prog_1', box: 'voice/gd_prog_2', gate: 'voice/gd_prog_3' };
|
||||
|
||||
const PREWARM_SFX = [
|
||||
'sfx/step', 'sfx/wall', 'sfx/pickup', 'sfx/unlock', 'sfx/door_creak',
|
||||
'sfx/spark', 'sfx/power_on', 'sfx/gate_open', 'sfx/win_chime',
|
||||
@@ -110,6 +134,10 @@ export class EscapeGame extends Game {
|
||||
this.cabinetOpen = false;
|
||||
this.powerOn = false;
|
||||
this.visited = new Set(); // 首到关键房间记录(进展事件 + room_* 描述)
|
||||
this.emptyVisited = new Set(); // 首到空房记录(B5a 首访描述,不算进展事件)
|
||||
this._freshEmpty = null; // 首访句刚播过的空房 key(本房间内单击不重复同一句)
|
||||
this._wallDirAt = {}; // B1 撞墙方位句同向 10s 限频:dir -> 上次播出时刻
|
||||
this._settleBusy = false; // B7 结算链守卫:播完前 ENDING 单击不重开
|
||||
this.startElapsedMs = 0;
|
||||
// 单击跳过:当前 voice 句是否可跳(每次 voice 播放时更新,见 _playVoice)
|
||||
this._voiceSkippable = false;
|
||||
@@ -118,10 +146,15 @@ export class EscapeGame extends Game {
|
||||
this.guideSwipes = 0; // G2 撞墙计数
|
||||
this.guideErrs = 0; // 当前步骤连续错误数
|
||||
this._guideBusy = false; // 步骤推进语音播放中(忽略非跳过分手势)
|
||||
this._guidePending = null; // B6:busy 窗口缓存的首个非跳过分手势(仅 1 个、不跨步存活)
|
||||
// 卡关检测(按"无操作时长"计时,见 _checkStuck)
|
||||
this._lastActiveAt = Date.now();
|
||||
this._stuckShown = new Set(); // 当前进展段内已自动播过的级别 'L1'|'L2'|'L3'
|
||||
this._lastL3At = 0;
|
||||
// B3 无进展计时(与无操作计时并存互不复位)
|
||||
this._lastProgressAt = Date.now(); // 上一次进展事件时刻
|
||||
this._gesturesSinceProgress = 0; // 进展段内有效手势数(≥5 才触发 gd_prog)
|
||||
this._progShown = new Set(); // 已播过 gd_prog 的阶段(每进展段限 1 次)
|
||||
this._pendingVoice = []; // 待播语音队列:排队等当前语音播完,绝不顶句
|
||||
this._playSeq = 0; // voice 播放请求序号(onComplete 内判断是否链播新句)
|
||||
// 菜单
|
||||
@@ -160,12 +193,14 @@ export class EscapeGame extends Game {
|
||||
if (this.phase === Phase.PLAY) {
|
||||
// 卡关提示按"无操作时长"计时:任何有效手势重置计时,并作废待播提示
|
||||
this._lastActiveAt = Date.now();
|
||||
this._gesturesSinceProgress++; // B3:活跃手势计数(无进展 150s 通道的闸门)
|
||||
this._dropPendingStuck();
|
||||
}
|
||||
switch (this.phase) {
|
||||
case Phase.REOPEN:
|
||||
if (g === G.UP) { this.audio.stopVoice(); this._startGuide(); }
|
||||
else if (g === G.TAP) { this.audio.stopVoice(); this._enterPlay(true); }
|
||||
// B8:REOPEN 单击直进路径在 start_room 后接播目标句 g7_goal
|
||||
else if (g === G.TAP) { this.audio.stopVoice(); this._enterPlay(true, true); }
|
||||
break;
|
||||
case Phase.GUIDE:
|
||||
this._onGuideGesture(g);
|
||||
@@ -174,7 +209,9 @@ export class EscapeGame extends Game {
|
||||
this._onPlayGesture(g);
|
||||
break;
|
||||
case Phase.ENDING:
|
||||
if (g === G.TAP) this._restart();
|
||||
// B7(escape-state round2):结算链播完前单击不立即重开——time_band/again
|
||||
// 的完整到达权(live round1 S7:习惯性单击把结算链截断,两句被永久吞掉)
|
||||
if (g === G.TAP) { if (!this._settleBusy) this._restart(); }
|
||||
else if (g === G.DOWN) this._openMenu(Phase.ENDING);
|
||||
break;
|
||||
case Phase.MENU:
|
||||
@@ -227,6 +264,13 @@ export class EscapeGame extends Game {
|
||||
this._guideBusy = false;
|
||||
this.guide.turn({}); // turn cue:引导步骤解锁输入(W2 播完即静默,向导补标记)
|
||||
if (onDone) onDone();
|
||||
// B6(escape-state round2):busy 窗口缓存的手势在步骤解锁后按新步骤补判
|
||||
// (onDone 若已离开 GUIDE——G6 链尾进 PLAY——缓存直接作废,不跨阶段存活)
|
||||
if (this._guidePending !== null) {
|
||||
const p = this._guidePending;
|
||||
this._guidePending = null;
|
||||
if (this.phase === Phase.GUIDE) this._onGuideGesture(p, { fromCache: true });
|
||||
}
|
||||
};
|
||||
this._timer(() => {
|
||||
if (this._guideBusy && this.guideStep === fromStep) done();
|
||||
@@ -236,16 +280,24 @@ export class EscapeGame extends Game {
|
||||
else done();
|
||||
}
|
||||
|
||||
_onGuideGesture(g) {
|
||||
_onGuideGesture(g, { fromCache = false } = {}) {
|
||||
// 下滑跳过仅限"答案不含滑动"的步骤(G0/G3/G5/G6):G1/G2 的正确答案是
|
||||
// 任意滑动、G4 的答案就是下滑——这些步骤下滑 = 作答,不可跳过(13 号文档
|
||||
// 裁定;round2-live:g1_move 明说"朝任意方向滑一下",玩家下滑却被保送
|
||||
// 自由探索,教学链就此断裂)
|
||||
if (g === G.DOWN && this.guideStep !== 1 && this.guideStep !== 2 && this.guideStep !== 4) {
|
||||
// 自由探索,教学链就此断裂)。B6:busy 缓存补判的手势不再触发下滑跳过
|
||||
// (live round1 S6:答案在 busy 窗口被吞后,玩家紧接着的下滑被当成跳过引导)
|
||||
if (!fromCache && g === G.DOWN && this.guideStep !== 1 && this.guideStep !== 2 && this.guideStep !== 4) {
|
||||
this._skipGuide();
|
||||
return;
|
||||
}
|
||||
if (this._guideBusy) return; // 推进语音播放中,忽略
|
||||
if (this._guideBusy) {
|
||||
// B6:busy 窗口缓存首个非跳过分手势,推进语音播完(_advance done)后按
|
||||
// 新步骤补判——合法则直接作答,不合法走答错路径(有纠正语音,可归因)。
|
||||
// 仅缓存 1 个、只存活到本步骤解锁,杜绝跨步幽灵输入(00 §5.4:做了手势
|
||||
// 3 秒内必须有反馈——原 busy 静默吞手势违反此条,本缓存是合规修复)
|
||||
if (!fromCache && this._guidePending === null) this._guidePending = g;
|
||||
return;
|
||||
}
|
||||
switch (this.guideStep) {
|
||||
case 0: // G0:单击继续(intro 播完 1.2s 未操作也会自动推进 G1,见 _startGuide)
|
||||
if (g === G.TAP) this._advance(1, ['voice/g1_move', 'voice/skip_hint']); // skip_hint 首局插播一次
|
||||
@@ -316,10 +368,17 @@ export class EscapeGame extends Game {
|
||||
this._session++; // 作废进行中的引导语音链
|
||||
this._clearTimers();
|
||||
this.audio.stopVoice();
|
||||
this._guidePending = null;
|
||||
try { localStorage.setItem(GUIDE_DONE_KEY, '1'); } catch (_) { /* 隐私模式 */ }
|
||||
this._speak(['voice/guide_skip'], () => this._enterPlay(true), { skippable: false });
|
||||
// 语音缺失兜底
|
||||
this._timer(() => { if (this.phase === Phase.GUIDE) this._enterPlay(true); }, 5000);
|
||||
this.guideStep = 7; // 跳过链期间视作 G7 等待:滑动手势全部忽略(防链中误触误答/二次跳过)
|
||||
// B8(escape-state round2):跳过确认句后、进 PLAY 前补播目标句 g7_goal——
|
||||
// 目标陈述原只在引导 G7 链尾出现一次,跳过的玩家(恰是最需要目标的一群)
|
||||
// 永远听不到(live round1 S4:跳过后目标维度完全空白)
|
||||
this._speak(['voice/guide_skip'], () => {
|
||||
this._playVoice('voice/g7_goal', { onComplete: () => this._enterPlay(true) });
|
||||
}, { skippable: false });
|
||||
// 语音缺失兜底(两句链:覆盖 guide_skip/g7_goal 缺失情形)
|
||||
this._timer(() => { if (this.phase === Phase.GUIDE) this._enterPlay(true); }, 9000);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,14 +400,26 @@ export class EscapeGame extends Game {
|
||||
|
||||
// ---------- 进入 / 重开 PLAY ----------
|
||||
|
||||
/** @param {boolean} announce 是否播 start_room(跳过引导/二周目直接进入时) */
|
||||
_enterPlay(announce) {
|
||||
/**
|
||||
* @param {boolean} announce 是否播 start_room(跳过引导/二周目直接进入时)
|
||||
* @param {boolean} withGoal B8:start_room 后接播目标句 g7_goal(REOPEN 直进
|
||||
* 路径;跳过引导路径的 g7_goal 已在 _enterPlay 前播过,此处不重复)
|
||||
*/
|
||||
_enterPlay(announce, withGoal = false) {
|
||||
this._session++;
|
||||
this._clearTimers();
|
||||
this.phase = Phase.PLAY;
|
||||
this.startElapsedMs = Date.now();
|
||||
this._resetStuck();
|
||||
if (announce) this._playVoice('voice/start_room');
|
||||
if (announce) {
|
||||
if (withGoal) {
|
||||
// B8:start_room(可跳)自然播完/被跳过后接播 g7_goal(可跳,
|
||||
// 二周目老手可单击跳过——教学义务句已随首局完成,此处是状态告知)
|
||||
this._playVoice('voice/start_room', { onComplete: () => this._playVoice('voice/g7_goal') });
|
||||
} else {
|
||||
this._playVoice('voice/start_room');
|
||||
}
|
||||
}
|
||||
this._playAmbient();
|
||||
}
|
||||
|
||||
@@ -397,22 +468,37 @@ export class EscapeGame extends Game {
|
||||
if (nx < 0 || nx > 2 || ny < 0 || ny > 2) {
|
||||
this.audio.play('sfx/wall');
|
||||
vibrate('error');
|
||||
// 撞墙极简反馈:只播「那边是墙,换个方向。」(round1-live 修复:原接播
|
||||
// guide_blunt_<dir>「手指贴着屏幕,向 X 推一下」教学腔方位句,中后期出戏;
|
||||
// 教学腔仅限引导期 G2/G3 纠错路径,见 _onGuideGesture/_guideWrong)
|
||||
this._playVoice('voice/wall');
|
||||
// 撞墙反馈:先播「那边是墙,换个方向。」,播完接播陈述式方位句
|
||||
// wall_dir_<dir>「左边是墙。」(escape-state round2 B1:round1-live 回退掉的
|
||||
// 是教学腔措辞,方位信息本身保留;复用 14-F2.3 原接线模式——被下一次语音
|
||||
// 顶掉则自然作废不迟到误导;同方向 10s 限频 1 次防贴墙连撞连播)。
|
||||
// 方位 = 滑动方向(escape 移动坐标系),按真实撞墙方向取句,归因真话。
|
||||
const dir = dy < 0 ? 'u' : dy > 0 ? 'd' : dx < 0 ? 'l' : 'r';
|
||||
const allowDir = !this._wallDirAt[dir] || Date.now() - this._wallDirAt[dir] >= 10000;
|
||||
this._playVoice('voice/wall', {
|
||||
onComplete: allowDir
|
||||
? () => { this._wallDirAt[dir] = Date.now(); this._playVoice(`voice/wall_dir_${dir}`); }
|
||||
: undefined,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.x = nx;
|
||||
this.y = ny;
|
||||
this.audio.play('sfx/step', { volume: 0.8 });
|
||||
this._playAmbient();
|
||||
this._freshEmpty = null; // 离开首访句刚播过的空房:单击检查恢复播 empty_*
|
||||
// 首次到达关键房间:进展事件 + 房间描述
|
||||
const key = `${nx},${ny}`;
|
||||
if (KEY_ROOMS[key] && !this.visited.has(key)) {
|
||||
this.visited.add(key);
|
||||
this._progressEvent();
|
||||
this._playVoice(KEY_ROOMS[key].room);
|
||||
} else if (EMPTY_FIRST_VOICE[key] && !this.emptyVisited.has(key)) {
|
||||
// B5a(escape-state round2):空房首访补播 empty_* 一次性听觉锚
|
||||
// (不算进展事件,不清卡关已播级别;重访零语音与关键房间同款)
|
||||
this.emptyVisited.add(key);
|
||||
this._freshEmpty = key;
|
||||
this._playVoice(EMPTY_FIRST_VOICE[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,10 +540,12 @@ export class EscapeGame extends Game {
|
||||
this._progressEvent();
|
||||
this.audio.play('sfx/pickup');
|
||||
vibrate('pickup');
|
||||
// H1(round4):钥匙到手句后接播铁柜房方位(下一目标 = cabinet (2,1))。
|
||||
// H1(round4)/ B2(escape-state round2):钥匙到手句后接播铁柜房
|
||||
// "目标名+方位"一体句 gd_cabinet_dir(下一目标 = cabinet (2,1),固定为右)。
|
||||
this._timer(() => {
|
||||
if (s !== this._session) return;
|
||||
emit('voice/found_key', false, () => this._playGoalDir(STAGES.cabinet.target));
|
||||
emit('voice/found_key', false,
|
||||
() => this._playGoalDir(STAGES.cabinet.target, 'voice/gd_cabinet_dir', 'voice/gd_room_r'));
|
||||
}, 800); // 先让环境音进耳朵再播描述
|
||||
} else {
|
||||
describe('voice/empty_2');
|
||||
@@ -470,12 +558,11 @@ export class EscapeGame extends Game {
|
||||
describe(this.powerOn ? 'voice/inspect_gate_ready' : 'voice/inspect_gate');
|
||||
} else if (x === 1 && y === 1) {
|
||||
describe('voice/start_room');
|
||||
} else if (x === 1 && y === 0) {
|
||||
describe('voice/empty_1');
|
||||
} else if (x === 0 && y === 1) {
|
||||
describe('voice/empty_2');
|
||||
} else {
|
||||
describe('voice/empty_3'); // (1,2)、(2,0)
|
||||
// 空房 (1,0)/(0,1)/(1,2)/(2,0):B5a 首访句刚播过的房间内,单击不再重复
|
||||
// 同一句(_freshEmpty 离开即清;重访后单击检查语义不变,照常播 empty_*)
|
||||
const key = `${x},${y}`;
|
||||
if (this._freshEmpty !== key) describe(EMPTY_FIRST_VOICE[key] || 'voice/empty_3');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,11 +580,12 @@ export class EscapeGame extends Game {
|
||||
// G4(round3):拾取反馈链尾接下一目标句「保险丝到手。接下来,去找电箱。」
|
||||
// (游戏反馈层全档位,gd_economy 先例——走游戏语音链不走向导通道)——堵上
|
||||
// P2-round2 P0「保险丝到手后目标悬空:没有新指令、没有下文」。
|
||||
// H1(round4):目标句播完接播目标房间方位句(P3 唯一拒因:目标无方位)。
|
||||
// H1(round4)/ B2(escape-state round2):目标句播完接播"目标名+方位"一体句
|
||||
// gd_box_dir(电箱房 (0,0) 固定为左)。
|
||||
this._playVoice('voice/unlock_cabinet', {
|
||||
skippable: false, // 关键获得不可跳
|
||||
onComplete: () => this._playVoice('voice/gd_next_fuse', {
|
||||
onComplete: () => this._playGoalDir(STAGES.box.target),
|
||||
onComplete: () => this._playGoalDir(STAGES.box.target, 'voice/gd_box_dir', 'voice/gd_room_l'),
|
||||
}),
|
||||
});
|
||||
} else if (x === 0 && y === 0 && this.hasFuse && !this.powerOn) {
|
||||
@@ -508,22 +596,28 @@ export class EscapeGame extends Game {
|
||||
this.audio.play('sfx/spark');
|
||||
this.audio.play('sfx/power_on', { volume: 0.8 });
|
||||
vibrate('success');
|
||||
// H1(round4):通电目标句后接播大门方位(下一目标 = gate (2,2))。
|
||||
// H1(round4)/ B2(escape-state round2):通电目标句后接播"目标名+方位"
|
||||
// 一体句 gd_gate_dir(大门 (2,2) 固定为右)。
|
||||
this._playVoice('voice/fix_box', {
|
||||
skippable: false, // 关键获得不可跳
|
||||
onComplete: () => this._playGoalDir(STAGES.gate.target),
|
||||
onComplete: () => this._playGoalDir(STAGES.gate.target, 'voice/gd_gate_dir', 'voice/gd_room_r'),
|
||||
});
|
||||
} else if (x === 2 && y === 2 && this.powerOn) {
|
||||
// 通电后开大门 -> 逃脱
|
||||
this._escape();
|
||||
} else {
|
||||
// 兜底:ERROR 震动 + 背包/use_fail + L2 级明示(ui_deny 已退役)
|
||||
// 兜底:ERROR 震动 + 背包/use_fail + L1 级意象暗示(escape-state round2 B4:
|
||||
// 原直通 L2 明示把答案白送给没卡关的玩家——live round1 两次实录;降级为 L1
|
||||
// 意象句(不点明房间与动作,零泄漏),答案仍锁在计时器 L2/L3 与进展链里。
|
||||
// 本进展段已播过 L1 则不重复;播了即记账(沿用 _stuckShown 既有去重))
|
||||
vibrate('error');
|
||||
const inKeyRoom = `${x},${y}` in KEY_ROOMS;
|
||||
this._speak([
|
||||
inKeyRoom ? 'voice/use_fail' : this._inventoryVoice(),
|
||||
`voice/stuck_${this._stage()}_2`,
|
||||
]);
|
||||
const ids = [inKeyRoom ? 'voice/use_fail' : this._inventoryVoice()];
|
||||
if (!this._stuckShown.has('L1')) {
|
||||
this._stuckShown.add('L1');
|
||||
ids.push(`voice/stuck_${this._stage()}_1`);
|
||||
}
|
||||
this._speak(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,10 +650,16 @@ export class EscapeGame extends Game {
|
||||
return dy < 0 ? 'voice/gd_room_u' : 'voice/gd_room_d';
|
||||
}
|
||||
|
||||
/** H1:目标句播完后接播目标房间方位句(游戏反馈层全档位,gd_next_fuse 先例)。 */
|
||||
_playGoalDir(target) {
|
||||
/**
|
||||
* H1(round4)/ B2(escape-state round2):目标句播完后接播目标房间方位句
|
||||
* (游戏反馈层全档位,gd_next_fuse 先例)。B2:三处固定接线点传 namedId +
|
||||
* expectedId,计算方位与枚举一致时播"目标名+方位"一体句;异常路径不符时
|
||||
* 回落原 gd_room_*(归因真话,原句保留不删)。
|
||||
*/
|
||||
_playGoalDir(target, namedId = null, expectedId = null) {
|
||||
const dir = this._roomDirVoice(target);
|
||||
if (dir) this._playVoice(dir);
|
||||
if (!dir) return;
|
||||
this._playVoice(namedId && dir === expectedId ? namedId : dir);
|
||||
}
|
||||
|
||||
// ---------- 卡关检测与三级提示 ----------
|
||||
@@ -573,12 +673,19 @@ export class EscapeGame extends Game {
|
||||
this._lastActiveAt = Date.now();
|
||||
this._stuckShown = new Set();
|
||||
this._lastL3At = 0;
|
||||
// B3 无进展计时:进入/重开 PLAY 时起算点与闸门一并复位
|
||||
this._lastProgressAt = Date.now();
|
||||
this._gesturesSinceProgress = 0;
|
||||
this._progShown = new Set();
|
||||
}
|
||||
|
||||
/** 进展事件:清空已播提示级别,下段静默期从 L1 重新分级(计时由手势重置)。 */
|
||||
_progressEvent() {
|
||||
this._stuckShown.clear();
|
||||
this._lastL3At = 0;
|
||||
// B3:无进展计时起算点与活跃手势计数复位(_progShown 按阶段记账,不清)
|
||||
this._lastProgressAt = Date.now();
|
||||
this._gesturesSinceProgress = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,6 +716,18 @@ export class EscapeGame extends Game {
|
||||
vibrate('warning');
|
||||
this._enqueueVoice('stuck', ['voice/stuck_ask', `voice/stuck_${stage}_1`], { level: 'L1' });
|
||||
}
|
||||
// B3(escape-state round2):无进展 150s 活跃计时器(与无操作计时并存互不复位)
|
||||
// ——活跃但零进展的玩家收到一条不泄题的进度重述 gd_prog_*(完成数由 _stage()
|
||||
// 反推,归因真话)。闸门:期间 ≥5 次有效手势(=活跃探索;挂机交给 60s L1
|
||||
// 体系);key 阶段不走本通道(L1/L2/L3 已覆盖"找不到钥匙",避免双计时器
|
||||
// 对同一阶段轰炸);每进展段限 1 次(触发即记账,待播被操作作废也不重发);
|
||||
// 队列语义与卡关提示同款(绝不顶句,待播期间有操作即作废),warning 震同款。
|
||||
if (stage !== 'key' && !this._progShown.has(stage)
|
||||
&& Date.now() - this._lastProgressAt >= 150000 && this._gesturesSinceProgress >= 5) {
|
||||
this._progShown.add(stage);
|
||||
vibrate('warning');
|
||||
this._enqueueVoice('stuck', [GD_PROG[stage]], { level: 'PROG' });
|
||||
}
|
||||
}
|
||||
|
||||
/** 从当前坐标到目标房间的导航语音(每轴一句,最多两句)。 */
|
||||
@@ -677,6 +796,9 @@ export class EscapeGame extends Game {
|
||||
this.audio.stopBgm(2500);
|
||||
this.guide.state('settle'); // 状态签名:结算(逃脱)
|
||||
this._endingBgmStarted = false;
|
||||
// B7(escape-state round2):结算链守卫——播完前 ENDING 单击不立即重开
|
||||
// (_startEndingBgm 处解除:链自然播完或 30s 资产缺失兜底,两条路径汇合)
|
||||
this._settleBusy = true;
|
||||
const totalSec = Math.floor((Date.now() - this.startElapsedMs) / 1000);
|
||||
this._saveEscape(totalSec);
|
||||
// 结算语音链(关键获得,不可跳);播完淡入 menu pad(10 号文档:volume 0.5,1500ms)
|
||||
@@ -696,6 +818,7 @@ export class EscapeGame extends Game {
|
||||
/** 逃脱结算 BGM:drone 淡出后淡入 bgm/menu(幂等,仅在仍是结算态时生效)。 */
|
||||
_startEndingBgm() {
|
||||
if (this._endingBgmStarted || this.phase !== Phase.ENDING) return;
|
||||
this._settleBusy = false; // B7:结算链播完(或 30s 兜底)后解除单击守卫
|
||||
this._endingBgmStarted = true;
|
||||
this.audio.play('bgm/menu', { volume: 0.5, fadeMs: 1500 });
|
||||
}
|
||||
|
||||
@@ -418,13 +418,16 @@ section('A. 关键路径:引导 → 解谜 → 逃脱 → 结算 → 菜单
|
||||
assert(rec.count('voice/wall') >= 1, '撞墙播 wall 语音');
|
||||
await finishVoices(1);
|
||||
|
||||
// ---- 边界:双击无目标兜底 = 背包/use_fail + L2 明示,不崩 ----
|
||||
// ---- 边界:双击无目标兜底 = 背包/use_fail + L1 意象暗示,不崩(escape-state
|
||||
// round2 B4 变更登记:原直通 L2 明示 stuck_*_2 把答案白送给没卡关的玩家,
|
||||
// 降级为 L1 意象句 stuck_*_1——不点明房间与动作;答案仍锁在计时器 L2/L3) ----
|
||||
const errCnt2 = vibrateCount(ERR_PAT);
|
||||
await gs(game, 'doubletap'); // 电箱房无保险丝
|
||||
assert(vibrateCount(ERR_PAT) === errCnt2 + 1, '双击无目标发 error 震动');
|
||||
assert(rec.count('voice/use_fail') === 1, '兜底播 use_fail(关键房间)');
|
||||
await finishVoices(1);
|
||||
assert(rec.count('voice/stuck_key_2') === 1, '兜底追加 L2 明示 stuck_key_2');
|
||||
assert(rec.count('voice/stuck_key_1') === 1, 'B4:兜底追加 L1 意象暗示 stuck_key_1(原 L2 已降级)');
|
||||
assert(rec.count('voice/stuck_key_2') === 0, 'B4:兜底不再直通 L2 明示 stuck_key_2');
|
||||
await finishVoices(1);
|
||||
|
||||
game.stop();
|
||||
@@ -501,7 +504,16 @@ section('A2. 冷启动引导链:intro 后 g1_move 自动播出,零单击走
|
||||
await gs(g2b.game, 'down'); // G3 答案 = 左滑,下滑 = 跳过
|
||||
assert(g2b.rec.count('voice/guide_skip') === 1, 'G3 下滑仍跳过引导');
|
||||
await tick(VOICE_END_SLACK);
|
||||
assert(g2b.game.phase === 'PLAY', 'G3 下滑跳过直达 PLAY');
|
||||
// B8(escape-state round2 变更登记):跳过确认句后、进 PLAY 前补播目标句
|
||||
// g7_goal——跳过链从 1 句变 2 句,第一句播完时仍在 GUIDE
|
||||
assert(g2b.rec.count('voice/g7_goal') === 1, 'B8:guide_skip 后补播 g7_goal');
|
||||
assert(g2b.game.phase === 'GUIDE', 'B8:g7_goal 补播期间尚未进 PLAY');
|
||||
await tick(VOICE_END_SLACK);
|
||||
assert(g2b.game.phase === 'PLAY', 'G3 下滑跳过(补播 g7_goal 后)直达 PLAY');
|
||||
assert(g2b.rec.count('voice/start_room') === 1, 'B8:跳过路径 g7_goal 后播 start_room');
|
||||
const goalT = g2b.rec.last('voice/g7_goal').t;
|
||||
const startT = g2b.rec.last('voice/start_room').t;
|
||||
assert(goalT < startT, 'B8:跳过路径播报顺序 guide_skip → g7_goal → start_room');
|
||||
g2b.game.stop();
|
||||
}
|
||||
|
||||
@@ -538,7 +550,7 @@ section('B. 引导纠错与跳过');
|
||||
assert(game.guideStep === 3 && game._guideBusy, '左滑后正常推进(G4 语音中)');
|
||||
game.stop();
|
||||
|
||||
// 下滑跳过引导
|
||||
// 下滑跳过引导(B8:确认句后补播 g7_goal 再进 PLAY)
|
||||
store.clear();
|
||||
const g2 = await newGame();
|
||||
g2.game.start();
|
||||
@@ -546,7 +558,9 @@ section('B. 引导纠错与跳过');
|
||||
await gs(g2.game, 'down');
|
||||
assert(g2.rec.count('voice/guide_skip') === 1, '引导期下滑播 guide_skip');
|
||||
await tick(VOICE_END_SLACK);
|
||||
assert(g2.game.phase === 'PLAY', '下滑跳过引导直达 PLAY');
|
||||
assert(g2.rec.count('voice/g7_goal') === 1, 'B8:guide_skip 后补播 g7_goal');
|
||||
await tick(VOICE_END_SLACK);
|
||||
assert(g2.game.phase === 'PLAY', '下滑跳过引导(补播 g7_goal 后)直达 PLAY');
|
||||
assert(store.get('soundgame.escape.guideDone') === '1', '跳过引导也写 guideDone');
|
||||
assert(g2.rec.count('voice/start_room') === 1, '跳过引导播 start_room');
|
||||
g2.game.stop();
|
||||
@@ -807,6 +821,466 @@ section('E. 设置边界');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 G:B1 撞墙方位句(wall_dir_* 接播 + 同向 10s 限频 + 打断作废;引导期不播)
|
||||
// ================================================================
|
||||
section('G. B1 撞墙方位句(escape-state round2 F1)');
|
||||
{
|
||||
// 引导期 G2 伪撞墙不播方位句(B1 仅 PLAY 阶段)
|
||||
store.clear();
|
||||
const gd = await newGame();
|
||||
gd.game.start();
|
||||
await flush();
|
||||
await tick(VOICE_END_SLACK);
|
||||
await gs(gd.game, 'tap'); // G0 → G1
|
||||
await finishVoices(2);
|
||||
await gs(gd.game, 'up'); // G1
|
||||
await finishVoices(2);
|
||||
await gs(gd.game, 'up'); // G2 ×2(伪撞墙)
|
||||
await gs(gd.game, 'left');
|
||||
await finishVoices(2);
|
||||
assert(gd.rec.count('voice/wall') >= 2, '前提:G2 撞墙播过 wall 语音');
|
||||
for (const d of ['l', 'r', 'u', 'd']) {
|
||||
assert(gd.rec.count(`voice/wall_dir_${d}`) === 0, `B1:引导期 G2 撞墙不播 wall_dir_${d}(仅 PLAY)`);
|
||||
}
|
||||
gd.game.stop();
|
||||
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY(start_room → g7_goal)
|
||||
await finishVoices(2);
|
||||
await gs(game, 'left'); // (0,1) B5a 首访 empty_2
|
||||
await gs(game, 'up'); // (0,0) room_power
|
||||
await finishVoices(2);
|
||||
|
||||
// ① 撞墙后 wall 播完接播方位句(顺序:wall → wall_dir_u)
|
||||
await gs(game, 'up'); // 撞北墙
|
||||
assert(rec.count('voice/wall_dir_u') === 0, 'B1:wall 播放中方位句未播(接播不抢话)');
|
||||
await finishVoices(1);
|
||||
assert(rec.count('voice/wall_dir_u') === 1, 'B1:wall 播完接播 wall_dir_u「上边是墙。」');
|
||||
assert(rec.last('voice/wall_dir_u').t >= rec.last('voice/wall').t + 1000, 'B1:方位句在 wall 自然播完之后');
|
||||
await finishVoices(1);
|
||||
|
||||
// ② 打断作废:撞左墙 wall 未播完再撞上墙——左墙方位句作废;
|
||||
// 上墙 10s 限频内(① 刚播过)不再重复
|
||||
await gs(game, 'left'); // wall(左)
|
||||
await gs(game, 'up'); // wall(上)顶掉上一句
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/wall_dir_l') === 0, 'B1:wall 被打断则方位句自然作废(wall_dir_l 未播)');
|
||||
assert(rec.count('voice/wall_dir_u') === 1, 'B1:同向 10s 限频——上墙方位句不重复(仍 1 次)');
|
||||
|
||||
// ③ 同向限频与恢复:左墙首播 → 10s 内再撞不重复 → 窗口过后恢复
|
||||
await gs(game, 'left'); // 左墙(② 的接播被作废,未播过 → 本次接播)
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/wall_dir_l') === 1, 'B1:被作废的方向补撞后方位句正常接播');
|
||||
await gs(game, 'left'); // 10s 窗口内再撞左墙
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/wall_dir_l') === 1, 'B1:同向 10s 内限频 1 次(wall_dir_l 不重复)');
|
||||
await tick(10000);
|
||||
await gs(game, 'left');
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/wall_dir_l') === 2, 'B1:限频窗口过后同向方位句恢复');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 H:B2 目标名+方位一体句(gd_*_dir 替换三处接播,异常路径回落 gd_room_*)
|
||||
// ================================================================
|
||||
section('H. B2 目标名+方位一体句(escape-state round2 F2)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY (1,1)
|
||||
await finishVoices(2); // start_room + g7_goal
|
||||
|
||||
// ① found_key 链尾 → gd_cabinet_dir(储物间 (0,2) → 铁柜房 (2,1),固定为右)
|
||||
game.x = 0; game.y = 2; // 测试钩子:瞬移储物间
|
||||
await gs(game, 'tap'); // 检查 → 拾钥匙
|
||||
await tick(800); // found_key 起播
|
||||
await finishVoices(2); // found_key → gd_cabinet_dir
|
||||
assert(rec.count('voice/found_key') === 1, '前提:拾钥匙播 found_key');
|
||||
assert(rec.count('voice/gd_cabinet_dir') === 1, 'B2:found_key 链尾播 gd_cabinet_dir「铁柜,在右面的房间。」');
|
||||
assert(rec.last('voice/gd_cabinet_dir').t > rec.last('voice/found_key').t, 'B2:一体句在 found_key 之后');
|
||||
assert(rec.count('voice/gd_room_r') === 0, 'B2:正常路径不再播无目标名的 gd_room_r');
|
||||
|
||||
// ② unlock_cabinet/gd_next_fuse 链尾 → gd_box_dir(铁柜房 → 电箱房 (0,0),固定为左)
|
||||
game.x = 2; game.y = 1; // 钩子:瞬移铁柜房
|
||||
await gs(game, 'doubletap');
|
||||
await finishVoices(3); // unlock_cabinet → gd_next_fuse → gd_box_dir
|
||||
assert(rec.count('voice/gd_box_dir') === 1, 'B2:gd_next_fuse 链尾播 gd_box_dir「电箱,在左面的房间。」');
|
||||
assert(rec.last('voice/gd_box_dir').t > rec.last('voice/gd_next_fuse').t, 'B2:一体句在 gd_next_fuse 之后');
|
||||
assert(rec.count('voice/gd_room_l') === 0, 'B2:正常路径不再播 gd_room_l');
|
||||
|
||||
// ③ fix_box 链尾 → gd_gate_dir(电箱房 → 大门 (2,2),固定为右)
|
||||
game.x = 0; game.y = 0; // 钩子:瞬移电箱房
|
||||
await gs(game, 'doubletap');
|
||||
await finishVoices(2); // fix_box → gd_gate_dir
|
||||
assert(rec.count('voice/gd_gate_dir') === 1, 'B2:fix_box 链尾播 gd_gate_dir「大门,在右面的房间。」');
|
||||
assert(rec.last('voice/gd_gate_dir').t > rec.last('voice/fix_box').t, 'B2:一体句在 fix_box 之后');
|
||||
|
||||
// ④ 异常路径回落:计算方位与枚举不符 → 回落原 gd_room_*(归因真话,原句保留接线)
|
||||
game.x = 1; game.y = 1; // 钩子:异常位置(正常链上不存在)
|
||||
game._playGoalDir([0, 1], 'voice/gd_cabinet_dir', 'voice/gd_room_r'); // 目标在西 ≠ 枚举右
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_room_l') === 1, 'B2:方位与枚举不符时回落 gd_room_*(原句保留接线)');
|
||||
await finishVoices(1);
|
||||
game._playGoalDir([1, 1], 'voice/gd_cabinet_dir', 'voice/gd_room_r'); // 同房间不播(H1 原语义)
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_room_l') === 1 && rec.count('voice/gd_cabinet_dir') === 1,
|
||||
'B2:目标在同一房间不播(H1 原语义不变)');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 I:B3 无进展 150s 活跃计时器(gd_prog 进度重述)
|
||||
// 边界:key 阶段不走 / ≥5 手势闸门(挂机不触)/ 每段限 1 次 /
|
||||
// 有进展时复位 / 待播期间操作作废且计入已播
|
||||
// ================================================================
|
||||
section('I. B3 无进展活跃计时器(escape-state round2 F3)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { audio, game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY
|
||||
await finishVoices(2);
|
||||
// 往返手势一律 (1,1)↔(0,1)(空房,避开关键房间的首到进展事件)
|
||||
const wander = async (n) => { for (let i = 0; i < n; i++) await gs(game, i % 2 ? 'right' : 'left'); };
|
||||
|
||||
// ① key 阶段不走本通道:无进展 200s + 活跃 5 手势 → 无 gd_prog
|
||||
await wander(5);
|
||||
game._lastProgressAt = now - 200000; // 钩子:模拟 200s 无进展
|
||||
game._checkStuck();
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_1') === 0, 'B3:key 阶段不走本通道(L1/L2/L3 已覆盖)');
|
||||
await tick(1600); // 消化首访 empty_2
|
||||
|
||||
// ② 拾钥匙进 cabinet 阶段(进展事件复位计时)
|
||||
game.x = 0; game.y = 2; // 钩子:瞬移储物间
|
||||
await gs(game, 'tap');
|
||||
await tick(800);
|
||||
await finishVoices(2); // found_key + gd_cabinet_dir
|
||||
assert(game._stage() === 'cabinet' && game._gesturesSinceProgress === 0,
|
||||
'B3 前提:cabinet 阶段,进展事件已复位计数');
|
||||
|
||||
// ③ 闸门:无进展 151s 但活跃手势 <5(挂机/低活跃)→ 不触
|
||||
game._lastProgressAt = now - 151000;
|
||||
game._checkStuck();
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_1') === 0, 'B3:活跃手势 <5 不触(挂机交给 60s L1 体系)');
|
||||
|
||||
// ④ 活跃触发:5 手势后无进展 151s → gd_prog_1 到达一次
|
||||
game.x = 1; game.y = 1;
|
||||
await wander(5);
|
||||
await tick(1600);
|
||||
game._checkStuck(); // _lastProgressAt 仍为 ② 的钩子值(移动不复位无进展计时)
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_1') === 1, 'B3:活跃(≥5 手势)无进展 150s 播 gd_prog_1');
|
||||
|
||||
// ⑤ 每进展段限 1 次:再到点不重复
|
||||
await finishVoices(1);
|
||||
game._lastProgressAt = now - 200000;
|
||||
game._checkStuck();
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_1') === 1, 'B3:gd_prog_1 每进展段限 1 次');
|
||||
|
||||
// ⑥ 有进展时复位:开柜(进展事件)→ 计数清零、计时重起,不立即触下一段
|
||||
game.x = 2; game.y = 1;
|
||||
await gs(game, 'doubletap'); // 开柜
|
||||
assert(game._gesturesSinceProgress === 0, 'B3:进展事件后活跃手势计数清零(复位)');
|
||||
game._checkStuck(); // _lastProgressAt 刚复位,远不足 150s
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_2') === 0, 'B3:有进展时计时器复位(不立即触 gd_prog_2)');
|
||||
await finishVoices(3); // unlock 链
|
||||
|
||||
// ⑦ box 段可再触一次
|
||||
game.x = 1; game.y = 1;
|
||||
await wander(5);
|
||||
await tick(1600);
|
||||
game._lastProgressAt = now - 151000;
|
||||
game._checkStuck();
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_2') === 1, 'B3:box 阶段活跃无进展 150s 播 gd_prog_2');
|
||||
await finishVoices(1);
|
||||
|
||||
// ⑧ 待播期间操作作废且计入已播(每段限 1 次不重发)
|
||||
game.x = 0; game.y = 0;
|
||||
await gs(game, 'doubletap'); // 修电 → gate 阶段(进展复位)
|
||||
await finishVoices(2); // fix_box + gd_gate_dir
|
||||
game.x = 1; game.y = 1;
|
||||
await wander(5);
|
||||
await tick(1600);
|
||||
await gs(game, 'tap'); // 单击检查
|
||||
await tick(800); // 检查描述播放中
|
||||
assert(audio.isVoicePlaying(), 'B3 前提:检查描述播放中');
|
||||
game._lastProgressAt = now - 151000;
|
||||
game._checkStuck(); // 到点 → gd_prog_3 只入队
|
||||
assert(rec.count('voice/gd_prog_3') === 0, 'B3:语音播放中 gd_prog 只入队不开播(不顶句)');
|
||||
await gs(game, 'left'); // 玩家操作 → 待播 gd_prog_3 作废
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/gd_prog_3') === 0, 'B3:待播期间操作即作废(不播出)');
|
||||
assert(game._progShown.has('gate'), 'B3:作废仍计入已播(每进展段限 1 次)');
|
||||
game._lastProgressAt = now - 200000;
|
||||
game._checkStuck();
|
||||
await flush();
|
||||
assert(rec.count('voice/gd_prog_3') === 0, 'B3:作废的 gd_prog 不重发');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 J:B4 双击兜底降级(背包 + L1 意象;去重;L2 仍由计时器到达)
|
||||
// ================================================================
|
||||
section('J. B4 双击兜底降级(escape-state round2 F4)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY (1,1) 非关键房
|
||||
await finishVoices(2);
|
||||
|
||||
// 非关键房兜底 = 背包 + L1 意象暗示(不再直通 L2);播了即记账
|
||||
await gs(game, 'doubletap');
|
||||
assert(rec.count('voice/inv_empty') === 1, 'B4:非关键房兜底先播背包 inv_empty');
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/stuck_key_1') === 1, 'B4:兜底接 L1 意象暗示 stuck_key_1');
|
||||
assert(rec.count('voice/stuck_key_2') === 0, 'B4:兜底不直通 L2 明示 stuck_key_2');
|
||||
assert(game._stuckShown.has('L1'), 'B4:兜底播 L1 即记账(沿用 _stuckShown 去重)');
|
||||
|
||||
// 同进展段再次兜底不重复 L1 意象句(既有去重)
|
||||
await gs(game, 'doubletap');
|
||||
await finishVoices(2);
|
||||
assert(rec.count('voice/inv_empty') === 2, 'B4:再次兜底仍播背包');
|
||||
assert(rec.count('voice/stuck_key_1') === 1, 'B4:同进展段再次兜底不重复 L1 意象句');
|
||||
|
||||
// 降级后 L2 仍可达:L1 已记账 → 60s 不再重复(整级跳过,stuck_ask 亦不播);
|
||||
// 120s 无操作 L2 明示照常到达(难度不降)
|
||||
await tick(65000);
|
||||
assert(rec.count('voice/stuck_ask') === 0, 'B4:L1 已记账,60s 无操作不再重复 L1 级');
|
||||
await tick(60000);
|
||||
assert(rec.count('voice/stuck_key_2') === 1, 'B4:降级后 L2 仍由计时器到达(120s 无操作)');
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 K:B5a 空房首访描述(首访到达 / 重访不重复 / 单击检查语义 / 非进展事件)
|
||||
// ================================================================
|
||||
section('K. B5a 空房首访描述(escape-state round2 F5)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY (1,1)
|
||||
await finishVoices(2);
|
||||
|
||||
// 首访空房不算进展事件:不清卡关已播级别
|
||||
game._stuckShown.add('L1'); // 钩子:模拟本段已播 L1
|
||||
await gs(game, 'up'); // (1,0) 首访
|
||||
assert(game._stuckShown.has('L1'), 'B5a:空房首访不算进展事件(不清 _stuckShown)');
|
||||
game._stuckShown.clear(); // 复位钩子
|
||||
|
||||
// 首访 (1,0) → empty_1;本房间内单击不再重复首访句;重访零语音;重访后单击照常
|
||||
assert(rec.count('voice/empty_1') === 1, 'B5a:空房首访补播 empty_1(一次性听觉锚)');
|
||||
await finishVoices(1);
|
||||
await gs(game, 'tap'); // 首访句刚播过的房间内单击
|
||||
await tick(900);
|
||||
assert(rec.count('voice/empty_1') === 1, 'B5a:首访句刚播过的房间内单击不重复同一句');
|
||||
await gs(game, 'down'); // (1,1)
|
||||
await gs(game, 'up'); // (1,0) 重访
|
||||
await tick(900);
|
||||
assert(rec.count('voice/empty_1') === 1, 'B5a:空房重访零语音(不重复首访句)');
|
||||
await gs(game, 'tap'); // 重访后单击检查
|
||||
await tick(900);
|
||||
assert(rec.count('voice/empty_1') === 2, 'B5a:重访后单击检查照常播 empty_1(语义不变)');
|
||||
await finishVoices(1);
|
||||
|
||||
// 四房映射:(0,1)→empty_2、(1,2)→empty_3、(2,0)→empty_3(对称水滴共用合法记忆点)
|
||||
await gs(game, 'down'); // (1,1)
|
||||
await gs(game, 'left'); // (0,1) 首访
|
||||
assert(rec.count('voice/empty_2') === 1, 'B5a:(0,1) 首访播 empty_2');
|
||||
await finishVoices(1);
|
||||
await gs(game, 'right'); // (1,1)
|
||||
await gs(game, 'down'); // (1,2) 首访
|
||||
assert(rec.count('voice/empty_3') === 1, 'B5a:(1,2) 首访播 empty_3');
|
||||
await finishVoices(1);
|
||||
game.x = 2; game.y = 1; // 钩子:瞬移铁柜房(已 visited 与否不影响下行)
|
||||
game.visited.add('2,1');
|
||||
await gs(game, 'up'); // (2,0) 首访
|
||||
assert(rec.count('voice/empty_3') === 2, 'B5a:(2,0) 首访复用 empty_3(两间"远处水滴"对称分布)');
|
||||
await finishVoices(1);
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 L:B6 引导 busy 窗口手势缓存(补判 / 答错路径 / 不触发跳过 / 仅 1 个)
|
||||
// ================================================================
|
||||
section('L. B6 引导 busy 手势缓存(escape-state round2 F7)');
|
||||
{
|
||||
store.clear();
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await tick(VOICE_END_SLACK); // intro 播完(自动推进 1.2s 未到点)
|
||||
await gs(game, 'tap'); // G0 → _advance(1) busy
|
||||
|
||||
// ① busy 窗口手势缓存:不当场判定,解锁后按新步骤补判(合法 = 作答)
|
||||
await gs(game, 'up'); // busy 窗口注入滑动 → 缓存
|
||||
assert(game.guideStep === 0 && game._guideBusy, 'B6 前提:busy 窗口内步骤未解锁');
|
||||
const stepsAtBusy = rec.count('sfx/step');
|
||||
assert(rec.count('sfx/step') === stepsAtBusy, 'B6:busy 窗口手势不当场判定(无脚步声)');
|
||||
await finishVoices(2); // g1_move + skip_hint 播完 → 解锁 G1 → 缓存 up 补判
|
||||
assert(rec.count('sfx/step') === stepsAtBusy + 1, 'B6:解锁后缓存手势补判(G1 滑动作答,脚步声)');
|
||||
assert(game.guideStep === 1 && game._guideBusy, 'B6:补判作答后正常推进(G2 语音中)');
|
||||
await finishVoices(2); // g1_done + g2_wall
|
||||
assert(game.guideStep === 2, 'B6:进入 G2');
|
||||
|
||||
// ② 缓存手势对新步骤合法:G2→G3 busy 缓存左滑(G3 的答案)→ 解锁直接作答
|
||||
await gs(game, 'up'); // G2 第一滑
|
||||
await tick(VOICE_END_SLACK); // wall 播完
|
||||
await gs(game, 'right'); // G2 第二滑 → _advance(3) busy
|
||||
await gs(game, 'left'); // busy 缓存左滑
|
||||
assert(game.guideStep === 2, 'B6:busy 窗口仍停 G2');
|
||||
await finishVoices(2); // wall + g3_left 播完 → 解锁 G3 → 缓存 left 补判
|
||||
assert(game.x === 0 && game.y === 1, 'B6:缓存左滑按 G3 补判作答(移到 (0,1))');
|
||||
assert(game.guideStep === 3 && game._guideBusy, 'B6:补判作答后推进 G4');
|
||||
assert(rec.count('voice/guide_skip') === 0, 'B6:缓存手势不触发下滑跳过(S6 事故修复)');
|
||||
await finishVoices(1); // g4_down → G4 解锁
|
||||
|
||||
// ③ 缓存手势对新步骤不合法:按答错路径处理(有纠正语音,可归因)
|
||||
await gs(game, 'down'); // G4 作答 → _advance(5) busy
|
||||
await gs(game, 'up'); // busy 缓存 up
|
||||
await finishVoices(1); // 解锁 G5 → 补判:G5 期望单击,up = 答错
|
||||
assert(game.guideStep === 5, 'B6:进入 G5');
|
||||
assert(rec.count('voice/guide_wrong_gesture') === 1, 'B6:缓存手势不合法按答错路径处理(纠正语音可归因)');
|
||||
assert(game.guideErrs === 1, 'B6:答错计数照常');
|
||||
assert(rec.count('voice/guide_skip') === 0, 'B6:答错路径同样不触发跳过');
|
||||
|
||||
// ④ 仅缓存 1 个:busy 连注两个手势,解锁后只补判首个
|
||||
await gs(game, 'tap'); // G5 作答 → _advance(6) busy
|
||||
await gs(game, 'doubletap'); // 缓存(恰为 G6 答案)
|
||||
await gs(game, 'left'); // 不再缓存(仅 1 个)
|
||||
await finishVoices(2); // g5_key + g6_doubletap → 解锁 G6 → 补判 doubletap
|
||||
assert(game.guideStep === 6 && game._guideBusy, 'B6:仅首个缓存手势补判(doubletap 作答 G6)');
|
||||
await finishVoices(3); // inv_key + g6_done + g7_goal → PLAY
|
||||
assert(game.phase === 'PLAY', 'B6:引导链完整走完(缓存不破坏既有推进)');
|
||||
game.stop();
|
||||
|
||||
// ⑤ 跳过分手势不缓存:busy 窗口下滑(可跳过步骤)仍立即跳过
|
||||
store.clear();
|
||||
const g2b = await newGame();
|
||||
g2b.game.start();
|
||||
await flush();
|
||||
await gs(g2b.game, 'tap'); // G0 → _advance(1) busy
|
||||
assert(g2b.game._guideBusy, '前提:G0→G1 推进语音播放中');
|
||||
await gs(g2b.game, 'down'); // busy 窗口下滑 = 跳过分手势 → 立即跳过,不缓存
|
||||
assert(g2b.rec.count('voice/guide_skip') === 1, 'B6:busy 窗口下滑跳过语义不变(不缓存)');
|
||||
assert(g2b.game._guidePending === null, 'B6:跳过分手势不进缓存');
|
||||
g2b.game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 M:B7 结算链单击守卫(播完前不重开 / 链完整到达 / 30s 兜底解除)
|
||||
// ================================================================
|
||||
section('M. B7 结算链单击守卫(escape-state round2 F8)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
await gs(game, 'tap'); // REOPEN → PLAY
|
||||
await finishVoices(2);
|
||||
// 钩子速通:开柜 → 修电 → 大门
|
||||
game.hasKey = true; game.x = 2; game.y = 1;
|
||||
await gs(game, 'doubletap'); // 开柜
|
||||
await finishVoices(3);
|
||||
game.x = 0; game.y = 0;
|
||||
await gs(game, 'doubletap'); // 修电
|
||||
await finishVoices(2);
|
||||
game.x = 2; game.y = 2;
|
||||
await gs(game, 'doubletap'); // 逃脱
|
||||
assert(game.phase === 'ENDING' && game._settleBusy, 'B7 前提:ENDING + 结算守卫挂载');
|
||||
|
||||
// 结算链播放中单击 = 忽略(链不被截断,time_band/again 完整到达)
|
||||
await gs(game, 'tap');
|
||||
assert(game.phase === 'ENDING', 'B7:结算链播完前单击不重开(仍 ENDING)');
|
||||
assert(rec.count('voice/replay') === 0, 'B7:守卫期单击不触发重开(无 replay)');
|
||||
await finishVoices(1);
|
||||
assert(rec.count('voice/time_band1') === 1, 'B7:结算链完整——time_band 到达(不再被吞)');
|
||||
await finishVoices(1);
|
||||
assert(rec.count('voice/again') === 1, 'B7:结算链完整——again 到达');
|
||||
await finishVoices(1); // 链完 → 守卫解除
|
||||
assert(!game._settleBusy, 'B7:链播完守卫解除');
|
||||
await gs(game, 'tap');
|
||||
assert(game.phase === 'PLAY' && rec.count('voice/replay') === 1, 'B7:守卫解除后单击重开原语义不变');
|
||||
game.stop();
|
||||
|
||||
// 30s 资产缺失兜底:again 缺失 → 链停摆 → 守卫靠兜底解除(防静默死锁)
|
||||
blockedAssets = ['again'];
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const g2 = await newGame();
|
||||
g2.game.start();
|
||||
await flush();
|
||||
await gs(g2.game, 'tap');
|
||||
await finishVoices(2);
|
||||
g2.game.hasKey = true; g2.game.x = 2; g2.game.y = 1;
|
||||
await gs(g2.game, 'doubletap');
|
||||
await finishVoices(3);
|
||||
g2.game.x = 0; g2.game.y = 0;
|
||||
await gs(g2.game, 'doubletap');
|
||||
await finishVoices(2);
|
||||
g2.game.x = 2; g2.game.y = 2;
|
||||
await gs(g2.game, 'doubletap');
|
||||
assert(g2.game.phase === 'ENDING', '前提:again 缺失下逃脱进 ENDING');
|
||||
await finishVoices(2); // escape + time_band 播完,again 缺失链停摆
|
||||
await gs(g2.game, 'tap');
|
||||
assert(g2.game.phase === 'ENDING', 'B7:again 缺失链停摆时守卫仍生效(单击不重开)');
|
||||
await tick(30000); // 兜底
|
||||
assert(!g2.game._settleBusy, 'B7:30s 资产缺失兜底解除守卫(防静默死锁)');
|
||||
await gs(g2.game, 'tap');
|
||||
assert(g2.game.phase === 'PLAY', 'B7:兜底解除后可重开');
|
||||
blockedAssets = [];
|
||||
g2.game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景 N:B8 REOPEN 直进路径补播目标句(start_room → g7_goal,可单击跳过)
|
||||
// ================================================================
|
||||
section('N. B8 REOPEN 直进补播 g7_goal(escape-state round2 F9)');
|
||||
{
|
||||
store.clear();
|
||||
store.set('soundgame.escape.guideDone', '1');
|
||||
const { game, rec } = await newGame();
|
||||
game.start();
|
||||
await flush();
|
||||
assert(game.phase === 'REOPEN', '前提:二周目 REOPEN');
|
||||
await gs(game, 'tap'); // 直接开始
|
||||
assert(game.phase === 'PLAY', 'REOPEN 单击直进 PLAY');
|
||||
assert(rec.count('voice/start_room') === 1, 'B8:直进播 start_room');
|
||||
await finishVoices(1);
|
||||
assert(rec.count('voice/g7_goal') === 1, 'B8:start_room 后接播 g7_goal');
|
||||
assert(rec.last('voice/g7_goal').t > rec.last('voice/start_room').t, 'B8:直进路径顺序 start_room → g7_goal');
|
||||
// g7_goal 可单击跳过(skippable 默认 true,12 号文档——教学义务句已随首局完成,
|
||||
// 此处是状态告知不是教学)
|
||||
const skips0 = rec.skips();
|
||||
await gs(game, 'tap'); // g7_goal 播放中单击 = 跳过 + 补发检查
|
||||
assert(rec.skips() === skips0 + 1, 'B8:二周目 g7_goal 可单击跳过');
|
||||
assert(game.phase === 'PLAY', 'B8:跳过后仍在 PLAY');
|
||||
await finishVoices(2); // 补发检查描述消化
|
||||
game.stop();
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 资产引用校验:game.js 引用的 id 在音频目录有 ogg + m4a(voice 双性别),零缺失
|
||||
// ================================================================
|
||||
@@ -822,6 +1296,7 @@ section('F. 资产引用校验');
|
||||
ids.add(`voice/guide_wrong_${d}`);
|
||||
ids.add(`voice/guide_blunt_${d}`);
|
||||
}
|
||||
for (const d of ['l', 'r', 'u', 'd']) ids.add(`voice/wall_dir_${d}`); // B1 撞墙方位句族
|
||||
for (const st of ['key', 'cabinet', 'box', 'gate']) {
|
||||
for (const lv of [1, 2, 3]) ids.add(`voice/stuck_${st}_${lv}`);
|
||||
}
|
||||
|
||||
+54
-17
@@ -756,9 +756,9 @@ realLog('== ⑩b H5 rhythm:教学应答窗口无任何尝试 → gd_miss_none
|
||||
resetTimers();
|
||||
}
|
||||
|
||||
realLog('== ⑩c H1 escape:目标句后按房间图播 gd_room_*(同房间不播,移动坐标系)==');
|
||||
realLog('== ⑩c H1/B2 escape:目标句后按房间图播方位句(round2 B2:三处固定接线点升级为"目标名+方位"一体句,异常路径回落 gd_room_*)==');
|
||||
{
|
||||
// 方向映射按图校验(直连单元断言)
|
||||
// 方向映射按图校验(直连单元断言,gd_room_* 映射表保留不动)
|
||||
const rig0 = makeRig(EscapeGame);
|
||||
const { game: g0 } = rig0;
|
||||
await rig0.audio.unlock();
|
||||
@@ -768,10 +768,15 @@ realLog('== ⑩c H1 escape:目标句后按房间图播 gd_room_*(同房间
|
||||
assert(g0._roomDirVoice([1, 0]) === 'voice/gd_room_u', 'H1:目标在北(上面的房间)→ gd_room_u');
|
||||
assert(g0._roomDirVoice([1, 2]) === 'voice/gd_room_d', 'H1:目标在南(下面的房间)→ gd_room_d');
|
||||
assert(g0._roomDirVoice([1, 1]) === null, 'H1:目标在同一房间不播');
|
||||
// B2 异常路径回落:计算方位与枚举不符 → 原 gd_room_*(原句保留接线,归因真话)
|
||||
g0._playGoalDir([0, 1], 'voice/gd_cabinet_dir', 'voice/gd_room_r'); // 目标在西 ≠ 枚举右
|
||||
await flush();
|
||||
assert(rig0.playLog.some((e) => e.id === 'voice/gd_room_l'), 'B2:方位与枚举不符时回落 gd_room_*');
|
||||
g0.stop();
|
||||
resetTimers();
|
||||
|
||||
// 三处目标句接线点:found_key → cabinet(2,1);gd_next_fuse → box(0,0);fix_box → gate(2,2)
|
||||
// (B2 换线:gd_room_r/l → gd_cabinet_dir/gd_box_dir/gd_gate_dir,断言同步登记变更)
|
||||
const rig = makeRig(EscapeGame);
|
||||
const { audio, playLog, game } = rig;
|
||||
storageData.set('soundgame.escape.guideDone', '1'); // 二周目直达 REOPEN→PLAY
|
||||
@@ -779,42 +784,74 @@ realLog('== ⑩c H1 escape:目标句后按房间图播 gd_room_*(同房间
|
||||
game.start();
|
||||
await advance(() => game.phase === 'REOPEN');
|
||||
await advance(() => !audio.isVoicePlaying()); // reopen_prompt 播完
|
||||
await gesture(game, 'tap'); // 直接开始 → PLAY (1,1)
|
||||
await gesture(game, 'tap'); // 直接开始 → PLAY (1,1)(B8:start_room → g7_goal 链)
|
||||
await advance(() => game.phase === 'PLAY' && !audio.isVoicePlaying());
|
||||
assert(game.x === 1 && game.y === 1 && !game.hasKey, '前提:二周目 PLAY 起点、身上无钥匙');
|
||||
|
||||
// ① found_key:储物间拾钥匙 → 铁柜房在东(右面的房间)
|
||||
await gesture(game, 'left'); // (0,1)
|
||||
// ① found_key:储物间拾钥匙 → 铁柜房在东 → B2 一体句 gd_cabinet_dir
|
||||
await gesture(game, 'left'); // (0,1)(B5a:首访播 empty_2)
|
||||
await gesture(game, 'down'); // (0,2) 储物间(首到播 room_storage)
|
||||
await advance(() => !audio.isVoicePlaying()); // 房间描述播完再单击(否则单击=跳句)
|
||||
await gesture(game, 'tap'); // 检查 → found_key(800ms 后)→ 方位句
|
||||
await advance(() => playLog.some((e) => e.id === 'voice/gd_room_r'));
|
||||
await gesture(game, 'tap'); // 检查 → found_key(800ms 后)→ 一体句
|
||||
await advance(() => playLog.some((e) => e.id === 'voice/gd_cabinet_dir'));
|
||||
const ifk = playLog.findIndex((e) => e.id === 'voice/found_key');
|
||||
assert(ifk > -1 && playLog.findIndex((e) => e.id === 'voice/gd_room_r') > ifk,
|
||||
'H1:found_key 后接播 gd_room_r(目标铁柜房按图在东)');
|
||||
assert(ifk > -1 && playLog.findIndex((e) => e.id === 'voice/gd_cabinet_dir') > ifk,
|
||||
'B2:found_key 后接播 gd_cabinet_dir(铁柜,在右面的房间)');
|
||||
assert(!playLog.some((e) => e.id === 'voice/gd_room_r'), 'B2:正常路径不再播 gd_room_r');
|
||||
|
||||
// ② gd_next_fuse:开柜得保险丝 → 电箱房在西(左面的房间)
|
||||
// ② gd_next_fuse:开柜得保险丝 → 电箱房在西 → B2 一体句 gd_box_dir
|
||||
await gesture(game, 'right'); await gesture(game, 'right'); // (1,2) (2,2)
|
||||
await gesture(game, 'up'); // (2,1) 铁柜房
|
||||
await gesture(game, 'doubletap'); // 开柜
|
||||
await advance(() => playLog.some((e) => e.id === 'voice/gd_room_l'));
|
||||
await advance(() => playLog.some((e) => e.id === 'voice/gd_box_dir'));
|
||||
const inf = playLog.findIndex((e) => e.id === 'voice/gd_next_fuse');
|
||||
assert(inf > -1 && playLog.findIndex((e) => e.id === 'voice/gd_room_l') > inf,
|
||||
'H1:gd_next_fuse 后接播 gd_room_l(目标电箱房按图在西)');
|
||||
assert(inf > -1 && playLog.findIndex((e) => e.id === 'voice/gd_box_dir') > inf,
|
||||
'B2:gd_next_fuse 后接播 gd_box_dir(电箱,在左面的房间)');
|
||||
assert(!playLog.some((e) => e.id === 'voice/gd_room_l'), 'B2:正常路径不再播 gd_room_l');
|
||||
|
||||
// ③ fix_box:修电箱通电 → 大门在东(右面的房间)
|
||||
// ③ fix_box:修电箱通电 → 大门在东 → B2 一体句 gd_gate_dir
|
||||
await advance(() => !audio.isVoicePlaying()); // gd_box_dir 播完再走(首访空房句不顶链)
|
||||
await gesture(game, 'left'); await gesture(game, 'left'); // (1,1) (0,1)
|
||||
await gesture(game, 'up'); // (0,0) 电箱房
|
||||
await gesture(game, 'doubletap'); // 修电箱
|
||||
await advance(() => playLog.filter((e) => e.id === 'voice/gd_room_r').length >= 2);
|
||||
await advance(() => playLog.some((e) => e.id === 'voice/gd_gate_dir'));
|
||||
const ifx = playLog.findIndex((e) => e.id === 'voice/fix_box');
|
||||
assert(ifx > -1 && playLog.map((e) => e.id).lastIndexOf('voice/gd_room_r') > ifx,
|
||||
'H1:fix_box 后接播 gd_room_r(目标大门按图在东)');
|
||||
assert(ifx > -1 && playLog.findIndex((e) => e.id === 'voice/gd_gate_dir') > ifx,
|
||||
'B2:fix_box 后接播 gd_gate_dir(大门,在右面的房间)');
|
||||
assert(game.powerOn, '前提:电箱已通电(接线点均在真实解谜链上)');
|
||||
game.stop();
|
||||
resetTimers();
|
||||
}
|
||||
|
||||
realLog('== ⑩d B6 escape:引导 busy 窗口手势缓存(full 档)——解锁后补判、答错路径、不触发跳过 ==');
|
||||
{
|
||||
const rig = makeRig(EscapeGame);
|
||||
const { audio, playLog, game } = rig;
|
||||
await audio.unlock();
|
||||
game.start();
|
||||
await advance(() => game.phase === 'GUIDE' && !game._guideBusy && !audio.isVoicePlaying()); // G0 待输入
|
||||
await gesture(game, 'tap'); // G0 → _advance(1) busy(g1_move + skip_hint)
|
||||
assert(game._guideBusy, '前提:G0→G1 推进语音播放中(busy 窗口)');
|
||||
await gesture(game, 'up'); // busy 窗口注入滑动 → 缓存(不当场判定)
|
||||
assert(game.guideStep === 0 && game.guideSwipes === 0, 'B6:busy 窗口手势不当场判定');
|
||||
// 解锁 G1 → 缓存 up 按 G1 补判 = 作答(sfx/step + 推进 G2)
|
||||
await advance(() => game.guideStep === 2 && !game._guideBusy);
|
||||
assert(playLog.some((e) => e.id === 'sfx/step'), 'B6:full 档下缓存手势解锁后补判作答(脚步声)');
|
||||
|
||||
// G2 busy 缓存非答案手势 → 解锁 G3 后按答错路径(纠正语音,不触发下滑跳过)
|
||||
await gesture(game, 'up'); // G2 第一滑
|
||||
await advance(() => !audio.isVoicePlaying());
|
||||
await gesture(game, 'right'); // G2 第二滑 → _advance(3) busy
|
||||
await gesture(game, 'down'); // busy 缓存下滑(非 G3 答案)
|
||||
assert(game.guideStep === 2, 'B6:busy 窗口仍停 G2');
|
||||
await advance(() => game.guideStep === 3 && !game._guideBusy);
|
||||
assert(voicePlays(playLog, 'voice/guide_wrong_left') === 1, 'B6:缓存手势不合法按答错路径处理(guide_wrong_left)');
|
||||
assert(voicePlays(playLog, 'voice/guide_skip') === 0, 'B6:缓存的下滑不触发跳过引导(live round1 S6 事故修复)');
|
||||
assert(game.phase === 'GUIDE', 'B6:仍在引导中(未被保送 PLAY)');
|
||||
game.stop();
|
||||
resetTimers();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- 汇总
|
||||
|
||||
realLog(`\n通过 ${passCount} 条断言,失败 ${failures.length} 条`);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* 《暗室》新手会话剧本:老玩家二周目不算——这里清空过进度走首局引导(G0-G7),
|
||||
* 每步听清再做;进 PLAY 后先连撞两次墙(触发向导提前一级的卡关提示),
|
||||
* 然后找到铁柜房开柜拿保险丝、照 round4 H1 的目标方位句跨四个房间修电箱、
|
||||
* 再摸到大门收工(目标句后 3s 内都能听到方位句)。
|
||||
* 每步听清再做;进 PLAY 后先连撞两次墙(round2 B1:wall 后跟陈述式方位句
|
||||
* 「上边是墙。」,同向 10s 限频),经空房首访描述(B5a)找到铁柜房开柜拿保险丝、
|
||||
* 照 round2 B2 的"目标名+方位"一体句跨四个房间修电箱、再摸到大门收工。
|
||||
*/
|
||||
export function describe(game) {
|
||||
switch (game.phase) {
|
||||
@@ -55,31 +55,34 @@ export async function session(ctx, mock) {
|
||||
if (why) ctx.note(why);
|
||||
};
|
||||
|
||||
// 先往北乱撞探探边界:两步走到 (0,0),再连撞两次北墙——向导把卡关提示提前带上来
|
||||
// 先往北乱撞探探边界:两步走到 (0,0)——(0,1) 首访会播 empty_2(B5a 空房听觉锚),
|
||||
// 再连撞两次北墙——wall 后各跟一句陈述式方位「上边是墙。」(B1,同向 10s 限频)
|
||||
ctx.silence(3, '辨了辨方向');
|
||||
await move('up');
|
||||
await move('up');
|
||||
await move('up', '北边是墙,撞了一下——「那边是墙」后面还跟了句方向(向上推的是北墙)');
|
||||
await move('up', '又撞了一下——听到游戏主动来问我了');
|
||||
await ctx.waitVirtual(5200); // 等卡关轮询的 5s tick:连续撞墙 → 提前一级的暗示
|
||||
await move('up', '路过一间空房,它自己开口了:摸到的只有冰冷粗糙的墙壁');
|
||||
await move('up', '电流声——电箱房到了');
|
||||
await move('up', '北边是墙,撞了一下——「那边是墙」后面跟了句「上边是墙。」,这面不通记住了');
|
||||
await move('up', '又撞了一下——同方向 10 秒内不重复报方位,游戏不啰嗦');
|
||||
await ctx.waitVirtual(5200); // 缓一缓(卡关轮询 5s tick 空转,活跃操作不触发提示)
|
||||
|
||||
// 去铁柜房:(0,0) → 右×2 = (2,0) → 下 = (2,1),双击用钥匙
|
||||
await move('right', '往东走,风声换了个方向');
|
||||
await move('right');
|
||||
// ((1,0)/(2,0) 首访各播 empty_1/empty_3——B5a:四间空房从此声学可区分)
|
||||
await move('right', '往东走,一间空房自报家门:空空荡荡只有回声');
|
||||
await move('right', '又一间空房:除了远处的水滴声什么都没有');
|
||||
await move('down', '到了铁柜房,柜子锁着');
|
||||
// 用钥匙 → unlock_cabinet + gd_next_fuse + gd_room_l(round4 H1:目标句带方位,
|
||||
// 从铁柜房 (2,1) 看电箱房 (0,0) 在西 = 左面的房间)
|
||||
// 用钥匙 → unlock_cabinet + gd_next_fuse + gd_box_dir(round2 B2:目标名+方位
|
||||
// 一体句,从铁柜房 (2,1) 看电箱房 (0,0) 在西 = 「电箱,在左面的房间。」)
|
||||
await ctx.gesture('doubletap');
|
||||
await ctx.waitVirtual(5600);
|
||||
ctx.status('柜子开了。「保险丝到手。接下来,去找电箱。」后面还跟了一句「左面的房间。」——这回知道该往哪边摸了');
|
||||
ctx.status('柜子开了。「保险丝到手。接下来,去找电箱。」后面跟的是「电箱,在左面的房间。」——目标名和方位一句话说全了');
|
||||
// round4 H1 剧本:照方位句跨房间去电箱房——(2,1) → 左×2 = (0,1) → 上 = (0,0)
|
||||
await move('left', '照方位句往左(西)摸');
|
||||
await move('left');
|
||||
await move('up', '电流声越来越清晰——电箱房到了');
|
||||
// 修电箱 → fix_box + gd_room_r(round4 H1:从 (0,0) 看大门 (2,2) 在东 = 右面的房间)
|
||||
// 修电箱 → fix_box + gd_gate_dir(round2 B2:从 (0,0) 看大门 (2,2) 在东 =
|
||||
// 「大门,在右面的房间。」)
|
||||
await ctx.gesture('doubletap');
|
||||
await ctx.waitVirtual(5600);
|
||||
ctx.status('电箱修好了。目标句后面照样跟着方位——「右面的房间。」大门在东边');
|
||||
ctx.status('电箱修好了。目标句后面照样是目标名+方位——「大门,在右面的房间。」');
|
||||
// 照方位句多跨两个房间摸向大门:(0,0) → 右×2 = (2,0) → 下×2 = (2,2)
|
||||
await move('right', '照方位句往右(东)摸');
|
||||
await move('right');
|
||||
|
||||
@@ -1038,7 +1038,17 @@
|
||||
"time_band4": "你逃出来了,用时超过十分钟。",
|
||||
"unlock_cabinet": "钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。",
|
||||
"use_fail": "这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。",
|
||||
"wall": "那边是墙,换个方向。"
|
||||
"wall": "那边是墙,换个方向。",
|
||||
"wall_dir_l": "左边是墙。",
|
||||
"wall_dir_r": "右边是墙。",
|
||||
"wall_dir_u": "上边是墙。",
|
||||
"wall_dir_d": "下边是墙。",
|
||||
"gd_cabinet_dir": "铁柜,在右面的房间。",
|
||||
"gd_box_dir": "电箱,在左面的房间。",
|
||||
"gd_gate_dir": "大门,在右面的房间。",
|
||||
"gd_prog_1": "钥匙已经到手。找到能用它的锁。",
|
||||
"gd_prog_2": "铁柜已经打开。电还没有通。",
|
||||
"gd_prog_3": "电已经通了。去找那扇大门。"
|
||||
},
|
||||
"hunt": {
|
||||
"breach": "有野兽冲进营地了!",
|
||||
@@ -1958,4 +1968,4 @@
|
||||
"zhou_r2_plain": "茶是茶,水是水,差点火候。儿子的事,改天再说吧。",
|
||||
"zhou_r2_wrong": "……今晚这盏不对。儿子的事,不说也罢。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user