Add Dingjun Mountain vanguard chapter

This commit is contained in:
2026-06-23 13:38:49 +09:00
parent c724d9d48f
commit 24b7db0b14
12 changed files with 894 additions and 39 deletions

View File

@@ -21,6 +21,8 @@ import {
guiyangRecruitUnits,
hanzhongOpeningRecruitBonds,
hanzhongOpeningRecruitUnits,
hanzhongMainRecruitBonds,
hanzhongMainRecruitUnits,
hanzhongScoutRecruitBonds,
hanzhongScoutRecruitUnits,
jingzhouRecruitBonds,
@@ -341,7 +343,11 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
title: '촉한 건국',
period: '한실을 잇는 깃발',
description: '여러 전장을 지나 촉한을 세우고 북벌을 바라보는 장기 목표입니다.',
battleIds: ['thirty-fourth-battle-jiameng-pass', 'thirty-fifth-battle-yangping-scout'],
battleIds: [
'thirty-fourth-battle-jiameng-pass',
'thirty-fifth-battle-yangping-scout',
'thirty-sixth-battle-dingjun-vanguard'
],
nextHints: ['왕업 선언', '오호대장군', '북벌 준비']
}
];
@@ -381,7 +387,8 @@ const campBattleIds = {
thirtySecond: 'thirty-second-battle-mianzhu-gate',
thirtyThird: 'thirty-third-battle-chengdu-surrender',
thirtyFourth: 'thirty-fourth-battle-jiameng-pass',
thirtyFifth: 'thirty-fifth-battle-yangping-scout'
thirtyFifth: 'thirty-fifth-battle-yangping-scout',
thirtySixth: 'thirty-sixth-battle-dingjun-vanguard'
} as const;
const requiredSortieUnitIds = new Set(['liu-bei']);
@@ -776,6 +783,18 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
{ unitId: 'fa-zheng', reason: '장로군의 내부 동요와 염포의 책략을 읽는 데 강합니다.' }
],
note: '양평관 정찰전은 스무 명 중 여섯 명만 출전합니다. 마초가 첫 아군 출전 후보로 들어오며, 기병 선봉과 책사 후원을 동시에 고르는 압박이 생깁니다.'
},
'thirty-sixth-battle-dingjun-vanguard': {
maxUnits: 6,
recommended: [
{ unitId: 'liu-bei', reason: '정군산 전선의 명분과 패배 조건의 중심입니다.' },
{ unitId: 'huang-zhong', reason: '정군산 전초전의 핵심 장수입니다. 고지 압박과 생존 목표가 맞물립니다.' },
{ unitId: 'fa-zheng', reason: '황충의 고지 돌파 타이밍과 하후연 선봉의 허점을 읽는 책사입니다.' },
{ unitId: 'ma-chao', reason: '서쪽 능선을 흔들어 하후연의 시선을 분산시킬 수 있습니다.' },
{ unitId: 'ma-dai', reason: '마초의 첫 돌파 뒤 후속 기병과 퇴로를 안정시키는 새 합류 장수입니다.' },
{ unitId: 'zhuge-liang', reason: '한중 본전으로 이어질 산악 전선과 왕평 설득을 설계합니다.' }
],
note: '정군산 전초전은 스물한 명 중 여섯 명만 출전합니다. 황충과 법정의 고지 압박, 마초·마대의 우회 기병, 제갈량의 큰 전선 설계를 모두 담을지 고민하게 됩니다.'
}
};
@@ -3695,6 +3714,87 @@ const campDialogues: CampDialogue[] = [
rewardExp: 12
}
]
},
{
id: 'huang-wang-after-dingjun',
title: '노장과 산길',
availableAfterBattleIds: [campBattleIds.thirtySixth],
unitIds: ['huang-zhong', 'wang-ping'],
bondId: 'huang-zhong__wang-ping',
rewardExp: 38,
lines: [
'왕평: 정군산의 길은 곧게 오르는 길보다 돌아가는 길이 더 빠를 때가 많습니다.',
'황충: 흥, 늙은 다리는 돌아가는 길을 싫어하지만 전장은 고집으로 이기는 곳이 아니지.',
'왕평: 장군의 칼이 닿을 순간을 만들 수 있다면, 산길은 제게 맡겨 주십시오.'
],
choices: [
{
id: 'trust-mountain-route',
label: '산길을 맡긴다',
response: '황충이 왕평의 지형 판단을 받아들이자, 노장의 돌파는 무모함이 아니라 계산된 일격으로 바뀌었습니다.',
rewardExp: 14
},
{
id: 'prepare-ridge-ambush',
label: '능선 매복을 준비한다',
response: '왕평이 숲길과 절벽 사이의 매복 지점을 표시했고, 황충은 그곳에서 칼을 뽑을 순간을 기다리기로 했습니다.',
rewardExp: 13
}
]
},
{
id: 'zhuge-wang-after-dingjun',
title: '한중 지형책',
availableAfterBattleIds: [campBattleIds.thirtySixth],
unitIds: ['zhuge-liang', 'wang-ping'],
bondId: 'zhuge-liang__wang-ping',
rewardExp: 36,
lines: [
'제갈량: 지도에는 산이 선으로 그려지지만, 병사는 그 선 사이에서 지치고 헤맵니다.',
'왕평: 그래서 지도만 보는 장수는 한중을 오래 품지 못합니다. 물길, 숲길, 겨울 길이 모두 다릅니다.',
'제갈량: 그대의 눈이 필요합니다. 한중을 얻는 것보다 지키는 일이 더 길 테니까요.'
],
choices: [
{
id: 'write-hanzhong-terrain-book',
label: '한중 지형책을 쓴다',
response: '제갈량과 왕평은 정군산, 양평관, 가맹관의 길을 하나의 지형책으로 묶기 시작했습니다.',
rewardExp: 13
},
{
id: 'mark-winter-roads',
label: '겨울 행군로를 표시한다',
response: '왕평은 눈이 오면 막히는 길과 오히려 단단해지는 강변 길을 지도에 따로 표시했습니다.',
rewardExp: 13
}
]
},
{
id: 'ma-dai-wang-after-dingjun',
title: '기병과 산길잡이',
availableAfterBattleIds: [campBattleIds.thirtySixth],
unitIds: ['ma-dai', 'wang-ping'],
bondId: 'ma-dai__wang-ping',
rewardExp: 34,
lines: [
'마대: 말이 달릴 수 없는 길에서도 기병은 쓸모가 있습니까?',
'왕평: 달리지 못하면 지키면 됩니다. 좁은 능선에서는 빠른 돌격보다 정확한 퇴로가 더 중요합니다.',
'마대: 그럼 제가 지킬 길을 알려 주십시오. 형님의 돌격이 돌아올 길을 잃지 않게 하겠습니다.'
],
choices: [
{
id: 'map-cavalry-return',
label: '기병 귀환로를 그린다',
response: '왕평과 마대가 능선의 귀환로를 정리하자, 서량 기병은 좁은 산길에서도 무리하게 흩어지지 않게 되었습니다.',
rewardExp: 12
},
{
id: 'train-dismount-guard',
label: '하마 방어를 훈련한다',
response: '마대는 말에서 내려 창진을 세우는 훈련을 받아, 산악 전투에서 기병의 빈틈을 줄였습니다.',
rewardExp: 12
}
]
}
];
@@ -4924,6 +5024,66 @@ const campVisits: CampVisitDefinition[] = [
itemRewards: ['탁주 4']
}
]
},
{
id: 'dingjun-ridge-survey',
title: '정군산 능선 조사',
location: '정군산 서쪽 능선',
availableAfterBattleIds: [campBattleIds.thirtySixth],
bondId: 'zhuge-liang__wang-ping',
description: '제갈량과 왕평이 정군산의 능선, 절벽, 보급로를 다시 확인해 한중 결전을 준비합니다.',
lines: [
'왕평: 이 능선은 보기보다 바람이 셉니다. 깃발이 흔들리는 방향만 봐도 적의 시야를 피할 수 있습니다.',
'제갈량: 바람과 길을 함께 적어 두면 다음 전투의 한 수가 됩니다.',
'두 사람은 산길을 하나씩 짚으며 한중 본전의 진형 후보를 정리했습니다.'
],
choices: [
{
id: 'record-ridge-winds',
label: '능선 바람을 기록한다',
response: '제갈량은 왕평의 설명을 바탕으로 정군산 능선의 바람과 시야를 지형책에 보탰습니다.',
bondExp: 32,
itemRewards: ['산악 지형도 1']
},
{
id: 'secure-ridge-store',
label: '능선 보급소를 확보한다',
response: '왕평이 작은 보급소의 위치를 알려 주며 한중 결전에서 버틸 군량을 조금 더 확보했습니다.',
bondExp: 30,
gold: 620,
itemRewards: ['콩 10', '상처약 5']
}
]
},
{
id: 'dingjun-veteran-drill',
title: '정군산 노장 훈련',
location: '정군산 중턱',
availableAfterBattleIds: [campBattleIds.thirtySixth],
bondId: 'huang-zhong__wang-ping',
description: '황충과 왕평이 고지 돌파와 산길 매복을 맞춰 보며 다음 한중 결전의 선봉 감각을 다듬습니다.',
lines: [
'황충: 젊은 장수들은 빠르게 오른다지만, 오래 버티는 법은 아직 모를 때가 많지.',
'왕평: 이 산은 오래 버티는 장수를 좋아합니다. 급한 발보다 끊기지 않는 숨이 중요합니다.',
'정군산 중턱에는 노장의 숨과 산길잡이의 눈이 맞물리며 새로운 훈련 길이 생겼습니다.'
],
choices: [
{
id: 'drill-high-ground-strike',
label: '고지 일격을 연습한다',
response: '황충은 왕평이 잡아 준 짧은 고지 길을 따라 치고 빠지는 훈련을 반복했습니다.',
bondExp: 32,
itemRewards: ['기병 훈련 기록 1']
},
{
id: 'set-old-guard-pace',
label: '노장 진군 속도를 맞춘다',
response: '왕평은 황충의 호흡에 맞춰 병사들의 오르막 속도를 정했고, 무리한 추격을 줄였습니다.',
bondExp: 30,
gold: 600,
itemRewards: ['탁주 4']
}
]
}
];
@@ -5010,6 +5170,51 @@ export class CampScene extends Phaser.Scene {
return;
}
if (battleId === campBattleIds.thirtySixth) {
this.campaign = ensureCampaignRosterUnits(
[
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits,
...jingzhouRecruitUnits,
...guiyangRecruitUnits,
...wulingRecruitUnits,
...changshaRecruitUnits,
...yizhouRecruitUnits,
...fuPassRecruitUnits,
...luoCastleRecruitUnits,
...luoCastleProperRecruitUnits,
...chengduPressureRecruitUnits,
...chengduSurrenderRecruitUnits,
...hanzhongOpeningRecruitUnits,
...hanzhongScoutRecruitUnits,
...hanzhongMainRecruitUnits
],
[
...xuzhouRecruitBonds,
...caoBreakRecruitBonds,
...liuBiaoRecruitBonds,
...zhugeRecruitBonds,
...jingzhouRecruitBonds,
...guiyangRecruitBonds,
...wulingRecruitBonds,
...changshaRecruitBonds,
...yizhouRecruitBonds,
...fuPassRecruitBonds,
...luoCastleRecruitBonds,
...luoCastleProperRecruitBonds,
...chengduPressureRecruitBonds,
...chengduSurrenderRecruitBonds,
...hanzhongOpeningRecruitBonds,
...hanzhongScoutRecruitBonds,
...hanzhongMainRecruitBonds
]
);
this.report = this.campaign.firstBattleReport ?? this.report;
return;
}
if (battleId === campBattleIds.thirtyFifth) {
this.campaign = ensureCampaignRosterUnits(
[
@@ -5446,6 +5651,9 @@ export class CampScene extends Phaser.Scene {
private currentCampTitle() {
const battleId = this.currentCampBattleId();
if (battleId === campBattleIds.thirtySixth) {
return '정군산 전초전 후 군영';
}
if (battleId === campBattleIds.thirtyFifth) {
return '양평관 정찰 후 군영';
}