feat(hall-of-fame): 명예의 전당 대폭 개선 및 장비/아이템 직렬화
- HallOfFameEntry에 finalEquipmentDetails 추가 (상세 장비 정보) - EquipmentItem/ItemStats에 toJson/fromJson 직렬화 추가 - 명예의 전당 상세 다이얼로그 UI 대폭 개선 - Canvas 타운/워킹 애니메이션 컴포저 개선 - 캐릭터 생성 화면 UI 개선 - 게임 텍스트 다국어 지원 확장
This commit is contained in:
@@ -89,6 +89,41 @@ class EquipmentItem {
|
||||
);
|
||||
}
|
||||
|
||||
/// JSON으로 직렬화
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'slot': slot.name,
|
||||
'level': level,
|
||||
'weight': weight,
|
||||
'stats': stats.toJson(),
|
||||
'rarity': rarity.name,
|
||||
};
|
||||
}
|
||||
|
||||
/// JSON에서 역직렬화
|
||||
factory EquipmentItem.fromJson(Map<String, dynamic> json) {
|
||||
final slotName = json['slot'] as String? ?? 'weapon';
|
||||
final rarityName = json['rarity'] as String? ?? 'common';
|
||||
|
||||
return EquipmentItem(
|
||||
name: json['name'] as String? ?? '',
|
||||
slot: EquipmentSlot.values.firstWhere(
|
||||
(s) => s.name == slotName,
|
||||
orElse: () => EquipmentSlot.weapon,
|
||||
),
|
||||
level: json['level'] as int? ?? 0,
|
||||
weight: json['weight'] as int? ?? 0,
|
||||
stats: json['stats'] != null
|
||||
? ItemStats.fromJson(json['stats'] as Map<String, dynamic>)
|
||||
: ItemStats.empty,
|
||||
rarity: ItemRarity.values.firstWhere(
|
||||
(r) => r.name == rarityName,
|
||||
orElse: () => ItemRarity.common,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => name.isEmpty ? '(empty)' : name;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:askiineverdie/src/core/model/combat_stats.dart';
|
||||
import 'package:askiineverdie/src/core/model/equipment_item.dart';
|
||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||
|
||||
/// 명예의 전당 엔트리 (Phase 10: Hall of Fame Entry)
|
||||
@@ -54,8 +55,8 @@ class HallOfFameEntry {
|
||||
/// 최종 전투 스탯 (향후 아스키 아레나용)
|
||||
final CombatStats? finalStats;
|
||||
|
||||
/// 최종 장비 목록 (향후 아스키 아레나용)
|
||||
final Map<String, String>? finalEquipment;
|
||||
/// 최종 장비 목록 (풀 스탯 포함)
|
||||
final List<EquipmentItem>? finalEquipment;
|
||||
|
||||
/// 최종 스펠북 (스펠 이름 + 랭크)
|
||||
final List<Map<String, String>>? finalSpells;
|
||||
@@ -98,19 +99,7 @@ class HallOfFameEntry {
|
||||
questsCompleted: state.progress.questCount,
|
||||
clearedAt: DateTime.now(),
|
||||
finalStats: combatStats,
|
||||
finalEquipment: {
|
||||
'weapon': state.equipment.weapon,
|
||||
'shield': state.equipment.shield,
|
||||
'helm': state.equipment.helm,
|
||||
'hauberk': state.equipment.hauberk,
|
||||
'brassairts': state.equipment.brassairts,
|
||||
'vambraces': state.equipment.vambraces,
|
||||
'gauntlets': state.equipment.gauntlets,
|
||||
'gambeson': state.equipment.gambeson,
|
||||
'cuisses': state.equipment.cuisses,
|
||||
'greaves': state.equipment.greaves,
|
||||
'sollerets': state.equipment.sollerets,
|
||||
},
|
||||
finalEquipment: List<EquipmentItem>.from(state.equipment.items),
|
||||
finalSpells: state.spellBook.spells
|
||||
.map((s) => {'name': s.name, 'rank': s.rank})
|
||||
.toList(),
|
||||
@@ -131,7 +120,7 @@ class HallOfFameEntry {
|
||||
'questsCompleted': questsCompleted,
|
||||
'clearedAt': clearedAt.toIso8601String(),
|
||||
'finalStats': finalStats?.toJson(),
|
||||
'finalEquipment': finalEquipment,
|
||||
'finalEquipment': finalEquipment?.map((e) => e.toJson()).toList(),
|
||||
'finalSpells': finalSpells,
|
||||
};
|
||||
}
|
||||
@@ -153,7 +142,9 @@ class HallOfFameEntry {
|
||||
? CombatStats.fromJson(json['finalStats'] as Map<String, dynamic>)
|
||||
: null,
|
||||
finalEquipment: json['finalEquipment'] != null
|
||||
? Map<String, String>.from(json['finalEquipment'] as Map)
|
||||
? (json['finalEquipment'] as List<dynamic>)
|
||||
.map((e) => EquipmentItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList()
|
||||
: null,
|
||||
finalSpells: json['finalSpells'] != null
|
||||
? (json['finalSpells'] as List<dynamic>)
|
||||
|
||||
@@ -127,6 +127,52 @@ class ItemStats {
|
||||
/// 빈 스탯 (보너스 없음)
|
||||
static const empty = ItemStats();
|
||||
|
||||
/// JSON으로 직렬화
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'atk': atk,
|
||||
'def': def,
|
||||
'magAtk': magAtk,
|
||||
'magDef': magDef,
|
||||
'criRate': criRate,
|
||||
'evasion': evasion,
|
||||
'blockRate': blockRate,
|
||||
'parryRate': parryRate,
|
||||
'hpBonus': hpBonus,
|
||||
'mpBonus': mpBonus,
|
||||
'strBonus': strBonus,
|
||||
'conBonus': conBonus,
|
||||
'dexBonus': dexBonus,
|
||||
'intBonus': intBonus,
|
||||
'wisBonus': wisBonus,
|
||||
'chaBonus': chaBonus,
|
||||
'attackSpeed': attackSpeed,
|
||||
};
|
||||
}
|
||||
|
||||
/// JSON에서 역직렬화
|
||||
factory ItemStats.fromJson(Map<String, dynamic> json) {
|
||||
return ItemStats(
|
||||
atk: json['atk'] as int? ?? 0,
|
||||
def: json['def'] as int? ?? 0,
|
||||
magAtk: json['magAtk'] as int? ?? 0,
|
||||
magDef: json['magDef'] as int? ?? 0,
|
||||
criRate: (json['criRate'] as num?)?.toDouble() ?? 0.0,
|
||||
evasion: (json['evasion'] as num?)?.toDouble() ?? 0.0,
|
||||
blockRate: (json['blockRate'] as num?)?.toDouble() ?? 0.0,
|
||||
parryRate: (json['parryRate'] as num?)?.toDouble() ?? 0.0,
|
||||
hpBonus: json['hpBonus'] as int? ?? 0,
|
||||
mpBonus: json['mpBonus'] as int? ?? 0,
|
||||
strBonus: json['strBonus'] as int? ?? 0,
|
||||
conBonus: json['conBonus'] as int? ?? 0,
|
||||
dexBonus: json['dexBonus'] as int? ?? 0,
|
||||
intBonus: json['intBonus'] as int? ?? 0,
|
||||
wisBonus: json['wisBonus'] as int? ?? 0,
|
||||
chaBonus: json['chaBonus'] as int? ?? 0,
|
||||
attackSpeed: json['attackSpeed'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
/// 두 스탯 합산
|
||||
///
|
||||
/// attackSpeed는 합산 대상 아님 (무기 슬롯 단일 값)
|
||||
|
||||
Reference in New Issue
Block a user