# P6 — 버프/디버프·Power 카드·적 방어도 UI 설계 날짜: 2026-06-12 브랜치: `feature/p6-buffs-power` 근거: 덱빌딩 코어 확장 — Slay the Spire 2의 약화·취약·힘 시스템과 Power 카드 종류를 메이플 IP로 이식. 적 방어도 미표시 문제 해결. ## 범위 1. **버프/디버프 3종** — 약화(Weak)·취약(Vulnerable)·힘(Strength), StS 표준 수치 2. **Power 카드 kind** — 전투 동안 지속되는 효과, 사용 시 소멸(전투 한정) 3. **적 방어도 UI** — 적 슬롯에 플레이어와 동일한 방어도 배지 표시 4. **예시 카드 4종** — 메이플 스킬명, StS 카드 효과 매핑 5. **적 디버프 인텐트** — 일부 적이 플레이어에게 약화/취약 부여 (양방향 시스템) 비범위: 물약·유물 강화(P7), 카드 강화(업그레이드), 민첩(Dexterity). ## 규칙 (StS 표준) | 상태 | 효과 | 지속 | |------|------|------| | 힘(Strength) | 공격 피해 +N | 전투 동안 영구 | | 약화(Weak) | 주는 공격 피해 25% 감소 (floor) | N턴, 자기 턴 종료 시 1 감소 | | 취약(Vulnerable) | 받는 공격 피해 50% 증가 (floor) | N턴, 자기 턴 종료 시 1 감소 | 피해 공식 (플레이어 공격): `floor( floor((base + 힘) × (약화 ? 0.75 : 1)) × (대상 취약 ? 1.5 : 1) )` 피해 공식 (적 공격): 동일 공식을 적 힘·적 약화·플레이어 취약으로 적용. 감소 타이밍: - 플레이어 약화/취약 → `EndPlayerTurn`에서 1 감소 - 적 약화/취약 → 적 개별 행동(`EnemyActStep`) 종료 시 1 감소 ## 상태 모델 - 플레이어: `PlayerStr` / `PlayerWeak` / `PlayerVuln` (number props), `PlayerPowers` (any) - 몬스터: `m.str` / `m.weak` / `m.vuln` (BuildMonsters에서 0 초기화) - 전투 시작(`StartCombat`) 시 전부 리셋 ## 카드 데이터 스키마 확장 (`data/cards.json`) | 필드 | 의미 | |------|------| | `kind: "Power"` | 파워 카드 — 사용 시 소멸, 전투 동안 지속 효과 | | `weak: N` | 대상 적에게 약화 N 부여 | | `vuln: N` | 대상 적에게 취약 N 부여 | | `strength: N` | 자신에게 힘 +N | | `powerEffect: "strengthPerTurn"`, `value: N` | 파워: 매 턴 시작 시 힘 +N | `luaCardsTable`이 신규 필드를 직렬화하도록 확장. ## 예시 카드 4종 (메이플 스킬명 × StS 효과) | id | 이름 | kind | 코스트 | 효과 | StS 원본 | |----|------|------|--------|------|----------| | ChargedBlow | 차지 블로우 | Attack | 2 | 피해 8, 취약 2 | Bash | | Threaten | 위협 | Skill | 0 | 타겟 적에게 약화 2 | Intimidate 계열 | | Enrage | 인레이지 | Skill | 1 | 힘 +2 | Inflame | | Rage | 분노 | Power | 1 | 매 턴 시작 시 힘 +1 | Demon Form(경량) | - 보상 풀은 `self.Cards` 전체 자동 편입이므로 추가 작업 없음. 시작 덱 변경 없음. - 카드 이미지는 MSW 공식 리소스 RUID를 검색·선별해 사용 (계정 업로드 리소스는 로컬 워크스페이스에서 흰 박스 — 금지). - 타겟팅: Attack은 기존 드래그 타겟, 디버프 Skill(위협)은 현재 `TargetIndex` 적에게 적용 (적 클릭으로 타겟 변경 가능). ## Power 카드 동작 - `PlayCard`에서 `kind == "Power"` 분기: `powerEffect` 등록(`PlayerPowers`에 push) 후 **버린 덱에 넣지 않고 소멸** (RunDeck에는 유지 — 다음 전투에서 다시 사용 가능) - `StartPlayerTurn`: `PlayerPowers` 순회, `strengthPerTurn`이면 `PlayerStr += value` - 카드 면 색: 기존 `ApplyCardFace`의 else 분기(초록)가 Power에 적용됨 — 명시적으로 `elseif c.kind == "Power"` 초록 지정 ## 적 디버프 인텐트 (`data/enemies.json`) 인텐트 스키마 확장: `{ "kind": "Debuff", "effect": "weak"|"vuln", "value": N }` | 적 | 추가 인텐트 | |----|------------| | mushmom (머쉬맘) | 포자 — 약화 2 | | slime_elite (정예 슬라임) | 약화 1 | | slime_boss (슬라임 킹) | 취약 2 | | king_slime (킹 슬라임) | 취약 2 | | modified_snail (변형된 달팽이) | 약화 1 | `EnemyActStep`에서 `kind == "Debuff"` 처리: `PlayerWeak/PlayerVuln += value`. ## UI 변경 (`gen-slaydeck.mjs` UI 생성부) 1. **적 방어도 배지**: 각 `MonsterSlot{i}`에 `BlockBadge`(파란 사각 44×40, HP바 좌측 x=-HP_BAR_W/2-32, y=-14) + `BlockBadge/Value` 텍스트. `RenderCombat`에서 `m.block > 0`일 때만 표시 — 플레이어 배지와 동일 패턴. 2. **적 버프 라인**: `MonsterSlot{i}/Buffs` 텍스트 (Intent 아래 y=-58, fontSize 15, 보라). 예: `힘+2 약화1 취약2`. 없으면 빈 문자열. 3. **플레이어 버프 라인**: `PlayerPanel/Buffs` 텍스트 (y=-44, fontSize 14). 파워 활성 시 `분노` 포함. 예: `힘+3 취약1 · 분노`. 4. **인텐트 표시 확장**: `Debuff` 인텐트 → `약화 2 부여` / `취약 2 부여`, 보라색. Attack 인텐트 숫자는 힘·약화·플레이어 취약 반영한 **최종 예상치** 표시 (StS 동일). ## 밸런스 시뮬 동기화 (`tools/balance/sim-balance.mjs`) - 카드: `strength`/`weak`/`vuln`/Power 처리 재현 (chooseAction은 Attack 우선 휴리스틱 유지, Power/버프 스킬은 에너지 남을 때 사용하는 단순 규칙 추가) - 적: `Debuff` 인텐트 재현 (플레이어 weak/vuln) - 피해 공식 양방향 동일 적용, 감소 타이밍 동일 - 기존 테스트(`sim-balance.test.mjs`) 통과 + 신규 케이스(약화/취약/힘 계산 단위 테스트) 추가 ## 검증 1. `node tools/deck/gen-slaydeck.mjs` 성공 (산출물 재생성: SlayDeckController.codeblock·DefaultGroup.ui·common.gamelogic) 2. `node --test tools/balance/sim-balance.test.mjs` 통과 3. `node tools/balance/sim-balance.mjs` 실행 — 승률이 0%/100% 극단으로 붕괴하지 않는지 확인 ## 결정 사항 - 민첩(Dexterity)은 도입하지 않음 (방어 카드 수가 적어 효용 낮음 — YAGNI) - 기존 카드(슬래시 블러스트 등) 수치 변경 없음 — 신규 카드로만 확장 - Power는 1종으로 시작, 물약/유물(P7)과의 연계는 P7에서