feat(game): 포션 시스템 및 UI 패널 추가
- 포션 시스템 구현 (PotionService, Potion 모델) - 포션 인벤토리 패널 위젯 - 활성 버프 패널 위젯 - 장비 스탯 패널 위젯 - 스킬 시스템 확장 - 일본어 번역 추가 - 전투 이벤트/상태 모델 개선
This commit is contained in:
@@ -181,6 +181,60 @@ class SkillService {
|
||||
);
|
||||
}
|
||||
|
||||
/// DOT 스킬 사용
|
||||
///
|
||||
/// DOT 효과를 생성하여 반환. 호출자가 전투 상태의 activeDoTs에 추가해야 함.
|
||||
/// INT → 틱당 데미지 보정, WIS → 틱 간격 보정
|
||||
({
|
||||
SkillUseResult result,
|
||||
CombatStats updatedPlayer,
|
||||
SkillSystemState updatedSkillSystem,
|
||||
DotEffect? dotEffect,
|
||||
}) useDotSkill({
|
||||
required Skill skill,
|
||||
required CombatStats player,
|
||||
required SkillSystemState skillSystem,
|
||||
required int playerInt,
|
||||
required int playerWis,
|
||||
}) {
|
||||
if (!skill.isDot) {
|
||||
return (
|
||||
result: SkillUseResult.failed(skill, SkillFailReason.invalidState),
|
||||
updatedPlayer: player,
|
||||
updatedSkillSystem: skillSystem,
|
||||
dotEffect: null,
|
||||
);
|
||||
}
|
||||
|
||||
// DOT 효과 생성 (INT/WIS 보정 적용)
|
||||
final dotEffect = DotEffect.fromSkill(
|
||||
skill,
|
||||
playerInt: playerInt,
|
||||
playerWis: playerWis,
|
||||
);
|
||||
|
||||
// MP 소모
|
||||
var updatedPlayer = player.withMp(player.mpCurrent - skill.mpCost);
|
||||
|
||||
// 스킬 상태 업데이트 (쿨타임 시작)
|
||||
final updatedSkillSystem = _updateSkillCooldown(skillSystem, skill.id);
|
||||
|
||||
// 예상 총 데미지 계산 (틱 수 × 틱당 데미지)
|
||||
final expectedTicks = dotEffect.totalDurationMs ~/ dotEffect.tickIntervalMs;
|
||||
final expectedDamage = expectedTicks * dotEffect.damagePerTick;
|
||||
|
||||
return (
|
||||
result: SkillUseResult(
|
||||
skill: skill,
|
||||
success: true,
|
||||
damage: expectedDamage,
|
||||
),
|
||||
updatedPlayer: updatedPlayer,
|
||||
updatedSkillSystem: updatedSkillSystem,
|
||||
dotEffect: dotEffect,
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 자동 스킬 선택
|
||||
// ============================================================================
|
||||
@@ -189,14 +243,16 @@ class SkillService {
|
||||
///
|
||||
/// 우선순위:
|
||||
/// 1. HP < 30% → 회복 스킬
|
||||
/// 2. 보스전 (레벨 차이 10 이상) → 가장 강력한 공격 스킬
|
||||
/// 3. 일반 전투 → MP 효율이 좋은 스킬
|
||||
/// 4. MP < 20% → null (일반 공격)
|
||||
/// 2. 몬스터 HP > 50% & DOT 없음 → DOT 스킬 (장기전 유리)
|
||||
/// 3. 보스전 (레벨 차이 10 이상) → 가장 강력한 공격 스킬
|
||||
/// 4. 일반 전투 → MP 효율이 좋은 스킬
|
||||
/// 5. MP < 20% → null (일반 공격)
|
||||
Skill? selectAutoSkill({
|
||||
required CombatStats player,
|
||||
required MonsterCombatStats monster,
|
||||
required SkillSystemState skillSystem,
|
||||
required List<String> availableSkillIds,
|
||||
List<DotEffect> activeDoTs = const [],
|
||||
}) {
|
||||
final currentMp = player.mpCurrent;
|
||||
final mpRatio = player.mpRatio;
|
||||
@@ -225,6 +281,12 @@ class SkillService {
|
||||
if (healSkill != null) return healSkill;
|
||||
}
|
||||
|
||||
// 몬스터 HP > 50% & 활성 DOT 없음 → DOT 스킬 사용
|
||||
if (monster.hpRatio > 0.5 && activeDoTs.isEmpty) {
|
||||
final dotSkill = _findBestDotSkill(availableSkills, currentMp);
|
||||
if (dotSkill != null) return dotSkill;
|
||||
}
|
||||
|
||||
// 보스전 판단 (몬스터 레벨이 높음)
|
||||
final isBossFight = monster.level >= 10 && monster.hpRatio > 0.5;
|
||||
|
||||
@@ -237,6 +299,28 @@ class SkillService {
|
||||
return _findEfficientAttackSkill(availableSkills);
|
||||
}
|
||||
|
||||
/// 가장 좋은 DOT 스킬 찾기
|
||||
///
|
||||
/// 예상 총 데미지 (틱 × 데미지) 기준으로 선택
|
||||
Skill? _findBestDotSkill(List<Skill> skills, int currentMp) {
|
||||
final dotSkills = skills
|
||||
.where((s) => s.isDot && s.mpCost <= currentMp)
|
||||
.toList();
|
||||
|
||||
if (dotSkills.isEmpty) return null;
|
||||
|
||||
// 예상 총 데미지 기준 정렬
|
||||
dotSkills.sort((a, b) {
|
||||
final aTotal = (a.baseDotDamage ?? 0) *
|
||||
((a.baseDotDurationMs ?? 0) ~/ (a.baseDotTickMs ?? 1000));
|
||||
final bTotal = (b.baseDotDamage ?? 0) *
|
||||
((b.baseDotDurationMs ?? 0) ~/ (b.baseDotTickMs ?? 1000));
|
||||
return bTotal.compareTo(aTotal);
|
||||
});
|
||||
|
||||
return dotSkills.first;
|
||||
}
|
||||
|
||||
/// 가장 좋은 회복 스킬 찾기
|
||||
Skill? _findBestHealSkill(List<Skill> skills, int currentMp) {
|
||||
final healSkills = skills
|
||||
|
||||
Reference in New Issue
Block a user