Add main menu flow

This commit is contained in:
maple
2026-06-07 23:27:44 +09:00
parent cfc41ac3d9
commit 8c397cbc09
3 changed files with 1225 additions and 73 deletions

View File

@@ -84,6 +84,13 @@
"SyncDirection": 0, "SyncDirection": 0,
"Attributes": [], "Attributes": [],
"Name": "EndTurnHandler" "Name": "EndTurnHandler"
},
{
"Type": "any",
"DefaultValue": "nil",
"SyncDirection": 0,
"Attributes": [],
"Name": "NewGameHandler"
} }
], ],
"Methods": [ "Methods": [
@@ -96,12 +103,57 @@
"Name": null "Name": null
}, },
"Arguments": [], "Arguments": [],
"Code": "self:StartCombat()", "Code": "self:ShowMainMenu()",
"Scope": 2, "Scope": 2,
"ExecSpace": 6, "ExecSpace": 6,
"Attributes": [], "Attributes": [],
"Name": "OnBeginPlay" "Name": "OnBeginPlay"
}, },
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "self:SetEntityEnabled(\"/ui/DefaultGroup/MainMenu\", true)\nself:SetEntityEnabled(\"/ui/DefaultGroup/CardHand\", false)\nself:SetEntityEnabled(\"/ui/DefaultGroup/DeckHud\", false)\nself:BindMenuButtons()",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "ShowMainMenu"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "local buttonEntity = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/MainMenu/NewGameButton\")\nif buttonEntity == nil or buttonEntity.ButtonComponent == nil then\n\treturn\nend\nif self.NewGameHandler ~= nil then\n\tbuttonEntity:DisconnectEvent(ButtonClickEvent, self.NewGameHandler)\n\tself.NewGameHandler = nil\nend\nself.NewGameHandler = buttonEntity:ConnectEvent(ButtonClickEvent, self.StartNewGame)",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "BindMenuButtons"
},
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [],
"Code": "self:SetEntityEnabled(\"/ui/DefaultGroup/MainMenu\", false)\nself:SetEntityEnabled(\"/ui/DefaultGroup/CardHand\", true)\nself:SetEntityEnabled(\"/ui/DefaultGroup/DeckHud\", true)\nself:StartCombat()",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "StartNewGame"
},
{ {
"Return": { "Return": {
"Type": "void", "Type": "void",
@@ -285,7 +337,7 @@
"Name": "cardId" "Name": "cardId"
} }
], ],
"Code": "local name = cardId\nlocal cost = 0\nlocal desc = \"\"\nlocal kind = \"Skill\"\nif cardId == \"Strike\" then\n\tname = \"타격\"\n\tcost = 1\n\tdesc = \"피해 6\"\n\tkind = \"Attack\"\nelseif cardId == \"Defend\" then\n\tname = \"방어\"\n\tcost = 1\n\tdesc = \"방어도 5\"\n\tkind = \"Skill\"\nelseif cardId == \"Bash\" then\n\tname = \"강타\"\n\tcost = 2\n\tdesc = \"피해 10\"\n\tkind = \"Attack\"\nend\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Cost\", tostring(cost))\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Name\", name)\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Desc\", desc)\nlocal cardEntity = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot))\nif cardEntity ~= nil and cardEntity.SpriteGUIRendererComponent ~= nil then\n\tlocal ok = false\n\tlocal color = nil\n\tif kind == \"Attack\" then\n\t\tok, color = pcall(function() return Color(0.86, 0.42, 0.38, 1) end)\n\telseif kind == \"Skill\" then\n\t\tok, color = pcall(function() return Color(0.42, 0.55, 0.85, 1) end)\n\telse\n\t\tok, color = pcall(function() return Color(0.46, 0.68, 0.52, 1) end)\n\tend\n\tif ok == true and color ~= nil then\n\t\tcardEntity.SpriteGUIRendererComponent.Color = color\n\tend\nend", "Code": "local name = cardId\nlocal cost = 0\nlocal desc = \"\"\nlocal kind = \"Skill\"\nif cardId == \"Strike\" then\n\tname = \"타격\"\n\tcost = 1\n\tdesc = \"피해 6\"\n\tkind = \"Attack\"\nelseif cardId == \"Defend\" then\n\tname = \"방어\"\n\tcost = 1\n\tdesc = \"방어도 5\"\n\tkind = \"Skill\"\nelseif cardId == \"Bash\" then\n\tname = \"강타\"\n\tcost = 2\n\tdesc = \"피해 10\"\n\tkind = \"Attack\"\nend\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Cost\", tostring(cost))\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Name\", name)\nself:SetText(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot) .. \"/Desc\", desc)\nlocal cardEntity = _EntityService:GetEntityByPath(\"/ui/DefaultGroup/CardHand/Card\" .. tostring(slot))\nif cardEntity ~= nil and cardEntity.SpriteGUIRendererComponent ~= nil then\n\tlocal ok = false\n\tlocal color = nil\n\tif kind == \"Attack\" then\n\t\tok, color = pcall(function() return Color(0.86, 0.42, 0.38, 1) end)\n\telseif kind == \"Skill\" then\n\t\tok, color = pcall(function() return Color(0.42, 0.55, 0.85, 1) end)\n\tend\n\tif ok == true and color ~= nil then\n\t\tcardEntity.SpriteGUIRendererComponent.Color = color\n\tend\nend",
"Scope": 2, "Scope": 2,
"ExecSpace": 6, "ExecSpace": 6,
"Attributes": [], "Attributes": [],
@@ -321,6 +373,36 @@
"Attributes": [], "Attributes": [],
"Name": "SetText" "Name": "SetText"
}, },
{
"Return": {
"Type": "void",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": null
},
"Arguments": [
{
"Type": "string",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "path"
},
{
"Type": "boolean",
"DefaultValue": null,
"SyncDirection": 0,
"Attributes": [],
"Name": "enabled"
}
],
"Code": "local entity = _EntityService:GetEntityByPath(path)\nif entity ~= nil then\n\tentity.Enable = enabled\nend",
"Scope": 2,
"ExecSpace": 6,
"Attributes": [],
"Name": "SetEntityEnabled"
},
{ {
"Return": { "Return": {
"Type": "void", "Type": "void",

View File

@@ -8,13 +8,10 @@ const DARK = { r: 0.08, g: 0.09, b: 0.11, a: 0.92 };
const GOLD = { r: 0.94, g: 0.74, b: 0.26, a: 1 }; const GOLD = { r: 0.94, g: 0.74, b: 0.26, a: 1 };
const ATTACK = { r: 0.86, g: 0.42, b: 0.38, a: 1 }; const ATTACK = { r: 0.86, g: 0.42, b: 0.38, a: 1 };
const DEFEND = { r: 0.42, g: 0.55, b: 0.85, a: 1 }; const DEFEND = { r: 0.42, g: 0.55, b: 0.85, a: 1 };
const SKILL = { r: 0.46, g: 0.68, b: 0.52, a: 1 };
const CARD_W = 180; const CARD_W = 180;
const CARD_H = 250; const CARD_H = 250;
const CARD_SPACING = 200;
const CARD_XS = [-400, -200, 0, 200, 400]; const CARD_XS = [-400, -200, 0, 200, 400];
const ALIGN_CENTER = 0; const ALIGN_CENTER = 0;
const ALIGN_BOTTOM_CENTER = 6; const ALIGN_BOTTOM_CENTER = 6;
@@ -23,8 +20,6 @@ function guid(prefix, n) {
} }
function transform({ parentW, parentH, anchor, pivot, size, pos, align = 0 }) { function transform({ parentW, parentH, anchor, pivot, size, pos, align = 0 }) {
const offMin = { x: pos.x - pivot.x * size.x, y: pos.y - pivot.y * size.y };
const offMax = { x: pos.x + (1 - pivot.x) * size.x, y: pos.y + (1 - pivot.y) * size.y };
return { return {
'@type': 'MOD.Core.UITransformComponent', '@type': 'MOD.Core.UITransformComponent',
ActivePlatform: 255, ActivePlatform: 255,
@@ -32,8 +27,8 @@ function transform({ parentW, parentH, anchor, pivot, size, pos, align = 0 }) {
AnchorsMax: anchor, AnchorsMax: anchor,
AnchorsMin: anchor, AnchorsMin: anchor,
MobileOnly: false, MobileOnly: false,
OffsetMax: offMax, OffsetMax: { x: pos.x + (1 - pivot.x) * size.x, y: pos.y + (1 - pivot.y) * size.y },
OffsetMin: offMin, OffsetMin: { x: pos.x - pivot.x * size.x, y: pos.y - pivot.y * size.y },
Pivot: pivot, Pivot: pivot,
RectSize: size, RectSize: size,
UIMode: 1, UIMode: 1,
@@ -83,7 +78,7 @@ function sprite({ dataId = '', color = TRANSPARENT, type = 1, raycast = false })
}; };
} }
function button() { function button({ enabled = true } = {}) {
return { return {
'@type': 'MOD.Core.ButtonComponent', '@type': 'MOD.Core.ButtonComponent',
Colors: { Colors: {
@@ -104,7 +99,7 @@ function button() {
KeyCode: 0, KeyCode: 0,
OverrideSorting: false, OverrideSorting: false,
Transition: 1, Transition: 1,
Enable: true, Enable: enabled,
}; };
} }
@@ -135,7 +130,7 @@ function text({ value, fontSize, bold = false, color = { r: 1, g: 1, b: 1, a: 1
}; };
} }
function entity({ id, path, modelId, entryId, componentNames, components, displayOrder }) { function entity({ id, path, modelId, entryId, componentNames, components, displayOrder, enable = true }) {
const parts = path.split('/'); const parts = path.split('/');
const name = parts[parts.length - 1]; const name = parts[parts.length - 1];
return { return {
@@ -146,7 +141,7 @@ function entity({ id, path, modelId, entryId, componentNames, components, displa
name, name,
path, path,
nameEditable: true, nameEditable: true,
enable: true, enable,
visible: true, visible: true,
localize: true, localize: true,
displayOrder, displayOrder,
@@ -168,10 +163,13 @@ function entity({ id, path, modelId, entryId, componentNames, components, displa
function upsertUi() { function upsertUi() {
const ui = JSON.parse(readFileSync(UI_FILE, 'utf8')); const ui = JSON.parse(readFileSync(UI_FILE, 'utf8'));
const E = ui.ContentProto.Entities; ui.ContentProto.Entities = ui.ContentProto.Entities.filter(
ui.ContentProto.Entities = E.filter((e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud')); (e) => !e.path.startsWith('/ui/DefaultGroup/DeckHud') && !e.path.startsWith('/ui/DefaultGroup/MainMenu'),
);
const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e])); const byPath = new Map(ui.ContentProto.Entities.map((e) => [e.path, e]));
const cardHand = byPath.get('/ui/DefaultGroup/CardHand');
if (cardHand) cardHand.jsonString.enable = false;
const cards = [ const cards = [
{ name: '타격', cost: '1', desc: '피해 6', tint: ATTACK }, { name: '타격', cost: '1', desc: '피해 6', tint: ATTACK },
@@ -181,7 +179,7 @@ function upsertUi() {
{ name: '강타', cost: '2', desc: '피해 10', tint: ATTACK }, { name: '강타', cost: '2', desc: '피해 10', tint: ATTACK },
]; ];
for (let i = 1; i <= 5; i++) { for (let i = 1; i <= 5; i += 1) {
const card = byPath.get(`/ui/DefaultGroup/CardHand/Card${i}`); const card = byPath.get(`/ui/DefaultGroup/CardHand/Card${i}`);
if (!card) continue; if (!card) continue;
const tr = card.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent'); const tr = card.jsonString['@components'].find((c) => c['@type'] === 'MOD.Core.UITransformComponent');
@@ -193,25 +191,24 @@ function upsertUi() {
sp.ImageRUID = { DataId: '' }; sp.ImageRUID = { DataId: '' };
sp.Type = 1; sp.Type = 1;
sp.Color = cards[i - 1].tint; sp.Color = cards[i - 1].tint;
card.jsonString.enable = true; card.jsonString.enable = false;
card.jsonString.visible = true;
const children = [ for (const [suffix, cfg] of [
['Cost', { size: { x: 50, y: 50 }, pos: { x: -60, y: 95 }, value: cards[i - 1].cost, fontSize: 34, bold: true }], ['Cost', { size: { x: 50, y: 50 }, pos: { x: -60, y: 95 }, value: cards[i - 1].cost, fontSize: 34, bold: true }],
['Name', { size: { x: 160, y: 50 }, pos: { x: 0, y: 50 }, value: cards[i - 1].name, fontSize: 26, bold: true }], ['Name', { size: { x: 160, y: 50 }, pos: { x: 0, y: 50 }, value: cards[i - 1].name, fontSize: 26, bold: true }],
['Desc', { size: { x: 160, y: 82 }, pos: { x: 0, y: -80 }, value: cards[i - 1].desc, fontSize: 20, bold: false }], ['Desc', { size: { x: 160, y: 82 }, pos: { x: 0, y: -80 }, value: cards[i - 1].desc, fontSize: 20, bold: false }],
]; ]) {
for (const [suffix, cfg] of children) {
const path = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`; const path = `/ui/DefaultGroup/CardHand/Card${i}/${suffix}`;
let child = byPath.get(path); let child = byPath.get(path);
if (!child) { if (!child) {
child = entity({ child = entity({
id: guid('dck', i * 10 + children.findIndex(([s]) => s === suffix)), id: guid('dck', i * 10 + (suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : 2)),
path, path,
modelId: 'uitext', modelId: 'uitext',
entryId: 'UIText', entryId: 'UIText',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent', componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.TextComponent',
displayOrder: suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : 2, displayOrder: suffix === 'Cost' ? 0 : suffix === 'Name' ? 1 : 2,
enable: false,
components: [ 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 }), 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 }), sprite({ color: TRANSPARENT }),
@@ -221,8 +218,7 @@ function upsertUi() {
ui.ContentProto.Entities.push(child); ui.ContentProto.Entities.push(child);
byPath.set(path, child); byPath.set(path, child);
} else { } else {
child.jsonString.enable = true; child.jsonString.enable = false;
child.jsonString.visible = true;
child.jsonString['@components'][2].Text = cfg.value; child.jsonString['@components'][2].Text = cfg.value;
child.jsonString['@components'][2].FontSize = cfg.fontSize; child.jsonString['@components'][2].FontSize = cfg.fontSize;
child.jsonString['@components'][2].MaxSize = cfg.fontSize; child.jsonString['@components'][2].MaxSize = cfg.fontSize;
@@ -230,8 +226,75 @@ function upsertUi() {
} }
} }
const hud = []; const ents = [];
const add = (e) => hud.push(e); const add = (e) => ents.push(e);
add(entity({
id: guid('menu', 0),
path: '/ui/DefaultGroup/MainMenu',
modelId: 'uisprite',
entryId: 'UISprite',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 20,
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.96 }, type: 1, raycast: true }),
],
}));
add(entity({
id: guid('menu', 1),
path: '/ui/DefaultGroup/MainMenu/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: 720, y: 100 }, pos: { x: 0, y: 180 }, align: ALIGN_CENTER }),
sprite({ color: TRANSPARENT }),
text({ value: '슬레이 메이플', fontSize: 64, bold: true, color: GOLD, alignment: 0 }),
],
}));
add(entity({
id: guid('menu', 2),
path: '/ui/DefaultGroup/MainMenu/Subtitle',
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: 760, y: 48 }, pos: { x: 0, y: 104 }, align: ALIGN_CENTER }),
sprite({ color: TRANSPARENT }),
text({ value: '카드를 뽑고, 덱을 만들고, 첨탑을 오른다', fontSize: 24, color: { r: 0.82, g: 0.86, b: 0.9, a: 1 }, alignment: 0 }),
],
}));
add(entity({
id: guid('menu', 3),
path: '/ui/DefaultGroup/MainMenu/NewGameButton',
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: 260, y: 68 }, pos: { x: 0, y: -20 }, align: ALIGN_CENTER }),
sprite({ color: { r: 0.13, g: 0.15, b: 0.18, a: 1 }, type: 1, raycast: true }),
button(),
text({ value: '새 게임', fontSize: 30, bold: true, color: GOLD, alignment: 0 }),
],
}));
add(entity({
id: guid('menu', 4),
path: '/ui/DefaultGroup/MainMenu/ContinueButton',
modelId: 'uibutton',
entryId: 'UIButton',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent,MOD.Core.ButtonComponent,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: 260, y: 58 }, pos: { x: 0, y: -100 }, align: ALIGN_CENTER }),
sprite({ color: { r: 0.1, g: 0.11, b: 0.13, a: 0.78 }, type: 1, raycast: false }),
button({ enabled: false }),
text({ value: '이어하기', fontSize: 24, bold: true, color: { r: 0.55, g: 0.58, b: 0.62, a: 1 }, alignment: 0 }),
],
}));
add(entity({ add(entity({
id: guid('hud', 0), id: guid('hud', 0),
@@ -240,6 +303,7 @@ function upsertUi() {
entryId: 'UIEmpty', entryId: 'UIEmpty',
componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent', componentNames: 'MOD.Core.UITransformComponent,MOD.Core.SpriteGUIRendererComponent',
displayOrder: 5, displayOrder: 5,
enable: false,
components: [ components: [
transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1280, y: 330 }, pos: { x: 0, y: 180 }, align: ALIGN_BOTTOM_CENTER }), transform({ parentW: 1920, parentH: 1080, anchor: { x: 0.5, y: 0 }, pivot: { x: 0.5, y: 0.5 }, size: { x: 1280, y: 330 }, pos: { x: 0, y: 180 }, align: ALIGN_BOTTOM_CENTER }),
sprite({ color: TRANSPARENT }), sprite({ color: TRANSPARENT }),
@@ -247,11 +311,11 @@ function upsertUi() {
})); }));
for (const pile of [ for (const pile of [
{ key: 'DrawPile', x: -590, label: '뽑을 덱', count: '10', color: { r: 0.17, g: 0.20, b: 0.25, a: 1 } }, { key: 'DrawPile', x: -590, label: '뽑을 덱', count: '10', color: { r: 0.17, g: 0.2, b: 0.25, a: 1 } },
{ key: 'DiscardPile', x: 590, label: '버린 덱', count: '0', color: { r: 0.22, g: 0.18, b: 0.16, a: 1 } }, { key: 'DiscardPile', x: 590, label: '버린 덱', count: '0', color: { r: 0.22, g: 0.18, b: 0.16, a: 1 } },
]) { ]) {
add(entity({ add(entity({
id: guid('hud', hud.length), id: guid('hud', ents.length),
path: `/ui/DefaultGroup/DeckHud/${pile.key}`, path: `/ui/DefaultGroup/DeckHud/${pile.key}`,
modelId: 'uisprite', modelId: 'uisprite',
entryId: 'UISprite', entryId: 'UISprite',
@@ -263,7 +327,7 @@ function upsertUi() {
], ],
})); }));
add(entity({ add(entity({
id: guid('hud', hud.length), id: guid('hud', ents.length),
path: `/ui/DefaultGroup/DeckHud/${pile.key}/Label`, path: `/ui/DefaultGroup/DeckHud/${pile.key}/Label`,
modelId: 'uitext', modelId: 'uitext',
entryId: 'UIText', entryId: 'UIText',
@@ -276,7 +340,7 @@ function upsertUi() {
], ],
})); }));
add(entity({ add(entity({
id: guid('hud', hud.length), id: guid('hud', ents.length),
path: `/ui/DefaultGroup/DeckHud/${pile.key}/Count`, path: `/ui/DefaultGroup/DeckHud/${pile.key}/Count`,
modelId: 'uitext', modelId: 'uitext',
entryId: 'UIText', entryId: 'UIText',
@@ -291,7 +355,7 @@ function upsertUi() {
} }
add(entity({ add(entity({
id: guid('hud', hud.length), id: guid('hud', ents.length),
path: '/ui/DefaultGroup/DeckHud/EndTurnButton', path: '/ui/DefaultGroup/DeckHud/EndTurnButton',
modelId: 'uibutton', modelId: 'uibutton',
entryId: 'UIButton', entryId: 'UIButton',
@@ -304,9 +368,8 @@ function upsertUi() {
text({ value: '턴 종료', fontSize: 25, bold: true, color: GOLD, alignment: 0 }), text({ value: '턴 종료', fontSize: 25, bold: true, color: GOLD, alignment: 0 }),
], ],
})); }));
add(entity({ add(entity({
id: guid('hud', hud.length), id: guid('hud', ents.length),
path: '/ui/DefaultGroup/DeckHud/Energy', path: '/ui/DefaultGroup/DeckHud/Energy',
modelId: 'uitext', modelId: 'uitext',
entryId: 'UIText', entryId: 'UIText',
@@ -319,7 +382,7 @@ function upsertUi() {
], ],
})); }));
ui.ContentProto.Entities.push(...hud); ui.ContentProto.Entities.push(...ents);
JSON.parse(JSON.stringify(ui)); JSON.parse(JSON.stringify(ui));
writeFileSync(UI_FILE, JSON.stringify(ui, null, 2), 'utf8'); writeFileSync(UI_FILE, JSON.stringify(ui, null, 2), 'utf8');
} }
@@ -328,13 +391,13 @@ function prop(Type, Name, DefaultValue = 'nil') {
return { Type, DefaultValue, SyncDirection: 0, Attributes: [], Name }; return { Type, DefaultValue, SyncDirection: 0, Attributes: [], Name };
} }
function method(Name, Code, Arguments = [], ExecSpace = 0) { function method(Name, Code, Arguments = []) {
return { return {
Return: { Type: 'void', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: null }, Return: { Type: 'void', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: null },
Arguments, Arguments,
Code, Code,
Scope: 2, Scope: 2,
ExecSpace, ExecSpace: 6,
Attributes: [], Attributes: [],
Name, Name,
}; };
@@ -383,8 +446,26 @@ function writeCodeblocks() {
prop('number', 'Turn', '0'), prop('number', 'Turn', '0'),
prop('number', 'TweenEventId', '0'), prop('number', 'TweenEventId', '0'),
prop('any', 'EndTurnHandler'), prop('any', 'EndTurnHandler'),
prop('any', 'NewGameHandler'),
], [ ], [
method('OnBeginPlay', `self:StartCombat()`), method('OnBeginPlay', `self:ShowMainMenu()`),
method('ShowMainMenu', `self:SetEntityEnabled("/ui/DefaultGroup/MainMenu", true)
self:SetEntityEnabled("/ui/DefaultGroup/CardHand", false)
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", false)
self:BindMenuButtons()`),
method('BindMenuButtons', `local buttonEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/NewGameButton")
if buttonEntity == nil or buttonEntity.ButtonComponent == nil then
\treturn
end
if self.NewGameHandler ~= nil then
\tbuttonEntity:DisconnectEvent(ButtonClickEvent, self.NewGameHandler)
\tself.NewGameHandler = nil
end
self.NewGameHandler = buttonEntity:ConnectEvent(ButtonClickEvent, self.StartNewGame)`),
method('StartNewGame', `self:SetEntityEnabled("/ui/DefaultGroup/MainMenu", false)
self:SetEntityEnabled("/ui/DefaultGroup/CardHand", true)
self:SetEntityEnabled("/ui/DefaultGroup/DeckHud", true)
self:StartCombat()`),
method('StartCombat', `self.MaxEnergy = 3 method('StartCombat', `self.MaxEnergy = 3
self.Turn = 0 self.Turn = 0
self.DiscardPile = {} self.DiscardPile = {}
@@ -491,8 +572,6 @@ if cardEntity ~= nil and cardEntity.SpriteGUIRendererComponent ~= nil then
\t\tok, color = pcall(function() return Color(0.86, 0.42, 0.38, 1) end) \t\tok, color = pcall(function() return Color(0.86, 0.42, 0.38, 1) end)
\telseif kind == "Skill" then \telseif kind == "Skill" then
\t\tok, color = pcall(function() return Color(0.42, 0.55, 0.85, 1) end) \t\tok, color = pcall(function() return Color(0.42, 0.55, 0.85, 1) end)
\telse
\t\tok, color = pcall(function() return Color(0.46, 0.68, 0.52, 1) end)
\tend \tend
\tif ok == true and color ~= nil then \tif ok == true and color ~= nil then
\t\tcardEntity.SpriteGUIRendererComponent.Color = color \t\tcardEntity.SpriteGUIRendererComponent.Color = color
@@ -508,6 +587,13 @@ end`, [
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }, { Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' }, { Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' },
]), ]),
method('SetEntityEnabled', `local entity = _EntityService:GetEntityByPath(path)
if entity ~= nil then
\tentity.Enable = enabled
end`, [
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'enabled' },
]),
method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot)) method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
if cardEntity == nil or cardEntity.UITransformComponent == nil then if cardEntity == nil or cardEntity.UITransformComponent == nil then
\treturn \treturn
@@ -531,9 +617,6 @@ end, 1 / 60)`, [
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' }, { Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' },
]), ]),
]); ]);
for (const m of combat.ContentProto.Json.Methods) {
m.ExecSpace = 6;
}
writeFileSync('RootDesk/MyDesk/SlayDeckController.codeblock', JSON.stringify(combat, null, 2), 'utf8'); writeFileSync('RootDesk/MyDesk/SlayDeckController.codeblock', JSON.stringify(combat, null, 2), 'utf8');
} }
@@ -552,4 +635,4 @@ upsertUi();
writeCodeblocks(); writeCodeblocks();
patchCommon(); patchCommon();
console.log('Slay deck UI and combat codeblocks generated.'); console.log('Slay deck UI and main menu generated.');

File diff suppressed because it is too large Load Diff