#💻・modding-dev
1 messages · Page 666 of 1
Ah
why not just do if table[1] then ?
Because some tables might have string keys, like local t = {["Apples"] = 4}. There is 1 element in the table but its key isn't 1
Doing table[1] would return nil in this case
oh I see.
and what about #table > 1 (or > 0)
#table will be 0 if it has no numbered indexes
#table isn't actually the amount of items in the table, it's just the biggest numeric index inside the table
Oh, I thought it was.
Yeah it's always explained as table size since it's almost always the case with array-like tables
More specifically it just returns some number n where t[n] ~= nil and t[n+1] == nil
I thought it was like that for years
I see...
So having gaps if you have those for whatever reason can also lead to wierd behaviour
mime does if context.repetition and context.cardarea == G.hand and (next(context.card_effects[1]) or #context.card_effects > 1) then (vanillaremade)
why do you do next(context.card_effects>>**[1]**<<) ?
what's the point of the [1]
Yeah
Not 100% sure how context.card_effects works but I think it's to check if there were any effects that activated?
That makes sense
With stuff like this it's usually weirdly programmed and instead of just making a list of all effects the game stores a list of tables, and every table is the list of all the effects of a single card (i.e. if you had 2 jokers that do 3 things each, the game would store 2 tables each containing the 3 effects)
Again, not 100% sure though
i think context.card_effects would contain the eval_card results?
Or somethinng similar
Could be
The wiki says
context.card_effects -- this is a table of effects that has been calculated during the end of round step
Oh ok.
Can you make a custom rarity poll for SMODS.create_card()?
Like, if I had a custom pool of jokers made with SMODS.ObjectType() and wanted to create a random joker out of that pool but with different probabilities so a Legendary could also spawn, how would I do that? The documentation makes it seem you can only choose the exact rarity or do nothing
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, card.ability.extra.dollars } }
end,
calculate = function(self, card, context)
if G.GAME.dollars => card.ability.extra.dollars then
return {
xmult = card.ability.extra.xmult
}
end
end,
}```
this should give x3 mult if you have more than the specified dollars but the game crashes, says there's no ```=``` near ```then```
You inverted the > and = near the if, it's supposed to be if G.GAME.dollars >= card.ability.extra.dollars then
the object type needs to support rarities
thank you, can't believe i missed that
tho now it's multiplying each time i select a card
lmao
yeah i figured ;-;
Ohhh alright, completely missed that, thanks!
Happens
uhm
return { vars = { card.ability.extra.creates, card.ability.extra.dollars } }
end,
calculate = function(self, card, context)
if context.setting_blind and G.GAME.dollars >= card.ability.extra.dollars then
local jokers_to_create = math.min(card.ability.extra.creates,
G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer))
G.GAME.joker_buffer = G.GAME.joker_buffer + jokers_to_create
G.E_MANAGER:add_event(Event({
func = function()
for _ = 1, jokers_to_create do
SMODS.add_card {
set = 'Joker',
edition = 'e_negative',
}
G.GAME.joker_buffer = 0
end
return true
end```
tried a few different things but idk how to get this to ignore joker slots
do you want it to create even if the slots are full?
yeah but dont worry i figured it out
Anyone have thoughts on this joker:
worse jimbo
How do I create a Joker with a specific rarity?
best way for a sticker to trigger an effect when its joker is added/removed?
Like changing its rarity from what it normally is?
No. Spawn a random joker that's of specified rarity.
^
get_current_pool function, that's to be involved.
So true tho
SMODS.add_card accepts a rarity field
the soul
o
can it be rarity = "Legendary" ? Because soul uses legendary = true?
no, rarity = 4 per the smods documentation
string rarities are only used for modded rarities
yes it can
Riff-raff (VanillaRemade) uses rarity = "Common".
VanillaRemade has its own common rarity
smods.add_card takes strings for vanilla rarities
Oh?
so that is not the vanilla one
pls stop misinforming
No wait
then it would be
vanillaremade_Common
(it also takes the numbers i mean in addition to)
oh, sorry
they keep saying dawg takes down other gifs.
Is there a context to see if a joker card is destroyed?
thanks
how do i make a deck that has the same effect as green stake?
increased scaling?
just increment the variable that green stake does when you buy it and decrement it when you lose it
i did not know you can buy decks
wait can i just do that
oh thanks
have y'all never bought playing card decks irl?
that's literally the way to obtain them
no I haven't
i just had the most shit idea for a joker
in essence it would do background rolls to add a random effect (from a list or stolen from an existing joker) to an internal list and another roll to decide if it'll switch the effect that it currently has, and one more roll to decide which effect from its own list to switch to
would be a pain to make but yk
what rarity would that even BE
That's how the RNJoker in Cryptid works, I think, so you could use that for reference
i suppose
cryptid's codebase is a little hard to parse though
okay I do NOT know how to make cardareas
sigh
line 298 is table.insert(card.ability.storage.cards, _card)
so i'm assuming it didn't init properly
copy the cards to a hidden cardarea
update, removed the code from the old version of the joker that didn't use cardareas and didnt work with modifiers
one sec
you shouldn't save a cardarea to card.ability
ah
save it to G like i said before
oh did you say that
i don't think i saw that
so like this
some of the parameters will be changed later i just need to test it out
yes
one moment
If there are two sandcastles, how do they interact?
would cards be returned regardless of which one I sell?
hm.
did you restart the run to test
with the old version, yes
with the new version, ideally
or add a new copy
yeah
Ah, that's good, haha, because that's way easier to set up 😛
it's like each sandcastle is a box and u put the cards in the box
so if u have two you'd end up with two copies of every card
try removing the :init
I would not use the word return in that case, but that's me being pendantic, haha
I'd use the word create.
also why is it that if i restart the game it leaves behind a vestigial console log
that's just what happens if you restart with a hotkey
lovely stuff, it gets fixed next update
sweet
I've got a system like this in Kino, which could work as reference, as I've had to deal with a bunch of strange issues related to how cards are saved and loaded that stem from doing something like this. But if it's not the cards being moved, but more so a copy being made, you might be better off looking into the code for the #1331462654732144721 graveyard, I think
after you create the area you can do area.states.visible = false
and it should disable the collision too
big and fat cards
okay cool there they are
now i just gotta finish the code and then make the cardarea invisible
make sure to test this kind of stuff with saving and loading runs, btw. Lots of potential for weird interactions
ah you also need to recreate the area on load i forgot about that
and save each card, and disable each card from being read as an existing playing card
otherwise the game will add them to your deck again on load
if it's just one area i would actually recommend setting up SMODS.current_mod.custom_card_areas instead of add_to_deck
oh?
Lets Find Out
but it should be out today or tomorrow anyway
this take care of all the loading stuff
should be right
game instead of gamea but yes
How do I create a custom info field for joker cards that i can read?
I've already added something like this:
evo_info = {
key = 'lmd_ultra'
},
to one of my jokers inside the SMODS.Joker() table but when I try to check it with G.jokers.highlighted[1].evo_info it says the field evo_info is always nil. It might have to do with it not being a center but I'm not sure, it's my first time working with custom info.
Did you spawn a fresh copy?
G.jokers.highlighted[1].config.center.evo_info
Oh alr thanks, didn't know it was so simple
i mean upon reload the deck skin died but that's not a problem considering that it'll be hidden
okay actually i should set it back to hand to make sure i can actually see the cards to ensure they're the right cards
funny that the z order of the cards in this area is irrelevant, you can shuffle them around but some will be shown above others
again, doesn't matter, but it's funny
hmm alright, new problem
haven't actually made the code for selling the joker yet but
how's it gonna know which cards belong to which sandcastle?
i guess I could in theory modify it slightly to where if you sell one, it sells all of them and just gives you the entirety of the cardarea
thats why i said before that you would need multiple areas lol
you can tag each card probably too
mm yeah true but I'm not sure how easy that'd be
?
like card.ability.from_sandcatle1 for example
in both cases you would need to give each card a unique id
can you even do that
i guess I could just
do a random number
in ability somewhere
which would be just doing G.GAME.modprefix_count = (G.GAME.modprefix_count or 0) +1
Oh
sorry im a slow typer
which function would that be in, add_to_deck?
yes
i meant each joker
so then you would tag the cards (or the cardareas if you go that route) with playing_card.ability.["from_sandcastle".. count] = true
If you need to assign each card the source joker that destroyed it, I really recommend referencing the Abduction code from #1340334060597285025. Abduction is almost exactly this system, except it doesn't trigger destroy effects
i might not be understanding this properly but
wouldn't that just
give each card from_sandcastle1 and then when you have two of them it would give each card from_sandcastle2
I ran into a bunch of interesting issues while setting that up, so even if the systems are more separate, it might give you some insight. One of the issues I had with it was animation timing
like that doesn't really tell me which specific one it comes from
oops forgot the important part lol
joker.ability.extra.id = count in add_to_deck
ah
figured actually
i was about to ask that
so, all in all, something like this
dont decrease on remove
also, you do not want to decrease the count in this case
as you'll be able to have multiple jokers with the same ID, and it'd give you a lot of issues with sell order
unless the player manages to get 1e308 of the joker nothing will happen
trust
also card.ability[ without the .
:3
https://github.com/icyethics/Kino/blob/main/src/abduction.lua
Here's my code for the abduction system, btw.
which I'm realizing now I should update in part, because I check for hardcoded qualities, rather than use can_calculate
So I was trying to fix a huge lag spike and now my game just says this does anyone know how to fix this (I have tried a lot of potential fixes but none of them worked, I need the mod out by tomorrow)
what's the code for beautifulart
uuuh i think i might want to see your joker code
i suspect the rarity is wrong
mm yeah
SMODS.Joker{ --Beautiful Art
key = "beautifulart",
config = {
extra = {
odds = 1,
emult0 = 100
}
},
loc_txt = {
['name'] = 'Beautiful Art',
['text'] = {
[1] = 'WOW TIMMY THIS IS THE BEST',
[2] = 'ART IVE EVER SEEN'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
pos = {
x = 3,
y = 0
},
display_size = {
w = 71 * 1,
h = 95 * 1
},
cost = 50,
rarity = "balatrop_transending",
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
atlas = 'CustomJokers',
pools = { ["balatrop_balatrop_jokers"] = true },
loc_vars = function(self, info_queue, card)
local new_numerator, new_denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_balatrop_beautifulart')
return {vars = {new_numerator, new_denominator}}
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if true then
if SMODS.pseudorandom_probability(card, 'group_0_e2efa2bc', 1, card.ability.extra.odds, 'j_balatrop_beautifulart', false) then
SMODS.calculate_effect({e_mult = 100}, card)
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = "fridge", colour = G.C.DARK_EDITION})
SMODS.calculate_effect({balance = true}, card)
end
end
end
end
}
may i see your code for balatrop_transending
ohwaitno
uh ok i don't know how custom pools work but that could also be defined wrong
yeah it's either of those
card:add_to_deck()
ah shit
saw that when looking at vremade, what's that
G.playing_cards puts it in the list of all the cards but not in an area
G.deck:emplace(card) would put it in the deck area
k so
i think thats correct
the lua extension shouts at me for that i do it often lol
i dont use vscode anymore but this code editor doesnt have a lua extension yet lol
???
oh whoops
maybe i shouldn't have done _, card
uh
they jus flipped over
they did get added to the deck though
playing cards being visible isn't their default, iirc most areas would default to them being face down
oh i actually like NEED to add something to my "increase joker values" card that doesn't affect the id LMAO
what the fuck?
yeah but they shouldn't be there anymore at all
oh i forgot about something imporant again
it happens
and i looked it up too lol
what'd we miss
you're like a tutorial npc explaining mechanics, damn
LMAO
area:remove_card(card)
N wanted to say you can hold shift to run
before emplacing
what would be the best way to add/remove a variable amount of shop slots smoothly
there was two cards and i sold the sandcastle and that one's still here
evil card
check vremade for that one voucher im guessing
nah this is like uhh
it didnt even get added what the hell
im guessing if you remove cards while looping it doesnt reach it
i want it to change w/o requiring manually changing like the smods card area stuff
yeah that is exactly what's happening it's only removing one card lol
because it would just be a bit more painful for me if i implemented starts / ends to what im doing
unfortunately i think you might have to
i would store the cards in a local list and then remove them
wdym
setup update function which checks does amount of slots matches amount you need and if not, use smods function to adjust it?
like how you can just change extra_slots_used on a card and itll update accordingly
is there a way to do something similar for shop slots with a different variable
i dont think so
bleh
seems very hardcoded
im just gonna do the jank solution and delete the last card in the shop i guess
This card will reappear when you redeem overstock
am I overcoding this
this is intended to be a temporary -1 shop slot effect but its based on a number that changes fairly often so if anything i'd prefer not to check every time it updates to see if the -1 shop slot effect should apply or not
or rather new card will take it place so amount of slots will not change
i think this will break because youre removing after emplacing
i wonder if change_shop_size(-1) would work
just do all the adding emplacing stuff in the bottom loop
hm so what just move emplace to the second loop? yeah ok
i mean it'd do that properly but then i would have to check for when it updates again to see if it should re-add or not
and then i'd also probably have to store if it already took away one or not
wait, all of it?
i just wanted to see if there was a way that avoided that jank
either
also make cards to remove a local
ok cool it works properly
is it not? i forget how lua owrks
well it is now
ok now to test tbhis
this should work right
No, It Doesnt
well i guess the area might be invisible but
it does. it's in 0,0 pos with 0,0 size
just checked it is in fact invisible
and like i mean technically? even if the cards inside were invisible, wouldn't that animation of them getting moved into the area still be shown
probably
i would prefer if that did not happen
like,
here hold on
does this not relate to cardarea type as well?
possibly
ah yeah the hand is also invisible in vanilla, no?
well,
checking the code for it, it seems to have some particularities, but it seems to me like setting the state to visible should just hide it, regardless, as that return is the first thing that code does. I wonder if it doesn't affect cards that get added after the state is changed?
oh true
it definitely does apply to cards added after for me
as in, for the joker area?
Cause I suspect there might be something that syncs the visible state for cards with their area, but only in certain cases
anyway, the area type doesnt matter if its invisible
I fear I accidentally fucked up and now I need to start the run over LMFAOOO
yeah anyway area type didnt do anything
do cards have the same states?
maybe I could just set their state to invisible when they're created
yes
oh that actually worked
I got sent this bug report but I have honestly no idea what's even happening there, any idea? Apparently it's tied to negative hand level but I don't see how exactly
the log only shows calls to draw functions which I havent touched in any way
oh hey a useless crash report
yeah that literally does not mean anything
ok glad to see it's not useless to just me lol
i mean clearly there's a bug in your code but that crash report doesnt mean anything
it appears this crash happens somewhat frequently when using cryptid with the wrong smods version
not sure rn what exactly that's about, but might be a similar case
would be good to know if it still happens with the latest dev version of smods
if you use a table when you return messages it will do this crash
because eremel added the ability to use ui elements in messages
it is fixed
there's no return in the use function of the consumable that allegedly caused the crash
and can_use is just return true
pick a random hand, 1 in 3 to decrease its level by 2 otherwise increase it
i have nothing besides whoever reported the bug's words to know that this is the thing that crashed
they could be wrong and the cause could be anything else, idk
hmm i dont see how this would do it
good to know, I've seen instances of the crash before that was a thing but I didn't know about / remember that change happening
i'll ignore it for now and told them to be more precise on what happened if they get it again
yeah it also happens every time you make ui wrong
hm, could also be something going on within the level up UI logic
yeah, that I know. at root it's trying to treat something as a UI element that isn't
they said it's leveling down to -3 that did this, but i leveled multiple hands to -3 on my end and it didnt do anything
fwiw, SMODS.is_poker_hand_visible(v). 
sanity check, do all the versions match between the report and what you're running?
thank you for promoting my function
21
i think i have lovely .9 instead of .8, but the rest is the same
mkay that shouldn't matter
assumed so too
Do any of you know if it's possible to reference the perishable sticker in localization?
Something like "T:j_mail", but for perishable.
I don't think that's a thing yet
I'm trying to make a sticker for playing cards that gives xmult of some kind, but no luck. (No message or anything)
calculate = function(self, card, context)
if context.individual then
if context.cardarea == G.hand and not context.end_of_round then
return {
xmult = 1.5,
message_card = context.other_card
}
end
end
end,```
main_scoring instead of individual
working, ty
New smods release get crackin’ dev chat
now i have to migrate my draw to hand and main menu card stuff to this
...wait... how... would i? 
uh, the menu card stuff, that is.
i have like a whole thing that cycles the card out with other stuff - i populate a pool of stuff to be picked from at random and then every 20 seconds or so, the card in the main menu is replaced with it
you can keep that code and just create the card in menu_cards probably
Has anyone figured out how to ban enhancements/editions/seals yet?
G.GAME.banned_keys[key] = true
Wait does that just work now?
I swear it didn't before
Yeah no it definitely doesn't work, they're still showing up from things like Incantation
incantation is just hardcoded to use all enhancements from what i see
it does call each individual in_pool but thats it
wait is this a thing and does this work for cards themselves (namely tarots) i literally was given an idea for a consumable that this'd be perfect for
it works for consumables at least yes
What do I put in my main.lua file to be able to have/load other .lua files for less clutter?
theres code at the bottom of the question
Thanks never saw that page
Hi, is there a way to edit the mult value of a boss blind in code? I am trying to make a boss blind that increases in value based on how many cards you have destroyed.
Just developed a method to buffer Booster Pack openings and I feel so smart because of it
-- COPYCAT JOKER
SMODS.Joker {
key = "test",
in_pool = function(self, args)
return true
end,
blueprint_compat = true,
rarity = 3,
cost = 9,
loc_txt = {
name = "Copycat",
text = {
"Imitates a random Joker.",
"Changes after each hand.",
"Currently imitating: {C:attention}#1#{}"
}
},
atlas = "test_atlas",
pos = { x = 0, y = 0 },
set_ability = function(self, card, initial)
card.ability.extra = card.ability.extra or {}
card.ability.extra.copied_key = "j_joker" -- safe default
end,
loc_vars = function(self, info_queue, card)
local key = card.ability.extra and card.ability.extra.copied_key
local copied = key and G.P_CENTERS[key]
local name = copied and copied.name or "Copycat Joker"
return {
vars = { name },
name_vars = { name }
}
end,
calculate = function(self, card, context)
-- 🔁 Change when a blind is exited
if context.end_of_round and not context.blueprint then
local pool = {}
for _, joker in ipairs(G.P_CENTER_POOLS.Joker) do
-- ❌ Don't copy itself
if joker.key ~= self.key then
pool[#pool + 1] = joker
end
end
if #pool > 0 then
local choice = pseudorandom_element(
pool,
pseudoseed("copycat_blind_change")
)
card.ability.extra.copied_key = choice.key
end
end
end
}
How to find the text of the copied joker and add it as a tool tip on the side?
Just add its center to info_queue
Anyone how to make it so through boss blinds, certain cards cannot score any base chips?
Hook Card:get_chip_bonus
thx
is there a way to get a list of all enabled mods, and then check list of jokers that belong to that mod?
i wanna make a compatible effect that spawns a joker from a different currently enabled mod
local mods = {}
for k, v in pairs(SMODS.Mods) do
if not v.disabled and v.can_load then
table.insert(mods, v)
end
end
local mod = pseudorandom_element(mods, 'seed').id
local jokers = {}
for k, v in pairs(get_current_pool('Joker')) do
if G.P_CENTERS[v] then
if G.P_CENTERS[v].set == 'Joker' and G.P_CENTERS[v].original_mod and G.P_CENTERS[v].original_mod.id == mod then
table.insert(jokers, G.P_CENTERS[v].key)
end
end
end
local key = pseudorandom_element(jokers, 'seed')
SMODS.add_card({key = key})
You absolutely don’t need to check the set of the centre
Working on a playing card sticker that gives a dollar when held in hand during scoring, then removes itself. However, I don't want it to activate multiple times if it were to have something like a red seal or having mime in play. Is there some sort of check I can add to prevent the repetitions?
calculate = function(self, card, context)
local sticker = self.config
if context.main_scoring then
if context.cardarea == G.hand and not context.end_of_round then
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + sticker.dollars
G.E_MANAGER:add_event(Event({
func = function()
card.ability[self.key] = false
return true
end
}))
return {
dollars = sticker.dollars,
func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.GAME.dollar_buffer = 0
return true
end
}))
end
}
end
end
if context.after then
G.E_MANAGER:add_event(Event({
func = function()
if card.ability[self.key] then
card:juice_up()
card.ability[self.key] = false
end
return true
end
}))
end
end,
this works perfectly, except for the fact that mod can also be an ID of a disabled mod (which then results in a crash). is there some sort of way to check if Mod Object is active/pull from pool of active mods? because SMODS itself does know about which mods are loaded
wait is this actually because of Balatro Mod Manager?
SMODS.Mods[original_mod.id] or {}).can_load maybe?
having this check should only allow something to work if the specified mod is currently active
yes thank you, can_load is the right property
i dont know the specifics, but it may help
it is correct
it doesnt seem to be documented on the wiki
https://github.com/Steamodded/Wiki/pull/77 🗣️ hopefully it will be now
what's get_current_pool('Joker') and why does it return 62 jokers? like i dont get the meaning of a "current pool", wouldnt that be every joker in the game?
current pool means it only includes the cards that are currently available and not blocked from spawning
which depends on what you've unlocked and what you currently own
i see
does the inject function of an SMODS.ObjectType run after all centers have been injected already?
nope
there should be an easier way to do this
--Checks if you have a Grandiose Rarity Joker
add_to_deck = function(self, card, from_debuff)
G.GAME.grandiose_check = true
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.grandiose_check = false
end,
the check should be a function that iterates through G.jokers.cards (and any custom areas you care about) and looks at the card's rarity directly
cause this method will fail if the player acquires a second one
function has_rarity(rarity)
if G.jokers then
for _, v in ipairs(G.jokers.cards) do
if v:is_rarity(rarity) then
return true
end
end
end
end
if has_rarity("busterb_Grandiose") then
G.GAME.grandiose_check = true
end
i just put this on top of grandjokers.lua where all the grandiose jokers are
idk what i'm doing
Remove the last if statement, since that'd only be ran once
You just wanna use has_rarity any time you'd check for G.GAME.grandiose_check
Also I wouldn't recommend making it a global function
I’m using a lovely patch that changes the background color if a joker of a specific rarity is present
Right now my current tasks look like this.
What does your patch look like
Yeah so where you did G.GAME.grandiose_check == true you'd now replace with has_rarity("busterb_Grandiose")
Ohh
I only looked at it because you mentioned it
:p
dawg
wdym attempting to call a global
so you only look for globals and not locals?
fuck you
probably you typed local has_rarity in one file and then tried to call it in a different file
this is how scope works and lua does it that way on purpose
i would recommend putting any global functions in your mod's global table
actually it's a function
actually no, it's not a local
then you may be attempting to call it before it is defined
the entire snippet looks like this:
function has_rarity(rarity)
if G.jokers then
for _, v in ipairs(G.jokers.cards) do
if v:is_rarity(rarity) then
return true
end
end
end
end```
and where is that snippet?
functionalities.lua
assert(SMODS.load_file("items/functionalities.lua"))()
assert(SMODS.load_file("items/gradients.lua"))()
assert(SMODS.load_file("items/rarities.lua"))()
assert(SMODS.load_file("items/pools.lua"))()
assert(SMODS.load_file("items/spectrals.lua"))()
assert(SMODS.load_file("items/infinity.lua"))()
assert(SMODS.load_file("items/packs.lua"))()
assert(SMODS.load_file("items/rarejoker.lua"))()
assert(SMODS.load_file("items/dreamyjokers.lua"))()
assert(SMODS.load_file("items/hyperjokers.lua"))()
assert(SMODS.load_file("items/deck.lua"))()
assert(SMODS.load_file("items/grandjokers.lua"))()
assert(SMODS.load_file("items/secret_jokers.lua"))()
assert(SMODS.load_file("items/edition.lua"))()
assert(SMODS.load_file("items/voucher.lua"))()
assert(SMODS.load_file("items/ace.lua"))()
and is it called in any lovely patches?
no?
did you try printing?
printing what
anything
just to confirm that you're reaching that part of the code
print"added has_rarity"
function has_rarity(rarity)
...
ok so it printed
hmm
is anything erasing has rarity later? search for has_rarity =
so it turns out putting them all in one functions file breaks, so i just separated them, no more crashes but no noticable change
search?
like
search your mod files
grep, to use the Linux term
if you're using vscode there's a search tab for this
erasing has_rarity? that's possible?
it's a variable
if anything runs has_rarity = nil later (and isn't referring to its own local variable) then poof. it's gone
that's a good idea as well
you don't, but it's very simple to make
BusBuf = {}
or whatever you feel like calling it
ok now i wanna make BB.grand_check if that's a valid whatchamacallit
yeah, you can store functions in tables like that
what like this?
BB.has_rarity = {
function bb_has_rarity(rarity)
if G.jokers then
for _, v in ipairs(G.jokers.cards) do
if v:is_rarity(rarity) then
return true
end
end
end
end
}
BB.has_rarity = function(rarity)
if G.jokers then
for _, v in ipairs(G.jokers.cards) do
if v:is_rarity(rarity) then
return true
end
end
end
end
like this?
it's already 1am, i'll handle this later...
that's fine, as long as you had BB = {} somewhere before that
im using this
localize({ type = "name_text", key = event.ability.extra.joker_key, set = "Joker" }),
to fetch localization for a joker.
however when key is a vanilla joker it fails.
how do i correcttly fetch the joker's name?
No, that should work for every joker.
okay i'll look through crash log again
how can I get this properly centered
return {
n = G.UIT.ROOT,
config = {align = "cm", padding = 0.05, colour = G.C.BLACK},
nodes = {
{ n = G.UIT.R, nodes = {
{ n = G.UIT.T, config = { align = "cm", text = "Status: ", scale = 0.4, colour = G.C.WHITE } },
{ n = G.UIT.T, config = { align = "cm", text = "Disconnected", scale = 0.4, colour = G.C.RED, id = "twitch_status" } },
}},
{ n = G.UIT.R, nodes = { { n = G.UIT.T, config = { align = "cm", text = "Cooldown (s):", scale = 0.4, colour = G.C.WHITE } } } },
{ n = G.UIT.R, nodes = { create_text_input({
max_length = 3, align = "cm", text = tostring(mod_obj.config.cooldown_sec), ref_table = mod_obj.config, ref_value = 'cooldown_sec',
}) } },
{ n = G.UIT.R, nodes = {
{ n = G.UIT.C, config = { id = "connect_button", align = "cm", padding = 0.1, button = 'twitch_connect_trigger', colour = G.C.PURPLE, r = 0.1, minw = 2, minh = 0.6 },
nodes = { { n = G.UIT.T, config = { align = "cm", text = "CONNECT", scale = 0.4, colour = G.C.WHITE, id = "connect_text" } } } }
}},
}
}
end```
align = "cm" -> align = "tm" i think
didn't work ;/
then idfk i dont understand UI at all lmao
lol
the release was tested, right?
yeah i looked at the wrong line, problem was with game not fetching the atlas for vanilla asset
Update lovely
you're way behind
oh, there was a lovely update
yes
yay
what did you update smods from, like 0827 or 1016?
i was about to say, that's pretty crazy that that happened
i think 0.8 was just the macos fix and no much more lol
the crash above is actually from a 0.8.0 change
which is before on module patches being optional
we just weren't making use of it before preflight
do i just need to specify a ref_table in the extension declaration?
something like ref_table = {}?
or is there more to this
hey quick dumb question, why order no work no matter number?
smods doesn't let you take control of the ordering of objects
they're organized in the order they're created in
so either byebye smods or find a way to override smods ordering
what do you need a specific order for and in what way isn't it achievable by just registering your objects in that order?
uhhhhhhhhhhhhhhhhhhhh personally I'd like the vouchers to be actually together instead of split
so like, how the vouchers are actually placed where tier1 on left & corresponding tier2 on right
then don't register them out of order? you have control over what order you register each voucher
I have a feeling my reluctance to put them all in 1 file is now biting me in the ass
bump
honestly one file would still have beena pain to edit
meh, you'd just have to make a list of the order to load the files in and then follow that
aaaannddd how?
UI stuff just doesn't wanna work with me I can't get anything to center
uh what are you doing with the object?
How are you currently loading your files?
a very simple solution that is now gonna be my downfall
these are just dummy centers whose express purpose is to be added to info_queue
so this happens whenever you throw the object into an info_queue?
no, this was on game startup
ok one sec
you need to initialize G.localization.descriptions[self.set]
we should probably make that null safe on smods' end
is there a way with SMODS to perform certain function AFTER all the other mods have loaded? i want to count total amount of custom jokers, but since my mod has a priority of -10000 i load in before other mods
Yeah this isn’t a consistent order
one thing i've also noticed now is that pressing R on the crash screen or some other methods of restart such as opening mods menu and enabling/disabling a mod isn't actually restarting balatro and just leaving it closed
is this an issue on my end or
lemme check the restart shortcuts, actually
ok those work
we should probably provide a uniform way to do that, but no. you should calculate the information when you need it if it doesn't need to be available at load time, else find an appropriately timed function to hook. or if it doesn't need to be after everything being injected, you can hijack an object's inject function
or you can use an event
yeah im gonna see if event works
on the crash screen, I think that can happen if the game crashed too early. Should be less prone to that on 1501 with preflight, but it might be that
yesssss event works
what's the proper way of moving a Card between CardAreas?
draw_card(area1, area2) should work?
if not then
area1:remove_card(card)
card:add_to_deck()
area2:emplace(card)
the add to deck is assuming youre trying to do the thing you were talking about in modding general
Are these ass, lol
yeah
but draw_card also works
is there a downside?
i guess second one specifies which card we're taking, and the first one only takes 1
you can also specify the card with draw_card, its one of the arguments
i see
im not sure if it calls add_to_deck tho
does add_to_deck() call some calculate context?
is modding dev not serious talking about mods, i still dont know how the new sorting of channels works lol
it calls the card's add_to_deck :3
ah, i thought that was support, mb
ahahahahh that makes sense
i see
i mean people talk about making mods here and it's part of what the channel is for
is there away to change the size of a create_text_input
still ugly but better than before
ty
this is my idea for the record.
could that be done?
That can be done fairly easily I think
anyway to swap the sprite of the joker on the startup animation?
You can do that very easily with a patch
oh cool, how do patch :3 (ive never used them and the syntax scars me qwq)
Patches are very simple, it’s basically telling lovely “Here’s this line of code, put this code nearby or replace it”
i almost just explained a hook, whoops
Lmao
i understand what they are in concept, i just have no idea how you use then or what code i would replace for something like this :/
Here’s my patch for replacing the splash card
[manifest]
version = "1.0.0"
dump_lua = true
priority = 1
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''
SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_joker'])
'''
position = "after"
payload = '''
SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_mxms_normal'],{bypass_discovery_center = true, bypass_discovery_ui = true})
'''
match_indent = true
times = 1```
Looking in the game dump will help you a lot in looking for stuff like this
In all honesty, looking through the dump code has elevated my ability to read and understand code a ton
same, the first real mod i made hooked vanilla code so much i had usually had a second instance of vs code open for the dump lmao
also thx, got it working ^w^
👌
Just this?
SMODS.Joker {
key = 'endo_01',
atlas = 'Joker',
pos = { x = 7, y = 0 },
rarity = 1,
cost = 2,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
fnaf_type = "Animatronic", -- Type of Card
fnaf_broken = false, -- Fixable or Not
config = { extra = { chip_mod = 100 }, },
loc_vars = function(self, info_queue, card)
info_type(self, info_queue, center)
return { vars = { card.ability.extra.chip_mod } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chip_mod
}
end
end
}```
also I'm trying to make a function to give info_queue of the type of the card as well
yea
info_type = function(self, info_queue, center)
if card.config.center.fnaf_type == 'Animatronic' then
info_queue[#info_queue + 1] = { key = "fnaf_Animatronic" , set = "Other" }
end
end
i did something like this in my mod ,,
hold up let me check
Change the center input to card
ok it worked, I just need to simplify so that it doesn't have 4 if states
how can i reference the card i created
does SMODS.current_mod.menu_cards() return a table with any created cards or
It does not
-- COPYCAT JOKER
SMODS.Joker {
key = "test",
in_pool = function(self, args)
return true
end,
blueprint_compat = true,
rarity = 3,
cost = 9,
loc_txt = {
name = "Copycat",
text = {
"Imitates a random Joker.",
"Changes after each hand.",
"Currently imitating: {C:attention}#1#{}"
}
},
atlas = "test_atlas",
pos = { x = 0, y = 0 },
set_ability = function(self, card, initial)
card.ability.extra = card.ability.extra or {}
card.ability.extra.copied_key = "j_joker" -- safe default
end,
loc_vars = function(self, info_queue, card)
local key = card.ability.extra and card.ability.extra.copied_key
local copied = key and G.P_CENTERS[key]
local name = copied and copied.name or "Copycat Joker"
return {
vars = { name },
name_vars = { name }
}
end,
calculate = function(self, card, context)
-- 🔁 Change when a blind is exited
if context.end_of_round and not context.blueprint then
local pool = {}
for _, joker in ipairs(G.P_CENTER_POOLS.Joker) do
-- ❌ Don't copy itself
-- ✅ Only copy blueprint-compatible Jokers
if joker.key ~= self.key
and joker.blueprint_compat == true then
pool[#pool + 1] = joker
end
end
if #pool > 0 then
local choice = pseudorandom_element(
pool,
pseudoseed("copycat_blind_change")
)
card.ability.extra.copied_key = choice.key
end
end
end
}
How can I add this as the 'other card' param needs a center of a card the user has.
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.BLUE
end
return ret
the arg you pass in for card is your joker, other_joker is the joker you've picked to imitate, then you just pass in context
Fyi copying a card that doesnt exist is very difficult
this is a little janky, but what you might end up having to do is instead of going by key, store a reference to the target joker in a variable in G.GAME and then referencing that
Im figuring this out
like as a card like throwback if copied gives Xnil
Also fyi
Blueprint compat is opt out now
So you should check if the blueprint compat value is true or nil
I think
i guess you could try instantiating a dummy version of the joker in a G.GAME var and try copying that, then? so long as it doesnt end up in a cardarea that gets calculated
I tried that before but couldnt figure out exactly how to make it work ended up like this:
They wernt calculated in the hand, but neither was the copycat joker 😢
do you think i could like, poach it by returning a func from the menu_cards func that puts cardinto a variable?
like just
myVar = card
end```
Does anyone know how to insert logic at the point in time when chad says 'again'? I've tried to patch something in functions/state_events.lua under the for h = 1, eval.jokers.repetitions do section or the SMODS src/utils.lua under repeat in SMODS.insert_repetitions, but idk why the logic doesn't work in the first case or triggers a single time before even the first card scoring in the second case
reptition context is an optional context, do you have it enabled
wdym do I have it enabled, I precisely want for the joker Hanging Chad to make it work, haven't checked if that joker uses this precise context
How is joker retriggers related to this
oh 
jokers do use repetitions in some contexts
is there a way to tell if a discard is coming from the hook during pre_discard?
context.hook
Create a fake card.
Thank you
bump
Use the function if you need to do anything to your cards (what do you need to do to your cards?)
i'm trying to migrate my title card cycling thing to work with menu_cards
any idea why this is this causes all cards in deck to be debuffed by suit debuffing blinds
is there a reason it shouldn't do that?
thats what happens to wild cards no
oh is it because it's only supposed to be flipped over cards
uhh i suspect it's because all cards in G.deck are face down before you draw them to your deck
but idk for sure
You can just call this function with the card, find it in the cardarea, I forget the name now but it’s in the release notes
G.title_top yes - but i'm not sure how to explicitly find what i'm looking for 
also i'm trying to wrestle with this crash that cropped up while picking all this apart
yes and its supposed to not check cards in the deck
hence the context.cardarea ~= G.deck
not sure entirely since i cant like boot up the game and do any experiments
Find card looking for card.mod_flag then use set_ability to change ezpz
will that still work after i've dissolved the card?
I think you can just materialize th card again
Change context.cardarea ~= G.deck to context.other_card.area ~= G.deck
i can't see what i'm doing wrong here
if G.jokers then
for k, v in pairs(G.jokers.cards) do
if v.edition and v.edition.negative then
negative_count = negative_count+1
end
end
end
Oh
wait, this works for base cards?
Ok now my function that I have doesn't seem to work now despite working before, where it tries to locate if a card has as prefix
SMODS.Joker {
key = 'catalog',
atlas = 'Joker',
pos = { x = 4, y = 3 },
rarity = 2,
cost = 4,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
fnaf_type = "Misc", -- Type of Card
fnaf_broken = false, -- Fixable or Not
config = { extra = { chip_mod = 100, chips = 0 }, },
loc_vars = function(self, info_queue, card)
info_type(self, info_queue, card)
return { vars = { card.ability.extra.chip_mod, card.ability.extra.chips } }
end,
calculate = function(self, card, context)
if context.joker_main then
print(#Find_type("Animatronic", card))
local Chips = card.ability.extra.chip_mod * #Find_type("Animatronic", card)
return {
chips = Chips
}
end
end
}
function:
Find_type = function(type, card)
local found = {}
if G.jokers and G.jokers.cards then
for k, v in pairs(G.jokers.cards) do
if card.config.center.fnaf_type == type then
table.insert(found, v)
end
end
end
return found
end
It should be v.config.center.fnaf_type == type
thank you
I don't know why it was working before
anyone know how to make a booster pack automatically either
a. pull up a hand of cards
or
b. have them be added to the consumable tray instead of immediately used?
bump. i actually have no idea what's happening with this crash
I might be stupid how do I get the rank of a card
card.base.value
thx
Does anyone know the details of how jokers are selected to show up in the shop/booster packs? I know it rolls rarity first but it seems to also favor against jokers you have or jokers earlier in the roll. I want to make it disregard any duplicate checks and let a shop/booster be all the same joker if RNG rolls that way
it's not just favored against jokers you have, it outright cannot roll jokers you already have. that said, the Showman joker explicitly makes it so you can roll jokers you already have, so i wouldn't recommend changing the system because that just makes showman useless
and i don't think the game does any weighting against jokers that have appeared recently in the shop at all, the pool is just big enough that it rarely rolls the same joker twice that quickly
I'm pretty sure it doesn't roll the same jokers you have in the shop if you open a booster iirc
if you really do want the showman effect to always be active, you can just hook the SMODS.showman() function to make it always return true
wouldn't that just fall under showman's effect? the joker exists in the shop so it's out of the pool unless the showman function returns true
As part of my mod right now, I banned all jokers except 4, one for each rarity, and still on a fresh run with no jokers sometimes it shows the default Jimbo joker after one of the approved jokers.
Let me try making the showman effect always on though, that might be exactly what I want
yes, I'm just clarifying because "appeared recently in the shop" might also include things that might be in the shop already and that might not be obvious
gotcha
Making showman always return true was exactly what I wanted, ty!
How do I use preexisting variables in jokerforge?
is there a cardsleeves equivilant of back.effect.config that gets saved?
G.GAME.sleeve_key = { stuff } is probably good enough
Anyone know where to find SMODS.recalc_debuff so I can hook it to trigger another function?
oh glad I didnt realize back was passed in a context when making adaptive deck and stored everything in G.game
what
when I made my adaptive deck I stored everything on G.game, which makes my card sleeve for it work without any modifications
ah ok
ah yes, astigmatism coding
bump
oh, figured it out
one of my patches was overwriting an important call
bump (can set_ability work for base cards? and if so, how? do i just do :set_ability('S_A') for an ace of spades?)
set_ability sets enhancements for playing cards. "unenhanced" counts as an enhancement
to set the suit and rank of a card, use SMODS.change_base instead
https://github.com/Steamodded/smods/wiki/Utility
but i'll work for everything else? jokers and consumables i know will - but what about vouchers
it should, yea
if you're curious, under the hood, set_ability is used to set the "center" of a card object, and a bunch of stuff counts as a "center"- decks, booster packs, consumables, enhancements, jokers, and vouchers
playing cards additionally have a "front", which is where the rank and suit are relevant. touching the center won't do anything for that
what would be away to make it where if u can't use a tarot card from a pack you can send it to ur consumable slot?
Hook G.FUNCS.can_use_consumeable and G.FUNCS.use_card
doesn't work 
in fact, it just makes a new thing over the card instead of replacing it, even without my function call.
although it doesn't get rid of the card
...oh, because start_dissolve calls remove()
what's the gamestate when inside a tarot pack called
there's not a specific state for types of packs, it's just G.STATE.SMODS_BOOSTER_OPENED inside any booster pack
Yeah was about to say I found it
if booster_obj and booster_obj.kind == 'Arcana'
Thx
how?
kinda has some weird effects when it tries to turn a joker into a playing card
do i have to do :set_ability('Base') first?
probably something of that nature?
No, it would be card:set_ability('c_base')
does anyone know why this crash occurs when i try and use a joker to make a custom enhancement?
is there something i need to do to a playing card to turn it into a joker without the face sprite?
doesn't look like it
still would like to nkow what to do about the shrinking though
alright and now it just straight up vanishes after a few changes and doesn't come back.
migrating is so much fun
ended up fixing both of these, but any cards with floating sprites end up with small floating sprites when materialised for the first time - then if they're materialised again later, their floating sprites are bigger but still a little too small, but actually centred
How would I give a card a random seal and enhancement?
should jump straight to it
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-give-a-card-a-random-editionenhancementseal
Thank you!
So with this, it'll debuff the target cards, but if I sell ANYTHING, it undoes the debuff.
Add true as the second input to the Card:is_suit calls.
Question: would anyone take a modding request for a relatively easy mod to make?
It would be cool to have a mod that has a little display of misprint that shows what the next drawn card is.
(Misprint tells you what the next drawn card will be in vanilla balatro.)
Oh sick! Didn't know that exists alr. Thanks!
So if I understand it right, it would be:
... (check for suit calls = true)?
I can't get on PC because my wifi is dead for now.
No, it would be context.debuff_card:is_suit('Clubs', true) or context.debuff_card:is_suit('Spades', true)
Ah, thanks for clearing that up.
-# Also NOW my wifi wants to fix itself!?
I have a large number of consumable sets in my mod (currently 4), and am thinking of adding more. This clutters the collection menu greatly, so I want to put all of the consumables inside one set to show in the collection. However, one of my sets requires that I change the shop_rate value to toggle availability in the shop for those cards. Am I able to use SMODS.ObjectType to "section off" all my consumables into different pools, and have a shop rate tied to each object type individually? And if not, what would be the best way to go about a fix for this?
I think you'd be better off using SMODS.ConsumableType to group them together.
that's what I'm hoping to do, as long as I can call each individual group using ObjectType and can also change shop rate for each of them
which is the part im unsure about
is there even a way to align the chips (and X) container with the mult one?
yes, put box nodes of the same size as the extra score container below them
how does this snippet work?```lua
select_music_track = function()
return (
#Cryptid.advanced_find_joker(nil, "busterb_Grandiose", nil, nil, true) ~= 0
) and 100.000
end,
if advenced_find_joker size is not 0,then it returns 100000
if its 0,then it returns nil
100, not 100000
other than that, that's technically what happens here
oh why would they put a floating point there, wierd
how the function works is that each track returns a priority value
so the track that returns the highest value is chosen to be played at any given time
why not, integers aren't special in lua
it's just numbers
yeah but... wierd to specify 3 zeros after the floating point ?
the number of digits is to be consistent with what they're doing elsewhere, e.g., 100.002
thats fair
Wdym
Does anyone know if there is a way to create a UI box in the main menu? I want to create one whenever the game loads.
yeah, you can just create the box in a hook to Game:main_menu and it works
what for
I want to let the user know there is a new update of the mod out
that should work then
toga's stuff and stocking stuffer both have similar things you can look into
I hate when mods do that
youre not going to like mine then :p
this one os okay since it's one-time welcome message fir reasonably complex mod
Plus initial reading test

Ah, I think I got it. Thank you so much!
i should do an iq test before the game starts
I think I am?
can i see
function Game:main_menu(change_context)
local ret = game_main_menu_ref(self, change_context)
update_checker.check_for_update(mod.SMODS_VERSION)
return ret
end```
what should I do to fix this?
!!!!!!!!!!!!
Please make sure your lovely is up to date (Minimum lovely v0.9.0)
!!!!!!!!!!!!
what does this say
!!!!!!!!!!!!
!!!!!!!!!!!!
So I updated the lovely and... uuuh...
do you have an smods zip in your mods folder
nope
it looks like smods is loaded as lovely-only for some reason
check if its not nested, you dont have a second one, etc
there most likely is a second one somewhere since smods shouldnt be listed under mods at all
Ok so for some reason it works now... basically I removed the smods-main folder that you see in this screenshot
yeah you had 2, make sure that's the updated one
yeah

it seems like the duplicate label "continue" no longer appears for duped smods installation
it's the syntax error inside functions/misc_functions.lua now
that'd be unfortunate, it was a really unique error to spot lol
I'm not sure if this new error is unique or not 🤔
at least we're seeing that quite commonly
but yea, it doesn't seem to be unique enough
will see if I can get a proper message sorted out
sorted it out, I think I'll push a new release this evening to fix this crash identification and also the profile crash
Heya, tried using take_ownership with smod to increase Ride The Bus's mult increment to +2. Caused an error, error-log attached. Lemme know if I'm overthinking this or if I made an obvious mistake. Testing lua attached as well.
does lua get mad if you declare a label and then never use it? could someone make a label that exists solely to detect duplicate installations?
it is trying to run the original function in vanilla
you can change the name of it and it should fix it
so if i made a lovely patch that adds a label named ::this label exists for the sole purpose of detecting duplicate installs; if you're seeing this please sanitize your mods folder::, that would work as expected?
(plus or minus some string formatting, I'm not sure whether you can do it exactly like that)
but also keep in mind this will get rid of the SMODS.scale_card call since vanillaremade doesn't use it
label isnt a comment unfortunately
you_can_probably_do_like_this
but if you make a new global var you can probably detect that
That makes sense, thankyou again N'. I'll see what I can do.
whats the easiest way that i can simulate button presses through code (new blind, skip blind, play, discard, reroll...)?
call the function that button calls
Long time ago I made a custom consumable that is supposed to "mix" 2 enhanced cards by deleting one and setting the other with another enhancement.
the problem is that I wanna specify which enhancements need to be "mixed" to set the card that isn't gonna be destroyed with a specific enhancemement.
For example: I select 2 cards with the chemical enhancement, one red and one blue and when I use the consumable it flips both, destroys the leftmost and sets the rightmost with another enhancement and then flips the card again.
also this crash shows up when I try to do that:
the key will never equal the center prototype
the right value should be a string
or get rid of .key
it seems like leftmost doesnt have a center tho
it's probably leftmost.config.center
they seem to be just stored as strings (e.g. e.config.button = 'play_cards_from_highlighted') but the actual functions often receive extra parameters (e.g. G.FUNCS.play_cards_from_highlighted = function(e)). how do i find out what should be passed (for e in this case)?
e is just the object that was pressed
e is the button node, but for most of them it can be an empty table usually
the only ones I can think of that actually use the information are the option selectors
like, that one doesnt use e at all
thanks, ig i will just try passing {} to everything and see if that works
thanks!
also I would like to know how can I make it so when I select playing cards, the "USE" button of said consumable can be used only if at least 2 playing cards specific enhancements are selected.
check for it in can_use
it's been a long time since I got used to the lua coding for balatro...
do you know which source or guide I can look up for the can_use function to make a condition for such?
it should be in the SMODS.Consumable wiki but you just need to return true if it can be used
for checking enhancements: https://github.com/nh6574/VanillaRemade/wiki#how-do-i-get-if-a-card-has-a-specific-editionenhancementsealsticker
Tried like this but it doesn't work:
card is the consumable here
you want to check G.hand.highlighted which is the table of highlighted cards in hand
oh, now appears this crash when I click on the consumable
don't use G.hand.highlighted in has_enhancement
it's a table of cards, you need to loop through it
and you probably want to check if there are 2 or more
yeah
wait so what should I use in has_enhancement then?
G.hand.highlighted[i]?
yes
tried like this but it still doesn't work (but it doesn't crash)
those comments are for checking if there are 2 selected
is_chemical might be nil?
it is
you might wanna do not is_chemical == not ...
now it's the situation as before, where the "USE" button gets active even if I selected a card without a specified enhancement
what's the difference between Card.debuffed and Card.debuff?
do yo uwant to make it so that if is_chemical is true it only accepts 3 enhancement and if it's false it doesnt accept 3 enhancements?
why are you using is_chemical at all
🤷♂️
Also is G.GAME.hands[context.scoring_name].played the amount of times context.scoring_name was played this run or..?
this run
this?
Card.debuff is the current debuffed state, a boolean
afaik theres no Card.debuffed
afaik theres no Card.debuffed
oh
How do you set the enhancement of a card?
I'm confused because Vampire (VanillaRemade) uses c_base (Card:set_ability("c_base")) but I thought the class prefix is m_?
What's the prefix?
Doesn't answer my question above.
c_base is unenhanced playing cards
isn't c the consumable prefix?
still m_
playing cards break several rules because 
they also have three names
it is c_base
theres no m_base
m_base doesn't exist
oh
this is a 'because thunk said so' moment
"it's not m because it's not modified" - thunk probably maybe idk
So it would be m_lucky but for base c_base?
yes
Alright.
also im pretty sure this is answered in the wiki
just in another question
hmm i guess not
speaking of the wiki
how the hell do i sort it to be more searchable
I want to check if 2 playing cards that have one of the 3 specified enhancements are selected.
im thinking about making a page for each topic and just duplicating the questions that are relevant for each
but I'm still unsure how
local is_chemical = true
if #G.hand.highlighted == 2 then
for _, playing_card in ipairs(G.hand.highlighted) do
if not SMODS.has_enhancement(playing_card, "key") and ... then -- do the rest
is_chemical = false
break
end
end
return is_chemical
end
im stupid
huh?
there
why isn't my hook working?
r is lowercase
right
it works now, thank you so much!
sorry if I overwhelmed you with tons of questions... I lost most of my experience in balatro lua coding
...wait, is load_profile not the function called when you switch profiles? 
are there any common vanilla functions people want docs for
every function that runs on game start and every function that runs at every point of switching profiles 
but outside of niche use cases like mine, i guess... maybe shop functions
wdym
every function that gets called on shop start
and anything that can happen while in the shop
from what i've seen, a lot of people like to try either just messing with the shop or building some extra thing for it
im asking more for utility functions
ah
there are contexts for shop things now as well
the c sure doesn't mean consumable. it probably just means center
it's the base center or something
idk
what even is a card
you are an card
clearly an instance of Card
and c_base is not a Card
so the c can't possibly mean card
wdym c_base is not a Card
i am not an card
it stands for cstring
it's a center
cdata_base
not an instance of the Card class
the c is short for c_base
c_base_base
it stands for consumable everywhere else though
is this a GNU = GNU's Not Unix situation
this is wrong
it stands for consumeable half the time
true...
anyone can pr the wiki now pls make it better idk how to write https://github.com/nh6574/VanillaRemadeWiki/
yeah
doesn't work
whats the code
hmm no idea
it stands for Cat obviously
https://github.com/EremelMods/Ortalab/blob/abfa713121ce6a99407273bfb0db73f8282aa0c5/localization/default.lua#L167
like this i think
How do I make a Joker unlock after discovering every other Joker in that mod
For example if I had a mod with 30 jokers and you need to have discovered all 30 of those jokers before unlocking that secret 31st joker
bump
😭
IM LOSING MY MIND
i got some help from n and got this code
local all_unlocked = true
for _, center in ipairs(G.P_CENTER_POOLS.minus_collectibles) do
if center.key ~= self.key and center.mod and center.mod.id == "balatrominus" and not center.unlocked then
all_unlocked = false
break
end
end
return all_unlocked
end
}
but it no worky
says tg is nil
card.ability isn't populated until after the load function is run i think
how would i persist the sprite change after load then
who tf pinged me
i did accidentally
boooo
How do you override the description of a card for debuff-like effects?
boooooooooooooo
well fuck you 🖕
wow how could you be so mean to eventlesstew
@granite jay im very sorry for feli's behaviour here
deflect, deny
shoud i use set_sprites then
Bump
what do you mean
All g
(Insult redacted)
use set_sprites, but use an event inside it, because card.ability also isn't populated until after set_sprites runs
i do the same thing for high roller
oh wow now i get insulted because mari successfully decieved someone else
Oh, I just read it, sorry about that
its fine
anyway wdym by override descriptionb
You know how the debuffed cards have the “score no chips and all abilities are disabled” description rather than +5 chips? I wanna do that for a boss blind condition where cards score no chips

wao
