merge: origin/main 통합 — hand.mjs 공격 라운드는 main의 RunAttackSequence 채택(히트별 정수 데미지로 floor 수정 대체), 산출물 재생성
- 충돌 해소: tools/deck/cb/hand.mjs = main 버전(RunAttackSequence 리팩터가 total/hitN 나눗셈 자체를 제거해 수정② 소수 데미지 픽스를 구조적으로 대체) - SlayDeckController.codeblock = 재생성 (수동 편집 없음) - 수정①③④⑤⑥은 자동 머지로 유지 확인 (combat.mjs ShowDmgPop 중복 없음, items.mjs 물약 중복팝업 제거 유지, shop.mjs HasRelic 필터 유지, reward.mjs 스킵 조건 유지, deckview.mjs CodexMode 처리 유지) - 가드: cardkinds 261장 이상 0 · cbprops 0 · cbgap GAP 0 · 테스트 126/126 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Ten5ewG6HUZMqgzFLfQ8d
This commit is contained in:
@@ -77,4 +77,7 @@ end`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'enabled' },
|
||||
], 2),
|
||||
method('IntStr', `return string.format("%d", math.floor((n or 0) + 0.00001))`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'n' },
|
||||
], 0, 'string'),
|
||||
];
|
||||
|
||||
@@ -38,7 +38,7 @@ if c == nil then
|
||||
return
|
||||
end
|
||||
if c.unplayable == true then
|
||||
self:Toast("사용할 수 없는 카드입니다")
|
||||
self:Toast("사용할 수 없는 카드입니다")
|
||||
return
|
||||
end
|
||||
if self:CanPlayCardNow(c) ~= true then
|
||||
@@ -49,6 +49,8 @@ local skillFree = false
|
||||
local skillRepeat = 0
|
||||
if self.HandCostZeroThisTurn == true then
|
||||
cost = 0
|
||||
elseif self.ZeroCostCardIdsThisTurn ~= nil and self.ZeroCostCardIdsThisTurn[cardId] == true then
|
||||
cost = 0
|
||||
elseif c.useAllEnergy == true then
|
||||
cost = self.Energy
|
||||
end
|
||||
@@ -71,6 +73,8 @@ if self.Energy < cost then
|
||||
end
|
||||
self.Energy = self.Energy - cost
|
||||
self.ActiveKillReward = c.rewardOnKill or 0
|
||||
self.ActiveKillMaxHpGain = c.maxHpOnKill or 0
|
||||
table.remove(self.Hand, slot)
|
||||
self:ResolveCardEffects(cardId, slot, c, false, cost)
|
||||
local function applyCardPlayHooks()
|
||||
if self:HasPowerField("cardPlayedBlock") == true then
|
||||
@@ -82,6 +86,8 @@ local function applyCardPlayHooks()
|
||||
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
||||
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
||||
end
|
||||
self:ApplyAttackCardPlayHooks(c)
|
||||
self:ApplyHolyForceCardPlayHooks(c)
|
||||
end
|
||||
applyCardPlayHooks()
|
||||
if skillRepeat > 0 then
|
||||
@@ -106,16 +112,19 @@ end
|
||||
if self.ActiveKillReward ~= nil and self.ActiveKillReward <= 0 then
|
||||
self.ActiveKillReward = 0
|
||||
end
|
||||
if self.ActiveKillMaxHpGain ~= nil and self.ActiveKillMaxHpGain <= 0 then
|
||||
self.ActiveKillMaxHpGain = 0
|
||||
end
|
||||
if c.combatCostReductionOnPlay ~= nil and c.combatCostReductionOnPlay > 0 then
|
||||
if self.CombatCardCostReduction == nil then
|
||||
self.CombatCardCostReduction = {}
|
||||
end
|
||||
self.CombatCardCostReduction[cardId] = (self.CombatCardCostReduction[cardId] or 0) + c.combatCostReductionOnPlay
|
||||
end
|
||||
table.remove(self.Hand, slot)
|
||||
if c.exhaust == true then
|
||||
if self.ExhaustPile == nil then self.ExhaustPile = {} end
|
||||
table.insert(self.ExhaustPile, cardId)
|
||||
self:TriggerExhaustEffects(1)
|
||||
elseif c.kind ~= "Power" then
|
||||
table.insert(self.DiscardPile, cardId)
|
||||
end
|
||||
@@ -163,8 +172,8 @@ for i = 1, #self.Monsters do
|
||||
local m = self.Monsters[i]
|
||||
local active = false
|
||||
if m ~= nil and m.alive == true and i == shownTarget then active = true end
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i) .. "/TargetMarker", active and dragActive)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i) .. "/TargetMarker/Label", active and dragActive)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(i) .. "/TargetMarker", active and dragActive)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(i) .. "/TargetMarker/Label", active and dragActive)
|
||||
end`),
|
||||
method('OnCardDragBegin', `if self.CombatOver == true or self.FxBusy == true or self.TurnBusy == true then
|
||||
return
|
||||
@@ -177,7 +186,7 @@ if self.CardHoverTweenId ~= nil and self.CardHoverTweenId ~= 0 then
|
||||
self.CardHoverTweenId = 0
|
||||
end
|
||||
for i = 1, 10 do
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(i))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(i), 0)
|
||||
@@ -189,7 +198,7 @@ self:RenderTargetFrames()`, [{ Type: 'number', DefaultValue: null, SyncDirection
|
||||
method('OnCardDrag', `if self.DragSlot ~= slot then
|
||||
return
|
||||
end
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
local ui = _UILogic:ScreenToUIPosition(touchPoint)
|
||||
e.UITransformComponent.anchoredPosition = Vector2(ui.x, ui.y + 360)
|
||||
@@ -211,7 +220,7 @@ end`, [
|
||||
return
|
||||
end
|
||||
self.DragSlot = 0
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(slot), 0)
|
||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||
@@ -288,6 +297,7 @@ if m.block > 0 and pierce ~= true then
|
||||
m.block = m.block - absorbed
|
||||
dmg = dmg - absorbed
|
||||
end
|
||||
self:ShakeCombatCamera()
|
||||
m.hp = m.hp - dmg
|
||||
if dmg > 0 then
|
||||
local poison = self:AddPowerFieldTotal("attackPoison")
|
||||
@@ -301,6 +311,13 @@ local killed = false
|
||||
if m.hp <= 0 then
|
||||
m.hp = 0
|
||||
self:KillMonster(m.slot)
|
||||
if self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + self.ActiveKillReward
|
||||
end
|
||||
if self.ActiveKillMaxHpGain ~= nil and self.ActiveKillMaxHpGain > 0 then
|
||||
self.PlayerMaxHp = self.PlayerMaxHp + self.ActiveKillMaxHpGain
|
||||
self.PlayerHp = self.PlayerHp + self.ActiveKillMaxHpGain
|
||||
end
|
||||
killed = true
|
||||
end
|
||||
return killed`, [
|
||||
@@ -317,6 +334,7 @@ end
|
||||
if m == nil then
|
||||
return false
|
||||
end
|
||||
self:ShakeCombatCamera()
|
||||
m.hp = m.hp - amount
|
||||
self:ShowDmgPop(m.slot, amount)
|
||||
self:MonsterHitMotion(m.slot)
|
||||
@@ -343,6 +361,7 @@ local m = alive[math.random(1, #alive)]
|
||||
if m == nil then
|
||||
return false
|
||||
end
|
||||
self:ShakeCombatCamera()
|
||||
m.hp = m.hp - amount
|
||||
self:ShowDmgPop(m.slot, amount)
|
||||
self:MonsterHitMotion(m.slot)
|
||||
@@ -368,7 +387,7 @@ local burstEvery = self:AddPowerFieldTotal("poisonApplicationBurstEvery")
|
||||
local burstDamage = self:AddPowerFieldTotal("poisonApplicationBurstDamage")
|
||||
if burstEvery ~= nil and burstEvery > 0 and burstDamage ~= nil and burstDamage > 0 then
|
||||
if (self.PoisonApplicationsThisCombat % burstEvery) == 0 then
|
||||
self:DealDamageToAllMonsters(burstDamage)
|
||||
self:DealDamageToAllMonsters(burstDamage, false)
|
||||
end
|
||||
end`, [
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'target' },
|
||||
@@ -377,6 +396,17 @@ end`, [
|
||||
method('DealDamageToAllMonsters', `if self.Monsters == nil then
|
||||
return false
|
||||
end
|
||||
local anyAlive = false
|
||||
for i = 1, #self.Monsters do
|
||||
local m = self.Monsters[i]
|
||||
if m ~= nil and m.alive == true then
|
||||
anyAlive = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if anyAlive == true and isAttack == true then
|
||||
self:ShakeCombatCamera()
|
||||
end
|
||||
local killCount = 0
|
||||
for i = 1, #self.Monsters do
|
||||
local m = self.Monsters[i]
|
||||
@@ -412,6 +442,11 @@ end
|
||||
if killCount > 0 and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + (killCount * self.ActiveKillReward)
|
||||
end
|
||||
if killCount > 0 and self.ActiveKillMaxHpGain ~= nil and self.ActiveKillMaxHpGain > 0 then
|
||||
local gain = killCount * self.ActiveKillMaxHpGain
|
||||
self.PlayerMaxHp = self.PlayerMaxHp + gain
|
||||
self.PlayerHp = self.PlayerHp + gain
|
||||
end
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
return killCount > 0`, [
|
||||
@@ -420,6 +455,13 @@ return killCount > 0`, [
|
||||
], 0, 'boolean'),
|
||||
method('PlayAttackFx', `local m = self.Monsters[targetIndex]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
local shown = damage
|
||||
if m ~= nil and m.alive == true and m.vuln > 0 then
|
||||
shown = math.floor(damage * 1.5)
|
||||
end
|
||||
if m ~= nil and m.alive == true and m.weak > 0 and self.ActiveAttackDamageVsWeakMultiplier ~= nil and self.ActiveAttackDamageVsWeakMultiplier > 1 then
|
||||
shown = math.floor(shown * self.ActiveAttackDamageVsWeakMultiplier)
|
||||
end
|
||||
self:DealDamageToTarget(damage, pierce)
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:RenderCombat()
|
||||
@@ -451,12 +493,9 @@ _TimerService:SetTimerOnce(function()
|
||||
shown = math.floor(shown * self.ActiveAttackDamageVsWeakMultiplier)
|
||||
end
|
||||
local killed = self:DealDamageToTarget(damage, pierce)
|
||||
if killed == true and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + self.ActiveKillReward
|
||||
end
|
||||
self.ActiveKillReward = 0
|
||||
self.ActiveKillMaxHpGain = 0
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:ShowDmgPop(targetIndex, shown)
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
end, 0.35)`, [
|
||||
@@ -511,10 +550,8 @@ _TimerService:SetTimerOnce(function()
|
||||
end
|
||||
end
|
||||
end
|
||||
if killCount > 0 and self.ActiveKillReward ~= nil and self.ActiveKillReward > 0 then
|
||||
self.BonusRewardScreens = (self.BonusRewardScreens or 0) + (killCount * self.ActiveKillReward)
|
||||
end
|
||||
self.ActiveKillReward = 0
|
||||
self.ActiveKillMaxHpGain = 0
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
@@ -531,11 +568,16 @@ if m.entity ~= nil and isvalid(m.entity) then
|
||||
local ent = m.entity
|
||||
_TimerService:SetTimerOnce(function() if isvalid(ent) then ent:SetVisible(false) end end, 0.4)
|
||||
end
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(slot), false)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(slot), false)
|
||||
for i = 1, #self.Monsters do
|
||||
if self.Monsters[i].alive == true then self.TargetIndex = i; break end
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('DealDamageToPlayer', `local dmg = amount
|
||||
local reduction = self:AddPowerFieldTotal("damageTakenReduction")
|
||||
if reduction ~= nil and reduction > 0 then
|
||||
reduction = math.min(0.75, reduction)
|
||||
dmg = math.floor(dmg * (1 - reduction))
|
||||
end
|
||||
if self.PlayerBlock > 0 then
|
||||
local absorbed = math.min(self.PlayerBlock, dmg)
|
||||
self.PlayerBlock = self.PlayerBlock - absorbed
|
||||
@@ -544,8 +586,20 @@ end
|
||||
if dmg > 0 and self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 and dmg > 1 then
|
||||
dmg = 1
|
||||
end
|
||||
self:ShakeCombatCamera()
|
||||
if dmg > 0 then
|
||||
self.PlayerHp = self.PlayerHp - dmg
|
||||
local reactiveBlock = self:AddPowerFieldTotal("blockOnDamaged")
|
||||
if reactiveBlock ~= nil and reactiveBlock > 0 then
|
||||
self:AddCardBlock(reactiveBlock)
|
||||
end
|
||||
if self.DamagePowerStrengthUsed ~= true then
|
||||
local reactiveStrength = self:AddPowerFieldTotal("strengthOnDamagedOnce")
|
||||
if reactiveStrength ~= nil and reactiveStrength > 0 then
|
||||
self.PlayerStr = self.PlayerStr + reactiveStrength
|
||||
self.DamagePowerStrengthUsed = true
|
||||
end
|
||||
end
|
||||
local reflect = self.PlayerThorns or 0
|
||||
if self:HasRelic("bronzeScales") then
|
||||
reflect = reflect + 3
|
||||
@@ -567,7 +621,7 @@ if dmg > 0 then
|
||||
end
|
||||
if self:HasRelic("centennialPuzzle") and self.FirstHpLossDone == false then
|
||||
self.FirstHpLossDone = true
|
||||
self:DrawCards(3)
|
||||
self:DrawCards(3, true)
|
||||
self:RenderHand(false)
|
||||
end
|
||||
end
|
||||
@@ -588,7 +642,7 @@ if idx == 0 or self.PlayerHp <= 0 then
|
||||
return
|
||||
end
|
||||
local m = self.Monsters[idx]
|
||||
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(idx)
|
||||
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(idx)
|
||||
self:SetEntityEnabled(base .. "/ActFrame", true)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local poisonTicks = 1
|
||||
|
||||
@@ -68,23 +68,68 @@ if allDeckClose ~= nil and (allDeckClose.ButtonComponent ~= nil or allDeckClose:
|
||||
allDeckClose:DisconnectEvent(ButtonClickEvent, self.AllDeckCloseHandler)
|
||||
self.AllDeckCloseHandler = nil
|
||||
end
|
||||
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||
self.AllDeckCloseHandler = allDeckClose:ConnectEvent(ButtonClickEvent, function() self:CloseAllDeck() end)
|
||||
end
|
||||
self:BindClassDeckTabs()
|
||||
local allDeckGrid = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid")
|
||||
if allDeckGrid ~= nil and (allDeckGrid.UITouchReceiveComponent ~= nil or allDeckGrid:AddComponent("UITouchReceiveComponent") ~= nil) then
|
||||
allDeckGrid:ConnectEvent(UITouchEnterEvent, function(ev) self.GridScrollActive = false; self:HoverGridCard("/ui/DeckUIGroup/DeckAllHud/Grid", ev.TouchPoint) end)
|
||||
allDeckGrid:ConnectEvent(UITouchDownEvent, function(ev) self.GridScrollActive = false; self:HoverGridCard("/ui/DeckUIGroup/DeckAllHud/Grid", ev.TouchPoint) end)
|
||||
allDeckGrid:ConnectEvent(UITouchDragEvent, function(ev) self.GridScrollActive = true; self:UnhoverGridCard("/ui/DeckUIGroup/DeckAllHud/Grid") end)
|
||||
allDeckGrid:ConnectEvent(UITouchEndDragEvent, function() self.GridScrollActive = false end)
|
||||
allDeckGrid:ConnectEvent(UITouchExitEvent, function() self.GridScrollActive = false; self:UnhoverGridCard("/ui/DeckUIGroup/DeckAllHud/Grid") end)
|
||||
end
|
||||
for i = 1, 120 do
|
||||
local allCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i))
|
||||
local allCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. self:IntStr(i))
|
||||
if allCard ~= nil and (allCard.ButtonComponent ~= nil or allCard:AddComponent("ButtonComponent") ~= nil) then
|
||||
if allCard.SpriteGUIRendererComponent ~= nil then
|
||||
allCard.SpriteGUIRendererComponent.RaycastTarget = true
|
||||
end
|
||||
local slot = i
|
||||
local cardPath = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. self:IntStr(i)
|
||||
allCard:ConnectEvent(ButtonStateChangeEvent, function(ev)
|
||||
local state = nil
|
||||
if ev ~= nil then
|
||||
state = ev.CurrentState or ev.ButtonState or ev.State
|
||||
end
|
||||
if state == ButtonState.Highlighted or state == ButtonState.Pressed or tostring(state) == "1" or tostring(state) == "2" then
|
||||
self:HoverCardByPath(cardPath)
|
||||
else
|
||||
self:UnhoverCardByPath(cardPath)
|
||||
end
|
||||
end)
|
||||
allCard:ConnectEvent(ButtonClickEvent, function() self:OnAllDeckCardButton(slot) end)
|
||||
end
|
||||
end
|
||||
local inspectGrid = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Grid")
|
||||
if inspectGrid ~= nil and (inspectGrid.UITouchReceiveComponent ~= nil or inspectGrid:AddComponent("UITouchReceiveComponent") ~= nil) then
|
||||
inspectGrid:ConnectEvent(UITouchEnterEvent, function(ev) self.GridScrollActive = false; self:HoverGridCard("/ui/DeckUIGroup/DeckInspectHud/Grid", ev.TouchPoint) end)
|
||||
inspectGrid:ConnectEvent(UITouchDownEvent, function(ev) self.GridScrollActive = false; self:HoverGridCard("/ui/DeckUIGroup/DeckInspectHud/Grid", ev.TouchPoint) end)
|
||||
inspectGrid:ConnectEvent(UITouchDragEvent, function(ev) self.GridScrollActive = true; self:UnhoverGridCard("/ui/DeckUIGroup/DeckInspectHud/Grid") end)
|
||||
inspectGrid:ConnectEvent(UITouchEndDragEvent, function() self.GridScrollActive = false end)
|
||||
inspectGrid:ConnectEvent(UITouchExitEvent, function() self.GridScrollActive = false; self:UnhoverGridCard("/ui/DeckUIGroup/DeckInspectHud/Grid") end)
|
||||
end
|
||||
for i = 1, 60 do
|
||||
local inspectCard = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. self:IntStr(i))
|
||||
if inspectCard ~= nil and (inspectCard.ButtonComponent ~= nil or inspectCard:AddComponent("ButtonComponent") ~= nil) then
|
||||
local cardPath = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. self:IntStr(i)
|
||||
inspectCard:ConnectEvent(ButtonStateChangeEvent, function(ev)
|
||||
local state = nil
|
||||
if ev ~= nil then
|
||||
state = ev.CurrentState or ev.ButtonState or ev.State
|
||||
end
|
||||
if state == ButtonState.Highlighted or state == ButtonState.Pressed or tostring(state) == "1" or tostring(state) == "2" then
|
||||
self:HoverCardByPath(cardPath)
|
||||
else
|
||||
self:UnhoverCardByPath(cardPath)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
for i = 1, 10 do
|
||||
local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||
local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(i))
|
||||
if cardEntity ~= nil and cardEntity.UITouchReceiveComponent ~= nil then
|
||||
local cardPath = "/ui/RunUIGroup/CardHand/Card" .. tostring(i)
|
||||
local cardPath = "/ui/RunUIGroup/CardHand/Card" .. self:IntStr(i)
|
||||
cardEntity:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||
cardEntity:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||
cardEntity:ConnectEvent(UITouchBeginDragEvent, function(ev) self:OnCardDragBegin(i) end)
|
||||
@@ -98,13 +143,15 @@ for i = 1, 10 do
|
||||
end
|
||||
end
|
||||
for i = 1, 3 do
|
||||
local rc = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud/Reward" .. tostring(i))
|
||||
local rc = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud/Reward" .. self:IntStr(i))
|
||||
if rc ~= nil and (rc.ButtonComponent ~= nil or rc:AddComponent("ButtonComponent") ~= nil) then
|
||||
rc:ConnectEvent(ButtonClickEvent, function() self:PickReward(i) end)
|
||||
if rc.UITouchReceiveComponent ~= nil then
|
||||
local cardPath = "/ui/RunUIGroup/RewardHud/Reward" .. tostring(i)
|
||||
local cardPath = "/ui/RunUIGroup/RewardHud/Reward" .. self:IntStr(i)
|
||||
rc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||
rc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||
rc:ConnectEvent(UITouchEnterEvent, function() self:HoverCardByPath(cardPath) end)
|
||||
rc:ConnectEvent(UITouchExitEvent, function() self:UnhoverCardByPath(cardPath) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -127,13 +174,15 @@ for i = 1, #mapNodeIds do
|
||||
end
|
||||
end
|
||||
for i = 1, 3 do
|
||||
local sc = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Card" .. tostring(i))
|
||||
local sc = _EntityService:GetEntityByPath("/ui/RunUIGroup/ShopHud/Card" .. self:IntStr(i))
|
||||
if sc ~= nil and (sc.ButtonComponent ~= nil or sc:AddComponent("ButtonComponent") ~= nil) then
|
||||
sc:ConnectEvent(ButtonClickEvent, function() self:BuyCard(i) end)
|
||||
if sc.UITouchReceiveComponent ~= nil then
|
||||
local cardPath = "/ui/RunUIGroup/ShopHud/Card" .. tostring(i)
|
||||
local cardPath = "/ui/RunUIGroup/ShopHud/Card" .. self:IntStr(i)
|
||||
sc:ConnectEvent(UITouchEnterEvent, function() self:SetCardHover(cardPath, true) end)
|
||||
sc:ConnectEvent(UITouchExitEvent, function() self:SetCardHover(cardPath, false) end)
|
||||
sc:ConnectEvent(UITouchEnterEvent, function() self:HoverCardByPath(cardPath) end)
|
||||
sc:ConnectEvent(UITouchExitEvent, function() self:UnhoverCardByPath(cardPath) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -150,13 +199,13 @@ if restLeave ~= nil and (restLeave.ButtonComponent ~= nil or restLeave:AddCompon
|
||||
restLeave:ConnectEvent(ButtonClickEvent, function() self:LeaveNode() end)
|
||||
end
|
||||
for i = 1, ${MAX_MONSTERS} do
|
||||
local ms = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i))
|
||||
local ms = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(i))
|
||||
if ms ~= nil and (ms.ButtonComponent ~= nil or ms:AddComponent("ButtonComponent") ~= nil) then
|
||||
ms:ConnectEvent(ButtonClickEvent, function() self:SetTarget(i) end)
|
||||
end
|
||||
end
|
||||
for i = 1, 10 do
|
||||
local rs = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. tostring(i))
|
||||
local rs = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. self:IntStr(i))
|
||||
if rs ~= nil and rs.UITouchReceiveComponent ~= nil then
|
||||
local idx = i
|
||||
rs:ConnectEvent(UITouchEnterEvent, function()
|
||||
@@ -170,7 +219,7 @@ for i = 1, 10 do
|
||||
end
|
||||
end
|
||||
for i = 1, 5 do
|
||||
local ps = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. tostring(i))
|
||||
local ps = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. self:IntStr(i))
|
||||
if ps ~= nil and ps.UITouchReceiveComponent ~= nil then
|
||||
local idx = i
|
||||
ps:ConnectEvent(UITouchEnterEvent, function()
|
||||
@@ -218,7 +267,7 @@ if jcJob ~= nil and (jcJob.ButtonComponent ~= nil or jcJob:AddComponent("ButtonC
|
||||
end
|
||||
for i = 1, 3 do
|
||||
local slotIdx = i
|
||||
local jb = _EntityService:GetEntityByPath("/ui/SelectUIGroup/JobSelectHud/Job_slot" .. tostring(i))
|
||||
local jb = _EntityService:GetEntityByPath("/ui/SelectUIGroup/JobSelectHud/Job_slot" .. self:IntStr(i))
|
||||
if jb ~= nil and (jb.ButtonComponent ~= nil or jb:AddComponent("ButtonComponent") ~= nil) then
|
||||
jb:ConnectEvent(ButtonClickEvent, function()
|
||||
if self.JobOpts ~= nil and self.JobOpts[slotIdx] ~= nil then
|
||||
@@ -243,6 +292,7 @@ self.BlockGainMultiplier = 1
|
||||
self:ApplyRelics("turnStart")
|
||||
if self.NextTurnKeepBlock == true then
|
||||
self.NextTurnKeepBlock = false
|
||||
elseif self:HasPowerEffect("keepBlock") == true then
|
||||
else
|
||||
self.PlayerBlock = 0
|
||||
end
|
||||
@@ -258,6 +308,7 @@ self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self.DrawDamageThisTurn = 0
|
||||
self.DrawPoisonThisTurn = 0
|
||||
self.ShivAoeThisCombat = false
|
||||
self.ZeroCostCardIdsThisTurn = {}
|
||||
self.SkillSlyOnPlayCards = self.SkillSlyOnPlayCards or {}
|
||||
self.TurnSkillSlyCards = {}
|
||||
self.EnemyStrengthLossThisTurn = 0
|
||||
@@ -275,6 +326,7 @@ if self.PlayerPowers ~= nil then
|
||||
self.Energy = self.Energy + pc.value
|
||||
elseif pc.powerEffect == "blockPerTurn" then
|
||||
self.PlayerBlock = self.PlayerBlock + pc.value
|
||||
elseif pc.powerEffect == "keepBlock" then
|
||||
elseif pc.powerEffect == "poisonPerTurn" then
|
||||
if self.Monsters ~= nil then
|
||||
for j = 1, #self.Monsters do
|
||||
@@ -288,6 +340,8 @@ if self.PlayerPowers ~= nil then
|
||||
if self.Monsters ~= nil then
|
||||
self:PlayAoeFx(pc.fx or pc.image, pc.value or 0)
|
||||
end
|
||||
elseif pc.powerEffect == "healPerTurn" then
|
||||
self.PlayerHp = math.min(self.PlayerMaxHp, self.PlayerHp + pc.value)
|
||||
end
|
||||
if pc.turnStartShiv ~= nil then
|
||||
self:AddCardsToHand("Shiv", pc.turnStartShiv)
|
||||
@@ -316,7 +370,7 @@ if self.NextTurnAddCards ~= nil then
|
||||
end
|
||||
local drawN = 5 + (self.NextTurnDraw or 0) + powerTurnDraw
|
||||
self.NextTurnDraw = 0
|
||||
self:DrawCards(drawN)
|
||||
self:DrawCards(drawN, true)
|
||||
self:RenderHand(true)
|
||||
self:RenderCombat()
|
||||
if powerTurnDiscard > 0 then
|
||||
@@ -481,8 +535,11 @@ for i = 1, amount do
|
||||
\t\tself:TriggerSly(cardId)
|
||||
\telse
|
||||
\t\ttable.insert(self.Hand, cardId)
|
||||
\t\tdrewAny = true
|
||||
\t\ttable.insert(drawnSlots, #self.Hand)
|
||||
\t\tlocal autoPlayed = self:TriggerDrawnCardAutoPlay(cardId)
|
||||
\t\tif autoPlayed ~= true then
|
||||
\t\t\tdrewAny = true
|
||||
\t\t\ttable.insert(drawnSlots, #self.Hand)
|
||||
\t\tend
|
||||
\tend
|
||||
end
|
||||
self:RenderPiles()
|
||||
@@ -495,8 +552,9 @@ if animate == true and #drawnSlots > 0 then
|
||||
\t\tlocal slot = drawnSlots[i]
|
||||
\t\tself:AnimateCardFrom(slot, drawStart, Vector2(self:GetHandSlotX(slot), 0), 0.08 + i * 0.045)
|
||||
\tend
|
||||
end
|
||||
return drawnCards
|
||||
end`, [
|
||||
`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' },
|
||||
], 0, 'any'),
|
||||
|
||||
@@ -44,7 +44,7 @@ end
|
||||
self:SetText("/ui/DeckUIGroup/DeckInspectHud/Title", title .. suffix)
|
||||
self:SetEntityEnabled("/ui/DeckUIGroup/DeckInspectHud/Empty", count <= 0)
|
||||
for i = 1, 60 do
|
||||
local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(i)
|
||||
local path = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. self:IntStr(i)
|
||||
local cardId = nil
|
||||
if pile ~= nil then
|
||||
cardId = pile[i]
|
||||
@@ -59,7 +59,7 @@ end`, [
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pile' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'title' },
|
||||
]),
|
||||
method('ApplyInspectCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. tostring(slot), cardId)`, [
|
||||
method('ApplyInspectCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckInspectHud/Grid/Card" .. self:IntStr(slot), cardId)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
]),
|
||||
@@ -227,7 +227,7 @@ self:SetText("/ui/DeckUIGroup/DeckAllHud/Title", title .. " (" .. tostring(count
|
||||
self:RenderClassDeckTabs()
|
||||
self:SetEntityEnabled("/ui/DeckUIGroup/DeckAllHud/Empty", count <= 0)
|
||||
for i = 1, 120 do
|
||||
local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(i)
|
||||
local path = "/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. self:IntStr(i)
|
||||
local cardId = pile[i]
|
||||
if cardId == nil then
|
||||
self:SetEntityEnabled(path, false)
|
||||
@@ -236,7 +236,7 @@ for i = 1, 120 do
|
||||
self:ApplyAllDeckCardVisual(i, cardId)
|
||||
end
|
||||
end`),
|
||||
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. tostring(slot), cardId)`, [
|
||||
method('ApplyAllDeckCardVisual', `self:ApplyCardFace("/ui/DeckUIGroup/DeckAllHud/Grid/Card" .. self:IntStr(slot), cardId)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
]),
|
||||
|
||||
@@ -56,7 +56,7 @@ if n > 8 then spacing = math.floor(1400 / n) end
|
||||
local startX = -((n - 1) * spacing) / 2
|
||||
local drawStart = Vector2(-590, 8)
|
||||
for i = 1, 10 do
|
||||
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(i))
|
||||
\tlocal cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(i))
|
||||
\tif cardEntity ~= nil then
|
||||
\t\tlocal cardId = self.Hand[i]
|
||||
\t\tif cardId == nil then
|
||||
@@ -151,7 +151,7 @@ if self.CardHoverTweenId ~= nil and self.CardHoverTweenId ~= 0 then
|
||||
end
|
||||
local items = {}
|
||||
for i = 1, count do
|
||||
local e = _EntityService:GetEntityByPath(prefix .. tostring(i))
|
||||
local e = _EntityService:GetEntityByPath(prefix .. self:IntStr(i))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
local tr = e.UITransformComponent
|
||||
local tx = xs[i]
|
||||
@@ -195,7 +195,7 @@ self.CardHoverTweenId = eventId`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hover' },
|
||||
]),
|
||||
method('ApplyCardVisual', `self:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. tostring(slot), cardId)`, [
|
||||
method('ApplyCardVisual', `self:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot), cardId)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
]),
|
||||
@@ -217,7 +217,7 @@ if math.abs(n - math.floor(n)) < 0.00001 then
|
||||
return string.format("%d", math.floor(n))
|
||||
end
|
||||
return tostring(n)`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' }], 0, 'string'),
|
||||
method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
method('AnimateCardFrom', `local cardEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
if cardEntity == nil or cardEntity.UITransformComponent == nil then
|
||||
\treturn
|
||||
end
|
||||
@@ -246,10 +246,10 @@ local target = Vector2(590, 8)
|
||||
local duration = 0.18
|
||||
for i = 1, #cardIds do
|
||||
\tlocal slot = slots[i] or i
|
||||
\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
\tif e ~= nil then
|
||||
\t\te.Enable = true
|
||||
\t\tself:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. tostring(slot), cardIds[i])
|
||||
\t\tself:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot), cardIds[i])
|
||||
\t\tif e.UITransformComponent ~= nil then
|
||||
\t\t\tlocal sx = 0
|
||||
\t\t\tif startXs ~= nil and startXs[i] ~= nil then sx = startXs[i] else sx = self:GetHandSlotX(slot) end
|
||||
@@ -266,7 +266,7 @@ eventId = _TimerService:SetTimerRepeat(function()
|
||||
\tlocal eased = _TweenLogic:Ease(0, 1, 1, EaseType.SineEaseIn, t)
|
||||
\tfor i = 1, #cardIds do
|
||||
\t\tlocal slot = slots[i] or i
|
||||
\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
\t\tif e ~= nil and e.UITransformComponent ~= nil then
|
||||
\t\t\tlocal sx = 0
|
||||
\t\t\tif startXs ~= nil and startXs[i] ~= nil then sx = startXs[i] else sx = self:GetHandSlotX(slot) end
|
||||
@@ -281,7 +281,7 @@ eventId = _TimerService:SetTimerRepeat(function()
|
||||
\t\t_TimerService:ClearTimer(eventId)
|
||||
\t\tfor i = 1, #cardIds do
|
||||
\t\t\tlocal slot = slots[i] or i
|
||||
\t\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
\t\t\tlocal e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
\t\t\tif e ~= nil then
|
||||
\t\t\t\tif self.Hand ~= nil and self.Hand[slot] ~= nil then
|
||||
\t\t\t\t\te.Enable = true
|
||||
@@ -313,6 +313,108 @@ if amount < 0 then
|
||||
end
|
||||
self.PlayerBlock = self.PlayerBlock + amount
|
||||
return amount`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
||||
method('RunAttackSequence', `if hitDamages == nil or #hitDamages <= 0 then
|
||||
return
|
||||
end
|
||||
local function countAliveMonsters()
|
||||
local n = 0
|
||||
if self.Monsters ~= nil then
|
||||
for mi = 1, #self.Monsters do
|
||||
local om = self.Monsters[mi]
|
||||
if om ~= nil and om.alive == true then
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return n
|
||||
end
|
||||
local function randomAliveMonsterIndex()
|
||||
local alive = {}
|
||||
if self.Monsters ~= nil then
|
||||
for mi = 1, #self.Monsters do
|
||||
local om = self.Monsters[mi]
|
||||
if om ~= nil and om.alive == true then
|
||||
table.insert(alive, mi)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #alive <= 0 then
|
||||
return 0
|
||||
end
|
||||
return alive[math.random(1, #alive)]
|
||||
end
|
||||
self.FxBusy = true
|
||||
local hitIndex = 1
|
||||
local lockedTargetIndex = self.TargetIndex or 0
|
||||
local function finishSequence()
|
||||
self.FxBusy = false
|
||||
self.ActiveAttackDamageVsWeakMultiplier = 1
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
end
|
||||
local function step()
|
||||
if self.CombatOver == true then
|
||||
finishSequence()
|
||||
return
|
||||
end
|
||||
if countAliveMonsters() <= 0 then
|
||||
finishSequence()
|
||||
return
|
||||
end
|
||||
if hitIndex == 1 then
|
||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + (roundPlannedDamage or 0)
|
||||
end
|
||||
local roundKilled = false
|
||||
if useAoe == true then
|
||||
roundKilled = self:DealDamageToAllMonsters(hitDamages[hitIndex] or 0, true)
|
||||
else
|
||||
local targetIdx = lockedTargetIndex
|
||||
if randomTargetEachHit == true then
|
||||
targetIdx = randomAliveMonsterIndex()
|
||||
end
|
||||
if targetIdx ~= nil and targetIdx > 0 then
|
||||
if randomTargetEachHit ~= true then
|
||||
local lockedMonster = nil
|
||||
if self.Monsters ~= nil then
|
||||
lockedMonster = self.Monsters[targetIdx]
|
||||
end
|
||||
if lockedMonster == nil or lockedMonster.alive ~= true then
|
||||
finishSequence()
|
||||
return
|
||||
end
|
||||
end
|
||||
local prev = self.TargetIndex
|
||||
self.TargetIndex = targetIdx
|
||||
roundKilled = self:DealDamageToTarget(hitDamages[hitIndex] or 0, pierce == true)
|
||||
self.TargetIndex = prev
|
||||
end
|
||||
end
|
||||
self:RenderCombat()
|
||||
self:CheckCombatEnd()
|
||||
hitIndex = hitIndex + 1
|
||||
if self.CombatOver == true then
|
||||
finishSequence()
|
||||
return
|
||||
end
|
||||
if hitIndex <= #hitDamages then
|
||||
_TimerService:SetTimerOnce(step, 0.2)
|
||||
return
|
||||
end
|
||||
if repeatOnKill == true and roundKilled == true and countAliveMonsters() > 0 then
|
||||
hitIndex = 1
|
||||
_TimerService:SetTimerOnce(step, 0.2)
|
||||
return
|
||||
end
|
||||
finishSequence()
|
||||
end
|
||||
step()`, [
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hitDamages' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'roundPlannedDamage' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'useAoe' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'randomTargetEachHit' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'pierce' },
|
||||
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'repeatOnKill' },
|
||||
]),
|
||||
method('CountOtherHandSkills', `if self.Hand == nil then
|
||||
return 0
|
||||
end
|
||||
@@ -326,7 +428,104 @@ for i = 1, #self.Hand do
|
||||
end
|
||||
end
|
||||
return n`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'number'),
|
||||
method('CountOwnedNameMatches', `if match == nil or match == "" then
|
||||
return 0
|
||||
end
|
||||
local n = 0
|
||||
local function countPile(pile)
|
||||
if pile == nil then return end
|
||||
for i = 1, #pile do
|
||||
local c2 = self.Cards[pile[i]]
|
||||
local name = ""
|
||||
if c2 ~= nil and c2.name ~= nil then name = c2.name end
|
||||
if string.find(name, match, 1, true) ~= nil then
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
countPile(self.Hand)
|
||||
countPile(self.DrawPile)
|
||||
countPile(self.DiscardPile)
|
||||
countPile(self.ExhaustPile)
|
||||
return n`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'match' }], 0, 'number'),
|
||||
method('MaxPowerField', `local best = 0
|
||||
if self.PlayerPowers == nil then
|
||||
return best
|
||||
end
|
||||
for i = 1, #self.PlayerPowers do
|
||||
local powerCard = self.Cards[self.PlayerPowers[i]]
|
||||
if powerCard ~= nil and powerCard[field] ~= nil and powerCard[field] > best then
|
||||
best = powerCard[field]
|
||||
end
|
||||
end
|
||||
return best`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'field' }], 0, 'number'),
|
||||
method('GetComboMax', `local comboMax = 5
|
||||
local powerMax = self:MaxPowerField("comboMax")
|
||||
if powerMax ~= nil and powerMax > comboMax then
|
||||
comboMax = powerMax
|
||||
end
|
||||
return comboMax`, [], 0, 'number'),
|
||||
method('GainCombo', `if amount == nil or amount <= 0 then
|
||||
return
|
||||
end
|
||||
self.ComboCount = math.min(self:GetComboMax(), (self.ComboCount or 0) + amount)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||
method('GetHolyChargeMax', `local chargeMax = 3
|
||||
local powerMax = self:MaxPowerField("holyChargeMax")
|
||||
if powerMax ~= nil and powerMax > chargeMax then
|
||||
chargeMax = powerMax
|
||||
end
|
||||
return chargeMax`, [], 0, 'number'),
|
||||
method('GainHolyCharge', `if amount == nil or amount <= 0 then
|
||||
return
|
||||
end
|
||||
self.HolyChargeCount = math.min(self:GetHolyChargeMax(), (self.HolyChargeCount or 0) + amount)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||
method('ApplyHolyForceCardPlayHooks', `if c == nil then
|
||||
return
|
||||
end
|
||||
local gain = c.holyChargeGain or 0
|
||||
if c.holyForce == true then
|
||||
gain = gain + self:AddPowerFieldTotal("holyChargeOnHolyForce")
|
||||
end
|
||||
self:GainHolyCharge(gain)
|
||||
if c.holyChargeSpendAll == true then
|
||||
self.HolyChargeCount = 0
|
||||
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
||||
method('ApplyAttackCardPlayHooks', `if c == nil or c.kind ~= "Attack" then
|
||||
return
|
||||
end
|
||||
local comboGain = c.comboGain or 0
|
||||
comboGain = comboGain + self:AddPowerFieldTotal("comboOnAttack")
|
||||
self:GainCombo(comboGain)
|
||||
local extraDamage = self:AddPowerFieldTotal("attackPlayedDamage")
|
||||
if extraDamage ~= nil and extraDamage > 0 then
|
||||
self:DealDirectDamageToTarget(extraDamage)
|
||||
end
|
||||
local weakAmount = self:AddPowerFieldTotal("attackWeak")
|
||||
if weakAmount ~= nil and weakAmount > 0 and self.Monsters ~= nil then
|
||||
local target = self.Monsters[self.TargetIndex]
|
||||
if target ~= nil and target.alive == true then
|
||||
if target.artifact ~= nil and target.artifact > 0 then
|
||||
target.artifact = target.artifact - 1
|
||||
else
|
||||
target.weak = (target.weak or 0) + weakAmount
|
||||
end
|
||||
end
|
||||
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
||||
method('AttackBaseForCard', `local base2 = c.damage or 0
|
||||
if c.damageNameMatch ~= nil and c.damagePerOwnedNameMatch ~= nil then
|
||||
base2 = base2 + self:CountOwnedNameMatches(c.damageNameMatch) * c.damagePerOwnedNameMatch
|
||||
end
|
||||
if c.damageFromCurrentBlock ~= nil and c.damageFromCurrentBlock ~= 0 then
|
||||
base2 = base2 + (self.PlayerBlock or 0) * c.damageFromCurrentBlock
|
||||
end
|
||||
local comboScale = c.damagePerCombo or 0
|
||||
comboScale = comboScale + self:AddPowerFieldTotal("attackDamagePerCombo")
|
||||
if comboScale ~= 0 then
|
||||
base2 = base2 + (self.ComboCount or 0) * comboScale
|
||||
end
|
||||
if c.damagePerHolyCharge ~= nil and c.damagePerHolyCharge ~= 0 then
|
||||
base2 = base2 + (self.HolyChargeCount or 0) * c.damagePerHolyCharge
|
||||
end
|
||||
local otherHand = 0
|
||||
if self.Hand ~= nil then
|
||||
otherHand = #self.Hand - 1
|
||||
@@ -365,6 +564,200 @@ return base2`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' },
|
||||
], 0, 'number'),
|
||||
method('TriggerExhaustEffects', `if count == nil or count <= 0 then
|
||||
return
|
||||
end
|
||||
local drawOnExhaust = self:AddPowerFieldTotal("drawOnExhaust")
|
||||
if drawOnExhaust ~= nil and drawOnExhaust > 0 then
|
||||
self:DrawCards(drawOnExhaust * count, true)
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'count' }]),
|
||||
method('MarkCardCostZeroThisTurn', `if cardId == nil or cardId == "" then
|
||||
return
|
||||
end
|
||||
if self.ZeroCostCardIdsThisTurn == nil then
|
||||
self.ZeroCostCardIdsThisTurn = {}
|
||||
end
|
||||
self.ZeroCostCardIdsThisTurn[cardId] = true`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' }]),
|
||||
method('AutoPlayCardId', `local c = self.Cards[cardId]
|
||||
if c == nil then
|
||||
return false
|
||||
end
|
||||
local spent = energySpent or 0
|
||||
local skillFree = false
|
||||
local skillRepeat = 0
|
||||
if c.kind == "Skill" and c.useAllEnergy ~= true and self.NextSkillCostZero == true then
|
||||
skillFree = true
|
||||
end
|
||||
if c.kind == "Skill" and self.NextSkillRepeatCount ~= nil and self.NextSkillRepeatCount > 0 then
|
||||
skillRepeat = self.NextSkillRepeatCount
|
||||
end
|
||||
self.ActiveKillReward = c.rewardOnKill or 0
|
||||
self.ActiveKillMaxHpGain = c.maxHpOnKill or 0
|
||||
self:ResolveCardEffects(cardId, 0, c, false, spent)
|
||||
local function applyCardPlayHooks()
|
||||
if self:HasPowerField("cardPlayedBlock") == true then
|
||||
self:AddCardBlock(self:AddPowerFieldTotal("cardPlayedBlock"))
|
||||
end
|
||||
if c.cardPlayedDamage ~= nil and c.cardPlayedDamage > 0 then
|
||||
self:DealDirectDamageToTarget(c.cardPlayedDamage)
|
||||
end
|
||||
if c.cardPlayedRandomDamage ~= nil and c.cardPlayedRandomDamage > 0 then
|
||||
self:DealDirectDamageToRandomMonster(c.cardPlayedRandomDamage)
|
||||
end
|
||||
self:ApplyAttackCardPlayHooks(c)
|
||||
self:ApplyHolyForceCardPlayHooks(c)
|
||||
end
|
||||
applyCardPlayHooks()
|
||||
if skillRepeat > 0 then
|
||||
local remaining = (self.NextSkillRepeatCount or 0) - skillRepeat
|
||||
if remaining < 0 then remaining = 0 end
|
||||
self.NextSkillRepeatCount = remaining
|
||||
for i = 1, skillRepeat do
|
||||
self:ResolveCardEffects(cardId, 0, c, false, spent)
|
||||
applyCardPlayHooks()
|
||||
end
|
||||
end
|
||||
if c.kind == "Attack" then
|
||||
self.TurnAttackCardsPlayed = (self.TurnAttackCardsPlayed or 0) + 1
|
||||
end
|
||||
if skillFree == true and c.nextSkillCostZero ~= true then
|
||||
self.NextSkillCostZero = false
|
||||
end
|
||||
if c.exhaust == true then
|
||||
if self.ExhaustPile == nil then self.ExhaustPile = {} end
|
||||
table.insert(self.ExhaustPile, cardId)
|
||||
self:TriggerExhaustEffects(1)
|
||||
elseif c.kind ~= "Power" then
|
||||
table.insert(self.DiscardPile, cardId)
|
||||
end
|
||||
if self.ActiveKillReward ~= nil and self.ActiveKillReward <= 0 then
|
||||
self.ActiveKillReward = 0
|
||||
end
|
||||
if self.ActiveKillMaxHpGain ~= nil and self.ActiveKillMaxHpGain <= 0 then
|
||||
self.ActiveKillMaxHpGain = 0
|
||||
end
|
||||
return true`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'energySpent' },
|
||||
], 0, 'boolean'),
|
||||
method('TriggerDrawnCardAutoPlay', `if cardId == nil or cardId == "" or self.Hand == nil or self.PlayerPowers == nil then
|
||||
return false
|
||||
end
|
||||
local c = self.Cards[cardId]
|
||||
if c == nil or c.name == nil or c.name == "" then
|
||||
return false
|
||||
end
|
||||
for i = 1, #self.PlayerPowers do
|
||||
local powerCard = self.Cards[self.PlayerPowers[i]]
|
||||
if powerCard ~= nil and powerCard.drawNameMatchAutoPlay ~= nil and powerCard.drawNameMatchAutoPlay ~= "" then
|
||||
if string.find(c.name, powerCard.drawNameMatchAutoPlay, 1, true) ~= nil then
|
||||
local foundSlot = 0
|
||||
for hi = 1, #self.Hand do
|
||||
if self.Hand[hi] == cardId then
|
||||
foundSlot = hi
|
||||
break
|
||||
end
|
||||
end
|
||||
if foundSlot <= 0 then
|
||||
return false
|
||||
end
|
||||
table.remove(self.Hand, foundSlot)
|
||||
self:AutoPlayCardId(cardId, 0)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' }], 0, 'boolean'),
|
||||
method('PlayTopDrawPileCards', `if c == nil or self.DrawPile == nil then
|
||||
return 0
|
||||
end
|
||||
local count = c.playTopDrawPileCount or 0
|
||||
if c.playTopDrawPileCountPerEnergy ~= nil and c.playTopDrawPileCountPerEnergy > 0 then
|
||||
count = count + ((energySpent or 0) * c.playTopDrawPileCountPerEnergy)
|
||||
end
|
||||
if count <= 0 then
|
||||
return 0
|
||||
end
|
||||
local played = 0
|
||||
for i = 1, count do
|
||||
if #self.DrawPile <= 0 then
|
||||
break
|
||||
end
|
||||
local topCardId = table.remove(self.DrawPile)
|
||||
if topCardId ~= nil then
|
||||
self:AutoPlayCardId(topCardId, 0)
|
||||
played = played + 1
|
||||
end
|
||||
end
|
||||
return played`, [
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'energySpent' },
|
||||
], 0, 'number'),
|
||||
method('AddRandomCardsFromEffect', `if c == nil or count == nil or count <= 0 then
|
||||
return 0
|
||||
end
|
||||
local pool = {}
|
||||
for id, rc in pairs(self.Cards) do
|
||||
if rc ~= nil and rc.token ~= true and rc.curse ~= true and rc.unplayable ~= true then
|
||||
local ok = true
|
||||
if c.addRandomCardKind ~= nil and rc.kind ~= c.addRandomCardKind then ok = false end
|
||||
if c.addRandomCardSameClass == true and rc.class ~= c.class then ok = false end
|
||||
if ok == true then table.insert(pool, id) end
|
||||
end
|
||||
end
|
||||
if #pool <= 0 then
|
||||
return 0
|
||||
end
|
||||
local added = 0
|
||||
for i = 1, count do
|
||||
local cardId2 = pool[math.random(1, #pool)]
|
||||
if cardId2 ~= nil then
|
||||
self:AddCardsToHand(cardId2, 1)
|
||||
if c.addedCardsCostZeroThisTurn == true then
|
||||
self:MarkCardCostZeroThisTurn(cardId2)
|
||||
end
|
||||
added = added + 1
|
||||
end
|
||||
end
|
||||
return added`, [
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'count' },
|
||||
], 0, 'number'),
|
||||
method('ExhaustHandNonAttack', `if c == nil or c.exhaustHandNonAttack ~= true or self.Hand == nil or #self.Hand <= 0 then
|
||||
return 0
|
||||
end
|
||||
local exhausted = 0
|
||||
for i = #self.Hand, 1, -1 do
|
||||
local cardId2 = self.Hand[i]
|
||||
local hc = self.Cards[cardId2]
|
||||
if hc == nil or hc.kind ~= "Attack" then
|
||||
table.remove(self.Hand, i)
|
||||
if self.ExhaustPile == nil then self.ExhaustPile = {} end
|
||||
table.insert(self.ExhaustPile, cardId2)
|
||||
exhausted = exhausted + 1
|
||||
end
|
||||
end
|
||||
if exhausted > 0 then
|
||||
if c.blockPerExhaustedCard ~= nil and c.blockPerExhaustedCard > 0 then
|
||||
self:AddCardBlock(exhausted * c.blockPerExhaustedCard)
|
||||
end
|
||||
self:TriggerExhaustEffects(exhausted)
|
||||
end
|
||||
return exhausted`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'number'),
|
||||
method('ExhaustHandAll', `if c == nil or c.exhaustHandAll ~= true or self.Hand == nil or #self.Hand <= 0 then
|
||||
return 0
|
||||
end
|
||||
local exhausted = 0
|
||||
while #self.Hand > 0 do
|
||||
local cardId2 = table.remove(self.Hand)
|
||||
if self.ExhaustPile == nil then self.ExhaustPile = {} end
|
||||
table.insert(self.ExhaustPile, cardId2)
|
||||
exhausted = exhausted + 1
|
||||
end
|
||||
if exhausted > 0 then
|
||||
self:TriggerExhaustEffects(exhausted)
|
||||
end
|
||||
return exhausted`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'number'),
|
||||
method('CalcPlayerAttack', `local base2 = base
|
||||
self.FightAttackCount = self.FightAttackCount + 1
|
||||
if self.FightAttackCount == 1 and self:HasRelic("akabeko") then
|
||||
@@ -485,14 +878,15 @@ if c.xWeakPerEnergy ~= nil and c.xWeakPerEnergy > 0 then
|
||||
weakAmount = weakAmount + xEnergy * c.xWeakPerEnergy
|
||||
end
|
||||
if c.kind == "Attack" then
|
||||
if c.damage ~= nil or c.xDamagePerEnergy ~= nil then
|
||||
if c.damage ~= nil or c.xDamagePerEnergy ~= nil or c.damageFromCurrentBlock ~= nil then
|
||||
self:PlayerAttackMotion()
|
||||
local baseDmg = self:AttackBaseForCard(slot, c)
|
||||
self.ActiveAttackDamageVsWeakMultiplier = c.attackDamageVsWeakMultiplier or 1
|
||||
self.ActiveAttackDamageVsWeakMultiplier = math.max(c.attackDamageVsWeakMultiplier or 1, self:MaxPowerField("attackDamageVsWeakMultiplier"))
|
||||
if c.xDamagePerEnergy ~= nil and c.xDamagePerEnergy > 0 then
|
||||
baseDmg = xEnergy * c.xDamagePerEnergy
|
||||
end
|
||||
local total = 0
|
||||
local hitDamages = {}
|
||||
local hitN = c.hits or 1
|
||||
if c.otherHandAtLeast ~= nil and c.bonusHitsWhenOtherHandAtLeast ~= nil then
|
||||
local otherHand = 0
|
||||
@@ -505,7 +899,9 @@ if c.kind == "Attack" then
|
||||
end
|
||||
end
|
||||
for h = 1, hitN do
|
||||
total = total + self:CalcPlayerAttack(baseDmg)
|
||||
local hitDamage = self:CalcPlayerAttack(baseDmg)
|
||||
hitDamages[h] = hitDamage
|
||||
total = total + hitDamage
|
||||
end
|
||||
local useAoe = c.aoe == true
|
||||
if c.class == "shiv" and (self.ShivAoeThisCombat == true or self:HasPowerField("shivAoe") == true) then
|
||||
@@ -514,70 +910,17 @@ if c.kind == "Attack" then
|
||||
if c.class == "shiv" and self.ShivFirstDamageBonusUsed ~= true and self:HasPowerField("firstShivDamageBonus") == true then
|
||||
self.ShivFirstDamageBonusUsed = true
|
||||
end
|
||||
local function countAliveMonsters()
|
||||
local n = 0
|
||||
if self.Monsters ~= nil then
|
||||
for mi = 1, #self.Monsters do
|
||||
local om = self.Monsters[mi]
|
||||
if om ~= nil and om.alive == true then n = n + 1 end
|
||||
end
|
||||
end
|
||||
return n
|
||||
end
|
||||
local function randomAliveMonsterIndex()
|
||||
local alive = {}
|
||||
if self.Monsters ~= nil then
|
||||
for mi = 1, #self.Monsters do
|
||||
local om = self.Monsters[mi]
|
||||
if om ~= nil and om.alive == true then
|
||||
table.insert(alive, mi)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #alive <= 0 then
|
||||
return 0
|
||||
end
|
||||
return alive[math.random(1, #alive)]
|
||||
end
|
||||
local function resolveAttackRound()
|
||||
local roundKilled = false
|
||||
if useAoe == true then
|
||||
local killed = self:DealDamageToAllMonsters(total, true)
|
||||
if killed == true then roundKilled = true end
|
||||
elseif c.randomTargetEachHit == true then
|
||||
for h = 1, hitN do
|
||||
local targetIdx = randomAliveMonsterIndex()
|
||||
if targetIdx ~= nil and targetIdx > 0 then
|
||||
local prev = self.TargetIndex
|
||||
self.TargetIndex = targetIdx
|
||||
local killed = self:DealDamageToTarget(math.floor(total / hitN), c.pierce == true)
|
||||
self.TargetIndex = prev
|
||||
if killed == true then roundKilled = true end
|
||||
end
|
||||
end
|
||||
else
|
||||
local killed = self:DealDamageToTarget(total, c.pierce == true)
|
||||
if killed == true then roundKilled = true end
|
||||
end
|
||||
return roundKilled
|
||||
end
|
||||
local totalDamage = 0
|
||||
local roundKilled = false
|
||||
repeat
|
||||
roundKilled = resolveAttackRound()
|
||||
totalDamage = totalDamage + total
|
||||
until c.repeatOnKill ~= true or roundKilled ~= true or countAliveMonsters() <= 0
|
||||
self.DamageDealtThisTurn = (self.DamageDealtThisTurn or 0) + totalDamage
|
||||
self:RunAttackSequence(hitDamages, total, useAoe, c.randomTargetEachHit == true, c.pierce == true, c.repeatOnKill == true)
|
||||
end
|
||||
if c.block ~= nil then
|
||||
self:AddCardBlock(c.block)
|
||||
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
||||
end
|
||||
if free ~= true then
|
||||
self:ApplyRelics("cardPlayed")
|
||||
end
|
||||
elseif c.kind == "Skill" then
|
||||
if c.block ~= nil then
|
||||
self:AddCardBlock(c.block)
|
||||
self:AddCardBlock(c.block + (self.HolyChargeCount or 0) * (c.blockPerHolyCharge or 0))
|
||||
end
|
||||
elseif c.kind == "Power" then
|
||||
if free ~= true then
|
||||
@@ -597,11 +940,19 @@ if c.selfVuln ~= nil then
|
||||
self.PlayerVuln = self.PlayerVuln + c.selfVuln
|
||||
end
|
||||
if c.heal ~= nil then
|
||||
self.PlayerHp = math.min(self.PlayerHp + c.heal, self.PlayerMaxHp)
|
||||
local healAmount = c.heal + (self.HolyChargeCount or 0) * (c.healPerHolyCharge or 0)
|
||||
self.PlayerHp = math.min(self.PlayerHp + healAmount, self.PlayerMaxHp)
|
||||
end
|
||||
if c.gainEnergy ~= nil and c.gainEnergy ~= 0 then
|
||||
self.Energy = self.Energy + c.gainEnergy
|
||||
end
|
||||
if c.kind ~= "Attack" and c.comboGain ~= nil and c.comboGain > 0 then
|
||||
self:GainCombo(c.comboGain)
|
||||
end
|
||||
if c.removePlayerDebuffs == true then
|
||||
self.PlayerWeak = 0
|
||||
self.PlayerVuln = 0
|
||||
end
|
||||
if c.intangible ~= nil and c.intangible > 0 then
|
||||
self.PlayerIntangible = (self.PlayerIntangible or 0) + c.intangible
|
||||
end
|
||||
@@ -719,6 +1070,23 @@ if c.drawSkillBlock ~= nil and c.drawSkillBlock > 0 then
|
||||
end
|
||||
if c.addShiv ~= nil and c.discard == nil and c.discardAll ~= true then
|
||||
self:AddCardsToHand("Shiv", c.addShiv)
|
||||
end
|
||||
local exhaustedNonAttack = self:ExhaustHandNonAttack(c)
|
||||
local exhaustedAll = self:ExhaustHandAll(c)
|
||||
local totalExhausted = exhaustedNonAttack + exhaustedAll
|
||||
if c.drawPerExhausted ~= nil and c.drawPerExhausted > 0 and totalExhausted > 0 then
|
||||
self:DrawCards(totalExhausted * c.drawPerExhausted, true)
|
||||
end
|
||||
if c.addRandomCardCount ~= nil and c.addRandomCardCount > 0 then
|
||||
self:AddRandomCardsFromEffect(c, c.addRandomCardCount)
|
||||
end
|
||||
if c.addRandomCardPerExhausted ~= nil and c.addRandomCardPerExhausted > 0 then
|
||||
if totalExhausted > 0 then
|
||||
self:AddRandomCardsFromEffect(c, totalExhausted * c.addRandomCardPerExhausted)
|
||||
end
|
||||
end
|
||||
if (c.playTopDrawPileCount ~= nil and c.playTopDrawPileCount > 0) or (c.playTopDrawPileCountPerEnergy ~= nil and c.playTopDrawPileCountPerEnergy > 0) then
|
||||
self:PlayTopDrawPileCards(c, xEnergy)
|
||||
end`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
|
||||
@@ -25,7 +25,7 @@ for i = 1, #self.RunRelics do
|
||||
elseif r.effect == "strength" then
|
||||
self.PlayerStr = self.PlayerStr + r.value
|
||||
elseif r.effect == "draw" then
|
||||
self:DrawCards(r.value)
|
||||
self:DrawCards(r.value, true)
|
||||
self:RenderHand(false)
|
||||
elseif r.effect == "heal" or r.effect == "healOnAttack" or r.effect == "healOnWin" then
|
||||
self.PlayerHp = self.PlayerHp + r.value
|
||||
@@ -95,7 +95,7 @@ if self:AddPotion(pid) == true then
|
||||
self:Toast("물약 획득: " .. p.name)
|
||||
end`),
|
||||
method('RenderPotions', `for i = 1, 5 do
|
||||
local base = "/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. tostring(i)
|
||||
local base = "/ui/RunUIGroup/CombatHud/TopBar/PotionSlot" .. self:IntStr(i)
|
||||
local e = _EntityService:GetEntityByPath(base)
|
||||
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
||||
local pid = nil
|
||||
@@ -188,7 +188,7 @@ if self.RunRelics ~= nil then
|
||||
count = #self.RunRelics
|
||||
end
|
||||
for i = 1, 10 do
|
||||
local base = "/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. tostring(i)
|
||||
local base = "/ui/RunUIGroup/CombatHud/TopBar/RelicSlot" .. self:IntStr(i)
|
||||
local e = _EntityService:GetEntityByPath(base)
|
||||
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
||||
local rid = nil
|
||||
|
||||
@@ -71,7 +71,7 @@ if opts == nil then
|
||||
end
|
||||
self.JobOpts = opts
|
||||
for i = 1, 3 do
|
||||
local base = "/ui/SelectUIGroup/JobSelectHud/Job_slot" .. tostring(i)
|
||||
local base = "/ui/SelectUIGroup/JobSelectHud/Job_slot" .. self:IntStr(i)
|
||||
local o = opts[i]
|
||||
if o ~= nil then
|
||||
self:SetEntityEnabled(base, true)
|
||||
|
||||
@@ -14,7 +14,7 @@ end
|
||||
local worldPos = transform.WorldPosition
|
||||
local screen = _UILogic:WorldToScreenPosition(Vector2(worldPos.x, worldPos.y + ${HEAD_OFFSET_Y}))
|
||||
local uipos = _UILogic:ScreenToUIPosition(screen)
|
||||
local slotEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(slot))
|
||||
local slotEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(slot))
|
||||
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
|
||||
slotEntity.UITransformComponent.anchoredPosition = uipos
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
|
||||
@@ -162,7 +162,7 @@ if node ~= nil then
|
||||
end
|
||||
end
|
||||
for k = 1, 3 do
|
||||
local d = _EntityService:GetEntityByPath("/ui/RunUIGroup/MapHud/Dot_" .. dotId .. "_" .. tostring(k))
|
||||
local d = _EntityService:GetEntityByPath("/ui/RunUIGroup/MapHud/Dot_" .. dotId .. "_" .. self:IntStr(k))
|
||||
if d ~= nil then
|
||||
d.Enable = has
|
||||
if has == true and d.SpriteGUIRendererComponent ~= nil then
|
||||
|
||||
@@ -1,296 +1,467 @@
|
||||
import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs';
|
||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
||||
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
|
||||
|
||||
export const renderMethods = [
|
||||
method('BuffsLabel', `local parts = {}
|
||||
if str ~= nil and str > 0 then table.insert(parts, "힘+" .. tostring(str)) end
|
||||
if weak ~= nil and weak > 0 then table.insert(parts, "약화" .. tostring(weak)) end
|
||||
if vuln ~= nil and vuln > 0 then table.insert(parts, "취약" .. tostring(vuln)) end
|
||||
if poison ~= nil and poison > 0 then table.insert(parts, "독" .. tostring(poison)) end
|
||||
return table.concat(parts, " ")`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'str' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'weak' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'vuln' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'poison' },
|
||||
], 0, 'string'),
|
||||
method('RenderCombat', `for i = 1, ${MAX_MONSTERS} do
|
||||
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. tostring(i)
|
||||
local m = self.Monsters[i]
|
||||
if m ~= nil and m.alive == true then
|
||||
self:SetEntityEnabled(base, true)
|
||||
self:SetText(base .. "/Name", m.name)
|
||||
self:SetText(base .. "/Hp", string.format("%d", m.hp) .. "/" .. string.format("%d", m.maxHp))
|
||||
local intent = m.intents[m.intentIdx]
|
||||
local t = ""
|
||||
if intent ~= nil then
|
||||
if intent.kind == "Attack" then
|
||||
local atk = intent.value + m.str
|
||||
if m.weak > 0 then atk = math.floor(atk * 0.75) end
|
||||
if self.PlayerVuln > 0 then atk = math.floor(atk * 1.5) end
|
||||
t = "공격 " .. tostring(atk)
|
||||
elseif intent.kind == "Defend" then t = "방어 " .. tostring(intent.value)
|
||||
elseif intent.kind == "Debuff" then
|
||||
if intent.effect == "weak" then t = "약화 " .. tostring(intent.value) .. " 부여"
|
||||
else t = "취약 " .. tostring(intent.value) .. " 부여" end
|
||||
elseif intent.kind == "AddCard" then
|
||||
t = "저주 카드 추가"
|
||||
end
|
||||
end
|
||||
self:SetText(base .. "/Intent", t)
|
||||
local dragActive = self.DragTargetIndex ~= nil and self.DragTargetIndex > 0
|
||||
local shownTarget = self.TargetIndex
|
||||
if dragActive == true then shownTarget = self.DragTargetIndex end
|
||||
self:SetEntityEnabled(base .. "/TargetMarker", i == shownTarget and dragActive)
|
||||
self:SetEntityEnabled(base .. "/TargetMarker/Label", i == shownTarget and dragActive)
|
||||
local intentEntity = _EntityService:GetEntityByPath(base .. "/Intent")
|
||||
if intentEntity ~= nil and intentEntity.TextComponent ~= nil and intent ~= nil then
|
||||
if intent.kind == "Attack" then
|
||||
intentEntity.TextComponent.FontColor = Color(1, 0.45, 0.35, 1)
|
||||
elseif intent.kind == "Debuff" then
|
||||
intentEntity.TextComponent.FontColor = Color(0.8, 0.5, 1, 1)
|
||||
elseif intent.kind == "AddCard" then
|
||||
intentEntity.TextComponent.FontColor = Color(0.6, 0.85, 0.4, 1)
|
||||
else
|
||||
intentEntity.TextComponent.FontColor = Color(0.5, 0.75, 1, 1)
|
||||
end
|
||||
end
|
||||
self:SetHpBar(base .. "/HpBarFill", m.hp, m.maxHp, ${HP_BAR_W})
|
||||
self:SetEntityEnabled(base .. "/BlockBadge", m.block > 0)
|
||||
self:SetText(base .. "/BlockBadge/Value", string.format("%d", m.block))
|
||||
self:SetText(base .. "/Buffs", self:BuffsLabel(m.str, m.weak, m.vuln, m.poison or 0))
|
||||
else
|
||||
self:SetEntityEnabled(base, false)
|
||||
end
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/HpText", string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp))
|
||||
self:SetHpBar("/ui/RunUIGroup/CombatHud/PlayerPanel/HpBarFill", self.PlayerHp, self.PlayerMaxHp, 220)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge", self.PlayerBlock > 0)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge/Value", string.format("%d", self.PlayerBlock))
|
||||
local pb = self:BuffsLabel(self.PlayerStr, self.PlayerWeak, self.PlayerVuln, 0)
|
||||
if self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "불가침" .. tostring(self.PlayerIntangible)
|
||||
end
|
||||
if self.PlayerDex ~= nil and self.PlayerDex > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "민첩+" .. tostring(self.PlayerDex)
|
||||
end
|
||||
if self.PlayerThorns ~= nil and self.PlayerThorns > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "가시" .. tostring(self.PlayerThorns)
|
||||
end
|
||||
if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
|
||||
local names = {}
|
||||
for i = 1, #self.PlayerPowers do
|
||||
local pc = self.Cards[self.PlayerPowers[i]]
|
||||
if pc ~= nil then table.insert(names, pc.name) end
|
||||
end
|
||||
if pb ~= "" then pb = pb .. " · " end
|
||||
pb = pb .. table.concat(names, " ")
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Buffs", pb)
|
||||
self:RenderRun()`),
|
||||
method('ShowDmgPop', `local slotKey = string.format("%d", math.floor(slot or 0))
|
||||
local base = "/ui/RunUIGroup/CombatHud/DmgPop" .. slotKey
|
||||
local pop = _EntityService:GetEntityByPath(base)
|
||||
if pop == nil then
|
||||
return
|
||||
end
|
||||
self.DmgPopSeq = (self.DmgPopSeq or 0) + 1
|
||||
local popSeq = self.DmgPopSeq
|
||||
self:SetText(base, "")
|
||||
local damageDigitRuids = { ${DAMAGE_DIGIT_RUIDS.map(luaStr).join(', ')} }
|
||||
local shown = tostring(math.max(0, math.floor(amount)))
|
||||
if string.len(shown) > ${DAMAGE_POP_MAX_DIGITS} then
|
||||
shown = string.sub(shown, 1, ${DAMAGE_POP_MAX_DIGITS})
|
||||
end
|
||||
local digits = {}
|
||||
for i = 1, string.len(shown) do
|
||||
table.insert(digits, tonumber(string.sub(shown, i, i)) or 0)
|
||||
end
|
||||
local totalW = #digits * ${DAMAGE_POP_DIGIT_W} + math.max(0, #digits - 1) * ${DAMAGE_POP_DIGIT_SPACING}
|
||||
local startX = -totalW / 2 + ${DAMAGE_POP_DIGIT_W} / 2
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
self:SetEntityEnabled(base .. "/Digit" .. tostring(i), false)
|
||||
end
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitPath = base .. "/Digit" .. tostring(i)
|
||||
local digitEntity = _EntityService:GetEntityByPath(digitPath)
|
||||
if digitEntity ~= nil and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
if digits[i] ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.ImageRUID = damageDigitRuids[digits[i] + 1]
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)
|
||||
if digitEntity.UITransformComponent ~= nil then
|
||||
digitEntity.UITransformComponent.anchoredPosition = Vector2(startX + (i - 1) * (${DAMAGE_POP_DIGIT_W} + ${DAMAGE_POP_DIGIT_SPACING}), 0)
|
||||
end
|
||||
self:SetEntityEnabled(digitPath, true)
|
||||
else
|
||||
self:SetEntityEnabled(digitPath, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
local popPos = nil
|
||||
local m = self.Monsters[slot]
|
||||
if m ~= nil and m.entity ~= nil and isvalid(m.entity) and m.entity.TransformComponent ~= nil then
|
||||
local wp = m.entity.TransformComponent.WorldPosition
|
||||
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y + 0.45}))
|
||||
popPos = _UILogic:ScreenToUIPosition(screen)
|
||||
else
|
||||
local slotEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. slotKey)
|
||||
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
|
||||
local sp = slotEntity.UITransformComponent.anchoredPosition
|
||||
popPos = Vector2(sp.x, sp.y + 76)
|
||||
end
|
||||
end
|
||||
if pop ~= nil and pop.UITransformComponent ~= nil then
|
||||
if popPos ~= nil then
|
||||
pop.UITransformComponent.anchoredPosition = popPos
|
||||
else
|
||||
pop.UITransformComponent.anchoredPosition = Vector2(0, 120)
|
||||
end
|
||||
end
|
||||
self:SetEntityEnabled(base, true)
|
||||
for i = 1, 6 do
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if self.DmgPopSeq ~= popSeq then
|
||||
return
|
||||
end
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.UITransformComponent ~= nil then
|
||||
local cur = p.UITransformComponent.anchoredPosition
|
||||
p.UITransformComponent.anchoredPosition = Vector2(cur.x, cur.y + 7)
|
||||
end
|
||||
end, 0.045 * i)
|
||||
end
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if self.DmgPopSeq ~= popSeq then
|
||||
return
|
||||
end
|
||||
self:SetEntityEnabled(base, false)
|
||||
end, 0.48)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||
]),
|
||||
method('ShowPlayerDmgPop', `local base = "/ui/RunUIGroup/CombatHud/PlayerPanel/DmgPop"
|
||||
if amount > 0 then
|
||||
self:SetText(base, "-" .. string.format("%d", amount))
|
||||
else
|
||||
self:SetText(base, "막음")
|
||||
end
|
||||
self:SetEntityEnabled(base, true)
|
||||
_TimerService:SetTimerOnce(function() self:SetEntityEnabled(base, false) end, 0.6)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||
method('PlayerAttackMotion', `local lp = _UserService.LocalPlayer
|
||||
if lp == nil then
|
||||
return
|
||||
end
|
||||
if lp.StateComponent == nil then
|
||||
return
|
||||
end
|
||||
pcall(function() lp.StateComponent:ChangeState("ATTACK") end)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if lp ~= nil and isvalid(lp) and lp.StateComponent ~= nil then
|
||||
pcall(function() lp.StateComponent:ChangeState("IDLE") end)
|
||||
end
|
||||
end, 0.5)`),
|
||||
method('PlayerHitMotion', `local lp = _UserService.LocalPlayer
|
||||
if lp == nil then
|
||||
return
|
||||
end
|
||||
if lp.StateComponent ~= nil then
|
||||
pcall(function() lp.StateComponent:ChangeState("HIT") end)
|
||||
end
|
||||
local tr = lp.TransformComponent
|
||||
if tr == nil then
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
tr.Position = Vector3(p.x - 0.15, p.y, p.z)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if lp ~= nil and isvalid(lp) and lp.TransformComponent ~= nil then
|
||||
lp.TransformComponent.Position = Vector3(p.x, p.y, p.z)
|
||||
end
|
||||
end, 0.15)`),
|
||||
method('MonsterLunge', `local m = self.Monsters[idx]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
return
|
||||
end
|
||||
if m.motionBusy == true then
|
||||
return
|
||||
end
|
||||
m.motionBusy = true
|
||||
local e = m.entity
|
||||
local tr = e.TransformComponent
|
||||
if tr == nil then
|
||||
m.motionBusy = false
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
tr.Position = Vector3(p.x - 0.35, p.y, p.z)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.TransformComponent ~= nil then
|
||||
e.TransformComponent.Position = Vector3(p.x, p.y, p.z)
|
||||
end
|
||||
m.motionBusy = false
|
||||
end, 0.18)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'idx' }]),
|
||||
method('MonsterHitMotion', `local m = self.Monsters[slot]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
return
|
||||
end
|
||||
local e = m.entity
|
||||
if m.hitClip ~= nil and e.SpriteRendererComponent ~= nil then
|
||||
e.SpriteRendererComponent.SpriteRUID = m.hitClip
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.SpriteRendererComponent ~= nil and m.alive == true and m.standClip ~= nil then
|
||||
e.SpriteRendererComponent.SpriteRUID = m.standClip
|
||||
end
|
||||
end, 0.5)
|
||||
else
|
||||
if m.motionBusy == true then
|
||||
return
|
||||
end
|
||||
m.motionBusy = true
|
||||
local tr = e.TransformComponent
|
||||
if tr == nil then
|
||||
m.motionBusy = false
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
local seq = { 0.12, -0.12, 0 }
|
||||
for i = 1, #seq do
|
||||
local dx = seq[i]
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.TransformComponent ~= nil then
|
||||
e.TransformComponent.Position = Vector3(p.x + dx, p.y, p.z)
|
||||
end
|
||||
if i == #seq then
|
||||
m.motionBusy = false
|
||||
end
|
||||
end, 0.06 * i)
|
||||
end
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('SetHpBar', `local e = _EntityService:GetEntityByPath(path)
|
||||
if e == nil or e.UITransformComponent == nil then
|
||||
return
|
||||
end
|
||||
local ratio = 0
|
||||
if maxHp > 0 then ratio = hp / maxHp end
|
||||
if ratio < 0 then ratio = 0 end
|
||||
local w = width * ratio
|
||||
e.UITransformComponent.RectSize = Vector2(w, 14)`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hp' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'maxHp' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'width' },
|
||||
]),
|
||||
method('SetTarget', `if self.Monsters[slot] ~= nil and self.Monsters[slot].alive == true then
|
||||
self.TargetIndex = slot
|
||||
self:RenderCombat()
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('RenderRun', `local floorText = "막 " .. string.format("%d", self.Floor) .. "/" .. string.format("%d", self.RunLength) .. " · " .. string.format("%d", self.Depth) .. "층"
|
||||
if self.AscensionLevel > 0 then
|
||||
floorText = floorText .. " · 승천" .. string.format("%d", self.AscensionLevel)
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Floor", floorText)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Gold", "메소 " .. string.format("%d", self.Gold))`),
|
||||
|
||||
import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs';
|
||||
import { CARDS, ENEMIES, CLASSES, JOBS, SOUL_UNLOCKS, CARDFRAMES, RARITIES, MAP_ROWS, MAP_COLS, CHEST_CLOSED_RUID, CHEST_OPEN_RUID, NODEICONS, CHARS, CAM, RELICS, POTIONS, luaSoulShopTable, frameRuid, luaFramesTable, luaNodeIconsTable, luaRelicsTable, luaPotionsTable, luaIntentsArray, luaEnemiesTable, luaStr, luaJobsTable, luaCardsTable, luaDeckTable } from '../lib/data.mjs';
|
||||
import { UI_FILE, COMMON_FILE, UI_ROOT, GENERATED_UI_SECTIONS, UI_APPEND_ORDER, DISABLED_STOCK_CONTROLS, TRANSPARENT, DARK, GOLD, ATTACK, DEFEND, SKILL, DAMAGE_DIGIT_RUIDS, DAMAGE_POP_MAX_DIGITS, DAMAGE_POP_DIGIT_W, DAMAGE_POP_DIGIT_H, DAMAGE_POP_DIGIT_SPACING, MAX_MONSTERS, HEAD_OFFSET_Y, HP_BAR_W, WHITE, CARD_NAME_TEXT, CARD_DESC_TEXT, cardFaceLayout, CARD_W, CARD_H, CARD_SPACING, CARD_XS, ALIGN_CENTER, ALIGN_BOTTOM_CENTER, guid, transform, sprite, button, text, scrollLayoutGroup, popupLayerFor, uiOrderFor, displayOrderFor, applySortingOverride, entity, uiPath, sectionRoot, isGeneratedUiEntity, appendUiSection } from '../lib/ui-helpers.mjs';
|
||||
|
||||
export const renderMethods = [
|
||||
method('BuffsLabel', `local parts = {}
|
||||
if str ~= nil and str > 0 then table.insert(parts, "힘+" .. tostring(str)) end
|
||||
if weak ~= nil and weak > 0 then table.insert(parts, "약화" .. tostring(weak)) end
|
||||
if vuln ~= nil and vuln > 0 then table.insert(parts, "취약" .. tostring(vuln)) end
|
||||
if poison ~= nil and poison > 0 then table.insert(parts, "독" .. tostring(poison)) end
|
||||
return table.concat(parts, " ")`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'str' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'weak' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'vuln' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'poison' },
|
||||
], 0, 'string'),
|
||||
method('RenderCombat', `for i = 1, ${MAX_MONSTERS} do
|
||||
local base = "/ui/RunUIGroup/CombatHud/MonsterStatus" .. self:IntStr(i)
|
||||
local m = self.Monsters[i]
|
||||
if m ~= nil and m.alive == true then
|
||||
self:SetEntityEnabled(base, true)
|
||||
self:SetText(base .. "/Name", m.name)
|
||||
self:SetText(base .. "/Hp", string.format("%d", m.hp) .. "/" .. string.format("%d", m.maxHp))
|
||||
local intent = m.intents[m.intentIdx]
|
||||
local t = ""
|
||||
if intent ~= nil then
|
||||
if intent.kind == "Attack" then
|
||||
local atk = intent.value + m.str
|
||||
if m.weak > 0 then atk = math.floor(atk * 0.75) end
|
||||
if self.PlayerVuln > 0 then atk = math.floor(atk * 1.5) end
|
||||
t = "공격 " .. tostring(atk)
|
||||
elseif intent.kind == "Defend" then t = "방어 " .. tostring(intent.value)
|
||||
elseif intent.kind == "Debuff" then
|
||||
if intent.effect == "weak" then t = "약화 " .. tostring(intent.value) .. " 부여"
|
||||
else t = "취약 " .. tostring(intent.value) .. " 부여" end
|
||||
elseif intent.kind == "AddCard" then
|
||||
t = "저주 카드 추가"
|
||||
end
|
||||
end
|
||||
self:SetText(base .. "/Intent", t)
|
||||
local dragActive = self.DragTargetIndex ~= nil and self.DragTargetIndex > 0
|
||||
local shownTarget = self.TargetIndex
|
||||
if dragActive == true then shownTarget = self.DragTargetIndex end
|
||||
self:SetEntityEnabled(base .. "/TargetMarker", i == shownTarget and dragActive)
|
||||
self:SetEntityEnabled(base .. "/TargetMarker/Label", i == shownTarget and dragActive)
|
||||
local intentEntity = _EntityService:GetEntityByPath(base .. "/Intent")
|
||||
if intentEntity ~= nil and intentEntity.TextComponent ~= nil and intent ~= nil then
|
||||
if intent.kind == "Attack" then
|
||||
intentEntity.TextComponent.FontColor = Color(1, 0.45, 0.35, 1)
|
||||
elseif intent.kind == "Debuff" then
|
||||
intentEntity.TextComponent.FontColor = Color(0.8, 0.5, 1, 1)
|
||||
elseif intent.kind == "AddCard" then
|
||||
intentEntity.TextComponent.FontColor = Color(0.6, 0.85, 0.4, 1)
|
||||
else
|
||||
intentEntity.TextComponent.FontColor = Color(0.5, 0.75, 1, 1)
|
||||
end
|
||||
end
|
||||
self:SetHpBar(base .. "/HpBarFill", m.hp, m.maxHp, ${HP_BAR_W})
|
||||
self:SetEntityEnabled(base .. "/BlockBadge", m.block > 0)
|
||||
self:SetText(base .. "/BlockBadge/Value", string.format("%d", m.block))
|
||||
self:SetText(base .. "/Buffs", self:BuffsLabel(m.str, m.weak, m.vuln, m.poison or 0))
|
||||
else
|
||||
self:SetEntityEnabled(base, false)
|
||||
end
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/HpText", string.format("%d", self.PlayerHp) .. "/" .. string.format("%d", self.PlayerMaxHp))
|
||||
self:SetHpBar("/ui/RunUIGroup/CombatHud/PlayerPanel/HpBarFill", self.PlayerHp, self.PlayerMaxHp, 220)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge", self.PlayerBlock > 0)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/BlockBadge/Value", string.format("%d", self.PlayerBlock))
|
||||
local pb = self:BuffsLabel(self.PlayerStr, self.PlayerWeak, self.PlayerVuln, 0)
|
||||
if self.PlayerIntangible ~= nil and self.PlayerIntangible > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "불가침" .. tostring(self.PlayerIntangible)
|
||||
end
|
||||
if self.PlayerDex ~= nil and self.PlayerDex > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "민첩+" .. tostring(self.PlayerDex)
|
||||
end
|
||||
if self.PlayerThorns ~= nil and self.PlayerThorns > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "가시" .. tostring(self.PlayerThorns)
|
||||
end
|
||||
if self.ComboCount ~= nil and self.ComboCount > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "콤보 " .. tostring(self.ComboCount) .. "/" .. tostring(self:GetComboMax())
|
||||
end
|
||||
if self.HolyChargeCount ~= nil and self.HolyChargeCount > 0 then
|
||||
if pb ~= "" then pb = pb .. " " end
|
||||
pb = pb .. "홀리 차지 " .. tostring(self.HolyChargeCount) .. "/" .. tostring(self:GetHolyChargeMax())
|
||||
end
|
||||
if self.PlayerPowers ~= nil and #self.PlayerPowers > 0 then
|
||||
local names = {}
|
||||
for i = 1, #self.PlayerPowers do
|
||||
local pc = self.Cards[self.PlayerPowers[i]]
|
||||
if pc ~= nil then table.insert(names, pc.name) end
|
||||
end
|
||||
if pb ~= "" then pb = pb .. " · " end
|
||||
pb = pb .. table.concat(names, " ")
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Buffs", pb)
|
||||
self:RenderRun()`),
|
||||
method('ShowDmgPop', `local slotKey = string.format("%d", math.floor(slot or 0))
|
||||
if self.DmgPopSlotQueue == nil then
|
||||
self.DmgPopSlotQueue = {}
|
||||
end
|
||||
local popIndex = (self.DmgPopSlotQueue[slotKey] or 0) + 1
|
||||
if popIndex > 5 then
|
||||
popIndex = 1
|
||||
end
|
||||
self.DmgPopSlotQueue[slotKey] = popIndex
|
||||
local base = "/ui/RunUIGroup/CombatHud/DmgPop" .. slotKey .. "_" .. self:IntStr(popIndex)
|
||||
local pop = _EntityService:GetEntityByPath(base)
|
||||
if pop == nil then
|
||||
return
|
||||
end
|
||||
local function showNow()
|
||||
self:SetEntityEnabled(base, false)
|
||||
self:SetText(base, "")
|
||||
local damageDigitRuids = { ${DAMAGE_DIGIT_RUIDS.map(luaStr).join(', ')} }
|
||||
local shown = tostring(math.max(0, math.floor(amount)))
|
||||
if string.len(shown) > ${DAMAGE_POP_MAX_DIGITS} then
|
||||
shown = string.sub(shown, 1, ${DAMAGE_POP_MAX_DIGITS})
|
||||
end
|
||||
local digits = {}
|
||||
local digitPathsToEnable = {}
|
||||
for i = 1, string.len(shown) do
|
||||
table.insert(digits, tonumber(string.sub(shown, i, i)) or 0)
|
||||
end
|
||||
local totalW = #digits * ${DAMAGE_POP_DIGIT_W} + math.max(0, #digits - 1) * ${DAMAGE_POP_DIGIT_SPACING}
|
||||
local startX = -totalW / 2 + ${DAMAGE_POP_DIGIT_W} / 2
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
self:SetEntityEnabled(base .. "/Digit" .. self:IntStr(i), false)
|
||||
end
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitPath = base .. "/Digit" .. self:IntStr(i)
|
||||
local digitEntity = _EntityService:GetEntityByPath(digitPath)
|
||||
if digitEntity ~= nil and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
if digits[i] ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.ImageRUID = damageDigitRuids[digits[i] + 1]
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)
|
||||
if digitEntity.UITransformComponent ~= nil then
|
||||
digitEntity.UITransformComponent.anchoredPosition = Vector2(startX + (i - 1) * (${DAMAGE_POP_DIGIT_W} + ${DAMAGE_POP_DIGIT_SPACING}), 0)
|
||||
end
|
||||
table.insert(digitPathsToEnable, digitPath)
|
||||
else
|
||||
self:SetEntityEnabled(digitPath, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
local popPos = nil
|
||||
local m = self.Monsters[slot]
|
||||
if m ~= nil and m.entity ~= nil and isvalid(m.entity) and m.entity.TransformComponent ~= nil then
|
||||
local wp = m.entity.TransformComponent.WorldPosition
|
||||
local screen = _UILogic:WorldToScreenPosition(Vector2(wp.x, wp.y + ${HEAD_OFFSET_Y + 0.45}))
|
||||
popPos = _UILogic:ScreenToUIPosition(screen)
|
||||
else
|
||||
local slotEntity = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/MonsterStatus" .. slotKey)
|
||||
if slotEntity ~= nil and slotEntity.UITransformComponent ~= nil then
|
||||
local sp = slotEntity.UITransformComponent.anchoredPosition
|
||||
popPos = Vector2(sp.x, sp.y + 76)
|
||||
end
|
||||
end
|
||||
if pop.UITransformComponent ~= nil then
|
||||
if popPos ~= nil then
|
||||
pop.UITransformComponent.anchoredPosition = popPos
|
||||
else
|
||||
pop.UITransformComponent.anchoredPosition = Vector2(0, 120)
|
||||
end
|
||||
end
|
||||
self:SetEntityEnabled(base, true)
|
||||
for i = 1, #digitPathsToEnable do
|
||||
self:SetEntityEnabled(digitPathsToEnable[i], true)
|
||||
end
|
||||
for i = 1, 6 do
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.UITransformComponent ~= nil then
|
||||
local cur = p.UITransformComponent.anchoredPosition
|
||||
p.UITransformComponent.anchoredPosition = Vector2(cur.x, cur.y + 7)
|
||||
end
|
||||
local alpha = 1 - (i / 6)
|
||||
if alpha < 0 then alpha = 0 end
|
||||
for di = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitEntity = _EntityService:GetEntityByPath(base .. "/Digit" .. self:IntStr(di))
|
||||
if digitEntity ~= nil and digitEntity.Enable == true and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, alpha)
|
||||
end
|
||||
end
|
||||
end, 0.05 * i)
|
||||
end
|
||||
_TimerService:SetTimerOnce(function()
|
||||
self:SetEntityEnabled(base, false)
|
||||
end, 0.3)
|
||||
end
|
||||
showNow()`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
||||
]),
|
||||
method('ShowPlayerDmgPop', `local shownAmount = math.max(0, math.floor(amount or 0))
|
||||
if shownAmount <= 0 then
|
||||
return
|
||||
end
|
||||
local function setEnabled(entity, enabled)
|
||||
if entity == nil then
|
||||
return
|
||||
end
|
||||
entity.Enable = enabled
|
||||
if entity.SpriteGUIRendererComponent ~= nil then
|
||||
entity.SpriteGUIRendererComponent.Enable = enabled
|
||||
end
|
||||
if entity.TextComponent ~= nil then
|
||||
entity.TextComponent.Enable = enabled
|
||||
end
|
||||
end
|
||||
self.PlayerDmgPopIndex = (self.PlayerDmgPopIndex or 0) + 1
|
||||
if self.PlayerDmgPopIndex > 4 then
|
||||
self.PlayerDmgPopIndex = 1
|
||||
end
|
||||
local base = "/ui/RunUIGroup/CombatHud/PlayerPanel/DmgPop_" .. self:IntStr(self.PlayerDmgPopIndex)
|
||||
local pop = _EntityService:GetEntityByPath(base)
|
||||
if pop == nil then
|
||||
return
|
||||
end
|
||||
setEnabled(pop, false)
|
||||
local damageDigitRuids = { ${DAMAGE_DIGIT_RUIDS.map(luaStr).join(', ')} }
|
||||
local shown = tostring(shownAmount)
|
||||
if string.len(shown) > ${DAMAGE_POP_MAX_DIGITS} then
|
||||
shown = string.sub(shown, 1, ${DAMAGE_POP_MAX_DIGITS})
|
||||
end
|
||||
local digits = {}
|
||||
local digitEntitiesToEnable = {}
|
||||
for i = 1, string.len(shown) do
|
||||
table.insert(digits, tonumber(string.sub(shown, i, i)) or 0)
|
||||
end
|
||||
local totalW = #digits * ${DAMAGE_POP_DIGIT_W} + math.max(0, #digits - 1) * ${DAMAGE_POP_DIGIT_SPACING}
|
||||
local startX = -totalW / 2 + ${DAMAGE_POP_DIGIT_W} / 2
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitEntity = _EntityService:GetEntityByPath(base .. "/Digit" .. self:IntStr(i))
|
||||
setEnabled(digitEntity, false)
|
||||
end
|
||||
for i = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitPath = base .. "/Digit" .. self:IntStr(i)
|
||||
local digitEntity = _EntityService:GetEntityByPath(digitPath)
|
||||
if digitEntity ~= nil and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
if digits[i] ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.ImageRUID = damageDigitRuids[digits[i] + 1]
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)
|
||||
if digitEntity.UITransformComponent ~= nil then
|
||||
digitEntity.UITransformComponent.anchoredPosition = Vector2(startX + (i - 1) * (${DAMAGE_POP_DIGIT_W} + ${DAMAGE_POP_DIGIT_SPACING}), 0)
|
||||
end
|
||||
table.insert(digitEntitiesToEnable, digitEntity)
|
||||
end
|
||||
end
|
||||
end
|
||||
local startPos = Vector2(16, 34)
|
||||
if pop.UITransformComponent ~= nil then
|
||||
local cur = pop.UITransformComponent.anchoredPosition
|
||||
if math.abs(cur.x) < 240 and math.abs(cur.y) < 140 then
|
||||
startPos = cur
|
||||
end
|
||||
pop.UITransformComponent.anchoredPosition = startPos
|
||||
end
|
||||
setEnabled(pop, true)
|
||||
for i = 1, #digitEntitiesToEnable do
|
||||
setEnabled(digitEntitiesToEnable[i], true)
|
||||
end
|
||||
for i = 1, 6 do
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.Enable == true and p.UITransformComponent ~= nil then
|
||||
local cur = p.UITransformComponent.anchoredPosition
|
||||
p.UITransformComponent.anchoredPosition = Vector2(cur.x, cur.y + 7)
|
||||
end
|
||||
local alpha = 1 - (i / 6)
|
||||
if alpha < 0 then alpha = 0 end
|
||||
for di = 1, ${DAMAGE_POP_MAX_DIGITS} do
|
||||
local digitEntity = _EntityService:GetEntityByPath(base .. "/Digit" .. self:IntStr(di))
|
||||
if digitEntity ~= nil and digitEntity.Enable == true and digitEntity.SpriteGUIRendererComponent ~= nil then
|
||||
digitEntity.SpriteGUIRendererComponent.Color = Color(1, 1, 1, alpha)
|
||||
end
|
||||
end
|
||||
end, 0.05 * i)
|
||||
end
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local p = _EntityService:GetEntityByPath(base)
|
||||
if p ~= nil and p.UITransformComponent ~= nil then
|
||||
p.UITransformComponent.anchoredPosition = startPos
|
||||
end
|
||||
setEnabled(p, false)
|
||||
end, 0.3)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' }]),
|
||||
method('ShakeCombatCamera', `local lp = _UserService.LocalPlayer
|
||||
local cam = nil
|
||||
if lp ~= nil then
|
||||
cam = lp.CameraComponent
|
||||
end
|
||||
if cam == nil then
|
||||
cam = _CameraService:GetCurrentCameraComponent()
|
||||
end
|
||||
if cam == nil then
|
||||
return
|
||||
end
|
||||
self.CombatCameraShakeSeq = (self.CombatCameraShakeSeq or 0) + 1
|
||||
local seq = self.CombatCameraShakeSeq
|
||||
local baseCameraOffset = Vector2(${CAM.cameraOffsetX}, ${CAM.cameraOffsetY})
|
||||
cam.CameraOffset = baseCameraOffset
|
||||
local offsets = {
|
||||
Vector2(-0.22, 0),
|
||||
Vector2(0.2, 0),
|
||||
Vector2(-0.12, 0),
|
||||
Vector2(0.06, 0),
|
||||
Vector2(0, 0),
|
||||
}
|
||||
for i = 1, #offsets do
|
||||
local delta = offsets[i]
|
||||
_TimerService:SetTimerOnce(function()
|
||||
local lp2 = _UserService.LocalPlayer
|
||||
local cam2 = nil
|
||||
if lp2 ~= nil then
|
||||
cam2 = lp2.CameraComponent
|
||||
end
|
||||
if cam2 == nil then
|
||||
cam2 = _CameraService:GetCurrentCameraComponent()
|
||||
end
|
||||
if cam2 == nil then
|
||||
return
|
||||
end
|
||||
if seq ~= self.CombatCameraShakeSeq then
|
||||
return
|
||||
end
|
||||
cam2.CameraOffset = Vector2(baseCameraOffset.x + delta.x, baseCameraOffset.y + delta.y)
|
||||
end, 0.028 * (i - 1))
|
||||
end`, []),
|
||||
method('PlayerAttackMotion', `local lp = _UserService.LocalPlayer
|
||||
if lp == nil then
|
||||
return
|
||||
end
|
||||
if lp.StateComponent == nil then
|
||||
return
|
||||
end
|
||||
pcall(function() lp.StateComponent:ChangeState("ATTACK") end)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if lp ~= nil and isvalid(lp) and lp.StateComponent ~= nil then
|
||||
pcall(function() lp.StateComponent:ChangeState("IDLE") end)
|
||||
end
|
||||
end, 0.5)`),
|
||||
method('PlayerHitMotion', `local lp = _UserService.LocalPlayer
|
||||
if lp == nil then
|
||||
return
|
||||
end
|
||||
if lp.StateComponent ~= nil then
|
||||
pcall(function() lp.StateComponent:ChangeState("HIT") end)
|
||||
end
|
||||
local tr = lp.TransformComponent
|
||||
if tr == nil then
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
tr.Position = Vector3(p.x - 0.15, p.y, p.z)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if lp ~= nil and isvalid(lp) and lp.TransformComponent ~= nil then
|
||||
lp.TransformComponent.Position = Vector3(p.x, p.y, p.z)
|
||||
end
|
||||
end, 0.15)`),
|
||||
method('MonsterLunge', `local m = self.Monsters[idx]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
return
|
||||
end
|
||||
if m.motionBusy == true then
|
||||
return
|
||||
end
|
||||
m.motionBusy = true
|
||||
local e = m.entity
|
||||
local tr = e.TransformComponent
|
||||
if tr == nil then
|
||||
m.motionBusy = false
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
tr.Position = Vector3(p.x - 0.35, p.y, p.z)
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.TransformComponent ~= nil then
|
||||
e.TransformComponent.Position = Vector3(p.x, p.y, p.z)
|
||||
end
|
||||
m.motionBusy = false
|
||||
end, 0.18)`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'idx' }]),
|
||||
method('MonsterHitMotion', `local m = self.Monsters[slot]
|
||||
if m == nil or m.alive ~= true or m.entity == nil or not isvalid(m.entity) then
|
||||
return
|
||||
end
|
||||
local e = m.entity
|
||||
if m.hitClip ~= nil and e.SpriteRendererComponent ~= nil then
|
||||
e.SpriteRendererComponent.SpriteRUID = m.hitClip
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.SpriteRendererComponent ~= nil and m.alive == true and m.standClip ~= nil then
|
||||
e.SpriteRendererComponent.SpriteRUID = m.standClip
|
||||
end
|
||||
end, 0.5)
|
||||
else
|
||||
if m.motionBusy == true then
|
||||
return
|
||||
end
|
||||
m.motionBusy = true
|
||||
local tr = e.TransformComponent
|
||||
if tr == nil then
|
||||
m.motionBusy = false
|
||||
return
|
||||
end
|
||||
local p = tr.Position
|
||||
local seq = { 0.12, -0.12, 0 }
|
||||
for i = 1, #seq do
|
||||
local dx = seq[i]
|
||||
_TimerService:SetTimerOnce(function()
|
||||
if isvalid(e) and e.TransformComponent ~= nil then
|
||||
e.TransformComponent.Position = Vector3(p.x + dx, p.y, p.z)
|
||||
end
|
||||
if i == #seq then
|
||||
m.motionBusy = false
|
||||
end
|
||||
end, 0.06 * i)
|
||||
end
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('SetHpBar', `local e = _EntityService:GetEntityByPath(path)
|
||||
if e == nil or e.UITransformComponent == nil then
|
||||
return
|
||||
end
|
||||
local ratio = 0
|
||||
if maxHp > 0 then ratio = hp / maxHp end
|
||||
if ratio < 0 then ratio = 0 end
|
||||
if ratio > 1 then ratio = 1 end
|
||||
if self.HpBarOrigins == nil then
|
||||
self.HpBarOrigins = {}
|
||||
end
|
||||
local t = e.UITransformComponent
|
||||
local origin = self.HpBarOrigins[path]
|
||||
if origin == nil then
|
||||
local pivotX = 0
|
||||
if t.Pivot ~= nil then
|
||||
pivotX = t.Pivot.x or 0
|
||||
end
|
||||
origin = {
|
||||
left = t.anchoredPosition.x - (t.RectSize.x * pivotX),
|
||||
y = t.anchoredPosition.y,
|
||||
height = t.RectSize.y,
|
||||
pivotX = pivotX,
|
||||
}
|
||||
self.HpBarOrigins[path] = origin
|
||||
end
|
||||
local w = width * ratio
|
||||
t.RectSize = Vector2(w, origin.height or 14)
|
||||
t.anchoredPosition = Vector2(origin.left + (w * (origin.pivotX or 0)), origin.y or t.anchoredPosition.y)`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'hp' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'maxHp' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'width' },
|
||||
]),
|
||||
method('SetTarget', `if self.Monsters[slot] ~= nil and self.Monsters[slot].alive == true then
|
||||
self.TargetIndex = slot
|
||||
self:RenderCombat()
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('RenderRun', `local floorText = "막 " .. string.format("%d", self.Floor) .. "/" .. string.format("%d", self.RunLength) .. " · " .. string.format("%d", self.Depth) .. "층"
|
||||
if self.AscensionLevel > 0 then
|
||||
floorText = floorText .. " · 승천" .. string.format("%d", self.AscensionLevel)
|
||||
end
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Floor", floorText)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/TopBar/Gold", "메소 " .. string.format("%d", self.Gold))`),
|
||||
|
||||
];
|
||||
|
||||
@@ -34,7 +34,7 @@ local hud = _EntityService:GetEntityByPath("/ui/RunUIGroup/RewardHud")
|
||||
if hud ~= nil then
|
||||
hud.Enable = true
|
||||
end`),
|
||||
method('ApplyRewardVisual', `self:ApplyCardFace("/ui/RunUIGroup/RewardHud/Reward" .. tostring(slot), cardId)`, [
|
||||
method('ApplyRewardVisual', `self:ApplyCardFace("/ui/RunUIGroup/RewardHud/Reward" .. self:IntStr(slot), cardId)`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
||||
]),
|
||||
|
||||
@@ -64,7 +64,7 @@ end, 0.2)`),
|
||||
self:KickCombatCamera()
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/Result", false)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/PotionMenu", false)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/TooltipBox", false)
|
||||
self:SetEntityEnabled("/ui/ToolTipGroup/TooltipBox", false)
|
||||
self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/DiscardPrompt", false)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/PlayerPanel/Name", self:JobLabel())
|
||||
self.MaxEnergy = 3
|
||||
@@ -95,13 +95,20 @@ self.PlayerVuln = 0
|
||||
self.PlayerIntangible = 0
|
||||
self.BonusRewardScreens = 0
|
||||
self.ActiveKillReward = 0
|
||||
self.ActiveKillMaxHpGain = 0
|
||||
self.PlayerPowers = {}
|
||||
self.FightAttackCount = 0
|
||||
self.TurnAttackCardsPlayed = 0
|
||||
self.TurnDiscardedCards = 0
|
||||
self.TurnCardsPlayedThisTurn = 0
|
||||
self.ComboCount = 0
|
||||
self.HolyChargeCount = 0
|
||||
self.DamagePowerStrengthUsed = false
|
||||
self.DamageDealtThisTurn = 0
|
||||
self.DmgPopSeq = 0
|
||||
self.CombatCameraShakeSeq = 0
|
||||
self.DmgPopSlotQueue = {}
|
||||
self.PlayerDmgPopIndex = 0
|
||||
self.FirstHpLossDone = false
|
||||
self.ClayBlockNext = 0
|
||||
self.DiscardSelectRemaining = 0
|
||||
@@ -118,6 +125,7 @@ self.TurnAttackMultiplier = 1
|
||||
self.NextTurnSelectPrompt = ""
|
||||
self.NextTurnSelectCopies = 0
|
||||
self.NextTurnAddCards = {}
|
||||
self.ZeroCostCardIdsThisTurn = {}
|
||||
self.CombatOver = false
|
||||
self.DiscardPile = {}
|
||||
self.ExhaustPile = {}
|
||||
|
||||
@@ -49,9 +49,9 @@ end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], N
|
||||
method('ShowMainMenu', `self.SelectedClass = ""
|
||||
self:RenderAscension()
|
||||
self:ShowState("menu")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/Title", "메이플 덱 어드벤처")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/Subtitle", "캐릭터를 고르고 덱을 만들어 모험을 시작하세요")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/NewGameButton", "새 게임")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/Title", "Maple Deck Adventure")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/Subtitle", "Choose your character and begin your run")
|
||||
self:SetText("/ui/DefaultGroup/MainMenu/NewGameButton", "New Game")
|
||||
self:BindMenuButtons()`),
|
||||
method('BindMenuButtons', `local buttonEntity = _EntityService:GetEntityByPath("/ui/DefaultGroup/MainMenu/NewGameButton")
|
||||
if buttonEntity ~= nil and (buttonEntity.ButtonComponent ~= nil or buttonEntity:AddComponent("ButtonComponent") ~= nil) then
|
||||
@@ -136,22 +136,28 @@ self:BindLobbyButtons()
|
||||
self:BindMenuButtons()
|
||||
self:GoLobbyMap()`),
|
||||
method('RenderSoulLabel', `local soulPoints = self.SoulPoints or 0
|
||||
self:SetText("/ui/LobbyUIGroup/LobbyHud/SoulLabel", "영혼 " .. string.format("%d", soulPoints))
|
||||
self:SetText("/ui/LobbyUIGroup/SoulShopHud/Souls", "영혼 " .. string.format("%d", soulPoints))`),
|
||||
self:SetText("/ui/LobbyUIGroup/LobbyHud/SoulLabel", "Soul " .. string.format("%d", soulPoints))
|
||||
self:SetText("/ui/LobbyUIGroup/SoulShopHud/Souls", "Soul " .. string.format("%d", soulPoints))`),
|
||||
method('BindLobbyButtons', `if self.LobbyBound == true then
|
||||
return
|
||||
end
|
||||
self.LobbyBound = true
|
||||
local function bindClick(path, handler)
|
||||
local entity = _EntityService:GetEntityByPath(path)
|
||||
if entity ~= nil and (entity.ButtonComponent ~= nil or entity:AddComponent("ButtonComponent") ~= nil) then
|
||||
entity:ConnectEvent(ButtonClickEvent, handler)
|
||||
end
|
||||
local ascMinus = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/LobbyHud/AscMinus")
|
||||
if ascMinus ~= nil and (ascMinus.ButtonComponent ~= nil or ascMinus:AddComponent("ButtonComponent") ~= nil) then
|
||||
ascMinus:ConnectEvent(ButtonClickEvent, function() self:AdjustAscension(-1) end)
|
||||
end
|
||||
bindClick("/ui/LobbyUIGroup/LobbyHud/AscMinus", function() self:AdjustAscension(-1) end)
|
||||
bindClick("/ui/LobbyUIGroup/LobbyHud/AscPlus", function() self:AdjustAscension(1) end)
|
||||
bindClick("/ui/LobbyUIGroup/BoardHud/Close", function() self:CloseBoard() end)
|
||||
bindClick("/ui/LobbyUIGroup/SoulShopHud/Close", function() self:CloseSoulShop() end)`),
|
||||
local ascPlus = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/LobbyHud/AscPlus")
|
||||
if ascPlus ~= nil and (ascPlus.ButtonComponent ~= nil or ascPlus:AddComponent("ButtonComponent") ~= nil) then
|
||||
ascPlus:ConnectEvent(ButtonClickEvent, function() self:AdjustAscension(1) end)
|
||||
end
|
||||
local boardClose = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/BoardHud/Close")
|
||||
if boardClose ~= nil and (boardClose.ButtonComponent ~= nil or boardClose:AddComponent("ButtonComponent") ~= nil) then
|
||||
boardClose:ConnectEvent(ButtonClickEvent, function() self:CloseBoard() end)
|
||||
end
|
||||
local soulClose = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/SoulShopHud/Close")
|
||||
if soulClose ~= nil and (soulClose.ButtonComponent ~= nil or soulClose:AddComponent("ButtonComponent") ~= nil) then
|
||||
soulClose:ConnectEvent(ButtonClickEvent, function() self:CloseSoulShop() end)
|
||||
end`),
|
||||
method('ShowCodex', `self.CodexMode = true
|
||||
self.ClassDeckMode = true
|
||||
local close = _EntityService:GetEntityByPath("/ui/DeckUIGroup/DeckAllHud/Close")
|
||||
|
||||
@@ -34,7 +34,7 @@ self:ShowState("shop")`),
|
||||
for i = 1, 3 do
|
||||
local cid = self.ShopChoices[i]
|
||||
local c = self.Cards[cid]
|
||||
local base = "/ui/RunUIGroup/ShopHud/Card" .. tostring(i)
|
||||
local base = "/ui/RunUIGroup/ShopHud/Card" .. self:IntStr(i)
|
||||
if c ~= nil then
|
||||
self:ApplyCardFace(base, cid)
|
||||
self:SetText(base .. "/Price", string.format("%d", ${CARD_PRICE}) .. " 메소")
|
||||
|
||||
@@ -41,43 +41,59 @@ if lp ~= nil then
|
||||
end
|
||||
self:RenderSoulLabel()`, [{ Type: "number", DefaultValue: null, SyncDirection: 0, Attributes: [], Name: "n" }]),
|
||||
method('BuySoulUnlock', `local d = nil
|
||||
if self.SoulShopDef ~= nil then d = self.SoulShopDef[slot] end
|
||||
if d == nil then return end
|
||||
if self.SoulUnlocks ~= nil and self.SoulUnlocks[d.key] == true then
|
||||
self:Toast("이미 보유 중입니다")
|
||||
if self.SoulShopDef ~= nil then
|
||||
d = self.SoulShopDef[slot]
|
||||
end
|
||||
if d == nil then
|
||||
return
|
||||
end
|
||||
if (self.SoulPoints or 0) < d.cost then
|
||||
self:Toast("영혼이 부족합니다")
|
||||
local unlockKey = d.key
|
||||
local unlockCost = d.cost
|
||||
local unlockName = d.name or "Unlock"
|
||||
if unlockKey == nil or unlockCost == nil then
|
||||
return
|
||||
end
|
||||
self.SoulPoints = self.SoulPoints - d.cost
|
||||
if self.SoulUnlocks == nil then self.SoulUnlocks = {} end
|
||||
self.SoulUnlocks[d.key] = true
|
||||
if self.SoulUnlocks ~= nil and self.SoulUnlocks[unlockKey] == true then
|
||||
self:Toast("Already owned")
|
||||
return
|
||||
end
|
||||
if (self.SoulPoints or 0) < unlockCost then
|
||||
self:Toast("Not enough soul")
|
||||
return
|
||||
end
|
||||
self.SoulPoints = self.SoulPoints - unlockCost
|
||||
if self.SoulUnlocks == nil then
|
||||
self.SoulUnlocks = {}
|
||||
end
|
||||
self.SoulUnlocks[unlockKey] = true
|
||||
local lp = _UserService.LocalPlayer
|
||||
if lp ~= nil then
|
||||
self:SaveSouls(self.SoulPoints, self:SerializeUnlocks(), lp.PlayerComponent.UserId)
|
||||
end
|
||||
self:Toast(d.name .. " 해금!")
|
||||
self:Toast(unlockName .. " unlocked")
|
||||
self:RenderSoulLabel()
|
||||
self:RenderSoulShop()`, [{ Type: "number", DefaultValue: null, SyncDirection: 0, Attributes: [], Name: "slot" }]),
|
||||
method('RenderSoulShop', `local defs = self.SoulShopDef or {}
|
||||
for i = 1, 4 do
|
||||
local base = "/ui/LobbyUIGroup/SoulShopHud/Item" .. tostring(i)
|
||||
local base = "/ui/LobbyUIGroup/SoulShopHud/Item" .. self:IntStr(i)
|
||||
local d = defs[i]
|
||||
if d == nil then
|
||||
self:SetEntityEnabled(base, false)
|
||||
else
|
||||
local itemName = d.name or "Unlock"
|
||||
local itemDesc = d.desc or ""
|
||||
local itemKey = d.key
|
||||
local itemCost = d.cost or 0
|
||||
self:SetEntityEnabled(base, true)
|
||||
self:SetText(base .. "/Name", d.name)
|
||||
self:SetText(base .. "/Desc", d.desc)
|
||||
local owned = self.SoulUnlocks ~= nil and self.SoulUnlocks[d.key] == true
|
||||
self:SetText(base .. "/Name", itemName)
|
||||
self:SetText(base .. "/Desc", itemDesc)
|
||||
local owned = itemKey ~= nil and self.SoulUnlocks ~= nil and self.SoulUnlocks[itemKey] == true
|
||||
if owned then
|
||||
self:SetText(base .. "/Status", "보유 중")
|
||||
elseif (self.SoulPoints or 0) >= d.cost then
|
||||
self:SetText(base .. "/Status", tostring(d.cost) .. " 영혼 · 구매")
|
||||
self:SetText(base .. "/Status", "Owned")
|
||||
elseif (self.SoulPoints or 0) >= itemCost then
|
||||
self:SetText(base .. "/Status", tostring(itemCost) .. " soul · buy")
|
||||
else
|
||||
self:SetText(base .. "/Status", tostring(d.cost) .. " 영혼 · 부족")
|
||||
self:SetText(base .. "/Status", tostring(itemCost) .. " soul · low")
|
||||
end
|
||||
end
|
||||
end`),
|
||||
@@ -87,7 +103,7 @@ end
|
||||
self.SoulShopBound = true
|
||||
for i = 1, 4 do
|
||||
local idx = i
|
||||
local e = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/SoulShopHud/Item" .. tostring(i))
|
||||
local e = _EntityService:GetEntityByPath("/ui/LobbyUIGroup/SoulShopHud/Item" .. self:IntStr(i))
|
||||
if e ~= nil and (e.ButtonComponent ~= nil or e:AddComponent("ButtonComponent") ~= nil) then
|
||||
e:ConnectEvent(ButtonClickEvent, function() self:BuySoulUnlock(idx) end)
|
||||
end
|
||||
|
||||
@@ -102,6 +102,217 @@ for i = 1, #lines do
|
||||
out = out .. lines[i]
|
||||
end
|
||||
return out`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'string'),
|
||||
method('GetHoveredCardId', `if path == nil or path == "" then
|
||||
return nil
|
||||
end
|
||||
if string.find(path, "/ui/RunUIGroup/CardHand/Card", 1, true) == 1 then
|
||||
if self.Hand == nil then
|
||||
return nil
|
||||
end
|
||||
local slot = tonumber(string.match(path, "Card(%d+)")) or 0
|
||||
return self.Hand[slot]
|
||||
end
|
||||
if string.find(path, "/ui/RunUIGroup/RewardHud/Reward", 1, true) == 1 then
|
||||
if self.RewardCards == nil then
|
||||
return nil
|
||||
end
|
||||
local slot = tonumber(string.match(path, "Reward(%d+)")) or 0
|
||||
return self.RewardCards[slot]
|
||||
end
|
||||
if string.find(path, "/ui/RunUIGroup/ShopHud/Card", 1, true) == 1 then
|
||||
if self.ShopCards == nil then
|
||||
return nil
|
||||
end
|
||||
local slot = tonumber(string.match(path, "Card(%d+)")) or 0
|
||||
return self.ShopCards[slot]
|
||||
end
|
||||
if string.find(path, "/ui/DeckUIGroup/DeckInspectHud/Grid/Card", 1, true) == 1 then
|
||||
local pile = nil
|
||||
if self.DeckInspectKind == "discard" then
|
||||
pile = self.DiscardPile
|
||||
elseif self.DeckInspectKind == "exhaust" then
|
||||
pile = self.ExhaustPile
|
||||
else
|
||||
pile = self.DrawPile
|
||||
end
|
||||
if pile == nil then
|
||||
return nil
|
||||
end
|
||||
local slot = tonumber(string.match(path, "Card(%d+)")) or 0
|
||||
return pile[slot]
|
||||
end
|
||||
if string.find(path, "/ui/DeckUIGroup/DeckAllHud/Grid/Card", 1, true) == 1 then
|
||||
local pile = self.RunDeck
|
||||
if self.ClassDeckMode == true then
|
||||
pile = self.ClassDeckCards
|
||||
elseif self.CodexMode == true then
|
||||
pile = self.CodexCards
|
||||
end
|
||||
if pile == nil then
|
||||
return nil
|
||||
end
|
||||
local slot = tonumber(string.match(path, "Card(%d+)")) or 0
|
||||
return pile[slot]
|
||||
end
|
||||
return nil`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }], 0, 'string'),
|
||||
method('GetGridCardPathAtPoint', `if gridPath == nil or gridPath == "" or touchPoint == nil then
|
||||
return nil
|
||||
end
|
||||
local prefix = nil
|
||||
local maxSlots = 0
|
||||
if gridPath == "/ui/DeckUIGroup/DeckAllHud/Grid" then
|
||||
prefix = "/ui/DeckUIGroup/DeckAllHud/Grid/Card"
|
||||
maxSlots = 120
|
||||
elseif gridPath == "/ui/DeckUIGroup/DeckInspectHud/Grid" then
|
||||
prefix = "/ui/DeckUIGroup/DeckInspectHud/Grid/Card"
|
||||
maxSlots = 60
|
||||
else
|
||||
return nil
|
||||
end
|
||||
local uiPos = _UILogic:ScreenToUIPosition(touchPoint)
|
||||
local bestPath = nil
|
||||
local bestDist = 999999
|
||||
for i = 1, maxSlots do
|
||||
local path = prefix .. self:IntStr(i)
|
||||
local cardEntity = _EntityService:GetEntityByPath(path)
|
||||
if cardEntity ~= nil and cardEntity.Enable == true and cardEntity.UITransformComponent ~= nil then
|
||||
local pos = self:GetUiPathPosition(path)
|
||||
local dx = uiPos.x - pos.x
|
||||
local dy = uiPos.y - pos.y
|
||||
if math.abs(dx) <= 90 and math.abs(dy) <= 125 then
|
||||
local dist = dx * dx + dy * dy
|
||||
if bestPath == nil or dist < bestDist then
|
||||
bestPath = path
|
||||
bestDist = dist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return bestPath`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'gridPath' },
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'touchPoint' },
|
||||
], 0, 'string'),
|
||||
method('GetUiPathPosition', `if path == nil or path == "" then
|
||||
return Vector2(0, 0)
|
||||
end
|
||||
local sumX = 0
|
||||
local sumY = 0
|
||||
local cur = path
|
||||
while cur ~= nil and cur ~= "" do
|
||||
local e = _EntityService:GetEntityByPath(cur)
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
local pos = e.UITransformComponent.anchoredPosition
|
||||
if pos ~= nil then
|
||||
sumX = sumX + (pos.x or 0)
|
||||
sumY = sumY + (pos.y or 0)
|
||||
end
|
||||
end
|
||||
local slash = string.match(cur, "^.*()/")
|
||||
if slash == nil or slash <= 1 then
|
||||
break
|
||||
end
|
||||
cur = string.sub(cur, 1, slash - 1)
|
||||
if cur == "/ui" then
|
||||
break
|
||||
end
|
||||
end
|
||||
return Vector2(sumX, sumY)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }], 0, 'any'),
|
||||
method('GetTooltipAnchorForPath', `local pos = self:GetUiPathPosition(path)
|
||||
local x = pos.x
|
||||
local y = pos.y
|
||||
local sideOffset = 230
|
||||
local verticalOffset = 0
|
||||
if string.find(path, "/ui/RunUIGroup/CardHand/Card", 1, true) == 1 then
|
||||
verticalOffset = 90
|
||||
elseif string.find(path, "/ui/RunUIGroup/RewardHud/Reward", 1, true) == 1 then
|
||||
verticalOffset = 30
|
||||
elseif string.find(path, "/ui/RunUIGroup/ShopHud/Card", 1, true) == 1 then
|
||||
verticalOffset = 20
|
||||
else
|
||||
verticalOffset = 0
|
||||
end
|
||||
local tipX = x + sideOffset
|
||||
if x > 180 then
|
||||
tipX = x - sideOffset
|
||||
end
|
||||
if tipX > 760 then
|
||||
tipX = x - sideOffset
|
||||
end
|
||||
if tipX < -760 then
|
||||
tipX = x + sideOffset
|
||||
end
|
||||
local tipY = y + verticalOffset
|
||||
if tipY > 430 then
|
||||
tipY = 430
|
||||
end
|
||||
if tipY < -430 then
|
||||
tipY = -430
|
||||
end
|
||||
return Vector2(tipX, tipY)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }], 0, 'any'),
|
||||
method('HoverCardByPath', `if path == nil or path == "" then
|
||||
return
|
||||
end
|
||||
if self.DragSlot ~= nil and self.DragSlot > 0 and string.find(path, "/ui/RunUIGroup/CardHand/Card", 1, true) == 1 then
|
||||
return
|
||||
end
|
||||
if self.GridScrollActive == true and (string.find(path, "/ui/DeckUIGroup/DeckAllHud/Grid/Card", 1, true) == 1 or string.find(path, "/ui/DeckUIGroup/DeckInspectHud/Grid/Card", 1, true) == 1) then
|
||||
return
|
||||
end
|
||||
local cardId = self:GetHoveredCardId(path)
|
||||
if cardId == nil or self.Cards == nil then
|
||||
self:HideTooltip()
|
||||
return
|
||||
end
|
||||
local c = self.Cards[cardId]
|
||||
if c == nil then
|
||||
self:HideTooltip()
|
||||
return
|
||||
end
|
||||
local tip = self:BuildCardKeywordTooltip(c)
|
||||
if tip == nil or tip == "" then
|
||||
self:HideTooltip()
|
||||
return
|
||||
end
|
||||
local e = _EntityService:GetEntityByPath(path)
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
if string.find(path, "/ui/RunUIGroup/CardHand/Card", 1, true) == 1 then
|
||||
e.UITransformComponent.UIScale = Vector3(1.3, 1.3, 1)
|
||||
end
|
||||
end
|
||||
local anchor = self:GetTooltipAnchorForPath(path)
|
||||
self:ShowTooltipAt("키워드", tip, anchor.x, anchor.y)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }]),
|
||||
method('HoverGridCard', `if gridPath == nil or touchPoint == nil then
|
||||
return
|
||||
end
|
||||
local path = self:GetGridCardPathAtPoint(gridPath, touchPoint)
|
||||
local lastPath = self.GridHoverPath
|
||||
if lastPath == path then
|
||||
return
|
||||
end
|
||||
if lastPath ~= nil and lastPath ~= "" then
|
||||
self:UnhoverCardByPath(lastPath)
|
||||
end
|
||||
self.GridHoverPath = path or ""
|
||||
if path ~= nil and path ~= "" then
|
||||
self:HoverCardByPath(path)
|
||||
end`, [
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'gridPath' },
|
||||
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'touchPoint' },
|
||||
]),
|
||||
method('UnhoverGridCard', `local path = self.GridHoverPath
|
||||
self.GridHoverPath = ""
|
||||
if path ~= nil and path ~= "" then
|
||||
self:UnhoverCardByPath(path)
|
||||
else
|
||||
self:HideTooltip()
|
||||
end`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'gridPath' }]),
|
||||
method('UnhoverCardByPath', `if path ~= nil and string.find(path, "/ui/RunUIGroup/CardHand/Card", 1, true) == 1 then
|
||||
local e = _EntityService:GetEntityByPath(path)
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||
end
|
||||
end
|
||||
self:HideTooltip()`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' }]),
|
||||
method('HoverCard', `if self.DragSlot ~= nil and self.DragSlot > 0 then
|
||||
return
|
||||
end
|
||||
@@ -112,26 +323,21 @@ local cardId = self.Hand[slot]
|
||||
if cardId == nil then
|
||||
return
|
||||
end
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
local tx = 0
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
tx = e.UITransformComponent.anchoredPosition.x
|
||||
e.UITransformComponent.UIScale = Vector3(1.3, 1.3, 1)
|
||||
end
|
||||
local c = self.Cards[cardId]
|
||||
if c ~= nil then
|
||||
local tip = self:BuildCardKeywordTooltip(c)
|
||||
if tip ~= "" then
|
||||
local tipX = tx + 270
|
||||
if tx > 180 then tipX = tx - 270 end
|
||||
if tipX > 760 then tipX = tx - 270 end
|
||||
if tipX < -760 then tipX = tx + 270 end
|
||||
self:ShowTooltipAt("키워드", tip, tipX, 90)
|
||||
local anchor = self:GetTooltipAnchorForPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
self:ShowTooltipAt("키워드", tip, anchor.x, anchor.y)
|
||||
else
|
||||
self:HideTooltip()
|
||||
end
|
||||
end`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }]),
|
||||
method('UnhoverCard', `local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. tostring(slot))
|
||||
method('UnhoverCard', `local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CardHand/Card" .. self:IntStr(slot))
|
||||
if e ~= nil and e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
||||
end
|
||||
@@ -141,9 +347,9 @@ self:HideTooltip()`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, At
|
||||
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'desc' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
||||
]),
|
||||
method('ShowTooltipAt', `self:SetText("/ui/RunUIGroup/CombatHud/TooltipBox/Name", name)
|
||||
self:SetText("/ui/RunUIGroup/CombatHud/TooltipBox/Desc", desc)
|
||||
local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/TooltipBox")
|
||||
method('ShowTooltipAt', `self:SetText("/ui/ToolTipGroup/TooltipBox/Name", name)
|
||||
self:SetText("/ui/ToolTipGroup/TooltipBox/Desc", desc)
|
||||
local e = _EntityService:GetEntityByPath("/ui/ToolTipGroup/TooltipBox")
|
||||
if e ~= nil then
|
||||
if e.UITransformComponent ~= nil then
|
||||
e.UITransformComponent.anchoredPosition = Vector2(x, y)
|
||||
@@ -155,5 +361,5 @@ end`, [
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'x' },
|
||||
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'y' },
|
||||
]),
|
||||
method('HideTooltip', `self:SetEntityEnabled("/ui/RunUIGroup/CombatHud/TooltipBox", false)`),
|
||||
method('HideTooltip', `self:SetEntityEnabled("/ui/ToolTipGroup/TooltipBox", false)`),
|
||||
];
|
||||
|
||||
@@ -36,6 +36,10 @@ function writeCodeblocks() {
|
||||
prop('number', 'TweenEventId', '0'),
|
||||
prop('number', 'CardHoverTweenId', '0'),
|
||||
prop('number', 'DmgPopSeq', '0'),
|
||||
prop('number', 'CombatCameraShakeSeq', '0'),
|
||||
prop('any', 'DmgPopSlotQueue'),
|
||||
prop('number', 'PlayerDmgPopIndex', '0'),
|
||||
prop('any', 'HpBarOrigins'),
|
||||
prop('any', 'EndTurnHandler'),
|
||||
prop('any', 'NewGameHandler'),
|
||||
prop('any', 'WarriorSelectHandler'),
|
||||
@@ -75,6 +79,8 @@ function writeCodeblocks() {
|
||||
prop('any', 'ClassDeckCards'),
|
||||
prop('string', 'ClassDeckTitle', '""'),
|
||||
prop('string', 'ClassDeckClass', '""'),
|
||||
prop('string', 'GridHoverPath', '""'),
|
||||
prop('boolean', 'GridScrollActive', 'false'),
|
||||
prop('any', 'SoulUnlocks'),
|
||||
prop('any', 'SoulShopDef'),
|
||||
prop('boolean', 'SoulShopBound', 'false'),
|
||||
@@ -142,10 +148,14 @@ function writeCodeblocks() {
|
||||
prop('number', 'PoisonApplicationsThisCombat', '0'),
|
||||
prop('number', 'EnemyStrengthLossThisTurn', '0'),
|
||||
prop('number', 'ActiveKillReward', '0'),
|
||||
prop('number', 'ActiveKillMaxHpGain', '0'),
|
||||
prop('number', 'BonusRewardScreens', '0'),
|
||||
prop('number', 'FightAttackCount', '0'),
|
||||
prop('number', 'TurnAttackCardsPlayed', '0'),
|
||||
prop('number', 'TurnCardsPlayedThisTurn', '0'),
|
||||
prop('number', 'ComboCount', '0'),
|
||||
prop('number', 'HolyChargeCount', '0'),
|
||||
prop('boolean', 'DamagePowerStrengthUsed', 'false'),
|
||||
prop('number', 'DamageDealtThisTurn', '0'),
|
||||
prop('number', 'TurnDiscardedCards', '0'),
|
||||
prop('boolean', 'FirstHpLossDone', 'false'),
|
||||
@@ -173,6 +183,7 @@ function writeCodeblocks() {
|
||||
prop('boolean', 'NextSkillCostZero', 'false'),
|
||||
prop('number', 'NextSkillRepeatCount', '0'),
|
||||
prop('any', 'NextTurnAddCards'),
|
||||
prop('any', 'ZeroCostCardIdsThisTurn'),
|
||||
], [
|
||||
...bootMethods,
|
||||
...screensMethods,
|
||||
|
||||
@@ -19,18 +19,18 @@ for (const cls of Object.keys(CLASSES)) {
|
||||
// 전직 옵션
|
||||
const JOBS = {
|
||||
warrior: [
|
||||
{ id: 'fighter', name: '파이터', desc: '공격 특화\n콤보 어택 · 버서크\n라이징 어택', starter: 'ComboAttack', tier: 2, parent: 'warrior' },
|
||||
{ id: 'page', name: '페이지', desc: '속성 차지 특화\n썬더/블리자드 차지\n파워 가드', starter: 'ThunderCharge', tier: 2, parent: 'warrior' },
|
||||
{ id: 'spearman', name: '스피어맨', desc: '방어·관통 특화\n피어스 · 아이언 월\n하이퍼 바디', starter: 'Pierce', tier: 2, parent: 'warrior' },
|
||||
{ id: 'fighter', name: '파이터', desc: '콤보와 다단 공격 특화\n공격으로 콤보를 쌓고\n추가타로 압박', starter: 'ComboAttack', tier: 2, parent: 'warrior' },
|
||||
{ id: 'page', name: '페이지', desc: '홀리 포스와 방어 특화\n홀리 차지를 쌓아\n공격과 생존 강화', starter: 'HolyCharge', tier: 2, parent: 'warrior' },
|
||||
{ id: 'spearman', name: '스피어맨', desc: '광역·장기전 계열\n대화재 · 소용돌이\n불의 심장', starter: 'Conflagration', tier: 2, parent: 'warrior' },
|
||||
],
|
||||
fighter: [
|
||||
{ id: 'crusader', name: '크루세이더', desc: 'Fighter의 3차 전직\n콤보 압박과 화력 심화\n파이터 카드 계승', starter: '', tier: 3, parent: 'fighter' },
|
||||
{ id: 'crusader', name: '크루세이더', desc: '파이터의 3차 전직\n콤보 상한과 연계 피해 강화\n파이터 카드 계승', starter: 'ComboSynergy', tier: 3, parent: 'fighter' },
|
||||
],
|
||||
page: [
|
||||
{ id: 'knight', name: '나이트', desc: 'Page의 3차 전직\n방어와 차지 운영 심화\n페이지 카드 계승', starter: '', tier: 3, parent: 'page' },
|
||||
{ id: 'knight', name: '나이트', desc: '페이지의 3차 전직\n홀리 차지를 공격·방어·회복으로 전환\n페이지 카드 계승', starter: 'DivineCharge', tier: 3, parent: 'page' },
|
||||
],
|
||||
spearman: [
|
||||
{ id: 'berserker', name: '버서커', desc: 'Spearman의 3차 전직\n관통과 생존 운영 심화\n스피어맨 카드 계승', starter: '', tier: 3, parent: 'spearman' },
|
||||
{ id: 'berserker', name: '버서커', desc: '스피어맨의 3차 전직\n아이언클래드 장기전 풀 계승\n전사 카드 사용', starter: '', tier: 3, parent: 'spearman' },
|
||||
],
|
||||
magician: [
|
||||
{ id: 'firepoison', name: '위자드(불·독)', desc: '화염·독 특화\n파이어 애로우\n포이즌 브레스 · 앰플', starter: 'FireArrow', tier: 2, parent: 'magician' },
|
||||
@@ -100,7 +100,7 @@ const SOUL_UNLOCKS = [
|
||||
{ key: 'relic', name: '유물 수집가', desc: '런 시작 시 유물 1개 추가', cost: 6 },
|
||||
];
|
||||
function luaSoulShopTable(unlocks) {
|
||||
const items = unlocks.map((u) => `\t{ key = ${luaStr(u.key)}, name = ${luaStr(u.name)}, desc = ${luaStr(u.desc)}, cost = ${u.cost} },`).join('\n');
|
||||
const items = unlocks.map((u) => `\t{ key = ${luaStr(u.key)}, name = ${luaStr(u.name)}, desc = ${luaStr(u.desc)}, cost = ${luaNum(u.cost)} },`).join('\n');
|
||||
return `self.SoulShopDef = {\n${items}\n}`;
|
||||
}
|
||||
if (!ENEMIES.enemies[ENEMIES.activeEnemy]) {
|
||||
@@ -165,7 +165,7 @@ for (const id of RELICS.relicPool) {
|
||||
}
|
||||
function luaRelicsTable(relics) {
|
||||
const lines = Object.entries(relics).map(([id, r]) =>
|
||||
`\t${id} = { name = ${luaStr(r.name)}, desc = ${luaStr(r.desc)}, hook = ${luaStr(r.hook)}, effect = ${luaStr(r.effect)}, value = ${r.value}, icon = ${luaStr(r.icon || '')} },`);
|
||||
`\t${id} = { name = ${luaStr(r.name)}, desc = ${luaStr(r.desc)}, hook = ${luaStr(r.hook)}, effect = ${luaStr(r.effect)}, value = ${luaNum(r.value)}, icon = ${luaStr(r.icon || '')} },`);
|
||||
return `self.Relics = {\n${lines.join('\n')}\n}`;
|
||||
}
|
||||
|
||||
@@ -175,32 +175,38 @@ for (const [pid, p] of Object.entries(POTIONS.potions)) {
|
||||
}
|
||||
function luaPotionsTable(potions) {
|
||||
const lines = Object.entries(potions).map(([id, p]) =>
|
||||
`\t${id} = { name = ${luaStr(p.name)}, desc = ${luaStr(p.desc)}, effect = ${luaStr(p.effect)}, value = ${p.value}, icon = ${luaStr(p.icon || '')} },`);
|
||||
`\t${id} = { name = ${luaStr(p.name)}, desc = ${luaStr(p.desc)}, effect = ${luaStr(p.effect)}, value = ${luaNum(p.value)}, icon = ${luaStr(p.icon || '')} },`);
|
||||
return `self.Potions = {\n${lines.join('\n')}\n}`;
|
||||
}
|
||||
|
||||
function luaIntentsArray(intents) {
|
||||
return '{ ' + intents.map((it) => {
|
||||
const fields = [`kind = ${luaStr(it.kind)}`, `value = ${it.value != null ? it.value : 0}`];
|
||||
const fields = [`kind = ${luaStr(it.kind)}`, `value = ${luaNum(it.value != null ? it.value : 0)}`];
|
||||
if (it.effect != null) fields.push(`effect = ${luaStr(it.effect)}`);
|
||||
if (it.card != null) fields.push(`card = ${luaStr(it.card)}`);
|
||||
if (it.count != null) fields.push(`count = ${it.count}`);
|
||||
if (it.count != null) fields.push(`count = ${luaNum(it.count)}`);
|
||||
return `{ ${fields.join(', ')} }`;
|
||||
}).join(', ') + ' }';
|
||||
}
|
||||
function luaEnemiesTable(enemies) {
|
||||
const lines = Object.entries(enemies).map(([id, e]) =>
|
||||
`\t${id} = { name = ${luaStr(e.name)}, maxHp = ${e.maxHp}, intents = ${luaIntentsArray(e.intents)} },`);
|
||||
`\t${id} = { name = ${luaStr(e.name)}, maxHp = ${luaNum(e.maxHp)}, intents = ${luaIntentsArray(e.intents)} },`);
|
||||
return `self.Enemies = {\n${lines.join('\n')}\n}`;
|
||||
}
|
||||
|
||||
function luaStr(s) {
|
||||
return '"' + String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"';
|
||||
}
|
||||
function luaNum(n) {
|
||||
const v = Number(n);
|
||||
if (!Number.isFinite(v)) return '0';
|
||||
if (Number.isInteger(v)) return String(v);
|
||||
return String(v);
|
||||
}
|
||||
function luaJobsTable(jobs) {
|
||||
const cls = Object.entries(jobs).map(([clsId, list]) => {
|
||||
const items = list.map((j) =>
|
||||
`\t\t{ id = ${luaStr(j.id)}, name = ${luaStr(j.name)}, desc = ${luaStr(j.desc)}, starter = ${luaStr(j.starter)}, tier = ${j.tier ?? 2}, parent = ${luaStr(j.parent ?? clsId)} },`).join('\n');
|
||||
`\t\t{ id = ${luaStr(j.id)}, name = ${luaStr(j.name)}, desc = ${luaStr(j.desc)}, starter = ${luaStr(j.starter)}, tier = ${luaNum(j.tier ?? 2)}, parent = ${luaStr(j.parent ?? clsId)} },`).join('\n');
|
||||
return `\t${clsId} = {\n${items}\n\t},`;
|
||||
}).join('\n');
|
||||
return `self.Jobs = {\n${cls}\n}`;
|
||||
@@ -217,97 +223,133 @@ function luaClassLineagesTable(lineages) {
|
||||
}
|
||||
function luaJobMetaTable(meta) {
|
||||
const rows = Object.entries(meta).map(([jobId, entry]) =>
|
||||
`\t${jobId} = { name = ${luaStr(entry.name)}, starter = ${luaStr(entry.starter)}, tier = ${entry.tier}, parent = ${luaStr(entry.parent)}, sourceClass = ${luaStr(entry.sourceClass)} },`);
|
||||
`\t${jobId} = { name = ${luaStr(entry.name)}, starter = ${luaStr(entry.starter)}, tier = ${luaNum(entry.tier)}, parent = ${luaStr(entry.parent)}, sourceClass = ${luaStr(entry.sourceClass)} },`);
|
||||
return `self.JobMeta = {\n${rows.join('\n')}\n}`;
|
||||
}
|
||||
function luaCardsTable(cards) {
|
||||
const lines = Object.entries(cards).map(([id, c]) => {
|
||||
const fields = [`name = ${luaStr(c.name)}`, `cost = ${c.cost}`, `desc = ${luaStr(c.desc)}`, `kind = ${luaStr(c.kind)}`];
|
||||
if (c.damage != null) fields.push(`damage = ${c.damage}`);
|
||||
if (c.damagePerOtherHandCard != null) fields.push(`damagePerOtherHandCard = ${c.damagePerOtherHandCard}`);
|
||||
if (c.damagePerAttackPlayedThisTurn != null) fields.push(`damagePerAttackPlayedThisTurn = ${c.damagePerAttackPlayedThisTurn}`);
|
||||
if (c.damagePerDiscardedThisTurn != null) fields.push(`damagePerDiscardedThisTurn = ${c.damagePerDiscardedThisTurn}`);
|
||||
if (c.damagePerSkillInHand != null) fields.push(`damagePerSkillInHand = ${c.damagePerSkillInHand}`);
|
||||
if (c.damagePerCardDrawnThisCombat != null) fields.push(`damagePerCardDrawnThisCombat = ${c.damagePerCardDrawnThisCombat}`);
|
||||
if (c.damagePerTurn != null) fields.push(`damagePerTurn = ${c.damagePerTurn}`);
|
||||
if (c.cardPlayedDamage != null) fields.push(`cardPlayedDamage = ${c.cardPlayedDamage}`);
|
||||
if (c.cardPlayedRandomDamage != null) fields.push(`cardPlayedRandomDamage = ${c.cardPlayedRandomDamage}`);
|
||||
if (c.firstCardDamageBonus != null) fields.push(`firstCardDamageBonus = ${c.firstCardDamageBonus}`);
|
||||
if (c.rewardOnKill != null) fields.push(`rewardOnKill = ${c.rewardOnKill}`);
|
||||
if (c.intangible != null) fields.push(`intangible = ${c.intangible}`);
|
||||
if (c.endTurnDexLoss != null) fields.push(`endTurnDexLoss = ${c.endTurnDexLoss}`);
|
||||
if (c.poisonPerTurn != null) fields.push(`poisonPerTurn = ${c.poisonPerTurn}`);
|
||||
if (c.attackPoison != null) fields.push(`attackPoison = ${c.attackPoison}`);
|
||||
if (c.otherHandAtLeast != null) fields.push(`otherHandAtLeast = ${c.otherHandAtLeast}`);
|
||||
if (c.bonusHitsWhenOtherHandAtLeast != null) fields.push(`bonusHitsWhenOtherHandAtLeast = ${c.bonusHitsWhenOtherHandAtLeast}`);
|
||||
if (c.block != null) fields.push(`block = ${c.block}`);
|
||||
if (c.blockGainMultiplier != null) fields.push(`blockGainMultiplier = ${c.blockGainMultiplier}`);
|
||||
if (c.blockPerDamageDealtThisTurn != null) fields.push(`blockPerDamageDealtThisTurn = ${c.blockPerDamageDealtThisTurn}`);
|
||||
if (c.strength != null) fields.push(`strength = ${c.strength}`);
|
||||
if (c.dex != null) fields.push(`dex = ${c.dex}`);
|
||||
if (c.thorns != null) fields.push(`thorns = ${c.thorns}`);
|
||||
if (c.cardPlayedBlock != null) fields.push(`cardPlayedBlock = ${c.cardPlayedBlock}`);
|
||||
if (c.weak != null) fields.push(`weak = ${c.weak}`);
|
||||
if (c.vuln != null) fields.push(`vuln = ${c.vuln}`);
|
||||
const fields = [`name = ${luaStr(c.name)}`, `cost = ${luaNum(c.cost)}`, `desc = ${luaStr(c.desc)}`, `kind = ${luaStr(c.kind)}`];
|
||||
if (c.damage != null) fields.push(`damage = ${luaNum(c.damage)}`);
|
||||
if (c.damageFromCurrentBlock != null) fields.push(`damageFromCurrentBlock = ${luaNum(c.damageFromCurrentBlock)}`);
|
||||
if (c.damagePerCombo != null) fields.push(`damagePerCombo = ${luaNum(c.damagePerCombo)}`);
|
||||
if (c.damagePerHolyCharge != null) fields.push(`damagePerHolyCharge = ${luaNum(c.damagePerHolyCharge)}`);
|
||||
if (c.attackDamagePerCombo != null) fields.push(`attackDamagePerCombo = ${luaNum(c.attackDamagePerCombo)}`);
|
||||
if (c.damageNameMatch != null) fields.push(`damageNameMatch = ${luaStr(c.damageNameMatch)}`);
|
||||
if (c.damagePerOwnedNameMatch != null) fields.push(`damagePerOwnedNameMatch = ${luaNum(c.damagePerOwnedNameMatch)}`);
|
||||
if (c.damagePerOtherHandCard != null) fields.push(`damagePerOtherHandCard = ${luaNum(c.damagePerOtherHandCard)}`);
|
||||
if (c.damagePerAttackPlayedThisTurn != null) fields.push(`damagePerAttackPlayedThisTurn = ${luaNum(c.damagePerAttackPlayedThisTurn)}`);
|
||||
if (c.damagePerDiscardedThisTurn != null) fields.push(`damagePerDiscardedThisTurn = ${luaNum(c.damagePerDiscardedThisTurn)}`);
|
||||
if (c.damagePerSkillInHand != null) fields.push(`damagePerSkillInHand = ${luaNum(c.damagePerSkillInHand)}`);
|
||||
if (c.damagePerCardDrawnThisCombat != null) fields.push(`damagePerCardDrawnThisCombat = ${luaNum(c.damagePerCardDrawnThisCombat)}`);
|
||||
if (c.damagePerTurn != null) fields.push(`damagePerTurn = ${luaNum(c.damagePerTurn)}`);
|
||||
if (c.cardPlayedDamage != null) fields.push(`cardPlayedDamage = ${luaNum(c.cardPlayedDamage)}`);
|
||||
if (c.cardPlayedRandomDamage != null) fields.push(`cardPlayedRandomDamage = ${luaNum(c.cardPlayedRandomDamage)}`);
|
||||
if (c.attackPlayedDamage != null) fields.push(`attackPlayedDamage = ${luaNum(c.attackPlayedDamage)}`);
|
||||
if (c.firstCardDamageBonus != null) fields.push(`firstCardDamageBonus = ${luaNum(c.firstCardDamageBonus)}`);
|
||||
if (c.rewardOnKill != null) fields.push(`rewardOnKill = ${luaNum(c.rewardOnKill)}`);
|
||||
if (c.maxHpOnKill != null) fields.push(`maxHpOnKill = ${luaNum(c.maxHpOnKill)}`);
|
||||
if (c.intangible != null) fields.push(`intangible = ${luaNum(c.intangible)}`);
|
||||
if (c.endTurnDexLoss != null) fields.push(`endTurnDexLoss = ${luaNum(c.endTurnDexLoss)}`);
|
||||
if (c.poisonPerTurn != null) fields.push(`poisonPerTurn = ${luaNum(c.poisonPerTurn)}`);
|
||||
if (c.attackPoison != null) fields.push(`attackPoison = ${luaNum(c.attackPoison)}`);
|
||||
if (c.otherHandAtLeast != null) fields.push(`otherHandAtLeast = ${luaNum(c.otherHandAtLeast)}`);
|
||||
if (c.bonusHitsWhenOtherHandAtLeast != null) fields.push(`bonusHitsWhenOtherHandAtLeast = ${luaNum(c.bonusHitsWhenOtherHandAtLeast)}`);
|
||||
if (c.block != null) fields.push(`block = ${luaNum(c.block)}`);
|
||||
if (c.blockGainMultiplier != null) fields.push(`blockGainMultiplier = ${luaNum(c.blockGainMultiplier)}`);
|
||||
if (c.blockPerDamageDealtThisTurn != null) fields.push(`blockPerDamageDealtThisTurn = ${luaNum(c.blockPerDamageDealtThisTurn)}`);
|
||||
if (c.strength != null) fields.push(`strength = ${luaNum(c.strength)}`);
|
||||
if (c.dex != null) fields.push(`dex = ${luaNum(c.dex)}`);
|
||||
if (c.thorns != null) fields.push(`thorns = ${luaNum(c.thorns)}`);
|
||||
if (c.cardPlayedBlock != null) fields.push(`cardPlayedBlock = ${luaNum(c.cardPlayedBlock)}`);
|
||||
if (c.comboOnAttack != null) fields.push(`comboOnAttack = ${luaNum(c.comboOnAttack)}`);
|
||||
if (c.comboMax != null) fields.push(`comboMax = ${luaNum(c.comboMax)}`);
|
||||
if (c.attackWeak != null) fields.push(`attackWeak = ${luaNum(c.attackWeak)}`);
|
||||
if (c.holyChargeOnHolyForce != null) fields.push(`holyChargeOnHolyForce = ${luaNum(c.holyChargeOnHolyForce)}`);
|
||||
if (c.holyChargeMax != null) fields.push(`holyChargeMax = ${luaNum(c.holyChargeMax)}`);
|
||||
if (c.damageTakenReduction != null) fields.push(`damageTakenReduction = ${luaNum(c.damageTakenReduction)}`);
|
||||
if (c.blockOnDamaged != null) fields.push(`blockOnDamaged = ${luaNum(c.blockOnDamaged)}`);
|
||||
if (c.strengthOnDamagedOnce != null) fields.push(`strengthOnDamagedOnce = ${luaNum(c.strengthOnDamagedOnce)}`);
|
||||
if (c.drawOnExhaust != null) fields.push(`drawOnExhaust = ${luaNum(c.drawOnExhaust)}`);
|
||||
if (c.drawNameMatchAutoPlay != null) fields.push(`drawNameMatchAutoPlay = ${luaStr(c.drawNameMatchAutoPlay)}`);
|
||||
if (c.weak != null) fields.push(`weak = ${luaNum(c.weak)}`);
|
||||
if (c.vuln != null) fields.push(`vuln = ${luaNum(c.vuln)}`);
|
||||
if (c.powerEffect != null) fields.push(`powerEffect = ${luaStr(c.powerEffect)}`);
|
||||
if (c.value != null) fields.push(`value = ${c.value}`);
|
||||
if (c.value != null) fields.push(`value = ${luaNum(c.value)}`);
|
||||
if (!c.class) throw new Error(`[gen-slaydeck] 카드 ${id}에 class 누락`);
|
||||
fields.push(`class = ${luaStr(c.class)}`);
|
||||
fields.push(`rarity = ${luaStr(c.rarity)}`);
|
||||
if (c.hits != null) fields.push(`hits = ${c.hits}`);
|
||||
if (c.hits != null) fields.push(`hits = ${luaNum(c.hits)}`);
|
||||
if (c.pierce === true) fields.push('pierce = true');
|
||||
if (c.selfVuln != null) fields.push(`selfVuln = ${c.selfVuln}`);
|
||||
if (c.draw != null) fields.push(`draw = ${c.draw}`);
|
||||
if (c.drawUntilHandSize != null) fields.push(`drawUntilHandSize = ${c.drawUntilHandSize}`);
|
||||
if (c.drawSkillBlock != null) fields.push(`drawSkillBlock = ${c.drawSkillBlock}`);
|
||||
if (c.drawDamage != null) fields.push(`drawDamage = ${c.drawDamage}`);
|
||||
if (c.drawPoison != null) fields.push(`drawPoison = ${c.drawPoison}`);
|
||||
if (c.heal != null) fields.push(`heal = ${c.heal}`);
|
||||
if (c.gainEnergy != null) fields.push(`gainEnergy = ${c.gainEnergy}`);
|
||||
if (c.poison != null) fields.push(`poison = ${c.poison}`);
|
||||
if (c.discard != null) fields.push(`discard = ${c.discard}`);
|
||||
if (c.selfVuln != null) fields.push(`selfVuln = ${luaNum(c.selfVuln)}`);
|
||||
if (c.draw != null) fields.push(`draw = ${luaNum(c.draw)}`);
|
||||
if (c.drawUntilHandSize != null) fields.push(`drawUntilHandSize = ${luaNum(c.drawUntilHandSize)}`);
|
||||
if (c.drawSkillBlock != null) fields.push(`drawSkillBlock = ${luaNum(c.drawSkillBlock)}`);
|
||||
if (c.drawDamage != null) fields.push(`drawDamage = ${luaNum(c.drawDamage)}`);
|
||||
if (c.drawPoison != null) fields.push(`drawPoison = ${luaNum(c.drawPoison)}`);
|
||||
if (c.exhaustHandNonAttack === true) fields.push('exhaustHandNonAttack = true');
|
||||
if (c.exhaustHandAll === true) fields.push('exhaustHandAll = true');
|
||||
if (c.drawPerExhausted != null) fields.push(`drawPerExhausted = ${luaNum(c.drawPerExhausted)}`);
|
||||
if (c.blockPerExhaustedCard != null) fields.push(`blockPerExhaustedCard = ${luaNum(c.blockPerExhaustedCard)}`);
|
||||
if (c.addRandomCardCount != null) fields.push(`addRandomCardCount = ${luaNum(c.addRandomCardCount)}`);
|
||||
if (c.addRandomCardPerExhausted != null) fields.push(`addRandomCardPerExhausted = ${luaNum(c.addRandomCardPerExhausted)}`);
|
||||
if (c.addRandomCardKind != null) fields.push(`addRandomCardKind = ${luaStr(c.addRandomCardKind)}`);
|
||||
if (c.addRandomCardSameClass === true) fields.push('addRandomCardSameClass = true');
|
||||
if (c.addedCardsCostZeroThisTurn === true) fields.push('addedCardsCostZeroThisTurn = true');
|
||||
if (c.playTopDrawPileCount != null) fields.push(`playTopDrawPileCount = ${luaNum(c.playTopDrawPileCount)}`);
|
||||
if (c.playTopDrawPileCountPerEnergy != null) fields.push(`playTopDrawPileCountPerEnergy = ${luaNum(c.playTopDrawPileCountPerEnergy)}`);
|
||||
if (c.heal != null) fields.push(`heal = ${luaNum(c.heal)}`);
|
||||
if (c.healPerHolyCharge != null) fields.push(`healPerHolyCharge = ${luaNum(c.healPerHolyCharge)}`);
|
||||
if (c.gainEnergy != null) fields.push(`gainEnergy = ${luaNum(c.gainEnergy)}`);
|
||||
if (c.comboGain != null) fields.push(`comboGain = ${luaNum(c.comboGain)}`);
|
||||
if (c.removePlayerDebuffs === true) fields.push('removePlayerDebuffs = true');
|
||||
if (c.holyForce === true) fields.push('holyForce = true');
|
||||
if (c.holyChargeGain != null) fields.push(`holyChargeGain = ${luaNum(c.holyChargeGain)}`);
|
||||
if (c.blockPerHolyCharge != null) fields.push(`blockPerHolyCharge = ${luaNum(c.blockPerHolyCharge)}`);
|
||||
if (c.holyChargeSpendAll === true) fields.push('holyChargeSpendAll = true');
|
||||
if (c.poison != null) fields.push(`poison = ${luaNum(c.poison)}`);
|
||||
if (c.discard != null) fields.push(`discard = ${luaNum(c.discard)}`);
|
||||
if (c.discardAll === true) fields.push('discardAll = true');
|
||||
if (c.drawPerDiscarded != null) fields.push(`drawPerDiscarded = ${c.drawPerDiscarded}`);
|
||||
if (c.addShiv != null) fields.push(`addShiv = ${c.addShiv}`);
|
||||
if (c.turnStartShiv != null) fields.push(`turnStartShiv = ${c.turnStartShiv}`);
|
||||
if (c.turnStartDraw != null) fields.push(`turnStartDraw = ${c.turnStartDraw}`);
|
||||
if (c.turnStartDiscard != null) fields.push(`turnStartDiscard = ${c.turnStartDiscard}`);
|
||||
if (c.drawPerDiscarded != null) fields.push(`drawPerDiscarded = ${luaNum(c.drawPerDiscarded)}`);
|
||||
if (c.addShiv != null) fields.push(`addShiv = ${luaNum(c.addShiv)}`);
|
||||
if (c.turnStartShiv != null) fields.push(`turnStartShiv = ${luaNum(c.turnStartShiv)}`);
|
||||
if (c.turnStartDraw != null) fields.push(`turnStartDraw = ${luaNum(c.turnStartDraw)}`);
|
||||
if (c.turnStartDiscard != null) fields.push(`turnStartDiscard = ${luaNum(c.turnStartDiscard)}`);
|
||||
if (c.handCostZeroThisTurn === true) fields.push('handCostZeroThisTurn = true');
|
||||
if (c.drawDisabledThisTurn === true) fields.push('drawDisabledThisTurn = true');
|
||||
if (c.addShivPerDiscard === true) fields.push('addShivPerDiscard = true');
|
||||
if (c.useAllEnergy === true) fields.push('useAllEnergy = true');
|
||||
if (c.shivDamageBonus != null) fields.push(`shivDamageBonus = ${c.shivDamageBonus}`);
|
||||
if (c.firstShivDamageBonus != null) fields.push(`firstShivDamageBonus = ${c.firstShivDamageBonus}`);
|
||||
if (c.shivDamageBonus != null) fields.push(`shivDamageBonus = ${luaNum(c.shivDamageBonus)}`);
|
||||
if (c.firstShivDamageBonus != null) fields.push(`firstShivDamageBonus = ${luaNum(c.firstShivDamageBonus)}`);
|
||||
if (c.shivRetain === true) fields.push('shivRetain = true');
|
||||
if (c.shivAoe === true) fields.push('shivAoe = true');
|
||||
if (c.attackDamageVsWeakMultiplier != null) fields.push(`attackDamageVsWeakMultiplier = ${c.attackDamageVsWeakMultiplier}`);
|
||||
if (c.poisonHits != null) fields.push(`poisonHits = ${c.poisonHits}`);
|
||||
if (c.attackDamageVsWeakMultiplier != null) fields.push(`attackDamageVsWeakMultiplier = ${luaNum(c.attackDamageVsWeakMultiplier)}`);
|
||||
if (c.poisonHits != null) fields.push(`poisonHits = ${luaNum(c.poisonHits)}`);
|
||||
if (c.poisonRandomTargets === true) fields.push('poisonRandomTargets = true');
|
||||
if (c.poisonIfTargetPoisoned === true) fields.push('poisonIfTargetPoisoned = true');
|
||||
if (c.xDamagePerEnergy != null) fields.push(`xDamagePerEnergy = ${c.xDamagePerEnergy}`);
|
||||
if (c.xWeakPerEnergy != null) fields.push(`xWeakPerEnergy = ${c.xWeakPerEnergy}`);
|
||||
if (c.nextTurnBlock != null) fields.push(`nextTurnBlock = ${c.nextTurnBlock}`);
|
||||
if (c.nextTurnDraw != null) fields.push(`nextTurnDraw = ${c.nextTurnDraw}`);
|
||||
if (c.xDamagePerEnergy != null) fields.push(`xDamagePerEnergy = ${luaNum(c.xDamagePerEnergy)}`);
|
||||
if (c.xWeakPerEnergy != null) fields.push(`xWeakPerEnergy = ${luaNum(c.xWeakPerEnergy)}`);
|
||||
if (c.nextTurnBlock != null) fields.push(`nextTurnBlock = ${luaNum(c.nextTurnBlock)}`);
|
||||
if (c.nextTurnDraw != null) fields.push(`nextTurnDraw = ${luaNum(c.nextTurnDraw)}`);
|
||||
if (c.nextTurnKeepBlock === true) fields.push('nextTurnKeepBlock = true');
|
||||
if (c.nextTurnAttackMultiplier != null) fields.push(`nextTurnAttackMultiplier = ${c.nextTurnAttackMultiplier}`);
|
||||
if (c.nextTurnCopies != null) fields.push(`nextTurnCopies = ${c.nextTurnCopies}`);
|
||||
if (c.nextTurnAttackMultiplier != null) fields.push(`nextTurnAttackMultiplier = ${luaNum(c.nextTurnAttackMultiplier)}`);
|
||||
if (c.nextTurnCopies != null) fields.push(`nextTurnCopies = ${luaNum(c.nextTurnCopies)}`);
|
||||
if (c.nextTurnSelectHandCard === true) fields.push('nextTurnSelectHandCard = true');
|
||||
if (c.nextTurnSelectPrompt != null) fields.push(`nextTurnSelectPrompt = ${luaStr(c.nextTurnSelectPrompt)}`);
|
||||
if (c.nextSkillRepeatCount != null) fields.push(`nextSkillRepeatCount = ${c.nextSkillRepeatCount}`);
|
||||
if (c.nextSkillRepeatCount != null) fields.push(`nextSkillRepeatCount = ${luaNum(c.nextSkillRepeatCount)}`);
|
||||
if (c.nextSkillCostZero === true) fields.push('nextSkillCostZero = true');
|
||||
if (c.skillCostReductionThisTurn != null) fields.push(`skillCostReductionThisTurn = ${c.skillCostReductionThisTurn}`);
|
||||
if (c.skillCostReductionThisTurn != null) fields.push(`skillCostReductionThisTurn = ${luaNum(c.skillCostReductionThisTurn)}`);
|
||||
if (c.skillSlyOnPlay === true) fields.push('skillSlyOnPlay = true');
|
||||
if (c.turnHandSlyCount != null) fields.push(`turnHandSlyCount = ${c.turnHandSlyCount}`);
|
||||
if (c.combatCostReductionOnPlay != null) fields.push(`combatCostReductionOnPlay = ${c.combatCostReductionOnPlay}`);
|
||||
if (c.turnHandSlyCount != null) fields.push(`turnHandSlyCount = ${luaNum(c.turnHandSlyCount)}`);
|
||||
if (c.combatCostReductionOnPlay != null) fields.push(`combatCostReductionOnPlay = ${luaNum(c.combatCostReductionOnPlay)}`);
|
||||
if (c.randomTargetEachHit === true) fields.push('randomTargetEachHit = true');
|
||||
if (c.repeatOnKill === true) fields.push('repeatOnKill = true');
|
||||
if (c.affectsAllEnemies === true) fields.push('affectsAllEnemies = true');
|
||||
if (c.removeEnemyBlock === true) fields.push('removeEnemyBlock = true');
|
||||
if (c.removeEnemyArtifact === true) fields.push('removeEnemyArtifact = true');
|
||||
if (c.enemyStrengthLossThisTurn != null) fields.push(`enemyStrengthLossThisTurn = ${c.enemyStrengthLossThisTurn}`);
|
||||
if (c.extraPoisonTicks != null) fields.push(`extraPoisonTicks = ${c.extraPoisonTicks}`);
|
||||
if (c.poisonApplicationBurstEvery != null) fields.push(`poisonApplicationBurstEvery = ${c.poisonApplicationBurstEvery}`);
|
||||
if (c.poisonApplicationBurstDamage != null) fields.push(`poisonApplicationBurstDamage = ${c.poisonApplicationBurstDamage}`);
|
||||
if (c.enemyStrengthLossThisTurn != null) fields.push(`enemyStrengthLossThisTurn = ${luaNum(c.enemyStrengthLossThisTurn)}`);
|
||||
if (c.extraPoisonTicks != null) fields.push(`extraPoisonTicks = ${luaNum(c.extraPoisonTicks)}`);
|
||||
if (c.poisonApplicationBurstEvery != null) fields.push(`poisonApplicationBurstEvery = ${luaNum(c.poisonApplicationBurstEvery)}`);
|
||||
if (c.poisonApplicationBurstDamage != null) fields.push(`poisonApplicationBurstDamage = ${luaNum(c.poisonApplicationBurstDamage)}`);
|
||||
if (c.innate === true) fields.push('innate = true');
|
||||
if (c.playableWhenDrawPileEmpty === true) fields.push('playableWhenDrawPileEmpty = true');
|
||||
if (c.sly === true) fields.push('sly = true');
|
||||
@@ -317,7 +359,7 @@ function luaCardsTable(cards) {
|
||||
if (c.unplayable === true) fields.push('unplayable = true');
|
||||
if (c.curse === true) fields.push('curse = true');
|
||||
if (c.token === true) fields.push('token = true');
|
||||
if (c.endTurnDamage != null) fields.push(`endTurnDamage = ${c.endTurnDamage}`);
|
||||
if (c.endTurnDamage != null) fields.push(`endTurnDamage = ${luaNum(c.endTurnDamage)}`);
|
||||
if (c.fx != null) fields.push(`fx = ${luaStr(c.fx)}`);
|
||||
if (c.image != null) fields.push(`image = ${luaStr(c.image)}`);
|
||||
return `\t${id} = { ${fields.join(', ')} },`;
|
||||
|
||||
Reference in New Issue
Block a user