feat: add first-victory camp exploration

This commit is contained in:
2026-07-27 09:17:09 +09:00
parent 89c755ca42
commit e9fcd27611
17 changed files with 4557 additions and 113 deletions

View File

@@ -321,19 +321,34 @@ async function waitForStoryReady(page) {
}
async function advanceStoryUntilBattle(page, battleId) {
for (let i = 0; i < 48; i += 1) {
const deadline = Date.now() + 120000;
while (Date.now() < deadline) {
const state = await page.evaluate((expectedBattleId) => {
try {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
const battle = window.__HEROS_DEBUG__?.battle();
const story = window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.();
const storyScene = window.__HEROS_DEBUG__?.scene('StoryScene');
const story = storyScene?.getDebugState?.();
const village = window.__HEROS_DEBUG__?.village?.();
const militiaCamp = window.__HEROS_DEBUG__?.militiaCamp?.();
return {
battleReady: battle?.scene === 'BattleScene' && battle?.battleId === expectedBattleId,
battleReady: (
activeScenes.includes('BattleScene') &&
battle?.scene === 'BattleScene' &&
battle?.battleId === expectedBattleId
),
storyActive: activeScenes.includes('StoryScene'),
storyReady: story?.ready === true,
storyTransitioning: storyScene?.transitioning === true,
storyLastPage: story?.isLastPage === true,
storyTargetsBattle: story?.nextScene === 'BattleScene',
currentPageReady: story?.assetStreaming?.currentPageReady === true,
villageReady: window.__HEROS_DEBUG__?.village?.()?.ready === true,
militiaCampReady: window.__HEROS_DEBUG__?.militiaCamp?.()?.ready === true
villageActive: activeScenes.includes('PrologueVillageScene'),
villageReady: village?.ready === true,
villageNavigationPending: village?.navigationPending === true,
militiaCampActive: activeScenes.includes('PrologueMilitiaCampScene'),
militiaCampReady: militiaCamp?.ready === true,
militiaCampNavigationPending: militiaCamp?.navigationPending === true
};
} catch {
return {};
@@ -342,15 +357,37 @@ async function advanceStoryUntilBattle(page, battleId) {
if (state.battleReady) {
throw new Error('Battle became ready before the transition start could be measured.');
}
if (state.storyReady && state.storyLastPage && state.storyTargetsBattle && state.currentPageReady) {
await page.waitForTimeout(600);
if (
state.storyActive &&
state.storyReady &&
!state.storyTransitioning &&
state.storyLastPage &&
state.storyTargetsBattle &&
state.currentPageReady
) {
const entries = await resourceEntries(page);
const startedAt = Date.now();
await page.keyboard.press('Space');
await page.waitForFunction((expectedBattleId) => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
const battle = window.__HEROS_DEBUG__?.battle();
const storyScene = window.__HEROS_DEBUG__?.scene('StoryScene');
return (
(
activeScenes.includes('BattleScene') &&
battle?.scene === 'BattleScene' &&
battle?.battleId === expectedBattleId
) ||
(
activeScenes.includes('StoryScene') &&
storyScene?.transitioning === true
)
);
}, battleId, { timeout: 5000 });
return { startedAt, resourceEntries: entries };
}
if (state.villageReady) {
if (state.villageActive && state.villageReady && !state.villageNavigationPending) {
const advanced = await page.evaluate(() => {
const scene = window.__HEROS_GAME__?.scene.getScene('PrologueVillageScene');
return scene?.debugCompleteVillage?.() ?? false;
@@ -358,11 +395,15 @@ async function advanceStoryUntilBattle(page, battleId) {
if (!advanced) {
throw new Error('Playable prologue village was ready but could not advance to the brotherhood story.');
}
await page.waitForTimeout(400);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
const village = window.__HEROS_DEBUG__?.village?.();
return !activeScenes.includes('PrologueVillageScene') || village?.navigationPending === true;
}, undefined, { timeout: 5000 });
continue;
}
if (state.militiaCampReady) {
if (state.militiaCampActive && state.militiaCampReady && !state.militiaCampNavigationPending) {
const advanced = await page.evaluate(() => {
const scene = window.__HEROS_GAME__?.scene.getScene('PrologueMilitiaCampScene');
return scene?.debugCompleteCamp?.() ?? false;
@@ -370,12 +411,18 @@ async function advanceStoryUntilBattle(page, battleId) {
if (!advanced) {
throw new Error('Playable prologue militia camp was ready but could not advance to the departure story.');
}
await page.waitForTimeout(400);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
const militiaCamp = window.__HEROS_DEBUG__?.militiaCamp?.();
return !activeScenes.includes('PrologueMilitiaCampScene') || militiaCamp?.navigationPending === true;
}, undefined, { timeout: 5000 });
continue;
}
await page.keyboard.press('Space');
await page.waitForTimeout(220);
if (state.storyActive && state.storyReady && !state.storyTransitioning && state.currentPageReady) {
await page.keyboard.press('Space');
}
await page.waitForTimeout(100);
}
throw new Error(`Story did not reach the battle transition for ${battleId}.`);
}