#đ»ă»modding-dev
1 messages · Page 147 of 1
this much i know
i just wasn't sure how to retrieve the table from SMODS.Ranks and get the key out
how do i check if the scored card has a certain enhancement?
i think SMODS.Ranks.key didn't work
or whatever i tried
SMODS.Joker {
key="AliceRabbit",
loc_txt = {
name="Alice_Rabbit",
text={
"Changes all {c:spades}Spades{} in deck to",
"a random Rank each, each {C:attention}Blind{}"
},
},
config = {
extra = {
}
},
atlas='FOM1',
pos= {x=3,y=0},
rarity=2,
cost=5,
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.cost
}
}
end,
calculate = function(self, card, context)
if context.end_of_round and not context.repetition and not context.individual then
local rank = pseudorandom_element(SMODS.Ranks, pseudoseed('alicerabbit'))
for i,v in pairs(G.playing_cards) do
if v:is_suit("Spades") then
SMODS.change_base(v, nil, pseudorandom_element({'2','3','4','5','6','7','8','9','10','Jack','Queen','King','Ace'}, pseudoseed('alicerabbit')))
end
end
SMODS.calculate_effect {
message = 'Scrambled!',
sound = 'myo_alicerabbit',
card = card
}
end
end
}
this works but i want it to work with modded ranks
the bit of attention is that giant change_base at the bottom
the local rank is just a leftover
from testing
rank.key
or pseudorandom_element(SMODS.Ranks, pseudoseed('alicerabbit')).key or whatever
okay THAT'S how i'm supposed to do it
i was passing pseudorandom_element(SMODS.Ranks.key
i think
If I name my variable as card.ability.extra.chancemodif would the game multiply it to G.GAME.probabilities.normal automatically?
Ok, I did that, and now it crashes instead
Yeah I figured.
SMODS.change_base(v, nil, pseudorandom_element(SMODS.Ranks, pseudoseed('alicerabbit').key))
that's a crash
oh wait
lol, lmao
nvm
joker_main doesn't have other_card
that's why i originally had the checks when the card was scored
but it didn't do anything
iterate over context.scored_hand
how do I do that
abilities can work in multiple contexts if you need them to
wheyy, works now
very nice
what do y'all think?
forgot shade lmao
No I want it to be generating 3 time, all this part work for me - but the juice up animation only play once and i donât understand why it does that
now it's complete hahaha
actually not sure i like how that looks ignore me
my first mod so idk what to expect
oh! right
i had a similar issue
wdym? the way that you cannot read the "joker"?
use calculate_effect()
it's an easy fix tbh, but idk
just was brainstorming how it'd look if the white inverted the joker text colors
@grave arch try passing this
fairly self explanatory
I just do not understant what ur saying lmao
e.g. pass mult how you would to return {}
like, u want the white parts to be dark when in the joker text?
Ohh thank you!
So this will be like the juice up animation? (I canât use my pc right now ahah)
o think I get it
don't know what you're referring to, but it'll make each thing pop up as separate visual events
it also handles the timing and stuff automatically
you use it for anything that does more than one "thing" per trigger, afaik
Ohh I see!
Im trying to make a joker that give a lot of things when it destroy himself (like money) and I want to do an animation on itself for each things it give
Exemple :
- +5$ animation
- another 5$ animation
- add a random joker animation
etc, etc
So thank you, it should help me :)
@leaden wren
it's not very visible tho
idk if instead of inverting colours maybe making it a little darker blue
like this?
ok I finally got it to work'
i moved the set to false to only trigger when the hand triggers the Joker effect
This way it does its intended effect
are the skulls a reference
my jokers still spawn in the shop when i own them without me having showman i tried to set the value of allow_duplicates to false but it seems to have not done anything
did you create them with debug mode
hi hi yall :3 this is probably a question that gets asked decently often, but
im lookin to make a mod with a friend that aims to add multiple new suits, and jokers that use those suits. is there some good way to get started on something like that, or is it more of a "work your way up to it" type of thing
Best way is plagiarism. There's a mod that already adds extra suits, Bunco:
https://github.com/Firch/Bunco/tree/old
What is programming but not blatantly copying from others
something something infinite monkeys infinite time etc
what does trigger and delay mean here?
i mean delay is fairly obvious
(this is in card.lua)
delay - delay
trigger - v
"immediate" (default) - Runs as soon as possible "after" - Will run after a set amount of time. Also see delay "condition" - Will not finish until the condition is met. For most cases, you probably just want to use immediate with a check (see func). See ref_table, ref_value and stop_val for how to set this. "ease" - Used to interpolate values. Useful for score incrementing or movement. Also see ref_table, ref_value and ease_to for how to set this. "before" - Will run immediately, but if it doesn't complete before the set amount of time, it will be cancelled. Also see delay
i see
What context is for "after each hand"?
.after?
I've used context.after and then context.joker_main but my joker still got caught looping in collection page.
yeah
This is when I write if context.after and context.cardarea == G.jokers then :
Wtf is your code
It's the update
What are you trying to do
It's juicing it and aying the sound every frame it can
Oh crap, I forgot update is an already taken function name.
I'll check if roll works.
It worked. No more endless drum roll.
And I just noticed the description almost rhymes.
Damn your right I'm now boping now
how would i call the name of the last hand played?
Maybe "last played hand"?
what function or what not for that
you want the hand type or?
hand type
trying to put it in this
i would do this how space joker does it, but it bugs a little
I think I remember seeing it somewhere in the Balatro code. Let me go check.
specifically, this happens and doesnt clear until something replaces it
so itll stick through the shop
and such
i probably could just clear it with a different function or something, but this would be cleaner
G.GAME.last_hand_played
how do i make this not freeze my game?
if G.RETURNLOCALIZATION then
G.RETURNLOCALIZATION = false
return {
message = localize('k_extinct_ex')
}
else
return waitReturnLoc()
end
end```
fuck me
its still happening
What is code now
i just undid it all bc nothing changed and arguably worked a little worse
And what's problem
Hmm
cus this is at end of round
Do you have njy?
njy?
Not just yet
i dont know what that is
this is the guy
this is the code
blue_seal_failed is a context i patched in so i could detect for the condition the card requires
update_hand_text?
what would i put in its arguments
idk
it's probably why it gets stuck
got this error upon trying to select a card in hand
for the record, yes i do
and its just for the message thing that happens when a joker does something
like
'+4 mult!'
isn't that just the message part? or do you need to use eval for custom stuff
or i guess message just links to the card_eval
i needed to move it to the playing card, and seemingly that was the only way to do so
message works
but it ties it to the joker
which isnt what i wanted
im gonna be real, its not causing a problem
yeah
well
its better
Need to learn more about balatro code
So many joker ideas now
Equity - Turns all jokers in hand to the average value 
what's the average value?
average value of hand
so lower value goes up, higher value goes down
sorry not jokers
playing cards
oh that makes a lot more sense
Expected effect: "Discarded non-Spade cards get destroyed."
Result: " 'Sacrificed!' message displayed normally but no card get destroyed."
I need help.
yo spade supremacy?
this is the code i use for destroying selected cards when the specific joker is sold
(kinda like hangman but cracked)
I mean, spade suits originated from swords/blades, arenât they?
true
So I just, bypass the return and directly tell the card to destroy itself?
yeah pretty much
and the shatter thing for glass cards cus while ive never destroyed a glass card i presume they do that instead of disolving
But I also want to track destroyed card count for leveling up this joker, though.
mmm
add a counter var?
increase it anytime that something gets dissolved/shattered
how do i get the level of the last hand played?
need it for this line
are there good resources for making a modded challenge for Balatro
You can probably look around for mods that add challenges to see how they do it as well
Anyone know off the top of their head how to make these two trigger seperately?
I was looking at other mods but it seemed inconsistent, some started with SMODS.Challenge other with SMODS=G.challenge
And Crypid mod had local sticker_sheet = {
object_type = "Challenge
So Iâm not sure how to do it
There is a way to do separate calculations in the same prompt almost like parentheses in math, I was asking about it a long time ago let me look for it
who the hell uses the latter
Cryptid does that because it has its own loader system, it also uses SMODS.Challenge
So itâs something called an Event, I couldnât find the exact code for it (lost in the archive or I didnât end up using it)
So how would it look
That'd be great :)
event manager?
That sounds correct



@narrow pendant
any open stability concerns with better calc lately? Trying to gauge if it's safe for me to make KCVanilla's better calc migration branch the official release
Where do mods go?
Clubs club
If you made a mod and uploaded it on github and etc, do you just create a new thread on #1209506514763522108 or is there anything to do beforehand?
Thanks <3
this is what i have for a chips+mult joker in kcvanilla
return {
chip_mod = effect.chips,
message = localize {
type = 'variable',
key = 'a_chips',
vars = {effect.chips}
},
colour = G.C.CHIPS,
extra = {
mult_mod = effect.mult,
message = localize {
type = 'variable',
key = 'a_mult',
vars = {effect.mult}
},
colour = G.C.MULT
}
}
Thatâs all, I know there is an option index you can add it to some where in #modded
Huh, extra is interesting
ask @south pagoda about it... i wasnt aware of it either
Its a recent feature bettercalc added
still only seems to do the chip trigger
does yours still work?
are you on better calc?
No idea
whats ur smod ver
ig im behind

yeah it aint easy... sorry
@cerulean rose figured I should ask permission before doing this but do u mind if I take it exodia code and rework into a similar card effect that requires 4 cards?
Ohh I'll se about that, ty!
Also is there code for if a joker is active the next round you can make it create a specific joker card?
Sushi is broken â
For some reason Lineup is crashing the game trying to call juice_up, even though that card doesnt use juice_up
So for some reason return { remove = true } under if context.discard then does not destroy discarded cards despite SMODS doc states so.
You could store whether it's active or not in card.ability, then in context.first_hand_drawn or context.setting_blind you could check if it's active and pass SMODS.create_card with the Id of the joker you wanna create
To me this looks like gibrish at the moment but I'm getting the idea of how I should do this
Gonna try this
Which part specifically

Honestly anything I've ever coded is held together by ducktape and glue
I'm a firm believer in the if it works it fucking works method of coding
SMODS.create_card() is explained here
What's that picture đ«„
Art
If #context.scoring_hand triggers on only scoring cards would #context.hand trigger on all played cards
Hmmm I wonder if I can use the smod create on pot of greed when you draw it from a pack to create it as a tarot card
I don't think so
As a work around to the use button not working when lumped in with jokers
Because I have the use function in the card but when u draw it u can't use it or add it to the consumables
Use G.play.cards while in context.scoring_hand
Because I'm gonna guess because it's in a state where u can't draw the use can't trigger lol
And when u pull a tarot from a pack u can't add it to the consumables

The duck tape and glue is coming together
Someone should make a GitHub report for example codes for people to start with
Would help a lot for beginners the joker template is nice but doesn't really teach much
beautiful art
I hope someone adds examples in the docs yeah
that's what it is
You think this could work
đ€
This is the code for Death, and on the right is my code for a Joker that's supposed to work like this
You play some cards and a three, those cards get transformed into the three before scoring
how would I do that
Damn i like your colours
Its the github theme
one of the best themes imho
anyone know how to do that?
Stuff that happens before scoring that would change the subsequent scoring is complex from my experience
I had to create a custom context for my use
It's the Flipper joker
https://github.com/fantasygone/Baladrone
There's probably a better way though
That reminds me I'll probably have to make contexts for myself as well 
Maybe it could be after, I mean that would also make it less powerful
For which use case?
I really just mean how to use copy_card to change the cards into the three
Does it need to only copy the rank or the editions/enhancements too
Copy everything, like death
Ah ok
One of my more ambitious goals for my mod is to implement a new class of card that almost act like Chaos upgrades in Hades, where you have to debuff yourself and then gain a great buff once a condition is met. Gonna need a new card area for it and everything probably
A new class?
The closest they would really be is a consumeable but at the same time not really
If it happens after scoring, then you can use if context.scoring_hand and context.after
To be or or not to be
lmfao
I know the condition, idk how to do the actual copying
An example
That looks powerful
Exactly
So then it disappears?
They're like risk/reward quests almost
yep
you're also doing the zodiacs?
Could be a joker with self destruct
Unless you don't want to it to occupy the joker slots
thats like, 10 now including me
We're calling them Horoscopes instead but yes
Yeah no, these are strictly not jokers
Have fun with cardarea, I have yet to delve into it too
I will definitely be asking around here
And I will conveniently read the responses đđœ
Aries is going to be pain and not compatible with mods
Is matador not?
Matador is not efficient in what it does, as in it doesn't trigger with all boss blinds
In vanilla, so let alone in modded blinds
Astra either hard codes it or makes it work like matador
My Zodiac cards are much simpler
+5 chips to all cards of a specific type and then increase by 3
A few things that need correction
config = { extra = { threes = 0 } },
for i = 1, played_cards do
đ
Which keyword in {C:} do I use on Negative,
edition or dark_edition?
C:dark_edition
I've been trying to figure out how to copy since yesterday
This effect is really hard to use
Isnât it just copy_card(original_3, card_to_change)
idk how to define what cards need to be changed
Whatâs the effect again?
If played hand contains a three and two other cards, transform them into the three
for a triangle Joker
Okay so how are you identifying the 3?
I still have your original version downloaded đ€Ł
-# I will when I play the game again lol
Thatâs looking for cards with an id of 0 and doing it across all cards for every card
oops
You can do it all in context.after
Lemme write some rough outline code for how Iâd do it
Ooh more Tarots!
Which vanilla sound is closest to clock ticking?
probably generic1
if context.after then
if #scoring_hand ~= 3 then return {}, false end
local threes = {}
for _, card in pairs(context.scoring_hand) do
if card:get_id() == 3 then
threes[#threes + 1] = card
end
end
if #threes == 1 then
for _, card in pairs(context.scoring_hand) do
if card ~= threes[1] then
copy_card(threes[1], card)
end
end
end
return {}, true
end
Iâm pretty sure this will work but it is mobile typed
#context.scoring_hand instead of #scoring_hand lol
I did that, but currently, it turns all scoring cards into threes, but only if a three is scored
so it turns your threes into threes unless you have splash
Yes that does look like what the code is doing
Oh not better calc đ
I changed it to G.play.cards and it works
But thatâll include non scoring cards
I genuinely have no clue if my code is on better calc or not ngl
What smods version are you on?
I've been updating somewhat consistently so it should be a somewhat recent version
its intended to actually
Well thatâs not what you said đ€Ł
Though I suppose how I interpreted it isnât possible
Found the version. I'm on 1.0.0~ALPHA-1321a
Thatâs fine then
Ok cool. I didn't know if there was something specific I had to do for better calc or not
How do I check if context.consumeable is a c_world?
i downloaded jimbo's pack to see how it handles jokers with text boxes but it seems to just crash when i hover over certain jokers? but the crash says its from common_events.lua
could something be wrong with my game files or is this just the mod's fault entirely?
ah, reading more it seems that there are a few items regarding the mod itself
ok, I think its because of the return {} but a little orange square shows up with no message after every hand
Try return nil instead
I also tried to make it send a message when triggering but that has the unintended consequence of breaking its effect
No brackets
Same in the non trigger check at the top
alr thanks
Though you should absolutely be developing on better calc, not a month old smods build
What's the function used by the emperor to create 2 random tarot cards
doesnt bettercalc not work
Wondering if I use that on pot of greed to create a second version of pot of greed to get the plus 2 effect working
Better calc didnât work for less than 24 hours nearly three weeks ago
that >24h period lined up with me learning how balatro modding worked lol
where can I download better calc
its just the latest steamodded
ok
I can't wait for Jan 25
I get to patch license joker to be permanently debuffed
Wonder how hard it would be to check for date and update based on that
what lol
24th Jan 2025 expiry date
amazing
thats fantastic that its so soon
God discord mobile sucks on bad internet
you can check dates

Is it possible to simply display text? Cause now I really wanna flesh this out
Add consumables that refresh dates and display it on the joker
Not as a little pop up but directly on the art
like for debugging?
you can print and look at the lovely console or install DebugPlus and use it's console
otherwise you can put varibales in the descriptions of jokers
I mean like straight up text on the joker that gets updated
But I guess doing it in the description would be better
And simpler for my doggy brain
you can update the sprite but as far as I know you would need to make a sprite for every text, or probably use some shader witchcraft
how would I spawn a specific other joker? I looked at Riff-raff's code but I don't see where it defines which joker to spawn
you can set a key
Look at SMODS.create_card
it's a bit easier to use
only shader work i'm able to do is throwing shade so description it is
oh my god that gets embedded everywhere now đ
It was funny the first time but now I hate it lol
we take our work very seriously
The common people already find it hard to get Steamodded now they'll definitely think it's not serious
switching to add_card because apparently create_card doesn't actually place the joker in the joker slot
Yea create_card is just to create the card, but it doesn't place it
So I can't use the create_card function to put a tarot card in the consumables slot
No you use the add_card util
So this is completely different from add_card?
Add_card is like a step above create_card
Add_card is enough đ
i must create more jimbos. my jimbo army must grow.
big fan of Jimbro just being a gym bro
that's the idea lul
@frosty dock yâknow with the new optional features, Quantum Ranks could be suboptimized at least for release. Or maybe have a version with optimized limited functionality in addition to the full, suboptimal version
@acoustic kiln
đ€
Is context.consumeable.key == 'c_world' correct for checking if the used consumeable is a The World?
Found an issue in sylvieSilly but can't find the thread for it.
I tried deleting the ,
which removed the error
But then the game crashed without even a log
soooo
not sure what to do
Is there a name I can put there?
more...
(downgraded dealer to uncommon i was gonna make it stronger but didnt bother)
Nothing seems to work, tried replacing it with "local fortune_jokers = pack_pools['Fortune'] and pack_pools['Fortune']['Joker'] or {}
local suits_jokers = pack_pools['Suits'] and pack_pools['Suits']['Joker'] or {}" so there would at least be a value...
@frosty dock you seem like you know a lot about this and your bio says pings are ok so I hope you dont mind me seeing if you could maybe help me take a look đ
ew 0.9.8 mods
I can downgrade lovely if thats the issue, I updated to latest to fix a mod needing 0.7.1
no that's not the issue
but this specific mod was made for a really old version of steamodded
apparently, i cant make symetrical bricks for deck texture đ
Ah, it hasn't been updated in almost a year, I'm assuming that maaay be why đ
I can't bother to debug such obviously illmaintained mods
Ok will do, thank you
https://canary.discord.com/channels/1116389027176787968/1217914433846775918 there's this thread, but the mod is abandoned so I'm not sure that helps
Its alright, looks like x card is gone as well, im going through some of the mod lists and trying to find what looks nice lol
Thank you for your time
np
am I crazy or does this not do anything? I was trying to see this blind's code since its effect is similar to one I want to code for a joker, but by the looks of it it doesn't do anything
dumb queston but how exactly do I use SMODS.add_card lol
You add these parameters in that order, or use nil if undeeded
key should be of interest for your case
so do I make this a function or something similar to atlas
Just type SMODS.add_card('Joker', G.jokers, ... ,'j_joker')
I guess ... would be the key for the card name?
The first 'joker' yes
gotcha thanks
Check blinds.toml in the lovely folder
gonna be honest trying to debug errors with lovely is ass
especially when it barely tell su what there error is within ur mod
Thatâs not how add card works, it takes a table of values
Ohhh ok
So the order doesn't matter
SMODS.add_card({set = âTarotâ, key = âc_deathâ}) etc
That's even better
That makes it easier for you chowder
I admit I hadn't used it yet lol
ty
also
what would be the proper g.game function for can use if the card is in a booster pack?
facing_blind i'm assuming is when ur actually in the game
and not at the booster pack
guessing I need something like this if G.STATE == G.STATES.TCG_Yugioh then return true
to tell the game that it's ok to enable the use button when the game is in the yugioh booster pack?
tried the key group name and group key can't get the use button to be enabled
use = SMODS.add_card({set = `Tarot`, key = `PotGreed`})
so something like this?
or would this have to be it's own seperate thing and I use create_card in use?
or just replace smod with function add_card?
heyo, is there a way to make a joker double the final result? after the calc
so anything else I should do after this?
or should I set set = 'Tarot' to the custom booster pack name?
what would the game state be considering when in a custom pack?
I think that's my main issue right now
I don't know what you're trying to do
if G.GAME.facing_blind then
return true
elseif G.STATE == G.STATES.TAROT_PACK then
return true
else
return false
end
end,
use = function(self, card, area, copier)
G.FUNCS.draw_from_deck_to_hand(2)
end,```
elseif G.STATE == G.STATES.TAROT_PACK then
since it' s a custom pack of cards I don't think the game state works properly?
becausae the USE button is always greyed out
yeah, the game state is G.STATES.SMODS_BOOSTER_OPENED
i'll see if that helps
Is there any open git where I can read ones code?
OML THANK U
and it works lol
now the hard part is getting it into the deck or the tarot slot
what would be the game state if the card was in ur hand
SELECTING_HAND
?
i think so
Can I not display info_queue if the item has not been discovered yet?
what's the function to put a card in ur deck?
add_to_deck seems to be it but looks like it's for joker effects?
got this error when i tried to copy my joker with brainstorm
anyone has any clue what may be the cause or fix?
this is the joker's code
Just don't return anything outside of those events.
?
local _card = ...
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.deck:emplace(_card)
Sorry, I accidentally set the reply to wrong person-
See the code snippet-
Remove that last return true, oop.
thank you very much
key = 'PotGreed', --joker key
set = 'Tarot',
loc_txt = { -- local text
name = 'Pot Of Greed',
text = {
'Draw 2 cards from your Deck.'
},
},
atlas = 'TCGyugioh', --atlas' key
cost = 10, --cost
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
pools = { TCG_Yugioh = true },
pos = {x = 0, y = 0}, --position in atlas, starts at 0, scales by the atlas' card size (px and py): {x = 1, y = 0} would mean the sprite is 71 pixels to the right
loc_vars = function(self, info_queue, center)
return {vars = {2}}
end,
config = {
extra = {
card_limit = 3 --configurable value
}
},
can_use = function(self, card)
if G.GAME.facing_blind then
return true
elseif G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
return true
else
return false
end
end,
use = function(self, card, area, copier)
if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
local _card = 'PotGreed'
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.deck:emplace(_card)
elseif G.STATE == G.STATES.SELECTING_HAND then
G.FUNCS.draw_from_deck_to_hand(2)
end
end,
})```
hopefully i'm doing this right
The _card is actual card you want to perform actions on... in my case (from where I pulled the code snippet), I use it to copy a playing card and then place it into the deck.
I figured when the error screen said add_to_deck lol
but in terms of the structions of the use = function
is that correct
like am I able to use if game states
in that way
...is the if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then check in use meant to add the PoG (tarot card) to the deck of playing cards?
and i replace _card in with the key of the card name right
yeah
because it's gonna come from a booster pack
and the other state is to check when it's in ur hand to use the draw two
Is it meant to be in the playing hand and not just in the consumable slots?
yeah
I know sounds dumb
but trying to make it function like the actual tcg
just for extra bit of dumbness to it
You'd want to "create" the PoG card again, then, and then emplace it into the deck.
local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'whateverkeyisforpogcardwithmodprefix' })
local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'j_tcgyugi_PotGreed' })
so basically this?
Should be it, yeah.
alright let's test this spaghetti code out

crashes on use
`
may not be possible to add the card to the deck
guessing I need a area = something?
I'm not as experienced, so can't really say much else. ÂŻ_(ă)_/ÂŻ
i wonder if I just remove area from the function
I know Iâm late but do what Minecraft did and have some bricks shorter and flip it on the other side
maybe @frosty dock might know
maybe it's just not possible lol without the game freaking out
yeah base card dimensions are a bit weird for stuff like this
was thinking of doing this local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, nil, nil, nil, nil, nil, key = 'j_tcgyugi_PotGreed' })
because I noticed the vanilla game has something similar
69 = 3x23 usable pixels which sure isn't very divisible
What's the cost of the joker?
you don't need all of those nils btw
mm id say 10 or 5, not yet decided
since its a table
is there a work around
you can make an atlas a different size
might do weird things with other sprites like stickers though
usually doesn't matter too much with back textures though so eh
What I would do:
destroy all jokers and gain 7x the sell value of all OTHER jokers (does not include the midas bomb card)
10$ or more
what I have right now is from a template
SMODS.Atlas({
key = "yugioh",
path = "yugioh.png",
px = 71,
py = 95
})
mm maybe i can just give it 0 sell value
but ye your solution makes sense
I'm using the MoreSpeeds mod as an example and how come it's main function gets called when the vanilla settings tab is called?
My turn to need help:
Is there a mod or anything that ensures Imma get my card first round?
error seems to be from this center = nil
functions/common_events.lua:2256: attempt to index local 'center' (a nil value)
no () just {}
use debug++ and just ctrl+3 your card in the collection
danke
also comma after 95
doesn't even lead anywhere but to a end function in the vanilla game for the tutorial
ok
what if USE create_playing_card FUNCTION INSTEAD?
what are you doing?
scroll up and you'll see
check the lovely dump
I was looking at the code
what if I add center = G.P_CENTERS.c_base, G.hand, nil, nil, nil ?
that didn't work lol
still returns a nil vaule
if forced_key and not G.GAME.banned_keys[forced_key] then center = G.P_CENTERS[forced_key] _type = (center.set ~= 'Default' and center.set or _type)
so i guess I need some kinda force key?
use = function(self, card, area, copier) if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'j_tcgyugi_PotGreed' }) center = G.P_CENTERS.c_base _card:add_to_deck() G.deck.config.card_limit = G.deck.config.card_limit + 1 table.insert(G.playing_cards, _card) G.deck:emplace(_card) elseif G.STATE == G.STATES.SELECTING_HAND then G.FUNCS.draw_from_deck_to_hand(2) end
so maybe something like this?
that didn't work
is there a way to detect and edit a vanilla uibox as it spawns
I was able to set up what I want pretty easily with Lovely but idk if it'd be better without it
hook the function to create it? most of them are something like create_UIBox_xxxx_xxx
well I tried doing that but it isn't triggering and idk why
basically something like this
of course this looks bad but the general idea
I've tried a lot of random stuff but none of it matters because it's not even calling the function like ever
so lovely is now saying I have an unepxected symbol near =
which is this center = G.P_CENTERS.c_base, G.hand, nil, nil, G.C.SECONDARY_SET.Tarot
found the unpected symbol
but still center is returing is as nil
would "transforms into a legendary joker if a soul card is used" be too stupid an effect to be fun?
in more than 90% of games the joker would be totally useless, but we live for tha gamble
if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'j_tcgyugi_PotGreed' })
front = pseudorandom_element(G.P_CARDS, pseudoseed('cert_fr'))
center = G.P_CENTERS.c_base, G.hand, nil, nil, G.C.SECONDARY_SET.Tarot
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.deck:emplace(_card)
elseif G.STATE == G.STATES.SELECTING_HAND then
G.FUNCS.draw_from_deck_to_hand(2)
end```
best functioning code I can get is this
but always crashes with the center error when I hit use
maybe i'm m issing something else?
key = 'poltergeist_jk',
loc_txt = {
name = 'Poltergeist',
text = {
"{C:chips}+50{} chips per discard.",
"{C:red}+#1#{} discard each round."
}
},
rarity = 2,
atlas = 'Jokers',
pos = { x = 1, y = 0 },
cost = 4,
config = { extra = { chips = 50, discard_size = 1 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.discard_size } }
end,
add_to_deck = function(self, card, from_debuff)
-- Aumenta o tamanho do descarte
G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discard_size
end,
calculate = function(self, card, context)
if context.discard then
-- Adiciona chips por descarte
return {
chip_mod = card.ability.extra.chips,
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } },
card = context.other_card
}
end
end
}
But the game crashes...
[SMODS _ "src/utils.lua"]:985: attempt to perform arithimetic on global 'hand_chips' (a nil value)
the game crashes when i discard
(unrelated, but seems a bit OP? with Wasteful, you can get up to 250 chips, which is what Stuntman does, but without the hand size constraint)
(OP for Uncommon, I mean)
yh, I will change that, don't worry
(all g)
use = function(self, card, area, copier) if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then for k, v in ipairs("j_tcgyugi_PotGreed") do if center.key ~= v and #SMODS.find_card(v) == 0 local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'j_tcgyugi_PotGreed' }) _card:add_to_deck() G.deck.config.card_limit = G.deck.config.card_limit + 1 table.insert(G.playing_cards, _card) G.deck:emplace(_card) then elseif G.STATE == G.STATES.SELECTING_HAND then G.FUNCS.draw_from_deck_to_hand(2) end end,
my last duck tape solution
before I give up
you cant call ipairs on a string
I still need help y'all pleaseee
what can I do to give center a value so it'll stop crashing
well I ave up and tried making it it's own function
for k, v in ipairs("j_tcgyugi_PotGreed") do
if center.key ~= v and #SMODS.find_card(v) == 0 then
return
end
end
local _card = SMODS.create_card({ set = 'Tarot', area = G.deck, key = 'j_tcgyugi_PotGreed' })
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.deck:emplace(_card)
end```
not sure if it's returning the same error or not but nothing mentions center anywhere
any suggestions to try before I give up for the day
how does one render multilayer cards like Soul?
I give I guess I'll just make it a consumeable
that would be wouldn't it?
local _card = SMODS.create_card({ set = 'Tarot', area = G.consumeables, key = 'j_tcgyugi_PotGreed' })
and i'm still getting the center nill issue?
key = 'PotGreed', --joker key
set = 'Tarot',
loc_txt = { -- local text
name = 'Pot Of Greed',
text = {
'Draw 2 cards from your Deck.'
},
},
atlas = 'TCGyugioh', --atlas' key
cost = 10, --cost
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
pools = { TCG_Yugioh = true },
pos = {x = 0, y = 0}, --position in atlas, starts at 0, scales by the atlas' card size (px and py): {x = 1, y = 0} would mean the sprite is 71 pixels to the right
loc_vars = function(self, info_queue, center)
return {vars = {2}}
end,
config = {
extra = {
card_limit = 3 --configurable value
}
},
can_use = function(self, card)
if G.GAME.facing_blind then
return true
elseif G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
return true
else
return false
end
end,
use = function(self, card, area, copier)
if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
local _card = SMODS.create_card({ set = 'Tarot', area = G.consumeables, key = 'j_tcgyugi_PotGreed' })
elseif G.STATE == G.STATES.SELECTING_HAND then
G.FUNCS.draw_from_deck_to_hand(2)
end
end,
})```
If your card is a tarot why did you use j_ in the key? It should be c_
how do i make this not freeze my game
MY FUCKING GOD THAT WAS IT

ONE FUCKING CHARACTER TYPO
function Card:add_speech_bubble(text_key, align, loc_vars, extra)
if self.children.speech_bubble then self.children.speech_bubble:remove() end
self.config.speech_bubble_align = {align=align or 'bm', offset = {x=0,y=0},parent = self}
self.children.speech_bubble =
UIBox{
definition = G.UIDEF.vic_speech_bubble(text_key, loc_vars, extra),
config = self.config.speech_bubble_align
}
self.children.speech_bubble.states.hover.can = false
self.children.speech_bubble.states.click.can = false
self.children.speech_bubble:set_role{
role_type = 'Minor',
xy_bond = 'Weak',
r_bond = 'Strong',
major = self,
}
self.children.speech_bubble.states.visible = false
end```
any idea why this keeps giving me this error?
little buggy but it worked
just the funtion for drawing doesn't seem to work yet
elseif G.STATE == G.STATES.SELECTING_HAND then
G.FUNCS.draw_from_deck_to_hand(2)
guess I need a differtent state
The card has no field called children
IT WORKS!
yes im aware of that but other jokers that use this exact code also dont seem to have a field called children
again thank you
I would be tearing my hair out for weeks figuring this shit out
Lol nw
You need some exit condition in your recursive function. As it is, if G.RETURNLOCALIZATION is false, you will continue to call waitReturnLoc forever
yes, i want to only return the localization if G.RETURNLOCALIZATION, but i think that if i were to exit, i couldnt catch the G.RETURNLOCALIZATION
Can't speak to those other instances without further context, but if you ever try to access a field belonging to another field that doesn't existing, you'll get that error. You should be able to resolve it by having a check like if not self.children then self.children = {} end
As it is, your function won't "catch" anything because no other code will run while your function loops infinitely. If you want something that will wait in the background until G.RETURNLOCALIZATION is true, check out https://github.com/Steamodded/smods/wiki/Guide-â-Event-Manager
but i need to return something, and i cant return something in an event
how do i make it so a certain joker can appear multiple times in the shop?
like showman for just itself
showman can appear twice if u have one tho
Define the in_pool(self, args) -> bool, { allow_duplicates = bool } method for your joker and set allow_duplicates to true
thank you!
What are you using the return value for?
idk, my code is all messed up
We've all been there
But if you don't know what you want the method to be doing, it's hard to help
How exactly does the sticker argument for the SMODS.create_card function works ?
Currently trying to add an eternal sticker to a joker, but trying to find usage examples of the create_card and add_card function is quite hard
this says the exctinct at the top of the joker, and i need it to not do that until i do my events beforehand
I see. Any time a message like "extinct" pops up next to a joker, that's also an event that's been added to the events queue at some point. So if you put your own events on the queue before the event for the "extinct" message goes on the queue, your events should happen first
If it doesn't, the next step is to find where in the game's code that "extinct" message event is being put on the queue, and look at the details of the event itself. It may be set to be non-blockable or something like that. An option if that's the case is to patch a change to that event, set it to not block other events, and have it return false until your events have completed
for some reason I'm tempted to make a HTML DOM to Balatro UI converter even though I know it'd be so horrible
Hello I want to create my own mod for balatro, but I am new to creating mods and have never done anything like this, I do know how to code in a bunch of languages but I'm not sure how to get started creating a mod.
i think i might have to patch a patch...
thank you
yw
Remove that from the return value and manually create the eval event instead. Then you can choose exactly when it displays
What exactly are you trying to do?
please som1 help đ
You deleted your last message. What do you need help with?
SMODS.Joker {
key = 'poltergeist_jk',
loc_txt = {
name = 'Poltergeist',
text = {
"Gain {C:chips}50{} chips per remaining discard."
}
},
rarity = 2,
atlas = 'Jokers',
pos = { x = 1, y = 0 },
cost = 5,
config = { extra = { chip_mod = 50 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chip_mod } }
end,
calculate = function(self, card, context)
if context.joker_main then
local remaining_discards = G.GAME.round_resets.discards or 0
local chips_awarded = remaining_discards * card.ability.extra.chip_mod
-- If remaining discards are 0, chips_awarded will be 0
if chips_awarded > 0 then
return {
chip_mod = chips_awarded,
message = localize { type = 'variable', key = 'a_chips', vars = { chips_awarded } },
card = card
}
end
end
end
}
I have this issue and i cannot figure it out. I tried AI too... Nothing. It just keeps giving the same amount of chips
first mod btw so idk alot of the libary and etc
idk if I should update the code every time i discard, so it checks every discard
Youâre using the round reset value to get discards
Rather than the current amount of discards
that's the only mod I found that uses discards, and it's like that
idk how to do it otherwise
not like this either lmao
just a question, I'm getting a grey screencrash when loading balatro with cryptic, can anyone help?
what variable would that be tho?
A glance at Banner in the original game shows it uses G.GAME.current_round.discards_left
I have NO IDEA how to check the games code... I already unziped tho
but thanks
What operating system are you using?
w11
Gotcha, I'm on mac so I won't be any help with that
Although there's an easier way to check the source code, actually. If you go to the folder where you installed lovely, inside there should be a folder called dump. That's where it puts all of the game files after they've been patched. It's actually a bit better than looking at the original game files since SMODS sometimes changes a lot of the source code
danke
How can I change the names of hands? Like in the run info menu
New to modding but I have the source code open.
any clue why this may not be working?
it it supposed to destroy all chemical 7 jokers if you own 3 and give you the money
it does exactly nothing
is that from LBAL?
yessss
nice
seeing this, can I just edit this and it will change in the run info?
Well you should fix some of the indentation, but my guess is that the v.ability.name doesn't work as you expect? Just guessing here
Off the bat, you can replace your logic for finding all your chemical7 jokers with SMODS.find_card(key)which will return all jokers matching the key you provide. It also adds some compatibility since another mod might have a joker named Chemical 7
But your joker
's key should be unique
ok great imma try that
Also, what function is this logic placed in?
like this?
if context.buying_card or context.joker_main then
well i do need to put the jokers in the chemical7 table to delete them later
how do i do that
with the find card function
see the docs on find_card here https://github.com/Steamodded/smods/wiki/Utility, but in short, it returns a table of all jokers matching the given key
Put it in add_to_deck(self, card, from_debuff) instead, which is called when you acquire the joker
Ok so just changing the name of the hands in self.handlist doesn't work as it doesn't display on the run info
Any thoughts?
these are localization strings
oh
Just use find_card to obtain your table of cards
So I'd find the hand names that would update in the en-us.lua file?
reimplemented the code, still does not work
G.localization.misc.poker_hands I believe
thanks
wait i found a typo
lemme try again
nope, still not working
SMODS.find_card(garv_chem7) will never == 3 because it's a table not a number
i fixed the #SMODS.find_card("garb_chem7") == 3 then not having the hashtag
ye that was the typo
fixed that
Also, your joker's id is probably j_garb_chem7
still doing nothing
oh ye that may be right
forgot i have to use the whole slug
still not working
updated code
i'm sorry but where would i find this đ
im finding a list called "hands" under a game:init_game_object function
Whatâs chosen_joker?
joker selected for deletion
But you never define it
it's defined in card.lua, hex also deletes jokers this way
and i have used it in other jokers
actually im not sure where its defined, but it is a base game function
i think i have found the issue, the function only activates after i buy a fourth joker, and it does not give the money
it also does not kill the fourth joker
seems like an easy fix, just change the necessary chem7s to two add a little bit of code which gives the money and then kills the third joker
the English loc strings would be in en-us.lua
tysm
ok, another issue, the killing works, but it can't give the money because the joker has been destroyed
no wait that's an easy fix.
alright so i've found myself the massive list file under smods, just unsure what to add in once i add poker_hands={}, and the same for the descriptions, not that seasoned on lua or balatro modding. doc didnt have the syntax for everything
it was not, in fact, an easy fix.
Nevermind, I've figured it out.
ease_dollars(your_dollar_amount_here) to earn money
oh, so it was an easy fix
ok im just dumb
lol
i was overcomplicating things by having the money as a remove from deck return value
WORKS PERFECTLY NOW
So I just had an insane idea
I found a nes emulator written in Lua+love
Hear me out a joker card that forces you to play smb1

