diff --git a/src/game/data/battles.ts b/src/game/data/battles.ts index c1921a4..ef6a71c 100644 --- a/src/game/data/battles.ts +++ b/src/game/data/battles.ts @@ -1199,10 +1199,59 @@ export const ninthBattleScenario: BattleScenarioDefinition = { victoryConditionLabel: '조표 격파', defeatConditionLabel: '유비 퇴각', openingObjectiveLines: [ - '조표가 성문 수비병을 움직이고 여포군 기병이 밤길을 타고 접근합니다. 조표를 격파하면 성문을 다시 장악할 수 있습니다.', - '성벽 궁병은 높은 곳을 지키고, 여포군 기병은 길을 따라 빠르게 파고듭니다. 마을과 성문 지형을 이용해 전열을 끊어야 합니다.', - '18턴 이내 성문을 안정시키면 서주 내부 불안을 잠시나마 눌러 둘 수 있습니다.' + '조표가 성문 수비병을 흔들고, 바깥의 여포군 기병은 불빛을 신호로 성문을 향해 파고듭니다. 조표를 격파하면 야습의 지휘를 끊을 수 있습니다.', + '8전에서 정돈한 보급품은 여기서 바로 의미가 있습니다. 미축은 성내 보급을 묶고, 간옹은 성벽 궁병과 기병 돌입을 책략으로 늦추십시오.', + '성문 중심을 확보한 채 18턴 이내 승리하면 서주 성문 수비와 내부 민심을 잠시나마 붙잡을 수 있습니다.' ], + 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: 'guan-yu', role: 'front', reason: '성문 정면에서 조표 수비병과 여포군 기병 압박을 받아내는 핵심 전열입니다.' }, + { unitId: 'jian-yong', role: 'support', reason: '화계와 격려로 성벽 궁병, 기병 돌입, 조표 주변 전열을 늦출 수 있습니다.' }, + { unitId: 'mi-zhu', role: 'reserve', reason: '8전 보급품과 군량 주머니를 활용해 성문 장기전의 회복 흐름을 안정시킵니다.' }, + { unitId: 'zhang-fei', role: 'flank', reason: '남쪽 길로 파고드는 기병을 끊고 성문 측면을 빠르게 압박합니다.' }, + { unitId: 'liu-bei', role: 'support', reason: '서주 성문을 되찾는 명분의 중심이므로 후방 지휘와 생존을 함께 챙깁니다.' } + ], + recommendedClasses: [ + { label: '성문 전열', classKeys: ['infantry'], reason: '요새 지형 앞에서 보병과 장수를 받아낼 안정적인 전열이 필요합니다.' }, + { label: '책략 제압', classKeys: ['strategist'], reason: '궁병 고정 사격과 기병 돌입을 화계, 격려, 응급으로 늦추는 역할이 큽니다.' }, + { label: '보급 유지', classKeys: ['quartermaster'], reason: '8전에서 얻은 보급품을 실제 전열 유지로 연결하기 좋습니다.' }, + { label: '측면 차단', classKeys: ['spearman'], reason: '남쪽 길 기병과 성문 배반병을 빠르게 끊어내야 합니다.' } + ], + deploymentSlots: [ + { role: 'front', unitId: 'guan-yu', x: 4, y: 17, label: '성문 전열' }, + { role: 'flank', unitId: 'zhang-fei', x: 3, y: 18, label: '남쪽 차단' }, + { role: 'support', unitId: 'jian-yong', x: 5, y: 18, label: '책략 엄호' }, + { role: 'reserve', unitId: 'mi-zhu', x: 4, y: 19, label: '보급 수레' }, + { role: 'support', unitId: 'liu-bei', x: 3, y: 17, label: '후방 지휘' } + ], + note: '서주 성문 야습은 8전 보상과 새 합류 무장을 실제로 써 보는 첫 성문전입니다. 관우는 정면, 장비는 남쪽, 간옹과 미축은 뒤에서 책략과 보급을 맡는 전열이 기본입니다.' + }, map: ninthBattleMap, units: ninthBattleUnits, bonds: ninthBattleBonds, @@ -1230,7 +1279,9 @@ export const ninthBattleScenario: BattleScenarioDefinition = { kind: 'secure-terrain', label: '서주 성문 확보', rewardGold: 400, - terrain: 'fort' + terrain: 'fort', + targetTile: { x: 20, y: 10, radius: 4 }, + threatRadius: 2 }, { id: 'quick', @@ -1242,6 +1293,14 @@ export const ninthBattleScenario: BattleScenarioDefinition = { ], defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }], itemRewards: ['콩 3', '상처약 2', '탁주 1', '서주 성문 수비 +1'], + campaignReward: { + supplies: ['콩 3', '상처약 2', '탁주 1'], + equipment: ['찰갑 1'], + reputation: ['서주 성문 수비 +1'], + unlockBattleId: 'tenth-battle-xuzhou-breakout', + unlockLabel: '서주 탈출전 개방', + note: '성문은 지켰지만 내부 균열이 깊어져, 다음 전투는 성을 되찾기보다 포위망을 빠져나가는 흐름으로 이어집니다.' + }, victoryPages: ninthBattleVictoryPages, nextCampScene: 'CampScene' }; diff --git a/src/game/data/campaignFlow.ts b/src/game/data/campaignFlow.ts index 62631a2..105799a 100644 --- a/src/game/data/campaignFlow.ts +++ b/src/game/data/campaignFlow.ts @@ -292,7 +292,7 @@ const sortieFlows: Record = { afterBattleId: eighthBattleScenario.id, eyebrow: '다음 전장', title: ninthBattleScenario.title, - description: '소패 보급로를 지켰지만 서주 성문 안팎의 불안은 곧 터집니다. 보급을 정돈한 미축과 책략 보조를 익힌 간옹을 다음 방위 편성에 넣을지 판단해야 합니다.', + description: '소패 보급로를 지켰지만 서주 성문 안팎의 불안은 곧 터집니다. 8전에서 얻은 보급품과 미축의 보급 운용, 간옹의 책략 지원을 성문 방위 편성에 넣을지 판단해야 합니다.', rewardHint: `예상 보상: ${ninthBattleScenario.title} 개방`, nextBattleId: ninthBattleScenario.id, campaignStep: 'ninth-battle', @@ -302,7 +302,7 @@ const sortieFlows: Record = { afterBattleId: ninthBattleScenario.id, eyebrow: '다음 전장', title: tenthBattleScenario.title, - description: '장비의 성급함과 여포의 야심이 맞물려 서주는 무너집니다. 성을 되찾기보다 포위망을 뚫고 다음 길을 찾는 전투가 됩니다.', + description: '성문은 지켰지만 내부 균열은 더 깊어집니다. 장비의 성급함과 여포의 야심이 맞물려 서주는 무너지고, 다음 전투는 성을 되찾기보다 포위망을 뚫는 흐름으로 이어집니다.', rewardHint: `예상 보상: ${tenthBattleScenario.title} 개방`, nextBattleId: tenthBattleScenario.id, campaignStep: 'tenth-battle', diff --git a/src/game/data/scenario.ts b/src/game/data/scenario.ts index 9c3d224..6d109cb 100644 --- a/src/game/data/scenario.ts +++ b/src/game/data/scenario.ts @@ -932,7 +932,8 @@ export const ninthBattleIntroPages: StoryPage[] = [ bgm: 'battle-prep', chapter: '조표의 야습', background: 'story-xuzhou', - text: '밤이 깊자 조표가 일부 성문 수비병을 움직였다. 바깥의 여포군 기병은 불빛을 신호로 삼아 성문을 향해 몰려들었다.' + speaker: '미축', + text: '소패에서 돌린 보급 수레를 성문 안쪽으로 옮기겠습니다. 불빛이 세 번 흔들리면 바깥과 안쪽이 맞춘 신호일 수 있으니, 회복품은 뒤에 두고 전열은 성문 앞으로 붙이십시오.' }, { id: 'ninth-xuzhou-gate', @@ -940,7 +941,7 @@ export const ninthBattleIntroPages: StoryPage[] = [ chapter: '서주 성문 방위', background: 'story-xuzhou', speaker: '간옹', - text: '현덕, 이 싸움은 이겨도 상처가 남을 걸세. 하지만 성문이 오늘 밤 무너지면 내일의 선택도 사라진다네.' + text: '현덕, 조표의 수비병은 성문 중앙을 잡고 궁병은 성벽에 남아 있네. 관우는 정면, 장비는 남쪽 길, 나는 화계와 격려로 기병 돌입을 늦추겠네.' } ]; diff --git a/src/game/scenes/CampScene.ts b/src/game/scenes/CampScene.ts index bde93cd..efb07be 100644 --- a/src/game/scenes/CampScene.ts +++ b/src/game/scenes/CampScene.ts @@ -662,11 +662,13 @@ const sortieRulesByBattleId: Partial