diff --git a/lib/src/core/engine/combat_tick_service.dart b/lib/src/core/engine/combat_tick_service.dart index 156a007..afbb5c3 100644 --- a/lib/src/core/engine/combat_tick_service.dart +++ b/lib/src/core/engine/combat_tick_service.dart @@ -265,79 +265,73 @@ class CombatTickService { return null; } - // 우선순위 1: HP 물약 (HP <= 30%) - final hpRatio = playerStats.hpCurrent / playerStats.hpMax; - if (hpRatio <= PotionService.emergencyHpThreshold) { - final hpPotion = potionService.selectEmergencyHpPotion( + // 우선순위 1: HP 물약 (소모된 HP >= 물약 회복량) + final hpPotion = potionService.selectEmergencyHpPotion( + currentHp: playerStats.hpCurrent, + maxHp: playerStats.hpMax, + inventory: potionInventory, + playerLevel: playerLevel, + ); + + if (hpPotion != null) { + final result = potionService.usePotion( + potionId: hpPotion.id, + inventory: potionInventory, currentHp: playerStats.hpCurrent, maxHp: playerStats.hpMax, - inventory: potionInventory, - playerLevel: playerLevel, + currentMp: playerStats.mpCurrent, + maxMp: playerStats.mpMax, ); - if (hpPotion != null) { - final result = potionService.usePotion( - potionId: hpPotion.id, - inventory: potionInventory, - currentHp: playerStats.hpCurrent, - maxHp: playerStats.hpMax, - currentMp: playerStats.mpCurrent, - maxMp: playerStats.mpMax, + if (result.success) { + return ( + playerStats: playerStats.copyWith(hpCurrent: result.newHp), + lastPotionUsedMs: timestamp, + potionInventory: result.newInventory!, + events: [ + CombatEvent.playerPotion( + timestamp: timestamp, + potionName: hpPotion.name, + healAmount: result.healedAmount, + isHp: true, + ), + ], ); - - if (result.success) { - return ( - playerStats: playerStats.copyWith(hpCurrent: result.newHp), - lastPotionUsedMs: timestamp, - potionInventory: result.newInventory!, - events: [ - CombatEvent.playerPotion( - timestamp: timestamp, - potionName: hpPotion.name, - healAmount: result.healedAmount, - isHp: true, - ), - ], - ); - } } } - // 우선순위 2: MP 물약 (MP <= 50%) - final mpRatio = playerStats.mpCurrent / playerStats.mpMax; - if (mpRatio <= PotionService.emergencyMpThreshold) { - final mpPotion = potionService.selectEmergencyMpPotion( + // 우선순위 2: MP 물약 (소모된 MP >= 물약 회복량) + final mpPotion = potionService.selectEmergencyMpPotion( + currentMp: playerStats.mpCurrent, + maxMp: playerStats.mpMax, + inventory: potionInventory, + playerLevel: playerLevel, + ); + + if (mpPotion != null) { + final result = potionService.usePotion( + potionId: mpPotion.id, + inventory: potionInventory, + currentHp: playerStats.hpCurrent, + maxHp: playerStats.hpMax, currentMp: playerStats.mpCurrent, maxMp: playerStats.mpMax, - inventory: potionInventory, - playerLevel: playerLevel, ); - if (mpPotion != null) { - final result = potionService.usePotion( - potionId: mpPotion.id, - inventory: potionInventory, - currentHp: playerStats.hpCurrent, - maxHp: playerStats.hpMax, - currentMp: playerStats.mpCurrent, - maxMp: playerStats.mpMax, + if (result.success) { + return ( + playerStats: playerStats.copyWith(mpCurrent: result.newMp), + lastPotionUsedMs: timestamp, + potionInventory: result.newInventory!, + events: [ + CombatEvent.playerPotion( + timestamp: timestamp, + potionName: mpPotion.name, + healAmount: result.healedAmount, + isHp: false, + ), + ], ); - - if (result.success) { - return ( - playerStats: playerStats.copyWith(mpCurrent: result.newMp), - lastPotionUsedMs: timestamp, - potionInventory: result.newInventory!, - events: [ - CombatEvent.playerPotion( - timestamp: timestamp, - potionName: mpPotion.name, - healAmount: result.healedAmount, - isHp: false, - ), - ], - ); - } } } diff --git a/lib/src/core/engine/potion_service.dart b/lib/src/core/engine/potion_service.dart index 119beb2..3069fb9 100644 --- a/lib/src/core/engine/potion_service.dart +++ b/lib/src/core/engine/potion_service.dart @@ -13,12 +13,6 @@ class PotionService { /// 글로벌 물약 쿨타임 (1배속 기준 3초) static const int globalPotionCooldownMs = 3000; - /// 긴급 물약 사용 HP 임계치 (30%) - static const double emergencyHpThreshold = 0.30; - - /// 긴급 물약 사용 MP 임계치 (50%) - static const double emergencyMpThreshold = 0.50; - // ============================================================================ // 물약 사용 가능 여부 // ============================================================================ @@ -104,7 +98,7 @@ class PotionService { /// 긴급 HP 물약 선택 /// - /// HP가 임계치 이하일 때 사용할 최적의 물약 선택 + /// 소모된 HP >= 물약 회복량이면 사용할 최적의 물약 선택 /// [currentHp] 현재 HP /// [maxHp] 최대 HP /// [inventory] 물약 인벤토리 @@ -115,9 +109,8 @@ class PotionService { required PotionInventory inventory, required int playerLevel, }) { - // 임계치 체크 - final hpRatio = currentHp / maxHp; - if (hpRatio > emergencyHpThreshold) return null; + final hpLost = maxHp - currentHp; + if (hpLost <= 0) return null; // 적정 티어 계산 final targetTier = PotionData.tierForLevel(playerLevel); @@ -126,7 +119,10 @@ class PotionService { for (var tier = targetTier; tier >= 1; tier--) { final potion = PotionData.getHpPotionByTier(tier); if (potion != null && inventory.hasPotion(potion.id)) { - return potion; + final healAmount = potion.calculateHeal(maxHp); + if (hpLost >= healAmount) { + return potion; + } } } @@ -134,7 +130,10 @@ class PotionService { for (var tier = targetTier + 1; tier <= 5; tier++) { final potion = PotionData.getHpPotionByTier(tier); if (potion != null && inventory.hasPotion(potion.id)) { - return potion; + final healAmount = potion.calculateHeal(maxHp); + if (hpLost >= healAmount) { + return potion; + } } } @@ -143,16 +142,15 @@ class PotionService { /// 긴급 MP 물약 선택 /// - /// MP가 임계치 이하일 때 사용할 최적의 물약 선택 + /// 소모된 MP >= 물약 회복량이면 사용할 최적의 물약 선택 Potion? selectEmergencyMpPotion({ required int currentMp, required int maxMp, required PotionInventory inventory, required int playerLevel, }) { - // 임계치 체크 - final mpRatio = currentMp / maxMp; - if (mpRatio > emergencyMpThreshold) return null; + final mpLost = maxMp - currentMp; + if (mpLost <= 0) return null; // 적정 티어 계산 final targetTier = PotionData.tierForLevel(playerLevel); @@ -161,7 +159,10 @@ class PotionService { for (var tier = targetTier; tier >= 1; tier--) { final potion = PotionData.getMpPotionByTier(tier); if (potion != null && inventory.hasPotion(potion.id)) { - return potion; + final healAmount = potion.calculateHeal(maxMp); + if (mpLost >= healAmount) { + return potion; + } } } @@ -169,7 +170,10 @@ class PotionService { for (var tier = targetTier + 1; tier <= 5; tier++) { final potion = PotionData.getMpPotionByTier(tier); if (potion != null && inventory.hasPotion(potion.id)) { - return potion; + final healAmount = potion.calculateHeal(maxMp); + if (mpLost >= healAmount) { + return potion; + } } }