From e4d0e0b19a05dae7feae6474944b429dd6aedeb5 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sat, 4 Jul 2026 15:20:34 +0900 Subject: [PATCH] Refine Xuzhou breakout battle flow --- src/game/data/battles.ts | 70 +++++++++++++++++++++++++++++++--- src/game/data/campaignFlow.ts | 2 +- src/game/data/scenario.ts | 10 ++--- src/game/scenes/BattleScene.ts | 8 ++-- src/game/scenes/CampScene.ts | 11 +++--- 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/game/data/battles.ts b/src/game/data/battles.ts index ef6a71c..3f86852 100644 --- a/src/game/data/battles.ts +++ b/src/game/data/battles.ts @@ -1311,10 +1311,60 @@ export const tenthBattleScenario: BattleScenarioDefinition = { victoryConditionLabel: '송헌 격파', defeatConditionLabel: '유비 퇴각', openingObjectiveLines: [ - '서주는 여포에게 넘어갔고, 유비군은 성 밖으로 빠져나갈 길을 열어야 합니다. 송헌을 격파하면 추격대의 지휘가 무너집니다.', - '여포군 기병은 길을 따라 빠르게 압박하고, 성내 배반병은 숲과 마을 근처에서 퇴로를 끊으려 합니다.', - '서쪽 진영과 마을을 확보한 채 20턴 안에 돌파하면 조조 의탁으로 이어질 병력과 보급을 더 많이 보존합니다.' + '서주는 여포에게 넘어갔고, 유비군은 성을 되찾기보다 백성과 보급을 보존한 채 성 밖 퇴로를 열어야 합니다. 송헌을 격파하면 추격대의 지휘가 무너집니다.', + '성내 배반병은 피난 마을과 수레 길을 끊고, 여포군 기병은 동쪽 성문 길을 따라 빠르게 압박합니다. 장비는 남쪽 길을 열고 관우는 추격을 막아야 합니다.', + '퇴로 마을을 확보하고 20턴 안에 돌파하면 조조 의탁으로 이어질 병력과 보급을 더 많이 보존합니다.' ], + tacticalGuide: { + summary: '서쪽 진영에서 퇴로 마을까지 길을 열고, 관우가 추격을 받아내는 동안 장비가 남쪽 차단병을 밀어냅니다.', + route: '서쪽 진영 → 피난 마을 → 남쪽 퇴로 → 송헌 추격대', + focus: '성을 되찾으려 깊게 들어가지 말고 피난 마을 주변 배반병을 먼저 정리하십시오. 간옹은 기병 돌입을 늦추고, 미축은 보급품으로 유비와 전열을 보존합니다.', + roles: ['유비: 후방 생존/퇴각 지휘', '관우: 추격 차단 전열', '장비: 남쪽 퇴로 돌파', '간옹: 화계/격려로 기병 지연', '미축: 피난민/보급 보존'], + events: { + 'village-approach': { + title: '피난 마을 접근', + lines: ['피난민과 보급 수레가 남쪽 마을 길에 묶여 있습니다.', '마을 주변 배반병을 정리하면 조조에게 향할 병력과 보급을 더 많이 보존할 수 있습니다.'] + }, + 'enemy-posture': { + title: '포위망 확인', + lines: ['송헌은 동쪽 길목에서 본대를 세우고, 배반병은 숲과 마을 사이 퇴로를 끊고 있습니다.', '관우가 추격을 받아내는 동안 장비로 남쪽 길을 열고 간옹과 미축을 너무 앞세우지 마십시오.'] + }, + 'cavalry-approach': { + title: '추격 기병 접근', + lines: ['여포군 기병이 성문 길을 타고 빠르게 따라붙습니다.', '무리하게 성 안쪽으로 파고들지 말고 관우 전열과 간옹의 책략으로 속도를 늦추십시오.'] + }, + 'leader-wavering': { + title: '송헌 지휘 흔들림', + lines: ['송헌의 추격대가 흔들리기 시작했습니다.', '유비를 뒤에 두고 전열을 좁히면 퇴로를 열 마지막 기회가 생깁니다.'] + } + } + }, + sortie: { + sortieLimit: 5, + requiredUnits: ['liu-bei'], + recommendedUnits: [ + { unitId: 'liu-bei', role: 'support', reason: '퇴각 지휘의 중심이자 패배 조건이므로 후방 생존을 우선해야 합니다.' }, + { unitId: 'guan-yu', role: 'front', reason: '여포군 추격대를 받아내며 유비와 보급 수레 뒤를 지키는 전열입니다.' }, + { unitId: 'zhang-fei', role: 'flank', reason: '실책을 만회하며 남쪽 퇴로를 여는 돌파 담당입니다.' }, + { unitId: 'jian-yong', role: 'support', reason: '화계와 격려로 기병 돌입을 늦추고 퇴로 판단을 보조합니다.' }, + { unitId: 'mi-zhu', role: 'reserve', reason: '피난민과 보급 수레를 보존하고 회복품 운용을 안정시킵니다.' } + ], + recommendedClasses: [ + { label: '퇴각 지휘', classKeys: ['lord'], reason: '유비가 살아남아야 다음 의탁과 재편이 이어집니다.' }, + { label: '추격 차단', classKeys: ['infantry'], reason: '동쪽 기병 압박을 정면에서 받아낼 전열이 필요합니다.' }, + { label: '퇴로 돌파', classKeys: ['spearman'], reason: '남쪽 길목의 배반병과 기병을 빠르게 끊어야 합니다.' }, + { label: '책략 지연', classKeys: ['strategist'], reason: '화계와 격려로 추격 속도를 늦추면 손실이 줄어듭니다.' }, + { label: '보급 보존', classKeys: ['quartermaster'], reason: '피난민과 보급품을 지키면 전투 후 보상이 실제 정비로 이어집니다.' } + ], + deploymentSlots: [ + { role: 'support', unitId: 'liu-bei', x: 3, y: 14, label: '퇴각 지휘' }, + { role: 'front', unitId: 'guan-yu', x: 4, y: 15, label: '추격 차단' }, + { role: 'flank', unitId: 'zhang-fei', x: 3, y: 16, label: '남쪽 돌파' }, + { role: 'support', unitId: 'jian-yong', x: 5, y: 17, label: '책략 지연' }, + { role: 'reserve', unitId: 'mi-zhu', x: 4, y: 18, label: '보급 수레' } + ], + note: '서주 탈출전은 성을 되찾는 전투가 아니라 퇴로를 여는 전투입니다. 관우는 추격을 막고, 장비는 남쪽 길을 열며, 간옹과 미축은 책략과 보급으로 손실을 줄이는 편성이 기본입니다.' + }, map: tenthBattleMap, units: tenthBattleUnits, bonds: tenthBattleBonds, @@ -1340,9 +1390,11 @@ export const tenthBattleScenario: BattleScenarioDefinition = { { id: 'village', kind: 'secure-terrain', - label: '피난 마을 확보', + label: '퇴로 마을 확보', rewardGold: 420, - terrain: 'village' + terrain: 'village', + targetTile: { x: 13, y: 17, radius: 4 }, + threatRadius: 0 }, { id: 'quick', @@ -1354,6 +1406,14 @@ export const tenthBattleScenario: BattleScenarioDefinition = { ], defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }], itemRewards: ['콩 4', '상처약 2', '탁주 1', '서주 피난민 보호 +1'], + campaignReward: { + supplies: ['콩 4', '상처약 2', '탁주 1'], + equipment: ['철창 1'], + reputation: ['서주 피난민 보호 +1'], + unlockBattleId: 'eleventh-battle-xudu-refuge-road', + unlockLabel: '허도 입성로 개방', + note: '서주는 잃었지만 병력과 피난민 일부를 보존해 조조 의탁 전선으로 이어집니다.' + }, victoryPages: tenthBattleVictoryPages, nextCampScene: 'CampScene' }; diff --git a/src/game/data/campaignFlow.ts b/src/game/data/campaignFlow.ts index 105799a..7b17147 100644 --- a/src/game/data/campaignFlow.ts +++ b/src/game/data/campaignFlow.ts @@ -312,7 +312,7 @@ const sortieFlows: Record = { afterBattleId: tenthBattleScenario.id, eyebrow: '다음 전장', title: eleventhBattleScenario.title, - description: '조조는 유비군을 받아들이되 허도 입성로의 원술 잔군을 치게 합니다. 의탁은 시작되지만, 동시에 유비군의 군율과 힘을 재는 시험입니다.', + description: '서주는 잃었지만 병력과 피난민 일부를 보존했습니다. 조조는 유비군을 받아들이되 허도 입성로의 원술 잔군을 치게 하며, 의탁은 곧 군율과 힘을 재는 시험으로 바뀝니다.', rewardHint: `예상 보상: ${eleventhBattleScenario.title} 개방`, nextBattleId: eleventhBattleScenario.id, campaignStep: 'eleventh-battle', diff --git a/src/game/data/scenario.ts b/src/game/data/scenario.ts index 6d109cb..3febef1 100644 --- a/src/game/data/scenario.ts +++ b/src/game/data/scenario.ts @@ -979,7 +979,7 @@ export const tenthBattleIntroPages: StoryPage[] = [ bgm: 'story-dark', chapter: '빼앗긴 서주', background: 'story-wandering', - text: '여포는 성문이 흔들린 틈을 놓치지 않았다. 서주 곳곳의 수비대가 갈라졌고, 유비가 돌아왔을 때 성루의 깃발은 이미 바뀌어 있었다.' + text: '여포는 성문이 흔들린 틈을 놓치지 않았다. 서주 곳곳의 수비대가 갈라졌고, 피난민과 보급 수레는 성 밖 길목에 묶인 채 흩어지기 시작했다.' }, { id: 'tenth-brothers-regroup', @@ -988,7 +988,7 @@ export const tenthBattleIntroPages: StoryPage[] = [ background: 'story-wandering', speaker: '관우', portrait: 'guanYu', - text: '형님, 지금 성을 되찾으려 들면 백성과 군졸을 모두 잃습니다. 익덕을 꾸짖는 일은 살아나간 뒤에 해도 늦지 않습니다.' + text: '형님, 지금 성을 되찾으려 들면 백성과 군졸을 모두 잃습니다. 미축의 수레는 남쪽 마을 길에 있고, 제가 뒤를 막는 동안 익덕이 퇴로를 열어야 합니다.' }, { id: 'tenth-xuzhou-escape', @@ -997,7 +997,7 @@ export const tenthBattleIntroPages: StoryPage[] = [ background: 'story-wandering', speaker: '유비', portrait: 'liuBei', - text: '서주는 오늘 내 손에서 떠났다. 그러나 백성과 형제와 뜻까지 잃을 수는 없다. 포위망을 뚫고 다음 길을 찾자.' + text: '서주는 오늘 내 손에서 떠났다. 그러나 백성과 형제와 뜻까지 잃을 수는 없다. 피난 마을을 거쳐 포위망을 뚫고, 살아서 다음 길을 찾자.' } ]; @@ -1007,7 +1007,7 @@ export const tenthBattleVictoryPages: StoryPage[] = [ bgm: 'militia-theme', chapter: '잃고도 남은 것', background: 'story-wandering', - text: '유비군은 여포군 선봉을 뚫고 서주 외곽으로 물러났다. 성은 빼앗겼으나, 세 형제와 새로 모인 장수들의 전열은 아직 흩어지지 않았다.' + text: '유비군은 피난 마을의 보급 수레를 거두고 여포군 선봉을 뚫어 서주 외곽으로 물러났다. 성은 빼앗겼으나, 백성과 장수들의 전열은 아직 흩어지지 않았다.' }, { id: 'tenth-cao-cao-shadow', @@ -1015,7 +1015,7 @@ export const tenthBattleVictoryPages: StoryPage[] = [ chapter: '허도로 향하는 그림자', background: 'story-wandering', speaker: '간옹', - text: '현덕, 이제 서주 안에서 버티는 길은 막혔네. 조조의 휘하로 들어가는 일은 마음에 걸리지만, 살아남아 다시 뜻을 세우려면 그 길을 지나야 할 걸세.' + text: '현덕, 병력과 보급은 가까스로 지켰네. 조조의 휘하로 들어가는 일은 마음에 걸리지만, 살아남아 다시 뜻을 세우려면 그 길을 지나야 할 걸세.' } ]; diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 4dc081b..b1711e5 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -1753,15 +1753,15 @@ const enemyAiByUnitId: Record = { 'lubu-cavalry-c': 'aggressive', 'xuzhou-leader-cao-bao': 'guard', 'xuzhou-escape-cavalry-a': 'aggressive', - 'xuzhou-escape-cavalry-b': 'aggressive', - 'xuzhou-escape-cavalry-c': 'aggressive', + 'xuzhou-escape-cavalry-b': 'guard', + 'xuzhou-escape-cavalry-c': 'guard', 'xuzhou-escape-guard-a': 'guard', 'xuzhou-escape-guard-b': 'guard', 'xuzhou-escape-guard-c': 'guard', 'xuzhou-escape-archer-a': 'hold', 'xuzhou-escape-archer-b': 'hold', - 'xuzhou-escape-raider-a': 'aggressive', - 'xuzhou-escape-raider-b': 'aggressive', + 'xuzhou-escape-raider-a': 'guard', + 'xuzhou-escape-raider-b': 'guard', 'xuzhou-escape-leader-song-xian': 'guard', 'xudu-road-raider-a': 'guard', 'xudu-road-raider-b': 'guard', diff --git a/src/game/scenes/CampScene.ts b/src/game/scenes/CampScene.ts index efb07be..58cec64 100644 --- a/src/game/scenes/CampScene.ts +++ b/src/game/scenes/CampScene.ts @@ -673,12 +673,13 @@ const sortieRulesByBattleId: Partial