Files
maplecontest/docs/superpowers/specs/2026-06-09-relics-design.md
gahusb 4c866f3cd9 docs(E5): 유물 설계·구현 계획
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 03:53:38 +09:00

3.8 KiB

유물 (TODO E5) — 설계

작성: 2026-06-09 / 상태: 승인됨 / 근거: TODO E 분해(E5) + 기존 전투/맵/상점 구조. 선행: E1~E4 완료. 후속: E6(저장/다음 층). 사용자 요청: 획득 3경로(시작·엘리트·상점) 모두.

문제

런 영속·맵·보상·상점은 됐으나 유물(패시브 빌드 요소)이 없다. 훅 기반 패시브 + 다양한 획득 경로가 필요하다.

설계

데이터 data/relics.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 등 직접 호출 + 상태 로그로 검증.)

범위 밖 (금지)

  • 부정적 유물·복합/조건부 효과·유물 제거·보스 유물·유물 등급/툴팁. 카드 제거(별도).