#💻・modding-dev
1 messages · Page 162 of 1
I did the art for my first terrain card. I decided to design it to look like a photo. Thoughts?
volcano
I didn't wanna mention it 😭
no no, gald this got pointed out right away rather than it going unnoticed
this is what it always looked like 100%

Looks really nice in-game!
Sorry, I'm new to modding balatro, so pardon my noob questions here.
I'm working on a joker that can destroy other jokers. I looked at the code for Madness to see how it does it, but when I try that same code to select another joker to destroy, on occasion it'll destroy itself even with the Eternal sticker applied.
I want it to only choose from the jokers currently active and never itself. If there's no other joker to destroy (either by eternal sticker, or some other protection, or it's the only joker), then it does nothing.
hello I was wondering if anyone could tell me why its giving me an error? I would very much appreciate the help.
Failed to collect file data for Atlas Mode_ModernFoods suggests there was trouble finding your atlas info or .png file.
The atlas section for your mod file should look something like this:
SMODS.Atlas {
key = "Mode_ModernFoods",
path = "GoldFinger.png",
px = 71,
py = 95
}
key is your mod's folder name
my atlas folder looks exactly like this SMODS.Atlas {
key = "Mode_ModernFoods",
path = "GoldFinger.png",
px = 71,
py = 95
and after I changed multiple other things like name of name of the folder i was getting the same error
hey, where in the default code does it calculate what the tarot cards do? i wanna make like an anti strength tarot card but i cant find the code to reference
no, key is how the altas is referenced by other mod elements
my mistake
what context could i use to make this run once the joker is "acquired"? like when it's bought, spawned, or really just added to the hand in any way. the idea is that it'll double blind amounts once when it's bought, but with the current context it doubles blinds every single round lol
context.buying_card
unfortunately that would only work for buying in the shop, and there's a definite chance of getting the joker from judgement or other means
well then i would assume u would have to make a check to see if it activated
and then not activate it again
yeah, that's where my issue lies lol
prob in the extra config, idk im new here
i wasn't sure how to make it occur only once
it probably does have to do with a simple boolean but nothing was actually going into effect unfortunately
something like config = { extra = { activated = false } },
then once it runs set it to true
and bada bing bada boom
maybe im crazy but i think that would work
❤️
i tried that, for whatever reason it wasn working but maybe that's a skill issue on my part
error!
effect is 100% not the variable you want
it's probably key
(self.config.center.key)
(because it's not in ability because funny)
i think i'll either have to make a check from scratch, or if i'm lucky i just fucked up the syntax for the applied boolean when i tried it the first time
does anyone know were the default code for the tarot card is, or have a working example of one? im lost there only seems to be good documentation on adding jokers
-# read my mod
was this directed at me??
what are you actually doing here? like whats this fucntion
bumping this once before i head to bed if anyone has an idea
tysm
a hook to Card:generate_UIBox_ability_table()
hello does anyone know why when I try to start the game it gives me this error (Im trying to make a custom joker) [SMODS _ "src/game_object.lua"]:363: Failed to collect file data for Atlas Mode_ModernFoods
Ok making art was a fun break but its time to go back to the code trenches
how do card references work? when do i lose the pointer?
i just made my own function to help myself
works wonders
what do i use to set the id of a card?
selected_card.base.id = selected_card:get_id() - 1
this isnt crashing me but its not working either
use = function(self, card, area, copier)
local selected_card = G.hand.highlighted[1]
selected_card.id = selected_card:get_id() - 1
end,``` i feel like im doing something wrong
add_to_deck
as in context.add_to_deck?
no
or wait, would that be card.add_to_deck
its a separate function
ohhh
How do I access my mod config value?
i think SMODS.current_mod.config
So SMODS.current_mod.config['config name']?
config key i believe
do not count me on that i haven't touched anything related to config yet
SMODS.current_mod.config.farts also can work.
ive been digging around and can t seem to find how people make consumeables be added to consumables instead of being used right away from booster packs
How would I go about changing the sticker on my playing cards?
im 90% sure the code for the joker is wrong somewhere does anyone know what might be cyuasing problems?
Bad news: SMODS.current_mod.config won't work in patches.
is this new calc
check if smods.current is valid first maybe
like i would check cascadingly
SMODS -> SMODS.current_mod -> SMODS.current_mod.config
I think it's because the patched code is inside the main game files so there's no "current_mod" to speak of.
what do you mean by new calc?
SMODS.current_mod is only ever true when loading mods.
This is code outside of that
There are different versions of SMODS calculation code
You need to check for SMODS.Mods[<mod id>].config
whats the difference?
Not sure how much, but as far as I've heard it's plentiful.
new calc is newer and more up to date
And more efficient
I was using the example mod on github as a base but ive been looking and following all the guides so i would garner a guess and say new calc
yes
Good news: I've learned how to separate the text boxes.
Bad news: They are... a bit too separated.
I'll fix the error later but I got a sticker in the game. It doesn't do anything yet but the text is there.
This just looks wrong lmao
I just feel like the card is trying to do too much lol
this is how it feels working with CSS
TRUE LMAO
and also tailwindcss
:walcomebuck:

ok
i am adding trivia to the game
oh boy do you not like trivia
the capital city of Senegal is Dakar
Now it's separated correctly.
please add the rounded background back
Yep, workin on it
time to patch the entire source code

ok well then lemme write some trivia question as a test
hey I knew that
i bet you don't even know the capital city of
Namibia
(i just looked it up it is Windhoek)
There.
😌
That one I did not know 
I wonder if there's a point where you start using external APIs or libraries to generate your blind puzzles lol
I think I'm gonna make a separate mod to handle multi_text_boxes
there has to be a point right
Probably
istg minecraft modders will make their own library to make their mod
just to make people download two mods
smfh
im joking some libraries are in fact useful
the yung's api in question
terrablend
eh, I've had my issues with terrablend lol
No,
I do this because it can be compat with other mods if the authors choose to.
look i come from modding minecraft i had a bit of stigma for library mods
aka half the modpack consists of library mods
me trying to download the scrimblo bimblo modpack and having to download 23548139 libraries including poopshit library, teamsigma library, library library, mojangsucksihatemojang library, mr skibidi library...
(i have my own library mod)
(but it's mostly so that ppl can utilize the mechanics i make in their own mods and not depend on the content)
(idk if anyone will but it's open as an option)
I want to say that we should make like a single library for a bunch of convenient features that anyone can refer to, but I worry that it will just lead to this situation
there are 52 standard libraries
"let's make a singular library that everyone can reference to so we dont have so many libraries"
there are 53 standard libraries
guess what chat
in this case it is better they are incompatible
what the fuck
ODDITIES WOOOOO
i should add better art to my mod
i am terrible at art so i just look at things and draw
inside you there are two wolves
I give up for now. I will go to sleep knowing the thing that beat me was stickers
btw the letters in my mod are not actually stickers
every playing card comes with one
imagine actually making stickers
true
(none of my card modifiers are smods objects
ugh the stupid "save item from pack" code is broken again AUGHHHHH
Im trying to make a new card modifier and was told stickers is the best way to do it
is there a clean way to do this yet
The unicorn horn is fantastic
Potato potahto
but it's there
Narwhals are unicorns of the sea. Unicorn horn
i can make the stickers fine but the problem is idk how to put them on my playing cards
So currently my main issue is to make them having different width...
Looks much better
Welp, not what I was looking to do... 
bro turned himself into gold funniest econ ever
I got an even worse mess up coming right up:
Depleted!
I struggle to get consumables to destroy themselves cleanly
cleanest ive been able to do it, and it does it way too early, but the effect still does what it needs to
Hi, is there a way to make a custom Booster guaranteed to appear in the first shop with smods?
show code :>
name = "Hand of Midas",
key = "ancient_Midas",
set = "ancients",
atlas = "leapfrog",
cost = 4,
destroyed = false,
config = {extra = {remaining = 3, destroyed = false}},
pos = {x = 6, y = 0},
loc_txt = {
name = "Hand of Midas",
text ={
"Turns the next {C:attention}#1#{} scored cards into {C:attention}Gold Cards{}",
},
},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.remaining } }
end,
can_use = function(self,card)
return(false)
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if card.ability.extra.remaining >= 1 then
card.ability.extra.remaining = card.ability.extra.remaining - 1
context.other_card:set_ability(G.P_CENTERS.m_gold, nil, true)
return{
message = "Touched!",
card = context.other_card,
focus = card
}
end
if card.ability.extra.remaining <= 0 then
card:start_dissolve()
return{
focus = context.other_card,
card = context.other_card,
message = "Depleted!"
}
end
end
end
}```
Just put the destruction in context.after
ye
Or
Put it in a function in the return if you want it to deplete after the third change
func = function()
dissolve?
end
?
It would need to be in an event, but yes
oh eremel do you know if smods allows this or should I go with lovely patches (following buffoon pack)
That’s not a smods feature afaik
lovely patching it is then 🔨
damn so first shop will have 2 forced packs
fair point, I might have to add one more slot in the first one
I'm really proud of myself for figuring out how to add UI elements
literally feels like CSS
I had a specific case for this, so all I had to do to fix this is to not close the old pack iirc
this worked a treat thank you and john smods 😊
Are Suits stuck in the pool? Or is there a way of taking a custom one out and only allowing them in certain decks? I've tried adding the in_pool = false in side the suit constructor(? I'm a java dev, don't really know what to call it), but it doesn't seem to make a difference.
in_pool should be a function, not a bool
the suit is available and in deck when it returns true or isn't a function
okay, that makes sense. Thank you!
Thoughts on this held consumable? Too broken, too specific, too underwhelming?
i want to generate a card from a small pool of jokers (like "any joker in my mod") but, when the joker is randomly added, still have it generate at normal rarities (i.e. still usually generate a common card and such). is this something that's easily doable with create_card and normal stuff and i just need to understand something i'm not currently understanding, or is this gonna be An Issue
hee hee hoo hoo
twice the goodies for you
how would i count for enhancements in the deck? like with steel joker, i tried to look for how steel/stone jokers is set up in src but it's specifically set for steel_tally/stone_tally so how else would i count for a modded enhancement
imagine a run with 6s and perkeo that would be 🤑
stone_tally is counted in the update function
Example with stone joker
if self.ability.name == "Stone Joker" then
self.ability.stone_tally = 0
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_stone then self.ability.stone_tally = self.ability.stone_tally+1 end
end
end
Perkeo makes most consumable broken anyway
true it would be a fun run though
Who needs Cryptid rigged when you got infinite bread
When the bread turns solid after 1 picosecond 😔
when the astro isn't
Me when the first card of scoring in a modded null card 
if it's aikoyori's letter deck it'll still upgrade the suit 
but i do check SMODS.has_no_suit so when they get on fixing that, it'll work properly lol
(and suit levels will stop applying to them also lol)
What if you made a suit level up specificaly for no suits? 🤔
is there a way to check if someone has 2 or more cards in their hand selected, similar to how some of the tarot cards do
is this for a consumable? there's config.max_highlighted that I think will take care of that for you
yeah, it is, and thanks!
sorry, im being stupid and cant figure it out but how would i then count something to update, would it be the calculate function and if so what sort of context? i have a enhancement called m_blr_wisp that i'm trying to count here
I gave you the name of the function
https://github.com/Steamodded/smods/wiki/SMODS.Joker#api-methods in case you need details
What's the ability.set for Seals, Stickers and Editions, Enhancements is "Enhanced"
Oh it's just "Seal" and "Edition" respectively, not sure for Stickers
why didnt thunk use the config.card_limit 😭
card counting in update 😭
woo hardcoding
No one is immune to "if it works it works"
what would you have done it as sorry its just me being stupid again as usual 😁
none of those define a card's ability
Do it in loc vars and calculate, there’s no need to count them every frame
ok got it to work perfectly thanks
actually got more done than I thought id get working, granted most a simple
artwork is not my thing, so that will come later
relatable
Whats the real difference between an enhancement and an edition, like would there be a reason to pick one over the other?
Curse, like in gungeon, big blinds have a chance to be boss blinds, each point of curse gives x0.2 mult(min 1)
Max 9 increases chance of cards being cursed.
Cursed cards cannot be destroyed and score half their chip value
Cursed cards have a 1 in 10 chance of giving 10$ when scored
And which would best fit a mechanic like this
sounds like an enhancement
they're just different ways to modify a card, there's not really a difference in what they do
How do I make my config toggleable in-game?
I see
I'll go with enhancement for this one
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
func = function()
local new_rank = math.ceil(playCard.base.id / 2)
local suit_prefix = string.sub(playCard.base.suit, 1, 1)..'_'
local rank_suffix = new_rank < 10 and tostring(new_rank)
or new_rank == 10 and 'T'
or new_rank == 11 and 'J'
or new_rank == 12 and 'Q'
or new_rank == 13 and 'K'
or 'A'
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local new_card = copy_card(playCard, nil, nil, G.playing_card)
new_card:set_base(G.P_CARDS[suit_prefix..rank_suffix])
G.deck.config.card_limit = G.deck.config.card_limit + 1
for i = 1, 2 do
table.insert(G.playing_cards, new_card)
G.hand:emplace(new_card)
new_card.states.visible = nil
new_card:start_materialize()
end
return true
end
}))
Trying to make a Joker that divides a Pair into two clones for each card but with their ranks halved, but when the clones get made, some ghost cards get created, and the cloned cards have this particle stuck to them. If I played the cloned cards they just go back to my hand flipped.
Any insights?
Touched! 😭
its midas touch 😛
the midas touch's allegations going crazy

