Add Jing Province defense vanguard chapter

This commit is contained in:
2026-06-23 15:00:54 +09:00
parent 63ac73f08b
commit 8585fec6b5
11 changed files with 898 additions and 48 deletions

View File

@@ -1736,7 +1736,7 @@ try {
if (
progressTabState?.activeTab !== 'progress' ||
progressTabState.campaignProgress?.completedKnown !== 17 ||
progressTabState.campaignProgress?.totalKnown !== 37 ||
progressTabState.campaignProgress?.totalKnown !== 38 ||
progressTabState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
progressTabState.campaignProgress?.latestBattleTitle !== '융중 방문로' ||
progressTabState.campaignProgress?.nextBattleTitle !== '박망파 매복전'
@@ -1888,7 +1888,7 @@ try {
if (
postBowangProgressState?.activeTab !== 'progress' ||
postBowangProgressState.campaignProgress?.completedKnown !== 18 ||
postBowangProgressState.campaignProgress?.totalKnown !== 37 ||
postBowangProgressState.campaignProgress?.totalKnown !== 38 ||
postBowangProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postBowangProgressState.campaignProgress?.latestBattleTitle !== '박망파 매복전' ||
postBowangProgressState.campaignProgress?.nextBattleTitle !== '장판파 피난로'
@@ -2026,7 +2026,7 @@ try {
if (
postChangbanProgressState?.activeTab !== 'progress' ||
postChangbanProgressState.campaignProgress?.completedKnown !== 19 ||
postChangbanProgressState.campaignProgress?.totalKnown !== 37 ||
postChangbanProgressState.campaignProgress?.totalKnown !== 38 ||
postChangbanProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postChangbanProgressState.campaignProgress?.latestBattleTitle !== '장판파 피난로' ||
postChangbanProgressState.campaignProgress?.nextBattleTitle !== '강동 사절로'
@@ -2164,7 +2164,7 @@ try {
if (
postJiangdongProgressState?.activeTab !== 'progress' ||
postJiangdongProgressState.campaignProgress?.completedKnown !== 20 ||
postJiangdongProgressState.campaignProgress?.totalKnown !== 37 ||
postJiangdongProgressState.campaignProgress?.totalKnown !== 38 ||
postJiangdongProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postJiangdongProgressState.campaignProgress?.latestBattleTitle !== '강동 사절로' ||
postJiangdongProgressState.campaignProgress?.nextBattleTitle !== '적벽 전초전'
@@ -2304,7 +2304,7 @@ try {
if (
postRedCliffsProgressState?.activeTab !== 'progress' ||
postRedCliffsProgressState.campaignProgress?.completedKnown !== 21 ||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 37 ||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 38 ||
postRedCliffsProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
postRedCliffsProgressState.campaignProgress?.latestBattleTitle !== '적벽 전초전' ||
postRedCliffsProgressState.campaignProgress?.nextBattleTitle !== '적벽 화공전'
@@ -2444,7 +2444,7 @@ try {
if (
postFireAttackProgressState?.activeTab !== 'progress' ||
postFireAttackProgressState.campaignProgress?.completedKnown !== 22 ||
postFireAttackProgressState.campaignProgress?.totalKnown !== 37 ||
postFireAttackProgressState.campaignProgress?.totalKnown !== 38 ||
postFireAttackProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postFireAttackProgressState.campaignProgress?.latestBattleTitle !== '적벽 화공전' ||
postFireAttackProgressState.campaignProgress?.nextBattleTitle !== '형주 남부 진입전'
@@ -2587,7 +2587,7 @@ try {
if (
postJingzhouProgressState?.activeTab !== 'progress' ||
postJingzhouProgressState.campaignProgress?.completedKnown !== 23 ||
postJingzhouProgressState.campaignProgress?.totalKnown !== 37 ||
postJingzhouProgressState.campaignProgress?.totalKnown !== 38 ||
postJingzhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postJingzhouProgressState.campaignProgress?.latestBattleTitle !== '형주 남부 진입전' ||
postJingzhouProgressState.campaignProgress?.nextBattleTitle !== '계양 설득전'
@@ -2729,7 +2729,7 @@ try {
if (
postGuiyangProgressState?.activeTab !== 'progress' ||
postGuiyangProgressState.campaignProgress?.completedKnown !== 24 ||
postGuiyangProgressState.campaignProgress?.totalKnown !== 37 ||
postGuiyangProgressState.campaignProgress?.totalKnown !== 38 ||
postGuiyangProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postGuiyangProgressState.campaignProgress?.latestBattleTitle !== '계양 설득전' ||
postGuiyangProgressState.campaignProgress?.nextBattleTitle !== '무릉 산길 확보전'
@@ -2872,7 +2872,7 @@ try {
if (
postWulingProgressState?.activeTab !== 'progress' ||
postWulingProgressState.campaignProgress?.completedKnown !== 25 ||
postWulingProgressState.campaignProgress?.totalKnown !== 37 ||
postWulingProgressState.campaignProgress?.totalKnown !== 38 ||
postWulingProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postWulingProgressState.campaignProgress?.latestBattleTitle !== '무릉 산길 확보전' ||
postWulingProgressState.campaignProgress?.nextBattleTitle !== '장사 노장 대면전'
@@ -3021,7 +3021,7 @@ try {
if (
postChangshaProgressState?.activeTab !== 'progress' ||
postChangshaProgressState.campaignProgress?.completedKnown !== 26 ||
postChangshaProgressState.campaignProgress?.totalKnown !== 37 ||
postChangshaProgressState.campaignProgress?.totalKnown !== 38 ||
postChangshaProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postChangshaProgressState.campaignProgress?.latestBattleTitle !== '장사 노장 대면전' ||
postChangshaProgressState.campaignProgress?.nextBattleTitle !== '익주 원군로'
@@ -3166,7 +3166,7 @@ try {
if (
postYizhouProgressState?.activeTab !== 'progress' ||
postYizhouProgressState.campaignProgress?.completedKnown !== 27 ||
postYizhouProgressState.campaignProgress?.totalKnown !== 37 ||
postYizhouProgressState.campaignProgress?.totalKnown !== 38 ||
postYizhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postYizhouProgressState.campaignProgress?.latestBattleTitle !== '익주 원군로' ||
postYizhouProgressState.campaignProgress?.nextBattleTitle !== '부수관 진입전'
@@ -3313,7 +3313,7 @@ try {
if (
postFuPassProgressState?.activeTab !== 'progress' ||
postFuPassProgressState.campaignProgress?.completedKnown !== 28 ||
postFuPassProgressState.campaignProgress?.totalKnown !== 37 ||
postFuPassProgressState.campaignProgress?.totalKnown !== 38 ||
postFuPassProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postFuPassProgressState.campaignProgress?.latestBattleTitle !== '부수관 진입전' ||
postFuPassProgressState.campaignProgress?.nextBattleTitle !== '낙성 외곽전'
@@ -3462,7 +3462,7 @@ try {
if (
postLuoProgressState?.activeTab !== 'progress' ||
postLuoProgressState.campaignProgress?.completedKnown !== 29 ||
postLuoProgressState.campaignProgress?.totalKnown !== 37 ||
postLuoProgressState.campaignProgress?.totalKnown !== 38 ||
postLuoProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuoProgressState.campaignProgress?.latestBattleTitle !== '낙성 외곽전' ||
postLuoProgressState.campaignProgress?.nextBattleTitle !== '낙봉파 매복전'
@@ -3608,7 +3608,7 @@ try {
if (
postLuofengProgressState?.activeTab !== 'progress' ||
postLuofengProgressState.campaignProgress?.completedKnown !== 30 ||
postLuofengProgressState.campaignProgress?.totalKnown !== 37 ||
postLuofengProgressState.campaignProgress?.totalKnown !== 38 ||
postLuofengProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuofengProgressState.campaignProgress?.latestBattleTitle !== '낙봉파 매복전' ||
postLuofengProgressState.campaignProgress?.nextBattleTitle !== '낙성 본성 공략'
@@ -3760,7 +3760,7 @@ try {
if (
postLuoMainProgressState?.activeTab !== 'progress' ||
postLuoMainProgressState.campaignProgress?.completedKnown !== 31 ||
postLuoMainProgressState.campaignProgress?.totalKnown !== 37 ||
postLuoMainProgressState.campaignProgress?.totalKnown !== 38 ||
postLuoMainProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postLuoMainProgressState.campaignProgress?.latestBattleTitle !== '낙성 본성 공략' ||
postLuoMainProgressState.campaignProgress?.nextBattleTitle !== '면죽관 압박전'
@@ -3913,7 +3913,7 @@ try {
if (
postMianzhuProgressState?.activeTab !== 'progress' ||
postMianzhuProgressState.campaignProgress?.completedKnown !== 32 ||
postMianzhuProgressState.campaignProgress?.totalKnown !== 37 ||
postMianzhuProgressState.campaignProgress?.totalKnown !== 38 ||
postMianzhuProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
postMianzhuProgressState.campaignProgress?.latestBattleTitle !== '면죽관 압박전' ||
postMianzhuProgressState.campaignProgress?.nextBattleTitle !== '성도 항복 권고전'
@@ -4067,7 +4067,7 @@ try {
if (
postChengduProgressState?.activeTab !== 'progress' ||
postChengduProgressState.campaignProgress?.completedKnown !== 33 ||
postChengduProgressState.campaignProgress?.totalKnown !== 37 ||
postChengduProgressState.campaignProgress?.totalKnown !== 38 ||
postChengduProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postChengduProgressState.campaignProgress?.latestBattleTitle !== '성도 항복 권고전' ||
postChengduProgressState.campaignProgress?.nextBattleTitle !== '가맹관 마초 대면전'
@@ -4222,7 +4222,7 @@ try {
if (
postJiamengProgressState?.activeTab !== 'progress' ||
postJiamengProgressState.campaignProgress?.completedKnown !== 34 ||
postJiamengProgressState.campaignProgress?.totalKnown !== 37 ||
postJiamengProgressState.campaignProgress?.totalKnown !== 38 ||
postJiamengProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postJiamengProgressState.campaignProgress?.latestBattleTitle !== '가맹관 마초 대면전' ||
postJiamengProgressState.campaignProgress?.nextBattleTitle !== '양평관 정찰전'
@@ -4378,7 +4378,7 @@ try {
if (
postYangpingProgressState?.activeTab !== 'progress' ||
postYangpingProgressState.campaignProgress?.completedKnown !== 35 ||
postYangpingProgressState.campaignProgress?.totalKnown !== 37 ||
postYangpingProgressState.campaignProgress?.totalKnown !== 38 ||
postYangpingProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postYangpingProgressState.campaignProgress?.latestBattleTitle !== '양평관 정찰전' ||
postYangpingProgressState.campaignProgress?.nextBattleTitle !== '정군산 전초전'
@@ -4535,7 +4535,7 @@ try {
if (
postDingjunProgressState?.activeTab !== 'progress' ||
postDingjunProgressState.campaignProgress?.completedKnown !== 36 ||
postDingjunProgressState.campaignProgress?.totalKnown !== 37 ||
postDingjunProgressState.campaignProgress?.totalKnown !== 38 ||
postDingjunProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postDingjunProgressState.campaignProgress?.latestBattleTitle !== '정군산 전초전' ||
postDingjunProgressState.campaignProgress?.nextBattleTitle !== '한중 결전'
@@ -4688,7 +4688,7 @@ try {
if (
postHanzhongProgressState?.activeTab !== 'progress' ||
postHanzhongProgressState.campaignProgress?.completedKnown !== 37 ||
postHanzhongProgressState.campaignProgress?.totalKnown !== 37 ||
postHanzhongProgressState.campaignProgress?.totalKnown !== 38 ||
postHanzhongProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
postHanzhongProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
postHanzhongProgressState.campaignProgress?.nextBattleTitle !== '한중왕 즉위 준비'
@@ -4749,7 +4749,7 @@ try {
if (
postKingCouncilProgressState?.activeTab !== 'progress' ||
postKingCouncilProgressState.campaignProgress?.completedKnown !== 37 ||
postKingCouncilProgressState.campaignProgress?.totalKnown !== 37 ||
postKingCouncilProgressState.campaignProgress?.totalKnown !== 38 ||
postKingCouncilProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
postKingCouncilProgressState.campaignProgress?.nextBattleTitle !== '촉한 건국 선포'
) {
@@ -4809,14 +4809,165 @@ try {
if (
postFoundationProgressState?.activeTab !== 'progress' ||
postFoundationProgressState.campaignProgress?.completedKnown !== 37 ||
postFoundationProgressState.campaignProgress?.totalKnown !== 37 ||
postFoundationProgressState.campaignProgress?.totalKnown !== 38 ||
postFoundationProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
postFoundationProgressState.campaignProgress?.nextBattleTitle !== '형주 방위 긴장'
postFoundationProgressState.campaignProgress?.nextBattleTitle !== '형주 방위 전초전'
) {
throw new Error(`Expected Shu-Han foundation camp to point the progress tab toward Jing Province defense: ${JSON.stringify(postFoundationProgressState?.campaignProgress)}`);
}
await page.screenshot({ path: 'dist/verification-post-foundation-progress.png', fullPage: true });
await page.mouse.click(1120, 38);
await page.waitForTimeout(180);
const jingDefenseSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
!jingDefenseSortieState?.sortieVisible ||
jingDefenseSortieState.campaign?.step !== 'shu-han-foundation-camp' ||
jingDefenseSortieState.sortiePlan?.objectiveLine !== '형주 방위 전초전 · 여몽 정찰대 격파' ||
jingDefenseSortieState.sortiePlan?.maxCount !== 7 ||
jingDefenseSortieState.sortiePlan?.recommendedTotal !== 7 ||
!jingDefenseSortieState.sortieRoster?.some((unit) => unit.id === 'guan-yu' && unit.recommended)
) {
throw new Error(`Expected Jing defense sortie prep to use a seven-officer roster and recommend Guan Yu's front: ${JSON.stringify(jingDefenseSortieState)}`);
}
assertSortieTacticalRoster(jingDefenseSortieState, [
'liu-bei',
'guan-yu',
'zhang-fei',
'jian-yong',
'mi-zhu',
'sun-qian',
'zhao-yun',
'zhuge-liang',
'ma-liang',
'yi-ji',
'gong-zhi',
'huang-zhong',
'wei-yan',
'pang-tong',
'fa-zheng',
'wu-yi',
'yan-yan',
'li-yan',
'huang-quan',
'ma-chao',
'ma-dai',
'wang-ping'
]);
const jingDefensePriorityUnits = ['guan-yu', 'zhang-fei', 'ma-liang', 'mi-zhu', 'zhuge-liang', 'zhao-yun'];
for (const unitId of jingDefensePriorityUnits) {
const currentSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (!currentSortieState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)) {
const removable = currentSortieState.sortieRoster?.find(
(unit) => unit.selected && unit.id !== 'liu-bei' && !jingDefensePriorityUnits.includes(unit.id)
);
if (removable) {
await clickSortieRosterUnit(page, removable.id);
}
await clickSortieRosterUnit(page, unitId);
}
}
const jingDefenseSortieReadyState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
!jingDefensePriorityUnits.every((unitId) =>
jingDefenseSortieReadyState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)
) ||
jingDefenseSortieReadyState.sortiePlan?.selectedCount !== 7 ||
jingDefenseSortieReadyState.sortiePlan?.recommendedSelectedCount < 7
) {
throw new Error(`Expected Jing defense sortie to deploy Guan Yu, Zhang Fei, Ma Liang, Mi Zhu, Zhuge Liang, and Zhao Yun with seven-officer pressure: ${JSON.stringify(jingDefenseSortieReadyState)}`);
}
await page.screenshot({ path: 'dist/verification-jing-defense-sortie.png', fullPage: true });
await page.mouse.click(1068, 646);
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('StoryScene');
});
await page.screenshot({ path: 'dist/verification-jing-defense-story.png', fullPage: true });
for (let i = 0; i < 45; i += 1) {
const enteredThirtyEighthBattle = await page.evaluate(() => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === 'thirty-eighth-battle-jing-defense';
});
if (enteredThirtyEighthBattle) {
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 === 'thirty-eighth-battle-jing-defense' && state?.battleOutcome === null && state?.phase === 'idle';
});
await page.screenshot({ path: 'dist/verification-thirty-eighth-battle.png', fullPage: true });
const thirtyEighthBattleState = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
const thirtyEighthEnemies = thirtyEighthBattleState.units.filter((unit) => unit.faction === 'enemy');
const thirtyEighthAllies = thirtyEighthBattleState.units.filter((unit) => unit.faction === 'ally');
const thirtyEighthEnemyBehaviors = new Set(thirtyEighthEnemies.map((unit) => unit.ai));
if (
thirtyEighthBattleState.camera?.mapWidth !== 76 ||
thirtyEighthBattleState.camera?.mapHeight !== 58 ||
thirtyEighthBattleState.victoryConditionLabel !== '여몽 정찰대 격파' ||
thirtyEighthEnemies.length < 30 ||
!thirtyEighthEnemyBehaviors.has('aggressive') ||
!thirtyEighthEnemyBehaviors.has('guard') ||
!thirtyEighthEnemyBehaviors.has('hold') ||
!thirtyEighthEnemies.some((unit) => unit.id === 'jing-defense-leader-lu-meng') ||
!thirtyEighthEnemies.some((unit) => unit.id === 'jing-defense-officer-cao-ren') ||
!thirtyEighthEnemies.some((unit) => unit.id === 'jing-defense-officer-lu-xun') ||
!thirtyEighthAllies.some((unit) => unit.id === 'guan-yu') ||
!thirtyEighthAllies.some((unit) => unit.id === 'ma-liang') ||
!thirtyEighthAllies.some((unit) => unit.id === 'mi-zhu') ||
!thirtyEighthAllies.some((unit) => unit.id === 'zhuge-liang') ||
!thirtyEighthAllies.some((unit) => unit.id === 'zhao-yun')
) {
throw new Error(`Expected thirty-eighth battle to use Jing defense map, Lu Meng objective, selected allied officers, and mixed Wu/Wei AI: ${JSON.stringify(thirtyEighthBattleState)}`);
}
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 thirtyEighthCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
thirtyEighthCampState?.campBattleId !== 'thirty-eighth-battle-jing-defense' ||
thirtyEighthCampState.campTitle !== '형주 방위 전초전 후 군영' ||
thirtyEighthCampState.availableDialogueIds?.length !== 3 ||
!thirtyEighthCampState.availableDialogueIds.every((id) => id.endsWith('jing-defense')) ||
thirtyEighthCampState.availableVisitIds?.length !== 2 ||
thirtyEighthCampState.rosterCollection?.total < 22
) {
throw new Error(`Expected thirty-eighth camp to expose Jing defense dialogue/visit sets and preserve the full officer roster: ${JSON.stringify(thirtyEighthCampState)}`);
}
await page.screenshot({ path: 'dist/verification-jing-defense-camp.png', fullPage: true });
await page.mouse.click(966, 38);
await page.waitForTimeout(180);
const postJingDefenseProgressState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
if (
postJingDefenseProgressState?.activeTab !== 'progress' ||
postJingDefenseProgressState.campaignProgress?.completedKnown !== 38 ||
postJingDefenseProgressState.campaignProgress?.totalKnown !== 38 ||
postJingDefenseProgressState.campaignProgress?.latestBattleTitle !== '형주 방위 전초전' ||
postJingDefenseProgressState.campaignProgress?.nextBattleTitle !== '준비 중'
) {
throw new Error(`Expected post-Jing defense progress tab to complete the thirty-eighth battle and leave Fan Castle as the next prepared slice: ${JSON.stringify(postJingDefenseProgressState?.campaignProgress)}`);
}
await page.screenshot({ path: 'dist/verification-post-jing-defense-progress.png', fullPage: true });
await page.evaluate(() => {
const game = window.__HEROS_GAME__;
game?.scene.stop('CampScene');
@@ -4835,7 +4986,7 @@ try {
return activeScenes.includes('CampScene');
});
console.log(`Verified title-to-thirty-seventh-battle flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, and Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng, Yangping, Dingjun, Hanzhong decisive battle, King of Hanzhong council, and Shu-Han foundation state at ${targetUrl}`);
console.log(`Verified title-to-thirty-eighth-battle flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng, Yangping, Dingjun, Hanzhong decisive battle, King of Hanzhong council, Shu-Han foundation state, and Jing Province defense vanguard state at ${targetUrl}`);
} finally {
await browser?.close();
if (serverProcess && !serverProcess.killed) {