diff --git a/src/game/data/battles.ts b/src/game/data/battles.ts index fa75b4b..e15eda5 100644 --- a/src/game/data/battles.ts +++ b/src/game/data/battles.ts @@ -727,8 +727,8 @@ export const thirdBattleScenario: BattleScenarioDefinition = { label: '강가 요새 확보', rewardGold: 220, terrain: 'fort', - targetTile: { x: 19, y: 2, radius: 2 }, - threatRadius: 0 + targetTile: { x: 18, y: 1, radius: 3 }, + threatRadius: 1 }, { id: 'quick', diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 71f521d..b939d9e 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -7826,6 +7826,17 @@ export class BattleScene extends Phaser.Scene { return preview.usable ? this.usablePowerIcon(preview.usable) : 'attack'; } + private pendingEndBattleBonusObjectiveLabels(preview: CombatPreview) { + if (preview.defender.id !== leaderUnitId || preview.damage < preview.defender.hp) { + return []; + } + const states = this.objectiveStates(); + return battleScenario.objectives + .map((definition, index) => ({ definition, state: states[index] })) + .filter(({ definition, state }) => state?.category === 'bonus' && state.status !== 'done' && definition.kind !== 'quick-victory') + .map(({ state }) => state.label); + } + private previewActionTypeLabel(preview: CombatPreview) { if (preview.usable) { return this.usableEffectLabel(preview.usable); @@ -7843,7 +7854,9 @@ export class BattleScene extends Phaser.Scene { const { panelX, panelWidth } = this.layout; const left = panelX + 24; const width = panelWidth - 48; - const height = locked ? 464 : 430; + const pendingBonusLabels = this.pendingEndBattleBonusObjectiveLabels(preview); + const showsObjectiveWarning = pendingBonusLabels.length > 0; + const height = locked ? (showsObjectiveWarning ? 500 : 464) : showsObjectiveWarning ? 466 : 430; const y = this.sideContentTop(); const accent = this.previewAccentColor(preview); const distance = this.tileDistance(preview.attacker, preview.defender); @@ -7932,11 +7945,29 @@ export class BattleScene extends Phaser.Scene { if (preview.equipmentEffectLabels.length > 0) { this.renderPreviewBadge(detailBadgeX, badgeY, 'mastery', '장비 보정', maxBadgeRight); } + if (showsObjectiveWarning) { + this.renderPreviewObjectiveWarning(left + 10, y + 408, width - 20, pendingBonusLabels); + } if (locked) { this.renderPreviewConfirmBar(left + 10, y + 426, width - 20, accent, `${preview.defender.name} 선택됨`); } } + private renderPreviewObjectiveWarning(x: number, y: number, width: number, labels: string[]) { + const targetLabel = labels.length > 1 ? `${labels[0]} 외 ${labels.length - 1}` : labels[0] ?? '보너스 목표'; + const bg = this.trackSideObject(this.add.rectangle(x, y, width, 18, 0x2a1712, 0.98)); + bg.setOrigin(0); + bg.setStrokeStyle(1, 0xd8732c, 0.82); + this.trackSideIcon(x + 12, y + 9, 'failure', 18); + this.trackSideObject(this.add.text(x + 25, y + 3, `적장 격파 시 종료 · 미확보: ${this.truncateUiText(targetLabel, 18)}`, { + fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', + fontSize: '10px', + color: '#ffd0a8', + fontStyle: '700', + fixedWidth: width - 31 + })); + } + private renderSupportPreviewSummaryCard(preview: SupportPreview, locked = false) { const { panelX, panelWidth } = this.layout; const left = panelX + 24;