diff --git a/lib/src/core/engine/potion_service.dart b/lib/src/core/engine/potion_service.dart index 7b8c6fd..8669d7b 100644 --- a/lib/src/core/engine/potion_service.dart +++ b/lib/src/core/engine/potion_service.dart @@ -1,4 +1,7 @@ +import 'dart:math' as math; + import 'package:asciineverdie/data/potion_data.dart'; +import 'package:asciineverdie/src/core/model/monster_grade.dart'; import 'package:asciineverdie/src/core/model/potion.dart'; /// 물약 서비스 @@ -357,19 +360,35 @@ class PotionService { /// /// 전투 승리 시 물약 드랍 여부 결정 및 물약 획득 /// [playerLevel] 플레이어 레벨 (드랍 확률 및 티어 결정) + /// [monsterLevel] 몬스터 레벨 (티어 결정에 영향) + /// [monsterGrade] 몬스터 등급 (드랍 확률 보너스) /// [inventory] 현재 물약 인벤토리 /// [roll] 0~99 범위의 난수 (드랍 확률 판정) /// [typeRoll] 0~99 범위의 난수 (HP/MP 결정) /// Returns: (업데이트된 인벤토리, 드랍된 물약 또는 null) (PotionInventory, Potion?) tryPotionDrop({ required int playerLevel, + required int monsterLevel, + required MonsterGrade monsterGrade, required PotionInventory inventory, required int roll, required int typeRoll, }) { - // 드랍 확률 계산 - final dropChance = (baseDropChance + playerLevel * dropChancePerLevel) + // 기본 드랍 확률 계산 + var dropChance = (baseDropChance + playerLevel * dropChancePerLevel) .clamp(baseDropChance, maxDropChance); + + // 몬스터 등급 보너스 (Elite +5%, Boss +15%) + dropChance += monsterGrade.potionDropBonus; + + // 몬스터 레벨 > 플레이어 레벨이면 추가 확률 (+1%/레벨 차이) + if (monsterLevel > playerLevel) { + dropChance += (monsterLevel - playerLevel) * 0.01; + } + + // 최대 확률 제한 (50%) + dropChance = dropChance.clamp(0.0, 0.5); + final dropThreshold = (dropChance * 100).round(); // 드랍 실패 @@ -380,8 +399,9 @@ class PotionService { // 물약 타입 결정 (60% HP, 40% MP) final isHpPotion = typeRoll < 60; - // 레벨 기반 티어 결정 - final tier = PotionData.tierForLevel(playerLevel); + // 티어 결정: max(플레이어 레벨, 몬스터 레벨) 기반 + final effectiveLevel = math.max(playerLevel, monsterLevel); + final tier = PotionData.tierForLevel(effectiveLevel); // 물약 선택 final Potion? potion; diff --git a/lib/src/core/engine/progress_service.dart b/lib/src/core/engine/progress_service.dart index 00047e6..d481ae1 100644 --- a/lib/src/core/engine/progress_service.dart +++ b/lib/src/core/engine/progress_service.dart @@ -14,6 +14,7 @@ import 'package:asciineverdie/src/core/model/equipment_item.dart'; import 'package:asciineverdie/src/core/model/equipment_slot.dart'; import 'package:asciineverdie/src/core/model/game_state.dart'; import 'package:asciineverdie/src/core/model/monster_combat_stats.dart'; +import 'package:asciineverdie/src/core/model/monster_grade.dart'; import 'package:asciineverdie/src/core/model/potion.dart'; import 'package:asciineverdie/src/core/model/pq_config.dart'; import 'package:asciineverdie/src/core/model/skill.dart'; @@ -591,6 +592,7 @@ class ProgressService { monsterBaseName: monsterResult.baseName, monsterPart: monsterResult.part, monsterLevel: monsterResult.level, + monsterGrade: monsterResult.grade, ), currentCombat: combatState, ); @@ -646,6 +648,7 @@ class ProgressService { monsterBaseName: 'Glitch God', monsterPart: '*', // 특수 전리품 monsterLevel: glitchGod.level, + monsterGrade: MonsterGrade.boss, // 최종 보스는 항상 boss 등급 ), currentCombat: combatState, ); @@ -963,8 +966,12 @@ class ProgressService { // 물약 드랍 시도 final potionService = const PotionService(); final rng = resultState.rng; + final monsterLevel = taskInfo.monsterLevel ?? resultState.traits.level; + final monsterGrade = taskInfo.monsterGrade ?? MonsterGrade.normal; final (updatedPotionInventory, droppedPotion) = potionService.tryPotionDrop( playerLevel: resultState.traits.level, + monsterLevel: monsterLevel, + monsterGrade: monsterGrade, inventory: resultState.potionInventory, roll: rng.nextInt(100), typeRoll: rng.nextInt(100),