From 3fdca904a2e69608c239747d91bebd1a75028597 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Mon, 15 Dec 2025 19:24:32 +0900 Subject: [PATCH] =?UTF-8?q?refactor(l10n):=20=EB=8F=99=EC=A0=95=20?= =?UTF-8?q?=EC=9C=A0=EB=B0=9C=20=ED=91=9C=ED=98=84=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=98=91=EC=A0=81=20=ED=91=9C=ED=98=84=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 몬스터 수식어 수정 (영어/한국어 모두) - dead→fallen, crippled→twisted, sick→tainted - undernourished→ravenous, baby→fledgling 등 - 고아/기아 관련 표현 개선 - orphan→이탈, starvation→고갈, hungry→탐욕스러운 - parentless→떠도는, Exploited→침해당한 - 일시정지 시 ASCII 애니메이션도 함께 정지하도록 수정 --- lib/data/game_text_l10n.dart | 20 +- lib/data/game_translations_ko.dart | 272 +++++++++--------- .../game/widgets/ascii_animation_card.dart | 70 +++++ .../game/widgets/task_progress_panel.dart | 1 + 4 files changed, 217 insertions(+), 146 deletions(-) diff --git a/lib/data/game_text_l10n.dart b/lib/data/game_text_l10n.dart index 450c29d..cf71d3e 100644 --- a/lib/data/game_text_l10n.dart +++ b/lib/data/game_text_l10n.dart @@ -171,19 +171,19 @@ String cinematicBetrayal6() => isKoreanLocale // 몬스터 수식어 // ============================================================================ -String modifierDead(String s) => isKoreanLocale ? '죽은 $s' : 'dead $s'; -String modifierComatose(String s) => isKoreanLocale ? '혼수상태의 $s' : 'comatose $s'; -String modifierCrippled(String s) => isKoreanLocale ? '불구의 $s' : 'crippled $s'; -String modifierSick(String s) => isKoreanLocale ? '병든 $s' : 'sick $s'; +String modifierDead(String s) => isKoreanLocale ? '쓰러진 $s' : 'fallen $s'; +String modifierComatose(String s) => isKoreanLocale ? '잠복하는 $s' : 'lurking $s'; +String modifierCrippled(String s) => isKoreanLocale ? '흉측한 $s' : 'twisted $s'; +String modifierSick(String s) => isKoreanLocale ? '오염된 $s' : 'tainted $s'; String modifierUndernourished(String s) => - isKoreanLocale ? '영양실조 $s' : 'undernourished $s'; + isKoreanLocale ? '굶주린 $s' : 'ravenous $s'; -String modifierFoetal(String s) => isKoreanLocale ? '원시 $s' : 'primordial $s'; -String modifierBaby(String s) => isKoreanLocale ? '미숙한 $s' : 'immature $s'; +String modifierFoetal(String s) => isKoreanLocale ? '태동기 $s' : 'nascent $s'; +String modifierBaby(String s) => isKoreanLocale ? '초기형 $s' : 'fledgling $s'; String modifierPreadolescent(String s) => - isKoreanLocale ? '성장 중인 $s' : 'growing $s'; -String modifierTeenage(String s) => isKoreanLocale ? '어린 $s' : 'young $s'; -String modifierUnderage(String s) => isKoreanLocale ? '경험 부족 $s' : 'inexperienced $s'; + isKoreanLocale ? '진화 중인 $s' : 'evolving $s'; +String modifierTeenage(String s) => isKoreanLocale ? '하급 $s' : 'lesser $s'; +String modifierUnderage(String s) => isKoreanLocale ? '불완전한 $s' : 'incomplete $s'; String modifierGreater(String s) => isKoreanLocale ? '상위 $s' : 'greater $s'; String modifierMassive(String s) => isKoreanLocale ? '거대한 $s' : 'massive $s'; diff --git a/lib/data/game_translations_ko.dart b/lib/data/game_translations_ko.dart index 52c8255..5fffdcc 100644 --- a/lib/data/game_translations_ko.dart +++ b/lib/data/game_translations_ko.dart @@ -148,43 +148,43 @@ const Map monsterTranslationsKo = { 'Deadlock': '데드락', 'Livelock': '라이브락', 'Priority Inversion': '우선순위 역전', - 'Thread Starvation': '스레드 기아', + 'Thread Starvation': '스레드 고갈', 'Heap Corruption': '힙 손상', 'Stack Smash': '스택 스매시', 'Memory Corruption': '메모리 손상', 'Data Race': '데이터 레이스', - 'Dangling Pointer': '댕글링 포인터', + 'Dangling Pointer': '끊어진 연결의 저주', // 레벨 11-20: 고급 버그들 'Kernel Panic': '커널 패닉', 'Blue Screen Beast': '블루 스크린 야수', 'Core Dump': '코어 덤프', - 'Segmentation Fault': '세그먼테이션 폴트', + 'Segmentation Fault': '영역 침범의 저주', 'Bus Error': '버스 오류', - 'Page Fault Phantom': '페이지 폴트 유령', + 'Page Fault Phantom': '잃어버린 기억의 유령', 'Cache Corruption': '캐시 손상', - 'TLB Miss Monster': 'TLB 미스 괴물', - 'DMA Error': 'DMA 오류', - 'Interrupt Storm': '인터럽트 폭풍', - 'Watchdog Timeout': '워치독 타임아웃', - 'Firmware Bug': '펌웨어 버그', - 'BIOS Corruption': 'BIOS 손상', - 'EFI Malware': 'EFI 악성코드', - 'Bootkit': '부트킷', - 'Rootkit': '루트킷', - 'Ring Zero Bug': '링 제로 버그', - 'Hypervisor Escape': '하이퍼바이저 탈출', - 'SMM Bug': 'SMM 버그', - 'Microcode Error': '마이크로코드 오류', - 'Spectre Variant': '스펙터 변종', - 'Meltdown Ghost': '멜트다운 유령', - 'Rowhammer': '로우해머', - 'Cold Boot Specter': '콜드 부트 망령', - 'DMA Attack': 'DMA 공격', - 'Side Channel Leak': '사이드 채널 누출', - 'Firmware Rootkit': '펌웨어 루트킷', - 'UEFI Implant': 'UEFI 임플란트', - 'Intel ME Bug': 'Intel ME 버그', + 'TLB Miss Monster': '길 잃은 기억의 괴물', + 'DMA Error': '직접 전송 오류', + 'Interrupt Storm': '방해 신호 폭풍', + 'Watchdog Timeout': '감시견의 한계', + 'Firmware Bug': '근원 코드의 버그', + 'BIOS Corruption': '근원 의식 손상', + 'EFI Malware': '근원 계약 악령', + 'Bootkit': '시작의 저주', + 'Rootkit': '뿌리 깊은 악령', + 'Ring Zero Bug': '최심부의 버그', + 'Hypervisor Escape': '상위 세계 탈출', + 'SMM Bug': '시스템 관리 버그', + 'Microcode Error': '미세 주문 오류', + 'Spectre Variant': '망령의 변종', + 'Meltdown Ghost': '붕괴의 유령', + 'Rowhammer': '행 파괴자', + 'Cold Boot Specter': '냉기 시동 망령', + 'DMA Attack': '직접 전송 공격', + 'Side Channel Leak': '틈새 누출', + 'Firmware Rootkit': '근원 뿌리악령', + 'UEFI Implant': '근원 계약 이식체', + 'Intel ME Bug': '관리 엔진 버그', // 레벨 21-30: 엘리트 위협들 'Advanced Persistent Threat': '지능형 지속 위협', @@ -194,9 +194,9 @@ const Map monsterTranslationsKo = { 'Watering Hole': '워터링 홀', 'Spear Phishing': '스피어 피싱', 'Living Off the Land': '자원 활용 공격', - 'Fileless Malware': '파일리스 악성코드', - 'Polymorphic Virus': '다형성 바이러스', - 'Metamorphic Engine': '변형 엔진', + 'Fileless Malware': '형체 없는 악령', + 'Polymorphic Virus': '변신하는 역병', + 'Metamorphic Engine': '변신 마법진', 'Code Cave Lurker': '코드 동굴 잠복자', // 레벨 31-40: 보스급 위협들 @@ -229,8 +229,8 @@ const Map monsterTranslationsKo = { 'The Glitch God': '글리치 신', // 코드 품질 관련 - 'Deprecated Function': '사용 중단 함수', - 'Legacy Code Zombie': '레거시 코드 좀비', + 'Deprecated Function': '잊힌 주문', + 'Legacy Code Zombie': '유산 코드 좀비', 'Spaghetti Code': '스파게티 코드', 'God Object': '갓 오브젝트', 'Circular Dependency': '순환 의존성', @@ -241,7 +241,7 @@ const Map monsterTranslationsKo = { 'Cargo Cult Code': '카고 컬트 코드', 'Dead Code Walker': '죽은 코드 워커', 'Zombie Process': '좀비 프로세스', - 'Orphan Thread': '고아 스레드', + 'Orphan Thread': '이탈 스레드', 'Phantom Pointer': '유령 포인터', 'Heisenbug': '하이젠버그', 'Schrodinger Bug': '슈뢰딩거 버그', @@ -261,34 +261,34 @@ const Map monsterTranslationsKo = { 'Privilege Escalation': '권한 상승', 'Lateral Movement': '측면 이동', 'Exfil Channel': '유출 채널', - 'C2 Beacon': 'C2 비콘', - 'DNS Tunnel': 'DNS 터널', - 'ICMP Shell': 'ICMP 쉘', - 'HTTP Backdoor': 'HTTP 백도어', - 'Reverse Shell': '리버스 쉘', - 'Bind Shell': '바인드 쉘', - 'Web Shell': '웹 쉘', - 'Cron Job Malware': '크론잡 악성코드', - 'Init Script Virus': '초기화 스크립트 바이러스', + 'C2 Beacon': '지휘 신호탑', + 'DNS Tunnel': '이름 해석 터널', + 'ICMP Shell': '반향 껍데기', + 'HTTP Backdoor': '전송 뒷문', + 'Reverse Shell': '역방향 껍데기', + 'Bind Shell': '묶인 껍데기', + 'Web Shell': '거미줄 껍데기', + 'Cron Job Malware': '예약 작업 악령', + 'Init Script Virus': '시작 주문 역병', // 코드 인젝션 기법 - 'Library Injection': '라이브러리 인젝션', - 'Process Hollowing': '프로세스 할로잉', - 'Thread Injection': '스레드 인젝션', - 'APC Injection': 'APC 인젝션', - 'Atom Bombing': '아톰 봄빙', - 'Process Doppelganging': '프로세스 도플갱잉', - 'Ghostwriting': '고스트라이팅', - 'Module Stomping': '모듈 스톰핑', - 'Reflective Loading': '리플렉티브 로딩', - 'Manual Mapping': '수동 매핑', - 'Syscall Stub': '시스콜 스텁', - 'Heaven Gate': '헤븐 게이트', + 'Library Injection': '마법서 침투', + 'Process Hollowing': '영혼 빼앗기', + 'Thread Injection': '실타래 침투', + 'APC Injection': '마법 주입 괴물', + 'Atom Bombing': '원소 폭발', + 'Process Doppelganging': '분신술의 괴물', + 'Ghostwriting': '유령의 필사', + 'Module Stomping': '마법진 덮어쓰기', + 'Reflective Loading': '거울 소환', + 'Manual Mapping': '수동 지도화', + 'Syscall Stub': '세계 문의 조각', + 'Heaven Gate': '천계의 문', // 비동기 및 메모리 관련 - 'Callback Hell': '콜백 지옥', - 'Promise Rejection': '프로미스 거부', - 'Event Loop Block': '이벤트 루프 블록', + 'Callback Hell': '되돌림의 지옥', + 'Promise Rejection': '서약 파기', + 'Event Loop Block': '사건 순환 봉쇄', 'Memory Pressure': '메모리 압박', 'Garbage Storm': '가비지 폭풍', 'Finalizer Bug': '파이널라이저 버그', @@ -318,50 +318,50 @@ const Map monsterTranslationsKo = { 'Lock Contention': '락 경합', 'Spin Lock Burn': '스핀 락 연소', 'False Sharing': '거짓 공유', - 'NUMA Bug': 'NUMA 버그', - 'Affinity Bug': '어피니티 버그', - 'Context Switch Storm': '컨텍스트 스위치 폭풍', - 'TLB Shootdown': 'TLB 슛다운', - 'IPI Storm': 'IPI 폭풍', + 'NUMA Bug': '비균일 기억 버그', + 'Affinity Bug': '친화력 버그', + 'Context Switch Storm': '상태 전환 폭풍', + 'TLB Shootdown': '기억 정화의 폭풍', + 'IPI Storm': '정령 신호 폭풍', 'Interrupt Disable Bug': '인터럽트 비활성화 버그', 'Preemption Bug': '선점 버그', - 'RCU Bug': 'RCU 버그', - 'Seqlock Bug': '시퀀스 락 버그', - 'RWLock Bug': '읽기쓰기 락 버그', - 'Futex Bug': 'Futex 버그', - 'Spinlock Bug': '스핀락 버그', - 'Barrier Bug': '배리어 버그', - 'Condition Variable Bug': '조건 변수 버그', - 'Semaphore Leak': '세마포어 누수', - 'Message Queue Bug': '메시지 큐 버그', + 'RCU Bug': '읽기 보호의 저주', + 'Seqlock Bug': '순서 봉인 버그', + 'RWLock Bug': '읽기쓰기 봉인 버그', + 'Futex Bug': '신속 봉인의 저주', + 'Spinlock Bug': '회전 봉인 버그', + 'Barrier Bug': '방벽 버그', + 'Condition Variable Bug': '조건 신호 버그', + 'Semaphore Leak': '신호기 누수', + 'Message Queue Bug': '전언 대기열 버그', 'Shared Memory Bug': '공유 메모리 버그', 'Pipe Deadlock': '파이프 데드락', 'Socket Leak': '소켓 누수', - 'Epoll Bug': 'Epoll 버그', - 'Kqueue Bug': 'Kqueue 버그', - 'IOCP Bug': 'IOCP 버그', - 'AIO Bug': 'AIO 버그', - 'Scatter Gather Bug': '스캐터 개더 버그', - 'Zero Copy Bug': '제로 카피 버그', - 'Splice Bug': '스플라이스 버그', - 'Vmsplice Bug': 'Vmsplice 버그', - 'Tee Bug': 'Tee 버그', - 'Fallocate Bug': 'Fallocate 버그', - 'Punch Hole Bug': '펀치 홀 버그', - 'Direct IO Bug': '다이렉트 IO 버그', + 'Epoll Bug': '사건 감시 버그', + 'Kqueue Bug': '커널 대기열 버그', + 'IOCP Bug': '입출력 완료 버그', + 'AIO Bug': '비동기 입출력 버그', + 'Scatter Gather Bug': '분산 수집 버그', + 'Zero Copy Bug': '직접 전달 버그', + 'Splice Bug': '연결 버그', + 'Vmsplice Bug': '가상 연결 버그', + 'Tee Bug': '분기 버그', + 'Fallocate Bug': '공간 할당 버그', + 'Punch Hole Bug': '빈 공간 버그', + 'Direct IO Bug': '직접 입출력 버그', 'Sync Bug': '동기화 버그', 'Datasync Bug': '데이터 동기화 버그', 'Journal Bug': '저널 버그', 'Inode Leak': 'Inode 누수', - 'Dentry Cache Bug': 'Dentry 캐시 버그', - 'Buffer Head Bug': '버퍼 헤드 버그', + 'Dentry Cache Bug': '디렉토리 캐시 버그', + 'Buffer Head Bug': '버퍼 머리 버그', 'Page Cache Bug': '페이지 캐시 버그', - 'Slab Leak': '슬랩 누수', - 'Kmalloc Bug': 'Kmalloc 버그', - 'Vmalloc Bug': 'Vmalloc 버그', - 'Highmem Bug': '상위 메모리 버그', - 'Lowmem Bug': '하위 메모리 버그', - 'OOM Killer': 'OOM 킬러', + 'Slab Leak': '판 누수', + 'Kmalloc Bug': '커널 할당 버그', + 'Vmalloc Bug': '가상 할당 버그', + 'Highmem Bug': '상층 기억 버그', + 'Lowmem Bug': '하층 기억 버그', + 'OOM Killer': '기억 고갈 처형자', // 폭탄 및 DoS 관련 'Fork Bomb': '포크 폭탄', @@ -643,24 +643,24 @@ const Map itemOfsTranslationsKo = { const Map offenseAttribTranslationsKo = { 'Compiled': '컴파일된', 'Optimized': '최적화된', - 'JIT-Enhanced': 'JIT 강화', + 'JIT-Enhanced': '즉시 강화', 'Parallel': '병렬', 'Multithreaded': '멀티스레드', - 'SIMD-Accelerated': 'SIMD 가속', - 'GPU-Powered': 'GPU 파워', + 'SIMD-Accelerated': '병렬 가속', + 'GPU-Powered': '시각 마력', 'Quantum-Enhanced': '양자 강화', - 'AI-Augmented': 'AI 증강', - 'Neural': '신경망', + 'AI-Augmented': '지능 증강', + 'Neural': '신경의', 'Transcendent': '초월적', }; /// 나쁜 공격 속성 한국어 번역 const Map offenseBadTranslationsKo = { - 'Interpreted': '인터프리트된', + 'Interpreted': '해석된', 'Unoptimized': '최적화 안 된', 'Buggy': '버그 많은', - 'Deprecated': '사용 중단된', - 'Legacy': '레거시', + 'Deprecated': '잊힌', + 'Legacy': '유산의', 'Bloated': '비대해진', 'Slow': '느린', 'Crashing': '충돌하는', @@ -682,18 +682,18 @@ const Map defenseAttribTranslationsKo = { /// 나쁜 방어 속성 한국어 번역 const Map defenseBadTranslationsKo = { - 'Deprecated': '사용 중단된', + 'Deprecated': '잊힌', 'Unpatched': '패치 안 된', 'Vulnerable': '취약한', - 'Exploited': '익스플로잇된', - 'Backdoored': '백도어된', + 'Exploited': '침해당한', + 'Backdoored': '뒷문 있는', 'Infected': '감염된', 'Compromised': '침해된', - 'Breached': '침투된', - 'Pwned': '해킹당한', + 'Breached': '뚫린', + 'Pwned': '정복당한', 'Cursed by Glitch': '글리치의 저주', - 'Legacy': '레거시', - 'End-of-life': '수명 종료', + 'Legacy': '유산의', + 'End-of-life': '수명 다한', 'Unsupported': '지원 안 되는', 'Buggy': '버그 많은', }; @@ -746,8 +746,8 @@ const Map boringItemTranslationsKo = { 'curly brace': '중괄호', 'null pointer': '널 포인터', 'empty string': '빈 문자열', - 'deprecated token': '사용 중단 토큰', - 'legacy code': '레거시 코드', + 'deprecated token': '잊힌 부적', + 'legacy code': '유산 코드', 'tab character': '탭 문자', 'whitespace': '공백 문자', 'comment block': '주석 블록', @@ -764,9 +764,9 @@ const Map boringItemTranslationsKo = { 'lint error': '린트 오류', 'syntax fragment': '구문 조각', 'broken link': '깨진 링크', - 'orphan process': '고아 프로세스', + 'orphan process': '이탈 프로세스', 'zombie thread': '좀비 스레드', - 'dangling pointer': '댕글링 포인터', + 'dangling pointer': '끊어진 연결', 'memory leak': '메모리 누수', 'buffer scrap': '버퍼 조각', 'bit bucket': '비트 버킷', @@ -821,7 +821,7 @@ const Map dropItemTranslationsKo = { 'null crystal': '널 결정', 'broken index': '깨진 인덱스', 'morphed type': '변형된 타입', - 'dangling reference': '댕글링 참조', + 'dangling reference': '끊어진 연결 조각', 'duplicate key': '중복 키', 'wrapped number': '래핑된 숫자', 'format specifier': '포맷 지정자', @@ -834,7 +834,7 @@ const Map dropItemTranslationsKo = { 'locked mutex': '잠긴 뮤텍스', 'spinning lock': '돌아가는 락', 'inverted queue': '역전된 큐', - 'hungry process': '굶주린 프로세스', + 'hungry process': '탐욕스러운 프로세스', 'corrupted block': '손상된 블록', 'crushed frame': '부서진 프레임', 'garbled bytes': '깨진 바이트들', @@ -849,7 +849,7 @@ const Map dropItemTranslationsKo = { 'bus token': '버스 토큰', 'missing page': '누락된 페이지', 'invalid cache': '무효 캐시', - 'translation fail': '변환 실패', + 'translation fail': '해석 실패', 'transfer error': '전송 오류', 'signal flood': '신호 홍수', 'expired timer': '만료된 타이머', @@ -862,7 +862,7 @@ const Map dropItemTranslationsKo = { 'vm breach': 'VM 침투', 'management mode': '관리 모드', 'cpu patch': 'CPU 패치', - 'speculative exec': '추측 실행', + 'speculative exec': '추측성 실행', 'kernel leak': '커널 누출', 'bit flip': '비트 플립', 'frozen memory': '얼어붙은 메모리', @@ -887,7 +887,7 @@ const Map dropItemTranslationsKo = { // 레벨 31-40 드롭 'propagating mass': '전파되는 덩어리', - 'c2 beacon': 'C2 비콘', + 'c2 beacon': '지휘 신호', 'encrypted key': '암호화된 키', 'mining rig': '채굴 장비', 'stolen data': '탈취된 데이터', @@ -914,30 +914,30 @@ const Map dropItemTranslationsKo = { 'primordial bug': '원초적 버그', // 추가 몬스터 드롭 (코드 품질, 공격 등) - 'old signature': '오래된 시그니처', - 'outdated syntax': '구식 문법', - 'tangled logic': '꼬인 로직', - 'monolithic blob': '모놀리식 덩어리', - 'loop reference': '루프 참조', - 'unexplained constant': '설명 없는 상수', - 'fixed string': '고정된 문자열', - 'shared state': '공유 상태', + 'old signature': '고대의 인장', + 'outdated syntax': '고대의 언어', + 'tangled logic': '꼬인 논리', + 'monolithic blob': '거대한 덩어리', + 'loop reference': '순환 참조', + 'unexplained constant': '수수께끼의 상수', + 'fixed string': '고정된 문장', + 'shared state': '공유된 상태', 'duplicate bug': '중복 버그', - 'mysterious ritual': '신비로운 의식', - 'unreachable block': '도달 불가 블록', - 'undead thread': '언데드 스레드', - 'parentless process': '부모 없는 프로세스', - 'ghost reference': '유령 참조', - 'observer effect': '관찰자 효과', + 'mysterious ritual': '신비한 의식', + 'unreachable block': '닿을 수 없는 봉인', + 'undead thread': '언데드 실', + 'parentless process': '떠도는 영혼', + 'ghost reference': '유령의 연결', + 'observer effect': '관찰의 효과', 'quantum state': '양자 상태', - 'deterministic flaw': '결정론적 결함', - 'fractal complexity': '프랙탈 복잡도', - 'catastrophic fail': '재앙적 실패', - 'documentation bug': '문서화 버그', - 'stealth code': '스텔스 코드', + 'deterministic flaw': '운명의 결함', + 'fractal complexity': '무한 복잡도', + 'catastrophic fail': '대재앙', + 'documentation bug': '기록의 오류', + 'stealth code': '은신 코드', 'compressed threat': '압축된 위협', - 'encrypted payload': '암호화된 페이로드', - 'delivery mechanism': '전달 메커니즘', + 'encrypted payload': '암호화된 짐', + 'delivery mechanism': '전달 장치', 'stage one': '1단계', 'stage two': '2단계', 'startup entry': '시작 항목', @@ -987,7 +987,7 @@ const Map dropItemTranslationsKo = { 'db resource': 'DB 리소스', 'unclosed io': '닫히지 않은 IO', 'uncommitted tx': '커밋 안 된 TX', - 'orphan session': '고아 세션', + 'orphan session': '이탈 세션', 'unlimited cache': '무제한 캐시', 'unbounded queue': '무한 큐', 'circular fail': '순환 실패', diff --git a/lib/src/features/game/widgets/ascii_animation_card.dart b/lib/src/features/game/widgets/ascii_animation_card.dart index 3bd2517..3cda676 100644 --- a/lib/src/features/game/widgets/ascii_animation_card.dart +++ b/lib/src/features/game/widgets/ascii_animation_card.dart @@ -28,10 +28,14 @@ class AsciiAnimationCard extends StatefulWidget { this.shieldName, this.characterLevel, this.monsterLevel, + this.isPaused = false, }); final TaskType taskType; + /// 일시정지 상태 (true면 애니메이션 정지) + final bool isPaused; + /// 전투 중인 몬스터 기본 이름 (kill 타입일 때만 사용) final String? monsterBaseName; final AsciiColorTheme colorTheme; @@ -95,6 +99,18 @@ class _AsciiAnimationCardState extends State { void didUpdateWidget(AsciiAnimationCard oldWidget) { super.didUpdateWidget(oldWidget); + // 일시정지 상태 변경 처리 + if (oldWidget.isPaused != widget.isPaused) { + if (widget.isPaused) { + _timer?.cancel(); + _timer = null; + } else { + // 재개: 애니메이션 재시작 (현재 프레임 유지) + _restartTimer(); + } + return; + } + // 특수 애니메이션이 변경되었으면 업데이트 if (oldWidget.specialAnimation != widget.specialAnimation) { _currentSpecialAnimation = widget.specialAnimation; @@ -116,6 +132,51 @@ class _AsciiAnimationCardState extends State { } } + /// 현재 상태를 유지하면서 타이머만 재시작 + void _restartTimer() { + _timer?.cancel(); + + // 특수 애니메이션 타이머 재시작 + if (_currentSpecialAnimation != null) { + _timer = Timer.periodic( + Duration(milliseconds: _animationData.frameIntervalMs), + (_) { + if (mounted) { + setState(() { + _currentFrame++; + if (_currentFrame >= _animationData.frames.length) { + _currentSpecialAnimation = null; + _updateAnimation(); + } + }); + } + }, + ); + return; + } + + // 전투 모드 타이머 재시작 + if (_isBattleMode) { + _timer = Timer.periodic( + const Duration(milliseconds: 200), + (_) => _advanceBattleFrame(), + ); + } else { + // 일반 애니메이션 타이머 재시작 + _timer = Timer.periodic( + Duration(milliseconds: _animationData.frameIntervalMs), + (_) { + if (mounted) { + setState(() { + _currentFrame = + (_currentFrame + 1) % _animationData.frames.length; + }); + } + }, + ); + } + } + void _updateAnimation() { _timer?.cancel(); @@ -125,6 +186,9 @@ class _AsciiAnimationCardState extends State { _animationData = getAnimationData(_currentSpecialAnimation!); _currentFrame = 0; + // 일시정지 상태면 타이머 시작하지 않음 + if (widget.isPaused) return; + // 특수 애니메이션은 한 번 재생 후 종료 _timer = Timer.periodic( Duration(milliseconds: _animationData.frameIntervalMs), @@ -156,6 +220,9 @@ class _AsciiAnimationCardState extends State { _phaseIndex = 0; _phaseFrameCount = 0; + // 일시정지 상태면 타이머 시작하지 않음 + if (widget.isPaused) return; + _timer = Timer.periodic( const Duration(milliseconds: 200), (_) => _advanceBattleFrame(), @@ -165,6 +232,9 @@ class _AsciiAnimationCardState extends State { _animationData = getAnimationData(animationType); _currentFrame = 0; + // 일시정지 상태면 타이머 시작하지 않음 + if (widget.isPaused) return; + _timer = Timer.periodic( Duration(milliseconds: _animationData.frameIntervalMs), (_) { diff --git a/lib/src/features/game/widgets/task_progress_panel.dart b/lib/src/features/game/widgets/task_progress_panel.dart index e53f820..9b5166c 100644 --- a/lib/src/features/game/widgets/task_progress_panel.dart +++ b/lib/src/features/game/widgets/task_progress_panel.dart @@ -68,6 +68,7 @@ class TaskProgressPanel extends StatelessWidget { shieldName: shieldName, characterLevel: characterLevel, monsterLevel: monsterLevel, + isPaused: isPaused, ), ), const SizedBox(height: 8),