Compare commits
4 Commits
b48cbb844e
...
c55530d3be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c55530d3be | ||
|
|
0865f842a0 | ||
|
|
4307485d49 | ||
|
|
828debfb08 |
@@ -22,6 +22,16 @@ bool get isKoreanLocale => _currentLocale == 'ko';
|
|||||||
/// 일본어 여부 확인
|
/// 일본어 여부 확인
|
||||||
bool get isJapaneseLocale => _currentLocale == 'ja';
|
bool get isJapaneseLocale => _currentLocale == 'ja';
|
||||||
|
|
||||||
|
/// 각 단어 첫 글자를 대문자로 변환 (Title Case)
|
||||||
|
///
|
||||||
|
/// 예: "syntax error" → "Syntax Error"
|
||||||
|
String _toTitleCase(String text) {
|
||||||
|
return text.split(' ').map((word) {
|
||||||
|
if (word.isEmpty) return word;
|
||||||
|
return word[0].toUpperCase() + word.substring(1).toLowerCase();
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 프롤로그 텍스트
|
// 프롤로그 텍스트
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -103,6 +113,13 @@ String taskSelling(String itemDescription) {
|
|||||||
// 부활 시퀀스 메시지
|
// 부활 시퀀스 메시지
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
/// 부활 애니메이션 중 표시 메시지
|
||||||
|
String get animationResurrecting {
|
||||||
|
if (isKoreanLocale) return '부활 중...';
|
||||||
|
if (isJapaneseLocale) return '復活中...';
|
||||||
|
return 'Resurrecting...';
|
||||||
|
}
|
||||||
|
|
||||||
String get taskReturningToTown {
|
String get taskReturningToTown {
|
||||||
if (isKoreanLocale) return '마을로 귀환 중...';
|
if (isKoreanLocale) return '마을로 귀환 중...';
|
||||||
if (isJapaneseLocale) return '町に戻っている...';
|
if (isJapaneseLocale) return '町に戻っている...';
|
||||||
@@ -149,10 +166,10 @@ String get deathNoSacrificeNeeded {
|
|||||||
return 'No sacrifice needed';
|
return 'No sacrifice needed';
|
||||||
}
|
}
|
||||||
|
|
||||||
String get deathGoldRemaining {
|
String get deathCoinRemaining {
|
||||||
if (isKoreanLocale) return '남은 골드';
|
if (isKoreanLocale) return '남은 코인';
|
||||||
if (isJapaneseLocale) return '残りゴールド';
|
if (isJapaneseLocale) return '残りコイン';
|
||||||
return 'Gold Remaining';
|
return 'Coin Remaining';
|
||||||
}
|
}
|
||||||
|
|
||||||
String get deathResurrect {
|
String get deathResurrect {
|
||||||
@@ -879,14 +896,23 @@ String namedMonsterFormat(String generatedName, String monsterType) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/// 몬스터 이름 번역 (기본 + 고급 몬스터 포함)
|
/// 몬스터 이름 번역 (기본 + 고급 몬스터 포함)
|
||||||
|
///
|
||||||
|
/// 대소문자 무시 검색: "syntax error" → "Syntax Error"로 변환 후 검색
|
||||||
String translateMonster(String englishName) {
|
String translateMonster(String englishName) {
|
||||||
|
// 대소문자 무시를 위해 Title Case로 변환
|
||||||
|
final titleCaseName = _toTitleCase(englishName);
|
||||||
|
|
||||||
if (isKoreanLocale) {
|
if (isKoreanLocale) {
|
||||||
return monsterTranslationsKo[englishName] ??
|
return monsterTranslationsKo[titleCaseName] ??
|
||||||
|
advancedMonsterTranslationsKo[titleCaseName] ??
|
||||||
|
monsterTranslationsKo[englishName] ??
|
||||||
advancedMonsterTranslationsKo[englishName] ??
|
advancedMonsterTranslationsKo[englishName] ??
|
||||||
englishName;
|
englishName;
|
||||||
}
|
}
|
||||||
if (isJapaneseLocale) {
|
if (isJapaneseLocale) {
|
||||||
return monsterTranslationsJa[englishName] ??
|
return monsterTranslationsJa[titleCaseName] ??
|
||||||
|
advancedMonsterTranslationsJa[titleCaseName] ??
|
||||||
|
monsterTranslationsJa[englishName] ??
|
||||||
advancedMonsterTranslationsJa[englishName] ??
|
advancedMonsterTranslationsJa[englishName] ??
|
||||||
englishName;
|
englishName;
|
||||||
}
|
}
|
||||||
@@ -1043,15 +1069,18 @@ String translateItemNameL10n(String itemString) {
|
|||||||
final words = itemString.split(' ');
|
final words = itemString.split(' ');
|
||||||
if (words.length >= 2) {
|
if (words.length >= 2) {
|
||||||
// 2-1. 마지막 2단어가 드롭 아이템인지 먼저 확인 (예: "outdated syntax")
|
// 2-1. 마지막 2단어가 드롭 아이템인지 먼저 확인 (예: "outdated syntax")
|
||||||
|
// boringItemTranslations도 확인 (2단어 boringItem: "null pointer" 등)
|
||||||
if (words.length >= 3) {
|
if (words.length >= 3) {
|
||||||
final lastTwoWords = '${words[words.length - 2]} ${words.last}'
|
final lastTwoWords = '${words[words.length - 2]} ${words.last}'
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
final dropKo2 =
|
final dropKo2 =
|
||||||
dropItemTranslationsKo[lastTwoWords] ??
|
dropItemTranslationsKo[lastTwoWords] ??
|
||||||
additionalDropTranslationsKo[lastTwoWords];
|
additionalDropTranslationsKo[lastTwoWords] ??
|
||||||
|
boringItemTranslationsKo[lastTwoWords];
|
||||||
final dropJa2 =
|
final dropJa2 =
|
||||||
dropItemTranslationsJa[lastTwoWords] ??
|
dropItemTranslationsJa[lastTwoWords] ??
|
||||||
additionalDropTranslationsJa[lastTwoWords];
|
additionalDropTranslationsJa[lastTwoWords] ??
|
||||||
|
boringItemTranslationsJa[lastTwoWords];
|
||||||
|
|
||||||
if (dropKo2 != null || dropJa2 != null) {
|
if (dropKo2 != null || dropJa2 != null) {
|
||||||
final monsterPart = words.sublist(0, words.length - 2).join(' ');
|
final monsterPart = words.sublist(0, words.length - 2).join(' ');
|
||||||
@@ -1065,13 +1094,16 @@ String translateItemNameL10n(String itemString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2-2. 마지막 단어가 드롭 아이템인지 확인
|
// 2-2. 마지막 단어가 드롭 아이템인지 확인
|
||||||
|
// boringItemTranslations도 확인 (monsterPart로 사용되는 경우)
|
||||||
final lastWord = words.last.toLowerCase();
|
final lastWord = words.last.toLowerCase();
|
||||||
final dropKo =
|
final dropKo =
|
||||||
dropItemTranslationsKo[lastWord] ??
|
dropItemTranslationsKo[lastWord] ??
|
||||||
additionalDropTranslationsKo[lastWord];
|
additionalDropTranslationsKo[lastWord] ??
|
||||||
|
boringItemTranslationsKo[lastWord];
|
||||||
final dropJa =
|
final dropJa =
|
||||||
dropItemTranslationsJa[lastWord] ??
|
dropItemTranslationsJa[lastWord] ??
|
||||||
additionalDropTranslationsJa[lastWord];
|
additionalDropTranslationsJa[lastWord] ??
|
||||||
|
boringItemTranslationsJa[lastWord];
|
||||||
|
|
||||||
if (dropKo != null || dropJa != null) {
|
if (dropKo != null || dropJa != null) {
|
||||||
// 앞 부분은 몬스터 이름
|
// 앞 부분은 몬스터 이름
|
||||||
|
|||||||
@@ -171,12 +171,12 @@
|
|||||||
"equipSollerets": "Sollerets",
|
"equipSollerets": "Sollerets",
|
||||||
"@equipSollerets": { "description": "Sollerets equipment slot" },
|
"@equipSollerets": { "description": "Sollerets equipment slot" },
|
||||||
|
|
||||||
"gold": "Gold",
|
"gold": "Coin",
|
||||||
"@gold": { "description": "Gold label" },
|
"@gold": { "description": "Coin label" },
|
||||||
|
|
||||||
"goldAmount": "Gold: {amount}",
|
"goldAmount": "Coin: {amount}",
|
||||||
"@goldAmount": {
|
"@goldAmount": {
|
||||||
"description": "Gold with amount",
|
"description": "Coin with amount",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"amount": { "type": "int" }
|
"amount": { "type": "int" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,8 @@
|
|||||||
"equipCuisses": "Cuisses",
|
"equipCuisses": "Cuisses",
|
||||||
"equipGreaves": "Greaves",
|
"equipGreaves": "Greaves",
|
||||||
"equipSollerets": "Sollerets",
|
"equipSollerets": "Sollerets",
|
||||||
"gold": "Gold",
|
"gold": "コイン",
|
||||||
"goldAmount": "Gold: {amount}",
|
"goldAmount": "コイン: {amount}",
|
||||||
"prologue": "Prologue",
|
"prologue": "Prologue",
|
||||||
"actNumber": "Act {number}",
|
"actNumber": "Act {number}",
|
||||||
"noActiveQuests": "No active quests",
|
"noActiveQuests": "No active quests",
|
||||||
|
|||||||
@@ -56,8 +56,8 @@
|
|||||||
"equipCuisses": "허벅지보호대",
|
"equipCuisses": "허벅지보호대",
|
||||||
"equipGreaves": "정강이보호대",
|
"equipGreaves": "정강이보호대",
|
||||||
"equipSollerets": "철제 신발",
|
"equipSollerets": "철제 신발",
|
||||||
"gold": "골드",
|
"gold": "코인",
|
||||||
"goldAmount": "골드: {amount}",
|
"goldAmount": "코인: {amount}",
|
||||||
"prologue": "프롤로그",
|
"prologue": "프롤로그",
|
||||||
"actNumber": "{number}막",
|
"actNumber": "{number}막",
|
||||||
"noActiveQuests": "진행 중인 퀘스트 없음",
|
"noActiveQuests": "진행 중인 퀘스트 없음",
|
||||||
|
|||||||
@@ -431,16 +431,16 @@ abstract class L10n {
|
|||||||
/// **'Sollerets'**
|
/// **'Sollerets'**
|
||||||
String get equipSollerets;
|
String get equipSollerets;
|
||||||
|
|
||||||
/// Gold label
|
/// Coin label
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Gold'**
|
/// **'Coin'**
|
||||||
String get gold;
|
String get gold;
|
||||||
|
|
||||||
/// Gold with amount
|
/// Coin with amount
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Gold: {amount}'**
|
/// **'Coin: {amount}'**
|
||||||
String goldAmount(int amount);
|
String goldAmount(int amount);
|
||||||
|
|
||||||
/// Prologue plot stage
|
/// Prologue plot stage
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ class L10nEn extends L10n {
|
|||||||
String get equipSollerets => 'Sollerets';
|
String get equipSollerets => 'Sollerets';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get gold => 'Gold';
|
String get gold => 'Coin';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String goldAmount(int amount) {
|
String goldAmount(int amount) {
|
||||||
return 'Gold: $amount';
|
return 'Coin: $amount';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ class L10nJa extends L10n {
|
|||||||
String get equipSollerets => 'Sollerets';
|
String get equipSollerets => 'Sollerets';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get gold => 'Gold';
|
String get gold => 'コイン';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String goldAmount(int amount) {
|
String goldAmount(int amount) {
|
||||||
return 'Gold: $amount';
|
return 'コイン: $amount';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ class L10nKo extends L10n {
|
|||||||
String get equipSollerets => '철제 신발';
|
String get equipSollerets => '철제 신발';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get gold => '골드';
|
String get gold => '코인';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String goldAmount(int amount) {
|
String goldAmount(int amount) {
|
||||||
return '골드: $amount';
|
return '코인: $amount';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/foundation.dart'
|
import 'package:flutter/foundation.dart'
|
||||||
show kIsWeb, defaultTargetPlatform, TargetPlatform;
|
show kIsWeb, defaultTargetPlatform, TargetPlatform;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart' show SchedulerBinding, SchedulerPhase;
|
||||||
|
|
||||||
import 'package:askiineverdie/data/game_text_l10n.dart' as game_l10n;
|
import 'package:askiineverdie/data/game_text_l10n.dart' as game_l10n;
|
||||||
import 'package:askiineverdie/data/skill_data.dart';
|
import 'package:askiineverdie/data/skill_data.dart';
|
||||||
@@ -428,8 +429,19 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
|||||||
if (state != null) {
|
if (state != null) {
|
||||||
_checkSpecialEvents(state);
|
_checkSpecialEvents(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WASM 안정성: 프레임 빌드 중이면 다음 프레임까지 대기
|
||||||
|
if (SchedulerBinding.instance.schedulerPhase ==
|
||||||
|
SchedulerPhase.persistentCallbacks) {
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 캐로셀 레이아웃 사용 여부 판단
|
/// 캐로셀 레이아웃 사용 여부 판단
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -147,7 +147,15 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
|
|||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = null;
|
_timer = null;
|
||||||
} else {
|
} else {
|
||||||
// 재개: 애니메이션 재시작 (현재 프레임 유지)
|
// 재개 시: specialAnimation 동기화 (isPaused와 동시에 변경될 수 있음)
|
||||||
|
// 예: 부활 시 isPaused가 true→false로 바뀌면서 동시에
|
||||||
|
// specialAnimation이 null→resurrection으로 변경됨
|
||||||
|
if (widget.specialAnimation != _currentSpecialAnimation) {
|
||||||
|
_currentSpecialAnimation = widget.specialAnimation;
|
||||||
|
_updateAnimation(); // _updateAnimation이 타이머 재시작도 처리함
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 일반 재개: 애니메이션 재시작 (현재 프레임 유지)
|
||||||
_restartTimer();
|
_restartTimer();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class DeathOverlay extends StatelessWidget {
|
|||||||
_buildInfoRow(
|
_buildInfoRow(
|
||||||
context,
|
context,
|
||||||
icon: Icons.monetization_on_outlined,
|
icon: Icons.monetization_on_outlined,
|
||||||
label: l10n.deathGoldRemaining,
|
label: l10n.deathCoinRemaining,
|
||||||
value: _formatGold(deathInfo.goldAtDeath),
|
value: _formatGold(deathInfo.goldAtDeath),
|
||||||
isNegative: false,
|
isNegative: false,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -609,6 +609,19 @@ class _EnhancedAnimationPanelState extends State<EnhancedAnimationPanel>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 현재 상태에 맞는 메시지 반환
|
||||||
|
///
|
||||||
|
/// 특수 애니메이션(부활 등) 중에는 해당 메시지 표시
|
||||||
|
String _getStatusMessage() {
|
||||||
|
// 부활 애니메이션 중에는 부활 메시지 표시
|
||||||
|
if (widget.specialAnimation == AsciiAnimationType.resurrection) {
|
||||||
|
return l10n.animationResurrecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본: 현재 태스크 캡션
|
||||||
|
return widget.progress.currentTask.caption;
|
||||||
|
}
|
||||||
|
|
||||||
/// 태스크 프로그레스 바
|
/// 태스크 프로그레스 바
|
||||||
Widget _buildTaskProgress() {
|
Widget _buildTaskProgress() {
|
||||||
final task = widget.progress.task;
|
final task = widget.progress.task;
|
||||||
@@ -620,7 +633,7 @@ class _EnhancedAnimationPanelState extends State<EnhancedAnimationPanel>
|
|||||||
children: [
|
children: [
|
||||||
// 캡션
|
// 캡션
|
||||||
Text(
|
Text(
|
||||||
widget.progress.currentTask.caption,
|
_getStatusMessage(),
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:askiineverdie/data/game_text_l10n.dart' as game_l10n;
|
||||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||||
import 'package:askiineverdie/src/core/animation/ascii_animation_type.dart';
|
import 'package:askiineverdie/src/core/animation/ascii_animation_type.dart';
|
||||||
import 'package:askiineverdie/src/core/model/combat_event.dart';
|
import 'package:askiineverdie/src/core/model/combat_event.dart';
|
||||||
@@ -87,9 +88,7 @@ class TaskProgressPanel extends StatelessWidget {
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
progress.currentTask.caption.isNotEmpty
|
_getStatusMessage(context),
|
||||||
? progress.currentTask.caption
|
|
||||||
: L10n.of(context).welcomeMessage,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
@@ -154,6 +153,22 @@ class TaskProgressPanel extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 현재 상태에 맞는 메시지 반환
|
||||||
|
///
|
||||||
|
/// 특수 애니메이션(부활 등) 중에는 해당 메시지 표시
|
||||||
|
String _getStatusMessage(BuildContext context) {
|
||||||
|
// 부활 애니메이션 중에는 부활 메시지 표시
|
||||||
|
if (specialAnimation == AsciiAnimationType.resurrection) {
|
||||||
|
return game_l10n.animationResurrecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본: 현재 태스크 캡션 또는 환영 메시지
|
||||||
|
if (progress.currentTask.caption.isNotEmpty) {
|
||||||
|
return progress.currentTask.caption;
|
||||||
|
}
|
||||||
|
return L10n.of(context).welcomeMessage;
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildProgressBar(BuildContext context) {
|
Widget _buildProgressBar(BuildContext context) {
|
||||||
final progressValue = progress.task.max > 0
|
final progressValue = progress.task.max > 0
|
||||||
? (progress.task.position / progress.task.max).clamp(0.0, 1.0)
|
? (progress.task.position / progress.task.max).clamp(0.0, 1.0)
|
||||||
|
|||||||
Reference in New Issue
Block a user