refactor(engine): 포션/진행 서비스 개선

- PotionService 로직 개선
- ProgressService 몬스터 등급 지원
This commit is contained in:
JiWoong Sul
2026-01-05 17:52:57 +09:00
parent 4688aff56b
commit 7570a4205c
2 changed files with 31 additions and 4 deletions

View File

@@ -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;

View File

@@ -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),