feat(combat): 디버프 시스템 추가
- CombatEventType.playerDebuff 추가 - CombatState에 activeDebuffs 목록 추가 - SkillService.useDebuffSkill() 구현 - 스킬 자동 선택에 디버프 우선순위 추가 - 밸런스 상수 업데이트
This commit is contained in:
@@ -185,6 +185,56 @@ class SkillService {
|
||||
);
|
||||
}
|
||||
|
||||
/// 디버프 스킬 사용
|
||||
///
|
||||
/// 디버프 효과를 생성하여 반환. 호출자가 CombatState.activeDebuffs에 추가해야 함.
|
||||
/// 디버프는 몬스터의 ATK/DEF를 감소시킴.
|
||||
({
|
||||
SkillUseResult result,
|
||||
CombatStats updatedPlayer,
|
||||
SkillSystemState updatedSkillSystem,
|
||||
ActiveBuff? debuffEffect,
|
||||
})
|
||||
useDebuffSkill({
|
||||
required Skill skill,
|
||||
required CombatStats player,
|
||||
required SkillSystemState skillSystem,
|
||||
required List<ActiveBuff> currentDebuffs,
|
||||
}) {
|
||||
if (skill.buff == null) {
|
||||
return (
|
||||
result: SkillUseResult.failed(skill, SkillFailReason.invalidState),
|
||||
updatedPlayer: player,
|
||||
updatedSkillSystem: skillSystem,
|
||||
debuffEffect: null,
|
||||
);
|
||||
}
|
||||
|
||||
// 디버프 효과 생성
|
||||
final newDebuff = ActiveBuff(
|
||||
effect: skill.buff!,
|
||||
startedMs: skillSystem.elapsedMs,
|
||||
sourceSkillId: skill.id,
|
||||
);
|
||||
|
||||
// MP 소모
|
||||
var updatedPlayer = player.withMp(player.mpCurrent - skill.mpCost);
|
||||
|
||||
// 스킬 상태 업데이트 (쿨타임 시작)
|
||||
final updatedSkillSystem = _updateSkillCooldown(skillSystem, skill.id);
|
||||
|
||||
return (
|
||||
result: SkillUseResult(
|
||||
skill: skill,
|
||||
success: true,
|
||||
appliedBuff: newDebuff,
|
||||
),
|
||||
updatedPlayer: updatedPlayer,
|
||||
updatedSkillSystem: updatedSkillSystem,
|
||||
debuffEffect: newDebuff,
|
||||
);
|
||||
}
|
||||
|
||||
/// DOT 스킬 사용
|
||||
///
|
||||
/// DOT 효과를 생성하여 반환. 호출자가 전투 상태의 activeDoTs에 추가해야 함.
|
||||
@@ -248,16 +298,19 @@ class SkillService {
|
||||
///
|
||||
/// 우선순위:
|
||||
/// 1. HP < 30% → 회복 스킬
|
||||
/// 2. 몬스터 HP > 50% & DOT 없음 → DOT 스킬 (장기전 유리)
|
||||
/// 3. 보스전 (레벨 차이 10 이상) → 가장 강력한 공격 스킬
|
||||
/// 4. 일반 전투 → MP 효율이 좋은 스킬
|
||||
/// 5. MP < 20% → null (일반 공격)
|
||||
/// 2. HP > 70% & MP > 50% → 버프 스킬 (안전할 때)
|
||||
/// 3. 몬스터 HP > 70% & 활성 디버프 없음 → 디버프 스킬
|
||||
/// 4. 몬스터 HP > 50% & DOT 없음 → DOT 스킬 (장기전 유리)
|
||||
/// 5. 보스전 (레벨 차이 10 이상) → 가장 강력한 공격 스킬
|
||||
/// 6. 일반 전투 → MP 효율이 좋은 스킬
|
||||
/// 7. MP < 20% → null (일반 공격)
|
||||
Skill? selectAutoSkill({
|
||||
required CombatStats player,
|
||||
required MonsterCombatStats monster,
|
||||
required SkillSystemState skillSystem,
|
||||
required List<String> availableSkillIds,
|
||||
List<DotEffect> activeDoTs = const [],
|
||||
List<ActiveBuff> activeDebuffs = const [],
|
||||
}) {
|
||||
final currentMp = player.mpCurrent;
|
||||
final mpRatio = player.mpRatio;
|
||||
@@ -289,6 +342,18 @@ class SkillService {
|
||||
if (healSkill != null) return healSkill;
|
||||
}
|
||||
|
||||
// HP > 70% & MP > 50% → 버프 스킬 (안전할 때)
|
||||
if (hpRatio > 0.7 && mpRatio > 0.5) {
|
||||
final buffSkill = _findBestBuffSkill(availableSkills, currentMp);
|
||||
if (buffSkill != null) return buffSkill;
|
||||
}
|
||||
|
||||
// 몬스터 HP > 70% & 활성 디버프 없음 → 디버프 스킬
|
||||
if (monster.hpRatio > 0.7 && activeDebuffs.isEmpty) {
|
||||
final debuffSkill = _findBestDebuffSkill(availableSkills, currentMp);
|
||||
if (debuffSkill != null) return debuffSkill;
|
||||
}
|
||||
|
||||
// 몬스터 HP > 50% & 활성 DOT 없음 → DOT 스킬 사용
|
||||
if (monster.hpRatio > 0.5 && activeDoTs.isEmpty) {
|
||||
final dotSkill = _findBestDotSkill(availableSkills, currentMp);
|
||||
@@ -369,6 +434,52 @@ class SkillService {
|
||||
return attackSkills.first;
|
||||
}
|
||||
|
||||
/// 가장 좋은 버프 스킬 찾기
|
||||
///
|
||||
/// ATK 증가 버프 우선, 그 다음 복합 버프
|
||||
Skill? _findBestBuffSkill(List<Skill> skills, int currentMp) {
|
||||
final buffSkills = skills
|
||||
.where((s) => s.isBuff && s.mpCost <= currentMp && s.buff != null)
|
||||
.toList();
|
||||
|
||||
if (buffSkills.isEmpty) return null;
|
||||
|
||||
// ATK 증가량 기준 정렬
|
||||
buffSkills.sort((a, b) {
|
||||
final aValue = (a.buff?.atkModifier ?? 0) +
|
||||
(a.buff?.defModifier ?? 0) * 0.5 +
|
||||
(a.buff?.criRateModifier ?? 0) * 0.3;
|
||||
final bValue = (b.buff?.atkModifier ?? 0) +
|
||||
(b.buff?.defModifier ?? 0) * 0.5 +
|
||||
(b.buff?.criRateModifier ?? 0) * 0.3;
|
||||
return bValue.compareTo(aValue);
|
||||
});
|
||||
|
||||
return buffSkills.first;
|
||||
}
|
||||
|
||||
/// 가장 좋은 디버프 스킬 찾기
|
||||
///
|
||||
/// 적 ATK 감소 디버프 우선
|
||||
Skill? _findBestDebuffSkill(List<Skill> skills, int currentMp) {
|
||||
final debuffSkills = skills
|
||||
.where((s) => s.isDebuff && s.mpCost <= currentMp && s.buff != null)
|
||||
.toList();
|
||||
|
||||
if (debuffSkills.isEmpty) return null;
|
||||
|
||||
// 디버프 효과 크기 기준 정렬 (음수 값이므로 절대값으로 비교)
|
||||
debuffSkills.sort((a, b) {
|
||||
final aValue = (a.buff?.atkModifier ?? 0).abs() +
|
||||
(a.buff?.defModifier ?? 0).abs() * 0.5;
|
||||
final bValue = (b.buff?.atkModifier ?? 0).abs() +
|
||||
(b.buff?.defModifier ?? 0).abs() * 0.5;
|
||||
return bValue.compareTo(aValue);
|
||||
});
|
||||
|
||||
return debuffSkills.first;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// MP 회복
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user