feat(death): Phase 4 사망/부활 시스템 구현

- DeathInfo, DeathCause 클래스 정의 (game_state.dart)
  - 사망 원인, 상실 장비 수, 사망 시점 정보 기록
- ShopService 구현 (shop_service.dart)
  - 장비 가격 계산 (레벨 * 50 * 희귀도 배율)
  - 슬롯별 장비 생성 (프로그래밍 테마)
  - 자동 구매 (빈 슬롯에 Common 장비)
- ResurrectionService 구현 (resurrection_service.dart)
  - 사망 처리: 모든 장비 상실, 기본 무기만 유지
  - 부활 처리: HP/MP 회복, 자동 장비 구매
- progress_service.dart 사망 판정 로직 추가
  - 전투 중 HP <= 0 시 사망 처리
  - ProgressTickResult에 playerDied 플래그 추가
- progress_loop.dart 사망 시 루프 정지
  - onPlayerDied 콜백 추가
  - 사망 상태에서 틱 진행 방지
- DeathOverlay 위젯 구현 (death_overlay.dart)
  - ASCII 스컬 아트, 사망 원인, 상실 정보 표시
  - 부활 버튼
- GameSessionController 사망/부활 상태 관리
  - GameSessionStatus.dead 상태 추가
  - resurrect() 메서드로 부활 처리
This commit is contained in:
JiWoong Sul
2025-12-17 17:15:22 +09:00
parent 517bf54a56
commit 21bf057cfc
7 changed files with 974 additions and 3 deletions

View File

@@ -8,6 +8,8 @@ import 'package:askiineverdie/src/core/engine/reward_service.dart';
import 'package:askiineverdie/src/core/engine/skill_service.dart';
import 'package:askiineverdie/src/core/model/combat_state.dart';
import 'package:askiineverdie/src/core/model/combat_stats.dart';
import 'package:askiineverdie/src/core/model/equipment_item.dart';
import 'package:askiineverdie/src/core/model/equipment_slot.dart';
import 'package:askiineverdie/src/core/model/game_state.dart';
import 'package:askiineverdie/src/core/model/monster_combat_stats.dart';
import 'package:askiineverdie/src/core/model/pq_config.dart';
@@ -19,6 +21,7 @@ class ProgressTickResult {
this.leveledUp = false,
this.completedQuest = false,
this.completedAct = false,
this.playerDied = false,
});
final GameState state;
@@ -26,7 +29,11 @@ class ProgressTickResult {
final bool completedQuest;
final bool completedAct;
bool get shouldAutosave => leveledUp || completedQuest || completedAct;
/// 플레이어 사망 여부 (Phase 4)
final bool playerDied;
bool get shouldAutosave =>
leveledUp || completedQuest || completedAct || playerDied;
}
/// Drives quest/plot/task progression by applying queued actions and rewards.
@@ -190,6 +197,17 @@ class ProgressService {
);
updatedCombat = combatResult.combat;
updatedSkillSystem = combatResult.skillSystem;
// Phase 4: 플레이어 사망 체크
if (!updatedCombat.playerStats.isAlive) {
final monsterName = updatedCombat.monsterStats.name;
nextState = _processPlayerDeath(
nextState,
killerName: monsterName,
cause: DeathCause.monster,
);
return ProgressTickResult(state: nextState, playerDied: true);
}
}
progress = progress.copyWith(
@@ -947,4 +965,55 @@ class ProgressService {
skillSystem: updatedSkillSystem,
);
}
/// 플레이어 사망 처리 (Phase 4)
///
/// 모든 장비 상실 및 사망 정보 기록
GameState _processPlayerDeath(
GameState state, {
required String killerName,
required DeathCause cause,
}) {
// 상실할 장비 개수 계산
final lostCount = state.equipment.equippedItems.length;
// 빈 장비 생성 (기본 무기만 유지)
final emptyEquipment = Equipment(
items: [
EquipmentItem.defaultWeapon(),
EquipmentItem.empty(EquipmentSlot.shield),
EquipmentItem.empty(EquipmentSlot.helm),
EquipmentItem.empty(EquipmentSlot.hauberk),
EquipmentItem.empty(EquipmentSlot.brassairts),
EquipmentItem.empty(EquipmentSlot.vambraces),
EquipmentItem.empty(EquipmentSlot.gauntlets),
EquipmentItem.empty(EquipmentSlot.gambeson),
EquipmentItem.empty(EquipmentSlot.cuisses),
EquipmentItem.empty(EquipmentSlot.greaves),
EquipmentItem.empty(EquipmentSlot.sollerets),
],
bestIndex: 0,
);
// 사망 정보 생성
final deathInfo = DeathInfo(
cause: cause,
killerName: killerName,
lostEquipmentCount: lostCount,
goldAtDeath: state.inventory.gold,
levelAtDeath: state.traits.level,
timestamp: state.skillSystem.elapsedMs,
);
// 전투 상태 초기화
final progress = state.progress.copyWith(
currentCombat: null,
);
return state.copyWith(
equipment: emptyEquipment,
progress: progress,
deathInfo: deathInfo,
);
}
}