745 lines
27 KiB
JavaScript
745 lines
27 KiB
JavaScript
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 handMethods = [
|
|
method('GetHandSlotX', `local n = 0
|
|
if self.Hand ~= nil then
|
|
n = #self.Hand
|
|
end
|
|
if n <= 0 then
|
|
return 0
|
|
end
|
|
local spacing = 175
|
|
if n > 8 then spacing = math.floor(1400 / n) end
|
|
local startX = -((n - 1) * spacing) / 2
|
|
return startX + (slot - 1) * spacing`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'number'),
|
|
method('RenderHand', `local n = #self.Hand
|
|
local spacing = 175
|
|
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))
|
|
\tif cardEntity ~= nil then
|
|
\t\tlocal cardId = self.Hand[i]
|
|
\t\tif cardId == nil then
|
|
\t\t\tcardEntity.Enable = false
|
|
\t\telse
|
|
\t\t\tcardEntity.Enable = true
|
|
\t\t\tif cardEntity.UITransformComponent ~= nil then cardEntity.UITransformComponent.UIScale = Vector3(1, 1, 1) end
|
|
\t\t\tself:ApplyCardVisual(i, cardId)
|
|
\t\t\tlocal tx = self:GetHandSlotX(i)
|
|
\t\t\tif animate == true then
|
|
\t\t\t\tself:AnimateCardFrom(i, drawStart, Vector2(tx, 0), 0.16 + i * 0.03)
|
|
\t\t\telse
|
|
\t\t\t\tif cardEntity.UITransformComponent ~= nil then cardEntity.UITransformComponent.anchoredPosition = Vector2(tx, 0) end
|
|
\t\t\tend
|
|
\t\tend
|
|
\tend
|
|
end
|
|
self:RenderPiles()`, [{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' }]),
|
|
method('ApplyCardFace', `local c = self.Cards[cardId]
|
|
if c == nil then
|
|
c = { name = cardId, cost = 0, desc = "", kind = "Skill", class = "warrior", rarity = "normal" }
|
|
end
|
|
local e = _EntityService:GetEntityByPath(base)
|
|
if e ~= nil and e.SpriteGUIRendererComponent ~= nil then
|
|
if e.UITransformComponent ~= nil then
|
|
e.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
|
end
|
|
local frames = self.CardFrames[self.ClassToFrame[c.class] or "warrior"]
|
|
local ruid = nil
|
|
if frames ~= nil then
|
|
ruid = frames[c.rarity or "normal"]
|
|
end
|
|
if ruid ~= nil then
|
|
e.SpriteGUIRendererComponent.ImageRUID = ruid
|
|
e.SpriteGUIRendererComponent.Color = Color(1, 1, 1, 1)
|
|
end
|
|
end
|
|
self:SetText(base .. "/Cost", string.format("%d", c.cost))
|
|
self:SetText(base .. "/Name", c.name)
|
|
self:SetText(base .. "/Desc", self:FormatCardDescription(c.desc))
|
|
local art = _EntityService:GetEntityByPath(base .. "/Art")
|
|
if art ~= nil then
|
|
if c.image ~= nil and c.image ~= "" then
|
|
art.Enable = true
|
|
if art.SpriteGUIRendererComponent ~= nil then
|
|
art.SpriteGUIRendererComponent.ImageRUID = c.image
|
|
end
|
|
else
|
|
art.Enable = false
|
|
end
|
|
end`, [
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' },
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
|
]),
|
|
method('SetCardHover', `local prefix = ""
|
|
local count = 0
|
|
local xs = {}
|
|
local baseY = 0
|
|
local hoverIndex = 0
|
|
local push = 110
|
|
if string.find(path, "/ui/RunUIGroup/CardHand/Card") == 1 then
|
|
if self.DragSlot ~= nil and self.DragSlot > 0 then
|
|
return
|
|
end
|
|
prefix = "/ui/RunUIGroup/CardHand/Card"
|
|
count = 0
|
|
if self.Hand ~= nil then count = #self.Hand end
|
|
for i = 1, count do
|
|
xs[i] = self:GetHandSlotX(i)
|
|
end
|
|
baseY = 0
|
|
hoverIndex = tonumber(string.match(path, "Card(%d+)")) or 0
|
|
elseif string.find(path, "/ui/RunUIGroup/RewardHud/Reward") == 1 then
|
|
prefix = "/ui/RunUIGroup/RewardHud/Reward"
|
|
count = 3
|
|
xs = { -300, 0, 300 }
|
|
baseY = 0
|
|
hoverIndex = tonumber(string.match(path, "Reward(%d+)")) or 0
|
|
elseif string.find(path, "/ui/RunUIGroup/ShopHud/Card") == 1 then
|
|
prefix = "/ui/RunUIGroup/ShopHud/Card"
|
|
count = 3
|
|
xs = { -300, 0, 300 }
|
|
baseY = 20
|
|
hoverIndex = tonumber(string.match(path, "Card(%d+)")) or 0
|
|
end
|
|
if count <= 0 then
|
|
return
|
|
end
|
|
if self.CardHoverTweenId ~= nil and self.CardHoverTweenId ~= 0 then
|
|
_TimerService:ClearTimer(self.CardHoverTweenId)
|
|
self.CardHoverTweenId = 0
|
|
end
|
|
local items = {}
|
|
for i = 1, count do
|
|
local e = _EntityService:GetEntityByPath(prefix .. tostring(i))
|
|
if e ~= nil and e.UITransformComponent ~= nil then
|
|
local tr = e.UITransformComponent
|
|
local tx = xs[i]
|
|
local ty = baseY
|
|
local sc = 1
|
|
if hover == true and hoverIndex > 0 then
|
|
if i == hoverIndex and e.Enable == true then
|
|
sc = 1.5
|
|
elseif i < hoverIndex then
|
|
tx = tx - push
|
|
elseif i > hoverIndex then
|
|
tx = tx + push
|
|
end
|
|
end
|
|
table.insert(items, { tr = tr, sx = tr.anchoredPosition.x, sy = tr.anchoredPosition.y, ss = tr.UIScale.x, tx = tx, ty = ty, ts = sc })
|
|
end
|
|
end
|
|
local elapsed = 0
|
|
local duration = 0.12
|
|
local eventId = 0
|
|
eventId = _TimerService:SetTimerRepeat(function()
|
|
elapsed = elapsed + 1 / 60
|
|
local t = math.min(elapsed / duration, 1)
|
|
local eased = _TweenLogic:Ease(0, 1, 1, EaseType.SineEaseOut, t)
|
|
for i = 1, #items do
|
|
local it = items[i]
|
|
local x = it.sx + (it.tx - it.sx) * eased
|
|
local y = it.sy + (it.ty - it.sy) * eased
|
|
local s = it.ss + (it.ts - it.ss) * eased
|
|
it.tr.anchoredPosition = Vector2(x, y)
|
|
it.tr.UIScale = Vector3(s, s, 1)
|
|
end
|
|
if t >= 1 then
|
|
_TimerService:ClearTimer(eventId)
|
|
if self.CardHoverTweenId == eventId then
|
|
self.CardHoverTweenId = 0
|
|
end
|
|
end
|
|
end, 1 / 60)
|
|
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)`, [
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
|
]),
|
|
method('SetText', `local entity = _EntityService:GetEntityByPath(path)
|
|
if entity ~= nil and entity.TextComponent ~= nil then
|
|
\tentity.TextComponent.Text = value
|
|
end`, [
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'path' },
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'value' },
|
|
]),
|
|
method('FormatNumber', `if value == nil then
|
|
return ""
|
|
end
|
|
local n = tonumber(value)
|
|
if n == nil then
|
|
return tostring(value)
|
|
end
|
|
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))
|
|
if cardEntity == nil or cardEntity.UITransformComponent == nil then
|
|
\treturn
|
|
end
|
|
local tr = cardEntity.UITransformComponent
|
|
tr.anchoredPosition = fromPos
|
|
local elapsed = 0
|
|
local eventId = 0
|
|
eventId = _TimerService:SetTimerRepeat(function()
|
|
\telapsed = elapsed + 1 / 60
|
|
\tlocal t = math.min(elapsed / duration, 1)
|
|
\tlocal eased = _TweenLogic:Ease(0, 1, 1, EaseType.SineEaseOut, t)
|
|
\ttr.anchoredPosition = Vector2(fromPos.x + (toPos.x - fromPos.x) * eased, fromPos.y + (toPos.y - fromPos.y) * eased)
|
|
\tif t >= 1 then
|
|
\t\t_TimerService:ClearTimer(eventId)
|
|
\tend
|
|
end, 1 / 60)`, [
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'fromPos' },
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'toPos' },
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'duration' },
|
|
]),
|
|
method('AnimateDiscardCards', `if cardIds == nil or slots == nil then
|
|
\treturn
|
|
end
|
|
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))
|
|
\tif e ~= nil then
|
|
\t\te.Enable = true
|
|
\t\tself:ApplyCardFace("/ui/RunUIGroup/CardHand/Card" .. tostring(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
|
|
\t\t\te.UITransformComponent.anchoredPosition = Vector2(sx, 0)
|
|
\t\t\te.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
|
\t\tend
|
|
\tend
|
|
end
|
|
local elapsed = 0
|
|
local eventId = 0
|
|
eventId = _TimerService:SetTimerRepeat(function()
|
|
\telapsed = elapsed + 1 / 60
|
|
\tlocal t = math.min(elapsed / duration, 1)
|
|
\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\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
|
|
\t\t\tlocal x = sx + (target.x - sx) * eased
|
|
\t\t\tlocal y = 0 + (target.y - 0) * eased
|
|
\t\t\tlocal s = 1 - 0.25 * eased
|
|
\t\t\te.UITransformComponent.anchoredPosition = Vector2(x, y)
|
|
\t\t\te.UITransformComponent.UIScale = Vector3(s, s, 1)
|
|
\t\tend
|
|
\tend
|
|
\tif t >= 1 then
|
|
\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\tif e ~= nil then
|
|
\t\t\t\tif self.Hand ~= nil and self.Hand[slot] ~= nil then
|
|
\t\t\t\t\te.Enable = true
|
|
\t\t\t\t\tself:ApplyCardVisual(slot, self.Hand[slot])
|
|
\t\t\t\t\tif e.UITransformComponent ~= nil then
|
|
\t\t\t\t\t\te.UITransformComponent.anchoredPosition = Vector2(self:GetHandSlotX(slot), 0)
|
|
\t\t\t\t\t\te.UITransformComponent.UIScale = Vector3(1, 1, 1)
|
|
\t\t\t\t\tend
|
|
\t\t\t\telse
|
|
\t\t\t\t\te.Enable = false
|
|
\t\t\t\tend
|
|
\t\t\tend
|
|
\t\tend
|
|
\tend
|
|
end, 1 / 60)`, [
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardIds' },
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'startXs' },
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slots' },
|
|
]),
|
|
method('AddCardBlock', `local amount = base or 0
|
|
if amount > 0 and self.PlayerDex ~= nil then
|
|
amount = amount + self.PlayerDex
|
|
end
|
|
if self.BlockGainMultiplier ~= nil and self.BlockGainMultiplier > 1 then
|
|
amount = amount * self.BlockGainMultiplier
|
|
end
|
|
if amount < 0 then
|
|
amount = 0
|
|
end
|
|
self.PlayerBlock = self.PlayerBlock + amount
|
|
return amount`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
|
method('CountOtherHandSkills', `if self.Hand == nil then
|
|
return 0
|
|
end
|
|
local n = 0
|
|
for i = 1, #self.Hand do
|
|
if i ~= slot then
|
|
local hc = self.Cards[self.Hand[i]]
|
|
if hc ~= nil and hc.kind == "Skill" then
|
|
n = n + 1
|
|
end
|
|
end
|
|
end
|
|
return n`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'number'),
|
|
method('AttackBaseForCard', `local base2 = c.damage or 0
|
|
local otherHand = 0
|
|
if self.Hand ~= nil then
|
|
otherHand = #self.Hand - 1
|
|
if otherHand < 0 then otherHand = 0 end
|
|
end
|
|
if c.damagePerOtherHandCard ~= nil then
|
|
base2 = base2 + otherHand * c.damagePerOtherHandCard
|
|
end
|
|
if c.damagePerAttackPlayedThisTurn ~= nil then
|
|
base2 = base2 + (self.TurnAttackCardsPlayed or 0) * c.damagePerAttackPlayedThisTurn
|
|
end
|
|
if c.damagePerDiscardedThisTurn ~= nil then
|
|
base2 = base2 + (self.TurnDiscardedCards or 0) * c.damagePerDiscardedThisTurn
|
|
end
|
|
if c.damagePerSkillInHand ~= nil then
|
|
base2 = base2 + self:CountOtherHandSkills(slot) * c.damagePerSkillInHand
|
|
end
|
|
if c.damagePerCardDrawnThisCombat ~= nil then
|
|
base2 = base2 + (self.CardsDrawnThisCombat or 0) * c.damagePerCardDrawnThisCombat
|
|
end
|
|
if base2 < 0 then
|
|
base2 = 0
|
|
end
|
|
return base2`, [
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
|
{ 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
|
|
base2 = base2 + 8
|
|
end
|
|
local dmg = base2 + self.PlayerStr
|
|
if self:HasRelic("penNib") and self.FightAttackCount % 10 == 0 then
|
|
dmg = dmg * 2
|
|
end
|
|
if self.PlayerWeak > 0 then
|
|
dmg = math.floor(dmg * 0.75)
|
|
end
|
|
if self.TurnAttackMultiplier ~= nil and self.TurnAttackMultiplier > 1 then
|
|
dmg = dmg * self.TurnAttackMultiplier
|
|
end
|
|
if dmg > 0 and dmg < 5 and self:HasRelic("boot") then
|
|
dmg = 5
|
|
end
|
|
if dmg < 0 then
|
|
dmg = 0
|
|
end
|
|
return dmg`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'base' }], 0, 'number'),
|
|
method('QueueNextTurnAddCard', `if cardId == nil or cardId == "" or amount == nil or amount <= 0 then
|
|
return
|
|
end
|
|
if self.NextTurnAddCards == nil then
|
|
self.NextTurnAddCards = {}
|
|
end
|
|
for i = 1, #self.NextTurnAddCards do
|
|
local entry = self.NextTurnAddCards[i]
|
|
if entry ~= nil and entry.cardId == cardId then
|
|
entry.amount = (entry.amount or 0) + amount
|
|
return
|
|
end
|
|
end
|
|
table.insert(self.NextTurnAddCards, { cardId = cardId, amount = amount })`, [
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'amount' },
|
|
]),
|
|
method('QueueNextTurnEffects', `if c == nil then
|
|
return
|
|
end
|
|
if c.nextTurnBlock ~= nil then
|
|
self.NextTurnBlock = (self.NextTurnBlock or 0) + c.nextTurnBlock
|
|
end
|
|
if c.nextTurnDraw ~= nil then
|
|
self.NextTurnDraw = (self.NextTurnDraw or 0) + c.nextTurnDraw
|
|
end
|
|
if c.nextTurnKeepBlock == true then
|
|
self.NextTurnKeepBlock = true
|
|
end
|
|
if c.nextTurnAttackMultiplier ~= nil and c.nextTurnAttackMultiplier > 0 then
|
|
local cur = self.NextTurnAttackMultiplier or 1
|
|
self.NextTurnAttackMultiplier = cur * c.nextTurnAttackMultiplier
|
|
end`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }]),
|
|
method('ResolveCardEffects', `if c == nil then
|
|
return
|
|
end
|
|
if c.blockGainMultiplier ~= nil and c.blockGainMultiplier > 0 then
|
|
self.BlockGainMultiplier = (self.BlockGainMultiplier or 1) * c.blockGainMultiplier
|
|
end
|
|
if c.nextSkillCostZero == true then
|
|
self.NextSkillCostZero = true
|
|
end
|
|
if c.skillCostReductionThisTurn ~= nil and c.skillCostReductionThisTurn > 0 then
|
|
self.SkillCostReductionThisTurn = (self.SkillCostReductionThisTurn or 0) + c.skillCostReductionThisTurn
|
|
end
|
|
if c.handCostZeroThisTurn == true then
|
|
self.HandCostZeroThisTurn = true
|
|
end
|
|
if c.drawDisabledThisTurn == true then
|
|
self.DrawDisabledThisTurn = true
|
|
end
|
|
local xEnergy = energySpent or 0
|
|
local weakAmount = c.weak or 0
|
|
local vulnAmount = c.vuln or 0
|
|
local poisonAmount = c.poison or 0
|
|
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
|
|
self:PlayerAttackMotion()
|
|
local baseDmg = self:AttackBaseForCard(slot, c)
|
|
if c.xDamagePerEnergy ~= nil and c.xDamagePerEnergy > 0 then
|
|
baseDmg = xEnergy * c.xDamagePerEnergy
|
|
end
|
|
local total = 0
|
|
local hitN = c.hits or 1
|
|
if c.otherHandAtLeast ~= nil and c.bonusHitsWhenOtherHandAtLeast ~= nil then
|
|
local otherHand = 0
|
|
if self.Hand ~= nil then
|
|
otherHand = #self.Hand - 1
|
|
if otherHand < 0 then otherHand = 0 end
|
|
end
|
|
if otherHand >= c.otherHandAtLeast then
|
|
hitN = hitN + c.bonusHitsWhenOtherHandAtLeast
|
|
end
|
|
end
|
|
for h = 1, hitN do
|
|
total = total + self:CalcPlayerAttack(baseDmg)
|
|
end
|
|
if c.aoe == true then
|
|
self:PlayAoeFx(c.fx or c.image, total)
|
|
else
|
|
self:PlayAttackFx(self.TargetIndex, c.fx or c.image, total, c.pierce == true)
|
|
end
|
|
end
|
|
if c.block ~= nil then
|
|
self:AddCardBlock(c.block)
|
|
end
|
|
if free ~= true then
|
|
self:ApplyRelics("cardPlayed")
|
|
end
|
|
elseif c.kind == "Skill" then
|
|
if c.block ~= nil then
|
|
self:AddCardBlock(c.block)
|
|
end
|
|
elseif c.kind == "Power" then
|
|
if free ~= true then
|
|
table.insert(self.PlayerPowers, cardId)
|
|
end
|
|
end
|
|
if c.strength ~= nil then
|
|
self.PlayerStr = self.PlayerStr + c.strength
|
|
end
|
|
if c.dex ~= nil then
|
|
self.PlayerDex = self.PlayerDex + c.dex
|
|
end
|
|
if c.thorns ~= nil then
|
|
self.PlayerThorns = self.PlayerThorns + c.thorns
|
|
end
|
|
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)
|
|
end
|
|
if c.gainEnergy ~= nil and c.gainEnergy ~= 0 then
|
|
self.Energy = self.Energy + c.gainEnergy
|
|
end
|
|
if c.intangible ~= nil and c.intangible > 0 then
|
|
self.PlayerIntangible = (self.PlayerIntangible or 0) + c.intangible
|
|
end
|
|
self:QueueNextTurnEffects(c)
|
|
if c.weak ~= nil or c.vuln ~= nil or c.poison ~= nil or c.xWeakPerEnergy ~= nil then
|
|
local tm = self.Monsters[self.TargetIndex]
|
|
if tm == nil or tm.alive ~= true then
|
|
for i = 1, #self.Monsters do
|
|
if self.Monsters[i].alive == true then tm = self.Monsters[i]; self.TargetIndex = i; break end
|
|
end
|
|
end
|
|
if tm ~= nil and tm.alive == true then
|
|
if weakAmount ~= nil and weakAmount > 0 then tm.weak = tm.weak + weakAmount end
|
|
if poisonAmount ~= nil and poisonAmount > 0 then tm.poison = (tm.poison or 0) + poisonAmount end
|
|
if vulnAmount ~= nil and vulnAmount > 0 then
|
|
tm.vuln = tm.vuln + vulnAmount
|
|
if self:HasRelic("championBelt") then
|
|
tm.weak = tm.weak + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local drawnCards = {}
|
|
if c.draw ~= nil then
|
|
drawnCards = self:DrawCards(c.draw, true) or {}
|
|
end
|
|
if c.drawUntilHandSize ~= nil and c.drawUntilHandSize > 0 then
|
|
local currentHand = 0
|
|
if self.Hand ~= nil then
|
|
currentHand = #self.Hand
|
|
if slot ~= nil and slot > 0 and self.Hand[slot] == cardId then
|
|
currentHand = currentHand - 1
|
|
end
|
|
end
|
|
local need = c.drawUntilHandSize - currentHand
|
|
if need > 0 then
|
|
local moreDrawnCards = self:DrawCards(need, true) or {}
|
|
for i = 1, #moreDrawnCards do
|
|
table.insert(drawnCards, moreDrawnCards[i])
|
|
end
|
|
end
|
|
end
|
|
if c.drawSkillBlock ~= nil and c.drawSkillBlock > 0 then
|
|
for i = 1, #drawnCards do
|
|
local drawnCard = self.Cards[drawnCards[i]]
|
|
if drawnCard ~= nil and drawnCard.kind == "Skill" then
|
|
self:AddCardBlock(c.drawSkillBlock)
|
|
end
|
|
end
|
|
end
|
|
if c.addShiv ~= nil and c.discard == nil and c.discardAll ~= true then
|
|
self:AddCardsToHand("Shiv", c.addShiv)
|
|
end`, [
|
|
{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' },
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
|
{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' },
|
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'free' },
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'energySpent' },
|
|
]),
|
|
method('TriggerSly', `local c = self.Cards[cardId]
|
|
if c == nil or c.sly ~= true then
|
|
return
|
|
end
|
|
self:Toast("교활 발동: " .. c.name)
|
|
self:ResolveCardEffects(cardId, 0, c, true, 0)`, [{ Type: 'string', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'cardId' }]),
|
|
method('DiscardHandCard', `if self.Hand == nil then
|
|
return
|
|
end
|
|
local cardId = self.Hand[slot]
|
|
if cardId == nil then
|
|
return
|
|
end
|
|
local startX = self:GetHandSlotX(slot)
|
|
table.remove(self.Hand, slot)
|
|
table.insert(self.DiscardPile, cardId)
|
|
self.TurnDiscardedCards = (self.TurnDiscardedCards or 0) + 1
|
|
if triggerSly == true then
|
|
self:TriggerSly(cardId)
|
|
end
|
|
if animate == true then
|
|
self:AnimateDiscardCards({ cardId }, { startX }, { slot })
|
|
end`, [
|
|
{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' },
|
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'triggerSly' },
|
|
{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'animate' },
|
|
]),
|
|
method('IsDiscardSelecting', `return self.DiscardSelectRemaining ~= nil and self.DiscardSelectRemaining > 0`, [], 0, 'boolean'),
|
|
method('IsRetainSelecting', `return self.RetainSelectActive == true`, [], 0, 'boolean'),
|
|
method('IsReserveSelecting', `return self.ReserveSelectActive == true`, [], 0, 'boolean'),
|
|
method('UpdateDiscardPrompt', `local e = _EntityService:GetEntityByPath("/ui/RunUIGroup/CombatHud/DiscardPrompt")
|
|
if e == nil then
|
|
return
|
|
end
|
|
if self:IsDiscardSelecting() == true then
|
|
local picked = self.DiscardSelectTotal - self.DiscardSelectRemaining
|
|
self:SetText("/ui/RunUIGroup/CombatHud/DiscardPrompt", "버릴 카드 선택 " .. self:FormatNumber(picked + 1) .. "/" .. self:FormatNumber(self.DiscardSelectTotal))
|
|
e.Enable = true
|
|
elseif self:IsRetainSelecting() == true then
|
|
self:SetText("/ui/RunUIGroup/CombatHud/DiscardPrompt", "보존할 카드 선택 (턴 종료: 건너뛰기)")
|
|
e.Enable = true
|
|
elseif self:IsReserveSelecting() == true then
|
|
local msg = self.NextTurnSelectPrompt or ""
|
|
if msg == "" then
|
|
msg = "다음 턴에 예약할 카드를 선택하세요"
|
|
end
|
|
self:SetText("/ui/RunUIGroup/CombatHud/DiscardPrompt", msg)
|
|
e.Enable = true
|
|
else
|
|
e.Enable = false
|
|
end`),
|
|
method('BeginDiscardSelection', `if c == nil or self.Hand == nil then
|
|
return false
|
|
end
|
|
if c.discardAll == true then
|
|
return self:AutoDiscardHand(c)
|
|
end
|
|
local n = 0
|
|
if c.discard ~= nil then
|
|
n = math.min(c.discard, #self.Hand)
|
|
end
|
|
if n <= 0 then
|
|
return false
|
|
end
|
|
self.DiscardSelectRemaining = n
|
|
self.DiscardSelectTotal = n
|
|
self.DiscardPostShiv = 0
|
|
self.DiscardShivPerPick = 0
|
|
self.DiscardPostDraw = 0
|
|
self.DiscardDrawPerPick = 0
|
|
if c.addShiv ~= nil then
|
|
self.DiscardPostShiv = c.addShiv
|
|
end
|
|
if c.addShivPerDiscard == true then
|
|
self.DiscardShivPerPick = 1
|
|
end
|
|
if c.drawPerDiscarded ~= nil and c.drawPerDiscarded > 0 then
|
|
self.DiscardDrawPerPick = c.drawPerDiscarded
|
|
end
|
|
self:UpdateDiscardPrompt()
|
|
self:Toast("버릴 카드를 선택하세요")
|
|
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
|
method('BeginReserveSelection', `if c == nil or c.nextTurnSelectHandCard ~= true or c.nextTurnCopies == nil or c.nextTurnCopies <= 0 then
|
|
return false
|
|
end
|
|
if self.Hand == nil or #self.Hand <= 0 then
|
|
return false
|
|
end
|
|
self.ReserveSelectActive = true
|
|
self.NextTurnSelectCopies = c.nextTurnCopies
|
|
self.NextTurnSelectPrompt = c.nextTurnSelectPrompt or ""
|
|
self:UpdateDiscardPrompt()
|
|
self:Toast("예약할 카드를 선택하세요")
|
|
self:RenderHand(false)
|
|
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
|
method('SelectReserveSlot', `if self:IsReserveSelecting() ~= true then
|
|
return false
|
|
end
|
|
if self.Hand == nil or self.Hand[slot] == nil then
|
|
return true
|
|
end
|
|
local cardId = self.Hand[slot]
|
|
local amount = self.NextTurnSelectCopies or 0
|
|
self.ReserveSelectActive = false
|
|
self.NextTurnSelectCopies = 0
|
|
self.NextTurnSelectPrompt = ""
|
|
self:UpdateDiscardPrompt()
|
|
if amount > 0 and cardId ~= nil then
|
|
self:QueueNextTurnAddCard(cardId, amount)
|
|
local label = cardId
|
|
if self.Cards[cardId] ~= nil and self.Cards[cardId].name ~= nil then
|
|
label = self.Cards[cardId].name
|
|
end
|
|
self:Toast("다음 턴 예약: " .. label .. " " .. self:FormatNumber(amount) .. "장")
|
|
end
|
|
self:RenderPiles()
|
|
self:RenderCombat()
|
|
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
|
method('SelectRetainSlot', `if self:IsRetainSelecting() ~= true then
|
|
return false
|
|
end
|
|
if self.Hand == nil or self.Hand[slot] == nil then
|
|
return true
|
|
end
|
|
self:FinishPlayerTurn(slot)
|
|
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
|
method('AutoDiscardHand', `if c == nil or self.Hand == nil or #self.Hand <= 0 then
|
|
return false
|
|
end
|
|
local cardIds = {}
|
|
local startXs = {}
|
|
local slots = {}
|
|
local n = #self.Hand
|
|
for i = 1, n do
|
|
local cardId = self.Hand[i]
|
|
table.insert(cardIds, cardId)
|
|
table.insert(startXs, self:GetHandSlotX(i))
|
|
table.insert(slots, i)
|
|
table.insert(self.DiscardPile, cardId)
|
|
self.TurnDiscardedCards = (self.TurnDiscardedCards or 0) + 1
|
|
end
|
|
self.Hand = {}
|
|
local shivCount = 0
|
|
if c.addShiv ~= nil then shivCount = shivCount + c.addShiv end
|
|
if c.addShivPerDiscard == true then shivCount = shivCount + n end
|
|
self.DiscardSelectRemaining = 0
|
|
self.DiscardSelectTotal = 0
|
|
self.DiscardPostShiv = 0
|
|
self.DiscardShivPerPick = 0
|
|
self.DiscardPostDraw = 0
|
|
self.DiscardDrawPerPick = 0
|
|
self:UpdateDiscardPrompt()
|
|
self:AnimateDiscardCards(cardIds, startXs, slots)
|
|
for i = 1, #cardIds do
|
|
self:TriggerSly(cardIds[i])
|
|
end
|
|
self:RenderPiles()
|
|
self:RenderCombat()
|
|
_TimerService:SetTimerOnce(function()
|
|
if shivCount > 0 then
|
|
self:AddCardsToHand("Shiv", shivCount)
|
|
else
|
|
self:RenderHand(false)
|
|
self:RenderPiles()
|
|
end
|
|
if c.drawPerDiscarded ~= nil and c.drawPerDiscarded > 0 then
|
|
self:DrawCards(n * c.drawPerDiscarded, true)
|
|
end
|
|
self:RenderCombat()
|
|
self:CheckCombatEnd()
|
|
end, 0.22)
|
|
return true`, [{ Type: 'any', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'c' }], 0, 'boolean'),
|
|
method('FinishDiscardSelection', `self.DiscardSelectRemaining = 0
|
|
self.DiscardSelectTotal = 0
|
|
local shivCount = self.DiscardPostShiv or 0
|
|
local drawCount = self.DiscardPostDraw or 0
|
|
self.DiscardPostShiv = 0
|
|
self.DiscardPostDraw = 0
|
|
self.DiscardShivPerPick = 0
|
|
self.DiscardDrawPerPick = 0
|
|
self:UpdateDiscardPrompt()
|
|
local finish = function()
|
|
if shivCount > 0 then
|
|
self:AddCardsToHand("Shiv", shivCount)
|
|
else
|
|
self:RenderHand(false)
|
|
self:RenderPiles()
|
|
end
|
|
if drawCount > 0 then
|
|
self:DrawCards(drawCount, true)
|
|
end
|
|
self:RenderCombat()
|
|
self:CheckCombatEnd()
|
|
end
|
|
if delayRender == true then
|
|
_TimerService:SetTimerOnce(finish, 0.22)
|
|
else
|
|
finish()
|
|
end`, [{ Type: 'boolean', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'delayRender' }]),
|
|
method('SelectDiscardSlot', `if self:IsDiscardSelecting() ~= true then
|
|
return false
|
|
end
|
|
if self.Hand == nil or self.Hand[slot] == nil then
|
|
return true
|
|
end
|
|
local discarded = self.Hand[slot]
|
|
self:DiscardHandCard(slot, true, true)
|
|
if discarded ~= nil and self.DiscardShivPerPick ~= nil and self.DiscardShivPerPick > 0 then
|
|
self.DiscardPostShiv = (self.DiscardPostShiv or 0) + self.DiscardShivPerPick
|
|
end
|
|
if discarded ~= nil and self.DiscardDrawPerPick ~= nil and self.DiscardDrawPerPick > 0 then
|
|
self.DiscardPostDraw = (self.DiscardPostDraw or 0) + self.DiscardDrawPerPick
|
|
end
|
|
self.DiscardSelectRemaining = self.DiscardSelectRemaining - 1
|
|
if self.DiscardSelectRemaining <= 0 or #self.Hand <= 0 then
|
|
self:FinishDiscardSelection(true)
|
|
else
|
|
self:UpdateDiscardPrompt()
|
|
self:RenderPiles()
|
|
self:RenderCombat()
|
|
_TimerService:SetTimerOnce(function() self:RenderHand(false) end, 0.22)
|
|
end
|
|
return true`, [{ Type: 'number', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: 'slot' }], 0, 'boolean'),
|
|
];
|