# 유물 (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