diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 019ede0..a0b6aee 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -1124,7 +1124,7 @@ type MapMenuAction = 'endTurn' | 'threat' | 'save' | 'load' | 'roster' | 'bond' type EnemyAiBehavior = 'aggressive' | 'guard' | 'hold'; type BattleOutcome = 'victory' | 'defeat'; type SaveSlotMode = 'save' | 'load'; -type TurnPromptMode = 'turn-end' | 'post-move'; +type TurnPromptMode = 'turn-end' | 'post-move' | 'load-confirm'; const battleSpeedStorageKey = 'heros-web:battle-speed'; const battleSpeedLabels: Record = { @@ -10876,6 +10876,10 @@ export class BattleScene extends Phaser.Scene { return; } + if (this.saveSlotPanelObjects.length > 0 || this.turnPromptObjects.length > 0) { + return; + } + if (this.phase === 'deployment') { if (this.isPointerOnSidePanel(pointer)) { return; @@ -11197,13 +11201,14 @@ export class BattleScene extends Phaser.Scene { if (!disabled) { const run = () => { + this.suppressNextLeftClick = true; soundDirector.playSelect(); if (mode === 'save') { this.saveBattleState(slot); + this.hideSaveSlotPanel(); } else { - this.loadBattleState(slot); + this.showLoadBattleConfirm(slot); } - this.hideSaveSlotPanel(); }; row.setInteractive({ useHandCursor: true }); row.on('pointerover', () => row.setFillStyle(0x263647, 0.98)); @@ -11225,6 +11230,7 @@ export class BattleScene extends Phaser.Scene { close.setDepth(depth + 2); close.setInteractive({ useHandCursor: true }); close.on('pointerdown', () => { + this.suppressNextLeftClick = true; soundDirector.playSelect(); this.hideSaveSlotPanel(); }); @@ -11236,6 +11242,31 @@ export class BattleScene extends Phaser.Scene { this.saveSlotPanelObjects = []; } + private showLoadBattleConfirm(slot: number) { + const state = this.readBattleSaveState(slot); + if (!state) { + this.renderSituationPanel('불러올 저장 데이터가 없습니다.'); + return; + } + + this.hideSaveSlotPanel(); + this.showTurnEndPrompt(undefined, { + mode: 'load-confirm', + title: '전투 불러오기 확인', + body: `슬롯 ${slot}의 전투를 불러올까요?\n현재 진행은 저장하지 않으면 사라집니다.`, + primaryLabel: '불러오기', + secondaryLabel: '취소', + primaryAction: () => { + this.hideTurnEndPrompt(); + this.loadBattleState(slot); + }, + secondaryAction: () => { + this.hideTurnEndPrompt(); + this.showSaveSlotPanel('load'); + } + }); + } + private battleSaveStorageKeyForSlot(slot: number) { return `${battleSaveStorageKey}:slot-${Phaser.Math.Clamp(Math.floor(slot), 1, campaignSaveSlotCount)}`; } @@ -15723,7 +15754,7 @@ export class BattleScene extends Phaser.Scene { bg.setInteractive({ useHandCursor: true }); bg.on('pointerover', () => bg.setFillStyle(0x283947, 0.98)); bg.on('pointerout', () => bg.setFillStyle(0x1a2630, 0.95)); - bg.on('pointerdown', () => (primary ? this.activateTurnPromptPrimaryAction() : this.activateTurnPromptSecondaryAction())); + bg.on('pointerdown', () => (primary ? this.activateTurnPromptPrimaryAction(true) : this.activateTurnPromptSecondaryAction(true))); this.turnPromptObjects.push(bg); const text = this.add.text(x, top + 116, label, { @@ -15735,24 +15766,30 @@ export class BattleScene extends Phaser.Scene { text.setOrigin(0.5); text.setDepth(42); text.setInteractive({ useHandCursor: true }); - text.on('pointerdown', () => (primary ? this.activateTurnPromptPrimaryAction() : this.activateTurnPromptSecondaryAction())); + text.on('pointerdown', () => (primary ? this.activateTurnPromptPrimaryAction(true) : this.activateTurnPromptSecondaryAction(true))); this.turnPromptObjects.push(text); }); void message; } - private activateTurnPromptPrimaryAction() { + private activateTurnPromptPrimaryAction(fromPointer = false) { if (!this.turnPromptPrimaryAction) { return; } + if (fromPointer) { + this.suppressNextLeftClick = true; + } soundDirector.playSelect(); this.turnPromptPrimaryAction(); } - private activateTurnPromptSecondaryAction() { + private activateTurnPromptSecondaryAction(fromPointer = false) { const action = this.turnPromptSecondaryAction ?? (() => this.hideTurnEndPrompt()); + if (fromPointer) { + this.suppressNextLeftClick = true; + } soundDirector.playSelect(); action(); }