Files
SoundGame/web/harness/sessions/storyline.mjs
T
SoundGame Dev 79dffac01e guide层v1: 全局向导交互层落地(状态签名earcon/turn cue/静默看门狗/纠错) + 6游戏接线 + 8句向导语音 + 测试全绿
- 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断言)+资产终检全绿
2026-08-30 22:46:05 +08:00

78 lines
3.2 KiB
JavaScript

/**
* 《声命线》新手会话剧本:像真人一样等语音播完再动、偶尔走神(触发看门狗)、
* 在非抉择节点试一次无效的左滑(触发向导纠错)、菜单进去逛一圈再出来、
* 抉择点一律选左,一路打到结局。
*/
export function describe(game) {
if (game.mode === 'MENU') return '菜单里:左滑重开、右滑或单击返回剧情、上滑听帮助';
if (game.awaitingRestart) return '结局播完了。单击屏幕,可以回到故事开始的地方';
if (game.choiceArmed) return `「请选择」念完了(节点 ${game.nodeId}):左滑或右滑,做出你的决定`;
if (game.voicePlaying) return '旁白正在播。单击跳过本句,双击重听整个节点';
return `剧情等着你(节点 ${game.nodeId}):单击继续,双击重听`;
}
export async function session(ctx, mock) {
const { game } = ctx;
let invalidTried = false;
let menuDone = false;
// 开场:n00 全听完,愣一会儿——向导看门狗先说话
await ctx.waitIdle();
ctx.status('开场旁白播完了,屏幕黑着,有点不知所措');
ctx.silence(8, '新手没反应过来');
await ctx.waitVirtual(8600); // 触发看门狗:nudge + gd_continue
ctx.status('听到一声轻响和「轻触屏幕,继续」,试着点一下');
await ctx.gesture('tap');
for (let i = 0; i < 60 && !game.awaitingRestart && mock.now < 20 * 60 * 1000; i++) {
await ctx.waitIdle(); // 等当前语音链播完(真人不会抢话)
if (game.awaitingRestart) break;
// 中途进一次菜单,逛一圈再出来
if (!menuDone && game.nodeId === 'n04') {
menuDone = true;
ctx.note('想看看还有什么可按的,下滑呼出菜单');
await ctx.gesture('down');
await ctx.waitIdle();
ctx.status('菜单里');
await ctx.gesture('up'); // 听帮助 + 进度
await ctx.waitIdle();
await ctx.gesture('doubletap'); // 重听菜单项
await ctx.waitIdle();
ctx.note('听懂了,先回去继续剧情');
await ctx.gesture('tap'); // 关菜单(回剧情并重播当前节点)
continue;
}
if (game.choiceArmed) {
ctx.status('抉择点,提示音念完了');
if (mock.now % 2 < 1) await ctx.waitVirtual(3000); // 偶尔犹豫一下
ctx.note('选了左边');
await ctx.gesture('left'); // 抉择点一律选左
continue;
}
// W1:叙事节点播完,静默等待
ctx.status('剧情停下来了,在等我');
if (!invalidTried) {
invalidTried = true;
ctx.note('试着左滑了一下——这里用不上,向导纠正了我');
await ctx.gesture('left');
await ctx.waitIdle();
} else if (i % 4 === 2) {
ctx.silence(8, '走神想剧情去了');
await ctx.waitVirtual(8600); // 偶尔挂机,触发看门狗轻提醒
ctx.status('又听到那声轻响,想起该点屏幕了');
}
await ctx.gesture('tap');
}
await ctx.waitIdle();
ctx.status('结局');
ctx.note('听完结局,单击重开一次看看别的走向');
await ctx.gesture('tap'); // 结算态单击重开
await ctx.waitIdle();
ctx.status('回到开头,会话结束');
}