refactor(model): SpellBook을 SkillBook으로 리네이밍

- 게임 컨셉에 맞게 주문서 → 스킬북 용어 통일
- 관련 모든 참조 일괄 변경
This commit is contained in:
JiWoong Sul
2026-01-06 18:45:16 +09:00
parent afc3c18ae4
commit 8d51263b2e
14 changed files with 114 additions and 114 deletions

View File

@@ -29,16 +29,16 @@ class ArenaService {
// 스킬 시스템 헬퍼
// ============================================================================
/// HallOfFameEntry의 finalSpells에서 Skill 목록 추출
/// HallOfFameEntry의 finalSkills에서 Skill 목록 추출
List<Skill> _getSkillsFromEntry(HallOfFameEntry entry) {
final spells = entry.finalSpells;
if (spells == null || spells.isEmpty) return [];
final skillData = entry.finalSkills;
if (skillData == null || skillData.isEmpty) return [];
final skills = <Skill>[];
for (final spell in spells) {
final spellName = spell['name'];
if (spellName != null) {
final skill = SkillData.getSkillBySpellName(spellName);
for (final data in skillData) {
final skillName = data['name'];
if (skillName != null) {
final skill = SkillData.getSkillBySpellName(skillName);
if (skill != null) {
skills.add(skill);
}

View File

@@ -49,17 +49,17 @@ class GameMutations {
final name = parts[0];
final rank = parts.length > 1 ? parts[1] : 'I';
final spells = [...state.spellBook.spells];
final index = spells.indexWhere((s) => s.name == name);
final skills = [...state.skillBook.skills];
final index = skills.indexWhere((s) => s.name == name);
if (index >= 0) {
spells[index] = spells[index].copyWith(rank: rank);
skills[index] = skills[index].copyWith(rank: rank);
} else {
spells.add(SpellEntry(name: name, rank: rank));
skills.add(SkillEntry(name: name, rank: rank));
}
return state.copyWith(
rng: state.rng,
spellBook: state.spellBook.copyWith(spells: spells),
skillBook: state.skillBook.copyWith(skills: skills),
);
}

View File

@@ -1240,11 +1240,11 @@ class ProgressService {
// 플레이어 공격 체크
if (playerAccumulator >= playerStats.attackDelayMs) {
// SpellBook에서 사용 가능한 스킬 ID 목록 조회
var availableSkillIds = skillService.getAvailableSkillIdsFromSpellBook(
state.spellBook,
// SkillBook에서 사용 가능한 스킬 ID 목록 조회
var availableSkillIds = skillService.getAvailableSkillIdsFromSkillBook(
state.skillBook,
);
// SpellBook에 스킬이 없으면 기본 스킬 사용
// SkillBook에 스킬이 없으면 기본 스킬 사용
if (availableSkillIds.isEmpty) {
availableSkillIds = SkillData.defaultSkillIds;
}
@@ -1259,9 +1259,9 @@ class ProgressService {
);
if (selectedSkill != null && selectedSkill.isAttack) {
// 스 랭크 조회 (SpellBook 기반)
final spellRank = skillService.getSkillRankFromSpellBook(
state.spellBook,
// 스 랭크 조회 (SkillBook 기반)
final skillRank = skillService.getSkillRankFromSkillBook(
state.skillBook,
selectedSkill.id,
);
// 랭크 스케일링 적용된 공격 스킬 사용
@@ -1270,7 +1270,7 @@ class ProgressService {
player: playerStats,
monster: monsterStats,
skillSystem: updatedSkillSystem,
rank: spellRank,
rank: skillRank,
);
playerStats = skillResult.updatedPlayer;
monsterStats = skillResult.updatedMonster;

View File

@@ -552,50 +552,50 @@ class SkillService {
}
// ============================================================================
// SpellBook 연동
// SkillBook 연동
// ============================================================================
/// SpellBook에서 사용 가능한 스킬 목록 조회
/// SkillBook에서 사용 가능한 스킬 목록 조회
///
/// SpellEntry 이름을 Skill로 매핑하여 반환
List<Skill> getAvailableSkillsFromSpellBook(SpellBook spellBook) {
return spellBook.spells
.map((spell) => SkillData.getSkillBySpellName(spell.name))
/// SkillEntry 이름을 Skill로 매핑하여 반환
List<Skill> getAvailableSkillsFromSkillBook(SkillBook skillBook) {
return skillBook.skills
.map((entry) => SkillData.getSkillBySpellName(entry.name))
.whereType<Skill>()
.toList();
}
/// SpellBook에서 스킬의 랭크(레벨) 조회
/// SkillBook에서 스킬의 랭크(레벨) 조회
///
/// 로마숫자 랭크(I, II, III)를 정수로 변환하여 반환
/// 스이 없으면 1 반환
int getSkillRankFromSpellBook(SpellBook spellBook, String skillId) {
/// 스이 없으면 1 반환
int getSkillRankFromSkillBook(SkillBook skillBook, String skillId) {
// skillId로 스킬 찾기
final skill = SkillData.getSkillById(skillId);
if (skill == null) return 1;
// 스킬 이름으로 SpellEntry 찾기
for (final spell in spellBook.spells) {
if (spell.name == skill.name) {
return romanToInt(spell.rank);
// 스킬 이름으로 SkillEntry 찾기
for (final entry in skillBook.skills) {
if (entry.name == skill.name) {
return romanToInt(entry.rank);
}
}
return 1; // 기본 랭크
}
/// SpellBook에서 스킬 ID 목록 조회
/// SkillBook에서 스킬 ID 목록 조회
///
/// 전투 시스템에서 사용 가능한 스킬 ID 목록 반환
List<String> getAvailableSkillIdsFromSpellBook(SpellBook spellBook) {
return getAvailableSkillsFromSpellBook(
spellBook,
List<String> getAvailableSkillIdsFromSkillBook(SkillBook skillBook) {
return getAvailableSkillsFromSkillBook(
skillBook,
).map((skill) => skill.id).toList();
}
/// 랭크 스케일링이 적용된 공격 스킬 사용
///
/// [rank] 스펠 랭크 (SpellBook에서 조회)
/// [rank] 스펠 랭크 (SkillBook에서 조회)
({
SkillUseResult result,
CombatStats updatedPlayer,

View File

@@ -21,7 +21,7 @@ class GameState {
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
SkillBook? skillBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
@@ -32,7 +32,7 @@ class GameState {
stats = stats ?? Stats.empty(),
inventory = inventory ?? Inventory.empty(),
equipment = equipment ?? Equipment.empty(),
spellBook = spellBook ?? SpellBook.empty(),
skillBook = skillBook ?? SkillBook.empty(),
progress = progress ?? ProgressState.empty(),
queue = queue ?? QueueState.empty(),
skillSystem = skillSystem ?? SkillSystemState.empty(),
@@ -44,7 +44,7 @@ class GameState {
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
SkillBook? skillBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
@@ -57,7 +57,7 @@ class GameState {
stats: stats,
inventory: inventory,
equipment: equipment,
spellBook: spellBook,
skillBook: skillBook,
progress: progress,
queue: queue,
skillSystem: skillSystem,
@@ -71,7 +71,7 @@ class GameState {
final Stats stats;
final Inventory inventory;
final Equipment equipment;
final SpellBook spellBook;
final SkillBook skillBook;
final ProgressState progress;
final QueueState queue;
@@ -93,7 +93,7 @@ class GameState {
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
SkillBook? skillBook,
ProgressState? progress,
QueueState? queue,
SkillSystemState? skillSystem,
@@ -107,7 +107,7 @@ class GameState {
stats: stats ?? this.stats,
inventory: inventory ?? this.inventory,
equipment: equipment ?? this.equipment,
spellBook: spellBook ?? this.spellBook,
skillBook: skillBook ?? this.skillBook,
progress: progress ?? this.progress,
queue: queue ?? this.queue,
skillSystem: skillSystem ?? this.skillSystem,
@@ -660,26 +660,26 @@ class Equipment {
}
}
class SpellEntry {
const SpellEntry({required this.name, required this.rank});
class SkillEntry {
const SkillEntry({required this.name, required this.rank});
final String name;
final String rank; // e.g., Roman numerals
SpellEntry copyWith({String? name, String? rank}) {
return SpellEntry(name: name ?? this.name, rank: rank ?? this.rank);
SkillEntry copyWith({String? name, String? rank}) {
return SkillEntry(name: name ?? this.name, rank: rank ?? this.rank);
}
}
class SpellBook {
const SpellBook({required this.spells});
class SkillBook {
const SkillBook({required this.skills});
final List<SpellEntry> spells;
final List<SkillEntry> skills;
factory SpellBook.empty() => const SpellBook(spells: []);
factory SkillBook.empty() => const SkillBook(skills: []);
SpellBook copyWith({List<SpellEntry>? spells}) {
return SpellBook(spells: spells ?? this.spells);
SkillBook copyWith({List<SkillEntry>? skills}) {
return SkillBook(skills: skills ?? this.skills);
}
}

View File

@@ -21,7 +21,7 @@ class HallOfFameEntry {
required this.clearedAt,
this.finalStats,
this.finalEquipment,
this.finalSpells,
this.finalSkills,
});
/// 고유 ID (UUID)
@@ -61,7 +61,7 @@ class HallOfFameEntry {
final List<EquipmentItem>? finalEquipment;
/// 최종 스펠북 (스펠 이름 + 랭크)
final List<Map<String, String>>? finalSpells;
final List<Map<String, String>>? finalSkills;
/// 플레이 시간을 Duration으로 변환
Duration get totalPlayTime => Duration(milliseconds: totalPlayTimeMs);
@@ -96,7 +96,7 @@ class HallOfFameEntry {
DateTime? clearedAt,
CombatStats? finalStats,
List<EquipmentItem>? finalEquipment,
List<Map<String, String>>? finalSpells,
List<Map<String, String>>? finalSkills,
}) {
return HallOfFameEntry(
id: id ?? this.id,
@@ -111,7 +111,7 @@ class HallOfFameEntry {
clearedAt: clearedAt ?? this.clearedAt,
finalStats: finalStats ?? this.finalStats,
finalEquipment: finalEquipment ?? this.finalEquipment,
finalSpells: finalSpells ?? this.finalSpells,
finalSkills: finalSkills ?? this.finalSkills,
);
}
@@ -135,7 +135,7 @@ class HallOfFameEntry {
clearedAt: DateTime.now(),
finalStats: combatStats,
finalEquipment: List<EquipmentItem>.from(state.equipment.items),
finalSpells: state.spellBook.spells
finalSkills: state.skillBook.skills
.map((s) => {'name': s.name, 'rank': s.rank})
.toList(),
);
@@ -156,7 +156,7 @@ class HallOfFameEntry {
'clearedAt': clearedAt.toIso8601String(),
'finalStats': finalStats?.toJson(),
'finalEquipment': finalEquipment?.map((e) => e.toJson()).toList(),
'finalSpells': finalSpells,
'finalSkills': finalSkills,
};
}
@@ -181,8 +181,8 @@ class HallOfFameEntry {
.map((e) => EquipmentItem.fromJson(e as Map<String, dynamic>))
.toList()
: null,
finalSpells: json['finalSpells'] != null
? (json['finalSpells'] as List<dynamic>)
finalSkills: json['finalSkills'] != null
? (json['finalSkills'] as List<dynamic>)
.map((s) => Map<String, String>.from(s as Map))
.toList()
: null,

View File

@@ -13,7 +13,7 @@ class GameSave {
required this.stats,
required this.inventory,
required this.equipment,
required this.spellBook,
required this.skillBook,
required this.progress,
required this.queue,
});
@@ -26,7 +26,7 @@ class GameSave {
stats: state.stats,
inventory: state.inventory,
equipment: state.equipment,
spellBook: state.spellBook,
skillBook: state.skillBook,
progress: state.progress,
queue: state.queue,
);
@@ -38,7 +38,7 @@ class GameSave {
final Stats stats;
final Inventory inventory;
final Equipment equipment;
final SpellBook spellBook;
final SkillBook skillBook;
final ProgressState progress;
final QueueState queue;
@@ -88,7 +88,7 @@ class GameSave {
'sollerets': equipment.sollerets,
'bestIndex': equipment.bestIndex,
},
'spells': spellBook.spells
'skills': skillBook.skills
.map((e) => {'name': e.name, 'rank': e.rank})
.toList(),
'progress': {
@@ -140,7 +140,7 @@ class GameSave {
final equipmentJson = json['equipment'] as Map<String, dynamic>;
final progressJson = json['progress'] as Map<String, dynamic>;
final queueJson = (json['queue'] as List<dynamic>? ?? []).cast<dynamic>();
final spellsJson = (json['spells'] as List<dynamic>? ?? []).cast<dynamic>();
final skillsJson = (json['skills'] as List<dynamic>? ?? []).cast<dynamic>();
return GameSave(
version: json['version'] as int? ?? kSaveVersion,
@@ -192,10 +192,10 @@ class GameSave {
sollerets: equipmentJson['sollerets'] as String? ?? '',
bestIndex: equipmentJson['bestIndex'] as int? ?? 0,
),
spellBook: SpellBook(
spells: spellsJson
skillBook: SkillBook(
skills: skillsJson
.map(
(e) => SpellEntry(
(e) => SkillEntry(
name: (e as Map<String, dynamic>)['name'] as String? ?? '',
rank: (e)['rank'] as String? ?? 'I',
),
@@ -261,7 +261,7 @@ class GameSave {
stats: stats,
inventory: inventory,
equipment: equipment,
spellBook: spellBook,
skillBook: skillBook,
progress: progress,
queue: queue,
);