Add Jieqiao relief campaign battle

This commit is contained in:
2026-06-23 00:24:03 +09:00
parent 8e9bddcacf
commit 84a5606a73
10 changed files with 737 additions and 16 deletions

View File

@@ -663,6 +663,117 @@ try {
throw new Error(`Expected fifth camp to expose Gongsun Zan/Sishui dialogue set: ${JSON.stringify(fifthCampState)}`);
}
await page.mouse.click(1120, 38);
await page.waitForTimeout(160);
const fifthCampSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (!fifthCampSortieState?.sortieVisible) {
throw new Error(`Expected fifth camp sortie preparation overlay: ${JSON.stringify(fifthCampSortieState)}`);
}
await page.mouse.click(938, 596);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('StoryScene');
});
for (let i = 0; i < 26; i += 1) {
const isSixthBattleActive = await page.evaluate(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === 'sixth-battle-jieqiao-relief';
});
if (isSixthBattleActive) {
break;
}
await page.keyboard.press('Space');
await page.waitForTimeout(320);
}
await page.waitForFunction(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === 'sixth-battle-jieqiao-relief' && state?.battleOutcome === null && state?.phase === 'idle';
});
await page.screenshot({ path: 'dist/verification-sixth-battle.png', fullPage: true });
const sixthBattleState = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
const sixthEnemies = sixthBattleState.units.filter((unit) => unit.faction === 'enemy');
const sixthEnemyBehaviors = new Set(sixthEnemies.map((unit) => unit.ai));
if (
sixthBattleState.camera?.mapWidth !== 24 ||
sixthBattleState.camera?.mapHeight !== 20 ||
sixthBattleState.victoryConditionLabel !== '곡의 격파' ||
sixthEnemies.length < 12 ||
!sixthEnemyBehaviors.has('aggressive') ||
!sixthEnemyBehaviors.has('guard') ||
!sixthEnemyBehaviors.has('hold')
) {
throw new Error(`Expected sixth battle map, objective, and mixed enemy AI: ${JSON.stringify(sixthBattleState)}`);
}
await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory'));
await page.waitForFunction(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.battleOutcome === 'victory' && state?.phase === 'resolved' && state?.resultVisible === true;
});
await page.mouse.click(738, 642);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('CampScene');
});
const campaignSaveAfterSixthBattle = await page.evaluate(() => {
const raw = window.localStorage.getItem('heros-web:campaign-state');
return raw ? JSON.parse(raw) : undefined;
});
if (
!campaignSaveAfterSixthBattle ||
campaignSaveAfterSixthBattle.step !== 'sixth-camp' ||
campaignSaveAfterSixthBattle.latestBattleId !== 'sixth-battle-jieqiao-relief' ||
!campaignSaveAfterSixthBattle.battleHistory?.['sixth-battle-jieqiao-relief']
) {
throw new Error(`Expected campaign save to persist sixth battle victory: ${JSON.stringify(campaignSaveAfterSixthBattle)}`);
}
const sixthCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
sixthCampState?.campBattleId !== 'sixth-battle-jieqiao-relief' ||
sixthCampState.campTitle !== '서주 원군 준비 군영' ||
sixthCampState.availableDialogueIds?.length !== 3 ||
!sixthCampState.availableDialogueIds.every((id) => id.endsWith('jieqiao'))
) {
throw new Error(`Expected sixth camp to expose Xu Province bridge dialogue set: ${JSON.stringify(sixthCampState)}`);
}
await page.mouse.click(1120, 38);
await page.waitForTimeout(160);
const sixthCampSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (!sixthCampSortieState?.sortieVisible) {
throw new Error(`Expected sixth camp story bridge overlay: ${JSON.stringify(sixthCampSortieState)}`);
}
await page.mouse.click(938, 596);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('StoryScene');
});
await page.screenshot({ path: 'dist/verification-xuzhou-bridge-story.png', fullPage: true });
for (let i = 0; i < 4; i += 1) {
const returnedToCamp = await page.evaluate(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('CampScene');
});
if (returnedToCamp) {
break;
}
await page.keyboard.press('Space');
await page.waitForTimeout(320);
}
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('CampScene');
});
await page.evaluate(() => window.__HEROS_GAME__?.scene.start('TitleScene'));
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
@@ -674,7 +785,7 @@ try {
return activeScenes.includes('CampScene');
});
console.log(`Verified title-to-fifth-battle flow, result states, and debug API at ${targetUrl}`);
console.log(`Verified title-to-sixth-battle flow, result states, and debug API at ${targetUrl}`);
} finally {
await browser?.close();
if (serverProcess && !serverProcess.killed) {