1067 lines
32 KiB
Lua
1067 lines
32 KiB
Lua
--- STEAMODDED HEADER
|
|
|
|
--- MOD_NAME: Incantation
|
|
--- MOD_ID: incantation
|
|
--- MOD_AUTHOR: [jenwalter666, MathIsFun_]
|
|
--- MOD_DESCRIPTION: Enables the ability to stack identical consumables.
|
|
--- PRIORITY: 89999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
|
|
--- BADGE_COLOR: 000000
|
|
--- PREFIX: inc
|
|
--- VERSION: 0.5.10
|
|
--- LOADER_VERSION_GEQ: 1.0.0
|
|
|
|
Incantation = {consumable_in_use = false, accelerate = false} --will port more things over to this global later, but for now it's going to be mostly empty
|
|
|
|
local CFG = SMODS.current_mod.config
|
|
|
|
local MaxStack = 9999
|
|
local BulkUseLimit = 9999
|
|
local NaiveBulkUseCancel = 100
|
|
local AccelerateThreshold = 3
|
|
|
|
local HardLimit = 9007199254740992
|
|
|
|
SMODS.current_mod.config_tab = function()
|
|
return {n = G.UIT.ROOT, config = {r = 0.1, align = "cm", padding = 0.1, colour = G.C.BLACK, minw = 8, minh = 4}, nodes = {
|
|
{n = G.UIT.R, config = {align = "cl", padding = 0}, nodes = {
|
|
{n = G.UIT.C, config = { align = "cl", padding = 0.05 }, nodes = {
|
|
create_toggle{ col = true, label = "", scale = 0.85, w = 0, shadow = true, ref_table = CFG, ref_value = "NegativesOnly" },
|
|
}},
|
|
{n = G.UIT.C, config = { align = "c", padding = 0 }, nodes = {
|
|
{ n = G.UIT.T, config = { text = localize('incant_negatives_only'), scale = 0.35, colour = G.C.UI.TEXT_LIGHT }},
|
|
}},
|
|
}},
|
|
{n = G.UIT.R, config = {align = "cl", padding = 0}, nodes = {
|
|
{n = G.UIT.C, config = { align = "cl", padding = 0.05 }, nodes = {
|
|
create_toggle{ col = true, label = "", scale = 0.85, w = 0, shadow = true, ref_table = CFG, ref_value = "StackAnything" },
|
|
}},
|
|
{n = G.UIT.C, config = { align = "c", padding = 0 }, nodes = {
|
|
{ n = G.UIT.T, config = { text = localize('incant_stack_anything'), scale = 0.35, colour = G.C.RED }},
|
|
}},
|
|
}},
|
|
{n = G.UIT.R, config = {align = "cl", padding = 0}, nodes = {
|
|
{n = G.UIT.C, config = { align = "cl", padding = 0.05 }, nodes = {
|
|
create_toggle{ col = true, label = "", scale = 0.85, w = 0, shadow = true, ref_table = CFG, ref_value = "UnsafeMode" },
|
|
}},
|
|
{n = G.UIT.C, config = { align = "c", padding = 0 }, nodes = {
|
|
{ n = G.UIT.T, config = { text = localize('incant_unsafe_mode'), scale = 0.35, colour = G.C.RED }},
|
|
}},
|
|
}}
|
|
}}
|
|
end
|
|
|
|
local function tablecontains(haystack, needle)
|
|
for k, v in pairs(haystack) do
|
|
if v == needle then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local Stackable = {
|
|
'Planet',
|
|
'Tarot',
|
|
'Spectral'
|
|
}
|
|
|
|
local StackableIndividual = {
|
|
'c_black_hole',
|
|
'c_cry_white_hole'
|
|
}
|
|
|
|
local Divisible = {
|
|
'Planet',
|
|
'Tarot',
|
|
'Spectral'
|
|
}
|
|
|
|
local DivisibleIndividual = {
|
|
'c_black_hole',
|
|
'c_cry_white_hole'
|
|
}
|
|
|
|
local BulkUsable = {
|
|
'Planet'
|
|
}
|
|
|
|
local BulkUsableIndividual = {
|
|
'c_black_hole',
|
|
'c_cry_white_hole'
|
|
}
|
|
|
|
--Allow mods to add/remove their own card types to the list
|
|
|
|
function AllowStacking(set)
|
|
if not tablecontains(Stackable, set) then
|
|
table.insert(Stackable, set)
|
|
end
|
|
end
|
|
|
|
function AllowStackingIndividual(key)
|
|
if not tablecontains(StackableIndividual, key) then
|
|
table.insert(StackableIndividual, key)
|
|
end
|
|
end
|
|
|
|
function AllowDividing(set)
|
|
AllowStacking(set)
|
|
if not tablecontains(Divisible, set) then
|
|
table.insert(Divisible, set)
|
|
end
|
|
end
|
|
|
|
function AllowDividingIndividual(key)
|
|
AllowStackingIndividual(key)
|
|
if not tablecontains(DivisibleIndividual, key) then
|
|
table.insert(DivisibleIndividual, key)
|
|
end
|
|
end
|
|
|
|
function AllowBulkUse(set)
|
|
AllowStacking(set)
|
|
AllowDividing(set)
|
|
if not tablecontains(BulkUsable, set) then
|
|
table.insert(BulkUsable, set)
|
|
end
|
|
end
|
|
|
|
function AllowBulkUseIndividual(key)
|
|
AllowStackingIndividual(key)
|
|
AllowDividingIndividual(key)
|
|
if not tablecontains(BulkUsableIndividual, key) then
|
|
table.insert(BulkUsableIndividual, key)
|
|
end
|
|
end
|
|
|
|
--[[
|
|
|
|
+++ MOD SUPPORT SKELETON : ALWAYS INCLUDE THIS IN YOUR MOD'S INITIALISATION SOMEWHERE +++
|
|
|
|
if not IncantationAddons then
|
|
IncantationAddons = {
|
|
Stacking = {},
|
|
Dividing = {},
|
|
BulkUse = {},
|
|
StackingIndividual = {},
|
|
DividingIndividual = {},
|
|
BulkUseIndividual = {}
|
|
}
|
|
end
|
|
|
|
then you can use table.insert() to insert sets/keys into the subtables contained within IncantationAddons
|
|
|
|
]]
|
|
|
|
if IncantationAddons then
|
|
if #IncantationAddons.Stacking > 0 then
|
|
for _, v in pairs(IncantationAddons.Stacking) do
|
|
AllowStacking(v)
|
|
end
|
|
end
|
|
if #IncantationAddons.StackingIndividual > 0 then
|
|
for _, v in pairs(IncantationAddons.StackingIndividual) do
|
|
AllowStackingIndividual(v)
|
|
end
|
|
end
|
|
if #IncantationAddons.Dividing > 0 then
|
|
for _, v in pairs(IncantationAddons.Dividing) do
|
|
AllowDividing(v)
|
|
end
|
|
end
|
|
if #IncantationAddons.DividingIndividual > 0 then
|
|
for _, v in pairs(IncantationAddons.DividingIndividual) do
|
|
AllowDividingIndividual(v)
|
|
end
|
|
end
|
|
if #IncantationAddons.BulkUse > 0 then
|
|
for _, v in pairs(IncantationAddons.BulkUse) do
|
|
AllowBulkUse(v)
|
|
end
|
|
end
|
|
if #IncantationAddons.BulkUseIndividual > 0 then
|
|
for _, v in pairs(IncantationAddons.BulkUseIndividual) do
|
|
AllowBulkUseIndividual(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
function Card:getQty()
|
|
return (self.ability or {}).qty or 1
|
|
end
|
|
|
|
function Card:setQty(quantity, dontupdatecost)
|
|
if not quantity then quantity = 1 end
|
|
if self:CanStack() then
|
|
if self.ability then
|
|
self.ability.qty = math.min(HardLimit, math.floor(quantity))
|
|
self:create_stack_display()
|
|
if not dontupdatecost then self:set_cost() end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Card:addQty(quantity, dontupdatecost)
|
|
self:setQty(self:getQty() + math.floor(quantity), dontupdatecost)
|
|
end
|
|
|
|
function Card:subQty(quantity, dont_dissolve, dontupdatecost)
|
|
if quantity >= self:getQty() and not dont_dissolve then
|
|
self:setQty(0)
|
|
self.ignorestacking = true
|
|
self:start_dissolve()
|
|
else
|
|
self:setQty(math.max(0, self:getQty() - math.ceil(quantity)), dontupdatecost)
|
|
end
|
|
end
|
|
|
|
function Card:CanStack()
|
|
if self.area and G.consumeables and self.area ~= G.consumeables then
|
|
return false
|
|
elseif self.ability and (self.ability.set == 'Booster' or self.ability.set == 'Voucher') then
|
|
return false
|
|
elseif CFG.NegativesOnly and not (self.edition and self.edition.negative) then
|
|
return false
|
|
elseif CFG.StackAnything then
|
|
return true
|
|
end
|
|
|
|
return (self.config.center and (type(self.config.center.can_stack) == 'function' and self.config.center:can_stack() or self.config.center.can_stack)) or tablecontains(Stackable, self.ability.set) or tablecontains(StackableIndividual, self.config.center_key)
|
|
end
|
|
|
|
function Card:CanDivide()
|
|
if CFG.StackAnything then
|
|
return true
|
|
end
|
|
return (self.config.center and (type(self.config.center.can_divide) == 'function' and self.config.center:can_divide() or self.config.center.can_divide)) or tablecontains(Divisible, self.ability.set) or tablecontains(DivisibleIndividual, self.config.center_key)
|
|
end
|
|
|
|
function Card:CanBulkUse(ignoreunsafe)
|
|
return (not ignoreunsafe and CFG.UnsafeMode) or not self.config.center.no_bulkuse and ((self.config.center and (type(self.config.center.can_bulk_use) == 'function' and self.config.center:can_bulk_use() or (self.config.center.can_bulk_use or (self.config.center.bulk_use and (type(self.config.center.bulk_use) == 'function'))))) or tablecontains(BulkUsable, self.ability.set) or tablecontains(BulkUsableIndividual, self.config.center_key))
|
|
end
|
|
|
|
function Card:getmaxuse()
|
|
--let modders define their own bulk-use limit in case of concerns with performance
|
|
return (self.config.center.bulk_use_limit or UseBulkCap) and math.min((self.config.center.bulk_use_limit or BulkUseLimit), self:getQty()) or (self:getQty())
|
|
end
|
|
|
|
function set_consumeable_usage(card, qty)
|
|
qty = math.floor(qty or 1)
|
|
if card.config.center_key and card.ability.consumeable then
|
|
if G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key] then
|
|
G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key].count = G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key].count + qty
|
|
else
|
|
G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key] = {count = 1, order = card.config.center.order}
|
|
end
|
|
if G.GAME.consumeable_usage[card.config.center_key] then
|
|
G.GAME.consumeable_usage[card.config.center_key].count = G.GAME.consumeable_usage[card.config.center_key].count + qty
|
|
else
|
|
G.GAME.consumeable_usage[card.config.center_key] = {count = 1, order = card.config.center.order, set = card.ability.set}
|
|
end
|
|
G.GAME.consumeable_usage_total = G.GAME.consumeable_usage_total or {tarot = 0, planet = 0, spectral = 0, tarot_planet = 0, all = 0}
|
|
if card.config.center.set == 'Tarot' then
|
|
G.GAME.consumeable_usage_total.tarot = G.GAME.consumeable_usage_total.tarot + qty
|
|
G.GAME.consumeable_usage_total.tarot_planet = G.GAME.consumeable_usage_total.tarot_planet + qty
|
|
elseif card.config.center.set == 'Planet' then
|
|
G.GAME.consumeable_usage_total.planet = G.GAME.consumeable_usage_total.planet + qty
|
|
G.GAME.consumeable_usage_total.tarot_planet = G.GAME.consumeable_usage_total.tarot_planet + qty
|
|
elseif card.config.center.set == 'Spectral' then G.GAME.consumeable_usage_total.spectral = G.GAME.consumeable_usage_total.spectral + qty
|
|
end
|
|
|
|
G.GAME.consumeable_usage_total.all = G.GAME.consumeable_usage_total.all + qty
|
|
|
|
if not card.config.center.discovered then
|
|
discover_card(card)
|
|
end
|
|
|
|
if card.config.center.set == 'Tarot' or card.config.center.set == 'Planet' then
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'immediate',
|
|
func = function()
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'immediate',
|
|
func = function()
|
|
G.GAME.last_tarot_planet = card.config.center_key
|
|
return true
|
|
end
|
|
}))
|
|
return true
|
|
end
|
|
}))
|
|
end
|
|
|
|
end
|
|
G:save_settings()
|
|
end
|
|
|
|
function Card:split(amount, forced, fullmax)
|
|
if not amount then amount = math.floor((self:getQty()) / 2) end
|
|
amount = math.max(1, amount)
|
|
if (self.ability.qty or 0) > (fullmax and 0 or 1) and (self:CanDivide() or forced) and not self.ignorestacking then
|
|
local traysize = G.consumeables.config.card_limit
|
|
if (self.edition or {}).negative then
|
|
traysize = traysize + 1
|
|
end
|
|
local split = copy_card(self)
|
|
local qty2 = math.min(self.ability.qty - (fullmax and 0 or 1), amount)
|
|
G.consumeables.config.card_limit = #G.consumeables.cards + 1
|
|
split.ignorestacking = true
|
|
split.created_from_split = true
|
|
split:add_to_deck()
|
|
G.consumeables:emplace(split, nil, nil, true)
|
|
split.ability.qty = qty2
|
|
self.ability.qty = self.ability.qty - qty2
|
|
G.consumeables.config.card_limit = traysize
|
|
if qty2 > 1 then
|
|
split:create_stack_display()
|
|
end
|
|
split:set_cost()
|
|
self:set_cost()
|
|
play_sound('card1')
|
|
return split
|
|
end
|
|
end
|
|
|
|
function Card:try_merge()
|
|
if self:CanStack() and not self.ignorestacking then
|
|
for _, v in pairs(G.consumeables.cards) do
|
|
|
|
if CFG.NegativesOnly and not (v.edition or {}).negative then
|
|
-- Ignore this
|
|
elseif v ~= self and not v.nomerging and not v.ignorestacking and v.config.center_key == self.config.center_key and (((v.edition or {}).type or '') == ((self.edition or {}).type or '')) and (v:getQty() < (UseStackCap and MaxStack or HardLimit)) then
|
|
local space = (UseStackCap and MaxStack or HardLimit) - (v:getQty())
|
|
v.ability.qty = (v:getQty()) + math.min((self:getQty()), space)
|
|
v:create_stack_display()
|
|
v:juice_up(0.5, 0.5)
|
|
play_sound('card1')
|
|
v:set_cost()
|
|
if (self:getQty()) - space < 1 then
|
|
self.ignorestacking = true
|
|
self.area:remove_card(self)
|
|
self:remove()
|
|
return true
|
|
else
|
|
self.ability.qty = (self:getQty()) - space
|
|
self:set_cost()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Card:getEvalQty()
|
|
return self.cardinuse and math.min(self:getQty(), (self.bulkuse and not self.naivebulkuse) and self:getQty() or (self.OverrideBulkUseLimit or NaiveBulkUseCancel)) or self:getQty()
|
|
end
|
|
|
|
local useconsumeref = Card.use_consumeable
|
|
|
|
function Card:use_consumeable(area, copier)
|
|
local obj = self.config.center
|
|
local uselim = self.OverrideBulkUseLimit or NaiveBulkUseCancel
|
|
local qty = self:getQty()
|
|
if qty <= 0 then
|
|
self:setQty(1, true)
|
|
qty = 1
|
|
end
|
|
if self.ability then
|
|
self.ability.qty_initial = qty
|
|
end
|
|
if not self.naivebulkuse and self.bulkuse and obj.bulk_use and type(obj.bulk_use) == 'function' then
|
|
set_consumeable_usage(self, qty)
|
|
return obj:bulk_use(self, area, copier, qty)
|
|
elseif not self.naivebulkuse and self.ability.consumeable.hand_type then
|
|
update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(self.ability.consumeable.hand_type, 'poker_hands'),chips = G.GAME.hands[self.ability.consumeable.hand_type].chips, mult = G.GAME.hands[self.ability.consumeable.hand_type].mult, level=G.GAME.hands[self.ability.consumeable.hand_type].level})
|
|
level_up_hand(copier or self, self.ability.consumeable.hand_type, nil, qty)
|
|
update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''})
|
|
set_consumeable_usage(self, qty)
|
|
elseif not self.naivebulkuse and self.ability.name == 'Black Hole' then
|
|
update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize('k_all_hands'),chips = '...', mult = '...', level=''})
|
|
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
|
|
play_sound('tarot1')
|
|
self:juice_up(0.8, 0.5)
|
|
G.TAROT_INTERRUPT_PULSE = true
|
|
return true end }))
|
|
update_hand_text({delay = 0}, {mult = '+', StatusText = true})
|
|
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function()
|
|
play_sound('tarot1')
|
|
self:juice_up(0.8, 0.5)
|
|
return true end }))
|
|
update_hand_text({delay = 0}, {chips = '+', StatusText = true})
|
|
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function()
|
|
play_sound('tarot1')
|
|
self:juice_up(0.8, 0.5)
|
|
G.TAROT_INTERRUPT_PULSE = nil
|
|
return true end }))
|
|
update_hand_text({sound = 'button', volume = 0.7, pitch = 0.9, delay = 0}, {level='+' .. qty})
|
|
delay(1.3)
|
|
for k, v in pairs(G.GAME.hands) do
|
|
level_up_hand(self, k, true, qty)
|
|
end
|
|
update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''})
|
|
set_consumeable_usage(self, qty)
|
|
else
|
|
Incantation.accelerate = qty > AccelerateThreshold or self.force_incantation_acceleration
|
|
self.cardinuse = true
|
|
Incantation.consumable_in_use = true
|
|
local lim = math.min(qty, uselim)
|
|
local newqty = math.max(0, qty - lim)
|
|
if not self.ability.qty then self.ability.qty = 1 end
|
|
for i = 1, lim do
|
|
useconsumeref(self,area,copier)
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'immediate',
|
|
delay = 0.1,
|
|
blockable = true,
|
|
func = function()
|
|
self.ability.qty = self.ability.qty - 1
|
|
play_sound('button', self.ability.qty <= 0 and 1 or 0.85, 0.7)
|
|
return true
|
|
end
|
|
}))
|
|
end
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'after',
|
|
delay = 0.1,
|
|
blockable = true,
|
|
func = function()
|
|
Incantation.consumable_in_use = false
|
|
Incantation.accelerate = false
|
|
self.cardinuse = nil
|
|
self.bulkuse = nil
|
|
self.naivebulkuse = nil
|
|
self.OverrideBulkUseLimit = nil
|
|
if obj.keep_on_use and obj:keep_on_use(self) then
|
|
self.ignorestacking = false
|
|
self.ability.qty = obj.keep_on_use_retain_stack and qty or (newqty + 1)
|
|
else
|
|
if newqty > 0 then
|
|
self:split(newqty, true, true)
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
}))
|
|
end
|
|
end
|
|
|
|
local startdissolveref = Card.start_dissolve
|
|
function Card:start_dissolve(a,b,c,d)
|
|
if self.ability.qty and self.ability.qty > 1 and Incantation.consumable_in_use and self.cardinuse and not self.ignore_incantation_consumable_in_use then return end
|
|
self.ignorestacking = true
|
|
return startdissolveref(self,a,b,c,d)
|
|
end
|
|
|
|
local usecardref = G.FUNCS.use_card
|
|
|
|
function CanUseStackButtons()
|
|
if ((G.play and #G.play.cards > 0) or (G.CONTROLLER.locked) or (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) and G.STATE ~= G.STATES.HAND_PLAYED and G.STATE ~= G.STATES.DRAW_TO_HAND and G.STATE ~= G.STATES.PLAY_TAROT then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
G.FUNCS.use_card = function(e, mute, nosave)
|
|
local card = e.config.ref_table
|
|
local useamount = card.bulkuse and card:getmaxuse() or 1
|
|
if ((card.ability or {}).qty or 1) > useamount then
|
|
card.highlighted = false
|
|
card.bulkuse = false
|
|
card.OverrideBulkUseLimit = useamount
|
|
end
|
|
usecardref(e, mute, nosave)
|
|
end
|
|
|
|
G.FUNCS.can_split_card = function(e)
|
|
local card = e.config.ref_table
|
|
local splitone = e.config.issplitone
|
|
if (card:getQty()) > 1 and card.highlighted and CanUseStackButtons() and not card.ignorestacking then
|
|
e.config.colour = splitone and G.C.GREEN or G.C.PURPLE
|
|
e.config.button = splitone and 'split_one' or 'split_half'
|
|
e.states.visible = true
|
|
else
|
|
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
|
|
e.config.button = nil
|
|
e.states.visible = false
|
|
end
|
|
end
|
|
|
|
function Card:MergeAvailable()
|
|
if ((self.config or {}).center or {}).set ~= 'Joker' and ((self.config or {}).center or {}).set ~= 'Booster' then
|
|
for k, v in pairs(G.consumeables.cards) do
|
|
if v then
|
|
if v ~= self and (v.config or {}).center_key == (self.config or {}).center_key and ((v.edition or {}).type or '') == ((self.edition or {}).type or '') then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
G.FUNCS.can_merge_card = function(e)
|
|
local card = e.config.ref_table
|
|
if card:CanStack() and card.highlighted and not card.ignorestacking and CanUseStackButtons() and card:MergeAvailable() then
|
|
e.config.colour = G.C.BLUE
|
|
e.config.button = 'merge_card'
|
|
e.states.visible = true
|
|
else
|
|
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
|
|
e.config.button = nil
|
|
e.states.visible = false
|
|
end
|
|
end
|
|
|
|
G.FUNCS.can_use_all = function(e)
|
|
local card = e.config.ref_table
|
|
local obj = card.config.center
|
|
if card:CanBulkUse() and ((tablecontains(BulkUsable, card.ability.set) or tablecontains(BulkUsableIndividual, card.config.center_key)) or (obj.bulk_use and type(obj.bulk_use) == 'function')) and (card:getQty()) > 1 and card.highlighted and CanUseStackButtons() and not card.ignorestacking then
|
|
e.config.colour = G.C.DARK_EDITION
|
|
e.config.button = 'use_all'
|
|
e.states.visible = true
|
|
else
|
|
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
|
|
e.config.button = nil
|
|
e.states.visible = false
|
|
end
|
|
end
|
|
|
|
G.FUNCS.can_use_every_planet = function(e)
|
|
local card = e.config.ref_table
|
|
local obj = card.config.center
|
|
if (((card.config or {}).center or {}).set or '') == 'Planet' and card:CanBulkUse() and CanUseStackButtons() and not card.ignorestacking and not obj.ignore_allplanets then
|
|
e.config.colour = G.C.SECONDARY_SET.Planet
|
|
e.config.button = 'use_every_planet'
|
|
e.states.visible = true
|
|
else
|
|
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
|
|
e.config.button = nil
|
|
e.states.visible = false
|
|
end
|
|
end
|
|
|
|
G.FUNCS.can_use_naivebulk = function(e)
|
|
local card = e.config.ref_table
|
|
local obj = card.config.center
|
|
if (card:CanBulkUse() or CFG.UnsafeMode) and (CFG.UnsafeMode or not obj.bulk_use or type(obj.bulk_use) ~= 'function') and (card:getQty()) > 1 and card.highlighted and CanUseStackButtons() and not card.ignorestacking then
|
|
e.config.colour = G.C.BLACK
|
|
e.config.button = 'use_naivebulk'
|
|
e.states.visible = true
|
|
else
|
|
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
|
|
e.config.button = nil
|
|
e.states.visible = false
|
|
end
|
|
end
|
|
|
|
G.FUNCS.split_half = function(e)
|
|
local card = e.config.ref_table
|
|
card:split(math.floor(card.ability.qty / 2))
|
|
end
|
|
|
|
G.FUNCS.split_one = function(e)
|
|
local card = e.config.ref_table
|
|
card:split(1)
|
|
end
|
|
|
|
G.FUNCS.merge_card = function(e)
|
|
local card = e.config.ref_table
|
|
card:try_merge()
|
|
end
|
|
|
|
G.FUNCS.use_all = function(e)
|
|
local card = e.config.ref_table
|
|
local obj = card.config.center
|
|
if card:CanBulkUse() and (not obj.can_use or obj:can_use(card)) and (card:getQty()) > 1 and card.highlighted then
|
|
card.bulkuse = true
|
|
G.FUNCS.use_card(e, false, true)
|
|
end
|
|
end
|
|
|
|
function runthrough_planets()
|
|
for i = 1, #G.play.cards do
|
|
local card = G.play.cards[i]
|
|
if card then
|
|
local obj = card.config.center
|
|
if (((card.config or {}).center or {}).set or '') == 'Planet' then
|
|
card.bulkuse = card:CanBulkUse() and math.max(1, card:getQty()) > 1
|
|
card.force_incantation_acceleration = true
|
|
card:use_consumeable(G.consumeables)
|
|
if G.betmma_abilities then
|
|
for i = 1, #G.betmma_abilities.cards do
|
|
G.betmma_abilities.cards[i]:calculate_joker({using_consumeable = true, consumeable = card})
|
|
end
|
|
end
|
|
for i = 1, #G.jokers.cards do
|
|
local effects = G.jokers.cards[i]:calculate_joker({using_consumeable = true, consumeable = card})
|
|
if effects and effects.joker_repetitions then
|
|
rep_list = effects.joker_repetitions
|
|
for z=1, #rep_list do
|
|
if type(rep_list[z]) == 'table' and rep_list[z].repetitions then
|
|
for r=1, rep_list[z].repetitions do
|
|
card_eval_status_text(rep_list[z].card, 'jokers', nil, nil, nil, rep_list[z])
|
|
G.jokers.cards[i]:calculate_joker({using_consumeable = true, consumeable = card, retrigger_joker = true})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
G.E_MANAGER:add_event(Event({func = function()
|
|
card.ignore_incantation_consumable_in_use = true
|
|
card:start_dissolve()
|
|
return true
|
|
end}))
|
|
end
|
|
end
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'after',
|
|
delay = 0.1,
|
|
blockable = true,
|
|
func = function()
|
|
Incantation.consumable_in_use = false
|
|
Incantation.accelerate = false
|
|
return true
|
|
end
|
|
}))
|
|
end
|
|
end
|
|
|
|
G.FUNCS.use_every_planet = function(e)
|
|
local targets = {}
|
|
for i = 1, #G.consumeables.cards do
|
|
local card = G.consumeables.cards[i]
|
|
if card then
|
|
local obj = card.config.center
|
|
if (((card.config or {}).center or {}).set or '') == 'Planet' and (not obj.can_use or obj:can_use(card)) and not obj.ignore_allplanets then
|
|
table.insert(targets, card)
|
|
end
|
|
end
|
|
end
|
|
for i = 1, #targets do
|
|
local card = targets[i]
|
|
G.E_MANAGER:add_event(Event({func = function()
|
|
if math.ceil(i/2) == i/2 then play_sound('card1') end
|
|
card.area:remove_card(card)
|
|
G.play:emplace(card)
|
|
return true
|
|
end}))
|
|
end
|
|
G.E_MANAGER:add_event(Event({func = function()
|
|
runthrough_planets()
|
|
return true
|
|
end}))
|
|
end
|
|
|
|
G.FUNCS.use_naivebulk = function(e)
|
|
local card = e.config.ref_table
|
|
local obj = card.config.center
|
|
if card:CanBulkUse() and (not obj.can_use or obj:can_use(card)) and (card:getQty()) > 1 and card.highlighted and CFG.UnsafeMode then
|
|
card.naivebulkuse = true
|
|
card.bulkuse = true
|
|
G.FUNCS.use_card(e, false, true)
|
|
end
|
|
end
|
|
|
|
G.FUNCS.disablestackdisplay = function(e)
|
|
local card = e.config.ref_table
|
|
e.states.visible = ((card:getQty()) > 1 and not card.ignorestacking) or card.cardinuse
|
|
end
|
|
|
|
function Card:create_stack_display()
|
|
if not self.children.stackdisplay and self:CanStack() and not self.playing_card then
|
|
self.children.stackdisplay = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.6,
|
|
maxh = 1.2,
|
|
minw = 0.5,
|
|
maxw = 2,
|
|
r = 0.001,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = adjust_alpha(darken(G.C.BLACK, 0.2), 0.6),
|
|
shadow = false,
|
|
func = 'disablestackdisplay',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'x',
|
|
scale = 0.4,
|
|
colour = G.C.MULT
|
|
}
|
|
},
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
ref_table = self.ability,
|
|
ref_value = 'qty',
|
|
scale = 0.4,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'cm',
|
|
bond = 'Strong',
|
|
parent = self
|
|
},
|
|
states = {
|
|
collide = { can = false },
|
|
drag = { can = true }
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
local card_load_ref = Card.load
|
|
function Card:load(cardTable, other_card)
|
|
card_load_ref(self, cardTable, other_card)
|
|
if self.ability then
|
|
if self.ability.qty then
|
|
self:create_stack_display()
|
|
end
|
|
end
|
|
end
|
|
|
|
local deckadd = Card.add_to_deck
|
|
function Card:add_to_deck(from_debuff)
|
|
deckadd(self, from_debuff)
|
|
if G.consumeables then
|
|
if self:CanStack() then
|
|
if not self.ignorestacking then
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = 'after',
|
|
delay = 0.1,
|
|
blocking = false,
|
|
func = function()
|
|
if self and self.area and self.area ~= 'shop' and self.area ~= 'pack_cards' then
|
|
self:try_merge()
|
|
end
|
|
return true
|
|
end
|
|
}))
|
|
end
|
|
self.ignorestacking = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
local hlref = Card.highlight
|
|
|
|
function Card:highlight(is_highlighted)
|
|
local isplanet = ((self.ability or {}).set or '') == 'Planet'
|
|
if self:CanStack() and self.added_to_deck and not self.ignorestacking then
|
|
if is_highlighted then
|
|
if isplanet then
|
|
self.children.everyplanetbutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = G.C.SECONDARY_SET.Planet,
|
|
shadow = true,
|
|
button = 'use_every_planet',
|
|
func = 'can_use_every_planet',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'MASS-USE PLANETS',
|
|
scale = 0.3,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 1
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
end
|
|
self.children.useallbutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = G.C.DARK_EDITION,
|
|
shadow = true,
|
|
button = 'use_all',
|
|
func = 'can_use_all',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'BULK USE' .. (CFG.UnsafeMode and ' (NORMAL)' or ''),
|
|
scale = 0.3,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 0.5
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
self.children.mergebutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = G.C.BLUE,
|
|
shadow = true,
|
|
button = 'merge_card',
|
|
func = 'can_merge_card',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'MERGE',
|
|
scale = 0.3,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 1 + (isplanet and 0.5 or 0)
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
self.children.splithalfbutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = G.C.PURPLE,
|
|
shadow = true,
|
|
button = 'split_half',
|
|
func = 'can_split_card',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'SPLIT HALF',
|
|
scale = 0.3,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 1.5 + (isplanet and 0.5 or 0)
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
self.children.splitonebutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
issplitone = true,
|
|
colour = G.C.GREEN,
|
|
shadow = true,
|
|
button = 'split_one',
|
|
func = 'can_split_card',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'SPLIT ONE',
|
|
scale = 0.3,
|
|
colour = G.C.UI.TEXT_LIGHT
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 2 + (isplanet and 0.5 or 0)
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
if CFG.UnsafeMode then
|
|
self.children.useallnaivebutton = UIBox {
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = {
|
|
minh = 0.3,
|
|
maxh = 0.6,
|
|
minw = 0.3,
|
|
maxw = 4,
|
|
r = 0.08,
|
|
padding = 0.1,
|
|
align = 'cm',
|
|
colour = G.C.BLACK,
|
|
shadow = true,
|
|
button = 'use_naivebulk',
|
|
func = 'can_use_naivebulk',
|
|
ref_table = self
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = 'BULK USE (ONE-AT-A-TIME)',
|
|
scale = 0.3,
|
|
colour = G.C.RED
|
|
}
|
|
}
|
|
}
|
|
},
|
|
config = {
|
|
align = 'bmi',
|
|
offset = {
|
|
x = 0,
|
|
y = 2.5 + (isplanet and 0.5 or 0)
|
|
},
|
|
bond = 'Strong',
|
|
parent = self
|
|
}
|
|
}
|
|
end
|
|
else
|
|
if isplanet then
|
|
if self.children.everyplanetbutton then self.children.everyplanetbutton:remove();self.children.everyplanetbutton = nil end
|
|
end
|
|
if self.children.splithalfbutton then self.children.splithalfbutton:remove();self.children.splithalfbutton = nil end
|
|
if self.children.splitonebutton then self.children.splitonebutton:remove();self.children.splitonebutton = nil end
|
|
if self.children.mergebutton then self.children.mergebutton:remove();self.children.mergebutton = nil end
|
|
if self.children.useallbutton then self.children.useallbutton:remove();self.children.useallbutton = nil end
|
|
if CFG.UnsafeMode then
|
|
if self.children.useallnaivebutton then self.children.useallnaivebutton:remove();self.children.useallnaivebutton = nil end
|
|
end
|
|
end
|
|
end
|
|
return hlref(self,is_highlighted)
|
|
end
|
|
|
|
local ccr = copy_card
|
|
|
|
function copy_card(other, new_card, card_scale, playing_card, strip_edition)
|
|
local card = ccr(other, new_card, card_scale, playing_card, strip_edition)
|
|
if card then
|
|
if card:getQty() <= 0 then card:setQty(1) end
|
|
end
|
|
card.OverrideBulkUseLimit = nil
|
|
card.bulkuse = nil
|
|
card.naivebulkuse = nil
|
|
card.cardinuse = nil
|
|
card.eval_qty = nil
|
|
return card
|
|
end
|
|
|
|
local costref = Card.set_cost
|
|
function Card:set_cost()
|
|
costref(self)
|
|
self.sell_cost = self.sell_cost * math.max(1, (self.ability or {}).qty or 1)
|
|
self.sell_cost_label = self.facing == 'back' and '?' or self.sell_cost
|
|
end
|
|
|
|
if not (SMODS.Mods['jen'] or {}).can_load then
|
|
SMODS.Joker:take_ownership('perkeo', {
|
|
name = "Perkeo (Incantation)",
|
|
loc_vars = function(self, info_queue, center)
|
|
info_queue[#info_queue+1] = {key = 'e_negative_consumable', set = 'Edition', config = {extra = 1}}
|
|
return {vars = {center.ability.extra}}
|
|
end,
|
|
calculate = function(self, card, context)
|
|
if context.ending_shop then
|
|
if G.consumeables.cards[1] then
|
|
G.E_MANAGER:add_event(Event({
|
|
func = function()
|
|
local total, checked, center = 0, 0, nil
|
|
for i = 1, #G.consumeables.cards do
|
|
total = total + (G.consumeables.cards[i]:getQty())
|
|
end
|
|
local poll = pseudorandom(pseudoseed('perkeo'))*total
|
|
for i = 1, #G.consumeables.cards do
|
|
checked = checked + (G.consumeables.cards[i]:getQty())
|
|
if checked >= poll then
|
|
center = G.consumeables.cards[i]
|
|
break
|
|
end
|
|
end
|
|
local card = copy_card(center, nil)
|
|
card.ability.qty = 1
|
|
card:set_edition({negative = true}, true)
|
|
card:add_to_deck()
|
|
G.consumeables:emplace(card)
|
|
return true
|
|
end}))
|
|
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')})
|
|
return {calculated = true}
|
|
end
|
|
end
|
|
end
|
|
})
|
|
end
|