Add Yiling vanguard chapter
This commit is contained in:
@@ -828,7 +828,15 @@ const unitTexture: Record<string, string> = {
|
||||
'maicheng-officer-ma-zhong': 'unit-rebel',
|
||||
'maicheng-officer-lu-xun': 'unit-rebel-archer',
|
||||
'maicheng-officer-xu-huang': 'unit-rebel-cavalry',
|
||||
'maicheng-leader-lu-meng': 'unit-rebel-leader'
|
||||
'maicheng-leader-lu-meng': 'unit-rebel-leader',
|
||||
'yiling-strategist-a': 'unit-rebel-archer',
|
||||
'yiling-strategist-b': 'unit-rebel-archer',
|
||||
'yiling-strategist-c': 'unit-rebel-archer',
|
||||
'yiling-officer-gan-ning-remnant': 'unit-rebel-leader',
|
||||
'yiling-officer-zhu-ran': 'unit-rebel-leader',
|
||||
'yiling-officer-pan-zhang': 'unit-rebel-leader',
|
||||
'yiling-officer-ma-zhong': 'unit-rebel',
|
||||
'yiling-leader-lu-xun': 'unit-rebel-leader'
|
||||
};
|
||||
|
||||
const unitTextureByClass: Partial<Record<UnitClassKey, string>> = {
|
||||
@@ -2114,7 +2122,46 @@ const enemyAiByUnitId: Record<string, EnemyAiBehavior> = {
|
||||
'maicheng-officer-ma-zhong': 'aggressive',
|
||||
'maicheng-officer-lu-xun': 'hold',
|
||||
'maicheng-officer-xu-huang': 'aggressive',
|
||||
'maicheng-leader-lu-meng': 'guard'
|
||||
'maicheng-leader-lu-meng': 'guard',
|
||||
'yiling-wu-scout-a': 'aggressive',
|
||||
'yiling-wu-scout-b': 'aggressive',
|
||||
'yiling-wu-scout-c': 'aggressive',
|
||||
'yiling-wu-scout-d': 'aggressive',
|
||||
'yiling-wu-infantry-a': 'guard',
|
||||
'yiling-wu-infantry-b': 'guard',
|
||||
'yiling-wu-infantry-c': 'guard',
|
||||
'yiling-wu-infantry-d': 'guard',
|
||||
'yiling-wu-infantry-e': 'guard',
|
||||
'yiling-wu-infantry-f': 'guard',
|
||||
'yiling-wu-archer-a': 'hold',
|
||||
'yiling-wu-archer-b': 'hold',
|
||||
'yiling-wu-archer-c': 'hold',
|
||||
'yiling-wu-archer-d': 'hold',
|
||||
'yiling-wu-archer-e': 'hold',
|
||||
'yiling-wu-archer-f': 'hold',
|
||||
'yiling-wu-cavalry-a': 'aggressive',
|
||||
'yiling-wu-cavalry-b': 'aggressive',
|
||||
'yiling-wu-cavalry-c': 'aggressive',
|
||||
'yiling-wu-cavalry-d': 'aggressive',
|
||||
'yiling-wu-marine-a': 'aggressive',
|
||||
'yiling-wu-marine-b': 'guard',
|
||||
'yiling-wu-marine-c': 'guard',
|
||||
'yiling-wu-ambusher-a': 'aggressive',
|
||||
'yiling-wu-ambusher-b': 'aggressive',
|
||||
'yiling-wu-ambusher-c': 'aggressive',
|
||||
'yiling-wu-ambusher-d': 'aggressive',
|
||||
'yiling-wu-ambusher-e': 'aggressive',
|
||||
'yiling-wu-guard-a': 'guard',
|
||||
'yiling-wu-guard-b': 'guard',
|
||||
'yiling-wu-guard-c': 'guard',
|
||||
'yiling-strategist-a': 'hold',
|
||||
'yiling-strategist-b': 'hold',
|
||||
'yiling-strategist-c': 'hold',
|
||||
'yiling-officer-gan-ning-remnant': 'aggressive',
|
||||
'yiling-officer-zhu-ran': 'guard',
|
||||
'yiling-officer-pan-zhang': 'aggressive',
|
||||
'yiling-officer-ma-zhong': 'aggressive',
|
||||
'yiling-leader-lu-xun': 'hold'
|
||||
};
|
||||
|
||||
const defaultEnemyAiByClass: Partial<Record<UnitClassKey, EnemyAiBehavior>> = {
|
||||
|
||||
@@ -10,6 +10,7 @@ import fortyFirstBattleMapUrl from '../../assets/images/battle/forty-first-battl
|
||||
import fortySecondBattleMapUrl from '../../assets/images/battle/forty-second-battle-map.svg';
|
||||
import fortyThirdBattleMapUrl from '../../assets/images/battle/forty-third-battle-map.svg';
|
||||
import fortyFourthBattleMapUrl from '../../assets/images/battle/forty-fourth-battle-map.svg';
|
||||
import fortyFifthBattleMapUrl from '../../assets/images/battle/forty-fifth-battle-map.svg';
|
||||
import fourteenthBattleMapUrl from '../../assets/images/battle/fourteenth-battle-map.svg';
|
||||
import fourthBattleMapUrl from '../../assets/images/battle/fourth-battle-map.svg';
|
||||
import ninthBattleMapUrl from '../../assets/images/battle/ninth-battle-map.svg';
|
||||
@@ -146,6 +147,7 @@ export class BootScene extends Phaser.Scene {
|
||||
this.load.image('battle-map-forty-second', fortySecondBattleMapUrl);
|
||||
this.load.image('battle-map-forty-third', fortyThirdBattleMapUrl);
|
||||
this.load.image('battle-map-forty-fourth', fortyFourthBattleMapUrl);
|
||||
this.load.image('battle-map-forty-fifth', fortyFifthBattleMapUrl);
|
||||
this.load.image('portrait-liu-bei', liuBeiPortraitUrl);
|
||||
this.load.image('portrait-guan-yu', guanYuPortraitUrl);
|
||||
this.load.image('portrait-zhang-fei', zhangFeiPortraitUrl);
|
||||
|
||||
@@ -47,6 +47,7 @@ import {
|
||||
xuzhouRecruitUnits,
|
||||
yizhouRecruitBonds,
|
||||
yizhouRecruitUnits,
|
||||
yilingVanguardBonds,
|
||||
zhugeRecruitBonds,
|
||||
zhugeRecruitUnits,
|
||||
type PortraitKey,
|
||||
@@ -398,9 +399,10 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
|
||||
'forty-first-battle-fan-castle-siege',
|
||||
'forty-second-battle-jing-rear-crisis',
|
||||
'forty-third-battle-gongan-collapse',
|
||||
'forty-fourth-battle-maicheng-isolation'
|
||||
'forty-fourth-battle-maicheng-isolation',
|
||||
'forty-fifth-battle-yiling-vanguard'
|
||||
],
|
||||
nextHints: ['왕업 선언', '번성 포위', '형주 위기']
|
||||
nextHints: ['왕업 선언', '번성 포위', '형주 위기', '이릉 복수전']
|
||||
}
|
||||
];
|
||||
|
||||
@@ -448,7 +450,8 @@ const campBattleIds = {
|
||||
fortyFirst: 'forty-first-battle-fan-castle-siege',
|
||||
fortySecond: 'forty-second-battle-jing-rear-crisis',
|
||||
fortyThird: 'forty-third-battle-gongan-collapse',
|
||||
fortyFourth: 'forty-fourth-battle-maicheng-isolation'
|
||||
fortyFourth: 'forty-fourth-battle-maicheng-isolation',
|
||||
fortyFifth: 'forty-fifth-battle-yiling-vanguard'
|
||||
} as const;
|
||||
|
||||
const defaultRequiredSortieUnitIds = ['liu-bei'];
|
||||
@@ -967,6 +970,20 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
|
||||
{ unitId: 'ma-liang', reason: '형주 민심과 맥성 북문 병사들의 흔들림을 다독이는 참모입니다.' }
|
||||
],
|
||||
note: '맥성 고립전은 스물두 명 중 일곱 명만 출전합니다. 유비와 관우는 필수이며, 북문 돌파, 갈대 물목 차단, 위군 기병 대응 중 어디에 힘을 실을지 선택하십시오.'
|
||||
},
|
||||
'forty-fifth-battle-yiling-vanguard': {
|
||||
maxUnits: 7,
|
||||
requiredUnitIds: ['liu-bei'],
|
||||
recommended: [
|
||||
{ unitId: 'liu-bei', reason: '형주 상실 뒤 이릉으로 향하는 복수전의 주장입니다.' },
|
||||
{ unitId: 'zhang-fei', reason: '분노를 전열 돌파로 바꾸는 강한 선봉입니다.' },
|
||||
{ unitId: 'zhao-yun', reason: '강변과 숲길 사이를 빠르게 오가며 늘어진 진영을 보강합니다.' },
|
||||
{ unitId: 'ma-chao', reason: '오군 기병과 선봉을 맞받아치는 강한 측면 압박 카드입니다.' },
|
||||
{ unitId: 'zhuge-liang', reason: '육손의 기다림과 화공 위험을 읽어 진영 과열을 막습니다.' },
|
||||
{ unitId: 'huang-quan', reason: '긴 보급로와 강변 진영을 신중하게 계산하는 참모입니다.' },
|
||||
{ unitId: 'ma-liang', reason: '형주 상실 뒤 흩어진 잔병과 현지 민심을 다독이는 연결 축입니다.' }
|
||||
],
|
||||
note: '이릉 진격로는 스물두 명 중 일곱 명만 출전합니다. 유비는 필수이며, 복수의 선봉과 보급·화공 대비를 균형 있게 고르는 전투입니다.'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4615,6 +4632,87 @@ const campDialogues: CampDialogue[] = [
|
||||
rewardExp: 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'liu-zhang-after-yiling-vanguard',
|
||||
title: '복수의 맹세',
|
||||
availableAfterBattleIds: [campBattleIds.fortyFifth],
|
||||
unitIds: ['liu-bei', 'zhang-fei'],
|
||||
bondId: 'liu-bei__zhang-fei_yiling',
|
||||
rewardExp: 52,
|
||||
lines: [
|
||||
'장비: 형님, 길이 열렸다면 더 기다릴 까닭이 없습니다. 오군의 깃발이 보이는 곳까지 단숨에 밀어붙입시다!',
|
||||
'유비: 익덕의 분노가 내 마음과 다르지 않소. 그러나 병사들이 분노보다 먼저 쓰러져서는 안 되오.',
|
||||
'장비: 그럼 제가 앞에서 길을 열겠습니다. 형님은 뒤의 깃발을 흔들리지 않게 붙잡아 주십시오.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'temper-revenge-charge',
|
||||
label: '분노의 돌격을 다스린다',
|
||||
response: '유비는 장비의 돌격을 인정하되 진영의 호흡을 맞추라 당부했고, 장비는 창끝을 한 번 더 가다듬었습니다.',
|
||||
rewardExp: 18
|
||||
},
|
||||
{
|
||||
id: 'promise-brother-oath',
|
||||
label: '형제의 맹세를 다시 세운다',
|
||||
response: '두 사람은 무너진 형주의 길 위에서 도원의 맹세를 다시 떠올렸고, 병사들은 복수의 깃발 아래 모였습니다.',
|
||||
rewardExp: 17
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'zhuge-huangquan-after-yiling-vanguard',
|
||||
title: '불길을 읽는 장부',
|
||||
availableAfterBattleIds: [campBattleIds.fortyFifth],
|
||||
unitIds: ['zhuge-liang', 'huang-quan'],
|
||||
bondId: 'zhuge-liang__huang-quan_yiling',
|
||||
rewardExp: 50,
|
||||
lines: [
|
||||
'황권: 이릉 길은 넓어 보여도 진영이 길게 늘어지면 하나의 불씨가 여러 군막으로 옮겨붙습니다.',
|
||||
'제갈량: 육손이 기다리는 까닭도 거기에 있겠지요. 승리보다 진영의 길이가 먼저 위험해졌습니다.',
|
||||
'황권: 보급 장부에 불이 옮겨붙기 전에, 군막의 간격과 물길을 다시 정해야 합니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'space-camps-carefully',
|
||||
label: '군막 간격을 다시 잰다',
|
||||
response: '제갈량과 황권은 군막의 간격과 물길을 다시 표시했고, 촉한군은 화공 위험을 조금 더 의식하게 되었습니다.',
|
||||
rewardExp: 18
|
||||
},
|
||||
{
|
||||
id: 'log-river-supply',
|
||||
label: '강변 보급 장부를 정리한다',
|
||||
response: '황권은 강변 보급 장부를 정리했고, 제갈량은 길어진 진영이 무너질 지점을 미리 짚었습니다.',
|
||||
rewardExp: 17
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'zhaoyun-machao-after-yiling-vanguard',
|
||||
title: '동진 기동대',
|
||||
availableAfterBattleIds: [campBattleIds.fortyFifth],
|
||||
unitIds: ['zhao-yun', 'ma-chao'],
|
||||
bondId: 'zhao-yun__ma-chao_yiling',
|
||||
rewardExp: 48,
|
||||
lines: [
|
||||
'마초: 오군은 달려들지 않고 뒤로 물러납니다. 말이 빠를수록 빈 곳을 치게 만들려는 속셈입니다.',
|
||||
'조운: 그렇다면 빠르게 가되, 돌아올 길을 먼저 보아야 하오.',
|
||||
'마초: 내가 측면을 흔들면 장군께서 끊어진 길을 메우십시오. 진영이 길어져도 기병이 서로를 잃지 않게 하겠습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'pair-cavalry-flanks',
|
||||
label: '기병 측면을 짝지운다',
|
||||
response: '조운과 마초는 기병대를 둘로 나누어도 서로의 깃발을 잃지 않도록 신호를 정했습니다.',
|
||||
rewardExp: 17
|
||||
},
|
||||
{
|
||||
id: 'hold-return-road',
|
||||
label: '귀환로를 먼저 잡는다',
|
||||
response: '마초는 돌격 전 귀환로를 표시했고, 조운은 뒤처진 진영을 빠르게 보강할 길을 익혔습니다.',
|
||||
rewardExp: 16
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -6384,6 +6482,66 @@ const campVisits: CampVisitDefinition[] = [
|
||||
itemRewards: ['갈대 물목 표식 1']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'yiling-river-camp-lines',
|
||||
title: '이릉 강변 군막 간격 점검',
|
||||
location: '이릉 서쪽 강변 진영',
|
||||
availableAfterBattleIds: [campBattleIds.fortyFifth],
|
||||
bondId: 'zhuge-liang__huang-quan_yiling',
|
||||
description: '제갈량과 황권이 강변 진영의 군막 간격, 물길, 불길이 번질 수 있는 마른 풀밭을 점검합니다.',
|
||||
lines: [
|
||||
'황권: 군막이 강을 따라 길게 늘어서면 보급은 편하지만, 불길을 끊을 지점이 줄어듭니다.',
|
||||
'제갈량: 적이 싸우지 않고 기다릴 때는, 우리가 스스로 약해지는 모양을 먼저 살펴야 합니다.',
|
||||
'병사들은 군막 사이의 마른 풀을 걷어 내고, 물동이를 두는 지점을 새로 표시했습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'clear-dry-grass-lines',
|
||||
label: '마른 풀밭을 걷어낸다',
|
||||
response: '강변 군막 사이의 마른 풀이 치워졌고, 화공 위험을 낮출 작은 방화선이 생겼습니다.',
|
||||
bondExp: 40,
|
||||
itemRewards: ['강변 진영 말뚝 1']
|
||||
},
|
||||
{
|
||||
id: 'recount-river-supply',
|
||||
label: '강변 보급을 재점검한다',
|
||||
response: '황권은 보급 수량을 다시 세고, 제갈량은 물길마다 예비 병력을 세울 위치를 정했습니다.',
|
||||
bondExp: 38,
|
||||
gold: 1160,
|
||||
itemRewards: ['상처약 6']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'yiling-forward-scouts',
|
||||
title: '동진로 전초 정찰',
|
||||
location: '이릉 동쪽 숲길',
|
||||
availableAfterBattleIds: [campBattleIds.fortyFifth],
|
||||
bondId: 'zhao-yun__ma-chao_yiling',
|
||||
description: '조운과 마초가 동쪽 숲길의 빈 공간과 오군의 유인 흔적을 살피며 기병 신호를 정합니다.',
|
||||
lines: [
|
||||
'마초: 적이 비운 숲길은 달리기 좋지만, 너무 좋은 길은 대개 함정입니다.',
|
||||
'조운: 길을 의심하되 멈추지는 않겠소. 우리가 먼저 흔들리면 뒤의 보병도 늦어집니다.',
|
||||
'정찰 기병들은 숲길 가장자리에 작은 천 조각을 묶어, 돌아올 때 놓치지 않을 신호를 남겼습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'mark-cavalry-signals',
|
||||
label: '기병 신호를 남긴다',
|
||||
response: '동진로의 숲길마다 작은 기병 신호가 남아, 촉한 선봉이 깊이 들어가도 서로의 위치를 더 쉽게 확인하게 되었습니다.',
|
||||
bondExp: 38,
|
||||
itemRewards: ['이릉 동진 지도 1']
|
||||
},
|
||||
{
|
||||
id: 'test-empty-forest-road',
|
||||
label: '빈 숲길을 시험한다',
|
||||
response: '조운과 마초는 일부러 빈 길을 시험해 보며, 오군이 숨기려는 매복 지점을 몇 곳 찾아냈습니다.',
|
||||
bondExp: 36,
|
||||
gold: 1120,
|
||||
itemRewards: ['탁주 4']
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -6476,7 +6634,8 @@ export class CampScene extends Phaser.Scene {
|
||||
battleId === campBattleIds.fortyFirst ||
|
||||
battleId === campBattleIds.fortySecond ||
|
||||
battleId === campBattleIds.fortyThird ||
|
||||
battleId === campBattleIds.fortyFourth
|
||||
battleId === campBattleIds.fortyFourth ||
|
||||
battleId === campBattleIds.fortyFifth
|
||||
) {
|
||||
this.campaign = ensureCampaignRosterUnits(
|
||||
[
|
||||
@@ -6523,7 +6682,8 @@ export class CampScene extends Phaser.Scene {
|
||||
...fanCastleSiegeBonds,
|
||||
...jingRearCrisisBonds,
|
||||
...jingCollapseBonds,
|
||||
...maichengIsolationBonds
|
||||
...maichengIsolationBonds,
|
||||
...yilingVanguardBonds
|
||||
]
|
||||
);
|
||||
this.report = this.campaign.firstBattleReport ?? this.report;
|
||||
@@ -7158,6 +7318,9 @@ export class CampScene extends Phaser.Scene {
|
||||
if (this.campaign?.step === 'hanzhong-king-camp') {
|
||||
return '한중왕 즉위 준비 군영';
|
||||
}
|
||||
if (battleId === campBattleIds.fortyFifth) {
|
||||
return '이릉 진격로 후 군영';
|
||||
}
|
||||
if (battleId === campBattleIds.fortyFourth) {
|
||||
return '맥성 고립전 후 군영';
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
fortySecondBattleScenario,
|
||||
fortyThirdBattleScenario,
|
||||
fortyFourthBattleScenario,
|
||||
fortyFifthBattleScenario,
|
||||
fifthBattleScenario,
|
||||
fifteenthBattleScenario,
|
||||
fourteenthBattleScenario,
|
||||
@@ -388,6 +389,7 @@ export class TitleScene extends Phaser.Scene {
|
||||
campaign.step === 'forty-second-camp' ||
|
||||
campaign.step === 'forty-third-camp' ||
|
||||
campaign.step === 'forty-fourth-camp' ||
|
||||
campaign.step === 'forty-fifth-camp' ||
|
||||
campaign.step === 'hanzhong-king-camp' ||
|
||||
campaign.step === 'shu-han-foundation-camp'
|
||||
) {
|
||||
@@ -615,6 +617,11 @@ export class TitleScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'forty-fifth-battle') {
|
||||
this.scene.start('BattleScene', { battleId: fortyFifthBattleScenario.id });
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'first-victory-story') {
|
||||
this.scene.start('StoryScene', { pages: firstBattleVictoryPages, nextScene: 'TitleScene' });
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user