Add Xuzhou gate night raid battle
This commit is contained in:
@@ -594,6 +594,61 @@ export const eighthBattleVictoryPages: StoryPage[] = [
|
||||
}
|
||||
];
|
||||
|
||||
export const ninthBattleIntroPages: StoryPage[] = [
|
||||
{
|
||||
id: 'ninth-lu-bu-refuge',
|
||||
bgm: 'militia-theme',
|
||||
chapter: '여포의 의탁',
|
||||
background: 'story-liu-bei',
|
||||
speaker: '유비',
|
||||
portrait: 'liuBei',
|
||||
text: '여포가 몸을 의탁하겠다 청했다. 난세에 갈 곳 없는 이를 내치는 것은 쉽지 않으나, 서주 백성의 불안을 모른 척할 수도 없다.'
|
||||
},
|
||||
{
|
||||
id: 'ninth-zhang-fei-suspicion',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '성문 안의 불씨',
|
||||
background: 'story-three-heroes',
|
||||
speaker: '장비',
|
||||
portrait: 'zhangFei',
|
||||
text: '여포 같은 자를 성 안에 들이면 반드시 화근이 됩니다. 도겸의 옛 무장들까지 술렁이니, 성문부터 단단히 지켜야 합니다.'
|
||||
},
|
||||
{
|
||||
id: 'ninth-cao-bao-mutiny',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '조표의 야습',
|
||||
background: 'story-sortie',
|
||||
text: '밤이 깊자 조표가 일부 성문 수비병을 움직였다. 바깥의 여포군 기병은 불빛을 신호로 삼아 성문을 향해 몰려들었다.'
|
||||
},
|
||||
{
|
||||
id: 'ninth-xuzhou-gate',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '서주 성문 방위',
|
||||
background: 'story-militia',
|
||||
speaker: '간옹',
|
||||
text: '현덕, 이 싸움은 이겨도 상처가 남을 걸세. 하지만 성문이 오늘 밤 무너지면 내일의 선택도 사라진다네.'
|
||||
}
|
||||
];
|
||||
|
||||
export const ninthBattleVictoryPages: StoryPage[] = [
|
||||
{
|
||||
id: 'ninth-victory-gate-held',
|
||||
bgm: 'militia-theme',
|
||||
chapter: '지켜낸 밤',
|
||||
background: 'story-militia',
|
||||
text: '조표의 야습은 물러났고 성문은 다시 닫혔다. 그러나 성 안의 의심과 두려움은 이미 선명한 금이 되어 남았다.'
|
||||
},
|
||||
{
|
||||
id: 'ninth-lu-bu-pretext',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '더 깊어진 그림자',
|
||||
background: 'story-liu-bei',
|
||||
speaker: '유비',
|
||||
portrait: 'liuBei',
|
||||
text: '여포는 서주의 혼란을 핑계 삼아 더 깊이 발을 들이려 했다. 오늘 밤 성문은 지켰으나, 서주를 잃을 싸움은 이제 시작되고 있었다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const firstBattleMap: BattleMap = {
|
||||
width: 20,
|
||||
height: 18,
|
||||
@@ -787,6 +842,12 @@ export const eighthBattleMap: BattleMap = {
|
||||
terrain: createEighthBattleTerrain()
|
||||
};
|
||||
|
||||
export const ninthBattleMap: BattleMap = {
|
||||
width: 26,
|
||||
height: 22,
|
||||
terrain: createNinthBattleTerrain()
|
||||
};
|
||||
|
||||
export const firstBattleUnits: UnitData[] = [
|
||||
{
|
||||
id: 'liu-bei',
|
||||
@@ -2916,6 +2977,230 @@ export const eighthBattleUnits: UnitData[] = [
|
||||
}
|
||||
];
|
||||
|
||||
const ninthBattleAllyPositions: Record<string, { x: number; y: number }> = {
|
||||
'liu-bei': { x: 3, y: 17 },
|
||||
'guan-yu': { x: 4, y: 17 },
|
||||
'zhang-fei': { x: 3, y: 18 },
|
||||
'jian-yong': { x: 5, y: 18 },
|
||||
'mi-zhu': { x: 4, y: 19 }
|
||||
};
|
||||
|
||||
export const ninthBattleUnits: UnitData[] = [
|
||||
...[...firstBattleUnits.filter((unit) => unit.faction === 'ally'), ...xuzhouRecruitUnits].map((unit) =>
|
||||
placeScenarioUnit(unit, ninthBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })
|
||||
),
|
||||
{
|
||||
id: 'xuzhou-gate-traitor-a',
|
||||
name: '성문 배반병',
|
||||
faction: 'enemy',
|
||||
className: '서주 배반병',
|
||||
classKey: 'bandit',
|
||||
level: 9,
|
||||
exp: 56,
|
||||
hp: 40,
|
||||
maxHp: 40,
|
||||
attack: 15,
|
||||
move: 4,
|
||||
stats: { might: 80, intelligence: 48, leadership: 58, agility: 74, luck: 52 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 30 },
|
||||
armor: { itemId: 'rebel-vest', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
|
||||
},
|
||||
x: 11,
|
||||
y: 12
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-gate-traitor-b',
|
||||
name: '성문 배반병',
|
||||
faction: 'enemy',
|
||||
className: '서주 배반병',
|
||||
classKey: 'bandit',
|
||||
level: 9,
|
||||
exp: 58,
|
||||
hp: 41,
|
||||
maxHp: 41,
|
||||
attack: 15,
|
||||
move: 4,
|
||||
stats: { might: 81, intelligence: 49, leadership: 59, agility: 74, luck: 52 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 32 },
|
||||
armor: { itemId: 'rebel-vest', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
|
||||
},
|
||||
x: 12,
|
||||
y: 14
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-gate-infantry-a',
|
||||
name: '성문 수비병',
|
||||
faction: 'enemy',
|
||||
className: '조표 휘하 보병',
|
||||
classKey: 'yellowTurban',
|
||||
level: 9,
|
||||
exp: 56,
|
||||
hp: 44,
|
||||
maxHp: 44,
|
||||
attack: 14,
|
||||
move: 3,
|
||||
stats: { might: 80, intelligence: 52, leadership: 68, agility: 62, luck: 54 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 30 },
|
||||
armor: { itemId: 'lamellar-armor', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'yellow-scarf-charm', level: 1, exp: 0 }
|
||||
},
|
||||
x: 17,
|
||||
y: 10
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-gate-infantry-b',
|
||||
name: '성문 수비병',
|
||||
faction: 'enemy',
|
||||
className: '조표 휘하 보병',
|
||||
classKey: 'yellowTurban',
|
||||
level: 9,
|
||||
exp: 58,
|
||||
hp: 45,
|
||||
maxHp: 45,
|
||||
attack: 14,
|
||||
move: 3,
|
||||
stats: { might: 81, intelligence: 52, leadership: 68, agility: 63, luck: 54 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 32 },
|
||||
armor: { itemId: 'lamellar-armor', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'yellow-scarf-charm', level: 1, exp: 0 }
|
||||
},
|
||||
x: 18,
|
||||
y: 12
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-gate-archer-a',
|
||||
name: '성벽 궁병',
|
||||
faction: 'enemy',
|
||||
className: '성벽 궁병',
|
||||
classKey: 'archer',
|
||||
level: 9,
|
||||
exp: 58,
|
||||
hp: 36,
|
||||
maxHp: 36,
|
||||
attack: 15,
|
||||
move: 3,
|
||||
stats: { might: 72, intelligence: 64, leadership: 62, agility: 73, luck: 55 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'short-bow', level: 2, exp: 32 },
|
||||
armor: { itemId: 'cloth-armor', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'wind-quiver', level: 1, exp: 0 }
|
||||
},
|
||||
x: 20,
|
||||
y: 7
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-gate-archer-b',
|
||||
name: '성벽 궁병',
|
||||
faction: 'enemy',
|
||||
className: '성벽 궁병',
|
||||
classKey: 'archer',
|
||||
level: 9,
|
||||
exp: 60,
|
||||
hp: 37,
|
||||
maxHp: 37,
|
||||
attack: 15,
|
||||
move: 3,
|
||||
stats: { might: 73, intelligence: 64, leadership: 63, agility: 74, luck: 55 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'short-bow', level: 2, exp: 34 },
|
||||
armor: { itemId: 'cloth-armor', level: 2, exp: 14 },
|
||||
accessory: { itemId: 'wind-quiver', level: 1, exp: 0 }
|
||||
},
|
||||
x: 22,
|
||||
y: 13
|
||||
},
|
||||
{
|
||||
id: 'lubu-cavalry-a',
|
||||
name: '여포군 기병',
|
||||
faction: 'enemy',
|
||||
className: '여포군 기병',
|
||||
classKey: 'cavalry',
|
||||
level: 10,
|
||||
exp: 62,
|
||||
hp: 49,
|
||||
maxHp: 49,
|
||||
attack: 17,
|
||||
move: 5,
|
||||
stats: { might: 88, intelligence: 50, leadership: 68, agility: 90, luck: 57 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 36 },
|
||||
armor: { itemId: 'rebel-vest', level: 2, exp: 18 },
|
||||
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
|
||||
},
|
||||
x: 23,
|
||||
y: 5
|
||||
},
|
||||
{
|
||||
id: 'lubu-cavalry-b',
|
||||
name: '여포군 기병',
|
||||
faction: 'enemy',
|
||||
className: '여포군 기병',
|
||||
classKey: 'cavalry',
|
||||
level: 10,
|
||||
exp: 64,
|
||||
hp: 50,
|
||||
maxHp: 50,
|
||||
attack: 17,
|
||||
move: 5,
|
||||
stats: { might: 89, intelligence: 50, leadership: 68, agility: 91, luck: 57 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 38 },
|
||||
armor: { itemId: 'rebel-vest', level: 2, exp: 18 },
|
||||
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
|
||||
},
|
||||
x: 24,
|
||||
y: 16
|
||||
},
|
||||
{
|
||||
id: 'lubu-cavalry-c',
|
||||
name: '여포군 기병',
|
||||
faction: 'enemy',
|
||||
className: '여포군 기병',
|
||||
classKey: 'cavalry',
|
||||
level: 10,
|
||||
exp: 66,
|
||||
hp: 50,
|
||||
maxHp: 50,
|
||||
attack: 18,
|
||||
move: 5,
|
||||
stats: { might: 90, intelligence: 52, leadership: 70, agility: 91, luck: 58 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 40 },
|
||||
armor: { itemId: 'rebel-vest', level: 2, exp: 18 },
|
||||
accessory: { itemId: 'grain-pouch', level: 1, exp: 0 }
|
||||
},
|
||||
x: 21,
|
||||
y: 10
|
||||
},
|
||||
{
|
||||
id: 'xuzhou-leader-cao-bao',
|
||||
name: '조표',
|
||||
faction: 'enemy',
|
||||
className: '서주 성문장',
|
||||
classKey: 'rebelLeader',
|
||||
level: 10,
|
||||
exp: 68,
|
||||
hp: 64,
|
||||
maxHp: 64,
|
||||
attack: 17,
|
||||
move: 4,
|
||||
stats: { might: 84, intelligence: 60, leadership: 82, agility: 66, luck: 56 },
|
||||
equipment: {
|
||||
weapon: { itemId: 'leader-axe', level: 2, exp: 38 },
|
||||
armor: { itemId: 'lamellar-armor', level: 2, exp: 20 },
|
||||
accessory: { itemId: 'war-manual', level: 1, exp: 0 }
|
||||
},
|
||||
x: 20,
|
||||
y: 10
|
||||
}
|
||||
];
|
||||
|
||||
export const firstBattleBonds: BattleBond[] = [
|
||||
{
|
||||
id: 'liu-bei__guan-yu',
|
||||
@@ -2969,6 +3254,7 @@ export const fifthBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBo
|
||||
export const sixthBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBondForScenario);
|
||||
export const seventhBattleBonds: BattleBond[] = firstBattleBonds.map(cloneBattleBondForScenario);
|
||||
export const eighthBattleBonds: BattleBond[] = [...firstBattleBonds, ...xuzhouRecruitBonds].map(cloneBattleBondForScenario);
|
||||
export const ninthBattleBonds: BattleBond[] = eighthBattleBonds.map(cloneBattleBondForScenario);
|
||||
|
||||
function createEighthBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 22 }, (_, y) =>
|
||||
@@ -3002,6 +3288,35 @@ function createEighthBattleTerrain(): TerrainType[][] {
|
||||
);
|
||||
}
|
||||
|
||||
function createNinthBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 22 }, (_, y) =>
|
||||
Array.from({ length: 26 }, (_, x): TerrainType => {
|
||||
if ((x >= 1 && x <= 4 && y >= 16 && y <= 20) || (x >= 5 && x <= 7 && y >= 18 && y <= 20)) {
|
||||
return 'camp';
|
||||
}
|
||||
if ((x >= 19 && x <= 24 && y >= 3 && y <= 8) || (x >= 18 && x <= 24 && y >= 12 && y <= 16)) {
|
||||
return 'fort';
|
||||
}
|
||||
if ((x >= 20 && x <= 22 && y >= 9 && y <= 11) || (x >= 11 && x <= 12 && y >= 13 && y <= 15)) {
|
||||
return 'village';
|
||||
}
|
||||
if ((x === 14 || x === 15) && y >= 0 && y <= 20) {
|
||||
return 'river';
|
||||
}
|
||||
if ((y === 10 && x >= 2 && x <= 24) || (x === 8 && y >= 5 && y <= 20) || (x === 18 && y >= 2 && y <= 18) || (x + y === 25 && x >= 7 && x <= 17)) {
|
||||
return 'road';
|
||||
}
|
||||
if ((x <= 5 && y <= 5) || (x >= 2 && x <= 7 && y >= 7 && y <= 12) || (x >= 8 && x <= 13 && y >= 1 && y <= 5) || (x >= 4 && x <= 10 && y >= 14 && y <= 17)) {
|
||||
return 'forest';
|
||||
}
|
||||
if ((x >= 21 && y <= 2) || (x >= 22 && y >= 17) || (x >= 10 && x <= 13 && y >= 16) || (x <= 3 && y >= 6 && y <= 9)) {
|
||||
return 'hill';
|
||||
}
|
||||
return 'plain';
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
|
||||
return {
|
||||
...cloneUnitForScenario(unit),
|
||||
|
||||
Reference in New Issue
Block a user