Malaise(불쾌, xWeakPerEnergy)·Skewer(꼬챙이, xDamagePerEnergy) 같은
useAllEnergy 카드는 X 효과가 소비 에너지에 비례하는데, Lua는 코스트
감소(스킬코스트감소·다음스킬무료·전투코스트감소)를 useAllEnergy에도
적용해 소비 에너지가 full보다 줄고 X도 약해졌다(코스트감소가 카드를
약화시키는 역설). JS는 스킬코스트감소만 건너뛰고 combatReduction은
적용해 양쪽이 미묘하게 달랐다.
정답: useAllEnergy는 "전 에너지 소비"이므로 어떤 코스트감소도 무시.
Lua는 3개 감소 조건에 useAllEnergy 제외 추가, JS는 finalCost를
useAllEnergy면 combatReduction 미적용으로. 양쪽 모두 full 에너지 소비로
일치. 산출물 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj
DealDamageToAllMonsters는 AoE 공격(취약 1.5x·attackPoison 적용)과
Outbreak 독 버스트(평면 피해) 두 용도로 공유되는데, 취약을 항상
적용해 버스트가 취약 대상에 과다 피해를 줬다(JS 미러는 버스트를
평면 applyDamage로 처리 — Lua만 발산). 또한 직전 커밋에서 추가한
attackPoison도 버스트에 적용돼, Envenom+Outbreak 동시 활성 시
버스트→attackPoison→독 적용→또 버스트의 재귀 위험이 있었다.
isAttack 매개변수를 추가해 취약·attackPoison을 공격일 때만 적용:
AoE 공격(ResolveCardEffects)은 true, 버스트는 미전달(평면). JS의
dealToTarget(취약+attackPoison) vs 버스트(평면) 분리와 일치.
산출물 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj
Lua는 Prepared(예비)에서 AddCardBlock으로 실제 방어를 부여하는데, JS
시뮬은 blockGained(통계 카운터)만 증가시키고 addBlock을 호출하지 않아
플레이어가 실제 방어를 못 받았다(시뮬이 방어를 과소집계).
JS도 다른 블록 출처처럼 addBlock 경유로 변경(Lua 동기화). 또한
Prepared 데이터는 discard:1 + blockPerDamageDealtThisTurn뿐(draw 없음)
인데 설명이 "1장 뽑고 1장 버립니다"로 부정확해, 실제 동작(1장 버리고
이번 턴 피해만큼 방어)에 맞게 보강. RED-GREEN 테스트 추가. 88개.
산출물 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj
Envenom(독 바르기: 공격이 막히지 않은 피해를 줄 때마다 중독 1)이
단일타겟(DealDamageToTarget)에는 적용됐지만 광역(DealDamageToAllMonsters)
에는 빠져 있어, Envenom+광역공격이 게임에선 아무 적도 중독 안 됐다
(JS 미러는 양쪽 적용 — Lua가 누락).
DealDamageToAllMonsters의 막히지 않은 피해(dmg>0) 분기에 단일타겟과
동일한 attackPoison 적용을 추가(적별 ApplyPoisonToMonster). JS 미러는
이미 올바라 무변경. 산출물 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj
StartRun이 run마다 BindButtons를 호출하는데 앞 7개 핸들러만
disconnect 가드돼 있고 reward/skip/map/shop/monster/relic/potion/job
등 ~30개 ConnectEvent는 미가드라, 2회차+ 런에서 핸들러가 누적된다.
특히 PickReward는 RewardChoices·CombatOver를 클리어하지 않아 중복
핸들러로 두 번 불리면 같은 보상 카드가 RunDeck에 2번 추가된다.
BindLobbyButtons/BindSoulShopButtons와 동일하게 self.ButtonsBound
1회 가드를 추가(런 UI 엔티티는 영속이라 1회 바인드로 충분).
신규 prop ButtonsBound 선언. 산출물 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj
`DiscardPostDraw`·`DiscardDrawPerPick`가 hand.mjs(BeginDiscardSelection·
AutoDiscardHand·FinishDiscardSelection·SelectDiscardSlot)에서 대입되는데
gen-slaydeck.mjs prop 목록에 선언되지 않아 런타임 "cannot set DiscardPostDraw,
no such field"로 BeginDiscardSelection이 중단됨. 그 직전 DiscardSelectRemaining/
Total이 이미 set되어 게임이 버리기-선택 모드에 갇혀, 이후 모든 카드(공중제비 포함)
클릭이 버리기 픽으로 처리됨("2장 버린다 표시 + 동작 없음").
근본 원인: 형제 prop DiscardPostShiv·DiscardShivPerPick는 선언됐으나
draw 변형 2개가 누락. 선언만 추가(병렬 패턴).
신규 가드 tools/verify/cbprops.mjs: cb의 `self.X =` 대입 ↔ 선언 prop 대조,
미선언 = no such field 후보 검출. 수정 전 2개 누락→후 0.
검증: cbprops 0·cbgap GAP 0·테스트 93/93. 산출물(codeblock) 재생성 포함.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OnBeginPlay에서 UI 로드 후 self:ShowMainMenu() 대신 self:ShowLobby() 호출.
게임 시작하면 MainMenu를 거치지 않고 곧장 로비 맵(LobbyUIGroup)으로 진입한다.
ShowState("lobby")가 MainMenu를 숨기므로 메뉴는 표시되지 않음.
MainMenu는 한동안 비활성이지만 ShowMainMenu 메서드·BindMenuButtons·
DefaultGroup/MainMenu UI는 그대로 유지 — 추후 싱글/멀티/게임 종료 선택
메뉴가 필요할 때 OnBeginPlay를 self:ShowMainMenu()로 되돌리면 복구된다.
산출물 재생성: SlayDeckController.codeblock. 검증: cbgap GAP 0, JS 41/41.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
메이커 저작(964cf7c)에서 map01에 수작업 배치한 몬스터
octopus·kapa_drake·junior_neki·junior_bugi(combat) / dile·mano(elite)의
EnemyId가 enemies.json에 미등록 상태였다. 전투 시 BuildMonsters가
self.Enemies[id]=nil → fallback {maxHp=10, intents={{Attack,5}}}(단일 intent)
으로 떨어져, EnemyActStep의 math.random(1,#intents)가 random(1,1)이 되어
항상 "공격 5"만 반복 → 행동 랜덤화 불가·이름 raw id·HP 10 고정.
수정: 6종을 기존 티어 밸런스(combat HP15~24/elite HP65~80, 다중 intent)에
맞춰 enemies.json에 등록하고 SlayDeckController.codeblock 재생성(산출물).
맵은 이미 해당 id를 참조하므로 맵 재생성 불필요(수작업 배치 유지).
검증: 전 맵 EnemyId 매핑 OK 33/MISSING 0, JS 미러 테스트 41/41.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
메이커에서 단일 DefaultGroup UI를 6개 UIGroup으로 재편:
- DefaultGroup(MainMenu+월드조작), SelectUIGroup(charselect/job),
LobbyUIGroup(lobby/board/soulshop), RunUIGroup(combat/map/shop 등),
DeckUIGroup(덱 도감) + PopupGroup/ToastGroup(기존)
- 신규 에셋: UIButton.model, 배경 스프라이트 4종, MapleTree.codeblock 등
- 몬스터 전투 슬롯 MonsterSlot{1..5} → MonsterStatus{1..4}, TargetFrame 제거
컨트롤러 재연결은 후속 커밋. (.gitignore: docs/superpowers·Mislocated 무시)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>