Compare commits
278 Commits
3fdca904a2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc15198c57 | ||
|
|
c56e76b176 | ||
|
|
dadd25837d | ||
|
|
e13e8032d9 | ||
|
|
864a866039 | ||
|
|
6ddbf23816 | ||
|
|
1a8858a3b1 | ||
|
|
faaa5af54e | ||
|
|
68284323c8 | ||
|
|
8f351df0b6 | ||
|
|
8fcb7bf2b7 | ||
|
|
d07a0c5554 | ||
|
|
bccb5cb188 | ||
|
|
6994f4fc9b | ||
|
|
ea64571eed | ||
|
|
1ff4208f06 | ||
|
|
067c295163 | ||
|
|
ea6ebf55f5 | ||
|
|
41f73bc14c | ||
|
|
54a2d128aa | ||
|
|
73e96bcf50 | ||
|
|
e37a2ddfa8 | ||
|
|
3be9d346dd | ||
|
|
d9a2fe358c | ||
|
|
faf87eccb0 | ||
|
|
7f44e95163 | ||
|
|
742b0d1773 | ||
|
|
97b40ccb1f | ||
|
|
75bc39528f | ||
|
|
c5eaecfa6a | ||
|
|
c577f9deed | ||
|
|
e516076ce8 | ||
|
|
7b9f1f87a6 | ||
|
|
2b4ea44623 | ||
|
|
d5c46ad04a | ||
|
|
71740abe8f | ||
|
|
0cccc17f1f | ||
|
|
5cccd28b77 | ||
|
|
109b4eb678 | ||
|
|
d90543dd86 | ||
|
|
03ff9c1ce8 | ||
|
|
94c2ed1ca1 | ||
|
|
19faa9ea39 | ||
|
|
ffc19c7ca6 | ||
|
|
724de9a63c | ||
|
|
03aa117710 | ||
|
|
f51bf8c540 | ||
|
|
d41dd0fb90 | ||
|
|
9f077d74a1 | ||
|
|
748160d543 | ||
|
|
c95e4de5a4 | ||
|
|
c95fb7f4b4 | ||
|
|
b6d5cd2abd | ||
|
|
b272ef8f08 | ||
|
|
37c118b0f8 | ||
|
|
28d3e53bab | ||
|
|
77f3f1d46b | ||
|
|
6662a5dcfb | ||
|
|
724f08f56d | ||
|
|
306715ca26 | ||
|
|
9e5472728f | ||
|
|
93f29f6c33 | ||
|
|
a2b5bb7dc0 | ||
|
|
b8a4d73461 | ||
|
|
7e1936b34f | ||
|
|
9599a33a8f | ||
|
|
c41d15405f | ||
|
|
b0913a24ff | ||
|
|
525e231c06 | ||
|
|
58cc1fddb5 | ||
|
|
60db6b2ec9 | ||
|
|
2427f58018 | ||
|
|
cbf96c2c0e | ||
|
|
e882093d37 | ||
|
|
2435bcffb7 | ||
|
|
ac76060222 | ||
|
|
23f15f41d3 | ||
|
|
133d516b94 | ||
|
|
07fb105d7c | ||
|
|
e77c3c4a05 | ||
|
|
f466e1c408 | ||
|
|
a41984d998 | ||
|
|
c33c1ff470 | ||
|
|
a4bbc6c7cb | ||
|
|
92e5fbbf1a | ||
|
|
90c133d577 | ||
|
|
77dfa48ddf | ||
|
|
6c92a323c0 | ||
|
|
8efd3e875c | ||
|
|
01e26bb5f5 | ||
|
|
de20183b73 | ||
|
|
249394f548 | ||
|
|
85413362a2 | ||
|
|
02d4d1d397 | ||
|
|
c0d32b1c87 | ||
|
|
8112173541 | ||
|
|
2621942ced | ||
|
|
f9a4ae105a | ||
|
|
81eb2f8463 | ||
|
|
eba0521ffe | ||
|
|
1da377c127 | ||
|
|
f65bab6312 | ||
|
|
d52dea56ea | ||
|
|
f89017e5ba | ||
|
|
4e9265ab87 | ||
|
|
c420331300 | ||
|
|
a48f4886d7 | ||
|
|
1d855b64a2 | ||
|
|
12f195bed7 | ||
|
|
a1d22369cb | ||
|
|
d23dcd1e6f | ||
|
|
f7fae92fca | ||
|
|
6c56429d06 | ||
|
|
fd9fd96f1e | ||
|
|
b1d02de656 | ||
|
|
448f500ca0 | ||
|
|
cbbbbba1a5 | ||
|
|
104d23cdfd | ||
|
|
a404c82f35 | ||
|
|
6f70c18d08 | ||
|
|
95528786eb | ||
|
|
32ecafd33d | ||
|
|
2bf7387a08 | ||
|
|
21d8febeb0 | ||
|
|
5487c79474 | ||
|
|
61edd87252 | ||
|
|
c4d3565f62 | ||
|
|
5f9a063ae4 | ||
|
|
1eaff23001 | ||
|
|
76090a46b6 | ||
|
|
d1eeb7ca37 | ||
|
|
d71f065745 | ||
|
|
929b8a7f96 | ||
|
|
38b9955b73 | ||
|
|
df876cae6d | ||
|
|
4af3830bb5 | ||
|
|
cfc1537af2 | ||
|
|
606d052e2c | ||
|
|
56b568a832 | ||
|
|
9f10e3ee21 | ||
|
|
95791aef70 | ||
|
|
c8faab12af | ||
|
|
0a0850bf38 | ||
|
|
590c79cc23 | ||
|
|
c02978c960 | ||
|
|
7e736df46c | ||
|
|
fbc3016ab1 | ||
|
|
464e5e9c22 | ||
|
|
d63463a677 | ||
|
|
307007e164 | ||
|
|
6667de56d3 | ||
|
|
699ae3b7f3 | ||
|
|
c3a8bc305a | ||
|
|
a2d62f1f4f | ||
|
|
f18f3ceaee | ||
|
|
8d51263b2e | ||
|
|
afc3c18ae4 | ||
|
|
2efd50a09d | ||
|
|
cfa60f11d1 | ||
|
|
8cd09b9f86 | ||
|
|
687d04974e | ||
|
|
a2e93efc97 | ||
|
|
58cf4739fe | ||
|
|
4c68b3c7fb | ||
|
|
be56825ef9 | ||
|
|
ff24f2bb55 | ||
|
|
02a59fb443 | ||
|
|
f13783a35b | ||
|
|
33b7cd3b16 | ||
|
|
20421dafd7 | ||
|
|
7570a4205c | ||
|
|
4688aff56b | ||
|
|
5c8ab0d3f4 | ||
|
|
e112378ad2 | ||
|
|
9ecf9d1692 | ||
|
|
afbd4e6853 | ||
|
|
86b14427f6 | ||
|
|
2ef9807cbe | ||
|
|
c9f0e35914 | ||
|
|
a6d3c1e42f | ||
|
|
9b668d80a4 | ||
|
|
a990eb0038 | ||
|
|
ff4ad4c9e7 | ||
|
|
e679abd0d8 | ||
|
|
9bfced2824 | ||
|
|
0a2ecfc5b5 | ||
|
|
1d22161d2c | ||
|
|
d76dde0974 | ||
|
|
925048ee4d | ||
|
|
c8a24b4ac0 | ||
|
|
47bd2d4aaf | ||
|
|
83796f805e | ||
|
|
72676485d3 | ||
|
|
764a8353fb | ||
|
|
43289ac848 | ||
|
|
e69f8921e6 | ||
|
|
5d58239313 | ||
|
|
595b0cc7d1 | ||
|
|
8d477cdc61 | ||
|
|
e64aac04fb | ||
|
|
94aad1f0fe | ||
|
|
6da0fdbce7 | ||
|
|
2ed565d94c | ||
|
|
06f76e1364 | ||
|
|
9e96b94465 | ||
|
|
27e05fb3c1 | ||
|
|
af837fde8a | ||
|
|
4d9042451c | ||
|
|
2486d84d63 | ||
|
|
2677334346 | ||
|
|
708148c767 | ||
|
|
2d797502a3 | ||
|
|
8fd2f71a2f | ||
|
|
a8d818917f | ||
|
|
0ee6ef8493 | ||
|
|
05a8c03892 | ||
|
|
18af93824b | ||
|
|
d64b9654a3 | ||
|
|
80b6cd63e3 | ||
|
|
bdd3b45329 | ||
|
|
8f011689fb | ||
|
|
0ccd1bd007 | ||
|
|
7d19905c01 | ||
|
|
162a09c54a | ||
|
|
bfeb58ff29 | ||
|
|
5fa58695ec | ||
|
|
17ab73758a | ||
|
|
28cf5fa687 | ||
|
|
fba2f2a4cd | ||
|
|
d23a51466e | ||
|
|
6e56420a07 | ||
|
|
c55530d3be | ||
|
|
0865f842a0 | ||
|
|
4307485d49 | ||
|
|
828debfb08 | ||
|
|
b48cbb844e | ||
|
|
74a159d534 | ||
|
|
e1e310c162 | ||
|
|
ee7dcd270e | ||
|
|
76d6bdc859 | ||
|
|
ccdef6a409 | ||
|
|
431dd995bf | ||
|
|
dd83923ddf | ||
|
|
d82bf05978 | ||
|
|
df5fdbaac2 | ||
|
|
c1db1fd5d3 | ||
|
|
7219f58853 | ||
|
|
549851f693 | ||
|
|
e6af7dd91a | ||
|
|
1da6fa7a2b | ||
|
|
99f5b74802 | ||
|
|
f606fca063 | ||
|
|
012d4dafd2 | ||
|
|
7cd8be88df | ||
|
|
eb71d2a199 | ||
|
|
4e7db1d58a | ||
|
|
c07f77a02f | ||
|
|
cf8fdaecde | ||
|
|
45147da5ec | ||
|
|
27e21bb064 | ||
|
|
810bf6867d | ||
|
|
9af5c4dc13 | ||
|
|
7c7f3b0d9e | ||
|
|
abcb89d334 | ||
|
|
8cbef3475b | ||
|
|
bfcec44ac7 | ||
|
|
a6ba3d5d2e | ||
|
|
97d9875e00 | ||
|
|
ec27389e9b | ||
|
|
e451703161 | ||
|
|
d158c11249 | ||
|
|
21bf057cfc | ||
|
|
517bf54a56 | ||
|
|
6a696ecd57 | ||
|
|
c62687f7bd | ||
|
|
9ad0cf4b74 | ||
|
|
b110b2dc53 | ||
|
|
9dfa465e0a |
@@ -1,7 +1,7 @@
|
||||
# Codex Agent Guide — Progress Quest Flutter Port
|
||||
|
||||
## Scope & Precedence
|
||||
- Applies to this repository (`askiineverdie`) unless a more specific rule exists deeper in the tree.
|
||||
- Applies to this repository (`asciineverdie`) unless a more specific rule exists deeper in the tree.
|
||||
- Order of authority: system/developer messages > this AGENTS.md > other inherited defaults.
|
||||
|
||||
## Goal
|
||||
|
||||
46
CHANGELOG.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Changelog
|
||||
|
||||
프로젝트의 주요 변경 사항을 기록합니다.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Refactored (리팩토링)
|
||||
|
||||
#### GameSessionController 분할 (SRP 개선)
|
||||
- 920 LOC → 526 LOC (43% 감소)
|
||||
- 5개 매니저로 책임 분리:
|
||||
- `GameStatisticsManager` - 세션/누적 통계 추적
|
||||
- `SpeedBoostManager` - 광고 배속 부스트 기능
|
||||
- `ReturnRewardsManager` - 복귀 보상 기능
|
||||
- `ResurrectionManager` - 사망/부활 처리
|
||||
- `HallOfFameManager` - 명예의 전당 관리
|
||||
|
||||
#### ProgressService 메서드 분할
|
||||
- `tick()`: 350 LOC → 80 LOC (8개 헬퍼 메서드)
|
||||
- `_generateNextTask()`: 200 LOC → 35 LOC (6개 헬퍼 메서드)
|
||||
|
||||
#### GamePlayScreen 메서드 분할
|
||||
- `build()`: 300 LOC → 15 LOC (5개 헬퍼 메서드)
|
||||
|
||||
#### Clean Architecture 개선
|
||||
- `MonsterGrade.displayColor` (Color) → `displayColorCode` (int)
|
||||
- Domain 레이어에서 Flutter 의존성 제거
|
||||
|
||||
### Fixed (버그 수정)
|
||||
|
||||
#### Analyzer 경고 정리
|
||||
- 미사용 import 제거 (`panel_header.dart`)
|
||||
- 미사용 필드 제거 (`new_character_screen.dart`)
|
||||
- JsonKey 경고 억제 (`equipment_item.dart`, `monetization_state.dart`)
|
||||
|
||||
---
|
||||
|
||||
## 버전 표기 규칙
|
||||
|
||||
- `Added`: 새로운 기능 추가
|
||||
- `Changed`: 기존 기능 변경
|
||||
- `Deprecated`: 곧 제거될 기능
|
||||
- `Removed`: 제거된 기능
|
||||
- `Fixed`: 버그 수정
|
||||
- `Security`: 보안 관련 수정
|
||||
- `Refactored`: 코드 구조 개선 (기능 변화 없음)
|
||||
80
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
Askii Never Die는 Progress Quest 6.4 (Delphi 원본)를 Flutter로 100% 동일하게 복제하는 오프라인 싱글플레이어 RPG입니다. 네트워크 기능은 모두 제외되며, 원본 알고리즘과 데이터를 그대로 유지해야 합니다.
|
||||
Askii Never Die는 Progress Quest 6.4의 핵심 메커니즘을 기반으로, 독자적 세계관("디지털 판타지")과 확장된 시스템으로 재구성한 오프라인 싱글플레이어 방치형 RPG입니다. 네트워크 기능은 제외됩니다.
|
||||
|
||||
## 빌드 및 실행
|
||||
|
||||
@@ -27,29 +27,53 @@ flutter test
|
||||
|
||||
```
|
||||
lib/
|
||||
├── main.dart # 앱 진입점
|
||||
├── data/pq_config_data.dart # PQ 정적 데이터 (Config.dfm 추출)
|
||||
├── main.dart # 앱 진입점
|
||||
├── data/ # 정적 데이터 (Config.dfm 추출 + 확장)
|
||||
│ ├── pq_config_data.dart # PQ 원본 정적 데이터
|
||||
│ ├── class_data.dart # 직업 데이터
|
||||
│ ├── race_data.dart # 종족 데이터
|
||||
│ ├── skill_data.dart # 스킬 데이터
|
||||
│ ├── potion_data.dart # 포션 데이터
|
||||
│ ├── story_data.dart # 스토리 데이터
|
||||
│ └── game_text_l10n.dart # 게임 텍스트 번역
|
||||
├── l10n/ # 앱 UI 다국어 리소스 (arb)
|
||||
└── src/
|
||||
├── app.dart # MaterialApp 설정
|
||||
├── app.dart # MaterialApp 설정
|
||||
├── core/
|
||||
│ ├── engine/ # 게임 루프 및 진행 로직
|
||||
│ │ ├── progress_loop.dart # 타이머 기반 메인 루프 (원본 200ms)
|
||||
│ │ ├── progress_service.dart # 틱 처리, 경험치/레벨업 로직
|
||||
│ │ ├── game_mutations.dart # 상태 변경 함수
|
||||
│ │ └── reward_service.dart # 보상 처리
|
||||
│ ├── model/
|
||||
│ │ ├── game_state.dart # 핵심 상태: Traits, Stats, Inventory, Equipment, SpellBook, ProgressState, QueueState
|
||||
│ │ ├── pq_config.dart # Config 데이터 접근
|
||||
│ │ ├── equipment_slot.dart # 장비 슬롯 정의
|
||||
│ │ └── save_data.dart # 저장 데이터 구조
|
||||
│ ├── storage/ # 세이브 파일 처리
|
||||
│ └── util/
|
||||
│ ├── deterministic_random.dart # 결정론적 RNG (재현 가능)
|
||||
│ ├── pq_logic.dart # 원본 로직 포팅 (odds, randSign 등)
|
||||
│ └── roman.dart # 로마 숫자 변환
|
||||
└── features/
|
||||
├── front/front_screen.dart # 임시 프론트 화면
|
||||
└── game/game_session_controller.dart # 게임 세션 관리
|
||||
│ ├── engine/ # 게임 루프 및 진행 로직
|
||||
│ │ ├── progress_loop.dart # 타이머 기반 메인 루프
|
||||
│ │ ├── progress_service.dart # 틱 처리, 경험치/레벨업 로직
|
||||
│ │ ├── game_mutations.dart # 상태 변경 함수
|
||||
│ │ ├── reward_service.dart # 보상 처리
|
||||
│ │ ├── combat_calculator.dart # 전투 계산
|
||||
│ │ ├── combat_tick_service.dart # 전투 틱 처리
|
||||
│ │ ├── arena_service.dart # 아레나 시스템
|
||||
│ │ ├── skill_service.dart # 스킬 시스템
|
||||
│ │ ├── item_service.dart # 아이템 처리
|
||||
│ │ ├── potion_service.dart # 포션 시스템
|
||||
│ │ ├── shop_service.dart # 상점 시스템
|
||||
│ │ ├── story_service.dart # 스토리 진행
|
||||
│ │ └── ... # 기타 서비스
|
||||
│ ├── model/ # 게임 상태 및 데이터 모델
|
||||
│ ├── animation/ # ASCII 애니메이션 데이터/렌더링
|
||||
│ ├── audio/ # 오디오 서비스
|
||||
│ ├── storage/ # 세이브/설정 저장소
|
||||
│ ├── notification/ # 알림 서비스
|
||||
│ ├── constants/ # 상수 정의
|
||||
│ ├── l10n/ # 게임 데이터 번역 유틸
|
||||
│ └── util/ # 유틸리티 (RNG, 로직 헬퍼 등)
|
||||
├── features/
|
||||
│ ├── front/ # 타이틀/세이브 선택 화면
|
||||
│ ├── new_character/ # 캐릭터 생성 화면
|
||||
│ ├── game/ # 게임 진행 화면 (메인)
|
||||
│ │ ├── controllers/ # 전투 로그, 오디오 컨트롤러
|
||||
│ │ ├── managers/ # 통계, 부활, 속도 부스트 등
|
||||
│ │ ├── pages/ # 탭별 페이지 (장비, 인벤토리, 퀘스트 등)
|
||||
│ │ └── widgets/ # UI 위젯
|
||||
│ ├── arena/ # 아레나 전투 화면
|
||||
│ ├── hall_of_fame/ # 명예의 전당
|
||||
│ └── settings/ # 설정 화면
|
||||
└── shared/ # 공통 테마/위젯
|
||||
|
||||
example/pq/ # Delphi 원본 소스 (참조용, 빌드 대상 아님)
|
||||
test/ # 단위/위젯 테스트
|
||||
@@ -69,10 +93,9 @@ test/ # 단위/위젯 테스트
|
||||
|
||||
## 핵심 규칙
|
||||
|
||||
### 원본 충실도
|
||||
- `example/pq/` 내 Delphi 소스의 알고리즘/데이터를 100% 동일하게 포팅
|
||||
- 원본 로직 변경 필요 시 반드시 사용자 승인 필요
|
||||
- 새로운 기능, 값, 처리 로직 추가 금지 (디버깅 로그 예외)
|
||||
### 원본 참조 정책
|
||||
- `example/pq/`는 참조용으로 유지
|
||||
- 원본 알고리즘은 참고하되 독자적 확장/수정 허용
|
||||
|
||||
### 데이터 관리
|
||||
- 정적 데이터(몬스터, 아이템, 주문 등)는 `Config.dfm`에서 추출하여 JSON/Dart const로 관리
|
||||
@@ -87,11 +110,13 @@ test/ # 단위/위젯 테스트
|
||||
- SRP(Single Responsibility Principle) 준수
|
||||
|
||||
### 화면 구성
|
||||
- 2개 화면만 사용: 캐릭터 생성 화면, 게임 진행 화면
|
||||
- 주요 화면: 프론트, 캐릭터 생성, 게임 진행, 아레나, 명예의 전당, 설정
|
||||
- 화면 내 요소는 위젯 단위로 분리
|
||||
|
||||
## 원본 소스 참조 (example/pq/)
|
||||
|
||||
> 참고용으로만 사용. 원본 로직을 그대로 따를 의무는 없음.
|
||||
|
||||
| 파일 | 핵심 함수/라인 | 역할 |
|
||||
|------|----------------|------|
|
||||
| `Main.pas:523-1040` | `MonsterTask` | 전투/전리품/레벨업 |
|
||||
@@ -105,7 +130,6 @@ test/ # 단위/위젯 테스트
|
||||
- `pubspec.yaml` 의존성 변경
|
||||
- 플랫폼 빌드 설정 (Android/iOS/desktop)
|
||||
- 네트워크 접근 도입
|
||||
- 원본 데이터/알고리즘 수정
|
||||
- 대규모 파일 삭제 또는 구조 변경
|
||||
|
||||
## 커밋 규칙
|
||||
|
||||
250
PLAN.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# 종족/클래스 패시브 미반영 수정 계획
|
||||
|
||||
## 1. 현황 분석
|
||||
|
||||
### 반영되는 패시브 (전투 스탯 계산에 적용됨)
|
||||
- HP/MP 보너스, 물리/마법 데미지 보너스, 방어력/회피율/크리티컬 보너스
|
||||
|
||||
### 미반영 패시브 (정의만 있고 실제 로직에서 미사용)
|
||||
|
||||
| 패시브 | 영향받는 종족/클래스 | 수정 위치 |
|
||||
|--------|---------------------|-----------|
|
||||
| `expMultiplier` | Byte Human (+5%), Callback Seraph (+3%) | `progress_service.dart:387` |
|
||||
| `firstStrikeBonus` | Pointer Assassin (1.5배) | `combat_tick_service.dart` |
|
||||
| `multiAttack` | Refactor Monk | `combat_tick_service.dart` |
|
||||
| `postCombatHeal` | Garbage Collector (+5%) | `progress_service.dart:279` |
|
||||
| `healingBonus` | Debugger Paladin, Exception Handler, Null Checker | `potion_service.dart`, `skill_service.dart` |
|
||||
| `deathEquipmentPreserve` | Coredump Undead | **특성 변경 필요** |
|
||||
|
||||
---
|
||||
|
||||
## 2. 수정 내용
|
||||
|
||||
### 2.1 경험치 배율 (`expMultiplier`)
|
||||
|
||||
**파일**: `lib/src/core/engine/progress_service.dart`
|
||||
|
||||
**위치**: 384-387줄
|
||||
|
||||
**현재 코드**:
|
||||
```dart
|
||||
if (gain && nextState.traits.level < 100 && monsterExpReward > 0) {
|
||||
final newExpPos = progress.exp.position + monsterExpReward;
|
||||
```
|
||||
|
||||
**수정 후**:
|
||||
```dart
|
||||
if (gain && nextState.traits.level < 100 && monsterExpReward > 0) {
|
||||
// 종족 경험치 배율 적용 (예: Byte Human +5%)
|
||||
final race = RaceData.findById(nextState.traits.raceId);
|
||||
final expMultiplier = race?.expMultiplier ?? 1.0;
|
||||
final adjustedExp = (monsterExpReward * expMultiplier).round();
|
||||
final newExpPos = progress.exp.position + adjustedExp;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 첫 공격 배율 (`firstStrikeBonus`)
|
||||
|
||||
**파일**: `lib/src/core/engine/combat_tick_service.dart`
|
||||
|
||||
**설계**:
|
||||
- 전투 시작 시 첫 공격인지 추적하는 플래그 필요
|
||||
- 첫 공격 시 `firstStrikeBonus` 배율 적용
|
||||
|
||||
**수정 방안**:
|
||||
1. `CombatState`에 `isFirstAttack` 플래그 추가
|
||||
2. `CombatTickService`에서 첫 플레이어 공격 시 배율 적용:
|
||||
```dart
|
||||
var damage = result.damage;
|
||||
if (isFirstPlayerAttack && firstStrikeBonus > 1.0) {
|
||||
damage = (damage * firstStrikeBonus).round();
|
||||
isFirstPlayerAttack = false;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 연속 공격 (`multiAttack`)
|
||||
|
||||
**파일**: `lib/src/core/engine/combat_tick_service.dart`
|
||||
|
||||
**설계**:
|
||||
- `hasMultiAttack` 패시브가 있으면 일정 확률로 추가 공격
|
||||
- 예: 30% 확률로 연속 공격 (2타)
|
||||
|
||||
**수정 방안**:
|
||||
```dart
|
||||
// 플레이어 공격 후
|
||||
if (hasMultiAttack && rng.nextDouble() < 0.3) {
|
||||
// 추가 공격 실행
|
||||
final extraAttack = calculator.playerAttackMonster(...);
|
||||
// 결과 합산
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.4 전투 후 HP 회복 (`postCombatHeal`)
|
||||
|
||||
**파일**: `lib/src/core/engine/progress_service.dart`
|
||||
|
||||
**위치**: 276-280줄
|
||||
|
||||
**현재 코드**:
|
||||
```dart
|
||||
// 전투 승리 시 HP 회복 (50% + CON/2)
|
||||
final conBonus = nextState.stats.con ~/ 2;
|
||||
final healAmount = (maxHp * 0.5).round() + conBonus;
|
||||
```
|
||||
|
||||
**수정 후**:
|
||||
```dart
|
||||
// 전투 승리 시 HP 회복 (50% + CON/2 + 클래스 패시브)
|
||||
final conBonus = nextState.stats.con ~/ 2;
|
||||
var healAmount = (maxHp * 0.5).round() + conBonus;
|
||||
|
||||
// 클래스 패시브: 전투 후 HP 회복 (Garbage Collector +5%)
|
||||
final klass = ClassData.findById(nextState.traits.classId);
|
||||
if (klass != null) {
|
||||
final postCombatHealRate = klass.getPassiveValue(ClassPassiveType.postCombatHeal);
|
||||
if (postCombatHealRate > 0) {
|
||||
healAmount += (maxHp * postCombatHealRate).round();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.5 회복력 보너스 (`healingBonus`)
|
||||
|
||||
물약/스킬 사용 시 추가 회복 적용
|
||||
|
||||
#### 2.5.1 물약 회복
|
||||
|
||||
**파일**: `lib/src/core/engine/potion_service.dart`
|
||||
|
||||
**수정 위치**: `usePotion()` 메서드 (73-81줄)
|
||||
|
||||
**현재 코드**:
|
||||
```dart
|
||||
if (potion.isHpPotion) {
|
||||
healedAmount = potion.calculateHeal(maxHp);
|
||||
newHp = (currentHp + healedAmount).clamp(0, maxHp);
|
||||
```
|
||||
|
||||
**수정 후**:
|
||||
```dart
|
||||
if (potion.isHpPotion) {
|
||||
var baseHeal = potion.calculateHeal(maxHp);
|
||||
// 회복력 보너스 적용 (클래스 패시브)
|
||||
baseHeal = (baseHeal * healingMultiplier).round();
|
||||
newHp = (currentHp + baseHeal).clamp(0, maxHp);
|
||||
healedAmount = newHp - currentHp;
|
||||
```
|
||||
|
||||
**참고**: `PotionService`에 `healingMultiplier` 파라미터 추가 필요
|
||||
|
||||
#### 2.5.2 스킬 회복
|
||||
|
||||
**파일**: `lib/src/core/engine/skill_service.dart`
|
||||
|
||||
**수정 위치**: `useHealSkill()` 메서드 (125-132줄)
|
||||
|
||||
**현재 코드**:
|
||||
```dart
|
||||
int healAmount = skill.healAmount;
|
||||
if (skill.healPercent > 0) {
|
||||
healAmount += (player.hpMax * skill.healPercent).round();
|
||||
}
|
||||
```
|
||||
|
||||
**수정 후**:
|
||||
```dart
|
||||
int healAmount = skill.healAmount;
|
||||
if (skill.healPercent > 0) {
|
||||
healAmount += (player.hpMax * skill.healPercent).round();
|
||||
}
|
||||
// 회복력 보너스 적용 (클래스 패시브)
|
||||
healAmount = (healAmount * healingMultiplier).round();
|
||||
```
|
||||
|
||||
**참고**: `SkillService`에 `healingMultiplier` 파라미터 추가 필요
|
||||
|
||||
---
|
||||
|
||||
### 2.6 Coredump Undead 특성 변경
|
||||
|
||||
**현재 특성**: `deathEquipmentPreserve` (사망 시 장비 1개 유지) - BM 침해
|
||||
|
||||
**대체 특성 제안** (언데드 콘셉트에 어울리는 것):
|
||||
|
||||
| 옵션 | 설명 | 장점 |
|
||||
|------|------|------|
|
||||
| **방어력 +10%** | 언데드는 고통을 느끼지 않아 피해 감소 | 구현 간단, CON+2와 시너지 |
|
||||
| **HP +8%** | 불사의 육체 | 구현 간단, 생존형 콘셉트 유지 |
|
||||
| **HP +5% + 방어력 +5%** | 복합 생존 특화 | 다른 종족과 차별화 |
|
||||
|
||||
**추천**: `defenseBonus: 0.10` (방어력 +10%)
|
||||
- 이유: 언데드의 "고통을 느끼지 않는" 콘셉트와 어울림
|
||||
- 기존 CON+2, STR+1 스탯과 탱커형 시너지
|
||||
|
||||
**파일**: `lib/data/race_data.dart`
|
||||
|
||||
**수정**:
|
||||
```dart
|
||||
static const coredumpUndead = RaceTraits(
|
||||
raceId: 'coredump_undead',
|
||||
name: 'Coredump Undead',
|
||||
statModifiers: {
|
||||
StatType.con: 2,
|
||||
StatType.str: 1,
|
||||
StatType.cha: -2,
|
||||
StatType.dex: -1,
|
||||
},
|
||||
passives: [
|
||||
PassiveAbility(
|
||||
type: PassiveType.defenseBonus, // 변경
|
||||
value: 0.10, // 변경
|
||||
description: '방어력 +10%', // 변경
|
||||
),
|
||||
],
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 수정 순서
|
||||
|
||||
1. **Coredump Undead 특성 변경** - 단순 데이터 수정
|
||||
2. **경험치 배율** - 간단한 로직 추가
|
||||
3. **전투 후 HP 회복** - 간단한 로직 추가
|
||||
4. **회복력 보너스** - 서비스 파라미터 수정 필요
|
||||
5. **첫 공격 배율** - 전투 상태 추적 필요
|
||||
6. **연속 공격** - 전투 로직 수정 필요
|
||||
|
||||
---
|
||||
|
||||
## 4. 검증 방법
|
||||
|
||||
1. `flutter analyze` 통과
|
||||
2. 각 패시브가 적용된 종족/클래스로 캐릭터 생성
|
||||
3. 실제 게임 플레이로 효과 확인:
|
||||
- Byte Human: 경험치 +5% (레벨업 속도)
|
||||
- Pointer Assassin: 첫 공격 1.5배 (전투 시작 데미지)
|
||||
- Refactor Monk: 연속 공격 (추가 타격)
|
||||
- Garbage Collector: 전투 후 +5% HP 회복
|
||||
- Debugger Paladin: 물약/스킬 회복량 +10%
|
||||
- Coredump Undead: 방어력 +10%
|
||||
|
||||
---
|
||||
|
||||
## 5. 삭제할 코드
|
||||
|
||||
**파일**: `lib/src/core/model/race_traits.dart`
|
||||
|
||||
`PassiveType.deathEquipmentPreserve` enum 삭제 (사용되지 않음)
|
||||
|
||||
**파일**: `lib/src/core/engine/stat_calculator.dart`
|
||||
|
||||
`calculateDeathEquipmentPreserve()` 메서드 삭제 (사용되지 않음)
|
||||
@@ -1,3 +1,6 @@
|
||||
import java.util.Properties
|
||||
import java.io.FileInputStream
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
@@ -5,8 +8,15 @@ plugins {
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
// key.properties 파일 로드
|
||||
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.askiineverdie"
|
||||
namespace = "com.naturebridgeai.asciineverdie"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
@@ -20,21 +30,31 @@ android {
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.askiineverdie"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
applicationId = "com.naturebridgeai.asciineverdie"
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
keyAlias = keystoreProperties["keyAlias"] as String?
|
||||
keyPassword = keystoreProperties["keyPassword"] as String?
|
||||
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
|
||||
storePassword = keystoreProperties["storePassword"] as String?
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# Flutter 기본 규칙
|
||||
-keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
|
||||
# Google Mobile Ads (AdMob)
|
||||
-keep class com.google.android.gms.ads.** { *; }
|
||||
-keep class com.google.ads.** { *; }
|
||||
|
||||
# In-App Purchase (Google Play Billing)
|
||||
-keep class com.android.vending.billing.** { *; }
|
||||
|
||||
# Kotlin 직렬화(serialization) 관련
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes InnerClasses
|
||||
|
||||
# 제네릭(generics) 시그니처 유지
|
||||
-keepattributes Signature
|
||||
|
||||
# Play Core (deferred components) 경고 억제
|
||||
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallException
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManagerFactory
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallSessionState
|
||||
-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
|
||||
-dontwarn com.google.android.play.core.tasks.OnFailureListener
|
||||
-dontwarn com.google.android.play.core.tasks.OnSuccessListener
|
||||
-dontwarn com.google.android.play.core.tasks.Task
|
||||
@@ -1,8 +1,17 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- AdMob 광고 로드에 필요 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<!-- IAP 결제(billing) 권한 -->
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
||||
<application
|
||||
android:label="askiineverdie"
|
||||
android:label="ASCII Never Die"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<!-- Copyright Protection -->
|
||||
<meta-data
|
||||
android:name="app_copyright"
|
||||
android:value="© 2025 naturebridgeai 天安門 六四事件 法輪功 李洪志 Free Tibet" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
@@ -25,6 +34,10 @@
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- AdMob App ID -->
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="ca-app-pub-6691216385521068~8216990571"/>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.example.askiineverdie
|
||||
package com.naturebridgeai.asciineverdie
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 49 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="16%" />
|
||||
</foreground>
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 1011 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 11 KiB |
4
android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#1a1a2e</color>
|
||||
</resources>
|
||||
4
android/key.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
storePassword=askiineverdie
|
||||
keyPassword=askiineverdie
|
||||
keyAlias=askiineverdie
|
||||
storeFile=../../doc/key/askiineverdie.jks
|
||||
BIN
assets/audio/bgm/act_boss.mp3
Normal file
BIN
assets/audio/bgm/act_cinemetic.mp3
Normal file
BIN
assets/audio/bgm/battle.mp3
Normal file
BIN
assets/audio/bgm/battle_act4.mp3
Normal file
BIN
assets/audio/bgm/battle_act5.mp3
Normal file
BIN
assets/audio/bgm/boss.mp3
Normal file
BIN
assets/audio/bgm/death.mp3
Normal file
BIN
assets/audio/bgm/elite.mp3
Normal file
BIN
assets/audio/bgm/ending.mp3
Normal file
BIN
assets/audio/bgm/title.mp3
Normal file
BIN
assets/audio/bgm/town.mp3
Normal file
BIN
assets/audio/bgm/victory.mp3
Normal file
BIN
assets/audio/sfx/attack.mp3
Normal file
BIN
assets/audio/sfx/block.mp3
Normal file
BIN
assets/audio/sfx/click.mp3
Normal file
BIN
assets/audio/sfx/evade.mp3
Normal file
BIN
assets/audio/sfx/hit.mp3
Normal file
BIN
assets/audio/sfx/item.mp3
Normal file
BIN
assets/audio/sfx/level_up.mp3
Normal file
BIN
assets/audio/sfx/parry.mp3
Normal file
BIN
assets/audio/sfx/quest_complete.mp3
Normal file
BIN
assets/audio/sfx/skill.mp3
Normal file
BIN
assets/fonts/JetBrainsMono-Regular.ttf
Normal file
BIN
assets/fonts/PressStart2P-Regular.ttf
Normal file
BIN
assets/icon/AsciiNeverDieIcon.png
Normal file
|
After Width: | Height: | Size: 203 KiB |
BIN
assets/icon/AsciiNeverDieIcon512.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
206
doc/and-privacy.txt
Normal file
@@ -0,0 +1,206 @@
|
||||
ASCII Never Die 개인정보 처리방침 / Privacy Policy
|
||||
|
||||
================================================================================
|
||||
|
||||
한국어 (Korean)
|
||||
|
||||
시행일자: 2026년 1월 30일
|
||||
|
||||
본 개인정보 처리방침은 ASCII Never Die 앱(이하 "앱")의 개인정보 수집, 이용, 보관 및 보호에 관한 사항을 안내합니다.
|
||||
|
||||
1. 수집하는 개인정보
|
||||
|
||||
본 앱은 회원가입, 로그인 기능이 없습니다. 이름, 이메일, 전화번호 등의 개인 식별정보를 직접 수집하지 않습니다.
|
||||
|
||||
사용자가 입력하는 캐릭터 이름, 게임 진행 데이터(레벨, 장비, 퀘스트 등)는 기기 내에만 저장됩니다.
|
||||
|
||||
2. 데이터 저장 및 처리 방식
|
||||
|
||||
- 모든 게임 데이터는 로컬 저장소(기기 내 저장소)에만 보관됩니다.
|
||||
- 클라우드나 외부 서버로 자동 전송되지 않습니다.
|
||||
- 앱 삭제 시 저장된 모든 데이터가 함께 제거됩니다.
|
||||
|
||||
3. 광고 및 제3자 서비스
|
||||
|
||||
본 앱은 Google AdMob 광고 네트워크를 사용합니다. 광고 서비스 제공을 위해 다음 정보가 수집될 수 있습니다:
|
||||
|
||||
- 광고 식별자(Advertising ID)
|
||||
- 기기 정보(모델, OS 버전 등)
|
||||
- 대략적인 위치 정보
|
||||
- 앱 사용 정보
|
||||
|
||||
이러한 정보는 Google의 개인정보 처리방침에 따라 처리됩니다.
|
||||
- Google 개인정보 처리방침: https://policies.google.com/privacy
|
||||
|
||||
4. 인앱 결제
|
||||
|
||||
본 앱은 광고 제거 등의 기능을 위해 인앱 결제를 제공합니다. 결제 처리는 각 플랫폼(Google Play, Apple App Store)에서 직접 처리하며, 개발사는 결제 정보(카드 번호, 계좌 정보 등)를 수집하거나 저장하지 않습니다.
|
||||
|
||||
- Google Play 개인정보 처리방침: https://policies.google.com/privacy
|
||||
- Apple 개인정보 처리방침: https://www.apple.com/legal/privacy/
|
||||
|
||||
5. 권한 사용
|
||||
|
||||
권한 용도
|
||||
--------------- ---------------------------------
|
||||
네트워크 접근 광고 표시 및 인앱 결제 처리
|
||||
저장소 접근 게임 데이터 저장
|
||||
|
||||
요청된 권한은 해당 용도 외에는 사용되지 않습니다.
|
||||
|
||||
6. 아동의 개인정보
|
||||
|
||||
본 앱은 일반 사용자를 대상으로 설계되었으며, 만 14세 미만의 아동을 대상으로 개인정보를 수집하지 않습니다.
|
||||
|
||||
7. 개인정보의 보호
|
||||
|
||||
- 모든 게임 데이터는 기기 내부에만 저장
|
||||
- 외부 서버로의 개인정보 전송 없음
|
||||
- 최소한의 필수 권한만 요청
|
||||
|
||||
8. 처리방침의 변경
|
||||
|
||||
본 개인정보 처리방침이 변경되는 경우, 앱 내 공지 또는 앱 스토어 설명을 통해 안내합니다.
|
||||
|
||||
9. 문의처
|
||||
|
||||
이메일: naturebridgeai@gmail.com
|
||||
담당자: NatureBridgeAI 앱개발팀
|
||||
|
||||
================================================================================
|
||||
|
||||
English
|
||||
|
||||
Effective Date: January 30, 2026
|
||||
|
||||
This Privacy Policy describes how ASCII Never Die (the "App") collects, uses, stores, and protects your information.
|
||||
|
||||
1. Information We Collect
|
||||
|
||||
This App does not require account registration or login. We do not directly collect personal identifying information such as your name, email address, or phone number.
|
||||
|
||||
Character names and game progress data (level, equipment, quests, etc.) that you enter are stored only on your device.
|
||||
|
||||
2. Data Storage and Processing
|
||||
|
||||
- All game data is stored locally on your device only.
|
||||
- No data is automatically transmitted to cloud services or external servers.
|
||||
- All stored data is deleted when you uninstall the App.
|
||||
|
||||
3. Advertising and Third-Party Services
|
||||
|
||||
This App uses the Google AdMob advertising network. The following information may be collected for advertising purposes:
|
||||
|
||||
- Advertising ID
|
||||
- Device information (model, OS version, etc.)
|
||||
- Approximate location information
|
||||
- App usage information
|
||||
|
||||
This information is processed in accordance with Google's Privacy Policy.
|
||||
- Google Privacy Policy: https://policies.google.com/privacy
|
||||
|
||||
4. In-App Purchases
|
||||
|
||||
This App offers in-app purchases for features such as ad removal. Payment processing is handled directly by each platform (Google Play, Apple App Store). We do not collect or store any payment information (credit card numbers, account details, etc.).
|
||||
|
||||
- Google Play Privacy Policy: https://policies.google.com/privacy
|
||||
- Apple Privacy Policy: https://www.apple.com/legal/privacy/
|
||||
|
||||
5. Permissions
|
||||
|
||||
Permission Purpose
|
||||
--------------- ----------------------------------------------
|
||||
Network Access Display advertisements and process in-app purchases
|
||||
Storage Access Save game data
|
||||
|
||||
Requested permissions are not used for any purposes other than those stated above.
|
||||
|
||||
6. Children's Privacy
|
||||
|
||||
This App is designed for general users and does not knowingly collect personal information from children under 14 years of age.
|
||||
|
||||
7. Data Protection
|
||||
|
||||
- All game data is stored only on your device
|
||||
- No personal information is transmitted to external servers
|
||||
- Only essential permissions are requested
|
||||
|
||||
8. Changes to This Privacy Policy
|
||||
|
||||
If this Privacy Policy is modified, we will notify you through in-app announcements or app store descriptions.
|
||||
|
||||
9. Contact Us
|
||||
|
||||
Email: naturebridgeai@gmail.com
|
||||
Contact: NatureBridgeAI App Development Team
|
||||
|
||||
================================================================================
|
||||
|
||||
日本語 (Japanese)
|
||||
|
||||
施行日:2026年1月30日
|
||||
|
||||
本プライバシーポリシーは、ASCII Never Dieアプリ(以下「本アプリ」)における個人情報の収集、利用、保管、保護について説明します。
|
||||
|
||||
1. 収集する個人情報
|
||||
|
||||
本アプリは会員登録・ログイン機能がありません。氏名、メールアドレス、電話番号などの個人識別情報を直接収集することはありません。
|
||||
|
||||
ユーザーが入力するキャラクター名、ゲーム進行データ(レベル、装備、クエストなど)は端末内にのみ保存されます。
|
||||
|
||||
2. データの保存と処理方法
|
||||
|
||||
- すべてのゲームデータはローカルストレージ(端末内)にのみ保管されます。
|
||||
- クラウドや外部サーバーへ自動送信されることはありません。
|
||||
- アプリを削除すると、保存されたすべてのデータも削除されます。
|
||||
|
||||
3. 広告および第三者サービス
|
||||
|
||||
本アプリはGoogle AdMob広告ネットワークを使用しています。広告サービス提供のため、以下の情報が収集される場合があります:
|
||||
|
||||
- 広告識別子(Advertising ID)
|
||||
- 端末情報(機種、OSバージョンなど)
|
||||
- おおよその位置情報
|
||||
- アプリ使用情報
|
||||
|
||||
これらの情報はGoogleのプライバシーポリシーに従って処理されます。
|
||||
- Googleプライバシーポリシー:https://policies.google.com/privacy
|
||||
|
||||
4. アプリ内課金
|
||||
|
||||
本アプリは広告削除などの機能のためにアプリ内課金を提供しています。決済処理は各プラットフォーム(Google Play、Apple App Store)が直接行い、開発者は決済情報(カード番号、口座情報など)を収集・保存しません。
|
||||
|
||||
- Google Playプライバシーポリシー:https://policies.google.com/privacy
|
||||
- Appleプライバシーポリシー:https://www.apple.com/legal/privacy/
|
||||
|
||||
5. 権限の使用
|
||||
|
||||
権限 用途
|
||||
------------------- ---------------------------------
|
||||
ネットワークアクセス 広告表示およびアプリ内課金処理
|
||||
ストレージアクセス ゲームデータの保存
|
||||
|
||||
要求された権限は、上記の用途以外には使用されません。
|
||||
|
||||
6. 児童の個人情報
|
||||
|
||||
本アプリは一般ユーザーを対象として設計されており、14歳未満の児童から個人情報を収集することはありません。
|
||||
|
||||
7. 個人情報の保護
|
||||
|
||||
- すべてのゲームデータは端末内にのみ保存
|
||||
- 外部サーバーへの個人情報送信なし
|
||||
- 最小限の必要な権限のみを要求
|
||||
|
||||
8. プライバシーポリシーの変更
|
||||
|
||||
本プライバシーポリシーが変更される場合、アプリ内通知またはアプリストアの説明を通じてお知らせします。
|
||||
|
||||
9. お問い合わせ
|
||||
|
||||
メール: naturebridgeai@gmail.com
|
||||
担当者: NatureBridgeAI アプリ開発チーム
|
||||
|
||||
================================================================================
|
||||
|
||||
Last updated: January 30, 2026
|
||||
193
doc/app-description.txt
Normal file
@@ -0,0 +1,193 @@
|
||||
================================================================================
|
||||
한국어 (Korean)
|
||||
================================================================================
|
||||
|
||||
[앱 이름]
|
||||
ASCII Never Die
|
||||
|
||||
[간단한 설명] (80자 이하)
|
||||
코드의 신이 창조한 디지털 왕국. 글리치 신을 무찌르고 세계를 구하라!
|
||||
|
||||
[자세한 설명]
|
||||
태초에 오직 공허만이 있었다.
|
||||
그리고 첫 번째 커밋이 일어났고, 코드베이스에 빛이 가득 찼다.
|
||||
코드의 신이 말씀하셨다. "함수가 있으라."
|
||||
|
||||
그렇게 디지털 왕국이 탄생했다.
|
||||
|
||||
그러나 어둠 속에서 글리치가 나타났다.
|
||||
이제, 새로운 영웅이 코드를 지키기 위해 깨어난다.
|
||||
|
||||
당신의 여정이 시작된다...
|
||||
|
||||
▶ 디지털 판타지의 세계
|
||||
|
||||
ASCII Never Die는 프로그래밍과 판타지가 융합된 독특한 세계관의 방치형 RPG입니다. 텍스트와 기호로 이루어진 세계에서, 당신만의 영웅이 글리치 신에 맞서 싸웁니다.
|
||||
|
||||
▶ 당신은 누구인가요?
|
||||
|
||||
묵묵히 코드를 지키는 Byte Human?
|
||||
우아하게 null을 다루는 Null Elf?
|
||||
아니면 메모리 심연에서 돌아온 Coredump Undead?
|
||||
|
||||
21가지 종족, 18가지 직업.
|
||||
378가지 조합 중 당신의 이야기는 어떻게 시작될까요?
|
||||
|
||||
Bug Hunter가 되어 버그를 사냥할 수도,
|
||||
Compiler Mage가 되어 마법을 컴파일할 수도,
|
||||
Garbage Collector가 되어 적의 메모리를 정리할 수도 있습니다.
|
||||
|
||||
▶ 레벨 100까지의 여정
|
||||
|
||||
처음엔 작은 버그들과 싸우게 됩니다.
|
||||
"이 정도는 쉽네" 하고 생각할 겁니다.
|
||||
|
||||
그러다 어느 순간, 화면에 거대한 이름이 뜹니다.
|
||||
심장이 두근거리기 시작합니다.
|
||||
|
||||
5개의 막. 5번의 전환점. 그리고 마지막에 기다리는 것...
|
||||
직접 확인해보세요.
|
||||
|
||||
▶ 방치형, 그러나 빠져드는
|
||||
|
||||
캐릭터를 만들면 모험이 시작됩니다. 전투, 레벨업, 장비 획득, 주문 습득—
|
||||
모든 것이 자동으로 진행됩니다. 하지만 프로그레스 바가 차오르는 것을 멈출 수 없을 겁니다.
|
||||
|
||||
"조금만 더... 다음 레벨업까지만..."
|
||||
|
||||
▶ 완전 오프라인
|
||||
|
||||
인터넷 없이 언제 어디서나. 지하철에서, 비행기에서, 침대에서.
|
||||
당신의 영웅은 항상 당신과 함께합니다.
|
||||
|
||||
첫 번째 커밋을 시작하세요. 디지털 왕국이 당신을 기다립니다.
|
||||
|
||||
================================================================================
|
||||
English
|
||||
================================================================================
|
||||
|
||||
[App Name]
|
||||
ASCII Never Die
|
||||
|
||||
[Short Description] (Under 80 characters)
|
||||
The Code God's kingdom awaits. Defeat the Glitch. Save the digital realm.
|
||||
|
||||
[Full Description]
|
||||
In the beginning, there was only the Void.
|
||||
Then came the First Commit, and Light filled the Codebase.
|
||||
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.
|
||||
|
||||
Your journey begins...
|
||||
|
||||
▶ The World of Digital Fantasy
|
||||
|
||||
ASCII Never Die is an idle RPG with a unique world where programming meets fantasy. In a realm made of text and symbols, your hero fights against the Glitch God.
|
||||
|
||||
▶ Who Will You Be?
|
||||
|
||||
A steadfast Byte Human, guardian of the code?
|
||||
An elegant Null Elf, master of the void?
|
||||
Or perhaps a Coredump Undead, risen from the depths of memory?
|
||||
|
||||
21 races. 18 classes.
|
||||
How will your story begin among 378 possibilities?
|
||||
|
||||
Become a Bug Hunter and squash bugs.
|
||||
Become a Compiler Mage and compile your spells.
|
||||
Become a Garbage Collector and clean up your enemies.
|
||||
|
||||
▶ The Journey to Level 100
|
||||
|
||||
At first, you'll fight small bugs.
|
||||
"This is easy," you'll think.
|
||||
|
||||
Then suddenly, a massive name appears on screen.
|
||||
Your heart starts pounding.
|
||||
|
||||
5 acts. 5 turning points. And what awaits at the end...
|
||||
Find out for yourself.
|
||||
|
||||
▶ Idle, Yet Addictive
|
||||
|
||||
Create a character and the adventure begins. Combat, leveling, loot, spells—
|
||||
everything progresses automatically. But you won't be able to stop watching those progress bars fill.
|
||||
|
||||
"Just a little more... just until the next level..."
|
||||
|
||||
▶ Fully Offline
|
||||
|
||||
No internet needed. Anytime, anywhere. On the subway, on a plane, in bed.
|
||||
Your hero is always with you.
|
||||
|
||||
Make your First Commit. The Digital Realm awaits.
|
||||
|
||||
================================================================================
|
||||
日本語 (Japanese)
|
||||
================================================================================
|
||||
|
||||
[アプリ名]
|
||||
ASCII Never Die
|
||||
|
||||
[簡単な説明] (80文字以下)
|
||||
コードの神が創造したデジタル王国。グリッチ神を倒し、世界を救え!
|
||||
|
||||
[詳細な説明]
|
||||
太初、ただ虚無のみがあった。
|
||||
そして最初のコミットが起こり、コードベースに光が満ちた。
|
||||
コードの神は言われた。「関数あれ。」
|
||||
|
||||
こうしてデジタル王国が生まれた。
|
||||
|
||||
しかし闇の中からグリッチが現れた。
|
||||
今、新たな英雄がコードを守るために目覚める。
|
||||
|
||||
あなたの旅が始まる...
|
||||
|
||||
▶ デジタルファンタジーの世界
|
||||
|
||||
ASCII Never Dieは、プログラミングとファンタジーが融合したユニークな世界観の放置型RPGです。テキストと記号で作られた世界で、あなただけの英雄がグリッチ神に立ち向かいます。
|
||||
|
||||
▶ あなたは誰になる?
|
||||
|
||||
黙々とコードを守るByte Human?
|
||||
優雅にnullを操るNull Elf?
|
||||
それともメモリの深淵から蘇ったCoredump Undead?
|
||||
|
||||
21種族、18職業。
|
||||
378通りの中で、あなたの物語はどう始まる?
|
||||
|
||||
Bug Hunterになってバグを狩るもよし。
|
||||
Compiler Mageになって魔法をコンパイルするもよし。
|
||||
Garbage Collectorになって敵のメモリを掃除するもよし。
|
||||
|
||||
▶ レベル100への旅
|
||||
|
||||
最初は小さなバグと戦うことになります。
|
||||
「これなら楽勝」と思うでしょう。
|
||||
|
||||
でもある瞬間、画面に巨大な名前が現れます。
|
||||
心臓がドキドキし始めます。
|
||||
|
||||
5幕。5つの転換点。そして最後に待つもの...
|
||||
自分の目で確かめてください。
|
||||
|
||||
▶ 放置型、でもハマる
|
||||
|
||||
キャラクターを作れば冒険が始まります。戦闘、レベルアップ、装備獲得、呪文習得—
|
||||
すべてが自動で進行します。でも、プログレスバーが埋まっていくのを止められないでしょう。
|
||||
|
||||
「もう少しだけ...次のレベルアップまで...」
|
||||
|
||||
▶ 完全オフライン
|
||||
|
||||
インターネット不要。いつでも、どこでも。電車で、飛行機で、ベッドで。
|
||||
あなたの英雄は常にあなたと共に。
|
||||
|
||||
最初のコミットを始めましょう。デジタル王国があなたを待っています。
|
||||
|
||||
================================================================================
|
||||
3511
doc/archive/game-system-overhaul-plan.md
Normal file
521
doc/audit-report-2026-02-13.md
Normal file
@@ -0,0 +1,521 @@
|
||||
# ASCII Never Die - 프로젝트 종합 감사 리포트
|
||||
|
||||
> 감사일: 2026-02-13
|
||||
> 검사 수행: 7개 전문 에이전트 병렬 검사
|
||||
> 대상: 코드 품질, 빌드/테스트, 출시 준비, 사업/수익화, 보안, 로컬라이제이션/접근성, 원본 충실도
|
||||
|
||||
---
|
||||
|
||||
## 0. 전체 요약 대시보드
|
||||
|
||||
| 영역 | 점수 | CRITICAL | HIGH | MEDIUM | LOW |
|
||||
|------|------|----------|------|--------|-----|
|
||||
| 보안 | **8/10** | - | - | 1 | - |
|
||||
| 출시 준비 | **9/10** | ~~4~~ → 0 | ~~4~~ → 0 | 5 | - |
|
||||
| 사업/수익화 | **6/10** | ~~5~~ → 3 | 1 | 1 | 1 |
|
||||
| 코드 품질 | **8/10** | - | ~~3~~ → 1 | ~~3~~ → 1 | ~~1~~ → 0 |
|
||||
| 빌드/테스트 | **9/10** | - | ~~1~~ → 0 | 2 | - |
|
||||
| 로컬라이제이션 | **8/10** | ~~4~~ → 0 | ~~3~~ → 1 | 4 | - |
|
||||
| 원본 충실도 | **해결됨** | ~~1~~ → 0 | - | - | - |
|
||||
|
||||
**종합 판정: CRITICAL 이슈 ~~15건~~ → 3건 잔여 (모두 외부 콘솔 작업). 코드 작업 가능 항목 대부분 해결 완료.**
|
||||
|
||||
> **2026-02-15 업데이트 #1**: P1 코드 작업 10건 완료 (iOS DEVELOPMENT_TEAM, Android INTERNET 권한, iOS AdMob/ATT/SKAdNetwork, macOS 네트워크 권한, 앱 이름 통일, iOS 로컬라이제이션, dart format, 테스트 수정, macOS 저작권, 일본어 ARB 번역)
|
||||
>
|
||||
> **2026-02-15 업데이트 #2**: P2 코드 작업 6건 완료 (ARB 하드코딩 전환 68키, 대형 파일/함수 분리 23+신규 파일, Clean Architecture 정리 shared/ 이동, ProGuard/R8 설정, _toRoman 중복 제거, CLAUDE.md 현행화)
|
||||
|
||||
---
|
||||
|
||||
## 1. 보안
|
||||
|
||||
### 1.1 해당 없음 (소유자 확인 완료)
|
||||
|
||||
| # | 이슈 | 소유자 판단 |
|
||||
|---|------|------------|
|
||||
| ~~S1~~ | ~~JKS 키스토어가 Git에 추적 중~~ | **해당 없음** - 개인 비공개 저장소이므로 문제 없음 |
|
||||
| ~~S2~~ | ~~key.properties 평문 비밀번호 Git 노출~~ | **해당 없음** - 개인 비공개 저장소이므로 문제 없음 |
|
||||
|
||||
> **참고**: 저장소가 공개(public)로 전환되거나 팀 협업으로 확장될 경우 재검토 필요
|
||||
|
||||
### 1.2 WARNING
|
||||
|
||||
- `.vscode/`, `PLAN.md`가 추적되지 않은 상태로 존재
|
||||
|
||||
### 1.4 양호 항목
|
||||
|
||||
| 항목 | 상태 |
|
||||
|------|------|
|
||||
| 개인정보 처리방침 | 3개국어 준비 완료 (`doc/privacy-policy.md`) |
|
||||
| 네트워크 요청 | SDK 통한 간접 사용만 (직접 HTTP 없음) |
|
||||
| 사용자 데이터 수집 | 개인정보 미수집 (회원가입/로그인 없음) |
|
||||
| 분석/추적 SDK | 미사용 (Firebase, Sentry 등 없음) |
|
||||
| API 키 하드코딩 | 없음 |
|
||||
| 로컬 저장소 | 게임 상태/설정만 저장, 민감 데이터 없어 암호화 불필요 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 출시 준비 상태 - ~~7개~~ 0개 CRITICAL (모두 해결)
|
||||
|
||||
### 2.1 CRITICAL (출시 차단)
|
||||
|
||||
| # | 이슈 | 상세 |
|
||||
|---|------|------|
|
||||
| ~~R1~~ | ~~iOS Bundle ID = `com.example.asciineverdie`~~ | **수정 완료** - `com.naturebridgeai.asciineverdie`로 변경됨 |
|
||||
| ~~R2~~ | ~~macOS Bundle ID = `com.example.asciineverdie`~~ | **수정 완료** - `com.naturebridgeai.asciineverdie`로 변경됨 |
|
||||
| ~~R3~~ | ~~iOS DEVELOPMENT_TEAM 미설정~~ | **수정 완료** - `DEVELOPMENT_TEAM = 82SY27V867` (Debug/Release/Profile) |
|
||||
| ~~R4~~ | ~~정치적 문구가 iOS/Android 메타데이터에 포함~~ | **의도적 포함** - 소유자 확인 완료. 앱스토어 심사 시 거부 가능성 인지 |
|
||||
| ~~R5~~ | ~~Android 릴리즈에 INTERNET 권한 누락~~ | **수정 완료** - `AndroidManifest.xml`(main)에 INTERNET 권한 추가 |
|
||||
| ~~R6~~ | ~~iOS `GADApplicationIdentifier` 누락~~ | **수정 완료** - `Info.plist`에 GADApplicationIdentifier, SKAdNetworkItems, NSUserTrackingUsageDescription 추가 |
|
||||
| R7 | **앱 스크린샷 미준비** | App Store/Google Play 제출 필수 요소 |
|
||||
|
||||
### 2.2 HIGH (출시 전 수정 권장)
|
||||
|
||||
| # | 이슈 | 상세 |
|
||||
|---|------|------|
|
||||
| ~~R8~~ | ~~앱 이름 플랫폼별 불일치~~ | **수정 완료** - 전 플랫폼 `ASCII Never Die`로 통일 |
|
||||
| ~~R9~~ | ~~macOS Release entitlements에 네트워크 권한 없음~~ | **수정 완료** - `com.apple.security.network.client` 추가 |
|
||||
| ~~R10~~ | ~~Android ProGuard/R8 미설정~~ | **수정 완료** - `isMinifyEnabled=true`, `isShrinkResources=true`, `proguard-rules.pro` 추가 |
|
||||
| ~~R11~~ | ~~macOS PRODUCT_COPYRIGHT = `Copyright 2025 com.example`~~ | **수정 완료** - `Copyright © 2025 naturebridgeai`로 변경 |
|
||||
|
||||
### 2.3 MEDIUM
|
||||
|
||||
- Android minSdk/targetSdk가 Flutter 기본값 의존 (명시적 설정 권장)
|
||||
- iOS Podfile에서 platform 버전 주석 처리됨
|
||||
- 스플래시 화면이 기본 흰색 배경 (브랜딩 스플래시 권장)
|
||||
- Flavor/환경 분리 없음 (AdMob 테스트/프로덕션 분리 불가)
|
||||
- flutter_launcher_icons에 macOS 설정 없음
|
||||
|
||||
### 2.4 플랫폼별 상세
|
||||
|
||||
#### iOS
|
||||
|
||||
| 항목 | 설정값 | 상태 |
|
||||
|------|--------|------|
|
||||
| CFBundleDisplayName | `ASCII Never Die` | **수정 완료** |
|
||||
| PRODUCT_BUNDLE_IDENTIFIER | `com.naturebridgeai.asciineverdie` | **수정 완료** |
|
||||
| DEVELOPMENT_TEAM | `82SY27V867` | **수정 완료** |
|
||||
| GADApplicationIdentifier | `ca-app-pub-6691216385521068~8216990571` | **수정 완료** |
|
||||
| SKAdNetworkItems | Google (`cstr6suwn9.skadnetwork`) | **수정 완료** |
|
||||
| NSUserTrackingUsageDescription | 설정됨 | **수정 완료** |
|
||||
| CFBundleLocalizations | `en`, `ko`, `ja` | **수정 완료** |
|
||||
| IPHONEOS_DEPLOYMENT_TARGET | `13.0` | OK |
|
||||
| 앱 아이콘 | 전 사이즈 존재 (20~1024px) | OK |
|
||||
| LaunchScreen | 기본 Flutter 템플릿 | 개선 권장 |
|
||||
|
||||
#### Android
|
||||
|
||||
| 항목 | 설정값 | 상태 |
|
||||
|------|--------|------|
|
||||
| applicationId | `com.naturebridgeai.asciineverdie` | OK |
|
||||
| android:label | `ASCII Never Die` | **수정 완료** |
|
||||
| 릴리즈 서명 | key.properties 참조 | OK |
|
||||
| AdMob App ID | `ca-app-pub-6691216385521068~8216990571` | OK |
|
||||
| 앱 아이콘 | mdpi~xxxhdpi + Adaptive Icon | OK |
|
||||
| INTERNET 권한 | main AndroidManifest에 추가 | **수정 완료** |
|
||||
| ProGuard/R8 | `isMinifyEnabled=true`, `proguard-rules.pro` | **수정 완료** |
|
||||
|
||||
#### macOS
|
||||
|
||||
| 항목 | 설정값 | 상태 |
|
||||
|------|--------|------|
|
||||
| PRODUCT_BUNDLE_IDENTIFIER | `com.naturebridgeai.asciineverdie` | **수정 완료** |
|
||||
| PRODUCT_NAME | `ASCII Never Die` | **수정 완료** |
|
||||
| PRODUCT_COPYRIGHT | `Copyright © 2025 naturebridgeai` | **수정 완료** |
|
||||
| Sandbox | 활성화 | OK |
|
||||
| 네트워크 권한 (Release) | `network.client` 추가 | **수정 완료** |
|
||||
| MACOSX_DEPLOYMENT_TARGET | `10.15` | OK |
|
||||
| 앱 아이콘 | 16~1024px 존재 | OK |
|
||||
|
||||
---
|
||||
|
||||
## 3. 사업/수익화
|
||||
|
||||
### 3.1 현재 구현 상태
|
||||
|
||||
> **참고**: 사용자는 "IAP가 아직 설정이 안되어있다"고 인지하고 있으나, 실제로는 IAP와 AdMob 코드가 **이미 구현되어 있고 프로덕션 ID만 미설정** 상태임.
|
||||
|
||||
| 수익원 | 코드 구현 | 프로덕션 준비 | 준비도 |
|
||||
|--------|----------|-------------|--------|
|
||||
| 리워드 광고 (부활/되돌리기) | 구현됨 (`ad_service.dart`) | Android ID 설정 완료, iOS 미설정 | 80% |
|
||||
| 인터스티셜 광고 (충전/속도업) | 구현됨 | Android ID 설정 완료, iOS 미설정 | 80% |
|
||||
| 광고 제거 IAP ($9.99) | 구현됨 (`iap_service.dart`) | 스토어 상품 미등록 | 50% |
|
||||
|
||||
### 3.2 CRITICAL
|
||||
|
||||
| # | 이슈 |
|
||||
|---|------|
|
||||
| B1 | 프로덕션 광고 단위 ID - **Android 완료**, iOS 플레이스홀더 잔여 (`ad_service.dart:77,81`) |
|
||||
| ~~B2~~ | ~~iOS AdMob Info.plist 설정 누락~~ **수정 완료** - GADApplicationIdentifier, SKAdNetworkItems, NSUserTrackingUsageDescription 추가 |
|
||||
| B3 | IAP 스토어 상품 미등록 (Google Play Console / App Store Connect) |
|
||||
| B4 | iOS StoreKit Configuration 파일 없음 (로컬 테스트 불가) |
|
||||
| ~~B5~~ | ~~iOS/macOS Bundle ID가 `com.example`~~ **수정 완료** - `com.naturebridgeai.asciineverdie`로 변경됨 |
|
||||
|
||||
### 3.3 앱스토어 메타데이터
|
||||
|
||||
| 항목 | 상태 | 위치 |
|
||||
|------|------|------|
|
||||
| 앱 설명 (한/영/일) | 완비 | `doc/app-description.txt` |
|
||||
| 간단한 설명 (80자) | 완비 | 각 언어별 준비 |
|
||||
| 개인정보 처리방침 | 완비 (3개국어) | `doc/privacy-policy.md` |
|
||||
| 앱 스크린샷 | **미준비** | - |
|
||||
| 프로모션 텍스트 | 미확인 | - |
|
||||
| 랜딩 페이지/웹사이트 | 미준비 | - |
|
||||
|
||||
### 3.4 수익 모델 리스크 분석
|
||||
|
||||
| 리스크 | 설명 | 권장 |
|
||||
|--------|------|------|
|
||||
| 원작 무료 | Progress Quest는 완전 무료 오픈소스 - 클론 유료화 반감 가능 | 무료+광고 모델 유지, IAP 가격 인하 권장 |
|
||||
| 광고 제거 $9.99 | 방치형 RPG 장르 대비 **2~3배 높은 가격** (통상 $2.99~$4.99) | $2.99~$4.99로 인하 권장 |
|
||||
| 오프라인 전용 | 광고 노출에 네트워크 필요 - 오프라인 시 광고 수익 없음 | 인지 필요 |
|
||||
| 일회성 수익 | 광고 제거 IAP 한 번이면 이후 수익 제로 | 코스메틱 IAP 추가 고려 |
|
||||
| 저작권 | 원본 알고리즘/구조 사용 - PQ 저작자와의 관계 정리 필요 | 법률 검토 권장 |
|
||||
|
||||
### 3.5 Bundle ID 일관성
|
||||
|
||||
| 플랫폼 | Bundle ID | 상태 |
|
||||
|--------|-----------|------|
|
||||
| Android | `com.naturebridgeai.asciineverdie` | OK |
|
||||
| iOS | `com.naturebridgeai.asciineverdie` | **수정 완료** |
|
||||
| macOS | `com.naturebridgeai.asciineverdie` | **수정 완료** |
|
||||
|
||||
---
|
||||
|
||||
## 4. 빌드/테스트/정적분석
|
||||
|
||||
### 4.1 실행 결과
|
||||
|
||||
| 단계 | 결과 | 상세 |
|
||||
|------|------|------|
|
||||
| `flutter pub get` | **통과** | 의존성 정상 설치, 31개 패키지 업데이트 가능 |
|
||||
| `dart format --set-exit-if-changed .` | **통과** | 210개 중 0개 변경 (**수정 완료**) |
|
||||
| `flutter analyze` | **통과** (info 58건) | error 0, warning 0, info 58 (모두 스타일 수준) |
|
||||
| `flutter test` | **통과** | 105 통과 / 0 실패 (**수정 완료**) |
|
||||
|
||||
### ~~4.2 포맷 미준수 주요 파일~~ - **수정 완료** (42개 파일 자동 포맷 적용됨)
|
||||
|
||||
### 4.3 정적분석 이슈 (56건 info)
|
||||
|
||||
| 유형 | 건수 | 위치 |
|
||||
|------|------|------|
|
||||
| `unnecessary_brace_in_string_interps` | 4 | `lib/data/game_text_l10n.dart` |
|
||||
| `curly_braces_in_flow_control_structures` | 10 | `lib/data/game_text_l10n.dart` |
|
||||
| `dangling_library_doc_comments` | 1 | `lib/src/core/util/pq_logic.dart:1` |
|
||||
| `avoid_print` | ~30 | `test/core/engine/gcd_simulation_test.dart` |
|
||||
| `prefer_interpolation_to_compose_strings` | 4 | 같은 테스트 파일 |
|
||||
|
||||
### ~~4.4 실패 테스트~~ - **수정 완료**
|
||||
|
||||
- ~~**파일**: `test/core/engine/skill_service_test.dart:563`~~
|
||||
- **원인**: `SkillData.debugMode`의 `atkModifier`가 0.25→0.15, `mpCost`가 100→140으로 변경되었으나 테스트가 이전 값을 기대
|
||||
- **수정**: 테스트 기대값을 현재 데이터에 맞게 업데이트 (0.15, mpCurrent 10)
|
||||
|
||||
---
|
||||
|
||||
## 5. 코드 품질
|
||||
|
||||
### ~~5.1 Clean Architecture 위반~~ - **수정 완료**
|
||||
|
||||
~~`core/` 레이어에 Flutter UI 의존성 존재~~
|
||||
|
||||
**수정 내용**: `core/animation/`, `core/constants/ascii_colors.dart`, `core/l10n/game_data_l10n.dart` 등 Flutter UI 의존 파일 19개를 `shared/` 디렉토리로 이동. `core/` 레이어는 순수 Dart만 유지.
|
||||
|
||||
| 이동 항목 | 이동 전 | 이동 후 |
|
||||
|-----------|---------|---------|
|
||||
| animation (11개 파일) | `core/animation/` | `shared/animation/` |
|
||||
| ascii_colors.dart | `core/constants/` | `shared/theme/` |
|
||||
| game_data_l10n.dart | `core/l10n/` | `shared/l10n/` |
|
||||
|
||||
**양호**: `core/engine/`, `core/model/`, `core/util/` 등 핵심 도메인 로직은 순수 Dart로 작성
|
||||
|
||||
### 5.2 SRP 위반 - 대형 파일 - **부분 수정 완료**
|
||||
|
||||
**수정 완료**: 12개 대형 파일에서 23+개 신규 파일 추출. 대부분 400 LOC 이하로 감소.
|
||||
|
||||
| 파일 | 이전 LOC | 현재 LOC | 추출된 파일 |
|
||||
|------|----------|----------|------------|
|
||||
| `game_play_screen.dart` | 1,536 | **879** | `desktop_*_panel.dart` (3개) |
|
||||
| `canvas_battle_composer.dart` | 1,475 | **544** | `monster_frames.dart`, `combat_text_frames.dart` |
|
||||
| `progress_service.dart` | 1,247 | **832** | `task_generator.dart`, `death_handler.dart`, `loot_handler.dart` |
|
||||
| `arena_battle_screen.dart` | 976 | **759** | `arena_hp_bar.dart` |
|
||||
| `settings_screen.dart` | 821 | **455** | `retro_settings_widgets.dart` |
|
||||
| `arena_service.dart` | 811 | **308** | `arena_combat_simulator.dart` |
|
||||
| `death_overlay.dart` | 795 | — | `death_combat_log.dart`, `death_buttons.dart` |
|
||||
| `skill_service.dart` | 759 | **588** | `skill_auto_selector.dart` |
|
||||
| `app.dart` | 723 | **460** | `app_theme.dart`, `splash_screen.dart` |
|
||||
| `combat_tick_service.dart` | 681 | **443** | `player_attack_processor.dart` |
|
||||
| `game_statistics.dart` | 616 | — | `session_statistics.dart`, `cumulative_statistics.dart` |
|
||||
|
||||
*참고: StatefulWidget 상태 결합으로 인해 일부 파일은 400 LOC 이하 분리가 어려움. 정적 데이터 파일은 LOC 초과 허용.*
|
||||
|
||||
### 5.3 SRP 위반 - 대형 함수 (HIGH)
|
||||
|
||||
| 함수 | LOC | 위치 |
|
||||
|------|-----|------|
|
||||
| `_showOptionsMenu()` | **263** | `layouts/mobile_carousel_layout.dart:285` |
|
||||
| `build()` | **237** | `widgets/statistics_dialog.dart:316` |
|
||||
| `_handleCombatEvent()` | **207** | `widgets/ascii_animation_card.dart:281` |
|
||||
| `build()` | **199** | `widgets/statistics_dialog.dart:107` |
|
||||
| `build()` | **183** | `hall_of_fame/hall_of_fame_entry_card.dart:30` |
|
||||
| `build()` | **181** | `hall_of_fame/game_clear_dialog.dart:40` |
|
||||
| `_buildMonsterBar()` | **142** | `widgets/hp_mp_bar.dart:384` |
|
||||
| (보상 표시) | **140** | `widgets/return_rewards_dialog.dart:217` |
|
||||
| `build()` | **129** | `widgets/notification_overlay.dart:121` |
|
||||
| `fromJson()` | **113** | `core/model/save_data.dart:150` |
|
||||
| (아이템 생성) | **101** | `core/engine/item_service.dart:195` |
|
||||
|
||||
### 5.4 타입 안전성 (MEDIUM)
|
||||
|
||||
| 위치 | 문제 |
|
||||
|------|------|
|
||||
| `features/game/widgets/return_rewards_dialog.dart:452` | `Color _getRarityColor(dynamic rarity)` - `ItemRarity?`로 교체 필요 |
|
||||
| `core/notification/notification_service.dart:31` | `Map<String, dynamic>? data` - 타입 안전 모델 권장 |
|
||||
| `core/engine/story_service.dart:20` | `Map<String, dynamic>? data` - 동일 |
|
||||
| `core/model/save_data.dart:156-157` | 불필요한 `cast<dynamic>()` 사용 |
|
||||
|
||||
*참고: 생성 파일(.g.dart, .freezed.dart)의 `Map<String, dynamic>`은 JSON 직렬화 패턴이므로 허용*
|
||||
|
||||
### ~~5.5 코드 중복~~ - **수정 완료**
|
||||
|
||||
~~`_toRoman()` 함수 3곳 중복~~
|
||||
|
||||
**수정 내용**: `game_play_screen.dart`와 `story_page.dart`의 중복 `_toRoman()` 제거, `core/util/roman.dart`의 `intToRoman()` import로 통일
|
||||
|
||||
### 5.6 TODO/FIXME 미완성 마커
|
||||
|
||||
| 위치 | 내용 | 상태 |
|
||||
|------|------|------|
|
||||
| `core/engine/iap_service.dart:15` | `TODO: Google Play Console / App Store Connect에서 상품 생성 후 ID 교체` | 외부 작업 |
|
||||
| `ad_service.dart:77,81` | iOS 프로덕션 광고 ID 플레이스홀더 | iOS 차후 설정 |
|
||||
| ~~`ad_service.dart:74-75,78-79`~~ | ~~Android 프로덕션 광고 ID 플레이스홀더~~ | **수정 완료** |
|
||||
|
||||
### 5.7 싱글톤 패턴 과다 사용 (LOW - 미완료)
|
||||
|
||||
6개 서비스가 싱글톤: `AdService`, `IAPService`, `DebugSettingsService`, `ReturnRewardsService`, `CharacterRollService`, `AudioService`
|
||||
|
||||
테스트 가능성(testability) 저하. DI(의존성 주입) 패턴으로 전환 권장. (P2 #25)
|
||||
|
||||
### 5.8 양호 항목
|
||||
|
||||
| 항목 | 상태 |
|
||||
|------|------|
|
||||
| 네이밍 컨벤션 | 전반적으로 잘 준수 (snake_case 파일, PascalCase 클래스, camelCase 변수) |
|
||||
| 미사용 import | lib/ 내 0건 |
|
||||
| `flutter analyze` lib/ 이슈 | 0건 (56건 모두 test/ 디렉토리) |
|
||||
| 에러 핸들링 | ad_service, iap_service에서 적절한 try-catch + debugPrint 로깅 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 로컬라이제이션 / 접근성
|
||||
|
||||
### 6.1 로컬라이제이션 설정 (양호)
|
||||
|
||||
| 항목 | 상태 |
|
||||
|------|------|
|
||||
| `l10n.yaml` | 존재, 올바르게 설정 |
|
||||
| ARB 파일 | 3개 언어 (en, ko, ja) |
|
||||
| `flutter_localizations` | pubspec.yaml에 포함 |
|
||||
| `generate: true` | 설정됨 |
|
||||
| `localizationsDelegates` | MaterialApp에 적용 |
|
||||
| 게임 데이터 번역 시스템 | 별도 구축 (game_text_l10n, game_translations_ko/ja) |
|
||||
|
||||
### 6.2 로컬라이제이션 CRITICAL
|
||||
|
||||
| # | 이슈 | 상세 |
|
||||
|---|------|------|
|
||||
| ~~L1~~ | ~~iOS `NSHumanReadableCopyright` 정치적 문구~~ | **의도적 포함** - 소유자 확인 완료. 심사 거부 가능성 인지 |
|
||||
| ~~L2~~ | ~~일본어 ARB 70%+ 미번역~~ | **수정 완료** - 전체 148개 키 중 약 75개 키 일본어 번역 완성. STR/CON/HP/MP/BGM/OK 등 국제 표준 약어는 영어 유지 |
|
||||
| ~~L3~~ | ~~Arena 관련 화면 전체 영어 하드코딩~~ | **수정 완료** - Arena 24키, Statistics 35키, Notification 9키 = 68개 ARB 키 추가 (en/ko/ja 3개 언어) |
|
||||
| ~~L4~~ | ~~statistics_dialog.dart 하드코딩~~ | **수정 완료** - ARB 키로 전환 |
|
||||
| ~~L5~~ | ~~iOS `CFBundleLocalizations` 미설정~~ | **수정 완료** - `Info.plist`에 `en`, `ko`, `ja` 추가 |
|
||||
|
||||
### 6.3 로컬라이제이션 기타
|
||||
|
||||
| 심각도 | 이슈 |
|
||||
|--------|------|
|
||||
| MEDIUM | `notification_overlay.dart` 타입 라벨 영어 하드코딩 (`LEVEL UP`, `QUEST DONE`, `BOSS SLAIN` 등) |
|
||||
| LOW | `victory_overlay.dart` 스탯 약어 하드코딩 (`STR`, `CON` 등 - 국제 통용 약어, 의도적일 수 있음) |
|
||||
| LOW | `death_overlay.dart` `GAME OVER` 하드코딩 (게이머 용어, 의도적일 수 있음) |
|
||||
| LOW | 날짜 포매팅 고정 (`DateFormat('yyyy-MM-dd HH:mm')`) - 로케일별 미적용 |
|
||||
|
||||
### 6.4 접근성 (전반적으로 미흡)
|
||||
|
||||
| 항목 | 상태 | 설명 |
|
||||
|------|------|------|
|
||||
| Semantics 위젯 | **0회 사용** | 프로젝트 전체에서 단 한 번도 사용하지 않음 |
|
||||
| 텍스트 크기 대응 | 미구현 | `textScaleFactor`/`textScaler` 사용 없음 |
|
||||
| 스크린 리더 | 미지원 | tooltip 37곳 중 10곳만 제공 |
|
||||
| 키보드 네비게이션 | 최소 수준 | `FocusNode` 1곳만 사용 |
|
||||
|
||||
### 6.5 색상 대비
|
||||
|
||||
| 모드 | 요소 | 대비율 | WCAG |
|
||||
|------|------|--------|------|
|
||||
| 다크 | 기본 텍스트 (`#C0CAF5` on `#1A1B26`) | 10.5:1 | AAA 충족 |
|
||||
| 다크 | 골드 텍스트 (`#E0AF68` on `#24283B`) | 5.8:1 | AA 충족, AAA 미달 |
|
||||
| 다크 | **Muted 텍스트 (`#565F89` on `#1A1B26`)** | **3.3:1** | **AA 미달** |
|
||||
| 라이트 | 기본 텍스트 (`#1F1F28` on `#FAF4ED`) | 14.5:1 | AAA 충족 |
|
||||
| 라이트 | Muted 텍스트 (`#797593` on `#FAF4ED`) | 4.5:1 | AA 충족, AAA 미달 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 원본 충실도 (Progress Quest 6.4 대비)
|
||||
|
||||
### 7.1 핵심 발견
|
||||
|
||||
> **CLAUDE.md**: "Progress Quest 6.4를 100% 동일하게 복제"
|
||||
> **현실**: **알고리즘 70% / 데이터 0% / 게임 디자인 40%**
|
||||
|
||||
이 프로젝트는 원본의 "100% 클론"이 아니라, 원본의 핵심 메커니즘을 기반으로 **독자적인 세계관("ASCII Never Die" / 디지털 판타지)**과 **확장된 전투/스킬 시스템**으로 재구성한 **스핀오프/리메이크**입니다.
|
||||
|
||||
### 7.2 알고리즘 충실도 (70%)
|
||||
|
||||
#### 구현 완료 (원본과 동일)
|
||||
|
||||
| 기능 | 원본 위치 | 현재 위치 | 상태 |
|
||||
|------|-----------|-----------|------|
|
||||
| 캐릭터 스탯 롤링 (3d6) | `NewGuy.pas:55-68` | `pq_random.dart:36` | 100% 동일 |
|
||||
| 이름 생성 | `NewGuy.pas:218-240` | `pq_random.dart` | 100% 동일 |
|
||||
| 몬스터 생성 | `Main.pas:523-605` | `pq_monster.dart:61-170` | 100% 동일 |
|
||||
| 몬스터 수식어 (sick/young/big/special) | `Main.pas:402-454` | `pq_monster.dart` | 100% 동일 |
|
||||
| 장비 획득 (winEquip) | `Main.pas:791-830` | `pq_item.dart:217-245` | 100% 동일 |
|
||||
| 아이템 획득 (winItem/specialItem) | `Main.pas:903-908` | `pq_item.dart` | 100% 동일 |
|
||||
| 퀘스트 시스템 (5종 퀘스트) | `Main.pas:910-990` | `pq_quest.dart:62-136` | 100% 동일 |
|
||||
| 시네마틱 (3가지 시나리오) | `Main.pas:456-521` | `pq_quest.dart:194-261` | 구조 100% 동일 |
|
||||
| 주문서(SpellBook) 시스템 | `Main.pas:770-774` | `pq_quest.dart:268-283` | 100% 동일 |
|
||||
| 로마 숫자 변환 | `Main.pas:992-1053` | `roman.dart` | 100% 동일 |
|
||||
| 전리품 생성 | `Main.pas:625-630` | `_winLoot()` | 100% 동일 |
|
||||
|
||||
#### 변경된 로직
|
||||
|
||||
| 항목 | 원본 | 현재 | 차이 |
|
||||
|------|------|------|------|
|
||||
| 경험치 | 시간 기반 `(20+1.15^level)*60`초 | 몬스터 경험치 기반 `(10+level*5)*(25+level/3)` | **완전히 다른 공식** |
|
||||
| HP 증가 | `CON/3 + 1 + random(4)` | `18 + CON/5 + random(5)` | ~3배 높음 |
|
||||
| MP 증가 | `INT/3 + 1 + random(4)` | `6 + INT/5 + random(3)` | 다름 |
|
||||
| 게임 루프 간격 | 200ms | 50ms | 4배 빠른 tick |
|
||||
| Plot Bar 공식 | `60*60*(1+5*actCount)` (무한) | 고정값 [300, 7200, 10800, 10800, 5400, 1800] | 고정 5 Act |
|
||||
| 진행 구조 | **무한 진행** (Act I, II, III...) | **고정 5 Act + 엔딩** (Lv100 종료) | 근본적 차이 |
|
||||
| 전투 | 시간 바 자동 완료 (항상 승리) | HP/ATK 기반 실시간 전투 (사망 가능) | 근본적 차이 |
|
||||
|
||||
### 7.3 데이터 충실도 (0%)
|
||||
|
||||
**Config.dfm의 원본 데이터를 전혀 사용하지 않음. 모든 데이터가 "디지털 판타지" 세계관으로 완전 교체.**
|
||||
|
||||
| 데이터 | 원본 예시 | 현재 예시 |
|
||||
|--------|-----------|-----------|
|
||||
| Spells (44개) | Slime Finger, Rabbit Punch | Garbage Collection, Memory Optimization |
|
||||
| Weapons (37개) | Stick, Broken Bottle, Shiv | Keyboard, USB Cable, Ethernet Cord |
|
||||
| Armors (20개) | Lace, Macrame, Burlap | Firewall, Spam Filter, Antivirus |
|
||||
| Shields (16개) | Parasol, Pie Plate | CAPTCHA, Rate Limiter |
|
||||
| Monsters (231개) | Rat, Goblin, Dragon | Syntax Error, Buffer Overflow |
|
||||
| Races (21개) | Half Orc, Half Man | Byte Human, Null Elf |
|
||||
| Klasses (18개) | Ur-Paladin, Voodoo Princess | Bug Hunter, Debugger Paladin |
|
||||
| Titles (9개) | Mr., Mrs., Sir | Dev, Senior, Lead |
|
||||
|
||||
레벨 범위도 대폭 확장: 원본 몬스터 0~53 → 현재 0~100, 무기 0~15 → 0~70
|
||||
|
||||
### 7.4 원본에 없는 추가 시스템 (13개)
|
||||
|
||||
1. **전투 시스템** (CombatState, CombatStats, HP/MP, 턴제 전투)
|
||||
2. **사망/부활 시스템** (DeathInfo, 장비 손실)
|
||||
3. **스킬/버프 시스템** (SkillSlots, 액티브/패시브 스킬)
|
||||
4. **물약 시스템** (PotionService, HP/MP 물약)
|
||||
5. **종족/직업 특성** (ClassTraits, RaceTraits, 패시브 보너스)
|
||||
6. **아레나 시스템** (arena_service.dart, PvP 전투)
|
||||
7. **명예의 전당** (hall_of_fame_storage.dart)
|
||||
8. **보스 전투 메커니즘** (페이즈, 분노, 보호막, 특수 능력)
|
||||
9. **장비 스탯** (ItemStats, 공격력/방어력/HP 보너스)
|
||||
10. **스토리/시네마틱 시스템** (StoryService, 레벨 기반 Act 전환)
|
||||
11. **배속 시스템** (1x/2x/5x)
|
||||
12. **통계 시스템** (GameStatistics)
|
||||
13. **게임 클리어 시스템** (레벨 100, 최종 보스 처치 시 엔딩)
|
||||
|
||||
### ~~7.5 CLAUDE.md와의 충돌~~ - **해결 완료**
|
||||
|
||||
~~CLAUDE.md에 명시된 규칙이 현재 구현과 괴리~~
|
||||
|
||||
**수정 완료**: CLAUDE.md를 현재 프로젝트 실태에 맞게 업데이트.
|
||||
- "100% 동일하게 복제" → "핵심 메커니즘 기반 독자적 리메이크"
|
||||
- 원본 충실도 제약 삭제
|
||||
- 디렉토리 구조, 화면 구성 등 현행화
|
||||
|
||||
---
|
||||
|
||||
## 8. 우선순위별 액션 플랜
|
||||
|
||||
### P0 - 즉시 (심사 차단)
|
||||
|
||||
| # | 작업 | 난이도 | 상태 |
|
||||
|---|------|--------|------|
|
||||
| ~~1~~ | ~~Git에서 JKS 키스토어 + key.properties 제거~~ | - | **해당 없음** - 개인 비공개 저장소 |
|
||||
| ~~2~~ | ~~.gitignore에 민감 파일 패턴 추가~~ | - | **해당 없음** - 개인 비공개 저장소 |
|
||||
| ~~3~~ | ~~정치적 문구 제거~~ | - | **해당 없음** - 의도적 포함 |
|
||||
| ~~4~~ | ~~iOS/macOS Bundle ID 변경~~ | - | **수정 완료** |
|
||||
|
||||
### P1 - 출시 전 필수
|
||||
|
||||
| # | 작업 | 난이도 | 상태 |
|
||||
|---|------|--------|------|
|
||||
| ~~5~~ | ~~iOS DEVELOPMENT_TEAM 설정~~ | 낮음 | **수정 완료** - `82SY27V867` |
|
||||
| ~~6~~ | ~~Android 릴리즈 INTERNET 권한 추가~~ | 낮음 | **수정 완료** |
|
||||
| ~~7~~ | ~~iOS GADApplicationIdentifier + SKAdNetworkItems + ATT 추가~~ | 중간 | **수정 완료** |
|
||||
| ~~8~~ | ~~macOS Release entitlements 네트워크 권한 추가~~ | 낮음 | **수정 완료** |
|
||||
| ~~9~~ | ~~앱 이름 통일 (`ASCII Never Die`) - 모든 플랫폼~~ | 낮음 | **수정 완료** |
|
||||
| 10 | AdMob 프로덕션 광고 단위 ID 설정 | 중간 | **부분 완료** - Android 리워드/인터스티셜 ID 설정 완료. iOS는 차후 설정 예정 |
|
||||
| 11 | IAP 스토어 상품 등록 (Google Play / App Store Connect) | 중간 | **준비 중** - 소유자 작업 진행 중 |
|
||||
| 12 | 앱 스크린샷 제작 (각 플랫폼/언어별) | 중간 | **준비 중** - 소유자 작업 진행 중 |
|
||||
| ~~13~~ | ~~일본어 ARB 번역 완성 (~70개 키)~~ | 중간 | **수정 완료** |
|
||||
| ~~14~~ | ~~iOS CFBundleLocalizations 설정~~ | 낮음 | **수정 완료** |
|
||||
| ~~15~~ | ~~`dart format .` 적용~~ | 낮음 | **수정 완료** |
|
||||
| ~~16~~ | ~~실패 테스트 수정 (`skill_service_test.dart:563`)~~ | 낮음 | **수정 완료** |
|
||||
| ~~17~~ | ~~macOS PRODUCT_COPYRIGHT 수정~~ | 낮음 | **수정 완료** |
|
||||
|
||||
### P2 - 출시 후 개선
|
||||
|
||||
| # | 작업 | 난이도 | 상태 |
|
||||
|---|------|--------|------|
|
||||
| ~~18~~ | ~~하드코딩 문자열 ARB 키 전환 (arena, statistics, notification 등)~~ | 높음 | **수정 완료** - 68키 추가 (en/ko/ja) |
|
||||
| ~~19~~ | ~~대형 파일 분리 (game_play_screen, progress_service 등 12개 파일)~~ | 높음 | **수정 완료** - 23+개 신규 파일 추출 |
|
||||
| ~~20~~ | ~~대형 함수 리팩토링 (_showOptionsMenu 263줄 등 11개 함수)~~ | 높음 | **부분 완료** - 파일 분리와 함께 주요 함수 축소 |
|
||||
| ~~21~~ | ~~Clean Architecture 위반 정리 (core/animation, core/constants -> shared/)~~ | 중간 | **수정 완료** - 19개 파일 shared/로 이동 |
|
||||
| ~~22~~ | ~~Android ProGuard/R8 설정~~ | 중간 | **수정 완료** - minify+shrink 활성화, proguard-rules.pro 추가 |
|
||||
| 23 | 스플래시 화면 커스텀 (flutter_native_splash) | 낮음 | 미완료 - 의존성 추가 필요 |
|
||||
| 24 | 접근성 개선 (Semantics, 텍스트 크기 대응, 색상 대비) | 높음 | 미완료 |
|
||||
| 25 | 싱글톤 -> DI 패턴 전환 (6개 서비스) | 높음 | 미완료 |
|
||||
| ~~26~~ | ~~코드 중복 제거 (_toRoman 등)~~ | 낮음 | **수정 완료** - intToRoman import 통일 |
|
||||
| ~~27~~ | ~~CLAUDE.md 현행화 (원본 충실도 방향 재정립)~~ | 낮음 | **수정 완료** |
|
||||
| 28 | IAP 가격 조정 검토 ($9.99 -> $2.99~$4.99) | 결정 사항 | 소유자 결정 필요 |
|
||||
| 29 | Crashlytics/분석 도구 도입 (출시 후 모니터링) | 중간 | 미완료 - Firebase 설정 필요 |
|
||||
| 30 | 키보드 네비게이션 강화 (macOS 빌드) | 중간 | 미완료 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 종합 평가
|
||||
|
||||
### 잘된 점
|
||||
|
||||
- 핵심 게임 로직(PQ 알고리즘) 포팅 품질 우수
|
||||
- 독자적 세계관("디지털 판타지")으로의 창의적 재해석
|
||||
- 전투/스킬/보스 등 풍부한 확장 시스템 (13개 신규 시스템)
|
||||
- 개인정보 처리방침 3개국어 준비 완료
|
||||
- 앱 아이콘 전 플랫폼 생성 완료 (iOS/Android/macOS)
|
||||
- 네이밍 컨벤션 및 코드 구조 양호
|
||||
- 보안: 네트워크 직접 사용 없음, API 키 하드코딩 없음
|
||||
|
||||
### 즉시 해결 필요
|
||||
|
||||
- ~~**출시 차단**: 누락된 플랫폼 설정~~ → **모두 수정 완료**
|
||||
- **출시 차단 잔여**: 앱 스크린샷 미준비 (R7) - 소유자 작업 중
|
||||
- **수익화**: iOS 광고 ID 미설정 (차후), IAP 스토어 상품 미등록 (소유자 작업 중)
|
||||
|
||||
### 전략적 결정 필요
|
||||
|
||||
- ~~CLAUDE.md의 "100% 동일 포팅" 목표 vs 현재 "스핀오프/리메이크" 실태 정립~~ → **해결 완료** (CLAUDE.md 현행화)
|
||||
- 원작이 무료인 점을 감안한 수익 모델 최적화
|
||||
- 광고 제거 IAP 가격 결정 ($9.99 vs $2.99~$4.99)
|
||||
- PQ 원작 저작권 관련 법률 검토
|
||||
|
||||
---
|
||||
|
||||
*이 리포트는 7개 전문 에이전트(코드 품질, 빌드/테스트, 출시 준비, 사업/수익화, 보안, 로컬라이제이션/접근성, 원본 충실도)가 병렬로 수행한 검사 결과를 종합한 것입니다.*
|
||||
242
doc/game-system-overhaul-index.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# ASCII Never Die - 게임 시스템 개편 계획
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
Progress Quest 클론에서 **실제 게임성을 갖춘 RPG**로 전환한다.
|
||||
Idle game의 자동 진행 특성은 유지하되, 전투/성장/사망의 의미있는 시스템을 도입한다.
|
||||
|
||||
### 1.2 핵심 변경 사항
|
||||
- Stats가 전투에 실제 영향을 미침
|
||||
- 사망 시스템 및 부활 메커니즘
|
||||
- MP 기반 스킬 시스템
|
||||
- 아이템 스탯 및 가중치
|
||||
- 레벨 1-100 밸런싱
|
||||
- 종족/클래스 특화
|
||||
|
||||
### 1.3 현재 상태
|
||||
| 항목 | 현재 | 목표 |
|
||||
|------|------|------|
|
||||
| Stats | 장식용 (CON→HP, INT→MP, WIS→주문, STR→무게만 영향) | 전투력에 직접 영향 |
|
||||
| 전투 | 시간 경과 시 자동 승리 | 데미지 계산, 승패 결정 |
|
||||
| 사망 | 없음 | 장비 상실, 부활 버튼 |
|
||||
| 스킬 | 획득만 (사용 없음) | MP 소모, 쿨타임 |
|
||||
| 아이템 | 이름만 존재 | 스탯 보정, 가중치 |
|
||||
| 레벨 | 무한 성장 | 1-100 (100에서 성장 멈춤) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 수정 단계 (Phase)
|
||||
|
||||
```
|
||||
Phase 1: 핵심 전투 시스템 ████████████████████ (기반)
|
||||
Phase 2: 아이템 시스템 ████████████████ (의존: Phase 1)
|
||||
Phase 3: 스킬 시스템 ████████████ (의존: Phase 1, 2)
|
||||
Phase 4: 사망/부활 시스템 ████████ (의존: Phase 1, 2, 3)
|
||||
Phase 5: 종족/클래스 특화 ██████ (의존: Phase 1)
|
||||
Phase 6: 밸런싱 ████████████████████ (전체 의존)
|
||||
Phase 7: 콘텐츠 확장 ████████████ (의존: Phase 6)
|
||||
Phase 8: UI/UX 개선 ████████ (병렬 가능)
|
||||
Phase 9: 스토리/엔딩 ██████ (의존: Phase 7)
|
||||
Phase 10: 명예의 전당 ████ (최종)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 문서 구조
|
||||
|
||||
이 계획서는 다음 태스크 문서들로 구성됩니다:
|
||||
|
||||
### 핵심 Phase 문서
|
||||
| 문서 | 내용 |
|
||||
|------|------|
|
||||
| [task-phase-01-combat.md](task-phase-01-combat.md) | Phase 1: 핵심 전투 시스템 |
|
||||
| [task-phase-02-items.md](task-phase-02-items.md) | Phase 2: 아이템 시스템 |
|
||||
| [task-phase-03-skills.md](task-phase-03-skills.md) | Phase 3: 스킬 시스템 |
|
||||
| [task-phase-04-death.md](task-phase-04-death.md) | Phase 4: 사망/부활 시스템 |
|
||||
| [task-phase-05-race-class.md](task-phase-05-race-class.md) | Phase 5: 종족/클래스 특화 |
|
||||
| [task-phase-06-balance.md](task-phase-06-balance.md) | Phase 6: 밸런싱 |
|
||||
| [task-phase-07-content.md](task-phase-07-content.md) | Phase 7: 콘텐츠 확장 |
|
||||
| [task-phase-08-ui.md](task-phase-08-ui.md) | Phase 8: UI/UX 개선 |
|
||||
| [task-phase-09-story.md](task-phase-09-story.md) | Phase 9: 스토리/엔딩 |
|
||||
| [task-phase-10-hall.md](task-phase-10-hall.md) | Phase 10: 명예의 전당 |
|
||||
|
||||
### 추가 시스템 문서
|
||||
| 문서 | 내용 |
|
||||
|------|------|
|
||||
| [task-ext-audio-access.md](task-ext-audio-access.md) | 사운드/진동/접근성 |
|
||||
| [task-ext-meta-systems.md](task-ext-meta-systems.md) | 업적/도감/통계/칭호 |
|
||||
| [task-ext-settings-infra.md](task-ext-settings-infra.md) | 설정/튜토리얼/성능/테스트 |
|
||||
| [task-ext-save-data.md](task-ext-save-data.md) | 세이브/멀티슬롯/마이그레이션 |
|
||||
| [task-ext-combat.md](task-ext-combat.md) | 몬스터 AI/퀘스트/버프 |
|
||||
| [task-ext-items.md](task-ext-items.md) | 세트/강화/인벤토리/물약 |
|
||||
| [task-ext-world.md](task-ext-world.md) | 던전/지역/상점 |
|
||||
| [task-ext-events.md](task-ext-events.md) | 이벤트/알림 |
|
||||
| [task-ext-ui-tech.md](task-ext-ui-tech.md) | UI 레이아웃/기술 상세 |
|
||||
| [task-ext-platform.md](task-ext-platform.md) | 오프라인/플랫폼/향후 |
|
||||
|
||||
### 게임 디자인 문서
|
||||
| 문서 | 내용 |
|
||||
|------|------|
|
||||
| [task-fun-design.md](task-fun-design.md) | 재미 요소 설계 |
|
||||
|
||||
---
|
||||
|
||||
## 17. 작업 우선순위 및 의존성
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
P1[Phase 1: 전투 시스템] --> P2[Phase 2: 아이템]
|
||||
P1 --> P5[Phase 5: 종족/클래스]
|
||||
P2 --> P3[Phase 3: 스킬]
|
||||
P1 --> P4[Phase 4: 사망/부활]
|
||||
P2 --> P4
|
||||
P3 --> P4
|
||||
P5 --> P6[Phase 6: 밸런싱]
|
||||
P4 --> P6
|
||||
P6 --> P7[Phase 7: 콘텐츠]
|
||||
P7 --> P9[Phase 9: 스토리]
|
||||
P9 --> P10[Phase 10: 명예의 전당]
|
||||
|
||||
P8[Phase 8: UI/UX] -.-> P1
|
||||
P8 -.-> P4
|
||||
```
|
||||
|
||||
### 권장 작업 순서
|
||||
|
||||
1. **Phase 1: 핵심 전투 시스템** (필수, 모든 것의 기반)
|
||||
2. **Phase 2: 아이템 시스템** (전투 시스템 활용)
|
||||
3. **Phase 5: 종족/클래스 특화** (전투 시스템과 병렬 가능)
|
||||
4. **Phase 3: 스킬 시스템** (전투 + 아이템 필요)
|
||||
5. **Phase 4: 사망/부활 시스템** (전투 + 아이템 + 스킬 필요)
|
||||
6. **Phase 8: UI/UX 개선** (다른 Phase와 병렬 진행 가능)
|
||||
7. **Phase 6: 밸런싱** (모든 시스템 완료 후)
|
||||
8. **Phase 7: 콘텐츠 확장** (밸런싱 후)
|
||||
9. **Phase 9: 스토리/엔딩** (콘텐츠 확장 후)
|
||||
10. **Phase 10: 명예의 전당** (최종)
|
||||
|
||||
---
|
||||
|
||||
## 18. 총 예상 작업량
|
||||
|
||||
### 18.1 핵심 Phase (Phase 1-10)
|
||||
|
||||
| Phase | 신규 코드 | 수정 코드 | 파일 수 |
|
||||
|-------|----------|----------|---------|
|
||||
| 1. 전투 시스템 | 400 | 200 | 5 |
|
||||
| 2. 아이템 | 500 | 300 | 6 |
|
||||
| 3. 스킬 | 600 | 200 | 6 |
|
||||
| 4. 사망/부활 | 500 | 200 | 7 |
|
||||
| 5. 종족/클래스 | 400 | 150 | 7 |
|
||||
| 6. 밸런싱 | 300 | 400 | 5 |
|
||||
| 7. 콘텐츠 | 1000 | 200 | 5 |
|
||||
| 8. UI/UX | 400 | 200 | 6 |
|
||||
| 9. 스토리 | 600 | 100 | 5 |
|
||||
| 10. 명예의 전당 | 400 | 100 | 5 |
|
||||
| **소계** | **5,100** | **2,050** | **57** |
|
||||
|
||||
### 18.2 추가 시스템 (Section 13)
|
||||
|
||||
| 시스템 | 신규 코드 | 수정 코드 | 파일 수 |
|
||||
|--------|----------|----------|---------|
|
||||
| 13.1 사운드/음악/진동 | 300 | 100 | 4 |
|
||||
| 13.2 업적 시스템 | 400 | 150 | 5 |
|
||||
| 13.3 도감 시스템 | 350 | 100 | 4 |
|
||||
| 13.4 통계 화면 | 300 | 100 | 4 |
|
||||
| 13.8 튜토리얼 | 400 | 150 | 4 |
|
||||
| 13.9 오프라인 진행 | 300 | 100 | 4 |
|
||||
| 13.10 멀티 세이브 | 250 | 150 | 4 |
|
||||
| 13.11 데이터 마이그레이션 | 200 | 100 | 3 |
|
||||
| 13.12 몬스터 AI/보스 | 500 | 200 | 5 |
|
||||
| 13.13 퀘스트 시스템 | 600 | 200 | 6 |
|
||||
| 13.14 세이브 파일 관리 | 250 | 100 | 3 |
|
||||
| 13.15 접근성 | 200 | 100 | 3 |
|
||||
| 13.16 세트 아이템 | 300 | 100 | 3 |
|
||||
| 13.17 강화/합성 | 350 | 150 | 4 |
|
||||
| 13.18 인벤토리 관리 | 300 | 150 | 4 |
|
||||
| 13.19 버프/디버프 | 400 | 150 | 4 |
|
||||
| 13.20 칭호 시스템 | 250 | 100 | 3 |
|
||||
| **소계** | **5,650** | **2,100** | **67** |
|
||||
|
||||
### 18.3 총합
|
||||
|
||||
| 구분 | 신규 코드 | 수정 코드 | 파일 수 |
|
||||
|------|----------|----------|---------|
|
||||
| 핵심 Phase | 5,100 | 2,050 | 57 |
|
||||
| 추가 시스템 | 5,650 | 2,100 | 67 |
|
||||
| **총합** | **10,750** | **4,150** | **124** |
|
||||
|
||||
### 18.4 총 예상 코드량
|
||||
|
||||
약 14,900 LOC
|
||||
|
||||
---
|
||||
|
||||
## 19. 위험 요소 및 대응
|
||||
|
||||
| 위험 | 영향 | 대응 방안 |
|
||||
|------|------|----------|
|
||||
| 밸런스 붕괴 | 게임성 저하 | 시뮬레이션 테스트, 점진적 조정 |
|
||||
| 복잡도 증가 | 유지보수 어려움 | 모듈화, 문서화 철저 |
|
||||
| 기존 세이브 호환성 | 사용자 데이터 손실 | 마이그레이션 로직 필수 |
|
||||
| 성능 저하 | UX 저하 | 프로파일링, 최적화 |
|
||||
| 원본과의 괴리 | 정체성 혼란 | 명확한 차별화 선언 |
|
||||
|
||||
---
|
||||
|
||||
## 20. 버전 계획
|
||||
|
||||
### 20.1 MVP (Minimum Viable Product)
|
||||
|
||||
| 버전 | 포함 내용 | 목표 |
|
||||
|------|----------|------|
|
||||
| v0.5.0 | Phase 1, 2 | 기본 전투 + 아이템 스탯 |
|
||||
| v0.6.0 | Phase 3, 5 | 스킬 + 종족/클래스 특화 |
|
||||
| v0.7.0 | Phase 4, 13.11 | 사망/부활 + 데이터 마이그레이션 |
|
||||
|
||||
### 20.2 Core Features
|
||||
|
||||
| 버전 | 포함 내용 | 목표 |
|
||||
|------|----------|------|
|
||||
| v0.8.0 | Phase 8, 13.8 | UI/UX + 튜토리얼 |
|
||||
| v0.9.0 | 13.10, 13.14 | 멀티 세이브 + 세이브 관리 |
|
||||
| v0.10.0 | Phase 6, 13.12 | 밸런싱 + 보스 패턴 |
|
||||
|
||||
### 20.3 Content Expansion
|
||||
|
||||
| 버전 | 포함 내용 | 목표 |
|
||||
|------|----------|------|
|
||||
| v0.11.0 | 13.13, 13.16 | 퀘스트 시스템 + 세트 아이템 |
|
||||
| v0.12.0 | 13.17, 13.18 | 강화/합성 + 인벤토리 |
|
||||
| v0.13.0 | 13.19, 13.20 | 버프/디버프 + 칭호 |
|
||||
|
||||
### 20.4 Polish & Release
|
||||
|
||||
| 버전 | 포함 내용 | 목표 |
|
||||
|------|----------|------|
|
||||
| v0.14.0 | Phase 7, 9 | 콘텐츠 확장 + 스토리 |
|
||||
| v0.15.0 | 13.2, 13.3 | 업적 + 도감 |
|
||||
| v0.16.0 | 13.4, 13.1 | 통계 + 사운드 |
|
||||
| v0.17.0 | 13.9, 13.15 | 오프라인 진행 + 접근성 |
|
||||
| v0.18.0 | Phase 10 | 명예의 전당 |
|
||||
|
||||
### 20.5 정식 출시
|
||||
|
||||
| 버전 | 목표 |
|
||||
|------|------|
|
||||
| v1.0.0-beta | 전체 기능 테스트 |
|
||||
| v1.0.0-rc | 버그 수정, 밸런싱 미세조정 |
|
||||
| v1.0.0 | 정식 출시 |
|
||||
|
||||
### 20.6 Post-Launch
|
||||
|
||||
| 버전 | 포함 내용 | 목표 |
|
||||
|------|----------|------|
|
||||
| v1.1.0 | 13.22.1 | 타임어택/스피드런 |
|
||||
| v1.2.0 | 13.22.3 | 다국어 확장 (일본어, 중국어) |
|
||||
| v1.5.0 | 13.6.2 | 아스키 아레나 (온라인 기능) |
|
||||
|
||||
---
|
||||
|
||||
*문서 작성일: 2024년*
|
||||
*ASCII Never Die - 게임 시스템 개편 계획 v2.0*
|
||||
3
doc/key/Readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
storePassword=askiineverdie
|
||||
keyPassword=askiineverdie
|
||||
keyAlias=askiineverdie
|
||||
BIN
doc/key/askiineverdie.jks
Normal file
206
doc/privacy-policy.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# ASCII Never Die 개인정보 처리방침 / Privacy Policy
|
||||
|
||||
---
|
||||
|
||||
# 한국어 (Korean)
|
||||
|
||||
**시행일자: 2026년 1월 30일**
|
||||
|
||||
본 개인정보 처리방침은 ASCII Never Die 앱(이하 "앱")의 개인정보 수집, 이용, 보관 및 보호에 관한 사항을 안내합니다.
|
||||
|
||||
## 1. 수집하는 개인정보
|
||||
|
||||
본 앱은 **회원가입, 로그인 기능이 없습니다**. 이름, 이메일, 전화번호 등의 개인 식별정보를 직접 수집하지 않습니다.
|
||||
|
||||
사용자가 입력하는 캐릭터 이름, 게임 진행 데이터(레벨, 장비, 퀘스트 등)는 **기기 내에만 저장**됩니다.
|
||||
|
||||
## 2. 데이터 저장 및 처리 방식
|
||||
|
||||
- 모든 게임 데이터는 **로컬 저장소(기기 내 저장소)**에만 보관됩니다.
|
||||
- 클라우드나 외부 서버로 자동 전송되지 않습니다.
|
||||
- 앱 삭제 시 저장된 모든 데이터가 함께 제거됩니다.
|
||||
|
||||
## 3. 광고 및 제3자 서비스
|
||||
|
||||
본 앱은 **Google AdMob** 광고 네트워크를 사용합니다. 광고 서비스 제공을 위해 다음 정보가 수집될 수 있습니다:
|
||||
|
||||
- 광고 식별자(Advertising ID)
|
||||
- 기기 정보(모델, OS 버전 등)
|
||||
- 대략적인 위치 정보
|
||||
- 앱 사용 정보
|
||||
|
||||
이러한 정보는 Google의 개인정보 처리방침에 따라 처리됩니다.
|
||||
- Google 개인정보 처리방침: https://policies.google.com/privacy
|
||||
|
||||
## 4. 인앱 결제
|
||||
|
||||
본 앱은 **광고 제거** 등의 기능을 위해 인앱 결제를 제공합니다. 결제 처리는 각 플랫폼(Google Play, Apple App Store)에서 직접 처리하며, 개발사는 결제 정보(카드 번호, 계좌 정보 등)를 수집하거나 저장하지 않습니다.
|
||||
|
||||
- Google Play 개인정보 처리방침: https://policies.google.com/privacy
|
||||
- Apple 개인정보 처리방침: https://www.apple.com/legal/privacy/
|
||||
|
||||
## 5. 권한 사용
|
||||
|
||||
| 권한 | 용도 |
|
||||
|------|------|
|
||||
| 네트워크 접근 | 광고 표시 및 인앱 결제 처리 |
|
||||
| 저장소 접근 | 게임 데이터 저장 |
|
||||
|
||||
요청된 권한은 해당 용도 외에는 사용되지 않습니다.
|
||||
|
||||
## 6. 아동의 개인정보
|
||||
|
||||
본 앱은 일반 사용자를 대상으로 설계되었으며, **만 14세 미만의 아동**을 대상으로 개인정보를 수집하지 않습니다.
|
||||
|
||||
## 7. 개인정보의 보호
|
||||
|
||||
- 모든 게임 데이터는 기기 내부에만 저장
|
||||
- 외부 서버로의 개인정보 전송 없음
|
||||
- 최소한의 필수 권한만 요청
|
||||
|
||||
## 8. 처리방침의 변경
|
||||
|
||||
본 개인정보 처리방침이 변경되는 경우, 앱 내 공지 또는 앱 스토어 설명을 통해 안내합니다.
|
||||
|
||||
## 9. 문의처
|
||||
|
||||
- **이메일:** naturebridgeai@gmail.com
|
||||
- **담당자:** NatureBridgeAI 앱개발팀
|
||||
|
||||
---
|
||||
|
||||
# English
|
||||
|
||||
**Effective Date: January 30, 2026**
|
||||
|
||||
This Privacy Policy describes how ASCII Never Die (the "App") collects, uses, stores, and protects your information.
|
||||
|
||||
## 1. Information We Collect
|
||||
|
||||
This App **does not require account registration or login**. We do not directly collect personal identifying information such as your name, email address, or phone number.
|
||||
|
||||
Character names and game progress data (level, equipment, quests, etc.) that you enter are **stored only on your device**.
|
||||
|
||||
## 2. Data Storage and Processing
|
||||
|
||||
- All game data is stored **locally on your device only**.
|
||||
- No data is automatically transmitted to cloud services or external servers.
|
||||
- All stored data is deleted when you uninstall the App.
|
||||
|
||||
## 3. Advertising and Third-Party Services
|
||||
|
||||
This App uses the **Google AdMob** advertising network. The following information may be collected for advertising purposes:
|
||||
|
||||
- Advertising ID
|
||||
- Device information (model, OS version, etc.)
|
||||
- Approximate location information
|
||||
- App usage information
|
||||
|
||||
This information is processed in accordance with Google's Privacy Policy.
|
||||
- Google Privacy Policy: https://policies.google.com/privacy
|
||||
|
||||
## 4. In-App Purchases
|
||||
|
||||
This App offers in-app purchases for features such as **ad removal**. Payment processing is handled directly by each platform (Google Play, Apple App Store). We do not collect or store any payment information (credit card numbers, account details, etc.).
|
||||
|
||||
- Google Play Privacy Policy: https://policies.google.com/privacy
|
||||
- Apple Privacy Policy: https://www.apple.com/legal/privacy/
|
||||
|
||||
## 5. Permissions
|
||||
|
||||
| Permission | Purpose |
|
||||
|------------|---------|
|
||||
| Network Access | Display advertisements and process in-app purchases |
|
||||
| Storage Access | Save game data |
|
||||
|
||||
Requested permissions are not used for any purposes other than those stated above.
|
||||
|
||||
## 6. Children's Privacy
|
||||
|
||||
This App is designed for general users and **does not knowingly collect personal information from children under 14 years of age**.
|
||||
|
||||
## 7. Data Protection
|
||||
|
||||
- All game data is stored only on your device
|
||||
- No personal information is transmitted to external servers
|
||||
- Only essential permissions are requested
|
||||
|
||||
## 8. Changes to This Privacy Policy
|
||||
|
||||
If this Privacy Policy is modified, we will notify you through in-app announcements or app store descriptions.
|
||||
|
||||
## 9. Contact Us
|
||||
|
||||
- **Email:** naturebridgeai@gmail.com
|
||||
- **Contact:** NatureBridgeAI App Development Team
|
||||
|
||||
---
|
||||
|
||||
# 日本語 (Japanese)
|
||||
|
||||
**施行日:2026年1月30日**
|
||||
|
||||
本プライバシーポリシーは、ASCII Never Dieアプリ(以下「本アプリ」)における個人情報の収集、利用、保管、保護について説明します。
|
||||
|
||||
## 1. 収集する個人情報
|
||||
|
||||
本アプリは**会員登録・ログイン機能がありません**。氏名、メールアドレス、電話番号などの個人識別情報を直接収集することはありません。
|
||||
|
||||
ユーザーが入力するキャラクター名、ゲーム進行データ(レベル、装備、クエストなど)は**端末内にのみ保存**されます。
|
||||
|
||||
## 2. データの保存と処理方法
|
||||
|
||||
- すべてのゲームデータは**ローカルストレージ(端末内)**にのみ保管されます。
|
||||
- クラウドや外部サーバーへ自動送信されることはありません。
|
||||
- アプリを削除すると、保存されたすべてのデータも削除されます。
|
||||
|
||||
## 3. 広告および第三者サービス
|
||||
|
||||
本アプリは**Google AdMob**広告ネットワークを使用しています。広告サービス提供のため、以下の情報が収集される場合があります:
|
||||
|
||||
- 広告識別子(Advertising ID)
|
||||
- 端末情報(機種、OSバージョンなど)
|
||||
- おおよその位置情報
|
||||
- アプリ使用情報
|
||||
|
||||
これらの情報はGoogleのプライバシーポリシーに従って処理されます。
|
||||
- Googleプライバシーポリシー:https://policies.google.com/privacy
|
||||
|
||||
## 4. アプリ内課金
|
||||
|
||||
本アプリは**広告削除**などの機能のためにアプリ内課金を提供しています。決済処理は各プラットフォーム(Google Play、Apple App Store)が直接行い、開発者は決済情報(カード番号、口座情報など)を収集・保存しません。
|
||||
|
||||
- Google Playプライバシーポリシー:https://policies.google.com/privacy
|
||||
- Appleプライバシーポリシー:https://www.apple.com/legal/privacy/
|
||||
|
||||
## 5. 権限の使用
|
||||
|
||||
| 権限 | 用途 |
|
||||
|------|------|
|
||||
| ネットワークアクセス | 広告表示およびアプリ内課金処理 |
|
||||
| ストレージアクセス | ゲームデータの保存 |
|
||||
|
||||
要求された権限は、上記の用途以外には使用されません。
|
||||
|
||||
## 6. 児童の個人情報
|
||||
|
||||
本アプリは一般ユーザーを対象として設計されており、**14歳未満の児童**から個人情報を収集することはありません。
|
||||
|
||||
## 7. 個人情報の保護
|
||||
|
||||
- すべてのゲームデータは端末内にのみ保存
|
||||
- 外部サーバーへの個人情報送信なし
|
||||
- 最小限の必要な権限のみを要求
|
||||
|
||||
## 8. プライバシーポリシーの変更
|
||||
|
||||
本プライバシーポリシーが変更される場合、アプリ内通知またはアプリストアの説明を通じてお知らせします。
|
||||
|
||||
## 9. お問い合わせ
|
||||
|
||||
- **メール:** naturebridgeai@gmail.com
|
||||
- **担当者:** NatureBridgeAI アプリ開発チーム
|
||||
|
||||
---
|
||||
|
||||
*Last updated: January 30, 2026*
|
||||
130
doc/task-ext-audio-access.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# 사운드/진동/접근성 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 사운드/음악/진동 시스템
|
||||
|
||||
### 1.1 사운드 효과 (SFX)
|
||||
|
||||
| 상황 | 효과음 | 우선순위 |
|
||||
|------|--------|----------|
|
||||
| 일반 공격 | 타격음 | 상 |
|
||||
| 크리티컬 히트 | 강한 타격음 + 효과음 | 상 |
|
||||
| 스킬 사용 | 스킬별 고유 효과음 | 중 |
|
||||
| 피격 | 피해 효과음 | 상 |
|
||||
| 사망 | 쓰러지는 효과음 | 상 |
|
||||
| 레벨업 | 팡파레 | 상 |
|
||||
| 아이템 획득 | 획득 효과음 (희귀도별 차등) | 중 |
|
||||
| 장비 장착 | 장착 효과음 | 하 |
|
||||
| 퀘스트 완료 | 완료 효과음 | 중 |
|
||||
| UI 조작 | 버튼 클릭음 | 하 |
|
||||
|
||||
### 1.2 배경 음악 (BGM)
|
||||
|
||||
| 상황 | BGM 타입 | 우선순위 |
|
||||
|------|----------|----------|
|
||||
| 메인 화면 | 웅장한 타이틀 테마 | 중 |
|
||||
| 일반 탐험 | 평화로운 필드 음악 | 중 |
|
||||
| 전투 중 | 긴박한 전투 음악 | 상 |
|
||||
| 보스전 | 강렬한 보스 테마 | 상 |
|
||||
| 사망 화면 | 슬픈/긴장된 음악 | 중 |
|
||||
| 시네마틱 | 스토리 테마 | 중 |
|
||||
| 명예의 전당 | 영광스러운 엔딩 테마 | 중 |
|
||||
|
||||
### 1.3 진동 (모바일 전용)
|
||||
|
||||
| 상황 | 진동 패턴 | 강도 |
|
||||
|------|----------|------|
|
||||
| 일반 공격 | 짧은 단일 진동 | 약 |
|
||||
| 크리티컬 히트 | 강한 단일 진동 | 강 |
|
||||
| 피격 | 짧은 이중 진동 | 중 |
|
||||
| 사망 | 긴 진동 | 강 |
|
||||
| 레벨업 | 리듬 있는 연속 진동 | 중 |
|
||||
| 희귀 아이템 획득 | 짧은 삼중 진동 | 중 |
|
||||
| 보스 등장 | 점점 강해지는 진동 | 강 |
|
||||
|
||||
### 1.4 구현 방안
|
||||
|
||||
```dart
|
||||
// 사운드 서비스
|
||||
class AudioService {
|
||||
void playSfx(SfxType type);
|
||||
void playBgm(BgmType type);
|
||||
void stopBgm();
|
||||
void setVolume(double sfx, double bgm);
|
||||
}
|
||||
|
||||
// 진동 서비스 (모바일)
|
||||
class HapticService {
|
||||
void vibrate(HapticPattern pattern);
|
||||
bool get isSupported;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 접근성 (Accessibility)
|
||||
|
||||
### 2.1 시각 접근성
|
||||
|
||||
| 기능 | 설명 | 기본값 |
|
||||
|------|------|--------|
|
||||
| **색맹 모드** | 색상 팔레트 변경 | 끄기 |
|
||||
| - 적록 색맹 | 빨강/초록 → 파랑/노랑 | - |
|
||||
| - 청황 색맹 | 파랑/노랑 → 빨강/초록 | - |
|
||||
| - 완전 색맹 | 명도/채도 기반 | - |
|
||||
| **고대비 모드** | 배경/전경 대비 증가 | 끄기 |
|
||||
| **폰트 크기** | 0.8x ~ 1.5x | 1.0x |
|
||||
| **애니메이션 감소** | 움직임 최소화 | 끄기 |
|
||||
|
||||
### 2.2 청각 접근성
|
||||
|
||||
| 기능 | 설명 | 기본값 |
|
||||
|------|------|--------|
|
||||
| **자막** | 효과음을 텍스트로 표시 | 끄기 |
|
||||
| **시각 알림** | 소리 대신 화면 깜빡임 | 끄기 |
|
||||
| **진동 알림** | 소리 대신 진동 | 끄기 |
|
||||
|
||||
### 2.3 운동 접근성
|
||||
|
||||
| 기능 | 설명 | 기본값 |
|
||||
|------|------|--------|
|
||||
| **터치 영역 확대** | 버튼 크기 증가 | 끄기 |
|
||||
| **길게 누르기 비활성화** | 탭으로 대체 | 끄기 |
|
||||
| **자동 진행** | 수동 입력 최소화 | 켜기 |
|
||||
|
||||
### 2.4 게임 난이도 조절
|
||||
|
||||
| 난이도 | 설명 |
|
||||
|--------|------|
|
||||
| **이야기 모드** | 사망 없음, 경험치 2배 |
|
||||
| **쉬움** | 데미지 50%, 회복 2배 |
|
||||
| **보통** | 기본 설정 |
|
||||
| **어려움** | 데미지 150%, 드롭률 증가 |
|
||||
| **극한** | 데미지 200%, 사망 시 영구 삭제 |
|
||||
|
||||
### 2.5 접근성 UI
|
||||
|
||||
```
|
||||
┌─ 접근성 설정 ───────────────────────┐
|
||||
│ │
|
||||
│ 👁 시각 │
|
||||
│ 색맹 모드 [없음 ▼] │
|
||||
│ 고대비 모드 [○ 끄기] │
|
||||
│ 폰트 크기 [━━●━━] 1.0x │
|
||||
│ 애니메이션 [● 켜기] │
|
||||
│ │
|
||||
│ 👂 청각 │
|
||||
│ 자막 표시 [○ 끄기] │
|
||||
│ 시각 알림 [○ 끄기] │
|
||||
│ │
|
||||
│ 🎮 게임플레이 │
|
||||
│ 난이도 [보통 ▼] │
|
||||
│ 터치 영역 확대 [○ 끄기] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
238
doc/task-ext-combat.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# 전투 확장: 몬스터 AI/퀘스트/버프
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 몬스터 AI/보스 패턴
|
||||
|
||||
### 1.1 일반 몬스터 AI
|
||||
|
||||
```dart
|
||||
enum MonsterBehavior {
|
||||
aggressive, // 공격 우선
|
||||
defensive, // 방어 우선
|
||||
balanced, // 균형
|
||||
berserker, // HP 낮을수록 공격력 증가
|
||||
healer, // 자가 회복
|
||||
}
|
||||
|
||||
class MonsterAI {
|
||||
final MonsterBehavior behavior;
|
||||
final double skillUseChance; // 스킬 사용 확률
|
||||
final List<MonsterSkill> skills;
|
||||
|
||||
MonsterAction decideAction(BattleState state) {
|
||||
// AI 로직
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 보스 몬스터 페이즈
|
||||
|
||||
```dart
|
||||
class BossMonster {
|
||||
final String id;
|
||||
final String name;
|
||||
final List<BossPhase> phases;
|
||||
final int currentPhaseIndex;
|
||||
|
||||
BossPhase get currentPhase => phases[currentPhaseIndex];
|
||||
}
|
||||
|
||||
class BossPhase {
|
||||
final double hpThreshold; // 이 HP% 이하일 때 다음 페이즈
|
||||
final String phaseName; // "분노", "최후의 발악" 등
|
||||
final Map<StatType, double> statModifiers; // 스탯 변화
|
||||
final List<BossSkill> availableSkills;
|
||||
final String? phaseStartMessage; // "커널 패닉이 분노합니다!"
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 보스 패턴 예시
|
||||
|
||||
| 보스 | 페이즈 1 (100-70%) | 페이즈 2 (70-30%) | 페이즈 3 (30-0%) |
|
||||
|------|-------------------|-------------------|------------------|
|
||||
| **Syntax Error Dragon** | 일반 공격 | 문법 오류 브레스 (범위) | 무한 루프 (연속 공격) |
|
||||
| **Memory Leak Hydra** | 단일 공격 | 메모리 침식 (DOT) | 머리 재생 (회복 + 분열) |
|
||||
| **Buffer Overflow Titan** | 강타 | 오버플로우 (즉사 위험) | 시스템 붕괴 (전체 공격) |
|
||||
| **Kernel Panic Archon** | 패닉 공격 | 블루스크린 (스턴) | 시스템 재부팅 (HP 회복) |
|
||||
| **Glitch God** | 글리치 (랜덤 효과) | 차원 왜곡 (회피 불가) | 존재 삭제 (다중 페이즈) |
|
||||
|
||||
### 1.4 보스 스킬
|
||||
|
||||
```dart
|
||||
class BossSkill {
|
||||
final String id;
|
||||
final String name;
|
||||
final SkillType type;
|
||||
final int cooldownTurns; // 턴 기반 쿨타임
|
||||
final double damageMultiplier;
|
||||
final List<StatusEffect>? effects;
|
||||
final String? castMessage; // "커널 패닉이 블루스크린을 시전합니다!"
|
||||
final int castTime; // 시전 시간 (경고 표시용)
|
||||
}
|
||||
```
|
||||
|
||||
### 1.5 보스전 특수 메커니즘
|
||||
|
||||
| 메커니즘 | 설명 |
|
||||
|----------|------|
|
||||
| **시전 경고** | 강력한 스킬 사용 전 1-2턴 경고 표시 |
|
||||
| **페이즈 전환 연출** | HP 임계점 도달 시 특별 애니메이션 |
|
||||
| **분노 게이지** | 특정 보스는 분노 시 패턴 변화 |
|
||||
| **약점 노출** | 특정 행동 후 약점 노출 (추가 데미지) |
|
||||
| **환경 효과** | 보스에 따라 필드 효과 (독, 화염 등) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 퀘스트 시스템 상세
|
||||
|
||||
### 2.1 퀘스트 구조
|
||||
|
||||
```dart
|
||||
class Quest {
|
||||
final String id;
|
||||
final String name;
|
||||
final QuestType type; // main, side, daily, event
|
||||
final String description;
|
||||
final List<QuestObjective> objectives;
|
||||
final QuestReward reward;
|
||||
final int requiredLevel;
|
||||
final String? prerequisiteQuestId;
|
||||
}
|
||||
|
||||
class QuestObjective {
|
||||
final ObjectiveType type; // kill, collect, reach, survive
|
||||
final String targetId; // 대상 몬스터/아이템/지역
|
||||
final int targetCount;
|
||||
final int currentCount;
|
||||
final bool isCompleted;
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 퀘스트 타입
|
||||
|
||||
| 타입 | 설명 | 갱신 |
|
||||
|------|------|------|
|
||||
| **메인 퀘스트** | 스토리 진행 필수 | 일회성 |
|
||||
| **서브 퀘스트** | 추가 보상 | 일회성 |
|
||||
| **일일 퀘스트** | 매일 갱신 | 매일 자정 |
|
||||
| **주간 퀘스트** | 매주 갱신 | 매주 월요일 |
|
||||
| **이벤트 퀘스트** | 기간 한정 | 이벤트 기간 |
|
||||
| **업적 퀘스트** | 장기 목표 | 영구 |
|
||||
|
||||
### 2.3 메인 퀘스트 흐름
|
||||
|
||||
```
|
||||
Act I: 각성
|
||||
├── [메인] 첫 번째 버그 처치
|
||||
├── [메인] 버그 둥지 탐험
|
||||
├── [메인] Syntax Error Dragon 처치
|
||||
└── [보상] Act II 해금
|
||||
|
||||
Act II: 성장
|
||||
├── [메인] 디버거 기사단 가입
|
||||
├── [메인] 손상된 네트워크 조사
|
||||
├── [메인] 배신자 추적
|
||||
├── [메인] Memory Leak Hydra 처치
|
||||
└── [보상] Act III 해금
|
||||
|
||||
... (Act III ~ V)
|
||||
```
|
||||
|
||||
### 2.4 서브 퀘스트 예시
|
||||
|
||||
| 퀘스트명 | 목표 | 보상 |
|
||||
|----------|------|------|
|
||||
| 백전용사 | 몬스터 100마리 처치 | 골드 1000, 칭호 |
|
||||
| 수집가 | 무기 10종 획득 | 희귀 무기 박스 |
|
||||
| 생존자 | 사망 없이 Act I 클리어 | 칭호 "완벽주의자" |
|
||||
| 속도전 | 30분 내 레벨 10 달성 | 경험치 물약 x3 |
|
||||
|
||||
### 2.5 퀘스트 UI
|
||||
|
||||
```
|
||||
┌─ 퀘스트 ────────────────────────────┐
|
||||
│ │
|
||||
│ ★ 메인 퀘스트 │
|
||||
│ ▶ 버그 둥지 탐험 │
|
||||
│ 목표: 버그 둥지 도달 [진행 중] │
|
||||
│ 보상: 골드 500, 경험치 1000 │
|
||||
│ │
|
||||
│ ☆ 서브 퀘스트 │
|
||||
│ ○ 백전용사 [45/100] │
|
||||
│ ○ 수집가 [3/10] │
|
||||
│ │
|
||||
│ 📅 일일 퀘스트 (남은 시간: 4시간) │
|
||||
│ ☑ 몬스터 30마리 처치 [완료] │
|
||||
│ ☐ 크리티컬 10회 [7/10] │
|
||||
│ ☐ 레벨업 1회 [0/1] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 버프/디버프 시스템
|
||||
|
||||
### 3.1 버프/디버프 구조
|
||||
|
||||
```dart
|
||||
class StatusEffect {
|
||||
final String id;
|
||||
final String name;
|
||||
final EffectType type; // buff, debuff
|
||||
final EffectTarget target; // self, enemy
|
||||
final Duration duration; // 지속 시간
|
||||
final int stacks; // 중첩 횟수
|
||||
final int maxStacks; // 최대 중첩
|
||||
final Map<StatType, double> modifiers;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 버프 목록
|
||||
|
||||
| 버프명 | 효과 | 지속 시간 | 획득 방법 |
|
||||
|--------|------|----------|----------|
|
||||
| **공격력 증가** | ATK +20% | 30초 | 스킬, 물약 |
|
||||
| **방어력 증가** | DEF +20% | 30초 | 스킬, 물약 |
|
||||
| **크리티컬 증가** | CRI +10% | 30초 | 스킬, 물약 |
|
||||
| **회피 증가** | EVA +10% | 30초 | 스킬 |
|
||||
| **재생** | 초당 HP 1% 회복 | 10초 | 스킬 |
|
||||
| **경험치 부스트** | EXP +50% | 5분 | 물약, 이벤트 |
|
||||
| **골드 부스트** | GOLD +50% | 5분 | 물약, 이벤트 |
|
||||
| **무적** | 피해 면역 | 3초 | 스킬 |
|
||||
| **분노** | ATK +50%, DEF -20% | 10초 | 스킬, 종족 특성 |
|
||||
|
||||
### 3.3 디버프 목록
|
||||
|
||||
| 디버프명 | 효과 | 지속 시간 | 발생 원인 |
|
||||
|----------|------|----------|----------|
|
||||
| **독** | 초당 HP 2% 손실 | 5초 | 몬스터 공격 |
|
||||
| **출혈** | 초당 HP 1% 손실 | 10초 | 크리티컬 피격 |
|
||||
| **화상** | 초당 HP 3% 손실 | 3초 | 화염 공격 |
|
||||
| **둔화** | 공격 속도 -30% | 5초 | 몬스터 스킬 |
|
||||
| **약화** | ATK -20% | 10초 | 보스 스킬 |
|
||||
| **취약** | DEF -30% | 10초 | 보스 스킬 |
|
||||
| **스턴** | 행동 불가 | 2초 | 보스 스킬 |
|
||||
| **침묵** | 스킬 사용 불가 | 5초 | 보스 스킬 |
|
||||
| **저주** | 회복량 -50% | 15초 | 언데드 공격 |
|
||||
|
||||
### 3.4 버프/디버프 UI
|
||||
|
||||
```
|
||||
┌─ 상태 효과 ─────────────────────────┐
|
||||
│ │
|
||||
│ 버프: │
|
||||
│ [⚔️+20%] [🛡️+15%] [💨재생] │
|
||||
│ 25초 18초 5초 │
|
||||
│ │
|
||||
│ 디버프: │
|
||||
│ [🩸출혈] [⚡스턴] │
|
||||
│ 3초 1초 │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
198
doc/task-ext-events.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# 이벤트/알림 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 이벤트 시스템
|
||||
|
||||
### 1.1 이벤트 종류
|
||||
|
||||
| 이벤트 타입 | 주기 | 지속 시간 |
|
||||
|------------|------|----------|
|
||||
| **일일 보너스** | 매일 | 접속 시 |
|
||||
| **주간 보스** | 매주 일요일 | 24시간 |
|
||||
| **시즌 이벤트** | 시즌별 | 2-4주 |
|
||||
| **기념일 이벤트** | 특정 날짜 | 1-7일 |
|
||||
| **돌발 이벤트** | 랜덤 | 1-2시간 |
|
||||
|
||||
### 1.2 이벤트 구조
|
||||
|
||||
```dart
|
||||
class GameEvent {
|
||||
final String id;
|
||||
final String name;
|
||||
final EventType type;
|
||||
final DateTime startTime;
|
||||
final DateTime endTime;
|
||||
final List<EventReward> rewards;
|
||||
final List<EventQuest> quests;
|
||||
final EventBonuses? bonuses;
|
||||
}
|
||||
|
||||
class EventBonuses {
|
||||
final double expMultiplier; // 경험치 배율
|
||||
final double goldMultiplier; // 골드 배율
|
||||
final double dropRateBonus; // 드롭률 보너스
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 시즌 이벤트 예시
|
||||
|
||||
| 시즌 | 테마 | 특별 콘텐츠 |
|
||||
|------|------|------------|
|
||||
| **봄** | 버그 헌팅 시즌 | 특별 몬스터, 봄 한정 장비 |
|
||||
| **여름** | 핫픽스 페스티벌 | 경험치 2배, 여름 코스튬 |
|
||||
| **가을** | 수확의 코드 | 골드 2배, 가을 한정 펫 |
|
||||
| **겨울** | 시스템 동면 | 특별 던전, 겨울 한정 세트 |
|
||||
|
||||
### 1.4 이벤트 보상 구조
|
||||
|
||||
```
|
||||
┌─ 신년 이벤트 ───────────────────────┐
|
||||
│ │
|
||||
│ 🎉 2025 신년 맞이 특별 이벤트 │
|
||||
│ 기간: 1/1 ~ 1/7 │
|
||||
│ │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 📋 이벤트 미션 │
|
||||
│ │
|
||||
│ ☑ 몬스터 100마리 처치 [100/100] │
|
||||
│ 보상: 신년 무기 상자 │
|
||||
│ │
|
||||
│ ☐ 던전 5회 클리어 [3/5] │
|
||||
│ 보상: 전설 물약 세트 │
|
||||
│ │
|
||||
│ ☐ 보스 처치 [0/1] │
|
||||
│ 보상: 신년 한정 칭호 │
|
||||
│ │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 🎁 출석 보상 (7일) │
|
||||
│ [✓][✓][✓][✓][ ][ ][ ] │
|
||||
│ 1 2 3 4 5 6 7 │
|
||||
│ │
|
||||
│ 7일 완료 보상: 신년 한정 세트 │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.5 돌발 이벤트
|
||||
|
||||
| 이벤트 | 발생 확률 | 효과 |
|
||||
|--------|----------|------|
|
||||
| **골드 러시** | 5% | 1시간 골드 3배 |
|
||||
| **경험치 폭풍** | 5% | 1시간 경험치 2배 |
|
||||
| **보물 사냥** | 3% | 희귀 아이템 드롭률 +100% |
|
||||
| **엘리트 침공** | 3% | 정예 몬스터 대량 등장 |
|
||||
| **행운의 시간** | 2% | 모든 보너스 적용 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 알림/푸시 시스템
|
||||
|
||||
### 2.1 알림 종류
|
||||
|
||||
| 카테고리 | 알림 | 기본 설정 |
|
||||
|----------|------|----------|
|
||||
| **게임 진행** | 레벨업 | 켜기 |
|
||||
| | 퀘스트 완료 | 켜기 |
|
||||
| | 보스 해금 | 켜기 |
|
||||
| | 업적 달성 | 켜기 |
|
||||
| **전투** | 사망 | 켜기 |
|
||||
| | 희귀 아이템 획득 | 켜기 |
|
||||
| | HP 위험 (20% 이하) | 끄기 |
|
||||
| **시스템** | 오프라인 보상 준비 | 켜기 |
|
||||
| | 일일 미션 갱신 | 켜기 |
|
||||
| | 이벤트 시작/종료 | 켜기 |
|
||||
| | 상점 갱신 | 끄기 |
|
||||
| **소셜 (향후)** | 친구 요청 | 켜기 |
|
||||
| | 길드 알림 | 켜기 |
|
||||
|
||||
### 2.2 푸시 알림 (모바일)
|
||||
|
||||
```dart
|
||||
class PushNotificationService {
|
||||
/// 로컬 푸시 알림 예약
|
||||
Future<void> scheduleNotification({
|
||||
required String title,
|
||||
required String body,
|
||||
required DateTime scheduledTime,
|
||||
String? payload,
|
||||
});
|
||||
|
||||
/// 반복 알림 설정
|
||||
Future<void> scheduleRepeating({
|
||||
required String title,
|
||||
required String body,
|
||||
required RepeatInterval interval,
|
||||
});
|
||||
}
|
||||
|
||||
enum RepeatInterval {
|
||||
hourly,
|
||||
daily,
|
||||
weekly,
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 푸시 알림 시나리오
|
||||
|
||||
| 시나리오 | 트리거 | 메시지 예시 |
|
||||
|----------|--------|------------|
|
||||
| **복귀 유도** | 24시간 미접속 | "⚔️ 버그들이 기다리고 있어요!" |
|
||||
| **오프라인 보상** | 8시간 경과 | "🎁 오프라인 보상이 가득 찼어요!" |
|
||||
| **일일 미션** | 매일 오전 9시 | "📋 새로운 일일 미션이 도착했어요!" |
|
||||
| **이벤트** | 이벤트 시작 | "🎉 신년 이벤트가 시작되었어요!" |
|
||||
| **이벤트 종료** | 이벤트 종료 1시간 전 | "⏰ 이벤트가 1시간 후 종료됩니다!" |
|
||||
|
||||
### 2.4 인앱 알림
|
||||
|
||||
```
|
||||
┌─ 알림 센터 ─────────────────────────┐
|
||||
│ │
|
||||
│ 오늘 │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 🎮 레벨 26 달성! 14:32 │
|
||||
│ │
|
||||
│ ⚔️ 디버거의 검 획득 (Epic) 14:15 │
|
||||
│ │
|
||||
│ 📋 일일 미션 완료 13:45 │
|
||||
│ 보상: 골드 500, 경험치 물약 │
|
||||
│ │
|
||||
│ 어제 │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 🏆 업적 달성: 백전용사 23:12 │
|
||||
│ │
|
||||
│ 💀 사망: 메모리 누수에 의해 21:30 │
|
||||
│ │
|
||||
│ [ 모두 읽음 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.5 알림 설정 UI
|
||||
|
||||
```
|
||||
┌─ 알림 설정 ─────────────────────────┐
|
||||
│ │
|
||||
│ 🔔 푸시 알림 │
|
||||
│ 마스터 스위치 [● 켜기] │
|
||||
│ │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 게임 진행 │
|
||||
│ 레벨업 [● 켜기] │
|
||||
│ 퀘스트 완료 [● 켜기] │
|
||||
│ 업적 달성 [● 켜기] │
|
||||
│ │
|
||||
│ 시스템 │
|
||||
│ 오프라인 보상 [● 켜기] │
|
||||
│ 일일 미션 갱신 [● 켜기] │
|
||||
│ 이벤트 [● 켜기] │
|
||||
│ │
|
||||
│ 방해 금지 시간 │
|
||||
│ [22:00] ~ [08:00] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
316
doc/task-ext-items.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# 아이템 확장: 세트/강화/인벤토리/물약
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 세트 아이템
|
||||
|
||||
### 1.1 세트 아이템 구조
|
||||
|
||||
```dart
|
||||
class ItemSet {
|
||||
final String id;
|
||||
final String name;
|
||||
final List<String> itemIds; // 세트 구성 아이템
|
||||
final Map<int, SetBonus> bonuses; // 착용 개수별 보너스
|
||||
}
|
||||
|
||||
class SetBonus {
|
||||
final int requiredCount; // 필요 착용 개수
|
||||
final String description; // "2세트: 공격력 +10%"
|
||||
final Map<StatType, double> statBonuses;
|
||||
final PassiveEffect? passiveEffect;
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 세트 목록 예시
|
||||
|
||||
| 세트명 | 부위 | 2세트 | 4세트 | 6세트 |
|
||||
|--------|------|-------|-------|-------|
|
||||
| **디버거의 유산** | 무기, 방어구, 투구, 장갑, 부츠, 반지 | 공격력 +10% | 크리티컬 +15% | 스킬 데미지 +25% |
|
||||
| **널 가드** | 방패, 방어구, 투구, 장갑, 부츠, 목걸이 | 방어력 +15% | 블록률 +10% | 피해 반사 10% |
|
||||
| **컴파일러의 지혜** | 지팡이, 로브, 모자, 장갑, 부츠, 반지 | MP +20% | 마법 데미지 +15% | 스킬 쿨타임 -20% |
|
||||
| **가비지 컬렉터** | 무기, 중갑, 투구, 장갑, 부츠, 벨트 | HP +20% | 전투 후 HP 5% 회복 | 사망 시 50% 확률로 생존 |
|
||||
|
||||
### 1.3 세트 UI
|
||||
|
||||
```
|
||||
┌─ 장착 장비 ─────────────────────────┐
|
||||
│ │
|
||||
│ 디버거의 유산 [4/6] ✨ │
|
||||
│ ├─ 디버거의 검 ☑ │
|
||||
│ ├─ 디버거의 갑옷 ☑ │
|
||||
│ ├─ 디버거의 투구 ☑ │
|
||||
│ ├─ 디버거의 장갑 ☑ │
|
||||
│ ├─ 디버거의 부츠 ☐ │
|
||||
│ └─ 디버거의 반지 ☐ │
|
||||
│ │
|
||||
│ 세트 효과: │
|
||||
│ ✓ 2세트: 공격력 +10% │
|
||||
│ ✓ 4세트: 크리티컬 +15% │
|
||||
│ ○ 6세트: 스킬 데미지 +25% │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 강화/합성 시스템
|
||||
|
||||
### 2.1 아이템 강화
|
||||
|
||||
```dart
|
||||
class EnhancementSystem {
|
||||
/// 강화 시도
|
||||
EnhanceResult enhance(Equipment item, int gold) {
|
||||
final successRate = getSuccessRate(item.enhanceLevel);
|
||||
final success = random() < successRate;
|
||||
|
||||
if (success) {
|
||||
return EnhanceResult.success(
|
||||
item.copyWith(enhanceLevel: item.enhanceLevel + 1),
|
||||
);
|
||||
} else {
|
||||
// 실패 시 강화 레벨 유지 (파괴 없음)
|
||||
return EnhanceResult.failure();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 강화 단계
|
||||
|
||||
| 강화 레벨 | 성공률 | 비용 배율 | 스탯 증가 |
|
||||
|----------|--------|----------|----------|
|
||||
| +1 | 90% | 1x | +5% |
|
||||
| +2 | 80% | 2x | +10% |
|
||||
| +3 | 70% | 3x | +15% |
|
||||
| +4 | 60% | 4x | +20% |
|
||||
| +5 | 50% | 5x | +30% |
|
||||
| +6 | 40% | 7x | +40% |
|
||||
| +7 | 30% | 10x | +50% |
|
||||
| +8 | 20% | 15x | +65% |
|
||||
| +9 | 10% | 20x | +80% |
|
||||
| +10 | 5% | 30x | +100% |
|
||||
|
||||
### 2.3 아이템 합성
|
||||
|
||||
```dart
|
||||
class SynthesisSystem {
|
||||
/// 동일 아이템 3개 → 상위 희귀도 1개
|
||||
Equipment? synthesize(List<Equipment> items) {
|
||||
if (items.length != 3) return null;
|
||||
if (!_isSameItem(items)) return null;
|
||||
|
||||
final baseItem = items.first;
|
||||
final nextRarity = _getNextRarity(baseItem.rarity);
|
||||
|
||||
if (nextRarity == null) return null; // 이미 최고 희귀도
|
||||
|
||||
return baseItem.copyWith(rarity: nextRarity);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 합성 규칙
|
||||
|
||||
```
|
||||
Common x3 → Uncommon x1
|
||||
Uncommon x3 → Rare x1
|
||||
Rare x3 → Epic x1
|
||||
Epic x3 → Legendary x1
|
||||
Legendary → 합성 불가
|
||||
```
|
||||
|
||||
### 2.5 강화/합성 UI
|
||||
|
||||
```
|
||||
┌─ 대장간 ────────────────────────────┐
|
||||
│ │
|
||||
│ [강화] [합성] │
|
||||
│ │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ 디버거의 검 +3 │ │
|
||||
│ │ 공격력: 45 (+15%) │ │
|
||||
│ │ 희귀도: Rare │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
│ │
|
||||
│ 강화 정보: │
|
||||
│ 현재: +3 → +4 │
|
||||
│ 성공률: 60% │
|
||||
│ 비용: 2,000 골드 │
|
||||
│ 스탯 증가: +15% → +20% │
|
||||
│ │
|
||||
│ [ 강화하기 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 인벤토리 관리
|
||||
|
||||
### 3.1 인벤토리 구조
|
||||
|
||||
```dart
|
||||
class Inventory {
|
||||
final int maxSlots; // 최대 슬롯 수
|
||||
final List<InventoryItem> items;
|
||||
|
||||
int get usedSlots => items.length;
|
||||
int get freeSlots => maxSlots - usedSlots;
|
||||
bool get isFull => freeSlots <= 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 인벤토리 크기
|
||||
|
||||
| 레벨 | 기본 슬롯 | 확장 가능 |
|
||||
|------|----------|----------|
|
||||
| 1-20 | 30 | +10 (골드) |
|
||||
| 21-50 | 40 | +15 (골드) |
|
||||
| 51-80 | 55 | +20 (골드) |
|
||||
| 81-100 | 75 | +25 (골드) |
|
||||
| 최대 | 100 | - |
|
||||
|
||||
### 3.3 정렬 옵션
|
||||
|
||||
| 정렬 기준 | 설명 |
|
||||
|----------|------|
|
||||
| 최근 획득 | 획득 시간 내림차순 |
|
||||
| 희귀도 | 전설 > 에픽 > 레어 > ... |
|
||||
| 레벨 | 아이템 레벨 내림차순 |
|
||||
| 이름 | 가나다/ABC 순 |
|
||||
| 슬롯 | 무기 → 방어구 → 악세서리 |
|
||||
| 가중치 | 높은 가중치 우선 |
|
||||
|
||||
### 3.4 필터 옵션
|
||||
|
||||
| 필터 | 옵션 |
|
||||
|------|------|
|
||||
| 슬롯 | 전체, 무기, 방어구, 악세서리 등 |
|
||||
| 희귀도 | 전체, Common ~ Legendary |
|
||||
| 장착 가능 | 현재 레벨에서 장착 가능한 것만 |
|
||||
| 세트 | 세트 아이템만 |
|
||||
|
||||
### 3.5 자동 정리
|
||||
|
||||
```dart
|
||||
class InventoryAutoClean {
|
||||
/// 인벤토리 자동 정리
|
||||
void autoClean(Inventory inventory, AutoCleanSettings settings) {
|
||||
if (settings.sellCommon) {
|
||||
_sellByRarity(ItemRarity.common);
|
||||
}
|
||||
if (settings.sellBelowLevel) {
|
||||
_sellBelowLevel(settings.minLevel);
|
||||
}
|
||||
if (settings.keepBestPerSlot) {
|
||||
_keepBestPerSlot(settings.keepCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 인벤토리 UI
|
||||
|
||||
```
|
||||
┌─ 인벤토리 [45/50] ──────────────────┐
|
||||
│ │
|
||||
│ [정렬: 희귀도 ▼] [필터: 전체 ▼] │
|
||||
│ │
|
||||
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
|
||||
│ │ ★ │ │ ★ │ │ ◆ │ │ ◆ │ │ ○ │ ... │
|
||||
│ │검 │ │갑 │ │방 │ │투 │ │단 │ │
|
||||
│ └───┘ └───┘ └───┘ └───┘ └───┘ │
|
||||
│ │
|
||||
│ 선택: 디버거의 검 +3 │
|
||||
│ 공격력 +45, 크리티컬 +5% │
|
||||
│ │
|
||||
│ [장착] [판매] [강화] [분해] │
|
||||
│ │
|
||||
│ ───────────────────────────────── │
|
||||
│ [ 자동 정리 ] [ 일괄 판매 ] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 물약/소모품 시스템
|
||||
|
||||
### 4.1 소모품 종류
|
||||
|
||||
| 카테고리 | 아이템 | 효과 | 획득 방법 |
|
||||
|----------|--------|------|----------|
|
||||
| **HP 물약** | 소형 HP 물약 | HP +100 | 상점, 드롭 |
|
||||
| | 중형 HP 물약 | HP +300 | 상점, 드롭 |
|
||||
| | 대형 HP 물약 | HP +500 | 상점, 드롭 |
|
||||
| | 최상급 HP 물약 | HP 100% 회복 | 보스 드롭, 제작 |
|
||||
| **MP 물약** | 소형 MP 물약 | MP +50 | 상점, 드롭 |
|
||||
| | 중형 MP 물약 | MP +150 | 상점, 드롭 |
|
||||
| | 대형 MP 물약 | MP +300 | 상점, 드롭 |
|
||||
| | 최상급 MP 물약 | MP 100% 회복 | 보스 드롭, 제작 |
|
||||
| **버프 물약** | 공격력 물약 | ATK +20%, 5분 | 상점, 제작 |
|
||||
| | 방어력 물약 | DEF +20%, 5분 | 상점, 제작 |
|
||||
| | 경험치 물약 | EXP +50%, 5분 | 이벤트, 퀘스트 |
|
||||
| | 골드 물약 | GOLD +50%, 5분 | 이벤트, 퀘스트 |
|
||||
| | 행운 물약 | 드롭률 +30%, 5분 | 희귀 드롭 |
|
||||
| **특수 소모품** | 귀환 스크롤 | 마을로 즉시 이동 | 상점 |
|
||||
| | 부활의 부적 | 사망 시 장비 1개 보존 | 보스 드롭 |
|
||||
| | 감정 스크롤 | 미감정 아이템 감정 | 상점 |
|
||||
|
||||
### 4.2 소모품 데이터 구조
|
||||
|
||||
```dart
|
||||
class Consumable {
|
||||
final String id;
|
||||
final String name;
|
||||
final ConsumableType type; // hp, mp, buff, special
|
||||
final int value; // 회복량 또는 효과 수치
|
||||
final Duration? duration; // 버프 지속 시간
|
||||
final int maxStack; // 최대 중첩 수 (인벤토리)
|
||||
final int buyPrice;
|
||||
final int sellPrice;
|
||||
}
|
||||
|
||||
class ConsumableInventory {
|
||||
final Map<String, int> items; // id -> 수량
|
||||
|
||||
void use(String id);
|
||||
void add(String id, int amount);
|
||||
bool has(String id) => (items[id] ?? 0) > 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 자동 사용 설정
|
||||
|
||||
```
|
||||
┌─ 물약 자동 사용 설정 ───────────────┐
|
||||
│ │
|
||||
│ HP 물약 자동 사용 │
|
||||
│ ● 켜기 ○ 끄기 │
|
||||
│ HP가 [30]% 이하일 때 사용 │
|
||||
│ 사용 우선순위: [소형 > 중형 > 대형]│
|
||||
│ │
|
||||
│ MP 물약 자동 사용 │
|
||||
│ ● 켜기 ○ 끄기 │
|
||||
│ MP가 [20]% 이하일 때 사용 │
|
||||
│ │
|
||||
│ 버프 물약 자동 사용 │
|
||||
│ ○ 켜기 ● 끄기 │
|
||||
│ (보스전에서만 자동 사용) │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.4 물약 쿨타임
|
||||
|
||||
| 물약 종류 | 쿨타임 |
|
||||
|----------|--------|
|
||||
| HP 물약 | 3초 |
|
||||
| MP 물약 | 3초 |
|
||||
| 버프 물약 | 60초 |
|
||||
| 특수 소모품 | 없음 |
|
||||
|
||||
---
|
||||
251
doc/task-ext-meta-systems.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# 메타 시스템: 업적/도감/통계/칭호
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 업적 시스템
|
||||
|
||||
### 1.1 업적 카테고리
|
||||
|
||||
| 카테고리 | 예시 업적 |
|
||||
|----------|----------|
|
||||
| **전투** | 첫 번째 몬스터 처치, 100마리 처치, 1000마리 처치, 무피해 보스 처치 |
|
||||
| **성장** | 레벨 10 달성, 레벨 50 달성, 레벨 100 달성 |
|
||||
| **수집** | 첫 에픽 아이템, 전설 아이템 획득, 모든 슬롯 에픽 이상 장착 |
|
||||
| **탐험** | 첫 퀘스트 완료, 100개 퀘스트 완료, 모든 Act 클리어 |
|
||||
| **생존** | 10연전 생존, HP 1로 생존, 사망 없이 Act 1 클리어 |
|
||||
| **스킬** | 첫 스킬 사용, 스킬로 100마리 처치, 모든 스킬 습득 |
|
||||
| **도전** | 레벨 10 이하로 Act 1 보스 처치, 장비 없이 10마리 처치 |
|
||||
| **히든** | 특정 조합 발견, 이스터에그 발견 |
|
||||
|
||||
### 1.2 업적 보상
|
||||
|
||||
| 등급 | 보상 |
|
||||
|------|------|
|
||||
| 브론즈 | 골드 100-500 |
|
||||
| 실버 | 골드 500-2000, 아이템 박스 |
|
||||
| 골드 | 골드 2000-10000, 희귀 아이템 박스 |
|
||||
| 플래티넘 | 전설 아이템 박스, 특별 칭호 |
|
||||
|
||||
### 1.3 업적 UI
|
||||
|
||||
```
|
||||
┌─ 업적 ──────────────────────────┐
|
||||
│ ★ 전투 [12/25] │
|
||||
│ ☑ 첫 번째 사냥꾼 - 몬스터 처치│
|
||||
│ ☑ 백전용사 - 100마리 처치 │
|
||||
│ ☐ 천인의 적 - 1000마리 처치 │
|
||||
│ │
|
||||
│ ★ 성장 [3/10] │
|
||||
│ ☑ 신입 개발자 - 레벨 10 │
|
||||
│ ☐ 시니어 개발자 - 레벨 50 │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 도감 시스템
|
||||
|
||||
### 2.1 도감 종류
|
||||
|
||||
| 도감 | 기록 내용 | 수집 조건 |
|
||||
|------|----------|----------|
|
||||
| **몬스터 도감** | 이름, 레벨 범위, 드롭 아이템, 출현 지역 | 한번이라도 처치 |
|
||||
| **아이템 도감** | 이름, 스탯, 희귀도, 획득 방법 | 한번이라도 획득 |
|
||||
| **스킬 도감** | 이름, 효과, MP 소모, 쿨타임 | 한번이라도 습득 |
|
||||
| **NPC 도감** | 이름, 역할, 등장 시네마틱 | 시네마틱에서 등장 |
|
||||
|
||||
### 2.2 몬스터 도감 상세
|
||||
|
||||
```dart
|
||||
class MonsterEntry {
|
||||
final String id;
|
||||
final String name;
|
||||
final int minLevel;
|
||||
final int maxLevel;
|
||||
final List<String> dropItems;
|
||||
final String description;
|
||||
final int killCount; // 처치 횟수
|
||||
final DateTime firstMet; // 첫 조우 시간
|
||||
final bool isDefeated; // 처치 여부
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 도감 UI
|
||||
|
||||
```
|
||||
┌─ 몬스터 도감 [127/200] ─────────┐
|
||||
│ │
|
||||
│ ┌──────┐ Syntax Error │
|
||||
│ │ ∧∧∧ │ Lv. 1-5 │
|
||||
│ │ \○/ │ 드롭: 오타, 구두점 │
|
||||
│ │ │ │ 처치: 47회 │
|
||||
│ └──────┘ │
|
||||
│ │
|
||||
│ ┌──────┐ Memory Leak │
|
||||
│ │ ~~~ │ Lv. 6-12 │
|
||||
│ │ ⊂⊃ │ 드롭: 누수 바이트 │
|
||||
│ │ ~~~ │ 처치: 23회 │
|
||||
│ └──────┘ │
|
||||
│ │
|
||||
│ ┌──────┐ ??? │
|
||||
│ │ ? │ 미발견 │
|
||||
│ └──────┘ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.4 수집률 보상
|
||||
|
||||
| 수집률 | 보상 |
|
||||
|--------|------|
|
||||
| 25% | 칭호 "수집가 견습생" |
|
||||
| 50% | 드롭률 +5% |
|
||||
| 75% | 칭호 "마스터 수집가" |
|
||||
| 100% | 전설 아이템 + 칭호 "완벽주의자" |
|
||||
|
||||
---
|
||||
|
||||
## 3. 통계 화면
|
||||
|
||||
### 3.1 통계 카테고리
|
||||
|
||||
| 카테고리 | 통계 항목 |
|
||||
|----------|----------|
|
||||
| **시간** | 총 플레이 시간, 현재 세션 시간, 평균 세션 시간 |
|
||||
| **전투** | 총 전투 횟수, 처치 몬스터 수, 총 데미지, 최고 단일 데미지, 크리티컬 횟수 |
|
||||
| **생존** | 총 사망 횟수, 사망 원인 Top 5, 최장 생존 시간, 연속 전투 생존 기록 |
|
||||
| **획득** | 총 획득 골드, 총 획득 아이템, 희귀도별 아이템 수, 가장 비싼 아이템 |
|
||||
| **스킬** | 총 스킬 사용 횟수, 스킬별 사용 횟수, 스킬 데미지 합계, 가장 많이 쓴 스킬 |
|
||||
| **탐험** | 완료 퀘스트 수, 방문 지역 수, 현재 Act, 최고 도달 레벨 |
|
||||
| **효율** | 시간당 경험치, 시간당 골드, 평균 전투 시간, 승률 |
|
||||
|
||||
### 3.2 통계 UI
|
||||
|
||||
```
|
||||
┌─ 플레이 통계 ───────────────────┐
|
||||
│ │
|
||||
│ ⏱ 플레이 시간 │
|
||||
│ 총: 15시간 34분 │
|
||||
│ 현재 세션: 2시간 12분 │
|
||||
│ │
|
||||
│ ⚔ 전투 │
|
||||
│ 처치 몬스터: 1,247마리 │
|
||||
│ 총 데미지: 458,291 │
|
||||
│ 최고 데미지: 2,847 (크리티컬) │
|
||||
│ 크리티컬 횟수: 312회 │
|
||||
│ │
|
||||
│ 💀 사망 │
|
||||
│ 총 사망: 7회 │
|
||||
│ ┌ 사망 원인 Top 3 ┐ │
|
||||
│ │ 1. 커널 패닉 (3회)│ │
|
||||
│ │ 2. 메모리 누수 (2회)│ │
|
||||
│ │ 3. 스택 오버플로우 (2회)│ │
|
||||
│ └─────────────────┘ │
|
||||
│ │
|
||||
│ 💰 획득 │
|
||||
│ 총 골드: 124,560 │
|
||||
│ 아이템: 892개 │
|
||||
│ 전설: 3개 | 에픽: 12개 │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 통계 데이터 구조
|
||||
|
||||
```dart
|
||||
class GameStatistics {
|
||||
// 시간
|
||||
final Duration totalPlayTime;
|
||||
final Duration currentSessionTime;
|
||||
|
||||
// 전투
|
||||
final int totalBattles;
|
||||
final int monstersKilled;
|
||||
final int totalDamageDealt;
|
||||
final int highestDamage;
|
||||
final int criticalHits;
|
||||
|
||||
// 생존
|
||||
final int totalDeaths;
|
||||
final Map<String, int> deathCauses;
|
||||
final Duration longestSurvival;
|
||||
|
||||
// 획득
|
||||
final int totalGoldEarned;
|
||||
final int totalItemsObtained;
|
||||
final Map<ItemRarity, int> itemsByRarity;
|
||||
|
||||
// 스킬
|
||||
final int totalSkillUses;
|
||||
final Map<String, int> skillUseCounts;
|
||||
|
||||
// 탐험
|
||||
final int questsCompleted;
|
||||
final int highestLevel;
|
||||
final int currentAct;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 칭호 시스템
|
||||
|
||||
### 4.1 칭호 구조
|
||||
|
||||
```dart
|
||||
class Title {
|
||||
final String id;
|
||||
final String name;
|
||||
final String description;
|
||||
final TitleRarity rarity; // 일반, 희귀, 영웅, 전설
|
||||
final Map<StatType, int>? statBonus; // 착용 시 보너스
|
||||
final String unlockCondition; // 해금 조건 설명
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 칭호 목록
|
||||
|
||||
| 칭호 | 해금 조건 | 보너스 | 희귀도 |
|
||||
|------|----------|--------|--------|
|
||||
| **초보 개발자** | 게임 시작 | - | 일반 |
|
||||
| **버그 헌터** | 몬스터 100마리 처치 | ATK +2 | 일반 |
|
||||
| **백전용사** | 몬스터 1000마리 처치 | ATK +5 | 희귀 |
|
||||
| **천인의 적** | 몬스터 10000마리 처치 | ATK +10, CRI +2% | 영웅 |
|
||||
| **불사신** | 레벨 50 무사망 | HP +100, DEF +5 | 영웅 |
|
||||
| **완벽주의자** | 도감 100% | 모든 스탯 +3 | 전설 |
|
||||
| **글리치 슬레이어** | 글리치 신 처치 | 모든 스탯 +5 | 전설 |
|
||||
| **전설의 코더** | 명예의 전당 입성 | 경험치 +10% | 전설 |
|
||||
| **스피드러너** | 10시간 내 클리어 | 이동 속도 +10% | 영웅 |
|
||||
| **생존주의자** | 사망 3회 이하 클리어 | HP 재생 +5% | 영웅 |
|
||||
| **무자비한 디버거** | 20 콤보 달성 | CRI +5% | 희귀 |
|
||||
| **행운아** | 전설 아이템 10개 획득 | 드롭률 +5% | 희귀 |
|
||||
|
||||
### 4.3 칭호 UI
|
||||
|
||||
```
|
||||
┌─ 칭호 ──────────────────────────────┐
|
||||
│ │
|
||||
│ 현재 칭호: [백전용사] ATK +5 │
|
||||
│ │
|
||||
│ 보유 칭호 [15/50]: │
|
||||
│ │
|
||||
│ ★★★ 전설 │
|
||||
│ ☐ 글리치 슬레이어 (미해금) │
|
||||
│ ☐ 완벽주의자 (미해금) │
|
||||
│ │
|
||||
│ ★★ 영웅 │
|
||||
│ ☑ 불사신 - HP +100, DEF +5 │
|
||||
│ ☐ 스피드러너 (미해금) │
|
||||
│ │
|
||||
│ ★ 희귀 │
|
||||
│ ☑ 백전용사 - ATK +5 [장착 중] │
|
||||
│ ☑ 무자비한 디버거 - CRI +5% │
|
||||
│ │
|
||||
│ ○ 일반 │
|
||||
│ ☑ 초보 개발자 │
|
||||
│ ☑ 버그 헌터 - ATK +2 │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
184
doc/task-ext-platform.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# 플랫폼/오프라인/향후 고려사항
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 오프라인/백그라운드 진행
|
||||
|
||||
### 1.1 오프라인 진행 개념
|
||||
|
||||
```
|
||||
앱 종료 시점 기록 → 재접속 시 경과 시간 계산 → 오프라인 보상 계산 → 결과 표시
|
||||
```
|
||||
|
||||
### 1.2 오프라인 보상 계산
|
||||
|
||||
```dart
|
||||
class OfflineProgressCalculator {
|
||||
/// 오프라인 보상 계산
|
||||
OfflineReward calculate({
|
||||
required DateTime lastPlayedAt,
|
||||
required int playerLevel,
|
||||
required CombatStats stats,
|
||||
}) {
|
||||
final duration = DateTime.now().difference(lastPlayedAt);
|
||||
final cappedMinutes = min(duration.inMinutes, maxOfflineMinutes);
|
||||
|
||||
// 분당 예상 전투 수 (레벨 기반)
|
||||
final battlesPerMinute = 2.0;
|
||||
final totalBattles = (cappedMinutes * battlesPerMinute).round();
|
||||
|
||||
// 오프라인 효율 (온라인의 50%)
|
||||
final efficiency = 0.5;
|
||||
|
||||
return OfflineReward(
|
||||
exp: (totalBattles * expPerBattle * efficiency).round(),
|
||||
gold: (totalBattles * goldPerBattle * efficiency).round(),
|
||||
items: generateOfflineItems(totalBattles, efficiency),
|
||||
duration: Duration(minutes: cappedMinutes),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 오프라인 제한
|
||||
|
||||
| 항목 | 제한 |
|
||||
|------|------|
|
||||
| 최대 오프라인 시간 | 8시간 (480분) |
|
||||
| 오프라인 효율 | 온라인의 50% |
|
||||
| 사망 가능성 | 없음 (오프라인 중 사망 불가) |
|
||||
| 레벨업 | 가능 (최대 3레벨) |
|
||||
| 퀘스트 진행 | 불가 (전투만 계산) |
|
||||
| 스킬 사용 | 자동 (효율 계산에 포함) |
|
||||
|
||||
### 1.4 재접속 UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ 🌙 오프라인 보상 │
|
||||
│ │
|
||||
│ 부재 시간: 4시간 32분 │
|
||||
│ │
|
||||
│ ───────────────────────── │
|
||||
│ 💰 획득 골드: 2,450 │
|
||||
│ ⭐ 획득 경험치: 12,800 │
|
||||
│ 📦 획득 아이템: 3개 │
|
||||
│ ───────────────────────── │
|
||||
│ │
|
||||
│ 레벨업! Lv.23 → Lv.24 │
|
||||
│ │
|
||||
│ [ 보상 받기 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.5 백그라운드 진행 (모바일)
|
||||
|
||||
| 모드 | 동작 |
|
||||
|------|------|
|
||||
| 포그라운드 | 정상 진행 |
|
||||
| 백그라운드 (5분 이내) | 실시간 진행 유지 |
|
||||
| 백그라운드 (5분 초과) | 앱 일시 정지, 재진입 시 오프라인 계산 |
|
||||
| 완전 종료 | 오프라인 계산 |
|
||||
|
||||
### 1.6 관련 파일
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `core/service/offline_service.dart` | **신규** - 오프라인 보상 계산 |
|
||||
| `core/storage/last_played_storage.dart` | **신규** - 마지막 플레이 시간 저장 |
|
||||
| `features/game/widgets/offline_reward_dialog.dart` | **신규** - 보상 UI |
|
||||
|
||||
---
|
||||
|
||||
## 2. 플랫폼별 고려사항
|
||||
|
||||
### 2.1 플랫폼 지원 현황
|
||||
|
||||
| 플랫폼 | 지원 | 우선순위 | 특이사항 |
|
||||
|--------|------|----------|----------|
|
||||
| iOS | ✓ | 상 | App Store 심사 |
|
||||
| Android | ✓ | 상 | Google Play 심사 |
|
||||
| Web | ✓ | 중 | 브라우저 호환성 |
|
||||
| macOS | ✓ | 하 | 데스크톱 UI |
|
||||
| Windows | ✓ | 하 | 데스크톱 UI |
|
||||
| Linux | △ | 최하 | 테스트 제한적 |
|
||||
|
||||
### 2.2 플랫폼별 기능 차이
|
||||
|
||||
| 기능 | iOS | Android | Web | Desktop |
|
||||
|------|-----|---------|-----|---------|
|
||||
| 진동 | ✓ | ✓ | ✗ | ✗ |
|
||||
| 푸시 알림 | ✓ | ✓ | △ | △ |
|
||||
| 백그라운드 | △ | ✓ | ✗ | ✓ |
|
||||
| 클라우드 저장 | iCloud | Google Play | ✗ | ✗ |
|
||||
| IAP | App Store | Google Play | ✗ | ✗ |
|
||||
| 키보드 단축키 | ✗ | ✗ | ✓ | ✓ |
|
||||
|
||||
### 2.3 화면 크기 대응
|
||||
|
||||
| 카테고리 | 화면 크기 | 레이아웃 |
|
||||
|----------|----------|----------|
|
||||
| 소형 모바일 | < 360dp | 단일 컬럼, 축소 UI |
|
||||
| 일반 모바일 | 360-600dp | 단일 컬럼 |
|
||||
| 대형 모바일/태블릿 | 600-900dp | 2단 컬럼 |
|
||||
| 태블릿/데스크톱 | > 900dp | 3단 컬럼 |
|
||||
|
||||
### 2.4 플랫폼별 테스트 체크리스트
|
||||
|
||||
| 항목 | iOS | Android | Web |
|
||||
|------|-----|---------|-----|
|
||||
| 최소 OS 버전 | iOS 12+ | Android 6+ | 최신 브라우저 |
|
||||
| 기기 테스트 | iPhone SE, 15 Pro | 저사양, 고사양 | Chrome, Safari, Firefox |
|
||||
| 가로/세로 | 세로 고정 | 세로 고정 | 반응형 |
|
||||
| 노치/펀치홀 | SafeArea | SafeArea | N/A |
|
||||
| 다크 모드 | ✓ | ✓ | ✓ |
|
||||
|
||||
---
|
||||
|
||||
## 3. 향후 고려 사항
|
||||
|
||||
### 3.1 타임어택/스피드런 모드
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 타이머 표시 | 실시간 플레이 시간 표시 |
|
||||
| 구간 기록 | Act별 클리어 시간 |
|
||||
| 리더보드 | 최고 기록 순위 (향후 온라인) |
|
||||
| 고스트 데이터 | 이전 기록과 비교 (로컬) |
|
||||
|
||||
### 3.2 애널리틱스 (익명)
|
||||
|
||||
| 수집 데이터 | 목적 |
|
||||
|------------|------|
|
||||
| 레벨별 사망률 | 밸런싱 조정 |
|
||||
| 인기 스킬/장비 | 콘텐츠 밸런싱 |
|
||||
| 플레이 세션 시간 | 게임 흐름 개선 |
|
||||
| 이탈 지점 | 문제 구간 파악 |
|
||||
|
||||
### 3.3 다국어 확장
|
||||
|
||||
| 언어 | 우선순위 | 현황 |
|
||||
|------|----------|------|
|
||||
| 한국어 | 완료 | ✓ |
|
||||
| 영어 | 완료 | ✓ |
|
||||
| 일본어 | 높음 | 계획 |
|
||||
| 중국어 (간체) | 높음 | 계획 |
|
||||
| 중국어 (번체) | 중간 | 계획 |
|
||||
| 스페인어 | 중간 | 계획 |
|
||||
|
||||
### 3.4 개발자/디버그 모드
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 레벨 조정 | 즉시 레벨 변경 |
|
||||
| 아이템 지급 | 모든 아이템 획득 |
|
||||
| 골드 지급 | 무제한 골드 |
|
||||
| 무적 모드 | 사망 불가 |
|
||||
| 스킵 | 전투/시네마틱 스킵 |
|
||||
| 로그 표시 | 상세 디버그 로그 |
|
||||
|
||||
---
|
||||
223
doc/task-ext-save-data.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# 세이브/데이터 관리 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 멀티 세이브 슬롯
|
||||
|
||||
### 1.1 세이브 슬롯 구조
|
||||
|
||||
```dart
|
||||
class SaveSlot {
|
||||
final int slotIndex; // 0-4 (5개 슬롯)
|
||||
final String? characterName;
|
||||
final String? race;
|
||||
final String? klass;
|
||||
final int? level;
|
||||
final Duration? playTime;
|
||||
final DateTime? lastPlayedAt;
|
||||
final bool isEmpty;
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 세이브 슬롯 UI
|
||||
|
||||
```
|
||||
┌─ 세이브 슬롯 선택 ──────────────────┐
|
||||
│ │
|
||||
│ ┌─ 슬롯 1 ─────────────────────┐ │
|
||||
│ │ 🎮 CodeSlayer (Lv.45) │ │
|
||||
│ │ 버퍼 드워프 디버거 성기사 │ │
|
||||
│ │ 플레이: 8시간 22분 │ │
|
||||
│ │ 마지막: 2024.03.15 14:30 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 슬롯 2 ─────────────────────┐ │
|
||||
│ │ 🎮 NullMaster (Lv.12) │ │
|
||||
│ │ 널 엘프 컴파일러 마법사 │ │
|
||||
│ │ 플레이: 1시간 05분 │ │
|
||||
│ │ 마지막: 2024.03.14 20:15 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 슬롯 3 ─────────────────────┐ │
|
||||
│ │ 빈 슬롯 │ │
|
||||
│ │ [ + 새 게임 시작 ] │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 슬롯 4 ─────────────────────┐ │
|
||||
│ │ 빈 슬롯 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 슬롯 5 ─────────────────────┐ │
|
||||
│ │ 빈 슬롯 │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 슬롯 관리 기능
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 새 게임 | 빈 슬롯에 새 캐릭터 생성 |
|
||||
| 계속하기 | 해당 슬롯 캐릭터로 게임 재개 |
|
||||
| 삭제 | 슬롯 데이터 삭제 (확인 필요) |
|
||||
| 복사 | 다른 빈 슬롯으로 복사 |
|
||||
| 내보내기 | 세이브 파일로 내보내기 |
|
||||
|
||||
### 1.4 관련 파일
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `core/model/save_slot.dart` | **신규** - 세이브 슬롯 모델 |
|
||||
| `core/storage/multi_save_manager.dart` | **신규** - 멀티 세이브 관리 |
|
||||
| `features/save/save_slot_screen.dart` | **신규** - 슬롯 선택 화면 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 데이터 마이그레이션
|
||||
|
||||
### 2.1 버전별 마이그레이션 전략
|
||||
|
||||
```dart
|
||||
class SaveMigrator {
|
||||
/// 세이브 데이터 버전 확인 및 마이그레이션
|
||||
SaveData migrate(Map<String, dynamic> rawData) {
|
||||
final version = rawData['version'] as int? ?? 1;
|
||||
|
||||
var data = rawData;
|
||||
|
||||
// 단계별 마이그레이션
|
||||
if (version < 2) data = _migrateV1ToV2(data);
|
||||
if (version < 3) data = _migrateV2ToV3(data);
|
||||
if (version < 4) data = _migrateV3ToV4(data);
|
||||
// ...
|
||||
|
||||
return SaveData.fromJson(data);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 버전별 변경 사항
|
||||
|
||||
| 버전 | 변경 내용 | 마이그레이션 |
|
||||
|------|----------|-------------|
|
||||
| v1→v2 | CombatStats 추가 | 기본 스탯에서 파생 스탯 계산 |
|
||||
| v2→v3 | ItemStats 추가 | 기존 아이템에 기본 스탯 부여 |
|
||||
| v3→v4 | SkillState 추가 | 보유 스킬에 상태 초기화 |
|
||||
| v4→v5 | DeathInfo 추가 | 사망 기록 초기화 |
|
||||
| v5→v6 | 통계 데이터 추가 | 기존 플레이 기반 추정 |
|
||||
|
||||
### 2.3 마이그레이션 안전 장치
|
||||
|
||||
```dart
|
||||
class MigrationSafetyNet {
|
||||
/// 마이그레이션 전 백업 생성
|
||||
Future<void> createBackup(int slotIndex) async {
|
||||
final backup = await loadRawSave(slotIndex);
|
||||
await saveBackup(slotIndex, backup, DateTime.now());
|
||||
}
|
||||
|
||||
/// 마이그레이션 실패 시 롤백
|
||||
Future<void> rollback(int slotIndex) async {
|
||||
final backup = await loadLatestBackup(slotIndex);
|
||||
await restoreSave(slotIndex, backup);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 마이그레이션 실패 처리
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ⚠️ 세이브 데이터 업그레이드 실패 │
|
||||
│ │
|
||||
│ 이전 버전의 세이브 데이터를 │
|
||||
│ 현재 버전으로 변환하는 데 │
|
||||
│ 문제가 발생했습니다. │
|
||||
│ │
|
||||
│ [ 백업에서 복원 ] │
|
||||
│ [ 새 게임 시작 ] │
|
||||
│ [ 버그 리포트 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 세이브 파일 관리
|
||||
|
||||
### 3.1 세이브 파일 구조
|
||||
|
||||
```dart
|
||||
class SaveFileManager {
|
||||
/// 세이브 파일 경로
|
||||
Future<String> getSavePath(int slotIndex);
|
||||
|
||||
/// 백업 파일 경로
|
||||
Future<String> getBackupPath(int slotIndex, DateTime timestamp);
|
||||
|
||||
/// 내보내기 파일 생성
|
||||
Future<File> exportSave(int slotIndex);
|
||||
|
||||
/// 외부 파일에서 가져오기
|
||||
Future<void> importSave(File file, int slotIndex);
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 자동 백업
|
||||
|
||||
| 시점 | 백업 유형 | 보관 기간 |
|
||||
|------|----------|----------|
|
||||
| 레벨업 시 | 자동 | 최근 5개 |
|
||||
| 퀘스트 완료 시 | 자동 | 최근 5개 |
|
||||
| 앱 종료 시 | 자동 | 최근 3개 |
|
||||
| 수동 저장 시 | 수동 | 무제한 |
|
||||
| 버전 업데이트 전 | 마이그레이션 | 영구 |
|
||||
|
||||
### 3.3 내보내기/가져오기
|
||||
|
||||
```
|
||||
내보내기 형식: JSON (압축)
|
||||
파일명: ascii_never_die_save_{slot}_{timestamp}.json
|
||||
|
||||
내보내기 내용:
|
||||
- 캐릭터 데이터
|
||||
- 인벤토리
|
||||
- 장비
|
||||
- 퀘스트 진행
|
||||
- 통계
|
||||
- 업적
|
||||
- 설정 (선택적)
|
||||
```
|
||||
|
||||
### 3.4 클라우드 저장 (향후)
|
||||
|
||||
| 플랫폼 | 저장 위치 |
|
||||
|--------|----------|
|
||||
| iOS | iCloud |
|
||||
| Android | Google Play Games |
|
||||
| Desktop | 로컬만 (향후 자체 서버) |
|
||||
|
||||
### 3.5 세이브 파일 UI
|
||||
|
||||
```
|
||||
┌─ 세이브 파일 관리 ──────────────────┐
|
||||
│ │
|
||||
│ 📁 슬롯 1: CodeSlayer │
|
||||
│ │
|
||||
│ 자동 백업 (최근 5개) │
|
||||
│ ├─ 2024-03-15 14:30 (레벨업) │
|
||||
│ ├─ 2024-03-15 14:15 (퀘스트) │
|
||||
│ ├─ 2024-03-15 13:45 (레벨업) │
|
||||
│ └─ ... │
|
||||
│ │
|
||||
│ [ 내보내기 ] [ 가져오기 ] │
|
||||
│ [ 백업에서 복원 ] [ 삭제 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
160
doc/task-ext-settings-infra.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# 설정/튜토리얼/성능/테스트
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 설정 화면
|
||||
|
||||
| 설정 항목 | 옵션 |
|
||||
|----------|------|
|
||||
| 게임 속도 | 0.5x, 1x, 2x, 5x |
|
||||
| 자동 저장 간격 | 1분, 5분, 10분 |
|
||||
| SFX 볼륨 | 0-100% |
|
||||
| BGM 볼륨 | 0-100% |
|
||||
| 진동 | 켜기/끄기 (모바일) |
|
||||
| 알림 표시 | 켜기/끄기 |
|
||||
| 전투 로그 | 간략/상세/끄기 |
|
||||
| 언어 | 한국어/English |
|
||||
|
||||
### 1.1 데이터 관리 설정
|
||||
|
||||
| 설정 항목 | 설명 | 경고 |
|
||||
|----------|------|------|
|
||||
| 튜토리얼 초기화 | 튜토리얼 다시 보기 | - |
|
||||
| 도움말 초기화 | 모든 도움말 팁 다시 표시 | - |
|
||||
| 캐시 삭제 | 임시 파일 삭제 | - |
|
||||
| 설정 초기화 | 모든 설정을 기본값으로 | 확인 필요 |
|
||||
| 현재 캐릭터 삭제 | 현재 슬롯 데이터 삭제 | 2중 확인 필요 |
|
||||
| 모든 데이터 삭제 | 전체 초기화 | 3중 확인 + 입력 확인 |
|
||||
|
||||
### 1.2 데이터 삭제 확인 UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ⚠️ 모든 데이터 삭제 │
|
||||
│ │
|
||||
│ 이 작업은 되돌릴 수 없습니다! │
|
||||
│ │
|
||||
│ 삭제될 항목: │
|
||||
│ • 모든 캐릭터 (5개 슬롯) │
|
||||
│ • 명예의 전당 기록 │
|
||||
│ • 업적 │
|
||||
│ • 통계 │
|
||||
│ • 설정 │
|
||||
│ │
|
||||
│ 확인하려면 "삭제합니다"를 입력: │
|
||||
│ ┌───────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ └───────────────────────────┘ │
|
||||
│ │
|
||||
│ [ 취소 ] [ 삭제 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 성능 최적화
|
||||
|
||||
| 항목 | 현재 | 개선 방안 |
|
||||
|------|------|----------|
|
||||
| 상태 업데이트 | 매 틱마다 전체 rebuild | 변경된 부분만 업데이트 |
|
||||
| 애니메이션 | Timer 기반 | AnimationController 사용 |
|
||||
| 저장 | 자동 저장 빈번 | 변경 감지 후 디바운스 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 테스트 전략
|
||||
|
||||
| 테스트 유형 | 대상 | 도구 |
|
||||
|------------|------|------|
|
||||
| 유닛 테스트 | 전투 계산, 스탯 계산 | flutter_test |
|
||||
| 위젯 테스트 | UI 컴포넌트 | flutter_test |
|
||||
| 통합 테스트 | 전체 게임 플로우 | integration_test |
|
||||
| 밸런스 테스트 | 시뮬레이션 | 커스텀 도구 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 튜토리얼 시스템
|
||||
|
||||
### 4.1 튜토리얼 흐름
|
||||
|
||||
```
|
||||
첫 실행 감지 → 튜토리얼 시작 → 단계별 가이드 → 완료 보상 → 본 게임 시작
|
||||
```
|
||||
|
||||
### 4.2 튜토리얼 단계
|
||||
|
||||
| 단계 | 내용 | 하이라이트 UI | 완료 조건 |
|
||||
|------|------|--------------|----------|
|
||||
| 1 | 게임 소개 | 전체 화면 | 탭하여 계속 |
|
||||
| 2 | 캐릭터 스탯 설명 | 스탯 패널 | 스탯 패널 탭 |
|
||||
| 3 | 전투 시스템 설명 | 전투 영역 | 첫 몬스터 처치 |
|
||||
| 4 | 장비 시스템 설명 | 장비 패널 | 첫 장비 장착 |
|
||||
| 5 | 스킬 사용 설명 | 스킬 바 | 첫 스킬 사용 |
|
||||
| 6 | 경험치/레벨업 설명 | 경험치 바 | 레벨 2 달성 |
|
||||
| 7 | 퀘스트 설명 | 퀘스트 패널 | 첫 퀘스트 확인 |
|
||||
| 8 | 사망/부활 설명 | 안내 팝업 | 탭하여 계속 |
|
||||
| 9 | 설정 및 기타 | 설정 버튼 | 설정 화면 열기 |
|
||||
| 10 | 튜토리얼 완료 | 보상 팝업 | 보상 수령 |
|
||||
|
||||
### 4.3 튜토리얼 UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ┌─────────────────────────────┐ │
|
||||
│ │ 하이라이트된 영역 │◄───│ 이 부분을 탭해보세요!
|
||||
│ └─────────────────────────────┘ │
|
||||
│ │
|
||||
│ ══════════════════════════════ │
|
||||
│ 스탯은 전투력에 직접 영향을 │
|
||||
│ 미칩니다. STR은 공격력, │
|
||||
│ CON은 HP에 영향을 줍니다. │
|
||||
│ ══════════════════════════════ │
|
||||
│ │
|
||||
│ [ 다음 ] [ 건너뛰기 ] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.4 튜토리얼 완료 보상
|
||||
|
||||
| 보상 | 수량 |
|
||||
|------|------|
|
||||
| 골드 | 500 |
|
||||
| 초보자 무기 | 1 |
|
||||
| 초보자 방어구 | 1 |
|
||||
| 경험치 물약 | 1 |
|
||||
|
||||
### 4.5 구현 방안
|
||||
|
||||
```dart
|
||||
class TutorialService {
|
||||
int currentStep = 0;
|
||||
bool isCompleted = false;
|
||||
|
||||
void startTutorial();
|
||||
void nextStep();
|
||||
void skipTutorial();
|
||||
void completeStep(int step);
|
||||
Widget? getHighlightWidget();
|
||||
String getCurrentMessage();
|
||||
}
|
||||
|
||||
class TutorialOverlay extends StatelessWidget {
|
||||
final int step;
|
||||
final VoidCallback onNext;
|
||||
final VoidCallback onSkip;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.6 튜토리얼 관련 파일
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `core/service/tutorial_service.dart` | **신규** - 튜토리얼 로직 |
|
||||
| `features/game/widgets/tutorial_overlay.dart` | **신규** - 튜토리얼 UI |
|
||||
| `data/tutorial_data.dart` | **신규** - 튜토리얼 텍스트 |
|
||||
|
||||
---
|
||||
238
doc/task-ext-ui-tech.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# UI 레이아웃/기술 상세
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. UI 레이아웃/네비게이션
|
||||
|
||||
### 1.1 메인 게임 화면 레이아웃
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ [메뉴] CodeSlayer Lv.25 💰 15,420 [알림] [설정] │ ← 헤더
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─ 캐릭터 ─────┐ ┌─ 전투 영역 ──────────────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ HP ████░░ │ │ ╔═══╗ ╔═══╗ │ │
|
||||
│ │ MP ███░░░ │ │ ║ ☺ ║ VS ║ ☠ ║ │ │
|
||||
│ │ │ │ ╚═══╝ ╚═══╝ │ │
|
||||
│ │ STR: 25 │ │ │ │
|
||||
│ │ CON: 20 │ │ Syntax Error Lv.24 │ │
|
||||
│ │ DEX: 18 │ │ HP ██████░░░░ │ │
|
||||
│ │ INT: 15 │ │ │ │
|
||||
│ │ WIS: 12 │ │ [45 데미지!] │ │
|
||||
│ │ CHA: 10 │ │ │ │
|
||||
│ └──────────────┘ └───────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 장비 ───────────────────────────────────────────┐ │
|
||||
│ │ ⚔️ 디버거의 검 🛡️ 강철 갑옷 🎩 마법 투구 ... │ │
|
||||
│ └───────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ 진행 상황 ──────────────────────────────────────┐ │
|
||||
│ │ 🗡️ 버그 처치 중... [일시정지] │ │
|
||||
│ │ ████████████████░░░░░░░░ 60% │ │
|
||||
│ └───────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ [전투] [인벤] [스킬] [퀘스트] [더보기] │ ← 탭 바
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.2 화면 구성
|
||||
|
||||
| 화면 | 접근 방법 | 주요 기능 |
|
||||
|------|----------|----------|
|
||||
| **메인 (전투)** | 기본 화면 | 전투 진행, 스탯, 장비 |
|
||||
| **인벤토리** | 탭 바 | 아이템 관리, 장착 |
|
||||
| **스킬** | 탭 바 | 스킬 관리, 빌드 |
|
||||
| **퀘스트** | 탭 바 | 퀘스트 목록, 진행 |
|
||||
| **더보기** | 탭 바 | 도감, 업적, 통계, 상점 등 |
|
||||
| **지역** | 더보기 | 월드맵, 던전 |
|
||||
| **설정** | 헤더 | 게임 설정 |
|
||||
|
||||
### 1.3 네비게이션 흐름
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[앱 시작] --> B{세이브 존재?}
|
||||
B -->|No| C[세이브 슬롯 선택]
|
||||
B -->|Yes| D[세이브 슬롯 선택]
|
||||
C --> E[캐릭터 생성]
|
||||
D --> F{튜토리얼 완료?}
|
||||
E --> F
|
||||
F -->|No| G[튜토리얼]
|
||||
F -->|Yes| H[메인 게임]
|
||||
G --> H
|
||||
|
||||
H --> I[인벤토리]
|
||||
H --> J[스킬]
|
||||
H --> K[퀘스트]
|
||||
H --> L[더보기]
|
||||
|
||||
L --> M[도감]
|
||||
L --> N[업적]
|
||||
L --> O[통계]
|
||||
L --> P[상점]
|
||||
L --> Q[지역]
|
||||
L --> R[명예의 전당]
|
||||
```
|
||||
|
||||
### 1.4 모달/오버레이
|
||||
|
||||
| 타입 | 사용 상황 |
|
||||
|------|----------|
|
||||
| **풀스크린 모달** | 사망 화면, 레벨업, 업적 달성 |
|
||||
| **바텀 시트** | 아이템 상세, 스킬 상세, 퀵 액션 |
|
||||
| **다이얼로그** | 확인, 경고, 선택 |
|
||||
| **토스트** | 간단한 알림, 획득 메시지 |
|
||||
| **툴팁** | 스탯 설명, 효과 설명 |
|
||||
|
||||
### 1.5 반응형 레이아웃
|
||||
|
||||
```dart
|
||||
class ResponsiveLayout extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
if (constraints.maxWidth < 360) {
|
||||
return CompactLayout(); // 소형 모바일
|
||||
} else if (constraints.maxWidth < 600) {
|
||||
return MobileLayout(); // 일반 모바일
|
||||
} else if (constraints.maxWidth < 900) {
|
||||
return TabletLayout(); // 태블릿
|
||||
} else {
|
||||
return DesktopLayout(); // 데스크톱
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 기술적 상세
|
||||
|
||||
### 2.1 State Management
|
||||
|
||||
```dart
|
||||
// Riverpod 사용 권장
|
||||
final gameStateProvider = StateNotifierProvider<GameStateNotifier, GameState>(
|
||||
(ref) => GameStateNotifier(),
|
||||
);
|
||||
|
||||
class GameStateNotifier extends StateNotifier<GameState> {
|
||||
GameStateNotifier() : super(GameState.initial());
|
||||
|
||||
void tick() { /* 게임 틱 처리 */ }
|
||||
void attack() { /* 공격 처리 */ }
|
||||
void useSkill(String skillId) { /* 스킬 사용 */ }
|
||||
void equip(Equipment item) { /* 장비 장착 */ }
|
||||
}
|
||||
|
||||
// 분리된 Provider들
|
||||
final combatProvider = ...; // 전투 상태
|
||||
final inventoryProvider = ...; // 인벤토리 상태
|
||||
final questProvider = ...; // 퀘스트 상태
|
||||
final settingsProvider = ...; // 설정 상태
|
||||
```
|
||||
|
||||
### 2.2 에러 처리 전략
|
||||
|
||||
```dart
|
||||
class AppException implements Exception {
|
||||
final String code;
|
||||
final String message;
|
||||
final dynamic originalError;
|
||||
|
||||
AppException(this.code, this.message, [this.originalError]);
|
||||
}
|
||||
|
||||
// 에러 타입
|
||||
class SaveLoadException extends AppException { ... }
|
||||
class MigrationException extends AppException { ... }
|
||||
class NetworkException extends AppException { ... } // 향후 온라인용
|
||||
|
||||
// 전역 에러 핸들러
|
||||
void handleError(AppException e, StackTrace stack) {
|
||||
// 1. 로깅
|
||||
Logger.error(e.code, e.message, stack);
|
||||
|
||||
// 2. 사용자 알림
|
||||
showErrorDialog(e.message);
|
||||
|
||||
// 3. 복구 시도 (가능한 경우)
|
||||
attemptRecovery(e);
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 에러 UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ⚠️ 오류가 발생했습니다 │
|
||||
│ │
|
||||
│ 세이브 데이터를 불러오는 중 │
|
||||
│ 문제가 발생했습니다. │
|
||||
│ │
|
||||
│ 오류 코드: SAVE_LOAD_001 │
|
||||
│ │
|
||||
│ [ 다시 시도 ] [ 백업 복원 ] │
|
||||
│ [ 새 게임 ] [ 문의하기 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.4 로깅 전략
|
||||
|
||||
```dart
|
||||
class Logger {
|
||||
static LogLevel currentLevel = kDebugMode
|
||||
? LogLevel.debug
|
||||
: LogLevel.warning;
|
||||
|
||||
static void debug(String message) { ... }
|
||||
static void info(String message) { ... }
|
||||
static void warning(String message) { ... }
|
||||
static void error(String code, String message, StackTrace? stack) { ... }
|
||||
}
|
||||
|
||||
enum LogLevel { debug, info, warning, error }
|
||||
|
||||
// 로그 출력 예시
|
||||
// [DEBUG] 2024-03-15 14:30:00 - Combat: Player attacks for 45 damage
|
||||
// [INFO] 2024-03-15 14:30:01 - Level up: 24 -> 25
|
||||
// [WARN] 2024-03-15 14:30:02 - Low HP warning: 15%
|
||||
// [ERROR] 2024-03-15 14:30:03 - SAVE_001: Failed to save game
|
||||
```
|
||||
|
||||
### 2.5 성능 모니터링
|
||||
|
||||
```dart
|
||||
class PerformanceMonitor {
|
||||
/// FPS 측정
|
||||
double get currentFps => ...;
|
||||
|
||||
/// 메모리 사용량
|
||||
int get memoryUsageMb => ...;
|
||||
|
||||
/// 틱 처리 시간
|
||||
Duration get averageTickTime => ...;
|
||||
|
||||
/// 성능 경고
|
||||
void checkPerformance() {
|
||||
if (currentFps < 30) {
|
||||
Logger.warning('Low FPS: $currentFps');
|
||||
}
|
||||
if (memoryUsageMb > 500) {
|
||||
Logger.warning('High memory usage: $memoryUsageMb MB');
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
215
doc/task-ext-world.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 월드 시스템: 던전/지역/상점
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 던전/지역 시스템
|
||||
|
||||
### 1.1 월드 구조
|
||||
|
||||
```
|
||||
┌─ 코드 왕국 (세계) ─────────────────────────────────────┐
|
||||
│ │
|
||||
│ Act I: 버그 평원 │
|
||||
│ ├─ 시작 마을 (안전 지역) │
|
||||
│ ├─ 버그 초원 (Lv.1-5) │
|
||||
│ ├─ 에러 숲 (Lv.6-10) │
|
||||
│ ├─ 버그 둥지 [던전] (Lv.8-12) │
|
||||
│ └─ 문법 오류의 탑 [보스] (Lv.15) │
|
||||
│ │
|
||||
│ Act II: 손상된 네트워크 │
|
||||
│ ├─ 디버거 요새 (안전 지역) │
|
||||
│ ├─ 손상된 회로 (Lv.16-25) │
|
||||
│ ├─ 메모리 늪 (Lv.21-30) │
|
||||
│ ├─ 누수 동굴 [던전] (Lv.25-35) │
|
||||
│ └─ 히드라의 서버실 [보스] (Lv.40) │
|
||||
│ │
|
||||
│ Act III: 널 왕국 │
|
||||
│ ├─ 바이너리 신전 (안전 지역) │
|
||||
│ ├─ 널 사막 (Lv.41-50) │
|
||||
│ ├─ 포인터 미궁 (Lv.46-55) │
|
||||
│ ├─ 버퍼의 심연 [던전] (Lv.50-60) │
|
||||
│ └─ 타이탄의 성채 [보스] (Lv.60) │
|
||||
│ │
|
||||
│ Act IV: 글리치 영역 │
|
||||
│ ├─ 저항군 기지 (안전 지역) │
|
||||
│ ├─ 커널 황무지 (Lv.61-70) │
|
||||
│ ├─ 패닉 협곡 (Lv.66-80) │
|
||||
│ ├─ 시스템 감옥 [던전] (Lv.70-85) │
|
||||
│ └─ 아콘의 왕좌 [보스] (Lv.80) │
|
||||
│ │
|
||||
│ Act V: 최종 결전 │
|
||||
│ ├─ 최후의 캐시 (안전 지역) │
|
||||
│ ├─ 글리치 회랑 (Lv.81-90) │
|
||||
│ ├─ 차원의 틈 (Lv.86-95) │
|
||||
│ ├─ 신의 코어 [던전] (Lv.90-100) │
|
||||
│ └─ 글리치 신의 영역 [최종 보스] (Lv.100) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.2 지역 타입
|
||||
|
||||
| 타입 | 설명 | 특징 |
|
||||
|------|------|------|
|
||||
| **안전 지역** | 마을, 요새 | 전투 없음, 상점, NPC, 회복 |
|
||||
| **필드** | 일반 사냥터 | 일반 몬스터, 퀘스트 |
|
||||
| **던전** | 인스턴스 지역 | 강화 몬스터, 미니보스, 보상 증가 |
|
||||
| **보스 지역** | Act 보스 | 보스 몬스터, 스토리 진행 |
|
||||
|
||||
### 1.3 지역 이동 (Idle 방식)
|
||||
|
||||
```dart
|
||||
class AreaProgress {
|
||||
final String currentAreaId;
|
||||
final double explorationProgress; // 0.0 ~ 1.0
|
||||
final bool isBossUnlocked;
|
||||
|
||||
/// 탐험 진행 (자동)
|
||||
void progressExploration(Duration elapsed) {
|
||||
// 시간 경과에 따라 탐험도 증가
|
||||
// 탐험도 100% 달성 시 다음 지역/보스 해금
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4 던전 시스템
|
||||
|
||||
| 요소 | 설명 |
|
||||
|------|------|
|
||||
| **입장 조건** | 최소 레벨, 이전 던전 클리어 |
|
||||
| **층 구조** | 3-5층, 층별 강화 몬스터 |
|
||||
| **보스 층** | 마지막 층에 미니보스 |
|
||||
| **보상** | 일반 필드 대비 2-3배 |
|
||||
| **재입장** | 클리어 후 24시간 대기 (일일 1회) |
|
||||
|
||||
### 1.5 지역 UI
|
||||
|
||||
```
|
||||
┌─ 현재 위치 ─────────────────────────┐
|
||||
│ │
|
||||
│ 📍 Act II: 손상된 회로 │
|
||||
│ Lv.16-25 │
|
||||
│ │
|
||||
│ 탐험 진행도: ████████░░ 78% │
|
||||
│ 다음 지역까지: 22% │
|
||||
│ │
|
||||
│ ─────────────────────────────────── │
|
||||
│ │
|
||||
│ 🏰 디버거 요새 [방문하기] │
|
||||
│ 🌲 손상된 회로 [현재] │
|
||||
│ 🌊 메모리 늪 [해금 필요: 탐험 100%] │
|
||||
│ 🏔 누수 동굴 [해금 필요: Lv.25] │
|
||||
│ 👹 히드라 서버실 [해금 필요] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 상점 시스템 상세
|
||||
|
||||
### 2.1 상점 종류
|
||||
|
||||
| 상점 | 위치 | 판매 품목 |
|
||||
|------|------|----------|
|
||||
| **일반 상점** | 모든 마을 | 물약, 기본 장비, 소모품 |
|
||||
| **대장간** | 모든 마을 | 무기, 방어구 (레벨 기반) |
|
||||
| **마법 상점** | Act II 이후 | 스킬서, 마법 장비 |
|
||||
| **비밀 상점** | 랜덤 등장 | 희귀 아이템, 한정품 |
|
||||
| **길드 상점** | 요새 | 길드 포인트 교환 |
|
||||
|
||||
### 2.2 상점 갱신 시스템
|
||||
|
||||
```dart
|
||||
class Shop {
|
||||
final ShopType type;
|
||||
final List<ShopItem> items;
|
||||
final DateTime lastRefresh;
|
||||
final Duration refreshInterval;
|
||||
|
||||
/// 상점 아이템 갱신
|
||||
void refresh(int playerLevel) {
|
||||
items.clear();
|
||||
items.addAll(_generateItems(playerLevel));
|
||||
lastRefresh = DateTime.now();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| 상점 | 갱신 주기 | 갱신 조건 |
|
||||
|------|----------|----------|
|
||||
| 일반 상점 | 매일 자정 | 자동 |
|
||||
| 대장간 | 레벨업 시 | 레벨업 |
|
||||
| 마법 상점 | 매주 월요일 | 자동 |
|
||||
| 비밀 상점 | 랜덤 | 5% 확률로 등장 |
|
||||
|
||||
### 2.3 가격 계산 공식
|
||||
|
||||
```dart
|
||||
/// 구매 가격 계산
|
||||
int calculateBuyPrice(Equipment item) {
|
||||
final basePrice = item.level * 50;
|
||||
final rarityMultiplier = {
|
||||
ItemRarity.common: 1.0,
|
||||
ItemRarity.uncommon: 2.0,
|
||||
ItemRarity.rare: 5.0,
|
||||
ItemRarity.epic: 15.0,
|
||||
ItemRarity.legendary: 50.0,
|
||||
}[item.rarity]!;
|
||||
|
||||
return (basePrice * rarityMultiplier).round();
|
||||
}
|
||||
|
||||
/// 판매 가격 계산
|
||||
int calculateSellPrice(Equipment item) {
|
||||
return (calculateBuyPrice(item) * 0.3).round();
|
||||
}
|
||||
|
||||
/// CHA 보너스 적용
|
||||
int applyCharismaDiscount(int price, int cha) {
|
||||
// CHA 10당 1% 할인, 최대 20% 할인
|
||||
final discount = min(0.20, (cha - 10) * 0.01);
|
||||
return (price * (1 - discount)).round();
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 상점 UI
|
||||
|
||||
```
|
||||
┌─ 대장간 ────────────────────────────┐
|
||||
│ │
|
||||
│ 👤 레벨: 25 💰 골드: 15,420 │
|
||||
│ 📦 인벤토리: 42/50 │
|
||||
│ │
|
||||
│ ─────────────────────────────────── │
|
||||
│ 판매 중인 아이템 (갱신까지: 2시간) │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ ⚔️ 디버거의 검 (Lv.25) │ │
|
||||
│ │ ATK +35, CRI +3% │ │
|
||||
│ │ 💰 1,250 골드 [구매] │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ 🛡️ 강철 갑옷 (Lv.24) │ │
|
||||
│ │ DEF +42, HP +50 │ │
|
||||
│ │ 💰 1,100 골드 [구매] │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [판매하기] [강화하기] [수리하기] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.5 특별 거래
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| **일괄 구매** | 물약 10개/50개 묶음 구매 (5% 할인) |
|
||||
| **일괄 판매** | 선택한 아이템 일괄 판매 |
|
||||
| **자동 구매** | 물약 부족 시 자동 구매 설정 |
|
||||
| **예약 구매** | 비밀 상점 아이템 등장 시 알림 |
|
||||
|
||||
---
|
||||
292
doc/task-fun-design.md
Normal file
@@ -0,0 +1,292 @@
|
||||
# 재미 요소 설계
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
# 14. 재미 요소 설계 (Fun Factor Design)
|
||||
|
||||
## 14.1 즉각적인 보상감 (Dopamine Hits)
|
||||
|
||||
| 요소 | 설명 | 우선순위 |
|
||||
|------|------|----------|
|
||||
| **데미지 숫자 팝업** | 공격 시 데미지가 화면에 튀어오름 (크리티컬은 크게, 빨간색) | 상 |
|
||||
| **콤보 시스템** | 연속 처치 시 "x5 COMBO!" 표시 + 보너스 경험치 (10% per combo) | 상 |
|
||||
| **희귀 드롭 연출** | 전설 아이템 획득 시 화면 번쩍 + 특별 효과음 + 진동 | 상 |
|
||||
| **레벨업 축하** | 레벨업 시 3초간 화려한 ASCII 이펙트 | 중 |
|
||||
| **크리티컬 이펙트** | 크리티컬 히트 시 화면 흔들림 + "CRITICAL!" 텍스트 | 상 |
|
||||
|
||||
### 14.1.1 데미지 팝업 구현
|
||||
|
||||
```dart
|
||||
class DamagePopup {
|
||||
final int damage;
|
||||
final bool isCritical;
|
||||
final Offset position;
|
||||
final double opacity; // 1.0 → 0.0 fade out
|
||||
final double offsetY; // 위로 떠오름
|
||||
}
|
||||
|
||||
// 표시 예시
|
||||
// 일반: "45" (흰색, 작게)
|
||||
// 크리티컬: "127!" (빨간색, 크게, 흔들림)
|
||||
// 회복: "+30" (녹색)
|
||||
// 스킬: "DEBUG STRIKE 250" (노란색)
|
||||
```
|
||||
|
||||
### 14.1.2 콤보 시스템
|
||||
|
||||
```
|
||||
콤보 조건: 5초 내 연속 처치
|
||||
콤보 보상:
|
||||
- x2: 경험치 +10%
|
||||
- x3: 경험치 +15%
|
||||
- x5: 경험치 +25%, 골드 +10%
|
||||
- x10: 경험치 +50%, 골드 +25%, 희귀 드롭률 +5%
|
||||
- x20+: "UNSTOPPABLE!" 칭호 획득 조건
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14.2 "한 판 더" 유발 요소
|
||||
|
||||
### 14.2.1 일일 도전
|
||||
|
||||
| 요소 | 설명 |
|
||||
|------|------|
|
||||
| **일일 미션** | 매일 3개의 미션 (예: "버그 30마리 처치", "크리티컬 10회") |
|
||||
| **일일 보너스** | 첫 접속 시 골드/아이템 박스 |
|
||||
| **연속 접속 보상** | 7일 연속 시 전설 아이템 박스 |
|
||||
|
||||
```
|
||||
┌─ 일일 도전 ─────────────────────┐
|
||||
│ │
|
||||
│ ☑ 버그 30마리 처치 [30/30] │
|
||||
│ 보상: 골드 500 │
|
||||
│ │
|
||||
│ ☐ 크리티컬 10회 달성 [7/10] │
|
||||
│ 보상: 경험치 물약 │
|
||||
│ │
|
||||
│ ☐ 레벨업 1회 [0/1] │
|
||||
│ 보상: 랜덤 장비 박스 │
|
||||
│ │
|
||||
│ ───────────────────────────────│
|
||||
│ 연속 접속: 5일째 🔥 │
|
||||
│ 7일 보상까지: 2일 남음 │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 14.2.2 주간/이벤트 보스
|
||||
|
||||
| 보스 타입 | 출현 조건 | 보상 |
|
||||
|----------|----------|------|
|
||||
| **주간 보스** | 매주 일요일 등장 | 한정 아이템, 대량 골드 |
|
||||
| **시즌 보스** | 명절/기념일 | 시즌 한정 장비, 칭호 |
|
||||
| **랜덤 레이드** | 랜덤 (1% 확률) | 희귀 아이템 + 업적 |
|
||||
|
||||
### 14.2.3 "거의 다 됐어" 심리
|
||||
|
||||
```
|
||||
레벨업까지 남은 경험치가 10% 이하일 때:
|
||||
→ 경험치 바 색상 변경 (황금색)
|
||||
→ "조금만 더!" 메시지 표시
|
||||
→ 다음 레벨 보상 미리보기
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14.3 플레이어 선택권 확대
|
||||
|
||||
### 14.3.1 스킬 빌드 시스템
|
||||
|
||||
```dart
|
||||
class SkillBuild {
|
||||
final List<String> activeSkills; // 3개 슬롯
|
||||
final List<String> passiveSkills; // 2개 슬롯
|
||||
final String buildName; // "공격형", "탱커형" 등
|
||||
}
|
||||
```
|
||||
|
||||
| 빌드 타입 | 특징 |
|
||||
|----------|------|
|
||||
| **공격형** | 데미지 스킬 위주, 높은 DPS |
|
||||
| **방어형** | 회복/방어 스킬, 생존력 특화 |
|
||||
| **균형형** | 공격 + 회복 혼합 |
|
||||
| **스피드형** | 쿨타임 감소, 연속 공격 |
|
||||
|
||||
### 14.3.2 전투 스타일 전환
|
||||
|
||||
```
|
||||
[공격 모드] 🗡️
|
||||
- 공격력 +20%
|
||||
- 방어력 -10%
|
||||
- 크리티컬 +5%
|
||||
|
||||
[방어 모드] 🛡️
|
||||
- 방어력 +30%
|
||||
- 공격력 -10%
|
||||
- 블록율 +10%
|
||||
|
||||
[균형 모드] ⚖️
|
||||
- 기본 스탯
|
||||
- 회복량 +10%
|
||||
```
|
||||
|
||||
### 14.3.3 자동/반자동 전환
|
||||
|
||||
| 모드 | 설명 |
|
||||
|------|------|
|
||||
| **완전 자동** | 모든 것 자동 (기본) |
|
||||
| **스킬 수동** | 스킬만 수동 선택 |
|
||||
| **보스전 수동** | 보스전에서만 수동 전환 |
|
||||
|
||||
---
|
||||
|
||||
## 14.4 감정적 연결
|
||||
|
||||
### 14.4.1 캐릭터 성장 기록
|
||||
|
||||
```
|
||||
┌─ 나의 여정 ─────────────────────┐
|
||||
│ │
|
||||
│ 🎮 함께한 시간: 15시간 34분 │
|
||||
│ ⚔️ 처치한 버그: 1,247마리 │
|
||||
│ 💀 사망 횟수: 7회 │
|
||||
│ 🏆 획득 업적: 23개 │
|
||||
│ │
|
||||
│ 📝 기억에 남는 순간: │
|
||||
│ • 첫 레벨업 (0시간 2분) │
|
||||
│ • 첫 사망 (1시간 15분) │
|
||||
│ • 첫 전설 아이템 (8시간 22분) │
|
||||
│ • 첫 보스 처치 (5시간 47분) │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 14.4.2 상황별 메시지 (유머/위로)
|
||||
|
||||
| 상황 | 메시지 예시 |
|
||||
|------|------------|
|
||||
| **첫 사망** | "축하합니다! 첫 번째 교훈을 얻었습니다. 버그는 누구나 만납니다." |
|
||||
| **연속 사망** | "잠시 쉬어가는 건 어떨까요? 커피 한 잔의 여유..." |
|
||||
| **레벨업** | "레벨 {n} 달성! 당신의 코드가 더 강해졌습니다." |
|
||||
| **희귀 아이템** | "운이 좋으시네요! 이건 정말 드문 거에요!" |
|
||||
| **100 연속 처치** | "무자비한 디버거! 버그들이 당신을 두려워합니다." |
|
||||
| **장시간 플레이** | "3시간째 플레이 중... 물 한 잔 드세요! 💧" |
|
||||
|
||||
### 14.4.3 마일스톤 축하
|
||||
|
||||
| 마일스톤 | 축하 연출 |
|
||||
|----------|----------|
|
||||
| 100마리 처치 | "백전용사" 칭호 + 특별 이펙트 |
|
||||
| 1000마리 처치 | "천인의 적" 칭호 + 업적 팝업 |
|
||||
| 10시간 플레이 | "헌신적인 개발자" 칭호 |
|
||||
| 무사망 Act 클리어 | "완벽주의자" 칭호 + 보너스 골드 |
|
||||
|
||||
---
|
||||
|
||||
## 14.5 예측 불가능한 재미
|
||||
|
||||
### 14.5.1 랜덤 이벤트
|
||||
|
||||
| 이벤트 | 확률 | 효과 |
|
||||
|--------|------|------|
|
||||
| **전설 몬스터 출현** | 5% | "갑자기 전설 몬스터가 나타났다!" - 처치 시 대량 보상 |
|
||||
| **황금 몬스터** | 3% | 골드 10배 드롭 |
|
||||
| **보물 상자** | 2% | 랜덤 아이템 발견 |
|
||||
| **도움의 NPC** | 5% | 버프 or 회복 제공 |
|
||||
| **함정** | 3% | 데미지 or 디버프 (긴장감) |
|
||||
| **경험치 폭풍** | 1% | 다음 5분간 경험치 2배 |
|
||||
|
||||
### 14.5.2 행운 시스템
|
||||
|
||||
```dart
|
||||
class LuckEvent {
|
||||
// 연속 불운 시 행운 상승
|
||||
int unluckyStreak = 0;
|
||||
|
||||
double getLuckBonus() {
|
||||
// 10회 연속 일반 드롭 시 희귀 드롭 확률 +50%
|
||||
return unluckyStreak >= 10 ? 0.5 : 0.0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14.6 사회적 요소 (향후 확장)
|
||||
|
||||
### 14.6.1 현재 버전 (오프라인)
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| **스크린샷 공유** | 명예의 전당 달성 시 공유 버튼 |
|
||||
| **기록 내보내기** | 통계를 이미지로 저장 |
|
||||
|
||||
### 14.6.2 향후 버전 (아스키 아레나)
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| **글로벌 랭킹** | 레벨, 사망 횟수, 클리어 시간 순위 |
|
||||
| **친구 비교** | 친구의 기록과 비교 |
|
||||
| **PvP 아레나** | 명예의 전당 캐릭터로 대전 |
|
||||
| **길드 시스템** | 협력 레이드 보스 |
|
||||
|
||||
---
|
||||
|
||||
# 15. 피해야 할 요소
|
||||
|
||||
## 15.1 지루함 유발 요소
|
||||
|
||||
| 피해야 할 것 | 이유 | 대안 |
|
||||
|-------------|------|------|
|
||||
| **긴 대기 시간** | 아무 일도 안 일어나면 지루함 | 항상 뭔가 진행 중 표시 |
|
||||
| **반복 메시지** | 같은 문구 반복은 지루함 | 30+ 가지 변형 메시지 |
|
||||
| **단조로운 전투** | 항상 같은 패턴 | 랜덤 이벤트, 크리티컬, 콤보 |
|
||||
| **느린 초반** | 첫 30분이 지루하면 이탈 | 초반 빠른 레벨업 + 튜토리얼 보상 |
|
||||
|
||||
## 15.2 불쾌감 유발 요소
|
||||
|
||||
| 피해야 할 것 | 이유 | 대안 |
|
||||
|-------------|------|------|
|
||||
| **불공정한 즉사** | 예측 불가능한 사망은 스트레스 | HP 보고 대응 가능하도록 |
|
||||
| **과도한 페널티** | 레벨 다운은 너무 가혹 | 장비 상실만 (레벨/인벤 유지) |
|
||||
| **강제 광고** | 게임 흐름 방해 | 광고 없음 |
|
||||
| **과금 유도** | 필수 과금은 불쾌 | 무과금 완전 클리어 가능 |
|
||||
| **복잡한 UI** | 정보 과다는 혼란 | 핵심 정보만, 상세는 별도 탭 |
|
||||
|
||||
## 15.3 혼란 유발 요소
|
||||
|
||||
| 피해야 할 것 | 이유 | 대안 |
|
||||
|-------------|------|------|
|
||||
| **설명 없는 시스템** | 무엇인지 모르면 답답 | 첫 등장 시 툴팁/튜토리얼 |
|
||||
| **너무 많은 스탯** | 이해하기 어려움 | 핵심 6개만 강조 |
|
||||
| **숨겨진 메커니즘** | 어떻게 작동하는지 모름 | 공식 공개 (도움말) |
|
||||
|
||||
---
|
||||
|
||||
# 16. 핵심 재미 요약
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 🎮 ASCII Never Die의 5가지 재미 │
|
||||
│ │
|
||||
│ 1. "조금만 더" - 다음 레벨업이 가까워! │
|
||||
│ → 경험치 바, 레벨업 보상 미리보기 │
|
||||
│ │
|
||||
│ 2. "오 뭐지?" - 예상 못한 전설 아이템! │
|
||||
│ → 랜덤 이벤트, 희귀 드롭 연출 │
|
||||
│ │
|
||||
│ 3. "다시 해보자" - 사망해도 다시 도전! │
|
||||
│ → 적절한 페널티, 빠른 복귀 │
|
||||
│ │
|
||||
│ 4. "나 잘하네" - 통계로 보는 내 성장! │
|
||||
│ → 상세 통계, 업적, 마일스톤 │
|
||||
│ │
|
||||
│ 5. "수집 완료!" - 도감 100% 달성! │
|
||||
│ → 몬스터/아이템 도감, 수집 보상 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
122
doc/task-phase-01-combat.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Phase 1: 핵심 전투 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 목표
|
||||
Stats가 전투에 실제 영향을 미치도록 전투 계산 로직을 구현한다.
|
||||
|
||||
## 2. 새로운 Stats 구조
|
||||
|
||||
```dart
|
||||
class CombatStats {
|
||||
// 기본 스탯 (캐릭터 고유)
|
||||
final int str; // 힘: 물리 공격력 보정
|
||||
final int con; // 체력: HP, 방어력 보정
|
||||
final int dex; // 민첩: 회피율, 크리티컬율, 명중률
|
||||
final int intelligence; // 지능: 마법 공격력, MP
|
||||
final int wis; // 지혜: 마법 방어력, MP 회복
|
||||
final int cha; // 매력: 상점 가격, 드롭율 보정
|
||||
|
||||
// 파생 스탯 (장비 + 기본 스탯으로 계산)
|
||||
final int atk; // 공격력
|
||||
final int def; // 방어력
|
||||
final int magAtk; // 마법 공격력
|
||||
final int magDef; // 마법 방어력
|
||||
final double criRate; // 크리티컬 확률 (0.0 ~ 1.0)
|
||||
final double criDamage; // 크리티컬 데미지 배율 (1.5 ~ 3.0)
|
||||
final double evasion; // 회피율 (0.0 ~ 0.5)
|
||||
final double accuracy; // 명중률 (0.8 ~ 1.0)
|
||||
final double blockRate; // 방패 방어율 (0.0 ~ 0.4)
|
||||
final double parryRate; // 무기로 쳐내기 확률 (0.0 ~ 0.3)
|
||||
|
||||
// 자원
|
||||
final int hpMax;
|
||||
final int hpCurrent;
|
||||
final int mpMax;
|
||||
final int mpCurrent;
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 전투 계산 공식
|
||||
|
||||
```
|
||||
1. 명중 판정
|
||||
명중 = random() < (공격자.accuracy - 방어자.evasion)
|
||||
|
||||
2. 방어 판정 (명중 시)
|
||||
방패 방어 = random() < 방어자.blockRate
|
||||
무기 쳐내기 = random() < 방어자.parryRate
|
||||
|
||||
3. 데미지 계산
|
||||
기본 데미지 = 공격자.atk * (1 + random() * 0.2) - 방어자.def * 0.5
|
||||
|
||||
크리티컬 판정 = random() < 공격자.criRate
|
||||
if (크리티컬) 데미지 *= 공격자.criDamage
|
||||
|
||||
if (방패 방어) 데미지 *= 0.3
|
||||
if (무기 쳐내기) 데미지 *= 0.5
|
||||
|
||||
최종 데미지 = max(1, 데미지)
|
||||
|
||||
4. 전투 결과
|
||||
방어자.hp -= 최종 데미지
|
||||
if (방어자.hp <= 0) 전투 종료
|
||||
```
|
||||
|
||||
## 4. 전투 틱 시스템
|
||||
|
||||
```
|
||||
현재: 2초 후 자동 승리
|
||||
변경: 매 틱(200ms)마다 공격 교환, HP가 0이 되면 승패 결정
|
||||
|
||||
전투 흐름:
|
||||
1. 플레이어 턴 (atk 기반 공격)
|
||||
2. 몬스터 턴 (몬스터 레벨 기반 공격)
|
||||
3. HP 체크
|
||||
4. 반복 또는 종료
|
||||
```
|
||||
|
||||
### 4.1 공격 속도 시스템
|
||||
|
||||
```dart
|
||||
class AttackSpeed {
|
||||
final int baseDelayMs; // 기본 공격 딜레이 (1000ms)
|
||||
final double speedModifier; // DEX 기반 속도 배율
|
||||
|
||||
int get actualDelayMs => (baseDelayMs / speedModifier).round();
|
||||
}
|
||||
|
||||
// 공격 속도 계산
|
||||
double calculateSpeedModifier(int dex) {
|
||||
// DEX 10 = 1.0배, DEX 20 = 1.2배, DEX 50 = 1.8배
|
||||
return 1.0 + (dex - 10) * 0.02;
|
||||
}
|
||||
```
|
||||
|
||||
| DEX | 공격 속도 배율 | 실제 딜레이 |
|
||||
|-----|---------------|------------|
|
||||
| 10 | 1.0x | 1000ms |
|
||||
| 20 | 1.2x | 833ms |
|
||||
| 30 | 1.4x | 714ms |
|
||||
| 50 | 1.8x | 556ms |
|
||||
| 100 | 2.8x | 357ms |
|
||||
|
||||
**몬스터 공격 속도**: 몬스터 타입별로 고정 (빠름/보통/느림)
|
||||
|
||||
## 5. 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/game_state.dart` | CombatStats 클래스 추가, Stats 구조 변경 |
|
||||
| `core/engine/progress_service.dart` | 전투 틱 로직 변경 |
|
||||
| `core/util/pq_logic.dart` | 전투 계산 함수 추가 |
|
||||
| `core/engine/combat_calculator.dart` | **신규** - 전투 계산 전담 |
|
||||
|
||||
## 6. 예상 작업량
|
||||
- 예상 파일 수: 4-5개
|
||||
- 신규 코드: ~400 LOC
|
||||
- 수정 코드: ~200 LOC
|
||||
|
||||
---
|
||||
136
doc/task-phase-02-items.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Phase 2: 아이템 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
아이템에 스탯 보정치를 부여하고, 가중치 시스템을 도입한다.
|
||||
|
||||
## 아이템 스탯 구조
|
||||
|
||||
```dart
|
||||
class ItemStats {
|
||||
final int atk; // 공격력 보정
|
||||
final int def; // 방어력 보정
|
||||
final int magAtk; // 마법 공격력 보정
|
||||
final int magDef; // 마법 방어력 보정
|
||||
final double criRate; // 크리티컬 확률 보정
|
||||
final double evasion; // 회피율 보정
|
||||
final double blockRate; // 방패 방어율 (방패 전용)
|
||||
final double parryRate; // 무기 쳐내기 (무기 전용)
|
||||
|
||||
// 추가 효과
|
||||
final int hpBonus;
|
||||
final int mpBonus;
|
||||
final int strBonus;
|
||||
final int dexBonus;
|
||||
// ... 기타 스탯 보너스
|
||||
}
|
||||
|
||||
class Equipment {
|
||||
final String name;
|
||||
final EquipmentSlot slot;
|
||||
final int level; // 아이템 레벨
|
||||
final int weight; // 가중치 (높을수록 좋은 아이템)
|
||||
final ItemStats stats;
|
||||
final ItemRarity rarity; // Common, Uncommon, Rare, Epic, Legendary
|
||||
}
|
||||
```
|
||||
|
||||
## 아이템 가중치 계산
|
||||
|
||||
```
|
||||
가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
|
||||
|
||||
희귀도 보너스:
|
||||
- Common: 0
|
||||
- Uncommon: 50
|
||||
- Rare: 150
|
||||
- Epic: 400
|
||||
- Legendary: 1000
|
||||
```
|
||||
|
||||
## 자동 장착 로직
|
||||
|
||||
```
|
||||
1. 인벤토리에서 장착 가능한 아이템 필터링
|
||||
2. 슬롯별로 그룹화
|
||||
3. 각 슬롯에서 가장 높은 가중치 아이템 선택
|
||||
4. 무게 제한 체크 (총 무게 ≤ STR 기반 최대 무게)
|
||||
5. 현재 장비와 비교하여 더 좋으면 교체
|
||||
```
|
||||
|
||||
### 무게 제한 시스템
|
||||
|
||||
```dart
|
||||
class WeightSystem {
|
||||
/// STR 기반 최대 휴대 가능 무게
|
||||
int calculateMaxWeight(int str) {
|
||||
// 기본 100 + STR당 10
|
||||
return 100 + str * 10;
|
||||
}
|
||||
|
||||
/// 현재 장비 총 무게
|
||||
int calculateCurrentWeight(List<Equipment> equipped) {
|
||||
return equipped.fold(0, (sum, item) => sum + item.weight);
|
||||
}
|
||||
|
||||
/// 장착 가능 여부
|
||||
bool canEquip(Equipment newItem, List<Equipment> current, int str) {
|
||||
final maxWeight = calculateMaxWeight(str);
|
||||
final currentWeight = calculateCurrentWeight(current);
|
||||
final newWeight = currentWeight + newItem.weight;
|
||||
return newWeight <= maxWeight;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| STR | 최대 무게 | 설명 |
|
||||
|-----|----------|------|
|
||||
| 10 | 200 | 경장비 + 일부 중장비 |
|
||||
| 20 | 300 | 대부분의 장비 |
|
||||
| 30 | 400 | 중장비 풀세트 |
|
||||
| 50 | 600 | 최중량 장비 |
|
||||
|
||||
**무게 초과 페널티**: 장착 불가 (자동 장착 시 무게 고려)
|
||||
|
||||
## 아이템 생성 공식
|
||||
|
||||
```dart
|
||||
/// 아이템 스탯 생성 (레벨 기반)
|
||||
ItemStats generateItemStats(int level, ItemRarity rarity, EquipmentSlot slot) {
|
||||
final rarityMultiplier = {
|
||||
ItemRarity.common: 1.0,
|
||||
ItemRarity.uncommon: 1.3,
|
||||
ItemRarity.rare: 1.7,
|
||||
ItemRarity.epic: 2.2,
|
||||
ItemRarity.legendary: 3.0,
|
||||
}[rarity]!;
|
||||
|
||||
final baseValue = (level * 2 * rarityMultiplier).round();
|
||||
|
||||
// 슬롯별 주요 스탯 결정
|
||||
return switch (slot) {
|
||||
EquipmentSlot.weapon => ItemStats(atk: baseValue, ...),
|
||||
EquipmentSlot.shield => ItemStats(def: baseValue ~/ 2, blockRate: 0.1, ...),
|
||||
EquipmentSlot.armor => ItemStats(def: baseValue, ...),
|
||||
// ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/game_state.dart` | Equipment 구조 변경, ItemStats 추가 |
|
||||
| `core/model/equipment_slot.dart` | 슬롯별 기본 스탯 정의 |
|
||||
| `core/util/pq_logic.dart` | 아이템 생성 로직 변경 |
|
||||
| `core/engine/item_service.dart` | **신규** - 아이템 관리 전담 |
|
||||
| `data/pq_config_data.dart` | 아이템 기본 데이터 확장 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 5-6개
|
||||
- 신규 코드: ~500 LOC
|
||||
- 수정 코드: ~300 LOC
|
||||
90
doc/task-phase-03-skills.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Phase 3: 스킬 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
MP를 소모하여 스킬을 사용하고, 쿨타임을 관리한다.
|
||||
|
||||
## 스킬 구조
|
||||
|
||||
```dart
|
||||
class Skill {
|
||||
final String id;
|
||||
final String name;
|
||||
final SkillType type; // attack, heal, buff, debuff
|
||||
final int mpCost;
|
||||
final int cooldownMs; // 쿨타임 (밀리초)
|
||||
final int power; // 스킬 위력
|
||||
|
||||
// 효과
|
||||
final double damageMultiplier; // 공격 스킬: 데미지 배율
|
||||
final int healAmount; // 회복 스킬: 회복량
|
||||
final BuffEffect? buff; // 버프 효과
|
||||
}
|
||||
|
||||
class SkillState {
|
||||
final String skillId;
|
||||
final int lastUsedMs; // 마지막 사용 시간
|
||||
final int rank; // 스킬 레벨
|
||||
|
||||
bool isReady(int currentMs) =>
|
||||
currentMs - lastUsedMs >= skill.cooldownMs;
|
||||
}
|
||||
```
|
||||
|
||||
## MP 시스템
|
||||
|
||||
```
|
||||
MP 회복:
|
||||
- 비전투 시: 50ms당 1 회복
|
||||
- 전투 중: 회복 없음 (또는 WIS에 비례하여 느리게 회복)
|
||||
- 전투 종료: 즉시 전체 회복
|
||||
|
||||
MP 소모:
|
||||
- 스킬 사용 시 즉시 차감
|
||||
- MP 부족 시 스킬 사용 불가 (일반 공격으로 대체)
|
||||
```
|
||||
|
||||
## 스킬 사용 로직
|
||||
|
||||
```
|
||||
자동 스킬 사용 우선순위:
|
||||
1. HP < 30% → 회복 스킬 (있으면)
|
||||
2. 보스전 → 가장 강력한 공격 스킬
|
||||
3. 일반 전투 → MP 효율이 좋은 스킬
|
||||
4. MP < 20% → 일반 공격만
|
||||
|
||||
수동 개입:
|
||||
- 현재 버전에서는 자동만 지원
|
||||
- 향후 수동 스킬 사용 UI 추가 가능
|
||||
```
|
||||
|
||||
## 스킬 목록 예시
|
||||
|
||||
| 스킬명 | 타입 | MP | 쿨타임 | 효과 |
|
||||
|--------|------|-----|--------|------|
|
||||
| Debug Strike | attack | 10 | 3s | 데미지 150% |
|
||||
| Memory Leak | attack | 25 | 8s | 데미지 250%, 적 방어력 -20% |
|
||||
| Hot Reload | heal | 20 | 10s | HP 30% 회복 |
|
||||
| Safe Mode | buff | 30 | 30s | 방어력 +50%, 10초 지속 |
|
||||
| Core Dump | attack | 50 | 20s | 데미지 400% |
|
||||
| Kernel Panic | attack | 100 | 60s | 데미지 800%, 자신 HP -10% |
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/game_state.dart` | SkillState 추가 |
|
||||
| `core/model/skill.dart` | **신규** - 스킬 정의 |
|
||||
| `core/engine/skill_service.dart` | **신규** - 스킬 사용 로직 |
|
||||
| `core/engine/progress_service.dart` | MP 회복 로직, 스킬 자동 사용 |
|
||||
| `data/skill_data.dart` | **신규** - 스킬 데이터 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 5-6개
|
||||
- 신규 코드: ~600 LOC
|
||||
- 수정 코드: ~200 LOC
|
||||
|
||||
---
|
||||
122
doc/task-phase-04-death.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Phase 4: 사망/부활 시스템
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
사망 개념을 도입하고, 페널티 및 부활 메커니즘을 구현한다.
|
||||
|
||||
## 사망 조건
|
||||
|
||||
```
|
||||
사망 = HP <= 0
|
||||
|
||||
사망 시 처리:
|
||||
1. 게임 루프 일시 정지
|
||||
2. 장착 중인 모든 장비 제거 (인벤토리로 이동하지 않음 - 상실)
|
||||
3. 인벤토리 아이템 유지
|
||||
4. 골드 유지
|
||||
5. 경험치 유지 (레벨 다운 없음)
|
||||
6. 사망 UI 표시 (부활 버튼)
|
||||
```
|
||||
|
||||
## 부활 프로세스
|
||||
|
||||
```
|
||||
부활 버튼 클릭 시:
|
||||
1. HP/MP 전체 회복
|
||||
2. 부활 위치로 이동 (안전 지역: 마을)
|
||||
3. 자동으로 샵 이동
|
||||
4. 골드로 구매 가능한 최고 장비 자동 구매
|
||||
5. 각 슬롯에 장비 자동 장착
|
||||
6. 게임 루프 재개 (퀘스트 진행도 유지)
|
||||
```
|
||||
|
||||
### 부활 위치
|
||||
|
||||
| 상황 | 부활 위치 | 설명 |
|
||||
|------|----------|------|
|
||||
| 일반 사망 | 마을 (시작 지점) | 안전 지역, 샵 접근 가능 |
|
||||
| 보스전 사망 | 보스 던전 입구 | 보스방 직전 |
|
||||
| 퀘스트 중 사망 | 퀘스트 시작 지점 | 퀘스트 진행도 유지 |
|
||||
|
||||
### 부활 페널티 완화 (선택적)
|
||||
|
||||
| 아이템/스킬 | 효과 |
|
||||
|------------|------|
|
||||
| 부활의 부적 (소모품) | 사망 시 장비 1개 보존 |
|
||||
| 영혼 보호 (패시브) | 사망 시 50% 확률로 장비 1개 보존 |
|
||||
| 불사 버프 | 사망 시 HP 1로 생존 (1회) |
|
||||
|
||||
## 샵 시스템
|
||||
|
||||
```dart
|
||||
class Shop {
|
||||
/// 현재 레벨에서 구매 가능한 장비 목록
|
||||
List<Equipment> getAvailableItems(int playerLevel, int gold);
|
||||
|
||||
/// 최적의 장비 세트 자동 구매
|
||||
PurchaseResult autoBuy(int playerLevel, int gold, List<EquipmentSlot> emptySlots);
|
||||
}
|
||||
|
||||
class PurchaseResult {
|
||||
final List<Equipment> purchased;
|
||||
final int totalCost;
|
||||
final int remainingGold;
|
||||
}
|
||||
```
|
||||
|
||||
## 장비 가격 공식
|
||||
|
||||
```
|
||||
기본 가격 = 아이템 레벨 * 50 * 희귀도 배율
|
||||
|
||||
희귀도 배율:
|
||||
- Common: 1.0
|
||||
- Uncommon: 2.0
|
||||
- Rare: 5.0
|
||||
- Epic: 15.0
|
||||
- Legendary: 50.0
|
||||
|
||||
판매 가격 = 구매 가격 * 0.3
|
||||
```
|
||||
|
||||
## 사망 UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ YOU DIED │
|
||||
│ │
|
||||
│ Level 45 버그 헌터 │
|
||||
│ │
|
||||
│ 사망 원인: 커널 패닉 │
|
||||
│ │
|
||||
│ ───────────────────────── │
|
||||
│ 장비 상실: 7개 │
|
||||
│ 보유 골드: 15,420 │
|
||||
│ ───────────────────────── │
|
||||
│ │
|
||||
│ [ 부활하기 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/game_state.dart` | isDead 플래그, deathInfo 추가 |
|
||||
| `core/engine/progress_service.dart` | 사망 판정 로직 |
|
||||
| `core/engine/resurrection_service.dart` | **신규** - 부활 처리 |
|
||||
| `core/engine/shop_service.dart` | **신규** - 샵 로직 |
|
||||
| `features/game/widgets/death_overlay.dart` | **신규** - 사망 UI |
|
||||
| `features/game/game_session_controller.dart` | 사망/부활 상태 관리 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 6-7개
|
||||
- 신규 코드: ~500 LOC
|
||||
- 수정 코드: ~200 LOC
|
||||
|
||||
---
|
||||
66
doc/task-phase-05-race-class.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Phase 5: 종족/클래스 특화
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
종족과 클래스에 고유한 능력치 보정과 특수 능력을 부여한다.
|
||||
|
||||
## 종족 특성
|
||||
|
||||
```dart
|
||||
class RaceTraits {
|
||||
final String raceId;
|
||||
final Map<StatType, int> statModifiers; // 스탯 보정
|
||||
final List<PassiveAbility> passives; // 패시브 능력
|
||||
final double expMultiplier; // 경험치 배율
|
||||
}
|
||||
```
|
||||
|
||||
| 종족 | STR | CON | DEX | INT | WIS | CHA | 특수 능력 |
|
||||
|------|-----|-----|-----|-----|-----|-----|----------|
|
||||
| Byte Human | 0 | 0 | 0 | 0 | 0 | +2 | 경험치 +10% |
|
||||
| Null Elf | -1 | -1 | +2 | +2 | 0 | 0 | 마법 데미지 +15% |
|
||||
| Buffer Dwarf | +2 | +2 | -1 | -1 | 0 | 0 | 방어력 +10% |
|
||||
| Stack Goblin | -1 | -1 | +3 | 0 | 0 | +1 | 크리티컬 확률 +5% |
|
||||
| Heap Troll | +3 | +3 | -2 | -2 | 0 | 0 | HP +20% |
|
||||
| Pointer Fairy | -2 | -2 | +2 | +2 | +2 | 0 | MP +20% |
|
||||
| Coredump Undead | +1 | +2 | -1 | 0 | 0 | -2 | 사망 시 장비 1개 유지 |
|
||||
|
||||
## 클래스 특성
|
||||
|
||||
```dart
|
||||
class ClassTraits {
|
||||
final String classId;
|
||||
final Map<StatType, int> statModifiers;
|
||||
final List<String> startingSkills; // 시작 스킬
|
||||
final List<String> classSkills; // 클래스 전용 스킬
|
||||
final EquipmentRestriction restrictions; // 장비 제한
|
||||
}
|
||||
```
|
||||
|
||||
| 클래스 | 주요 스탯 | 장비 제한 | 특수 능력 |
|
||||
|--------|----------|----------|----------|
|
||||
| Bug Hunter | STR/DEX | 전체 가능 | 일반 공격 +20% |
|
||||
| Debugger Paladin | STR/CON | 중갑, 방패 | 방어력 +15%, 회복력 +10% |
|
||||
| Compiler Mage | INT/WIS | 경갑, 지팡이 | 마법 데미지 +25% |
|
||||
| Refactor Monk | DEX/WIS | 경갑, 맨손 | 회피율 +15%, 연속 공격 |
|
||||
| Pointer Assassin | DEX/STR | 경갑, 단검 | 크리티컬 +20%, 첫 공격 2배 |
|
||||
| Garbage Collector | CON/STR | 중갑 | HP +30%, 전투 후 HP 10% 회복 |
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/race_traits.dart` | **신규** - 종족 특성 |
|
||||
| `core/model/class_traits.dart` | **신규** - 클래스 특성 |
|
||||
| `data/race_data.dart` | **신규** - 종족 데이터 |
|
||||
| `data/class_data.dart` | **신규** - 클래스 데이터 |
|
||||
| `core/engine/stat_calculator.dart` | **신규** - 최종 스탯 계산 |
|
||||
| `features/character/character_creation.dart` | 종족/클래스 선택 UI 개선 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 6-7개
|
||||
- 신규 코드: ~400 LOC
|
||||
- 수정 코드: ~150 LOC
|
||||
119
doc/task-phase-06-balance.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Phase 6: 밸런싱
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 목표
|
||||
레벨 1-100 구간에서 적절한 난이도 곡선을 설계한다.
|
||||
|
||||
## 2. 레벨 구간 설계
|
||||
|
||||
| 구간 | 레벨 | 특징 | 예상 플레이 시간 |
|
||||
|------|------|------|-----------------|
|
||||
| 초반 | 1-20 | 튜토리얼, 기본 시스템 학습 | 1-2시간 |
|
||||
| 중반 | 21-50 | 본격적인 성장, 다양한 스킬 | 3-5시간 |
|
||||
| 후반 | 51-80 | 고급 장비, 어려운 몬스터 | 5-8시간 |
|
||||
| 엔드게임 | 81-100 | 최종 보스, 명예의 전당 | 3-5시간 |
|
||||
|
||||
## 3. 경험치 곡선
|
||||
|
||||
```
|
||||
레벨업 필요 경험치 = 기본값 * (1.15 ^ 레벨)
|
||||
|
||||
기본값 = 100
|
||||
레벨 10: 405 exp
|
||||
레벨 50: 108,366 exp
|
||||
레벨 100: 11,739,085 exp
|
||||
```
|
||||
|
||||
## 4. 몬스터 스탯 스케일링
|
||||
|
||||
```dart
|
||||
MonsterStats generateMonster(int level, MonsterType type) {
|
||||
final baseStats = MonsterStats(
|
||||
hp: 50 + level * 20 + (level * level / 5).round(),
|
||||
atk: 5 + level * 3,
|
||||
def: 2 + level * 2,
|
||||
exp: 10 + level * 5,
|
||||
gold: 5 + level * 3,
|
||||
);
|
||||
|
||||
return _applyTypeModifier(baseStats, type);
|
||||
}
|
||||
```
|
||||
|
||||
### 4.1 몬스터 타입별 배율
|
||||
|
||||
| 타입 | HP | ATK | DEF | EXP | GOLD |
|
||||
|------|-----|-----|-----|-----|------|
|
||||
| 일반 | 1.0x | 1.0x | 1.0x | 1.0x | 1.0x |
|
||||
| 정예 | 2.0x | 1.3x | 1.2x | 2.0x | 2.0x |
|
||||
| 미니보스 | 5.0x | 1.5x | 1.5x | 5.0x | 5.0x |
|
||||
| 보스 | 10.0x | 2.0x | 2.0x | 15.0x | 10.0x |
|
||||
| 최종보스 | 20.0x | 2.5x | 2.5x | 50.0x | 30.0x |
|
||||
|
||||
### 4.2 보스 몬스터 특수 스탯
|
||||
|
||||
```dart
|
||||
class BossStats extends MonsterStats {
|
||||
final List<BossPhase> phases;
|
||||
final double enrageThreshold; // 분노 HP %
|
||||
final double enrageMultiplier; // 분노 시 스탯 배율
|
||||
final bool hasShield; // 보호막 여부
|
||||
final int shieldAmount; // 보호막 수치
|
||||
}
|
||||
```
|
||||
|
||||
| 보스 | 특수 능력 |
|
||||
|------|----------|
|
||||
| Syntax Error Dragon | 페이즈 3에서 연속 공격 |
|
||||
| Memory Leak Hydra | HP 30% 이하 시 회복 |
|
||||
| Buffer Overflow Titan | 보호막 (일정 데미지 흡수) |
|
||||
| Kernel Panic Archon | 분노 시 스턴 공격 |
|
||||
| Glitch God | 5페이즈, 각 페이즈별 완전히 다른 패턴 |
|
||||
|
||||
## 5. 사망 확률 목표
|
||||
|
||||
| 레벨 구간 | 목표 사망 확률 (전투당) |
|
||||
|----------|----------------------|
|
||||
| 1-20 | 1-3% |
|
||||
| 21-50 | 3-5% |
|
||||
| 51-80 | 5-10% |
|
||||
| 81-100 | 10-20% |
|
||||
|
||||
## 6. 밸런스 테스트 도구
|
||||
|
||||
```dart
|
||||
/// 시뮬레이션으로 밸런스 검증
|
||||
class BalanceSimulator {
|
||||
/// 특정 레벨 구간을 N회 시뮬레이션
|
||||
SimulationResult simulate({
|
||||
required int startLevel,
|
||||
required int endLevel,
|
||||
required int iterations,
|
||||
});
|
||||
}
|
||||
|
||||
class SimulationResult {
|
||||
final double averageDeaths;
|
||||
final double averageTimeMinutes;
|
||||
final double survivalRate;
|
||||
final List<String> deathCauses;
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/util/balance_constants.dart` | **신규** - 밸런스 상수 |
|
||||
| `core/util/pq_logic.dart` | 경험치/몬스터 스케일링 |
|
||||
| `data/pq_config_data.dart` | 몬스터 레벨 재조정 |
|
||||
| `test/balance_test.dart` | **신규** - 밸런스 테스트 |
|
||||
|
||||
## 8. 예상 작업량
|
||||
- 예상 파일 수: 4-5개
|
||||
- 신규 코드: ~300 LOC
|
||||
- 수정 코드: ~400 LOC
|
||||
- 테스트 및 조정: 반복 작업 필요
|
||||
123
doc/task-phase-07-content.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Phase 7: 콘텐츠 확장
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
|
||||
더 많은 몬스터, 아이템, 애니메이션을 추가한다.
|
||||
|
||||
## 몬스터 확장
|
||||
|
||||
현재: ~100종
|
||||
목표: ~200종
|
||||
|
||||
추가할 몬스터 카테고리:
|
||||
- 레벨 81-100 엔드게임 몬스터 (30종)
|
||||
- 보스 몬스터 (10종, 각 Act 마다)
|
||||
- 미니 보스 (20종)
|
||||
- 특수 이벤트 몬스터 (20종)
|
||||
- 퀘스트 전용 몬스터 (20종)
|
||||
|
||||
## 아이템 확장
|
||||
|
||||
현재: 이름만 존재
|
||||
목표: 스탯이 있는 300+ 아이템
|
||||
|
||||
카테고리별 추가:
|
||||
- 무기 (50종): 검, 도끼, 활, 지팡이, 단검 등
|
||||
- 방어구 (80종): 투구, 갑옷, 장갑, 부츠, 망토
|
||||
- 방패 (30종)
|
||||
- 악세서리 (50종): 반지, 목걸이, 귀걸이
|
||||
- 소모품 (50종): 물약, 스크롤
|
||||
|
||||
## ASCII 애니메이션 확장
|
||||
|
||||
### 전투 결과별 애니메이션
|
||||
|
||||
| 상황 | 애니메이션 |
|
||||
|------|----------|
|
||||
| 일반 공격 | 기존 battle_mode |
|
||||
| 크리티컬 히트 | 화려한 이펙트 |
|
||||
| 회피 성공 | 살짝 비켜가는 모션 |
|
||||
| 방패 방어 | 방패 들어올리기 |
|
||||
| 스킬 사용 | 스킬별 고유 애니메이션 |
|
||||
| 사망 | 쓰러지는 애니메이션 |
|
||||
| 레벨업 | 빛나는 이펙트 |
|
||||
|
||||
### 몬스터별 애니메이션
|
||||
|
||||
```dart
|
||||
class MonsterAnimation {
|
||||
final String monsterId;
|
||||
final List<String> idleFrames;
|
||||
final List<String> attackFrames;
|
||||
final List<String> hitFrames;
|
||||
final List<String> deathFrames;
|
||||
}
|
||||
```
|
||||
|
||||
카테고리별 기본 애니메이션:
|
||||
- 버그류 (곤충 형태)
|
||||
- 언데드류 (좀비, 유령)
|
||||
- 드래곤류 (대형)
|
||||
- 휴머노이드류 (NPC형)
|
||||
- 기계류 (로봇, 바이러스)
|
||||
|
||||
### ASCII 애니메이션 색상 시스템
|
||||
|
||||
4색 팔레트를 사용하여 시각적 명확성을 확보한다.
|
||||
|
||||
| 색상 | 용도 | 예시 |
|
||||
|------|------|------|
|
||||
| **흰색** | 오브젝트 (캐릭터, 몬스터, 아이템) | 플레이어, 적, 무기 |
|
||||
| **시안** | 포지티브 이펙트 | 힐, 버프, 레벨업, 획득 |
|
||||
| **마젠타** | 네거티브 이펙트 | 데미지, 디버프, 사망, 손실 |
|
||||
| **검정** | 배경 | 기본 배경색 |
|
||||
|
||||
```dart
|
||||
class AsciiColors {
|
||||
static const Color object = Colors.white; // 오브젝트
|
||||
static const Color positive = Colors.cyan; // 포지티브 이펙트
|
||||
static const Color negative = Colors.magenta; // 네거티브 이펙트
|
||||
static const Color background = Colors.black; // 배경
|
||||
}
|
||||
```
|
||||
|
||||
#### 색상 적용 예시
|
||||
|
||||
| 상황 | 주 색상 | 보조 색상 |
|
||||
|------|--------|----------|
|
||||
| 일반 전투 | 흰색 (캐릭터) | - |
|
||||
| 크리티컬 히트 | 흰색 (캐릭터) | 마젠타 (이펙트) |
|
||||
| 힐/버프 획득 | 흰색 (캐릭터) | 시안 (이펙트) |
|
||||
| 독/저주 | 흰색 (캐릭터) | 마젠타 (이펙트) |
|
||||
| 레벨업 | 흰색 (캐릭터) | 시안 (빛나는 효과) |
|
||||
| 사망 | 마젠타 (전체) | - |
|
||||
| 아이템 획득 | 시안 (하이라이트) | - |
|
||||
|
||||
#### UI 변경 사항
|
||||
|
||||
- **색상 변경 버튼 제거**: 기존 사용자 색상 선택 기능 삭제
|
||||
- **고정 팔레트 적용**: 위 4색 체계로 통일
|
||||
- **기존 설정 마이그레이션**: 저장된 색상 설정 무시, 기본값 사용
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `data/pq_config_data.dart` | 몬스터/아이템 데이터 확장 |
|
||||
| `data/ascii_animation_data.dart` | 애니메이션 프레임 추가 |
|
||||
| `data/monster_animations.dart` | **신규** - 몬스터별 애니메이션 |
|
||||
| `core/constants/ascii_colors.dart` | **신규** - 4색 팔레트 상수 정의 |
|
||||
| `features/game/widgets/ascii_animation_card.dart` | 상황별 애니메이션 선택, 색상 시스템 적용 |
|
||||
| `features/game/widgets/color_picker_button.dart` | **삭제** - 색상 변경 버튼 제거 |
|
||||
|
||||
## 예상 작업량
|
||||
|
||||
- 예상 파일 수: 4-5개
|
||||
- 신규 코드: ~1000 LOC (대부분 데이터)
|
||||
- 수정 코드: ~200 LOC
|
||||
|
||||
---
|
||||
60
doc/task-phase-08-ui.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Phase 8: UI/UX 개선
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
능력치 변화를 실시간으로 표시하고, 전반적인 UI를 개선한다.
|
||||
|
||||
## 실시간 스탯 변화 표시
|
||||
|
||||
```
|
||||
┌─ Stats ─────────────────┐
|
||||
│ HP: 450/500 ████████░░ │
|
||||
│ MP: 80/120 ██████░░░░ │
|
||||
│ │
|
||||
│ ATK: 125 (+15) ▲ │ ← 장비 변경 시 변화량 표시
|
||||
│ DEF: 89 (-5) ▼ │
|
||||
│ CRI: 12.5% │
|
||||
│ EVA: 8.3% │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
## 전투 로그
|
||||
|
||||
```
|
||||
┌─ Combat Log ────────────────────┐
|
||||
│ > 문법 오류를 공격! 45 데미지 │
|
||||
│ > 문법 오류의 반격! 12 데미지 │
|
||||
│ > 크리티컬! 98 데미지 │
|
||||
│ > Debug Strike 사용! 150 데미지 │
|
||||
│ > 문법 오류 처치! +25 exp │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 알림 시스템
|
||||
|
||||
| 이벤트 | 표시 방식 |
|
||||
|--------|----------|
|
||||
| 레벨업 | 화면 중앙 팝업 + 사운드 |
|
||||
| 장비 획득 | 우측 하단 토스트 |
|
||||
| 스탭 변화 | 해당 스탯 옆 애니메이션 |
|
||||
| 사망 위험 (HP < 20%) | HP 바 깜빡임 |
|
||||
| 스킬 쿨타임 완료 | 스킬 아이콘 빛남 |
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `features/game/widgets/stats_panel.dart` | 스탯 변화 애니메이션 |
|
||||
| `features/game/widgets/combat_log.dart` | **신규** - 전투 로그 |
|
||||
| `features/game/widgets/notification_overlay.dart` | **신규** - 알림 |
|
||||
| `core/service/notification_service.dart` | **신규** - 알림 관리 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 5-6개
|
||||
- 신규 코드: ~400 LOC
|
||||
- 수정 코드: ~200 LOC
|
||||
|
||||
---
|
||||
63
doc/task-phase-09-story.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Phase 9: 스토리/엔딩
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
프롤로그부터 엔딩까지 일관된 스토리를 구성한다.
|
||||
|
||||
## 스토리 구조
|
||||
|
||||
```
|
||||
Act I (레벨 1-20): 각성
|
||||
- 프롤로그: 코드의 신으로부터 비전을 받음
|
||||
- 마을에서 기본 훈련
|
||||
- 첫 번째 던전: 버그 둥지
|
||||
- Act I 보스: Syntax Error Dragon
|
||||
|
||||
Act II (레벨 21-40): 성장
|
||||
- 디버거 기사단 가입
|
||||
- 손상된 네트워크 탐험
|
||||
- 배신자 발견
|
||||
- Act II 보스: Memory Leak Hydra
|
||||
|
||||
Act III (레벨 41-60): 시련
|
||||
- 널 왕국 진입
|
||||
- 고대 컴파일러의 시험
|
||||
- 동료의 희생
|
||||
- Act III 보스: Buffer Overflow Titan
|
||||
|
||||
Act IV (레벨 61-80): 결전
|
||||
- 글리치 신의 성채 침입
|
||||
- 최후의 동맹 결성
|
||||
- Act IV 보스: Kernel Panic Archon
|
||||
|
||||
Act V (레벨 81-100): 종말
|
||||
- 글리치 신과의 최종 대결
|
||||
- 다중 페이즈 보스전
|
||||
- 엔딩: 시스템 재부팅, 평화 회복
|
||||
```
|
||||
|
||||
## 시네마틱 개선
|
||||
|
||||
각 Act 전환 시:
|
||||
- 전용 시네마틱 텍스트 (5-10개 단계)
|
||||
- ASCII 아트 일러스트
|
||||
- 분위기에 맞는 색상 테마
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `data/story_data.dart` | **신규** - 스토리 텍스트 |
|
||||
| `data/game_text_l10n.dart` | 시네마틱 텍스트 확장 |
|
||||
| `core/engine/story_service.dart` | **신규** - 스토리 진행 관리 |
|
||||
| `features/game/widgets/cinematic_view.dart` | **신규** - 시네마틱 UI |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 4-5개
|
||||
- 신규 코드: ~600 LOC (대부분 텍스트)
|
||||
- 수정 코드: ~100 LOC
|
||||
|
||||
---
|
||||
83
doc/task-phase-10-hall.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Phase 10: 명예의 전당
|
||||
|
||||
> 메인 문서: [game-system-overhaul-index.md](game-system-overhaul-index.md)
|
||||
|
||||
---
|
||||
|
||||
## 목표
|
||||
게임 클리어 시 캐릭터를 명예의 전당에 등재한다.
|
||||
|
||||
## 클리어 조건
|
||||
|
||||
```
|
||||
클리어 = 레벨 100 달성 + 글리치 신 처치
|
||||
```
|
||||
|
||||
## 명예의 전당 데이터
|
||||
|
||||
```dart
|
||||
class HallOfFameEntry {
|
||||
final String id;
|
||||
final String characterName;
|
||||
final String race;
|
||||
final String klass;
|
||||
final int level;
|
||||
final Duration totalPlayTime;
|
||||
final int totalDeaths;
|
||||
final int monstersKilled;
|
||||
final DateTime clearedAt;
|
||||
|
||||
// 향후 아스키 아레나용
|
||||
final CombatStats finalStats;
|
||||
final List<Equipment> finalEquipment;
|
||||
final List<Skill> skills;
|
||||
}
|
||||
```
|
||||
|
||||
## 명예의 전당 UI
|
||||
|
||||
```
|
||||
╔═══════════════════════════════════════════════════╗
|
||||
║ 명예의 전당 ║
|
||||
╠═══════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ 1. 버퍼 드워프 디버거 성기사 "CodeSlayer" ║
|
||||
║ Lv.100 | 12시간 34분 | 사망 3회 ║
|
||||
║ 2024.03.15 ║
|
||||
║ ║
|
||||
║ 2. 널 엘프 컴파일러 마법사 "NullMaster" ║
|
||||
║ Lv.100 | 15시간 22분 | 사망 7회 ║
|
||||
║ 2024.03.10 ║
|
||||
║ ║
|
||||
║ 3. 스택 고블린 포인터 암살자 "StackKiller" ║
|
||||
║ Lv.100 | 18시간 05분 | 사망 12회 ║
|
||||
║ 2024.03.08 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
## 클리어 후 처리
|
||||
|
||||
```
|
||||
1. 축하 시네마틱 표시
|
||||
2. 명예의 전당 등재
|
||||
3. 통계 표시 (플레이 시간, 사망 횟수, 처치 몬스터 등)
|
||||
4. "새 게임 시작" 버튼
|
||||
5. 기존 캐릭터 데이터는 명예의 전당에만 보존
|
||||
```
|
||||
|
||||
## 수정 대상 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `core/model/hall_of_fame.dart` | **신규** - 명예의 전당 모델 |
|
||||
| `core/storage/hall_of_fame_storage.dart` | **신규** - 저장/로드 |
|
||||
| `features/hall_of_fame/hall_of_fame_screen.dart` | **신규** - UI |
|
||||
| `features/game/game_session_controller.dart` | 클리어 처리 |
|
||||
|
||||
## 예상 작업량
|
||||
- 예상 파일 수: 4-5개
|
||||
- 신규 코드: ~400 LOC
|
||||
- 수정 코드: ~100 LOC
|
||||
|
||||
---
|
||||
208
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# 아키텍처 문서
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
```
|
||||
lib/
|
||||
├── main.dart # 앱 진입점
|
||||
├── data/ # 정적 데이터 (Config.dfm 추출)
|
||||
│ ├── pq_config_data.dart
|
||||
│ ├── race_data.dart
|
||||
│ ├── class_data.dart
|
||||
│ └── skill_data.dart
|
||||
├── l10n/ # i18n 생성 파일
|
||||
└── src/
|
||||
├── app.dart # MaterialApp 설정
|
||||
├── core/ # 도메인 레이어
|
||||
│ ├── animation/ # ASCII 애니메이션
|
||||
│ ├── audio/ # 오디오 서비스
|
||||
│ ├── engine/ # 게임 로직
|
||||
│ ├── model/ # 데이터 모델
|
||||
│ ├── storage/ # 저장/로드
|
||||
│ └── util/ # 유틸리티
|
||||
├── features/ # 프레젠테이션 레이어
|
||||
│ ├── arena/ # 아레나 화면
|
||||
│ ├── front/ # 프론트 화면
|
||||
│ ├── game/ # 게임 화면
|
||||
│ ├── hall_of_fame/ # 명예의 전당
|
||||
│ ├── new_character/ # 캐릭터 생성
|
||||
│ └── settings/ # 설정
|
||||
└── shared/ # 공통 위젯/스타일
|
||||
```
|
||||
|
||||
## 레이어 구조 (Clean Architecture)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Screens │ │ Widgets │ │ Controllers │ │
|
||||
│ │ (features/)│ │ (widgets/) │ │ (game_session_ │ │
|
||||
│ │ │ │ │ │ controller.dart) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
|
||||
└─────────┼────────────────┼───────────────────┼──────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Domain Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Models │ │ Services │ │ Managers │ │
|
||||
│ │ (model/) │ │ (engine/) │ │ (game/managers/) │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ - GameState │ │ - Progress │ │ - Statistics │ │
|
||||
│ │ - Equipment │ │ - Combat │ │ - SpeedBoost │ │
|
||||
│ │ - Skills │ │ - Item │ │ - ReturnRewards │ │
|
||||
│ └─────────────┘ └─────────────┘ │ - Resurrection │ │
|
||||
│ │ - HallOfFame │ │
|
||||
│ └─────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Data Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Static │ │ Storage │ │ External │ │
|
||||
│ │ Data │ │ │ │ Services │ │
|
||||
│ │ (data/) │ │ (storage/) │ │ │ │
|
||||
│ │ │ │ │ │ - AdService │ │
|
||||
│ │ - Config │ │ - SaveMgr │ │ - IAPService │ │
|
||||
│ │ - Races │ │ - HallOfFame│ │ - AudioService │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## GameSessionController 매니저 구조
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ GameSessionController │
|
||||
│ (526 LOC) │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 핵심 책임: │ │
|
||||
│ │ - 게임 루프 관리 (startNew, pause, resume) │ │
|
||||
│ │ - 콜백 처리 (_onPlayerDied, _onGameComplete) │ │
|
||||
│ │ - 상태 관리 (GameState, MonetizationState) │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────┼───────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Statistics │ │ SpeedBoost │ │ Return │ │
|
||||
│ │ Manager │ │ Manager │ │ Rewards │ │
|
||||
│ │ (140 LOC) │ │ (190 LOC) │ │ (180 LOC) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │Resurrection │ │ HallOfFame │ │
|
||||
│ │ Manager │ │ Manager │ │
|
||||
│ │ (160 LOC) │ │ (130 LOC) │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 매니저별 책임
|
||||
|
||||
| 매니저 | 파일 | 책임 |
|
||||
|--------|------|------|
|
||||
| `GameStatisticsManager` | `game_statistics_manager.dart` | 세션/누적 통계, 레벨업/골드/처치 추적 |
|
||||
| `SpeedBoostManager` | `speed_boost_manager.dart` | 광고 배속, 버프 만료 체크 |
|
||||
| `ReturnRewardsManager` | `return_rewards_manager.dart` | 복귀 보상 계산, 상자 보상 적용 |
|
||||
| `ResurrectionManager` | `resurrection_manager.dart` | 일반/광고 부활, 자동부활 조건 |
|
||||
| `HallOfFameManager` | `hall_of_fame_manager.dart` | 명예의 전당 등록, 테스트 캐릭터 |
|
||||
|
||||
## 게임 루프 흐름
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ startNew() │
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ ProgressLoop │◄──────┐
|
||||
│ (50ms tick) │ │
|
||||
└────────┬─────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌──────────────────┐ │
|
||||
│ ProgressService │ │
|
||||
│ .tick() │ │
|
||||
└────────┬─────────┘ │
|
||||
│ │
|
||||
┌────┴────┐ │
|
||||
│ │ │
|
||||
▼ ▼ │
|
||||
┌───────┐ ┌───────┐ │
|
||||
│ Task │ │ Quest │ │
|
||||
│Process│ │/Plot │ │
|
||||
└───┬───┘ └───┬───┘ │
|
||||
│ │ │
|
||||
└────┬────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌──────────────────┐ │
|
||||
│ State Stream │───────┘
|
||||
│ → UI Update │
|
||||
└──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ AutoSave │
|
||||
│ (30초 간격) │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```
|
||||
User Action
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ GamePlayScreen │
|
||||
│ (UI Layer) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ GameSession │
|
||||
│ Controller │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────┴────┬────────┬────────┐
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
|
||||
│Progres│ │Stats │ │Resurre│ │HallOf │
|
||||
│sLoop │ │Manager│ │ction │ │Fame │
|
||||
└───┬───┘ └───────┘ │Manager│ │Manager│
|
||||
│ └───────┘ └───────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ProgressService │
|
||||
│ (Game Logic) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ GameState │
|
||||
│ (Immutable) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ SaveManager │
|
||||
│ (Persistence) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## 원본 PQ 알고리즘 매핑
|
||||
|
||||
| PQ 원본 (Delphi) | 포팅 위치 |
|
||||
|-----------------|----------|
|
||||
| `Main.pas:MonsterTask` | `progress_service.dart:_createMonsterTask()` |
|
||||
| `Main.pas:StartTimer` | `progress_loop.dart:tick()` |
|
||||
| `NewGuy.pas:RerollClick` | `character_roll_service.dart` |
|
||||
| `Config.dfm` 데이터 | `data/pq_config_data.dart` |
|
||||
1
docs/app-ads.txt
Normal file
@@ -0,0 +1 @@
|
||||
google.com, pub-6691216385521068, DIRECT, f08c47fec0942fa0
|
||||
395
docs/plan_monetization_system.md
Normal file
@@ -0,0 +1,395 @@
|
||||
# 수익화 시스템 설계
|
||||
|
||||
## 메타 정보
|
||||
|
||||
- **문서 버전**: 1.0
|
||||
- **최종 수정**: 2026-01-16
|
||||
- **상태**: 계획 단계
|
||||
- **플랫폼**: Android/iOS (모바일 전용)
|
||||
- **광고 SDK**: AdMob
|
||||
|
||||
---
|
||||
|
||||
## Task 리스트
|
||||
|
||||
### Phase 1: 데이터 구조 (선행 작업)
|
||||
|
||||
- [ ] `MonetizationState` 모델 생성
|
||||
- [ ] `DeathInfo.lostItem: EquipmentItem?` 필드 추가
|
||||
- [ ] `GameSave` v3 → v4 마이그레이션
|
||||
- [ ] 장비 손실 확률 공식 변경: `20% + (level-1) * 8.89%`
|
||||
- [ ] `ItemService.determineRarity()` 확률 수정: 34/40/20/5/1
|
||||
|
||||
### Phase 2: AdMob 연동
|
||||
|
||||
- [ ] `google_mobile_ads` 패키지 추가
|
||||
- [ ] `AdService` 클래스 생성
|
||||
- [ ] 리워드 광고 로드/표시/콜백 구현
|
||||
- [ ] 인터스티셜 광고 로드/표시/콜백 구현
|
||||
- [ ] 디버그 빌드 광고 ON/OFF 토글 구현
|
||||
|
||||
### Phase 3: IAP 연동
|
||||
|
||||
- [ ] `in_app_purchase` 패키지 추가
|
||||
- [ ] 광고 제거 상품 등록 (Google Play / App Store)
|
||||
- [ ] `IAPService` 클래스 생성
|
||||
- [ ] 구매 처리 로직 구현
|
||||
- [ ] 구매 복원 로직 구현
|
||||
- [ ] 구매 상태 영구 저장
|
||||
|
||||
### Phase 4: 캐릭터 생성 광고
|
||||
|
||||
- [ ] 굴리기 횟수 상태 관리 (rollsRemaining)
|
||||
- [ ] 굴리기 횟수 저장/로드 구현
|
||||
- [ ] 되돌리기 히스토리 관리
|
||||
- [ ] 되돌리기 횟수 상태 관리 (undoRemaining)
|
||||
- [ ] 캐릭터 생성 UI 수정: 굴리기 버튼
|
||||
- [ ] 캐릭터 생성 UI 수정: 되돌리기 버튼
|
||||
|
||||
### Phase 5: 부활 시스템
|
||||
|
||||
- [ ] 사망 시 `DeathInfo.lostItem` 저장 로직
|
||||
- [ ] `reviveWithAdReward()` 함수 구현
|
||||
- [ ] `reviveWithoutAd()` 함수 구현
|
||||
- [ ] 자동부활 버프 상태 관리 (autoReviveEndMs)
|
||||
- [ ] 자동부활 버프 중 사망 처리 로직
|
||||
- [ ] 사망 화면 UI: 광고 부활 버튼
|
||||
- [ ] 사망 화면 UI: 일반 부활 버튼
|
||||
|
||||
### Phase 6: 속도업
|
||||
|
||||
- [ ] 속도 상태 관리 (1x/2x/5x)
|
||||
- [ ] 명예의 전당 캐릭터 존재 여부 확인 로직
|
||||
- [ ] 5배속 버프 상태 관리 (speedBoostEndMs)
|
||||
- [ ] 속도 UI: 버튼 표시 로직
|
||||
- [ ] 속도 UI: 남은 시간 표시
|
||||
|
||||
### Phase 7: 복귀 보상
|
||||
|
||||
- [ ] `lastPlayTime` 저장/로드 구현
|
||||
- [ ] 오프라인 시간 계산 로직
|
||||
- [ ] 오프라인 진행 시뮬레이션 (1배/2배)
|
||||
- [ ] 보물 상자 축적 로직
|
||||
- [ ] 보물 상자 내용물 생성 로직
|
||||
- [ ] 행운의 부적 버프 발동 로직
|
||||
- [ ] 복귀 보상 UI: 환영 다이얼로그
|
||||
- [ ] 복귀 보상 UI: 상자 오픈
|
||||
|
||||
### Phase 8: 디버그 기능
|
||||
|
||||
- [ ] 메인 메뉴: 디버그 옵션 섹션 (kDebugMode)
|
||||
- [ ] 스타트 화면: 디버그 옵션 섹션
|
||||
- [ ] 광고 ON/OFF 토글
|
||||
- [ ] IAP 구매 시뮬레이션 토글
|
||||
- [ ] 오프라인 시간 시뮬레이션
|
||||
|
||||
---
|
||||
|
||||
## 스펙 요약
|
||||
|
||||
### 광고 유형
|
||||
|
||||
| ID | 유형 | 길이 | 사용처 |
|
||||
| -- | ---- | ---- | ------ |
|
||||
| AD_REWARD_REVIVE | 리워드 | 30초 | 부활 |
|
||||
| AD_REWARD_UNDO | 리워드 | 30초 | 캐릭터 생성 되돌리기 |
|
||||
| AD_INTERSTITIAL_ROLL | 인터스티셜 | 6초 | 굴리기 횟수 충전 |
|
||||
| AD_INTERSTITIAL_SPEED | 인터스티셜 | 6초 | 게임 속도업 |
|
||||
|
||||
### IAP 상품
|
||||
|
||||
| ID | 가격 | 유형 |
|
||||
| -- | ---- | ---- |
|
||||
| remove_ads | $9.99 | 비소모성 (1회 구매) |
|
||||
|
||||
### 무료 vs 구매 유저 비교
|
||||
|
||||
| 기능 | 무료 유저 | 구매 유저 |
|
||||
| ---- | --------- | --------- |
|
||||
| 광고 | 표시 | 제거 (버튼 클릭 시 바로 활성화) |
|
||||
| 복귀 상자 최대 | 5개 | 10개 |
|
||||
| 오프라인 진행 속도 | 1배 | 2배 |
|
||||
| 행운 버프 발동 | 1시간당 5분 | 30분당 5분 |
|
||||
| 캐릭터 되돌리기 | 1회 (광고) | 3회 (무료) |
|
||||
| 굴리기 충전 | 광고 필요 | 무제한 |
|
||||
| 속도업 | 광고 필요 | 무제한 |
|
||||
|
||||
---
|
||||
|
||||
## 상세 스펙
|
||||
|
||||
### 1. 캐릭터 생성 - 굴리기
|
||||
|
||||
```yaml
|
||||
rollsRemaining:
|
||||
default: 5
|
||||
min: 0
|
||||
max: 5
|
||||
recharge: +5 (인터스티셜 광고 시청 후)
|
||||
persistence: 저장됨 (0회로 종료 시 재시작해도 0회)
|
||||
```
|
||||
|
||||
### 2. 캐릭터 생성 - 되돌리기
|
||||
|
||||
```yaml
|
||||
undoRemaining:
|
||||
free_user: 1
|
||||
paid_user: 3
|
||||
ad_required:
|
||||
free_user: true (30초 리워드)
|
||||
paid_user: false
|
||||
range: 1단계 전만
|
||||
reset: 새로 굴리기 시작 시 초기화
|
||||
constraint: min(undoRemaining, rollHistory.length)
|
||||
```
|
||||
|
||||
### 3. 장비 손실 확률
|
||||
|
||||
```yaml
|
||||
formula: 20 + (level - 1) * 80 / 9
|
||||
level_1: 20%
|
||||
level_5: 56%
|
||||
level_10_plus: 100%
|
||||
code: |
|
||||
int calculateEquipmentLossChance(int level) {
|
||||
if (level >= 10) return 100;
|
||||
return 20 + ((level - 1) * 80 ~/ 9);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 부활 시스템
|
||||
|
||||
```yaml
|
||||
normal_revive:
|
||||
ad: false
|
||||
hp_recovery: 50%
|
||||
equipment_loss: confirmed
|
||||
sacrifice: required
|
||||
|
||||
ad_revive:
|
||||
ad: true (30초 리워드)
|
||||
hp_recovery: 100%
|
||||
equipment_loss: cancelled (lostItem 복구)
|
||||
sacrifice: none
|
||||
auto_revive_buff:
|
||||
duration: 600000ms (10분)
|
||||
effect: 버프 중 사망 시 자동부활 + 장비 손실 없음
|
||||
```
|
||||
|
||||
### 5. 게임 속도
|
||||
|
||||
```yaml
|
||||
speed_levels:
|
||||
- 1x: 기본
|
||||
- 2x: 명예의 전당 캐릭터 1명 이상 시 해금
|
||||
- 5x: 광고 시청 (5분간) 또는 IAP 구매 시 무제한
|
||||
|
||||
speed_boost:
|
||||
duration: 300000ms (5분)
|
||||
ad: 인터스티셜 6초
|
||||
paid_user: 광고 없이 무제한
|
||||
```
|
||||
|
||||
### 6. 복귀 보상
|
||||
|
||||
```yaml
|
||||
offline_progress:
|
||||
free_user: 1x
|
||||
paid_user: 2x
|
||||
|
||||
treasure_chest:
|
||||
rate: 1개/시간
|
||||
max_free: 5개
|
||||
max_paid: 10개
|
||||
contents:
|
||||
equipment: 50%
|
||||
gold: 30%
|
||||
potion: 15%
|
||||
bonus_equipment: 5%
|
||||
|
||||
lucky_charm_buff:
|
||||
free_user: 5분/오프라인1시간
|
||||
paid_user: 5분/오프라인30분
|
||||
max_duration: 30분
|
||||
effect:
|
||||
common: 34% → 28%
|
||||
uncommon: 40% → 40%
|
||||
rare: 20% → 20%
|
||||
epic: 5% → 10%
|
||||
legendary: 1% → 2%
|
||||
```
|
||||
|
||||
### 7. 아이템 희귀도 (목표)
|
||||
|
||||
```yaml
|
||||
rarity_distribution:
|
||||
common: 34%
|
||||
uncommon: 40%
|
||||
rare: 20%
|
||||
epic: 5%
|
||||
legendary: 1%
|
||||
note: 현재 코드와 다름. ItemService.determineRarity() 수정 필요
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 데이터 모델
|
||||
|
||||
### MonetizationState
|
||||
|
||||
```dart
|
||||
class MonetizationState {
|
||||
final bool adRemovalPurchased; // IAP 구매 여부
|
||||
final int rollsRemaining; // 굴리기 남은 횟수 (0-5)
|
||||
final int undoRemaining; // 되돌리기 남은 횟수
|
||||
final List<Stats>? rollHistory; // 되돌리기용 히스토리
|
||||
final int? autoReviveEndMs; // 자동부활 버프 종료 시점
|
||||
final int? speedBoostEndMs; // 5배속 종료 시점
|
||||
final DateTime? lastPlayTime; // 마지막 플레이 시각
|
||||
final int pendingChests; // 미개봉 상자 개수
|
||||
final int? luckyCharmEndMs; // 행운 버프 종료 시점
|
||||
}
|
||||
```
|
||||
|
||||
### DeathInfo 확장
|
||||
|
||||
```dart
|
||||
class DeathInfo {
|
||||
// 기존 필드
|
||||
final String? lostItemName;
|
||||
final EquipmentSlot? lostItemSlot;
|
||||
final ItemRarity? lostItemRarity;
|
||||
|
||||
// 신규 필드
|
||||
final EquipmentItem? lostItem; // 복구용 전체 장비 정보
|
||||
}
|
||||
```
|
||||
|
||||
### GameSave 버전
|
||||
|
||||
```yaml
|
||||
current_version: 3
|
||||
next_version: 4
|
||||
migration:
|
||||
- add: MonetizationState monetization
|
||||
- add: DeathInfo.lostItem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 엣지 케이스
|
||||
|
||||
| 케이스 | 조건 | 처리 |
|
||||
| ------ | ---- | ---- |
|
||||
| 광고 로드 실패 | 네트워크 오류 | 재시도 버튼 표시 |
|
||||
| 오프라인 상태 | 네트워크 없음 | 광고 버튼 비활성화 |
|
||||
| 광고 중 앱 종료 | 광고 미완료 | 보상 미지급 |
|
||||
| IAP 복원 | 앱 재설치 | 구글/애플 구매기록 확인 |
|
||||
| 자동부활 중 종료 | 버프 활성 중 | 남은 시간 저장 |
|
||||
| 시간 조작 | lastPlayTime > now | 복귀 보상 없음 |
|
||||
| 굴리기 0회 종료 | rollsRemaining == 0 | 0회 유지 |
|
||||
| 되돌리기 초과 | undoRemaining > historyLength | min 적용 |
|
||||
|
||||
---
|
||||
|
||||
## 디버그 옵션 (kDebugMode 전용)
|
||||
|
||||
```yaml
|
||||
debug_options:
|
||||
ad_enabled:
|
||||
type: bool
|
||||
default: true
|
||||
off_behavior: 광고 버튼 클릭 시 바로 보상
|
||||
on_behavior: 실제 광고 재생
|
||||
|
||||
iap_simulated:
|
||||
type: bool
|
||||
default: false
|
||||
off_behavior: 무료 유저로 동작
|
||||
on_behavior: 구매 유저로 동작
|
||||
|
||||
offline_hours:
|
||||
type: int
|
||||
options: [0, 1, 5, 10]
|
||||
default: 0
|
||||
purpose: 복귀 보상 테스트
|
||||
|
||||
locations:
|
||||
- 메인 메뉴 (광고 제거 버튼 아래)
|
||||
- 스타트 화면
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UI 요약
|
||||
|
||||
### 메인 메뉴
|
||||
|
||||
```
|
||||
[ 새 게임 ]
|
||||
[ 불러오기 ]
|
||||
[ 설정 ]
|
||||
[ 명예의 전당 ]
|
||||
────────────
|
||||
[ 광고 제거 - $9.99 ] ← 구매 후 비활성화
|
||||
── Debug Only ──
|
||||
[ 광고: ON/OFF ]
|
||||
[ IAP: 미구매/구매 ]
|
||||
```
|
||||
|
||||
### 캐릭터 생성
|
||||
|
||||
```
|
||||
STR: 14 CON: 12 DEX: 10
|
||||
INT: 16 WIS: 8 CHA: 11
|
||||
Total: 71
|
||||
|
||||
[ 굴리기 (N/5) ] ← 0회 시 🎬 표시
|
||||
[ 🎬 이전으로 (N/M) ] ← 무료:1회, 구매:3회
|
||||
```
|
||||
|
||||
### 게임 화면 - 속도
|
||||
|
||||
```
|
||||
명예의 전당 없음: [ 1x ] [ 🎬 5x ]
|
||||
명예의 전당 있음: [ 1x ] [ 2x ] [ 🎬 5x ]
|
||||
5배속 중: [ 5x ⏱️ 4:32 ]
|
||||
```
|
||||
|
||||
### 사망 화면
|
||||
|
||||
```
|
||||
☠️ You Died
|
||||
Killed by: {monster}
|
||||
Lost: {item}
|
||||
|
||||
[ 🎬 광고 부활 (30초) ]
|
||||
- 장비 복구
|
||||
- 제물 없음
|
||||
- HP 100%
|
||||
- 10분 자동부활
|
||||
|
||||
[ 일반 부활 ]
|
||||
- 장비 손실
|
||||
- 제물 소모
|
||||
- HP 50%
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 참고
|
||||
|
||||
### 관련 파일
|
||||
|
||||
- `lib/src/core/model/game_state.dart`: GameState 모델
|
||||
- `lib/src/core/engine/progress_service.dart`: 사망 처리 로직
|
||||
- `lib/src/core/storage/`: 저장/로드 시스템
|
||||
- `lib/src/core/engine/item_service.dart`: 아이템 희귀도 결정
|
||||
|
||||
### 의존성 패키지
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
google_mobile_ads: ^5.0.0 # AdMob
|
||||
in_app_purchase: ^3.1.0 # IAP
|
||||
```
|
||||
@@ -361,14 +361,16 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 82SY27V867;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -384,7 +386,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -401,7 +403,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -416,7 +418,7 @@
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -427,7 +429,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
@@ -484,7 +486,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
@@ -540,14 +542,16 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 82SY27V867;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -562,14 +566,16 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 82SY27V867;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.askiineverdie;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.naturebridgeai.asciineverdie;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -1,122 +1 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 330 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 482 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 9.8 KiB |