From 04002919393f32593cc46eedaef3c35ab47a845e Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 9 Jun 2026 03:35:05 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(E4):=20=EC=83=81=EC=A0=90/=ED=9C=B4?= =?UTF-8?q?=EC=8B=9D=20=EB=85=B8=EB=93=9C=20=E2=80=94=20=EA=B3=A8=EB=93=9C?= =?UTF-8?q?=20=EC=86=8C=EB=B9=84=C2=B7HP=20=ED=9A=8C=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 맵에 상점/휴식 노드 추가, 진입 시 전투 대신 상호작용 UI로 분기. - data/map.json: 4행 맵에 rest(휴식)·shop(상점) 노드 추가(enemy 없음) - 생성기: enemy 선택적 검증/직렬화, MapHud 노드 y 행수 비례 중앙정렬, TYPE_KO에 상점/휴식 - PickNode 타입 분기: shop→ShowShop, rest→ShowRest, 그 외→StartCombat - 상점: ShowShop(카드3 무작위)·RenderShop·BuyCard(골드-30·RunDeck+1·재구매/부족 가드) - 휴식: ShowRest(HP+30 상한 클램프) - LeaveNode(상점/휴식 공용 나가기→ShowMap) - UI: ShopHud(카드3·가격·골드·나가기)·RestHud(회복 정보·나가기), 상수 CARD_PRICE=30·REST_HEAL=30 - 메이커 Play 검증: 상점 구매(부족/재구매 무시 포함)·휴식 회복·맵 분기 정상 - 알려진 튜닝: 골드/승리 15 < 카드값 30 → 경제 밸런싱 필요(sim-balance 활용) - 범위 밖: 카드 제거(덱 보기 UI)·유물(E5)·저장(E6) Co-Authored-By: Claude Opus 4.8 (1M context) --- RootDesk/MyDesk/SlayDeckController.codeblock | 103 +- data/map.json | 11 +- tools/gen-slaydeck.mjs | 266 +- ui/DefaultGroup.ui | 4794 +++++++++++++++++- 4 files changed, 5110 insertions(+), 64 deletions(-) diff --git a/RootDesk/MyDesk/SlayDeckController.codeblock b/RootDesk/MyDesk/SlayDeckController.codeblock index a49215e..760555a 100644 --- a/RootDesk/MyDesk/SlayDeckController.codeblock +++ b/RootDesk/MyDesk/SlayDeckController.codeblock @@ -238,6 +238,20 @@ "SyncDirection": 0, "Attributes": [], "Name": "CurrentEnemyId" + }, + { + "Type": "any", + "DefaultValue": "nil", + "SyncDirection": 0, + "Attributes": [], + "Name": "ShopChoices" + }, + { + "Type": "any", + "DefaultValue": "nil", + "SyncDirection": 0, + "Attributes": [], + "Name": "ShopBought" } ], "Methods": [ @@ -265,7 +279,7 @@ "Name": null }, "Arguments": [], - "Code": "self.PlayerMaxHp = 80\nself.PlayerHp = self.PlayerMaxHp\nself.Gold = 0\nself.Floor = 0\nself.RunLength = 3\nself.RunDeck = { \"Strike\", \"Strike\", \"Strike\", \"Strike\", \"Strike\", \"Defend\", \"Defend\", \"Defend\", \"Defend\", \"Bash\" }\nself.RunActive = true\nself.Enemies = {\n\tslime = { name = \"슬라임\", maxHp = 45, intents = { { kind = \"Attack\", value = 10 }, { kind = \"Attack\", value = 6 }, { kind = \"Defend\", value = 8 } } },\n\tslime_elite = { name = \"정예 슬라임\", maxHp = 70, intents = { { kind = \"Attack\", value = 14 }, { kind = \"Attack\", value = 8 }, { kind = \"Defend\", value = 10 } } },\n\tslime_boss = { name = \"슬라임 킹\", maxHp = 120, intents = { { kind = \"Attack\", value = 18 }, { kind = \"Defend\", value = 12 }, { kind = \"Attack\", value = 10 }, { kind = \"Attack\", value = 22 } } },\n}\nself.MapNodes = {\n\tA = { type = \"combat\", enemy = \"slime\", row = 1, col = -1, next = { \"C\", \"D\" } },\n\tB = { type = \"combat\", enemy = \"slime\", row = 1, col = 1, next = { \"D\", \"E\" } },\n\tC = { type = \"elite\", enemy = \"slime_elite\", row = 2, col = -2, next = { \"BOSS\" } },\n\tD = { type = \"combat\", enemy = \"slime\", row = 2, col = 0, next = { \"BOSS\" } },\n\tE = { type = \"combat\", enemy = \"slime\", row = 2, col = 2, next = { \"BOSS\" } },\n\tBOSS = { type = \"boss\", enemy = \"slime_boss\", row = 3, col = 0, next = { } },\n}\nself.MapStart = { \"A\", \"B\" }\nself.CurrentNodeId = \"\"\nself.CurrentEnemyId = \"\"\nself:BindButtons()\nself:ShowMap()", + "Code": "self.PlayerMaxHp = 80\nself.PlayerHp = self.PlayerMaxHp\nself.Gold = 0\nself.Floor = 0\nself.RunLength = 4\nself.RunDeck = { \"Strike\", \"Strike\", \"Strike\", \"Strike\", \"Strike\", \"Defend\", \"Defend\", \"Defend\", \"Defend\", \"Bash\" }\nself.RunActive = true\nself.Enemies = {\n\tslime = { name = \"슬라임\", maxHp = 45, intents = { { kind = \"Attack\", value = 10 }, { kind = \"Attack\", value = 6 }, { kind = \"Defend\", value = 8 } } },\n\tslime_elite = { name = \"정예 슬라임\", maxHp = 70, intents = { { kind = \"Attack\", value = 14 }, { kind = \"Attack\", value = 8 }, { kind = \"Defend\", value = 10 } } },\n\tslime_boss = { name = \"슬라임 킹\", maxHp = 120, intents = { { kind = \"Attack\", value = 18 }, { kind = \"Defend\", value = 12 }, { kind = \"Attack\", value = 10 }, { kind = \"Attack\", value = 22 } } },\n}\nself.MapNodes = {\n\tA = { type = \"combat\", enemy = \"slime\", row = 1, col = -1, next = { \"C\", \"D\" } },\n\tB = { type = \"combat\", enemy = \"slime\", row = 1, col = 1, next = { \"C\", \"D\" } },\n\tC = { type = \"rest\", row = 2, col = -1, next = { \"E\", \"F\" } },\n\tD = { type = \"shop\", row = 2, col = 1, next = { \"E\", \"F\" } },\n\tE = { type = \"elite\", enemy = \"slime_elite\", row = 3, col = -1, next = { \"BOSS\" } },\n\tF = { type = \"combat\", enemy = \"slime\", row = 3, col = 1, next = { \"BOSS\" } },\n\tBOSS = { type = \"boss\", enemy = \"slime_boss\", row = 4, col = 0, next = { } },\n}\nself.MapStart = { \"A\", \"B\" }\nself.CurrentNodeId = \"\"\nself.CurrentEnemyId = \"\"\nself:BindButtons()\nself:ShowMap()", "Scope": 2, "ExecSpace": 6, "Attributes": [], @@ -318,7 +332,7 @@ "Name": null }, "Arguments": [], - "Code": "local endTurn = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckHud/EndTurnButton\")\nif endTurn ~= nil and endTurn.ButtonComponent ~= nil then\n\tif self.EndTurnHandler ~= nil then\n\t\tendTurn:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler)\n\t\tself.EndTurnHandler = nil\n\tend\n\tself.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() end)\nend\nfor i = 1, 5 do\n\tlocal cardEntity = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(i))\n\tif cardEntity ~= nil and cardEntity.ButtonComponent ~= nil then\n\t\tcardEntity:ConnectEvent(ButtonClickEvent, function() self:PlayCard(i) end)\n\tend\nend\nfor i = 1, 3 do\n\tlocal rc = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RewardHud/Reward\" .. tostring(i))\n\tif rc ~= nil and rc.ButtonComponent ~= nil then\n\t\trc:ConnectEvent(ButtonClickEvent, function() self:PickReward(i) end)\n\tend\nend\nlocal skip = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RewardHud/Skip\")\nif skip ~= nil and skip.ButtonComponent ~= nil then\n\tskip:ConnectEvent(ButtonClickEvent, function() self:PickReward(0) end)\nend\nlocal mapNodeIds = { \"A\", \"B\", \"C\", \"D\", \"E\", \"BOSS\" }\nfor i = 1, #mapNodeIds do\n\tlocal nid = mapNodeIds[i]\n\tlocal mn = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/MapHud/Node_\" .. nid)\n\tif mn ~= nil and mn.ButtonComponent ~= nil then\n\t\tmn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end)\n\tend\nend", + "Code": "local endTurn = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckHud/EndTurnButton\")\nif endTurn ~= nil and endTurn.ButtonComponent ~= nil then\n\tif self.EndTurnHandler ~= nil then\n\t\tendTurn:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler)\n\t\tself.EndTurnHandler = nil\n\tend\n\tself.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() end)\nend\nfor i = 1, 5 do\n\tlocal cardEntity = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(i))\n\tif cardEntity ~= nil and cardEntity.ButtonComponent ~= nil then\n\t\tcardEntity:ConnectEvent(ButtonClickEvent, function() self:PlayCard(i) end)\n\tend\nend\nfor i = 1, 3 do\n\tlocal rc = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RewardHud/Reward\" .. tostring(i))\n\tif rc ~= nil and rc.ButtonComponent ~= nil then\n\t\trc:ConnectEvent(ButtonClickEvent, function() self:PickReward(i) end)\n\tend\nend\nlocal skip = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RewardHud/Skip\")\nif skip ~= nil and skip.ButtonComponent ~= nil then\n\tskip:ConnectEvent(ButtonClickEvent, function() self:PickReward(0) end)\nend\nlocal mapNodeIds = { \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"BOSS\" }\nfor i = 1, #mapNodeIds do\n\tlocal nid = mapNodeIds[i]\n\tlocal mn = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/MapHud/Node_\" .. nid)\n\tif mn ~= nil and mn.ButtonComponent ~= nil then\n\t\tmn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end)\n\tend\nend\nfor i = 1, 3 do\n\tlocal sc = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud/Card\" .. tostring(i))\n\tif sc ~= nil and sc.ButtonComponent ~= nil then\n\t\tsc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end)\n\tend\nend\nlocal shopLeave = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud/Leave\")\nif shopLeave ~= nil and shopLeave.ButtonComponent ~= nil then\n\tshopLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)\nend\nlocal restLeave = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RestHud/Leave\")\nif restLeave ~= nil and restLeave.ButtonComponent ~= nil then\n\trestLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)\nend", "Scope": 2, "ExecSpace": 6, "Attributes": [], @@ -847,11 +861,94 @@ "Name": "id" } ], - "Code": "if self.RunActive ~= true then\n\treturn\nend\nif self:IsReachable(id) ~= true then\n\treturn\nend\nself.CurrentNodeId = id\nself.CurrentEnemyId = self.MapNodes[id].enemy\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/MapHud\")\nif hud ~= nil then\n\thud.Enable = false\nend\nself:StartCombat()", + "Code": "if self.RunActive ~= true then\n\treturn\nend\nif self:IsReachable(id) ~= true then\n\treturn\nend\nself.CurrentNodeId = id\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/MapHud\")\nif hud ~= nil then\n\thud.Enable = false\nend\nlocal node = self.MapNodes[id]\nif node.type == \"shop\" then\n\tself:ShowShop()\nelseif node.type == \"rest\" then\n\tself:ShowRest()\nelse\n\tself.CurrentEnemyId = node.enemy\n\tself:StartCombat()\nend", "Scope": 2, "ExecSpace": 6, "Attributes": [], "Name": "PickNode" + }, + { + "Return": { + "Type": "void", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": null + }, + "Arguments": [], + "Code": "local pool = {}\nfor cid, _ in pairs(self.Cards) do\n\ttable.insert(pool, cid)\nend\nself.ShopChoices = {}\nself.ShopBought = { false, false, false }\nfor i = 1, 3 do\n\tself.ShopChoices[i] = pool[math.random(1, #pool)]\nend\nself:RenderShop()\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud\")\nif hud ~= nil then\n\thud.Enable = true\nend", + "Scope": 2, + "ExecSpace": 6, + "Attributes": [], + "Name": "ShowShop" + }, + { + "Return": { + "Type": "void", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": null + }, + "Arguments": [], + "Code": "self:SetText(\"/ui/DefaultGroup/ShopHud/Gold\", \"골드 \" .. string.format(\"%d\", self.Gold))\nfor i = 1, 3 do\n\tlocal cid = self.ShopChoices[i]\n\tlocal c = self.Cards[cid]\n\tlocal base = \"/ui/DefaultGroup/ShopHud/Card\" .. tostring(i)\n\tif c ~= nil then\n\t\tself:SetText(base .. \"/Name\", c.name)\n\t\tself:SetText(base .. \"/Cost\", tostring(c.cost))\n\t\tself:SetText(base .. \"/Desc\", c.desc)\n\t\tself:SetText(base .. \"/Price\", string.format(\"%d\", 30) .. \" 골드\")\n\t\tlocal e = _EntityService:GetEntityByPath(base)\n\t\tif e ~= nil and e.SpriteGUIRendererComponent ~= nil then\n\t\t\tif self.ShopBought[i] == true then\n\t\t\t\te.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6)\n\t\t\telseif c.kind == \"Attack\" then\n\t\t\t\te.SpriteGUIRendererComponent.Color = Color(0.86, 0.42, 0.38, 1)\n\t\t\telseif c.kind == \"Skill\" then\n\t\t\t\te.SpriteGUIRendererComponent.Color = Color(0.42, 0.55, 0.85, 1)\n\t\t\telse\n\t\t\t\te.SpriteGUIRendererComponent.Color = Color(0.46, 0.68, 0.52, 1)\n\t\t\tend\n\t\tend\n\tend\nend", + "Scope": 2, + "ExecSpace": 6, + "Attributes": [], + "Name": "RenderShop" + }, + { + "Return": { + "Type": "void", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": null + }, + "Arguments": [ + { + "Type": "number", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": "slot" + } + ], + "Code": "if self.ShopBought == nil or self.ShopBought[slot] == true then\n\treturn\nend\nif self.Gold < 30 then\n\treturn\nend\nself.Gold = self.Gold - 30\ntable.insert(self.RunDeck, self.ShopChoices[slot])\nself.ShopBought[slot] = true\nself:RenderShop()\nself:RenderRun()", + "Scope": 2, + "ExecSpace": 6, + "Attributes": [], + "Name": "BuyCard" + }, + { + "Return": { + "Type": "void", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": null + }, + "Arguments": [], + "Code": "local old = self.PlayerHp\nself.PlayerHp = self.PlayerHp + 30\nif self.PlayerHp > self.PlayerMaxHp then\n\tself.PlayerHp = self.PlayerMaxHp\nend\nlocal healed = self.PlayerHp - old\nself:SetText(\"/ui/DefaultGroup/RestHud/Info\", \"HP \" .. string.format(\"%d\", old) .. \" → \" .. string.format(\"%d\", self.PlayerHp) .. \" (+\" .. string.format(\"%d\", healed) .. \")\")\nself:RenderCombat()\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RestHud\")\nif hud ~= nil then\n\thud.Enable = true\nend", + "Scope": 2, + "ExecSpace": 6, + "Attributes": [], + "Name": "ShowRest" + }, + { + "Return": { + "Type": "void", + "DefaultValue": null, + "SyncDirection": 0, + "Attributes": [], + "Name": null + }, + "Arguments": [], + "Code": "local s = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud\")\nif s ~= nil then\n\ts.Enable = false\nend\nlocal r = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/RestHud\")\nif r ~= nil then\n\tr.Enable = false\nend\nself:ShowMap()", + "Scope": 2, + "ExecSpace": 6, + "Attributes": [], + "Name": "LeaveNode" } ], "EntityEventHandlers": [] diff --git a/data/map.json b/data/map.json index 89964e1..154719b 100644 --- a/data/map.json +++ b/data/map.json @@ -2,10 +2,11 @@ "start": ["A", "B"], "nodes": { "A": { "type": "combat", "enemy": "slime", "row": 1, "col": -1, "next": ["C", "D"] }, - "B": { "type": "combat", "enemy": "slime", "row": 1, "col": 1, "next": ["D", "E"] }, - "C": { "type": "elite", "enemy": "slime_elite", "row": 2, "col": -2, "next": ["BOSS"] }, - "D": { "type": "combat", "enemy": "slime", "row": 2, "col": 0, "next": ["BOSS"] }, - "E": { "type": "combat", "enemy": "slime", "row": 2, "col": 2, "next": ["BOSS"] }, - "BOSS": { "type": "boss", "enemy": "slime_boss", "row": 3, "col": 0, "next": [] } + "B": { "type": "combat", "enemy": "slime", "row": 1, "col": 1, "next": ["C", "D"] }, + "C": { "type": "rest", "row": 2, "col": -1, "next": ["E", "F"] }, + "D": { "type": "shop", "row": 2, "col": 1, "next": ["E", "F"] }, + "E": { "type": "elite", "enemy": "slime_elite", "row": 3, "col": -1, "next": ["BOSS"] }, + "F": { "type": "combat", "enemy": "slime", "row": 3, "col": 1, "next": ["BOSS"] }, + "BOSS": { "type": "boss", "enemy": "slime_boss", "row": 4, "col": 0, "next": [] } } } diff --git a/tools/gen-slaydeck.mjs b/tools/gen-slaydeck.mjs index dc7fc80..397f0b7 100644 --- a/tools/gen-slaydeck.mjs +++ b/tools/gen-slaydeck.mjs @@ -19,7 +19,7 @@ for (const id of MAP.start) { if (!MAP.nodes[id]) throw new Error(`[gen-slaydeck] map.start에 없는 노드 id: ${id}`); } for (const [id, n] of Object.entries(MAP.nodes)) { - if (!ENEMIES.enemies[n.enemy]) throw new Error(`[gen-slaydeck] 노드 ${id}의 enemy 없음: ${n.enemy}`); + if (n.enemy && !ENEMIES.enemies[n.enemy]) throw new Error(`[gen-slaydeck] 노드 ${id}의 enemy 없음: ${n.enemy}`); for (const nx of n.next) { if (!MAP.nodes[nx]) throw new Error(`[gen-slaydeck] 노드 ${id}.next에 없는 노드 id: ${nx}`); } @@ -37,7 +37,8 @@ function luaEnemiesTable(enemies) { function luaMapNodesTable(nodes) { const lines = Object.entries(nodes).map(([id, n]) => { const nx = '{ ' + n.next.map(luaStr).join(', ') + ' }'; - return `\t${id} = { type = ${luaStr(n.type)}, enemy = ${luaStr(n.enemy)}, row = ${n.row}, col = ${n.col}, next = ${nx} },`; + const enemyField = n.enemy ? `enemy = ${luaStr(n.enemy)}, ` : ''; + return `\t${id} = { type = ${luaStr(n.type)}, ${enemyField}row = ${n.row}, col = ${n.col}, next = ${nx} },`; }); return `self.MapNodes = {\n${lines.join('\n')}\n}`; } @@ -91,7 +92,7 @@ const ALIGN_BOTTOM_CENTER = 6; function guid(prefix, n) { // 유효한 8-4-4-4-12 hex GUID 생성. prefix는 충돌 방지용 네임스페이스 바이트로 매핑. - const ns = prefix === 'hud' ? 0xd0 : prefix === 'dck' ? 0xca : prefix === 'cmb' ? 0xcb : prefix === 'rwd' ? 0xcc : prefix === 'map' ? 0xcd : 0xfe; + const ns = prefix === 'hud' ? 0xd0 : prefix === 'dck' ? 0xca : prefix === 'cmb' ? 0xcb : prefix === 'rwd' ? 0xcc : prefix === 'map' ? 0xcd : prefix === 'shp' ? 0xce : prefix === 'rst' ? 0xcf : 0xfe; const v = (ns * 0x100000 + n) >>> 0; return `${v.toString(16).padStart(8, '0')}-0000-4000-8000-${v.toString(16).padStart(12, '0')}`; } @@ -243,7 +244,7 @@ function entity({ id, path, modelId, entryId, componentNames, components, displa function upsertUi() { const ui = JSON.parse(readFileSync(UI_FILE, 'utf8')); const E = ui.ContentProto.Entities; - ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/CombatHud') && !e.path.startsWith('/ui/DefaultGroup/RewardHud') && !e.path.startsWith('/ui/DefaultGroup/MapHud')); + ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/CombatHud') && !e.path.startsWith('/ui/DefaultGroup/RewardHud') && !e.path.startsWith('/ui/DefaultGroup/MapHud') && !e.path.startsWith('/ui/DefaultGroup/ShopHud') && !e.path.startsWith('/ui/DefaultGroup/RestHud')); const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e])); @@ -598,7 +599,7 @@ function upsertUi() { })); ui.ContentProto.Entities.push(...reward); - const TYPE_KO = { combat: '전투', elite: '엘리트', boss: '보스' }; + const TYPE_KO = { combat: '전투', elite: '엘리트', boss: '보스', shop: '상점', rest: '휴식' }; const map = []; const mapHud = entity({ id: guid('map', 0), @@ -630,7 +631,7 @@ function upsertUi() { let mapN = 2; for (const [id, node] of Object.entries(MAP.nodes)) { const nodePath = `/ui/DefaultGroup/MapHud/Node_${id}`; - const pos = { x: node.col * 180, y: node.row * 170 - 80 }; + const pos = { x: node.col * 180, y: (node.row - (MAX_ROW + 1) / 2) * 140 }; map.push(entity({ id: guid('map', mapN++), path: nodePath, @@ -654,12 +655,164 @@ function upsertUi() { components: [ transform({ parentW: 150, parentH: 80, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 144, y: 72 }, pos: { x: 0, y: 0 } }), sprite({ color: TRANSPARENT }), - text({ value: `${TYPE_KO[node.type]}\n${ENEMIES.enemies[node.enemy].name}`, fontSize: 20, bold: true }), + text({ value: node.enemy ? `${TYPE_KO[node.type]}\n${ENEMIES.enemies[node.enemy].name}` : TYPE_KO[node.type], fontSize: 20, bold: true }), ], })); } ui.ContentProto.Entities.push(...map); + const shop = []; + const shopHud = entity({ + id: guid('shp', 0), + path: '/ui/DefaultGroup/ShopHud', + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 8, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1920, y: 1080 }, pos: { x: 0, y: 0 }, align: ALIGN_CENTER }), + sprite({ color: { r: 0.05, g: 0.06, b: 0.09, a: 0.92 }, type: 1, raycast: true }), + ], + }); + shopHud.jsonString.enable = false; + shop.push(shopHud); + shop.push(entity({ + id: guid('shp', 1), + path: '/ui/DefaultGroup/ShopHud/Title', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 0, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 700, y: 60 }, pos: { x: 0, y: 400 } }), + sprite({ color: TRANSPARENT }), + text({ value: '상점', fontSize: 44, bold: true, color: GOLD, alignment: 4 }), + ], + })); + shop.push(entity({ + id: guid('shp', 2), + path: '/ui/DefaultGroup/ShopHud/Gold', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 1, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 300, y: 44 }, pos: { x: 0, y: 330 } }), + sprite({ color: TRANSPARENT }), + text({ value: '골드 0', fontSize: 28, bold: true, color: { r: 0.98, g: 0.85, b: 0.4, a: 1 }, alignment: 4 }), + ], + })); + let shpN = 3; + const shopXs = [-300, 0, 300]; + for (let i = 1; i <= 3; i++) { + const cardPath = `/ui/DefaultGroup/ShopHud/Card${i}`; + shop.push(entity({ + id: guid('shp', shpN++), + path: cardPath, + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent', + displayOrder: i, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: CARD_W, y: CARD_H }, pos: { x: shopXs[i - 1], y: 20 } }), + sprite({ color: ATTACK, type: 1, raycast: true }), + button(), + ], + })); + for (const [suffix, cfg] of [ + ['Cost', { size: { x: 50, y: 50 }, pos: { x: -60, y: 95 }, value: '1', fontSize: 34, bold: true, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Name', { size: { x: 160, y: 50 }, pos: { x: 0, y: 50 }, value: '카드', fontSize: 26, bold: true, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Desc', { size: { x: 160, y: 60 }, pos: { x: 0, y: -50 }, value: '', fontSize: 20, bold: false, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Price', { size: { x: 160, y: 40 }, pos: { x: 0, y: -105 }, value: '30 골드', fontSize: 22, bold: true, color: { r: 0.98, g: 0.85, b: 0.4, a: 1 } }], + ]) { + shop.push(entity({ + id: guid('shp', shpN++), + path: `${cardPath}/${suffix}`, + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : suffix === 'Desc' ? 2 : 3, + components: [ + transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }), + sprite({ color: TRANSPARENT }), + text({ value: cfg.value, fontSize: cfg.fontSize, bold: cfg.bold, color: cfg.color }), + ], + })); + } + } + shop.push(entity({ + id: guid('shp', shpN++), + path: '/ui/DefaultGroup/ShopHud/Leave', + modelId: 'uibutton', + entryId: 'UIButton', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent', + displayOrder: 10, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 200, y: 60 }, pos: { x: 0, y: -300 } }), + sprite({ color: DARK, type: 1, raycast: true }), + button(), + text({ value: '나가기', fontSize: 26, bold: true, color: GOLD, alignment: 4 }), + ], + })); + ui.ContentProto.Entities.push(...shop); + + const rest = []; + const restHud = entity({ + id: guid('rst', 0), + path: '/ui/DefaultGroup/RestHud', + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 9, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1920, y: 1080 }, pos: { x: 0, y: 0 }, align: ALIGN_CENTER }), + sprite({ color: { r: 0.05, g: 0.08, b: 0.06, a: 0.92 }, type: 1, raycast: true }), + ], + }); + restHud.jsonString.enable = false; + rest.push(restHud); + rest.push(entity({ + id: guid('rst', 1), + path: '/ui/DefaultGroup/RestHud/Title', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 0, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 700, y: 60 }, pos: { x: 0, y: 140 } }), + sprite({ color: TRANSPARENT }), + text({ value: '휴식', fontSize: 44, bold: true, color: GOLD, alignment: 4 }), + ], + })); + rest.push(entity({ + id: guid('rst', 2), + path: '/ui/DefaultGroup/RestHud/Info', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 1, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 600, y: 50 }, pos: { x: 0, y: 30 } }), + sprite({ color: TRANSPARENT }), + text({ value: 'HP 회복', fontSize: 30, bold: true, color: { r: 1, g: 1, b: 1, a: 1 }, alignment: 4 }), + ], + })); + rest.push(entity({ + id: guid('rst', 3), + path: '/ui/DefaultGroup/RestHud/Leave', + modelId: 'uibutton', + entryId: 'UIButton', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent', + displayOrder: 2, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 200, y: 60 }, pos: { x: 0, y: -120 } }), + sprite({ color: DARK, type: 1, raycast: true }), + button(), + text({ value: '나가기', fontSize: 26, bold: true, color: GOLD, alignment: 4 }), + ], + })); + ui.ContentProto.Entities.push(...rest); + JSON.parse(JSON.stringify(ui)); writeFileSync(UI_FILE, JSON.stringify(ui, null, 2), 'utf8'); } @@ -716,6 +869,8 @@ function codeblock(id, name, properties, methods) { function writeCodeblocks() { const RUN_LENGTH = 3; const GOLD_PER_WIN = 15; + const CARD_PRICE = 30; + const REST_HEAL = 30; const combat = codeblock('SlayDeckController', 'SlayDeckController', [ prop('any', 'DrawPile'), prop('any', 'DiscardPile'), @@ -747,6 +902,8 @@ function writeCodeblocks() { prop('any', 'MapStart'), prop('string', 'CurrentNodeId', '""'), prop('string', 'CurrentEnemyId', '""'), + prop('any', 'ShopChoices'), + prop('any', 'ShopBought'), ], [ method('OnBeginPlay', `self:StartRun()`), method('StartRun', `self.PlayerMaxHp = 80 @@ -826,6 +983,20 @@ for i = 1, #mapNodeIds do if mn ~= nil and mn.ButtonComponent ~= nil then mn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end) end +end +for i = 1, 3 do + local sc = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Card" .. tostring(i)) + if sc ~= nil and sc.ButtonComponent ~= nil then + sc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end) + end +end +local shopLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Leave") +if shopLeave ~= nil and shopLeave.ButtonComponent ~= nil then + shopLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end) +end +local restLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud/Leave") +if restLeave ~= nil and restLeave.ButtonComponent ~= nil then + restLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end) end`), method('StartPlayerTurn', `self.Turn = self.Turn + 1 self.Energy = self.MaxEnergy @@ -1137,12 +1308,89 @@ if self:IsReachable(id) ~= true then return end self.CurrentNodeId = id -self.CurrentEnemyId = self.MapNodes[id].enemy local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud") if hud ~= nil then hud.Enable = false end -self:StartCombat()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }]), +local node = self.MapNodes[id] +if node.type == "shop" then + self:ShowShop() +elseif node.type == "rest" then + self:ShowRest() +else + self.CurrentEnemyId = node.enemy + self:StartCombat() +end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }]), + method('ShowShop', `local pool = {} +for cid, _ in pairs(self.Cards) do + table.insert(pool, cid) +end +self.ShopChoices = {} +self.ShopBought = { false, false, false } +for i = 1, 3 do + self.ShopChoices[i] = pool[math.random(1, #pool)] +end +self:RenderShop() +local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud") +if hud ~= nil then + hud.Enable = true +end`), + method('RenderShop', `self:SetText("/ui/DefaultGroup/ShopHud/Gold", "골드 " .. string.format("%d", self.Gold)) +for i = 1, 3 do + local cid = self.ShopChoices[i] + local c = self.Cards[cid] + local base = "/ui/DefaultGroup/ShopHud/Card" .. tostring(i) + if c ~= nil then + self:SetText(base .. "/Name", c.name) + self:SetText(base .. "/Cost", tostring(c.cost)) + self:SetText(base .. "/Desc", c.desc) + self:SetText(base .. "/Price", string.format("%d", ${CARD_PRICE}) .. " 골드") + local e = _EntityService:GetEntityByPath(base) + if e ~= nil and e.SpriteGUIRendererComponent ~= nil then + if self.ShopBought[i] == true then + e.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6) + elseif c.kind == "Attack" then + e.SpriteGUIRendererComponent.Color = Color(0.86, 0.42, 0.38, 1) + elseif c.kind == "Skill" then + e.SpriteGUIRendererComponent.Color = Color(0.42, 0.55, 0.85, 1) + else + e.SpriteGUIRendererComponent.Color = Color(0.46, 0.68, 0.52, 1) + end + end + end +end`), + method('BuyCard', `if self.ShopBought == nil or self.ShopBought[slot] == true then + return +end +if self.Gold < ${CARD_PRICE} then + return +end +self.Gold = self.Gold - ${CARD_PRICE} +table.insert(self.RunDeck, self.ShopChoices[slot]) +self.ShopBought[slot] = true +self:RenderShop() +self:RenderRun()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]), + method('ShowRest', `local old = self.PlayerHp +self.PlayerHp = self.PlayerHp + ${REST_HEAL} +if self.PlayerHp > self.PlayerMaxHp then + self.PlayerHp = self.PlayerMaxHp +end +local healed = self.PlayerHp - old +self:SetText("/ui/DefaultGroup/RestHud/Info", "HP " .. string.format("%d", old) .. " → " .. string.format("%d", self.PlayerHp) .. " (+" .. string.format("%d", healed) .. ")") +self:RenderCombat() +local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud") +if hud ~= nil then + hud.Enable = true +end`), + method('LeaveNode', `local s = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud") +if s ~= nil then + s.Enable = false +end +local r = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud") +if r ~= nil then + r.Enable = false +end +self:ShowMap()`), ]); for (const m of combat.ContentProto.Json.Methods) { m.ExecSpace = 6; diff --git a/ui/DefaultGroup.ui b/ui/DefaultGroup.ui index 12e4e77..f33c51c 100644 --- a/ui/DefaultGroup.ui +++ b/ui/DefaultGroup.ui @@ -11866,11 +11866,11 @@ "MobileOnly": false, "OffsetMax": { "x": -105, - "y": 130 + "y": -170 }, "OffsetMin": { "x": -255, - "y": 50 + "y": -250 }, "Pivot": { "x": 0.5, @@ -11889,11 +11889,11 @@ "UIVersion": 2, "anchoredPosition": { "x": -180, - "y": 90 + "y": -210 }, "Position": { "x": -180, - "y": 90, + "y": -210, "z": 0 }, "QuaternionRotation": { @@ -12242,11 +12242,11 @@ "MobileOnly": false, "OffsetMax": { "x": 255, - "y": 130 + "y": -170 }, "OffsetMin": { "x": 105, - "y": 50 + "y": -250 }, "Pivot": { "x": 0.5, @@ -12265,11 +12265,11 @@ "UIVersion": 2, "anchoredPosition": { "x": 180, - "y": 90 + "y": -210 }, "Position": { "x": 180, - "y": 90, + "y": -210, "z": 0 }, "QuaternionRotation": { @@ -12617,12 +12617,12 @@ }, "MobileOnly": false, "OffsetMax": { - "x": -285, - "y": 300 + "x": -105, + "y": -30 }, "OffsetMin": { - "x": -435, - "y": 220 + "x": -255, + "y": -110 }, "Pivot": { "x": 0.5, @@ -12640,12 +12640,12 @@ }, "UIVersion": 2, "anchoredPosition": { - "x": -360, - "y": 260 + "x": -180, + "y": -70 }, "Position": { - "x": -360, - "y": 260, + "x": -180, + "y": -70, "z": 0 }, "QuaternionRotation": { @@ -12948,7 +12948,7 @@ "bottom": 0 }, "SizeFit": false, - "Text": "엘리트\n정예 슬라임", + "Text": "휴식", "UseOutLine": true, "Enable": true } @@ -12993,12 +12993,12 @@ }, "MobileOnly": false, "OffsetMax": { - "x": 75, - "y": 300 + "x": 255, + "y": -30 }, "OffsetMin": { - "x": -75, - "y": 220 + "x": 105, + "y": -110 }, "Pivot": { "x": 0.5, @@ -13016,12 +13016,12 @@ }, "UIVersion": 2, "anchoredPosition": { - "x": 0, - "y": 260 + "x": 180, + "y": -70 }, "Position": { - "x": 0, - "y": 260, + "x": 180, + "y": -70, "z": 0 }, "QuaternionRotation": { @@ -13324,7 +13324,7 @@ "bottom": 0 }, "SizeFit": false, - "Text": "전투\n슬라임", + "Text": "상점", "UseOutLine": true, "Enable": true } @@ -13343,7 +13343,7 @@ "enable": true, "visible": true, "localize": true, - "displayOrder": 2, + "displayOrder": 3, "pathConstraints": "////", "revision": 1, "origin": { @@ -13369,12 +13369,12 @@ }, "MobileOnly": false, "OffsetMax": { - "x": 435, - "y": 300 + "x": -105, + "y": 110 }, "OffsetMin": { - "x": 285, - "y": 220 + "x": -255, + "y": 30 }, "Pivot": { "x": 0.5, @@ -13392,12 +13392,12 @@ }, "UIVersion": 2, "anchoredPosition": { - "x": 360, - "y": 260 + "x": -180, + "y": 70 }, "Position": { - "x": 360, - "y": 260, + "x": -180, + "y": 70, "z": 0 }, "QuaternionRotation": { @@ -13700,7 +13700,7 @@ "bottom": 0 }, "SizeFit": false, - "Text": "전투\n슬라임", + "Text": "엘리트\n정예 슬라임", "UseOutLine": true, "Enable": true } @@ -13710,11 +13710,11 @@ }, { "id": "0cd0000c-0000-4000-8000-00000cd0000c", - "path": "/ui/DefaultGroup/MapHud/Node_BOSS", + "path": "/ui/DefaultGroup/MapHud/Node_F", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", "jsonString": { - "name": "Node_BOSS", - "path": "/ui/DefaultGroup/MapHud/Node_BOSS", + "name": "Node_F", + "path": "/ui/DefaultGroup/MapHud/Node_F", "nameEditable": true, "enable": true, "visible": true, @@ -13745,12 +13745,12 @@ }, "MobileOnly": false, "OffsetMax": { - "x": 75, - "y": 470 + "x": 255, + "y": 110 }, "OffsetMin": { - "x": -75, - "y": 390 + "x": 105, + "y": 30 }, "Pivot": { "x": 0.5, @@ -13768,12 +13768,12 @@ }, "UIVersion": 2, "anchoredPosition": { - "x": 0, - "y": 430 + "x": 180, + "y": 70 }, "Position": { - "x": 0, - "y": 430, + "x": 180, + "y": 70, "z": 0 }, "QuaternionRotation": { @@ -13898,6 +13898,382 @@ }, { "id": "0cd0000d-0000-4000-8000-00000cd0000d", + "path": "/ui/DefaultGroup/MapHud/Node_F/Label", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Label", + "path": "/ui/DefaultGroup/MapHud/Node_F/Label", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 72, + "y": 36 + }, + "OffsetMin": { + "x": -72, + "y": -36 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 144, + "y": 72 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 0 + }, + "Position": { + "x": 0, + "y": 0, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 20, + "MaxSize": 20, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "전투\n슬라임", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cd0000e-0000-4000-8000-00000cd0000e", + "path": "/ui/DefaultGroup/MapHud/Node_BOSS", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", + "jsonString": { + "name": "Node_BOSS", + "path": "/ui/DefaultGroup/MapHud/Node_BOSS", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 4, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 75, + "y": 250 + }, + "OffsetMin": { + "x": -75, + "y": 170 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 150, + "y": 80 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 210 + }, + "Position": { + "x": 0, + "y": 210, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.3, + "g": 0.55, + "b": 0.85, + "a": 1 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cd0000f-0000-4000-8000-00000cd0000f", "path": "/ui/DefaultGroup/MapHud/Node_BOSS/Label", "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", "jsonString": { @@ -14083,6 +14459,4330 @@ ], "@version": 1 } + }, + { + "id": "0ce00000-0000-4000-8000-00000ce00000", + "path": "/ui/DefaultGroup/ShopHud", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent", + "jsonString": { + "name": "ShopHud", + "path": "/ui/DefaultGroup/ShopHud", + "nameEditable": true, + "enable": false, + "visible": true, + "localize": true, + "displayOrder": 8, + "pathConstraints": "///", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 960, + "y": 540 + }, + "OffsetMin": { + "x": -960, + "y": -540 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 1920, + "y": 1080 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 0 + }, + "Position": { + "x": 0, + "y": 0, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.05, + "g": 0.06, + "b": 0.09, + "a": 0.92 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00001-0000-4000-8000-00000ce00001", + "path": "/ui/DefaultGroup/ShopHud/Title", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Title", + "path": "/ui/DefaultGroup/ShopHud/Title", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 350, + "y": 430 + }, + "OffsetMin": { + "x": -350, + "y": 370 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 700, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 400 + }, + "Position": { + "x": 0, + "y": 400, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.94, + "g": 0.74, + "b": 0.26, + "a": 1 + }, + "FontSize": 44, + "MaxSize": 44, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "상점", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00002-0000-4000-8000-00000ce00002", + "path": "/ui/DefaultGroup/ShopHud/Gold", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Gold", + "path": "/ui/DefaultGroup/ShopHud/Gold", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 150, + "y": 352 + }, + "OffsetMin": { + "x": -150, + "y": 308 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 300, + "y": 44 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 330 + }, + "Position": { + "x": 0, + "y": 330, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.98, + "g": 0.85, + "b": 0.4, + "a": 1 + }, + "FontSize": 28, + "MaxSize": 28, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "골드 0", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00003-0000-4000-8000-00000ce00003", + "path": "/ui/DefaultGroup/ShopHud/Card1", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", + "jsonString": { + "name": "Card1", + "path": "/ui/DefaultGroup/ShopHud/Card1", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": -210, + "y": 145 + }, + "OffsetMin": { + "x": -390, + "y": -105 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 180, + "y": 250 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": -300, + "y": 20 + }, + "Position": { + "x": -300, + "y": 20, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.86, + "g": 0.42, + "b": 0.38, + "a": 1 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00004-0000-4000-8000-00000ce00004", + "path": "/ui/DefaultGroup/ShopHud/Card1/Cost", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Cost", + "path": "/ui/DefaultGroup/ShopHud/Card1/Cost", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": -35, + "y": 120 + }, + "OffsetMin": { + "x": -85, + "y": 70 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 50, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": -60, + "y": 95 + }, + "Position": { + "x": -60, + "y": 95, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 34, + "MaxSize": 34, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "1", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00005-0000-4000-8000-00000ce00005", + "path": "/ui/DefaultGroup/ShopHud/Card1/Name", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Name", + "path": "/ui/DefaultGroup/ShopHud/Card1/Name", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": 75 + }, + "OffsetMin": { + "x": -80, + "y": 25 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 50 + }, + "Position": { + "x": 0, + "y": 50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 26, + "MaxSize": 26, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "카드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00006-0000-4000-8000-00000ce00006", + "path": "/ui/DefaultGroup/ShopHud/Card1/Desc", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Desc", + "path": "/ui/DefaultGroup/ShopHud/Card1/Desc", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 2, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -20 + }, + "OffsetMin": { + "x": -80, + "y": -80 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -50 + }, + "Position": { + "x": 0, + "y": -50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": false, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 20, + "MaxSize": 20, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00007-0000-4000-8000-00000ce00007", + "path": "/ui/DefaultGroup/ShopHud/Card1/Price", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Price", + "path": "/ui/DefaultGroup/ShopHud/Card1/Price", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 3, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -85 + }, + "OffsetMin": { + "x": -80, + "y": -125 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 40 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -105 + }, + "Position": { + "x": 0, + "y": -105, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.98, + "g": 0.85, + "b": 0.4, + "a": 1 + }, + "FontSize": 22, + "MaxSize": 22, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "30 골드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00008-0000-4000-8000-00000ce00008", + "path": "/ui/DefaultGroup/ShopHud/Card2", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", + "jsonString": { + "name": "Card2", + "path": "/ui/DefaultGroup/ShopHud/Card2", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 2, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 90, + "y": 145 + }, + "OffsetMin": { + "x": -90, + "y": -105 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 180, + "y": 250 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 20 + }, + "Position": { + "x": 0, + "y": 20, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.86, + "g": 0.42, + "b": 0.38, + "a": 1 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00009-0000-4000-8000-00000ce00009", + "path": "/ui/DefaultGroup/ShopHud/Card2/Cost", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Cost", + "path": "/ui/DefaultGroup/ShopHud/Card2/Cost", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": -35, + "y": 120 + }, + "OffsetMin": { + "x": -85, + "y": 70 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 50, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": -60, + "y": 95 + }, + "Position": { + "x": -60, + "y": 95, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 34, + "MaxSize": 34, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "1", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000a-0000-4000-8000-00000ce0000a", + "path": "/ui/DefaultGroup/ShopHud/Card2/Name", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Name", + "path": "/ui/DefaultGroup/ShopHud/Card2/Name", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": 75 + }, + "OffsetMin": { + "x": -80, + "y": 25 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 50 + }, + "Position": { + "x": 0, + "y": 50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 26, + "MaxSize": 26, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "카드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000b-0000-4000-8000-00000ce0000b", + "path": "/ui/DefaultGroup/ShopHud/Card2/Desc", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Desc", + "path": "/ui/DefaultGroup/ShopHud/Card2/Desc", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 2, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -20 + }, + "OffsetMin": { + "x": -80, + "y": -80 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -50 + }, + "Position": { + "x": 0, + "y": -50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": false, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 20, + "MaxSize": 20, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000c-0000-4000-8000-00000ce0000c", + "path": "/ui/DefaultGroup/ShopHud/Card2/Price", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Price", + "path": "/ui/DefaultGroup/ShopHud/Card2/Price", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 3, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -85 + }, + "OffsetMin": { + "x": -80, + "y": -125 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 40 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -105 + }, + "Position": { + "x": 0, + "y": -105, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.98, + "g": 0.85, + "b": 0.4, + "a": 1 + }, + "FontSize": 22, + "MaxSize": 22, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "30 골드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000d-0000-4000-8000-00000ce0000d", + "path": "/ui/DefaultGroup/ShopHud/Card3", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent", + "jsonString": { + "name": "Card3", + "path": "/ui/DefaultGroup/ShopHud/Card3", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 3, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 390, + "y": 145 + }, + "OffsetMin": { + "x": 210, + "y": -105 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 180, + "y": 250 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 300, + "y": 20 + }, + "Position": { + "x": 300, + "y": 20, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.86, + "g": 0.42, + "b": 0.38, + "a": 1 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000e-0000-4000-8000-00000ce0000e", + "path": "/ui/DefaultGroup/ShopHud/Card3/Cost", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Cost", + "path": "/ui/DefaultGroup/ShopHud/Card3/Cost", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": -35, + "y": 120 + }, + "OffsetMin": { + "x": -85, + "y": 70 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 50, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": -60, + "y": 95 + }, + "Position": { + "x": -60, + "y": 95, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 34, + "MaxSize": 34, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "1", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce0000f-0000-4000-8000-00000ce0000f", + "path": "/ui/DefaultGroup/ShopHud/Card3/Name", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Name", + "path": "/ui/DefaultGroup/ShopHud/Card3/Name", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": 75 + }, + "OffsetMin": { + "x": -80, + "y": 25 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 50 + }, + "Position": { + "x": 0, + "y": 50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 26, + "MaxSize": 26, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "카드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00010-0000-4000-8000-00000ce00010", + "path": "/ui/DefaultGroup/ShopHud/Card3/Desc", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Desc", + "path": "/ui/DefaultGroup/ShopHud/Card3/Desc", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 2, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -20 + }, + "OffsetMin": { + "x": -80, + "y": -80 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -50 + }, + "Position": { + "x": 0, + "y": -50, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": false, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 20, + "MaxSize": 20, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00011-0000-4000-8000-00000ce00011", + "path": "/ui/DefaultGroup/ShopHud/Card3/Price", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Price", + "path": "/ui/DefaultGroup/ShopHud/Card3/Price", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 3, + "pathConstraints": "/////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 80, + "y": -85 + }, + "OffsetMin": { + "x": -80, + "y": -125 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 160, + "y": 40 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -105 + }, + "Position": { + "x": 0, + "y": -105, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.98, + "g": 0.85, + "b": 0.4, + "a": 1 + }, + "FontSize": 22, + "MaxSize": 22, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "30 골드", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0ce00012-0000-4000-8000-00000ce00012", + "path": "/ui/DefaultGroup/ShopHud/Leave", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Leave", + "path": "/ui/DefaultGroup/ShopHud/Leave", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 10, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIButton", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uibutton", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 100, + "y": -270 + }, + "OffsetMin": { + "x": -100, + "y": -330 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 200, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -300 + }, + "Position": { + "x": 0, + "y": -300, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.08, + "g": 0.09, + "b": 0.11, + "a": 0.92 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.94, + "g": 0.74, + "b": 0.26, + "a": 1 + }, + "FontSize": 26, + "MaxSize": 26, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "나가기", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cf00000-0000-4000-8000-00000cf00000", + "path": "/ui/DefaultGroup/RestHud", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent", + "jsonString": { + "name": "RestHud", + "path": "/ui/DefaultGroup/RestHud", + "nameEditable": true, + "enable": false, + "visible": true, + "localize": true, + "displayOrder": 9, + "pathConstraints": "///", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UISprite", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uisprite", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 960, + "y": 540 + }, + "OffsetMin": { + "x": -960, + "y": -540 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 1920, + "y": 1080 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 0 + }, + "Position": { + "x": 0, + "y": 0, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.05, + "g": 0.08, + "b": 0.06, + "a": 0.92 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cf00001-0000-4000-8000-00000cf00001", + "path": "/ui/DefaultGroup/RestHud/Title", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Title", + "path": "/ui/DefaultGroup/RestHud/Title", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 0, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 350, + "y": 170 + }, + "OffsetMin": { + "x": -350, + "y": 110 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 700, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 140 + }, + "Position": { + "x": 0, + "y": 140, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.94, + "g": 0.74, + "b": 0.26, + "a": 1 + }, + "FontSize": 44, + "MaxSize": 44, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "휴식", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cf00002-0000-4000-8000-00000cf00002", + "path": "/ui/DefaultGroup/RestHud/Info", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Info", + "path": "/ui/DefaultGroup/RestHud/Info", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 1, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIText", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uitext", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 300, + "y": 55 + }, + "OffsetMin": { + "x": -300, + "y": 5 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 600, + "y": 50 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": 30 + }, + "Position": { + "x": 0, + "y": 30, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0, + "g": 0, + "b": 0, + "a": 0 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": false, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "FontSize": 30, + "MaxSize": 30, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "HP 회복", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } + }, + { + "id": "0cf00003-0000-4000-8000-00000cf00003", + "path": "/ui/DefaultGroup/RestHud/Leave", + "componentNames": "MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent", + "jsonString": { + "name": "Leave", + "path": "/ui/DefaultGroup/RestHud/Leave", + "nameEditable": true, + "enable": true, + "visible": true, + "localize": true, + "displayOrder": 2, + "pathConstraints": "////", + "revision": 1, + "origin": { + "type": "Model", + "entry_id": "UIButton", + "sub_entity_id": null, + "root_entity_id": null, + "replaced_model_id": null + }, + "modelId": "uibutton", + "@components": [ + { + "@type": "MOD.Core.UITransformComponent", + "ActivePlatform": 255, + "AlignmentOption": 0, + "AnchorsMax": { + "x": 0.5, + "y": 0.5 + }, + "AnchorsMin": { + "x": 0.5, + "y": 0.5 + }, + "MobileOnly": false, + "OffsetMax": { + "x": 100, + "y": -90 + }, + "OffsetMin": { + "x": -100, + "y": -150 + }, + "Pivot": { + "x": 0.5, + "y": 0.5 + }, + "RectSize": { + "x": 200, + "y": 60 + }, + "UIMode": 1, + "UIScale": { + "x": 1, + "y": 1, + "z": 1 + }, + "UIVersion": 2, + "anchoredPosition": { + "x": 0, + "y": -120 + }, + "Position": { + "x": 0, + "y": -120, + "z": 0 + }, + "QuaternionRotation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "Scale": { + "x": 1, + "y": 1, + "z": 1 + }, + "Enable": true + }, + { + "@type": "MOD.Core.SpriteGUIRendererComponent", + "AnimClipPlayType": 0, + "EndFrameIndex": 2147483647, + "ImageRUID": { + "DataId": "" + }, + "LocalPosition": { + "x": 0, + "y": 0 + }, + "LocalScale": { + "x": 1, + "y": 1 + }, + "OverrideSorting": false, + "PlayRate": 1, + "PreserveSprite": 0, + "StartFrameIndex": 0, + "Color": { + "r": 0.08, + "g": 0.09, + "b": 0.11, + "a": 0.92 + }, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "FillAmount": 1, + "FillCenter": true, + "FillClockWise": true, + "FillMethod": 0, + "FillOrigin": 0, + "FlipX": false, + "FlipY": false, + "FrameColumn": 1, + "FrameRate": 0, + "FrameRow": 1, + "Outline": false, + "OutlineColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 1 + }, + "OutlineWidth": 3, + "RaycastTarget": true, + "Type": 1, + "Enable": true + }, + { + "@type": "MOD.Core.ButtonComponent", + "Colors": { + "NormalColor": { + "r": 1, + "g": 1, + "b": 1, + "a": 1 + }, + "HighlightedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "PressedColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 1 + }, + "SelectedColor": { + "r": 0.9607843, + "g": 0.9607843, + "b": 0.9607843, + "a": 1 + }, + "DisabledColor": { + "r": 0.784313738, + "g": 0.784313738, + "b": 0.784313738, + "a": 0.5019608 + }, + "ColorMultiplier": 1, + "FadeDuration": 0.1 + }, + "ImageRUIDs": { + "HighlightedSprite": null, + "PressedSprite": null, + "SelectedSprite": null, + "DisabledSprite": null + }, + "KeyCode": 0, + "OverrideSorting": false, + "Transition": 1, + "Enable": true + }, + { + "@type": "MOD.Core.TextComponent", + "Alignment": 4, + "Bold": true, + "DropShadow": false, + "DropShadowAngle": 30, + "DropShadowColor": { + "r": 0, + "g": 0, + "b": 0, + "a": 0.72 + }, + "DropShadowDistance": 32, + "Font": 0, + "FontColor": { + "r": 0.94, + "g": 0.74, + "b": 0.26, + "a": 1 + }, + "FontSize": 26, + "MaxSize": 26, + "MinSize": 8, + "OutlineColor": { + "r": 0.08, + "g": 0.08, + "b": 0.08, + "a": 1 + }, + "OutlineDistance": { + "x": 1, + "y": -1 + }, + "OutlineWidth": 1, + "Overflow": 0, + "OverrideSorting": false, + "Padding": { + "left": 0, + "right": 0, + "top": 0, + "bottom": 0 + }, + "SizeFit": false, + "Text": "나가기", + "UseOutLine": true, + "Enable": true + } + ], + "@version": 1 + } } ] } From 03b59eeafc08f651d3a85acd0c257cb6f38bff9b Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 9 Jun 2026 03:35:05 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs(E4):=20=EC=83=81=EC=A0=90/=ED=9C=B4?= =?UTF-8?q?=EC=8B=9D=20=EC=84=A4=EA=B3=84=C2=B7=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../superpowers/plans/2026-06-09-shop-rest.md | 488 ++++++++++++++++++ .../specs/2026-06-09-shop-rest-design.md | 70 +++ 2 files changed, 558 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-09-shop-rest.md create mode 100644 docs/superpowers/specs/2026-06-09-shop-rest-design.md diff --git a/docs/superpowers/plans/2026-06-09-shop-rest.md b/docs/superpowers/plans/2026-06-09-shop-rest.md new file mode 100644 index 0000000..5f0d081 --- /dev/null +++ b/docs/superpowers/plans/2026-06-09-shop-rest.md @@ -0,0 +1,488 @@ +# 상점/휴식 노드 (TODO E4) Implementation Plan + +> **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:** 맵에 상점(골드→카드)·휴식(HP 회복) 노드를 추가하고, 진입 시 전투 대신 상점/휴식 UI로 분기. + +**Architecture:** `data/map.json`에 shop/rest 노드 추가(enemy 없음). SlayDeckController에 상점/휴식 메서드, PickNode 타입 분기, ShopHud/RestHud UI. 모두 `gen-slaydeck.mjs`에서 생성. + +**Tech Stack:** Node.js ESM 생성기, MSW Lua codeblock/UI. 검증은 node --check+재생성+결정성+메이커 Play. + +--- + +## File Structure +- Modify: `data/map.json` — 4행, shop/rest 노드. +- Modify: `tools/gen-slaydeck.mjs` — 검증 완화, enemy 조건부 직렬화, 상수, 속성, PickNode 분기, 상점/휴식 메서드, ShopHud/RestHud UI, MapHud y 중앙정렬. + +검증: MSW Lua 단위테스트 불가 → 생성기 문법·재생성·결정성·메이커 Play. + +--- + +### Task 1: 데이터 + 검증완화 + enemy 조건부 직렬화 + 상수·속성 + +**Files:** Modify `data/map.json`, `tools/gen-slaydeck.mjs` + +- [ ] **Step 1: `data/map.json` 교체** + +```json +{ + "start": ["A", "B"], + "nodes": { + "A": { "type": "combat", "enemy": "slime", "row": 1, "col": -1, "next": ["C", "D"] }, + "B": { "type": "combat", "enemy": "slime", "row": 1, "col": 1, "next": ["C", "D"] }, + "C": { "type": "rest", "row": 2, "col": -1, "next": ["E", "F"] }, + "D": { "type": "shop", "row": 2, "col": 1, "next": ["E", "F"] }, + "E": { "type": "elite", "enemy": "slime_elite", "row": 3, "col": -1, "next": ["BOSS"] }, + "F": { "type": "combat", "enemy": "slime", "row": 3, "col": 1, "next": ["BOSS"] }, + "BOSS": { "type": "boss", "enemy": "slime_boss", "row": 4, "col": 0, "next": [] } + } +} +``` + +- [ ] **Step 2: 검증 완화 (enemy 선택적)** — 생성기의 맵 검증 루프를 교체: + +```js +for (const [id, n] of Object.entries(MAP.nodes)) { + if (n.enemy && !ENEMIES.enemies[n.enemy]) throw new Error(`[gen-slaydeck] 노드 ${id}의 enemy 없음: ${n.enemy}`); + for (const nx of n.next) { + if (!MAP.nodes[nx]) throw new Error(`[gen-slaydeck] 노드 ${id}.next에 없는 노드 id: ${nx}`); + } +} +``` + +- [ ] **Step 3: luaMapNodesTable enemy 조건부** — 함수를 교체: + +```js +function luaMapNodesTable(nodes) { + const lines = Object.entries(nodes).map(([id, n]) => { + const nx = '{ ' + n.next.map(luaStr).join(', ') + ' }'; + const enemyField = n.enemy ? `enemy = ${luaStr(n.enemy)}, ` : ''; + return `\t${id} = { type = ${luaStr(n.type)}, ${enemyField}row = ${n.row}, col = ${n.col}, next = ${nx} },`; + }); + return `self.MapNodes = {\n${lines.join('\n')}\n}`; +} +``` + +- [ ] **Step 4: 상수 추가** — `writeCodeblocks()` 안 `const GOLD_PER_WIN = 15;` 다음에: + +```js + const CARD_PRICE = 30; + const REST_HEAL = 30; +``` + +- [ ] **Step 5: 상점 상태 속성 추가** — `prop('string', 'CurrentEnemyId', '""'),` 다음에: + +```js + prop('any', 'ShopChoices'), + prop('any', 'ShopBought'), +``` + +- [ ] **Step 6: JSON·문법 검사** + +Run: `node -e "JSON.parse(require('fs').readFileSync('data/map.json','utf8')); console.log('JSON OK')" && node --check tools/gen-slaydeck.mjs` +Expected: `JSON OK` + 오류 없음 + +- [ ] **Step 7: 커밋** + +```bash +git add data/map.json tools/gen-slaydeck.mjs +git commit -m "data(E4): 상점/휴식 노드 맵 + enemy 선택적 검증/직렬화 + 상수/속성" +``` + +--- + +### Task 2: PickNode 분기 + 상점/휴식 메서드 + +**Files:** Modify `tools/gen-slaydeck.mjs` + +- [ ] **Step 1: PickNode 교체 (타입 분기)** + +```js + method('PickNode', `if self.RunActive ~= true then + return +end +if self:IsReachable(id) ~= true then + return +end +self.CurrentNodeId = id +local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud") +if hud ~= nil then + hud.Enable = false +end +local node = self.MapNodes[id] +if node.type == "shop" then + self:ShowShop() +elseif node.type == "rest" then + self:ShowRest() +else + self.CurrentEnemyId = node.enemy + self:StartCombat() +end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'id' }]), +``` + +- [ ] **Step 2: 상점/휴식 메서드 추가** — PickNode 메서드 다음에 삽입: + +```js + method('ShowShop', `local pool = {} +for cid, _ in pairs(self.Cards) do + table.insert(pool, cid) +end +self.ShopChoices = {} +self.ShopBought = { false, false, false } +for i = 1, 3 do + self.ShopChoices[i] = pool[math.random(1, #pool)] +end +self:RenderShop() +local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud") +if hud ~= nil then + hud.Enable = true +end`), + method('RenderShop', `self:SetText("/ui/DefaultGroup/ShopHud/Gold", "골드 " .. string.format("%d", self.Gold)) +for i = 1, 3 do + local cid = self.ShopChoices[i] + local c = self.Cards[cid] + local base = "/ui/DefaultGroup/ShopHud/Card" .. tostring(i) + if c ~= nil then + self:SetText(base .. "/Name", c.name) + self:SetText(base .. "/Cost", tostring(c.cost)) + self:SetText(base .. "/Desc", c.desc) + self:SetText(base .. "/Price", string.format("%d", ${CARD_PRICE}) .. " 골드") + local e = _EntityService:GetEntityByPath(base) + if e ~= nil and e.SpriteGUIRendererComponent ~= nil then + if self.ShopBought[i] == true then + e.SpriteGUIRendererComponent.Color = Color(0.2, 0.22, 0.26, 0.6) + elseif c.kind == "Attack" then + e.SpriteGUIRendererComponent.Color = Color(0.86, 0.42, 0.38, 1) + elseif c.kind == "Skill" then + e.SpriteGUIRendererComponent.Color = Color(0.42, 0.55, 0.85, 1) + else + e.SpriteGUIRendererComponent.Color = Color(0.46, 0.68, 0.52, 1) + end + end + end +end`), + method('BuyCard', `if self.ShopBought == nil or self.ShopBought[slot] == true then + return +end +if self.Gold < ${CARD_PRICE} then + return +end +self.Gold = self.Gold - ${CARD_PRICE} +table.insert(self.RunDeck, self.ShopChoices[slot]) +self.ShopBought[slot] = true +self:RenderShop() +self:RenderRun()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]), + method('ShowRest', `local old = self.PlayerHp +self.PlayerHp = self.PlayerHp + ${REST_HEAL} +if self.PlayerHp > self.PlayerMaxHp then + self.PlayerHp = self.PlayerMaxHp +end +local healed = self.PlayerHp - old +self:SetText("/ui/DefaultGroup/RestHud/Info", "HP " .. string.format("%d", old) .. " → " .. string.format("%d", self.PlayerHp) .. " (+" .. string.format("%d", healed) .. ")") +self:RenderCombat() +local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud") +if hud ~= nil then + hud.Enable = true +end`), + method('LeaveNode', `local s = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud") +if s ~= nil then + s.Enable = false +end +local r = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud") +if r ~= nil then + r.Enable = false +end +self:ShowMap()`), +``` + +- [ ] **Step 3: 문법 검사** + +Run: `node --check tools/gen-slaydeck.mjs` +Expected: 오류 없음 + +- [ ] **Step 4: 커밋** + +```bash +git add tools/gen-slaydeck.mjs +git commit -m "gen-slaydeck(E4): PickNode 타입 분기·상점(구매)/휴식(회복) 메서드" +``` + +--- + +### Task 3: BindButtons 바인딩 + +**Files:** Modify `tools/gen-slaydeck.mjs` + +- [ ] **Step 1: BindButtons 맵 노드 루프 다음에 상점/휴식 바인딩 추가** — BindButtons 코드의 맵 노드 for-loop(`...PickNode(nid)...end\nend`) 다음, 닫는 백틱 직전에 삽입. 맵 노드 루프 끝 부분을 아래로 교체: + +```js +for i = 1, #mapNodeIds do + local nid = mapNodeIds[i] + local mn = _EntityService:GetEntityByPath("/ui/DefaultGroup/MapHud/Node_" .. nid) + if mn ~= nil and mn.ButtonComponent ~= nil then + mn:ConnectEvent(ButtonClickEvent, function() self:PickNode(nid) end) + end +end +for i = 1, 3 do + local sc = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Card" .. tostring(i)) + if sc ~= nil and sc.ButtonComponent ~= nil then + sc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end) + end +end +local shopLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/ShopHud/Leave") +if shopLeave ~= nil and shopLeave.ButtonComponent ~= nil then + shopLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end) +end +local restLeave = _EntityService:GetEntityByPath("/ui/DefaultGroup/RestHud/Leave") +if restLeave ~= nil and restLeave.ButtonComponent ~= nil then + restLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end) +end`), +``` + +- [ ] **Step 2: 문법 검사** + +Run: `node --check tools/gen-slaydeck.mjs` +Expected: 오류 없음 + +- [ ] **Step 3: 커밋** + +```bash +git add tools/gen-slaydeck.mjs +git commit -m "gen-slaydeck(E4): 상점 구매/나가기·휴식 나가기 버튼 바인딩" +``` + +--- + +### Task 4: ShopHud·RestHud UI + MapHud 4행 정렬 + +**Files:** Modify `tools/gen-slaydeck.mjs` (`guid`, `upsertUi`) + +- [ ] **Step 1: guid 'shp'·'rst' 분기** — ns 매핑에 추가(map 분기 다음): + +```js + const ns = prefix === 'hud' ? 0xd0 : prefix === 'dck' ? 0xca : prefix === 'cmb' ? 0xcb : prefix === 'rwd' ? 0xcc : prefix === 'map' ? 0xcd : prefix === 'shp' ? 0xce : prefix === 'rst' ? 0xcf : 0xfe; +``` + +- [ ] **Step 2: 필터 확장** — upsertUi 필터에 ShopHud·RestHud 추가: + +```js + ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/CombatHud') && !e.path.startsWith('/ui/DefaultGroup/RewardHud') && !e.path.startsWith('/ui/DefaultGroup/MapHud') && !e.path.startsWith('/ui/DefaultGroup/ShopHud') && !e.path.startsWith('/ui/DefaultGroup/RestHud')); +``` + +- [ ] **Step 3: MapHud 노드 y 중앙정렬** — upsertUi의 노드 pos 계산을 교체: + +```js + const pos = { x: node.col * 180, y: (node.row - (MAX_ROW + 1) / 2) * 140 }; +``` + +- [ ] **Step 4: ShopHud·RestHud 생성** — `ui.ContentProto.Entities.push(...map);` 다음에 삽입: + +```js + const shop = []; + const shopHud = entity({ + id: guid('shp', 0), + path: '/ui/DefaultGroup/ShopHud', + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 8, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1920, y: 1080 }, pos: { x: 0, y: 0 }, align: ALIGN_CENTER }), + sprite({ color: { r: 0.05, g: 0.06, b: 0.09, a: 0.92 }, type: 1, raycast: true }), + ], + }); + shopHud.jsonString.enable = false; + shop.push(shopHud); + shop.push(entity({ + id: guid('shp', 1), + path: '/ui/DefaultGroup/ShopHud/Title', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 0, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 700, y: 60 }, pos: { x: 0, y: 400 } }), + sprite({ color: TRANSPARENT }), + text({ value: '상점', fontSize: 44, bold: true, color: GOLD, alignment: 4 }), + ], + })); + shop.push(entity({ + id: guid('shp', 2), + path: '/ui/DefaultGroup/ShopHud/Gold', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 1, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 300, y: 44 }, pos: { x: 0, y: 330 } }), + sprite({ color: TRANSPARENT }), + text({ value: '골드 0', fontSize: 28, bold: true, color: { r: 0.98, g: 0.85, b: 0.4, a: 1 }, alignment: 4 }), + ], + })); + let shpN = 3; + const shopXs = [-300, 0, 300]; + for (let i = 1; i <= 3; i++) { + const cardPath = `/ui/DefaultGroup/ShopHud/Card${i}`; + shop.push(entity({ + id: guid('shp', shpN++), + path: cardPath, + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent', + displayOrder: i, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: CARD_W, y: CARD_H }, pos: { x: shopXs[i - 1], y: 20 } }), + sprite({ color: ATTACK, type: 1, raycast: true }), + button(), + ], + })); + for (const [suffix, cfg] of [ + ['Cost', { size: { x: 50, y: 50 }, pos: { x: -60, y: 95 }, value: '1', fontSize: 34, bold: true, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Name', { size: { x: 160, y: 50 }, pos: { x: 0, y: 50 }, value: '카드', fontSize: 26, bold: true, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Desc', { size: { x: 160, y: 60 }, pos: { x: 0, y: -50 }, value: '', fontSize: 20, bold: false, color: { r: 1, g: 1, b: 1, a: 1 } }], + ['Price', { size: { x: 160, y: 40 }, pos: { x: 0, y: -105 }, value: '30 골드', fontSize: 22, bold: true, color: { r: 0.98, g: 0.85, b: 0.4, a: 1 } }], + ]) { + shop.push(entity({ + id: guid('shp', shpN++), + path: `${cardPath}/${suffix}`, + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : suffix === 'Desc' ? 2 : 3, + components: [ + transform({ parentW: CARD_W, parentH: CARD_H, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: cfg.size, pos: cfg.pos }), + sprite({ color: TRANSPARENT }), + text({ value: cfg.value, fontSize: cfg.fontSize, bold: cfg.bold, color: cfg.color }), + ], + })); + } + } + shop.push(entity({ + id: guid('shp', shpN++), + path: '/ui/DefaultGroup/ShopHud/Leave', + modelId: 'uibutton', + entryId: 'UIButton', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent', + displayOrder: 10, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 200, y: 60 }, pos: { x: 0, y: -300 } }), + sprite({ color: DARK, type: 1, raycast: true }), + button(), + text({ value: '나가기', fontSize: 26, bold: true, color: GOLD, alignment: 4 }), + ], + })); + ui.ContentProto.Entities.push(...shop); + + const rest = []; + const restHud = entity({ + id: guid('rst', 0), + path: '/ui/DefaultGroup/RestHud', + modelId: 'uisprite', + entryId: 'UISprite', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', + displayOrder: 9, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1920, y: 1080 }, pos: { x: 0, y: 0 }, align: ALIGN_CENTER }), + sprite({ color: { r: 0.05, g: 0.08, b: 0.06, a: 0.92 }, type: 1, raycast: true }), + ], + }); + restHud.jsonString.enable = false; + rest.push(restHud); + rest.push(entity({ + id: guid('rst', 1), + path: '/ui/DefaultGroup/RestHud/Title', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 0, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 700, y: 60 }, pos: { x: 0, y: 140 } }), + sprite({ color: TRANSPARENT }), + text({ value: '휴식', fontSize: 44, bold: true, color: GOLD, alignment: 4 }), + ], + })); + rest.push(entity({ + id: guid('rst', 2), + path: '/ui/DefaultGroup/RestHud/Info', + modelId: 'uitext', + entryId: 'UIText', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', + displayOrder: 1, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 600, y: 50 }, pos: { x: 0, y: 30 } }), + sprite({ color: TRANSPARENT }), + text({ value: 'HP 회복', fontSize: 30, bold: true, color: { r: 1, g: 1, b: 1, a: 1 }, alignment: 4 }), + ], + })); + rest.push(entity({ + id: guid('rst', 3), + path: '/ui/DefaultGroup/RestHud/Leave', + modelId: 'uibutton', + entryId: 'UIButton', + componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,MOD.Core.TextComponent', + displayOrder: 2, + components: [ + transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 200, y: 60 }, pos: { x: 0, y: -120 } }), + sprite({ color: DARK, type: 1, raycast: true }), + button(), + text({ value: '나가기', fontSize: 26, bold: true, color: GOLD, alignment: 4 }), + ], + })); + ui.ContentProto.Entities.push(...rest); +``` + +- [ ] **Step 5: 문법 검사** + +Run: `node --check tools/gen-slaydeck.mjs` +Expected: 오류 없음 + +- [ ] **Step 6: 커밋** + +```bash +git add tools/gen-slaydeck.mjs +git commit -m "gen-slaydeck(E4): ShopHud/RestHud UI·MapHud 4행 중앙정렬" +``` + +--- + +### Task 5: 재생성 + 검증 + +**Files:** 생성물 + +- [ ] **Step 1: 생성** + +Run: `node tools/gen-slaydeck.mjs` +Expected: `Slay deck UI and combat codeblocks generated.` + +- [ ] **Step 2: 메서드·UI 확인** + +Run: `node -e "const j=JSON.parse(require('fs').readFileSync('RootDesk/MyDesk/SlayDeckController.codeblock','utf8')); const n=j.ContentProto.Json.Methods.map(m=>m.Name); console.log(['ShowShop','BuyCard','ShowRest','LeaveNode','RenderShop'].every(x=>n.includes(x))?'METHODS OK':'MISSING'); const u=JSON.parse(require('fs').readFileSync('ui/DefaultGroup.ui','utf8')); const has=p=>u.ContentProto.Entities.some(e=>e.path===p); console.log(has('/ui/DefaultGroup/ShopHud/Card1/Price')&&has('/ui/DefaultGroup/RestHud/Info')&&has('/ui/DefaultGroup/MapHud/Node_D')?'UI OK':'UI MISSING')"` +Expected: `METHODS OK` / `UI OK` + +- [ ] **Step 3: 결정성** + +Run: `node tools/gen-slaydeck.mjs >/dev/null && sha1sum ui/DefaultGroup.ui RootDesk/MyDesk/SlayDeckController.codeblock > /tmp/a.sha && node tools/gen-slaydeck.mjs >/dev/null && sha1sum ui/DefaultGroup.ui RootDesk/MyDesk/SlayDeckController.codeblock > /tmp/b.sha && diff /tmp/a.sha /tmp/b.sha && echo DETERMINISTIC` +Expected: `DETERMINISTIC` + +- [ ] **Step 4: git status** + +Run: `git checkout -- Global/common.gamelogic 2>/dev/null; git status --short` +Expected: `data/map.json`, `tools/gen-slaydeck.mjs`, `ui/DefaultGroup.ui`, `RootDesk/MyDesk/SlayDeckController.codeblock` (+docs). + +- [ ] **Step 5: 생성물 커밋** + +```bash +git add ui/DefaultGroup.ui RootDesk/MyDesk/SlayDeckController.codeblock +git commit -m "재생성(E4): 상점/휴식 노드·UI 반영" +``` + +- [ ] **Step 6: 메이커 Play 수동 검증 (MCP)** + +reload→Play: 맵(4행, 2행에 휴식C·상점D) → PickNode("D")→상점(카드3·골드) → BuyCard(골드≥30이면 -30·RunDeck+1·비활성; 부족하면 무시) → LeaveNode→맵 / PickNode("C")→휴식(HP+30 클램프)→LeaveNode→맵 / 전투·보스·런 클리어 회귀 확인. MCP는 PickNode/BuyCard/LeaveNode 직접 호출 + 로그. + +--- + +## Self-Review +- **Spec coverage:** 맵/검증/직렬화/상수/속성(Task1), PickNode분기·상점·휴식(Task2), 바인딩(Task3), UI·MapHud정렬(Task4), 검증(Task5). 스펙 전 항목 매핑. +- **Placeholder scan:** 모든 단계 실제 코드/명령. +- **Type consistency:** 메서드 `PickNode/ShowShop/RenderShop/BuyCard/ShowRest/LeaveNode` 정의·호출·바인딩 일치. 속성 `ShopChoices/ShopBought` 정의(Task1)·사용(Task2) 일치. UI 경로 `/ui/DefaultGroup/ShopHud/Card{1..3}/{Name,Cost,Desc,Price}`·`/Gold`·`/Leave`, `/RestHud/{Info,Leave}`가 codeblock(RenderShop/ShowRest/BindButtons)·생성(Task4)에서 동일. 상수 `CARD_PRICE/REST_HEAL` Task1 정의·Task2 사용 일치. diff --git a/docs/superpowers/specs/2026-06-09-shop-rest-design.md b/docs/superpowers/specs/2026-06-09-shop-rest-design.md new file mode 100644 index 0000000..7815057 --- /dev/null +++ b/docs/superpowers/specs/2026-06-09-shop-rest-design.md @@ -0,0 +1,70 @@ +# 상점/휴식 노드 (TODO E4) — 설계 + +> 작성: 2026-06-09 / 상태: 승인됨 / 근거: TODO E 분해(E4) + E3 맵 노드 구조. +> 선행: E3(분기 맵) 완료. 후속: E5(유물)·E6(저장). 카드 제거는 덱 보기 UI 필요 → 후속 분리. + +## 문제 + +E3로 분기 맵은 됐으나 모든 노드가 전투다. 골드는 적립만 되고 소비처가 없다. 상점(골드→카드)· +휴식(HP 회복) 노드가 필요하다. + +## 범위 + +맵에 상점/휴식 노드 추가, 진입 시 전투 대신 상점/휴식 UI. 상점 = 카드 구매(골드). 휴식 = HP 회복. +**카드 제거(덱 보기 UI 필요)·유물·저장·휴식 업그레이드는 범위 밖.** + +## 설계 + +### 데이터 (`data/map.json` 교체 — 4행) +```json +{ + "start": ["A", "B"], + "nodes": { + "A": { "type": "combat", "enemy": "slime", "row": 1, "col": -1, "next": ["C", "D"] }, + "B": { "type": "combat", "enemy": "slime", "row": 1, "col": 1, "next": ["C", "D"] }, + "C": { "type": "rest", "row": 2, "col": -1, "next": ["E", "F"] }, + "D": { "type": "shop", "row": 2, "col": 1, "next": ["E", "F"] }, + "E": { "type": "elite", "enemy": "slime_elite", "row": 3, "col": -1, "next": ["BOSS"] }, + "F": { "type": "combat", "enemy": "slime", "row": 3, "col": 1, "next": ["BOSS"] }, + "BOSS": { "type": "boss", "enemy": "slime_boss", "row": 4, "col": 0, "next": [] } + } +} +``` +- rest/shop 노드는 `enemy` 없음. 생성기 검증을 "`enemy` 있을 때만 ENEMIES 확인"으로 완화. + Lua MapNodes 직렬화도 enemy 있을 때만 `enemy = "..."` 포함. + +### 파라미터 (생성기 상수) +- `CARD_PRICE = 30`, `REST_HEAL = 30`. + +### 상태 추가 +- `ShopChoices`(any) — 상점 제시 카드 id 3개. +- `ShopBought`(any) — 슬롯별 구매 여부 {bool×3}. + +### 메서드 +- `PickNode`(수정): CurrentNodeId 세팅·맵 숨김 후 타입 분기 — + `shop`→`ShowShop`, `rest`→`ShowRest`, 그 외→`CurrentEnemyId=node.enemy`·`StartCombat`. +- `ShowShop`(신규): 카드 풀에서 3개 무작위→ShopChoices, ShopBought 초기화(false), + 각 슬롯 비주얼·가격·골드 갱신, ShopHud 표시. +- `BuyCard(slot)`(신규): ShopBought[slot]==true 또는 Gold