feat(game): 게임 시스템 전면 개편 및 다국어 지원 확장
## 스킬 시스템 개선 - skill_data.dart: 스킬 데이터 구조 전면 개편 (+1176 라인) - skill_service.dart: 스킬 발동 로직 확장 및 버프 시스템 연동 - skill.dart: 스킬 모델 개선, 쿨다운/효과 타입 추가 ## Canvas 애니메이션 리팩토링 - battle_composer.dart 삭제 (레거시 위젯 기반 렌더러) - monster_colors.dart 삭제 (AsciiCell 색상 시스템으로 통합) - canvas_battle_composer.dart: z-index 정렬 (몬스터 z=1, 캐릭터 z=2, 이펙트 z=3) - ascii_cell.dart, ascii_layer.dart: 코드 정리 ## UI/UX 개선 - hp_mp_bar.dart: l10n 적용, 몬스터 HP 바 컴팩트화 - death_overlay.dart: 사망 화면 개선 - equipment_stats_panel.dart: 장비 스탯 표시 확장 - active_buff_panel.dart: 버프 패널 개선 - notification_overlay.dart: 알림 시스템 개선 ## 다국어 지원 확장 - game_text_l10n.dart: 게임 텍스트 통합 (+758 라인) - 한국어/일본어/영어/중국어 번역 업데이트 - ARB 파일 동기화 ## 게임 로직 개선 - progress_service.dart: 진행 로직 리팩토링 - combat_calculator.dart: 전투 계산 로직 개선 - stat_calculator.dart: 스탯 계산 시스템 개선 - story_service.dart: 스토리 진행 로직 개선 ## 기타 - theme_preferences.dart 삭제 (미사용) - 테스트 파일 업데이트 - class_data.dart: 클래스 데이터 정리
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/data/game_text_l10n.dart' as l10n;
|
||||
import 'package:askiineverdie/src/core/engine/item_service.dart';
|
||||
import 'package:askiineverdie/src/core/model/equipment_item.dart';
|
||||
import 'package:askiineverdie/src/core/model/equipment_slot.dart';
|
||||
@@ -135,7 +136,7 @@ class _EmptySlotTile extends StatelessWidget {
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
leading: _SlotIcon(slot: slot, isEmpty: true),
|
||||
title: Text(
|
||||
'[${_getSlotName(slot)}] (empty)',
|
||||
'[${_getSlotName(slot)}] ${l10n.uiEmpty}',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey.shade600,
|
||||
@@ -222,10 +223,7 @@ class _TotalScoreHeader extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.blueGrey.shade700,
|
||||
Colors.blueGrey.shade600,
|
||||
],
|
||||
colors: [Colors.blueGrey.shade700, Colors.blueGrey.shade600],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
@@ -239,11 +237,7 @@ class _TotalScoreHeader extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
// 장비 아이콘
|
||||
const Icon(
|
||||
Icons.shield,
|
||||
size: 20,
|
||||
color: Colors.white70,
|
||||
),
|
||||
const Icon(Icons.shield, size: 20, color: Colors.white70),
|
||||
const SizedBox(width: 8),
|
||||
|
||||
// 총합 점수
|
||||
@@ -251,12 +245,9 @@ class _TotalScoreHeader extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'Equipment Score',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white70,
|
||||
),
|
||||
Text(
|
||||
l10n.uiEquipmentScore,
|
||||
style: const TextStyle(fontSize: 10, color: Colors.white70),
|
||||
),
|
||||
Text(
|
||||
'$totalScore',
|
||||
@@ -304,46 +295,80 @@ class _StatsGrid extends StatelessWidget {
|
||||
final entries = <_StatEntry>[];
|
||||
|
||||
// 공격 스탯
|
||||
if (stats.atk > 0) entries.add(_StatEntry('ATK', '+${stats.atk}'));
|
||||
if (stats.magAtk > 0) entries.add(_StatEntry('MATK', '+${stats.magAtk}'));
|
||||
if (stats.atk > 0) entries.add(_StatEntry(l10n.statAtk, '+${stats.atk}'));
|
||||
if (stats.magAtk > 0) {
|
||||
entries.add(_StatEntry(l10n.statMAtk, '+${stats.magAtk}'));
|
||||
}
|
||||
if (stats.criRate > 0) {
|
||||
entries.add(_StatEntry('CRI', '${(stats.criRate * 100).toStringAsFixed(1)}%'));
|
||||
entries.add(
|
||||
_StatEntry(l10n.statCri, '${(stats.criRate * 100).toStringAsFixed(1)}%'),
|
||||
);
|
||||
}
|
||||
if (stats.parryRate > 0) {
|
||||
entries.add(_StatEntry('PARRY', '${(stats.parryRate * 100).toStringAsFixed(1)}%'));
|
||||
entries.add(
|
||||
_StatEntry(
|
||||
l10n.statParry,
|
||||
'${(stats.parryRate * 100).toStringAsFixed(1)}%',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 방어 스탯
|
||||
if (stats.def > 0) entries.add(_StatEntry('DEF', '+${stats.def}'));
|
||||
if (stats.magDef > 0) entries.add(_StatEntry('MDEF', '+${stats.magDef}'));
|
||||
if (stats.def > 0) entries.add(_StatEntry(l10n.statDef, '+${stats.def}'));
|
||||
if (stats.magDef > 0) {
|
||||
entries.add(_StatEntry(l10n.statMDef, '+${stats.magDef}'));
|
||||
}
|
||||
if (stats.blockRate > 0) {
|
||||
entries.add(_StatEntry('BLOCK', '${(stats.blockRate * 100).toStringAsFixed(1)}%'));
|
||||
entries.add(
|
||||
_StatEntry(
|
||||
l10n.statBlock,
|
||||
'${(stats.blockRate * 100).toStringAsFixed(1)}%',
|
||||
),
|
||||
);
|
||||
}
|
||||
if (stats.evasion > 0) {
|
||||
entries.add(_StatEntry('EVA', '${(stats.evasion * 100).toStringAsFixed(1)}%'));
|
||||
entries.add(
|
||||
_StatEntry(l10n.statEva, '${(stats.evasion * 100).toStringAsFixed(1)}%'),
|
||||
);
|
||||
}
|
||||
|
||||
// 자원 스탯
|
||||
if (stats.hpBonus > 0) entries.add(_StatEntry('HP', '+${stats.hpBonus}'));
|
||||
if (stats.mpBonus > 0) entries.add(_StatEntry('MP', '+${stats.mpBonus}'));
|
||||
if (stats.hpBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statHp, '+${stats.hpBonus}'));
|
||||
}
|
||||
if (stats.mpBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statMp, '+${stats.mpBonus}'));
|
||||
}
|
||||
|
||||
// 능력치 보너스
|
||||
if (stats.strBonus > 0) entries.add(_StatEntry('STR', '+${stats.strBonus}'));
|
||||
if (stats.conBonus > 0) entries.add(_StatEntry('CON', '+${stats.conBonus}'));
|
||||
if (stats.dexBonus > 0) entries.add(_StatEntry('DEX', '+${stats.dexBonus}'));
|
||||
if (stats.intBonus > 0) entries.add(_StatEntry('INT', '+${stats.intBonus}'));
|
||||
if (stats.wisBonus > 0) entries.add(_StatEntry('WIS', '+${stats.wisBonus}'));
|
||||
if (stats.chaBonus > 0) entries.add(_StatEntry('CHA', '+${stats.chaBonus}'));
|
||||
if (stats.strBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statStr, '+${stats.strBonus}'));
|
||||
}
|
||||
if (stats.conBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statCon, '+${stats.conBonus}'));
|
||||
}
|
||||
if (stats.dexBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statDex, '+${stats.dexBonus}'));
|
||||
}
|
||||
if (stats.intBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statInt, '+${stats.intBonus}'));
|
||||
}
|
||||
if (stats.wisBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statWis, '+${stats.wisBonus}'));
|
||||
}
|
||||
if (stats.chaBonus > 0) {
|
||||
entries.add(_StatEntry(l10n.statCha, '+${stats.chaBonus}'));
|
||||
}
|
||||
|
||||
// 무기 공속
|
||||
if (slot == EquipmentSlot.weapon && stats.attackSpeed > 0) {
|
||||
entries.add(_StatEntry('SPEED', '${stats.attackSpeed}ms'));
|
||||
entries.add(_StatEntry(l10n.statSpeed, '${stats.attackSpeed}ms'));
|
||||
}
|
||||
|
||||
if (entries.isEmpty) {
|
||||
return const Text(
|
||||
'No bonus stats',
|
||||
style: TextStyle(fontSize: 10, color: Colors.grey),
|
||||
return Text(
|
||||
l10n.uiNoBonusStats,
|
||||
style: const TextStyle(fontSize: 10, color: Colors.grey),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -406,7 +431,7 @@ class _ItemMetaRow extends StatelessWidget {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
'Lv.${item.level}',
|
||||
l10n.uiLevel(item.level),
|
||||
style: const TextStyle(fontSize: 9, color: Colors.grey),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -420,7 +445,7 @@ class _ItemMetaRow extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'Wt.${item.weight}',
|
||||
l10n.uiWeight(item.weight),
|
||||
style: const TextStyle(fontSize: 9, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
@@ -441,16 +466,16 @@ class _ItemMetaRow extends StatelessWidget {
|
||||
/// 슬롯 이름 반환
|
||||
String _getSlotName(EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
EquipmentSlot.weapon => 'Weapon',
|
||||
EquipmentSlot.shield => 'Shield',
|
||||
EquipmentSlot.helm => 'Helm',
|
||||
EquipmentSlot.hauberk => 'Hauberk',
|
||||
EquipmentSlot.brassairts => 'Brassairts',
|
||||
EquipmentSlot.vambraces => 'Vambraces',
|
||||
EquipmentSlot.gauntlets => 'Gauntlets',
|
||||
EquipmentSlot.gambeson => 'Gambeson',
|
||||
EquipmentSlot.cuisses => 'Cuisses',
|
||||
EquipmentSlot.greaves => 'Greaves',
|
||||
EquipmentSlot.sollerets => 'Sollerets',
|
||||
EquipmentSlot.weapon => l10n.slotWeapon,
|
||||
EquipmentSlot.shield => l10n.slotShield,
|
||||
EquipmentSlot.helm => l10n.slotHelm,
|
||||
EquipmentSlot.hauberk => l10n.slotHauberk,
|
||||
EquipmentSlot.brassairts => l10n.slotBrassairts,
|
||||
EquipmentSlot.vambraces => l10n.slotVambraces,
|
||||
EquipmentSlot.gauntlets => l10n.slotGauntlets,
|
||||
EquipmentSlot.gambeson => l10n.slotGambeson,
|
||||
EquipmentSlot.cuisses => l10n.slotCuisses,
|
||||
EquipmentSlot.greaves => l10n.slotGreaves,
|
||||
EquipmentSlot.sollerets => l10n.slotSollerets,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user