Or a boss battle
Isnât this already a thing
Canât remember if it was ported from Balamod to Steamodded or not.
roblox is also written in lua...
already exists
getting this error upon launch, i havent edited utils.lua at all
engine is cpp
thus if you wanted to interface with it (which you couldnt even realistically do because hyperion) youd use cpp
which you can do by writing a DLL in cpp and linking that via luajit ffi (where all the lua-available functions are using extern "C")
so honestly just bypass hyperion easy as that..
although idk i stopped paying attention to roblox stuff ages ago
How do I get an enhanced card to destroy itself after the hand is finished calculating like glass cards? Since I can't return true like with Jokers, do I just need to come up with my own solution?
Hello ! how do I go about adding a singular legendary joker that can be obtainned through the soul card?
I was kidding bro đ
should i only say anything serious on a topic when someone else is also being serious about it or what
maybe u thought I was being serious about playing roblox in balatro
i didnt consider it because it didnt matter to me
than no
I think it sounds like a good idea
lmao
possibly. it's pretty common nowadays for tamper protection libs to run checksums against loaded dlls
robloxatro?
robalatro
bablox
too on the nose
ooh ooh what about a fornite collab called "fortlatro"
add miku from fortnite to balatro please
how do i stop my cards from echoing the screams of the damned? (warning: loud)
i wanted to send that as video, idk why its in that format
basically what i am asking is why does the message display on all cards held in hand and not just the joker
because your contexts are wrong
?
Each card gets evaluated at end of round
add context.main_eval
added this, it just doesn't trigger
Joker scoring guide recommends if context.end_of_round and not context.repetition and not context.individual
if context.end_of_round and context.main_eval
that specific joker scoring guide is not up to date with new calc
works perfectly
it works tho...
Never been clear on when new calc was introduced. Pretty sure I've been on a version of smods with new calc the whole time but idk
it does, but it's not the encouraged way to do things because it breaks easily if other mods mess with things
Jan 6th
yes
LMAOOO
it was loud indeed
Is there a way to tell if players are using the Plasma Deck? One of my jokers seems to be busted specifically with Plasma
is there any joker that verifies how many x cards are in the deck? Like:
it gains 0,10x mult per glass card in deck?
I need to take a look at the code...
ok this isnt written, it doesnt handle the buffer right?
yeah it doesn't
thanks
can someone help me pls
I want to make it so that my joker only scores when played hand is 4 cards, as of now the joker ads X4 every hand
if context.joker_main and #context.scoring_hand == 4 then
j_steel_joker= {order = 32, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Steel Joker", pos = {x=7,y=2}, set = "Joker", effect = "Steel Card Buff", cost_mult = 1.0, config = {extra = 0.2}, enhancement_gate = 'm_steel'},
that's all?
thank youuu
Alternatively, on same note of Steel Cards, my Anvil Joker checks for how many of them are in the full deck.
if a joker has rarity = 4 then it's guaranteed to eventually appear in a soul card?
That is Legendary rarity, yeah... unless the particular Joker is not set to appear by its' in_pool function.
is it too much to ask for a sample of the code? I just do NOT know how to check the game's code...
Unpack it with 7zip or something, then look for .lua files.
But the code for the actual Steel Joker is
if self.ability.name == "Steel Joker" then
self.ability.steel_tally = 0
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_steel then self.ability.steel_tally = self.ability.steel_tally+1 end
end
end
have it already
this, right? what is wawa and wawa2 
Notepad++ has "Search in Files" that you can use.
in_pool functions have a self and args as arguments. If the resulting function returns false, won't appear at all. If true, other checks have to pass.
just played a seeded run
first soul card gave me my modded joker
:D
how can I make it so that my mod has a custom icon ?
want to know too
SMODS.Atlas({key = "modicon", path = "iconthing.png", px = 32, py = 32}):register()
It worked for me
I belive register is just for 0.9.8 compat and shouldn't be used
oh I see, whats the correct way
just define multiple atlases
just remove the register part
no register
đ Removed on my end for next time I push to my mod repo.
It reminds me of that one paperback joker
Pestrica my beloved
I love that so much
I already knew the code for making custom joker designs just didn't know jack about scoring
Would you put this inside the SMODS.Joker for that joker?
this feels like your mod is in 0.9.8 compat mode
A part of it, I suppose? Here's my Anvil Joker though.
I forgor to make lovely mods not use the no prefix mod icon
Oh my god I was making it so messier
i have a very specific question!
is there a way to make a self-destructing joker wait before self-destructing?
yeah you shouldn't be using the SMODS.INIT
yes
Just do it raw.
oh so the function init makes it only work on old calc?
no its something from really old steamodded versions that theres still a bit of comaptibiltiy for but you shouldn't use
that explains lot
I wonder if in beta we just wipe the compat layer
hold on gotta change the code for another mod
return math.floor(allsteel/4)
why tho?
maybe only for mods with json metadata
thanks!
wait how long
I specifically want a full amount of sets of 4 Steel Cards.
oh ok
hey I removed the function and now the mod doesn't work?
a couple seconds? enough for a text box to be readable and a voice line to be audible
a few events can do that probably
you can delay events
how so?
how would i, for no reason at all, patch a smods patch?
smods patches load before normal priority patches so just put what the file looks like after smods patches it
NVM fixed it, i had a debug deck with the joker before the change and when continuing the run it was basically trying to get a joker that didn't exist, just had to make a new deck
where is SMODS.calculate_context?
smods/src/utils.lua
is there a way to activate add to deck in calculate
why would you want to do that
its a long story
long story shory scalae(cryptid) does not work in add_to_deck and only calculate
what does scalae do?
scale caling jokers by a degree polynomial
then why do you need add to dekc in calculate?
because the scaling happens when added to deck
is there an alternative for playing hand instead of just scoring?
context.full_hand I think
crash ; 3 ;
what for?
it only gives mult when there's 4 scoring cards
G.play.cards
not like a hand with 3 scoring cards and 1 non scoring card
where can I see example of jokers code in the base game?
how can I check how many glass cards are in the deck?
quick question! in text, what are the values E, S and s?
i assume S and s correspond to font size, but what about E?
ohhh true, maybe it adds some sort of glow to the text
i found it in another mod and was curious, thanks for the answer!
np
E is for effect
makes sense
can u help me at this tho?
just iterate through the deck and count them
with a for loop?
the thing is
does G.deck exist? or something like that
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_steel then self.ability.steel_tally = self.ability.steel_tally+1 end
end
end
that's the stone card code
you're going to have to get used to looking at code that already exists and adapting it

