feat(phase5): 종족/클래스 시스템 균형 및 UI 통합
- 21개 종족 균형 재설계 (스탯 합계 = 0) - 18개 클래스 균형 재설계 (스탯 합계 = +3) - Traits에 raceId, classId 필드 추가 - 저장/불러오기에 종족/클래스 ID 추가 - 캐릭터 생성 UI에서 RaceData/ClassData 사용 - 선택 시 스탯 보정 및 패시브 정보 표시
This commit is contained in:
@@ -2,20 +2,42 @@ import 'package:askiineverdie/src/core/model/race_traits.dart';
|
||||
|
||||
/// 종족 데이터 정의 (race data)
|
||||
///
|
||||
/// 프로그래밍 테마의 21가지 종족 정의
|
||||
/// pq_config_data.dart의 Races 데이터 기반
|
||||
/// 21가지 종족 - 모든 종족의 스탯 합계 = 0 (균형)
|
||||
/// 패시브는 각 종족의 고유한 플레이스타일을 정의
|
||||
class RaceData {
|
||||
RaceData._();
|
||||
|
||||
// ==========================================================================
|
||||
// 기본 종족 (HP/밸런스형)
|
||||
// HP/균형형 종족
|
||||
// ==========================================================================
|
||||
|
||||
/// Byte Human: HP 보너스
|
||||
/// Byte Human: 균형형 (스탯 합계: 0)
|
||||
/// 특화 없이 경험치로 보상
|
||||
static const byteHuman = RaceTraits(
|
||||
raceId: 'byte_human',
|
||||
name: 'Byte Human',
|
||||
statModifiers: {},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.expBonus,
|
||||
value: 0.05,
|
||||
description: '경험치 +5%',
|
||||
),
|
||||
],
|
||||
expMultiplier: 1.05,
|
||||
);
|
||||
|
||||
/// Kernel Giant: 탱커형 (스탯 합계: 0)
|
||||
/// STR/CON +2, DEX/INT -2
|
||||
static const kernelGiant = RaceTraits(
|
||||
raceId: 'kernel_giant',
|
||||
name: 'Kernel Giant',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.con: 2,
|
||||
StatType.dex: -2,
|
||||
StatType.intelligence: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.hpBonus,
|
||||
@@ -25,45 +47,32 @@ class RaceData {
|
||||
],
|
||||
);
|
||||
|
||||
/// Kernel Giant: STR + HP 보너스
|
||||
static const kernelGiant = RaceTraits(
|
||||
raceId: 'kernel_giant',
|
||||
name: 'Kernel Giant',
|
||||
statModifiers: {
|
||||
StatType.str: 3,
|
||||
StatType.dex: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.hpBonus,
|
||||
value: 0.15,
|
||||
description: 'HP +15%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 지혜 종족 (WIS 기반)
|
||||
// 지혜/마법 종족 (WIS 기반)
|
||||
// ==========================================================================
|
||||
|
||||
/// Null Elf: WIS 보너스
|
||||
/// Null Elf: 마법형 (스탯 합계: 0)
|
||||
/// WIS/INT +2, STR/CON -2
|
||||
static const nullElf = RaceTraits(
|
||||
raceId: 'null_elf',
|
||||
name: 'Null Elf',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.intelligence: 1,
|
||||
StatType.str: -2,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.magicDamageBonus,
|
||||
value: 0.10,
|
||||
description: '마법 데미지 +10%',
|
||||
value: 0.08,
|
||||
description: '마법 데미지 +8%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Recursive Sage: WIS + INT 보너스
|
||||
/// Recursive Sage: 순수 마법형 (스탯 합계: 0)
|
||||
/// WIS/INT +2, STR -2, DEX -1, CHA +1
|
||||
static const recursiveSage = RaceTraits(
|
||||
raceId: 'recursive_sage',
|
||||
name: 'Recursive Sage',
|
||||
@@ -71,6 +80,8 @@ class RaceData {
|
||||
StatType.wis: 2,
|
||||
StatType.intelligence: 2,
|
||||
StatType.str: -2,
|
||||
StatType.dex: -1,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
@@ -81,47 +92,62 @@ class RaceData {
|
||||
],
|
||||
);
|
||||
|
||||
/// Callback Priest: WIS + CHA 보너스
|
||||
/// Callback Priest: 지원형 (스탯 합계: 0)
|
||||
/// WIS +2, CHA +1, STR -1, DEX -1, CON -1
|
||||
static const callbackPriest = RaceTraits(
|
||||
raceId: 'callback_priest',
|
||||
name: 'Callback Priest',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.cha: 2,
|
||||
StatType.cha: 1,
|
||||
StatType.str: -1,
|
||||
StatType.dex: -1,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [],
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.expBonus,
|
||||
value: 0.03,
|
||||
description: '경험치 +3%',
|
||||
),
|
||||
],
|
||||
expMultiplier: 1.03,
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 체력 종족 (CON 기반)
|
||||
// 체력/방어 종족 (CON 기반)
|
||||
// ==========================================================================
|
||||
|
||||
/// Buffer Dwarf: CON 보너스
|
||||
/// Buffer Dwarf: 방어형 (스탯 합계: 0)
|
||||
/// CON +2, STR +1, DEX -2, CHA -1
|
||||
static const bufferDwarf = RaceTraits(
|
||||
raceId: 'buffer_dwarf',
|
||||
name: 'Buffer Dwarf',
|
||||
statModifiers: {
|
||||
StatType.con: 2,
|
||||
StatType.dex: -1,
|
||||
StatType.str: 1,
|
||||
StatType.dex: -2,
|
||||
StatType.cha: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.defenseBonus,
|
||||
value: 0.05,
|
||||
description: '방어력 +5%',
|
||||
value: 0.08,
|
||||
description: '방어력 +8%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Coredump Undead: CON 보너스
|
||||
/// Coredump Undead: 생존형 (스탯 합계: 0)
|
||||
/// CON +2, STR +1, CHA -2, DEX -1
|
||||
static const coredumpUndead = RaceTraits(
|
||||
raceId: 'coredump_undead',
|
||||
name: 'Coredump Undead',
|
||||
statModifiers: {
|
||||
StatType.con: 2,
|
||||
StatType.str: 1,
|
||||
StatType.cha: -2,
|
||||
StatType.dex: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
@@ -133,16 +159,19 @@ class RaceData {
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 민첩 종족 (DEX 기반)
|
||||
// 민첩/크리티컬 종족 (DEX 기반)
|
||||
// ==========================================================================
|
||||
|
||||
/// Bit Halfling: DEX 보너스
|
||||
/// Bit Halfling: 민첩형 (스탯 합계: 0)
|
||||
/// DEX +2, CHA +1, STR -2, CON -1
|
||||
static const bitHalfling = RaceTraits(
|
||||
raceId: 'bit_halfling',
|
||||
name: 'Bit Halfling',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.str: -1,
|
||||
StatType.cha: 1,
|
||||
StatType.str: -2,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
@@ -153,69 +182,81 @@ class RaceData {
|
||||
],
|
||||
);
|
||||
|
||||
/// Cache Imp: DEX 보너스
|
||||
/// Cache Imp: 속도형 (스탯 합계: 0)
|
||||
/// DEX +2, INT +1, CON -2, WIS -1
|
||||
static const cacheImp = RaceTraits(
|
||||
raceId: 'cache_imp',
|
||||
name: 'Cache Imp',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [],
|
||||
);
|
||||
|
||||
/// Iterator Rogue: DEX 보너스
|
||||
static const iteratorRogue = RaceTraits(
|
||||
raceId: 'iterator_rogue',
|
||||
name: 'Iterator Rogue',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.intelligence: 1,
|
||||
StatType.con: -2,
|
||||
StatType.wis: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.criticalBonus,
|
||||
value: 0.05,
|
||||
description: '크리티컬 +5%',
|
||||
value: 0.02,
|
||||
description: '크리티컬 +2%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Iterator Rogue: 암살형 (스탯 합계: 0)
|
||||
/// DEX +3, STR +1, CON -2, WIS -1, CHA -1
|
||||
static const iteratorRogue = RaceTraits(
|
||||
raceId: 'iterator_rogue',
|
||||
name: 'Iterator Rogue',
|
||||
statModifiers: {
|
||||
StatType.dex: 3,
|
||||
StatType.str: 1,
|
||||
StatType.con: -2,
|
||||
StatType.wis: -1,
|
||||
StatType.cha: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.criticalBonus,
|
||||
value: 0.04,
|
||||
description: '크리티컬 +4%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 힘 종족 (STR 기반)
|
||||
// 힘/물리 종족 (STR 기반)
|
||||
// ==========================================================================
|
||||
|
||||
/// Array Orc: STR 보너스
|
||||
/// Array Orc: 공격형 (스탯 합계: 0)
|
||||
/// STR +2, CON +1, INT -2, WIS -1
|
||||
static const arrayOrc = RaceTraits(
|
||||
raceId: 'array_orc',
|
||||
name: 'Array Orc',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.intelligence: -1,
|
||||
StatType.con: 1,
|
||||
StatType.intelligence: -2,
|
||||
StatType.wis: -1,
|
||||
},
|
||||
passives: [],
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.hpBonus,
|
||||
value: 0.05,
|
||||
description: 'HP +5%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Flag Knight: CHA + STR 보너스
|
||||
/// Flag Knight: 전사형 (스탯 합계: 0)
|
||||
/// STR +2, CHA +1, INT -2, WIS -1
|
||||
static const flagKnight = RaceTraits(
|
||||
raceId: 'flag_knight',
|
||||
name: 'Flag Knight',
|
||||
statModifiers: {
|
||||
StatType.cha: 2,
|
||||
StatType.str: 2,
|
||||
StatType.cha: 1,
|
||||
StatType.intelligence: -2,
|
||||
},
|
||||
passives: [],
|
||||
);
|
||||
|
||||
/// Protocol Paladin: STR + CHA 보너스
|
||||
static const protocolPaladin = RaceTraits(
|
||||
raceId: 'protocol_paladin',
|
||||
name: 'Protocol Paladin',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.cha: 2,
|
||||
StatType.dex: -2,
|
||||
StatType.wis: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
@@ -226,23 +267,53 @@ class RaceData {
|
||||
],
|
||||
);
|
||||
|
||||
/// Protocol Paladin: 수호자형 (스탯 합계: 0)
|
||||
/// STR +2, CON +1, CHA +1, DEX -2, INT -2
|
||||
static const protocolPaladin = RaceTraits(
|
||||
raceId: 'protocol_paladin',
|
||||
name: 'Protocol Paladin',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.con: 1,
|
||||
StatType.cha: 1,
|
||||
StatType.dex: -2,
|
||||
StatType.intelligence: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.defenseBonus,
|
||||
value: 0.06,
|
||||
description: '방어력 +6%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 복합 스탯 종족
|
||||
// ==========================================================================
|
||||
|
||||
/// Stack Goblin: DEX + CON 보너스
|
||||
/// Stack Goblin: 기동형 (스탯 합계: 0)
|
||||
/// DEX +2, CON +1, STR -1, CHA -2
|
||||
static const stackGoblin = RaceTraits(
|
||||
raceId: 'stack_goblin',
|
||||
name: 'Stack Goblin',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.con: 1,
|
||||
StatType.str: -1,
|
||||
StatType.cha: -2,
|
||||
},
|
||||
passives: [],
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.criticalBonus,
|
||||
value: 0.02,
|
||||
description: '크리티컬 +2%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Heap Troll: CON + STR 보너스
|
||||
/// Heap Troll: 중장갑형 (스탯 합계: 0)
|
||||
/// CON +2, STR +2, INT -2, DEX -2
|
||||
static const heapTroll = RaceTraits(
|
||||
raceId: 'heap_troll',
|
||||
name: 'Heap Troll',
|
||||
@@ -250,18 +321,19 @@ class RaceData {
|
||||
StatType.con: 2,
|
||||
StatType.str: 2,
|
||||
StatType.intelligence: -2,
|
||||
StatType.dex: -1,
|
||||
StatType.dex: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.hpBonus,
|
||||
value: 0.10,
|
||||
description: 'HP +10%',
|
||||
value: 0.12,
|
||||
description: 'HP +12%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Index Ranger: DEX + CON 보너스
|
||||
/// Index Ranger: 정찰형 (스탯 합계: 0)
|
||||
/// DEX +2, CON +1, INT -1, CHA -2
|
||||
static const indexRanger = RaceTraits(
|
||||
raceId: 'index_ranger',
|
||||
name: 'Index Ranger',
|
||||
@@ -269,21 +341,70 @@ class RaceData {
|
||||
StatType.dex: 2,
|
||||
StatType.con: 1,
|
||||
StatType.intelligence: -1,
|
||||
StatType.cha: -2,
|
||||
},
|
||||
passives: [],
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.criticalBonus,
|
||||
value: 0.03,
|
||||
description: '크리티컬 +3%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
// 마법 종족 (MP/INT 기반)
|
||||
// MP/주문 종족 (INT/MP 기반)
|
||||
// ==========================================================================
|
||||
|
||||
/// Pointer Fairy: MP Max + WIS 보너스
|
||||
/// Pointer Fairy: MP 특화형 (스탯 합계: 0)
|
||||
/// WIS +2, INT +1, STR -2, CON -1
|
||||
static const pointerFairy = RaceTraits(
|
||||
raceId: 'pointer_fairy',
|
||||
name: 'Pointer Fairy',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.intelligence: 1,
|
||||
StatType.str: -2,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.mpBonus,
|
||||
value: 0.12,
|
||||
description: 'MP +12%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Register Gnome: 지능형 (스탯 합계: 0)
|
||||
/// INT +2, DEX +1, STR -2, CON -1
|
||||
static const registerGnome = RaceTraits(
|
||||
raceId: 'register_gnome',
|
||||
name: 'Register Gnome',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.dex: 1,
|
||||
StatType.str: -2,
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.magicDamageBonus,
|
||||
value: 0.05,
|
||||
description: '마법 데미지 +5%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Thread Spirit: 영체형 (스탯 합계: 0)
|
||||
/// INT +1, WIS +1, CON -2
|
||||
static const threadSpirit = RaceTraits(
|
||||
raceId: 'thread_spirit',
|
||||
name: 'Thread Spirit',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 1,
|
||||
StatType.wis: 1,
|
||||
StatType.con: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
@@ -294,57 +415,34 @@ class RaceData {
|
||||
],
|
||||
);
|
||||
|
||||
/// Register Gnome: INT 보너스
|
||||
static const registerGnome = RaceTraits(
|
||||
raceId: 'register_gnome',
|
||||
name: 'Register Gnome',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.str: -1,
|
||||
},
|
||||
passives: [],
|
||||
);
|
||||
|
||||
/// Thread Spirit: MP Max 보너스
|
||||
static const threadSpirit = RaceTraits(
|
||||
raceId: 'thread_spirit',
|
||||
name: 'Thread Spirit',
|
||||
statModifiers: {
|
||||
StatType.con: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.mpBonus,
|
||||
value: 0.20,
|
||||
description: 'MP +20%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Loop Wizard: INT + MP Max 보너스
|
||||
/// Loop Wizard: 순환 마법형 (스탯 합계: 0)
|
||||
/// INT +2, WIS +1, STR -1, CON -1, DEX -1
|
||||
static const loopWizard = RaceTraits(
|
||||
raceId: 'loop_wizard',
|
||||
name: 'Loop Wizard',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.wis: 1,
|
||||
StatType.str: -1,
|
||||
StatType.con: -1,
|
||||
StatType.dex: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.mpBonus,
|
||||
value: 0.10,
|
||||
description: 'MP +10%',
|
||||
value: 0.08,
|
||||
description: 'MP +8%',
|
||||
),
|
||||
PassiveAbility(
|
||||
type: PassiveType.magicDamageBonus,
|
||||
value: 0.05,
|
||||
description: '마법 데미지 +5%',
|
||||
value: 0.04,
|
||||
description: '마법 데미지 +4%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// Lambda Druid: INT + WIS 보너스
|
||||
/// Lambda Druid: 자연 마법형 (스탯 합계: 0)
|
||||
/// INT +2, WIS +2, STR -2, CON -2
|
||||
static const lambdaDruid = RaceTraits(
|
||||
raceId: 'lambda_druid',
|
||||
name: 'Lambda Druid',
|
||||
@@ -352,20 +450,25 @@ class RaceData {
|
||||
StatType.intelligence: 2,
|
||||
StatType.wis: 2,
|
||||
StatType.str: -2,
|
||||
StatType.con: -1,
|
||||
StatType.con: -2,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.magicDamageBonus,
|
||||
value: 0.10,
|
||||
description: '마법 데미지 +10%',
|
||||
value: 0.06,
|
||||
description: '마법 데미지 +6%',
|
||||
),
|
||||
PassiveAbility(
|
||||
type: PassiveType.mpBonus,
|
||||
value: 0.06,
|
||||
description: 'MP +6%',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
/// 모든 종족 목록 (21개)
|
||||
static const List<RaceTraits> all = [
|
||||
// 기본/HP형
|
||||
// 균형형
|
||||
byteHuman,
|
||||
kernelGiant,
|
||||
// 지혜형
|
||||
|
||||
Reference in New Issue
Block a user