diff --git a/Docs/Plans/Text_RPG_Plan.md b/Docs/Plans/Text_RPG_Plan.md new file mode 100644 index 0000000..edb6ba5 --- /dev/null +++ b/Docs/Plans/Text_RPG_Plan.md @@ -0,0 +1,636 @@ +# Text RPG 기능 기획서 + +이 문서는 Kord에 추가할 예정인 Text RPG 기능의 설계 방향과 구현 범위를 정리한 기획 문서입니다. + +## 개요 + +Text RPG 시스템은 Discord 음성 채널을 던전처럼 활용하는 전투형 콘텐츠입니다. + +사용자가 특정 규칙을 따르는 음성 채널에 입장하면, 봇이 채널 이름 Prefix를 읽어 던전 종류와 난이도를 판별하고, 플레이어의 저장된 RPG 데이터와 장착 스킬을 기준으로 전투를 시작합니다. + +이 시스템은 크게 두 종류의 데이터로 구성됩니다. + +- DB에 저장되는 플레이어 상태 데이터 +- fishing 시스템처럼 JSON 파일로 관리하는 정적 게임 데이터 + +초기 목표는 구조를 단단하게 설계해 두고, 이후 던전 종류, 몬스터, 아이템, 스킬, 상점 등을 계속 확장할 수 있게 만드는 것입니다. + +## 목표 + +- 기존 경제 시스템과 연결되는 RPG 전용 성장 구조 추가 +- 골드는 현재 저장 중인 재화 값을 그대로 연동 +- 스킬, 아이템, 던전, 드랍 테이블은 JSON 기반으로 관리 +- 음성 채널 입장만으로 자연스럽게 전투가 시작되는 흐름 구성 +- 전투 종료 후 다음 전투, 휴식, 상점 선택으로 반복 플레이 지원 + +## 전체 게임 루프 + +1. 사용자가 던전용 음성 채널에 입장 +2. 봇이 채널 이름 Prefix를 읽어 던전 종류와 난이도 판별 +3. 플레이어의 RPG 저장 데이터와 장착 스킬 불러오기 +4. 전투 자동 시작 +5. 승리 또는 패배 처리 +6. 보상 지급 +- 골드 +- 아이템 드랍 +- 추후 확장 시 재료, 특수 재화, 경험치 등 추가 가능 +7. 전투 종료 후 선택 UI 표시 +- 다음 전투 +- 휴식 +- 상점 +8. 사용자가 이모지 또는 버튼으로 다음 행동 선택 + +## 데이터 구분 + +### DB 저장 데이터 + +아래 데이터는 사용자별로 DB에 저장되어야 합니다. + +- RPG 플레이어 기본 프로필 +- 능력치 분배 상태 +- 습득 스킬 및 장착 스킬 +- 다이아 보유량 +- 아이템 인벤토리 +- 장비 상태 +- 필요 시 전투 중 임시 상태 +- 추후 확장용 전투 기록, 일일 제한 정보 등 + +### JSON 데이터 + +아래 데이터는 JSON 파일로 관리합니다. + +- 스킬 정의 +- 아이템 정의 +- 던전 정의 +- 몬스터 정의 +- 드랍 테이블 +- 밸런스 상수 및 수치 데이터 + +## 플레이어 데이터 구조 설계 + +### 1. 플레이어 기본 프로필 + +DB 기준으로 아래 역할의 데이터가 필요합니다. + +- `userId` +- `guildId` +- `level` 또는 성장 단계 +- `str` +- `dex` +- `int` +- `statPoints` +- `gold` +- `diamond` +- `equippedSkillIds` +- `currentHp` +- `maxHp` +- `lastDungeonChannelId` +- `lastDungeonType` +- `lastDungeonDifficulty` +- `createdAt` +- `updatedAt` + +설계 메모: + +- `gold`는 기존 미니게임에서 사용하는 골드 값과 중복 저장하지 않고 같은 값을 사용해야 합니다. +- `diamond`는 유료 재화이므로 별도 필드로 분리합니다. +- `str`, `dex`, `int`는 빌드 방향을 정하는 핵심 능력치입니다. +- 치명타율, 회피율, 속도 같은 파생 수치는 DB에 저장하기보다 런타임 계산을 우선으로 합니다. + +### 2. 능력치 설계 + +기본 능력치는 아래 3개를 사용합니다. + +- `str` +- `dex` +- `int` + +각 능력치의 역할 제안: + +- `str`: 물리 공격력, 최대 HP, 중량형 스킬 계수 +- `dex`: 명중, 회피, 치명타, 연속 공격형 스킬 계수 +- `int`: 마법 공격력, 보호막, 회복, 상태이상 계수 + +파생 수치 예시: + +- 물리 공격력 +- 마법 공격력 +- 명중률 +- 회피율 +- 치명타 확률 +- 치명타 피해량 +- 최대 HP +- 행동 속도 + +이 값들은 기본 능력치와 장비, 버프를 조합해 계산하는 구조를 권장합니다. + +### 3. 스킬 저장 구조 + +플레이어 스킬은 아래 두 상태를 구분해야 합니다. + +- 배운 스킬 +- 현재 장착 중인 스킬 + +추천 저장 방식: + +- `PlayerSkill` + - `userId` + - `skillId` + - `skillLevel` + - `isUnlocked` +- `equippedSkillIds` + - 프로필 배열 필드 또는 별도 장착 테이블 + +설계 규칙: + +- 플레이어는 여러 스킬을 배울 수 있지만, 동시에 장착 가능한 스킬 수는 제한합니다. +- 초기 버전은 장착 슬롯 3개 또는 4개 정도가 적절합니다. +- 스킬 성능은 스킬 고유 값과 플레이어 능력치 계수를 함께 사용해 계산합니다. + +### 4. 재화 구조 + +재화는 아래 두 종류를 사용합니다. + +- 골드 +- 다이아 + +골드: + +- 기존 경제 시스템과 공용 +- 낚시, 강화, RPG 전투 보상과 모두 연결 +- 상점 구매, 소비 아이템 사용, 추후 강화 재화 등으로 활용 + +다이아: + +- 유료 재화 +- DB에 별도 저장 +- 추후 편의 기능, 특별 입장권, 스킨, 부가 상품 등에 활용 가능 + +### 5. 인벤토리 구조 + +인벤토리는 수량형 아이템과 고유 상태 아이템을 모두 지원해야 합니다. + +추천 DB 구조: + +- `PlayerInventoryItem` + - `userId` + - `itemId` + - `quantity` + - `enhancementLevel` + - `durability` + - `metadataJson` + +설계 메모: + +- 포션처럼 겹칠 수 있는 아이템은 `quantity` 중심으로 관리 +- 장비는 강화 수치, 랜덤 옵션, 귀속 여부 같은 확장 정보를 위해 `metadataJson` 여지를 두는 것이 좋습니다. +- 아이템 정의 자체는 JSON에서 관리하고, DB에는 소유 상태와 변경 가능한 값만 저장합니다. + +## 아이템 데이터 설계 + +아이템 정의는 JSON 파일로 관리합니다. + +예상 파일 경로: + +- `resource/data/rpg/items.json` + +아이템 분류 예시: + +- 무기 +- 방어구 +- 장신구 +- 소비 아이템 +- 재료 아이템 +- 재화 아이템 +- 퀘스트 아이템 + +예시 구조: + +```json +{ + "items": [ + { + "id": "bronze_sword", + "name": "Bronze Sword", + "type": "weapon", + "rarity": "common", + "stackable": false, + "equipSlot": "weapon", + "statModifiers": { + "str": 2, + "dex": 0, + "int": 0, + "attackPower": 5 + }, + "priceGold": 120, + "sellGold": 30, + "tags": ["starter", "physical"] + } + ] +} +``` + +권장 필드: + +- `id` +- `name` +- `description` +- `type` +- `subType` +- `rarity` +- `stackable` +- `maxStack` +- `equipSlot` +- `statModifiers` +- `priceGold` +- `priceDiamond` +- `sellGold` +- `tags` +- `icon` +- `usableEffect` + +## 스킬 데이터 설계 + +스킬 정의 역시 JSON 파일로 관리합니다. + +예상 파일 경로: + +- `resource/data/rpg/skills.json` + +핵심 조건: + +- 각 스킬은 `str`, `dex`, `int`에 대해 서로 다른 계수를 가질 수 있어야 합니다. +- 동일한 스킬이라도 어떤 스텟 빌드인지에 따라 성능이 달라져야 합니다. + +예시 구조: + +```json +{ + "skills": [ + { + "id": "power_strike", + "name": "Power Strike", + "type": "active", + "target": "single", + "cooldownTurns": 2, + "resourceCost": { + "mana": 0 + }, + "basePower": 20, + "scaling": { + "str": 1.4, + "dex": 0.2, + "int": 0.0 + }, + "hitCount": 1, + "effects": [], + "tags": ["physical", "burst"] + } + ] +} +``` + +권장 필드: + +- `id` +- `name` +- `description` +- `type` +- `target` +- `basePower` +- `scaling` +- `cooldownTurns` +- `resourceCost` +- `accuracyModifier` +- `critModifier` +- `hitCount` +- `effects` +- `unlockCondition` +- `tags` + +스킬 분류 예시: + +- 단일 공격 스킬 +- 광역 공격 스킬 +- 방어 스킬 +- 회복 스킬 +- 버프 스킬 +- 디버프 스킬 +- 패시브 스킬 + +## 던전 및 음성 채널 설계 + +### 음성 채널을 던전으로 사용하는 방식 + +특정 규칙을 따르는 음성 채널을 던전 입구처럼 사용합니다. + +채널 이름 앞 Prefix를 읽어 아래 정보를 판별합니다. + +- 던전 종류 +- 난이도 +- 필요 시 지역 또는 티어 + +예시 채널명: + +- `[slime-easy] Green Fields` +- `[goblin-normal] Goblin Camp` +- `[undead-hard] Forgotten Chapel` + +예시 해석: + +- `slime`: 슬라임 계열 몬스터가 등장하는 던전 그룹 +- `easy`: 쉬움 난이도, 낮은 스펙의 적과 낮은 보상 배수 + +### 던전 JSON 구조 + +예상 파일 경로: + +- `resource/data/rpg/dungeons.json` + +예시: + +```json +{ + "dungeons": [ + { + "id": "slime_easy", + "prefix": "slime-easy", + "name": "Green Fields", + "enemyPool": ["slime", "big_slime"], + "rewardMultiplier": 1.0, + "dropTableId": "slime_easy_drop", + "recommendedStats": { + "str": 5, + "dex": 3, + "int": 2 + } + } + ] +} +``` + +## 전투 시스템 설계 + +### 기본 방향 + +- 유효한 던전 음성 채널에 들어가면 전투가 자동으로 시작됩니다. +- 플레이어가 장착한 스킬이 전투 행동의 기반이 됩니다. +- 초기 버전은 복잡한 수동 입력보다 빠르게 반복 가능한 반자동 전투를 우선합니다. +- 전투 결과는 Discord 텍스트 메시지로 읽기 쉽게 요약합니다. + +### 전투 흐름 + +1. 사용자가 유효한 던전 음성 채널에 입장 +2. 플레이어 상태 검증 +- RPG 프로필 존재 여부 +- 장착 스킬 존재 여부 +- 전투 가능 HP 보유 여부 +3. 전투 세션 생성 +4. 던전의 적 풀에서 적 선택 +5. 전투 턴 루프 실행 +6. 승패 계산 +7. 전투 결과 메시지 전송 +8. 후속 행동 선택 UI 표시 + +### 전투 판정 방식 + +초기 버전 권장안: + +- 반자동 전투 +- 장착 스킬을 우선순위 또는 순환 로직으로 사용 +- `dex` 또는 속도 수치에 따라 선공 결정 +- 각 스킬은 고유 수치와 능력치 계수로 피해량 계산 + +초기 피해 공식 예시: + +- 물리 스킬 피해량 = `basePower + (str * strScaling) + (dex * dexScaling)` +- 마법 스킬 피해량 = `basePower + (int * intScaling) + (dex * secondaryScaling)` + +방어력, 상태이상, 속성 상성은 기본 루프가 안정화된 뒤 확장하는 것이 좋습니다. + +### 전투 세션 런타임 상태 + +메모리 기반 세션으로 아래 정보가 필요합니다. + +- `userId` +- `guildId` +- `channelId` +- `dungeonId` +- `enemyId` +- `playerSnapshot` +- `enemySnapshot` +- `turn` +- `cooldowns` +- `battleLog` +- `result` + +초기 버전은 전투 종료 후 최종 결과만 DB에 반영해도 충분합니다. + +## 몬스터 데이터 설계 + +예상 파일 경로: + +- `resource/data/rpg/enemies.json` + +권장 필드: + +- `id` +- `name` +- `category` +- `stats` +- `skills` +- `rewardGoldRange` +- `dropTableId` +- `aiPattern` +- `tags` + +예시: + +```json +{ + "enemies": [ + { + "id": "slime", + "name": "Slime", + "category": "normal", + "stats": { + "hp": 30, + "attack": 5, + "defense": 1, + "speed": 4 + }, + "skills": ["slime_body_slam"], + "rewardGoldRange": { + "min": 10, + "max": 18 + }, + "dropTableId": "slime_easy_drop", + "aiPattern": "basic_attack", + "tags": ["slime", "beginner"] + } + ] +} +``` + +## 보상 및 드랍 설계 + +전투 종료 후 아래 보상을 계산합니다. + +- 골드 보상 +- 아이템 드랍 +- 추후 확장 시 재료 드랍 +- 낮은 확률의 희귀 보상 + +예상 파일 경로: + +- `resource/data/rpg/drop_tables.json` + +예시: + +```json +{ + "dropTables": [ + { + "id": "slime_easy_drop", + "entries": [ + { + "itemId": "slime_gel", + "chance": 0.45, + "min": 1, + "max": 2 + }, + { + "itemId": "tiny_mana_potion", + "chance": 0.08, + "min": 1, + "max": 1 + } + ] + } + ] +} +``` + +## 전투 종료 후 선택 흐름 + +전투가 끝나면 아래 3가지 선택지를 제공합니다. + +- 다음 전투 +- 휴식 +- 상점 + +### 다음 전투 + +- 같은 던전에서 다음 전투 즉시 시작 +- 던전 종류와 난이도 유지 +- 설계에 따라 HP, 버프, 쿨타임 상태를 이어갈 수 있음 + +### 휴식 + +- HP 회복 +- 필요 시 상태이상 해제 +- 추후 확장 시 골드 소모, 아이템 소모, 턴 소모 등을 붙일 수 있음 + +### 상점 + +- 소비 아이템, 임시 버프, 장비 등을 구매 +- 구매 전 재화와 인벤토리 상태 확인 필요 + +초기 구현은 이모지보다 버튼을 우선 권장합니다. +Discord 인터랙션 기준으로 검증과 관리가 더 쉽기 때문입니다. + +## 권장 DB 모델 분리 + +추가 후보 모델: + +- `RpgProfile` +- `PlayerSkill` +- `PlayerInventoryItem` +- `PlayerEquipment` +- `RpgBattleRecord` + +추후 확장 후보: + +- `RpgDungeonRun` +- `RpgQuestProgress` +- `RpgShopRefresh` + +## 권장 리소스 파일 구조 + +```text +resource/data/rpg/ + dungeons.json + enemies.json + items.json + skills.json + drop_tables.json + balance.json +``` + +## 연동 메모 + +- 골드는 기존 DB 골드 필드와 반드시 연동되어야 함 +- RPG 시스템도 `FishingService`, `RefinementService`처럼 전용 서비스 계층으로 분리하는 것이 좋음 +- JSON 로더는 서버 시작 시 유효성 검사를 수행해야 함 +- 음성 채널 Prefix 파싱 실패 시 안전하게 무시해야 함 +- 사용자가 전투 중 음성 채널을 나간 경우 처리 규칙을 명확히 정의해야 함 + +## 예외 상황 + +- 지원하지 않는 음성 채널에 입장한 경우 +- RPG 프로필이 아직 없는 경우 +- 장착 스킬이 하나도 없는 경우 +- 전투 도중 음성 채널 이탈 +- 전투 결과 선택 전에 연결이 끊긴 경우 +- 인벤토리가 가득 찬 상태에서 아이템 드랍 발생 +- 다른 미니게임과 골드 지급 타이밍이 겹치는 경우 +- 빠른 채널 이동으로 전투 시작 이벤트가 중복 호출되는 경우 + +## 권장 구현 순서 + +### 1단계 + +- RPG 프로필, 스킬, 인벤토리용 DB 스키마 설계 +- JSON 파일 구조 및 스타터 데이터 정의 +- JSON 로더 및 검증기 구현 + +### 2단계 + +- 음성 채널 Prefix 파싱 구현 +- 던전 진입 감지 구현 +- 단일 적 기준 전투 세션 생성 및 자동 전투 루프 구현 + +### 3단계 + +- 전투 보상 지급 +- 전투 종료 후 다음 행동 선택 UI 구현 +- 휴식 및 상점 로직 구현 + +### 4단계 + +- 장비 옵션 확장 +- 상태이상, 패시브, 버프/디버프 확장 +- 파티 플레이 또는 협동 던전 확장 여부 검토 + +## 추가 확인이 필요한 사항 + +- RPG 프로필을 서버 공용으로 할지, 길드별로 분리할지 +- HP를 전투마다 초기화할지, 연속 전투 동안 유지할지 +- 장착 가능한 스킬 수를 몇 개로 할지 +- MP, 스태미나 같은 자원을 둘지, 쿨타임 중심으로 단순화할지 +- 상점 구성이 던전 종류에 따라 달라질지 +- 전투 로그를 짧은 요약형으로 할지, 상세 턴 로그로 할지 +- 초기 버전에서 장비 슬롯까지 바로 넣을지, 인벤토리 중심으로 먼저 갈지 + +## 초기 버전 권장 범위 + +첫 버전은 아래 정도로 작게 시작하는 것이 안정적입니다. + +- 기본 능력치 3종 +- 시작 스킬 3~5개 +- 던전 그룹 2~3종 +- 전투당 적 1마리 +- 전투 종료 후 선택지 3종 +- 골드와 아이템 보상 우선 적용 + +초기 범위를 좁게 잡으면 시스템 구조를 빠르게 안정화할 수 있고, 이후 콘텐츠 확장도 훨씬 수월해집니다.