diff --git a/scripts/verify-flow.mjs b/scripts/verify-flow.mjs index a3acd44..7c725c7 100644 --- a/scripts/verify-flow.mjs +++ b/scripts/verify-flow.mjs @@ -189,6 +189,93 @@ try { throw new Error(`Expected enemy threat markers from map menu: ${JSON.stringify(threatState)}`); } + const visibleEnemyScreen = await page.evaluate(() => { + const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); + const state = window.__HEROS_DEBUG__?.battle(); + const enemy = state?.units?.find((unit) => unit.faction === 'enemy' && unit.hp > 0); + + if (!scene || !enemy) { + throw new Error('Expected enemy and battle scene for enemy threat click test.'); + } + + scene.centerCameraOnTile(enemy.x, enemy.y); + return { + x: scene.tileCenterX(enemy.x), + y: scene.tileCenterY(enemy.y) + }; + }); + await page.waitForTimeout(120); + await page.mouse.click(visibleEnemyScreen.x, visibleEnemyScreen.y); + await page.waitForTimeout(180); + + const clickedEnemyThreatState = await page.evaluate(() => window.__HEROS_DEBUG__?.battle()); + if ( + !clickedEnemyThreatState?.enemyMoveMarkerCount || + clickedEnemyThreatState.enemyMoveMarkerCount <= 0 || + !clickedEnemyThreatState.threatMarkerCount || + clickedEnemyThreatState.threatMarkerCount <= 0 + ) { + throw new Error(`Expected clicked enemy movement and attack markers: ${JSON.stringify(clickedEnemyThreatState)}`); + } + + const combatMechanicsProbe = clickedEnemyThreatState.combatMechanicsProbe; + if ( + !combatMechanicsProbe || + combatMechanicsProbe.adjacentBondDamageBonus <= 0 || + combatMechanicsProbe.sameTargetBondDamageBonus <= 0 || + combatMechanicsProbe.farBondDamageBonus !== 0 || + combatMechanicsProbe.counterDamage >= combatMechanicsProbe.normalDamage + ) { + throw new Error(`Expected positional bond bonuses and reduced counter damage: ${JSON.stringify(combatMechanicsProbe)}`); + } + + const moveWaitTurnPromptState = await page.evaluate(() => { + const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); + const state = window.__HEROS_DEBUG__?.battle(); + const lastAlly = state?.units?.find((unit) => unit.id === 'zhang-fei'); + + if (!scene || !state || !lastAlly) { + throw new Error('Expected Zhang Fei and battle scene for move-wait turn prompt test.'); + } + + scene.hideTurnEndPrompt(); + scene.clearMarkers(); + scene.hideCommandMenu(); + scene.actedUnitIds = new Set(state.units.filter((unit) => unit.faction === 'ally' && unit.hp > 0 && unit.id !== lastAlly.id).map((unit) => unit.id)); + scene.phase = 'idle'; + scene.selectedUnit = undefined; + scene.pendingMove = undefined; + + const liveLastAlly = scene.debugUnitById(lastAlly.id); + if (!liveLastAlly) { + throw new Error('Expected live Zhang Fei unit for move-wait turn prompt test.'); + } + + scene.selectUnit(liveLastAlly); + scene.moveSelectedUnit(liveLastAlly.x, liveLastAlly.y); + scene.completeUnitAction(liveLastAlly, 'wait'); + return window.__HEROS_DEBUG__?.battle(); + }); + if (!moveWaitTurnPromptState?.turnPromptVisible || moveWaitTurnPromptState.phase !== 'idle') { + throw new Error(`Expected move-wait completion to show turn-end prompt: ${JSON.stringify(moveWaitTurnPromptState)}`); + } + + await page.evaluate(() => { + const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); + if (!scene) { + return; + } + scene.actedUnitIds.clear(); + scene.selectedUnit = undefined; + scene.pendingMove = undefined; + scene.targetingAction = undefined; + scene.selectedUsable = undefined; + scene.phase = 'idle'; + scene.clearMarkers(); + scene.hideCommandMenu(); + scene.hideTurnEndPrompt(); + }); + await page.mouse.click(260, 300, { button: 'right' }); await page.waitForTimeout(120); await page.mouse.click(182, 230); @@ -407,12 +494,15 @@ try { if ( secondBattleState.camera?.mapWidth !== 24 || secondBattleState.camera?.mapHeight !== 20 || + secondBattleState.mapTextureKey !== 'battle-map-second' || + !secondBattleState.mapTextureReady || + !secondBattleState.mapBackgroundReady || secondEnemies.length < 10 || !secondEnemyBehaviors.has('aggressive') || !secondEnemyBehaviors.has('guard') || !secondEnemyBehaviors.has('hold') ) { - throw new Error(`Expected expanded second battle map and mixed enemy AI: ${JSON.stringify(secondBattleState)}`); + throw new Error(`Expected loaded expanded second battle map and mixed enemy AI: ${JSON.stringify(secondBattleState)}`); } await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory')); @@ -1830,12 +1920,11 @@ try { !eighteenthEnemyBehaviors.has('hold') || !eighteenthEnemies.some((unit) => unit.id === 'bowang-leader-xiahou-dun') || !eighteenthAllies.some((unit) => unit.id === 'zhuge-liang') || - !treasureLabels.has('자웅일대검 공명') || (!treasureLabels.has('청룡언월도 무력 우위') && !treasureLabels.has('청룡언월도 대도')) || !treasureLabels.has('장팔사모 치명') || !treasureLabels.has('백우선 책략') ) { - throw new Error(`Expected eighteenth battle to use Bowang map, Xiahou Dun objective, mixed AI, deployed Zhuge Liang, and treasure equipment effects: ${JSON.stringify(eighteenthBattleState)}`); + throw new Error(`Expected eighteenth battle to use Bowang map, Xiahou Dun objective, mixed AI, deployed Zhuge Liang, and non-positional treasure equipment effects: ${JSON.stringify(eighteenthBattleState)}`); } await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory')); diff --git a/src/assets/images/story/06-yellow-turban-pursuit.png b/src/assets/images/story/06-yellow-turban-pursuit.png new file mode 100644 index 0000000..38932d4 Binary files /dev/null and b/src/assets/images/story/06-yellow-turban-pursuit.png differ diff --git a/src/assets/images/story/07-anti-dong-pass.png b/src/assets/images/story/07-anti-dong-pass.png new file mode 100644 index 0000000..e5543c2 Binary files /dev/null and b/src/assets/images/story/07-anti-dong-pass.png differ diff --git a/src/assets/images/story/08-xuzhou-handover.png b/src/assets/images/story/08-xuzhou-handover.png new file mode 100644 index 0000000..b1c14d2 Binary files /dev/null and b/src/assets/images/story/08-xuzhou-handover.png differ diff --git a/src/assets/images/story/09-wandering-road.png b/src/assets/images/story/09-wandering-road.png new file mode 100644 index 0000000..14f8611 Binary files /dev/null and b/src/assets/images/story/09-wandering-road.png differ diff --git a/src/assets/images/story/10-wolong-cottage.png b/src/assets/images/story/10-wolong-cottage.png new file mode 100644 index 0000000..64fcb0b Binary files /dev/null and b/src/assets/images/story/10-wolong-cottage.png differ diff --git a/src/assets/images/story/11-red-cliffs-fire.png b/src/assets/images/story/11-red-cliffs-fire.png new file mode 100644 index 0000000..3c5d18f Binary files /dev/null and b/src/assets/images/story/11-red-cliffs-fire.png differ diff --git a/src/assets/images/story/12-yizhou-mountain-pass.png b/src/assets/images/story/12-yizhou-mountain-pass.png new file mode 100644 index 0000000..6b20a67 Binary files /dev/null and b/src/assets/images/story/12-yizhou-mountain-pass.png differ diff --git a/src/assets/images/story/13-northern-expedition.png b/src/assets/images/story/13-northern-expedition.png new file mode 100644 index 0000000..31ccb6d Binary files /dev/null and b/src/assets/images/story/13-northern-expedition.png differ diff --git a/src/assets/images/story/14-nanzhong-pacification.png b/src/assets/images/story/14-nanzhong-pacification.png new file mode 100644 index 0000000..1d606c4 Binary files /dev/null and b/src/assets/images/story/14-nanzhong-pacification.png differ diff --git a/src/assets/images/story/15-yiling-baidi-aftermath.png b/src/assets/images/story/15-yiling-baidi-aftermath.png new file mode 100644 index 0000000..1116b0f Binary files /dev/null and b/src/assets/images/story/15-yiling-baidi-aftermath.png differ diff --git a/src/game/data/scenario.ts b/src/game/data/scenario.ts index 318823f..aef978a 100644 --- a/src/game/data/scenario.ts +++ b/src/game/data/scenario.ts @@ -146,14 +146,14 @@ export const firstBattleVictoryPages: StoryPage[] = [ id: 'first-victory-village', bgm: 'militia-theme', chapter: '첫 승리', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '황건적의 깃발이 쓰러지자, 숨어 있던 백성들이 하나둘 마을 어귀로 돌아왔다.' }, { id: 'first-victory-liu-bei', bgm: 'militia-theme', chapter: '첫 승리', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '오늘의 승리는 작다. 그러나 백성 한 사람을 지키는 일에서 천하를 바로잡는 뜻이 시작된다.' @@ -162,7 +162,7 @@ export const firstBattleVictoryPages: StoryPage[] = [ id: 'first-victory-guan-yu', bgm: 'militia-theme', chapter: '의용군의 이름', - background: 'story-three-heroes', + background: 'story-yellow-pursuit', speaker: '관우', portrait: 'guanYu', text: '형님의 뜻을 보고 사람들이 모일 것입니다. 다음 싸움은 오늘보다 더 큰 책임을 요구하겠지요.' @@ -171,7 +171,7 @@ export const firstBattleVictoryPages: StoryPage[] = [ id: 'first-victory-zhang-fei', bgm: 'militia-theme', chapter: '의용군의 이름', - background: 'story-militia', + background: 'story-yellow-pursuit', speaker: '장비', portrait: 'zhangFei', text: '하하! 그럼 더 크게 외쳐야겠소. 창을 들 자는 모여라! 우리 의용군은 물러서지 않는다!' @@ -180,7 +180,7 @@ export const firstBattleVictoryPages: StoryPage[] = [ id: 'first-victory-next', bgm: 'battle-prep', chapter: '다음 길', - background: 'story-sortie', + background: 'story-yellow-pursuit', text: '세 형제의 이름은 탁현 일대에 퍼지기 시작했다. 이제 더 넓은 전장과 더 많은 인연이 그들을 기다린다.' } ]; @@ -190,14 +190,14 @@ export const secondBattleIntroPages: StoryPage[] = [ id: 'second-pursuit-rumor', bgm: 'militia-theme', chapter: '잔당의 그림자', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '첫 승리의 기쁨이 채 가시기도 전에, 황건 잔당이 북쪽 길목의 마을을 습격하고 있다는 급보가 도착했다.' }, { id: 'second-liu-bei-command', bgm: 'battle-prep', chapter: '추격 명령', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '백성이 다시 칼끝에 몰렸다면 우리가 쉬어 갈 곳은 없다. 길을 따라 추격하되, 마을을 먼저 지켜야 한다.' @@ -206,7 +206,7 @@ export const secondBattleIntroPages: StoryPage[] = [ id: 'second-guan-yu-vow', bgm: 'battle-prep', chapter: '좁은 길목', - background: 'story-three-heroes', + background: 'story-yellow-pursuit', speaker: '관우', portrait: 'guanYu', text: '적은 숲과 강을 끼고 물러설 것입니다. 제가 앞길을 열겠습니다. 형님께서는 백성을 살피십시오.' @@ -215,7 +215,7 @@ export const secondBattleIntroPages: StoryPage[] = [ id: 'second-zhang-fei-charge', bgm: 'battle-prep', chapter: '의용군 출진', - background: 'story-sortie', + background: 'story-yellow-pursuit', speaker: '장비', portrait: 'zhangFei', text: '좋다! 숨어 있는 놈들도 모조리 끌어내 주마. 이번에는 도망칠 틈도 주지 않겠다!' @@ -227,14 +227,14 @@ export const secondBattleVictoryPages: StoryPage[] = [ id: 'second-victory-village', bgm: 'militia-theme', chapter: '마을의 안도', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '잔당의 불길은 꺼지고, 피난하던 백성들이 하나둘 마을로 돌아왔다. 의용군의 이름은 이제 길목의 장터마다 오르내렸다.' }, { id: 'second-victory-liu-bei', bgm: 'militia-theme', chapter: '다음 책임', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '우리가 이긴 것은 힘만으로 된 일이 아니다. 백성을 지키겠다는 뜻을 잊지 않는다면, 더 큰 전장도 견딜 수 있을 것이다.' @@ -243,7 +243,7 @@ export const secondBattleVictoryPages: StoryPage[] = [ id: 'second-victory-next', bgm: 'battle-prep', chapter: '넓어지는 전장', - background: 'story-sortie', + background: 'story-yellow-pursuit', text: '탁현 인근의 소란은 잦아들었지만, 황건의 난은 아직 천하 곳곳에서 타오르고 있었다. 세 형제의 길은 이제 더 멀리 이어진다.' } ]; @@ -253,14 +253,14 @@ export const thirdBattleIntroPages: StoryPage[] = [ id: 'third-guangzong-report', bgm: 'militia-theme', chapter: '광종의 급보', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '탁현 북쪽의 소란을 잠재우자, 장터에는 더 큰 소식이 밀려왔다. 광종 방면에서 황건 본대가 관군을 압박하고 있다는 전갈이었다.' }, { id: 'third-liu-bei-decision', bgm: 'battle-prep', chapter: '넓어지는 길', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '작은 마을만 지키고 물러선다면 난세는 끝나지 않는다. 광종으로 향하는 길을 열어, 더 많은 백성이 버틸 시간을 만들어야 한다.' @@ -269,7 +269,7 @@ export const thirdBattleIntroPages: StoryPage[] = [ id: 'third-guan-yu-bridge', bgm: 'battle-prep', chapter: '강가의 길목', - background: 'story-three-heroes', + background: 'story-yellow-pursuit', speaker: '관우', portrait: 'guanYu', text: '적 전령이 강가 요새를 거쳐 본대로 향한다면, 그 길을 끊어야 합니다. 좁은 다리와 숲길을 먼저 장악하겠습니다.' @@ -278,7 +278,7 @@ export const thirdBattleIntroPages: StoryPage[] = [ id: 'third-zhang-fei-vanguard', bgm: 'battle-prep', chapter: '전초전', - background: 'story-sortie', + background: 'story-yellow-pursuit', speaker: '장비', portrait: 'zhangFei', text: '전령이든 두령이든 내 앞길에 서면 다 똑같소! 형님, 명만 내리시오. 길목을 시원하게 열어 버리겠소!' @@ -290,14 +290,14 @@ export const thirdBattleVictoryPages: StoryPage[] = [ id: 'third-victory-road', bgm: 'militia-theme', chapter: '열린 길목', - background: 'story-sortie', + background: 'story-yellow-pursuit', text: '황건 전령의 깃발이 꺾이자 광종으로 향하는 길목에 잠시 숨통이 트였다. 흩어진 백성들은 의용군의 이름을 기억하기 시작했다.' }, { id: 'third-victory-liu-bei', bgm: 'militia-theme', chapter: '큰 싸움의 그림자', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '우리가 막은 것은 작은 전갈 하나일 뿐이다. 그러나 작은 길 하나가 열리면, 다음 전장에서도 백성을 구할 길이 생긴다.' @@ -306,7 +306,7 @@ export const thirdBattleVictoryPages: StoryPage[] = [ id: 'third-victory-next', bgm: 'battle-prep', chapter: '광종으로', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '세 형제는 병사를 추스르고 광종 방면으로 눈을 돌렸다. 황건의 큰 물결은 아직 꺾이지 않았다.' } ]; @@ -316,14 +316,14 @@ export const fourthBattleIntroPages: StoryPage[] = [ id: 'fourth-guangzong-camp', bgm: 'militia-theme', chapter: '광종 본영', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '전령의 길이 끊기자 황건 본대는 광종 들판에 진을 굳혔다. 노란 깃발이 겹겹이 서고, 장각의 이름이 병사들 사이에 낮게 울렸다.' }, { id: 'fourth-liu-bei-resolve', bgm: 'battle-prep', chapter: '의용군의 결의', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '장각을 치는 일은 한 사람을 꺾는 일이 아니다. 두려움에 몰린 백성들이 다시 길을 찾게 하는 일이다.' @@ -332,7 +332,7 @@ export const fourthBattleIntroPages: StoryPage[] = [ id: 'fourth-guan-yu-line', bgm: 'battle-prep', chapter: '본영 돌파', - background: 'story-three-heroes', + background: 'story-yellow-pursuit', speaker: '관우', portrait: 'guanYu', text: '적은 요새와 숲 사이에 궁병을 숨겼습니다. 전열을 흐트러뜨리지 않고 본영의 깃발까지 밀고 들어가야 합니다.' @@ -341,7 +341,7 @@ export const fourthBattleIntroPages: StoryPage[] = [ id: 'fourth-zhang-fei-roar', bgm: 'battle-prep', chapter: '황건적 토벌', - background: 'story-sortie', + background: 'story-yellow-pursuit', speaker: '장비', portrait: 'zhangFei', text: '좋소! 광종의 누런 깃발을 오늘 모두 뽑아 버립시다. 뒤돌아볼 틈 없이 밀고 들어가겠소!' @@ -353,14 +353,14 @@ export const fourthBattleVictoryPages: StoryPage[] = [ id: 'fourth-victory-yellow-flags-fall', bgm: 'militia-theme', chapter: '황건적 토벌', - background: 'story-militia', + background: 'story-yellow-pursuit', text: '광종의 들판에서 황건의 본영이 무너졌다. 피난민들은 오래 닫았던 문을 열고, 쓰러진 깃발 너머로 관군과 의용군을 바라보았다.' }, { id: 'fourth-victory-liu-bei', bgm: 'militia-theme', chapter: '이름이 퍼지다', - background: 'story-liu-bei', + background: 'story-yellow-pursuit', speaker: '유비', portrait: 'liuBei', text: '난은 잠시 가라앉았지만, 천하가 바로 선 것은 아니다. 오늘의 공이 교만이 되지 않도록 마음을 다잡자.' @@ -369,7 +369,7 @@ export const fourthBattleVictoryPages: StoryPage[] = [ id: 'fourth-victory-next-era', bgm: 'battle-prep', chapter: '새로운 혼란', - background: 'story-sortie', + background: 'story-yellow-pursuit', text: '황건의 불길이 잦아들 무렵, 조정 안에서는 또 다른 그림자가 자라났다. 세 형제의 길은 이제 반동탁의 흐름으로 이어진다.' } ]; @@ -379,14 +379,14 @@ export const fifthBattleIntroPages: StoryPage[] = [ id: 'fifth-coalition-rumor', bgm: 'militia-theme', chapter: '반동탁의 격문', - background: 'story-militia', + background: 'story-anti-dong', text: '황건의 불길이 잦아들자 조정에는 또 다른 폭풍이 일었다. 동탁이 낙양을 장악했다는 소식과 함께, 각지의 제후들이 반동탁의 격문에 응하기 시작했다.' }, { id: 'fifth-liu-bei-choice', bgm: 'battle-prep', chapter: '새로운 대의', - background: 'story-liu-bei', + background: 'story-anti-dong', speaker: '유비', portrait: 'liuBei', text: '백성을 괴롭히는 난을 막았다 하나, 조정이 어지러우면 천하는 다시 피를 흘린다. 우리는 더 큰 흐름 속으로 들어가야 한다.' @@ -395,7 +395,7 @@ export const fifthBattleIntroPages: StoryPage[] = [ id: 'fifth-gongsun-zan', bgm: 'battle-prep', chapter: '공손찬의 진영', - background: 'story-three-heroes', + background: 'story-anti-dong', speaker: '관우', portrait: 'guanYu', text: '공손찬의 군영에 합류하면 연합군의 움직임을 가까이서 볼 수 있습니다. 그러나 동탁군도 사수관 앞길을 막고 있습니다.' @@ -404,7 +404,7 @@ export const fifthBattleIntroPages: StoryPage[] = [ id: 'fifth-sishui-sortie', bgm: 'battle-prep', chapter: '사수관 전초전', - background: 'story-sortie', + background: 'story-anti-dong', speaker: '장비', portrait: 'zhangFei', text: '동탁군이든 황건적이든 백성을 짓밟는 놈들은 똑같소. 사수관 앞길부터 뚫어 봅시다!' @@ -416,14 +416,14 @@ export const fifthBattleVictoryPages: StoryPage[] = [ id: 'fifth-victory-sishui', bgm: 'militia-theme', chapter: '사수관의 문턱', - background: 'story-sortie', + background: 'story-anti-dong', text: '동탁군의 전초 부대가 물러서자 연합군 진영에 세 형제의 이름이 다시 한 번 전해졌다.' }, { id: 'fifth-victory-next', bgm: 'battle-prep', chapter: '공손찬 의탁', - background: 'story-militia', + background: 'story-anti-dong', text: '사수관 앞 전초전은 끝났지만, 반동탁의 싸움은 이제 막 시작되었다. 유비는 공손찬의 군영에서 다음 기회를 기다린다.' } ]; @@ -433,14 +433,14 @@ export const sixthBattleIntroPages: StoryPage[] = [ id: 'sixth-gongsun-zan-order', bgm: 'militia-theme', chapter: '공손찬의 명', - background: 'story-three-heroes', + background: 'story-anti-dong', text: '사수관 전초전 뒤, 유비군은 공손찬의 군영에 머물며 북방의 정세를 살폈다. 원소군의 별동대가 계교로 향하는 보급로를 위협하자, 공손찬은 세 형제에게 길목을 맡겼다.' }, { id: 'sixth-liu-bei-service', bgm: 'battle-prep', chapter: '의탁의 무게', - background: 'story-liu-bei', + background: 'story-anti-dong', speaker: '유비', portrait: 'liuBei', text: '남의 깃발 아래에 서더라도 백성을 지키는 뜻은 변하지 않는다. 공손찬 장군의 군영에 머무는 동안에도 우리의 길을 분명히 하자.' @@ -449,7 +449,7 @@ export const sixthBattleIntroPages: StoryPage[] = [ id: 'sixth-guan-yu-road', bgm: 'battle-prep', chapter: '계교 원군로', - background: 'story-militia', + background: 'story-anti-dong', speaker: '관우', portrait: 'guanYu', text: '계교로 향하는 길은 강과 숲이 얽혀 있습니다. 원소군의 궁병과 기병을 나누어 상대해야 길을 열 수 있습니다.' @@ -458,7 +458,7 @@ export const sixthBattleIntroPages: StoryPage[] = [ id: 'sixth-zhang-fei-sortie', bgm: 'battle-prep', chapter: '북방의 먼지', - background: 'story-sortie', + background: 'story-anti-dong', speaker: '장비', portrait: 'zhangFei', text: '원소군이든 누구든 길을 막는 놈은 비켜서게 만들면 됩니다. 형님, 이번엔 제가 먼저 먼지를 일으키겠습니다!' @@ -470,14 +470,14 @@ export const sixthBattleVictoryPages: StoryPage[] = [ id: 'sixth-victory-jieqiao', bgm: 'militia-theme', chapter: '계교의 길', - background: 'story-militia', + background: 'story-anti-dong', text: '계교로 향하는 보급로가 열리자 공손찬의 군영에도 한숨 돌릴 여유가 생겼다. 그러나 북방의 전공은 세 형제의 마음을 오래 붙잡아 두지 못했다.' }, { id: 'sixth-xuzhou-envoy', bgm: 'battle-prep', chapter: '서주의 사신', - background: 'story-liu-bei', + background: 'story-anti-dong', speaker: '유비', portrait: 'liuBei', text: '도겸 공이 서주에서 원군을 청한다면, 백성의 고통을 외면할 수 없소. 공손찬 장군께 허락을 구하고 서주로 향할 준비를 하자.' @@ -489,14 +489,14 @@ export const seventhBattleIntroPages: StoryPage[] = [ id: 'seventh-xuzhou-envoy-arrives', bgm: 'militia-theme', chapter: '도겸의 사신', - background: 'story-militia', + background: 'story-xuzhou', text: '서주의 도겸이 조조군의 압박을 견디지 못하고 원군을 청했다. 공손찬의 허락을 받은 유비는 세 형제와 의용군을 이끌고 남쪽 길로 향했다.' }, { id: 'seventh-liu-bei-xuzhou', bgm: 'battle-prep', chapter: '서주로 가는 길', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '서주 백성이 위태롭다는데 어찌 머뭇거리겠는가. 도겸 공을 돕고, 백성들이 피난길에서 더 쓰러지지 않게 길을 열자.' @@ -505,7 +505,7 @@ export const seventhBattleIntroPages: StoryPage[] = [ id: 'seventh-guan-yu-field', bgm: 'battle-prep', chapter: '조조군 선봉', - background: 'story-three-heroes', + background: 'story-xuzhou', speaker: '관우', portrait: 'guanYu', text: '조조군 선봉은 길과 촌락을 함께 누르고 있습니다. 기병은 길을 따라 빠르게 내려오고, 궁병은 강가와 마을 뒤에서 전열을 끊을 것입니다.' @@ -514,7 +514,7 @@ export const seventhBattleIntroPages: StoryPage[] = [ id: 'seventh-zhang-fei-charge', bgm: 'battle-prep', chapter: '서주 구원전', - background: 'story-sortie', + background: 'story-xuzhou', speaker: '장비', portrait: 'zhangFei', text: '서주 백성을 울리는 놈들이라면 이름이 누구든 상관없습니다. 형님, 조조군 선봉부터 박살내고 길을 열어 봅시다!' @@ -526,14 +526,14 @@ export const seventhBattleVictoryPages: StoryPage[] = [ id: 'seventh-victory-xuzhou-road', bgm: 'militia-theme', chapter: '서주의 문', - background: 'story-militia', + background: 'story-xuzhou', text: '조조군 선봉이 물러서자 서주 성문 앞 피난민들의 숨통이 트였다. 도겸은 유비의 군기를 맞이하며 깊이 고개를 숙였다.' }, { id: 'seventh-tao-qian-entrusts', bgm: 'battle-prep', chapter: '도겸의 부탁', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '서주를 맡아 달라는 도겸 공의 청은 너무 무거운 일이다. 그러나 백성이 의지할 곳이 없다면, 외면하는 것도 의가 아니다.' @@ -545,14 +545,14 @@ export const eighthBattleIntroPages: StoryPage[] = [ id: 'eighth-xuzhou-handover', bgm: 'militia-theme', chapter: '서주의 새 군영', - background: 'story-militia', + background: 'story-xuzhou', text: '도겸은 병든 몸을 일으켜 서주의 장부와 군량 창고를 유비에게 넘겼다. 간옹과 미축은 백성의 청원과 보급로를 정리하며 새 군영의 기초를 세웠다.' }, { id: 'eighth-lu-bu-shadow', bgm: 'battle-prep', chapter: '여포의 그림자', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '여포가 떠돌고 있다는 소식은 가볍지 않다. 그 이름 하나만으로도 여러 군세가 흔들린다. 그러나 지금은 서주의 길과 백성을 먼저 지켜야 한다.' @@ -561,7 +561,7 @@ export const eighthBattleIntroPages: StoryPage[] = [ id: 'eighth-xiaopei-road', bgm: 'battle-prep', chapter: '소패 보급로', - background: 'story-sortie', + background: 'story-xuzhou', speaker: '미축', text: '소패로 이어지는 창고 길목이 습격받고 있습니다. 군량이 끊기면 서주를 안정시킬 수 없습니다. 보급로와 마을을 동시에 지켜야 합니다.' }, @@ -569,7 +569,7 @@ export const eighthBattleIntroPages: StoryPage[] = [ id: 'eighth-sortie-choice', bgm: 'battle-prep', chapter: '첫 방위전', - background: 'story-three-heroes', + background: 'story-xuzhou', speaker: '간옹', text: '현덕, 이제 함께 갈 장수를 고르는 일도 전술이 되었네. 칼이 필요한 곳과 말이 필요한 곳, 그리고 말보다 장부가 필요한 곳을 구분해야 하네.' } @@ -580,14 +580,14 @@ export const eighthBattleVictoryPages: StoryPage[] = [ id: 'eighth-victory-supply-road', bgm: 'militia-theme', chapter: '지켜낸 보급로', - background: 'story-militia', + background: 'story-xuzhou', text: '소패의 보급로가 다시 열리자 서주의 창고와 마을은 겨우 숨을 돌렸다. 새로 합류한 장수들은 각자의 방식으로 유비군의 빈틈을 메웠다.' }, { id: 'eighth-lu-bu-arrival', bgm: 'battle-prep', chapter: '뜻밖의 손님', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '전투가 끝난 뒤, 여포가 몸을 의탁할 곳을 구한다는 전갈이 왔다. 그를 받아들이는 일은 의로울 수 있으나, 서주에 또 다른 불씨를 들이는 일이기도 했다.' @@ -599,7 +599,7 @@ export const ninthBattleIntroPages: StoryPage[] = [ id: 'ninth-lu-bu-refuge', bgm: 'militia-theme', chapter: '여포의 의탁', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '여포가 몸을 의탁하겠다 청했다. 난세에 갈 곳 없는 이를 내치는 것은 쉽지 않으나, 서주 백성의 불안을 모른 척할 수도 없다.' @@ -608,7 +608,7 @@ export const ninthBattleIntroPages: StoryPage[] = [ id: 'ninth-zhang-fei-suspicion', bgm: 'battle-prep', chapter: '성문 안의 불씨', - background: 'story-three-heroes', + background: 'story-xuzhou', speaker: '장비', portrait: 'zhangFei', text: '여포 같은 자를 성 안에 들이면 반드시 화근이 됩니다. 도겸의 옛 무장들까지 술렁이니, 성문부터 단단히 지켜야 합니다.' @@ -617,14 +617,14 @@ export const ninthBattleIntroPages: StoryPage[] = [ id: 'ninth-cao-bao-mutiny', bgm: 'battle-prep', chapter: '조표의 야습', - background: 'story-sortie', + background: 'story-xuzhou', text: '밤이 깊자 조표가 일부 성문 수비병을 움직였다. 바깥의 여포군 기병은 불빛을 신호로 삼아 성문을 향해 몰려들었다.' }, { id: 'ninth-xuzhou-gate', bgm: 'battle-prep', chapter: '서주 성문 방위', - background: 'story-militia', + background: 'story-xuzhou', speaker: '간옹', text: '현덕, 이 싸움은 이겨도 상처가 남을 걸세. 하지만 성문이 오늘 밤 무너지면 내일의 선택도 사라진다네.' } @@ -635,14 +635,14 @@ export const ninthBattleVictoryPages: StoryPage[] = [ id: 'ninth-victory-gate-held', bgm: 'militia-theme', chapter: '지켜낸 밤', - background: 'story-militia', + background: 'story-xuzhou', text: '조표의 야습은 물러났고 성문은 다시 닫혔다. 그러나 성 안의 의심과 두려움은 이미 선명한 금이 되어 남았다.' }, { id: 'ninth-lu-bu-pretext', bgm: 'battle-prep', chapter: '더 깊어진 그림자', - background: 'story-liu-bei', + background: 'story-xuzhou', speaker: '유비', portrait: 'liuBei', text: '여포는 서주의 혼란을 핑계 삼아 더 깊이 발을 들이려 했다. 오늘 밤 성문은 지켰으나, 서주를 잃을 싸움은 이제 시작되고 있었다.' @@ -654,7 +654,7 @@ export const tenthBattleIntroPages: StoryPage[] = [ id: 'tenth-zhang-fei-fault', bgm: 'story-dark', chapter: '술잔이 부른 균열', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '장비', portrait: 'zhangFei', text: '조표의 잔당을 다그치던 장비는 분노를 이기지 못했다. 말 한마디, 술 한잔, 그리고 성 안의 오래된 원한이 한밤중에 다시 타올랐다.' @@ -663,14 +663,14 @@ export const tenthBattleIntroPages: StoryPage[] = [ id: 'tenth-lu-bu-takes-xuzhou', bgm: 'story-dark', chapter: '빼앗긴 서주', - background: 'story-militia', + background: 'story-wandering', text: '여포는 성문이 흔들린 틈을 놓치지 않았다. 서주 곳곳의 수비대가 갈라졌고, 유비가 돌아왔을 때 성루의 깃발은 이미 바뀌어 있었다.' }, { id: 'tenth-brothers-regroup', bgm: 'militia-theme', chapter: '무너진 성 앞에서', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '관우', portrait: 'guanYu', text: '형님, 지금 성을 되찾으려 들면 백성과 군졸을 모두 잃습니다. 익덕을 꾸짖는 일은 살아나간 뒤에 해도 늦지 않습니다.' @@ -679,7 +679,7 @@ export const tenthBattleIntroPages: StoryPage[] = [ id: 'tenth-xuzhou-escape', bgm: 'battle-prep', chapter: '서주 탈출', - background: 'story-sortie', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '서주는 오늘 내 손에서 떠났다. 그러나 백성과 형제와 뜻까지 잃을 수는 없다. 포위망을 뚫고 다음 길을 찾자.' @@ -691,14 +691,14 @@ export const tenthBattleVictoryPages: StoryPage[] = [ id: 'tenth-victory-breakout', bgm: 'militia-theme', chapter: '잃고도 남은 것', - background: 'story-militia', + background: 'story-wandering', text: '유비군은 여포군 선봉을 뚫고 서주 외곽으로 물러났다. 성은 빼앗겼으나, 세 형제와 새로 모인 장수들의 전열은 아직 흩어지지 않았다.' }, { id: 'tenth-cao-cao-shadow', bgm: 'story-dark', chapter: '허도로 향하는 그림자', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '간옹', text: '현덕, 이제 서주 안에서 버티는 길은 막혔네. 조조의 휘하로 들어가는 일은 마음에 걸리지만, 살아남아 다시 뜻을 세우려면 그 길을 지나야 할 걸세.' } @@ -709,14 +709,14 @@ export const eleventhBattleIntroPages: StoryPage[] = [ id: 'eleventh-arrive-cao-cao-camp', bgm: 'story-dark', chapter: '조조의 장막', - background: 'story-liu-bei', + background: 'story-wandering', text: '서주를 잃은 유비군은 허도로 향했다. 조조는 웃으며 맞이했지만, 그 웃음 뒤에는 사람을 재는 날카로운 눈빛이 숨어 있었다.' }, { id: 'eleventh-cao-cao-test', bgm: 'militia-theme', chapter: '의탁의 대가', - background: 'story-militia', + background: 'story-wandering', speaker: '간옹', text: '현덕, 조조는 우리에게 머물 곳을 주겠지만 공짜로 주지는 않을 걸세. 허도 입성로에 남은 원술 잔군을 치라는 명은 환대이자 시험이지.' }, @@ -724,7 +724,7 @@ export const eleventhBattleIntroPages: StoryPage[] = [ id: 'eleventh-brothers-under-watch', bgm: 'story-dark', chapter: '감시 속의 출진', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '관우', portrait: 'guanYu', text: '형님, 조조의 깃발 아래 싸우더라도 우리의 칼끝은 백성을 향하지 않습니다. 명을 따르되 뜻은 잃지 않겠습니다.' @@ -733,7 +733,7 @@ export const eleventhBattleIntroPages: StoryPage[] = [ id: 'eleventh-xudu-road-sortie', bgm: 'battle-prep', chapter: '허도 입성로', - background: 'story-sortie', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '지금은 몸을 낮추어야 할 때다. 그러나 낮춘 몸 안에서도 마음까지 굽힐 수는 없다. 길을 열고, 살아남아 다시 일어서자.' @@ -745,14 +745,14 @@ export const eleventhBattleVictoryPages: StoryPage[] = [ id: 'eleventh-victory-road-cleared', bgm: 'militia-theme', chapter: '열린 허도 길', - background: 'story-militia', + background: 'story-wandering', text: '원술 잔군은 물러났고 허도로 향하는 길이 열렸다. 조조군의 감시병들은 유비군의 전열과 군율을 조용히 기록했다.' }, { id: 'eleventh-cao-cao-accepts', bgm: 'story-dark', chapter: '웃음 속의 칼', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '조조의 장막은 비바람을 피하게 해 주지만, 그 안의 공기는 오래 머물수록 무겁다. 나는 살아남기 위해 들어가되, 나올 날을 잊지 않겠다.' @@ -764,14 +764,14 @@ export const twelfthBattleIntroPages: StoryPage[] = [ id: 'twelfth-cao-cao-order', bgm: 'story-dark', chapter: '조조의 명', - background: 'story-liu-bei', + background: 'story-wandering', text: '허도에 머문 지 오래지 않아 조조는 유비군을 하비 포위전에 부른다. 여포를 치는 명령은 서주를 잃은 한을 풀 기회이자, 조조의 칼끝이 어디를 향하는지 가늠하는 시험이었다.' }, { id: 'twelfth-xiapi-shadow', bgm: 'militia-theme', chapter: '하비의 물길', - background: 'story-militia', + background: 'story-wandering', speaker: '미축', text: '하비 외곽은 강과 진흙이 얽혀 있습니다. 보급로를 끊고 둑길을 잡지 못하면, 여포군 기병이 포위망의 빈틈을 찢고 나올 것입니다.' }, @@ -779,7 +779,7 @@ export const twelfthBattleIntroPages: StoryPage[] = [ id: 'twelfth-brothers-before-lubu', bgm: 'story-dark', chapter: '다시 마주한 여포', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '장비', portrait: 'zhangFei', text: '형님, 이번엔 여포의 이름만 들어도 창끝이 뜨겁습니다. 허나 서두르지 않겠습니다. 먼저 포위망을 조이고, 놈의 날뛰는 길을 끊겠습니다.' @@ -788,7 +788,7 @@ export const twelfthBattleIntroPages: StoryPage[] = [ id: 'twelfth-xiapi-sortie', bgm: 'battle-prep', chapter: '하비 외곽전', - background: 'story-sortie', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '여포를 치는 싸움이 조조의 명이라 해도, 서주 백성이 다시 짓밟히지 않게 하는 일은 우리의 뜻이다. 물길을 잡고 포위망을 열어라.' @@ -800,14 +800,14 @@ export const twelfthBattleVictoryPages: StoryPage[] = [ id: 'twelfth-victory-outer-camp', bgm: 'militia-theme', chapter: '무너진 외곽 진영', - background: 'story-militia', + background: 'story-wandering', text: '유비군은 하비 외곽의 둑길과 보급 진영을 장악했다. 여포군 선봉은 성 안으로 물러났고, 조조군은 포위망을 한층 더 좁혔다.' }, { id: 'twelfth-cao-cao-watches', bgm: 'story-dark', chapter: '칭찬과 감시', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '간옹', text: '현덕, 조조는 오늘의 공을 칭찬하겠지만 동시에 더 깊이 살필 걸세. 여포를 치는 동안에도, 우리가 조조의 손안에만 있지 않다는 것을 잊지 말아야 하네.' } @@ -818,14 +818,14 @@ export const thirteenthBattleIntroPages: StoryPage[] = [ id: 'thirteenth-cao-cao-final-order', bgm: 'story-dark', chapter: '하비 결전의 명', - background: 'story-liu-bei', + background: 'story-wandering', text: '하비 외곽이 무너지자 조조는 마지막 총공세를 명했다. 성 안의 여포는 아직 강했고, 진궁은 남은 성루와 수문을 엮어 마지막 반격을 준비하고 있었다.' }, { id: 'thirteenth-brothers-before-final', bgm: 'militia-theme', chapter: '여포를 앞두고', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '관우', portrait: 'guanYu', text: '형님, 여포는 용맹하나 믿음이 얕습니다. 다만 그 칼끝이 어지러운 세상의 그림자라면, 오늘 싸움 뒤에 우리 길도 더 뚜렷해질 것입니다.' @@ -834,7 +834,7 @@ export const thirteenthBattleIntroPages: StoryPage[] = [ id: 'thirteenth-liu-bei-resolve', bgm: 'story-dark', chapter: '조조의 그늘', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '조조의 명으로 싸우되, 백성의 원망을 덜고 난세의 사슬을 끊기 위해 싸운다. 여포의 끝을 보더라도 우리의 뜻까지 맡기지는 말자.' @@ -843,7 +843,7 @@ export const thirteenthBattleIntroPages: StoryPage[] = [ id: 'thirteenth-xiapi-final-sortie', bgm: 'battle-prep', chapter: '하비 결전', - background: 'story-sortie', + background: 'story-wandering', speaker: '장비', portrait: 'zhangFei', text: '좋습니다, 형님. 이번엔 성문을 열고 여포의 깃발까지 밀고 들어가겠습니다. 누가 함께 나설지 정해 주십시오. 대기한 자도 다음 싸움을 위해 힘을 아껴야 합니다.' @@ -855,14 +855,14 @@ export const thirteenthBattleVictoryPages: StoryPage[] = [ id: 'thirteenth-victory-lubu-falls', bgm: 'militia-theme', chapter: '무너진 여포', - background: 'story-militia', + background: 'story-wandering', text: '하비 성내의 마지막 저항이 꺾이고 여포의 깃발이 내려갔다. 뛰어난 무용도 믿음을 잃으면 성 하나를 지키지 못한다는 소문이 병사들 사이에 퍼졌다.' }, { id: 'thirteenth-cao-cao-weighs-liu-bei', bgm: 'story-dark', chapter: '칭찬과 경계', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '간옹', text: '조조는 형님의 말을 들은 뒤 오래 웃지 않았네. 여포의 운명은 끝났지만, 이제부터는 조조가 우리를 어디까지 품고 어디서부터 경계할지 살펴야 하네.' }, @@ -870,7 +870,7 @@ export const thirteenthBattleVictoryPages: StoryPage[] = [ id: 'thirteenth-road-to-cao-break', bgm: 'story-dark', chapter: '떠날 때를 헤아리다', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '오늘 싸움으로 빚도 공도 쌓였다. 그러나 의로 시작한 길을 남의 장부 속 숫자로 끝낼 수는 없다. 떠날 때가 오면 망설이지 않도록 마음을 단단히 하자.' @@ -882,7 +882,7 @@ export const fourteenthBattleIntroPages: StoryPage[] = [ id: 'fourteenth-secret-edict-shadow', bgm: 'story-dark', chapter: '조조의 그늘', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '하비의 공은 컸지만 조조의 시선은 더욱 무거워졌다. 허도의 잔치와 칭찬 사이에서, 유비는 황실의 명분과 자신의 뜻이 더는 같은 장막 안에 머물 수 없음을 느꼈다.' @@ -891,7 +891,7 @@ export const fourteenthBattleIntroPages: StoryPage[] = [ id: 'fourteenth-sun-qian-arrives', bgm: 'militia-theme', chapter: '새로 온 책사', - background: 'story-militia', + background: 'story-wandering', speaker: '손건', text: '현덕공, 저는 손건이라 합니다. 서주와 허도 사이의 길을 오가며 민심과 조조군의 움직임을 살펴 왔습니다. 이제 떠날 때를 고르신다면, 그 길의 말과 문서를 제가 맡겠습니다.' }, @@ -899,7 +899,7 @@ export const fourteenthBattleIntroPages: StoryPage[] = [ id: 'fourteenth-brothers-break-from-cao', bgm: 'battle-prep', chapter: '서주로 나아가다', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '장비', portrait: 'zhangFei', text: '조조의 눈치를 보느라 칼집만 만지고 있을 순 없습니다. 형님, 서주 길목의 감시대를 뚫고 백성들이 우리 깃발을 다시 볼 수 있게 합시다.' @@ -908,7 +908,7 @@ export const fourteenthBattleIntroPages: StoryPage[] = [ id: 'fourteenth-xuzhou-gate-sortie', bgm: 'battle-prep', chapter: '서주 재기', - background: 'story-sortie', + background: 'story-wandering', speaker: '간옹', text: '차주는 조조의 명을 앞세워 성문과 역참을 잡고 있습니다. 길목을 끊고 차주를 격파하면, 조조의 장막 밖으로 나갈 첫 명분을 세울 수 있습니다.' } @@ -919,14 +919,14 @@ export const fourteenthBattleVictoryPages: StoryPage[] = [ id: 'fourteenth-victory-xuzhou-gate-opens', bgm: 'militia-theme', chapter: '다시 열린 서주 길', - background: 'story-militia', + background: 'story-wandering', text: '차주의 감시대가 흩어지자 서주로 향하는 관문이 열렸다. 백성들은 유비군의 깃발을 알아보았고, 조조의 이름보다 현덕의 이름을 먼저 속삭이기 시작했다.' }, { id: 'fourteenth-cao-cao-anger', bgm: 'story-dark', chapter: '돌이킬 수 없는 길', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '손건', text: '이 승리는 조조에게는 반역의 조짐으로 보일 것입니다. 허도로 돌아갈 길은 사실상 끊겼고, 다음으로 기대야 할 큰 세력은 원소입니다.' }, @@ -934,7 +934,7 @@ export const fourteenthBattleVictoryPages: StoryPage[] = [ id: 'fourteenth-road-to-yuan-shao', bgm: 'battle-prep', chapter: '원소를 향하여', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '조조를 떠난 이상, 더 큰 파도 속으로 들어가야 한다. 원소의 진영은 안전한 항구가 아니라 또 다른 시험일 것이다. 그래도 뜻을 이어 가려면 그 길을 지나야 한다.' @@ -946,7 +946,7 @@ export const fifteenthBattleIntroPages: StoryPage[] = [ id: 'fifteenth-yuan-envoy-rumor', bgm: 'story-dark', chapter: '북쪽의 초대', - background: 'story-militia', + background: 'story-wandering', speaker: '손건', text: '원소 진영에서 사자가 내려왔습니다. 조조를 떠난 주공을 받아들일 뜻은 있으나, 북상로 곳곳에는 조조군 추격대가 깔려 있습니다.' }, @@ -954,7 +954,7 @@ export const fifteenthBattleIntroPages: StoryPage[] = [ id: 'fifteenth-liu-bei-under-yuan-shadow', bgm: 'battle-prep', chapter: '원소 의탁', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '원소의 깃발 아래로 들어가는 일은 뜻을 접는 일이 아니다. 지금은 큰 세력의 틈에서 백성을 지킬 시간을 얻어야 한다.' @@ -963,7 +963,7 @@ export const fifteenthBattleIntroPages: StoryPage[] = [ id: 'fifteenth-guan-yu-pursuit-road', bgm: 'battle-prep', chapter: '추격로', - background: 'story-three-heroes', + background: 'story-wandering', speaker: '관우', portrait: 'guanYu', text: '추격대가 강가와 고갯길을 나누어 막고 있습니다. 채양의 군세를 물리치고 접선지를 확보해야 원소 진영과 이어질 수 있습니다.' @@ -972,7 +972,7 @@ export const fifteenthBattleIntroPages: StoryPage[] = [ id: 'fifteenth-yuan-road-sortie', bgm: 'battle-prep', chapter: '북상 전투', - background: 'story-sortie', + background: 'story-wandering', speaker: '장비', portrait: 'zhangFei', text: '쫓아오는 놈들이 조조의 명이라 떠들어도 결국 길을 막는 적일 뿐입니다. 형님, 이번엔 북쪽 길을 시원하게 열어 봅시다!' @@ -984,14 +984,14 @@ export const fifteenthBattleVictoryPages: StoryPage[] = [ id: 'fifteenth-victory-pursuit-breaks', bgm: 'militia-theme', chapter: '추격을 끊다', - background: 'story-sortie', + background: 'story-wandering', text: '채양의 추격대가 흩어지자 북상로의 먼지가 잠시 가라앉았다. 유비군은 원소의 사자가 기다리는 접선지에 닿을 수 있었다.' }, { id: 'fifteenth-yuan-camp-opens', bgm: 'story-dark', chapter: '원소의 장막', - background: 'story-militia', + background: 'story-wandering', speaker: '간옹', text: '원소의 진영은 넓고 군세는 크지만, 그만큼 말과 눈도 많습니다. 몸을 맡기되 마음까지 맡기지는 말아야 하겠지요.' }, @@ -999,7 +999,7 @@ export const fifteenthBattleVictoryPages: StoryPage[] = [ id: 'fifteenth-road-to-liu-biao', bgm: 'battle-prep', chapter: '다음 의탁의 그림자', - background: 'story-liu-bei', + background: 'story-wandering', speaker: '유비', portrait: 'liuBei', text: '큰 깃발 아래에서도 우리의 뜻은 작아져서는 안 된다. 원소의 군영에서 기회를 살피고, 다시 백성을 지킬 길을 찾아야 한다.' @@ -1011,7 +1011,7 @@ export const sixteenthBattleIntroPages: StoryPage[] = [ id: 'sixteenth-yuan-camp-shifts', bgm: 'story-dark', chapter: '원소 진영의 그림자', - background: 'story-militia', + background: 'story-wolong', speaker: '간옹', text: '원소의 군막은 넓지만, 그 안에서는 말 한마디가 칼보다 빠르게 옮겨집니다. 조조를 떠난 유비군을 오래 품으려는 자도, 조조에게 빌미를 주지 않으려는 자도 모두 눈치를 보고 있습니다.' }, @@ -1019,7 +1019,7 @@ export const sixteenthBattleIntroPages: StoryPage[] = [ id: 'sixteenth-zhao-yun-returns', bgm: 'militia-theme', chapter: '백마의 재회', - background: 'story-three-heroes', + background: 'story-wolong', speaker: '조운', text: '공손찬 장군의 군세가 흩어진 뒤에도 주공의 의리를 잊지 않았습니다. 오늘부터 이 조자룡의 창은 백성을 버리지 않는 군주를 위해 달리겠습니다.' }, @@ -1027,7 +1027,7 @@ export const sixteenthBattleIntroPages: StoryPage[] = [ id: 'sixteenth-liu-biao-road', bgm: 'battle-prep', chapter: '형주로 가는 길', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '유비', portrait: 'liuBei', text: '원소의 장막 아래 머무는 것은 잠시 몸을 숨기는 일일 뿐, 뜻을 세울 땅은 되지 못한다. 형주의 유표에게 의탁해 백성을 거둘 길을 다시 찾아야 하오.' @@ -1036,7 +1036,7 @@ export const sixteenthBattleIntroPages: StoryPage[] = [ id: 'sixteenth-jingzhou-road-sortie', bgm: 'battle-prep', chapter: '형주 의탁로', - background: 'story-sortie', + background: 'story-wolong', speaker: '장비', portrait: 'zhangFei', text: '형님, 조조군 추격대가 또 길목을 막고 있소. 이번에는 조운도 합류했으니, 데려갈 장수를 잘 골라 한 번에 길을 열어 봅시다.' @@ -1048,14 +1048,14 @@ export const sixteenthBattleVictoryPages: StoryPage[] = [ id: 'sixteenth-victory-jingzhou-gate', bgm: 'militia-theme', chapter: '형주 관문', - background: 'story-sortie', + background: 'story-wolong', text: '조인의 추격대가 물러서자 형주로 향하는 관문이 열렸다. 유비군은 원소 진영의 무거운 시선에서 벗어나, 다시 스스로 길을 고를 수 있는 숨을 얻었다.' }, { id: 'sixteenth-liu-biao-welcome', bgm: 'story-dark', chapter: '유표의 객장', - background: 'story-militia', + background: 'story-wolong', speaker: '손건', text: '유표는 주공을 객장으로 맞이하겠다고 합니다. 환대는 분명하지만 형주 안에도 각자의 계산이 있습니다. 이제 싸움만큼이나 사람의 마음을 읽어야 할 때입니다.' }, @@ -1063,7 +1063,7 @@ export const sixteenthBattleVictoryPages: StoryPage[] = [ id: 'sixteenth-next-zhuge-shadow', bgm: 'battle-prep', chapter: '와룡의 소문', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '간옹', text: '형주 선비들 사이에 융중의 와룡이라는 이름이 오갑니다. 주공의 뜻을 천하의 길로 펼칠 사람이라면, 다음 걸음은 그 사람을 찾아가는 일이 되겠습니다.' } @@ -1074,7 +1074,7 @@ export const seventeenthBattleIntroPages: StoryPage[] = [ id: 'seventeenth-wolong-clue-gathered', bgm: 'story-dark', chapter: '와룡의 단서', - background: 'story-militia', + background: 'story-wolong', speaker: '손건', text: '형주 선비들의 말이 하나로 모입니다. 융중의 초가에 머무는 제갈공명, 사람들은 그를 와룡이라 부릅니다. 주공께서 직접 찾아가 예를 다한다면 길이 열릴지도 모릅니다.' }, @@ -1082,7 +1082,7 @@ export const seventeenthBattleIntroPages: StoryPage[] = [ id: 'seventeenth-liu-bei-third-visit', bgm: 'militia-theme', chapter: '삼고초려', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '유비', portrait: 'liuBei', text: '한 번 찾아가 만나지 못했다 하여 뜻이 얕아지는 것은 아니오. 천하를 구할 계책을 구하려면, 내가 먼저 몸을 낮추어 그 문 앞에 서야 하오.' @@ -1091,7 +1091,7 @@ export const seventeenthBattleIntroPages: StoryPage[] = [ id: 'seventeenth-road-to-longzhong', bgm: 'battle-prep', chapter: '융중 방문로', - background: 'story-three-heroes', + background: 'story-wolong', speaker: '조운', text: '융중으로 향하는 산길에 수상한 가병들이 숨어 있습니다. 주공의 방문이 형주 안의 권신들에게 알려진 듯합니다. 길을 먼저 정리하겠습니다.' }, @@ -1099,7 +1099,7 @@ export const seventeenthBattleIntroPages: StoryPage[] = [ id: 'seventeenth-longzhong-sortie', bgm: 'battle-prep', chapter: '와룡을 찾아', - background: 'story-sortie', + background: 'story-wolong', speaker: '장비', portrait: 'zhangFei', text: '군사 하나 만나러 가는데 길목마다 잔챙이들이 성가시게 하는군요. 그래도 형님 뜻이라면 길부터 시원하게 열어 보겠습니다.' @@ -1111,14 +1111,14 @@ export const seventeenthBattleVictoryPages: StoryPage[] = [ id: 'seventeenth-victory-longzhong-road', bgm: 'militia-theme', chapter: '열린 초가 길', - background: 'story-sortie', + background: 'story-wolong', text: '융중으로 향하는 길목의 가병들이 흩어지고, 산길은 조용해졌다. 유비는 갑옷의 먼지를 털지도 않은 채 제갈량의 초가 앞에 다시 섰다.' }, { id: 'seventeenth-zhuge-liang-counsel', bgm: 'story-dark', chapter: '천하삼분의 말', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '제갈량', text: '한실을 일으키려면 먼저 형주와 익주를 얻어 근본을 세우고, 때를 기다려 북벌의 길을 여십시오. 주공의 뜻이 백성에게 닿는다면, 저는 그 길에 지혜를 보태겠습니다.' }, @@ -1126,7 +1126,7 @@ export const seventeenthBattleVictoryPages: StoryPage[] = [ id: 'seventeenth-zhuge-liang-joins', bgm: 'battle-prep', chapter: '와룡 출려', - background: 'story-three-heroes', + background: 'story-wolong', speaker: '유비', portrait: 'liuBei', text: '공명 선생이 함께한다면 우리 군은 비로소 길을 보는 눈을 얻은 것이오. 이제 형주의 머무름은 다음 큰 전장을 준비하는 시간이 될 것이오.' @@ -1138,7 +1138,7 @@ export const eighteenthBattleIntroPages: StoryPage[] = [ id: 'eighteenth-cao-vanguard-moves', bgm: 'story-dark', chapter: '조조 남하의 그림자', - background: 'story-militia', + background: 'story-wolong', speaker: '손건', text: '조조가 형주를 향해 병력을 움직이고 있습니다. 유표의 병세와 형주의 불안이 겹치자, 신야의 작은 군영에도 큰 물결이 밀려옵니다.' }, @@ -1146,7 +1146,7 @@ export const eighteenthBattleIntroPages: StoryPage[] = [ id: 'eighteenth-zhuge-first-plan', bgm: 'battle-prep', chapter: '박망파의 계책', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '제갈량', text: '하후돈의 선봉은 빠르나 숲과 좁은 길을 가볍게 여길 것입니다. 길을 내어 주는 척하다가 박망파의 숲길에서 불과 매복으로 그 기세를 꺾겠습니다.' }, @@ -1154,7 +1154,7 @@ export const eighteenthBattleIntroPages: StoryPage[] = [ id: 'eighteenth-generals-doubt', bgm: 'militia-theme', chapter: '새 군사의 첫 명', - background: 'story-three-heroes', + background: 'story-wolong', speaker: '관우', portrait: 'guanYu', text: '군사의 말이 이치에 맞다 하여도, 전장은 말과 다릅니다. 그러나 형님께서 맡기셨다면 우리 또한 그 계책을 전장에서 증명하겠습니다.' @@ -1163,7 +1163,7 @@ export const eighteenthBattleIntroPages: StoryPage[] = [ id: 'eighteenth-bowang-sortie', bgm: 'battle-prep', chapter: '박망파 매복전', - background: 'story-sortie', + background: 'story-wolong', speaker: '유비', portrait: 'liuBei', text: '오늘 싸움은 적을 많이 베는 것보다 조조군의 발을 묶는 것이 중요하오. 공명의 계책을 중심에 두고, 숲길과 불길 사이에서 전열을 흩트리지 맙시다.' @@ -1175,14 +1175,14 @@ export const eighteenthBattleVictoryPages: StoryPage[] = [ id: 'eighteenth-victory-bowang-fire', bgm: 'militia-theme', chapter: '숲길의 불빛', - background: 'story-sortie', + background: 'story-wolong', text: '박망파의 숲길에 불빛이 번지고, 하후돈의 선봉은 좁은 길에서 서로의 퇴로를 막았다. 유비군은 큰 병력 없이도 조조군의 진격을 늦추었다.' }, { id: 'eighteenth-zhuge-trust-earned', bgm: 'battle-prep', chapter: '계책을 믿다', - background: 'story-liu-bei', + background: 'story-wolong', speaker: '장비', portrait: 'zhangFei', text: '처음에는 군사 양반이 종이 위에서만 싸우는 줄 알았습니다. 그런데 오늘 보니, 종이 위의 길이 정말 전장의 길이 되더군요.' @@ -1191,7 +1191,7 @@ export const eighteenthBattleVictoryPages: StoryPage[] = [ id: 'eighteenth-red-cliffs-wind', bgm: 'story-dark', chapter: '강동으로 부는 바람', - background: 'story-three-heroes', + background: 'story-wolong', speaker: '제갈량', text: '조조의 큰 군세는 여기서 멈추지 않을 것입니다. 이제 강동과 손을 잡을 길을 열어야 합니다. 바람은 아직 멀리 있으나, 방향은 보이기 시작했습니다.' } @@ -1202,7 +1202,7 @@ export const nineteenthBattleIntroPages: StoryPage[] = [ id: 'nineteenth-cao-army-south', bgm: 'story-dark', chapter: '조조의 남하', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '손건', text: '박망파에서 시간을 벌었지만 조조의 대군은 멈추지 않았습니다. 신야의 백성들이 남쪽으로 몰리고, 장판파 길목에는 추격 기병이 먼저 닿고 있습니다.' }, @@ -1210,7 +1210,7 @@ export const nineteenthBattleIntroPages: StoryPage[] = [ id: 'nineteenth-zhao-yun-rescue', bgm: 'battle-prep', chapter: '백마의 구원', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '조운', text: '주공, 피난 행렬이 흩어지면 백성도 군도 모두 잃습니다. 제가 앞뒤를 오가며 길을 묶겠습니다. 다리와 마을을 먼저 지켜 주십시오.' }, @@ -1218,7 +1218,7 @@ export const nineteenthBattleIntroPages: StoryPage[] = [ id: 'nineteenth-zhang-fei-bridge', bgm: 'battle-prep', chapter: '장판교의 호령', - background: 'story-sortie', + background: 'story-red-cliffs', speaker: '장비', portrait: 'zhangFei', text: '형님은 백성을 이끌고 남쪽 길을 보시오. 뒤쫓는 놈들은 제가 다리목에서 한 번 꺾어 놓겠습니다. 다만 누가 옆을 받쳐 줄지는 잘 골라야겠소!' @@ -1227,7 +1227,7 @@ export const nineteenthBattleIntroPages: StoryPage[] = [ id: 'nineteenth-changban-sortie', bgm: 'battle-prep', chapter: '장판파 피난로', - background: 'story-liu-bei', + background: 'story-red-cliffs', speaker: '유비', portrait: 'liuBei', text: '오늘의 싸움은 이기는 것만으로 끝나지 않소. 백성이 지나갈 길을 열고, 조운과 익덕이 무너지지 않게 서로 받쳐야 하오. 함께할 무장을 신중히 정합시다.' @@ -1239,14 +1239,14 @@ export const nineteenthBattleVictoryPages: StoryPage[] = [ id: 'nineteenth-victory-refuge-road', bgm: 'militia-theme', chapter: '피난로가 열리다', - background: 'story-militia', + background: 'story-red-cliffs', text: '장판파의 먼지 속에서 유비군은 피난 행렬을 가까스로 남쪽 길로 흘려보냈습니다. 조운의 창과 장비의 호령이 무너질 뻔한 길목을 붙들었습니다.' }, { id: 'nineteenth-zhao-yun-returns', bgm: 'battle-prep', chapter: '흩어진 깃발을 모아', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '조운', text: '흩어진 병사와 백성을 모두 되찾지는 못했습니다. 그러나 주공의 깃발이 뒤돌아보았기에 사람들은 다시 모일 곳을 알게 되었습니다.' }, @@ -1254,7 +1254,7 @@ export const nineteenthBattleVictoryPages: StoryPage[] = [ id: 'nineteenth-jiangdong-envoy', bgm: 'story-dark', chapter: '강동으로 보낼 사절', - background: 'story-liu-bei', + background: 'story-red-cliffs', speaker: '제갈량', text: '조조의 남하는 이제 강동도 외면할 수 없습니다. 장판파에서 지켜낸 백성의 길과 조조군의 속도를 함께 전하면, 손권과 마주 앉을 명분이 생깁니다.' } @@ -1265,7 +1265,7 @@ export const twentiethBattleIntroPages: StoryPage[] = [ id: 'twentieth-envoy-road-opens', bgm: 'story-dark', chapter: '강동으로 가는 길', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '손건', text: '장판파의 피난로를 지나 유비군은 하구로 향합니다. 강동에 사절을 보내려면 조조군 추격대가 강나루를 닫기 전에 길을 열어야 합니다.' }, @@ -1273,7 +1273,7 @@ export const twentiethBattleIntroPages: StoryPage[] = [ id: 'twentieth-zhuge-envoy-plan', bgm: 'battle-prep', chapter: '사절의 문서', - background: 'story-liu-bei', + background: 'story-red-cliffs', speaker: '제갈량', text: '강동은 조조를 두려워하지만, 싸울 계산이 서야 움직입니다. 손건의 문서와 장판파의 기록을 나루까지 지켜야 합니다.' }, @@ -1281,7 +1281,7 @@ export const twentiethBattleIntroPages: StoryPage[] = [ id: 'twentieth-generals-protect-envoy', bgm: 'battle-prep', chapter: '호위와 돌파', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '관우', portrait: 'guanYu', text: '이번 길은 적을 많이 베는 것보다 사절을 온전히 보내는 일이 먼저입니다. 전열과 기동, 보급을 골고루 세우는 편성이 필요하겠습니다.' @@ -1290,7 +1290,7 @@ export const twentiethBattleIntroPages: StoryPage[] = [ id: 'twentieth-jiangdong-envoy-sortie', bgm: 'battle-prep', chapter: '강동 사절로', - background: 'story-sortie', + background: 'story-red-cliffs', speaker: '유비', portrait: 'liuBei', text: '선생과 손건이 강동에 닿아야 조조의 큰 군세를 막을 길이 열리오. 오늘은 칼끝만이 아니라 말과 문서를 지키는 싸움이오.' @@ -1302,14 +1302,14 @@ export const twentiethBattleVictoryPages: StoryPage[] = [ id: 'twentieth-victory-river-port', bgm: 'militia-theme', chapter: '나루가 열리다', - background: 'story-sortie', + background: 'story-red-cliffs', text: '문빙의 추격대가 물러서자 강나루의 문이 열렸습니다. 유비군은 피난 행렬을 뒤에 두고, 강동으로 향할 작은 배와 사절 문서를 지켜냈습니다.' }, { id: 'twentieth-sun-qian-letter-ready', bgm: 'battle-prep', chapter: '손권에게 보낼 말', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '손건', text: '강동에 전할 말은 이제 분명합니다. 조조의 남하, 장판파의 피난로, 그리고 주공께서 백성을 버리지 않았다는 사실을 함께 적겠습니다.' }, @@ -1317,7 +1317,7 @@ export const twentiethBattleVictoryPages: StoryPage[] = [ id: 'twentieth-red-cliffs-near', bgm: 'story-dark', chapter: '적벽으로 부는 바람', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '제갈량', text: '이제 강동의 마음을 움직일 차례입니다. 손권과 주유가 계산을 마치면, 조조의 대군은 장강 위에서 처음으로 멈춰 서게 될 것입니다.' } @@ -1328,7 +1328,7 @@ export const twentyFirstBattleIntroPages: StoryPage[] = [ id: 'twenty-first-sun-quan-council', bgm: 'story-dark', chapter: '강동 회담', - background: 'story-liu-bei', + background: 'story-red-cliffs', speaker: '제갈량', text: '손권의 장막 안에서는 항복과 결전의 말이 맞섰습니다. 제갈량은 조조의 대군이 강을 건너면 강동도, 유비군도 설 곳을 잃는다는 사실을 차분히 짚었습니다.' }, @@ -1336,7 +1336,7 @@ export const twentyFirstBattleIntroPages: StoryPage[] = [ id: 'twenty-first-zhou-yu-decision', bgm: 'battle-prep', chapter: '주유의 결단', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '주유', text: '조조가 강 위에서 싸우는 법을 모른다면, 장강은 우리 편이 될 것입니다. 손권께서 결심하셨으니, 이제 말이 아니라 배와 불길로 답해야 합니다.' }, @@ -1344,7 +1344,7 @@ export const twentyFirstBattleIntroPages: StoryPage[] = [ id: 'twenty-first-liu-bei-alliance', bgm: 'militia-theme', chapter: '손유 동맹', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '유비', portrait: 'liuBei', text: '강동이 함께 선다면 조조의 군세도 처음으로 멈출 수 있소. 우리는 작은 군이지만, 장강의 바람과 백성을 지키는 뜻을 함께 세웁시다.' @@ -1353,7 +1353,7 @@ export const twentyFirstBattleIntroPages: StoryPage[] = [ id: 'twenty-first-red-cliffs-sortie', bgm: 'battle-prep', chapter: '적벽 전초전', - background: 'story-sortie', + background: 'story-red-cliffs', speaker: '제갈량', text: '조조군 수군 선봉이 강가 포구를 시험하고 있습니다. 채모의 선봉을 물리쳐야 강동 수군과 합류할 첫 자리를 지킬 수 있습니다.' } @@ -1364,14 +1364,14 @@ export const twentyFirstBattleVictoryPages: StoryPage[] = [ id: 'twenty-first-victory-river-line', bgm: 'militia-theme', chapter: '강 위의 첫 승리', - background: 'story-sortie', + background: 'story-red-cliffs', text: '채모의 선봉이 물러서자 장강의 물결 위에 손유 동맹의 첫 전선이 세워졌습니다. 작은 승리였지만 조조군이 강 위에서 무적이 아님을 모두가 보았습니다.' }, { id: 'twenty-first-zhou-yu-fire-plan', bgm: 'battle-prep', chapter: '화공의 실마리', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '주유', text: '조조군의 배는 많지만 서로를 믿지 못하고, 사슬로 묶으면 바람 앞에서 약점이 됩니다. 아직 때가 무르익지는 않았지만 불길의 길은 보이기 시작했습니다.' }, @@ -1379,7 +1379,7 @@ export const twentyFirstBattleVictoryPages: StoryPage[] = [ id: 'twenty-first-zhuge-wind', bgm: 'story-dark', chapter: '바람을 기다리다', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '제갈량', text: '다음 싸움은 힘으로만 밀어붙일 수 없습니다. 황개의 결단, 주유의 수군, 그리고 바람의 때가 맞아야 조조의 대군을 무너뜨릴 수 있습니다.' } @@ -1390,7 +1390,7 @@ export const twentySecondBattleIntroPages: StoryPage[] = [ id: 'twenty-second-huang-gai-bitter-plan', bgm: 'story-dark', chapter: '황개의 결단', - background: 'story-liu-bei', + background: 'story-red-cliffs', speaker: '주유', text: '황개 장군은 거짓 항복의 배를 준비했습니다. 조조가 그 배를 의심하지 않게 하려면, 유비군은 강안의 감시선을 흔들어 화선이 다가갈 길을 열어야 합니다.' }, @@ -1398,7 +1398,7 @@ export const twentySecondBattleIntroPages: StoryPage[] = [ id: 'twenty-second-zhuge-wind-watch', bgm: 'battle-prep', chapter: '동남풍을 기다리다', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '제갈량', text: '바람은 아직 완전히 돌지 않았습니다. 그러나 때가 오면 불길은 강 위에서 산처럼 번질 것입니다. 그 전까지 조조의 척후와 갑판 궁병을 묶어 두어야 합니다.' }, @@ -1406,7 +1406,7 @@ export const twentySecondBattleIntroPages: StoryPage[] = [ id: 'twenty-second-liu-bei-fire-line', bgm: 'militia-theme', chapter: '불길 앞의 뜻', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '유비', portrait: 'liuBei', text: '오늘의 불은 백성을 태우기 위한 불이 아니라 난세의 물결을 멈추기 위한 불이오. 화선이 닿을 때까지 강안 전선을 흔들림 없이 지킵시다.' @@ -1415,7 +1415,7 @@ export const twentySecondBattleIntroPages: StoryPage[] = [ id: 'twenty-second-fire-attack-sortie', bgm: 'battle-prep', chapter: '적벽 화공전', - background: 'story-sortie', + background: 'story-red-cliffs', speaker: '제갈량', text: '조조의 함대가 사슬로 묶인 채 강북에 모였습니다. 화선의 길을 막는 초병을 베고, 조조 본선이 불길에 휩싸일 때까지 전선을 지키십시오.' } @@ -1426,14 +1426,14 @@ export const twentySecondBattleVictoryPages: StoryPage[] = [ id: 'twenty-second-victory-fire-rises', bgm: 'battle-prep', chapter: '불길이 일다', - background: 'story-sortie', + background: 'story-red-cliffs', text: '화선이 조조군 함대에 닿자 강 위가 붉게 일렁였습니다. 사슬로 묶인 배들은 서로를 구하지 못했고, 장강의 바람은 불길을 북쪽으로 몰아붙였습니다.' }, { id: 'twenty-second-cao-cao-retreat', bgm: 'story-dark', chapter: '조조의 퇴각', - background: 'story-three-heroes', + background: 'story-red-cliffs', speaker: '조조', text: '오늘은 하늘과 강이 나를 막는구나. 그러나 난세는 아직 끝나지 않았다. 살아 돌아가 다시 군을 모으면, 이 치욕도 갚을 날이 있을 것이다.' }, @@ -1441,7 +1441,7 @@ export const twentySecondBattleVictoryPages: StoryPage[] = [ id: 'twenty-second-liu-bei-next-land', bgm: 'militia-theme', chapter: '형주를 바라보다', - background: 'story-militia', + background: 'story-red-cliffs', speaker: '유비', portrait: 'liuBei', text: '조조의 대군은 물러났지만 우리의 근본은 아직 없습니다. 이제 백성이 머물 땅을 얻고, 형주와 익주로 향할 길을 차근히 세워야 합니다.' @@ -1453,7 +1453,7 @@ export const twentyThirdBattleIntroPages: StoryPage[] = [ id: 'twenty-third-jingzhou-cause', bgm: 'militia-theme', chapter: '형주 남부의 문', - background: 'story-militia', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '적벽의 불길은 조조를 막았지만 백성이 기대어 살 땅은 아직 없소. 형주 남부의 군현을 힘으로 짓밟지 말고, 먼저 길과 민심을 열어야 하오.' @@ -1462,7 +1462,7 @@ export const twentyThirdBattleIntroPages: StoryPage[] = [ id: 'twenty-third-zhuge-plan', bgm: 'battle-prep', chapter: '군현을 여는 계책', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '영릉의 유도는 아직 마음을 정하지 못했고, 형도영은 길목을 막아 자신의 힘을 보이려 합니다. 그를 물리치되 백성을 다치게 하지 않으면 형주 남부가 움직일 것입니다.' }, @@ -1470,7 +1470,7 @@ export const twentyThirdBattleIntroPages: StoryPage[] = [ id: 'twenty-third-ma-liang-rumor', bgm: 'story-dark', chapter: '백미의 소문', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '손건', text: '형주 선비들 사이에 마량이라는 이름이 오갑니다. 눈썹이 희어 백미라 불리는 사람인데, 남부 군현의 민심과 길을 누구보다 잘 안다고 합니다.' }, @@ -1478,7 +1478,7 @@ export const twentyThirdBattleIntroPages: StoryPage[] = [ id: 'twenty-third-jingzhou-sortie', bgm: 'battle-prep', chapter: '형주 남부 진입전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '제갈량', text: '형도영의 가병이 남부 길목과 마을을 막고 있습니다. 성급히 몰아붙이면 백성이 흩어지니, 전열을 세우고 마을을 지키며 길목을 확보하십시오.' } @@ -1489,14 +1489,14 @@ export const twentyThirdBattleVictoryPages: StoryPage[] = [ id: 'twenty-third-victory-southern-road', bgm: 'militia-theme', chapter: '남부 길목이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '형도영이 물러서자 남부 군현으로 이어지는 길이 열렸습니다. 유비군은 약탈 없이 마을을 안정시키며 적벽 이후 처음으로 머물 땅의 윤곽을 얻었습니다.' }, { id: 'twenty-third-ma-liang-joins', bgm: 'battle-prep', chapter: '마량의 합류', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '주공께서 백성을 먼저 살피셨다는 말을 들었습니다. 형주 남부의 길과 사람을 잇는 일이라면, 제 작은 글과 말도 보탬이 될 것입니다.' }, @@ -1504,7 +1504,7 @@ export const twentyThirdBattleVictoryPages: StoryPage[] = [ id: 'twenty-third-next-commandery', bgm: 'story-dark', chapter: '군현을 차례로', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '영릉의 문은 열렸지만 형주 남부 전체가 움직인 것은 아닙니다. 계양, 무릉, 장사까지 차례로 설득하고 지켜야 비로소 근거지가 됩니다.' } @@ -1515,7 +1515,7 @@ export const twentyFourthBattleIntroPages: StoryPage[] = [ id: 'twenty-fourth-guiyang-cause', bgm: 'militia-theme', chapter: '계양으로 가는 서신', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '계양의 조범은 항복과 저항 사이에서 눈치를 보고 있습니다. 먼저 서신을 보내되, 길목의 군사들이 백성을 겁박하지 못하게 막아야 합니다.' }, @@ -1523,7 +1523,7 @@ export const twentyFourthBattleIntroPages: StoryPage[] = [ id: 'twenty-fourth-zhuge-plan', bgm: 'battle-prep', chapter: '칼보다 먼저 놓는 글', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '이번 전투는 성을 불태우는 싸움이 아닙니다. 마을을 안정시키고 조범의 친위대를 물리치면, 계양은 스스로 문을 열 것입니다.' }, @@ -1531,7 +1531,7 @@ export const twentyFourthBattleIntroPages: StoryPage[] = [ id: 'twenty-fourth-yi-ji-rumor', bgm: 'story-dark', chapter: '이적의 이름', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '손건', text: '형주의 문사 이적이 계양의 움직임을 지켜보고 있다고 합니다. 무리한 점령보다 예를 갖춘 설득을 보이면, 그 역시 길을 함께할지 모릅니다.' }, @@ -1539,7 +1539,7 @@ export const twentyFourthBattleIntroPages: StoryPage[] = [ id: 'twenty-fourth-guiyang-sortie', bgm: 'battle-prep', chapter: '계양 설득전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '오늘의 목적은 계양을 꺾는 것이 아니라 열어 보이는 것이오. 마을을 지키고 성채를 압박하되, 백성이 다시 문을 닫지 않게 하시오.' @@ -1551,14 +1551,14 @@ export const twentyFourthBattleVictoryPages: StoryPage[] = [ id: 'twenty-fourth-victory-guiyang-open', bgm: 'militia-theme', chapter: '계양의 문이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '조범의 친위대가 물러나자 계양의 성문은 불길이 아니라 서신 앞에서 열렸습니다. 유비군은 군율을 세우고 마을의 창고를 함부로 건드리지 않았습니다.' }, { id: 'twenty-fourth-yi-ji-joins', bgm: 'battle-prep', chapter: '이적의 합류', - background: 'story-militia', + background: 'story-yizhou', speaker: '이적', text: '주공께서 계양을 힘으로만 다루지 않으셨다는 말을 들었습니다. 형주의 글과 예가 필요하다면, 저도 붓과 길을 보태겠습니다.' }, @@ -1566,7 +1566,7 @@ export const twentyFourthBattleVictoryPages: StoryPage[] = [ id: 'twenty-fourth-next-commandery', bgm: 'story-dark', chapter: '험한 무릉의 길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '계양은 열렸지만 무릉의 산길은 아직 닫혀 있습니다. 다음에는 험한 길을 뚫고 흩어진 마을을 잇는 싸움이 될 것입니다.' } @@ -1577,7 +1577,7 @@ export const twentyFifthBattleIntroPages: StoryPage[] = [ id: 'twenty-fifth-wuling-road', bgm: 'story-dark', chapter: '무릉의 닫힌 산길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '마량', text: '무릉은 계양처럼 성문 하나만 바라보는 땅이 아닙니다. 산길과 작은 마을이 흩어져 있어, 길을 잃으면 군량도 마음도 끊어집니다.' }, @@ -1585,7 +1585,7 @@ export const twentyFifthBattleIntroPages: StoryPage[] = [ id: 'twenty-fifth-yi-ji-letter', bgm: 'battle-prep', chapter: '먼저 보내는 예', - background: 'story-militia', + background: 'story-yizhou', speaker: '이적', text: '김선은 강하게 버티려 하지만, 아래 장수 공지는 백성의 피해를 걱정한다고 들었습니다. 산길 마을을 지키면 그에게 말이 닿을 것입니다.' }, @@ -1593,7 +1593,7 @@ export const twentyFifthBattleIntroPages: StoryPage[] = [ id: 'twenty-fifth-zhuge-formation', bgm: 'battle-prep', chapter: '좁은 길의 진형', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '제갈량', text: '좁은 산길에서는 무장이 많다고 곧 힘이 되는 것이 아닙니다. 앞길을 여는 자, 마을을 달래는 자, 보급을 잇는 자를 골라야 합니다.' }, @@ -1601,7 +1601,7 @@ export const twentyFifthBattleIntroPages: StoryPage[] = [ id: 'twenty-fifth-wuling-sortie', bgm: 'battle-prep', chapter: '무릉 산길 확보전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '산길을 불태우지 말고 이어야 하오. 무릉의 길과 마을을 지켜 내면, 닫힌 마음도 함께 열릴 것이오.' @@ -1613,14 +1613,14 @@ export const twentyFifthBattleVictoryPages: StoryPage[] = [ id: 'twenty-fifth-victory-wuling-open', bgm: 'militia-theme', chapter: '무릉의 길이 이어지다', - background: 'story-sortie', + background: 'story-yizhou', text: '김선의 산길 방어선이 무너지자 무릉의 마을들은 먼저 불안한 문을 열었습니다. 유비군은 산길 창고를 봉하고 백성의 길을 지켰습니다.' }, { id: 'twenty-fifth-gong-zhi-joins', bgm: 'battle-prep', chapter: '공지의 결심', - background: 'story-militia', + background: 'story-yizhou', speaker: '공지', text: '무릉을 힘으로만 누르지 않으셨군요. 백성을 앞세우는 군이라면, 저도 산길과 고을의 형세를 바쳐 따르겠습니다.' }, @@ -1628,7 +1628,7 @@ export const twentyFifthBattleVictoryPages: StoryPage[] = [ id: 'twenty-fifth-changsha-shadow', bgm: 'story-dark', chapter: '장사의 노장', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '무릉까지 길이 이어졌습니다. 남은 장사에는 황충이라는 노장이 있습니다. 다음 싸움은 힘보다 예우와 인내를 시험할 것입니다.' } @@ -1639,7 +1639,7 @@ export const twentySixthBattleIntroPages: StoryPage[] = [ id: 'twenty-sixth-changsha-old-general', bgm: 'story-dark', chapter: '장사의 노장', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '공지', text: '장사에는 황충이라는 노장이 있습니다. 나이는 들었으나 활은 여전히 매섭고, 성 안 병사들은 그 이름을 믿고 버팁니다.' }, @@ -1647,7 +1647,7 @@ export const twentySixthBattleIntroPages: StoryPage[] = [ id: 'twenty-sixth-han-xuan-suspicion', bgm: 'battle-prep', chapter: '의심 많은 태수', - background: 'story-militia', + background: 'story-yizhou', speaker: '이적', text: '한현은 황충의 명망도 의심한다고 합니다. 성을 무너뜨리기보다 황충의 체면을 지키면, 장사 사람들의 마음도 흔들릴 것입니다.' }, @@ -1655,7 +1655,7 @@ export const twentySixthBattleIntroPages: StoryPage[] = [ id: 'twenty-sixth-wei-yan-rumor', bgm: 'battle-prep', chapter: '성문 안의 불씨', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '마량', text: '위연이라는 장수는 성 안의 부당함을 참지 못한다고 들었습니다. 백성을 해치지 않고 한현의 의심을 꺾으면, 성 안에서 길이 열릴 수 있습니다.' }, @@ -1663,7 +1663,7 @@ export const twentySixthBattleIntroPages: StoryPage[] = [ id: 'twenty-sixth-changsha-sortie', bgm: 'battle-prep', chapter: '장사 노장 대면전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '오늘은 노장의 이름을 꺾으러 가는 것이 아니오. 예를 갖추고 한현의 의심을 물리쳐, 장사의 사람을 얻어야 하오.' @@ -1675,14 +1675,14 @@ export const twentySixthBattleVictoryPages: StoryPage[] = [ id: 'twenty-sixth-victory-changsha-open', bgm: 'militia-theme', chapter: '장사 성문이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '한현의 의심이 전장 위에서 무너지자, 장사 성문은 크게 흔들렸습니다. 유비군은 황충의 명예를 욕보이지 않고 병사들에게 길을 열었습니다.' }, { id: 'twenty-sixth-huang-zhong-joins', bgm: 'battle-prep', chapter: '황충의 합류', - background: 'story-militia', + background: 'story-yizhou', speaker: '황충', text: '늙은 몸이라 하나, 아직 활은 뜻을 향해 날아갈 수 있습니다. 장사를 예로 대하신 주공의 군에 제 활을 맡기겠습니다.' }, @@ -1690,7 +1690,7 @@ export const twentySixthBattleVictoryPages: StoryPage[] = [ id: 'twenty-sixth-wei-yan-joins', bgm: 'battle-prep', chapter: '위연의 결심', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '위연', text: '의심과 두려움으로 닫힌 성문을 더는 따를 수 없습니다. 제 창은 닫힌 문을 여는 데 쓰겠습니다.' }, @@ -1698,7 +1698,7 @@ export const twentySixthBattleVictoryPages: StoryPage[] = [ id: 'twenty-sixth-next-yi-province', bgm: 'story-dark', chapter: '형주 남부의 끝', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '장사까지 열리면 형주 남부의 뿌리가 굳어집니다. 이제 익주로 이어질 더 큰 길을 바라볼 때가 다가옵니다.' } @@ -1709,7 +1709,7 @@ export const twentySeventhBattleIntroPages: StoryPage[] = [ id: 'twenty-seventh-yizhou-request', bgm: 'story-dark', chapter: '익주에서 온 요청', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '손건', text: '익주의 유장이 한중 장로의 압박을 두려워하여 원군을 청했습니다. 형주 남부를 안정시킨 지금, 이 요청은 촉으로 향하는 첫 문이 될 수 있습니다.' }, @@ -1717,7 +1717,7 @@ export const twentySeventhBattleIntroPages: StoryPage[] = [ id: 'twenty-seventh-pang-tong-rumor', bgm: 'battle-prep', chapter: '봉추의 그림자', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '제갈량', text: '익주로 들어가는 길목에는 봉추라 불리는 방통이 머문다는 소문이 있습니다. 그가 뜻을 함께한다면, 산과 관문으로 막힌 촉의 길도 달리 보일 것입니다.' }, @@ -1725,7 +1725,7 @@ export const twentySeventhBattleIntroPages: StoryPage[] = [ id: 'twenty-seventh-gate-warning', bgm: 'story-dark', chapter: '원군로의 관문', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '양회가 이끄는 전초 병력이 원군로를 막고 있습니다. 길목의 마을을 지켜 명분을 잃지 않고, 산길의 척후를 먼저 끊어야 합니다.' }, @@ -1733,7 +1733,7 @@ export const twentySeventhBattleIntroPages: StoryPage[] = [ id: 'twenty-seventh-yizhou-sortie', bgm: 'battle-prep', chapter: '익주 원군로', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '우리는 익주를 빼앗으러 가는 것이 아니라, 백성을 지키라는 부름에 응하는 것이오. 군율을 세우고 길을 열어 봉추의 마음까지 얻어 봅시다.' @@ -1745,14 +1745,14 @@ export const twentySeventhBattleVictoryPages: StoryPage[] = [ id: 'twenty-seventh-victory-road-open', bgm: 'militia-theme', chapter: '익주의 길이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '양회의 전초 병력이 물러나고 익주 원군로가 열렸습니다. 유비군은 마을의 창고를 건드리지 않고 길목을 안정시켜, 원군이라는 명분을 분명히 세웠습니다.' }, { id: 'twenty-seventh-pang-tong-joins', bgm: 'battle-prep', chapter: '방통의 합류', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '방통', text: '인의를 말로만 내세우는 군은 많으나, 길목의 작은 마을까지 지키며 움직이는 군은 드뭅니다. 이 방통, 촉으로 향하는 험한 길을 함께 보겠습니다.' }, @@ -1760,7 +1760,7 @@ export const twentySeventhBattleVictoryPages: StoryPage[] = [ id: 'twenty-seventh-next-fu-pass', bgm: 'story-dark', chapter: '부수관을 바라보다', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '봉추가 합류하니 익주의 지세와 사람의 마음을 함께 읽을 수 있게 되었습니다. 다음 길은 부수관과 낙성으로 이어지는 더 깊은 산문입니다.' } @@ -1771,7 +1771,7 @@ export const twentyEighthBattleIntroPages: StoryPage[] = [ id: 'twenty-eighth-fu-pass-shadow', bgm: 'story-dark', chapter: '부수관의 그림자', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '방통', text: '익주 원군로는 열렸으나 부수관은 아직 닫혀 있습니다. 고패가 관문 병력을 모아 길을 끊으면, 우리 명분은 산문 앞에서 멈출 것입니다.' }, @@ -1779,7 +1779,7 @@ export const twentyEighthBattleIntroPages: StoryPage[] = [ id: 'twenty-eighth-fa-zheng-message', bgm: 'battle-prep', chapter: '익주 내부의 손', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '제갈량', text: '익주 안쪽에서 법정이라는 인물이 은밀히 소식을 보냈습니다. 그는 유장의 답답한 정치를 걱정하며, 부수관을 넘을 길목을 알려 주겠다고 합니다.' }, @@ -1787,7 +1787,7 @@ export const twentyEighthBattleIntroPages: StoryPage[] = [ id: 'twenty-eighth-roster-pressure', bgm: 'battle-prep', chapter: '와룡과 봉추의 첫 편성', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '이번 전투부터 방통도 출전 후보가 됩니다. 책사 둘을 모두 데려가면 관문 계책은 강해지지만, 전열과 보급 중 하나가 얇아질 수 있습니다.' }, @@ -1795,7 +1795,7 @@ export const twentyEighthBattleIntroPages: StoryPage[] = [ id: 'twenty-eighth-fu-pass-sortie', bgm: 'battle-prep', chapter: '부수관 진입전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '관문을 부수는 일보다 중요한 것은, 그 너머의 백성이 우리를 어떻게 기억하느냐요. 방통의 기책과 제갈량의 큰 판을 살려 부수관의 길을 열겠소.' @@ -1807,14 +1807,14 @@ export const twentyEighthBattleVictoryPages: StoryPage[] = [ id: 'twenty-eighth-victory-pass-open', bgm: 'militia-theme', chapter: '부수관이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '고패의 관문 병력이 물러나고 부수관의 첫 문이 열렸습니다. 유비군은 관문 창고를 봉인하고 마을의 곡식을 지켜, 익주 내부의 의심을 조금 누그러뜨렸습니다.' }, { id: 'twenty-eighth-fa-zheng-joins', bgm: 'battle-prep', chapter: '법정의 합류', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '법정', text: '익주는 험한 땅이지만, 더 험한 것은 닫힌 마음입니다. 주공께서 그 마음을 함부로 베지 않으신다면, 이 법정이 안쪽 길을 밝히겠습니다.' }, @@ -1822,7 +1822,7 @@ export const twentyEighthBattleVictoryPages: StoryPage[] = [ id: 'twenty-eighth-next-luo-castle', bgm: 'story-dark', chapter: '낙성으로 이어지는 길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '방통', text: '부수관은 문에 불과합니다. 낙성으로 이어지는 길에는 더 깊은 매복과 더 복잡한 마음이 기다립니다. 이제 법정의 내부 정보까지 함께 써야 합니다.' } @@ -1833,7 +1833,7 @@ export const twentyNinthBattleIntroPages: StoryPage[] = [ id: 'twenty-ninth-luo-outer-wall', bgm: 'story-dark', chapter: '낙성의 바깥 성벽', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '법정', text: '부수관을 넘으면 낙성의 바깥 성벽이 기다립니다. 장임은 성 밖의 고개와 마을을 겹쳐 방어선을 세웠고, 성 안의 장수들은 아직 우리 뜻을 믿지 않습니다.' }, @@ -1841,7 +1841,7 @@ export const twentyNinthBattleIntroPages: StoryPage[] = [ id: 'twenty-ninth-wu-yi-rumor', bgm: 'battle-prep', chapter: '흔들리는 오의', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '방통', text: '오의는 성문을 지키지만 백성을 함부로 몰아붙이는 명령을 달가워하지 않는다고 합니다. 전장을 거칠게 밀지 않고 길을 열면, 그의 마음도 움직일 수 있습니다.' }, @@ -1849,7 +1849,7 @@ export const twentyNinthBattleIntroPages: StoryPage[] = [ id: 'twenty-ninth-roster-pressure', bgm: 'battle-prep', chapter: '법정의 첫 출전 선택', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '이번 전투부터 법정도 출전 후보입니다. 익주 내부 사정을 아는 법정을 데려가면 설득은 쉬워지지만, 무장을 줄이는 부담은 더 커집니다.' }, @@ -1857,7 +1857,7 @@ export const twentyNinthBattleIntroPages: StoryPage[] = [ id: 'twenty-ninth-luo-sortie', bgm: 'battle-prep', chapter: '낙성 외곽전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '낙성의 문을 여는 일은 칼보다 마음이 먼저요. 마을을 지키고 장임의 전열을 물리쳐, 성 안 사람들에게 우리가 어떤 군인지 보이겠소.' @@ -1869,14 +1869,14 @@ export const twentyNinthBattleVictoryPages: StoryPage[] = [ id: 'twenty-ninth-victory-outer-wall', bgm: 'militia-theme', chapter: '외곽 방어선 붕괴', - background: 'story-sortie', + background: 'story-yizhou', text: '장임은 낙성 안쪽으로 물러났고, 외곽 마을은 큰 피해 없이 유비군의 보호 아래 들어왔습니다. 성 안의 장수들은 유비군을 단순한 침입군으로만 볼 수 없게 되었습니다.' }, { id: 'twenty-ninth-wu-yi-joins', bgm: 'battle-prep', chapter: '오의의 합류', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '오의', text: '성문을 지킨다는 명분으로 백성을 몰아넣는 일은 장수의 길이 아니었습니다. 주공께서 마을을 먼저 살피셨으니, 이 오의도 낙성의 다음 길을 열겠습니다.' }, @@ -1884,7 +1884,7 @@ export const twentyNinthBattleVictoryPages: StoryPage[] = [ id: 'twenty-ninth-next-luofeng', bgm: 'story-dark', chapter: '낙봉파의 그늘', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '방통', text: '낙성 바깥은 열렸지만 길은 더 좁아집니다. 봉황이 떨어진다는 이름의 고개가 있다 하니, 다음 진군은 가볍게 볼 수 없습니다.' } @@ -1895,7 +1895,7 @@ export const thirtiethBattleIntroPages: StoryPage[] = [ id: 'thirtieth-luofeng-shadow', bgm: 'story-dark', chapter: '낙봉파의 좁은 길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '오의', text: '낙성 안쪽으로 들어가는 빠른 길은 낙봉파입니다. 길은 짧지만 양쪽 산세가 높고, 장임이 기다리기에는 지나치게 좋은 곳입니다.' }, @@ -1903,7 +1903,7 @@ export const thirtiethBattleIntroPages: StoryPage[] = [ id: 'thirtieth-pang-tong-warning', bgm: 'battle-prep', chapter: '봉추의 불길한 직감', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '방통', text: '좋은 길이 언제나 좋은 길은 아닙니다. 적이 우리를 빠르게 오게 만들었다면, 빠르게 물러날 길도 함께 보아 두어야 합니다.' }, @@ -1911,7 +1911,7 @@ export const thirtiethBattleIntroPages: StoryPage[] = [ id: 'thirtieth-roster-pressure', bgm: 'battle-prep', chapter: '오의의 첫 출전 선택', - background: 'story-militia', + background: 'story-yizhou', speaker: '법정', text: '이번 전투부터 오의도 출전 후보입니다. 낙성의 길을 아는 오의를 데려가면 매복을 읽기 쉬우나, 전열과 보급 후보는 더 좁아집니다.' }, @@ -1919,7 +1919,7 @@ export const thirtiethBattleIntroPages: StoryPage[] = [ id: 'thirtieth-luofeng-sortie', bgm: 'battle-prep', chapter: '낙봉파 매복전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '빠른 길을 택하되 방심하지 않겠소. 방통의 눈, 법정의 정보, 오의의 길 안내를 함께 엮어 장임의 매복을 거꾸로 무너뜨리겠소.' @@ -1931,14 +1931,14 @@ export const thirtiethBattleVictoryPages: StoryPage[] = [ id: 'thirtieth-victory-ambush-broken', bgm: 'militia-theme', chapter: '매복을 꿰뚫다', - background: 'story-sortie', + background: 'story-yizhou', text: '장임의 매복은 거칠게 덮쳐 왔으나, 유비군은 길목을 버티며 역으로 활로를 열었습니다. 낙봉파의 좁은 비탈에는 무너진 방책과 흩어진 깃발만 남았습니다.' }, { id: 'thirtieth-pang-tong-survives', bgm: 'battle-prep', chapter: '봉추의 생환', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '방통', text: '하마터면 길의 이름값을 할 뻔했습니다. 그러나 이번에는 우리 쪽이 한 수 먼저 보았습니다. 이제 낙성 본성은 더 이상 멀지 않습니다.' }, @@ -1946,7 +1946,7 @@ export const thirtiethBattleVictoryPages: StoryPage[] = [ id: 'thirtieth-next-luo-castle', bgm: 'story-dark', chapter: '낙성 본성 앞', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '낙봉파를 넘었으니 장임의 방어선은 본성에 몰렸습니다. 다음 전장은 낙성의 문과 익주 장수들의 마음을 함께 여는 싸움이 될 것입니다.' } @@ -1957,7 +1957,7 @@ export const thirtyFirstBattleIntroPages: StoryPage[] = [ id: 'thirty-first-luo-main-gate', bgm: 'story-dark', chapter: '낙성 본성의 문', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '법정', text: '장임은 낙봉파에서 물러난 뒤 낙성 본성의 문을 모두 닫았습니다. 성벽은 높고, 성 안의 장수들은 아직 유비공의 뜻을 의심하고 있습니다.' }, @@ -1965,7 +1965,7 @@ export const thirtyFirstBattleIntroPages: StoryPage[] = [ id: 'thirty-first-veteran-wall', bgm: 'battle-prep', chapter: '노장 엄안', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '오의', text: '성 안에는 엄안이라는 노장이 있습니다. 장임과 뜻을 같이해 버티고 있으나, 백성을 해치지 않겠다는 약속을 보이면 마음이 움직일 수 있습니다.' }, @@ -1973,7 +1973,7 @@ export const thirtyFirstBattleIntroPages: StoryPage[] = [ id: 'thirty-first-siege-choice', bgm: 'battle-prep', chapter: '돌파와 설득', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '성문을 부수는 힘만으로는 낙성을 얻을 수 없습니다. 방통, 법정, 오의를 함께 쓰면 설득의 길이 열리고, 무장을 더 세우면 짧은 돌파가 가능해집니다.' }, @@ -1981,7 +1981,7 @@ export const thirtyFirstBattleIntroPages: StoryPage[] = [ id: 'thirty-first-sortie', bgm: 'battle-prep', chapter: '낙성 본성 공략', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '성문을 열되 백성의 마음은 닫지 않겠소. 장임의 방어선을 깨고 엄안 같은 장수에게 우리가 지키려는 뜻을 보여 주시오.' @@ -1993,14 +1993,14 @@ export const thirtyFirstBattleVictoryPages: StoryPage[] = [ id: 'thirty-first-victory-gate-opened', bgm: 'militia-theme', chapter: '낙성의 문이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '낙성 본성의 문은 마침내 열렸습니다. 성벽 위의 깃발은 내려갔고, 장임의 마지막 방어선도 유비군의 꾸준한 압박 앞에 무너졌습니다.' }, { id: 'thirty-first-yan-yan-joins', bgm: 'battle-prep', chapter: '엄안의 결심', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '엄안', text: '성을 잃고도 백성이 다치지 않았다면, 장수는 패배 속에서도 새 주군을 볼 수 있습니다. 노장의 활이 이제 유비공의 군영을 지키겠습니다.' }, @@ -2008,7 +2008,7 @@ export const thirtyFirstBattleVictoryPages: StoryPage[] = [ id: 'thirty-first-next-chengdu-road', bgm: 'story-dark', chapter: '성도 압박의 길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '법정', text: '낙성이 열렸으니 익주의 심장부가 흔들립니다. 이제 유비군은 성도를 향한 길에서 더 많은 항복과 저항을 동시에 맞이하게 될 것입니다.' } @@ -2019,7 +2019,7 @@ export const thirtySecondBattleIntroPages: StoryPage[] = [ id: 'thirty-second-chengdu-pressure', bgm: 'story-dark', chapter: '성도 압박의 시작', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '법정', text: '낙성이 열리자 성도는 놀랐으나 아직 문을 닫고 있습니다. 면죽관의 수비장 이엄이 항복과 결전을 저울질하고 있으니, 힘과 명분을 함께 보여 주어야 합니다.' }, @@ -2027,7 +2027,7 @@ export const thirtySecondBattleIntroPages: StoryPage[] = [ id: 'thirty-second-yan-yan-first-counsel', bgm: 'battle-prep', chapter: '엄안의 첫 출전', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '엄안', text: '이엄은 무턱대고 물러설 장수가 아닙니다. 그러나 백성을 해치지 않는 군율과 익주 장수를 예우하는 마음을 보이면, 그의 칼끝도 흔들릴 것입니다.' }, @@ -2035,7 +2035,7 @@ export const thirtySecondBattleIntroPages: StoryPage[] = [ id: 'thirty-second-mianzhu-plan', bgm: 'battle-prep', chapter: '면죽관 설득', - background: 'story-militia', + background: 'story-yizhou', speaker: '방통', text: '정면으로만 밀면 성도는 더 굳게 닫힙니다. 엄안으로 익주 장수의 마음을 열고, 법정과 오의로 길을 짚으며, 황충과 장비가 수비선을 짧게 끊어야 합니다.' }, @@ -2043,7 +2043,7 @@ export const thirtySecondBattleIntroPages: StoryPage[] = [ id: 'thirty-second-sortie', bgm: 'battle-prep', chapter: '면죽관 압박전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '우리가 얻으려는 것은 성 하나가 아니라 익주의 마음이오. 면죽관을 넘되 백성을 다치게 하지 말고, 이엄에게도 함께 살 길을 보여 주시오.' @@ -2055,14 +2055,14 @@ export const thirtySecondBattleVictoryPages: StoryPage[] = [ id: 'thirty-second-victory-pass-yields', bgm: 'militia-theme', chapter: '면죽관이 열리다', - background: 'story-sortie', + background: 'story-yizhou', text: '면죽관의 수비선은 무너졌지만 성도 길목의 마을은 불타지 않았습니다. 유비군이 군율을 지키자 익주 병사들은 패배보다 이후의 처우를 먼저 바라보았습니다.' }, { id: 'thirty-second-li-yan-joins', bgm: 'battle-prep', chapter: '이엄의 선택', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '이엄', text: '칼을 거두는 일이 반드시 부끄러운 것은 아니군요. 백성을 살리고 익주의 길을 보전한다면, 이엄 또한 새 주군의 군율 아래 서겠습니다.' }, @@ -2070,7 +2070,7 @@ export const thirtySecondBattleVictoryPages: StoryPage[] = [ id: 'thirty-second-next-chengdu-surrender', bgm: 'story-dark', chapter: '성도 항복 권고', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '낙성과 면죽이 열렸으니 유장의 선택지는 더욱 좁아졌습니다. 다음 길은 성도 포위와 항복 권고, 그리고 익주를 어떻게 다스릴 것인가에 달렸습니다.' } @@ -2081,7 +2081,7 @@ export const thirtyThirdBattleIntroPages: StoryPage[] = [ id: 'thirty-third-chengdu-encircled', bgm: 'story-dark', chapter: '성도 앞의 마지막 권고', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '면죽관이 열렸고 이엄까지 합류했습니다. 성도는 아직 문을 닫았으나, 이제 유장은 싸움과 항복 사이에서 더 이상 오래 머물 수 없습니다.' }, @@ -2089,7 +2089,7 @@ export const thirtyThirdBattleIntroPages: StoryPage[] = [ id: 'thirty-third-li-yan-counsel', bgm: 'battle-prep', chapter: '이엄의 증언', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '이엄', text: '황권은 성도의 체면과 백성의 안위를 함께 보는 장수입니다. 그가 물러서면 유장공도 백성을 살리는 길을 택할 수 있습니다.' }, @@ -2097,7 +2097,7 @@ export const thirtyThirdBattleIntroPages: StoryPage[] = [ id: 'thirty-third-final-plan', bgm: 'battle-prep', chapter: '성도 항복 권고전', - background: 'story-militia', + background: 'story-yizhou', speaker: '법정', text: '성도 성문을 부수는 것이 능사가 아닙니다. 황권의 방어선을 눌러 항복 조건을 받아들이게 하고, 마을과 창고를 지켜 유비군의 약속을 증명해야 합니다.' }, @@ -2105,7 +2105,7 @@ export const thirtyThirdBattleIntroPages: StoryPage[] = [ id: 'thirty-third-sortie', bgm: 'battle-prep', chapter: '익주를 얻는 길', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '오늘의 승리는 성도의 문을 여는 것보다, 문 안의 백성이 두려움을 내려놓게 하는 데 있소. 칼을 들되 마음을 먼저 잃지 마시오.' @@ -2117,14 +2117,14 @@ export const thirtyThirdBattleVictoryPages: StoryPage[] = [ id: 'thirty-third-victory-chengdu-yields', bgm: 'militia-theme', chapter: '성도 항복', - background: 'story-sortie', + background: 'story-yizhou', text: '성도 외곽의 방어선은 무너졌지만 성문 안쪽은 불타지 않았습니다. 유장에게 보내진 마지막 권고문은 백성을 보전하고 장수의 체면을 남기는 조건을 담았습니다.' }, { id: 'thirty-third-huang-quan-joins', bgm: 'battle-prep', chapter: '황권의 귀순', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '황권', text: '익주를 지키려던 마음은 변하지 않았습니다. 다만 이제는 백성을 살리는 길이 유비공의 군율 아래 있다는 것을 보았습니다. 황권이 그 길에 서겠습니다.' }, @@ -2132,7 +2132,7 @@ export const thirtyThirdBattleVictoryPages: StoryPage[] = [ id: 'thirty-third-yizhou-secured', bgm: 'story-dark', chapter: '익주 확보', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '형주와 익주의 기반이 마련되었습니다. 유비군은 이제 유랑군이 아니라 나라의 뿌리를 갖춘 세력으로 바뀌며, 촉한 건국을 향한 다음 장을 준비합니다.' } @@ -2143,7 +2143,7 @@ export const thirtyFourthBattleIntroPages: StoryPage[] = [ id: 'thirty-fourth-hanzhong-road', bgm: 'story-dark', chapter: '한중으로 향하는 길', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '성도는 안정되었으나 북쪽 한중은 아직 장로와 조조의 그늘 아래 흔들립니다. 촉한의 이름을 세우려면 북문을 지킬 길부터 열어야 합니다.' }, @@ -2151,7 +2151,7 @@ export const thirtyFourthBattleIntroPages: StoryPage[] = [ id: 'thirty-fourth-huang-quan-first-counsel', bgm: 'battle-prep', chapter: '황권의 첫 출전', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '황권', text: '가맹관은 익주와 한중을 잇는 목입니다. 그곳에 마초의 기병이 나타났다면, 싸움만이 아니라 그가 누구의 길을 택할지도 보아야 합니다.' }, @@ -2159,7 +2159,7 @@ export const thirtyFourthBattleIntroPages: StoryPage[] = [ id: 'thirty-fourth-ma-chao-appears', bgm: 'battle-prep', chapter: '서량의 기병', - background: 'story-militia', + background: 'story-yizhou', speaker: '법정', text: '마초는 조조에게 쫓기고 장로에게도 마음을 다 주지 못했습니다. 그의 돌격을 막아 내고, 유비군이 서량의 창을 품을 그릇임을 보여 주십시오.' }, @@ -2167,7 +2167,7 @@ export const thirtyFourthBattleIntroPages: StoryPage[] = [ id: 'thirty-fourth-sortie', bgm: 'battle-prep', chapter: '가맹관 마초 대면전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '마초의 용맹을 꺾으려 하지 말고, 그 창끝이 향할 뜻을 바꾸어야 하오. 황권과 법정은 길을 열고, 장수들은 기병의 돌파를 받아내시오.' @@ -2179,14 +2179,14 @@ export const thirtyFourthBattleVictoryPages: StoryPage[] = [ id: 'thirty-fourth-victory-charge-stopped', bgm: 'militia-theme', chapter: '서량 돌격을 막다', - background: 'story-sortie', + background: 'story-yizhou', text: '가맹관의 좁은 길에서 서량 기병의 첫 돌격은 멈췄습니다. 마초는 패배보다도 유비군의 군율과 익주 장수들의 안정된 태도를 더 오래 바라보았습니다.' }, { id: 'thirty-fourth-ma-chao-joins', bgm: 'battle-prep', chapter: '마초의 합류', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '마초', text: '창을 맡길 주군을 찾지 못해 오래 떠돌았습니다. 유비공이 백성을 보전하고 장수를 예우한다면, 서량의 창 또한 그 깃발 아래 서겠습니다.' }, @@ -2194,7 +2194,7 @@ export const thirtyFourthBattleVictoryPages: StoryPage[] = [ id: 'thirty-fourth-next-hanzhong', bgm: 'story-dark', chapter: '한중 전선의 개막', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '마초가 합류하자 북쪽 길이 한층 넓어졌습니다. 이제 촉한의 기반은 성도 안쪽에서 끝나지 않고, 한중을 향한 전선으로 나아가게 됩니다.' } @@ -2205,7 +2205,7 @@ export const thirtyFifthBattleIntroPages: StoryPage[] = [ id: 'thirty-fifth-hanzhong-front', bgm: 'story-dark', chapter: '한중 전선의 첫 정찰', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '마초가 합류하자 가맹관 너머의 길이 열렸습니다. 그러나 양평관은 장로의 군세가 한중으로 드나드는 목으로, 먼저 길과 병력을 살펴야 합니다.' }, @@ -2213,7 +2213,7 @@ export const thirtyFifthBattleIntroPages: StoryPage[] = [ id: 'thirty-fifth-ma-chao-first-sortie', bgm: 'battle-prep', chapter: '마초의 첫 출전', - background: 'story-liu-bei', + background: 'story-northern', speaker: '마초', text: '양평관의 말길은 거칠지만 서량 기병이 숨을 맞추면 뚫을 수 있습니다. 이번에는 제가 앞에서 달리며 유비군의 깃발을 보이겠습니다.' }, @@ -2221,7 +2221,7 @@ export const thirtyFifthBattleIntroPages: StoryPage[] = [ id: 'thirty-fifth-huang-quan-map', bgm: 'battle-prep', chapter: '황권의 길잡이', - background: 'story-militia', + background: 'story-northern', speaker: '황권', text: '적을 모두 몰아내는 것보다 관문 창고와 강변 길을 잡는 것이 중요합니다. 한중을 향한 첫 정찰은 병력보다 지형을 얻는 싸움입니다.' }, @@ -2229,7 +2229,7 @@ export const thirtyFifthBattleIntroPages: StoryPage[] = [ id: 'thirty-fifth-sortie', bgm: 'battle-prep', chapter: '양평관 정찰전', - background: 'story-sortie', + background: 'story-northern', speaker: '유비', portrait: 'liuBei', text: '마초는 선봉을 맡고, 황권과 법정은 길을 보시오. 이 싸움은 한중을 빼앗는 첫걸음이 아니라, 한중을 얻을 자격을 살피는 첫걸음이오.' @@ -2241,14 +2241,14 @@ export const thirtyFifthBattleVictoryPages: StoryPage[] = [ id: 'thirty-fifth-victory-pass-opened', bgm: 'militia-theme', chapter: '양평관 길을 열다', - background: 'story-sortie', + background: 'story-northern', text: '양평관의 선봉대가 물러나자 한중으로 향하는 길목과 보급 창고가 유비군의 눈앞에 드러났습니다. 마초의 첫 돌격은 이제 유비군의 돌격이 되었습니다.' }, { id: 'thirty-fifth-ma-dai-joins', bgm: 'battle-prep', chapter: '마대의 합류', - background: 'story-liu-bei', + background: 'story-northern', speaker: '마대', text: '서량의 흩어진 기병을 거두어 마초 형님의 깃발 아래로 데려왔습니다. 유비공께서 허락하신다면 저도 한중 길을 여는 창이 되겠습니다.' }, @@ -2256,7 +2256,7 @@ export const thirtyFifthBattleVictoryPages: StoryPage[] = [ id: 'thirty-fifth-next-hanzhong', bgm: 'story-dark', chapter: '북문을 향하여', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '마초와 마대의 기병이 갖춰지자 북쪽 전선은 더 빠르게 움직일 수 있게 되었습니다. 이제 한중을 둘러싼 큰 싸움이 가까워집니다.' } @@ -2267,7 +2267,7 @@ export const thirtySixthBattleIntroPages: StoryPage[] = [ id: 'thirty-sixth-dingjun-mountain', bgm: 'story-dark', chapter: '정군산으로', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '양평관의 길을 살핀 뒤 한중의 핵심은 정군산으로 모였습니다. 산을 잡으면 한중을 굽어보고, 산을 잃으면 북문 전체가 흔들립니다.' }, @@ -2275,7 +2275,7 @@ export const thirtySixthBattleIntroPages: StoryPage[] = [ id: 'thirty-sixth-huang-zhong-plan', bgm: 'battle-prep', chapter: '노장의 결심', - background: 'story-liu-bei', + background: 'story-northern', speaker: '황충', text: '나이가 전열을 막지는 못합니다. 법정의 계책으로 능선을 잡아 주신다면, 이 늙은 활과 칼이 하후연의 기세를 꺾어 보이겠습니다.' }, @@ -2283,7 +2283,7 @@ export const thirtySixthBattleIntroPages: StoryPage[] = [ id: 'thirty-sixth-western-cavalry', bgm: 'battle-prep', chapter: '서량 기병의 우회로', - background: 'story-militia', + background: 'story-northern', speaker: '마초', text: '정군산 서쪽 능선은 말이 달리기 어렵지만, 마대와 함께 길을 잡으면 적의 눈을 돌릴 수 있습니다. 황충 장군이 치는 순간을 만들겠습니다.' }, @@ -2291,7 +2291,7 @@ export const thirtySixthBattleIntroPages: StoryPage[] = [ id: 'thirty-sixth-sortie', bgm: 'battle-prep', chapter: '정군산 전초전', - background: 'story-sortie', + background: 'story-northern', speaker: '유비', portrait: 'liuBei', text: '정군산을 얻으면 한중의 이름이 가까워질 것이오. 황충과 법정은 산을 보고, 마초와 마대는 길을 흔들며, 모두 유비군의 깃발을 산 위에 세우시오.' @@ -2303,14 +2303,14 @@ export const thirtySixthBattleVictoryPages: StoryPage[] = [ id: 'thirty-sixth-victory-ridge-held', bgm: 'militia-theme', chapter: '정군산 능선을 잡다', - background: 'story-sortie', + background: 'story-northern', text: '정군산의 첫 능선이 유비군 손에 들어오자 한중 전선의 무게가 바뀌었습니다. 하후연의 선봉은 물러났고, 산길의 병사들은 새 주인을 가늠하기 시작했습니다.' }, { id: 'thirty-sixth-wang-ping-joins', bgm: 'battle-prep', chapter: '왕평의 투항', - background: 'story-liu-bei', + background: 'story-northern', speaker: '왕평', text: '저는 한중의 산길과 병사들의 마음을 압니다. 조조군의 군율은 엄하나 이 땅을 품지는 못했습니다. 유비공께서 한중을 안정시킨다면 제 길도 그곳에 있겠습니다.' }, @@ -2318,7 +2318,7 @@ export const thirtySixthBattleVictoryPages: StoryPage[] = [ id: 'thirty-sixth-next-foundation', bgm: 'story-dark', chapter: '한중의 깃발', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '정군산의 승리와 왕평의 합류로 한중의 산길은 조금씩 유비군 편으로 기울었습니다. 이제 한중 본전과 촉한의 이름이 더 가까워집니다.' } @@ -2329,7 +2329,7 @@ export const thirtySeventhBattleIntroPages: StoryPage[] = [ id: 'thirty-seventh-hanzhong-front', bgm: 'story-dark', chapter: '한중 결전으로', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '정군산의 능선이 열리자 한중의 길은 마침내 하나의 전장으로 이어졌습니다. 조조군은 물러나기 전에 마지막으로 북문을 움켜쥐려 합니다.' }, @@ -2337,7 +2337,7 @@ export const thirtySeventhBattleIntroPages: StoryPage[] = [ id: 'thirty-seventh-wang-ping-map', bgm: 'battle-prep', chapter: '산길의 눈', - background: 'story-liu-bei', + background: 'story-northern', speaker: '왕평', text: '본진으로 곧장 오르는 길은 적이 기다리는 길입니다. 강변 창고를 잡고 서쪽 숲길을 열면 조조군의 퇴로와 보급이 동시에 흔들립니다.' }, @@ -2345,7 +2345,7 @@ export const thirtySeventhBattleIntroPages: StoryPage[] = [ id: 'thirty-seventh-huang-fa-plan', bgm: 'battle-prep', chapter: '노장과 군사의 합', - background: 'story-sortie', + background: 'story-northern', speaker: '법정', text: '황충 장군이 고지를 누르고 왕평이 길을 잇는 사이, 마초와 마대가 북쪽 기병대를 묶어야 합니다. 이 싸움은 힘보다 순서가 중요합니다.' }, @@ -2353,7 +2353,7 @@ export const thirtySeventhBattleIntroPages: StoryPage[] = [ id: 'thirty-seventh-sortie', bgm: 'battle-prep', chapter: '한중 결전', - background: 'story-militia', + background: 'story-northern', speaker: '유비', portrait: 'liuBei', text: '한중을 얻는 것은 북문을 얻는 일이고, 북문을 얻는 것은 촉의 백성을 지킬 이름을 얻는 일이오. 모두 각자의 길에서 하나의 깃발을 세우시오.' @@ -2365,14 +2365,14 @@ export const thirtySeventhBattleVictoryPages: StoryPage[] = [ id: 'thirty-seventh-victory-hanzhong-held', bgm: 'militia-theme', chapter: '한중을 얻다', - background: 'story-sortie', + background: 'story-northern', text: '조조군의 본진이 흔들리고 한중의 창고와 산길이 유비군의 손에 들어왔습니다. 북문을 지키던 군세는 물러났고, 촉으로 향하는 길은 비로소 안정되었습니다.' }, { id: 'thirty-seventh-king-of-hanzhong', bgm: 'battle-prep', chapter: '한중왕의 이름', - background: 'story-liu-bei', + background: 'story-northern', speaker: '제갈량', text: '주공께서 한중을 얻었으니 이제 사람들은 촉의 주인이 누구인지 묻게 될 것입니다. 이름은 칼보다 늦게 움직이나, 때로는 칼보다 멀리 갑니다.' }, @@ -2380,7 +2380,7 @@ export const thirtySeventhBattleVictoryPages: StoryPage[] = [ id: 'thirty-seventh-next-shu-han', bgm: 'story-dark', chapter: '촉한의 문턱', - background: 'story-three-heroes', + background: 'story-northern', speaker: '유비', portrait: 'liuBei', text: '우리가 세우려는 것은 땅의 이름만이 아니오. 한실을 잇고 백성을 품을 뜻이라면, 이제 그 뜻을 나라의 이름으로 밝힐 준비를 해야 하오.' @@ -2392,7 +2392,7 @@ export const hanzhongKingCouncilPages: StoryPage[] = [ id: 'hanzhong-king-council-open', bgm: 'story-dark', chapter: '한중왕 즉위 논의', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '한중을 얻은 뒤 군영의 분위기는 전장의 승리에서 나라의 이름으로 옮겨 갔습니다. 이제 유비군은 어디를 지키는 군대인지, 누구의 뜻을 잇는 세력인지 밝혀야 합니다.' }, @@ -2400,7 +2400,7 @@ export const hanzhongKingCouncilPages: StoryPage[] = [ id: 'hanzhong-king-liu-bei-doubt', bgm: 'battle-prep', chapter: '이름의 무게', - background: 'story-liu-bei', + background: 'story-northern', speaker: '유비', portrait: 'liuBei', text: '내가 왕의 이름을 받는 것이 백성을 위한 길이라면 마다하지 않겠소. 다만 그 이름이 욕심으로 보인다면 지금까지 따른 이들의 뜻을 해칠까 두렵소.' @@ -2409,7 +2409,7 @@ export const hanzhongKingCouncilPages: StoryPage[] = [ id: 'hanzhong-king-officers', bgm: 'battle-prep', chapter: '장수들의 서명', - background: 'story-militia', + background: 'story-northern', speaker: '관우', portrait: 'guanYu', text: '형님이 세우는 이름은 한실을 잇기 위한 깃발입니다. 전장마다 모인 장수들이 그 깃발 아래 서명한다면, 병사들도 무엇을 위해 싸우는지 알게 될 것입니다.' @@ -2418,7 +2418,7 @@ export const hanzhongKingCouncilPages: StoryPage[] = [ id: 'hanzhong-king-next-foundation', bgm: 'militia-theme', chapter: '촉한의 문 앞에서', - background: 'story-sortie', + background: 'story-northern', speaker: '제갈량', text: '한중왕의 격문이 준비되면 다음은 촉한의 이름을 세울 차례입니다. 그러나 나라의 이름은 새 전장을 부릅니다. 형주의 긴장과 북방의 그림자도 함께 보아야 합니다.' } @@ -2429,7 +2429,7 @@ export const shuHanFoundationPages: StoryPage[] = [ id: 'shu-han-foundation-banner', bgm: 'militia-theme', chapter: '한중왕 즉위', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '한중의 깃발 아래 장수들의 이름이 모였습니다. 유비는 한중왕의 이름을 받아들이며, 이 이름이 욕심이 아니라 한실을 잇는 약속임을 밝히려 합니다.' }, @@ -2437,7 +2437,7 @@ export const shuHanFoundationPages: StoryPage[] = [ id: 'shu-han-foundation-oath', bgm: 'battle-prep', chapter: '촉한의 이름', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '우리가 세우려는 나라는 나 한 사람의 나라가 아니오. 도원에서 맺은 뜻, 전장을 지나 모인 장수들의 뜻, 그리고 백성을 지키려는 뜻을 촉한의 이름으로 세우겠소.' @@ -2446,7 +2446,7 @@ export const shuHanFoundationPages: StoryPage[] = [ id: 'shu-han-foundation-generals', bgm: 'battle-prep', chapter: '오호의 깃발', - background: 'story-sortie', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '형님께서 이름을 세우셨으니 장수들도 각자의 자리를 지켜야 합니다. 서쪽은 안정되었으나 형주의 바람은 점점 거칠어지고 있습니다.' @@ -2455,7 +2455,7 @@ export const shuHanFoundationPages: StoryPage[] = [ id: 'shu-han-foundation-next-front', bgm: 'story-dark', chapter: '형주의 먹구름', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '촉한의 이름은 세워졌지만, 그 이름은 새로운 책임을 부릅니다. 관우가 지키는 형주에는 손권과 조조의 시선이 함께 모이고 있습니다.' } @@ -2466,7 +2466,7 @@ export const thirtyEighthBattleIntroPages: StoryPage[] = [ id: 'thirty-eighth-jing-warning', bgm: 'story-dark', chapter: '형주의 먹구름', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '촉한의 이름이 세워지자 형주의 무게가 더 커졌습니다. 관우가 지키는 강릉과 남군은 조조와 손권이 동시에 바라보는 칼끝이 되었습니다.' }, @@ -2474,7 +2474,7 @@ export const thirtyEighthBattleIntroPages: StoryPage[] = [ id: 'thirty-eighth-guan-yu-front', bgm: 'battle-prep', chapter: '관우의 전선', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '형주는 형님의 등을 지키는 문입니다. 위의 정찰대가 북쪽에서 움직이고, 오의 배가 강가를 맴돈다면 먼저 봉화대와 나루를 묶어야 합니다.' @@ -2483,7 +2483,7 @@ export const thirtyEighthBattleIntroPages: StoryPage[] = [ id: 'thirty-eighth-two-fronts', bgm: 'battle-prep', chapter: '강과 성 사이', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '강변 마을은 오의 말에 흔들리고, 북쪽 성채는 위의 군세를 두려워합니다. 백성이 흔들리면 형주는 성벽보다 먼저 무너집니다.' }, @@ -2491,7 +2491,7 @@ export const thirtyEighthBattleIntroPages: StoryPage[] = [ id: 'thirty-eighth-sortie', bgm: 'battle-prep', chapter: '형주 방위 전초전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '촉한의 이름을 세운 지금, 형주를 잃는다면 그 이름도 흔들릴 것이오. 관우는 봉화대를 지키고, 모두 강과 성 사이의 불안을 잠재우시오.' @@ -2503,14 +2503,14 @@ export const thirtyEighthBattleVictoryPages: StoryPage[] = [ id: 'thirty-eighth-victory-beacon-secured', bgm: 'militia-theme', chapter: '봉화가 다시 오르다', - background: 'story-sortie', + background: 'story-yizhou', text: '형주의 봉화대가 다시 불을 밝혔습니다. 위의 정찰대는 물러났고 오의 배는 강 건너로 물러났지만, 두 시선이 동시에 형주를 향하고 있다는 사실은 분명해졌습니다.' }, { id: 'thirty-eighth-guan-yu-resolve', bgm: 'battle-prep', chapter: '관우의 결의', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '적이 둘이라 하여 뜻도 둘이 될 수는 없습니다. 형주를 지키는 칼은 더욱 곧아야 합니다. 다만 강가의 마음까지 지켜야 오래 버틸 수 있겠습니다.' @@ -2519,7 +2519,7 @@ export const thirtyEighthBattleVictoryPages: StoryPage[] = [ id: 'thirty-eighth-next-fan-castle', bgm: 'story-dark', chapter: '번성의 그림자', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '형주의 불안은 잠시 가라앉았지만 북쪽 번성의 문은 여전히 굳게 닫혀 있습니다. 촉한의 첫 큰 시험은 관우의 전선에서 시작될 것입니다.' } @@ -2530,7 +2530,7 @@ export const thirtyNinthBattleIntroPages: StoryPage[] = [ id: 'thirty-ninth-fan-castle-shadow', bgm: 'story-dark', chapter: '번성의 그림자', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '형주의 봉화는 다시 올랐으나, 번성의 문은 더욱 굳게 닫혔습니다. 조조의 북방 병력은 수로와 성채를 엮어 시간을 벌려 하고, 오의 시선도 강 건너에서 조용히 움직입니다.' }, @@ -2538,7 +2538,7 @@ export const thirtyNinthBattleIntroPages: StoryPage[] = [ id: 'thirty-ninth-guan-yu-north', bgm: 'battle-prep', chapter: '관우의 북상', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '형주를 지키는 일은 곧 한실을 일으키는 일입니다. 번성 외곽의 보루와 나루를 눌러야 적의 숨통을 조이고, 뒤이어 큰 결전을 열 수 있습니다.' @@ -2547,7 +2547,7 @@ export const thirtyNinthBattleIntroPages: StoryPage[] = [ id: 'thirty-ninth-flooded-fields', bgm: 'battle-prep', chapter: '물길을 보는 눈', - background: 'story-militia', + background: 'story-yizhou', speaker: '법정', text: '한수의 물길은 평소에는 느려 보이나, 비와 둑의 높이에 따라 전장의 형세를 통째로 바꿉니다. 이번 전투에서는 성 밖 보급선과 제방 감시초를 먼저 잡아야 합니다.' }, @@ -2555,7 +2555,7 @@ export const thirtyNinthBattleIntroPages: StoryPage[] = [ id: 'thirty-ninth-sortie', bgm: 'battle-prep', chapter: '번성 외곽 압박전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '관우가 선봉을 잡되 모두가 그 뒤를 받쳐라. 번성 외곽을 열면 다음 물길과 성문을 함께 도모할 수 있다. 오늘의 선택이 다음 전장의 폭을 넓힐 것이다.' @@ -2567,14 +2567,14 @@ export const thirtyNinthBattleVictoryPages: StoryPage[] = [ id: 'thirty-ninth-victory-outer-wall', bgm: 'militia-theme', chapter: '외곽 보루 함락', - background: 'story-sortie', + background: 'story-yizhou', text: '번성 외곽의 보루와 나루가 촉한군의 손에 들어왔습니다. 조조군은 성 안쪽으로 물러났고, 방덕의 선봉은 다시 방어진을 고쳐 세우며 다음 격돌을 예고했습니다.' }, { id: 'thirty-ninth-pang-de-resolve', bgm: 'battle-prep', chapter: '방덕의 결의', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '방덕은 물러났으나 기세를 잃지 않았습니다. 조인과 우금도 성 안의 병력을 다시 묶고 있으니, 다음 전투에서는 물길과 성벽이 함께 움직일 것입니다.' }, @@ -2582,7 +2582,7 @@ export const thirtyNinthBattleVictoryPages: StoryPage[] = [ id: 'thirty-ninth-next-water-lines', bgm: 'story-dark', chapter: '한수 수공 준비', - background: 'story-militia', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '성은 아직 멀리 있고, 강은 우리 곁에 있소. 병사들에게 둑을 살피게 하고 배와 밧줄을 준비하라. 다음에는 물길마저 우리 편으로 삼아야 하오.' @@ -2594,7 +2594,7 @@ export const fortiethBattleIntroPages: StoryPage[] = [ id: 'fortieth-han-river-rain', bgm: 'story-dark', chapter: '불어난 한수', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '비가 이어지며 한수의 물길이 불어났습니다. 번성 밖의 평지는 진흙으로 변했고, 우금의 본대와 방덕의 선봉은 강과 둑 사이에 길게 늘어섰습니다.' }, @@ -2602,7 +2602,7 @@ export const fortiethBattleIntroPages: StoryPage[] = [ id: 'fortieth-water-plan', bgm: 'battle-prep', chapter: '수공의 군령', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '법정', text: '둑을 무너뜨리는 것만이 수공은 아닙니다. 물이 차오를 때 적이 믿는 퇴로를 먼저 끊고, 궁병과 기병을 높은 둑 위로 몰아야 합니다.' }, @@ -2610,7 +2610,7 @@ export const fortiethBattleIntroPages: StoryPage[] = [ id: 'fortieth-guan-yu-command', bgm: 'battle-prep', chapter: '관우의 결단', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '물길이 우리 편에 선다면 적의 칼도 무뎌질 것이오. 우금의 본대를 눌러 번성의 숨통을 끊고, 방덕의 돌격은 둑 위에서 맞받아치겠소.' @@ -2619,7 +2619,7 @@ export const fortiethBattleIntroPages: StoryPage[] = [ id: 'fortieth-sortie', bgm: 'battle-prep', chapter: '한수 수공', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '관우가 앞을 열고, 법정과 마량이 물길을 살피며, 기동대는 둑과 나루를 끊어라. 이번 싸움은 성벽보다 먼저 강을 얻는 싸움이다.' @@ -2631,14 +2631,14 @@ export const fortiethBattleVictoryPages: StoryPage[] = [ id: 'fortieth-victory-seven-armies', bgm: 'militia-theme', chapter: '칠군이 물에 잠기다', - background: 'story-sortie', + background: 'story-yizhou', text: '한수의 물길이 전장을 덮치자 조조군의 진형은 무너졌습니다. 우금의 본대는 퇴로를 잃었고, 번성 외곽에는 관우군의 깃발이 더욱 가까워졌습니다.' }, { id: 'fortieth-yu-jin-surrenders', bgm: 'battle-prep', chapter: '우금의 항복', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '제갈량', text: '우금은 병사들을 살리기 위해 무기를 내려놓았습니다. 그러나 방덕은 끝까지 물러서지 않았고, 번성 안의 조인은 더 깊은 수성전을 준비하기 시작했습니다.' }, @@ -2646,7 +2646,7 @@ export const fortiethBattleVictoryPages: StoryPage[] = [ id: 'fortieth-next-siege', bgm: 'story-dark', chapter: '번성 포위', - background: 'story-militia', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '강은 길을 열었으나 성문은 아직 남아 있소. 병사들에게 쉬게 하되 경계를 늦추지 마시오. 다음은 번성의 성벽을 직접 마주할 차례요.' @@ -2658,7 +2658,7 @@ export const fortyFirstBattleIntroPages: StoryPage[] = [ id: 'forty-first-fan-wall', bgm: 'story-dark', chapter: '성벽 앞의 밤', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '한수의 물길은 조조군의 칠군을 무너뜨렸지만, 번성의 성벽은 아직 닫혀 있습니다. 조인은 성문을 걸어 잠그고, 방덕은 마지막 돌격을 준비합니다.' }, @@ -2666,7 +2666,7 @@ export const fortyFirstBattleIntroPages: StoryPage[] = [ id: 'forty-first-siege-plan', bgm: 'battle-prep', chapter: '포위의 순서', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '마량', text: '성벽을 바로 두드리면 병사만 지칩니다. 외성 보루와 수문, 강가의 낮은 마을을 먼저 붙잡아야 성 안의 사기가 흔들립니다.' }, @@ -2674,7 +2674,7 @@ export const fortyFirstBattleIntroPages: StoryPage[] = [ id: 'forty-first-wu-shadow', bgm: 'story-dark', chapter: '강 건너의 시선', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '북쪽 성문만 보아서는 안 되오. 강동의 배가 멀리서 움직이고 있으니, 번성을 치는 동안 뒤의 나루도 비워 두지 마시오.' @@ -2683,7 +2683,7 @@ export const fortyFirstBattleIntroPages: StoryPage[] = [ id: 'forty-first-sortie', bgm: 'battle-prep', chapter: '번성 공성전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '관우가 성문을 압박하고, 남은 무장들은 보루와 나루를 나누어 맡아라. 이번 싸움은 성을 치면서도 뒤의 그림자를 놓치지 않는 싸움이다.' @@ -2695,14 +2695,14 @@ export const fortyFirstBattleVictoryPages: StoryPage[] = [ id: 'forty-first-victory-gate', bgm: 'militia-theme', chapter: '성문이 흔들리다', - background: 'story-sortie', + background: 'story-yizhou', text: '번성의 외성 보루가 무너지고 조인의 방어선은 성 안쪽으로 밀려났습니다. 방덕의 결사대도 더는 성문 밖에서 버티지 못했습니다.' }, { id: 'forty-first-pang-de-end', bgm: 'battle-prep', chapter: '방덕의 결말', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '방덕은 끝까지 물러서지 않았소. 적이라 하나 그 기개는 가벼이 볼 수 없으니, 병사들에게 전하되 오만해지지 말라 이르시오.' @@ -2711,7 +2711,7 @@ export const fortyFirstBattleVictoryPages: StoryPage[] = [ id: 'forty-first-jing-warning', bgm: 'story-dark', chapter: '형주의 불안', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '번성의 성벽은 흔들렸으나, 강 건너 오의 움직임은 더 가까워졌습니다. 다음 장에서는 포위의 승세와 형주 후방의 균열을 함께 다루어야 합니다.' } @@ -2722,7 +2722,7 @@ export const fortySecondBattleIntroPages: StoryPage[] = [ id: 'forty-second-river-rumors', bgm: 'story-dark', chapter: '강릉의 불안', - background: 'story-militia', + background: 'story-yizhou', speaker: '마량', text: '번성 성문은 흔들리고 있지만, 강릉 동쪽 나루에는 낯선 상선이 늘었습니다. 장사꾼의 말투 속에 군령이 섞여 있고, 밤 신호는 평소보다 늦게 올라옵니다.' }, @@ -2730,7 +2730,7 @@ export const fortySecondBattleIntroPages: StoryPage[] = [ id: 'forty-second-lu-meng-shadow', bgm: 'battle-prep', chapter: '흰 옷의 그림자', - background: 'story-liu-bei', + background: 'story-yizhou', speaker: '제갈량', text: '강동의 장수들은 칼을 들고 오지 않을 수도 있습니다. 흰 옷의 상인, 약재 배, 빈 곡식 자루가 모두 길을 재는 눈이 될 수 있습니다.' }, @@ -2738,7 +2738,7 @@ export const fortySecondBattleIntroPages: StoryPage[] = [ id: 'forty-second-guan-yu-rear-order', bgm: 'battle-prep', chapter: '후방 경계령', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '관우', portrait: 'guanYu', text: '번성을 치는 손을 늦출 수는 없으나, 형주의 뒤를 비울 수도 없소. 나루와 창고를 지키며 강동 정찰대를 몰아내시오.' @@ -2747,7 +2747,7 @@ export const fortySecondBattleIntroPages: StoryPage[] = [ id: 'forty-second-sortie', bgm: 'battle-prep', chapter: '강릉 나루 경계전', - background: 'story-sortie', + background: 'story-yizhou', speaker: '유비', portrait: 'liuBei', text: '전선의 승리와 후방의 평온은 따로 있지 않다. 관우의 깃발이 번성 앞에 선 동안, 강릉 나루의 작은 흔들림까지 놓치지 말라.' @@ -2759,14 +2759,14 @@ export const fortySecondBattleVictoryPages: StoryPage[] = [ id: 'forty-second-victory-river-watch', bgm: 'militia-theme', chapter: '나루의 밤이 밝아지다', - background: 'story-sortie', + background: 'story-yizhou', text: '강릉 동쪽 나루의 정찰선은 물러났고, 강변 창고의 불안은 잠시 가라앉았습니다. 그러나 붙잡힌 척후의 말은 오히려 더 큰 위기를 가리켰습니다.' }, { id: 'forty-second-lu-xun-letter', bgm: 'story-dark', chapter: '부드러운 글과 날카로운 뜻', - background: 'story-three-heroes', + background: 'story-yizhou', speaker: '마량', text: '강동에서 온 문서는 예를 갖추고 있었지만, 글 사이에는 형주의 빈틈을 재는 뜻이 숨어 있었습니다. 승리보다 후방의 믿음이 더 급해졌습니다.' }, @@ -2774,7 +2774,7 @@ export const fortySecondBattleVictoryPages: StoryPage[] = [ id: 'forty-second-next-crack', bgm: 'story-dark', chapter: '갈라지는 형주', - background: 'story-militia', + background: 'story-yizhou', speaker: '제갈량', text: '나루 하나는 지켰으나, 강릉과 공안의 장수들이 흔들리기 시작했습니다. 다음 장에서는 형주 후방의 균열이 더 노골적인 배신과 침투로 이어질 것입니다.' } @@ -2785,7 +2785,7 @@ export const fortyThirdBattleIntroPages: StoryPage[] = [ id: 'forty-third-gongan-gate', bgm: 'story-dark', chapter: '공안의 성문', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '미축', text: '강릉 창고 장부를 대조하니 공안으로 보낸 군량이 사라진 흔적이 있습니다. 성문을 지키는 병사들은 명령을 기다린다 하면서도 강동 배를 그냥 들이고 있습니다.' }, @@ -2793,7 +2793,7 @@ export const fortyThirdBattleIntroPages: StoryPage[] = [ id: 'forty-third-fu-shiren-wavers', bgm: 'story-dark', chapter: '흔들리는 수비장', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '마량', text: '부사인은 관우 장군의 엄한 군령을 두려워하고, 미방은 강동의 말에 마음이 흔들립니다. 이 싸움은 적을 베는 일보다 성문 안의 믿음을 붙드는 일이 더 어렵습니다.' }, @@ -2801,7 +2801,7 @@ export const fortyThirdBattleIntroPages: StoryPage[] = [ id: 'forty-third-lu-meng-infiltration', bgm: 'battle-prep', chapter: '강동의 본대', - background: 'story-liu-bei', + background: 'story-yiling-baidi', speaker: '제갈량', text: '여몽은 더는 작은 정찰선만 보내지 않을 것입니다. 흰 옷의 상인이 길을 열고, 육손의 글이 의심을 누그러뜨린 뒤, 본대가 공안 성문을 향해 움직일 것입니다.' }, @@ -2809,7 +2809,7 @@ export const fortyThirdBattleIntroPages: StoryPage[] = [ id: 'forty-third-sortie', bgm: 'battle-prep', chapter: '공안 성문 변고', - background: 'story-sortie', + background: 'story-yiling-baidi', speaker: '관우', portrait: 'guanYu', text: '번성 앞 깃발을 거둘 수 없다면, 후방의 성문을 먼저 다시 잠가야 하오. 공안 성문을 붙들고 부사인의 병사들을 안정시켜 형주가 한순간에 무너지지 않게 하시오.' @@ -2821,14 +2821,14 @@ export const fortyThirdBattleVictoryPages: StoryPage[] = [ id: 'forty-third-victory-gate-held', bgm: 'militia-theme', chapter: '잠긴 성문', - background: 'story-sortie', + background: 'story-yiling-baidi', text: '공안 성문은 다시 잠겼고, 강동의 선봉은 물러났습니다. 그러나 부사인의 얼굴에는 안도보다 두려움이 더 짙게 남았습니다.' }, { id: 'forty-third-mi-fang-silence', bgm: 'story-dark', chapter: '말 없는 장부', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '미축', text: '미방은 끝내 분명한 대답을 하지 않았습니다. 창고 장부는 맞춰 놓았으나, 사람의 마음은 장부처럼 줄을 맞추기 어렵습니다.' }, @@ -2836,7 +2836,7 @@ export const fortyThirdBattleVictoryPages: StoryPage[] = [ id: 'forty-third-next-shadow', bgm: 'story-dark', chapter: '맥성으로 드리우는 그림자', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '제갈량', text: '성문 하나를 지켰지만 형주는 이미 바깥과 안쪽에서 함께 갈라지고 있습니다. 다음 장에서는 관우의 번성 전선이 고립으로 바뀌는 순간을 다루어야 합니다.' } @@ -2847,7 +2847,7 @@ export const fortyFourthBattleIntroPages: StoryPage[] = [ id: 'forty-fourth-maicheng-orders', bgm: 'story-dark', chapter: '끊어진 후방', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '마량', text: '공안 성문을 다시 잠갔으나 강릉과 나루의 소식이 끊겼습니다. 관우 장군의 번성 전선은 앞의 조조군과 뒤의 강동군 사이에서 길을 잃고 있습니다.' }, @@ -2855,7 +2855,7 @@ export const fortyFourthBattleIntroPages: StoryPage[] = [ id: 'forty-fourth-lu-meng-seals-roads', bgm: 'story-dark', chapter: '봉쇄되는 길', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '왕평', text: '맥성으로 빠지는 길목마다 흰 옷을 벗은 강동 병사가 서 있습니다. 큰길은 막혔고, 숲과 물목의 작은 길도 오래 버티지 못할 것입니다.' }, @@ -2863,7 +2863,7 @@ export const fortyFourthBattleIntroPages: StoryPage[] = [ id: 'forty-fourth-guan-yu-resolve', bgm: 'battle-prep', chapter: '남은 깃발', - background: 'story-liu-bei', + background: 'story-yiling-baidi', speaker: '관우', portrait: 'guanYu', text: '성 하나가 아니라 의리를 지키는 싸움이 되었소. 맥성으로 길을 내고 남은 병사들을 수습하겠소. 길이 좁을수록 마음이 먼저 무너지지 않게 하시오.' @@ -2872,7 +2872,7 @@ export const fortyFourthBattleIntroPages: StoryPage[] = [ id: 'forty-fourth-sortie', bgm: 'battle-prep', chapter: '맥성 고립전', - background: 'story-sortie', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '운장의 깃발이 고립되었다면, 늦더라도 길을 열어야 하오. 북문과 갈대 물목을 동시에 살펴 포위망을 찢고 맥성의 퇴로를 확보하시오.' @@ -2884,14 +2884,14 @@ export const fortyFourthBattleVictoryPages: StoryPage[] = [ id: 'forty-fourth-victory-road-opened', bgm: 'militia-theme', chapter: '뚫린 좁은 길', - background: 'story-sortie', + background: 'story-yiling-baidi', text: '맥성 북문의 좁은 길은 간신히 열렸고, 흩어진 병사들이 다시 깃발 아래로 모였습니다. 그러나 길 밖의 횃불은 여전히 더 많았습니다.' }, { id: 'forty-fourth-lu-meng-tightens', bgm: 'story-dark', chapter: '좁아지는 포위', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '제갈량', text: '여몽은 물러난 것이 아니라 더 넓게 둘러섰습니다. 맥성의 작은 승리는 시간을 벌었을 뿐, 형주를 되찾는 길은 아직 멀고 험합니다.' }, @@ -2899,7 +2899,7 @@ export const fortyFourthBattleVictoryPages: StoryPage[] = [ id: 'forty-fourth-next-jing-loss', bgm: 'story-dark', chapter: '형주의 상실', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '마량', text: '맥성의 포위는 풀렸으나 강릉과 공안의 마음은 이미 갈라졌습니다. 다음 장에서는 형주 상실의 대가와 유비의 분노가 더 큰 전쟁으로 번지는 흐름을 준비해야 합니다.' } @@ -2910,7 +2910,7 @@ export const fortyFifthBattleIntroPages: StoryPage[] = [ id: 'forty-fifth-jing-loss-news', bgm: 'story-dark', chapter: '형주 상실의 비보', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '마량', text: '맥성의 길은 열렸지만 형주의 큰 성들은 이미 강동의 깃발 아래로 넘어갔습니다. 돌아온 전령들은 흩어진 잔병과 끊긴 나루, 그리고 다시 모이지 못한 깃발의 소식을 전했습니다.' }, @@ -2918,7 +2918,7 @@ export const fortyFifthBattleIntroPages: StoryPage[] = [ id: 'forty-fifth-liu-bei-grief', bgm: 'story-dark', chapter: '복수의 칼끝', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '형주의 상실은 땅 하나를 잃은 일이 아니오. 함께 세운 뜻이 강동의 말과 불길에 찢긴 일이오. 이릉으로 가는 길을 열어, 무너진 의리를 다시 묻겠소.' @@ -2927,7 +2927,7 @@ export const fortyFifthBattleIntroPages: StoryPage[] = [ id: 'forty-fifth-zhuge-warning', bgm: 'story-dark', chapter: '분노와 군략', - background: 'story-resolve', + background: 'story-yiling-baidi', speaker: '제갈량', text: '분노는 군을 움직이지만, 오래 버티게 하지는 못합니다. 오군은 산림과 물길을 이용해 긴 보급로를 태우려 할 것입니다. 먼저 이릉으로 향하는 동진로를 열고 진영을 흩어지지 않게 해야 합니다.' }, @@ -2935,7 +2935,7 @@ export const fortyFifthBattleIntroPages: StoryPage[] = [ id: 'forty-fifth-sortie', bgm: 'battle-prep', chapter: '이릉 진격로', - background: 'story-sortie', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '장강을 따라 깊이 들어가면 돌아올 길도 길어지오. 동진로의 숲과 나루를 안정시키고, 오군 선봉을 밀어 이릉 전쟁의 첫 진영을 세우시오.' @@ -2947,14 +2947,14 @@ export const fortyFifthBattleVictoryPages: StoryPage[] = [ id: 'forty-fifth-victory-road-camp', bgm: 'militia-theme', chapter: '세워진 복수의 진', - background: 'story-sortie', + background: 'story-yiling-baidi', text: '이릉으로 향하는 첫 진격로가 열렸습니다. 유비군은 강가와 숲 사이에 진영을 세웠지만, 긴 보급로와 뜨거운 여름 바람은 이미 다음 위기를 예고했습니다.' }, { id: 'forty-fifth-lu-xun-watches', bgm: 'story-dark', chapter: '육손의 침묵', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '제갈량', text: '오군은 크게 맞붙지 않았습니다. 육손은 물러난 것이 아니라 기다리고 있습니다. 진영이 길게 늘어설수록, 불길 하나가 군 전체를 흔들 수 있습니다.' }, @@ -2962,7 +2962,7 @@ export const fortyFifthBattleVictoryPages: StoryPage[] = [ id: 'forty-fifth-next-yiling-main', bgm: 'story-dark', chapter: '이릉의 불씨', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '첫 길은 열렸으나 전쟁은 이제 시작이오. 다음에는 흩어진 진영을 붙들고, 강동의 기다림이 무엇을 노리는지 확인해야 하오.' @@ -2974,7 +2974,7 @@ export const fortySixthBattleIntroPages: StoryPage[] = [ id: 'forty-sixth-camps-stretch', bgm: 'story-dark', chapter: '길어진 진영', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '황권', text: '이릉의 첫 진영은 세웠지만, 촉한의 군막은 강변과 숲길을 따라 너무 길게 늘어졌습니다. 물길은 멀고, 마른 풀은 높으며, 오군은 여전히 큰 싸움을 피하고 있습니다.' }, @@ -2982,7 +2982,7 @@ export const fortySixthBattleIntroPages: StoryPage[] = [ id: 'forty-sixth-lu-xun-fire', bgm: 'story-dark', chapter: '기다린 불씨', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '제갈량', text: '육손의 침묵은 물러남이 아니었습니다. 바람이 동쪽에서 불고 군막이 말랐을 때, 오군의 작은 횃불이 긴 진영 전체를 흔드는 칼이 되었습니다.' }, @@ -2990,7 +2990,7 @@ export const fortySixthBattleIntroPages: StoryPage[] = [ id: 'forty-sixth-liu-bei-orders', bgm: 'story-dark', chapter: '불길 속의 명령', - background: 'story-resolve', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '불길이 먼저 달려든다면, 사람의 길을 먼저 열어야 하오. 진영을 버려도 병사를 버릴 수는 없소. 서쪽 퇴로와 강변 물길을 붙들어 백제성으로 물러날 길을 만드시오.' @@ -2999,7 +2999,7 @@ export const fortySixthBattleIntroPages: StoryPage[] = [ id: 'forty-sixth-sortie', bgm: 'battle-prep', chapter: '이릉 화공전', - background: 'story-sortie', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '육손의 화공망이 진영을 갈라 놓았소. 불타는 군막 사이로 퇴로를 열고, 흩어진 병사를 모아 서쪽 협곡으로 빠져나가시오.' @@ -3011,14 +3011,14 @@ export const fortySixthBattleVictoryPages: StoryPage[] = [ id: 'forty-sixth-victory-fire-broken', bgm: 'story-dark', chapter: '불길을 뚫은 길', - background: 'story-sortie', + background: 'story-yiling-baidi', text: '불타는 군막 사이로 좁은 퇴로가 열렸습니다. 승리라 부르기에는 잃은 것이 많았지만, 유비의 깃발은 완전히 꺼지지 않았습니다.' }, { id: 'forty-sixth-retreat-baidi', bgm: 'story-dark', chapter: '백제성으로', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '제갈량', text: '이릉의 불길은 복수의 속도를 꺾었습니다. 남은 병사들은 백제성으로 물러나며, 촉한의 다음 길이 전장에서 조정과 후계로 옮겨가고 있음을 느꼈습니다.' }, @@ -3026,7 +3026,7 @@ export const fortySixthBattleVictoryPages: StoryPage[] = [ id: 'forty-sixth-next-baidi', bgm: 'story-dark', chapter: '남은 뜻', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '뜻을 세운 날은 멀어졌고, 손에 남은 것은 불탄 깃발뿐이오. 그러나 남은 이들이 있다면 뜻도 아직 끝나지 않았소. 다음 장에서는 백제성에서 남은 나라의 길을 정해야 하오.' @@ -3038,7 +3038,7 @@ export const baidiEntrustmentPages: StoryPage[] = [ id: 'baidi-entrustment-arrival', bgm: 'story-dark', chapter: '백제성의 밤', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '제갈량', text: '이릉의 불길을 지나 백제성에 닿은 촉한군은 승전의 북소리 대신 낮은 숨소리로 밤을 맞았습니다. 전장은 멀어졌지만, 나라가 잃은 무게는 성 안까지 따라왔습니다.' }, @@ -3046,7 +3046,7 @@ export const baidiEntrustmentPages: StoryPage[] = [ id: 'baidi-entrustment-liu-bei', bgm: 'story-dark', chapter: '남은 말', - background: 'story-liu-bei', + background: 'story-yiling-baidi', speaker: '유비', portrait: 'liuBei', text: '내가 사람을 얻어 나라를 세웠으나, 분노를 이기지 못해 사람을 잃었소. 공명, 남은 촉한을 그대에게 부탁하오. 후주가 따를 만하면 보필하고, 부족하면 나라의 뜻을 먼저 보시오.' @@ -3055,7 +3055,7 @@ export const baidiEntrustmentPages: StoryPage[] = [ id: 'baidi-entrustment-zhuge', bgm: 'battle-prep', chapter: '받아 든 짐', - background: 'story-three-heroes', + background: 'story-yiling-baidi', speaker: '제갈량', text: '신은 감히 두 마음을 품지 않겠습니다. 폐하께서 남기신 뜻이 백성에게 닿을 때까지, 군영의 장부와 조정의 붓과 전장의 깃발을 모두 놓지 않겠습니다.' }, @@ -3063,7 +3063,7 @@ export const baidiEntrustmentPages: StoryPage[] = [ id: 'baidi-entrustment-officers', bgm: 'militia-theme', chapter: '새 질서', - background: 'story-sortie', + background: 'story-yiling-baidi', speaker: '조운', text: '장수들은 백제성 뜰에서 조용히 군례를 올렸습니다. 이제 유비의 분노가 남긴 상처를 수습하고, 제갈량을 중심으로 촉한의 다음 길을 다시 세워야 합니다.' }, @@ -3071,7 +3071,7 @@ export const baidiEntrustmentPages: StoryPage[] = [ id: 'baidi-entrustment-next', bgm: 'story-dark', chapter: '남쪽의 불안', - background: 'story-militia', + background: 'story-yiling-baidi', speaker: '황권', text: '이릉의 패전 뒤 촉한은 안팎으로 흔들리고 있습니다. 남중의 불안과 북방의 압박을 동시에 볼 수는 없습니다. 먼저 나라 안을 다독이고, 흩어진 장수들의 마음을 모아야 합니다.' } @@ -3082,7 +3082,7 @@ export const fortySeventhBattleIntroPages: StoryPage[] = [ id: 'forty-seventh-southern-unrest', bgm: 'story-dark', chapter: '남중의 흔들림', - background: 'story-militia', + background: 'story-nanzhong', speaker: '황권', text: '백제성의 유탁 뒤 촉한은 아직 상처를 다 씻지 못했습니다. 그러나 남중의 여러 호족과 반란군은 바로 그 틈을 보며, 성도 남쪽의 길과 창고를 흔들기 시작했습니다.' }, @@ -3090,7 +3090,7 @@ export const fortySeventhBattleIntroPages: StoryPage[] = [ id: 'forty-seventh-zhuge-policy', bgm: 'battle-prep', chapter: '먼저 안을 다스리다', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '북방을 논하기 전에 나라 안의 불안을 먼저 다스려야 합니다. 남중을 힘으로만 누르면 길은 열려도 마음은 닫힙니다. 반란의 길목을 끊고, 마을과 창고는 살려 두십시오.' }, @@ -3098,7 +3098,7 @@ export const fortySeventhBattleIntroPages: StoryPage[] = [ id: 'forty-seventh-zhao-yun-vanguard', bgm: 'battle-prep', chapter: '남쪽 길의 선봉', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '조운', text: '산길과 숲길이 겹친 전장이라 기병만 앞세울 수 없습니다. 왕평이 길을 보고, 황권이 보급을 재며, 마량이 마을의 말을 들어야 합니다. 저는 뒤처진 부대를 회수하겠습니다.' }, @@ -3106,7 +3106,7 @@ export const fortySeventhBattleIntroPages: StoryPage[] = [ id: 'forty-seventh-sortie', bgm: 'battle-prep', chapter: '남중 안정로', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '제갈량', text: '옹개와 남중 반란군이 밀림 길목에 진을 쳤습니다. 반란군 지휘선을 흩뜨리고, 마을과 창고를 확보해 남중 평정의 첫 발판을 세우십시오.' } @@ -3117,14 +3117,14 @@ export const fortySeventhBattleVictoryPages: StoryPage[] = [ id: 'forty-seventh-victory-road-opened', bgm: 'militia-theme', chapter: '남쪽 길이 열리다', - background: 'story-sortie', + background: 'story-nanzhong', text: '밀림과 산길 사이의 반란군 지휘선이 흔들렸습니다. 촉한군은 마을을 약탈하지 않고 창고를 정리하며, 남중 평정이 단순한 추격전이 아님을 병사들에게 보였습니다.' }, { id: 'forty-seventh-meng-huo-shadow', bgm: 'story-dark', chapter: '더 깊은 산', - background: 'story-militia', + background: 'story-nanzhong', speaker: '왕평', text: '옹개의 선봉은 물러났지만 남중의 산은 아직 깊습니다. 맹획의 이름이 여러 마을 사이에서 오가고 있고, 힘으로 꺾은 길 뒤에는 설득해야 할 마음이 남아 있습니다.' }, @@ -3132,7 +3132,7 @@ export const fortySeventhBattleVictoryPages: StoryPage[] = [ id: 'forty-seventh-next-nanman', bgm: 'story-dark', chapter: '남만 평정의 시작', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '첫 길은 열렸습니다. 이제 남중의 여러 세력을 모두 적으로 만들지 않으면서, 반란의 중심을 하나씩 마주해야 합니다. 다음 장에서는 맹획의 본대와 처음으로 맞섭니다.' } @@ -3143,7 +3143,7 @@ export const fortyEighthBattleIntroPages: StoryPage[] = [ id: 'forty-eighth-meng-huo-gathers', bgm: 'story-dark', chapter: '맹획의 깃발', - background: 'story-militia', + background: 'story-nanzhong', speaker: '왕평', text: '옹개의 지휘선은 흩어졌지만 남중의 마을들은 아직 촉한군을 멀리서 바라봅니다. 깊은 숲 안쪽에서는 맹획이 여러 호족을 모아, 첫 패배를 갚겠다고 병력을 다시 세우고 있습니다.' }, @@ -3151,7 +3151,7 @@ export const fortyEighthBattleIntroPages: StoryPage[] = [ id: 'forty-eighth-zhuge-amnesty', bgm: 'battle-prep', chapter: '힘과 회유', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '맹획을 쓰러뜨리는 것만으로는 남중을 얻을 수 없습니다. 반드시 생포하여 돌려보낼 길을 남기십시오. 마을과 포로 수용소를 지키면, 다음 싸움에서 칼보다 말이 먼저 닿을 것입니다.' }, @@ -3159,7 +3159,7 @@ export const fortyEighthBattleIntroPages: StoryPage[] = [ id: 'forty-eighth-sortie', bgm: 'battle-prep', chapter: '맹획 본대전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '마량', text: '맹획의 본대는 숲길, 늪지, 산채를 함께 쓰고 있습니다. 조운과 마초가 돌격을 막고, 왕평이 지형을 읽으며, 황권이 포로와 군량의 장부를 흐트러뜨리지 않아야 합니다.' } @@ -3170,14 +3170,14 @@ export const fortyEighthBattleVictoryPages: StoryPage[] = [ id: 'forty-eighth-victory-captured', bgm: 'militia-theme', chapter: '첫 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획의 본대는 흩어졌고, 촉한군은 산채의 불길을 키우지 않은 채 포로와 마을 사람을 갈라 세웠습니다. 병사들은 적장을 베지 않고 생포하는 싸움이 왜 어려운지 처음으로 깨달았습니다.' }, { id: 'forty-eighth-victory-release', bgm: 'story-dark', chapter: '돌려보내는 책략', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '맹획은 아직 진심으로 굴복하지 않았습니다. 그러나 억지 항복은 오래가지 않습니다. 오늘은 그를 돌려보내 남중의 사람들에게 촉한군이 약탈하러 온 군대가 아님을 보이겠습니다.' }, @@ -3185,7 +3185,7 @@ export const fortyEighthBattleVictoryPages: StoryPage[] = [ id: 'forty-eighth-next-capture', bgm: 'story-dark', chapter: '칠종칠금의 첫 장', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '맹획은 풀려났으나 산속의 호족들은 이제 촉한군의 태도를 보았습니다. 다음 싸움부터는 힘뿐 아니라 누구를 먼저 달래고 누구를 끝까지 추격할지 선택해야 합니다.' } @@ -3196,7 +3196,7 @@ export const fortyNinthBattleIntroPages: StoryPage[] = [ id: 'forty-ninth-meng-huo-returns', bgm: 'story-dark', chapter: '돌아온 맹획', - background: 'story-militia', + background: 'story-nanzhong', speaker: '왕평', text: '맹획은 풀려나자마자 다시 산채를 모았습니다. 그러나 지난 싸움과 달리 마을 사람들은 촉한군이 약탈하지 않았다는 사실을 알고 있습니다. 이번 싸움은 그 마음의 흔들림을 전장 위에서 붙잡는 일입니다.' }, @@ -3204,7 +3204,7 @@ export const fortyNinthBattleIntroPages: StoryPage[] = [ id: 'forty-ninth-second-capture-plan', bgm: 'battle-prep', chapter: '두 번째 생포', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번에도 베어서는 안 됩니다. 강가의 늪지와 산채 길목을 끊어 맹획을 다시 생포하고, 마을과 포로장을 지켜 그가 돌아갈 때 들을 말까지 남겨 두십시오.' }, @@ -3212,7 +3212,7 @@ export const fortyNinthBattleIntroPages: StoryPage[] = [ id: 'forty-ninth-sortie', bgm: 'battle-prep', chapter: '칠종칠금 2차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '마량', text: '맹획은 이번에 매복과 주술사를 앞세웠습니다. 왕평이 길을 읽고, 황권이 포로 장부를 지키며, 조운과 황충이 돌격과 고지 궁병을 끊어야 합니다. 회유의 말은 전열이 버텨야 닿습니다.' } @@ -3223,14 +3223,14 @@ export const fortyNinthBattleVictoryPages: StoryPage[] = [ id: 'forty-ninth-victory-second-capture', bgm: 'militia-theme', chapter: '두 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 다시 포위되었고, 이번에도 촉한군은 진영을 불태우지 않았습니다. 포로장은 닫혔지만 약탈은 없었고, 마을 사람들은 어느 군대가 오래 남을 수 있는지를 보기 시작했습니다.' }, { id: 'forty-ninth-victory-release-again', bgm: 'story-dark', chapter: '다시 풀어 보내다', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '두 번 잡아도 마음이 굽지 않는다면 다시 놓아 보낼 뿐입니다. 다만 이번에는 그가 돌아가는 길마다 촉한군이 지킨 마을과 포로들이 그의 말을 시험할 것입니다.' }, @@ -3238,7 +3238,7 @@ export const fortyNinthBattleVictoryPages: StoryPage[] = [ id: 'forty-ninth-next-southern-minds', bgm: 'story-dark', chapter: '남중의 마음', - background: 'story-militia', + background: 'story-nanzhong', speaker: '황권', text: '포로 명부와 군량 장부가 어긋나지 않았습니다. 다음 싸움에서는 맹획만이 아니라 그를 따르는 호족들의 마음도 흔들릴 것입니다. 회유는 이제 전투 뒤의 일이 아니라 전투 중의 목표가 되었습니다.' } @@ -3249,7 +3249,7 @@ export const fiftiethBattleIntroPages: StoryPage[] = [ id: 'fiftieth-southern-clans-waver', bgm: 'story-dark', chapter: '흔들리는 호족들', - background: 'story-militia', + background: 'story-nanzhong', speaker: '황권', text: '맹획이 두 번 붙잡혔다가 풀려나자 남중의 호족들은 서로 다른 말을 하기 시작했습니다. 어떤 이는 촉한군의 군율을 두려워했고, 어떤 이는 맹획이 아직 꺾이지 않았다고 외쳤습니다.' }, @@ -3257,7 +3257,7 @@ export const fiftiethBattleIntroPages: StoryPage[] = [ id: 'fiftieth-third-capture-plan', bgm: 'battle-prep', chapter: '세 번째 회유', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번 싸움에서는 맹획만 다시 잡아서는 부족합니다. 그를 따르는 호족들이 보는 앞에서 마을과 포로장을 지키고, 회유를 받아들일 길을 전장 안에 남겨야 합니다.' }, @@ -3265,7 +3265,7 @@ export const fiftiethBattleIntroPages: StoryPage[] = [ id: 'fiftieth-sortie', bgm: 'battle-prep', chapter: '칠종칠금 3차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '왕평', text: '산채는 더 깊고 늪지는 더 넓습니다. 마량이 호족의 말을 붙잡고, 황권이 장부를 흔들리지 않게 하며, 조운과 마초가 돌격을 막아야 맹획을 세 번째로 생포할 수 있습니다.' } @@ -3276,14 +3276,14 @@ export const fiftiethBattleVictoryPages: StoryPage[] = [ id: 'fiftieth-victory-third-capture', bgm: 'militia-theme', chapter: '세 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 세 번째로 붙잡혔고, 그의 곁에 있던 호족들은 촉한군이 이번에도 마을을 태우지 않았다는 사실을 직접 보았습니다. 전장의 승리는 이제 남중 사람들의 말 속으로 번지기 시작했습니다.' }, { id: 'fiftieth-victory-clan-choice', bgm: 'story-dark', chapter: '호족의 흔들림', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '몇몇 촌장은 더 싸워도 마을이 남지 않는다고 말하기 시작했습니다. 그러나 맹획은 아직 고개를 숙이지 않았습니다. 그를 다시 풀어 보내면, 이번에는 남중의 호족들이 먼저 서로를 설득할 것입니다.' }, @@ -3291,7 +3291,7 @@ export const fiftiethBattleVictoryPages: StoryPage[] = [ id: 'fiftieth-next-persuasive-camp', bgm: 'story-dark', chapter: '전장 밖의 회유', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '남중을 얻는 길은 점점 분명해지고 있습니다. 다음 장에서는 맹획을 따르던 호족들과 직접 이야기를 나누고, 전투 전 선택이 전장 목표에 영향을 주는 흐름을 준비해야 합니다.' } @@ -3302,7 +3302,7 @@ export const fiftyFirstBattleIntroPages: StoryPage[] = [ id: 'fifty-first-clan-council-result', bgm: 'story-dark', chapter: '회유가 전장으로', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '호족 회의 뒤 일부 촌장은 맹획을 따르되 끝까지 싸우지는 않겠다고 속내를 보였습니다. 그들이 물러날 길을 남겨 두면 다음 전투는 섬멸보다 설득에 가까워질 것입니다.' }, @@ -3310,7 +3310,7 @@ export const fiftyFirstBattleIntroPages: StoryPage[] = [ id: 'fifty-first-fourth-capture-plan', bgm: 'battle-prep', chapter: '네 번째 생포', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번에는 맹획의 본영뿐 아니라 오돌골의 등갑병과 독천 제사장들이 전장을 뒤덮을 것입니다. 화덕과 독천을 함부로 건드리지 말고, 회유 퇴로와 마을 보증을 함께 지키십시오.' }, @@ -3318,7 +3318,7 @@ export const fiftyFirstBattleIntroPages: StoryPage[] = [ id: 'fifty-first-sortie', bgm: 'battle-prep', chapter: '칠종칠금 4차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '왕평', text: '숲길은 더 좁고 강물은 더 깊습니다. 마량이 호족의 말을 붙잡고, 황권이 보증 장부를 지키며, 왕평과 마대가 열어 둔 산길을 따라 맹획을 네 번째 생포해야 합니다.' } @@ -3329,14 +3329,14 @@ export const fiftyFirstBattleVictoryPages: StoryPage[] = [ id: 'fifty-first-victory-fourth-capture', bgm: 'militia-theme', chapter: '네 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 네 번째로 포위되었고, 등갑병의 화덕과 독천 제사장들은 마을까지 밀려오지 못했습니다. 회유 퇴로로 물러난 호족들은 촉한군이 약속한 길을 지켰다는 사실을 직접 보았습니다.' }, { id: 'fifty-first-victory-amnesty-route', bgm: 'story-dark', chapter: '열어 둔 길', - background: 'story-militia', + background: 'story-nanzhong', speaker: '황권', text: '돌아간 자와 끝까지 싸운 자의 이름이 장부에 나뉘었습니다. 이제 남중의 호족들은 맹획의 고집만이 아니라, 촉한군의 약속이 지켜지는지도 함께 따지게 될 것입니다.' }, @@ -3344,7 +3344,7 @@ export const fiftyFirstBattleVictoryPages: StoryPage[] = [ id: 'fifty-first-next-deeper-nanzhong', bgm: 'story-dark', chapter: '더 깊은 남중', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '네 번 잡아도 맹획은 아직 남중 전체의 마음을 대표한다고 말합니다. 그렇다면 더 깊은 산채와 더 어려운 조건 앞에서도 같은 군율을 지켜 보여야 합니다.' } @@ -3355,7 +3355,7 @@ export const fiftySecondBattleIntroPages: StoryPage[] = [ id: 'fifty-second-hardliner-split', bgm: 'story-dark', chapter: '강경파의 갈라짐', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '네 번째 회유 뒤 일부 호족은 맹획의 깃발 아래 남아 있으면서도 마을을 지키는 길을 찾고 있습니다. 반대로 강경파는 그 길을 배신이라 부르며 퇴로를 끊으려 합니다.' }, @@ -3363,7 +3363,7 @@ export const fiftySecondBattleIntroPages: StoryPage[] = [ id: 'fifty-second-fifth-capture-plan', bgm: 'battle-prep', chapter: '다섯 번째 생포', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번 전투는 맹획을 다시 잡는 것만으로는 부족합니다. 강경파 호족을 본대와 분리하고, 회유 길목과 마을 보증을 동시에 지키면 남중 안에서 싸움을 그만둘 명분이 더 커질 것입니다.' }, @@ -3371,7 +3371,7 @@ export const fiftySecondBattleIntroPages: StoryPage[] = [ id: 'fifty-second-sortie', bgm: 'battle-prep', chapter: '칠종칠금 5차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '왕평', text: '깊은 죽림과 협곡이 이어져 있습니다. 장수마다 맡을 길이 다릅니다. 마량과 황권은 말을 남기고, 왕평과 마대는 물러날 길을 열며, 조운과 황충은 추격을 막아야 합니다.' } @@ -3382,14 +3382,14 @@ export const fiftySecondBattleVictoryPages: StoryPage[] = [ id: 'fifty-second-victory-fifth-capture', bgm: 'militia-theme', chapter: '다섯 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 다섯 번째로 포위되었고, 강경파 호족은 본대와 갈라졌습니다. 촉한군은 다시 마을과 퇴로를 지켰고, 돌아간 자들은 이제 맹획의 말만 듣지 않게 되었습니다.' }, { id: 'fifty-second-victory-hardliner-ledger', bgm: 'story-dark', chapter: '갈라진 장부', - background: 'story-militia', + background: 'story-nanzhong', speaker: '황권', text: '끝까지 싸운 자와 물러난 자의 이름이 더 분명해졌습니다. 처벌의 장부가 아니라 약속의 장부로 남겨야 합니다. 그래야 다음 석방도 군율을 잃지 않습니다.' }, @@ -3397,7 +3397,7 @@ export const fiftySecondBattleVictoryPages: StoryPage[] = [ id: 'fifty-second-next-sixth-capture', bgm: 'story-dark', chapter: '여섯 번째 길', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '남중의 마음은 점점 흔들리고 있습니다. 그러나 맹획의 자존심은 아직 마지막 벽처럼 남아 있습니다. 다음 싸움에서는 그 자존심을 꺾되, 남중 전체를 꺾지는 말아야 합니다.' } @@ -3408,7 +3408,7 @@ export const fiftyThirdBattleIntroPages: StoryPage[] = [ id: 'fifty-third-pride-remains', bgm: 'story-dark', chapter: '남은 자존심', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '다섯 번째 생포 뒤 강경파와 물러설 호족의 말이 갈라졌습니다. 그러나 맹획은 아직 남중의 자존심을 내세우며, 마지막으로 깊은 계곡의 부족들을 불러 모았습니다.' }, @@ -3416,7 +3416,7 @@ export const fiftyThirdBattleIntroPages: StoryPage[] = [ id: 'fifty-third-sixth-capture-plan', bgm: 'battle-prep', chapter: '여섯 번째 생포', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번에는 적을 밀어붙이는 힘보다 멈춰 설 줄 아는 군율이 중요합니다. 마을 신뢰를 지키고 강경파 잔당의 길을 끊되, 맹획에게 남중 전체가 더는 같은 마음이 아님을 보이십시오.' }, @@ -3424,7 +3424,7 @@ export const fiftyThirdBattleIntroPages: StoryPage[] = [ id: 'fifty-third-sortie', bgm: 'battle-prep', chapter: '칠종칠금 6차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '황권', text: '계곡 길은 넓어 보이나 물길과 절벽이 칼처럼 갈라져 있습니다. 장부를 들 장수, 산길을 지킬 장수, 추격을 멈출 장수를 따로 세워야 여섯 번째 생포가 설득으로 남습니다.' } @@ -3435,14 +3435,14 @@ export const fiftyThirdBattleVictoryPages: StoryPage[] = [ id: 'fifty-third-victory-sixth-capture', bgm: 'militia-theme', chapter: '여섯 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 여섯 번째로 붙잡혔고, 깊은 계곡의 부족들은 촉한군이 강경파 잔당을 누르면서도 마을을 함부로 밟지 않는 모습을 보았습니다.' }, { id: 'fifty-third-victory-trust-ledger', bgm: 'story-dark', chapter: '신뢰의 장부', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '처음에는 두려워 숨던 촌장들이 이제는 직접 이름을 말했습니다. 두려움의 장부가 아니라 신뢰의 장부가 만들어졌으니, 마지막 설득의 말도 조금은 닿을 수 있습니다.' }, @@ -3450,7 +3450,7 @@ export const fiftyThirdBattleVictoryPages: StoryPage[] = [ id: 'fifty-third-next-final-capture', bgm: 'story-dark', chapter: '마지막 설득 앞', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '여섯 번 잡고도 맹획은 쉽게 항복하지 않을 것입니다. 그러나 이제 남중의 눈은 맹획의 고집뿐 아니라 촉한군의 약속도 함께 보고 있습니다. 다음은 칠종칠금의 마지막 문턱입니다.' } @@ -3461,7 +3461,7 @@ export const fiftyFourthBattleIntroPages: StoryPage[] = [ id: 'fifty-fourth-final-council', bgm: 'story-dark', chapter: '마지막 문턱', - background: 'story-militia', + background: 'story-nanzhong', speaker: '마량', text: '여섯 번째 생포 뒤 남중의 촌장들은 더는 맹획의 말만 듣지 않았습니다. 그러나 맹획은 마지막 자존심을 걸고, 모든 부족 앞에서 다시 한 번 싸워 보자고 외쳤습니다.' }, @@ -3469,7 +3469,7 @@ export const fiftyFourthBattleIntroPages: StoryPage[] = [ id: 'fifty-fourth-seventh-capture-plan', bgm: 'battle-prep', chapter: '일곱 번째 생포', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '제갈량', text: '이번 싸움은 남중을 꺾는 전투가 아니라 남중이 스스로 고개를 끄덕이게 만드는 전투입니다. 맹획을 마지막으로 생포하되, 회의장과 마을, 신뢰 장부를 모두 지키십시오.' }, @@ -3477,7 +3477,7 @@ export const fiftyFourthBattleIntroPages: StoryPage[] = [ id: 'fifty-fourth-sortie', bgm: 'battle-prep', chapter: '칠종칠금 7차전', - background: 'story-sortie', + background: 'story-nanzhong', speaker: '왕평', text: '마지막 전장은 길이 많아 보이지만, 잘못 밀고 들어가면 촌장들이 보는 앞에서 군율을 잃게 됩니다. 빠른 장수는 추격을 멈추고, 문사는 약속을 남기며, 전열은 회의장을 지켜야 합니다.' } @@ -3488,14 +3488,14 @@ export const fiftyFourthBattleVictoryPages: StoryPage[] = [ id: 'fifty-fourth-victory-seventh-capture', bgm: 'militia-theme', chapter: '일곱 번째 생포', - background: 'story-sortie', + background: 'story-nanzhong', text: '맹획은 일곱 번째로 포위되었습니다. 그러나 이번에는 포로장의 침묵이 아니라, 촌장들의 눈앞에서 지켜진 약속과 무너진 고집이 함께 남았습니다.' }, { id: 'fifty-fourth-victory-meng-huo-yields', bgm: 'story-dark', chapter: '맹획의 항복', - background: 'story-three-heroes', + background: 'story-nanzhong', speaker: '맹획', text: '일곱 번 잡히고 일곱 번 풀려도 그대들은 남중의 백성을 짓밟지 않았다. 이제는 내가 졌음을 인정하겠다. 남중의 길은 촉한의 길과 함께하겠다.' }, @@ -3503,7 +3503,7 @@ export const fiftyFourthBattleVictoryPages: StoryPage[] = [ id: 'fifty-fourth-nanzhong-pacified', bgm: 'story-dark', chapter: '남중 평정', - background: 'story-militia', + background: 'story-nanzhong', speaker: '제갈량', text: '남중은 힘으로만 묶인 땅이 아닙니다. 약속을 지킨 뒤 얻은 땅입니다. 이제 촉한은 뒤를 안정시키고, 북쪽을 바라볼 준비를 시작해야 합니다.' } @@ -3514,7 +3514,7 @@ export const northernCampaignPrepPages: StoryPage[] = [ id: 'northern-prep-back-secured', bgm: 'story-dark', chapter: '북벌 준비', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '남중이 안정되었으니 촉한의 뒤는 흔들림을 줄였습니다. 이제 한중의 창고, 익주의 장부, 장수들의 출전 순서를 다시 맞추어 북쪽으로 향할 때를 준비하겠습니다.' }, @@ -3522,7 +3522,7 @@ export const northernCampaignPrepPages: StoryPage[] = [ id: 'northern-prep-roster-council', bgm: 'battle-prep', chapter: '무장 재편', - background: 'story-sortie', + background: 'story-northern', speaker: '조운', text: '북쪽 길은 남중과 다릅니다. 산길을 읽는 장수, 보급을 세는 문관, 기병을 끊는 전열이 함께 움직여야 합니다. 다음 출진부터는 누가 먼저 나설지 더 신중히 고르겠습니다.' }, @@ -3530,7 +3530,7 @@ export const northernCampaignPrepPages: StoryPage[] = [ id: 'northern-prep-long-war', bgm: 'militia-theme', chapter: '긴 전쟁의 문턱', - background: 'story-three-heroes', + background: 'story-northern', speaker: '황권', text: '북벌은 한 번의 승리로 끝나는 길이 아닙니다. 군량과 대기 무장의 훈련, 공명 관계까지 모두 장부에 남겨야 오래 버틸 수 있습니다.' } @@ -3541,7 +3541,7 @@ export const fiftyFifthBattleIntroPages: StoryPage[] = [ id: 'fifty-fifth-qishan-road-opens', bgm: 'story-dark', chapter: '제1차 북벌', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '남중이 평정되자 촉한의 군량과 길이 비로소 북쪽을 향할 수 있게 되었습니다. 그러나 북벌은 단번에 끝나는 싸움이 아닙니다. 먼저 기산으로 향하는 산길과 한중 보급로를 동시에 붙잡아야 합니다.' }, @@ -3549,7 +3549,7 @@ export const fiftyFifthBattleIntroPages: StoryPage[] = [ id: 'fifty-fifth-sortie-council', bgm: 'battle-prep', chapter: '기산 출진로', - background: 'story-sortie', + background: 'story-northern', speaker: '조운', text: '승상께서 직접 지휘하신다면 유비공의 이름만으로 밀어붙이던 때와는 달라집니다. 산길을 여는 무장, 보급을 지킬 문관, 기병을 막을 추격대까지 골라야 합니다. 누구를 함께 데려갈지가 곧 전투의 반입니다.' }, @@ -3557,7 +3557,7 @@ export const fiftyFifthBattleIntroPages: StoryPage[] = [ id: 'fifty-fifth-wei-vanguard', bgm: 'battle-prep', chapter: '위군 선봉', - background: 'story-three-heroes', + background: 'story-northern', speaker: '황권', text: '조진이 전초 부대를 앞세워 기산의 입구와 마을, 보급 거점을 눌러 두었습니다. 길을 뚫는 것만으로는 부족합니다. 산길을 확보하고, 마을을 안정시키며, 한중으로 이어지는 보급 거점을 지켜야 합니다.' } @@ -3568,14 +3568,14 @@ export const fiftyFifthBattleVictoryPages: StoryPage[] = [ id: 'fifty-fifth-victory-road-secured', bgm: 'militia-theme', chapter: '기산 출진로 확보', - background: 'story-sortie', + background: 'story-northern', text: '조진의 전초 부대는 물러났고, 기산으로 이어지는 산길에는 촉한의 깃발이 세워졌습니다. 한중 보급대도 길을 잃지 않았으며, 마을 사람들은 북벌군이 약탈자가 아니라 질서를 세우는 군대임을 보았습니다.' }, { id: 'fifty-fifth-victory-northern-front', bgm: 'story-dark', chapter: '북벌의 첫 발', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '첫 길은 열렸으나, 위나라의 본대는 아직 물러나지 않았습니다. 이제부터는 전투 하나하나가 촉한의 국력을 갉아먹는 긴 싸움이 됩니다. 무장들의 배치와 공명, 보급의 선택이 더 중요해질 것입니다.' }, @@ -3583,7 +3583,7 @@ export const fiftyFifthBattleVictoryPages: StoryPage[] = [ id: 'fifty-fifth-next-front', bgm: 'story-dark', chapter: '천수 방면의 기척', - background: 'story-three-heroes', + background: 'story-northern', speaker: '마량', text: '기산 길목을 지나자 천수 방면에서 새로운 소문이 들어옵니다. 위군 안에서도 촉한의 북벌을 가볍게 보지 않는 장수들이 움직이고 있습니다. 다음 진군은 더 넓은 전선과 더 어려운 선택을 요구할 것입니다.' } @@ -3594,7 +3594,7 @@ export const fiftySixthBattleIntroPages: StoryPage[] = [ id: 'fifty-sixth-tianshui-rumor', bgm: 'story-dark', chapter: '천수 방면', - background: 'story-militia', + background: 'story-northern', speaker: '마량', text: '기산 길목을 확보하자 천수와 가정 사이의 성들이 급히 봉화를 올렸습니다. 위군은 조진의 전초대가 물러난 틈을 곽회에게 맡기고, 젊은 장수 강유가 산길의 허점을 살피고 있다고 합니다.' }, @@ -3602,7 +3602,7 @@ export const fiftySixthBattleIntroPages: StoryPage[] = [ id: 'fifty-sixth-qishan-council', bgm: 'battle-prep', chapter: '진군로 재편', - background: 'story-sortie', + background: 'story-northern', speaker: '제갈량', text: '북벌은 빠르게 밀어붙이는 것보다 끊기지 않는 것이 중요합니다. 조운은 우회로를 보고, 황권과 마량은 마을과 창고를 묶고, 왕평은 가정으로 이어지는 고개를 살펴 주십시오.' }, @@ -3610,7 +3610,7 @@ export const fiftySixthBattleIntroPages: StoryPage[] = [ id: 'fifty-sixth-jiang-wei-shadow', bgm: 'battle-prep', chapter: '젊은 장수의 그림자', - background: 'story-three-heroes', + background: 'story-northern', speaker: '조운', text: '강유라는 장수는 평범한 수비장이 아닙니다. 정면에서만 치면 곽회의 방어선에 묶이고, 너무 깊이 들어가면 가정 방면의 퇴로가 끊깁니다. 이번 싸움은 적장 하나보다 전선 전체를 읽는 싸움이 되겠습니다.' } @@ -3621,14 +3621,14 @@ export const fiftySixthBattleVictoryPages: StoryPage[] = [ id: 'fifty-sixth-victory-tianshui-road', bgm: 'militia-theme', chapter: '천수 진군로 확보', - background: 'story-sortie', + background: 'story-northern', text: '곽회의 방어선은 물러났고, 천수로 향하는 길에는 촉한군의 표식이 세워졌습니다. 그러나 강유의 움직임은 끝내 가볍지 않았고, 위군은 가정 방면으로 더 넓은 방어선을 펼치기 시작했습니다.' }, { id: 'fifty-sixth-victory-jiang-wei', bgm: 'story-dark', chapter: '강유의 이름', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '강유는 아직 우리의 사람이 아니지만, 그 재능은 전장 위에 분명히 드러났습니다. 억지로 꺾기보다 길을 남겨 두어야 합니다. 다음 전선에서는 사람을 얻는 일과 땅을 얻는 일이 함께 시험받을 것입니다.' }, @@ -3636,7 +3636,7 @@ export const fiftySixthBattleVictoryPages: StoryPage[] = [ id: 'fifty-sixth-next-jieting', bgm: 'story-dark', chapter: '가정의 불안', - background: 'story-three-heroes', + background: 'story-northern', speaker: '왕평', text: '가정으로 이어지는 고개는 생각보다 좁고 물길도 멀리 있습니다. 진영을 어디에 세우느냐에 따라 북벌 전체가 흔들릴 수 있습니다. 다음 전장은 승리보다 배치의 판단이 더 무겁게 다가올 것입니다.' } @@ -3647,7 +3647,7 @@ export const fiftySeventhBattleIntroPages: StoryPage[] = [ id: 'fifty-seventh-jieting-order', bgm: 'story-dark', chapter: '가정 방면', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '천수 길목은 열렸으나 가정의 고개가 흔들리면 북벌의 군량과 퇴로가 한꺼번에 끊깁니다. 높은 곳만 바라보는 진영은 오래 버티지 못합니다. 물길과 길목을 함께 지키십시오.' }, @@ -3655,7 +3655,7 @@ export const fiftySeventhBattleIntroPages: StoryPage[] = [ id: 'fifty-seventh-ma-su-insists', bgm: 'battle-prep', chapter: '마속의 주장', - background: 'story-sortie', + background: 'story-northern', speaker: '왕평', text: '마속은 고지를 잡으면 적이 감히 오르지 못한다고 말합니다. 그러나 고개 아래 물길과 수레 길을 잃으면 위군은 우리를 치지 않고도 말릴 수 있습니다. 이번 출전은 강한 장수보다 지형을 읽을 장수가 필요합니다.' }, @@ -3663,7 +3663,7 @@ export const fiftySeventhBattleIntroPages: StoryPage[] = [ id: 'fifty-seventh-jiang-wei-contact', bgm: 'battle-prep', chapter: '강유 접촉', - background: 'story-three-heroes', + background: 'story-northern', speaker: '마량', text: '천수에서 남긴 글이 강유에게 닿았습니다. 그는 아직 위군의 장수로 서 있지만, 싸움이 명분을 잃는 순간 마음이 흔들릴 것입니다. 가정의 길을 지키며 강유에게 돌아올 길도 남겨 두어야 합니다.' } @@ -3674,14 +3674,14 @@ export const fiftySeventhBattleVictoryPages: StoryPage[] = [ id: 'fifty-seventh-victory-jieting-held', bgm: 'militia-theme', chapter: '가정 방면 수습', - background: 'story-sortie', + background: 'story-northern', text: '장합의 선봉은 고개 아래에서 멈췄고, 촉한군은 가정의 물길과 수레 길을 간신히 잇는 데 성공했습니다. 마속의 고집은 큰 위험을 남겼지만, 왕평의 지형 판단이 북벌의 퇴로를 붙잡았습니다.' }, { id: 'fifty-seventh-victory-jiang-wei-joins', bgm: 'story-dark', chapter: '새 장수', - background: 'story-militia', + background: 'story-northern', speaker: '강유', text: '강유는 위군의 의심과 백성의 말 사이에서 끝내 마음을 정했습니다. 오늘부터 그는 촉한의 깃발 아래 서지만, 새로 얻은 장수 하나가 곧바로 모든 길을 열어 주지는 않습니다. 다음 출전부터는 더 넓어진 장수진 안에서 누구를 고를지 판단해야 합니다.' }, @@ -3689,7 +3689,7 @@ export const fiftySeventhBattleVictoryPages: StoryPage[] = [ id: 'fifty-seventh-next-front', bgm: 'story-dark', chapter: '북벌의 다음 부담', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '가정의 위기는 수습되었으나 위군은 이제 우리의 길과 사람을 모두 보았습니다. 강유를 얻은 기쁨과 마속의 실책을 함께 품고, 다음 북벌에서는 더 엄격한 편성과 보급 판단이 필요할 것입니다.' } @@ -3700,7 +3700,7 @@ export const fiftyEighthBattleIntroPages: StoryPage[] = [ id: 'fifty-eighth-qishan-retreat-council', bgm: 'story-dark', chapter: '기산 퇴각 명령', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '가정의 물길은 가까스로 지켰지만 북방의 군량 길은 이미 오래 늘어졌습니다. 지금 억지로 깊게 밀고 들어가면 승리가 아니라 고립을 얻게 됩니다. 기산으로 돌아가는 수레 길을 열고, 병사와 장부를 먼저 살려야 합니다.' }, @@ -3708,7 +3708,7 @@ export const fiftyEighthBattleIntroPages: StoryPage[] = [ id: 'fifty-eighth-jiang-wei-first-sortie', bgm: 'battle-prep', chapter: '강유의 첫 출전', - background: 'story-sortie', + background: 'story-northern', speaker: '강유', text: '제가 알던 천수의 낮은 길이 이제 촉한의 퇴로가 되었습니다. 아직 모두가 저를 믿지는 못하겠지만, 오늘은 말보다 길로 증명하겠습니다. 조운과 마대가 회수 길을 지키고, 왕평이 물길을 보면 위군의 추격을 끊을 수 있습니다.' }, @@ -3716,7 +3716,7 @@ export const fiftyEighthBattleIntroPages: StoryPage[] = [ id: 'fifty-eighth-sima-yi-shadow', bgm: 'story-dark', chapter: '새로운 그림자', - background: 'story-three-heroes', + background: 'story-northern', speaker: '마량', text: '장합의 추격만 막으면 끝나는 전장이 아닙니다. 위군 본영 뒤에서 사마의가 군량 수레가 어디로 빠지는지 보고 있습니다. 강유를 내보내면 길은 넓어지지만, 누군가는 조운이나 왕평의 자리를 양보해야 합니다.' } @@ -3727,14 +3727,14 @@ export const fiftyEighthBattleVictoryPages: StoryPage[] = [ id: 'fifty-eighth-victory-retreat-road', bgm: 'militia-theme', chapter: '기산 퇴로 확보', - background: 'story-sortie', + background: 'story-northern', text: '촉한군은 군량 수레를 잃지 않고 기산의 낮은 길로 물러났습니다. 장합의 추격은 물길 앞에서 꺾였고, 사마의의 본대는 더 깊게 들어오지 못했습니다. 패배를 승리로 꾸밀 수는 없지만, 다음 북벌을 위한 병사와 장부는 지켜냈습니다.' }, { id: 'fifty-eighth-victory-jiang-wei-reviewed', bgm: 'story-dark', chapter: '강유의 첫 평가', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '강유는 천수의 길을 숨기지 않았고, 조운과 마대는 병사들이 돌아올 시간을 벌었습니다. 왕평의 물길 판단도 여전히 군의 목숨줄입니다. 이제부터 출전 명단은 단순히 강한 장수를 고르는 일이 아니라, 어떤 길을 택할지 정하는 일이 됩니다.' }, @@ -3742,7 +3742,7 @@ export const fiftyEighthBattleVictoryPages: StoryPage[] = [ id: 'fifty-eighth-next-northern-plan', bgm: 'story-dark', chapter: '다음 북벌을 위하여', - background: 'story-three-heroes', + background: 'story-northern', speaker: '강유', text: '이번 후퇴로 저는 촉한의 군율과 병사들의 숨을 배웠습니다. 다음에는 물러나는 길이 아니라 나아가는 길을 열겠습니다. 승상께서 다시 북쪽을 보실 때, 제가 먼저 그 길을 살피겠습니다.' } @@ -3753,7 +3753,7 @@ export const fiftyNinthBattleIntroPages: StoryPage[] = [ id: 'fifty-ninth-chencang-order', bgm: 'story-dark', chapter: '진창 성채', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '기산에서 병사를 살렸기에 다시 북쪽을 볼 수 있습니다. 그러나 이번 길은 넓은 들이 아니라 진창의 굳은 성채입니다. 성문을 무리하게 깨기보다 공성 진영, 군량 수레, 퇴로를 함께 보아야 합니다.' }, @@ -3761,7 +3761,7 @@ export const fiftyNinthBattleIntroPages: StoryPage[] = [ id: 'fifty-ninth-hao-zhao-wall', bgm: 'battle-prep', chapter: '학소의 성벽', - background: 'story-sortie', + background: 'story-northern', speaker: '강유', text: '진창의 수비장 학소는 성을 버리지 않을 사람입니다. 제가 앞길을 살피겠습니다만, 성벽만 바라보면 왕쌍의 기병이 뒤를 물 것입니다. 조운, 마대, 왕평 중 누구를 앞으로 세우느냐가 이번 편성의 무게입니다.' }, @@ -3769,7 +3769,7 @@ export const fiftyNinthBattleIntroPages: StoryPage[] = [ id: 'fifty-ninth-supply-limit', bgm: 'story-dark', chapter: '군량의 시간', - background: 'story-three-heroes', + background: 'story-northern', speaker: '황권', text: '성채 하나에 오래 묶이면 북벌 전체가 굶습니다. 법정의 계책, 마량의 문서, 황권의 장부가 함께 있어야 공성전이 단순한 힘겨루기로 흐르지 않습니다. 진창을 압박하되 돌아갈 수 있는 시간을 남기십시오.' } @@ -3780,14 +3780,14 @@ export const fiftyNinthBattleVictoryPages: StoryPage[] = [ id: 'fifty-ninth-victory-chencang-pressure', bgm: 'militia-theme', chapter: '진창 압박', - background: 'story-sortie', + background: 'story-northern', text: '촉한군은 진창의 외곽 진영과 보급로를 흔들었지만, 학소의 성벽은 끝내 쉽게 열리지 않았습니다. 승리라 부르기에는 조심스럽고 패배라 덮기에는 얻은 길이 분명한 전투였습니다.' }, { id: 'fifty-ninth-victory-wang-shuang-cut', bgm: 'story-dark', chapter: '왕쌍 추격 차단', - background: 'story-militia', + background: 'story-northern', speaker: '조운', text: '왕쌍의 기병은 공성 진영 뒤를 물려 했으나, 강유의 길 안내와 마대의 우회, 왕평의 진영 표식이 먼저 움직였습니다. 오래 버티는 성을 상대로도 물러날 때를 정하는 장수가 필요합니다.' }, @@ -3795,7 +3795,7 @@ export const fiftyNinthBattleVictoryPages: StoryPage[] = [ id: 'fifty-ninth-next-northern-plan', bgm: 'story-dark', chapter: '다음 북방 계산', - background: 'story-three-heroes', + background: 'story-northern', speaker: '제갈량', text: '진창은 북벌의 끝이 아니라, 무리한 공세가 어디서 멈춰야 하는지를 보여 준 성입니다. 다음 출정에서는 성을 치는 힘뿐 아니라 군량이 버틸 날, 돌아올 길, 장수의 고집을 모두 함께 계산해야 합니다.' } @@ -3806,7 +3806,7 @@ export const sixtiethBattleIntroPages: StoryPage[] = [ id: 'sixtieth-wudu-yinping-order', bgm: 'story-dark', chapter: '무도와 음평', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '진창의 성벽은 오래 물고 늘어질 곳이 아니었습니다. 이번에는 성을 치기보다 무도와 음평의 산길을 나누어 잡아, 북방의 두 고을을 촉한의 숨통으로 만들겠습니다.' }, @@ -3814,7 +3814,7 @@ export const sixtiethBattleIntroPages: StoryPage[] = [ id: 'sixtieth-guo-huai-relief', bgm: 'battle-prep', chapter: '곽회의 구원로', - background: 'story-sortie', + background: 'story-northern', speaker: '강유', text: '곽회는 성을 지키는 장수가 아니라 길을 끊는 장수입니다. 제가 아는 천수 길로 앞을 보겠습니다. 다만 위연 장군의 돌파, 조운과 마대의 기병, 왕평의 산길 판단을 모두 한꺼번에 쓸 수는 없습니다.' }, @@ -3822,7 +3822,7 @@ export const sixtiethBattleIntroPages: StoryPage[] = [ id: 'sixtieth-two-commandery-supply', bgm: 'story-dark', chapter: '둘로 갈라진 보급', - background: 'story-three-heroes', + background: 'story-northern', speaker: '황권', text: '무도와 음평을 동시에 안정시키려면 장부가 둘로 갈라집니다. 마량이 마을을 달래고, 왕평이 산길 표식을 세우며, 누가 빠르게 치고 누가 멈출지 출전 전에 정해야 합니다.' } @@ -3833,14 +3833,14 @@ export const sixtiethBattleVictoryPages: StoryPage[] = [ id: 'sixtieth-victory-commanderies-secured', bgm: 'militia-theme', chapter: '두 고을 확보', - background: 'story-sortie', + background: 'story-northern', text: '촉한군은 무도와 음평의 길목을 차례로 눌러 곽회의 구원로를 늦췄습니다. 큰 성 하나를 무너뜨린 승리가 아니라, 북벌이 다시 숨 쉴 수 있는 산길을 확보한 승리였습니다.' }, { id: 'sixtieth-victory-jiangwei-weiyan-choice', bgm: 'story-dark', chapter: '돌파 뒤의 지도', - background: 'story-militia', + background: 'story-northern', speaker: '제갈량', text: '강유는 길을 읽었고 위연은 길이 열릴 때 망설이지 않았습니다. 하지만 둘이 함께 앞서갈수록 조운과 마대의 회수선, 왕평과 황권의 제동 장치가 더 중요해졌습니다.' }, @@ -3848,7 +3848,7 @@ export const sixtiethBattleVictoryPages: StoryPage[] = [ id: 'sixtieth-next-northern-plan', bgm: 'story-dark', chapter: '다음 북방 계산', - background: 'story-three-heroes', + background: 'story-northern', speaker: '마량', text: '무도와 음평의 백성에게는 오늘의 승리가 끝이 아니라 약속의 시작입니다. 다음 북벌에서는 얻은 땅을 지키는 장부와 다시 나아갈 장수의 마음을 함께 보아야 합니다.' } @@ -3859,7 +3859,7 @@ export const sixtyFirstBattleIntroPages: StoryPage[] = [ id: 'sixty-first-hanzhong-rain-warning', bgm: 'story-dark', chapter: '한중의 빗길', - background: 'story-three-heroes', + background: 'story-northern', speaker: '황권', text: '무도와 음평을 얻은 뒤부터 한중의 장부는 더 두꺼워졌습니다. 조진이 북문으로 내려오고, 사마의가 빗길을 따라 별동대를 움직이면 새 고을은 승리의 이름이 아니라 지켜야 할 짐이 됩니다.' }, @@ -3867,7 +3867,7 @@ export const sixtyFirstBattleIntroPages: StoryPage[] = [ id: 'sixty-first-cao-zhen-counteroffensive', bgm: 'battle-prep', chapter: '조진의 역공', - background: 'story-sortie', + background: 'story-northern', speaker: '제갈량', text: '이번에는 성을 치지 않습니다. 한중 북문의 창고, 무도와 음평으로 이어지는 수레 길, 그리고 비에 무너지는 고개를 함께 지켜야 합니다. 위연의 돌파와 강유의 길눈, 이엄과 황권의 보급 장부 중 무엇을 앞세울지 정하십시오.' }, @@ -3875,7 +3875,7 @@ export const sixtyFirstBattleIntroPages: StoryPage[] = [ id: 'sixty-first-two-commandery-burden', bgm: 'story-dark', chapter: '넓어진 책임', - background: 'story-militia', + background: 'story-northern', speaker: '마량', text: '백성은 촉한의 깃발만 보고 안심하지 않습니다. 비가 오면 수레는 늦고, 군문이 흔들리면 새 고을은 먼저 두려워합니다. 출전 명단에서 누가 길을 잡고 누가 장부를 지킬지 분명히 해야 합니다.' } @@ -3886,14 +3886,14 @@ export const sixtyFirstBattleVictoryPages: StoryPage[] = [ id: 'sixty-first-victory-rain-defense', bgm: 'militia-theme', chapter: '빗길을 막다', - background: 'story-sortie', + background: 'story-northern', text: '촉한군은 한중 북문의 창고를 비워 내지 않고 지켜 냈고, 무도와 음평으로 향하는 수레 길도 끊기지 않게 붙들었습니다. 조진의 역공은 빗길과 산길 사이에서 힘을 잃었습니다.' }, { id: 'sixty-first-victory-supply-responsibility', bgm: 'story-dark', chapter: '장부의 무게', - background: 'story-three-heroes', + background: 'story-northern', speaker: '이엄', text: '고을을 얻는 일보다 고을을 먹여 살리는 일이 더 오래 갑니다. 황권의 장부와 마량의 문서가 늦어지면, 강유와 위연이 아무리 앞에서 길을 열어도 뒤의 비명은 전선으로 돌아옵니다.' }, @@ -3901,7 +3901,7 @@ export const sixtyFirstBattleVictoryPages: StoryPage[] = [ id: 'sixty-first-next-northern-plan', bgm: 'story-dark', chapter: '다시 북쪽을 보다', - background: 'story-militia', + background: 'story-northern', speaker: '강유', text: '조진을 막아 냈지만 위의 북방은 한 번 물러난 것으로 끝나지 않습니다. 다음 출정에서는 지켜 낸 길을 다시 공격의 길로 바꿀 수 있는지, 그리고 그때 누구를 뒤에 남길지까지 따져야 합니다.' } diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 4fb4ee1..0f1cbdd 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -1026,6 +1026,13 @@ type BondState = BattleBond & { battleExp: number; }; +type BondCombatBonus = { + damageBonus: number; + chainRate: number; + label?: string; + partnerIds: string[]; +}; + type UnitBattleStats = { damageDealt: number; damageTaken: number; @@ -1146,6 +1153,7 @@ type CombatPreview = { damage: number; bondDamageBonus: number; bondLabel?: string; + bondPartnerIds: string[]; equipmentDamageBonus: number; equipmentDamageReduction: number; equipmentHitBonus: number; @@ -3289,8 +3297,8 @@ export class BattleScene extends Phaser.Scene { this.selectedUnit = undefined; this.pendingMove = undefined; this.phase = 'idle'; - this.clearMarkers(); this.hideCommandMenu(); + this.showEnemyUnitThreatRange(unit); this.renderUnitDetail(unit, this.enemyDetailMessage(unit)); return; } @@ -3377,7 +3385,8 @@ export class BattleScene extends Phaser.Scene { this.moveUnitView(unit, x, y, view); } this.showCommandMenu(unit, pointer?.x ?? targetX, pointer?.y ?? targetY); - this.renderUnitDetail(unit, '공격, 책략, 도구, 대기 중 하나를 선택하세요.\n우클릭하면 이동을 취소합니다.'); + const finalAllyHint = this.remainingAllyCount() === 1 ? '\n마지막 미행동 장수입니다. 대기를 선택하면 턴 종료 확인이 열립니다.' : ''; + this.renderUnitDetail(unit, `공격, 책략, 도구, 대기 중 하나를 선택하세요.\n우클릭하면 이동을 취소합니다.${finalAllyHint}`); } private canMoveTo(unit: UnitData, x: number, y: number) { @@ -3503,6 +3512,84 @@ export class BattleScene extends Phaser.Scene { ); } + private showEnemyUnitThreatRange(enemy: UnitData) { + this.clearMarkers(); + const behavior = this.enemyBehavior(enemy); + const moveTiles = this.reachableTiles(enemy); + const threatTiles = this.enemyThreatTilesFor(enemy, moveTiles); + + moveTiles.forEach((tile) => this.renderEnemyMoveMarker(enemy, tile.x, tile.y)); + threatTiles.forEach((tile) => this.renderEnemyUnitThreatMarker(enemy, tile.x, tile.y)); + this.renderSituationPanel( + [ + `${enemy.name} 대응 범위`, + `이동 ${moveTiles.length}칸 · 공격 ${threatTiles.length}칸`, + `${this.enemyBehaviorLabel(behavior)} 태세 · 이동 ${enemy.move} · 사거리 ${this.attackRange(enemy)}` + ].join('\n') + ); + } + + private enemyThreatTilesFor(enemy: UnitData, moveTiles = this.reachableTiles(enemy)) { + const threats = new Map(); + const origins = [{ x: enemy.x, y: enemy.y, cost: 0 }, ...moveTiles]; + const range = this.attackRange(enemy); + origins.forEach((origin) => { + this.tilesWithinDistance(origin.x, origin.y, range).forEach(({ x, y }) => { + if (!this.isThreatTargetTile(x, y, enemy.id)) { + return; + } + threats.set(this.tileKey(x, y), { x, y }); + }); + }); + return Array.from(threats.values()).sort((a, b) => a.y - b.y || a.x - b.x); + } + + private renderEnemyMoveMarker(enemy: UnitData, x: number, y: number) { + const marker = this.add.rectangle(this.tileTopLeftX(x), this.tileTopLeftY(y), this.layout.tileSize, this.layout.tileSize, palette.blue, 0.16); + marker.setData('tileX', x); + marker.setData('tileY', y); + marker.setData('markerType', 'enemy-move'); + marker.setOrigin(0); + marker.setStrokeStyle(1, palette.blue, 0.42); + marker.setDepth(4.15); + if (this.mapMask) { + marker.setMask(this.mapMask); + } + marker.setVisible(this.isTileVisible(x, y)); + marker.setInteractive({ useHandCursor: true }); + marker.on('pointerover', () => { + marker.setFillStyle(palette.blue, 0.26); + this.renderUnitDetail(enemy, `${this.enemyDetailMessage(enemy)}\n\n이동 가능 칸`); + }); + marker.on('pointerout', () => marker.setFillStyle(palette.blue, 0.16)); + marker.on('pointerdown', () => this.renderUnitDetail(enemy, `${this.enemyDetailMessage(enemy)}\n\n이동 가능 칸`)); + this.markers.push(marker); + } + + private renderEnemyUnitThreatMarker(enemy: UnitData, x: number, y: number) { + const behavior = this.enemyBehavior(enemy); + const color = this.threatColor(behavior); + const marker = this.add.rectangle(this.tileTopLeftX(x), this.tileTopLeftY(y), this.layout.tileSize, this.layout.tileSize, color, 0.28); + marker.setData('tileX', x); + marker.setData('tileY', y); + marker.setData('markerType', 'threat'); + marker.setOrigin(0); + marker.setStrokeStyle(1, 0xffd1a1, 0.64); + marker.setDepth(4.65); + if (this.mapMask) { + marker.setMask(this.mapMask); + } + marker.setVisible(this.isTileVisible(x, y)); + marker.setInteractive({ useHandCursor: true }); + marker.on('pointerover', () => { + marker.setFillStyle(color, 0.46); + this.renderUnitDetail(enemy, `${this.enemyDetailMessage(enemy)}\n\n이동 후 공격 가능 칸`); + }); + marker.on('pointerout', () => marker.setFillStyle(color, 0.28)); + marker.on('pointerdown', () => this.renderUnitDetail(enemy, `${this.enemyDetailMessage(enemy)}\n\n이동 후 공격 가능 칸`)); + this.markers.push(marker); + } + private enemyThreatTiles() { const threats = new Map(); battleUnits @@ -4037,6 +4124,7 @@ export class BattleScene extends Phaser.Scene { this.phase = 'animating'; const result = this.resolveCombatAction(attacker, target, action, false, usable); this.clearMarkers(); + await this.showBondMapEffect(result); await this.playCombatCutIn(result); result.counter = this.resolveCounterAttack(result); if (result.counter) { @@ -4127,9 +4215,11 @@ export class BattleScene extends Phaser.Scene { remaining > 0 ? `${remaining}명의 아군이 아직 행동할 수 있습니다.` : '모든 아군이 행동했습니다. 턴 종료 여부를 선택하세요.'; - this.renderRosterPanel('ally', `${message}\n${turnHint}`); + const completionMessage = `${message}\n${turnHint}`; + this.renderRosterPanel('ally', completionMessage); if (remaining === 0) { + this.renderSituationPanel(completionMessage); this.showTurnEndPrompt(message); } } @@ -5034,15 +5124,16 @@ export class BattleScene extends Phaser.Scene { return this.tileDistance(user, target) <= usable.range; } - private combatPreview(attacker: UnitData, defender: UnitData, action: DamageCommand, usable?: BattleUsable): CombatPreview { + private combatPreview(attacker: UnitData, defender: UnitData, action: DamageCommand, usable?: BattleUsable, isCounter = false): CombatPreview { const terrain = battleMap.terrain[defender.y][defender.x]; const terrainRule = getTerrainRule(terrain); const attackPower = this.actionPower(attacker, action, usable); const defensePower = this.actionDefense(defender, action, terrainRule.defenseBonus); - const bondBonus = attacker.faction === 'ally' ? this.strongestBondBonus(attacker.id) : { damageBonus: 0, chainRate: 0 }; - const equipmentEffect = this.combatEquipmentEffect(attacker, defender, action, usable); + const bondBonus = this.activeBondCombatBonus(attacker, defender, action, isCounter); + const equipmentEffect = this.combatEquipmentEffect(attacker, defender, action, usable, bondBonus); const totalDamageBonus = bondBonus.damageBonus + equipmentEffect.damageBonus - equipmentEffect.damageReduction; - const damage = Phaser.Math.Clamp(Math.round((attackPower - defensePower) * (1 + totalDamageBonus / 100)), 3, defender.maxHp); + const baseDamage = Phaser.Math.Clamp(Math.round((attackPower - defensePower) * (1 + totalDamageBonus / 100)), 3, defender.maxHp); + const damage = isCounter ? Phaser.Math.Clamp(Math.round(baseDamage * 0.45), 1, defender.maxHp) : baseDamage; const defenderTerrainRating = getUnitClass(defender.classKey).terrainRatings[terrain] ?? 100; const terrainHitPenalty = Math.floor(terrainRule.defenseBonus / 2) + Math.max(0, Math.floor((defenderTerrainRating - 100) / 4)); const hitRate = Phaser.Math.Clamp( @@ -5076,6 +5167,7 @@ export class BattleScene extends Phaser.Scene { damage, bondDamageBonus: bondBonus.damageBonus, bondLabel: bondBonus.label, + bondPartnerIds: bondBonus.partnerIds, equipmentDamageBonus: equipmentEffect.damageBonus, equipmentDamageReduction: equipmentEffect.damageReduction, equipmentHitBonus: equipmentEffect.hitBonus, @@ -5122,7 +5214,7 @@ export class BattleScene extends Phaser.Scene { } private resolveCombatAction(attacker: UnitData, defender: UnitData, action: DamageCommand, isCounter = false, usable?: BattleUsable): CombatResult { - const preview = this.combatPreview(attacker, defender, action, usable); + const preview = this.combatPreview(attacker, defender, action, usable, isCounter); const previousDefenderHp = defender.hp; const hit = this.rollPercent(preview.hitRate); const critical = hit && this.rollPercent(preview.criticalRate); @@ -5245,7 +5337,13 @@ export class BattleScene extends Phaser.Scene { return Math.min(target.maxHp - target.hp, Math.max(1, usable.power + bonus + equipmentBonus)); } - private combatEquipmentEffect(attacker: UnitData, defender: UnitData, action: DamageCommand, usable?: BattleUsable) { + private combatEquipmentEffect( + attacker: UnitData, + defender: UnitData, + action: DamageCommand, + usable?: BattleUsable, + bondBonus: BondCombatBonus = this.activeBondCombatBonus(attacker, defender, action) + ) { const labels: string[] = []; let damageBonus = 0; let damageReduction = 0; @@ -5256,7 +5354,6 @@ export class BattleScene extends Phaser.Scene { const armor = getItem(defender.equipment.armor.itemId); const accessory = getItem(attacker.equipment.accessory.itemId); const defenderAccessory = getItem(defender.equipment.accessory.itemId); - const bondBonus = attacker.faction === 'ally' ? this.strongestBondBonus(attacker.id) : { damageBonus: 0, chainRate: 0 }; if (action === 'attack' && weapon.id === 'twin-oath-blades' && bondBonus.chainRate > 0) { damageBonus += 6; @@ -5387,7 +5484,7 @@ export class BattleScene extends Phaser.Scene { private formatCounterLine(result: CombatResult) { const outcome = result.hit ? `${result.critical ? '치명타로 ' : ''}${result.damage} 피해` : '회피됨'; const defeated = result.defeated ? ` / ${result.defender.name} 퇴각` : ` / ${result.defender.name} HP ${result.defender.hp}/${result.defender.maxHp}`; - return `반격: ${result.attacker.name} -> ${result.defender.name} ${outcome}${defeated}`; + return `반격(감소): ${result.attacker.name} -> ${result.defender.name} ${outcome}${defeated}`; } private combatGrowthLines(result: CombatResult) { @@ -7114,6 +7211,69 @@ export class BattleScene extends Phaser.Scene { return container; } + private showBondMapEffect(result: CombatResult) { + if (result.bondDamageBonus <= 0 || result.bondPartnerIds.length === 0) { + return Promise.resolve(); + } + + const attackerView = this.unitViews.get(result.attacker.id); + if (!attackerView || !this.isTileVisible(result.attacker.x, result.attacker.y)) { + return Promise.resolve(); + } + + const partnerUnits = result.bondPartnerIds + .map((partnerId) => battleUnits.find((unit) => unit.id === partnerId && unit.hp > 0)) + .filter((unit): unit is UnitData => Boolean(unit)); + const visiblePartners = partnerUnits.filter((unit) => this.isTileVisible(unit.x, unit.y) && this.unitViews.has(unit.id)); + if (visiblePartners.length === 0) { + return Promise.resolve(); + } + + soundDirector.playEffect('strategy-cast', { volume: 0.18, rate: 1.14, stopAfterMs: 520 }); + + const objects: Phaser.GameObjects.GameObject[] = []; + const line = this.add.graphics(); + line.setDepth(34); + line.lineStyle(4, 0xffdf7b, 0.78); + visiblePartners.forEach((partner) => { + const partnerView = this.unitViews.get(partner.id); + if (!partnerView) { + return; + } + line.beginPath(); + line.moveTo(attackerView.sprite.x, attackerView.sprite.y - this.layout.tileSize * 0.28); + line.lineTo(partnerView.sprite.x, partnerView.sprite.y - this.layout.tileSize * 0.28); + line.strokePath(); + objects.push(this.createBondBadge(partnerView.sprite.x, partnerView.sprite.y - this.layout.tileSize * 0.86, `${partner.name} ♥ 공명`, 35)); + }); + objects.push(line); + objects.push(this.createBondBadge(attackerView.sprite.x, attackerView.sprite.y - this.layout.tileSize * 0.96, '연계 발동', 36)); + + this.tweens.add({ targets: objects, alpha: 0, y: '-=12', duration: 620, ease: 'Sine.easeOut' }); + return this.delay(660).then(() => objects.forEach((object) => object.destroy())); + } + + private createBondBadge(x: number, y: number, label: string, depth: number) { + const container = this.add.container(x, y); + container.setDepth(depth); + const width = Math.max(84, label.length * 13 + 22); + const bg = this.add.rectangle(0, 0, width, 30, 0x2a1820, 0.92); + bg.setStrokeStyle(2, 0xffdf7b, 0.92); + const glow = this.add.circle(-width / 2 + 17, 0, 10, 0xff6f91, 0.82); + const text = this.add.text(5, 0, label, { + fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', + fontSize: '14px', + color: '#fff2b8', + fontStyle: '700', + stroke: '#30100d', + strokeThickness: 3 + }); + text.setOrigin(0.5); + container.add([bg, glow, text]); + this.tweens.add({ targets: glow, scale: 1.35, alpha: 0.28, yoyo: true, repeat: 1, duration: 180 }); + return container; + } + private showBondCombatEffect(result: CombatResult, textX: number, textY: number, auraX: number, auraY: number, depth: number) { if (!result.bondLabel || result.bondDamageBonus <= 0) { return Promise.resolve(); @@ -7503,9 +7663,7 @@ export class BattleScene extends Phaser.Scene { } private recordBondAttackIntent(unit: UnitData, target: UnitData) { - const partners = this.attackIntents - .filter((intent) => intent.targetId === target.id && intent.attackerId !== unit.id) - .map((intent) => intent.attackerId); + const partners = this.activeBondCombatBonus(unit, target, 'attack').partnerIds; const growthResults: BondGrowthResult[] = []; partners.forEach((partnerId) => { @@ -7549,9 +7707,8 @@ export class BattleScene extends Phaser.Scene { return `${unit.name} 공격 명령 완료\n공격 가능한 적이 없습니다.\n${this.formatEquipmentGrowth(weaponGrowth)}`; } - const partners = this.attackIntents - .filter((intent) => intent.targetId === target.id && intent.attackerId !== unit.id) - .map((intent) => intent.attackerId); + const bondBonus = this.activeBondCombatBonus(unit, target, 'attack'); + const partners = bondBonus.partnerIds; let gained = 0; partners.forEach((partnerId) => { @@ -7571,8 +7728,7 @@ export class BattleScene extends Phaser.Scene { this.attackIntents = this.attackIntents.filter((intent) => intent.attackerId !== unit.id); this.attackIntents.push({ attackerId: unit.id, targetId: target.id }); - const bonus = this.strongestBondBonus(unit.id); - const chain = bonus.chainRate > 0 ? `\n공명 보너스: 피해 +${bonus.damageBonus}% / 연계 ${bonus.chainRate}%` : ''; + const chain = bondBonus.chainRate > 0 ? `\n공명 보너스: 피해 +${bondBonus.damageBonus}% / 연계 ${bondBonus.chainRate}%` : ''; const exp = gained > 0 ? `\n같은 목표를 노린 공명 경험치 +${gained}` : '\n같은 목표를 노린 장수가 생기면 공명 경험치가 쌓입니다.'; return `${unit.name} 공격 명령 완료\n예상 목표: ${target.name}\n${this.formatEquipmentGrowth(weaponGrowth)}${chain}${exp}`; } @@ -7702,6 +7858,47 @@ export class BattleScene extends Phaser.Scene { }); } + private activeBondCombatBonus(attacker: UnitData, defender: UnitData, action: DamageCommand, isCounter = false): BondCombatBonus { + if (isCounter || action !== 'attack' || attacker.faction !== 'ally') { + return { damageBonus: 0, chainRate: 0, partnerIds: [] }; + } + + const candidates = Array.from(this.bondStates.values()) + .map((bond) => { + if (!bond.unitIds.includes(attacker.id)) { + return undefined; + } + const partnerId = bond.unitIds.find((unitId) => unitId !== attacker.id); + const partner = partnerId ? battleUnits.find((unit) => unit.id === partnerId && unit.hp > 0) : undefined; + if (!partner || partner.faction !== attacker.faction || !this.canBondPartnerJoinAttack(attacker, partner, defender)) { + return undefined; + } + return { bond, partner }; + }) + .filter((candidate): candidate is { bond: BondState; partner: UnitData } => Boolean(candidate)) + .sort((a, b) => b.bond.level - a.bond.level); + + const strongest = candidates[0]; + if (!strongest) { + return { damageBonus: 0, chainRate: 0, partnerIds: [] }; + } + + const [first, second] = strongest.bond.unitIds.map((id) => this.unitName(id)); + return { + damageBonus: Math.floor(strongest.bond.level / 20) * 3, + chainRate: strongest.bond.level >= 70 ? 18 : strongest.bond.level >= 50 ? 8 : 0, + label: `${strongest.bond.title}: ${first}·${second}`, + partnerIds: [strongest.partner.id] + }; + } + + private canBondPartnerJoinAttack(attacker: UnitData, partner: UnitData, defender: UnitData) { + if (this.tileDistance(attacker, partner) <= 1) { + return true; + } + return this.canUseDamageCommand(partner, defender, 'attack'); + } + private strongestBondBonus(unitId: string) { const related = Array.from(this.bondStates.values()).filter((bond) => bond.unitIds.includes(unitId)); const strongest = related.sort((a, b) => b.level - a.level)[0]; @@ -8858,9 +9055,14 @@ export class BattleScene extends Phaser.Scene { activeFaction: this.activeFaction, phase: this.phase, battleOutcome: this.battleOutcome ?? null, + mapTextureKey: battleScenario.mapTextureKey, + mapTextureReady: this.textures.exists(battleScenario.mapTextureKey), + mapBackgroundReady: this.mapBackground?.texture.key === battleScenario.mapTextureKey, resultVisible: this.resultObjects.length > 0, + turnPromptVisible: this.turnPromptObjects.length > 0, markerCount: this.markers.length, threatMarkerCount: this.markers.filter((marker) => marker.getData('markerType') === 'threat').length, + enemyMoveMarkerCount: this.markers.filter((marker) => marker.getData('markerType') === 'enemy-move').length, camera: { x: this.cameraTileX, y: this.cameraTileY, @@ -8887,6 +9089,7 @@ export class BattleScene extends Phaser.Scene { itemStocks: this.serializeItemStocks(), battleBuffs: Array.from(this.battleBuffs.values()).map((buff) => ({ ...buff })), treasureEffectPreviews: this.debugTreasureEffectPreviews(), + combatMechanicsProbe: this.debugCombatMechanicsProbe(), units: battleUnits.map((unit) => ({ id: unit.id, name: unit.name, @@ -8914,6 +9117,61 @@ export class BattleScene extends Phaser.Scene { }; } + debugUnitById(unitId: string) { + if (!import.meta.env.DEV) { + return undefined; + } + + return battleUnits.find((unit) => unit.id === unitId); + } + + private debugCombatMechanicsProbe() { + const bond = Array.from(this.bondStates.values()).find((candidate) => { + const units = candidate.unitIds.map((unitId) => battleUnits.find((unit) => unit.id === unitId && unit.hp > 0)); + return units.length === 2 && units.every((unit) => unit?.faction === 'ally') && Math.floor(candidate.level / 20) * 3 > 0; + }); + const attacker = bond ? battleUnits.find((unit) => unit.id === bond.unitIds[0] && unit.hp > 0) : undefined; + const partner = bond ? battleUnits.find((unit) => unit.id === bond.unitIds[1] && unit.hp > 0) : undefined; + const enemy = battleUnits.find((unit) => unit.faction === 'enemy' && unit.hp > 0); + if (!bond || !attacker || !partner || !enemy) { + return null; + } + + const direction = partner.x <= battleMap.width - 3 ? 1 : -1; + const nearX = partner.x + direction; + const edgeX = partner.x + direction * 2; + if (!this.isInBounds(nearX, partner.y) || !this.isInBounds(edgeX, partner.y)) { + return null; + } + + const farAttackerX = Math.abs(battleMap.width - 2 - partner.x) > 2 ? battleMap.width - 2 : 1; + const farDefenderX = farAttackerX > 0 ? farAttackerX - 1 : farAttackerX + 1; + if (!this.isInBounds(farAttackerX, partner.y) || !this.isInBounds(farDefenderX, partner.y)) { + return null; + } + + const adjacentPreview = this.combatPreview({ ...attacker, x: nearX, y: partner.y }, { ...enemy, x: edgeX, y: partner.y }, 'attack'); + const sameTargetPreview = this.combatPreview({ ...attacker, x: edgeX, y: partner.y }, { ...enemy, x: nearX, y: partner.y }, 'attack'); + const farPreview = this.combatPreview({ ...attacker, x: farAttackerX, y: partner.y }, { ...enemy, x: farDefenderX, y: partner.y }, 'attack'); + const normalIncomingPreview = this.combatPreview(enemy, attacker, 'attack'); + const counterIncomingPreview = this.combatPreview(enemy, attacker, 'attack', undefined, true); + + return { + bondId: bond.id, + attackerId: attacker.id, + partnerId: partner.id, + enemyId: enemy.id, + adjacentBondDamageBonus: adjacentPreview.bondDamageBonus, + adjacentPartnerIds: adjacentPreview.bondPartnerIds, + sameTargetBondDamageBonus: sameTargetPreview.bondDamageBonus, + sameTargetPartnerIds: sameTargetPreview.bondPartnerIds, + farBondDamageBonus: farPreview.bondDamageBonus, + farPartnerIds: farPreview.bondPartnerIds, + normalDamage: normalIncomingPreview.damage, + counterDamage: counterIncomingPreview.damage + }; + } + private debugTreasureEffectPreviews() { return ['liu-bei', 'guan-yu', 'zhang-fei', 'zhuge-liang'] .map((unitId) => battleUnits.find((unit) => unit.id === unitId && unit.hp > 0)) diff --git a/src/game/scenes/BootScene.ts b/src/game/scenes/BootScene.ts index f71dbf0..ab643fc 100644 --- a/src/game/scenes/BootScene.ts +++ b/src/game/scenes/BootScene.ts @@ -2,11 +2,22 @@ import Phaser from 'phaser'; import guanYuPortraitUrl from '../../assets/images/portraits/guan-yu.png'; import liuBeiPortraitUrl from '../../assets/images/portraits/liu-bei.png'; import zhangFeiPortraitUrl from '../../assets/images/portraits/zhang-fei.png'; +import { battleMapAssets } from '../data/battleMapAssets'; import storyChaosUrl from '../../assets/images/story/01-yellow-turban-chaos.png'; import storyLiuBeiUrl from '../../assets/images/story/02-liu-bei-resolve.png'; import storyThreeHeroesUrl from '../../assets/images/story/03-three-heroes-meet.png'; import storyMilitiaUrl from '../../assets/images/story/04-volunteer-militia.png'; import storySortieUrl from '../../assets/images/story/05-first-sortie.png'; +import storyYellowPursuitUrl from '../../assets/images/story/06-yellow-turban-pursuit.png'; +import storyAntiDongPassUrl from '../../assets/images/story/07-anti-dong-pass.png'; +import storyXuzhouHandoverUrl from '../../assets/images/story/08-xuzhou-handover.png'; +import storyWanderingRoadUrl from '../../assets/images/story/09-wandering-road.png'; +import storyWolongCottageUrl from '../../assets/images/story/10-wolong-cottage.png'; +import storyRedCliffsFireUrl from '../../assets/images/story/11-red-cliffs-fire.png'; +import storyYizhouMountainPassUrl from '../../assets/images/story/12-yizhou-mountain-pass.png'; +import storyNorthernExpeditionUrl from '../../assets/images/story/13-northern-expedition.png'; +import storyNanzhongPacificationUrl from '../../assets/images/story/14-nanzhong-pacification.png'; +import storyYilingBaidiAftermathUrl from '../../assets/images/story/15-yiling-baidi-aftermath.png'; import titleBackgroundUrl from '../../assets/images/taoyuan-oath-title.png'; import guanYuActionSheetUrl from '../../assets/images/units/unit-guan-yu-actions.png'; import guanYuUnitSheetUrl from '../../assets/images/units/unit-guan-yu.png'; @@ -58,10 +69,25 @@ export class BootScene extends Phaser.Scene { this.load.image('story-three-heroes', storyThreeHeroesUrl); this.load.image('story-militia', storyMilitiaUrl); this.load.image('story-sortie', storySortieUrl); + this.load.image('story-yellow-pursuit', storyYellowPursuitUrl); + this.load.image('story-anti-dong', storyAntiDongPassUrl); + this.load.image('story-xuzhou', storyXuzhouHandoverUrl); + this.load.image('story-wandering', storyWanderingRoadUrl); + this.load.image('story-wolong', storyWolongCottageUrl); + this.load.image('story-red-cliffs', storyRedCliffsFireUrl); + this.load.image('story-yizhou', storyYizhouMountainPassUrl); + this.load.image('story-northern', storyNorthernExpeditionUrl); + this.load.image('story-nanzhong', storyNanzhongPacificationUrl); + this.load.image('story-yiling-baidi', storyYilingBaidiAftermathUrl); + this.load.image('story-resolve', storyLiuBeiUrl); this.load.image('portrait-liu-bei', liuBeiPortraitUrl); this.load.image('portrait-guan-yu', guanYuPortraitUrl); this.load.image('portrait-zhang-fei', zhangFeiPortraitUrl); + Object.entries(battleMapAssets).forEach(([key, url]) => { + this.load.image(key, url); + }); + unitSheets.forEach(({ key, url, actionKey, actionUrl }) => { this.load.spritesheet(key, url, { frameWidth: unitSheetFrameSize,