- engine/guide.js 运行时合成8个签名earcon(方法论L2硬参数),off档零定时器,插播queue不顶对白 - settings: guide三档(full/standard/off默认full) + 语速2.2视障档;audio: isVoicePlaying()/setRateBoostEnabled() 清两个已知问题 - 6游戏按schemes§2接线: storyline看门狗+无效手势纠错、simon免扣重听看门狗、escape turn cue+提前卡关提示、rhythm gd_answer/gd_miss+结算看门狗+快进豁免、space首撞指令提示+结算看门狗、rpg格挡纠错+60s催促+状态签名 - 大厅设置面板+向导文档(14-guide-layer.md)+00-global-ux §6;R5台词表补4条一致性 - 试玩转写含向导事件;6 playtest(guide=off断言零改动)+guide.test(34断言)+资产终检全绿
73 lines
3.7 KiB
JavaScript
73 lines
3.7 KiB
JavaScript
/**
|
||
* 《暗室》新手会话剧本:老玩家二周目不算——这里清空过进度走首局引导(G0-G7),
|
||
* 每步听清再做;进 PLAY 后先连撞两次墙(触发向导提前一级的卡关提示),
|
||
* 然后找到储物间拿钥匙、去铁柜房开柜(解到第二间),收工。
|
||
*/
|
||
export function describe(game) {
|
||
switch (game.phase) {
|
||
case 'REOPEN': return '有人问我回不回来看过引导:单击直接开始,上滑重听引导';
|
||
case 'GUIDE': return game._guideBusy ? '引导在说话,照它说的做就行' : `引导第 ${game.guideStep + 1}/8 步,等我做手势`;
|
||
case 'PLAY': return `探索中,我在 (${game.x},${game.y})。四向滑挪步,单击摸一遍房间,双击用物品`;
|
||
case 'ENDING': return '逃脱了,结算播报中。播完单击再来,下滑开菜单';
|
||
case 'MENU': return '菜单里:单击切选项,双击确认,下滑关闭';
|
||
default: return '……';
|
||
}
|
||
}
|
||
|
||
export async function session(ctx, mock) {
|
||
const { game } = ctx;
|
||
|
||
// 首局:交互式引导 G0-G7(n = 引导步号 guideStep)。
|
||
// 注意:卡关轮询 interval 常驻,虚拟时钟永不"空闲"——等待一律用有界/带条件等待。
|
||
ctx.status('黑屏,只有引子的声音,先听完');
|
||
await ctx.waitCond(() => game.phase === 'GUIDE' && !game._guideBusy); // g0_intro 播完
|
||
const steps = [
|
||
{ n: 0, do: async () => { ctx.note('照引导单击了一下'); await ctx.gesture('tap'); } },
|
||
{ n: 1, do: async () => { ctx.note('随便滑了一步,有脚步声'); await ctx.gesture('up'); } },
|
||
{
|
||
n: 2,
|
||
do: async () => {
|
||
await ctx.gesture('left');
|
||
await ctx.waitVirtual(1600);
|
||
ctx.note('又滑一步,又撞墙了——墙的方位听出来了');
|
||
await ctx.gesture('right');
|
||
},
|
||
},
|
||
{ n: 3, do: async () => { ctx.note('这回往左,走通了一步'); await ctx.gesture('left'); } },
|
||
{ n: 4, do: async () => { ctx.note('往下滑,进了储物间'); await ctx.gesture('down'); } },
|
||
{ n: 5, do: async () => { ctx.note('单击摸一遍房间,摸到钥匙了'); await ctx.gesture('tap'); } },
|
||
{ n: 6, do: async () => { ctx.note('双击看了看背包'); await ctx.gesture('doubletap'); } },
|
||
];
|
||
for (const s of steps) {
|
||
await ctx.waitCond(() => game.phase === 'GUIDE' && game.guideStep === s.n && !game._guideBusy);
|
||
ctx.status(`引导第 ${s.n + 1}/8 步`);
|
||
await s.do();
|
||
await ctx.waitVirtual(800); // 缓一缓再继续(推进链由语音 onComplete 驱动)
|
||
}
|
||
|
||
// PLAY:自由探索。引导结束时我站在储物间 (0,2),手里已有钥匙
|
||
await ctx.waitCond(() => game.phase === 'PLAY');
|
||
ctx.status('引导完毕,正式开始。我在储物间');
|
||
const move = async (g, why) => {
|
||
await ctx.gesture(g);
|
||
await ctx.waitVirtual(1600); // 听脚步/环境音/描述
|
||
if (why) ctx.note(why);
|
||
};
|
||
|
||
// 先往北乱撞探探边界:两步走到 (0,0),再连撞两次北墙——向导把卡关提示提前带上来
|
||
ctx.silence(3, '辨了辨方向');
|
||
await move('up');
|
||
await move('up');
|
||
await move('up', '北边是墙,撞了一下');
|
||
await move('up', '又撞了一下——听到游戏主动来问我了');
|
||
await ctx.waitVirtual(5200); // 等卡关轮询的 5s tick:连续撞墙 → 提前一级的暗示
|
||
|
||
// 去铁柜房:(0,0) → 右×2 = (2,0) → 下 = (2,1),双击用钥匙
|
||
await move('right', '往东走,风声换了个方向');
|
||
await move('right');
|
||
await move('down', '到了铁柜房,柜子锁着');
|
||
await ctx.gesture('doubletap'); // 用钥匙 → unlock_cabinet(第二间解完)
|
||
await ctx.waitVirtual(3000);
|
||
ctx.status('柜子开了,拿到保险丝——解到第二间,收工');
|
||
}
|