docs(E4): 상점/휴식 설계·구현 계획
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
70
docs/superpowers/specs/2026-06-09-shop-rest-design.md
Normal file
70
docs/superpowers/specs/2026-06-09-shop-rest-design.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# 상점/휴식 노드 (TODO E4) — 설계
|
||||
|
||||
> 작성: 2026-06-09 / 상태: 승인됨 / 근거: TODO E 분해(E4) + E3 맵 노드 구조.
|
||||
> 선행: E3(분기 맵) 완료. 후속: E5(유물)·E6(저장). 카드 제거는 덱 보기 UI 필요 → 후속 분리.
|
||||
|
||||
## 문제
|
||||
|
||||
E3로 분기 맵은 됐으나 모든 노드가 전투다. 골드는 적립만 되고 소비처가 없다. 상점(골드→카드)·
|
||||
휴식(HP 회복) 노드가 필요하다.
|
||||
|
||||
## 범위
|
||||
|
||||
맵에 상점/휴식 노드 추가, 진입 시 전투 대신 상점/휴식 UI. 상점 = 카드 구매(골드). 휴식 = HP 회복.
|
||||
**카드 제거(덱 보기 UI 필요)·유물·저장·휴식 업그레이드는 범위 밖.**
|
||||
|
||||
## 설계
|
||||
|
||||
### 데이터 (`data/map.json` 교체 — 4행)
|
||||
```json
|
||||
{
|
||||
"start": ["A", "B"],
|
||||
"nodes": {
|
||||
"A": { "type": "combat", "enemy": "slime", "row": 1, "col": -1, "next": ["C", "D"] },
|
||||
"B": { "type": "combat", "enemy": "slime", "row": 1, "col": 1, "next": ["C", "D"] },
|
||||
"C": { "type": "rest", "row": 2, "col": -1, "next": ["E", "F"] },
|
||||
"D": { "type": "shop", "row": 2, "col": 1, "next": ["E", "F"] },
|
||||
"E": { "type": "elite", "enemy": "slime_elite", "row": 3, "col": -1, "next": ["BOSS"] },
|
||||
"F": { "type": "combat", "enemy": "slime", "row": 3, "col": 1, "next": ["BOSS"] },
|
||||
"BOSS": { "type": "boss", "enemy": "slime_boss", "row": 4, "col": 0, "next": [] }
|
||||
}
|
||||
}
|
||||
```
|
||||
- rest/shop 노드는 `enemy` 없음. 생성기 검증을 "`enemy` 있을 때만 ENEMIES 확인"으로 완화.
|
||||
Lua MapNodes 직렬화도 enemy 있을 때만 `enemy = "..."` 포함.
|
||||
|
||||
### 파라미터 (생성기 상수)
|
||||
- `CARD_PRICE = 30`, `REST_HEAL = 30`.
|
||||
|
||||
### 상태 추가
|
||||
- `ShopChoices`(any) — 상점 제시 카드 id 3개.
|
||||
- `ShopBought`(any) — 슬롯별 구매 여부 {bool×3}.
|
||||
|
||||
### 메서드
|
||||
- `PickNode`(수정): CurrentNodeId 세팅·맵 숨김 후 타입 분기 —
|
||||
`shop`→`ShowShop`, `rest`→`ShowRest`, 그 외→`CurrentEnemyId=node.enemy`·`StartCombat`.
|
||||
- `ShowShop`(신규): 카드 풀에서 3개 무작위→ShopChoices, ShopBought 초기화(false),
|
||||
각 슬롯 비주얼·가격·골드 갱신, ShopHud 표시.
|
||||
- `BuyCard(slot)`(신규): ShopBought[slot]==true 또는 Gold<CARD_PRICE면 무시. 아니면
|
||||
Gold-=CARD_PRICE, RunDeck에 ShopChoices[slot] 추가, ShopBought[slot]=true, 해당 카드 어둡게, 골드 갱신.
|
||||
- `ShowRest`(신규): `PlayerHp = min(PlayerMaxHp, PlayerHp + REST_HEAL)`, RestHud에 "HP 옛→새 (+회복)" 표시, RestHud 표시.
|
||||
- `LeaveNode`(신규): ShopHud·RestHud 숨김 → `ShowMap`. (상점·휴식 나가기 공용)
|
||||
- `RenderShop`(신규): 3 카드 비주얼/가격/구매상태 + 골드 텍스트 갱신.
|
||||
|
||||
### UI (신규)
|
||||
- `ShopHud`(모달, 숨김): 제목 "상점", 골드 텍스트, 카드 3장(sprite+button + Name/Cost/Desc/Price 자식), "나가기" 버튼.
|
||||
- `RestHud`(모달, 숨김): 제목 "휴식", 정보 텍스트(런타임), "나가기" 버튼.
|
||||
- BindButtons: 상점 카드 버튼 3(→BuyCard i)·상점 나가기(→LeaveNode)·휴식 나가기(→LeaveNode) 바인딩.
|
||||
|
||||
### MapHud (4행 대응)
|
||||
- 노드 y = `(row - (MAX_ROW+1)/2) * 140` (행 수에 맞춰 세로 중앙 정렬). col×180 유지.
|
||||
|
||||
## 검증 (메이커 Play)
|
||||
- 맵→상점(D) 진입 → 카드 3장·가격·골드 표시 → 구매 시 골드 -30·RunDeck +1·해당 카드 비활성 →
|
||||
골드 부족 시 구매 무시 → 나가기 → 맵(다음 노드).
|
||||
- 맵→휴식(C) 진입 → HP +30(상한 클램프) → 나가기 → 맵.
|
||||
- 전투/엘리트/보스/런 클리어/패배 회귀 없음. 생성기 결정적·JSON 유효.
|
||||
- (버튼 클릭은 런타임 — MCP는 PickNode/BuyCard/ShowRest/LeaveNode 직접 호출로 검증.)
|
||||
|
||||
## 범위 밖 (금지)
|
||||
- 카드 제거·덱 보기 UI(후속)·유물(E5)·저장(E6)·휴식 업그레이드·상점 유물/물약.
|
||||
Reference in New Issue
Block a user