Add Luo Castle outer wall chapter

This commit is contained in:
2026-06-23 09:43:18 +09:00
parent 8349d1044f
commit cc6365d5ba
11 changed files with 1270 additions and 34 deletions

View File

@@ -35,6 +35,10 @@ import {
twentyEighthBattleMap,
twentyEighthBattleUnits,
twentyEighthBattleVictoryPages,
twentyNinthBattleBonds,
twentyNinthBattleMap,
twentyNinthBattleUnits,
twentyNinthBattleVictoryPages,
tenthBattleBonds,
tenthBattleMap,
tenthBattleUnits,
@@ -145,7 +149,8 @@ export type BattleScenarioId =
| 'twenty-fifth-battle-wuling-mountain-road'
| 'twenty-sixth-battle-changsha-veteran'
| 'twenty-seventh-battle-yizhou-relief-road'
| 'twenty-eighth-battle-fu-pass-entry';
| 'twenty-eighth-battle-fu-pass-entry'
| 'twenty-ninth-battle-luo-outer-wall';
export type BattleObjectiveKind = 'defeat-leader' | 'keep-unit-alive' | 'secure-terrain' | 'quick-victory';
@@ -1769,6 +1774,69 @@ export const twentyEighthBattleScenario: BattleScenarioDefinition = {
nextCampScene: 'CampScene'
};
export const twentyNinthBattleScenario: BattleScenarioDefinition = {
id: 'twenty-ninth-battle-luo-outer-wall',
title: '낙성 외곽전',
victoryConditionLabel: '장임 퇴각',
defeatConditionLabel: '유비 또는 제갈량 퇴각',
openingObjectiveLines: [
'부수관을 넘어선 유비군은 낙성 외곽 방어선에 도착했습니다. 장임은 성 밖 마을과 고개를 이용해 시간을 벌고 있습니다.',
'이번 전투부터 법정도 출전 후보입니다. 익주 내부 사정을 아는 법정을 데려가면 오의와 성문 장수들을 설득할 실마리가 커집니다.',
'유비와 제갈량을 지키며 장임을 물러나게 하십시오. 마을을 안정시키면 오의가 낙성으로 향하는 길을 열 수 있습니다.'
],
map: twentyNinthBattleMap,
units: twentyNinthBattleUnits,
bonds: twentyNinthBattleBonds,
mapTextureKey: 'battle-map-twenty-ninth',
leaderUnitId: 'luo-leader-zhang-ren',
quickVictoryTurnLimit: 38,
baseVictoryGold: 4200,
objectives: [
{
id: 'leader',
kind: 'defeat-leader',
label: '장임 퇴각',
rewardGold: 2640,
unitId: 'luo-leader-zhang-ren'
},
{
id: 'liu-bei',
kind: 'keep-unit-alive',
label: '유비 생존',
rewardGold: 780,
unitId: 'liu-bei'
},
{
id: 'zhuge-liang',
kind: 'keep-unit-alive',
label: '제갈량 생존',
rewardGold: 1080,
unitId: 'zhuge-liang'
},
{
id: 'luo-village',
kind: 'secure-terrain',
label: '낙성 외곽 마을 안정',
rewardGold: 1280,
terrain: 'village'
},
{
id: 'quick',
kind: 'quick-victory',
label: '38턴 이내 승리',
rewardGold: 1000,
maxTurn: 38
}
],
defeatConditions: [
{ kind: 'unit-defeated', unitId: 'liu-bei' },
{ kind: 'unit-defeated', unitId: 'zhuge-liang' }
],
itemRewards: ['콩 14', '상처약 10', '탁주 6', '낙성 외곽 지도 +1', '오의 합류'],
victoryPages: twentyNinthBattleVictoryPages,
nextCampScene: 'CampScene'
};
export const defaultBattleScenarioId: BattleScenarioId = firstBattleScenario.id;
export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition> = {
@@ -1799,7 +1867,8 @@ export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition>
'twenty-fifth-battle-wuling-mountain-road': twentyFifthBattleScenario,
'twenty-sixth-battle-changsha-veteran': twentySixthBattleScenario,
'twenty-seventh-battle-yizhou-relief-road': twentySeventhBattleScenario,
'twenty-eighth-battle-fu-pass-entry': twentyEighthBattleScenario
'twenty-eighth-battle-fu-pass-entry': twentyEighthBattleScenario,
'twenty-ninth-battle-luo-outer-wall': twentyNinthBattleScenario
};
export const defaultBattleScenario = battleScenarios[defaultBattleScenarioId];

View File

@@ -18,6 +18,7 @@ import {
tenthBattleScenario,
thirteenthBattleScenario,
twentyEighthBattleScenario,
twentyNinthBattleScenario,
twentyFirstBattleScenario,
twentySecondBattleScenario,
twentyThirdBattleScenario,
@@ -66,6 +67,8 @@ import {
thirteenthBattleVictoryPages,
twentyEighthBattleIntroPages,
twentyEighthBattleVictoryPages,
twentyNinthBattleIntroPages,
twentyNinthBattleVictoryPages,
twentyFirstBattleIntroPages,
twentyFirstBattleVictoryPages,
twentySecondBattleIntroPages,
@@ -389,13 +392,24 @@ const sortieFlows: Record<string, SortieFlow> = {
},
[twentyEighthBattleScenario.id]: {
afterBattleId: twentyEighthBattleScenario.id,
eyebrow: '다음 장 준비',
title: '낙성 진입 준비',
eyebrow: '다음 장',
title: twentyNinthBattleScenario.title,
description:
'부수관이 열리고 법정이 합류했습니다. 이제 유비군은 익주 안쪽의 마음과 길을 동시에 읽으며 낙성으로 이어지는 더 어려운 전장을 준비해야 합니다.',
rewardHint: '다음 장: 낙성 진입 준비 중',
pages: twentyEighthBattleVictoryPages,
unavailableNotice: '낙성 이후 익주 심부 장은 다음 작업에서 이어집니다. 군영에서 법정과 방통의 공명도를 올리고 다음 관문을 준비하십시오.'
'부수관이 열리고 법정이 합류했습니다. 이제 낙성 외곽으로 들어가 장임의 방어선과 오의의 흔들리는 마음을 동시에 상대해야 합니다.',
rewardHint: `예상 보상: ${twentyNinthBattleScenario.title} 개방 / 오의 합류`,
nextBattleId: twentyNinthBattleScenario.id,
campaignStep: 'twenty-ninth-battle',
pages: [...twentyEighthBattleVictoryPages, ...twentyNinthBattleIntroPages]
},
[twentyNinthBattleScenario.id]: {
afterBattleId: twentyNinthBattleScenario.id,
eyebrow: '다음 장 준비',
title: '낙봉파 진입 준비',
description:
'낙성 외곽을 넘고 오의가 합류했습니다. 장임은 더 안쪽으로 물러났고, 방통은 낙봉파라는 좁은 길의 불길한 그림자를 살피고 있습니다.',
rewardHint: '다음 장: 낙봉파 진입 준비 중',
pages: twentyNinthBattleVictoryPages,
unavailableNotice: '낙봉파와 낙성 본성 공략은 다음 작업에서 이어집니다. 군영에서 새로 합류한 오의를 포함해 출전 조합과 공명 이벤트를 준비하십시오.'
}
};

View File

@@ -1828,6 +1828,68 @@ export const twentyEighthBattleVictoryPages: StoryPage[] = [
}
];
export const twentyNinthBattleIntroPages: StoryPage[] = [
{
id: 'twenty-ninth-luo-outer-wall',
bgm: 'story-dark',
chapter: '낙성의 바깥 성벽',
background: 'story-three-heroes',
speaker: '법정',
text: '부수관을 넘으면 낙성의 바깥 성벽이 기다립니다. 장임은 성 밖의 고개와 마을을 겹쳐 방어선을 세웠고, 성 안의 장수들은 아직 우리 뜻을 믿지 않습니다.'
},
{
id: 'twenty-ninth-wu-yi-rumor',
bgm: 'battle-prep',
chapter: '흔들리는 오의',
background: 'story-liu-bei',
speaker: '방통',
text: '오의는 성문을 지키지만 백성을 함부로 몰아붙이는 명령을 달가워하지 않는다고 합니다. 전장을 거칠게 밀지 않고 길을 열면, 그의 마음도 움직일 수 있습니다.'
},
{
id: 'twenty-ninth-roster-pressure',
bgm: 'battle-prep',
chapter: '법정의 첫 출전 선택',
background: 'story-militia',
speaker: '제갈량',
text: '이번 전투부터 법정도 출전 후보입니다. 익주 내부 사정을 아는 법정을 데려가면 설득은 쉬워지지만, 무장을 줄이는 부담은 더 커집니다.'
},
{
id: 'twenty-ninth-luo-sortie',
bgm: 'battle-prep',
chapter: '낙성 외곽전',
background: 'story-sortie',
speaker: '유비',
portrait: 'liuBei',
text: '낙성의 문을 여는 일은 칼보다 마음이 먼저요. 마을을 지키고 장임의 전열을 물리쳐, 성 안 사람들에게 우리가 어떤 군인지 보이겠소.'
}
];
export const twentyNinthBattleVictoryPages: StoryPage[] = [
{
id: 'twenty-ninth-victory-outer-wall',
bgm: 'militia-theme',
chapter: '외곽 방어선 붕괴',
background: 'story-sortie',
text: '장임은 낙성 안쪽으로 물러났고, 외곽 마을은 큰 피해 없이 유비군의 보호 아래 들어왔습니다. 성 안의 장수들은 유비군을 단순한 침입군으로만 볼 수 없게 되었습니다.'
},
{
id: 'twenty-ninth-wu-yi-joins',
bgm: 'battle-prep',
chapter: '오의의 합류',
background: 'story-liu-bei',
speaker: '오의',
text: '성문을 지킨다는 명분으로 백성을 몰아넣는 일은 장수의 길이 아니었습니다. 주공께서 마을을 먼저 살피셨으니, 이 오의도 낙성의 다음 길을 열겠습니다.'
},
{
id: 'twenty-ninth-next-luofeng',
bgm: 'story-dark',
chapter: '낙봉파의 그늘',
background: 'story-three-heroes',
speaker: '방통',
text: '낙성 바깥은 열렸지만 길은 더 좁아집니다. 봉황이 떨어진다는 이름의 고개가 있다 하니, 다음 진군은 가볍게 볼 수 없습니다.'
}
];
export const firstBattleMap: BattleMap = {
width: 20,
height: 18,
@@ -2141,6 +2203,12 @@ export const twentyEighthBattleMap: BattleMap = {
terrain: createTwentyEighthBattleTerrain()
};
export const twentyNinthBattleMap: BattleMap = {
width: 58,
height: 40,
terrain: createTwentyNinthBattleTerrain()
};
export const firstBattleUnits: UnitData[] = [
{
id: 'liu-bei',
@@ -4262,6 +4330,30 @@ export const fuPassRecruitUnits: UnitData[] = [
}
];
export const luoCastleRecruitUnits: UnitData[] = [
{
id: 'wu-yi',
name: '오의',
faction: 'ally',
className: '익주 장군',
classKey: 'infantry',
level: 18,
exp: 0,
hp: 46,
maxHp: 46,
attack: 15,
move: 4,
stats: { might: 82, intelligence: 72, leadership: 86, agility: 74, luck: 78 },
equipment: {
weapon: { itemId: 'iron-spear', level: 3, exp: 16 },
armor: { itemId: 'reinforced-lamellar', level: 2, exp: 18 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 9,
y: 26
}
];
const eighthBattleAllyPositions: Record<string, { x: number; y: number }> = {
'liu-bei': { x: 2, y: 17 },
'guan-yu': { x: 3, y: 17 },
@@ -11649,6 +11741,460 @@ export const twentyEighthBattleUnits: UnitData[] = [
}
];
const twentyNinthBattleAllyPositions: Record<string, { x: number; y: number }> = {
'liu-bei': { x: 4, y: 34 },
'guan-yu': { x: 6, y: 33 },
'zhang-fei': { x: 5, y: 36 },
'jian-yong': { x: 3, y: 37 },
'mi-zhu': { x: 4, y: 38 },
'sun-qian': { x: 7, y: 37 },
'zhao-yun': { x: 8, y: 34 },
'zhuge-liang': { x: 5, y: 34 },
'ma-liang': { x: 8, y: 38 },
'yi-ji': { x: 9, y: 36 },
'gong-zhi': { x: 10, y: 38 },
'huang-zhong': { x: 7, y: 35 },
'wei-yan': { x: 10, y: 33 },
'pang-tong': { x: 9, y: 35 },
'fa-zheng': { x: 11, y: 36 }
};
export const twentyNinthBattleUnits: UnitData[] = [
...[
...firstBattleUnits.filter((unit) => unit.faction === 'ally'),
...xuzhouRecruitUnits,
...caoBreakRecruitUnits,
...liuBiaoRecruitUnits,
...zhugeRecruitUnits,
...jingzhouRecruitUnits,
...guiyangRecruitUnits,
...wulingRecruitUnits,
...changshaRecruitUnits,
...yizhouRecruitUnits,
...fuPassRecruitUnits
].map((unit) => placeScenarioUnit(unit, twentyNinthBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
{
id: 'luo-scout-a',
name: '낙성 척후',
faction: 'enemy',
className: '외곽 척후',
classKey: 'bandit',
level: 47,
exp: 74,
hp: 122,
maxHp: 122,
attack: 46,
move: 4,
stats: { might: 142, intelligence: 100, leadership: 116, agility: 130, luck: 88 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 24 },
armor: { itemId: 'rebel-vest', level: 5, exp: 10 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 16,
y: 34
},
{
id: 'luo-scout-b',
name: '낙성 척후',
faction: 'enemy',
className: '동문 척후',
classKey: 'bandit',
level: 47,
exp: 74,
hp: 122,
maxHp: 122,
attack: 46,
move: 4,
stats: { might: 142, intelligence: 100, leadership: 116, agility: 130, luck: 88 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 24 },
armor: { itemId: 'rebel-vest', level: 5, exp: 10 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 22,
y: 32
},
{
id: 'luo-infantry-a',
name: '낙성 보병',
faction: 'enemy',
className: '외곽 보병',
classKey: 'yellowTurban',
level: 48,
exp: 76,
hp: 168,
maxHp: 168,
attack: 52,
move: 3,
stats: { might: 158, intelligence: 100, leadership: 136, agility: 108, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 36 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 22 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 27,
y: 31
},
{
id: 'luo-infantry-b',
name: '낙성 보병',
faction: 'enemy',
className: '성벽 보병',
classKey: 'yellowTurban',
level: 48,
exp: 76,
hp: 168,
maxHp: 168,
attack: 52,
move: 3,
stats: { might: 158, intelligence: 100, leadership: 136, agility: 108, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 36 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 22 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 34,
y: 27
},
{
id: 'luo-infantry-c',
name: '낙성 보병',
faction: 'enemy',
className: '서문 보병',
classKey: 'yellowTurban',
level: 49,
exp: 78,
hp: 176,
maxHp: 176,
attack: 54,
move: 3,
stats: { might: 162, intelligence: 102, leadership: 140, agility: 110, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 44 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 30 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 42,
y: 22
},
{
id: 'luo-infantry-d',
name: '낙성 보병',
faction: 'enemy',
className: '성문 보병',
classKey: 'yellowTurban',
level: 49,
exp: 78,
hp: 176,
maxHp: 176,
attack: 54,
move: 3,
stats: { might: 162, intelligence: 102, leadership: 140, agility: 110, luck: 88 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 44 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 30 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 50,
y: 18
},
{
id: 'luo-archer-a',
name: '낙성 궁병',
faction: 'enemy',
className: '산루 궁병',
classKey: 'archer',
level: 48,
exp: 76,
hp: 120,
maxHp: 120,
attack: 48,
move: 3,
stats: { might: 112, intelligence: 112, leadership: 118, agility: 126, luck: 90 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 30 },
armor: { itemId: 'cloth-armor', level: 5, exp: 18 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 31,
y: 24
},
{
id: 'luo-archer-b',
name: '낙성 궁병',
faction: 'enemy',
className: '성벽 궁병',
classKey: 'archer',
level: 49,
exp: 78,
hp: 124,
maxHp: 124,
attack: 49,
move: 3,
stats: { might: 114, intelligence: 114, leadership: 120, agility: 128, luck: 90 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 38 },
armor: { itemId: 'cloth-armor', level: 5, exp: 24 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 45,
y: 16
},
{
id: 'luo-archer-c',
name: '낙성 궁병',
faction: 'enemy',
className: '성루 궁병',
classKey: 'archer',
level: 49,
exp: 78,
hp: 124,
maxHp: 124,
attack: 49,
move: 3,
stats: { might: 114, intelligence: 114, leadership: 120, agility: 128, luck: 90 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 38 },
armor: { itemId: 'cloth-armor', level: 5, exp: 24 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 53,
y: 21
},
{
id: 'luo-cavalry-a',
name: '낙성 기병',
faction: 'enemy',
className: '외곽 기병',
classKey: 'cavalry',
level: 49,
exp: 78,
hp: 178,
maxHp: 178,
attack: 55,
move: 5,
stats: { might: 162, intelligence: 102, leadership: 138, agility: 130, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 46 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 32 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 25,
y: 36
},
{
id: 'luo-cavalry-b',
name: '낙성 기병',
faction: 'enemy',
className: '성문 기병',
classKey: 'cavalry',
level: 49,
exp: 78,
hp: 178,
maxHp: 178,
attack: 55,
move: 5,
stats: { might: 162, intelligence: 102, leadership: 138, agility: 130, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 46 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 32 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 44,
y: 31
},
{
id: 'luo-cavalry-c',
name: '낙성 기병',
faction: 'enemy',
className: '동문 기병',
classKey: 'cavalry',
level: 50,
exp: 80,
hp: 186,
maxHp: 186,
attack: 57,
move: 5,
stats: { might: 166, intelligence: 104, leadership: 142, agility: 132, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 54 },
armor: { itemId: 'lamellar-armor', level: 5, exp: 40 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 52,
y: 29
},
{
id: 'luo-guard-a',
name: '장임 친위대',
faction: 'enemy',
className: '낙성 친위대',
classKey: 'yellowTurban',
level: 50,
exp: 80,
hp: 188,
maxHp: 188,
attack: 57,
move: 3,
stats: { might: 168, intelligence: 104, leadership: 146, agility: 112, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 58 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 42 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 50,
y: 16
},
{
id: 'luo-guard-b',
name: '장임 친위대',
faction: 'enemy',
className: '성문 친위대',
classKey: 'yellowTurban',
level: 50,
exp: 80,
hp: 188,
maxHp: 188,
attack: 57,
move: 3,
stats: { might: 168, intelligence: 104, leadership: 146, agility: 112, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 58 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 42 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 54,
y: 19
},
{
id: 'luo-strategist-a',
name: '낙성 책사',
faction: 'enemy',
className: '성벽 책사',
classKey: 'archer',
level: 49,
exp: 78,
hp: 124,
maxHp: 124,
attack: 49,
move: 3,
stats: { might: 96, intelligence: 128, leadership: 120, agility: 102, luck: 90 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 40 },
armor: { itemId: 'cloth-armor', level: 5, exp: 26 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 46,
y: 14
},
{
id: 'luo-strategist-b',
name: '낙성 책사',
faction: 'enemy',
className: '외곽 책사',
classKey: 'archer',
level: 49,
exp: 78,
hp: 124,
maxHp: 124,
attack: 49,
move: 3,
stats: { might: 96, intelligence: 128, leadership: 120, agility: 102, luck: 90 },
equipment: {
weapon: { itemId: 'short-bow', level: 5, exp: 40 },
armor: { itemId: 'cloth-armor', level: 5, exp: 26 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 53,
y: 24
},
{
id: 'luo-ambusher-a',
name: '낙성 복병',
faction: 'enemy',
className: '서쪽 복병',
classKey: 'bandit',
level: 48,
exp: 76,
hp: 128,
maxHp: 128,
attack: 48,
move: 4,
stats: { might: 146, intelligence: 102, leadership: 118, agility: 132, luck: 88 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 34 },
armor: { itemId: 'rebel-vest', level: 5, exp: 20 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 34,
y: 36
},
{
id: 'luo-ambusher-b',
name: '낙성 복병',
faction: 'enemy',
className: '북쪽 복병',
classKey: 'bandit',
level: 48,
exp: 76,
hp: 128,
maxHp: 128,
attack: 48,
move: 4,
stats: { might: 146, intelligence: 102, leadership: 118, agility: 132, luck: 88 },
equipment: {
weapon: { itemId: 'yellow-turban-saber', level: 5, exp: 34 },
armor: { itemId: 'rebel-vest', level: 5, exp: 20 },
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
},
x: 37,
y: 8
},
{
id: 'luo-officer-wu-yi',
name: '오의',
faction: 'enemy',
className: '익주 장군',
classKey: 'yellowTurban',
level: 50,
exp: 82,
hp: 190,
maxHp: 190,
attack: 56,
move: 4,
stats: { might: 158, intelligence: 108, leadership: 148, agility: 114, luck: 90 },
equipment: {
weapon: { itemId: 'iron-spear', level: 5, exp: 60 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 46 },
accessory: { itemId: 'bravery-token', level: 1, exp: 0 }
},
x: 47,
y: 23
},
{
id: 'luo-leader-zhang-ren',
name: '장임',
faction: 'enemy',
className: '낙성 수장',
classKey: 'rebelLeader',
level: 51,
exp: 84,
hp: 238,
maxHp: 238,
attack: 59,
move: 4,
stats: { might: 170, intelligence: 118, leadership: 152, agility: 116, luck: 92 },
equipment: {
weapon: { itemId: 'leader-axe', level: 5, exp: 48 },
armor: { itemId: 'reinforced-lamellar', level: 5, exp: 48 },
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
},
x: 54,
y: 18
}
];
export const firstBattleBonds: BattleBond[] = [
{
id: 'liu-bei__guan-yu',
@@ -11946,6 +12492,33 @@ export const fuPassRecruitBonds: BattleBond[] = [
}
];
export const luoCastleRecruitBonds: BattleBond[] = [
{
id: 'liu-bei__wu-yi',
unitIds: ['liu-bei', 'wu-yi'],
title: '낙성의 새 길',
level: 34,
exp: 0,
description: '유비의 절제된 진군과 오의의 성문 지식이 만나 낙성으로 들어가는 길을 열어 갑니다.'
},
{
id: 'fa-zheng__wu-yi',
unitIds: ['fa-zheng', 'wu-yi'],
title: '익주 내부 설득',
level: 32,
exp: 0,
description: '법정의 내부 정세 판단과 오의의 현장 인맥이 맞물려 익주 장수들의 마음을 흔듭니다.'
},
{
id: 'pang-tong__wu-yi',
unitIds: ['pang-tong', 'wu-yi'],
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);
@@ -11979,6 +12552,7 @@ export const twentyFifthBattleBonds: BattleBond[] = [...twentyFourthBattleBonds,
export const twentySixthBattleBonds: BattleBond[] = [...twentyFifthBattleBonds, ...wulingRecruitBonds].map(cloneBattleBondForScenario);
export const twentySeventhBattleBonds: BattleBond[] = [...twentySixthBattleBonds, ...changshaRecruitBonds].map(cloneBattleBondForScenario);
export const twentyEighthBattleBonds: BattleBond[] = [...twentySeventhBattleBonds, ...yizhouRecruitBonds].map(cloneBattleBondForScenario);
export const twentyNinthBattleBonds: BattleBond[] = [...twentyEighthBattleBonds, ...fuPassRecruitBonds].map(cloneBattleBondForScenario);
function createEighthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 22 }, (_, y) =>
@@ -13056,6 +13630,66 @@ function createTwentyEighthBattleTerrain(): TerrainType[][] {
);
}
function createTwentyNinthBattleTerrain(): TerrainType[][] {
return Array.from({ length: 40 }, (_, y) =>
Array.from({ length: 58 }, (_, x): TerrainType => {
if (x <= 4 && y >= 33) {
return 'camp';
}
if ((x >= 48 && x <= 56 && y >= 13 && y <= 23) || (x >= 44 && x <= 50 && y >= 10 && y <= 15)) {
return 'fort';
}
if (
(x >= 18 && x <= 21 && y >= 30 && y <= 32) ||
(x >= 34 && x <= 36 && y >= 25 && y <= 27) ||
(x >= 41 && x <= 43 && y >= 19 && y <= 21)
) {
return 'village';
}
if (
(y >= 35 && x >= 4 && x <= 16) ||
(x >= 15 && x <= 27 && y >= 31 && y <= 35) ||
(x >= 26 && x <= 36 && y >= 27 && y <= 31) ||
(x >= 35 && x <= 45 && y >= 22 && y <= 27) ||
(x >= 44 && x <= 53 && y >= 17 && y <= 22) ||
(x >= 52 && x <= 56 && y >= 18 && y <= 20)
) {
return 'road';
}
if ((x === 12 || x === 13) && y >= 0 && y <= 29) {
return 'river';
}
if ((x === 31 || x === 32) && y >= 2 && y <= 25) {
return 'river';
}
if ((x === 40 || x === 41) && y >= 30 && y <= 39) {
return 'river';
}
if (
(x >= 4 && x <= 18 && y >= 8 && y <= 24) ||
(x >= 19 && x <= 30 && y >= 12 && y <= 25) ||
(x >= 33 && x <= 46 && y >= 30 && y <= 39) ||
(x >= 45 && x <= 57 && y >= 25 && y <= 38)
) {
return 'forest';
}
if (
(x >= 0 && x <= 10 && y <= 13) ||
(x >= 20 && x <= 30 && y <= 11) ||
(x >= 32 && x <= 47 && y >= 3 && y <= 14) ||
(x >= 50 && x <= 57 && y <= 12) ||
(x >= 24 && x <= 34 && y >= 33 && y <= 39)
) {
return 'hill';
}
if ((x <= 2 && y <= 32) || (x >= 56 && y >= 23) || (x >= 45 && x <= 47 && y <= 9)) {
return 'cliff';
}
return 'plain';
})
);
}
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
return {
...cloneUnitForScenario(unit),