Add Fu Pass entry chapter

This commit is contained in:
2026-06-23 09:14:41 +09:00
parent 17cbaab55d
commit 8349d1044f
11 changed files with 1260 additions and 34 deletions

View File

@@ -11,6 +11,8 @@ import {
changshaRecruitUnits,
firstBattleBonds,
firstBattleUnits,
fuPassRecruitBonds,
fuPassRecruitUnits,
guiyangRecruitBonds,
guiyangRecruitUnits,
jingzhouRecruitBonds,
@@ -310,9 +312,10 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
'twenty-fourth-battle-guiyang-persuasion',
'twenty-fifth-battle-wuling-mountain-road',
'twenty-sixth-battle-changsha-veteran',
'twenty-seventh-battle-yizhou-relief-road'
'twenty-seventh-battle-yizhou-relief-road',
'twenty-eighth-battle-fu-pass-entry'
],
nextHints: ['형주 방위', '익주 진입', '방통 합류']
nextHints: ['형주 방위', '익주 진입', '방통·법정 합류']
},
{
id: 'shu-han',
@@ -351,7 +354,8 @@ const campBattleIds = {
twentyFourth: 'twenty-fourth-battle-guiyang-persuasion',
twentyFifth: 'twenty-fifth-battle-wuling-mountain-road',
twentySixth: 'twenty-sixth-battle-changsha-veteran',
twentySeventh: 'twenty-seventh-battle-yizhou-relief-road'
twentySeventh: 'twenty-seventh-battle-yizhou-relief-road',
twentyEighth: 'twenty-eighth-battle-fu-pass-entry'
} as const;
const requiredSortieUnitIds = new Set(['liu-bei']);
@@ -650,6 +654,18 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
{ unitId: 'mi-zhu', reason: '큰 로스터 전투에서 회복 도구와 보급 안정성이 빛납니다.' }
],
note: '익주 원군로는 열세 명 중 여섯 명만 고르는 전장입니다. 황충·위연을 시험할지, 기존 책사와 보급을 두껍게 둘지 직접 선택하십시오.'
},
'twenty-eighth-battle-fu-pass-entry': {
maxUnits: 6,
recommended: [
{ unitId: 'liu-bei', reason: '부수관 진입 명분과 패배 조건의 중심입니다.' },
{ unitId: 'pang-tong', reason: '부수관 관문을 흔드는 기책 담당이며 이번 전투의 새 선택 축입니다.' },
{ unitId: 'zhuge-liang', reason: '관문 돌파와 보급선을 함께 보는 큰 판의 핵심입니다.' },
{ unitId: 'wei-yan', reason: '좁은 관문 전열을 빠르게 흔들 돌파 역할입니다.' },
{ unitId: 'huang-zhong', reason: '성루 궁병과 산비탈 적을 안정적으로 견제합니다.' },
{ unitId: 'zhao-yun', reason: '협곡 기병과 복병을 빠르게 끊는 기동 핵심입니다.' }
],
note: '부수관 진입전은 열네 명 중 여섯 명만 고르는 전장입니다. 방통을 데려가면 계책은 강해지지만, 보급이나 전열 후보를 한 명 줄여야 합니다.'
}
};
@@ -2921,6 +2937,87 @@ const campDialogues: CampDialogue[] = [
rewardExp: 9
}
]
},
{
id: 'liu-fa-after-fupass',
title: '익주 내부의 길',
availableAfterBattleIds: [campBattleIds.twentyEighth],
unitIds: ['liu-bei', 'fa-zheng'],
bondId: 'liu-bei__fa-zheng',
rewardExp: 30,
lines: [
'법정: 익주 사람들은 강한 군보다 약속을 지키는 군을 더 오래 기억합니다.',
'유비: 그래서 관문 창고를 봉했소. 길을 열어도 백성의 밥그릇을 건드리면 마음은 닫히오.',
'법정: 그렇다면 저는 그 마음이 어디서 열리고 닫히는지 알려 드리겠습니다.'
],
choices: [
{
id: 'ask-fa-zheng-people',
label: '익주 민심을 묻는다',
response: '법정은 관문보다 먼저 설득해야 할 마을과 사람의 이름을 적었다.',
rewardExp: 12
},
{
id: 'promise-yizhou-discipline',
label: '군율을 약속한다',
response: '유비가 군율을 다시 못박자, 법정은 안쪽 길을 밝히겠다고 답했다.',
rewardExp: 11
}
]
},
{
id: 'pang-fa-after-fupass',
title: '봉추와 내부책',
availableAfterBattleIds: [campBattleIds.twentyEighth],
unitIds: ['pang-tong', 'fa-zheng'],
bondId: 'pang-tong__fa-zheng',
rewardExp: 28,
lines: [
'방통: 안쪽 사정을 아는 사람이 있으니, 이제 문을 두드릴지 흔들지 결정하기 쉬워졌군요.',
'법정: 흔들어야 할 문도 있고, 조용히 열어야 할 문도 있습니다. 순서를 틀리면 익주가 피로 답할 것입니다.',
'방통: 그러면 그 순서를 당신이, 그 틈을 제가 보겠습니다.'
],
choices: [
{
id: 'mark-hidden-gates',
label: '숨은 문을 표시한다',
response: '법정은 익주 내부의 숨은 길목을 표시했고, 방통은 그 길목을 흔드는 계책을 덧붙였다.',
rewardExp: 11
},
{
id: 'set-bold-and-soft-plan',
label: '강온책을 나눈다',
response: '두 사람은 강하게 압박할 곳과 조용히 설득할 곳을 분리했다.',
rewardExp: 10
}
]
},
{
id: 'zhuge-fa-after-fupass',
title: '큰 판과 속내',
availableAfterBattleIds: [campBattleIds.twentyEighth],
unitIds: ['zhuge-liang', 'fa-zheng'],
bondId: 'zhuge-liang__fa-zheng',
rewardExp: 28,
lines: [
'제갈량: 익주는 지세가 험하니 길을 얻어도 마음을 잃으면 오래 지키기 어렵습니다.',
'법정: 그래서 저는 안쪽 사람들의 두려움과 불만을 함께 보려 합니다.',
'제갈량: 큰 판에 그 속내를 더하면, 피를 줄이는 길도 보일 것입니다.'
],
choices: [
{
id: 'combine-map-and-sentiment',
label: '지도와 민심을 합친다',
response: '제갈량의 지도 위에 법정의 사람 이름이 더해지자, 익주 공략의 다음 순서가 또렷해졌다.',
rewardExp: 11
},
{
id: 'prepare-luo-castle-letter',
label: '낙성 서찰을 준비한다',
response: '두 책사는 다음 성으로 보낼 글과 병력 배치의 순서를 함께 정했다.',
rewardExp: 10
}
]
}
];
@@ -3670,6 +3767,66 @@ const campVisits: CampVisitDefinition[] = [
itemRewards: ['관문 유인 초안 1']
}
]
},
{
id: 'fu-pass-storehouse-seal',
title: '부수관 창고 봉인',
location: '부수관 창고',
availableAfterBattleIds: [campBattleIds.twentyEighth],
bondId: 'liu-bei__fa-zheng',
description: '법정의 조언에 따라 부수관 창고를 함부로 열지 않고 장부와 민심을 먼저 정리합니다.',
lines: [
'법정: 익주 사람들은 창고 문이 열리는 순간을 보고 새 주인을 판단할 것입니다.',
'유비: 병사들이 배고파도 백성의 곡식을 빼앗아서는 안 되오. 장부를 먼저 세우겠소.',
'창고 앞에 모인 사람들은 병사들이 물러서고 장부가 펼쳐지는 모습을 조용히 지켜보았습니다.'
],
choices: [
{
id: 'seal-storehouse-ledger',
label: '장부를 먼저 세운다',
response: '법정은 창고 장부를 정리했고, 유비군은 필요한 보급만 표시해 주민의 불안을 줄였다.',
bondExp: 24,
itemRewards: ['부수관 창고 장부 1']
},
{
id: 'guard-storehouse-night',
label: '야간 경계를 세운다',
response: '창고를 노리는 잔병을 막아 내자, 부수관 주민들은 유비군이 약속을 지킨다는 말을 전하기 시작했다.',
bondExp: 20,
gold: 260,
itemRewards: ['콩 4']
}
]
},
{
id: 'luo-castle-entry-council',
title: '낙성 진입 회의',
location: '부수관 군막',
availableAfterBattleIds: [campBattleIds.twentyEighth],
bondId: 'pang-tong__fa-zheng',
description: '방통과 법정이 낙성으로 이어지는 길을 두고 빠른 기책과 내부 설득의 균형을 조율합니다.',
lines: [
'방통: 빠르게 움직이면 낙성 앞의 적이 미처 모이지 못합니다.',
'법정: 그러나 빠른 길일수록 뒤에 남는 사람의 마음이 상합니다. 누가 남고 누가 따를지 먼저 보아야 합니다.',
'두 사람의 말이 부딪히자, 군막 안의 지도 위에는 빠른 길과 조심스러운 길이 동시에 그어졌습니다.'
],
choices: [
{
id: 'prepare-fast-luo-entry',
label: '빠른 진입로를 잡는다',
response: '방통은 협곡을 통과하는 빠른 진입로를 표시했고, 법정은 그 길의 반발을 줄일 연락책을 붙였다.',
bondExp: 24,
itemRewards: ['낙성 진입 초안 1']
},
{
id: 'prepare-soft-luo-entry',
label: '내부 설득을 우선한다',
response: '법정은 설득해야 할 호족과 관리의 이름을 적었고, 방통은 그 사이를 흔들 유인책을 더했다.',
bondExp: 22,
gold: 280,
itemRewards: ['익주 연락 명단 1']
}
]
}
];
@@ -3755,6 +3912,37 @@ export class CampScene extends Phaser.Scene {
return;
}
if (battleId === campBattleIds.twentyEighth) {
this.campaign = ensureCampaignRosterUnits(
[
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits,
...jingzhouRecruitUnits,
...guiyangRecruitUnits,
...wulingRecruitUnits,
...changshaRecruitUnits,
...yizhouRecruitUnits,
...fuPassRecruitUnits
],
[
...xuzhouRecruitBonds,
...caoBreakRecruitBonds,
...liuBiaoRecruitBonds,
...zhugeRecruitBonds,
...jingzhouRecruitBonds,
...guiyangRecruitBonds,
...wulingRecruitBonds,
...changshaRecruitBonds,
...yizhouRecruitBonds,
...fuPassRecruitBonds
]
);
this.report = this.campaign.firstBattleReport ?? this.report;
return;
}
if (battleId === campBattleIds.twentySeventh) {
this.campaign = ensureCampaignRosterUnits(
[
@@ -3932,6 +4120,9 @@ export class CampScene extends Phaser.Scene {
private currentCampTitle() {
const battleId = this.currentCampBattleId();
if (battleId === campBattleIds.twentyEighth) {
return '부수관 진입 후 군영';
}
if (battleId === campBattleIds.twentySeventh) {
return '익주 원군로 후 군영';
}