this one's more of just a general lua question but im making mods without knowing lua 😁
local function getMult(enhanceType)
local enhanceCount = 0
for k, v in pairs(G.playing_cards) do
if v.config.center == enhanceType then enhanceCount = enhanceCount+1 end
end
return enhanceCount
end
could i not just pass center through enhancetype? as there's other jokers with similar effects based on x cards in deck for different enhancements just thought it would be better not to hard code the count for each one and just do something like this getMult(G.P_CENTERS.m_blr_wisp)
hey every time i put the Deck builder mod into my modfolder it shows this when i start balatro
Bild
already did a fresh install and reinstalled smods and talisman
and lovley installed itself
oh and i put the versions.dll in the game directory of Balatro
i rly have no clue what else to do
this deck creator is outdated and doesn't work on current steamodded
there's a fork that should be updated
this one, i think https://github.com/Kenidur1561/Balatro-DeckCreator
this isn't an old calc vs. new calc problem
deck creator is way older
https://canary.discord.com/channels/1116389027176787968/1325492282421547018 I'm under the impression from this thread that the fork I sent above should work though?
nope
i think it is a new error code
apparently you need this version? idk
now it works
thank u so much
but how did u know/find the version i need
teach me sempai
i knew off the top of my head that the fork existed, i just didn't also check the thread at first to see that there's a different version posted there (which is ahead of the one on github)
this post in the modding forum https://canary.discord.com/channels/1116389027176787968/1325492282421547018
a fork is just someone else's modified version of the original code
what's the "correct way" to use probabilities (in a way that is compatible with "Oops all 6s" for instance)
G.GAME.probabilities.normal
it's the "1" in "1 in X chance" effects that gets modified by oops
Alright, thanks a lot mate!
👀
fucked up and evil
here's the api you are looking for
https://www.grac.or.kr/WebService/GameSearchSvc.asmx/game?op=game&gametitle=balatro&display=10&pageno=1
if the rating isn't 19+, then mult x100
If I want to set the reroll cost to 1 with a joker, how can I do that without impacting the reroll cost when the joker is sold?
what's the best way to delete a card in hand , (the hanged man style, with the animation that come with it) I can't find a way to use remove_card() , and remove() does work but without the animation
start_dissolve
is it the function that remove it or that plays the anim ? (like, should it be used with remove() or should it be used alone for the described purpose ?)
it does both
okay, just making sure ; thanks man , appreciate it
works like a charm , thanks again
is there a way to replace jimbo's sprite? i don't want him to appear in my shops but i keep on seeing him everywhere
What's the proper way to have a joker show a message? Like when it destroys a card, or adds to mult or something? card_eval_status_text keeps giving me an error
just return the message in your calculate function
thought to myself 'oh why can't i find canio in the code?' 😭
card layer api when /j
It’s been something I’ve toyed with
shoutout to shadow_parrallax
everything is british
gluttenous_joker
?
a lot of things are just wrong
to make it worse, it's referred to as parallax in other places
arent there even some spots where consumable is used in vanilla code
negative_consumable apparently
Do we have a start of shop context?
me when i mod an entire card layer in in 3 hours because i thought it'd be funny
(still need to make them all have unique effects rn they're all just X3 Mult lul)
No
Is there a reasonable alternative?
It depends what your effect is
I'm just looking to set the G.GAME.round_resets.temp_reroll_cost to zero when the shop starts
making a joker that just gives 3$ every time a card is added or destroyed, it works normally but when using hanged man it only procs once from the 2 deleted cards how would i fix that
so, that's just one message per calculate?
What If I want it to say multiple messages like making decisions in a multi-step if statement?
also very much possible as of better calc
return {
message = "Hee Hee!",
extra = {
message = "Hoo hoo!",
},
}
this can be repeated ad infinitum
linked list mentioned?
i'm not mentioning whatever the hell a linking list is and you can't make me
who up linking they list
-# help now i have to code 12 card upgrades
don't you link my list

how to disable jokers in custom blinds?
bumping on this one rq
Is this a proper way to make description for cards?
it seems like it doesnt work
mb I did something wrong with prefix/key?
need help
nvm
ok :D
that's in locale my bad
yeah
Basically what I understood is that its more cleaner to use a separate file for all descp instead of writing loc_txt for each joker/card in main.lua
and it has better functionality
ok this may be dumb but try rename the locale file to en-us.lua
It worked!
:D
Random question. If Madness doesn't have any joker available to destroy that's active (eternal, to slice, etc.), why is it still gaining x0.5 per small/big blind? Is it destroying a joker in_pool?
Madness is just programmed to gain Xmult regardless of joker destruction
in the text it is written as such
ah, makes sense
it doesn't need to destroy a joker to gain mult
madness is worded roughly as "gain mult and destroy a joker", whereas dagger is the other way around
the implicit rule is that only the former is a condition for the latter
implies that the second event is reliant on the first event
with dagger, if it can't complete destruction then there is no sell value to add if that makes sense
gaining .5 xmult can just happen
yeah, it's that and that gets it. I thought the effect worked something like "Destroys 1 Joker when Small/Big Blind selected. Gains x0.5 when a joker is destroyed". The way it's currently written makes more sense.
For your own effects that could be a gray area with this, something like 'Do A to do B' probably shows most concisely that B happening relies on A's completion
'Do A and do B' just means they both happen (or at least try and happen)
Unless the specifics of B's text already imply that A needed to happen, like dagger
How would one go about learning how to code mods from the ground up?
for one, you should learn lua as a coding language first
and when you are familiarized with it, you can start checking out the steamodded wiki, balatro's source code, example mods, and such to understand what to do next
https://github.com/Steamodded/smods/wiki/Your-First-Mod
thanks
np, feel free to post your problems here when you find yourself troubled too, there should be a lot of people willing to help you
i know this is like super late but how would i use this in the lua file? I wanna make something similar to 'The Wheel' but for a Joker, and I saw this, but idk how to use it >_<
The code is for a lovely patch (.toml file)
To use the new context, you program just like for any other context
although I do recommend changing the name of the context
i know, i already put the patch in lovely, but how would i then use the new context in a mod?
Like this
how would i do this then
cause i dont wanna get it confused
i didn't do that, i picked up lua by writing my mod :p
this probably only worked because i already had a basic understanding of general coding principles
i had like, 2 years of experience coding on roblox before trying out balatro modding 😭
luau and lua r pretty much identical so it didnt take long for me to actually make my first functional mod lol
is setting a random joker's edition to negative just :set_edition('e_negative', true) ?
i've been trying to make one where when defeating a boss blind it has a 1 in 2 chance of giving negative to a random joker but idk what im doing wrong in making it
yep
just change vic to your mod's prefix
card:[that]
do you know what i'm doing wrong in here? i thought i could just take the logic for madness and just make it negative instead of destroying the card
if context.end_of_round and G.GAME.blind.boss and not context.blueprint then
if pseudorandom('machina') < G.GAME.probabilities.normal / card.ability.extra.odds then
local negativePool = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= self and G.jokers.cards[i].eligible_editionless_jokers then negativePool[#negativePool+1] = G.jokers.cards[i] end
end
local negativePick = #negativePool > 0 and pseudorandom_element(negativePool, pseudoseed('machina')) or nil
return {
negativePick:set_edition('e_negative', true)
}
hm, wait a bit, let me try
if i want to define a suit in a different way would i do G.suits = or G.GAME.suits
when the game is going to retrigger something, it figures out how many times it will retrigger it before it does anything else related to scoring that card
so it looks at all possible effects (jokers and seals by default) that can grant a playing card retriggers, and tallies them all up, then gets to scoring
Thanks! But what "context.individual = true" is responsible for?
indicating the timing of the context, individual means "on a playing card"
no wait thats not right cards in hand get individual too dont they
it says it goes through all scoring cards and held in hand cards
yeah that makes sense
you can check context.individual and context.cardarea == G.play for played cards, or context.individual and context.cardarea == G.hand for held in hand
if you want to narrow it down
thanks!
that makes sense
Can 'context.other_card = [CARD]' used for specific suits?
and if there are multiple, should it look like context.other_card = Spade, Diamond or I have to type out each individually
?
so context.other_card (while we're talking about context.individual anyway) is going to be the playing card actually being scored
not the name of it or anything, the whole card object
you can check whatever values you want thereof, i believe there's a card:is_suit function?
yeah
this wording
yea there is
ok, sorry for being a bit late since i was a bit confused over something
here, i think the code should be like this
so that would look like context.other_card:is_suit("Diamonds") or whichever
if context.end_of_round and context.cardarea == G.jokers and G.GAME.blind.boss and not context.blueprint then
local pool = {}
for i,v in pairs(G.jokers.cards) do
if not v:get_edition() and v ~= self then
pool[#pool + 1] = v
end
end
local randomJokerChosen = pool[math.random(1,#pool)]
if randomJokerChosen then
randomJokerChosen:set_edition('e_negative',true)
end
end
i'll give that a try, thanks
here is how i use it
what is main_scoring?
main_scoring is the context for when a playing card scores itself
it's used for enhancements and other card upgrade effects
so I cant use scoring_hand for this?
context.scoring_hand isn't a timing context
it'll just have all the cards that are actively being scored (i.e. are part of the scoring hand)
there's two kinds of contexts
and it's annoying that there's not really much obvious difference
an array of them, right
but some are meant for timing and some are just ways to get information about things happening at the moment (i.e. context)
yep its an array
or table or whatever lua's calling them this month
i'll tell you when you're older
context.other_card is just that; the other card.
it's the card your card is being "compared" or "checked" against; usually meaning it's the impetus for the context being calculated
oh, real quick
So one is for "when" and the other is for "what"
whats the difference between "self" and "card"?
i had this assumption thinking "self" means the whatever is using the calculation, but turned out it was "card"
i havent figured out wtf is self yet 💀
bump^
im trying to disable every joker in hand
so you see, words in programming languages only mean things when they're told to
the card itself?
if you're looking at base balatro code, or writing a function that's an extension of the Card object (or other vanilla objects) you'll likely use self more, since the notation object:function() is the same as object.function(self)
so how does card:is_suit work with custom suits
OHH
I understand it now
game looks at the card being scored and compare it to what I typed in
sounds logical
but for smods code, you'll usually write functions with (self, card, ...) in the function definition
this is because the self here isn't a card
it's the center; the SMODS object you're defining
self is "this object"
-scrolls up to see what I missed- she link on my list till I incorrect buzzer noise
the tricky part is keeping track of what object "this" is
no it's just a variable name with this special property
so its a name, gotcha
if you're working within a SMODS object, you probably don't want to change self
not because you can't, but because it probably means you're doing something wrong
i think it works the same as verdant leaf
So if I need to check if poker hand contains X, I use scoring_hand? Lets say I want Joker to check if poker hand contains a card of each suit, what do I type in? Should I add: context.scoring_hand and context.other_card:is_suit("Diamonds") and context.other_card:is_suit("Spades")... etc. ?
can i see where you are using card:is_suit
there's not much here yet
this pretty much works but it can trigger itself which i thought this would prevent right?
oh, you should change the "self" to "card"
i just noticed that, sorry
awesome thank you
no probs :D
card:is_suit goes in a if statment
just a small thing, but you dont really need to use "context.joker_main == true", you can just use "context.joker_main" and it means pretty much the same thing
Does anyone know how you would write code to put a sticker on a playing card?
Hi guys i wanted to try to make a mod but how do i do that ? I know nothing about balatro modding
stickers are read as abbilities if i remember correctly
no, context.other_card will have no meaning here in context.joker_main. you could instead iterate over context.scoring_hand, and count how many of each suit appear, then check it against whatever parameters you wish. vanilla's flower pot may be helpful to you to look at; all vanilla joker code is in card.lua in the balatro executable (which can be opened with 7zip :3 )
Are
context.other_card:is_suit("Diamonds")
and
card:is_suit("Diamonds")
the same thing?
here card is your joker, so i imagine you probably dont want to do that
context.other_card would mean the playing card being scored if you were in context.individual, but this check appears to be in context.joker_main
where i forget if context.other_card even exists but if it does it's probably just your joker again
while technically both of these are valid statements to make, it's pretty nonsensical to ask what the suit of a joker is
context.scoring_hand has what you need; loop over it with ipairs or something idk
im trying this but cant figure out how to use it
So this part of the code (from Flower Pot) checks for wild cards in played hand and counts if hand has certain suits in it (at the end)
i meant to reply to this
^
mmm i never actually coded a blind before, let me try to make one with that function (probably will take a decent amount of time since im relatively new, dont have high expectations 💀)
hmmmm
@dreamy thunder how do you spawn a blind using debug menu?
using 3
huh, thought it would be different, lemme try
i hate blinds
its probably this tbh
but the problem here is
i dont know how to get a blind to function to begin with
so i cant even test it out
:sku
...like, what is this?
im just as confused as you are
don't set_debuff manually
alright sooo its actually this
the only thing left here is to figure out if theres a way to see whether "card" is a joker
uhhh
is there a way to do that?
card.ability.set == 'Joker'
thanks!
recalc_debuff = function(self,card,from_blind)
if card.ability.set == 'Joker' then return true end
end
how hard would it be to combine hands and discards into one as an ability for a deck?
i remember a mod being able to do that, so its plausible, though i forgot which 😭
something like, if you have no discard left then it will use your hand to discard, vice versa
can I use set_ability with scoring_hand?
how could I apply set ability to all scoring cards?
i dont think so, no
for i=1, #context.scoring_hand do
blah blah blah i forgot the rest 😭
for i,v in ipairs(somethingscoringhand) do
v:setability(yadayada)
i think
i v ipairs is so so so good
for this?
mhm, got it
flower pot 
yeah
how to actually call smods.change_base() ? like, putting a str for a suit doesn't work so I guess it's a specific type but after looking for 30min I still don't know what to put instead
oh lol
i never used context.scoring_hand so i was a bit worried context.other_card wouldnt work
so im kinda typing out your entire code here for me to try out first 💀
one problem tho
Midas Mask turns cards into gold before they start giving score
but my code makes it so that card becomes Wild right when it scores
It basically makes no difference but yes
for consisntency ig
yeah, got it, let me try out smt
can you show the full code
i have a specific thing in mind that i want to clarify, i specifically want it to like change the ui of the hands/discards to be one box that has one counter that counts for both discards and hands
(and then everything that gives one or the other adds it to that one mixed counter)
it would probably be best to keep them separate internally and then just add them for the hud
elseif random_effect == 3 then
-- Remplace des cartes
local random_num = math.random(1, #G.hand.cards)
local SuitChosen = PickRandomRank()
local NumberChosen = PickRandomCard()
for i = 1, random_num, 1 do
if #G.hand.cards > 0 then
local random_card = math.random(1, #G.hand.cards)
--G.hand.cards[random_card]:start_dissolve()
SMODS.change_base(G.hand.cards[random_card], SMODS.Suits[math.random(1, #SMODS.Ranks)], SMODS.Ranks[math.random(1, #SMODS.Ranks)])
end
end
return {
message = "CAr..Card ?replac.Z.?e "
}
end
I just don't really know how to get a table for every suits in the game , saw something similar to that in the code but it doesn't work unfortunately (also don't mind the message, it's intentional lmao)
Im trying to put stickers on playing cards through a consumable but it crashes everytime
just whatever achieves the intended effect
use suit keys (ex. "Clubs")
it doesn't actually work , that's the thing
also tables like SMODS.Suits aren't indexed numerically
alrighttt, so
you want to change the "context.scoring_hand" in the first if statement to "context.before"
and it should work
ah, and change your "context.cardarea == G.play" to "context.cardarea == G.jokers" too
yeah I figured, I created a table with the suits string and tried to access one randomly and still nothing , I figured it doesn't accept strings for some reason
how would i make it so that a joker has a chance to flip cards over and keep them flipped over?
like keep them flipped between rounds?
can you show code for that?
:flip(), i dont think they will be flipped back if you dont flip them again anyways
set_ability is for enhancements
simply "local suits = { 'Hearts', 'Diamonds','Spades','Clubs'}" at the top of the file, and accessed it like suits[math.random( 1, #suits)]
just for the singular round, i'm trying to make it so that a Joker gives good X mult but the downside is that whenever you draw cards they have a chance to be flipped over
flip()
what's with the quotation marks?
I did that on accident last night
do you know how I would set stickers?
mistake while sending the message
set_STICKER_NAME(true)
😭
wha
thats odd, whats the error?
midas mask works under the same context too, so its weird how yours just crash
like this?
oh, you gotta change the "context.other_card:set_ability(G.P_CENTERS.m_wild,nil,true)" part this time
Sticker:apply(card, true):?
for i,v in ipairs(context.scoring_hand) do
v:set_ability(G.P_CENTERS.m_wild,nil,true)
end
replace it with that
nvm I fixed it for some reason it works if I use a function , do you just know by any chance if there's a way to flip the cards after modifying them ?
remove the "and context.individual" if it still crashes, though im (kinda?) sure it wont affect anything
look at how strength animates
i say strength specifically because its easiest to ctrl-f
yeah I figured it would be easier to look into strength specifically
thanks for the help btw !
I works now!
thanks <3
nice :D
for the little tooltips on the side that say related cards (for example if a card creates a specific Tarot card it'll say what that Tarot card does) is that automatic or do we have to do that ourselves?
you have to do it manually
info_queue[#info_queue+1] = YOUR_CENTER_HERE
within the loc_vars function
ah gotcha
is there a template for creating joker cards
check the steamodded github page, there's a lot of documentation on how to start making jokers, and there are some example jokers that you can take code from if needed
i meant art wise
i swear there was a thread in this discord
oh, i used the atlas from the example jokers for the sizing
wow that's really useful, wish i saw that before doing two joker arts already lmao
Ok I give up on stickers for now, not enough people work with them so using them makes my life way harder. Im just gonna make these editions for now and once I have a better idea of how things work in lua I'll try and see if I can make stickers work again
https://media.discordapp.net/attachments/905648601156423691/1335868379604717619/image.png?ex=67a264a0&is=67a11320&hm=30ee514913f395ac23fcdb6042f8db6190bec6188f8b55eb69b18f2463d10261& i wondered why the background on the left one looked wrong, it's too dark
its great
had an idea for a joker
note the word joker on the edges
Try adding your mod prefix to the key in play_sound()
https://streamable.com/ds4qp4 these two jokers in action together are a stone generator
no idea yet
x e mult
https://media.discordapp.net/attachments/905648601156423691/1335559093175320628/Screenshot_2025-02-02_022718.png?ex=67a1ed55&is=67a09bd5&hm=e5aa96c28b9d97f34df182857ad4a2237e9ffb5fd0147c75f4e1e297d192c37c& function of the globe one, it might be a little bit busted
A little?
okay a lot busted
i might nerf it at some point
it's only cards played not cards in hand but still, very unbalanced and that's the point
i've updated it to state that since i took that screenshot
didn't help
unfortunately
how would i have a deck modify the starting deck like checkered and ancient do?
specifically i want it to do this
how does one mess up the saving system, my game isn't saving anymore welp
debugplus save states are broken too
ok it was this
(self, args)
any thoughts?
https://github.com/Aurelius7309/SixSuits/blob/master/SixSuits.lua#L242 check this out as an example
Contribute to Aurelius7309/SixSuits development by creating an account on GitHub.
cool
that fixed it, ty
G.GAME.starting_deck_size = #G.playing_cards is important to make sure erosion works properly
what to use to edit the discard ammount?
<@&1133519078540185692>
oh well
ease_discard
how do you destroy unscored cards? context.destroying_card doesn't seem to interact with them at all
thanks
nothing interacts with unscored cards
well that's inconvenient :T
doesn't sound like it adds a lot of overhead
so long as it doesn't interfere with existing calculation, i don't think it'd need to be optional
but sounds nice to have in smods
on another note... https://github.com/Steamodded/smods/pull/428#discussion_r1936446211 is this something that old skins do? if not i think i can just get away with checking for outdated
I'm not sure what any old skin stuff does tbh
fair. i assume you were referring to new skins that use hc and lc palette keys then?
thanks , I've kinda fixed my issue but this might be cleaner, I'll try it
yes
then I'll just make it a fallback i guess
the other case should cover it if it's not an elseif
though I'm not sure on the need to use hc and lc on custom skins
i mean it's bad to have them be magic values
is it possible to make cards with multiple enhancements?
steamodded allows cards to act as though they had multiple enhancements, added by means of a joker (i guess we could support other sources of extra enhancements, but as of now we don't)
aww shit here we go again
2 in 15 mins!
Originally I was gonna use stickers to function as a new enhancement without interfering with the original ones but I couldn't figure out how to actually get them onto my playing cards

How would you destroy a card after playing but before scoring? Just remove it from scoring_hand and G.play.cards?
🤔
ewwwww
yeah it's terrible
medium contrast 🔥
how does blueprint decide whats compatible
blueprint_compat on the center
except that's just how it decides if it should display something as compatible
yeah thats what they asked
the actual compat happens in code
follow up, can i modify that? id like my card to not work with all stuff blueprint does and also not work with blueprint
got me a better way?
I'll have a think
idk what u mean by this
do we definitely want the toggle rather than a config value on the actual palette?
ok
you set blueprint_compat = false on your joker and check not context.blueprint in your calculation
this is just for cards that aren't replaced by the deck skin
yeah that's what I mean, we could have a config that controls the lc/hc-ness of the unchanged cards
hmm, how would the first line change anything?
like it you're using a hc skin, why would you ever want lc other cards
like, it seems like 1 line to control all of that is a bit weird
what if i changed my card to copy the right most card just as an example
#1209564621644505158 message i just don't want it to have to be jank like this that everyone won't do in their own skins
as i already said, it only controls the display
blueprint_compat doesn't control "all of that", it just controls the part where blueprint says it's compatible
context.blueprint means "i am currently a blueprint copying this card", so you put not context.blueprint in your calculation function in appropriate places
I was thinking something like hc_others = true to toggle it
ah
i realize what the miscommunicaton is
im making a card that has a function similar to blueprint
so this card should 1. be able to copy the effects of other cards similar to blueprint, and 2. not be able to copy blueprint or be copied by blueprint
i can do the first one
then you'd need to check if context.blueprint_card is a blueprint
im just curious if i can make it so this card cant copy blueprint
ykw
i realized
this is so easy
or check if the card you're trying to copy is a blueprint^
whichever way
i just do this (addresses the part where it cant be copied)
wait i have a question
like in vanilla, if i took a blueprint and a brainstorm
and nothing else
and put the blueprint on the left
what happens
absolutely nothing
there's no effect to copy, and they stop looking after going too deep
i ask because the card i was making is like blueprint but it copies a different card so in theory u could do the same situation with my card
too deep being however many jokers there are
ah so it would actually recursively loop and the game will just stop it?
after a while
So if I switch "m_gold" to "element_fire" it should apply my custume enhancement to the card, correct?
m_modprefix_element_fire
ty
where modprefix is whatever your mod prefix is (duh)
Worked perfect! (I have to change the spirit because it was made with the intend of being a sticker orignally)
chat i think i messed up
Can you remove a card before scoring?
no
Can a card be destoryed mid scoring?
no
Can a card be destroyed post scoring?
yes
We did it boys
we did it boys
what was the solution?
i ended up giving palettes an hc_default option
everything else seemed too convoluted and bad for api design
i think it's about ready now
Seeing this working makes me so happy
deck skins seem good to go. there's probably an issue or two hiding somewhere :cba:
do i say fuck it we ball 🤔
they seemed pretty much done when I tested the other day
ball it we fuck
and the crowd exchanges confused glances 🔥 🔥 🔥
ball fuck we it
it we ball fuck
we fuck it ball
ball, fuck it we
ball we fuck it
bucket if wall
check for the played card, then use :is_suit(), it can be Spades, Diamonds, Clubs, Hearts
for instance, context.other_card:is_suit("Diamonds"), which checks if the card suit is diamonds
no probs
nicee
Does any mod add a single Booster pack?
that one MASSIVE voucher mod does add a voucher booster pack
(i actually still cant remember the mod name, holy shit)
betmma's?
i think so, yeah
I've never been able to understand Betmma's code v_v
more like jank ;P
oof, so spaghetti code?
Maybe the rumours of Betmma's spaghetti are overstated
But that was my impression back then
well at least it works, so we don't question it 😭
lol ai guy deleted
someone asked about the right ai model to use to generate joker functions
hell naw
i don't think i've ever seen any person use ai for a mod and have it actually work
How do I access hand level number?
I thought G.GAME.hands[hand_type].level was it but it's a table instead of a number if with Talisman for some reason.
All numbers are tables with Talisman
it's how they get past the e308 limit - they store numbers as tables, with the first part being before the e and the second part being after the e
https://streamable.com/poiqda something is definitely not working right
i missed a return true and it made it loop infinitely apparently
a couple days ago my brother suggested a joker idea, and I like the concept, but I don't know how I'd go about it. I could probably use context.before to change what a hand scores as, but how would I add cards to the scoring hand?
concrete mixer joker that does this on purpose 🔥
cobblestone generator
now for the actual problem i'm trying to solve which caused that video
https://streamable.com/2y32ex this is mostly the intended behavior but for whatever reason the alert always happens after scoring is done, instead of when the stone card is created
as far as i know, this should happen at the same time as the rest of the event, and i don't know what to change to make that happen
Huh, that is a weird one. If I had to guess, maybe card_eval_status_text doesn't go odd during context.individual?
you want to return a table with a message and a func that then creates your stone card
ohh so should i not be using the event manager at all?
I didn't even know you could return a function. How 'bout that
i'm not sure how the timing works out precisely, you'll have to tweak it, but i know this is the general form you want
okay i'll try reformatting it like that, hopefully i can figure it out
you can leave the stone bit in the main part, just return the message
the reason its mistimed is card{_eval_status_text queues an event, so it gets pushed to the end of the queue
is this what you mean?
i tested this and it doesn't display the message, i'll try putting the function in the return
how would i format this? i tried just putting the event into the function and it threw a bunch of syntax errors at me (i might have been dumb and messed up the syntax idk)
keep your previous card_eval_status_text code but pass instant = true to it alongside colour and message
Hey yall, this may be dumb but is there some sort of template or something for reskinning jokers mods?
you're not ending the func function
the rest looks like your code program going apeshit
oh no i see
...this just works immediately lmao
of course it was something simple loll
but also go off if instant worked lol
heya, is is possible to force a particular voucher to be in a shop via debug console or some such? need a specific one for testing
debugplus spawns stuff with 3 from collection
i just wanna say that i'm diving into balatro modding without learning lua first so uh. i'm just surprised that anything i'm doing is affecting the game in the first place
it's been really fun though
So I hooked up this function by using the highlighted part as pattern:
Should I use the whole function as pattern instead to be safer or this is good enough?
position is 'after' by the way.
Do you want to add something before or after that
after
then you don't need to use a lovely patch, you can use a hook
https://streamable.com/4szfud it functions properly now, alert pops when the stone is spawned like intended
Thank you very much, that worked perfectly :)
Wait, I thought patching is how to do a hook... wut
lovely patches and hooks are different
OK
let me find an example
#💻・modding-dev message this is an example
you store a reference to the original function, then you replace it, making sure to make use of the reference previously saved in some part of the new function
So like,local LUH = level_up_hand function level_up_hand(card, hand, instant, amount) LUH(card, hand, instant, amount) for _,J in ipairs(G.jokers.cards) do J:calculate_joker({level_up_hand = hand, level_up_amount = amount}) end
exactly
Where do I put this piece of code?
Anywhere in your mod's code, as long as it runs
Balatro isn’t reviving the return messages, please help
They are in a calc function btw
What's your code
And what's the issue exactly?
Anyone knows how to mod pirated balatro?
I wanna try the Neato mod Roffle streamed earlier
Is it possible to mod pirated balatro?
you should genuinely be ashamed of yourself- it's one thing to pirate a triple a video game but a) this is an indie game by an independent developer who deserves every cent you give him and b) you're asking such a question IN HIS OWN SERVER. like do you realize how disrespectful that is? if you're gonna pirate don't do it so blatantly, you look like an ass for doing such
jesus christ maybe they just cant afford it
🤷
I know that and I plan on buying it. I don't have money rn. I'm just wondering if you can mod it
I wholeheartly recommend modding AFTER purchase.
you're on your own for this
i know it's probably just a matter of order, but how do i keep the message from showing up twice? the joker functions entirely correctly otherwise
Is mobile balatro possible to mod? I bought mobile balatro. If not when will mobile balatro be moddable?
Ok thanks
context.individual runs for each card individually, you can refer to it using context.other_card
The code that isn’t in the return’s selection runs fine, but everything inside of it doesn’t do anything. My code btw (can’t get discord on my computer, never worked for some reason. So sorry for bad image quality)
Why only trans to Queen? Why not both(K<->Q) ways?
The problem is only in calc btw
its estrogen specifically
it's an estrogen joker, although in theory it'd be pretty easy to make a T one as well
from what i saw earlier
what's your steamodded version
Oops, I didn't saw that.
s'all good
1.0.0~alpha-1304a-steammodded
hold up this is fire 🔥
when first created how is G.playing_cards ordered? is it sorted by rank or suit?
(i.e. is it 2-2-2-2-3-3-3-3-etc or 2-3-4-5-6-7-8-etc)
(im asking bc im making a deck)
a little unsure what you mean here, should i change context.individual to context.other_card or?
wait does print() print to the debug log or what
1.0.0~alpha-1304a-steammodded
yeah, with debugplus it'll print to the in game log as well
cool
why is the apply function running multiple times seemingly?
(print(i) is just for debugging)
can I increase the line limit in the Lovely console?
is it possible to disable/hide the lovely console
yeah i figured out that one
you're getting multiple prints of each number?
yeah seemingly infinitely
like it just straight just doesnt stop
(this obviously happens when i actually start up with the deck)
you forgot to return true in the event
how do u make a joker check if theres a specific word in the name of other jokers that u have ?
the main parts im having trouble with r getting it to actually check for the word,
and im not entirely sure which things let a joker check text/variable (etc) in other jokers in hand
whats a good way to randomize the suit of a card?
ik theres other_jokers but im lowk tired and been doing this for like 5 hours
like G.playing_cards[i]:{whatfunctionhere}
i think incorperating psuedorandom would be nice
psuedorandom makes it so that the same card can be gotten on a specific seed
well i can tell you this gets a random suit and rank
true
normal random would be random regardless of seed
i need just the suit
i believe in you
the goal is this but all random suits
no, what you should do is not loop through every card in the scoring_hand, since context.individual already does that for you
I'm iterating through G.playing_cards[i] and looking at the joker's key j_* to look for other jokers in play.
u can use the ` bracket to make italics not work
each scoring card will be evaluated in that context, and you can get the reference to that card from context.other_card
like *dfsfsdfjk*
part of the issue im having is im not not sure like how to make it so that it can be from anytime a joker is added (like baseball card)
the joker is conceptually very similar to baseball card
SMODS.change_base(G.playing_cards[i], pseudorandom_element(SMODS.Suits, "your_key"))
Ugh... I'm on mobile and it's not letting me edit my message
dang yeah discord mobile is buns
if that doesn't work try SMODS.change_base(G.playing_cards[i], pseudorandom_element(SMODS.Suits, "your_key").key)
tysm
the wording makes me think that playing_cards means like, your deck?
that sounds like a *really* unnecessary step
is it just confusing words
G.playing_cards is your full deck
i was talking abt discord texts (discord italics messags with underscores, not just asterisks)
you didnt even notice? lol
You right. I'm tired too. Hang on...
yeah i thought so 😭
is there a specific name for the jokers area
well i think _that_ is also possible?
this happened with both of the things you sent
use SMODS.find_card to search for a specific jokers
G.jokers surprisingly enough
discor works weirdly with it idfk
i did try that actually im just not sure where to put that
so im kinda leading myself in circles 😭
if this is my joker's key, how do I create this card with SMODS.create_joker?
im new to modding sorry
SMODS.change_base(G.playing_cards[i], pseudorandom_element(SMODS.Suits, pseudoseed("your_key")).key) how about
that function returns a table of all matching jokers
for i = 1, #G.jokers.cards do
local currentJoker = G.jokers.cards[i]
-- look for the joker's key "j_*" as currentJoker
end
currentJoker is just the variable name I gave the joker the for loop is currently looking at
ohh
the trick is that escape characters still work \_ \_
im stupid

