Merge pull request 'fix: map01 신규 몬스터 6종 등록 — 랜덤 행동 복구' (#76) from fix/map01-monster-roster into main

This commit was merged in pull request #76.
This commit is contained in:
2026-06-18 01:44:10 +09:00
11 changed files with 473 additions and 412 deletions

View File

@@ -157,6 +157,17 @@ c:AdjustAscension(1) -- 메뉴에서 승천 단계 +1
밸런스 검증: `node tools/balance/sim-balance.mjs [N] [--seed S]` · 테스트: `node --test tools/balance/sim-balance.test.mjs tools/map/rogue-map.test.mjs`.
상세 설계는 [`docs/slaymaple_basic_framework.md`](docs/slaymaple_basic_framework.md) 및 `docs/superpowers/specs/` 참조.
### 디버그 단축키
개발·QA용 키보드 단축키. **전투 중**(런 활성 + 전투 진행 중)에만 동작합니다.
| 단축키 | 기능 |
|---|---|
| **Ctrl + Shift + C** | **카드 picker** — 직업 전체 카드 패널을 띄우고, 카드를 클릭하면 **즉시 손패에 추가**. 상단 탭(전사/도적/마법사)으로 직업별 카드 풀 전환. 카드 효과·메커니즘 즉석 테스트용 |
| **Ctrl + Shift + E** | **에너지 치트** — 현재 에너지를 최대치로 회복 |
> 카드 picker는 메이커 저작 UI `DeckUIGroup/DeckAllHud`(120 슬롯 그리드 + 직업 탭 3종)를 사용하고, 컨트롤러가 런타임에 카드 비주얼·버튼을 바인딩합니다. 구현: 키 바인딩 `tools/deck/cb/boot.mjs`, picker 로직 `tools/deck/cb/deckview.mjs`(`OpenDebugCardPicker`/`OnAllDeckCardButton`), 버튼 바인딩 `tools/deck/cb/deckturn.mjs`(`BindButtons`). 옛 picker UI 생성기 `tools/deck/legacy/hud/deckall.mjs`는 UI 메이커-저작 전환 후 **휴면**(Maker UI가 대체).
### 산출물 재생성
```bash
node tools/deck/gen-slaydeck.mjs # 컨트롤러+common (UI는 메이커 저작 — 미생성)

File diff suppressed because one or more lines are too long

View File

@@ -119,6 +119,65 @@
{ "kind": "Attack", "value": 12 },
{ "kind": "Attack", "value": 24 }
]
},
"octopus": {
"name": "문어",
"maxHp": 15,
"intents": [
{ "kind": "Attack", "value": 5 },
{ "kind": "Attack", "value": 6 },
{ "kind": "Defend", "value": 4 }
]
},
"kapa_drake": {
"name": "카파 드레이크",
"maxHp": 24,
"intents": [
{ "kind": "Attack", "value": 9 },
{ "kind": "Attack", "value": 6 },
{ "kind": "Defend", "value": 6 },
{ "kind": "Attack", "value": 11 }
]
},
"junior_neki": {
"name": "주니어 네키",
"maxHp": 18,
"intents": [
{ "kind": "Attack", "value": 6 },
{ "kind": "Attack", "value": 8 },
{ "kind": "Debuff", "effect": "weak", "value": 1 }
]
},
"junior_bugi": {
"name": "주니어 부기",
"maxHp": 20,
"intents": [
{ "kind": "Attack", "value": 7 },
{ "kind": "Defend", "value": 5 },
{ "kind": "Attack", "value": 9 }
]
},
"dile": {
"name": "다일",
"maxHp": 65,
"intents": [
{ "kind": "Attack", "value": 13 },
{ "kind": "Defend", "value": 9 },
{ "kind": "Attack", "value": 8 },
{ "kind": "Attack", "value": 16 },
{ "kind": "Debuff", "effect": "weak", "value": 1 }
]
},
"mano": {
"name": "마노",
"maxHp": 80,
"intents": [
{ "kind": "Defend", "value": 12 },
{ "kind": "Attack", "value": 14 },
{ "kind": "Debuff", "effect": "vuln", "value": 1 },
{ "kind": "Attack", "value": 10 },
{ "kind": "AddCard", "card": "Wound", "count": 1 }
]
}
},
"activeEnemy": "slime",

View File

@@ -70,6 +70,9 @@ self:BindClassDeckTabs()
for i = 1, 120 do
local allCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
if allCard ~= nil and (allCard.ButtonComponent ~= nil or allCard:AddComponent("ButtonComponent") ~= nil) then
if allCard.SpriteGUIRendererComponent ~= nil then
allCard.SpriteGUIRendererComponent.RaycastTarget = true
end
local slot = i
allCard:ConnectEvent(ButtonClickEvent, function() self:OnAllDeckCardButton(slot) end)
end

View File

@@ -42,23 +42,18 @@ if count > 60 then
suffix = suffix .. " - 60장까지 표시"
end
self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix)
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Empty")
if empty ~= nil then
empty.Enable = count <= 0
end
self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud/Empty", count <= 0)
for i = 1, 60 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i))
if e ~= nil then
local cardId = nil
if pile ~= nil then
cardId = pile[i]
end
if cardId == nil then
e.Enable = false
else
e.Enable = true
self:ApplyInspectCardVisual(i, cardId)
end
local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)
local cardId = nil
if pile ~= nil then
cardId = pile[i]
end
if cardId == nil then
self:SetEntityEnabled(path, false)
else
self:SetEntityEnabled(path, true)
self:ApplyInspectCardVisual(i, cardId)
end
end`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
@@ -171,15 +166,13 @@ self:RenderClassDeckTabs()`, [{ Type: 'string', DefaultValue: null, SyncDirectio
{ path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" },
}
for i = 1, #tabs do
self:SetEntityEnabled(tabs[i].path, self.ClassDeckMode == true)
local e = _EntityService:GetEntityByPath(tabs[i].path)
if e ~= nil then
e.Enable = self.ClassDeckMode == true
if e.SpriteGUIRendererComponent ~= nil then
if self.ClassDeckClass == tabs[i].cls then
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
else
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
end
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
if self.ClassDeckClass == tabs[i].cls then
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
else
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
end
end
end`),
@@ -230,20 +223,15 @@ end
local count = #pile
self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")")
self:RenderClassDeckTabs()
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Empty")
if empty ~= nil then
empty.Enable = count <= 0
end
self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud/Empty", count <= 0)
for i = 1, 120 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
if e ~= nil then
local cardId = pile[i]
if cardId == nil then
e.Enable = false
else
e.Enable = true
self:ApplyAllDeckCardVisual(i, cardId)
end
local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)
local cardId = pile[i]
if cardId == nil then
self:SetEntityEnabled(path, false)
else
self:SetEntityEnabled(path, true)
self:ApplyAllDeckCardVisual(i, cardId)
end
end`),
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 5,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 5,
"GroupOrder": 1,
"GroupType": 2,
"Enable": true
},

View File

@@ -97,7 +97,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 1,
"GroupOrder": 2,
"GroupType": 1,
"Enable": true
},

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 6,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 6,
"GroupOrder": 5,
"GroupType": 2,
"Enable": true
},

View File

@@ -23,7 +23,7 @@
"nameEditable": true,
"enable": true,
"visible": true,
"localize": false,
"localize": true,
"displayOrder": 3,
"pathConstraints": "//",
"revision": 1,
@@ -86,7 +86,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 3,
"GroupOrder": 4,
"GroupType": 2,
"Enable": true
},

View File

@@ -97,7 +97,7 @@
{
"@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false,
"GroupOrder": 2,
"GroupOrder": 3,
"GroupType": 1,
"Enable": true
},