feat(core): 엔진, 모델, 애니메이션 개선

- ProgressService 로직 개선
- CombatCalculator 업데이트
- GameState, MonsterCombatStats 확장
- CanvasBattleComposer 개선
This commit is contained in:
JiWoong Sul
2026-01-14 00:17:59 +09:00
parent 4e9265ab87
commit f89017e5ba
5 changed files with 101 additions and 36 deletions

View File

@@ -475,7 +475,8 @@ class Inventory {
final int gold;
final List<InventoryEntry> items;
factory Inventory.empty() => const Inventory(gold: 0, items: []);
/// 초기 골드 1000 지급 (캐릭터 생성 시)
factory Inventory.empty() => const Inventory(gold: 1000, items: []);
Inventory copyWith({int? gold, List<InventoryEntry>? items}) {
return Inventory(gold: gold ?? this.gold, items: items ?? this.items);
@@ -800,6 +801,7 @@ class ProgressState {
this.deathCount = 0,
this.finalBossState = FinalBossState.notSpawned,
this.pendingActCompletion = false,
this.bossLevelingEndTime,
});
final ProgressBarState task;
@@ -835,6 +837,10 @@ class ProgressState {
/// Act Boss 처치 대기 중 여부 (처치 후 시네마틱 재생 트리거)
final bool pendingActCompletion;
/// 보스 사망 후 레벨링 모드 종료 시간 (milliseconds since epoch)
/// null이면 레벨링 모드 아님, 값이 있으면 해당 시간까지 레벨링
final int? bossLevelingEndTime;
factory ProgressState.empty() => ProgressState(
task: ProgressBarState.empty(),
quest: ProgressBarState.empty(),
@@ -867,6 +873,8 @@ class ProgressState {
int? deathCount,
FinalBossState? finalBossState,
bool? pendingActCompletion,
int? bossLevelingEndTime,
bool clearBossLevelingEndTime = false,
}) {
return ProgressState(
task: task ?? this.task,
@@ -885,8 +893,17 @@ class ProgressState {
deathCount: deathCount ?? this.deathCount,
finalBossState: finalBossState ?? this.finalBossState,
pendingActCompletion: pendingActCompletion ?? this.pendingActCompletion,
bossLevelingEndTime: clearBossLevelingEndTime
? null
: (bossLevelingEndTime ?? this.bossLevelingEndTime),
);
}
/// 현재 레벨링 모드인지 확인
bool get isInBossLevelingMode {
if (bossLevelingEndTime == null) return false;
return DateTime.now().millisecondsSinceEpoch < bossLevelingEndTime!;
}
}
class QueueEntry {

View File

@@ -131,15 +131,29 @@ class MonsterCombatStats {
/// [level] 몬스터 레벨 (원본 데이터 기준)
/// [speedType] 공격 속도 타입 (기본: normal)
/// [monsterType] 몬스터 타입 (기본: normal)
/// [plotStageCount] 현재 Act (1=Prologue, 2=Act I, 3=Act II, ...)
factory MonsterCombatStats.fromLevel({
required String name,
required int level,
MonsterSpeedType speedType = MonsterSpeedType.normal,
MonsterType monsterType = MonsterType.normal,
int plotStageCount = 1,
}) {
// balance_constants.dart의 MonsterBaseStats 사용
final baseStats = MonsterBaseStats.generate(level, monsterType);
// Act II 이후 (plotStageCount >= 3) HP 10% 상승
final hpMultiplier = plotStageCount >= 3 ? 1.1 : 1.0;
final adjustedHp = (baseStats.hp * hpMultiplier).round();
// Act별 경험치 배율 (후반부 레벨업 가속)
final expMultiplier = switch (plotStageCount) {
5 => 1.3, // Act IV: 30% 보너스
6 => 1.8, // Act V: 80% 보너스 (보스전 대비)
_ => 1.0, // 기본
};
final adjustedExp = (baseStats.exp * expMultiplier).round();
// 크리티컬 확률: 레벨에 따라 천천히 증가 (0.02 ~ 0.3)
final criRate = (0.02 + level * 0.003).clamp(0.02, 0.3);
@@ -164,14 +178,14 @@ class MonsterCombatStats {
level: level,
atk: baseStats.atk,
def: baseStats.def,
hpMax: baseStats.hp,
hpCurrent: baseStats.hp,
hpMax: adjustedHp,
hpCurrent: adjustedHp,
criRate: criRate,
criDamage: criDamage,
evasion: evasion,
accuracy: accuracy,
attackDelayMs: attackDelayMs,
expReward: baseStats.exp,
expReward: adjustedExp,
);
}