Add Gongan collapse chapter

This commit is contained in:
2026-06-23 18:01:03 +09:00
parent 8591fd7fa3
commit dd6d85ffe9
11 changed files with 908 additions and 50 deletions

View File

@@ -29,6 +29,7 @@ import {
hanzhongScoutRecruitUnits,
fanCastleBonds,
fanCastleSiegeBonds,
jingCollapseBonds,
jingRearCrisisBonds,
jingDefenseBonds,
jingzhouRecruitBonds,
@@ -370,7 +371,8 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
'thirty-ninth-battle-fan-castle-vanguard',
'fortieth-battle-han-river-flood',
'forty-first-battle-fan-castle-siege',
'forty-second-battle-jing-rear-crisis'
'forty-second-battle-jing-rear-crisis',
'forty-third-battle-gongan-collapse'
],
nextHints: ['왕업 선언', '번성 포위', '형주 위기']
}
@@ -418,7 +420,8 @@ const campBattleIds = {
thirtyNinth: 'thirty-ninth-battle-fan-castle-vanguard',
fortieth: 'fortieth-battle-han-river-flood',
fortyFirst: 'forty-first-battle-fan-castle-siege',
fortySecond: 'forty-second-battle-jing-rear-crisis'
fortySecond: 'forty-second-battle-jing-rear-crisis',
fortyThird: 'forty-third-battle-gongan-collapse'
} as const;
const defaultRequiredSortieUnitIds = ['liu-bei'];
@@ -909,6 +912,20 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
{ unitId: 'wang-ping', reason: '숲길과 강변 초소의 지형을 읽어 후방 기습을 막기 좋습니다.' }
],
note: '강릉 나루 경계전은 스물두 명 중 일곱 명만 출전합니다. 유비와 관우는 필수이며, 후방 창고, 강동 정찰, 숲길 기습을 어떻게 막을지 고르는 전투입니다.'
},
'forty-third-battle-gongan-collapse': {
maxUnits: 7,
requiredUnitIds: ['liu-bei', 'guan-yu'],
recommended: [
{ unitId: 'liu-bei', reason: '흔들리는 공안 병사들에게 형주의 명분을 직접 보여 줍니다.' },
{ unitId: 'guan-yu', reason: '번성 전선과 후방 성문을 동시에 묶어야 하는 핵심 장수입니다.' },
{ unitId: 'ma-liang', reason: '공안 수비대의 민심과 강동 설객의 말투를 읽는 현지 참모입니다.' },
{ unitId: 'mi-zhu', reason: '강릉 창고 장부와 미방의 흔들림을 추적하는 보급 축입니다.' },
{ unitId: 'huang-quan', reason: '부사인과 미방의 군령을 신중하게 판정해 내분을 줄입니다.' },
{ unitId: 'wang-ping', reason: '공안 성문과 강변 숲길을 잇는 지형 판단에 강합니다.' },
{ unitId: 'zhao-yun', reason: '나루와 성문 사이를 빠르게 오가며 백의 복병을 차단합니다.' }
],
note: '공안 성문 변고는 스물두 명 중 일곱 명만 출전합니다. 유비와 관우는 필수이며, 장부, 민심, 성문 지형, 기동 차단 중 무엇을 두껍게 할지 선택하십시오.'
}
};
@@ -4395,6 +4412,87 @@ const campDialogues: CampDialogue[] = [
rewardExp: 14
}
]
},
{
id: 'guan-maliang-after-gongan-collapse',
title: '성문 안의 균열',
availableAfterBattleIds: [campBattleIds.fortyThird],
unitIds: ['guan-yu', 'ma-liang'],
bondId: 'guan-yu__ma-liang_collapse',
rewardExp: 48,
lines: [
'마량: 공안 성문은 닫혔지만, 병사들의 눈은 아직 흔들립니다. 강동의 말이 칼보다 먼저 들어왔습니다.',
'관우: 군령이 엄하면 마음이 붙는 줄 알았으나, 두려움이 틈이 될 수도 있구려.',
'마량: 엄함을 거두자는 뜻은 아닙니다. 다만 이유를 설명하지 않은 군령은 적의 말에 밀릴 수 있습니다.'
],
choices: [
{
id: 'explain-gate-orders',
label: '성문 군령의 이유를 밝힌다',
response: '관우는 공안 병사들에게 군령의 이유를 설명했고, 마량은 성문 안의 불신을 줄일 말을 정리했습니다.',
rewardExp: 18
},
{
id: 'watch-soft-letters',
label: '강동의 글을 더 경계한다',
response: '마량은 육손의 낮은 글을 다시 분석했고, 관우군은 부드러운 문서가 남기는 흔적을 더 촘촘히 살피게 되었습니다.',
rewardExp: 17
}
]
},
{
id: 'mizhu-huangquan-after-gongan-collapse',
title: '흔들린 장부',
availableAfterBattleIds: [campBattleIds.fortyThird],
unitIds: ['mi-zhu', 'huang-quan'],
bondId: 'mi-zhu__huang-quan_collapse',
rewardExp: 46,
lines: [
'미축: 장부의 빈칸보다 두려운 것은, 빈칸을 숨기려는 사람의 침묵입니다.',
'황권: 미방을 몰아붙이면 더 깊이 숨을 것입니다. 숫자와 증언을 천천히 맞춰 도망칠 길을 줄여야 합니다.',
'미축: 창고의 문을 잠그는 것보다 사람의 마음이 새지 않게 하는 일이 더 어렵군요.'
],
choices: [
{
id: 'compare-hidden-ledgers',
label: '숨긴 장부를 대조한다',
response: '미축과 황권은 숨은 장부와 선박 명부를 맞추며, 후방 배신으로 이어질 작은 구멍을 찾아냈습니다.',
rewardExp: 17
},
{
id: 'avoid-public-blame',
label: '공개 문책을 늦춘다',
response: '황권은 성급한 문책을 막았고, 미축은 창고 관리들이 증언할 시간을 벌었습니다.',
rewardExp: 16
}
]
},
{
id: 'zhaoyun-wangping-after-gongan-collapse',
title: '나루를 끊는 눈',
availableAfterBattleIds: [campBattleIds.fortyThird],
unitIds: ['zhao-yun', 'wang-ping'],
bondId: 'zhao-yun__wang-ping_collapse',
rewardExp: 44,
lines: [
'왕평: 강동 수군은 큰길보다 갈대밭 뒤의 좁은 물목을 택했습니다. 다음에도 그럴 것입니다.',
'조운: 내가 빠르게 달려도 길을 모르면 늦소. 그대가 물목을 짚어 주면, 내가 먼저 끊겠소.',
'왕평: 성문보다 먼저 나루가 무너집니다. 나루를 막으면 성문도 하루 더 버틸 수 있습니다.'
],
choices: [
{
id: 'mark-hidden-fords',
label: '숨은 물목을 표시한다',
response: '왕평은 갈대밭 사이 물목을 표시했고, 조운은 다음 출진의 차단 경로를 익혔습니다.',
rewardExp: 16
},
{
id: 'drill-fast-blockade',
label: '빠른 차단을 훈련한다',
response: '조운의 기동대는 왕평이 잡은 길을 따라 나루 차단 훈련을 반복했습니다.',
rewardExp: 15
}
]
}
];
@@ -6044,6 +6142,66 @@ const campVisits: CampVisitDefinition[] = [
itemRewards: ['상처약 5']
}
]
},
{
id: 'gongan-collapse-gate-ledgers',
title: '공안 성문 군령 대조',
location: '공안 서문 군영',
availableAfterBattleIds: [campBattleIds.fortyThird],
bondId: 'mi-zhu__huang-quan_collapse',
description: '미축과 황권이 공안 성문 군령과 창고 장부를 대조하며, 강동 설객이 흔든 빈틈을 찾습니다.',
lines: [
'황권: 성문을 여닫은 기록과 창고 출입 기록이 서로 맞지 않습니다. 누군가 군령을 핑계로 빈칸을 만들었습니다.',
'미축: 장부를 다시 쓰면 숫자는 맞출 수 있지만, 이번에는 누가 왜 숨겼는지를 보아야 합니다.',
'성문 관리들은 침묵했지만, 선박 명부와 야간 군령 사이의 작은 차이가 드러났습니다.'
],
choices: [
{
id: 'trace-gate-orders',
label: '성문 군령을 추적한다',
response: '성문 군령의 경로가 정리되어 공안 병사들이 강동의 거짓 명령에 흔들릴 가능성이 줄었습니다.',
bondExp: 38,
itemRewards: ['공안 성문 기록 1']
},
{
id: 'protect-witnesses',
label: '증언자를 보호한다',
response: '황권은 성급한 문책을 막고 증언자를 보호했으며, 미축은 숨은 장부를 더 안전하게 확보했습니다.',
bondExp: 36,
gold: 1060,
itemRewards: ['상처약 6']
}
]
},
{
id: 'gongan-collapse-hidden-fords',
title: '갈대밭 물목 조사',
location: '공안 남쪽 갈대 나루',
availableAfterBattleIds: [campBattleIds.fortyThird],
bondId: 'zhao-yun__wang-ping_collapse',
description: '조운과 왕평이 강동 수군이 숨어든 갈대밭 물목을 조사하며, 다음 고립 전투의 차단 경로를 찾습니다.',
lines: [
'왕평: 이 물목은 큰 배가 못 지나갑니다. 그러나 작은 배와 백의 병사라면 밤에 충분히 넘어올 수 있습니다.',
'조운: 말이 닿지 않는 곳은 발로 익히면 되오. 다음에 저들이 오면 이 길부터 막겠소.',
'정찰병들은 갈대밭 사이에 작은 표식을 세우고, 나루마다 다른 횃불 신호를 정했습니다.'
],
choices: [
{
id: 'map-hidden-fords',
label: '숨은 물목을 지도에 남긴다',
response: '왕평은 물목 지도를 완성했고, 조운의 기동대는 다음 전투에서 먼저 차단할 길을 알게 되었습니다.',
bondExp: 38,
itemRewards: ['갈대밭 물목도 1']
},
{
id: 'train-ferry-blockade',
label: '나루 차단 훈련을 한다',
response: '조운의 기동대가 나루 차단 훈련을 마치자, 공안 남쪽 경계가 한층 빨라졌습니다.',
bondExp: 36,
gold: 1040,
itemRewards: ['탁주 4']
}
]
}
];
@@ -6130,7 +6288,12 @@ export class CampScene extends Phaser.Scene {
return;
}
if (battleId === campBattleIds.fortieth || battleId === campBattleIds.fortyFirst || battleId === campBattleIds.fortySecond) {
if (
battleId === campBattleIds.fortieth ||
battleId === campBattleIds.fortyFirst ||
battleId === campBattleIds.fortySecond ||
battleId === campBattleIds.fortyThird
) {
this.campaign = ensureCampaignRosterUnits(
[
...xuzhouRecruitUnits,
@@ -6174,7 +6337,8 @@ export class CampScene extends Phaser.Scene {
...fanCastleBonds,
...hanRiverFloodBonds,
...fanCastleSiegeBonds,
...jingRearCrisisBonds
...jingRearCrisisBonds,
...jingCollapseBonds
]
);
this.report = this.campaign.firstBattleReport ?? this.report;
@@ -6809,6 +6973,9 @@ export class CampScene extends Phaser.Scene {
if (this.campaign?.step === 'hanzhong-king-camp') {
return '한중왕 즉위 준비 군영';
}
if (battleId === campBattleIds.fortyThird) {
return '공안 성문 변고 후 군영';
}
if (battleId === campBattleIds.fortySecond) {
return '강릉 나루 경계전 후 군영';
}