Add Qishan renewed offensive chapter
This commit is contained in:
@@ -3907,6 +3907,59 @@ export const sixtyFirstBattleVictoryPages: StoryPage[] = [
|
||||
}
|
||||
];
|
||||
|
||||
export const sixtySecondBattleIntroPages: StoryPage[] = [
|
||||
{
|
||||
id: 'sixty-second-renewed-qishan-council',
|
||||
bgm: 'story-dark',
|
||||
chapter: '기산 재출정',
|
||||
background: 'story-qishan-renewed',
|
||||
speaker: '제갈량',
|
||||
text: '한중 북문의 비가 그치자 지켜 낸 길은 다시 북쪽을 향한 길이 되었습니다. 이번에는 노성 앞의 위군 지연선을 흔들어, 무도와 음평에서 이어진 보급로를 공격의 숨으로 바꾸겠습니다.'
|
||||
},
|
||||
{
|
||||
id: 'sixty-second-sima-yi-delay-line',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '사마의의 지연전',
|
||||
background: 'story-qishan-renewed',
|
||||
speaker: '강유',
|
||||
text: '사마의는 성을 내주지 않고 길을 늦추려 합니다. 장합은 기병으로 앞선을 찌르고, 곽회는 돌아갈 길을 끊으려 할 것입니다. 빠른 돌파와 돌아올 표식이 함께 움직여야 합니다.'
|
||||
},
|
||||
{
|
||||
id: 'sixty-second-supply-into-offense',
|
||||
bgm: 'story-dark',
|
||||
chapter: '보급을 공세로',
|
||||
background: 'story-qishan-renewed',
|
||||
speaker: '황권',
|
||||
text: '지난 전투에서 지킨 장부를 이번에는 밀어 올릴 차례입니다. 이엄을 후방에 남길지, 마대의 측면 기동을 넣을지, 혹은 마량의 민심 문서를 앞세울지 출전 명단에서 먼저 정해야 합니다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const sixtySecondBattleVictoryPages: StoryPage[] = [
|
||||
{
|
||||
id: 'sixty-second-victory-lucheng-pressure',
|
||||
bgm: 'militia-theme',
|
||||
chapter: '노성 앞을 누르다',
|
||||
background: 'story-qishan-renewed',
|
||||
text: '촉한군은 노성 앞의 지연선을 밀어 냈고, 사마의의 봉화와 곽회의 차단로가 동시에 이어지는 것을 막았습니다. 기산의 길은 다시 북벌군의 군문 앞에 열렸습니다.'
|
||||
},
|
||||
{
|
||||
id: 'sixty-second-victory-return-markers',
|
||||
bgm: 'story-dark',
|
||||
chapter: '돌아올 표식',
|
||||
background: 'story-qishan-renewed',
|
||||
speaker: '왕평',
|
||||
text: '앞으로 나아간 길마다 돌아올 표식이 함께 세워졌습니다. 강유와 위연이 열어 둔 길을 조운이 회수선으로 묶고, 황권과 마량은 그 길이 백성의 부담이 되지 않게 장부를 고쳤습니다.'
|
||||
},
|
||||
{
|
||||
id: 'sixty-second-next-northern-plan',
|
||||
bgm: 'story-dark',
|
||||
chapter: '더 깊은 북방 계산',
|
||||
background: 'story-qishan-renewed',
|
||||
speaker: '제갈량',
|
||||
text: '사마의는 한 번 물러났으나 전쟁은 아직 짧아지지 않았습니다. 다음 북벌에서는 이긴 길을 지키는 사람과 더 깊이 들어갈 사람을 다시 나누어야 합니다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const firstBattleMap: BattleMap = {
|
||||
width: 20,
|
||||
height: 18,
|
||||
@@ -4418,6 +4471,12 @@ export const sixtyFirstBattleMap: BattleMap = {
|
||||
terrain: createSixtyFirstBattleTerrain()
|
||||
};
|
||||
|
||||
export const sixtySecondBattleMap: BattleMap = {
|
||||
width: 124,
|
||||
height: 106,
|
||||
terrain: createSixtySecondBattleTerrain()
|
||||
};
|
||||
|
||||
export const firstBattleUnits: UnitData[] = [
|
||||
{
|
||||
id: 'liu-bei',
|
||||
@@ -17726,6 +17785,97 @@ export const sixtyFirstBattleUnits: UnitData[] = [
|
||||
createThirtyFirstEnemyUnit('northern-seventh-leader-cao-zhen', '조진', '위군 역공 총대장', 'rebelLeader', 213, 1660, 392, 114, 38)
|
||||
];
|
||||
|
||||
const sixtySecondBattleAllyPositions: Record<string, { x: number; y: number }> = {
|
||||
'guan-yu': { x: 15, y: 94 },
|
||||
'zhang-fei': { x: 22, y: 96 },
|
||||
'jian-yong': { x: 8, y: 101 },
|
||||
'mi-zhu': { x: 13, y: 102 },
|
||||
'sun-qian': { x: 18, y: 102 },
|
||||
'zhao-yun': { x: 30, y: 93 },
|
||||
'zhuge-liang': { x: 18, y: 89 },
|
||||
'ma-liang': { x: 24, y: 86 },
|
||||
'yi-ji': { x: 8, y: 103 },
|
||||
'gong-zhi': { x: 28, y: 101 },
|
||||
'huang-zhong': { x: 38, y: 90 },
|
||||
'wei-yan': { x: 45, y: 91 },
|
||||
'pang-tong': { x: 15, y: 85 },
|
||||
'fa-zheng': { x: 28, y: 84 },
|
||||
'wu-yi': { x: 47, y: 99 },
|
||||
'yan-yan': { x: 51, y: 92 },
|
||||
'li-yan': { x: 34, y: 83 },
|
||||
'huang-quan': { x: 12, y: 88 },
|
||||
'ma-chao': { x: 54, y: 88 },
|
||||
'ma-dai': { x: 59, y: 95 },
|
||||
'wang-ping': { x: 41, y: 83 },
|
||||
'jiang-wei': { x: 35, y: 86 }
|
||||
};
|
||||
|
||||
export const sixtySecondBattleUnits: UnitData[] = [
|
||||
...[
|
||||
...firstBattleUnits.filter((unit) => unit.faction === 'ally' && unit.id !== 'liu-bei'),
|
||||
...xuzhouRecruitUnits,
|
||||
...caoBreakRecruitUnits,
|
||||
...liuBiaoRecruitUnits,
|
||||
...zhugeRecruitUnits,
|
||||
...jingzhouRecruitUnits,
|
||||
...guiyangRecruitUnits,
|
||||
...wulingRecruitUnits,
|
||||
...changshaRecruitUnits,
|
||||
...yizhouRecruitUnits,
|
||||
...fuPassRecruitUnits,
|
||||
...luoCastleRecruitUnits,
|
||||
...luoCastleProperRecruitUnits,
|
||||
...chengduPressureRecruitUnits,
|
||||
...chengduSurrenderRecruitUnits,
|
||||
...hanzhongOpeningRecruitUnits,
|
||||
...hanzhongScoutRecruitUnits,
|
||||
...hanzhongMainRecruitUnits,
|
||||
...jiangWeiRecruitUnits
|
||||
].map((unit) => placeScenarioUnit(unit, sixtySecondBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-a', '노성 서로 척후병', '서쪽 고개 정찰', 'bandit', 214, 1060, 292, 52, 84),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-b', '기산 보급로 척후병', '보급로 정찰', 'bandit', 214, 1060, 292, 64, 81),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-c', '노성 앞 척후병', '중앙 고개 정찰', 'bandit', 215, 1072, 294, 78, 74),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-d', '동쪽 물목 척후병', '동쪽 물목 정찰', 'bandit', 215, 1072, 294, 92, 66),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-e', '사마의 전초 척후병', '본영 정찰', 'bandit', 216, 1084, 296, 108, 50),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-scout-f', '북쪽 봉화 척후병', '봉화대 정찰', 'bandit', 216, 1084, 296, 121, 30),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-a', '위군 기산 보병', '서쪽 고개 보병', 'yellowTurban', 215, 1540, 368, 55, 78),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-b', '위군 보급로 보병', '보급로 보병', 'yellowTurban', 215, 1540, 368, 68, 74),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-c', '위군 노성 보병', '중앙 보병', 'yellowTurban', 216, 1560, 372, 81, 68),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-d', '위군 물목 보병', '동쪽 물목 보병', 'yellowTurban', 216, 1560, 372, 94, 61),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-e', '위군 지연 보병', '지연선 보병', 'yellowTurban', 217, 1580, 376, 106, 53),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-f', '사마의 본영 보병', '본영 보병', 'yellowTurban', 217, 1580, 376, 116, 41),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-g', '위군 보급 차단병', '수레길 차단 보병', 'yellowTurban', 218, 1600, 380, 100, 82),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-infantry-h', '장합 별동 보병', '별동대 보병', 'yellowTurban', 218, 1600, 380, 121, 23),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-a', '기산 서로 궁병', '서쪽 능선 궁병', 'archer', 215, 1130, 310, 62, 69),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-b', '보급로 궁병', '보급로 궁병', 'archer', 215, 1130, 310, 74, 64),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-c', '노성 능선 궁병', '중앙 능선 궁병', 'archer', 216, 1142, 312, 89, 57),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-d', '동쪽 물목 궁병', '동쪽 물목 궁병', 'archer', 217, 1154, 314, 102, 49),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-e', '사마의 본영 궁병', '본영 궁병', 'archer', 217, 1154, 314, 114, 37),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-archer-f', '북쪽 봉화 궁병', '봉화대 궁병', 'archer', 218, 1166, 316, 122, 18),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-a', '장합 추격 기병', '서쪽 추격 기병', 'cavalry', 216, 1600, 388, 53, 72),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-b', '장합 추격 기병', '보급로 추격 기병', 'cavalry', 216, 1600, 388, 66, 69),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-c', '장합 추격 기병', '중앙 추격 기병', 'cavalry', 217, 1622, 392, 82, 62),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-d', '곽회 차단 기병', '동쪽 차단 기병', 'cavalry', 218, 1644, 396, 96, 55),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-e', '사마의 예비 기병', '본영 예비 기병', 'cavalry', 218, 1644, 396, 110, 47),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-cavalry-f', '북쪽 봉화 기병', '봉화 차단 기병', 'cavalry', 219, 1666, 400, 121, 28),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-a', '기산 서로 수비대', '서쪽 고개 수비', 'yellowTurban', 216, 1560, 374, 48, 58),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-b', '보급로 수비대', '보급로 수비', 'yellowTurban', 216, 1560, 374, 64, 53),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-c', '노성 앞 수비대', '중앙 고개 수비', 'yellowTurban', 217, 1580, 378, 80, 45),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-d', '동쪽 물목 수비대', '동쪽 물목 수비', 'yellowTurban', 217, 1580, 378, 96, 38),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-e', '사마의 본영 수비대', '본영 수비', 'yellowTurban', 218, 1600, 382, 110, 30),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-ridge-guard-f', '북쪽 봉화 수비대', '북쪽 봉화 수비', 'yellowTurban', 218, 1600, 382, 122, 14),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-strategist-a', '위군 지연 군리', '지연 장부 군리', 'strategist', 216, 1200, 328, 78, 60),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-strategist-b', '위군 보급 군리', '보급 차단 군리', 'strategist', 217, 1212, 330, 92, 51),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-strategist-c', '사마의 본영 군리', '본영 장부 군리', 'strategist', 217, 1212, 330, 106, 42),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-strategist-d', '곽회 차단 군리', '차단로 장부 군리', 'strategist', 218, 1224, 332, 112, 70),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-officer-lucheng', '노성 전초장', '노성 압박 장수', 'rebelLeader', 220, 1660, 398, 90, 76),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-officer-supply', '보급 차단장', '기산 보급 차단 장수', 'rebelLeader', 220, 1660, 398, 103, 64),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-officer-guo-huai', '곽회', '측면 차단 장수', 'rebelLeader', 219, 1640, 394, 112, 74),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-officer-relay', '봉화 연락장', '노성 봉화 장수', 'rebelLeader', 219, 1640, 394, 108, 58),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-officer-zhang-he', '장합', '추격 별동대장', 'rebelLeader', 221, 1700, 404, 118, 27),
|
||||
createThirtyFirstEnemyUnit('northern-eighth-leader-sima-yi', '사마의', '위군 지연 총지휘', 'rebelLeader', 222, 1740, 410, 116, 40)
|
||||
];
|
||||
|
||||
export const firstBattleBonds: BattleBond[] = [
|
||||
{
|
||||
id: 'liu-bei__guan-yu',
|
||||
@@ -19083,6 +19233,46 @@ export const sixtyFirstBattleBonds: BattleBond[] = [
|
||||
...northernSeventhBattleBonds
|
||||
].map(cloneBattleBondForScenario);
|
||||
|
||||
export const northernEighthBattleBonds: BattleBond[] = [
|
||||
{
|
||||
id: 'jiang-wei__wei-yan_northern-eighth',
|
||||
unitIds: ['jiang-wei', 'wei-yan'],
|
||||
title: '앞길과 돌파',
|
||||
level: 52,
|
||||
exp: 0,
|
||||
description: '강유의 길눈과 위연의 돌파 판단이 맞물리면, 노성 앞 지연선을 빠르게 흔들되 돌아올 길을 잃지 않을 수 있습니다.'
|
||||
},
|
||||
{
|
||||
id: 'zhao-yun__wang-ping_northern-eighth',
|
||||
unitIds: ['zhao-yun', 'wang-ping'],
|
||||
title: '회수선의 표식',
|
||||
level: 54,
|
||||
exp: 0,
|
||||
description: '조운의 예비대 회수와 왕평의 산길 표식이 이어지면, 깊이 들어간 부대도 사마의의 지연전 속에서 제때 돌아올 수 있습니다.'
|
||||
},
|
||||
{
|
||||
id: 'huang-quan__ma-liang_northern-eighth',
|
||||
unitIds: ['huang-quan', 'ma-liang'],
|
||||
title: '장부와 고시문',
|
||||
level: 48,
|
||||
exp: 0,
|
||||
description: '황권의 군량 장부와 마량의 민심 문서가 함께 움직이면, 공격로가 백성의 부담으로만 남지 않게 조정할 수 있습니다.'
|
||||
},
|
||||
{
|
||||
id: 'li-yan__ma-dai_northern-eighth',
|
||||
unitIds: ['li-yan', 'ma-dai'],
|
||||
title: '수레와 측면',
|
||||
level: 44,
|
||||
exp: 0,
|
||||
description: '이엄의 운송 기준과 마대의 측면 기동이 맞으면, 보급 수레가 늦어질 때도 기병이 빈틈을 메울 수 있습니다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const sixtySecondBattleBonds: BattleBond[] = [
|
||||
...sixtyFirstBattleBonds,
|
||||
...northernEighthBattleBonds
|
||||
].map(cloneBattleBondForScenario);
|
||||
|
||||
function createEighthBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 22 }, (_, y) =>
|
||||
Array.from({ length: 26 }, (_, x): TerrainType => {
|
||||
@@ -22479,6 +22669,86 @@ function createSixtyFirstBattleTerrain(): TerrainType[][] {
|
||||
);
|
||||
}
|
||||
|
||||
function createSixtySecondBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 106 }, (_, y) =>
|
||||
Array.from({ length: 124 }, (_, x): TerrainType => {
|
||||
if (
|
||||
(x >= 5 && x <= 12 && y >= 0 && y <= 105) ||
|
||||
(x >= 64 && x <= 71 && y >= 12 && y <= 105) ||
|
||||
(x >= 0 && x <= 123 && y >= 98)
|
||||
) {
|
||||
return 'river';
|
||||
}
|
||||
if (
|
||||
(x >= 7 && x <= 84 && y >= 90 && y <= 96) ||
|
||||
(x >= 22 && x <= 103 && y >= 78 && y <= 86) ||
|
||||
(x >= 48 && x <= 112 && y >= 66 && y <= 76) ||
|
||||
(x >= 76 && x <= 120 && y >= 52 && y <= 64) ||
|
||||
(x >= 93 && x <= 123 && y >= 37 && y <= 49) ||
|
||||
(x >= 30 && x <= 40 && y >= 70 && y <= 100) ||
|
||||
(x >= 55 && x <= 64 && y >= 56 && y <= 92) ||
|
||||
(x >= 85 && x <= 95 && y >= 42 && y <= 82) ||
|
||||
(x >= 99 && x <= 109 && y >= 24 && y <= 68) ||
|
||||
(x >= 44 && x <= 82 && y >= 82 && y <= 88)
|
||||
) {
|
||||
return 'road';
|
||||
}
|
||||
if (
|
||||
(x >= 0 && x <= 38 && y >= 60 && y <= 94) ||
|
||||
(x >= 42 && x <= 82 && y >= 75 && y <= 97) ||
|
||||
(x >= 88 && x <= 123 && y >= 69 && y <= 95) ||
|
||||
(x >= 14 && x <= 42 && y >= 44 && y <= 64) ||
|
||||
(x >= 98 && x <= 123 && y >= 52 && y <= 74) ||
|
||||
(x >= 116 && x <= 123 && y >= 26 && y <= 48)
|
||||
) {
|
||||
return 'forest';
|
||||
}
|
||||
if (
|
||||
(x >= 0 && x <= 52 && y <= 41) ||
|
||||
(x >= 46 && x <= 94 && y <= 35) ||
|
||||
(x >= 86 && x <= 123 && y <= 53) ||
|
||||
(x >= 98 && x <= 123 && y >= 45 && y <= 74)
|
||||
) {
|
||||
return 'hill';
|
||||
}
|
||||
if (
|
||||
(x <= 2 && y <= 96) ||
|
||||
(x >= 121 && y <= 90) ||
|
||||
(x >= 39 && x <= 46 && y >= 0 && y <= 66) ||
|
||||
(x >= 77 && x <= 83 && y >= 0 && y <= 48) ||
|
||||
(x >= 60 && x <= 68 && y >= 86 && y <= 105)
|
||||
) {
|
||||
return 'cliff';
|
||||
}
|
||||
if (
|
||||
(x >= 12 && x <= 30 && y >= 86 && y <= 96) ||
|
||||
(x >= 43 && x <= 64 && y >= 73 && y <= 85) ||
|
||||
(x >= 80 && x <= 100 && y >= 59 && y <= 71) ||
|
||||
(x >= 102 && x <= 120 && y >= 43 && y <= 57)
|
||||
) {
|
||||
return 'village';
|
||||
}
|
||||
if (
|
||||
(x >= 20 && x <= 48 && y >= 80 && y <= 94) ||
|
||||
(x >= 55 && x <= 82 && y >= 67 && y <= 80) ||
|
||||
(x >= 89 && x <= 114 && y >= 53 && y <= 66) ||
|
||||
(x >= 99 && x <= 118 && y >= 24 && y <= 39)
|
||||
) {
|
||||
return 'camp';
|
||||
}
|
||||
if (
|
||||
(x >= 49 && x <= 70 && y >= 48 && y <= 64) ||
|
||||
(x >= 73 && x <= 100 && y >= 38 && y <= 53) ||
|
||||
(x >= 95 && x <= 120 && y >= 47 && y <= 63) ||
|
||||
(x >= 104 && x <= 123 && y >= 14 && y <= 36)
|
||||
) {
|
||||
return 'fort';
|
||||
}
|
||||
return 'plain';
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
|
||||
return {
|
||||
...cloneUnitForScenario(unit),
|
||||
|
||||
Reference in New Issue
Block a user