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

@@ -1766,6 +1766,68 @@ export const twentySeventhBattleVictoryPages: StoryPage[] = [
}
];
export const twentyEighthBattleIntroPages: StoryPage[] = [
{
id: 'twenty-eighth-fu-pass-shadow',
bgm: 'story-dark',
chapter: '부수관의 그림자',
background: 'story-three-heroes',
speaker: '방통',
text: '익주 원군로는 열렸으나 부수관은 아직 닫혀 있습니다. 고패가 관문 병력을 모아 길을 끊으면, 우리 명분은 산문 앞에서 멈출 것입니다.'
},
{
id: 'twenty-eighth-fa-zheng-message',
bgm: 'battle-prep',
chapter: '익주 내부의 손',
background: 'story-liu-bei',
speaker: '제갈량',
text: '익주 안쪽에서 법정이라는 인물이 은밀히 소식을 보냈습니다. 그는 유장의 답답한 정치를 걱정하며, 부수관을 넘을 길목을 알려 주겠다고 합니다.'
},
{
id: 'twenty-eighth-roster-pressure',
bgm: 'battle-prep',
chapter: '와룡과 봉추의 첫 편성',
background: 'story-militia',
speaker: '마량',
text: '이번 전투부터 방통도 출전 후보가 됩니다. 책사 둘을 모두 데려가면 관문 계책은 강해지지만, 전열과 보급 중 하나가 얇아질 수 있습니다.'
},
{
id: 'twenty-eighth-fu-pass-sortie',
bgm: 'battle-prep',
chapter: '부수관 진입전',
background: 'story-sortie',
speaker: '유비',
portrait: 'liuBei',
text: '관문을 부수는 일보다 중요한 것은, 그 너머의 백성이 우리를 어떻게 기억하느냐요. 방통의 기책과 제갈량의 큰 판을 살려 부수관의 길을 열겠소.'
}
];
export const twentyEighthBattleVictoryPages: StoryPage[] = [
{
id: 'twenty-eighth-victory-pass-open',
bgm: 'militia-theme',
chapter: '부수관이 열리다',
background: 'story-sortie',
text: '고패의 관문 병력이 물러나고 부수관의 첫 문이 열렸습니다. 유비군은 관문 창고를 봉인하고 마을의 곡식을 지켜, 익주 내부의 의심을 조금 누그러뜨렸습니다.'
},
{
id: 'twenty-eighth-fa-zheng-joins',
bgm: 'battle-prep',
chapter: '법정의 합류',
background: 'story-liu-bei',
speaker: '법정',
text: '익주는 험한 땅이지만, 더 험한 것은 닫힌 마음입니다. 주공께서 그 마음을 함부로 베지 않으신다면, 이 법정이 안쪽 길을 밝히겠습니다.'
},
{
id: 'twenty-eighth-next-luo-castle',
bgm: 'story-dark',
chapter: '낙성으로 이어지는 길',
background: 'story-three-heroes',
speaker: '방통',
text: '부수관은 문에 불과합니다. 낙성으로 이어지는 길에는 더 깊은 매복과 더 복잡한 마음이 기다립니다. 이제 법정의 내부 정보까지 함께 써야 합니다.'
}
];
export const firstBattleMap: BattleMap = {
width: 20,
height: 18,
@@ -2073,6 +2135,12 @@ export const twentySeventhBattleMap: BattleMap = {
terrain: createTwentySeventhBattleTerrain()
};
export const twentyEighthBattleMap: BattleMap = {
width: 56,
height: 38,
terrain: createTwentyEighthBattleTerrain()
};
export const firstBattleUnits: UnitData[] = [
{
id: 'liu-bei',
@@ -4170,6 +4238,30 @@ export const yizhouRecruitUnits: UnitData[] = [
}
];
export const fuPassRecruitUnits: UnitData[] = [
{
id: 'fa-zheng',
name: '법정',
faction: 'ally',
className: '익주 모사',
classKey: 'strategist',
level: 17,
exp: 0,
hp: 38,
maxHp: 38,
attack: 9,
move: 4,
stats: { might: 42, intelligence: 94, leadership: 84, agility: 70, luck: 80 },
equipment: {
weapon: { itemId: 'white-feather-fan', level: 2, exp: 18 },
armor: { itemId: 'cloth-armor', level: 2, exp: 16 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 8,
y: 25
}
];
const eighthBattleAllyPositions: Record<string, { x: number; y: number }> = {
'liu-bei': { x: 2, y: 17 },
'guan-yu': { x: 3, y: 17 },
@@ -11105,6 +11197,458 @@ export const twentySeventhBattleUnits: UnitData[] = [
}
];
const twentyEighthBattleAllyPositions: Record<string, { x: number; y: number }> = {
'liu-bei': { x: 4, y: 32 },
'guan-yu': { x: 6, y: 31 },
'zhang-fei': { x: 5, y: 34 },
'jian-yong': { x: 3, y: 35 },
'mi-zhu': { x: 4, y: 36 },
'sun-qian': { x: 7, y: 35 },
'zhao-yun': { x: 8, y: 32 },
'zhuge-liang': { x: 5, y: 32 },
'ma-liang': { x: 8, y: 36 },
'yi-ji': { x: 9, y: 34 },
'gong-zhi': { x: 10, y: 36 },
'huang-zhong': { x: 7, y: 33 },
'wei-yan': { x: 10, y: 31 },
'pang-tong': { x: 9, y: 33 }
};
export const twentyEighthBattleUnits: UnitData[] = [
...[
...firstBattleUnits.filter((unit) => unit.faction === 'ally'),
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits,
...jingzhouRecruitUnits,
...guiyangRecruitUnits,
...wulingRecruitUnits,
...changshaRecruitUnits,
...yizhouRecruitUnits
].map((unit) => placeScenarioUnit(unit, twentyEighthBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
{
id: 'fupass-scout-a',
name: '부수관 척후',
faction: 'enemy',
className: '관문 척후',
classKey: 'bandit',
level: 44,
exp: 68,
hp: 112,
maxHp: 112,
attack: 43,
move: 4,
stats: { might: 134, intelligence: 96, leadership: 110, agility: 126, luck: 86 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 6 },
armor: { itemId: 'rebel-vest', level: 4, exp: 40 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 16,
y: 32
},
{
id: 'fupass-scout-b',
name: '부수관 척후',
faction: 'enemy',
className: '서문 척후',
classKey: 'bandit',
level: 44,
exp: 68,
hp: 112,
maxHp: 112,
attack: 43,
move: 4,
stats: { might: 134, intelligence: 96, leadership: 110, agility: 126, luck: 86 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 6 },
armor: { itemId: 'rebel-vest', level: 4, exp: 40 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 21,
y: 30
},
{
id: 'fupass-infantry-a',
name: '부수관 보병',
faction: 'enemy',
className: '산문 보병',
classKey: 'yellowTurban',
level: 45,
exp: 70,
hp: 154,
maxHp: 154,
attack: 48,
move: 3,
stats: { might: 150, intelligence: 96, leadership: 128, agility: 104, luck: 86 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 18 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 8 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 25,
y: 29
},
{
id: 'fupass-infantry-b',
name: '부수관 보병',
faction: 'enemy',
className: '협곡 보병',
classKey: 'yellowTurban',
level: 45,
exp: 70,
hp: 154,
maxHp: 154,
attack: 48,
move: 3,
stats: { might: 150, intelligence: 96, leadership: 128, agility: 104, luck: 86 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 18 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 8 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 30,
y: 26
},
{
id: 'fupass-infantry-c',
name: '부수관 보병',
faction: 'enemy',
className: '관문 보병',
classKey: 'yellowTurban',
level: 46,
exp: 72,
hp: 162,
maxHp: 162,
attack: 50,
move: 3,
stats: { might: 154, intelligence: 98, leadership: 132, agility: 106, luck: 86 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 26 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 14 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 38,
y: 23
},
{
id: 'fupass-infantry-d',
name: '부수관 보병',
faction: 'enemy',
className: '성문 보병',
classKey: 'yellowTurban',
level: 46,
exp: 72,
hp: 162,
maxHp: 162,
attack: 50,
move: 3,
stats: { might: 154, intelligence: 98, leadership: 132, agility: 106, luck: 86 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 26 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 14 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 44,
y: 19
},
{
id: 'fupass-archer-a',
name: '부수관 궁병',
faction: 'enemy',
className: '산루 궁병',
classKey: 'archer',
level: 45,
exp: 70,
hp: 112,
maxHp: 112,
attack: 45,
move: 3,
stats: { might: 108, intelligence: 108, leadership: 114, agility: 122, luck: 88 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 14 },
armor: { itemId: 'cloth-armor', level: 5, exp: 4 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 30,
y: 22
},
{
id: 'fupass-archer-b',
name: '부수관 궁병',
faction: 'enemy',
className: '관문 궁병',
classKey: 'archer',
level: 46,
exp: 72,
hp: 116,
maxHp: 116,
attack: 46,
move: 3,
stats: { might: 110, intelligence: 110, leadership: 116, agility: 124, luck: 88 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 22 },
armor: { itemId: 'cloth-armor', level: 5, exp: 10 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 42,
y: 16
},
{
id: 'fupass-archer-c',
name: '부수관 궁병',
faction: 'enemy',
className: '성루 궁병',
classKey: 'archer',
level: 46,
exp: 72,
hp: 116,
maxHp: 116,
attack: 46,
move: 3,
stats: { might: 110, intelligence: 110, leadership: 116, agility: 124, luck: 88 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 22 },
armor: { itemId: 'cloth-armor', level: 5, exp: 10 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 50,
y: 20
},
{
id: 'fupass-cavalry-a',
name: '부수관 기병',
faction: 'enemy',
className: '고개 기병',
classKey: 'cavalry',
level: 46,
exp: 72,
hp: 162,
maxHp: 162,
attack: 51,
move: 5,
stats: { might: 154, intelligence: 98, leadership: 130, agility: 126, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 28 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 16 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 23,
y: 34
},
{
id: 'fupass-cavalry-b',
name: '부수관 기병',
faction: 'enemy',
className: '관문 기병',
classKey: 'cavalry',
level: 46,
exp: 72,
hp: 162,
maxHp: 162,
attack: 51,
move: 5,
stats: { might: 154, intelligence: 98, leadership: 130, agility: 126, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 28 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 16 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 40,
y: 29
},
{
id: 'fupass-cavalry-c',
name: '부수관 기병',
faction: 'enemy',
className: '성문 기병',
classKey: 'cavalry',
level: 47,
exp: 74,
hp: 170,
maxHp: 170,
attack: 53,
move: 5,
stats: { might: 158, intelligence: 100, leadership: 134, agility: 128, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 36 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 24 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 49,
y: 27
},
{
id: 'fupass-guard-a',
name: '고패 친위대',
faction: 'enemy',
className: '관문 친위대',
classKey: 'yellowTurban',
level: 47,
exp: 74,
hp: 174,
maxHp: 174,
attack: 53,
move: 3,
stats: { might: 160, intelligence: 100, leadership: 138, agility: 108, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 40 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 26 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 47,
y: 17
},
{
id: 'fupass-guard-b',
name: '고패 친위대',
faction: 'enemy',
className: '성문 친위대',
classKey: 'yellowTurban',
level: 47,
exp: 74,
hp: 174,
maxHp: 174,
attack: 53,
move: 3,
stats: { might: 160, intelligence: 100, leadership: 138, agility: 108, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 40 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 26 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 51,
y: 19
},
{
id: 'fupass-strategist-a',
name: '부수관 책사',
faction: 'enemy',
className: '관문 책사',
classKey: 'archer',
level: 46,
exp: 72,
hp: 116,
maxHp: 116,
attack: 46,
move: 3,
stats: { might: 94, intelligence: 124, leadership: 116, agility: 100, luck: 88 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 24 },
armor: { itemId: 'cloth-armor', level: 5, exp: 12 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 43,
y: 14
},
{
id: 'fupass-strategist-b',
name: '부수관 책사',
faction: 'enemy',
className: '성문 책사',
classKey: 'archer',
level: 46,
exp: 72,
hp: 116,
maxHp: 116,
attack: 46,
move: 3,
stats: { might: 94, intelligence: 124, leadership: 116, agility: 100, luck: 88 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 24 },
armor: { itemId: 'cloth-armor', level: 5, exp: 12 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 51,
y: 23
},
{
id: 'fupass-ambusher-a',
name: '산길 복병',
faction: 'enemy',
className: '서쪽 복병',
classKey: 'bandit',
level: 45,
exp: 70,
hp: 120,
maxHp: 120,
attack: 45,
move: 4,
stats: { might: 140, intelligence: 98, leadership: 112, agility: 128, luck: 86 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 18 },
armor: { itemId: 'rebel-vest', level: 5, exp: 4 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 31,
y: 34
},
{
id: 'fupass-ambusher-b',
name: '산길 복병',
faction: 'enemy',
className: '북쪽 복병',
classKey: 'bandit',
level: 45,
exp: 70,
hp: 120,
maxHp: 120,
attack: 45,
move: 4,
stats: { might: 140, intelligence: 98, leadership: 112, agility: 128, luck: 86 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 18 },
armor: { itemId: 'rebel-vest', level: 5, exp: 4 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 35,
y: 8
},
{
id: 'fupass-ambusher-c',
name: '산길 복병',
faction: 'enemy',
className: '남쪽 복병',
classKey: 'bandit',
level: 45,
exp: 70,
hp: 120,
maxHp: 120,
attack: 45,
move: 4,
stats: { might: 140, intelligence: 98, leadership: 112, agility: 128, luck: 86 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 18 },
armor: { itemId: 'rebel-vest', level: 5, exp: 4 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 45,
y: 31
},
{
id: 'fupass-leader-gao-pei',
name: '고패',
faction: 'enemy',
className: '부수관 수장',
classKey: 'rebelLeader',
level: 48,
exp: 78,
hp: 222,
maxHp: 222,
attack: 55,
move: 4,
stats: { might: 162, intelligence: 116, leadership: 144, agility: 110, luck: 90 },
equipment: {
weapon: { itemId: 'leader-axe', level: 5, exp: 34 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 30 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 52,
y: 18
}
];
export const firstBattleBonds: BattleBond[] = [
{
id: 'liu-bei__guan-yu',
@@ -11375,6 +11919,33 @@ export const yizhouRecruitBonds: BattleBond[] = [
}
];
export const fuPassRecruitBonds: BattleBond[] = [
{
id: 'liu-bei__fa-zheng',
unitIds: ['liu-bei', 'fa-zheng'],
title: '익주 내부의 길',
level: 34,
exp: 0,
description: '유비의 명분과 법정의 내부 정보가 만나, 익주의 닫힌 마음과 관문을 함께 열어 갑니다.'
},
{
id: 'pang-tong__fa-zheng',
unitIds: ['pang-tong', 'fa-zheng'],
title: '봉추와 내부책',
level: 32,
exp: 0,
description: '방통의 과감한 기책과 법정의 익주 사정이 맞물려, 적이 숨긴 길목을 먼저 흔듭니다.'
},
{
id: 'zhuge-liang__fa-zheng',
unitIds: ['zhuge-liang', 'fa-zheng'],
title: '큰 판과 속내',
level: 30,
exp: 0,
description: '제갈량의 큰 전략과 법정의 내부 정세 판단이 더해져, 익주 공략의 무리한 피를 줄입니다.'
}
];
export const secondBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBondForScenario);
export const thirdBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBondForScenario);
export const fourthBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBondForScenario);
@@ -11407,6 +11978,7 @@ export const twentyFourthBattleBonds: BattleBond[] = [...twentyThirdBattleBonds,
export const twentyFifthBattleBonds: BattleBond[] = [...twentyFourthBattleBonds, ...guiyangRecruitBonds].map(cloneBattleBondForScenario);
export const twentySixthBattleBonds: BattleBond[] = [...twentyFifthBattleBonds, ...wulingRecruitBonds].map(cloneBattleBondForScenario);
export const twentySeventhBattleBonds: BattleBond[] = [...twentySixthBattleBonds, ...changshaRecruitBonds].map(cloneBattleBondForScenario);
export const twentyEighthBattleBonds: BattleBond[] = [...twentySeventhBattleBonds, ...yizhouRecruitBonds].map(cloneBattleBondForScenario);
function createEighthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 22 }, (_, y) =>
@@ -12428,6 +13000,62 @@ function createTwentySeventhBattleTerrain(): TerrainType[][] {
);
}
function createTwentyEighthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 38 }, (_, y) =>
Array.from({ length: 56 }, (_, x): TerrainType => {
if (x <= 4 && y >= 31) {
return 'camp';
}
if ((x >= 46 && x <= 54 && y >= 13 && y <= 22) || (x >= 42 && x <= 48 && y >= 10 && y <= 15)) {
return 'fort';
}
if ((x >= 17 && x <= 20 && y >= 28 && y <= 30) || (x >= 32 && x <= 34 && y >= 24 && y <= 26) || (x >= 39 && x <= 41 && y >= 18 && y <= 20)) {
return 'village';
}
if (
(y >= 33 && x >= 4 && x <= 15) ||
(x >= 14 && x <= 25 && y >= 29 && y <= 33) ||
(x >= 24 && x <= 34 && y >= 25 && y <= 29) ||
(x >= 33 && x <= 42 && y >= 20 && y <= 25) ||
(x >= 41 && x <= 50 && y >= 16 && y <= 20) ||
(x >= 49 && x <= 53 && y >= 17 && y <= 19)
) {
return 'road';
}
if ((x === 12 || x === 13) && y >= 0 && y <= 27) {
return 'river';
}
if ((x === 30 || x === 31) && y >= 2 && y <= 23) {
return 'river';
}
if ((x === 38 || x === 39) && y >= 28 && y <= 37) {
return 'river';
}
if (
(x >= 4 && x <= 17 && y >= 8 && y <= 22) ||
(x >= 18 && x <= 29 && y >= 11 && y <= 23) ||
(x >= 31 && x <= 44 && y >= 28 && y <= 37) ||
(x >= 43 && x <= 55 && y >= 24 && y <= 36)
) {
return 'forest';
}
if (
(x >= 0 && x <= 10 && y <= 12) ||
(x >= 19 && x <= 29 && y <= 10) ||
(x >= 31 && x <= 45 && y >= 3 && y <= 13) ||
(x >= 48 && x <= 55 && y <= 12) ||
(x >= 23 && x <= 33 && y >= 31 && y <= 37)
) {
return 'hill';
}
if ((x <= 2 && y <= 30) || (x >= 54 && y >= 22) || (x >= 44 && x <= 46 && y <= 9)) {
return 'cliff';
}
return 'plain';
})
);
}
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
return {
...cloneUnitForScenario(unit),