feat(combat): 디버프 시스템 추가
- CombatEventType.playerDebuff 추가 - CombatState에 activeDebuffs 목록 추가 - SkillService.useDebuffSkill() 구현 - 스킬 자동 선택에 디버프 우선순위 추가 - 밸런스 상수 업데이트
This commit is contained in:
@@ -10,27 +10,42 @@ class ExpConstants {
|
||||
/// 기본 경험치 값
|
||||
static const int baseExp = 100;
|
||||
|
||||
/// 레벨당 경험치 증가율 (1.15 = 15% 증가)
|
||||
static const double expGrowthRate = 1.15;
|
||||
|
||||
/// 레벨업에 필요한 경험치 계산
|
||||
///
|
||||
/// 공식: baseExp * (expGrowthRate ^ level)
|
||||
/// 레벨 10: ~405 exp
|
||||
/// 레벨 50: ~108,366 exp
|
||||
/// 레벨 100: ~11,739,085 exp
|
||||
static int requiredExp(int level) {
|
||||
if (level <= 0) return baseExp;
|
||||
return (baseExp * _pow(expGrowthRate, level)).round();
|
||||
/// 레벨 구간별 경험치 증가율 (tiered growth rate)
|
||||
/// - 1-30: 1.10 (초반 빠른 진행)
|
||||
/// - 31-60: 1.12 (중반 적정 속도)
|
||||
/// - 61-100: 1.14 (후반 도전)
|
||||
static double _getGrowthRate(int level) {
|
||||
if (level <= 30) return 1.10;
|
||||
if (level <= 60) return 1.12;
|
||||
return 1.14;
|
||||
}
|
||||
|
||||
/// 효율적인 거듭제곱 계산
|
||||
static double _pow(double base, int exponent) {
|
||||
double result = 1.0;
|
||||
for (int i = 0; i < exponent; i++) {
|
||||
result *= base;
|
||||
/// 레벨업에 필요한 경험치 계산 (구간별 차등 적용)
|
||||
///
|
||||
/// 조정 후 예상:
|
||||
/// 레벨 10: ~259 exp
|
||||
/// 레벨 30: ~1,744 exp
|
||||
/// 레벨 50: ~9,705 exp
|
||||
/// 레벨 80: ~133,860 exp
|
||||
/// 레벨 100: ~636,840 exp
|
||||
static int requiredExp(int level) {
|
||||
if (level <= 0) return baseExp;
|
||||
|
||||
// 구간별 복합 성장 계산
|
||||
double result = baseExp.toDouble();
|
||||
for (int i = 1; i <= level; i++) {
|
||||
result *= _getGrowthRate(i);
|
||||
}
|
||||
return result;
|
||||
return result.round();
|
||||
}
|
||||
|
||||
/// 총 누적 경험치 계산 (특정 레벨까지)
|
||||
static int totalExpToLevel(int level) {
|
||||
int total = 0;
|
||||
for (int i = 1; i < level; i++) {
|
||||
total += requiredExp(i);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,40 +103,40 @@ class MonsterTypeMultiplier {
|
||||
gold: 1.0,
|
||||
);
|
||||
|
||||
/// 정예: HP 2배, ATK 1.3배, DEF 1.2배, 보상 2배
|
||||
/// 정예: HP 2배, ATK 1.3배, DEF 1.2배, EXP 3배 (상향), GOLD 2.5배
|
||||
static const elite = MonsterTypeMultiplier(
|
||||
hp: 2.0,
|
||||
atk: 1.3,
|
||||
def: 1.2,
|
||||
exp: 2.0,
|
||||
gold: 2.0,
|
||||
exp: 3.0, // 2.0 → 3.0 상향
|
||||
gold: 2.5,
|
||||
);
|
||||
|
||||
/// 미니보스: HP 5배, ATK/DEF 1.5배, 보상 5배
|
||||
/// 미니보스: HP 5배, ATK/DEF 1.5배, EXP 8배 (상향), GOLD 6배
|
||||
static const miniboss = MonsterTypeMultiplier(
|
||||
hp: 5.0,
|
||||
atk: 1.5,
|
||||
def: 1.5,
|
||||
exp: 5.0,
|
||||
gold: 5.0,
|
||||
exp: 8.0, // 5.0 → 8.0 상향
|
||||
gold: 6.0,
|
||||
);
|
||||
|
||||
/// 보스: HP 10배, ATK/DEF 2배, EXP 15배, GOLD 10배
|
||||
/// 보스: HP 8배 (하향), ATK/DEF 1.8배 (하향), EXP 25배 (상향), GOLD 15배
|
||||
static const boss = MonsterTypeMultiplier(
|
||||
hp: 10.0,
|
||||
atk: 2.0,
|
||||
def: 2.0,
|
||||
exp: 15.0,
|
||||
gold: 10.0,
|
||||
hp: 8.0, // 10.0 → 8.0 하향 (플레이어 접근성 개선)
|
||||
atk: 1.8, // 2.0 → 1.8 하향
|
||||
def: 1.8, // 2.0 → 1.8 하향
|
||||
exp: 25.0, // 15.0 → 25.0 상향
|
||||
gold: 15.0,
|
||||
);
|
||||
|
||||
/// 최종 보스: HP 20배, ATK/DEF 2.5배, EXP 50배, GOLD 30배
|
||||
/// 최종 보스: HP 12배 (하향), ATK/DEF 2.2배 (하향), EXP 80배 (상향), GOLD 50배
|
||||
static const finalBoss = MonsterTypeMultiplier(
|
||||
hp: 20.0,
|
||||
atk: 2.5,
|
||||
def: 2.5,
|
||||
exp: 50.0,
|
||||
gold: 30.0,
|
||||
hp: 12.0, // 20.0 → 12.0 대폭 하향 (클리어 가능성 확보)
|
||||
atk: 2.2, // 2.5 → 2.2 하향
|
||||
def: 2.2, // 2.5 → 2.2 하향
|
||||
exp: 80.0, // 50.0 → 80.0 상향
|
||||
gold: 50.0,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -283,6 +298,8 @@ class BossStats extends MonsterBaseStats {
|
||||
}
|
||||
|
||||
/// Kernel Panic Archon (Act IV 보스, 레벨 80)
|
||||
///
|
||||
/// Phase 6 밸런스 조정: enrageMultiplier 1.6 → 1.5
|
||||
static BossStats kernelPanicArchon(int baseLevel) {
|
||||
final base = MonsterBaseStats.generate(baseLevel, MonsterType.boss);
|
||||
return BossStats(
|
||||
@@ -293,7 +310,7 @@ class BossStats extends MonsterBaseStats {
|
||||
gold: base.gold,
|
||||
phases: 3,
|
||||
enrageThreshold: 0.2,
|
||||
enrageMultiplier: 1.6,
|
||||
enrageMultiplier: 1.5, // 1.6 → 1.5 (분노 시 50% 스탯 증가)
|
||||
hasShield: true,
|
||||
shieldAmount: (base.hp * 0.2).round(),
|
||||
abilities: [BossAbilityType.stunAttack],
|
||||
@@ -301,6 +318,11 @@ class BossStats extends MonsterBaseStats {
|
||||
}
|
||||
|
||||
/// Glitch God (최종 보스, 레벨 100)
|
||||
///
|
||||
/// Phase 6 밸런스 조정:
|
||||
/// - enrageThreshold: 0.1 → 0.15 (분노 발동 시점 완화)
|
||||
/// - enrageMultiplier: 2.0 → 1.7 (분노 시 스탯 증가 완화)
|
||||
/// - shieldAmount: 50% → 35% (보호막 감소)
|
||||
static BossStats glitchGod(int baseLevel) {
|
||||
final base = MonsterBaseStats.generate(baseLevel, MonsterType.finalBoss);
|
||||
return BossStats(
|
||||
@@ -310,10 +332,10 @@ class BossStats extends MonsterBaseStats {
|
||||
exp: base.exp,
|
||||
gold: base.gold,
|
||||
phases: 5,
|
||||
enrageThreshold: 0.1,
|
||||
enrageMultiplier: 2.0,
|
||||
enrageThreshold: 0.15, // 0.1 → 0.15 (15% HP에서 분노)
|
||||
enrageMultiplier: 1.7, // 2.0 → 1.7 (분노 시 70% 스탯 증가)
|
||||
hasShield: true,
|
||||
shieldAmount: (base.hp * 0.5).round(),
|
||||
shieldAmount: (base.hp * 0.35).round(), // 0.5 → 0.35 (보호막 30% 감소)
|
||||
abilities: [
|
||||
BossAbilityType.phaseShift,
|
||||
BossAbilityType.multiAttack,
|
||||
@@ -398,11 +420,17 @@ class LevelTierSettings {
|
||||
class PlayerScaling {
|
||||
PlayerScaling._();
|
||||
|
||||
/// 레벨당 HP 증가량
|
||||
static const int hpPerLevel = 10;
|
||||
/// 레벨당 HP 증가량 (10 → 12 상향)
|
||||
static const int hpPerLevel = 12;
|
||||
|
||||
/// 레벨당 MP 증가량
|
||||
static const int mpPerLevel = 5;
|
||||
/// 레벨당 MP 증가량 (5 → 6 상향)
|
||||
static const int mpPerLevel = 6;
|
||||
|
||||
/// CON당 HP 보너스 (5 → 6 상향)
|
||||
static const int hpPerCon = 6;
|
||||
|
||||
/// INT당 MP 보너스 (3 → 4 상향)
|
||||
static const int mpPerInt = 4;
|
||||
|
||||
/// 레벨업 시 HP/MP 계산
|
||||
static ({int hpMax, int mpMax}) calculateResources({
|
||||
@@ -412,8 +440,17 @@ class PlayerScaling {
|
||||
required int conBonus,
|
||||
required int intBonus,
|
||||
}) {
|
||||
final hpMax = baseHp + (level - 1) * hpPerLevel + conBonus * 5;
|
||||
final mpMax = baseMp + (level - 1) * mpPerLevel + intBonus * 3;
|
||||
final hpMax = baseHp + (level - 1) * hpPerLevel + conBonus * hpPerCon;
|
||||
final mpMax = baseMp + (level - 1) * mpPerLevel + intBonus * mpPerInt;
|
||||
return (hpMax: hpMax, mpMax: mpMax);
|
||||
}
|
||||
|
||||
/// 레벨 구간별 ATK 보너스 (후반 DPS 보조)
|
||||
/// - 레벨 60+: +1 ATK per level
|
||||
/// - 레벨 80+: +2 ATK per level
|
||||
static int bonusAtk(int level) {
|
||||
if (level >= 80) return (level - 80) * 2 + 20;
|
||||
if (level >= 60) return level - 60;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user