feat(game): 포션 시스템 및 UI 패널 추가
- 포션 시스템 구현 (PotionService, Potion 모델) - 포션 인벤토리 패널 위젯 - 활성 버프 패널 위젯 - 장비 스탯 패널 위젯 - 스킬 시스템 확장 - 일본어 번역 추가 - 전투 이벤트/상태 모델 개선
This commit is contained in:
136
lib/src/core/model/potion.dart
Normal file
136
lib/src/core/model/potion.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
/// 물약 종류
|
||||
enum PotionType {
|
||||
/// HP 회복 물약
|
||||
hp,
|
||||
|
||||
/// MP 회복 물약
|
||||
mp,
|
||||
}
|
||||
|
||||
/// 물약 아이템
|
||||
///
|
||||
/// 전투 중 사용 가능한 소모품.
|
||||
/// 전투당 종류별 1회만 사용 가능.
|
||||
class Potion {
|
||||
const Potion({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.type,
|
||||
required this.tier,
|
||||
this.healAmount = 0,
|
||||
this.healPercent = 0.0,
|
||||
this.price = 0,
|
||||
});
|
||||
|
||||
/// 물약 ID
|
||||
final String id;
|
||||
|
||||
/// 물약 이름
|
||||
final String name;
|
||||
|
||||
/// 물약 종류 (hp / mp)
|
||||
final PotionType type;
|
||||
|
||||
/// 물약 티어 (1~5, 높을수록 강력)
|
||||
final int tier;
|
||||
|
||||
/// 고정 회복량
|
||||
final int healAmount;
|
||||
|
||||
/// 비율 회복량 (0.0 ~ 1.0)
|
||||
final double healPercent;
|
||||
|
||||
/// 구매 가격 (골드)
|
||||
final int price;
|
||||
|
||||
/// HP 물약 여부
|
||||
bool get isHpPotion => type == PotionType.hp;
|
||||
|
||||
/// MP 물약 여부
|
||||
bool get isMpPotion => type == PotionType.mp;
|
||||
|
||||
/// 실제 회복량 계산
|
||||
///
|
||||
/// [maxValue] 최대 HP 또는 MP
|
||||
int calculateHeal(int maxValue) {
|
||||
final percentHeal = (maxValue * healPercent).round();
|
||||
return healAmount + percentHeal;
|
||||
}
|
||||
}
|
||||
|
||||
/// 물약 인벤토리 상태
|
||||
///
|
||||
/// 보유 물약 수량 및 전투 중 사용 기록 관리
|
||||
class PotionInventory {
|
||||
const PotionInventory({
|
||||
this.potions = const {},
|
||||
this.usedInBattle = const {},
|
||||
});
|
||||
|
||||
/// 보유 물약 (물약 ID → 수량)
|
||||
final Map<String, int> potions;
|
||||
|
||||
/// 현재 전투에서 사용한 물약 종류
|
||||
final Set<PotionType> usedInBattle;
|
||||
|
||||
/// 물약 보유 여부
|
||||
bool hasPotion(String potionId) => (potions[potionId] ?? 0) > 0;
|
||||
|
||||
/// 물약 수량 조회
|
||||
int getQuantity(String potionId) => potions[potionId] ?? 0;
|
||||
|
||||
/// 특정 종류 물약 사용 가능 여부
|
||||
///
|
||||
/// 전투당 종류별 1회 제한 체크
|
||||
bool canUseType(PotionType type) => !usedInBattle.contains(type);
|
||||
|
||||
/// 물약 추가
|
||||
PotionInventory addPotion(String potionId, [int count = 1]) {
|
||||
final newPotions = Map<String, int>.from(potions);
|
||||
newPotions[potionId] = (newPotions[potionId] ?? 0) + count;
|
||||
return PotionInventory(
|
||||
potions: newPotions,
|
||||
usedInBattle: usedInBattle,
|
||||
);
|
||||
}
|
||||
|
||||
/// 물약 사용 (수량 감소)
|
||||
PotionInventory usePotion(String potionId, PotionType type) {
|
||||
final currentQty = potions[potionId] ?? 0;
|
||||
if (currentQty <= 0) return this;
|
||||
|
||||
final newPotions = Map<String, int>.from(potions);
|
||||
newPotions[potionId] = currentQty - 1;
|
||||
if (newPotions[potionId] == 0) {
|
||||
newPotions.remove(potionId);
|
||||
}
|
||||
|
||||
final newUsed = Set<PotionType>.from(usedInBattle)..add(type);
|
||||
|
||||
return PotionInventory(
|
||||
potions: newPotions,
|
||||
usedInBattle: newUsed,
|
||||
);
|
||||
}
|
||||
|
||||
/// 전투 종료 시 사용 기록 초기화
|
||||
PotionInventory resetBattleUsage() {
|
||||
return PotionInventory(
|
||||
potions: potions,
|
||||
usedInBattle: const {},
|
||||
);
|
||||
}
|
||||
|
||||
/// 빈 인벤토리
|
||||
static const empty = PotionInventory();
|
||||
|
||||
PotionInventory copyWith({
|
||||
Map<String, int>? potions,
|
||||
Set<PotionType>? usedInBattle,
|
||||
}) {
|
||||
return PotionInventory(
|
||||
potions: potions ?? this.potions,
|
||||
usedInBattle: usedInBattle ?? this.usedInBattle,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user