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:
@@ -16,10 +16,7 @@ class ClassData {
|
||||
static const bugHunter = ClassTraits(
|
||||
classId: 'bug_hunter',
|
||||
name: 'Bug Hunter',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.intelligence: 1,
|
||||
},
|
||||
statModifiers: {StatType.str: 2, StatType.intelligence: 1},
|
||||
startingSkills: ['power_strike'],
|
||||
classSkills: ['power_strike', 'execute', 'bug_smash'],
|
||||
passives: [
|
||||
@@ -36,10 +33,7 @@ class ClassData {
|
||||
static const overflowWarrior = ClassTraits(
|
||||
classId: 'overflow_warrior',
|
||||
name: 'Overflow Warrior',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.con: 1,
|
||||
},
|
||||
statModifiers: {StatType.str: 2, StatType.con: 1},
|
||||
startingSkills: ['power_strike'],
|
||||
classSkills: ['power_strike', 'overflow_slash', 'buffer_break'],
|
||||
passives: [
|
||||
@@ -56,10 +50,7 @@ class ClassData {
|
||||
static const stackCrusher = ClassTraits(
|
||||
classId: 'stack_crusher',
|
||||
name: 'Stack Crusher',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.con: 1,
|
||||
},
|
||||
statModifiers: {StatType.str: 2, StatType.con: 1},
|
||||
startingSkills: ['power_strike'],
|
||||
classSkills: ['power_strike', 'stack_smash', 'heap_slam'],
|
||||
passives: [
|
||||
@@ -81,10 +72,7 @@ class ClassData {
|
||||
static const assertionKnight = ClassTraits(
|
||||
classId: 'assertion_knight',
|
||||
name: 'Assertion Knight',
|
||||
statModifiers: {
|
||||
StatType.str: 2,
|
||||
StatType.wis: 1,
|
||||
},
|
||||
statModifiers: {StatType.str: 2, StatType.wis: 1},
|
||||
startingSkills: ['shield_bash'],
|
||||
classSkills: ['shield_bash', 'assert_strike', 'validation_guard'],
|
||||
passives: [
|
||||
@@ -94,9 +82,7 @@ class ClassData {
|
||||
description: '방어력 +10%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.heavy,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.heavy),
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
@@ -107,10 +93,7 @@ class ClassData {
|
||||
static const debuggerPaladin = ClassTraits(
|
||||
classId: 'debugger_paladin',
|
||||
name: 'Debugger Paladin',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.con: 1,
|
||||
},
|
||||
statModifiers: {StatType.wis: 2, StatType.con: 1},
|
||||
startingSkills: ['shield_bash'],
|
||||
classSkills: ['shield_bash', 'debug_heal', 'breakpoint_guard'],
|
||||
passives: [
|
||||
@@ -125,19 +108,14 @@ class ClassData {
|
||||
description: '회복력 +10%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.heavy,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.heavy),
|
||||
);
|
||||
|
||||
/// Loop Breaker: CON + STR (스탯 합계: +3)
|
||||
static const loopBreaker = ClassTraits(
|
||||
classId: 'loop_breaker',
|
||||
name: 'Loop Breaker',
|
||||
statModifiers: {
|
||||
StatType.con: 2,
|
||||
StatType.str: 1,
|
||||
},
|
||||
statModifiers: {StatType.con: 2, StatType.str: 1},
|
||||
startingSkills: ['shield_bash'],
|
||||
classSkills: ['shield_bash', 'infinite_guard', 'break_stance'],
|
||||
passives: [
|
||||
@@ -147,19 +125,14 @@ class ClassData {
|
||||
description: 'HP +15%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.heavy,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.heavy),
|
||||
);
|
||||
|
||||
/// Garbage Collector: CON + STR (스탯 합계: +3)
|
||||
static const garbageCollector = ClassTraits(
|
||||
classId: 'garbage_collector',
|
||||
name: 'Garbage Collector',
|
||||
statModifiers: {
|
||||
StatType.con: 2,
|
||||
StatType.str: 1,
|
||||
},
|
||||
statModifiers: {StatType.con: 2, StatType.str: 1},
|
||||
startingSkills: ['absorb'],
|
||||
classSkills: ['absorb', 'recycle', 'memory_sweep'],
|
||||
passives: [
|
||||
@@ -174,9 +147,7 @@ class ClassData {
|
||||
description: '전투 후 HP 5% 회복',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.heavy,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.heavy),
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
@@ -187,10 +158,7 @@ class ClassData {
|
||||
static const compilerMage = ClassTraits(
|
||||
classId: 'compiler_mage',
|
||||
name: 'Compiler Mage',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.wis: 1,
|
||||
},
|
||||
statModifiers: {StatType.intelligence: 2, StatType.wis: 1},
|
||||
startingSkills: ['fireball'],
|
||||
classSkills: ['fireball', 'compile_blast', 'syntax_storm'],
|
||||
passives: [
|
||||
@@ -200,19 +168,14 @@ class ClassData {
|
||||
description: '마법 데미지 +15%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Recursion Master: INT + DEX (스탯 합계: +3)
|
||||
static const recursionMaster = ClassTraits(
|
||||
classId: 'recursion_master',
|
||||
name: 'Recursion Master',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.dex: 1,
|
||||
},
|
||||
statModifiers: {StatType.intelligence: 2, StatType.dex: 1},
|
||||
startingSkills: ['fireball'],
|
||||
classSkills: ['fireball', 'recursive_bolt', 'stack_overflow'],
|
||||
passives: [
|
||||
@@ -222,19 +185,14 @@ class ClassData {
|
||||
description: '마법 데미지 +20%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Memory Leaker: INT + WIS (스탯 합계: +3)
|
||||
static const memoryLeaker = ClassTraits(
|
||||
classId: 'memory_leaker',
|
||||
name: 'Memory Leaker',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.wis: 1,
|
||||
},
|
||||
statModifiers: {StatType.intelligence: 2, StatType.wis: 1},
|
||||
startingSkills: ['fireball'],
|
||||
classSkills: ['fireball', 'leak_drain', 'memory_corrupt'],
|
||||
passives: [
|
||||
@@ -244,19 +202,14 @@ class ClassData {
|
||||
description: '마법 데미지 +10%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Type Caster: INT + CHA (스탯 합계: +3)
|
||||
static const typeCaster = ClassTraits(
|
||||
classId: 'type_caster',
|
||||
name: 'Type Caster',
|
||||
statModifiers: {
|
||||
StatType.intelligence: 2,
|
||||
StatType.cha: 1,
|
||||
},
|
||||
statModifiers: {StatType.intelligence: 2, StatType.cha: 1},
|
||||
startingSkills: ['fireball'],
|
||||
classSkills: ['fireball', 'type_coercion', 'cast_spell'],
|
||||
passives: [
|
||||
@@ -266,19 +219,14 @@ class ClassData {
|
||||
description: '마법 데미지 +10%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// DevOps Shaman: CON + INT (스탯 합계: +3)
|
||||
static const devOpsShaman = ClassTraits(
|
||||
classId: 'devops_shaman',
|
||||
name: 'DevOps Shaman',
|
||||
statModifiers: {
|
||||
StatType.con: 1,
|
||||
StatType.intelligence: 2,
|
||||
},
|
||||
statModifiers: {StatType.con: 1, StatType.intelligence: 2},
|
||||
startingSkills: ['fireball'],
|
||||
classSkills: ['fireball', 'deploy_strike', 'ci_cd_flow'],
|
||||
passives: [
|
||||
@@ -293,9 +241,7 @@ class ClassData {
|
||||
description: 'HP +10%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
@@ -306,10 +252,7 @@ class ClassData {
|
||||
static const refactorMonk = ClassTraits(
|
||||
classId: 'refactor_monk',
|
||||
name: 'Refactor Monk',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.con: 1,
|
||||
},
|
||||
statModifiers: {StatType.dex: 2, StatType.con: 1},
|
||||
startingSkills: ['flurry'],
|
||||
classSkills: ['flurry', 'clean_code_strike', 'refactor_combo'],
|
||||
passives: [
|
||||
@@ -324,19 +267,14 @@ class ClassData {
|
||||
description: '연속 공격',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Pointer Assassin: DEX + STR (스탯 합계: +3)
|
||||
static const pointerAssassin = ClassTraits(
|
||||
classId: 'pointer_assassin',
|
||||
name: 'Pointer Assassin',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.str: 1,
|
||||
},
|
||||
statModifiers: {StatType.dex: 2, StatType.str: 1},
|
||||
startingSkills: ['backstab'],
|
||||
classSkills: ['backstab', 'null_strike', 'dereference_kill'],
|
||||
passives: [
|
||||
@@ -351,19 +289,14 @@ class ClassData {
|
||||
description: '첫 공격 1.5배',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Callback Samurai: DEX + STR (스탯 합계: +3)
|
||||
static const callbackSamurai = ClassTraits(
|
||||
classId: 'callback_samurai',
|
||||
name: 'Callback Samurai',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.str: 1,
|
||||
},
|
||||
statModifiers: {StatType.dex: 2, StatType.str: 1},
|
||||
startingSkills: ['power_strike'],
|
||||
classSkills: ['power_strike', 'async_slash', 'promise_blade'],
|
||||
passives: [
|
||||
@@ -385,10 +318,7 @@ class ClassData {
|
||||
static const testerJester = ClassTraits(
|
||||
classId: 'tester_jester',
|
||||
name: 'Tester Jester',
|
||||
statModifiers: {
|
||||
StatType.dex: 2,
|
||||
StatType.cha: 1,
|
||||
},
|
||||
statModifiers: {StatType.dex: 2, StatType.cha: 1},
|
||||
startingSkills: ['flurry'],
|
||||
classSkills: ['flurry', 'mock_strike', 'assert_fail'],
|
||||
passives: [
|
||||
@@ -403,9 +333,7 @@ class ClassData {
|
||||
description: '크리티컬 +5%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
// ==========================================================================
|
||||
@@ -416,10 +344,7 @@ class ClassData {
|
||||
static const exceptionHandler = ClassTraits(
|
||||
classId: 'exception_handler',
|
||||
name: 'Exception Handler',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.intelligence: 1,
|
||||
},
|
||||
statModifiers: {StatType.wis: 2, StatType.intelligence: 1},
|
||||
startingSkills: ['heal'],
|
||||
classSkills: ['heal', 'try_catch', 'finally_heal'],
|
||||
passives: [
|
||||
@@ -429,19 +354,14 @@ class ClassData {
|
||||
description: '회복력 +15%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// Null Checker: WIS + INT (스탯 합계: +3)
|
||||
static const nullChecker = ClassTraits(
|
||||
classId: 'null_checker',
|
||||
name: 'Null Checker',
|
||||
statModifiers: {
|
||||
StatType.wis: 2,
|
||||
StatType.intelligence: 1,
|
||||
},
|
||||
statModifiers: {StatType.wis: 2, StatType.intelligence: 1},
|
||||
startingSkills: ['heal'],
|
||||
classSkills: ['heal', 'null_guard', 'safe_call'],
|
||||
passives: [
|
||||
@@ -456,9 +376,7 @@ class ClassData {
|
||||
description: '방어력 +5%',
|
||||
),
|
||||
],
|
||||
restriction: EquipmentRestriction(
|
||||
armorWeight: ArmorWeight.light,
|
||||
),
|
||||
restriction: EquipmentRestriction(armorWeight: ArmorWeight.light),
|
||||
);
|
||||
|
||||
/// 모든 클래스 목록 (18개)
|
||||
|
||||
@@ -99,6 +99,362 @@ String taskSelling(String itemDescription) {
|
||||
return 'Selling $itemDescription';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 부활 시퀀스 메시지
|
||||
// ============================================================================
|
||||
|
||||
String get taskReturningToTown {
|
||||
if (isKoreanLocale) return '마을로 귀환 중...';
|
||||
if (isJapaneseLocale) return '町に戻っている...';
|
||||
return 'Returning to town...';
|
||||
}
|
||||
|
||||
String get taskRestockingAtShop {
|
||||
if (isKoreanLocale) return '상점에서 장비 정비 중...';
|
||||
if (isJapaneseLocale) return 'ショップで装備を整備中...';
|
||||
return 'Restocking at shop...';
|
||||
}
|
||||
|
||||
String get taskHeadingToHuntingGrounds {
|
||||
if (isKoreanLocale) return '사냥터로 이동 중...';
|
||||
if (isJapaneseLocale) return '狩り場へ向かっている...';
|
||||
return 'Heading to hunting grounds...';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 사망 화면 메시지
|
||||
// ============================================================================
|
||||
|
||||
String get deathYouDied {
|
||||
if (isKoreanLocale) return '사망';
|
||||
if (isJapaneseLocale) return '死亡';
|
||||
return 'YOU DIED';
|
||||
}
|
||||
|
||||
String get deathSacrificedToResurrect {
|
||||
if (isKoreanLocale) return '부활 대가로 희생됨';
|
||||
if (isJapaneseLocale) return '復活のために犠牲';
|
||||
return 'Sacrificed to Resurrect';
|
||||
}
|
||||
|
||||
String get deathEquipment {
|
||||
if (isKoreanLocale) return '장비';
|
||||
if (isJapaneseLocale) return '装備';
|
||||
return 'Equipment';
|
||||
}
|
||||
|
||||
String get deathNoSacrificeNeeded {
|
||||
if (isKoreanLocale) return '희생 없이 부활';
|
||||
if (isJapaneseLocale) return '犠牲なしで復活';
|
||||
return 'No sacrifice needed';
|
||||
}
|
||||
|
||||
String get deathGoldRemaining {
|
||||
if (isKoreanLocale) return '남은 골드';
|
||||
if (isJapaneseLocale) return '残りゴールド';
|
||||
return 'Gold Remaining';
|
||||
}
|
||||
|
||||
String get deathResurrect {
|
||||
if (isKoreanLocale) return '부활';
|
||||
if (isJapaneseLocale) return '復活';
|
||||
return 'Resurrect';
|
||||
}
|
||||
|
||||
String get deathCombatLog {
|
||||
if (isKoreanLocale) return '전투 기록';
|
||||
if (isJapaneseLocale) return '戦闘ログ';
|
||||
return 'Combat Log';
|
||||
}
|
||||
|
||||
String deathKilledBy(String killerName) {
|
||||
if (isKoreanLocale) return '$killerName에게 사망';
|
||||
if (isJapaneseLocale) return '$killerNameに倒された';
|
||||
return 'Killed by $killerName';
|
||||
}
|
||||
|
||||
String get deathEnvironmentalHazard {
|
||||
if (isKoreanLocale) return '환경 피해로 사망';
|
||||
if (isJapaneseLocale) return '環境ダメージで死亡';
|
||||
return 'Environmental hazard';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// UI 일반 메시지
|
||||
// ============================================================================
|
||||
|
||||
String get uiNoPotions {
|
||||
if (isKoreanLocale) return '포션 없음';
|
||||
if (isJapaneseLocale) return 'ポーションなし';
|
||||
return 'No potions';
|
||||
}
|
||||
|
||||
String get uiTapToContinue {
|
||||
if (isKoreanLocale) return '탭하여 계속';
|
||||
if (isJapaneseLocale) return 'タップして続行';
|
||||
return 'Tap to continue';
|
||||
}
|
||||
|
||||
String get uiNoSkills {
|
||||
if (isKoreanLocale) return '습득한 스킬이 없습니다';
|
||||
if (isJapaneseLocale) return 'スキルなし';
|
||||
return 'No skills';
|
||||
}
|
||||
|
||||
String get uiNoBonusStats {
|
||||
if (isKoreanLocale) return '추가 스탯 없음';
|
||||
if (isJapaneseLocale) return 'ボーナスステータスなし';
|
||||
return 'No bonus stats';
|
||||
}
|
||||
|
||||
String get uiNoActiveBuffs {
|
||||
if (isKoreanLocale) return '활성 버프 없음';
|
||||
if (isJapaneseLocale) return 'アクティブバフなし';
|
||||
return 'No active buffs';
|
||||
}
|
||||
|
||||
String get uiReady {
|
||||
if (isKoreanLocale) return '준비';
|
||||
if (isJapaneseLocale) return '準備完了';
|
||||
return 'Ready';
|
||||
}
|
||||
|
||||
String get uiPotions {
|
||||
if (isKoreanLocale) return '포션';
|
||||
if (isJapaneseLocale) return 'ポーション';
|
||||
return 'Potions';
|
||||
}
|
||||
|
||||
String get uiBuffs {
|
||||
if (isKoreanLocale) return '버프';
|
||||
if (isJapaneseLocale) return 'バフ';
|
||||
return 'Buffs';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 스탯 약어
|
||||
// ============================================================================
|
||||
|
||||
String get statStr {
|
||||
if (isKoreanLocale) return '힘';
|
||||
if (isJapaneseLocale) return '筋力';
|
||||
return 'STR';
|
||||
}
|
||||
|
||||
String get statCon {
|
||||
if (isKoreanLocale) return '체력';
|
||||
if (isJapaneseLocale) return '耐久';
|
||||
return 'CON';
|
||||
}
|
||||
|
||||
String get statDex {
|
||||
if (isKoreanLocale) return '민첩';
|
||||
if (isJapaneseLocale) return '敏捷';
|
||||
return 'DEX';
|
||||
}
|
||||
|
||||
String get statInt {
|
||||
if (isKoreanLocale) return '지능';
|
||||
if (isJapaneseLocale) return '知力';
|
||||
return 'INT';
|
||||
}
|
||||
|
||||
String get statWis {
|
||||
if (isKoreanLocale) return '지혜';
|
||||
if (isJapaneseLocale) return '精神';
|
||||
return 'WIS';
|
||||
}
|
||||
|
||||
String get statCha {
|
||||
if (isKoreanLocale) return '매력';
|
||||
if (isJapaneseLocale) return '魅力';
|
||||
return 'CHA';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 패시브 능력 설명
|
||||
// ============================================================================
|
||||
|
||||
String passiveHpBonus(int percent) {
|
||||
if (isKoreanLocale) return 'HP +$percent%';
|
||||
if (isJapaneseLocale) return 'HP +$percent%';
|
||||
return 'HP +$percent%';
|
||||
}
|
||||
|
||||
String passiveMpBonus(int percent) {
|
||||
if (isKoreanLocale) return 'MP +$percent%';
|
||||
if (isJapaneseLocale) return 'MP +$percent%';
|
||||
return 'MP +$percent%';
|
||||
}
|
||||
|
||||
String passivePhysicalBonus(int percent) {
|
||||
if (isKoreanLocale) return '물리 공격 +$percent%';
|
||||
if (isJapaneseLocale) return '物理攻撃 +$percent%';
|
||||
return 'Physical +$percent%';
|
||||
}
|
||||
|
||||
String passiveDefenseBonus(int percent) {
|
||||
if (isKoreanLocale) return '방어력 +$percent%';
|
||||
if (isJapaneseLocale) return '防御力 +$percent%';
|
||||
return 'Defense +$percent%';
|
||||
}
|
||||
|
||||
String passiveMagicBonus(int percent) {
|
||||
if (isKoreanLocale) return '마법 공격 +$percent%';
|
||||
if (isJapaneseLocale) return '魔法攻撃 +$percent%';
|
||||
return 'Magic +$percent%';
|
||||
}
|
||||
|
||||
String passiveEvasionBonus(int percent) {
|
||||
if (isKoreanLocale) return '회피율 +$percent%';
|
||||
if (isJapaneseLocale) return '回避率 +$percent%';
|
||||
return 'Evasion +$percent%';
|
||||
}
|
||||
|
||||
String passiveCritBonus(int percent) {
|
||||
if (isKoreanLocale) return '크리티컬 +$percent%';
|
||||
if (isJapaneseLocale) return 'クリティカル +$percent%';
|
||||
return 'Critical +$percent%';
|
||||
}
|
||||
|
||||
String passiveHpRegen(int percent) {
|
||||
if (isKoreanLocale) return '전투 후 HP $percent% 회복';
|
||||
if (isJapaneseLocale) return '戦闘後HP $percent%回復';
|
||||
return 'Recover $percent% HP after combat';
|
||||
}
|
||||
|
||||
String passiveMpRegen(int percent) {
|
||||
if (isKoreanLocale) return '전투 후 MP $percent% 회복';
|
||||
if (isJapaneseLocale) return '戦闘後MP $percent%回復';
|
||||
return 'Recover $percent% MP after combat';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 전투 로그 메시지
|
||||
// ============================================================================
|
||||
|
||||
String combatYouHit(String targetName, int damage) {
|
||||
if (isKoreanLocale) return '$targetName에게 $damage 데미지';
|
||||
if (isJapaneseLocale) return '$targetNameに$damageダメージ';
|
||||
return 'You hit $targetName for $damage damage';
|
||||
}
|
||||
|
||||
String combatYouEvaded(String targetName) {
|
||||
if (isKoreanLocale) return '$targetName의 공격 회피!';
|
||||
if (isJapaneseLocale) return '$targetNameの攻撃を回避!';
|
||||
return 'You evaded $targetName\'s attack!';
|
||||
}
|
||||
|
||||
String combatEvadedAttackFrom(String targetName) {
|
||||
if (isKoreanLocale) return '$targetName의 공격 회피';
|
||||
if (isJapaneseLocale) return '$targetNameの攻撃を回避';
|
||||
return 'Evaded attack from $targetName';
|
||||
}
|
||||
|
||||
String combatHealedFor(int amount) {
|
||||
if (isKoreanLocale) return 'HP $amount 회복';
|
||||
if (isJapaneseLocale) return 'HP $amount回復';
|
||||
return 'Healed for $amount HP';
|
||||
}
|
||||
|
||||
String combatCritical(int damage, String targetName) {
|
||||
if (isKoreanLocale) return '크리티컬! $targetName에게 $damage 데미지!';
|
||||
if (isJapaneseLocale) return 'クリティカル! $targetNameに$damageダメージ!';
|
||||
return 'CRITICAL! $damage damage to $targetName!';
|
||||
}
|
||||
|
||||
String combatMonsterHitsYou(String monsterName, int damage) {
|
||||
if (isKoreanLocale) return '$monsterName이(가) $damage 데미지';
|
||||
if (isJapaneseLocale) return '$monsterNameが$damageダメージを与えた';
|
||||
return '$monsterName hits you for $damage damage';
|
||||
}
|
||||
|
||||
String combatMonsterEvaded(String monsterName) {
|
||||
if (isKoreanLocale) return '$monsterName이(가) 공격 회피!';
|
||||
if (isJapaneseLocale) return '$monsterNameが攻撃を回避!';
|
||||
return '$monsterName evaded your attack!';
|
||||
}
|
||||
|
||||
String combatBlocked(int damage) {
|
||||
if (isKoreanLocale) return '방어! $damage 데미지로 감소';
|
||||
if (isJapaneseLocale) return 'ブロック! $damageダメージに軽減';
|
||||
return 'Blocked! Reduced to $damage damage';
|
||||
}
|
||||
|
||||
String combatParried(int damage) {
|
||||
if (isKoreanLocale) return '패리! $damage 데미지로 감소';
|
||||
if (isJapaneseLocale) return 'パリィ! $damageダメージに軽減';
|
||||
return 'Parried! Reduced to $damage damage';
|
||||
}
|
||||
|
||||
// 스킬 관련 전투 메시지
|
||||
String combatSkillCritical(String skillName, int damage) {
|
||||
if (isKoreanLocale) return '크리티컬 $skillName! $damage 데미지!';
|
||||
if (isJapaneseLocale) return 'クリティカル$skillName! $damageダメージ!';
|
||||
return 'CRITICAL $skillName! $damage damage!';
|
||||
}
|
||||
|
||||
String combatSkillDamage(String skillName, int damage) {
|
||||
if (isKoreanLocale) return '$skillName: $damage 데미지';
|
||||
if (isJapaneseLocale) return '$skillName: $damageダメージ';
|
||||
return '$skillName: $damage damage';
|
||||
}
|
||||
|
||||
String combatSkillHeal(String skillName, int amount) {
|
||||
if (isKoreanLocale) return '$skillName: +$amount HP';
|
||||
if (isJapaneseLocale) return '$skillName: +$amount HP';
|
||||
return '$skillName: +$amount HP';
|
||||
}
|
||||
|
||||
String get uiHeal {
|
||||
if (isKoreanLocale) return '힐';
|
||||
if (isJapaneseLocale) return 'ヒール';
|
||||
return 'Heal';
|
||||
}
|
||||
|
||||
String combatBuffActivated(String skillName) {
|
||||
if (isKoreanLocale) return '$skillName 발동!';
|
||||
if (isJapaneseLocale) return '$skillName 発動!';
|
||||
return '$skillName activated!';
|
||||
}
|
||||
|
||||
String combatDotTick(String skillName, int damage) {
|
||||
if (isKoreanLocale) return '$skillName: $damage 지속 데미지';
|
||||
if (isJapaneseLocale) return '$skillName: $damage 継続ダメージ';
|
||||
return '$skillName ticks for $damage damage';
|
||||
}
|
||||
|
||||
String combatPotionUsed(String potionName, int amount, String statName) {
|
||||
if (isKoreanLocale) return '$potionName: +$amount $statName';
|
||||
if (isJapaneseLocale) return '$potionName: +$amount $statName';
|
||||
return '$potionName: +$amount $statName';
|
||||
}
|
||||
|
||||
String combatPotionDrop(String potionName) {
|
||||
if (isKoreanLocale) return '획득: $potionName';
|
||||
if (isJapaneseLocale) return '獲得: $potionName';
|
||||
return 'Dropped: $potionName';
|
||||
}
|
||||
|
||||
// 사망 화면 전투 로그 (death overlay)
|
||||
String combatBlockedAttack(String monsterName, int reducedDamage) {
|
||||
if (isKoreanLocale) return '$monsterName의 공격 방어 ($reducedDamage 감소)';
|
||||
if (isJapaneseLocale) return '$monsterNameの攻撃を防御 ($reducedDamage軽減)';
|
||||
return 'Blocked $monsterName\'s attack ($reducedDamage reduced)';
|
||||
}
|
||||
|
||||
String combatParriedAttack(String monsterName, int reducedDamage) {
|
||||
if (isKoreanLocale) return '$monsterName의 공격 패리 ($reducedDamage 감소)';
|
||||
if (isJapaneseLocale) return '$monsterNameの攻撃をパリィ ($reducedDamage軽減)';
|
||||
return 'Parried $monsterName\'s attack ($reducedDamage reduced)';
|
||||
}
|
||||
|
||||
String get deathSelfInflicted {
|
||||
if (isKoreanLocale) return '자해 데미지로 사망';
|
||||
if (isJapaneseLocale) return '自傷ダメージで死亡';
|
||||
return 'Self-inflicted damage';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 퀘스트 캡션
|
||||
// ============================================================================
|
||||
@@ -572,7 +928,8 @@ String translateImpressiveTitle(String englishName) {
|
||||
/// 특수 아이템 이름 번역
|
||||
String translateSpecial(String englishName) {
|
||||
if (isKoreanLocale) return specialTranslationsKo[englishName] ?? englishName;
|
||||
if (isJapaneseLocale) return specialTranslationsJa[englishName] ?? englishName;
|
||||
if (isJapaneseLocale)
|
||||
return specialTranslationsJa[englishName] ?? englishName;
|
||||
return englishName;
|
||||
}
|
||||
|
||||
@@ -627,14 +984,16 @@ String translateBoringItem(String englishName) {
|
||||
/// 예: "Golden Iterator" → "황금 이터레이터" / "黄金のイテレーター"
|
||||
String translateInterestingItem(String attrib, String special) {
|
||||
if (isKoreanLocale) {
|
||||
final translatedAttrib = itemAttribTranslationsKo[attrib] ??
|
||||
final translatedAttrib =
|
||||
itemAttribTranslationsKo[attrib] ??
|
||||
additionalItemAttribTranslationsKo[attrib] ??
|
||||
attrib;
|
||||
final translatedSpecial = specialTranslationsKo[special] ?? special;
|
||||
return '$translatedAttrib $translatedSpecial';
|
||||
}
|
||||
if (isJapaneseLocale) {
|
||||
final translatedAttrib = itemAttribTranslationsJa[attrib] ??
|
||||
final translatedAttrib =
|
||||
itemAttribTranslationsJa[attrib] ??
|
||||
additionalItemAttribTranslationsJa[attrib] ??
|
||||
attrib;
|
||||
final translatedSpecial = specialTranslationsJa[special] ?? special;
|
||||
@@ -643,48 +1002,419 @@ String translateInterestingItem(String attrib, String special) {
|
||||
return '$attrib $special';
|
||||
}
|
||||
|
||||
/// 아이템 이름 문자열 전체 번역 (판매, 로그 등에 사용)
|
||||
/// 예: "Golden Iterator of Compilation" → "컴파일의 황금 이터레이터"
|
||||
/// 예: "Syntax Error fragment" → "구문 오류 조각"
|
||||
String translateItemNameL10n(String itemString) {
|
||||
if (!isKoreanLocale && !isJapaneseLocale) return itemString;
|
||||
if (itemString.isEmpty) return itemString;
|
||||
|
||||
// 1. specialItem 형식: "Attrib Special of ItemOf"
|
||||
final ofMatch = RegExp(r'^(.+)\s+of\s+(.+)$').firstMatch(itemString);
|
||||
if (ofMatch != null) {
|
||||
final beforeOf = ofMatch.group(1)!;
|
||||
final afterOf = ofMatch.group(2)!;
|
||||
|
||||
// afterOf가 itemOfs 목록에 있는지 확인
|
||||
final itemOfKo =
|
||||
itemOfsTranslationsKo[afterOf] ??
|
||||
additionalItemOfsTranslationsKo[afterOf];
|
||||
final itemOfJa =
|
||||
itemOfsTranslationsJa[afterOf] ??
|
||||
additionalItemOfsTranslationsJa[afterOf];
|
||||
|
||||
if (itemOfKo != null || itemOfJa != null) {
|
||||
// beforeOf를 interestingItem으로 분리 (attrib + special)
|
||||
final beforeWords = beforeOf.split(' ');
|
||||
if (beforeWords.length >= 2) {
|
||||
final attrib = beforeWords[0];
|
||||
final special = beforeWords.sublist(1).join(' ');
|
||||
final translatedBefore = translateInterestingItem(attrib, special);
|
||||
if (isKoreanLocale) {
|
||||
return '$itemOfKo의 $translatedBefore';
|
||||
} else if (isJapaneseLocale) {
|
||||
return '$itemOfJaの$translatedBefore';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 몬스터 드롭 형식: "{monster} {drop}" (예: "syntax error fragment")
|
||||
final words = itemString.split(' ');
|
||||
if (words.length >= 2) {
|
||||
// 마지막 단어가 드롭 아이템인지 확인
|
||||
final lastWord = words.last.toLowerCase();
|
||||
final dropKo =
|
||||
dropItemTranslationsKo[lastWord] ??
|
||||
additionalDropTranslationsKo[lastWord];
|
||||
final dropJa =
|
||||
dropItemTranslationsJa[lastWord] ??
|
||||
additionalDropTranslationsJa[lastWord];
|
||||
|
||||
if (dropKo != null || dropJa != null) {
|
||||
// 앞 부분은 몬스터 이름
|
||||
final monsterPart = words.sublist(0, words.length - 1).join(' ');
|
||||
final translatedMonster = translateMonster(monsterPart);
|
||||
if (isKoreanLocale && dropKo != null) {
|
||||
return '$translatedMonster $dropKo';
|
||||
} else if (isJapaneseLocale && dropJa != null) {
|
||||
return '$translatedMonsterの$dropJa';
|
||||
}
|
||||
}
|
||||
|
||||
// 3. interestingItem 형식: "Attrib Special" (2단어)
|
||||
if (words.length == 2) {
|
||||
return translateInterestingItem(words[0], words[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 단일 단어 - boringItem 번역 시도
|
||||
return translateBoringItem(itemString);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 스토리/시네마틱 번역 함수 (Story/Cinematic Translation Functions)
|
||||
// ============================================================================
|
||||
|
||||
/// Act 제목 번역
|
||||
String translateActTitle(String englishTitle) {
|
||||
if (isKoreanLocale) return actTitleTranslationsKo[englishTitle] ?? englishTitle;
|
||||
if (isJapaneseLocale) return actTitleTranslationsJa[englishTitle] ?? englishTitle;
|
||||
if (isKoreanLocale)
|
||||
return actTitleTranslationsKo[englishTitle] ?? englishTitle;
|
||||
if (isJapaneseLocale)
|
||||
return actTitleTranslationsJa[englishTitle] ?? englishTitle;
|
||||
return englishTitle;
|
||||
}
|
||||
|
||||
/// Act 보스 이름 번역
|
||||
String translateActBoss(String englishBoss) {
|
||||
if (isKoreanLocale) return actBossTranslationsKo[englishBoss] ?? englishBoss;
|
||||
if (isJapaneseLocale) return actBossTranslationsJa[englishBoss] ?? englishBoss;
|
||||
if (isJapaneseLocale)
|
||||
return actBossTranslationsJa[englishBoss] ?? englishBoss;
|
||||
return englishBoss;
|
||||
}
|
||||
|
||||
/// Act 퀘스트 번역
|
||||
String translateActQuest(String englishQuest) {
|
||||
if (isKoreanLocale) return actQuestTranslationsKo[englishQuest] ?? englishQuest;
|
||||
if (isJapaneseLocale) return actQuestTranslationsJa[englishQuest] ?? englishQuest;
|
||||
if (isKoreanLocale)
|
||||
return actQuestTranslationsKo[englishQuest] ?? englishQuest;
|
||||
if (isJapaneseLocale)
|
||||
return actQuestTranslationsJa[englishQuest] ?? englishQuest;
|
||||
return englishQuest;
|
||||
}
|
||||
|
||||
/// 시네마틱 텍스트 번역
|
||||
String translateCinematic(String englishText) {
|
||||
if (isKoreanLocale) return cinematicTranslationsKo[englishText] ?? englishText;
|
||||
if (isJapaneseLocale) return cinematicTranslationsJa[englishText] ?? englishText;
|
||||
if (isKoreanLocale)
|
||||
return cinematicTranslationsKo[englishText] ?? englishText;
|
||||
if (isJapaneseLocale)
|
||||
return cinematicTranslationsJa[englishText] ?? englishText;
|
||||
return englishText;
|
||||
}
|
||||
|
||||
/// 지역 이름 번역
|
||||
String translateLocation(String englishLocation) {
|
||||
if (isKoreanLocale) return locationTranslationsKo[englishLocation] ?? englishLocation;
|
||||
if (isJapaneseLocale) return locationTranslationsJa[englishLocation] ?? englishLocation;
|
||||
if (isKoreanLocale)
|
||||
return locationTranslationsKo[englishLocation] ?? englishLocation;
|
||||
if (isJapaneseLocale)
|
||||
return locationTranslationsJa[englishLocation] ?? englishLocation;
|
||||
return englishLocation;
|
||||
}
|
||||
|
||||
/// 세력/조직 이름 번역
|
||||
String translateFaction(String englishFaction) {
|
||||
if (isKoreanLocale) return factionTranslationsKo[englishFaction] ?? englishFaction;
|
||||
if (isJapaneseLocale) return factionTranslationsJa[englishFaction] ?? englishFaction;
|
||||
if (isKoreanLocale)
|
||||
return factionTranslationsKo[englishFaction] ?? englishFaction;
|
||||
if (isJapaneseLocale)
|
||||
return factionTranslationsJa[englishFaction] ?? englishFaction;
|
||||
return englishFaction;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 프론트 화면 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get uiHallOfFame {
|
||||
if (isKoreanLocale) return '명예의 전당';
|
||||
if (isJapaneseLocale) return '栄誉の殿堂';
|
||||
return 'Hall of Fame';
|
||||
}
|
||||
|
||||
String get frontDescription {
|
||||
if (isKoreanLocale) return 'Flutter로 재구축된 오프라인 Progress Quest (PQ 6.4)';
|
||||
if (isJapaneseLocale) return 'Flutterで再構築されたオフラインProgress Quest (PQ 6.4)';
|
||||
return 'Offline Progress Quest (PQ 6.4) rebuilt with Flutter.';
|
||||
}
|
||||
|
||||
String get frontTodayFocus {
|
||||
if (isKoreanLocale) return '오늘의 중점';
|
||||
if (isJapaneseLocale) return '今日のフォーカス';
|
||||
return "Today's focus";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 명예의 전당 화면 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get hofNoHeroes {
|
||||
if (isKoreanLocale) return '영웅이 아직 없습니다';
|
||||
if (isJapaneseLocale) return 'まだ英雄がいません';
|
||||
return 'No heroes yet';
|
||||
}
|
||||
|
||||
String get hofDefeatGlitchGod {
|
||||
if (isKoreanLocale) return '글리치 신을 처치하여 전설을 남기세요!';
|
||||
if (isJapaneseLocale) return 'グリッチゴッドを倒して伝説を刻もう!';
|
||||
return 'Defeat the Glitch God to enshrine your legend!';
|
||||
}
|
||||
|
||||
String get hofVictory {
|
||||
if (isKoreanLocale) return '승리!';
|
||||
if (isJapaneseLocale) return '勝利!';
|
||||
return 'VICTORY!';
|
||||
}
|
||||
|
||||
String get hofDefeatedGlitchGod {
|
||||
if (isKoreanLocale) return '글리치 신을 처치했습니다!';
|
||||
if (isJapaneseLocale) return 'グリッチゴッドを倒しました!';
|
||||
return 'You have defeated the Glitch God!';
|
||||
}
|
||||
|
||||
String get hofLegendEnshrined {
|
||||
if (isKoreanLocale) return '당신의 전설이 명예의 전당에 기록되었습니다!';
|
||||
if (isJapaneseLocale) return 'あなたの伝説が栄誉の殿堂に刻まれました!';
|
||||
return 'Your legend has been enshrined in the Hall of Fame!';
|
||||
}
|
||||
|
||||
String get hofViewHallOfFame {
|
||||
if (isKoreanLocale) return '명예의 전당 보기';
|
||||
if (isJapaneseLocale) return '栄誉の殿堂を見る';
|
||||
return 'View Hall of Fame';
|
||||
}
|
||||
|
||||
String get hofNewGame {
|
||||
if (isKoreanLocale) return '새 게임';
|
||||
if (isJapaneseLocale) return '新しいゲーム';
|
||||
return 'New Game';
|
||||
}
|
||||
|
||||
String get hofLevel {
|
||||
if (isKoreanLocale) return '레벨';
|
||||
if (isJapaneseLocale) return 'レベル';
|
||||
return 'Level';
|
||||
}
|
||||
|
||||
String get hofTime {
|
||||
if (isKoreanLocale) return '시간';
|
||||
if (isJapaneseLocale) return '時間';
|
||||
return 'Time';
|
||||
}
|
||||
|
||||
String get hofDeaths {
|
||||
if (isKoreanLocale) return '사망';
|
||||
if (isJapaneseLocale) return '死亡';
|
||||
return 'Deaths';
|
||||
}
|
||||
|
||||
String get hofQuests {
|
||||
if (isKoreanLocale) return '퀘스트';
|
||||
if (isJapaneseLocale) return 'クエスト';
|
||||
return 'Quests';
|
||||
}
|
||||
|
||||
String uiLevel(int level) {
|
||||
if (isKoreanLocale) return 'Lv.$level';
|
||||
if (isJapaneseLocale) return 'Lv.$level';
|
||||
return 'Lv.$level';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 시네마틱 뷰 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get uiSkip {
|
||||
if (isKoreanLocale) return '건너뛰기';
|
||||
if (isJapaneseLocale) return 'スキップ';
|
||||
return 'SKIP';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 게임 플레이 화면 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get uiLevelUp {
|
||||
if (isKoreanLocale) return '레벨 업!';
|
||||
if (isJapaneseLocale) return 'レベルアップ!';
|
||||
return 'Level Up!';
|
||||
}
|
||||
|
||||
String uiQuestComplete(String questName) {
|
||||
if (isKoreanLocale) return '퀘스트 완료: $questName';
|
||||
if (isJapaneseLocale) return 'クエスト完了: $questName';
|
||||
return 'Quest Complete: $questName';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 장비 패널 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get uiEquipmentScore {
|
||||
if (isKoreanLocale) return '장비 점수';
|
||||
if (isJapaneseLocale) return '装備スコア';
|
||||
return 'Equipment Score';
|
||||
}
|
||||
|
||||
String get uiEmpty {
|
||||
if (isKoreanLocale) return '(비어있음)';
|
||||
if (isJapaneseLocale) return '(空)';
|
||||
return '(empty)';
|
||||
}
|
||||
|
||||
String uiWeight(int weight) {
|
||||
if (isKoreanLocale) return '무게 $weight';
|
||||
if (isJapaneseLocale) return '重量 $weight';
|
||||
return 'Wt.$weight';
|
||||
}
|
||||
|
||||
// 장비 슬롯 이름
|
||||
String get slotWeapon {
|
||||
if (isKoreanLocale) return '무기';
|
||||
if (isJapaneseLocale) return '武器';
|
||||
return 'Weapon';
|
||||
}
|
||||
|
||||
String get slotShield {
|
||||
if (isKoreanLocale) return '방패';
|
||||
if (isJapaneseLocale) return '盾';
|
||||
return 'Shield';
|
||||
}
|
||||
|
||||
String get slotHelm {
|
||||
if (isKoreanLocale) return '투구';
|
||||
if (isJapaneseLocale) return '兜';
|
||||
return 'Helm';
|
||||
}
|
||||
|
||||
String get slotHauberk {
|
||||
if (isKoreanLocale) return '갑옷';
|
||||
if (isJapaneseLocale) return '鎧';
|
||||
return 'Hauberk';
|
||||
}
|
||||
|
||||
String get slotBrassairts {
|
||||
if (isKoreanLocale) return '상완갑';
|
||||
if (isJapaneseLocale) return '上腕甲';
|
||||
return 'Brassairts';
|
||||
}
|
||||
|
||||
String get slotVambraces {
|
||||
if (isKoreanLocale) return '전완갑';
|
||||
if (isJapaneseLocale) return '前腕甲';
|
||||
return 'Vambraces';
|
||||
}
|
||||
|
||||
String get slotGauntlets {
|
||||
if (isKoreanLocale) return '건틀릿';
|
||||
if (isJapaneseLocale) return 'ガントレット';
|
||||
return 'Gauntlets';
|
||||
}
|
||||
|
||||
String get slotGambeson {
|
||||
if (isKoreanLocale) return '패딩';
|
||||
if (isJapaneseLocale) return 'パッデッドアーマー';
|
||||
return 'Gambeson';
|
||||
}
|
||||
|
||||
String get slotCuisses {
|
||||
if (isKoreanLocale) return '허벅지갑';
|
||||
if (isJapaneseLocale) return '腿当て';
|
||||
return 'Cuisses';
|
||||
}
|
||||
|
||||
String get slotGreaves {
|
||||
if (isKoreanLocale) return '정강이갑';
|
||||
if (isJapaneseLocale) return '脛当て';
|
||||
return 'Greaves';
|
||||
}
|
||||
|
||||
String get slotSollerets {
|
||||
if (isKoreanLocale) return '철제부츠';
|
||||
if (isJapaneseLocale) return '鉄靴';
|
||||
return 'Sollerets';
|
||||
}
|
||||
|
||||
// 스탯 약어 (장비용)
|
||||
String get statAtk {
|
||||
if (isKoreanLocale) return '공격';
|
||||
if (isJapaneseLocale) return '攻撃';
|
||||
return 'ATK';
|
||||
}
|
||||
|
||||
String get statMAtk {
|
||||
if (isKoreanLocale) return '마공';
|
||||
if (isJapaneseLocale) return '魔攻';
|
||||
return 'MATK';
|
||||
}
|
||||
|
||||
String get statCri {
|
||||
if (isKoreanLocale) return '치명';
|
||||
if (isJapaneseLocale) return 'クリ';
|
||||
return 'CRI';
|
||||
}
|
||||
|
||||
String get statParry {
|
||||
if (isKoreanLocale) return '패리';
|
||||
if (isJapaneseLocale) return 'パリィ';
|
||||
return 'PARRY';
|
||||
}
|
||||
|
||||
String get statDef {
|
||||
if (isKoreanLocale) return '방어';
|
||||
if (isJapaneseLocale) return '防御';
|
||||
return 'DEF';
|
||||
}
|
||||
|
||||
String get statMDef {
|
||||
if (isKoreanLocale) return '마방';
|
||||
if (isJapaneseLocale) return '魔防';
|
||||
return 'MDEF';
|
||||
}
|
||||
|
||||
String get statBlock {
|
||||
if (isKoreanLocale) return '블록';
|
||||
if (isJapaneseLocale) return 'ブロック';
|
||||
return 'BLOCK';
|
||||
}
|
||||
|
||||
String get statEva {
|
||||
if (isKoreanLocale) return '회피';
|
||||
if (isJapaneseLocale) return '回避';
|
||||
return 'EVA';
|
||||
}
|
||||
|
||||
String get statHp {
|
||||
if (isKoreanLocale) return 'HP';
|
||||
if (isJapaneseLocale) return 'HP';
|
||||
return 'HP';
|
||||
}
|
||||
|
||||
String get statMp {
|
||||
if (isKoreanLocale) return 'MP';
|
||||
if (isJapaneseLocale) return 'MP';
|
||||
return 'MP';
|
||||
}
|
||||
|
||||
String get statSpeed {
|
||||
if (isKoreanLocale) return '속도';
|
||||
if (isJapaneseLocale) return '速度';
|
||||
return 'SPEED';
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 스킬 패널 텍스트
|
||||
// ============================================================================
|
||||
|
||||
String get uiDot {
|
||||
if (isKoreanLocale) return '지속';
|
||||
if (isJapaneseLocale) return 'DOT';
|
||||
return 'DOT';
|
||||
}
|
||||
|
||||
@@ -1175,7 +1175,8 @@ const Map<String, String> cinematicTranslationsJa = {
|
||||
// Act I: 覚醒
|
||||
'=== ACT I: AWAKENING ===': '=== 第1幕: 覚醒 ===',
|
||||
'You have proven yourself against the lesser bugs.': '下級バグとの戦いで実力を証明した。',
|
||||
'The Debugger Knights take notice of your potential.': 'デバッガー騎士団があなたの可能性に注目する。',
|
||||
'The Debugger Knights take notice of your potential.':
|
||||
'デバッガー騎士団があなたの可能性に注目する。',
|
||||
'But a greater threat lurks in the Bug Nest...': 'しかしより大きな脅威がバグの巣に潜んでいる…',
|
||||
'The Syntax Error Dragon awaits.': '構文エラードラゴンが待ち構えている。',
|
||||
|
||||
@@ -1217,7 +1218,8 @@ const Map<String, String> cinematicTranslationsJa = {
|
||||
'The Glitch God falls. The corruption fades.': 'グリッチゴッドが倒れた。破損が消えていく。',
|
||||
'System Reboot initiated...': 'システム再起動開始…',
|
||||
'Peace returns to the Digital Realm.': 'デジタル世界に平和が戻った。',
|
||||
'Your legend will be compiled into the eternal logs.': 'あなたの伝説は永遠のログにコンパイルされるだろう。',
|
||||
'Your legend will be compiled into the eternal logs.':
|
||||
'あなたの伝説は永遠のログにコンパイルされるだろう。',
|
||||
'THE END': '完',
|
||||
'...or is it?': '…本当に?',
|
||||
};
|
||||
@@ -1485,37 +1487,37 @@ const Map<String, String> additionalItemOfsTranslationsJa = {
|
||||
|
||||
/// すべてのモンスター翻訳を統合して返す
|
||||
Map<String, String> get allMonsterTranslationsJa => {
|
||||
...monsterTranslationsJa,
|
||||
...advancedMonsterTranslationsJa,
|
||||
};
|
||||
...monsterTranslationsJa,
|
||||
...advancedMonsterTranslationsJa,
|
||||
};
|
||||
|
||||
/// すべてのアイテム属性翻訳を統合して返す
|
||||
Map<String, String> get allItemAttribTranslationsJa => {
|
||||
...itemAttribTranslationsJa,
|
||||
...additionalItemAttribTranslationsJa,
|
||||
};
|
||||
...itemAttribTranslationsJa,
|
||||
...additionalItemAttribTranslationsJa,
|
||||
};
|
||||
|
||||
/// すべてのアイテム接尾辞(~の)翻訳を統合して返す
|
||||
Map<String, String> get allItemOfsTranslationsJa => {
|
||||
...itemOfsTranslationsJa,
|
||||
...additionalItemOfsTranslationsJa,
|
||||
};
|
||||
...itemOfsTranslationsJa,
|
||||
...additionalItemOfsTranslationsJa,
|
||||
};
|
||||
|
||||
/// すべてのドロップアイテム翻訳を統合して返す
|
||||
Map<String, String> get allDropTranslationsJa => {
|
||||
...boringItemTranslationsJa,
|
||||
...dropItemTranslationsJa,
|
||||
...additionalDropTranslationsJa,
|
||||
};
|
||||
...boringItemTranslationsJa,
|
||||
...dropItemTranslationsJa,
|
||||
...additionalDropTranslationsJa,
|
||||
};
|
||||
|
||||
/// すべての鎧翻訳を統合して返す
|
||||
Map<String, String> get allArmorTranslationsJa => {
|
||||
...armorTranslationsJa,
|
||||
...additionalArmorTranslationsJa,
|
||||
};
|
||||
...armorTranslationsJa,
|
||||
...additionalArmorTranslationsJa,
|
||||
};
|
||||
|
||||
/// すべての盾翻訳を統合して返す
|
||||
Map<String, String> get allShieldTranslationsJa => {
|
||||
...shieldTranslationsJa,
|
||||
...additionalShieldTranslationsJa,
|
||||
};
|
||||
...shieldTranslationsJa,
|
||||
...additionalShieldTranslationsJa,
|
||||
};
|
||||
|
||||
@@ -1165,16 +1165,13 @@ const Map<String, String> actQuestTranslationsKo = {
|
||||
/// 시네마틱 텍스트 한국어 번역
|
||||
const Map<String, String> cinematicTranslationsKo = {
|
||||
// 프롤로그
|
||||
'In the beginning, there was only the Void...':
|
||||
'태초에, 오직 공허(Void)만이 존재했다...',
|
||||
'In the beginning, there was only the Void...': '태초에, 오직 공허(Void)만이 존재했다...',
|
||||
'Then came the First Commit, and Light filled the Codebase.':
|
||||
'그리고 첫 번째 커밋이 도래하여, 빛이 코드베이스를 가득 채웠다.',
|
||||
'The Code God spoke: "Let there be Functions."':
|
||||
'코드의 신이 말씀하셨다: "함수가 있으라."',
|
||||
'The Code God spoke: "Let there be Functions."': '코드의 신이 말씀하셨다: "함수가 있으라."',
|
||||
'And so the Digital Realm was born...': '그리하여 디지털 세계가 탄생하였다...',
|
||||
'But from the shadows emerged the Glitch.': '그러나 어둠 속에서 글리치가 출현했다.',
|
||||
'Now, a new hero awakens to defend the Code.':
|
||||
'이제, 코드를 수호할 새로운 영웅이 깨어난다.',
|
||||
'Now, a new hero awakens to defend the Code.': '이제, 코드를 수호할 새로운 영웅이 깨어난다.',
|
||||
'Your journey begins...': '당신의 여정이 시작된다...',
|
||||
|
||||
// Act I: 각성
|
||||
@@ -1191,11 +1188,9 @@ const Map<String, String> cinematicTranslationsKo = {
|
||||
'=== ACT II: GROWTH ===': '=== 제2막: 성장 ===',
|
||||
'With the Dragon slain, you join the Debugger Knights.':
|
||||
'드래곤을 처치하고, 당신은 디버거 기사단에 입단한다.',
|
||||
'The Corrupted Network spreads its infection...':
|
||||
'손상된 네트워크가 감염을 퍼뜨리고 있다...',
|
||||
'The Corrupted Network spreads its infection...': '손상된 네트워크가 감염을 퍼뜨리고 있다...',
|
||||
'A traitor among the Knights is revealed!': '기사단 내 배신자가 드러났다!',
|
||||
'The Memory Leak Hydra threatens all data.':
|
||||
'메모리 누수 히드라가 모든 데이터를 위협한다.',
|
||||
'The Memory Leak Hydra threatens all data.': '메모리 누수 히드라가 모든 데이터를 위협한다.',
|
||||
'You must stop the corruption before it consumes everything.':
|
||||
'모든 것을 삼키기 전에 손상을 멈춰야 한다.',
|
||||
|
||||
@@ -1206,20 +1201,16 @@ const Map<String, String> cinematicTranslationsKo = {
|
||||
'고대 컴파일러가 당신에게 시련을 건넨다.',
|
||||
'A companion falls... their sacrifice not in vain.':
|
||||
'동료가 쓰러진다... 그들의 희생은 헛되지 않으리.',
|
||||
'The Buffer Overflow Titan guards the gate.':
|
||||
'버퍼 오버플로우 타이탄이 문을 지키고 있다.',
|
||||
'The Buffer Overflow Titan guards the gate.': '버퍼 오버플로우 타이탄이 문을 지키고 있다.',
|
||||
'Only through great sacrifice can you proceed.':
|
||||
'오직 큰 희생을 통해서만 앞으로 나아갈 수 있다.',
|
||||
|
||||
// Act IV: 결전
|
||||
'=== ACT IV: CONFRONTATION ===': '=== 제4막: 결전 ===',
|
||||
"The Glitch God's Citadel looms before you.":
|
||||
'글리치 신의 성채가 눈앞에 어렴풋이 보인다.',
|
||||
'Former enemies unite against the common threat.':
|
||||
'이전의 적들이 공동의 위협에 맞서 연합한다.',
|
||||
"The Glitch God's Citadel looms before you.": '글리치 신의 성채가 눈앞에 어렴풋이 보인다.',
|
||||
'Former enemies unite against the common threat.': '이전의 적들이 공동의 위협에 맞서 연합한다.',
|
||||
'The Final Alliance is forged.': '최후의 동맹이 결성되었다.',
|
||||
'The Kernel Panic Archon blocks your path.':
|
||||
'커널 패닉 아르콘이 당신의 길을 막는다.',
|
||||
'The Kernel Panic Archon blocks your path.': '커널 패닉 아르콘이 당신의 길을 막는다.',
|
||||
'One final battle before the end...': '종말 전의 마지막 전투...',
|
||||
|
||||
// Act V: 종말
|
||||
@@ -1227,13 +1218,11 @@ const Map<String, String> cinematicTranslationsKo = {
|
||||
'The Glitch God reveals its true form.': '글리치 신이 진정한 모습을 드러낸다.',
|
||||
'Reality itself begins to corrupt.': '현실 그 자체가 손상되기 시작한다.',
|
||||
'All hope rests upon your shoulders.': '모든 희망이 당신의 어깨에 달려 있다.',
|
||||
'The final battle for the Codebase begins!':
|
||||
'코드베이스를 위한 최후의 전투가 시작된다!',
|
||||
'The final battle for the Codebase begins!': '코드베이스를 위한 최후의 전투가 시작된다!',
|
||||
|
||||
// 엔딩
|
||||
'=== THE END ===': '=== 완결 ===',
|
||||
'The Glitch God falls. The corruption fades.':
|
||||
'글리치 신이 쓰러진다. 손상이 사라진다.',
|
||||
'The Glitch God falls. The corruption fades.': '글리치 신이 쓰러진다. 손상이 사라진다.',
|
||||
'System Reboot initiated...': '시스템 재부팅 시작...',
|
||||
'Peace returns to the Digital Realm.': '디지털 세계에 평화가 돌아온다.',
|
||||
'Your legend will be compiled into the eternal logs.':
|
||||
@@ -1505,37 +1494,37 @@ const Map<String, String> additionalItemOfsTranslationsKo = {
|
||||
|
||||
/// 모든 몬스터 번역을 통합하여 반환
|
||||
Map<String, String> get allMonsterTranslationsKo => {
|
||||
...monsterTranslationsKo,
|
||||
...advancedMonsterTranslationsKo,
|
||||
};
|
||||
...monsterTranslationsKo,
|
||||
...advancedMonsterTranslationsKo,
|
||||
};
|
||||
|
||||
/// 모든 아이템 속성 번역을 통합하여 반환
|
||||
Map<String, String> get allItemAttribTranslationsKo => {
|
||||
...itemAttribTranslationsKo,
|
||||
...additionalItemAttribTranslationsKo,
|
||||
};
|
||||
...itemAttribTranslationsKo,
|
||||
...additionalItemAttribTranslationsKo,
|
||||
};
|
||||
|
||||
/// 모든 아이템 접미사("~의") 번역을 통합하여 반환
|
||||
Map<String, String> get allItemOfsTranslationsKo => {
|
||||
...itemOfsTranslationsKo,
|
||||
...additionalItemOfsTranslationsKo,
|
||||
};
|
||||
...itemOfsTranslationsKo,
|
||||
...additionalItemOfsTranslationsKo,
|
||||
};
|
||||
|
||||
/// 모든 드롭 아이템 번역을 통합하여 반환
|
||||
Map<String, String> get allDropTranslationsKo => {
|
||||
...boringItemTranslationsKo,
|
||||
...dropItemTranslationsKo,
|
||||
...additionalDropTranslationsKo,
|
||||
};
|
||||
...boringItemTranslationsKo,
|
||||
...dropItemTranslationsKo,
|
||||
...additionalDropTranslationsKo,
|
||||
};
|
||||
|
||||
/// 모든 갑옷 번역을 통합하여 반환
|
||||
Map<String, String> get allArmorTranslationsKo => {
|
||||
...armorTranslationsKo,
|
||||
...additionalArmorTranslationsKo,
|
||||
};
|
||||
...armorTranslationsKo,
|
||||
...additionalArmorTranslationsKo,
|
||||
};
|
||||
|
||||
/// 모든 방패 번역을 통합하여 반환
|
||||
Map<String, String> get allShieldTranslationsKo => {
|
||||
...shieldTranslationsKo,
|
||||
...additionalShieldTranslationsKo,
|
||||
};
|
||||
...shieldTranslationsKo,
|
||||
...additionalShieldTranslationsKo,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -80,18 +80,12 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
text: 'Now, a new hero awakens to defend the Code.',
|
||||
durationMs: 3500,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'Your journey begins...',
|
||||
durationMs: 2500,
|
||||
),
|
||||
CinematicStep(text: 'Your journey begins...', durationMs: 2500),
|
||||
],
|
||||
|
||||
// Act I: 각성 (레벨 1-20)
|
||||
StoryAct.act1: [
|
||||
CinematicStep(
|
||||
text: '=== ACT I: AWAKENING ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== ACT I: AWAKENING ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'You have proven yourself against the lesser bugs.',
|
||||
durationMs: 3000,
|
||||
@@ -114,10 +108,7 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
|
||||
// Act II: 성장 (레벨 21-40)
|
||||
StoryAct.act2: [
|
||||
CinematicStep(
|
||||
text: '=== ACT II: GROWTH ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== ACT II: GROWTH ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'With the Dragon slain, you join the Debugger Knights.',
|
||||
durationMs: 3500,
|
||||
@@ -144,10 +135,7 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
|
||||
// Act III: 시련 (레벨 41-60)
|
||||
StoryAct.act3: [
|
||||
CinematicStep(
|
||||
text: '=== ACT III: TRIALS ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== ACT III: TRIALS ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'The path leads to the Null Kingdom...',
|
||||
asciiArt: _asciiNullKingdom,
|
||||
@@ -174,10 +162,7 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
|
||||
// Act IV: 결전 (레벨 61-80)
|
||||
StoryAct.act4: [
|
||||
CinematicStep(
|
||||
text: '=== ACT IV: CONFRONTATION ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== ACT IV: CONFRONTATION ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: "The Glitch God's Citadel looms before you.",
|
||||
asciiArt: _asciiCitadel,
|
||||
@@ -187,36 +172,24 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
text: 'Former enemies unite against the common threat.',
|
||||
durationMs: 3500,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'The Final Alliance is forged.',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: 'The Final Alliance is forged.', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'The Kernel Panic Archon blocks your path.',
|
||||
asciiArt: _asciiArchon,
|
||||
durationMs: 4000,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'One final battle before the end...',
|
||||
durationMs: 3500,
|
||||
),
|
||||
CinematicStep(text: 'One final battle before the end...', durationMs: 3500),
|
||||
],
|
||||
|
||||
// Act V: 종말 (레벨 81-100)
|
||||
StoryAct.act5: [
|
||||
CinematicStep(
|
||||
text: '=== ACT V: ENDGAME ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== ACT V: ENDGAME ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'The Glitch God reveals its true form.',
|
||||
asciiArt: _asciiGlitchGod,
|
||||
durationMs: 4000,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'Reality itself begins to corrupt.',
|
||||
durationMs: 3500,
|
||||
),
|
||||
CinematicStep(text: 'Reality itself begins to corrupt.', durationMs: 3500),
|
||||
CinematicStep(
|
||||
text: 'All hope rests upon your shoulders.',
|
||||
durationMs: 3000,
|
||||
@@ -229,19 +202,13 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
|
||||
// 엔딩: 시스템 재부팅, 평화 회복
|
||||
StoryAct.ending: [
|
||||
CinematicStep(
|
||||
text: '=== THE END ===',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: '=== THE END ===', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'The Glitch God falls. The corruption fades.',
|
||||
asciiArt: _asciiVictory,
|
||||
durationMs: 4000,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'System Reboot initiated...',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: 'System Reboot initiated...', durationMs: 3000),
|
||||
CinematicStep(
|
||||
text: 'Peace returns to the Digital Realm.',
|
||||
durationMs: 3500,
|
||||
@@ -250,15 +217,8 @@ const Map<StoryAct, List<CinematicStep>> cinematicData = {
|
||||
text: 'Your legend will be compiled into the eternal logs.',
|
||||
durationMs: 4000,
|
||||
),
|
||||
CinematicStep(
|
||||
text: 'THE END',
|
||||
asciiArt: _asciiTheEnd,
|
||||
durationMs: 5000,
|
||||
),
|
||||
CinematicStep(
|
||||
text: '...or is it?',
|
||||
durationMs: 3000,
|
||||
),
|
||||
CinematicStep(text: 'THE END', asciiArt: _asciiTheEnd, durationMs: 5000),
|
||||
CinematicStep(text: '...or is it?', durationMs: 3000),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user