Add class and terrain battle rules
This commit is contained in:
195
src/game/data/battleRules.ts
Normal file
195
src/game/data/battleRules.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
export type TerrainType = 'plain' | 'road' | 'forest' | 'hill' | 'village' | 'fort' | 'camp';
|
||||
|
||||
export type UnitClassKey = 'lord' | 'infantry' | 'cavalry' | 'spearman' | 'archer' | 'bandit' | 'yellowTurban' | 'rebelLeader';
|
||||
|
||||
export type TerrainRule = {
|
||||
label: string;
|
||||
color: number;
|
||||
alpha: number;
|
||||
moveCost: number;
|
||||
defenseBonus: number;
|
||||
};
|
||||
|
||||
export type UnitClassDefinition = {
|
||||
key: UnitClassKey;
|
||||
name: string;
|
||||
family: string;
|
||||
role: string;
|
||||
description: string;
|
||||
terrainRatings: Record<TerrainType, number>;
|
||||
movementCosts?: Partial<Record<TerrainType, number>>;
|
||||
};
|
||||
|
||||
export const terrainRules: Record<TerrainType, TerrainRule> = {
|
||||
plain: { label: '평지', color: 0x6d8056, alpha: 0.04, moveCost: 1, defenseBonus: 0 },
|
||||
road: { label: '길', color: 0xb08b55, alpha: 0.1, moveCost: 1, defenseBonus: 0 },
|
||||
forest: { label: '숲', color: 0x355f42, alpha: 0.17, moveCost: 2, defenseBonus: 10 },
|
||||
hill: { label: '언덕', color: 0x82724e, alpha: 0.15, moveCost: 2, defenseBonus: 8 },
|
||||
village: { label: '마을', color: 0x8d6f4b, alpha: 0.2, moveCost: 1, defenseBonus: 12 },
|
||||
fort: { label: '요새', color: 0x735c46, alpha: 0.22, moveCost: 1, defenseBonus: 18 },
|
||||
camp: { label: '진영', color: 0x4f6a73, alpha: 0.17, moveCost: 1, defenseBonus: 15 }
|
||||
};
|
||||
|
||||
export const unitClasses: Record<UnitClassKey, UnitClassDefinition> = {
|
||||
lord: {
|
||||
key: 'lord',
|
||||
name: '군웅',
|
||||
family: '군주계',
|
||||
role: '지휘 / 균형',
|
||||
description: '지형을 크게 타지 않고 아군 전선을 안정시키는 지휘관 병과.',
|
||||
terrainRatings: {
|
||||
plain: 100,
|
||||
road: 105,
|
||||
forest: 95,
|
||||
hill: 95,
|
||||
village: 110,
|
||||
fort: 115,
|
||||
camp: 115
|
||||
}
|
||||
},
|
||||
infantry: {
|
||||
key: 'infantry',
|
||||
name: '의용 보병',
|
||||
family: '보병계',
|
||||
role: '전열 / 방어',
|
||||
description: '숲과 진영에서 버티는 힘이 좋고 기병의 돌격을 받아내기 좋다.',
|
||||
terrainRatings: {
|
||||
plain: 100,
|
||||
road: 100,
|
||||
forest: 110,
|
||||
hill: 105,
|
||||
village: 115,
|
||||
fort: 120,
|
||||
camp: 115
|
||||
},
|
||||
movementCosts: {
|
||||
forest: 1,
|
||||
village: 1,
|
||||
fort: 1,
|
||||
camp: 1
|
||||
}
|
||||
},
|
||||
cavalry: {
|
||||
key: 'cavalry',
|
||||
name: '경기병',
|
||||
family: '기병계',
|
||||
role: '기동 / 돌파',
|
||||
description: '길과 평지에서 빠르게 압박하지만 숲과 언덕에서는 힘이 떨어진다.',
|
||||
terrainRatings: {
|
||||
plain: 110,
|
||||
road: 120,
|
||||
forest: 75,
|
||||
hill: 80,
|
||||
village: 95,
|
||||
fort: 90,
|
||||
camp: 100
|
||||
},
|
||||
movementCosts: {
|
||||
road: 1,
|
||||
forest: 3,
|
||||
hill: 3
|
||||
}
|
||||
},
|
||||
spearman: {
|
||||
key: 'spearman',
|
||||
name: '창병',
|
||||
family: '창병계',
|
||||
role: '대기병 / 압박',
|
||||
description: '기병 견제와 전선 고정에 특화된 근접 병과.',
|
||||
terrainRatings: {
|
||||
plain: 105,
|
||||
road: 100,
|
||||
forest: 95,
|
||||
hill: 105,
|
||||
village: 105,
|
||||
fort: 110,
|
||||
camp: 110
|
||||
}
|
||||
},
|
||||
archer: {
|
||||
key: 'archer',
|
||||
name: '궁병',
|
||||
family: '궁병계',
|
||||
role: '원거리 / 견제',
|
||||
description: '언덕과 요새에서 유리하고 근접 압박에는 약한 원거리 병과.',
|
||||
terrainRatings: {
|
||||
plain: 95,
|
||||
road: 95,
|
||||
forest: 90,
|
||||
hill: 115,
|
||||
village: 100,
|
||||
fort: 120,
|
||||
camp: 105
|
||||
},
|
||||
movementCosts: {
|
||||
hill: 1
|
||||
}
|
||||
},
|
||||
bandit: {
|
||||
key: 'bandit',
|
||||
name: '도적',
|
||||
family: '적병계',
|
||||
role: '습격 / 산악',
|
||||
description: '숲과 언덕에서 강하고 정규전 방어 지형에서는 약하다.',
|
||||
terrainRatings: {
|
||||
plain: 95,
|
||||
road: 95,
|
||||
forest: 115,
|
||||
hill: 115,
|
||||
village: 100,
|
||||
fort: 90,
|
||||
camp: 95
|
||||
},
|
||||
movementCosts: {
|
||||
forest: 1,
|
||||
hill: 1
|
||||
}
|
||||
},
|
||||
yellowTurban: {
|
||||
key: 'yellowTurban',
|
||||
name: '황건병',
|
||||
family: '황건적계',
|
||||
role: '민병 / 물량',
|
||||
description: '능력은 낮지만 험지에서 성가시게 버티는 반란군 병과.',
|
||||
terrainRatings: {
|
||||
plain: 95,
|
||||
road: 95,
|
||||
forest: 105,
|
||||
hill: 105,
|
||||
village: 100,
|
||||
fort: 90,
|
||||
camp: 95
|
||||
},
|
||||
movementCosts: {
|
||||
forest: 1
|
||||
}
|
||||
},
|
||||
rebelLeader: {
|
||||
key: 'rebelLeader',
|
||||
name: '두령',
|
||||
family: '두령계',
|
||||
role: '지휘 / 근접',
|
||||
description: '황건적을 이끄는 지휘관형 적병. 진영과 험지에서 버티는 힘이 있다.',
|
||||
terrainRatings: {
|
||||
plain: 100,
|
||||
road: 100,
|
||||
forest: 110,
|
||||
hill: 110,
|
||||
village: 105,
|
||||
fort: 105,
|
||||
camp: 110
|
||||
},
|
||||
movementCosts: {
|
||||
forest: 1,
|
||||
hill: 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function getUnitClass(classKey: UnitClassKey) {
|
||||
return unitClasses[classKey];
|
||||
}
|
||||
|
||||
export function getTerrainRule(terrain: TerrainType) {
|
||||
return terrainRules[terrain];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { TerrainType, UnitClassKey } from './battleRules';
|
||||
|
||||
export type PortraitKey = 'liuBei' | 'guanYu' | 'zhangFei';
|
||||
|
||||
export type StoryPage = {
|
||||
@@ -15,6 +17,7 @@ export type UnitData = {
|
||||
name: string;
|
||||
faction: 'ally' | 'enemy';
|
||||
className: string;
|
||||
classKey: UnitClassKey;
|
||||
hp: number;
|
||||
maxHp: number;
|
||||
attack: number;
|
||||
@@ -41,8 +44,6 @@ export type BattleBond = {
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type TerrainType = 'plain' | 'forest' | 'hill' | 'fort';
|
||||
|
||||
export type BattleMap = {
|
||||
width: number;
|
||||
height: number;
|
||||
@@ -140,18 +141,18 @@ export const firstBattleMap: BattleMap = {
|
||||
width: 12,
|
||||
height: 12,
|
||||
terrain: [
|
||||
['plain', 'plain', 'forest', 'forest', 'plain', 'plain', 'plain', 'hill', 'hill', 'plain', 'plain', 'plain'],
|
||||
['plain', 'forest', 'forest', 'plain', 'plain', 'plain', 'plain', 'plain', 'hill', 'plain', 'plain', 'plain'],
|
||||
['plain', 'forest', 'plain', 'plain', 'plain', 'plain', 'forest', 'plain', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'hill', 'hill', 'plain', 'forest', 'forest', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'hill', 'plain', 'plain', 'plain', 'forest', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'fort', 'plain', 'plain', 'plain', 'plain', 'forest', 'forest'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'forest', 'plain'],
|
||||
['forest', 'forest', 'plain', 'plain', 'plain', 'plain', 'plain', 'hill', 'hill', 'plain', 'plain', 'plain'],
|
||||
['forest', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'hill', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'forest', 'forest', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'plain', 'forest', 'plain', 'plain', 'plain', 'plain', 'forest', 'forest', 'plain'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'forest', 'plain']
|
||||
['plain', 'plain', 'forest', 'forest', 'plain', 'road', 'road', 'hill', 'hill', 'plain', 'plain', 'plain'],
|
||||
['plain', 'forest', 'forest', 'plain', 'plain', 'road', 'road', 'plain', 'hill', 'plain', 'plain', 'plain'],
|
||||
['plain', 'forest', 'plain', 'plain', 'plain', 'road', 'forest', 'plain', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'hill', 'hill', 'road', 'forest', 'forest', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'plain', 'plain', 'hill', 'plain', 'road', 'road', 'forest', 'plain', 'plain', 'fort', 'plain'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'village', 'road', 'plain', 'plain', 'plain', 'forest', 'forest'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'road', 'road', 'plain', 'plain', 'plain', 'forest', 'plain'],
|
||||
['forest', 'forest', 'plain', 'plain', 'plain', 'road', 'plain', 'hill', 'hill', 'plain', 'plain', 'plain'],
|
||||
['forest', 'plain', 'plain', 'plain', 'plain', 'road', 'plain', 'hill', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'camp', 'plain', 'forest', 'forest', 'road', 'road', 'plain', 'plain', 'plain', 'plain', 'plain'],
|
||||
['plain', 'camp', 'camp', 'plain', 'forest', 'plain', 'road', 'plain', 'plain', 'forest', 'forest', 'plain'],
|
||||
['plain', 'plain', 'plain', 'plain', 'plain', 'plain', 'road', 'road', 'plain', 'plain', 'forest', 'plain']
|
||||
]
|
||||
};
|
||||
|
||||
@@ -160,7 +161,8 @@ export const firstBattleUnits: UnitData[] = [
|
||||
id: 'liu-bei',
|
||||
name: '유비',
|
||||
faction: 'ally',
|
||||
className: '의병장',
|
||||
className: '군웅',
|
||||
classKey: 'lord',
|
||||
hp: 32,
|
||||
maxHp: 32,
|
||||
attack: 9,
|
||||
@@ -173,7 +175,8 @@ export const firstBattleUnits: UnitData[] = [
|
||||
id: 'guan-yu',
|
||||
name: '관우',
|
||||
faction: 'ally',
|
||||
className: '보병',
|
||||
className: '의용 보병',
|
||||
classKey: 'infantry',
|
||||
hp: 30,
|
||||
maxHp: 30,
|
||||
attack: 10,
|
||||
@@ -187,6 +190,7 @@ export const firstBattleUnits: UnitData[] = [
|
||||
name: '장비',
|
||||
faction: 'ally',
|
||||
className: '창병',
|
||||
classKey: 'spearman',
|
||||
hp: 30,
|
||||
maxHp: 30,
|
||||
attack: 10,
|
||||
@@ -199,7 +203,8 @@ export const firstBattleUnits: UnitData[] = [
|
||||
id: 'rebel-a',
|
||||
name: '황건병',
|
||||
faction: 'enemy',
|
||||
className: '도적',
|
||||
className: '황건병',
|
||||
classKey: 'yellowTurban',
|
||||
hp: 20,
|
||||
maxHp: 20,
|
||||
attack: 6,
|
||||
@@ -212,7 +217,8 @@ export const firstBattleUnits: UnitData[] = [
|
||||
id: 'rebel-b',
|
||||
name: '황건병',
|
||||
faction: 'enemy',
|
||||
className: '도적',
|
||||
className: '황건병',
|
||||
classKey: 'yellowTurban',
|
||||
hp: 20,
|
||||
maxHp: 20,
|
||||
attack: 6,
|
||||
@@ -226,6 +232,7 @@ export const firstBattleUnits: UnitData[] = [
|
||||
name: '황건궁병',
|
||||
faction: 'enemy',
|
||||
className: '궁병',
|
||||
classKey: 'archer',
|
||||
hp: 18,
|
||||
maxHp: 18,
|
||||
attack: 7,
|
||||
@@ -239,6 +246,7 @@ export const firstBattleUnits: UnitData[] = [
|
||||
name: '두령 한석',
|
||||
faction: 'enemy',
|
||||
className: '두령',
|
||||
classKey: 'rebelLeader',
|
||||
hp: 30,
|
||||
maxHp: 30,
|
||||
attack: 9,
|
||||
|
||||
Reference in New Issue
Block a user