Merge remote-tracking branch 'origin/main' into feature/map-monster-combat

# Conflicts:
#	RootDesk/MyDesk/SlayDeckController.codeblock
This commit is contained in:
2026-06-10 08:34:23 +09:00
3 changed files with 43875 additions and 8 deletions

View File

@@ -92,6 +92,34 @@
"Attributes": [],
"Name": "NewGameHandler"
},
{
"Type": "any",
"DefaultValue": "nil",
"SyncDirection": 0,
"Attributes": [],
"Name": "DrawPileHandler"
},
{
"Type": "any",
"DefaultValue": "nil",
"SyncDirection": 0,
"Attributes": [],
"Name": "DiscardPileHandler"
},
{
"Type": "any",
"DefaultValue": "nil",
"SyncDirection": 0,
"Attributes": [],
"Name": "DeckInspectCloseHandler"
},
{
"Type": "string",
"DefaultValue": "\"\"",
"SyncDirection": 0,
"Attributes": [],
"Name": "DeckInspectKind"
},
{
"Type": "any",
"DefaultValue": "nil",
@@ -503,7 +531,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\", \"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 shopRelic = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud/Relic\")\nif shopRelic ~= nil and shopRelic.ButtonComponent ~= nil then\n\tshopRelic:ConnectEvent(ButtonClickEvent, function() self:BuyRelic() 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\nfor i = 1, 4 do\n\tlocal ms = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CombatHud/MonsterSlot\" .. tostring(i))\n\tif ms ~= nil and ms.ButtonComponent ~= nil then\n\t\tms:ConnectEvent(ButtonClickEvent, function() self:SetTarget(i) 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\nlocal drawPile = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckHud/DrawPile\")\nif drawPile ~= nil and drawPile.ButtonComponent ~= nil then\n\tif self.DrawPileHandler ~= nil then\n\t\tdrawPile:DisconnectEvent(ButtonClickEvent, self.DrawPileHandler)\n\t\tself.DrawPileHandler = nil\n\tend\n\tself.DrawPileHandler = drawPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect(\"draw\") end)\nend\nlocal discardPile = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckHud/DiscardPile\")\nif discardPile ~= nil and discardPile.ButtonComponent ~= nil then\n\tif self.DiscardPileHandler ~= nil then\n\t\tdiscardPile:DisconnectEvent(ButtonClickEvent, self.DiscardPileHandler)\n\t\tself.DiscardPileHandler = nil\n\tend\n\tself.DiscardPileHandler = discardPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect(\"discard\") end)\nend\nlocal inspectClose = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud/Close\")\nif inspectClose ~= nil and inspectClose.ButtonComponent ~= nil then\n\tif self.DeckInspectCloseHandler ~= nil then\n\t\tinspectClose:DisconnectEvent(ButtonClickEvent, self.DeckInspectCloseHandler)\n\t\tself.DeckInspectCloseHandler = nil\n\tend\n\tself.DeckInspectCloseHandler = inspectClose:ConnectEvent(ButtonClickEvent, function() self:CloseDeckInspect() 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 shopRelic = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/ShopHud/Relic\")\nif shopRelic ~= nil and shopRelic.ButtonComponent ~= nil then\n\tshopRelic:ConnectEvent(ButtonClickEvent, function() self:BuyRelic() 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\nfor i = 1, 4 do\n\tlocal ms = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CombatHud/MonsterSlot\" .. tostring(i))\n\tif ms ~= nil and ms.ButtonComponent ~= nil then\n\t\tms:ConnectEvent(ButtonClickEvent, function() self:SetTarget(i) end)\n\tend\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
@@ -586,12 +614,110 @@
"Name": null
},
"Arguments": [],
"Code": "self:SetText(\"/ui/DefaultGroup/DeckHud/DrawPile/Count\", tostring(#self.DrawPile))\nself:SetText(\"/ui/DefaultGroup/DeckHud/DiscardPile/Count\", tostring(#self.DiscardPile))\nself:SetText(\"/ui/DefaultGroup/DeckHud/Energy\", \"에너지 \" .. string.format(\"%d\", self.Energy) .. \"/\" .. string.format(\"%d\", self.MaxEnergy))",
"Code": "self:SetText(\"/ui/DefaultGroup/DeckHud/DrawPile/Count\", tostring(#self.DrawPile))\nself:SetText(\"/ui/DefaultGroup/DeckHud/DiscardPile/Count\", tostring(#self.DiscardPile))\nself:SetText(\"/ui/DefaultGroup/DeckHud/Energy\", \"에너지 \" .. string.format(\"%d\", self.Energy) .. \"/\" .. string.format(\"%d\", self.MaxEnergy))\nlocal inspect = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud\")\nif inspect ~= nil and inspect.Enable == true and self.DeckInspectKind ~= \"\" then\n\tself:OpenDeckInspect(self.DeckInspectKind)\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "RenderPiles"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "string",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "kind"
}
],
"Code": "self.DeckInspectKind = kind\nlocal pile = {}\nlocal title = \"\"\nif kind == \"discard\" then\n\tpile = self.DiscardPile or {}\n\ttitle = \"버린 덱\"\nelse\n\tpile = self.DrawPile or {}\n\ttitle = \"뽑을 덱\"\nend\nself:RenderDeckInspect(pile, title)\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud\")\nif hud ~= nil then\n\thud.Enable = true\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "OpenDeckInspect"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "self.DeckInspectKind = \"\"\nlocal hud = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud\")\nif hud ~= nil then\n\thud.Enable = false\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "CloseDeckInspect"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "any",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "pile"
},
{
"Type": "string",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "title"
}
],
"Code": "local count = 0\nif pile ~= nil then\n\tcount = #pile\nend\nlocal suffix = \" (\" .. tostring(count) .. \")\"\nif count > 60 then\n\tsuffix = suffix .. \" - 60장까지 표시\"\nend\nself:SetText(\"/ui/DefaultGroup/DeckInspectHud/Title\", title .. suffix)\nlocal empty = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud/Empty\")\nif empty ~= nil then\n\tempty.Enable = count <= 0\nend\nfor i = 1, 60 do\n\tlocal e = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/DeckInspectHud/Grid/Card\" .. tostring(i))\n\tif e ~= nil then\n\t\tlocal cardId = nil\n\t\tif pile ~= nil then\n\t\t\tcardId = pile[i]\n\t\tend\n\t\tif cardId == nil then\n\t\t\te.Enable = false\n\t\telse\n\t\t\te.Enable = true\n\t\t\tself:ApplyInspectCardVisual(i, cardId)\n\t\tend\n\tend\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "RenderDeckInspect"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "number",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "slot"
},
{
"Type": "string",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "cardId"
}
],
"Code": "local c = self.Cards[cardId]\nif c == nil then\n\tc = { name = cardId, cost = 0, desc = \"\", kind = \"Skill\" }\nend\nlocal base = \"/ui/DefaultGroup/DeckInspectHud/Grid/Card\" .. tostring(slot)\nself:SetText(base .. \"/Cost\", tostring(c.cost))\nself:SetText(base .. \"/Name\", c.name)\nself:SetText(base .. \"/Desc\", c.desc)\nlocal e = _EntityService:GetEntityByPath(base)\nif e ~= nil and e.SpriteGUIRendererComponent ~= nil then\n\tif c.kind == \"Attack\" then\n\t\te.SpriteGUIRendererComponent.Color = Color(0.86, 0.42, 0.38, 1)\n\telseif c.kind == \"Skill\" then\n\t\te.SpriteGUIRendererComponent.Color = Color(0.42, 0.55, 0.85, 1)\n\telse\n\t\te.SpriteGUIRendererComponent.Color = Color(0.46, 0.68, 0.52, 1)\n\tend\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "ApplyInspectCardVisual"
},
{
"Return": {
"Type": "void",

View File

@@ -97,7 +97,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 : prefix === 'shp' ? 0xce : prefix === 'rst' ? 0xcf : prefix === 'menu' ? 0xe0 : 0xfe;
const ns = prefix === 'hud' ? 0xd0 : prefix === 'dck' ? 0xca : prefix === 'cmb' ? 0xcb : prefix === 'rwd' ? 0xcc : prefix === 'map' ? 0xcd : prefix === 'shp' ? 0xce : prefix === 'rst' ? 0xcf : prefix === 'menu' ? 0xe0 : prefix === 'ins' ? 0xe1 : 0xfe;
const v = (ns * 0x100000 + n) >>> 0;
return `${v.toString(16).padStart(8, '0')}-0000-4000-8000-${v.toString(16).padStart(12, '0')}`;
}
@@ -215,6 +215,38 @@ function text({ value, fontSize, bold = false, color = { r: 1, g: 1, b: 1, a: 1
};
}
function scrollLayoutGroup({ cellSize, spacing, columns }) {
return {
'@type': 'MOD.Core.ScrollLayoutGroupComponent',
CellSize: cellSize,
ChildAlignment: 0,
Constraint: 1,
ConstraintCount: columns,
GridChildAlignment: 0,
GridSpacing: spacing,
HorizontalScrollBarDirection: 0,
IgnoreMapLayerCheck: false,
OrderInLayer: 0,
OverrideSorting: false,
Padding: { left: 16, right: 16, top: 16, bottom: 16 },
ReverseArrangement: false,
ScrollBarBackgroundColor: { r: 1, g: 1, b: 1, a: 0.18 },
ScrollBarBgImageRUID: { DataId: '' },
ScrollBarHandleColor: { r: 0.94, g: 0.74, b: 0.26, a: 0.9 },
ScrollBarHandleImageRUID: { DataId: '' },
ScrollBarThickness: 12,
ScrollBarVisible: 1,
SortingLayer: 'UI',
Spacing: 0,
StartAxis: 0,
StartCorner: 0,
Type: 2,
UseScroll: true,
VerticalScrollBarDirection: 1,
Enable: true,
};
}
function entity({ id, path, modelId, entryId, componentNames, components, displayOrder }) {
const parts = path.split('/');
const name = parts[parts.length - 1];
@@ -252,7 +284,7 @@ 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') && !e.path.startsWith('/ui/DefaultGroup/ShopHud') && !e.path.startsWith('/ui/DefaultGroup/RestHud') && !e.path.startsWith('/ui/DefaultGroup/MainMenu'));
ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/DeckInspectHud') && !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') && !e.path.startsWith('/ui/DefaultGroup/MainMenu'));
const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e]));
@@ -346,11 +378,12 @@ function upsertUi() {
path: `/ui/DefaultGroup/DeckHud/${pile.key}`,
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent',
displayOrder: pile.key === 'DrawPile' ? 0 : 1,
components: [
transform({ parentW: 1280, parentH: 330, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 132, y: 186 }, pos: { x: pile.x, y: 8 }, align: ALIGN_CENTER }),
sprite({ color: pile.color, type: 1, raycast: true }),
button(),
],
}));
add(entity({
@@ -412,6 +445,128 @@ function upsertUi() {
ui.ContentProto.Entities.push(...hud);
const inspect = [];
const inspectHud = entity({
id: guid('ins', 0),
path: '/ui/DefaultGroup/DeckInspectHud',
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 15,
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.04, g: 0.05, b: 0.07, a: 0.78 }, type: 1, raycast: true }),
],
});
inspectHud.jsonString.enable = false;
inspect.push(inspectHud);
inspect.push(entity({
id: guid('ins', 1),
path: '/ui/DefaultGroup/DeckInspectHud/Panel',
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 0,
components: [
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1040, y: 760 }, pos: { x: 0, y: 10 }, align: ALIGN_CENTER }),
sprite({ color: { r: 0.08, g: 0.09, b: 0.11, a: 0.96 }, type: 1 }),
],
}));
inspect.push(entity({
id: guid('ins', 2),
path: '/ui/DefaultGroup/DeckInspectHud/Title',
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: 720, y: 54 }, pos: { x: 0, y: 350 } }),
sprite({ color: TRANSPARENT }),
text({ value: '\uB371 \uBCF4\uAE30', fontSize: 34, bold: true, color: GOLD, alignment: 4 }),
],
}));
inspect.push(entity({
id: guid('ins', 3),
path: '/ui/DefaultGroup/DeckInspectHud/Close',
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: 78, y: 52 }, pos: { x: 466, y: 350 } }),
sprite({ color: { r: 0.16, g: 0.18, b: 0.22, a: 1 }, type: 1, raycast: true }),
button(),
text({ value: 'X', fontSize: 26, bold: true, color: GOLD, alignment: 4 }),
],
}));
inspect.push(entity({
id: guid('ins', 4),
path: '/ui/DefaultGroup/DeckInspectHud/Empty',
modelId: 'uitext',
entryId: 'UIText',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
displayOrder: 3,
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: '\uCE74\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4', fontSize: 28, bold: true, color: { r: 0.82, g: 0.86, b: 0.9, a: 1 }, alignment: 4 }),
],
}));
inspect.push(entity({
id: guid('ins', 5),
path: '/ui/DefaultGroup/DeckInspectHud/Grid',
modelId: 'uiempty',
entryId: 'UIEmpty',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ScrollLayoutGroupComponent',
displayOrder: 4,
components: [
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 950, y: 610 }, pos: { x: 0, y: 0 } }),
sprite({ color: TRANSPARENT, type: 1, raycast: true }),
scrollLayoutGroup({ cellSize: { x: 158, y: 214 }, spacing: { x: 22, y: 22 }, columns: 5 }),
],
}));
let insN = 6;
const INSPECT_CARD_COUNT = 60;
const INSPECT_CARD_W = 142;
const INSPECT_CARD_H = 198;
for (let i = 1; i <= INSPECT_CARD_COUNT; i++) {
const cardPath = `/ui/DefaultGroup/DeckInspectHud/Grid/Card${i}`;
const card = entity({
id: guid('ins', insN++),
path: cardPath,
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: i,
components: [
transform({ parentW: 950, parentH: 610, anchor: { x: 0.5, y: 0.5 }, pivot: { x: 0.5, y: 0.5 }, size: { x: INSPECT_CARD_W, y: INSPECT_CARD_H }, pos: { x: 0, y: 0 } }),
sprite({ color: ATTACK, type: 1 }),
],
});
card.jsonString.enable = false;
inspect.push(card);
for (const [suffix, cfg] of [
['Cost', { size: { x: 42, y: 38 }, pos: { x: -46, y: 73 }, value: '1', fontSize: 25, bold: true }],
['Name', { size: { x: 126, y: 42 }, pos: { x: 0, y: 34 }, value: '', fontSize: 21, bold: true }],
['Desc', { size: { x: 126, y: 70 }, pos: { x: 0, y: -58 }, value: '', fontSize: 16, bold: false }],
]) {
inspect.push(entity({
id: guid('ins', insN++),
path: `${cardPath}/${suffix}`,
modelId: 'uitext',
entryId: 'UIText',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
displayOrder: suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : 2,
components: [
transform({ parentW: INSPECT_CARD_W, parentH: INSPECT_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 }),
],
}));
}
}
ui.ContentProto.Entities.push(...inspect);
const PANEL_BG = { r: 0.08, g: 0.09, b: 0.11, a: 0.78 };
const combat = [];
combat.push(entity({
@@ -1045,6 +1200,10 @@ function writeCodeblocks() {
prop('number', 'TweenEventId', '0'),
prop('any', 'EndTurnHandler'),
prop('any', 'NewGameHandler'),
prop('any', 'DrawPileHandler'),
prop('any', 'DiscardPileHandler'),
prop('any', 'DeckInspectCloseHandler'),
prop('string', 'DeckInspectKind', '""'),
prop('any', 'Cards'),
prop('number', 'PlayerHp', '0'),
prop('number', 'PlayerMaxHp', '80'),
@@ -1189,6 +1348,30 @@ if endTurn ~= nil and endTurn.ButtonComponent ~= nil then
end
self.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() end)
end
local drawPile = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/DrawPile")
if drawPile ~= nil and drawPile.ButtonComponent ~= nil then
if self.DrawPileHandler ~= nil then
drawPile:DisconnectEvent(ButtonClickEvent, self.DrawPileHandler)
self.DrawPileHandler = nil
end
self.DrawPileHandler = drawPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("draw") end)
end
local discardPile = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/DiscardPile")
if discardPile ~= nil and discardPile.ButtonComponent ~= nil then
if self.DiscardPileHandler ~= nil then
discardPile:DisconnectEvent(ButtonClickEvent, self.DiscardPileHandler)
self.DiscardPileHandler = nil
end
self.DiscardPileHandler = discardPile:ConnectEvent(ButtonClickEvent, function() self:OpenDeckInspect("discard") end)
end
local inspectClose = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Close")
if inspectClose ~= nil and inspectClose.ButtonComponent ~= nil then
if self.DeckInspectCloseHandler ~= nil then
inspectClose:DisconnectEvent(ButtonClickEvent, self.DeckInspectCloseHandler)
self.DeckInspectCloseHandler = nil
end
self.DeckInspectCloseHandler = inspectClose:ConnectEvent(ButtonClickEvent, function() self:CloseDeckInspect() end)
end
for i = 1, 5 do
local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))
if cardEntity ~= nil and cardEntity.ButtonComponent ~= nil then
@@ -1281,7 +1464,83 @@ self.DiscardPile = {}
self:Shuffle(self.DrawPile)`),
method('RenderPiles', `self:SetText("/ui/DefaultGroup/DeckHud/DrawPile/Count", tostring(#self.DrawPile))
self:SetText("/ui/DefaultGroup/DeckHud/DiscardPile/Count", tostring(#self.DiscardPile))
self:SetText("/ui/DefaultGroup/DeckHud/Energy", "에너지 " .. string.format("%d", self.Energy) .. "/" .. string.format("%d", self.MaxEnergy))`),
self:SetText("/ui/DefaultGroup/DeckHud/Energy", "에너지 " .. string.format("%d", self.Energy) .. "/" .. string.format("%d", self.MaxEnergy))
local inspect = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
if inspect ~= nil and inspect.Enable == true and self.DeckInspectKind ~= "" then
self:OpenDeckInspect(self.DeckInspectKind)
end`),
method('OpenDeckInspect', `self.DeckInspectKind = kind
local pile = {}
local title = ""
if kind == "discard" then
pile = self.DiscardPile or {}
title = "버린 덱"
else
pile = self.DrawPile or {}
title = "뽑을 덱"
end
self:RenderDeckInspect(pile, title)
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
if hud ~= nil then
hud.Enable = true
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'kind' }]),
method('CloseDeckInspect', `self.DeckInspectKind = ""
local hud = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud")
if hud ~= nil then
hud.Enable = false
end`),
method('RenderDeckInspect', `local count = 0
if pile ~= nil then
count = #pile
end
local suffix = " (" .. tostring(count) .. ")"
if count > 60 then
suffix = suffix .. " - 60장까지 표시"
end
self:SetText("/ui/DefaultGroup/DeckInspectHud/Title", title .. suffix)
local empty = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Empty")
if empty ~= nil then
empty.Enable = count <= 0
end
for i = 1, 60 do
local e = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckInspectHud/Grid/Card" .. tostring(i))
if e ~= nil then
local cardId = nil
if pile ~= nil then
cardId = pile[i]
end
if cardId == nil then
e.Enable = false
else
e.Enable = true
self:ApplyInspectCardVisual(i, cardId)
end
end
end`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'title' },
]),
method('ApplyInspectCardVisual', `local c = self.Cards[cardId]
if c == nil then
c = { name = cardId, cost = 0, desc = "", kind = "Skill" }
end
local base = "/ui/DefaultGroup/DeckInspectHud/Grid/Card" .. tostring(slot)
self:SetText(base .. "/Cost", tostring(c.cost))
self:SetText(base .. "/Name", c.name)
self:SetText(base .. "/Desc", c.desc)
local e = _EntityService:GetEntityByPath(base)
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
if 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`, [
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
]),
method('RenderHand', `local drawStart = Vector2(-590, 8)
for i = 1, 5 do
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(i))

File diff suppressed because it is too large Load Diff