From d7c706852e39a8cede8ab592d11fda66e2374da0 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sun, 5 Jul 2026 02:27:13 +0900 Subject: [PATCH] Summarize campaign saves on title screen --- src/game/scenes/TitleScene.ts | 50 +++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/game/scenes/TitleScene.ts b/src/game/scenes/TitleScene.ts index 3a97567..9512950 100644 --- a/src/game/scenes/TitleScene.ts +++ b/src/game/scenes/TitleScene.ts @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { soundDirector } from '../audio/SoundDirector'; +import { getBattleScenario } from '../data/battles'; import { battleIdForCampaignStep, isCampCampaignStep } from '../state/campaignRouting'; import { hasCampaignSave, loadCampaignState, startNewCampaign } from '../state/campaignState'; import { palette } from '../ui/palette'; @@ -202,7 +203,7 @@ export class TitleScene extends Phaser.Scene { const canContinue = hasCampaignSave(); const campaign = canContinue ? loadCampaignState() : undefined; const isEndingComplete = campaign?.step === 'ending-complete'; - const plateHeight = isEndingComplete ? 324 : 252; + const plateHeight = campaign ? 324 : 252; const plate = this.add.rectangle(menuX, menuY, 250, plateHeight, 0x111821, 0.66); plate.setStrokeStyle(1, palette.gold, 0.45); @@ -213,19 +214,22 @@ export class TitleScene extends Phaser.Scene { this.createMenuButton(menuX, menuY, isEndingComplete ? '엔딩 보기' : '이어하기', canContinue, () => this.continueGame()); this.createMenuButton(menuX, menuY + 70, '설정', true, () => this.openSettingsPanel(menuX, menuY)); - if (isEndingComplete && campaign) { - this.drawCampaignCompleteBadge(menuX, menuY + 132, campaign); + if (campaign) { + this.drawCampaignSaveBadge(menuX, menuY + 132, campaign, isEndingComplete); } } - private drawCampaignCompleteBadge(x: number, y: number, campaign: ReturnType) { - const completedBattles = Object.keys(campaign.battleHistory).length; - const rosterCount = campaign.roster.length; + private drawCampaignSaveBadge( + x: number, + y: number, + campaign: ReturnType, + isEndingComplete: boolean + ) { const badge = this.add.container(x, y); const background = this.add.rectangle(0, 0, 210, 58, 0x21180f, 0.92); background.setStrokeStyle(1, palette.gold, 0.52); - const title = this.add.text(0, -14, '완결 저장', { + const title = this.add.text(0, -14, isEndingComplete ? '완결 저장' : '진행 저장', { fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', fontSize: '18px', color: '#f6e6bd', @@ -236,7 +240,7 @@ export class TitleScene extends Phaser.Scene { }); title.setOrigin(0.5); - const detail = this.add.text(0, 14, `${completedBattles}전 완수 · ${rosterCount}명 합류`, { + const detail = this.add.text(0, 14, this.campaignSaveDetail(campaign, isEndingComplete), { fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', fontSize: '14px', color: '#d8b15f', @@ -248,6 +252,36 @@ export class TitleScene extends Phaser.Scene { badge.add([background, title, detail]); } + private campaignSaveDetail(campaign: ReturnType, isEndingComplete: boolean) { + if (isEndingComplete) { + return `${Object.keys(campaign.battleHistory).length}전 완수 · ${campaign.roster.length}명 합류`; + } + + const nextBattleId = battleIdForCampaignStep(campaign.step); + if (nextBattleId) { + return this.compactSaveDetail(`다음 전장 · ${getBattleScenario(nextBattleId).title}`); + } + + if (isCampCampaignStep(campaign.step)) { + const latestTitle = campaign.latestBattleId ? getBattleScenario(campaign.latestBattleId).title : '전투 이후'; + return this.compactSaveDetail(`군영 정비 · ${latestTitle}`); + } + + if (campaign.step === 'prologue') { + return '도원 결의 · 첫 출진 전'; + } + + if (campaign.step === 'first-victory-story') { + return '승리 후일담 · 군영 복귀'; + } + + return `군자금 ${campaign.gold} · ${campaign.roster.length}명`; + } + + private compactSaveDetail(label: string) { + return label.length > 19 ? `${label.slice(0, 18)}...` : label; + } + private createMenuButton( x: number, y: number,