Add Weishui north bank chapter

This commit is contained in:
2026-06-24 21:10:11 +09:00
parent ddc862d217
commit 018132b59c
11 changed files with 869 additions and 84 deletions

View File

@@ -56,6 +56,7 @@ import {
northernFourthBattleBonds,
northernFirstBattleBonds,
northernNinthBattleBonds,
northernEleventhBattleBonds,
northernSecondBattleBonds,
northernSeventhBattleBonds,
northernSixthBattleBonds,
@@ -460,9 +461,10 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
'sixty-first-battle-hanzhong-rain-defense',
'sixty-second-battle-qishan-renewed-offensive',
'sixty-third-battle-lucheng-pursuit',
'sixty-fourth-battle-weishui-camps'
'sixty-fourth-battle-weishui-camps',
'sixty-fifth-battle-weishui-northbank'
],
nextHints: ['한중 창고 정비', '출전 무장 재편', '기산 출진로', '천수·가정 방면', '강유 합류', '진창 공성 재계산', '무도·음평 확보', '한중 우로 방어', '기산 재출정', '노성 추격', '위수 진영']
nextHints: ['한중 창고 정비', '출전 무장 재편', '기산 출진로', '천수·가정 방면', '강유 합류', '진창 공성 재계산', '무도·음평 확보', '한중 우로 방어', '기산 재출정', '노성 추격', '위수 진영', '위수 북안']
}
];
@@ -530,7 +532,8 @@ const campBattleIds = {
sixtyFirst: 'sixty-first-battle-hanzhong-rain-defense',
sixtySecond: 'sixty-second-battle-qishan-renewed-offensive',
sixtyThird: 'sixty-third-battle-lucheng-pursuit',
sixtyFourth: 'sixty-fourth-battle-weishui-camps'
sixtyFourth: 'sixty-fourth-battle-weishui-camps',
sixtyFifth: 'sixty-fifth-battle-weishui-northbank'
} as const;
const defaultRequiredSortieUnitIds = ['liu-bei'];
@@ -1348,6 +1351,23 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
{ unitId: 'ma-liang', reason: '강가 마을의 고시문과 안심 약속을 정리해 북벌 명분을 실제 약속으로 이어 줍니다.' }
],
note: '위수 진영전은 추천 무장이 9명입니다. 물목 판단, 진영 확보, 수레 운송, 봉화 차단, 마을 안심 중 둘을 군영에 남겨야 합니다.'
},
'sixty-fifth-battle-weishui-northbank': {
maxUnits: 7,
requiredUnitIds: ['zhuge-liang'],
excludedUnitIds: ['liu-bei'],
recommended: [
{ unitId: 'zhuge-liang', reason: '북안 지연선과 전진 진영, 회수선의 폭을 동시에 조율해야 하는 총지휘관입니다.' },
{ unitId: 'jiang-wei', reason: '강북 낮은 길과 장합의 재추격로를 읽어 먼저 끊어야 합니다.' },
{ unitId: 'ma-dai', reason: '서량 기병의 측면 감각으로 곽회의 봉화로와 장합의 우회 기병을 견제합니다.' },
{ unitId: 'wang-ping', reason: '북안 전진 진영마다 정지선과 회수 표식을 세워 돌파가 고립으로 바뀌지 않게 합니다.' },
{ unitId: 'huang-quan', reason: '강북 진영을 얻은 뒤 버틸 날짜와 물릴 날짜를 장부로 계산합니다.' },
{ unitId: 'li-yan', reason: '강북 수레선과 예비 운송 기준을 현장에서 맞춰 보급 붕괴를 막습니다.' },
{ unitId: 'wei-yan', reason: '북안 진영 사이를 짧게 흔들 돌파 장수입니다. 조운의 회수선과 함께 계산해야 합니다.' },
{ unitId: 'zhao-yun', reason: '넓어진 강북 전선에서 예비대를 회수선으로 묶는 안정적 기동 담당입니다.' },
{ unitId: 'ma-liang', reason: '강북 마을의 고시문과 안심 약속을 정리해 북벌 명분을 실제 약속으로 이어 줍니다.' }
],
note: '위수 북안 압박전은 추천 무장이 9명입니다. 낮은 길 판단, 측면 견제, 장부와 수레, 돌파와 회수 중 둘을 군영에 남겨야 합니다.'
}
};
@@ -1480,6 +1500,23 @@ const sortieRulesByCampaignStep: Partial<Record<CampaignStep, SortieRuleDefiniti
{ unitId: 'ma-liang', reason: '강가 마을의 고시문을 다음 북벌 명분과 실제 약속으로 이어 줍니다.' }
],
note: '위수 진영 이후도 엔딩이 아니라 더 깊은 북방 전선의 재정비입니다. 강을 끼고 오래 싸울 사람과 더 밀고 들어갈 사람을 다시 나누어 보십시오.'
},
'sixty-fifth-camp': {
maxUnits: 7,
requiredUnitIds: ['zhuge-liang'],
excludedUnitIds: ['liu-bei'],
recommended: [
{ unitId: 'zhuge-liang', reason: '북안 지연선 이후 다음 전선의 폭을 다시 줄이고 늘릴 중심입니다.' },
{ unitId: 'jiang-wei', reason: '강북 낮은 길과 장합 재추격 대응 경험을 다음 북방 공격로로 정리합니다.' },
{ unitId: 'ma-dai', reason: '곽회 봉화로와 서량 기병 우회 기준을 다음 측면 운용에 반영합니다.' },
{ unitId: 'wang-ping', reason: '북안 전진 진영의 정지선과 회수 표식을 다음 배치의 안전장치로 남깁니다.' },
{ unitId: 'huang-quan', reason: '강북에서 소모된 군량과 남은 수레를 다음 출정 가능량으로 환산합니다.' },
{ unitId: 'li-yan', reason: '강북 운송 지연과 예비 수레 배정을 후방 기준으로 다시 세웁니다.' },
{ unitId: 'wei-yan', reason: '북안 진영 사이 돌파가 성과를 낸 지점과 멈춰야 했던 지점을 다음 군령으로 남깁니다.' },
{ unitId: 'zhao-yun', reason: '예비대 회수 기준을 더 넓어진 강북 전선의 안전장치로 남깁니다.' },
{ unitId: 'ma-liang', reason: '강북 마을의 고시문을 다음 북벌 명분과 실제 약속으로 이어 줍니다.' }
],
note: '위수 북안 이후도 엔딩이 아니라 더 깊은 북방 전선의 재정비입니다. 지킬 진영과 물릴 진영, 다시 밀고 들어갈 길을 나누어 보십시오.'
}
};
@@ -6889,6 +6926,60 @@ const campDialogues: CampDialogue[] = [
rewardExp: 34
}
]
},
{
id: 'northern-eleventh-jiangwei-madai-flank',
title: '낮은 길과 측면',
availableAfterBattleIds: [campBattleIds.sixtyFifth],
unitIds: ['jiang-wei', 'ma-dai'],
bondId: 'jiang-wei__ma-dai_northern-eleventh',
rewardExp: 112,
lines: [
'강유: 북안 낮은 길은 장합의 재추격이 먼저 지나갈 길이기도 했습니다.',
'마대: 그래서 옆을 물어야 했습니다. 적이 빠른 길을 믿을수록 측면이 먼저 흔들립니다.',
'강유: 다음 지도에는 빠른 길과 물어야 할 옆길을 같은 먹으로 남기겠습니다.'
],
choices: [
{
id: 'mark-low-road-flanks',
label: '낮은 길의 측면 표식을 남긴다',
response: '강유는 낮은 물목을 다시 그렸고, 마대는 그 길마다 기병이 물 측면 표식을 덧붙였습니다.',
rewardExp: 40
},
{
id: 'delay-rearguard-cavalry',
label: '재추격 기병을 늦춘다',
response: '마대는 재추격 기병이 모였던 길을 기억했고, 강유는 다음 출정에서 그 길을 먼저 끊는 군령을 적었습니다.',
rewardExp: 36
}
]
},
{
id: 'northern-eleventh-zhuge-liyan-carts',
title: '군령과 수레',
availableAfterBattleIds: [campBattleIds.sixtyFifth],
unitIds: ['zhuge-liang', 'li-yan'],
bondId: 'zhuge-liang__li-yan_northern-eleventh',
rewardExp: 110,
lines: [
'이엄: 북안 진영을 얻은 뒤에도 수레가 따라오지 못하면, 군령은 종이 위에서만 이깁니다.',
'제갈량: 그래서 오늘의 명령에는 나아갈 곳만이 아니라 물릴 곳도 적어야 합니다.',
'이엄: 다음에는 승리한 진영마다 수레를 붙일지, 깃발만 남길지 먼저 묻겠습니다.'
],
choices: [
{
id: 'bind-order-to-cart-line',
label: '군령과 수레선을 묶는다',
response: '제갈량은 전진 명령 옆에 수레가 닿을 날짜를 적었고, 이엄은 그보다 늦는 진영을 예비 표시로 돌렸습니다.',
rewardExp: 38
},
{
id: 'choose-retreatable-camps',
label: '물릴 수 있는 진영을 고른다',
response: '이엄은 물릴 수 있는 진영과 붙들 진영을 나누었고, 제갈량은 그 구분을 다음 북방 명령의 첫 줄에 올렸습니다.',
rewardExp: 36
}
]
}
];
@@ -9765,6 +9856,36 @@ const campVisits: CampVisitDefinition[] = [
itemRewards: ['쌀 40', '상처약 30']
}
]
},
{
id: 'northern-eleventh-northbank-forward-ledger',
title: '북안 전진 장부',
location: '위수 북안 군막',
availableAfterBattleIds: [campBattleIds.sixtyFifth],
bondId: 'wang-ping__huang-quan_northern-eleventh',
description: '왕평과 황권이 북안 전진 진영마다 정지선, 남길 군량, 물릴 날짜를 하나의 장부로 맞춥니다.',
lines: [
'왕평: 진영을 얻은 뒤에도 병사가 멈출 선을 모르면, 이긴 진영이 곧 갇힌 진영이 됩니다.',
'황권: 그렇다면 장부에는 진영 이름보다 먼저 멈출 선과 물릴 날짜를 적겠습니다.',
'군막의 탁자에는 북안 전진 진영, 회수 깃발, 강북 마을 군량이 한 장의 장부로 묶였습니다.'
],
choices: [
{
id: 'seal-northbank-forward-ledger',
label: '북안 전진 장부를 봉한다',
response: '황권은 북안 전진 장부를 봉했고, 왕평은 각 진영의 정지선에 같은 문양의 깃발을 세웠습니다.',
bondExp: 94,
itemRewards: ['북안 전진 장부 1']
},
{
id: 'store-northbank-village-supplies',
label: '강북 마을 예비 군량을 남긴다',
response: '강북 마을마다 쌀과 상처약이 남았고, 병사들은 돌아올 길이 지도뿐 아니라 실제 마을에도 남았다는 것을 확인했습니다.',
bondExp: 88,
gold: 3100,
itemRewards: ['쌀 42', '상처약 32']
}
]
}
];
@@ -9877,7 +9998,8 @@ export class CampScene extends Phaser.Scene {
battleId === campBattleIds.sixtyFirst ||
battleId === campBattleIds.sixtySecond ||
battleId === campBattleIds.sixtyThird ||
battleId === campBattleIds.sixtyFourth
battleId === campBattleIds.sixtyFourth ||
battleId === campBattleIds.sixtyFifth
) {
this.campaign = ensureCampaignRosterUnits(
[
@@ -9898,7 +10020,7 @@ export class CampScene extends Phaser.Scene {
...hanzhongOpeningRecruitUnits,
...hanzhongScoutRecruitUnits,
...hanzhongMainRecruitUnits,
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? jiangWeiRecruitUnits : [])
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? jiangWeiRecruitUnits : [])
],
[
...xuzhouRecruitBonds,
@@ -9938,15 +10060,16 @@ export class CampScene extends Phaser.Scene {
...mengHuoFinalCaptureBonds,
...northernFirstBattleBonds,
...northernSecondBattleBonds,
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernThirdBattleBonds : []),
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? jiangWeiRecruitBonds : []),
...(battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernFourthBattleBonds : []),
...(battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernFifthBattleBonds : []),
...(battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernSixthBattleBonds : []),
...(battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernSeventhBattleBonds : []),
...(battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernEighthBattleBonds : []),
...(battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth ? northernNinthBattleBonds : []),
...(battleId === campBattleIds.sixtyFourth ? northernTenthBattleBonds : [])
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernThirdBattleBonds : []),
...(battleId === campBattleIds.fiftySeventh || battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? jiangWeiRecruitBonds : []),
...(battleId === campBattleIds.fiftyEighth || battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernFourthBattleBonds : []),
...(battleId === campBattleIds.fiftyNinth || battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernFifthBattleBonds : []),
...(battleId === campBattleIds.sixtieth || battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernSixthBattleBonds : []),
...(battleId === campBattleIds.sixtyFirst || battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernSeventhBattleBonds : []),
...(battleId === campBattleIds.sixtySecond || battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernEighthBattleBonds : []),
...(battleId === campBattleIds.sixtyThird || battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernNinthBattleBonds : []),
...(battleId === campBattleIds.sixtyFourth || battleId === campBattleIds.sixtyFifth ? northernTenthBattleBonds : []),
...(battleId === campBattleIds.sixtyFifth ? northernEleventhBattleBonds : [])
]
);
this.report = this.campaign.firstBattleReport ?? this.report;
@@ -10587,6 +10710,9 @@ export class CampScene extends Phaser.Scene {
if (this.campaign?.step === 'northern-campaign-prep-camp') {
return '북벌 준비 군영';
}
if (battleId === campBattleIds.sixtyFifth) {
return '위수 북안 압박 후 군영';
}
if (battleId === campBattleIds.sixtyFourth) {
return '위수 진영전 후 군영';
}

View File

@@ -20,6 +20,7 @@ import {
sixtySecondBattleScenario,
sixtyThirdBattleScenario,
sixtyFourthBattleScenario,
sixtyFifthBattleScenario,
fortiethBattleScenario,
fortyFirstBattleScenario,
fortySecondBattleScenario,
@@ -428,6 +429,7 @@ export class TitleScene extends Phaser.Scene {
campaign.step === 'sixty-second-camp' ||
campaign.step === 'sixty-third-camp' ||
campaign.step === 'sixty-fourth-camp' ||
campaign.step === 'sixty-fifth-camp' ||
campaign.step === 'hanzhong-king-camp' ||
campaign.step === 'shu-han-foundation-camp' ||
campaign.step === 'baidi-entrustment-camp' ||
@@ -757,6 +759,11 @@ export class TitleScene extends Phaser.Scene {
return;
}
if (campaign.step === 'sixty-fifth-battle') {
this.scene.start('BattleScene', { battleId: sixtyFifthBattleScenario.id });
return;
}
if (campaign.step === 'first-victory-story') {
this.scene.start('StoryScene', { pages: firstBattleVictoryPages, nextScene: 'TitleScene' });
return;