diff --git a/scripts/verify-flow.mjs b/scripts/verify-flow.mjs index ee95461..24c8b19 100644 --- a/scripts/verify-flow.mjs +++ b/scripts/verify-flow.mjs @@ -9559,6 +9559,27 @@ try { return story?.currentPageId === 'sixty-sixth-victory-wuzhang-held' && story?.backgroundReady === true; }); await page.screenshot({ path: 'dist/verification-ending-epilogue-story.png', fullPage: true }); + await page.evaluate(async () => { + const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms)); + for (let i = 0; i < 8; i += 1) { + const story = window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.(); + if (story?.currentPageId === 'ending-wuzhang-council') { + break; + } + window.__HEROS_DEBUG__?.scene('StoryScene')?.advance?.(); + await delay(520); + } + }); + await page.waitForFunction(() => { + const story = window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.(); + return ( + story?.currentPageId === 'ending-wuzhang-council' && + story?.requestedBackground === 'story-wuzhang-jiangwei-inheritance' && + story?.backgroundReady === true && + story?.background?.startsWith('story-wuzhang-jiangwei-inheritance') + ); + }); + await page.screenshot({ path: 'dist/verification-wuzhang-inheritance-story.png', fullPage: true }); await page.evaluate(async () => { const delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms)); for (let i = 0; i < 20; i += 1) { @@ -9584,7 +9605,9 @@ try { endingState.ending?.campaignStep !== 'ending-complete' || endingState.ending?.latestBattleId !== 'sixty-sixth-battle-wuzhang-final' || endingState.ending?.completedBattles !== 66 || - endingState.ending?.endingTitle !== '북벌의 끝과 남은 뜻' + endingState.ending?.endingTitle !== '북벌의 끝과 남은 뜻' || + endingState.ending?.backgroundKey !== 'story-wuzhang-jiangwei-inheritance' || + endingState.ending?.backgroundReady !== true ) { throw new Error(`Expected final epilogue to mark ending-complete and show EndingScene: ${JSON.stringify(endingState)}`); } @@ -9639,7 +9662,11 @@ try { activeScenes: window.__HEROS_DEBUG__?.activeScenes() ?? [], ending: window.__HEROS_DEBUG__?.scene('EndingScene')?.getDebugState?.() ?? null })); - if (!titleContinueState.activeScenes.includes('EndingScene') || titleContinueState.ending?.campaignStep !== 'ending-complete') { + if ( + !titleContinueState.activeScenes.includes('EndingScene') || + titleContinueState.ending?.campaignStep !== 'ending-complete' || + titleContinueState.ending?.backgroundKey !== 'story-wuzhang-jiangwei-inheritance' + ) { throw new Error(`Expected title continue to reopen the ending screen: ${JSON.stringify(titleContinueState)}`); } diff --git a/src/assets/images/story/135-wuzhang-jiangwei-inheritance.png b/src/assets/images/story/135-wuzhang-jiangwei-inheritance.png new file mode 100644 index 0000000..16338a4 Binary files /dev/null and b/src/assets/images/story/135-wuzhang-jiangwei-inheritance.png differ diff --git a/src/game/data/scenario.ts b/src/game/data/scenario.ts index c3a8626..2be22d6 100644 --- a/src/game/data/scenario.ts +++ b/src/game/data/scenario.ts @@ -4177,17 +4177,17 @@ export const endingEpiloguePages: StoryPage[] = [ id: 'ending-wuzhang-council', bgm: 'story-dark', chapter: '불 꺼진 본영', - background: 'story-weishui-northbank', + background: 'story-wuzhang-jiangwei-inheritance', speaker: '내레이션', - text: '오장원의 불빛이 사라진 뒤에도 장부의 마지막 줄은 남았습니다. 남은 장수들은 더 밀고 들어갈 길보다 돌아갈 병사와 지킬 나라를 먼저 적었고, 승상의 뜻은 다음 사람이 이어 받을 약속이 되었습니다.' + text: '오장원의 불빛이 사라진 뒤에도 빈 의자 앞의 장부는 남았습니다. 남은 장수들은 더 밀고 들어갈 길보다 돌아갈 병사와 지킬 나라를 먼저 적었고, 승상의 뜻은 다음 사람이 이어 받을 약속이 되었습니다.' }, { id: 'ending-jiang-wei-inherits-map', bgm: 'battle-prep', chapter: '이어 받은 지도', - background: 'story-northern', + background: 'story-wuzhang-jiangwei-inheritance', speaker: '강유', - text: '강유는 낡은 지도를 접어 품에 넣었습니다. 오늘의 북벌은 멈추지만, 촉한이 백성을 버리지 않았다는 증거와 다시 길을 볼 눈은 다음 세대의 군문에 남았습니다.' + text: '강유는 낡은 지도와 봉한 장부를 품에 넣었습니다. 오늘의 북벌은 멈추지만, 촉한이 백성을 버리지 않았다는 증거와 다시 길을 볼 눈은 다음 세대의 군문에 남았습니다.' }, { id: 'ending-roster-returns', diff --git a/src/game/scenes/EndingScene.ts b/src/game/scenes/EndingScene.ts index 2fc49e4..1b33c22 100644 --- a/src/game/scenes/EndingScene.ts +++ b/src/game/scenes/EndingScene.ts @@ -1,11 +1,12 @@ import Phaser from 'phaser'; import { soundDirector } from '../audio/SoundDirector'; +import { getBattleScenario } from '../data/battles'; import { storyBackgroundAssets } from '../data/storyAssets'; import { getCampaignState } from '../state/campaignState'; import { palette } from '../ui/palette'; export class EndingScene extends Phaser.Scene { - private readonly backgroundKey = 'story-weishui-northbank'; + private readonly backgroundKey = 'story-wuzhang-jiangwei-inheritance'; private ready = false; constructor() { @@ -30,7 +31,9 @@ export class EndingScene extends Phaser.Scene { latestBattleId: campaign.latestBattleId ?? null, completedBattles: Object.keys(campaign.battleHistory).length, rosterCount: campaign.roster.length, - endingTitle: '북벌의 끝과 남은 뜻' + endingTitle: '북벌의 끝과 남은 뜻', + backgroundKey: this.backgroundKey, + backgroundReady: this.textures.exists(this.backgroundKey) }; } @@ -76,6 +79,7 @@ export class EndingScene extends Phaser.Scene { private drawEnding() { const { width, height } = this.scale; const campaign = getCampaignState(); + const latestBattleTitle = campaign.latestBattleId ? getBattleScenario(campaign.latestBattleId).title : '기록 없음'; const textureKey = this.textures.exists(this.backgroundKey) ? this.backgroundKey : 'ending-fallback'; const background = this.add.image(width / 2, height / 2, textureKey); const source = this.textures.get(textureKey).getSourceImage(); @@ -121,7 +125,7 @@ export class EndingScene extends Phaser.Scene { const summary = [ `완료 전투 ${completedBattles}개`, - `최종 전장 ${campaign.latestBattleId ? '위수 북안 압박전' : '기록 없음'}`, + `최종 전장 ${latestBattleTitle}`, `합류 무장 ${campaign.roster.length}명`, `군영 공명 ${campaign.bonds.length}개` ];