Files
maplecontest/docs/superpowers/plans/2026-06-12-job-advancement.md

6.2 KiB
Raw Blame History

P9 — 전직 시스템 코어 + 전사 2차 구현 계획

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 카드 클래스 모델·전직 선택 흐름·전사 2차 3직업(전용 카드 9종 + 신규 메커니즘 4종).

Architecture: cards.json class/hits/pierce/selfVuln 스키마 확장 → gen-slaydeck.mjs (직렬화·CardPool 필터·전투 메커니즘·JobChoiceHud/JobSelectHud·ContinueAfterBoss 추출) → sim-balance 동기화. RULES.md 하네스 준수 (산출물 검증은 grep -c).

설계: docs/superpowers/specs/2026-06-12-job-advancement-design.md (승인 완료)


Task 1: 카드 이미지 RUID 9종 선별 (메이커)

  • Step 1: asset_search(source=maplestory, sprite) 쿼리 — "콤보", "버서크", "라이징", "썬더", "블리자드", "파워 가드", "창", "철벽", "하이퍼" (빈약 시 보조 쿼리)
  • Step 2: SkillFx 복제 격자 미리보기 → 9종 확정 → 정리·종료 (기존 절차)

Task 2: 데이터 — cards.json 확장

  • Step 1: 기존 카드 9종 전부에 "class": "warrior" 추가
  • Step 2: 신규 9종 추가 (설계 표 그대로, image=Task 1 선별값):
"ComboAttack":    { "name": "콤보 어택",     "cost": 1, "kind": "Attack", "class": "fighter",  "damage": 5, "hits": 2, "desc": "피해 5 × 2회", "image": "<RUID>" },
"Berserk":        { "name": "버서크",        "cost": 2, "kind": "Power",  "class": "fighter",  "powerEffect": "energyPerTurn", "value": 1, "selfVuln": 1, "desc": "매턴 에너지 +1, 취약 1 자가", "image": "<RUID>" },
"RisingAttack":   { "name": "라이징 어택",   "cost": 2, "kind": "Attack", "class": "fighter",  "damage": 12, "desc": "피해 12", "image": "<RUID>" },
"ThunderCharge":  { "name": "썬더 차지",     "cost": 1, "kind": "Attack", "class": "page",     "damage": 7, "weak": 1, "desc": "피해 7, 약화 1", "image": "<RUID>" },
"BlizzardCharge": { "name": "블리자드 차지", "cost": 1, "kind": "Attack", "class": "page",     "damage": 7, "vuln": 1, "desc": "피해 7, 취약 1", "image": "<RUID>" },
"PowerGuard":     { "name": "파워 가드",     "cost": 1, "kind": "Skill",  "class": "page",     "block": 10, "desc": "방어도 10", "image": "<RUID>" },
"Pierce":         { "name": "피어스",        "cost": 1, "kind": "Attack", "class": "spearman", "damage": 9, "pierce": true, "desc": "피해 9, 방어 무시", "image": "<RUID>" },
"IronWall":       { "name": "아이언 월",     "cost": 2, "kind": "Skill",  "class": "spearman", "block": 12, "desc": "방어도 12", "image": "<RUID>" },
"HyperBody":      { "name": "하이퍼 바디",   "cost": 1, "kind": "Power",  "class": "spearman", "powerEffect": "blockPerTurn", "value": 3, "desc": "매턴 방어도 +3", "image": "<RUID>" }
  • Step 3: 커밋 feat(job): 전사 2차 카드 9종·클래스 필드 데이터

Task 3: 생성기 — 직렬화·전투 메커니즘

Files: Modify tools/deck/gen-slaydeck.mjs

  • Step 1: luaCardsTable에 class(필수 — 누락 시 throw)·hits·pierce·selfVuln 직렬화
  • Step 2: prop PlayerJob(string "") 추가, StartRun에 self.PlayerJob = "" 리셋
  • Step 3: PlayCard Attack 분기 — 다단히트·pierce·selfVuln:
if c.kind == "Attack" then
	if c.damage ~= nil then
		local total = 0
		local n = c.hits or 1
		for h = 1, n do
			total = total + self:CalcPlayerAttack(c.damage)
		end
		self:PlayAttackFx(self.TargetIndex, c.image, total, c.pierce == true)
	end
	...
end
-- 공통부 (버프 적용 옆): if c.selfVuln ~= nil then self.PlayerVuln = self.PlayerVuln + c.selfVuln end
  • Step 4: PlayAttackFx(targetIndex, image, damage, pierce) / DealDamageToTarget(amount, pierce) 시그니처 확장 — pierce면 block 차감 생략. 기존 호출부(물약 화염병 포함) false 전달
  • Step 5: StartPlayerTurn 파워 루프 확장 — energyPerTurn→Energy, blockPerTurn→PlayerBlock (ClayBlockNext 처리 뒤)
  • Step 6: 커밋 feat(job): 다단히트·방어무시·자가취약·파워 2종 (생성기)

Task 4: 생성기 — 풀 필터·전직 흐름·UI

  • Step 1: CardPool() 헬퍼 (정렬된 id 배열 반환 — class 필터), OfferReward·ShowShop이 사용
  • Step 2: CheckCombatEnd 보스 분기 → ContinueAfterBoss() 추출. 분기: PlayerJob == "" and Floor < RunLengthShowJobChoice(), else 유물+ContinueAfterBoss()
  • Step 3: ShowJobChoice/PickJobReward(kind) (relic→유물+Continue / job→ShowJobSelect), ShowJobSelect/SetJob(jobId) (PlayerJob·대표 카드 지급·토스트·Continue), JobLabel() 헬퍼 (전사/파이터/페이지/스피어맨)
  • Step 4: UI — guid 'job'=0xe4: JobChoiceHud(타이틀+버튼 2)·JobSelectHud(3패널: 직업명·설명·대표 카드명). HideGameHud·BindButtons 등록
  • Step 5: PlayerPanel/Name 갱신 — StartCombat·SetJob에서 JobLabel()
  • Step 6: 커밋 feat(job): 클래스 풀 필터·전직 선택 흐름·전직 HUD (생성기)

Task 5: 시뮬 동기화 (TDD)

  • Step 1: 실패 테스트 — hits 합산(힘 타격마다)·pierce(블록 무시)·selfVuln·energyPerTurn·blockPerTurn 5건
  • Step 2: sim-balance.mjs 재현 → 전체 PASS (기존 21+5, rogue-map 9)
  • Step 3: 커밋 feat(job): 시뮬 신규 메커니즘 동기화

Task 6: 재생성·메이커 검증·PR

  • Step 1: 재생성 + grep -c "PlayerJob\|JobChoiceHud" 산출물 카운트 확인 + 전체 테스트
  • Step 2: 메이커 refresh→빌드 0에러→플레이테스트: 보스 클리어→선택 화면→전직(파이터)→전용 카드 풀 편입·직업명 표기·콤보/피어스 동작 스크린샷
  • Step 3: 커밋·푸시 → gitea-pr.mjs로 PR(UTF-8 spec)·머지 → main pull

Self-Review

  • 설계 전 항목 매핑 ✓ (클래스 모델 T2/T4, 전직 흐름 T4, 카드 9종 T1/T2, 메커니즘 T3/T5, 표기 T4)
  • 시그니처 일관성: PlayAttackFx/DealDamageToTarget pierce 전 호출부 갱신 명시 ✓
  • 하네스: 산출물 검증 카운트만 ✓