Jane/src/slugcat.lua

729 lines
22 KiB
Lua

SMODS.Sound({key = "enlightened", path = "enlightened.ogg"})
SMODS.Sound({key = "warning_heartbeat", path = "warning_heartbeat.ogg"})
for i = 1, 8 do
SMODS.Sound({key = "gore" .. i, path = "gore" .. i .. ".ogg"})
end
SMODS.Sound({
key = "music_attuned",
path = "music_attuned.ogg",
volume = 1,
select_music_track = function()
for _, v in pairs(SMODS.find_card("j_jane_saint")) do
if v.ability.extra.is_attuned then
return Jane.sinister and -1 / 0 or 10
end
end
return -1 / 0
end,
})
SMODS.Sound({
key = "music_attuned_sinister",
path = "music_attuned_sinister.ogg",
volume = 1,
select_music_track = function()
for _, v in pairs(SMODS.find_card("j_jane_saint")) do
if v.ability.extra.is_attuned then
return Jane.sinister and 10 or -1 / 0
end
end
return -1 / 0
end,
})
for _, v in pairs({
"artificer",
"hunter",
"gourmand",
"monk",
"rivulet",
"rot",
"saint",
"spearmaster",
"survivor",
}) do
SMODS.Atlas {
key = "jane" .. v,
px = 71,
py = 95,
path = Jane.config.texture_pack .. "/j_jane_" .. v .. ".png",
}
end
local epic = Cryptid and "cry_epic" or 3
local exotic = Cryptid and "cry_exotic" or 4
SMODS.Rarity {
key = "junk",
default_weight = 1e-9,
loc_txt = {name = "Junk"},
badge_colour = G.C.JOKER_GREY,
}
local monk_limit = 25
SMODS.Joker {
key = "monk",
atlas = "janemonk",
loc_txt = {
name = "The Monk",
text = {
"{C:attention}Retrigger {}scored",
"cards {C:attention}#1# time#2# {}if",
"hand contains {C:attention}#3#",
"or fewer card#4#",
},
},
config = {extra = {retriggers = 2, requirement = 4}},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 20,
rarity = 4,
blueprint_compat = true,
loc_vars = function(_, _, card)
local extra = card.ability.extra
local retriggers = extra.retriggers
local requirement = extra.requirement
return {
vars = {
retriggers,
retriggers == 1 and "" or "s",
requirement,
requirement == 1 and "" or "s",
},
}
end,
calculate = function(_, card, context)
if not context.repetition or
context.cardarea ~= G.play or not
context.other_card or
#G.play.cards > card.ability.extra.requirement then
return
end
local min = math.min(card.ability.extra.retriggers, monk_limit)
card.ability.extra.retriggers = min
return {
card = card,
repetitions = min,
colour = G.C.ORANGE,
message = localize("k_again_ex"),
}, true
end,
}
SMODS.Joker {
key = "survivor",
atlas = "janesurvivor",
loc_txt = {
name = "The Survivor",
text = {
"All cards held in hand",
"{C:attention}contribute to scoring" .. (Cryptid and " {}and" or ""),
Cryptid and "are all considered as" or nil,
Cryptid and "the {C:attention}first played card" or nil,
},
},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 20,
rarity = 4,
}
local hunter = {5, 4, 3, 2, 1}
SMODS.Joker {
key = "hunter",
atlas = "janehunter",
loc_txt = {
name = "The Hunter",
text = {
"{C:blue}Provides infinite hands",
"{C:red,s,E:1}Succumbs to the Rot {}and creates",
(Cryptid and "an {C:spectral}Empowered Tag" or "a {C:dark_edition}Negative {C:spectral}Soul") .. " {}after #1#",
"When {C:attention}sold#2#{}, turns#3#",
"#4#{C:red}The Rot{} without rewards",
},
},
config = {extra = {rounds_left = hunter[1]}},
pos = {x = 0, y = 0},
eternal_compat = false,
perishable_compat = false,
soul_pos = {x = 1, y = 0},
cost = Cryptid and 15 or 8,
rarity = Cryptid and epic or 3,
loc_vars = function(_, info_queue, card)
local function rounds(amount)
return " round" .. ((math.abs(amount) > 1 or math.abs(amount) == 0) and "s" or "")
end
info_queue[#info_queue + 1] = Cryptid and G.P_CENTERS.c_cry_empowered or G.P_CENTERS.c_soul
local rounds_left = card.ability.extra.rounds_left
local sold = rounds_left - hunter[3]
return {
vars = {
rounds_left .. rounds(rounds_left) .. (rounds_left <= 0 and "...?" or ""),
sold <= 0 and "" or " after " .. sold .. rounds(sold),
sold <= 0 and " into" or "",
sold <= 0 and "" or "into ",
},
}
end,
update = function(_, card, _)
if card.added_to_deck and card.children.center and card.children.floating_sprite then
for k, v in ipairs(hunter) do
if card.ability.extra.rounds_left <= v then
card.children.center:set_sprite_pos({x = 0, y = k - 1})
card.children.floating_sprite:set_sprite_pos({x = 1, y = k - 1})
else
break
end
end
end
end,
calculate = function(_, card, context)
local function spawn_rot()
card:flip()
card:juice_up(2, 0.8)
card.getting_sliced = true
Jane.card_status_text(card, "Dead!", nil, 0.05 * card.T.h, G.C.BLACK, 2, 0, 0, nil, "bm", "jane_gore6")
Jane.q(function()
local card2 = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jane_rot", "hunter_rot_death")
card2:add_to_deck()
G.jokers:emplace(card2)
card:set_eternal(nil)
card2:set_eternal(true)
play_sound("jane_gore5")
end)
Jane.q(function()
card:start_dissolve()
end, 1)
end
local function die()
Jane.q(function()
Jane.empowered()
end, 0.1)
spawn_rot()
end
if context.blueprint then
return
end
if context.selling_self and card.ability.extra.rounds_left <= hunter[3] then
spawn_rot()
elseif not context.individual and not context.repetition and not context.retrigger_joker then
if G.GAME.round_resets.hands <= 0 then
G.GAME.round_resets.hands = 1
end
if not card.hunter_prep then
card.hunter_prep = true
Jane.q(function()
card.hunter_prep = nil
if G.GAME.current_round.hands_left < G.GAME.round_resets.hands then
ease_hands_played(G.GAME.round_resets.hands - G.GAME.current_round.hands_left)
end
end)
end
if not context.end_of_round then
return
end
card.hunter_prep = nil
card.ability.extra.rounds_left = card.ability.extra.rounds_left - 1
local rl = card.ability.extra.rounds_left
Jane.card_status_text(card, tostring(card.ability.extra.rounds_left), nil, nil, G.C.RED, nil, nil, nil, nil,
nil, "generic1")
if rl > hunter[2] then
card:juice_up(0.6, 0.1)
elseif rl > hunter[3] then
if rl == hunter[2] then
Jane.play_sound("jane_gore1")
end
card:juice_up(0.6, 0.1)
elseif rl > hunter[4] then
if rl == hunter[3] then
Jane.play_sound("jane_gore3")
end
card:juice_up(0.6, 0.1)
elseif rl > hunter[5] then
if rl == hunter[4] then
Jane.play_sound("jane_gore8")
end
card:juice_up(0.6, 0.1)
Jane.play_sound("jane_warning_heartbeat")
elseif rl > 0 then
if rl == hunter[5] then
Jane.play_sound("jane_gore4")
end
card:juice_up(1.8, 0.3)
Jane.play_sound("jane_warning_heartbeat")
else
card:juice_up(2, 0.8)
Jane.play_sound("jane_warning_heartbeat")
Jane.q(die, 0)
end
end
end,
}
SMODS.Joker {
key = "gourmand",
atlas = "janegourmand",
loc_txt = {
name = "The Gourmand",
text = {
"Values on {C:attention}consumables",
"are {C:attention}multiplied{} by {C:attention}#1#",
"when they are created",
"{C:inactive}(If possible)",
},
},
loc_vars = function(_, _, center)
return {vars = {center.ability.modifier}}
end,
config = {modifier = 2},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 8,
rarity = 3,
}
local orig_set_ability = Card.set_ability
---@diagnostic disable-next-line: duplicate-set-field
function Card:set_ability(center, initial, delay_sprites)
orig_set_ability(self, center, initial, delay_sprites)
if next(SMODS.find_card("j_jane_gourmand")) and
self.gc and
self:gc().key ~= "c_base" and
string.sub(self:gc().key, 1, 2) == "c_" then
local mod = 1
for _, v in pairs(SMODS.find_card("j_jane_gourmand")) do
mod = mod * v.ability.modifier
end
Jane.misprintize(self, {min = mod, max = mod}, nil, true)
end
end
SMODS.Joker {
key = "artificer",
atlas = "janeartificer",
loc_txt = {
name = "The Artificer",
text = {
"Grants the {C:green}ability{} to {C:red}destroy",
"selected {C:attention}playing cards",
},
},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = Cryptid and 50 or 20,
rarity = exotic,
Bakery_use_button_text = function(_, _) return "DESTROY" end,
Bakery_can_use = function(_, card)
return not card.debuff and Jane.can_use() and next(G.hand.highlighted)
end,
Bakery_use_joker = function(_, _)
for _, v in pairs(SMODS.find_card("j_jane_oxy")) do
Jane.oxy(v, G.hand.highlighted)
end
for _, v in pairs(G.hand.highlighted) do
v:start_dissolve()
end
end,
}
local spearmaster_limit = 25
SMODS.Joker {
key = "spearmaster",
atlas = "janespearmaster",
loc_txt = {
name = "The Spearmaster",
text = {
"You can choose {C:attention}any number of cards",
"after opening {C:attention}any Booster Pack",
"{C:attention}Booster Packs{} have {C:green}+#1#{} additional cards",
},
},
config = {extra = {choices = 1}},
loc_vars = function(_, _, card)
return {vars = {card.ability.extra.choices}}
end,
calculate = function(_, card, _)
card.ability.extra.choices = math.min(card.ability.extra.choices, spearmaster_limit)
end,
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = Cryptid and 12 or 20,
rarity = Cryptid and epic or 4,
}
local orig_open = Card.open
---@diagnostic disable-next-line: duplicate-set-field
function Card:open()
local orig = self.ability.extra or 1
local spearmasters = SMODS.find_card("j_jane_spearmaster")
if next(spearmasters) then
for _, v in pairs(spearmasters) do
orig = orig + v.ability.extra.choices
end
self.config.choose = math.floor(orig)
self.ability.extra = math.floor(orig)
end
orig_open(self)
Jane.q(function()
if next(spearmasters) then
G.GAME.pack_choices = math.floor(self.ability.extra)
end
end, 0.5, "REAL")
end
SMODS.Joker {
key = "rivulet",
atlas = "janerivulet",
loc_txt = {
name = "The Rivulet",
text = {
"Non-{C:dark_edition}editioned{} cards are",
"{C:attention}given a random {C:dark_edition}Edition",
},
},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 20,
rarity = 4,
}
local orig_draw = Card.draw
function Card:draw(layer)
local cen = self.gc and self:gc()
if self.children.floating_sprite and cen.sinis then
if Jane.sinister and not self.shows_sinister then
self.shows_sinister = true
self.children.floating_sprite:set_sprite_pos(cen.sinis)
elseif not Jane.sinister and self.shows_sinister then
self.shows_sinister = nil
self.children.floating_sprite:set_sprite_pos(cen.soul_pos)
end
if self.shows_sinister then
self:juice_up(0, math.random())
end
end
if cen and
self.facing == "front" and
self.config and
(self.added_to_deck or (self.area and self.area == G.hand)) and not
self.edition and
(self.area == G.consumeables or cen.set ~= "Booster") and
next(SMODS.find_card("j_jane_rivulet")) then
self:set_edition(poll_edition("rivulet_edition", nil, nil, true))
end
orig_draw(self, layer)
end
local orig_debuff = Card.set_debuff
function Card:set_debuff(should_debuff)
if should_debuff and ((self.config or {}).center or {}).debuff_immune then
Jane.card_status_text(self, "Immune", nil, 0.05 * self.T.h, G.C.RED, nil, 0.6, nil, nil, "bm", "cancel", 1, 0.9)
return false
else
orig_debuff(self, should_debuff)
end
end
local function attunement()
return (G.GAME or {}).weeckweeck and 2 or (Cryptid and 1.001 or 1.2)
end
SMODS.Joker {
key = "saint",
atlas = "janesaint",
loc_txt = {
name = "The Saint{C:jane_RGB}#1#",
text = Cryptid and {
"{C:spectral}Analog{}, {C:spectral}Ankh{}, {C:spectral}Gateway{}, and",
"{C:spectral,s:0.95}Summoning {s:0.95}will {C:attention,s:0.95}not destroy Jokers",
"{C:jane_RGB}#2#{}#3#{X:black,C:jane_RGB,s:1.5}#4#{C:spectral}#5#{C:chips}#6#{}#7#{C:mult}#8#",
"{C:inactive,s:1.25}#9#{C:attention,s:1.25}#10#{C:inactive,s:1.25}#11#{C:inactive}#12#",
} or {
"{C:spectral}Ankh {}will {C:attention}not destroy Jokers",
"{C:jane_RGB}#2#{}#3#{C:dark_edition}#4#{C:spectral}#5#",
"{C:inactive,s:1.25}#6#{C:attention,s:1.25}#7#{C:inactive,s:1.25}#8#{C:inactive}#9#",
},
},
config = {extra = {karma = 0, max_karma = Cryptid and 10 or 3}},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 20,
rarity = 4,
blueprint_compat = true,
loc_vars = function(_, info_queue, card)
if Cryptid then
info_queue[#info_queue + 1] = G.P_CENTERS.c_cry_analog
end
info_queue[#info_queue + 1] = G.P_CENTERS.c_ankh
info_queue[#info_queue + 1] = Cryptid and G.P_CENTERS.c_cry_gateway or G.P_CENTERS.c_soul
if Cryptid then
info_queue[#info_queue + 1] = G.P_CENTERS.c_cry_summoning
end
local extra = card.ability.extra
local karma = extra.karma
local max_karma = extra.max_karma
local attuned = karma >= max_karma
return {
vars = Cryptid and {
attuned and " (Attuned)" or "",
attuned and "" or "Attune ",
attuned and "" or "after using ",
attuned and "^^" .. attunement() or max_karma,
attuned and "" or " Gateways",
attuned and " Chips " or "",
attuned and "& " or "",
attuned and "Mult" or "",
attuned and "" or "[",
attuned and "" or karma,
attuned and "" or " / " .. max_karma .. "]",
attuned and "(Cannot be debuffed)" or "",
} or {
attuned and " (Attuned)" or "",
attuned and "" or "Attune ",
attuned and "Fires on cards with " or "after using ",
attuned and "editions" or max_karma,
attuned and "" or " Ankh or Soul Cards",
attuned and "" or "[",
attuned and "" or karma,
attuned and "" or " / " .. max_karma .. "]",
attuned and "(Cannot be debuffed)" or "",
},
}
end,
update = function(_, card, _)
card.debuff_immune = card.ability.extra.is_attuned
if card.added_to_deck and card.children.center and card.children.floating_sprite then
local extra = card.ability.extra
card.children.floating_sprite:set_sprite_pos({x = extra.is_attuned and 2 or 1, y = 0})
end
end,
calculate = function(_, card, context)
local extra = card.ability.extra
local max_karma = extra.max_karma
extra.is_attuned = extra.is_attuned and extra.karma >= max_karma
local function ascend()
if extra.is_attuning then
return
end
extra.is_attuning = true
Jane.card_status_text(
card,
"!!!",
nil,
0.05 * card.T.h,
G.C.DARK_EDITION,
0.6,
0.6,
2,
2,
"bm",
"jane_enlightened"
)
Jane.q(function()
card:flip()
play_sound("card1")
end, 0.1)
Jane.q(function()
card:flip()
card:juice_up(1, 1)
play_sound("card1")
extra.is_attuned = true
end, 1)
end
if extra.is_attuned then
card.debuff = false
if card.ability then
card.ability.perishable = false
card.ability.perish_tally = 1e9
end
if Cryptid and not context.joker_main then
return
end
if not Cryptid and not context.other_joker and (not context.individual or context.cardarea ~= G.play) then
return
end
local attune = attunement()
local trigger = ({
e_holo = {mult = 50},
e_foil = {chips = 250},
e_polychrome = {x_mult = 2.5},
e_jane_polygloss = {
mult = 10,
chips = 10,
x_mult = 2,
x_chips = 2,
p_dollars = 10,
},
e_jane_moire = {
colour = G.C.jane_RGB,
sound = "talisman_eeechip",
[Cryptid and "EEchip_mod" or "Echip_mod"] = attune,
[Cryptid and "EEmult_mod" or "Emult_mod"] = attune,
message = (Cryptid and "^^" or "^") .. attune .. " Chips & Mult",
},
})[Cryptid and "e_jane_moire" or ((context.other_card or context.other_joker or {}).edition or {}).key]
if trigger then
trigger.card = card
end
return trigger
elseif extra.karma >= max_karma then
ascend()
end
if not (not context.blueprint and
(not context.retrigger_joker_check and not context.retrigger_joker) and
context.using_consumeable and
context.consumeable) then
return
end
local key = context.consumeable:gc().key
if Cryptid and key ~= "c_cry_gateway" or not Cryptid and (key ~= "c_ankh" and key ~= "c_soul") then
return
end
local quota = context.consumeable.getEvalQty and context.consumeable:getEvalQty() or 1
extra.karma = extra.karma + quota
card_eval_status_text(
card,
"extra",
nil,
nil,
nil,
{message = "+" .. quota .. " Karma", colour = G.C.PALE_GREEN}
)
card_eval_status_text(
card,
"extra",
nil,
nil,
nil,
{message = extra.karma .. " / " .. max_karma, colour = G.C.GREEN}
)
if extra.karma < max_karma then
return
end
ascend()
end,
}
if Cryptid then
Cryptid.aliases["saint"] = "j_jane_saint"
Cryptid.aliases["the saint"] = "j_jane_saint"
end
SMODS.Joker {
key = "rot",
atlas = "janerot",
loc_txt = {
name = "The Rot",
text = {
"Clogs up your Joker slots",
"{C:attention}Duplicates itself{} at the",
"end of {C:attention}every ante",
},
},
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
cost = 1,
rarity = "jane_junk",
in_pool = function(_, _)
for _, v in pairs(SMODS.find_card("j_jane_honey")) do
if tonumber(v.ability.extra.level) == #Jane.rarity_ids - 1 then
return true
end
end
return not not next(SMODS.find_card("j_jane_rot"))
end,
calculate = function(_, card, context)
local function has_room()
return G.jokers.config.card_count < G.jokers.config.card_limit
end
local function spawn()
if card.cloned then
return
end
local rot = copy_card(card)
rot.cloned = true
rot:add_to_deck()
G.jokers:emplace(rot)
Jane.card_status_text(rot, "...", nil, 0.05 * card.T.h, G.C.BLACK, 3, 0, 0, nil, "bm")
end
if has_room() and not card.cloned and Jane.is_end_of_ante(context, card) then
Jane.q(spawn, 0.5)
else
card.cloned = false
end
end,
}