feat(skill): Phase 3 MP 기반 스킬 시스템 구현

- Skill, SkillType, BuffEffect, SkillState, SkillUseResult 클래스 정의 (skill.dart)
- SkillSystemState를 GameState에 통합 (activeBuffs, skillStates, elapsedMs)
- 프로그래밍 테마 스킬 데이터 정의 (skill_data.dart)
  - 공격: Debug Strike, Memory Leak, Core Dump, Kernel Panic 등
  - 회복: Hot Reload, Garbage Collection, Quick Fix
  - 버프: Safe Mode, Overclock, Firewall
- SkillService 구현 (skill_service.dart)
  - 스킬 사용 가능 여부 확인 (MP, 쿨타임)
  - 공격/회복/버프 스킬 사용 로직
  - 자동 스킬 선택 (HP < 30% → 회복, 보스전 → 강력한 공격, 일반 → MP 효율)
  - MP 자연 회복 (비전투: 50ms당 1, 전투: WIS 기반)
- progress_service.dart에 스킬 시스템 통합
  - tick()에서 스킬 시간 업데이트 및 버프 만료 처리
  - _processCombatTickWithSkills()로 전투 중 자동 스킬 사용
This commit is contained in:
JiWoong Sul
2025-12-17 17:05:48 +09:00
parent 6a696ecd57
commit 517bf54a56
5 changed files with 1041 additions and 22 deletions

View File

@@ -4,6 +4,7 @@ import 'package:askiineverdie/src/core/model/combat_state.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/item_stats.dart';
import 'package:askiineverdie/src/core/model/skill.dart';
import 'package:askiineverdie/src/core/util/deterministic_random.dart';
/// Minimal skeletal state to mirror Progress Quest structures.
@@ -20,6 +21,7 @@ class GameState {
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
}) : rng = DeterministicRandom.clone(rng),
traits = traits ?? Traits.empty(),
stats = stats ?? Stats.empty(),
@@ -27,7 +29,8 @@ class GameState {
equipment = equipment ?? Equipment.empty(),
spellBook = spellBook ?? SpellBook.empty(),
progress = progress ?? ProgressState.empty(),
queue = queue ?? QueueState.empty();
queue = queue ?? QueueState.empty(),
skillSystem = skillSystem ?? SkillSystemState.empty();
factory GameState.withSeed({
required int seed,
@@ -38,6 +41,7 @@ class GameState {
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
}) {
return GameState(
rng: DeterministicRandom(seed),
@@ -48,6 +52,7 @@ class GameState {
spellBook: spellBook,
progress: progress,
queue: queue,
skillSystem: skillSystem,
);
}
@@ -60,6 +65,9 @@ class GameState {
final ProgressState progress;
final QueueState queue;
/// 스킬 시스템 상태 (Phase 3)
final SkillSystemState skillSystem;
GameState copyWith({
DeterministicRandom? rng,
Traits? traits,
@@ -69,6 +77,7 @@ class GameState {
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
}) {
return GameState(
rng: rng ?? DeterministicRandom.clone(this.rng),
@@ -79,6 +88,76 @@ class GameState {
spellBook: spellBook ?? this.spellBook,
progress: progress ?? this.progress,
queue: queue ?? this.queue,
skillSystem: skillSystem ?? this.skillSystem,
);
}
}
/// 스킬 시스템 상태 (Phase 3)
///
/// 스킬 쿨타임, 활성 버프, 게임 경과 시간 등을 관리
class SkillSystemState {
const SkillSystemState({
required this.skillStates,
required this.activeBuffs,
required this.elapsedMs,
});
/// 스킬별 쿨타임 상태
final List<SkillState> skillStates;
/// 현재 활성화된 버프 목록
final List<ActiveBuff> activeBuffs;
/// 게임 진행 경과 시간 (밀리초, 스킬 쿨타임 계산용)
final int elapsedMs;
factory SkillSystemState.empty() => const SkillSystemState(
skillStates: [],
activeBuffs: [],
elapsedMs: 0,
);
/// 특정 스킬 상태 가져오기
SkillState? getSkillState(String skillId) {
for (final state in skillStates) {
if (state.skillId == skillId) return state;
}
return null;
}
/// 버프 효과 합산 (동일 버프는 중복 적용 안 됨)
({double atkMod, double defMod, double criMod, double evasionMod}) get totalBuffModifiers {
double atkMod = 0;
double defMod = 0;
double criMod = 0;
double evasionMod = 0;
final seenBuffIds = <String>{};
for (final buff in activeBuffs) {
if (seenBuffIds.contains(buff.effect.id)) continue;
seenBuffIds.add(buff.effect.id);
if (!buff.isExpired(elapsedMs)) {
atkMod += buff.effect.atkModifier;
defMod += buff.effect.defModifier;
criMod += buff.effect.criRateModifier;
evasionMod += buff.effect.evasionModifier;
}
}
return (atkMod: atkMod, defMod: defMod, criMod: criMod, evasionMod: evasionMod);
}
SkillSystemState copyWith({
List<SkillState>? skillStates,
List<ActiveBuff>? activeBuffs,
int? elapsedMs,
}) {
return SkillSystemState(
skillStates: skillStates ?? this.skillStates,
activeBuffs: activeBuffs ?? this.activeBuffs,
elapsedMs: elapsedMs ?? this.elapsedMs,
);
}
}