fix: map01 신규 몬스터 6종 등록 — 랜덤 행동 복구 #76

Merged
gahusb merged 3 commits from fix/map01-monster-roster into main 2026-06-18 01:44:12 +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`. 밸런스 검증: `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/` 참조. 상세 설계는 [`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 ```bash
node tools/deck/gen-slaydeck.mjs # 컨트롤러+common (UI는 메이커 저작 — 미생성) 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": 12 },
{ "kind": "Attack", "value": 24 } { "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", "activeEnemy": "slime",

View File

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

View File

@@ -42,23 +42,18 @@ if count > 60 then
suffix = suffix .. " - 60장까지 표시" suffix = suffix .. " - 60장까지 표시"
end end
self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix) self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix)
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Empty") self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud/Empty", count <= 0)
if empty ~= nil then
empty.Enable = count <= 0
end
for i = 1, 60 do for i = 1, 60 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)) local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)
if e ~= nil then local cardId = nil
local cardId = nil if pile ~= nil then
if pile ~= nil then cardId = pile[i]
cardId = pile[i] end
end if cardId == nil then
if cardId == nil then self:SetEntityEnabled(path, false)
e.Enable = false else
else self:SetEntityEnabled(path, true)
e.Enable = true self:ApplyInspectCardVisual(i, cardId)
self:ApplyInspectCardVisual(i, cardId)
end
end end
end`, [ end`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' }, { 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" }, { path = "/ui/DeckUIGroup/DeckAllHud/MageTab", cls = "magician" },
} }
for i = 1, #tabs do for i = 1, #tabs do
self:SetEntityEnabled(tabs[i].path, self.ClassDeckMode == true)
local e = _EntityService:GetEntityByPath(tabs[i].path) local e = _EntityService:GetEntityByPath(tabs[i].path)
if e ~= nil then if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
e.Enable = self.ClassDeckMode == true if self.ClassDeckClass == tabs[i].cls then
if e.SpriteGUIRendererComponent ~= nil then e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1)
if self.ClassDeckClass == tabs[i].cls then else
e.SpriteGUIRendererComponent.Color = Color(0.22, 0.28, 0.34, 1) e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
else
e.SpriteGUIRendererComponent.Color = Color(0.11, 0.13, 0.16, 1)
end
end end
end end
end`), end`),
@@ -230,20 +223,15 @@ end
local count = #pile local count = #pile
self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")") self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count) .. ")")
self:RenderClassDeckTabs() self:RenderClassDeckTabs()
local empty = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Empty") self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud/Empty", count <= 0)
if empty ~= nil then
empty.Enable = count <= 0
end
for i = 1, 120 do for i = 1, 120 do
local e = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)) local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)
if e ~= nil then local cardId = pile[i]
local cardId = pile[i] if cardId == nil then
if cardId == nil then self:SetEntityEnabled(path, false)
e.Enable = false else
else self:SetEntityEnabled(path, true)
e.Enable = true self:ApplyAllDeckCardVisual(i, cardId)
self:ApplyAllDeckCardVisual(i, cardId)
end
end end
end`), end`),
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [ 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, "nameEditable": true,
"enable": true, "enable": true,
"visible": true, "visible": true,
"localize": false, "localize": true,
"displayOrder": 5, "displayOrder": 5,
"pathConstraints": "//", "pathConstraints": "//",
"revision": 1, "revision": 1,
@@ -86,7 +86,7 @@
{ {
"@type": "MOD.Core.UIGroupComponent", "@type": "MOD.Core.UIGroupComponent",
"DefaultShow": false, "DefaultShow": false,
"GroupOrder": 5, "GroupOrder": 1,
"GroupType": 2, "GroupType": 2,
"Enable": true "Enable": true
}, },

View File

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

View File

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

View File

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

View File

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