/**
* Сценарий final — финал акта 2: правильный звон Старой Машины.
* 1) путь акта 2: Звенец -> роща -> разъезд -> люк в зал Машины;
* 2) без настроенного резонатора Машина отказывает (locked-текст);
* 3) чит-настройка (quest_resonator_done): клик по Машине -> реакция ставит
* machine_lulled и запускает катсцену (тост «дышит тише», конец);
* 4) повторный клик: Машина спит;
* 5) инварианты чисты после финала.
* Запуск: node tools/agent.mjs run tools/checks/final.mjs
*/
import { withChecks } from '../lib.mjs';
export default async function ({ pretty }) {
return withChecks(
'final',
async (t) => {
const { c } = t;
await c.run('путь акта 2: спуск через люк в зал Машины', async () => {
await t.boot();
await t.sleepEnemies();
await t.goToArea('zvenets', { x: 26, y: 14 });
await t.sleepEnemies();
await t.ctx.agent.command('scene:teleport', { x: 25, y: 10 });
await t.goToArea('rust_grove', { x: 26, y: 10 });
await t.sleepEnemies();
await t.goToArea('old_siding', { x: 22, y: 10 });
await t.sleepEnemies();
await t.goToArea('machine_hall', { x: 15, y: 15 });
const s = await t.ctx.agent.snapshot();
c.expect(s.area === 'machine_hall', 'герой не в зале Машины', s.area);
return null;
});
await c.run('без резонатора Машина отказывает', async () => {
await t.ctx.agent.tapTile(6, 1);
const w = await t.ctx.agent.waitFor('(s.lastToast?.text ?? "").includes("не настроен")', {
timeoutTicks: 1200
});
c.expect(w.ok, 'Машина не отказала без резонатора', w.snapshot.lastToast);
c.expect(!w.snapshot.flags.includes('machine_lulled'), 'флаг machine_lulled без настройки');
return null;
});
await c.run('правильный звон: катсцена, machine_lulled', async () => {
await t.ctx.agent.command('scene:setFlag', { flag: 'quest_resonator_done' });
await t.ctx.agent.tapTile(6, 1);
const f = await t.ctx.agent.waitFor('s.flags.includes("machine_lulled")', {
timeoutTicks: 1200
});
c.expect(f.ok, 'реакция не подняла machine_lulled', f.snapshot.flags);
const toast = await t.ctx.agent.waitFor('(s.lastToast?.text ?? "").includes("дышит тише")', {
timeoutTicks: 1200
});
c.expect(toast.ok, 'нет тоста финала', toast.snapshot.lastToast);
await t.ctx.agent.waitFor('!s.cutscene?.active', { timeoutTicks: 1200 });
return null;
});
await c.run('повторный клик: Машина спит', async () => {
await t.ctx.agent.tapTile(6, 1);
const w = await t.ctx.agent.waitFor('(s.lastToast?.text ?? "").includes("спит")', {
timeoutTicks: 1200
});
c.expect(w.ok, 'повторная реакция не про «сон»', w.snapshot.lastToast);
return null;
});
await c.run('инварианты чисты после финала', async () => {
await t.expectInvariantsClean('после финала акта 2');
return null;
});
},
{ pretty }
);
}