70 lines
3.8 KiB
Markdown
70 lines
3.8 KiB
Markdown
# 유물 (TODO E5) — 설계
|
|
|
|
> 작성: 2026-06-09 / 상태: 승인됨 / 근거: TODO E 분해(E5) + 기존 전투/맵/상점 구조.
|
|
> 선행: E1~E4 완료. 후속: E6(저장/다음 층). 사용자 요청: 획득 3경로(시작·엘리트·상점) 모두.
|
|
|
|
## 문제
|
|
|
|
런 영속·맵·보상·상점은 됐으나 유물(패시브 빌드 요소)이 없다. 훅 기반 패시브 + 다양한 획득 경로가 필요하다.
|
|
|
|
## 설계
|
|
|
|
### 데이터 `data/relics.json`
|
|
```json
|
|
{
|
|
"relics": {
|
|
"ironHeart": { "name": "강철 심장", "desc": "전투 시작 시 방어도 +6", "hook": "combatStart", "effect": "block", "value": 6 },
|
|
"energyCore": { "name": "에너지 코어", "desc": "턴 시작 시 에너지 +1", "hook": "turnStart", "effect": "energy", "value": 1 },
|
|
"vampire": { "name": "흡혈 송곳니", "desc": "공격 카드 사용 시 HP +1", "hook": "cardPlayed", "effect": "healOnAttack", "value": 1 },
|
|
"goldIdol": { "name": "황금 우상", "desc": "전투 승리 시 골드 +10", "hook": "combatReward", "effect": "gold", "value": 10 }
|
|
},
|
|
"startingRelic": "ironHeart",
|
|
"relicPool": ["energyCore", "vampire", "goldIdol"]
|
|
}
|
|
```
|
|
- `relicPool` = 엘리트/상점에서 무작위로 줄 후보(시작 유물 제외). 중복 허용(스택).
|
|
|
|
### 파라미터 (생성기 상수)
|
|
- `RELIC_PRICE = 60`.
|
|
|
|
### 상태 추가
|
|
- `Relics`(any) — 전체 유물 정의(주입).
|
|
- `RunRelics`(any) — 보유 유물 id 목록.
|
|
- `ShopRelic`(string) — 상점 제시 유물 id.
|
|
- `ShopRelicBought`(boolean).
|
|
|
|
### 훅 시스템
|
|
- `ApplyRelics(hook)`: RunRelics 순회, `hook` 일치 유물의 effect 적용:
|
|
- `block`→PlayerBlock+=value, `energy`→Energy+=value, `healOnAttack`→PlayerHp+=value(상한 클램프), `gold`→Gold+=value.
|
|
- 연결 지점:
|
|
- `combatStart` → StartCombat 끝(StartPlayerTurn 호출 뒤 — 방어도 리셋 이후 적용 → RenderCombat).
|
|
- `turnStart` → StartPlayerTurn(에너지 회복 직후).
|
|
- `cardPlayed` → PlayCard의 Attack 분기(데미지 적용 후).
|
|
- `combatReward` → CheckCombatEnd 승리(기본 골드 += 후).
|
|
|
|
### 획득 (공통 `AddRelic(id)` → RunRelics 추가·RenderRelics)
|
|
- **C 시작**: `StartRun`에서 `RunRelics={}` → `AddRelic(startingRelic)`.
|
|
- **A 엘리트**: `CheckCombatEnd` 승리 시 노드 `type=="elite"`면 `relicPool`에서 무작위 `AddRelic`(보스는 런 종료라 제외).
|
|
- **B 상점**: `ShowShop`에서 `ShopRelic = relicPool 무작위`, ShopRelicBought=false; `BuyRelic`(ShopRelicBought거나 Gold<RELIC_PRICE면 무시; 아니면 Gold-=60·AddRelic·비활성).
|
|
|
|
### UI
|
|
- 상단 유물 바: `/ui/DefaultGroup/CombatHud/Relics` 텍스트, `RenderRelics`가 보유 유물 이름을 ", "로 join해 "유물: …" 표시(없으면 "유물: 없음").
|
|
- ShopHud에 유물 슬롯: `/ui/DefaultGroup/ShopHud/Relic`(sprite+button) + Name/Desc/Price 자식. `RenderShop`이 ShopRelic 비주얼·가격·구매상태 갱신.
|
|
- 엘리트 유물 획득은 유물 바 갱신으로 표시.
|
|
|
|
### 단일 소스
|
|
모든 변경은 `tools/gen-slaydeck.mjs`에서 생성. relics.json은 데이터 단일 소스.
|
|
|
|
## 검증 (메이커 Play)
|
|
- 시작 유물(강철심장) → 전투 시작 시 PlayerBlock 6.
|
|
- energyCore 보유 → 턴 시작 에너지 4(3+1).
|
|
- vampire 보유 → 공격 카드 사용 시 HP +1(상한).
|
|
- goldIdol 보유 → 승리 시 골드 +25(15+10).
|
|
- 엘리트 승리 → relicPool 유물 1개 RunRelics 추가(바 갱신).
|
|
- 상점 유물 구매 → 골드 -60·RunRelics 추가·슬롯 비활성. 골드 부족/재구매 무시.
|
|
- 생성기 결정적·JSON 유효.
|
|
- (버튼은 런타임 — MCP는 AddRelic/BuyRelic/PlayCard 등 직접 호출 + 상태 로그로 검증.)
|
|
|
|
## 범위 밖 (금지)
|
|
- 부정적 유물·복합/조건부 효과·유물 제거·보스 유물·유물 등급/툴팁. 카드 제거(별도).
|