덱 컨트롤러 생성기: 핸들러 클로저화·카드데이터 단일화·카드클릭 사용·pcall 제거

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 01:07:46 +09:00
parent 6c392764d5
commit 5bc5b3dc5c

View File

@@ -193,6 +193,14 @@ 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;
sp.RaycastTarget = true;
const comps = card.jsonString['@components'];
if (!comps.some((c) => c['@type'] === 'MOD.Core.ButtonComponent')) {
comps.push(button());
}
if (!card.componentNames.includes('MOD.Core.ButtonComponent')) {
card.componentNames += ',MOD.Core.ButtonComponent';
}
card.jsonString.enable = true; card.jsonString.enable = true;
card.jsonString.visible = true; card.jsonString.visible = true;
@@ -383,12 +391,18 @@ 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', 'Cards'),
], [ ], [
method('OnBeginPlay', `self:StartCombat()`), method('OnBeginPlay', `self:StartCombat()`),
method('StartCombat', `self.MaxEnergy = 3 method('StartCombat', `self.MaxEnergy = 3
self.Turn = 0 self.Turn = 0
self.DiscardPile = {} self.DiscardPile = {}
self.Hand = {} self.Hand = {}
self.Cards = {
Strike = { name = "타격", cost = 1, desc = "피해 6", kind = "Attack" },
Defend = { name = "방어", cost = 1, desc = "방어도 5", kind = "Skill" },
Bash = { name = "강타", cost = 2, desc = "피해 10", kind = "Attack" },
}
self.DrawPile = { "Strike", "Strike", "Strike", "Strike", "Strike", "Defend", "Defend", "Defend", "Defend", "Bash" } self.DrawPile = { "Strike", "Strike", "Strike", "Strike", "Strike", "Defend", "Defend", "Defend", "Defend", "Bash" }
self:Shuffle(self.DrawPile) self:Shuffle(self.DrawPile)
self:BindButtons() self:BindButtons()
@@ -400,15 +414,20 @@ for i = #list, 2, -1 do
\tlocal j = math.random(1, i) \tlocal j = math.random(1, i)
\tlist[i], list[j] = list[j], list[i] \tlist[i], list[j] = list[j], list[i]
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'list' }]), end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'list' }]),
method('BindButtons', `local buttonEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/EndTurnButton") method('BindButtons', `local endTurn = _EntityService:GetEntityByPath("/ui/DefaultGroup/DeckHud/EndTurnButton")
if buttonEntity == nil or buttonEntity.ButtonComponent == nil then if endTurn ~= nil and endTurn.ButtonComponent ~= nil then
\treturn
end
if self.EndTurnHandler ~= nil then if self.EndTurnHandler ~= nil then
\tbuttonEntity:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler) endTurn:DisconnectEvent(ButtonClickEvent, self.EndTurnHandler)
\tself.EndTurnHandler = nil self.EndTurnHandler = nil
end end
self.EndTurnHandler = buttonEntity:ConnectEvent(ButtonClickEvent, self.EndPlayerTurn)`), self.EndTurnHandler = endTurn:ConnectEvent(ButtonClickEvent, function() self:EndPlayerTurn() 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
cardEntity:ConnectEvent(ButtonClickEvent, function() self:PlayCard(i) end)
end
end`),
method('StartPlayerTurn', `self.Turn = self.Turn + 1 method('StartPlayerTurn', `self.Turn = self.Turn + 1
self.Energy = self.MaxEnergy self.Energy = self.MaxEnergy
self:DrawCards(5) self:DrawCards(5)
@@ -460,43 +479,22 @@ for i = 1, 5 do
\tend \tend
end end
self:RenderPiles()`, [{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' }]), self:RenderPiles()`, [{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' }]),
method('ApplyCardVisual', `local name = cardId method('ApplyCardVisual', `local c = self.Cards[cardId]
local cost = 0 if c == nil then
local desc = "" c = { name = cardId, cost = 0, desc = "", kind = "Skill" }
local kind = "Skill"
if cardId == "Strike" then
\tname = "타격"
\tcost = 1
\tdesc = "피해 6"
\tkind = "Attack"
elseif cardId == "Defend" then
\tname = "방어"
\tcost = 1
\tdesc = "방어도 5"
\tkind = "Skill"
elseif cardId == "Bash" then
\tname = "강타"
\tcost = 2
\tdesc = "피해 10"
\tkind = "Attack"
end end
self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Cost", tostring(cost)) self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Cost", tostring(c.cost))
self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Name", name) self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Name", c.name)
self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Desc", desc) self:SetText("/ui/DefaultGroup/CardHand/Card" .. tostring(slot) .. "/Desc", c.desc)
local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot)) local cardEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/CardHand/Card" .. tostring(slot))
if cardEntity ~= nil and cardEntity.SpriteGUIRendererComponent ~= nil then if cardEntity ~= nil and cardEntity.SpriteGUIRendererComponent ~= nil then
\tlocal ok = false if c.kind == "Attack" then
\tlocal color = nil cardEntity.SpriteGUIRendererComponent.Color = Color(0.86, 0.42, 0.38, 1)
\tif kind == "Attack" then elseif c.kind == "Skill" then
\t\tok, color = pcall(function() return Color(0.86, 0.42, 0.38, 1) end) cardEntity.SpriteGUIRendererComponent.Color = Color(0.42, 0.55, 0.85, 1)
\telseif kind == "Skill" then else
\t\tok, color = pcall(function() return Color(0.42, 0.55, 0.85, 1) end) cardEntity.SpriteGUIRendererComponent.Color = Color(0.46, 0.68, 0.52, 1)
\telse end
\t\tok, color = pcall(function() return Color(0.46, 0.68, 0.52, 1) end)
\tend
\tif ok == true and color ~= nil then
\t\tcardEntity.SpriteGUIRendererComponent.Color = color
\tend
end`, [ end`, [
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }, { Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' }, { Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
@@ -530,6 +528,28 @@ end, 1 / 60)`, [
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'toPos' }, { Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'toPos' },
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' }, { Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' },
]), ]),
method('PlayCard', `if self.Hand == nil then
return
end
local cardId = self.Hand[slot]
if cardId == nil then
return
end
local c = self.Cards[cardId]
if c == nil then
return
end
if self.Energy < c.cost then
self:Toast("에너지가 부족합니다")
return
end
self.Energy = self.Energy - c.cost
self:Toast(c.name .. " — " .. c.desc)
table.remove(self.Hand, slot)
table.insert(self.DiscardPile, cardId)
self:RenderHand(false)
self:RenderPiles()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
method('Toast', `log(message)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'message' }]),
]); ]);
for (const m of combat.ContentProto.Json.Methods) { for (const m of combat.ContentProto.Json.Methods) {
m.ExecSpace = 6; m.ExecSpace = 6;