feat(model): 스킬 티어 및 파워 스코어 시스템 추가

- Skill 클래스에 tier 필드 추가 (1~5, 높을수록 강함)
- 타입별 powerScore 동적 계산 로직 구현
- isStrongerThan() 메서드로 스킬 강도 비교 지원
- SkillFailReason에 onGlobalCooldown 추가
- SkillSlots 클래스 신규 추가 (타입별 슬롯 제한)
This commit is contained in:
JiWoong Sul
2026-01-14 23:03:51 +09:00
parent f9a4ae105a
commit 2621942ced
2 changed files with 357 additions and 0 deletions

View File

@@ -117,6 +117,7 @@ class Skill {
required this.mpCost,
required this.cooldownMs,
required this.power,
this.tier = 1,
this.damageMultiplier = 1.0,
this.healAmount = 0,
this.healPercent = 0.0,
@@ -133,6 +134,9 @@ class Skill {
this.mpHealAmount = 0,
});
/// 스킬 티어 (1~5, 높을수록 강함)
final int tier;
/// 스킬 ID
final String id;
@@ -213,6 +217,79 @@ class Skill {
if (type != SkillType.attack || damageMultiplier <= 0) return 0;
return damageMultiplier / mpCost;
}
/// 스킬 파워 점수 (동적 계산, 같은 티어 내 비교용)
///
/// 타입별 다른 공식:
/// - 공격: DPS 기반
/// - 회복: HPS 기반
/// - 버프/디버프: 효과 강도 × 지속시간 / 쿨타임
double get powerScore {
final cdSec = cooldownMs / 1000;
if (cdSec <= 0) return 0;
return switch (type) {
SkillType.attack => _attackPowerScore(cdSec),
SkillType.heal => _healPowerScore(cdSec),
SkillType.buff => _buffPowerScore(cdSec),
SkillType.debuff => _debuffPowerScore(cdSec),
};
}
double _attackPowerScore(double cdSec) {
// DOT 스킬
if (isDot &&
baseDotDamage != null &&
baseDotDurationMs != null &&
baseDotTickMs != null &&
baseDotTickMs! > 0) {
final ticks = baseDotDurationMs! / baseDotTickMs!;
return (baseDotDamage! * ticks) / cdSec;
}
// 즉발 공격: power × 배율 × 타수 / 쿨타임
var score = power * damageMultiplier * hitCount / cdSec;
score *= (1 + lifestealPercent); // 흡혈 보너스
score *= (1 + targetDefReduction); // 방감 보너스
return score;
}
double _healPowerScore(double cdSec) {
// 고정 회복 + %회복(1000HP 기준) + MP회복
final totalHeal = healAmount + (healPercent * 1000) + mpHealAmount;
var score = totalHeal / cdSec;
if (buff != null) score *= 1.2; // 추가 버프 보너스
return score;
}
double _buffPowerScore(double cdSec) {
if (buff == null) return 0;
final b = buff!;
final strength =
b.atkModifier.abs() +
b.defModifier.abs() +
b.criRateModifier.abs() +
b.evasionModifier.abs();
return strength * (b.durationMs / 1000) / cdSec * 100;
}
double _debuffPowerScore(double cdSec) {
if (buff == null) return 0;
final b = buff!;
final strength = b.atkModifier.abs() + b.defModifier.abs();
return strength * (b.durationMs / 1000) / cdSec * 100;
}
/// 다른 스킬과 비교하여 이 스킬이 더 강한지 판단
///
/// 1. 티어가 다르면 티어로 판단
/// 2. 티어가 같으면 파워 점수로 판단
bool isStrongerThan(Skill other) {
if (tier != other.tier) {
return tier > other.tier;
}
return powerScore > other.powerScore;
}
}
/// 스킬 사용 상태 (쿨타임 추적)
@@ -347,6 +424,9 @@ enum SkillFailReason {
/// 쿨타임 중
onCooldown,
/// 글로벌 쿨타임(GCD) 중
onGlobalCooldown,
/// 스킬 없음
skillNotFound,