refactor(potion): 물약 자동 사용 조건 변경
- 임계치 기반 → 소모량 기반 조건 전환 - HP/MP 소모량 >= 물약 회복량일 때 사용 - emergencyHpThreshold, emergencyMpThreshold 상수 제거 - 우선순위 HP > MP 유지
This commit is contained in:
@@ -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,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user