#💻・modding-dev
1 messages · Page 273 of 1
then it's just an extension
correct
do i get even better toml?
no
if you want to
You can choose a Lua one
what do i get :<
you search formatter in the marketplace and get one of those
Me: Why is my card freaking out?!?!?!
Also me: puts an event inside of an event
what does it do
it gives you syntax highlighting and code formatting
eye see you
note the outside event continues below the bottom 
helps you catch syntax errors like the one you just had
I have no idea why mine freaked out then
But it stopped freaking out when I didn't put the event inside the event
function() if true then foo()
end
end
might become
function()
if true then
foo()
end
end
You did something wrong probably
i wonder why it doesn't show a yellow line or smt here
a common mistake is forgetting return true
you most likely forgot to return true
without return true, does it just run forever
what does return true do?
if you don't return true it will assume that the event has not yet concluded and continue running it endlessly
it returns true
true...
I've got this code to shove a card into the shop inside a deck back, and it's doing so, but then the card doesn't have the shop UI, can't be highlighted, and you can drag it anywhere on the screen
For Events, it notifies the Event Manager that the Event has concluded and should be removed from the Event Queue
dont use card as a var please
what are the names of the consumable pools?
💔
didn't emplace it
use SMODS.add_card
This is copied straight from the base game code
specify the correct area
channeling all of my creative energy into making more ritual cards
yeah don't use create_card it's kinda annoying
i should make cursed cards into a thing
Am I able to use SMODS.add_card as a variable in the same way create_card does it?
so i have the mechanic for later
but you're likely overwriting your function signature
-ish
hey quick question can i have an event display a message on a card
like a joker effect
yes
like let’s say my cursed cards activates and debuffs the card
can i have a message displaying that for extra effect
and if so how can i do that
yes
but depending on how you do it
you don't need an Event
just return the message
like with Jokers
can i pack it into an event
card_eval_status_text
i have a lovely patch for this if you want it
Would this work?
I think you need to do local new_joker?
I have no idea how that wouldn't cause a syntax error the way you're doing it right now
use SMODS.calculate_effect instead
but guessing by the colors you don't have syntax highlighting
what ide are you using
actually
doesn't that like also actually do the effect?
i can find a plugin
like if you put mult it will give mult
no
SMODS.calculate_effect({ message = "your message" }, card)
can i do SMODS.calculate_effect({mult_mod = 5}, nil)?
yes but it might not like it at the wrong timing
nice
I guess that's easier
oh just checked, it will crash if you do nil i think
oof
so now that i have added 1 joker how do i say add another
just do the same thing below that one
whats the filename of the png of tarot cards?
the same way you added the first one?
if you mean inside like the .exe, I mean
that's what it's called in /resources/textures/1x
yeah
hey, did you ever find a fix for this issue?
sorry for the necro post, but im running into a similar problem
was actually gonna ask about it here again, still dealing with it
bummer
yall
I think you need to provide vars
rate the design of ♾️ from 0 to 10
somehow
thats what im thinking but how
cuz to get perishable and rental stickers working I had to include their vars else they would crash the game ```lua
info_queue[#info_queue + 1] = { key = "eternal", set = "Other" }
info_queue[#info_queue + 1] = { key = "perishable", set = "Other", vars = { G.GAME.perishable_rounds or 1 } }
info_queue[#info_queue + 1] = { key = "rental", set = "Other", vars = { G.GAME.rental_rate or 1 } }
I'm assuming you'd just do { key = "j_constellation", set = "Joker", vars = { 1, 1 }}
set is either Joker or Jokers idk which one
this is the version im dealing with
my issue is that I have an info queue that changes to completely random jokers, so I need a way to fetch that dynamically
uh oh
i tried this, but whenever i tried to hover over the joker it crashed the game
hold on let me send the log
did you try with Jokers instead of Joker? cuz i wasn't 100% sure about that
this is kind of pissing me off because this is an easy joker otherwise lmao
I'm voting option number 1 but if it gets dissolved after 3 rounds it should be way stronger
because it'd just be a worse polychrome otherwise
INFO - [G] 2025-03-27 21:53:49 :: ERROR :: StackTrace :: Oops! The game crashed [SMODS BALATRO2 "main.lua"]:545: attempt to perform arithmetic on field 'dollars_per_hand' (a nil value) Stack Traceback
info_queue[#info_queue+1] = {key = 'tag_handy', set = 'Tag', vars = {self.config.dollars_per_hand, self.config.dollars_per_hand*(G.GAME.hands_played or 0)} }
i just copy pasted tag.lua lmoa
Im achieving realism here
Carbon dioxide from burning oils is good in the short term, but terrible in the long term
well that obviously wouldn't work because we aren't doing this on the tag itself
so self is just the joker or whatever this is on
true
Alternate idea: Gives X2.5 mult, loses X0.5 per trigger, destroy itself at X1 mult
well yeah that's kinda obvious too
lol
I just realized is the whole reason M is a huge part of Cryptid is because you accidentally spam mmmmmmmmm into your text editor when you're holding to restart your game?
wait I think I got it
what do yall think
looks good
yay
A card from RandomDude that actually fits the Balatro style no way
😭
if you want a nitpick you could move the word dart to the right a little bit
its a bit off center
oh yeah
by like 2 pixels
so Xmult gives Xmult but how do you get a joker to give chips or flat mult
What does it do
@scarlet spire I GOT IT
anyone have the base game tarrots.png?, i overrid the originals when i started modding and never it backed up
Extract the balatro.exe file
kino?
thats the issue
adds this to a card
wait black deck is one of the harder ones
local constellation = G.P_CENTERS.j_constellation
constellation.config = {
extra = 0.1,
x_mult = 1
}
info_queue[#info_queue + 1] = constellation
``` this is what I had to do
PC / Computer - Balatro - Tarot, Planet and Spectral Cards - The #1 source for video game sprites on the internet!
thanks
Verify integrity of game files?
you should also probably verify integrity to restore the base files
what is the config name for chips and flat mult
I was not answering you with this
for chips and flat mult you just do ```lua
return {
chips = 1,
mult = 1
}
is it without manually specifying each var?
change the values
@scarlet spire
oh lol its that shrimple
this is what I did
ah wait, okay, hmm
you might want to read the documentation on SMODS https://github.com/Steamodded/smods/wiki/calculate_functions
there is little documentation as of now, but there is some
I think the problem is that
it can for some reason only properly copy one variable?
or smtn
so like the first variable shows up fine
but every other one after that is just fucked
no problem :3
how are you calling for each joker?
let me test a theory
theoretically maybe you can try to pull a config from somewhere, but i have no idea how you'd do that
i think its because in P_CENTERS it's called Xmult instead of x_mult
Tecci you're the goat
I have a key for a random joker that's initialized as j_joker and randomized whenever a hand is played
didn't notice that actually, was tryna copy it
i caved im wsling it 😔
i love wsl
if this is what you were asking
ok yeah you're right, if I do it with Xmult it doesn't work anymore ??
There's the RandomDude style I know
lmao
I wonder why that is
Absolutely peak
beauty
✋
🤚


because you need another end for the function itself
whenever you have a function there has to be an end to close it, and same for if statements
ahh ofc
Every function, for, and if needs an end
Game keeps crashing because extra is a nil value, not sure what to do to fix it
to actually get a random joker, I just get a random element of G.P_CENTERS and check if the key starts with j_ because I don't want it affected by weights
are we allowed to ask the thunk questions
what does that mean
Also I don't think G.Jokers is right, it's G.jokers, right?
there's G.P_CENTER_POOLS.Joker
Is that a reference to the hit Balatro mod Neato Jokers?
my jokers... they're neat
Oh
oh...
🧠 💥
dartboard
Also I think it's meant to be self, not card, add_to_deck and remove_from_deck only has from_debuff as arguments in the documentation
Nevermind
I read the documentation wrong
Guys how do I enhance cards again? And how do I check what cards are selected?
self is always the center, not the card
elseif self.ability.name == 'Constellation' then loc_vars = {self.ability.extra, self.ability.x_mult}
``` oh my god I think I just found out why Xmult doesn't work
oh my god this is painful ```lua
if self.ability.name == 'Constellation' and not context.blueprint and context.consumeable.ability.set == 'Planet' then
self.ability.x_mult = self.ability.x_mult + self.ability.extra
- :set_ability
- area.highlighted
the centers of some jokers in the game are initialized incorrectly
thank you thunk
Constellation's center is initialized as Xmult
but then loc_vars and calculate_joker use x_mult


Balatro was not made for mods, he was content with inconsistency because nobody's supposed to be digging through the game code
thats why my mod is entirely self contained and doesnt touch vanilla much
so if you wanna make something like what Wheat is doing display them correctly I think you might have to go through the code and ptach the incorrect ones or something
Now my own code doesn't replace any functions thanks to N', which means my code is a little bit smarter
-# (but -inf smartness + some is still -inf smartness) [=
or make a function of your own that outputs the correct center
would be better since you don't have to patch it; better compatibility with other mods
Smortness

RIP mod compatibility
? it'd be worse if you patched the original code
i would just copy the entire loc_vars if chain
i would input the values manually but you can also call :create_fake_card
is that a thing?
i think smods adds it
no documentation at the very least
imo everything no matter how obscure should have documentation, but ofc not the most realistic goal
oh I see
do you like my awesome new rarity
create_fake_card = function(self)
return { ability = copy_table(self.config), fake_card = true }
end,
oops ping
I don't think this would work cuz no key
maybe with ability.name but idk
wdym no key
well that's just a table with ability and fake_card and it needs a key to be localized
otherwise it'll just show error
i meant using that instead of self in the loc_vars and then passing those manually
why is this running twice? i see the tagged return message twice for some reason
hi, how would i go about making my own blueprint styled joker?
what's the difference between G.play and G.playing_cards?
You can look at the balatro source code, just extract the .exe with 7z
You can look at blueprint
I'm currently trying to make a joker that allows for 7 card hands to be played, I've got it to allow selecting 7 cards but can't play any hand, I'm guessing cause the vanilla balatro hands are coded for 5 card hands, is there any way I can allow for the vanilla hands to be played with 7 cards instead of 5?
G.play i believe refers to the played hand?
or all cards in play?
what do u want to do
add a card to the deck
i would assume neither of those is what u want then (or at least, not G.play)
i think G.deck
yea its probably G.deck
that is indeed a thing
How do I get a joker's key from it's card?
I've tried .key and .base.key and neither worked, so I might as well just ask
game.lua has all the jokers and their "order" number, not sure if that's the key you're needing
It's internal identifier, not it's key as in keys and values
i told you 😒
This
thanks
oops sorry!
My fix for this kind of thing is to just store a "triggers" variable and make it only happen if triggers == 0, increment trigger by 1 when the condition passes, and then reset triggers at another point
i would just check if not context.repetition then right?
it's better to do a positive check of context.individual
is it possible to change the vanilla joker with the modded one, as in reworking it
yes that's what take_ownership is for
oh right
i mean the thing is this isnt a joker its a sticker
i assume it still works
no idea 🙂
is there a context for cards that are played but not scored?
nw
ill experiement
it was already a big help
apologies for somehow missing ur message earlier
there's an optional feature to enable context.cardarea = 'unscored'
or you can just check the unplayed cards in context.full_hand
ok adding that made it do nothing again lol
so it probably isnt why its repeating
ill figure it out tmrw
maybe context.main_eval then?
either that or repetition is the culprit?
@scarlet spire were any of the other jokers giving you issues with delivery? r just constellation?
ill give this a shot
maybe you can patch the config with lovely
This was my solution to the problem
if. that dont work i gtg sleep etc
yea ill do this worst case
my friends and i are trying to fix the problem
ooo cool and i can combine it with context.individual and context.cardarea = 'unscored' to loop over those cards and do effects with context.other_card?
there's a bunch of them, I don't remember off the top of my head
i mean this is the easiest way
yes
mostly the scaling jokers
i just wanna do it with context if possible for clean code
thank you!
keep in mind it's an optional feature you have to enable manually
where can i enable it?
Also still looking for this
i think it's
SMODS.optional_features = {cardareas= {unscored=true}}
card.config.center.key
Thank you
like this right?
awesome, and id put this in my main file yes?
yeah
thank you!
never done it, no idea
fair
What do people do for "resets every ante" triggers? not seeing the context for it listed nvm just remembered campfire exists
also hello again,
i'm looking for a way to spawn a tag (Investment, Negative, etc.) as a part of a new UI element. where do i find the logic that spawns/animates the tag appearing? thanks
i've already done that, found where blueprint is to look at how it's done but i have less then 0 idea how it does what it does
if only the example joker mod has blueprint
card id for jacks is 11 yes?
ye
Anyone know of a way to randomly select a scored card
pseudorandom_element(context.scoring_hand)
Thank you so much, I really ought to read through all the syntax. Regardless, many thanks once again!
might want to toss in a pseudoseed() argument as well
so it would be pseudorandom_element(context.scoring_hand, pseudoseed('<seed>')
and replace <seed> with whatever, it just makes it so it chooses something different for different jokers when they use the pseudorandom_element() function
in vanilla the game usually just uses the joker's name as a seed so its always unique
to be more specific pseudorandom_element(table, pseudoseed(seed)) will pull a random entry from the table, and context.scoring_hand is just a table of all your scoring cards
glad to help!
my end goal is to make a blueprint joker that selects a random joker (apart from itself) to copy the ability of
SMODS.blueprint_effect(card, copiedjoker, context)
how do I embed a custom save parameter into save.jkr 💀
I'm trying to do stuff similar to Ancient/Idol/Rebate
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
local card = context.other_card
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
card:juice_up()
card:set_base(G.P_CARDS[suit_prefix..'Q'])
else
local card = context.other_card
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
card:juice_up()
card:set_base(G.P_CARDS[suit_prefix..'K'])
end
return true end }))
end
end
end
end
Trying to convert jacks to either kings or queens but im running into this error message, not sure whats going on
local card = context.other_card this seems to be causing an issue
You'd use a global variable for that, the example mods have a castle2 that shows it off a bit
?
how do i use this? and why isn't this in the docs?
card is the blueprint and copiedjoker is the joker your copying, I'm not sure why it's not in the docs.
key = 'singular',
loc_txt = {
name = 'Singularity',
text = {
"Squares the current {X:mult,C:white}Multiplier{}",
"{C:inactive}(Currently {X:mult,C:white}x#1#{} {C:inactive}Mult)",
}
},
rarity = 1, -- Rare rarity
atlas = 'singularity', -- Replace with actual sprite atlas if different
pos = { x = 0, y = 0 },
cost = 1, -- Adjust cost as needed
loc_vars = function(self, info_queue, card)
return { vars = { "x" .. tostring(info_queue.Xmult * info_queue.Xmult) } }
end,
calculate = function(self, card, context)
if context.joker_main then
local new_mult = context.Xmult * context.Xmult
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { new_mult } },
Xmult_mod = new_mult
}
end
end
}
I'm trying to make a joker that sqiares the mult, but whenever it pops up in the shop I get this error.
ok, takes time for me to learn Ig
the more I know
today in "things which definitely do what i want them to do but also feel like literally torturing the code, like with knives and stuff"
which line here is line 247?
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
again, please stop referring stuff as "card"
that is your joker
you will have no means to refer to your joker after you do that
doesn't really help me much, i could intuit what the var's would contain, but i don't know how to use it in my mod
how does this help me achive my goals?
i see, okay i just saw the implementation in the base game for strength and thought it would work, thank you!
oh but also
i think the reason why it doesnt work is that
it runs "local card = context.other_card" only when the event happens, and by that time, its likely the context.other_card no longer exists
i tried to remove the event manager and that made it work but it happens so quickly that i had no way of seeing an animation for it
so how do i store that card?
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local card = context.other_card --just a ref, change the var's name too :3
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
card:juice_up()
card:set_base(G.P_CARDS[suit_prefix..'Q'])
else
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
card:juice_up()
card:set_base(G.P_CARDS[suit_prefix..'K'])
end
return true end }))
end
end
end
end
appreciate it!
i actually dont remember if thats the solution or not :3
im not sure since ive not used it but looking at the code i think you just call the function in your calculate?
tell me if it doesnt work lol
wait I might be dumb
new crash
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
this is line 246
oh
did u change the var's name
exactly
context.Xmult isnt a thing
i assume you're trying to get the current mult which would be simply mult
np :D
yeah I was using another mod for reference and they have a goofy repository
or whatever it's called
I use python for math, Modding is new ground for me lmao
I'm a bit confused here
it says that G.GAME.current_round.castle2_card should reset every round, but I don't see the end_round() check
ah i see
anyhow you would do this by just adding whatever the current mult is as xmult
If i wanted to add a message on the joker when the change happens, would i do it like this?
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = context.other_card
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
message = 'Queened!'
message_card = card
else
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
message = 'Kinged!'
message_card = card
end
return true end }))
end
end
end
end
that makes a lot of sense, i was thinking it would go outside my SMODS.Joker, now all i need to do it get a random joker and boom, thanks!
lwgwnd, cheers
I swear I can spell
message only works when you return it, but you can also do
SMODS.calculate_effect({message = smt}, cardYouWantTheMessageToBeOn)
and i would use this line to replace my current "message" line
mhm
awesome let me try
im pretty sure it just runs at end of round despite what it looks like
at the very least i can attest to it working
also wow i didnt realize they updated the example mods to explain what hooks are
oh, they didnt have hooks before?
nah my download of it doesnt have it
well it has the hook
it just doesnt explain it
icic, i started modding a month ago and the example mod already explained hooks
its convenient
it is very convenient once you learn its a thing
tried this
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = context.other_card
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
SMODS.calculate_effect({message = 'Queened!'}, card)
else
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
SMODS.calculate_effect({message = 'Kinged!'}, card)
end
return true end }))
end
end
end
end
but the message didnt pop up on my joker
weird, it should do that
maybe bcz its inside an event? i doubt it though
can u try running the line outside the event rq
i just realised another issue with this, what if the game calculates the hand as a two pair but after it changes the card it becomes a 3 of a kind?
yup one second
ive not actually seen SMODS.calculate_effect() inside an event before, its always outside of it from my experience
so it could be that
true
maybe you need to use the uhhh
eval smt smt for the message instead
damn, i forgot its name
💔
does work outside the event btw
okok
lemme go find the function's name
i suppose i could make two different events, one for kind one for queen and return the message like that? @manic rune
you should be able to just check a local variable if it gets kinged/queened and add an if outside the event that triggers the message
ah, so SMODS.current_mod.reset_game_globals(run_start) is called at end of round
therefore I don't have to define that, only overriding init_game_object is needed
card_eval_status_text(cardInHand, 'extra', nil, nil, nil, {message = d_message})
I just need to inject a custom parameter, the resetting logic can also be defined on my side
the first part just defines the variable and gives it a default value
the second part makes it change each round
but i do suggest Osquo's approach too, actually
the timing seems to be more accurate that way
so I don't need the second part, I can define the resetting logic myself
got it
okay let me try
func = function()
toconvert:juice_up() --JUUUUIICEEE
return true
end}))
if check then SMODS.calculate_effect({message = localize('osquo_ext_amberconvert'), colour = G.C.ATTENTION}, card) end```
heres an example of how i did it in a mod im making
this converts a card but same principle
check is a local variable defined earlier
hmm okay this helps, let me modify
any idea if this breaks the game?
probably not
i dont think poker hands can change mid-scoring
it wont affect your hand at all
hmm if i did context.before?
itll just calculate as whatever it was when you clicked play
yeah
okay
i will try this next once this message thing is fixed
what does check do here?
yeah i forgot to specificy my bad
check is set to true earlier when finding the card to be converted
maybe u can do stuff like
...message = (checkA and localize("a")) or (checkB and localize("b")) or nil
?
im actually not sure what happens when message is nil
if it doesn't do anything then i think it looks cleaner :3
i think i figured out a solution
will report back in a min if it works
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = context.other_card
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
technically this uses the SMODS thing outside the event but still inside the if condition
-# why is it there
omg this works perfectly
that is a very good question
np lad
np :D
why r they hanging around there tho 😭
bluds think they r part of the team
...can you play cards from the joker area?
i dont think so, no
I am checking for context.card_destroyed and context.cardarea == G.jokers and context.other_card ~= card with lua SMODS.calculate_context({ card_destroyed = true, cardarea = self.area, other_card = self }, nil) , and yet it triggers when self.area == G.play or self.area == G.hand
im pretty sure it checks G.hand.highlighted for playing hand
those cards are in G.jokers
yeah that's because uhh
would be kinda cool if you could
like you could "reserve" a card for later
oh, autumn mood actually had a joker which does that
but
how the fuck does it even trigger for G.play and G.hand
:(
you can actualy put anything in any area :3
well yes, but I am explicitly checking if it's G.jokers
just that some stuff will break, since they lack vars which code of the respective area checks
context.cardarea == G.jokers is wrong here
since
it kinda means nothing
how come?
its telling ur joker to run the effect
u know when u add context.cardarea == G.jokers in stuff like context.end_of_round?
okay so the answer is no, even this cant change the poker hand
i changed the initial if conditon to
if context.before and context.individual and context.cardarea == G.play then
oh but I made it so cardarea = self.area
context.before isnt supposed to go with context.individual and allat
its just context.before
ah i see
and you are supposed to run a loop through G.play.cards, which refers to your playing hand
hmm how do i iterate over full_hand though
Bruh this coding stuff ain't easy lmao
I now realize where I went wrong though
cuz it
fucking overrides that or smtn
for _,otherCard in ipairs(G.play.cards) do
end
ah so like for k,v in ipairs(G.play.cards)
okay let me try
for REAL
I'll just check context.other_card.area == G.jokers and context.other_card ~= card
it becomes easy when you code a lot lol
dw
most of the time its just the sheer amount of contexts, functions and stuff that confuse you
All I'm trying to do is mult * mult and I can't
when you remember them, they r not that big of a deal
watchu doin
calculate = function(self, card, context)
if context.before then
for _,otherCard in ipairs(G.play.cards)
if otherCard:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = otherCard
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
testing this out, moment of truth
Making a joker that squares mult
ah
unbalenced as hell
i think you should use talisman for that one
they support squaring mult and chips within return itself
wait wait
otherCard, other_card
I'm just using a prexisting modded joker as a skeleton
seems it isn't so simple though
its a lib mod to allow for insanely big numbers
they also add ^mult and stuff
yup i just fixed the other_card to otherCard
nice
completely forgot about the cardarea thing SMODS does in calculate_context
Talisman is a mod that adds new ways to return scoring effects
so instead of just mult or xmult you can do emult which is exponential mult
in this case return { emult = 2 } would square your mult
calculate = function(self, card, context)
if context.before then
for k,v in ipairs(G.play.cards)
if v:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = v
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
this just breaks my game by invalidating my joker file
AHhhhh now that's an idea
oh thats cool
wait, how so
so your calculate function would be something like
if context.joker_main then
return {
emult = 2
}
end
end```
no clue, last time something like this happened, it was like a typo or something
since this depends on talisman though you'll have to add it as a dependancy or itll crash without it installed
oh wait
i think i figured it out
oof, icic
oh no
nvm that didnt fix it either
would it be mult^2?
what on earth
math deck.
coolmathgames / balatro crossover
calculate = function(self, card, context)
if context.before then
for k,v in ipairs(G.play.cards)
if v:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = v
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
end
any idea why this would just invalidate my joker file lol
any syntax errors?
whats the crash log
pretty sure it would
doesnt find my mod file, as in it didnt load in
this is the crash log
In python the equivalent would work, but lua aint python
Engineering did't teach me lua...
sadge
everyday i wish there was a google translate for languages
There is
how about this?
you just
described what google translate does
It's called being cranked outta your gorg at computers
💔
unfortunately i dont fall within this category
giving up on this, i will just put a disclaimer saying this will not change poker hand
you seem to be
missing something
hm?
what is that
i tried pasting your code in my own file
and it works?
no, the opposite
lol
WAIT CAN YOU CHANGE JOKERS BY FLIPPING THEM
BECAUSE THAT WOULD BE GAME CHANGING FOR MY MOD
oh my god
card_flip()
you change jokers by changing them
the flip is just to mask it
isnt it just
this is game changing holy shit thank you
:flip()
i recommend getting used to this feeling
yeah, never have your expectations high when you are testing your code
be prepared to debug a seemingly simple function like 10 times
wtf is that
before actually getting it to work
i hate that vscode doesnt have errors that i can see in my code for lua before i open the game
me when i hate you
why you hate me :(
it's nothing personal i hate everyone
yeah it's misanthropy 💔
My PC is going out the window
balatro modding, or, a tale on how a single-letter typo can cause decades worth of sanity deterioration within a few hours
whats wrong?
how
im also using vsc
Literally everything
did you download the lua extension?
calculate = function(self, card, context)
if context.before then
for k,v in ipairs(G.play.cards) do
if v:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = v
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
end
this works but will NOT change the poker hand @manic rune
Mainly that I don't know lua
mmmm
they probably don't have the lua extension installed and hence no syntax highlighting and whatnot
doesnt that mean it doesnt work
this is probably why, but would it show the "do" issue we saw?
yes
yes
wait what do you mean theres a lua extension for vscode
it shows whenever your code is wrong
yes i just meant that it doesnt break the game
chat what should i add to the letter deck 😭😭😭
no literally LMAO
oh yeah I think I had a problem similar to this one
greek
dude ive just been opening the game and closing the game...
it's getting less attention from me because it has 0 sunergies
painfully
math deck also has literally 0 synergies
what did you do to fix it?
where aces were getting counted as face cards when scored after I'd changed their rank in context.before
mmm i guess changing enhancements do work, but they dont change the poker hand themselves
wait
I scrapped the joker before I thought about it 💔
isnt there context.modify_scoring_hand?
belis
who tf is belis 😭
I have finally installed the lua extention for vscode...
is there?
guess im belis now
belias
oh my god i have to uninstall the vscode extention
i think i revealed it to exactly 1 person
let me check
and what would it be
and did u try myst's new blind :3
wth there is
its used like 4 times in smods code
@manic rune how on earth do you find this
do you mean the thing
benefit of being friends with insanely talented people, i suppose
nor did any of you
:3
I forgot about modify_scoring_hand tbh
what thing
i cant even find it on the wiki
WHAT
wait where do you get these from
JUST EXPLAIN IT TO ME
I've seen it in auto-completion but hadn't thought about what it might very obviously do
I'm missing the fuck out
get wat
because its not on it lmao
i love undocumented features
wait so how do i implement this 😭 do i just add that context alongside context.before
oh god
I LOVE UNDOCUMENTED FUNCTIONS 🗣️
I assume those lua files are examples?
can someone help me diagnose why my joker isnt showing up in the collection? it works for others but not for me for some reason
no, its my mod
holy canoli
yeah you need intellisense to see it after typing context.
silksong
man smods really needs a rework on documentation
wait...
i see
I've tried that one
easy way to get it is to open your entire mods folder as a workspace in VSCode 
so would context.modify_scoring_hand solve your problem too @tall wharf ?
dw, Eremel is working on a better documentation
I shoulda seen that coming, since it's in your name....
i mean, do you think its a nickname or smt 😭
i do have it open on vscode
Yknow what...
then it's probably cuz you don't have the lua extension or smtn
what problem
it should show up
then there's the other way.......
finally, gambling in the funny poker game
what would that be
wrong tag sorry, i meant @rain slate
i do :(
fraud 🗣️
just installed it
yeah it's ok I didn't wanna make the joker anyway
was js an exercise to see if I could do it
using the smods lua lsp
saw a cool joker on YouTube and wanted to try implement it
if context.modify_scoring_hand and context.before then
this is what i would do @manic rune ?
if i have in my main.lua
SMODS.Atlas{
key = 'Jokers',
path = 'Jokers.png',
px = 71,
py = 95
}
SMODS.Joker{
key = 'Redboard',
loc_txt = {
name = 'Redboard',
text = {
'{X:mult,C:white}X#1#{} Mult If all',
'cards held in hand',
'are Hearts or Diamonds'
},
},
atlas = 'Jokers',
...
and my folder structure looks like
Redboard/
├── assets
│ ├── 1x
│ │ └── Jokers.png
│ └── 2x
│ └── Jokers.png
└── main.lua
why might my joker not show up in the collection? it works for a friend but not for me
i see
what is pos?
what is love
pos={x=0,y=0}
oh wait show up in the collection nvm
Does your mod show up when you load up the game?
wait do you have the
json file or whatever
with your mod prefix and shit
pretty sure SMODS needs that to load it
wait no i never did any of that
since you need to specify your main file in there
calculate = function(self, card, context)
if context.modify_scoring_hand then
for k,v in ipairs(G.play.cards) do
if v:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = v
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
end
so i did this, it modified the card 3 times and then did NOT change the playing hand? lol
any ideas?
Yeah that'd be it
it doesnt and i cant believe i didnt think to check this
thanks for the help
Might it be because you're doing it in the event after a delay?
i actually dont know how to use context.modify_scoring_hand myself
i only remember that it exists
😭
i love undocumented functions for god sake
thats just for animations sake
well yeah, but, it's still after a delay
maybe the poker hand gets set somewhere there, and you're supposed to change it immediately?
okay let me remove the delay
try checking how context.modify_scoring_hand is set up in better_calc.toml in smods
belis
i dont really know how it works either
personally i recommend bashing rocks together until it works
no results lol
oh really
belis
wait
should be line 1385
i searched for modify_scoring_hand and it shows now
nice
SMODS.calculate_context({modify_scoring_hand = true, other_card = G.play.cards[i], full_hand = G.play.cards, scoring_hand = scoring_hand}
Look at the surrounding code
It'll tell you what kind of context (not like calculation context) you're in
for i=1, #G.play.cards do
local splashed = SMODS.always_scores(G.play.cards[i]) or next(find_joker('Splash'))
local unsplashed = SMODS.never_scores(G.play.cards[i])
if not splashed then
for _, card in pairs(scoring_hand) do
if card == G.play.cards[i] then splashed = true end
end
end
local effects = {}
SMODS.calculate_context({modify_scoring_hand = true, other_card = G.play.cards[i], full_hand = G.play.cards, scoring_hand = scoring_hand}, effects)
SMODS.trigger_effects(effects, G.play.cards[i])
for _, eval in pairs(effects) do
if type(eval) == 'table' then
for key, eval2 in pairs(eval) do
if key == 'add_to_hand' or (type(eval2) == 'table' and eval2.add_to_hand) then splashed = true end
if key == 'remove_from_hand' or (type(eval2) == 'table' and eval2.remove_from_hand) then unsplashed = true end
end
end
end
if splashed and not unsplashed then table.insert(final_scoring_hand, G.play.cards[i]) end
end
-- TARGET: adding to hand effects
scoring_hand = final_scoring_hand
'''```
i think its not a context but something i add? to the calculate function?
oh it's only for like
dont miss that at the end it sets scoring_hand to final_scoring_hand
i could be fully wrong
adding and removing ?
oh yes
added it
stealing this
i thiiiink it makes a new table of cards to be scored and just modifies the scoring_hand table
at least thats how id intuitively assume it works
yeah thats what i think as well, i just dont know how my function needs to change to incorporate this
i think i have to set the variable to true
I think it's some return table bullshit
modify_scoring_hand
probably return a table with all the modified cards in order
Look at the add_to_hand and remove_from_hand thingy
ill be honest i have no clue what that means lol, this is my first modding project
girl sounding name but no judgment my name is literally aikoyori
no excuses harmonious, mine is too
LOL
I'm sorry astra
something tells me, this is not your first rodeo
i can't say these i made Minecraft mods before
first time im modding a game, but def not the first time im coding smt
it searches effects in context.modify_scoring_hand for keys
and adds and removes cards from scoring accordingly
it calculates that context, gets its return table (i.e. the table you return in calculate), calculates it individually per card (i think) and then it also does something with add_to_hand or remove_from_hand if its5in the table
so i think this is used to add/remove specific cards from scoring?
are we breaking down the modify_scoring_hand's code
yes
yea, altho idk how it should be done
oh my god yeah this is probably only for the scoring hand
yeah which like completely defeats the purpose
if only a smods god is here rn
so it can't like change the type of poker hand or smtn
since scoring hand is decided when you hit play
no it doesnt seem like it
its just splash-lite
so what the flip does "modify_scoring_hand" even mean
You got one of them, just the one that didn't write this code 😭
😭
It modifies the scoring hand by letting you add or remove cards from it I think
wait did you help in making smods?
like not literally the whole hand, just the ones that score
like what the Splash joker does in vanilla
i see....
okay that makes sense
in that case
youd probably need a hook or a patch
chat is this above my paygrade
only thing i can think of is that one code card from cryptid that forces a certain hand to be calculated as [x] poker hand
Yeah this seems like something that isn't covered by SMODS
:0
pretty surprised smods doesn't have smt to support this
played cards are permanently debuffed
wtf aiko
there are a lot of things smods doesn't support
so i have to reimplement the scoring hand function with the new set of cards just to get this to work huh
context.card_removed, the brother of context.card_added when...
?
isnt this done with destroyed?
when will we get context.rank_changed and context.suit_changed by default 😭
nop
what's wrong belis
its probably not easy, that much i can say
game wasnt exactly designed for this kinda stuff lol
is good
any triggered cards are permanently debuffed
that is fair
how do i get rid of these messages holy shit
yeah good luck, you have to somehow get your shit to trigger somewhere in between and change the poker hand
red seal steel king build killer
wild ranks...
i am going to just say it will not modify your poker hand and call it a day lol
mario
I'd do it so this runs before stuff like midas mask or vampire so like before before if that makes sense
Include Balatro source code as a workspace.
it changes jacks to kings or queens so face card stuff should be okay
Just get new ones tbh
smods too
no i mean like
midas mask was just an example
it should run before stuff in context.before or smtn
like you play the hand and then your stuff triggers and changes the stuff
all cards with seals are permanently debuffed
what is
evil
implemented
damn you're fast
lol i just had to ctrl z, i had it before i tried to do the whole modify_scoring_hand
like i had context.before implemented before i tried to do the other stuff
doesn't matter
this is going to keep me up at night
what cant be done by default im confused
or you can look into the code that gets called when a hand is played
and somehow change the poker hand by referencing that
okay i just realized
what you meant
i thought you meant like as a temporary thing, you were telling me to just do context.before and not change the poker hand
but yeah
ill look more into it later
back
Is this a good Plasma Deck-like sound for my rare joker that turns every flushable hand into it's flush variant and turns all played cards into wild cards?
new question for you
calculate = function(self, card, context)
if context.before then
for k,v in ipairs(G.play.cards) do
if v:get_id() == 11 then
if pseudorandom('tindwyl_one') < G.GAME.probabilities.normal/card.ability.extra.init_odds then
local jack_card = v
if pseudorandom('tindwyl_two') < G.GAME.probabilities.normal/card.ability.extra.end_odds then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'Q'])
return true end }))
SMODS.calculate_effect({message = 'Queened!'}, jack_card)
else
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function()
local suit_prefix = string.sub(jack_card.base.suit, 1, 1)..'_'
jack_card:juice_up()
jack_card:set_base(G.P_CARDS[suit_prefix..'K'])
return true end }))
SMODS.calculate_effect({message = 'Kinged!'}, jack_card)
end
end
end
end
end
end
how do i make sure it only converts those jacks that are being scored
for k,v in ipairs(G.play.cards) -> for k,v in ipairs(context.scoring_hand)?
mhm
awesome
Hi! I'm making a custom texture pack for friends and I got all the art done but I have no clue how to implement this in a way that'd be easy for others to download other than manually replacing the sprites with 7zip. All I really want to do is replace the base cards front and back sprites.
I'm extremely new to lua so any and all help would be appreciated if possible 
I despise how good at art you are because I can't ever see it again for the first time
firstly it sounds pretty over the top for balatro, especially with how long it lasts
if you want to have a custom sound for it i'd go for something more minimalist sound-wise, like how vanilla does it mostly
second, does this cause the played poker hand to change? because it looks like it does and there was just a question here about how to do that
lmao ty
hello chat
i think you can just use deckskin api from steamodded
no need for malverk
I hooked into the modify_hand and calculate_joker functions to change all of the hand parameters like text, chips, and mult, and then reversed all the hands played counters to be the flush variants instead, and forced every joker that gives chips, mult, or xmult based on flushes to trigger, as well as Seance
oh my god how did you do all this? is your mod available on github
i only wish i was as good
so that would allow me to edit front and back sprites? I'll try that since malverk just confused me and kept crashing on attempts, tyvm!
Also, I kinda want it to be over-the-top because it's a unique joker, and I wanna show off my music making and sound design with the mod
it sounds really cool
I haven't even thought about making a github for this, I probably won't even publicize this, this is my code, it's pretty shoddily put together, so
i cant thank you enough tbh this is insane
i only wish
The Seance force trigger just straight up steals the Seance code to make it work, because I can't figure out how to make it just use the same code
Okay, not sure what I've done wrong now
(Lines 25 and 26) loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.Xmult } }
whats your config line?
I put this in my joker code to tell the game what to force trigger
gotcha, i will be trying to reimplement this during class tomorrow, thank you
Just a tip, it isn't compatible with Space Joker, and I don't know how to make it compatible
loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.Xmult } }
maybe you can force it to retrugger space joker after your joker if it exists?
It'll trigger for the base hand and the modified hand in that case, which isn't desirable
thats not your config line, heres an example:
config = { extra = { chip = 0, chip_mod = 20, faces = 3 } },
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.chip_mod,
card.ability.extra.chip
}
}
end,
debuff the joker before your joker runs and un-debuff it after?
I also put this line in to make it update the text, which is also why it has quotation marks
update_hand_text({delay = 0}, {chips = G.GAME.hands[G.GAME.new_poker_hand].chips, mult = G.GAME.hands[G.GAME.new_poker_hand].mult, handname = '"'..G.GAME.new_poker_hand..'"'})
oop... I may not have one
Goober moment
Maybe, but seeing the joker debuff itself temporarily would seem a bit janky
theres the problem, it needs to find that variable somewhere, the config line is where you add it
i see, this makes sense
yeah i agree, maybe theres a way to do it without the visual effects
Also for how long the sound is, the 5 notes at the end are for each card turned into a wild card, so it only plays that many times
ooooh now thats cool
why are different jokers displaying messages for same functionality?
Those are 3 different jokers, I don't have art for any of my jokers yet
OKay now it's working
That last one gives X0.1 mult for all 4 suits played in sequence
I just need an effiecent way to have it square the mult in the function
ah gotcha, makes sense now
So Spades > Hearts > Clubs > Diamonds = +X0.1