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:
JiWoong Sul
2025-12-22 19:00:58 +09:00
parent f606fca063
commit 99f5b74802
63 changed files with 3403 additions and 2740 deletions

View File

@@ -117,6 +117,9 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
// 전투 이벤트 동기화용 (Phase 5)
int? _lastEventTimestamp;
bool _showCriticalEffect = false;
bool _showBlockEffect = false;
bool _showParryEffect = false;
bool _showSkillEffect = false;
// 특수 애니메이션 프레임 수는 ascii_animation_type.dart의
// specialAnimationFrameCounts 상수 사용
@@ -177,33 +180,114 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
// 전투 모드가 아니면 무시
if (_animationMode != AnimationMode.battle) return;
// 이벤트 타입에 따라 페이즈 강제 전환
final (targetPhase, isCritical) = switch (event.type) {
// 이벤트 타입에 따라 페이즈 및 효과 결정
final (
targetPhase,
isCritical,
isBlock,
isParry,
isSkill,
) = switch (event.type) {
// 플레이어 공격 → attack 페이즈
CombatEventType.playerAttack => (BattlePhase.attack, event.isCritical),
CombatEventType.playerSkill => (BattlePhase.attack, event.isCritical),
CombatEventType.playerAttack => (
BattlePhase.attack,
event.isCritical,
false,
false,
false,
),
// 스킬 사용 → attack 페이즈 + 스킬 이펙트
CombatEventType.playerSkill => (
BattlePhase.attack,
event.isCritical,
false,
false,
true,
),
// 몬스터 공격/플레이어 피격 → hit 페이즈
CombatEventType.monsterAttack => (BattlePhase.hit, false),
CombatEventType.playerBlock => (BattlePhase.hit, false),
CombatEventType.playerParry => (BattlePhase.hit, false),
// 몬스터 공격 → hit 페이즈
CombatEventType.monsterAttack => (
BattlePhase.hit,
false,
false,
false,
false,
),
// 블록 → hit 페이즈 + 블록 이펙트
CombatEventType.playerBlock => (
BattlePhase.hit,
false,
true,
false,
false,
),
// 패리 → hit 페이즈 + 패리 이펙트
CombatEventType.playerParry => (
BattlePhase.hit,
false,
false,
true,
false,
),
// 회피 → recover 페이즈 (빠른 회피 동작)
CombatEventType.playerEvade => (BattlePhase.recover, false),
CombatEventType.monsterEvade => (BattlePhase.idle, false),
CombatEventType.playerEvade => (
BattlePhase.recover,
false,
false,
false,
false,
),
CombatEventType.monsterEvade => (
BattlePhase.idle,
false,
false,
false,
false,
),
// 회복/버프 → idle 페이즈 유지
CombatEventType.playerHeal => (BattlePhase.idle, false),
CombatEventType.playerBuff => (BattlePhase.idle, false),
CombatEventType.playerHeal => (
BattlePhase.idle,
false,
false,
false,
false,
),
CombatEventType.playerBuff => (
BattlePhase.idle,
false,
false,
false,
false,
),
// DOT 틱 → attack 페이즈 (지속 피해)
CombatEventType.dotTick => (BattlePhase.attack, false),
CombatEventType.dotTick => (
BattlePhase.attack,
false,
false,
false,
false,
),
// 물약 사용 → idle 페이즈 유지
CombatEventType.playerPotion => (BattlePhase.idle, false),
CombatEventType.playerPotion => (
BattlePhase.idle,
false,
false,
false,
false,
),
// 물약 드랍 → idle 페이즈 유지
CombatEventType.potionDrop => (BattlePhase.idle, false),
CombatEventType.potionDrop => (
BattlePhase.idle,
false,
false,
false,
false,
),
};
setState(() {
@@ -211,6 +295,9 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
_battleSubFrame = 0;
_phaseFrameCount = 0;
_showCriticalEffect = isCritical;
_showBlockEffect = isBlock;
_showParryEffect = isParry;
_showSkillEffect = isSkill;
// 페이즈 인덱스 동기화
_phaseIndex = _battlePhaseSequence.indexWhere((p) => p.$1 == targetPhase);
@@ -322,8 +409,11 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
_phaseIndex = (_phaseIndex + 1) % _battlePhaseSequence.length;
_phaseFrameCount = 0;
_battleSubFrame = 0;
// 크리티컬 이펙트 리셋 (페이즈 전환 시)
// 이펙트 리셋 (페이즈 전환 시)
_showCriticalEffect = false;
_showBlockEffect = false;
_showParryEffect = false;
_showSkillEffect = false;
} else {
_battleSubFrame++;
}
@@ -340,21 +430,22 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
/// 현재 애니메이션 레이어 생성
List<AsciiLayer> _composeLayers() {
return switch (_animationMode) {
AnimationMode.battle => _battleComposer?.composeLayers(
_battlePhase,
_battleSubFrame,
widget.monsterBaseName,
_environment,
_globalTick,
) ??
[AsciiLayer.empty()],
AnimationMode.battle =>
_battleComposer?.composeLayers(
_battlePhase,
_battleSubFrame,
widget.monsterBaseName,
_environment,
_globalTick,
) ??
[AsciiLayer.empty()],
AnimationMode.walking => _walkingComposer.composeLayers(_globalTick),
AnimationMode.town => _townComposer.composeLayers(_globalTick),
AnimationMode.special => _specialComposer.composeLayers(
_currentSpecialAnimation ?? AsciiAnimationType.levelUp,
_currentFrame,
_globalTick,
),
_currentSpecialAnimation ?? AsciiAnimationType.levelUp,
_currentFrame,
_globalTick,
),
};
}
@@ -363,17 +454,38 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
// Phase 7: 고정 4색 팔레트 사용 (colorTheme 무시)
const bgColor = AsciiColors.background;
// 테두리 효과 결정 (특수 애니메이션 또는 크리티컬 히트)
// 테두리 효과 결정 (전투 이벤트 또는 특수 애니메이션)
final isSpecial = _currentSpecialAnimation != null;
Border? borderEffect;
if (_showCriticalEffect) {
// 크리티컬 히트: 노란색 테두리 (Phase 5)
borderEffect =
Border.all(color: Colors.yellow.withValues(alpha: 0.8), width: 2);
// 크리티컬 히트: 노란색 테두리
borderEffect = Border.all(
color: Colors.yellow.withValues(alpha: 0.8),
width: 2,
);
} else if (_showBlockEffect) {
// 블록 (방패 방어): 파란색 테두리
borderEffect = Border.all(
color: Colors.blue.withValues(alpha: 0.8),
width: 2,
);
} else if (_showParryEffect) {
// 패리 (무기 쳐내기): 주황색 테두리
borderEffect = Border.all(
color: Colors.orange.withValues(alpha: 0.8),
width: 2,
);
} else if (_showSkillEffect) {
// 스킬 사용: 마젠타 테두리
borderEffect = Border.all(
color: Colors.purple.withValues(alpha: 0.8),
width: 2,
);
} else if (isSpecial) {
// 특수 애니메이션: 시안 테두리
borderEffect =
Border.all(color: AsciiColors.positive.withValues(alpha: 0.5));
borderEffect = Border.all(
color: AsciiColors.positive.withValues(alpha: 0.5),
);
}
return Container(