From 83bba0c508111196cd602e1a9728eaa5ded361cb Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sun, 5 Jul 2026 04:34:43 +0900 Subject: [PATCH] Confirm camp save overwrites --- src/game/scenes/CampScene.ts | 111 ++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/src/game/scenes/CampScene.ts b/src/game/scenes/CampScene.ts index e2d9076..90d3376 100644 --- a/src/game/scenes/CampScene.ts +++ b/src/game/scenes/CampScene.ts @@ -10717,6 +10717,8 @@ export class CampScene extends Phaser.Scene { private dialogueObjects: Phaser.GameObjects.GameObject[] = []; private sortieObjects: Phaser.GameObjects.GameObject[] = []; private saveSlotObjects: Phaser.GameObjects.GameObject[] = []; + private saveSlotConfirmObjects: Phaser.GameObjects.GameObject[] = []; + private pendingSaveSlot?: number; private tabButtons: CampTabButtonView[] = []; private visitedTabs = new Set(); private selectedSortieUnitIds: string[] = []; @@ -10742,6 +10744,8 @@ export class CampScene extends Phaser.Scene { this.dialogueObjects = []; this.sortieObjects = []; this.saveSlotObjects = []; + this.saveSlotConfirmObjects = []; + this.pendingSaveSlot = undefined; this.tabButtons = []; this.visitedTabs = new Set(['status']); this.campaign = getCampaignState(); @@ -11936,7 +11940,7 @@ export class CampScene extends Phaser.Scene { saveLabel.setDepth(depth + 1); this.saveSlotObjects.push(saveLabel); - const run = () => this.saveCampToSlot(summary.slot); + const run = () => this.requestSaveCampToSlot(summary.slot); [row, title, detail, meta, saveLabel].forEach((object) => { object.setInteractive({ useHandCursor: true }); object.on('pointerdown', run); @@ -11973,6 +11977,88 @@ export class CampScene extends Phaser.Scene { return `${month}/${day} ${hour}:${minute}`; } + private requestSaveCampToSlot(slot: number) { + const activeSlot = this.campaign?.activeSaveSlot ?? getCampaignState().activeSaveSlot; + const summary = listCampaignSaveSlots().find((candidate) => candidate.slot === slot); + if (summary?.exists && summary.slot !== activeSlot) { + this.showCampSaveOverwriteConfirm(summary); + return; + } + + this.saveCampToSlot(slot); + } + + private showCampSaveOverwriteConfirm(summary: CampaignSaveSlotSummary) { + this.hideCampSaveConfirm(); + this.pendingSaveSlot = summary.slot; + + const depth = 64; + const width = 386; + const height = 166; + const x = this.scale.width - width - 58; + const y = 158; + + const shade = this.add.rectangle(0, 0, this.scale.width, this.scale.height, 0x020406, 0.34); + shade.setOrigin(0); + shade.setDepth(depth - 1); + shade.setInteractive(); + this.saveSlotConfirmObjects.push(shade); + + const panel = this.add.rectangle(x, y, width, height, 0x111a24, 0.99); + panel.setOrigin(0); + panel.setDepth(depth); + panel.setStrokeStyle(2, palette.gold, 0.9); + panel.setInteractive(); + this.saveSlotConfirmObjects.push(panel); + + const title = this.add.text(x + 22, y + 18, `슬롯 ${summary.slot} 덮어쓰기`, this.textStyle(20, '#f2e3bf', true)); + title.setDepth(depth + 1); + this.saveSlotConfirmObjects.push(title); + + const detail = this.add.text( + x + 22, + y + 50, + `${this.campSaveSlotDetail(summary)}\n${this.campSaveSlotMeta(summary)}`, + this.textStyle(12, '#b9c3cf') + ); + detail.setDepth(depth + 1); + detail.setLineSpacing(5); + this.saveSlotConfirmObjects.push(detail); + + const message = this.add.text(x + 22, y + 96, '현재 군영 진행으로 이 슬롯을 교체합니다.', this.textStyle(12, '#ffdf7b', true)); + message.setDepth(depth + 1); + this.saveSlotConfirmObjects.push(message); + + const confirm = this.add.text(x + width - 174, y + 126, '덮어쓰기', this.textStyle(14, '#f2e3bf', true)); + confirm.setDepth(depth + 1); + confirm.setPadding(14, 5, 14, 5); + confirm.setBackgroundColor('#6d4420'); + confirm.setInteractive({ useHandCursor: true }); + confirm.on('pointerdown', () => this.confirmCampSaveOverwrite()); + this.saveSlotConfirmObjects.push(confirm); + + const cancel = this.add.text(x + width - 70, y + 126, '취소', this.textStyle(14, '#d8b15f', true)); + cancel.setDepth(depth + 1); + cancel.setPadding(14, 5, 14, 5); + cancel.setBackgroundColor('#1a2630'); + cancel.setInteractive({ useHandCursor: true }); + cancel.on('pointerdown', () => { + soundDirector.playSelect(); + this.hideCampSaveConfirm(); + }); + this.saveSlotConfirmObjects.push(cancel); + } + + private confirmCampSaveOverwrite() { + const slot = this.pendingSaveSlot; + if (!slot) { + this.hideCampSaveConfirm(); + return; + } + + this.saveCampToSlot(slot); + } + private saveCampToSlot(slot: number) { soundDirector.playSelect(); this.hideCampSaveSlotPanel(); @@ -11982,6 +12068,14 @@ export class CampScene extends Phaser.Scene { } private handleSaveSlotKey(event: KeyboardEvent) { + if (this.saveSlotConfirmObjects.length > 0) { + if (event.key === 'Enter') { + event.preventDefault(); + this.confirmCampSaveOverwrite(); + } + return; + } + if (this.saveSlotObjects.length === 0) { return; } @@ -11992,15 +12086,28 @@ export class CampScene extends Phaser.Scene { } event.preventDefault(); - this.saveCampToSlot(slot); + this.requestSaveCampToSlot(slot); } private hideCampSaveSlotPanel() { + this.hideCampSaveConfirm(); this.saveSlotObjects.forEach((object) => object.destroy()); this.saveSlotObjects = []; } + private hideCampSaveConfirm() { + this.saveSlotConfirmObjects.forEach((object) => object.destroy()); + this.saveSlotConfirmObjects = []; + this.pendingSaveSlot = undefined; + } + private handleEscapeKey() { + if (this.saveSlotConfirmObjects.length > 0) { + soundDirector.playSelect(); + this.hideCampSaveConfirm(); + return; + } + if (this.saveSlotObjects.length > 0) { soundDirector.playSelect(); this.hideCampSaveSlotPanel();