#💻・modding-dev
1 messages · Page 117 of 1
Thanks!
I made the jonkler. And I need him to play the jonkler beatbox every time he is scored
wdym when its scored
i feel like centers should be their own pages, just in a category of the side-panel
My b
I think I remember this being a planned change
tried that. gave me numbers rather than nil, but ace was 14 hmm. guess i can work with that. but the prime bit was returning irrelevant numbers or nil. not true or false
local prime = {1,2,3,5,7}
print(context.other_card.base.id, prime[context.other_card.base.id])
yes ace is 14
11 jack
12 queen
13 king
14 ace
how do you add a seal to a card
local prime = {14,2,3,5,7}
print(context.other_card.base.id, prime[context.other_card.base.id])
if prime[context.other_card.base.id] then
yeah, but how do i make my if run if prime? rn this isnt returning true or false but random numbers or nil. lua is so confusing. when i first played with it outside of balatro i thought it was like python, but nope
first you add a sound in your main file
then you can call it in the joker calculation
-# context.joker_main if you want to play it when its your joker's turn I think
.add_seal('blue')?
That’s huge thanks!
that's because you're doing prime[<card's ID number>] which tries to access the ID'th index in prime, which doesn't exist if it's above 5 because the list is 5 long
oh so i need a list of true/false 14 long?
no
you can do something like {[2] = true, [3] = true, [5] = true, } etc.
for index = 1, #prime do
if context.other_card:get_id() == prime{index] then
primeflag = true
end
end
if primeflag == true then
---okay, this means it's prime
end
this should work
i tried that earlier, but ig i was also doing .rank then which was the fault
just checks the card's ID number against everything in the prime list
oh wait hold on you'll need a flag for this
your else block is unusable here
Hi, I'm trying to make a joker similar to steel joker but when I go to look at it in collection the game crashes with an error that playing_cards is a nil value
SMODS.Joker {
atlas = 'Estrocards',
key = 'echoagenda',
pos = { x = 3, y = 0 },
rarity = 2,
config = { extra = 1 },
loc_vars = function(self, info_queue, center)
info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_echo
return { vars = { center.ability.extra } }
end,
loc_txt = {
['en-us'] = {
name = 'Echo Agenda',
text = {"Every {C:attention}echo{} card",
"in your deck gives",
"{C:attention}+#1#{} joker slots"
}
},
},
update = function(self, card, dt)
local echo_tally = 0
if #G.playing_cards > 0 then
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_cry_echo then echo_tally = echo_tally+1 end
end
G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra
end
end,
}
also inefficiency alert
why is that in an update function?
I wasn't sure where else to put it
this will sequentially increase the joker limit every frame
Oh and so it will
I know what you're going to say next!
"You don't need the == true"!
I didn't notice that, where should I put it?
it's fine to have here, you just need to keep track of the old limit added
as for the crash, just check that G.playing_cards exists
like if G.playing_cards and #G.playing_cards > 0 then
Thanks
i don't even need to say that, the worse problem here is that it's inefficient
local prime = {[14] = true,[2] = true,[3] = true,[5] = true,[7] = true}
if prime[context.other_card.base.id] then
It works! thx so much @violet void and @frosty dock
should do prime[context.other_card:get_id()] do catch stone cards and whatnot
How do I check for not scoring cards?
with quantum enhancements, it actually does because get_id is expensive due to having to ask every joker for extra enhancements 🙄
that message starts with "with quantum enhancements"
no of course it doesn't make a huge difference, but lots of unoptimized code adds up in the long run
i correct, since quantum enhancements exist
is there a get_rank()? would that fix my early issue?
that's practically what get_id is
aight
do you mean like splash
rank key is still card.base.value
just thought it would give 1 for ace instead of 14
that's just how the game does things
ig i could always do get_id()%13
don't
No, I want to give 3 mult for every non-scoring card
if you do that, stone cards will start behaving as completely random ranks
so like splash but instead of scoring they give +3 mult?
#context.full_hand - #context.scoring_hand gives you the amount of unscored cards in joker_main calc
ahh, .base.value i was just doing .value
Thanks!
i heard of a balatro mod about yomihustle but like
i heard about it once and cant find it now 💀
oh thx
simple search in #1209506514763522108
coincidentally, how would I get the unscoring cards from the current played hand
I made a joker like Splash that gave unscored cards 1/2 chance to score twice and I had to add a new property to card to make it work but im sure theres a better way
ok i need some help because i have been trying to figure this out for like an hour straight
the efficient way would look like this
local scored_map = {}
for _,v in ipairs(context.scoring_hand) do scored_map[v] = true end
local unscored_cards = {}
for _,v in ipairs(context.full_hand) do
if not scored_map[v] then table.insert(unscored_cards, v)
end
but you can't score unscored cards from joker calculation, and if you score them prior they're no longer unscored
what is that set_seal doing inside the return
and what is it you're trying to accomplish?
idk
also doesn't this add the seal to the joker?
if a played hand has face cards, add a blue seal to them
i didn't really know what to do
i just started out like yesterday
other_card:set_seal() after play_sound? not in the return?
gimme one sec
same
but you can't score unscored cards from joker calculation, and if you score them prior they're no longer unscored
yes, Splash logic is put just before the played cards are highlighted so a lovely patch was necessary either way Ig
splash mention
if you want to work like midas mask, I'd go for something like this
calculate = function(self, card, context)
if context.before and context.cardarea == G.jokers and not context.blueprint then
local faces = {}
for k, v in ipairs(context.scoring_hand) do
if v:is_face() then
faces[#faces + 1] = v
v:set_seal('Blue', true)
G.E_MANAGER:add_event(Event({
func = function()
v:juice_up()
return true
end
}))
end
end
if #faces > 0 then
return {
message = 'Seal!',
colour = G.C.CHIPS,
card = card
}
end
end
end
this adds the seals before scoring, not as the cards score
ok
function remove_from_deck(self, card, from_debuff)
if card.ability.extra.slot_removed then
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
end
end
``` do i put this in the calculate of my joker?
example mods exist
but we don't have examples for everything
-# you'd probably find an example for most things supported in some mod though
there are no enhancement examples graagh
a small snippet of code after showing a function would be great
but yeah uhh https://github.com/Steamopollys/Steamodded/blob/main/example_mods/Mods/ExampleJokersMod/ModdedVanilla.lua example mod
I find it really annoying that the week I decided to unscuff enhancement calculations seemingly everyone has decided they want to make enhancements
i am going thru the example mod currently, its only marginally more helpful than the wiki XD
I'll make an edition instead if I can figure out how to make a shader
it's just that you're paying more attention to enhancements as a whole
so it feels like there's more
no there's definitely more
there's just more people making mods yeah
mostly i want to make jokers
everyone mostly wants to make jokers
peanut butter is one word
wot?
i didnt get enough sleep last night
prime time pairs well with fib
is it possible to replace the original quips (these ones) with custom ones via mods? i can't figure it out
ive never seen dq_1. when does it show?
l=lose
im guessing lower w=win?
lol, 2 jokers later example covered what i wanted
simply replace the text here with whatever you want, if you change the names or number of quips that would cause issues as they seem to be hard coded. for example:
if you had <10 loser quotes, theres a chance of returning an error, >10 and some will never appear
is it possible to do it without editing the game luas? i wanna send my mod to a couple people I don't want to have to explain to them how to overwrite it
using lovely injector https://github.com/ethangreen-dev/lovely-injector?tab=readme-ov-file
i think you can also just literally just override the variables since its just stored in a variable
how would i decrease the number of joker slots?
yes
o yea btw i got the doubled joker thing working with add_to_deck and remove_from_deck
thx for the help yall
for lovely injector regex, is there a way to use capture groups in your payload?
This isn't working
return {
message = localize("k_nope_ex"),
colour = G.C.FILTER,
}
am I missing something?
Also while im here, will a weight of 0 make a card not show up?
card = card
Thank you
Just after colour right?
doesn't matter idt
Order doesn't matter
Thanks
now that the weezer joker is done i can start working on the next one
am i allowed to ask someone to update a mod for me?
why wouldn't you be allowed...
i dunno just wanted to make sure
whether someone will do it, i don't know
there's a custom deck mod that hasn't been updated since april and i'd like to be able to use it
is there an easy way to specify for a joker to be rental in a challenge definition nvm i figured out how to allow rentals
realized a tiny flaw in doubled joker
how do i check if a joker is negative?
is it like if cardname.edition == 'negative' then?
if card.edition.negative should work
lmao
ok gotta do smth
we got to have the add_joker also have the edition
yes, this is arguably one of the best features of the regex patch
do you know the syntax?
I made the syntax 
it's standard regex capture group syntax. afaik I have an example on lovely's readme
i dont get it 😭
i made a custom function to return the first existent value in a table
OH WAIT
I do not have an example
i forgot how for works in lua
its not like python
it should be for i = 1, t do i think
it should just be $1 or whatever you've named the capture group
wait no for i = 1, table_length(t)
thx, been a while since ive used regex
for i = 1, #t be like:
for i,v in ipairs(t) be like:
oh yeah
dq is right before boss blind in demo
in this example deck, why do they do '4' in config and use it only ONCE in assert call, instead of just sayin '4' directly in the assert call
Maybe using some kind of template
It'd achieve the same thing if you just put '4'
And removed config
yea, so idrk why the person who made that example used config instead of just '4'
ask them!
i have no idea who made that example
idk if its steamo (the creator of steamodded) or just a random other person in the github
lol
but if you want to know who made that and it's on github
click "Blame" on the top left
when looking at the file in github
this was much of my confusion
like its not related to anything im doing but im genuinely curious why they did the more boilerplate option than just '4'
I'm trying to make a joker that upgrades mult when cards are destroyed using something like the hanged man or immolate. would context.cards_destroyed work for that?
im still confused by how config works
i am having so much fun over here
had to make some lovely patches to make rental jokers and negative consumables in challenge definitions possible
the 'down in' challenges, and 'standing ovation'/'round of applause' etc (including the locked ones) are the same challenge at their core, just gradually getting harder and harder
destroyed_cards is for glass cards IIRC? maybe?
test it, but thats what i've been told
What's the prefix for tarot cards?
like with enhancements its m_cry_echo
and for jokers its cry_jimball_joker
trigger_effect = function(self, args)
if G.GAME.last_blind and G.GAME.last_blind.boss then
G.E_MANAGER:add_event(Event({
func = (function()
add_tag(Tag('tag_double'))
return true
end)
}))
end
end
how do i use trigger_effect. clearly im doing something wrong. crashes on launch
this is in a deck(back) btw
Does anyone know the right API call to replace the texture of an existing joker?
how do i get a joker's edition? i know how to check if it is negative, but cant figure out how to actually just get what it is
I have a seal that tracks its discards as a value in its config, but the number persists through runs, does anyone know why that is or how to solve that
Daily reminder for everyone wants who their Mod on the Balatro Mod Manager:
https://github.com/skyline69/balatro-mod-index
if context.other_card.edition.type == 'foil' then```
I couldnt tell you if that works for jokers, but it works for cards so its possible if you use `context.other_joker` or just `card` with `== negative` then that could work
other_card should work as card refers to anything card-shaped, not just playing cards
Figured this out (it's c_prefix_key for anyone needing help in the future)
is there a way to check if a certain hand is being discarded (ex. discarding a pair)?
calculate = function(self, card, context)
if context.joker_main then
return {
-- mult = number of cards left in hand
mult = #context.hand,
message = localize { type = 'variable', key = 'a_mult', vars = { #context.hand } }
}
end
end
Any idea how to retrieve the number of cards left in hand (not in the played hand; thats .full_hand)
I want how many were not played. so if handsize=8 and you play high card, 7 remain in hand
calculate = function(self, card, context)
if context.cardarea == G.jokers then
if context.after then
local card = create_card("c_est_miniblahaj", G.consumables)
card:set_edition({ negative = true })
card:add_to_deck()
G.consumeables:emplace(card)
end
end
end,
I think I have my contexts wrong here. I want this to activate when a hand is played like ice cream but it's making my game crash
whats your config?
Me? None
Or do you mean the whole code?
wait
wait sorry im a moron, here you go
config = { extra = { amount = 1 } },
it's not being used though
hey, i dont know this either. i just thought #1 meant vars which relies on config. but no its talking about ipairs which i dont see in your code snippet
Yeah. when I make it this
if context.before and not context.blueprint then
if context.cardarea == G.play then
``` then it doesnt crash so I think maybe the error is actually in the creation of c_est_miniblahaj?
¯_(ツ)_/¯
(I think it doesn't crash here because the code is never getting to the tarot creation code)
OH WAIT I THINK I KNOW WHAT I DID. there should be more arguments in create_card
it looks like the crash is within the game code itself based on the error message
Yeah i agree
anyone know if there's any check for start of run or anything like that?
you can probably check your lovely dumps for that; line 2177 of your functions/common_events.lua might not match other peoples'
Sure i'll take a look
line 2177 is end 😔
love this trail and error of just guessing what variable im looking for
i love how that hhappens with almost every single situation ever 😭
i know exactly what i want to do, and my code works. i just dont know which of the infinite permutations is the correct var/field i need
i need to know #cards in hand
well i know its some kind of area
like #G.jokers.cards but for the hand
so maybe like #G.hand.cards or smth
oh wait that worked? wow i just guessed based on the situation lol
Ok well we have a new error now which is progress. I can make a random tarot card and add it to the consumables but then it crashes and complains about center
It works!
calculate = function(self, card, context)
if context.joker_main then
return {
mult_mod = #G.hand.cards,
message = localize { type = 'variable', key = 'a_mult', vars = { #G.hand.cards } }
}
end
end
niceee
Ok it's mad at c_est_miniblahaj so i might've been wrong here
in Lovely is it possible to catch more than one line in a pattern
i need to do some pretty extensive modification of some base game behaviours
how would I put a random hand in the description of a joker like the to do list
multiline patterns are a thing and regex patches are always an option
right, thank you
IT WORKS, my first proper joker!
are you the person who made lovely btw
based on your username
lets goo!! sick!
what's lovely?
john lovely
I am he
lol
i need multiline patterns because of this stipulation in my challenge descriptions, as some of my challenges are designed to give just the bare amount of resources to win ante 8 and no further
no point trapping the player in a doomed run
i know what i'm doing now though
just got flashbanged by that gif
I suppose your new challenge will be doing it while maintainin mod compat
good luck o7
regex patterns can be multiline right
these are all meant to be experienced vanilla without any additional mods installed, so to make them compatible with other mods is out of scope :p
pretty sure smods uses them as such
Hey guys is it a bad idea to have an unlockable legendary because none of the legendaries I've seen are unlockable
is there anyone that can help with this?
Burnt Joker maybe?
yes
i have had to do some horrible things in my time
what should the brat joker do
Asking this again because I was wrong
OK. It is c_ but theres no prefix
just c_key
calculate = function(self,card,context)
if context.discard then
for card in G.discard do
G.deck:remove_card(card)
end
end
end
Any advice on how to remove discarded cards?
i didnt expect this to work, but i dont know what will
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
for i = 1, #context.full_hand do
local card = context.full_hand[i]
if card.ability.name == 'Glass Card' then
card:shatter()
else
card:start_dissolve(nil, i == #context.full_hand)
end
end
return true end })
try that after context.discard
Doesn't that create ghost cards?
@tidal steppe
Man, is it really going to take about 20 different patches to make a custom enhancement work like stone :(
This is going to be tiring.
if context.discard and not context.blueprint then
return {
remove = true,
card = card
}
end
i have a looping event here:
function lobc_abno_text(key, eval_func, delay, quips)
...
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = delay or 0,
blocking = false,
blockable = false,
timer = 'REAL',
func = function()
if eval_func() then
lobc_screen_text(...)
lobc_abno_text(key, eval_func, math.random(2, 10), quips)
end
return true
end
}))
end
how do i make it so that it removes itself from the event when lobc_abno_text is recalled?
Add an extra argument that is sent only by a recall?
Woah, its really that simple. thank you! ❤️
Are there any checks to prevent cards from being forcefully discarded or debuffed, trying to make an Enhancement where its ability is just being immune to debuffs
EDIT: Nvm I figured it out, done by overriding the function by defining this block of code outside of my SMODS sections
local alias_set_debuff = Card.set_debuff
function Card:set_debuff(should_debuff)
if self.config.center_key == "m_fm_wovenmail" then
self.debuff = false
return
end
return alias_set_debuff(self, should_debuff)
end
oh wait i'm fucking stupid i forgot to return true in the events in lobc_screen_text
i mean to just return what it is, not return if it being a certain type is true or false
but it seems that that might worke
work*
lemme see
Hey I'm curious when multiple ppl get together to work on a mod is it more often just like two friends like
"Oh hey I can program"
"Oh hey I can draw"
"Let's do it"
i mean thats me and my friend working on games together (and never finishing them)
Or is it more like
"Hey I really liked your art/programming on hrhfqhsgvj1itq can I commission you" does thar ever happen 😭
yeah
still have no idea what the brat joker should do
partying and drugs
ngl i should make a custom edition which is like an actually useful negative: just negative but instead of +1 its +2 slots
ok then
i have no idea either
Makes all jokers drunk(1 in 2 chance to retrigger, else doesn't trigger)
wow
good idea ngl
bc rn negative jokers just take up the slot they give so its really just useless
except for having that joker
how do i put him in my game
anyone know how to get the chips currently in the blue chip box during joker calculation?
hand_chips and mult are globals you can access.
...bizarre that remove_from_deck triggers when a Joker is debuffed.
awesome, thank you
i tried G.chips, G.current_round.current_hand.chips, and G.current_round.current_hand.chip_total and none were what i wanted lmao
that might be so it still properly changes hand size even if its debuffed?
Perhaps... though, this introduces an unintentional SFX trigger on some of my Jokers.
you can use if not from_debuff
UNLOCKS FOR MY DECK(tattered red) WOO
White stake(common joker):
Speedrunner: Skipping a blind gives +1 hand to the next selected blind
Red stake(t1 voucher): Thrift: Discarding has a 3 in 4 chance to use a discard
Green stake(uncommon joker): Sleight of Hand: After playing a hand, draw an additional card
Black Stake(challenge):
--Slow Burn--
Start with 5 hands and 4 discards
Even antes permanently remove 1 discard
Odd antes(after 1) permanently remove 1 hand
Blue Stake(uncommon joker):
Trash Hoarder: If blind is won after using all discards, grant a garbage tag
Purple Stake(t2 voucher):
Steal: Discarding has a 1 in 2 chance to use a discard
Orange Stake(rare joker):
Trade-off: The first two discards of round give +1 hand, the first two hands of round five +1 discard
Gold Stake(background)
Red and black, upon scoring over 5x the blind requirement, the background will start to burn
What would I need to do if I were to make a a new type of playing card effect category seperate from Enhancements and Seals
which are you, cuz id love art assist XD
:P
i have yet to fix something of my deck
she is literally too big
Oh I'm a solo dev and I do both the art and programming of this
🔥
But you're free to help if you would like :3
how to get art for your mod:
step 1: ask lyman
step 2:
i usually do the art myself
tell me more about what youve got, plan to do, and what i can do 🙂
how to get art for your mod:
do weird scribbles
someone feels bad for you and draws the thing better
at least you tried
how does this booster api even work orz
Can I see some of ur art :3
im not an artist, im looking for artist
i am grate artiest
PEAK
stunning
whats the trigger on deck(back) for defeating blind(boss)
and
what is the command to increase the number of joker slots?
i'm highly confused by this crash im getting, happening when i hover a booster pack i've added
Wait which mod is this
I've never seen that 😭
🧓
TRUE
idk i just started doing emoji at one point #💻・modding-dev message
Implementing this felt dirty lol
why do i keep makin bocchi the rock characters
30 dollar website ahh joker
(i know they are twemojis)

this x mult text feels so wrong
anyone have any ideas about how to re-trigger jokers?
from cryptid's source
huh ok
im guessing retrigger_joker_check and retrigger_joker are defined in cryptid an not smods?
ill look for it though ty
oh really
yeah
🥳
i would prefer to inject it instead of take_ownership but man i am relieved
i was dreading this part
I don't see why it would need any
Considering Intellisense works with workspaces.
Assuming your code editor supports those
We are in need of some intellisense
as it is luals is pretty slow
some general definitions that don't need a 600ms search would be nice
It's that slow?!
+cutting back on undefined global end your own life now is nice
when you have a good amount of mods + the balatro source code + the lovely dumps of the balatro source code yeah
it gets a little rough
Is there a setting for the lua extension that allows it to work with multiple workspaces? From my experience my files would need to be in the same workspace as the source for it to consider giving me any kind of completions
if you limit yourself to just a few things it gets a good bit better, but with how often i need to search through other mods/debug them i just don't feel like it's worth the tradeoff, i just ball without any sort of autocomplete
Oh yeah if you're adding mods in that would slow down.
I just defined LOVE, Balatro source, and Steamodded in my neovim config and called it a day
VSCode config files should work no?
I don't know, all I did was add folders to my workspace, it spent a bit doing a "diagnosis" and then proceeded to tell me undefined globals
That's why I'm asking if I'm missing something
naw it's just a fact of life unfortunately i don't think anyone here has ever looked at any luals detected "problems"
minus syntax errors
That's what I did
including literally everything in your workspace + installing love2d definition extensions + praying usually does okay
To use more advanced typesetting, specify your description as a localization entry at G.localization.descriptions.Mod[id]... does that value need to be a table too?
Whenever I use this, the completions are separated between workspaces
So in my mod folder it doesn't know SMODS exist, but if I go to steamodded source folder it does know
oh
what should i make next in my mod?
Any ideas?
is steamodded in your mods folder?
i mean id assume so
if you want both your mod and SMODS to be included, just change your workspace folder to the mods folder, itll know SMODS exists once you do that
Wait wha
So just open the mods folder directly?
How in the world is this considered "undefined" yet can also fetch every value that can be ties to them
yup!
then you can also look at other mods you have installed too
I'll try that when I'm on pc, I actually hadn't considered that
if you wanna see how they work
I just wish variables had types, I hate not being able to see everything context or card have to offer
i thought they did have types
wdym by that, im kinda confused
Variables don't have types, they can hold any value
oh yea
i really wish they did
i dont get why they dont tho
i mean there are workarounds
i mean non statics can be cool, like python doesnt hide as much from you
but statics still are coolio
alright im losing my mind, i made blueprint retrigger all other jokers but i want it to not retrigger other blueprints to prevent wacky interactions, what's wrong with this? abort is never printed
Is it supposed to be context.other_joker? I've seen that used before, but I haven't messed with that kinda stuff
no change with that
you're comparing a card with a center
it is currently retriggering itself which is odd considering i would think context.other_joker ~= self would block that
Other_card.center insteqd
Try ~= card instead
Do you need to pass context.other_card into the return statement instead of card?
I guess that would only be for which Joker to show the "Again!" message under
That sounds correct to me
You passed 1 to repetitions
You only return early when it's not blueprint, so that adds up
i thought self was blueprint
card is blueprint
Self might refer to the center but that's just a guess, I've never used it
I've only ever used self to represent the card when I hook into a function. With the custom SMODS APIs, the card is passed in separately
self in that context should refer to SMODS.Joker
which isn't what you need
huh ok
i just kinda copied this code and worked with it
which contains self
Cryptids code is a mess
maybe its different with take_ownership as opposed to calculate functions in new jokers?
brother all this code is a mess
The base game code is a mess
So I've no idea what they're doing to setup their jokers, didn't bother looking through files with over 3k lines
we are so back
I blame it all on lua
dont mean to detract from your success, and that looks sick, but what is that font
its the mtg font
ahhh
what oddities are in there
Joker dollars
20 jollars
Is that an icicle
narwhal horn
man that is some sick art
thanks lyman did it
shoutout to lyman
shoutout to that guy
How do I add retrigger support to a joker
*blah blah*
return{
message = localize("k_again_ex"),
repetitions = 1,--card.ability.extra.retriggers,
card = card
}
end```
this is what i did to make blueprint retrigger all other jokers one time, excluding other blueprints and brainstorms
its a consumable that causes you to draw two cards when used
oddities notably always go to your consumables from the pack, instead of being used immediately
Does it tell two jokes
apply = function()
G.GAME.starting_params.joker_slots = 1
end,
trigger_effect = function(self, args)
if args.context == "eval" and G.GAME.last_blind and G.GAME.last_blind.boss then
G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots + 1
end
end
apply is working 🙂
- setting joker slots to 1 at start
But trigger is NOT working 😦 - it isnt increasing slots by 1 per boss defeat
how do i increase joker slots?
this might help, the antimatter voucher code
i would guess that anything in starting_params would become irrelevant after the run has started, given they're, yknow, starting params
but tbf its equally likely its extremely relevant given some code ive seen
awesome, glad to hear it
shall i call this the antimatter deck?
Joker Slots = Ante
personally i try to avoid reusing names, even if it's two completely different things, but it's up to you
subject to rename, open to suggestions
me on Ante -1:
psst ||like some vanilla mechanis that have secret tricks, this doesnt actually equal ante. but starts at 1 and increases per boss blind. so heirogliph is king on this deck||
So context.retrigger_joker
Thanks
first custom balatro thing :)
Oh shit that's amazing
I've been doing card conversions like that for my mod, but how do you make it so that it plays the bounce animation? And also doing it after the hand is scored?
Also that card destruction you did there by 16 seconds, did you run into any problems with ghost cards?
I think I have a good base to work with
oooo more zodiacs I wonder what these ones do
i want them to be kinda reverse planets (because constellations are tied to the stars) and have them take away levels from hands and grant an equivalent reward
i made myself an eternal testing chamber
So like a combination of Spectrals and Planets
yes
How did you manage to make that extra slot beneath the consumeable area
with some new rewards tied to other features of the mod
Looking through your source code, what is that extra slot named
Ogh
whyre you asking
Can anyone help me understand what config does for enhancement? I assume it's the values used in calculation, but I don't know what they all mean
{
bonus, --Not sure what this one is
bonus_chips, --Additive bonus chips
mult, --Additive multiplier
x_mult, --Multiplicitive multiplier
p_dollars, --Money?
h_mult, --??
h_x_mult, --??
}``` These are my best guess
h_mult - held mult
h_x_mult - held x mult
yea wtf is bonus
bonus is also chips
then what's the difference?
hee hee
hoo hoo
looks like the joke's
on you!
What's the context for checking enhancements?
The bounce animation is just card::juice_up()
I had issues with ghost cards at first, but later fixed it by utilizing what handles glass shattering. I injected all the code I need into the for loop that iterates through scoring cards to check for glass, which marks them for safe deletion with both a variable stored in each card and an array with variable size.
Having it happen after you score just depends on where the code is injected.
Oh you wrote a Lovely patch for the shattering?
Yeah, pretty much everything is lovely patches aside from the definitions/info for the enhancements.
And this juice_up, is it a part of a G.E_MANAGER:add_event function or can it be called by itself like card.juice_up()
No wait, it's both
Which one do you use instead
I just called the juice_up function with card[i]:juice_up() on each effected card iteratively.
I haven't figured out events yet lol.
Ah right then
One more thing, which file in the source code did you patch the shattering code into? This ghost card problem is killing me, and I have zero experience with Lovely patches
It's in state_events. If you search for shatter/glass through it you should find the spot that handles it easily.
is there a way to do custom unlock conditions for a specific joker?
🔥
Still curious how to format such...
why is there a card.ability.extra.chips and a card.ability.extra.chips2? What's the difference?
same as card descriptions
Any specific prefix, aside from the mod ID?
just the mod ID
Well, this adds the white background to the text, nice.
you can change the background color with a loc_vars function
description_loc_vars, rather
fuck am I doing wrong? The text simply displays 'error'
(uses the talisman mod thing for xchips)
Is a_xchips even defined in your case? Unless you also have Talisman itself involved... otherwise, you may need a custom localization entry for that.
I have Talisman installed and as a dependency.
It is just super not working for some reason.
Ah, right, Talisman itself doesn't add the localization entries for that... just the functions and what not.
Using localization file yet?
Right, at the same level of descriptions, make another key of misc... then v_dictionary and then you can a_xchips = {"X#1# Chips"},. Cryptid does define such entries by itself, which is where I am pulling this from.
calculate = function(self, card, context, effect)
if context.cardarea == G.play and not context.repetition then
for i, playedCard in ipairs(context.scoring_hand) do
if playedCard == card then
if i > 1 and context.scoring_hand[i-1].base.suit == card.base.suit then
leftCard:set_ability(G.P_CENTERS.m_fm_slow, nil, true)
card.ability.extra = { frozen = false }
card_eval_status_text(leftCard, 'extra', nil, nil, nil, {
message = "Slowed!",
sound = "fm_slow",
colour = G.C.BLUE
})
end
break
end
end
end
end
Is there a way to make it so that if there is no leftCard it will proceed as normal? Now Balatro's crashing because there's a nil value if there's no left card
random bs go
This is also a good catch for me to also fix the oversight on my part if not used with Cryptid.
where are you identifying the left card?
Wait I pasted the wrong code
azaming
great!
Feels a bit weird still without shadow on the text, but 'tis neat anyway.
Is there a check to see if a card has no Enhancements? Is it not card.config.center
Making an enhancement that will convert the left card into a specific enhancement but it needs a blank card to do so
convert theleft card into the right card
What
there is a way to set balatro to have more ram?
card.ability.set ~= ‘Enhanced’
Oooo gotcha, thanks
how do i pass loc vars into a info queue
when i use info queue for this, its nil in nil chance
Thats only for text
For title or description
Oh live variables
Not fixed
Idk
show your loc_vars function
key = keyeeee,
set = 'Enhanced',
config = {extra = 1}
}```
keyeeee = "m_TGTM_SturdyGlass"
else
keyeeee = "m_TGTM_SturdierGlass"
end ```
i
i meant the entire loc_vars function
i
oh
local keyeeee = ""
if not TGTMConsumables.config.CursedRunes then
keyeeee = "m_TGTM_SturdyGlass"
else
keyeeee = "m_TGTM_SturdierGlass"
end
print(keyeeee)
info_queue[#info_queue + 1] = {
key = keyeeee,
set = 'Enhanced',
config = {extra = 1}
}
return {vars = {card.ability.extra.CardAmt, RuneCurse}, key = card.config.center.key .. (TGTMConsumables.config.CursedRunes and "C" or "")}
end,```
what is RuneCurse
and what is card.ability.extra.CardAmt
ok
did you forget to change your values
i meant where did you put it
at the start
but where
can you just send a screenshot of your whole Joker
its a consumable
or do you mean the info_queue
what
do you mean the info_queue or the consumable itself
Look at how Jokers with probabilities are written in the game
The probability doesn’t exist outside of a run
So in the main menu it won’t show up unless
You do the same as vanilla Jokers do
(binary operator trick)
replace
info_queue[#info_queue + 1] = {
key = keyeeee,
set = 'Enhanced',
config = {extra = 1}
}```
with
```lua
info_queue[#info_queue + 1] = {
set = "Enhanced",
key = keyeeee,
specific_vars = {}, --table of the variable you want to pass on in the info_queue
}```
specific_vars = {(G.GAME.probabilities and G.GAME.probabilities.normal) or 1, 5}, like this?
yea
How would I get the key of a specific joker in the joker area?
why isnt this on the wiki
im p sure it is
idfk i dont really use the wiki that much
i wonder if this is over the line of being not physically possible
i'll probably up the discard count to like 20 or 25
i might have done somethin ewrong
maybe with skips
no tag bans
how would you even win ante 1? force 4 of a kind?
pretty much, that's how my girlfriend did it when clearing down in 8 (this)
you just need a strong opening hand
hm
something i am considering doing is making 'locked' challenges selectable, but not playable, and having the 'custom rules' box tell you the unlock requirements
anyone got documentation for a sample custom deck?
You can also just add the center object and it should grab the vars for you
is there a way I can pass a custom sound to card_eval without using lovely?
You'll have to patch that in... I did it for use in card_eval_status_text and return {}.
mm I guess I'll create a copy of that function and add the key of the sound in its parameters
that can work too
I cant find SMODS.eval_this in the docs, does that not allow custom sounds either?
Nope.
-# better calc 2 pls be faster
thanks for the info (:
how do i fix this
most excellent, and smart way to edit it in, ty
Thus, you can literally have it as extra argument. It won't play the usual "click", using your provided sound instead, something like such: 🦆
return {
message = localize('toga_bonusapply'),
colour = G.C.CHIPS,
card = card,
sound = 'toga_duck'
}
this also didnt work
Perhaps it's complaining about the key one.
lets go
im so good at this
(im not)
i think i forgot the m_TGTM
nice
how would i format this description, like what colors?
Reroll, rarity, raised, generated w/ attention
Chance w/ green
Joker should be attention too
creative liberty, curse change with purple
i forgot about the other version
i think the all future blinds is not worded goos
i should put a thing
like current: 2x or whatever
line breaks found where
what
your rune descriptions have few line breaks
you will not like this then
maybe
i gotta work on like actually doing the runes
i have like 12 done, and i need like 25
ugh
i HATE runes

then i have to do cryptid .... ugh
then i have to balance.....
man
why is modding so DUMB!!!
how do i make it so that score gets balanced when a variable is true
would it be patches
With fancy animations and all? Or do you want to have just the balance of the two occuring?
just balance if its not like super hard
[patches.pattern]
target = "state_events.lua"
pattern = '''local nu_chip, nu_mult = G.GAME.selected_back:trigger_effect{context = 'final_scoring_step', chips = hand_chips, mult = mult}'''
position = "after"
payload = '''
if UnPlasmaRnd then
local tot = hand_chips + mult
nu_chip = math.floor(tot/2)
mult = math.floor(tot/2)
update_hand_text({delay = 0}, {mult = nu_mult, chips = nu_chip})
end
'''
match_indent = true``` why is my patch not working
Do mod_chips(nu_chip) and mod_mult(nu_mult), respectively. Also, nu_mult = math.floor(tot/2)
is it named that because you mine for cards?
Where is buildy buildy deck
was thinking of one where it's the inverse
not sure how fun that'd be though. burglar basically does the same thing
it's moreso that a deck which basically does what Burglar already does doesn't seem too fun to me
i have a seal that im making and it has some data where it keeps track of discards but that count stays through runs and doesnt reset, anyone know how to stop that from happening?
well, this deck isn't restricted like Golden Needle
might try and figure out how to add cardsleeves compat for these decks I'm doing
for the time being they'll be very simple variable tweaks, as I'm not experienced enough at all to do too much more than that
wait were you referring to it being with the Dwarven Deck?
if so then I'm perfectly fine with people having Burglar
moreso meant making an inverse of this deck (no discards, 7 hands)
Where is buildy buildy deck
^^
1 hand, like +5 handsize

0 hands so you lose immediatly
that's why Troubadour works in Golden Needle
same effect
hand count is different from hand size tho
yeah, I know lmao, just meant that you could do the instant game over with hand size instead of hand count
opted to go the no discards route
consider this the buildy buildy deck I guess
lets go
very easy to play flushes and can really abuse things like Mime but harder to dig
but hey, at least one boss blind does effectively nothing to you at first
oh hey that's kind of what one of my challenges used to do, except you get 50/40/30 discards total for the whole run
i reworked it to give you the normal 4 hands because it just wasn't fun
oh yeah that makes sense, when you're that limited on discards
I also just buffed the dwarf deck to give +5 instead of +4
might drop that down again but
given how hard it is to score with just one hand I think it's fiiiiiine? will play test it
does anyone know what's wrong here
it's looking for an .ogg when you have .wav
anyone have, like, a full set of variables for SMODS decks?
I assume a lot of it will just be digging through the balatro code itself but thought if there was a source anywhere to make things easier I could use that
i'm addicted to making challenges so i might workshop creating a daily challenge
the idea is that the challenge's parameters would change daily, the mod would require an internet connection to play because it would pull the parameters from a remote server
might it not be better to have it use the system's date to determine which one is active, then just release like biweekly updates to add new ones?
that's susceptible to "the wordle exploit" aka changing the date in windows (or reading the source) to spoil challenges ahead
that's true actually
it also requires me to update the mod on a regular basis which i will forget to do
yeah I didn't consider the spoiling scenario
would be cool to let them go back and play older ones though
could always just do semi-regular separate mods with all the challenges
like once a month or so you just release the challenges so far in that period as offline accessible
that'd mean you don't have to program a way to go back days and you could then access them without wifi
just released robalatro reborn!
only includes gears tho
theres a bunch more content planned
im abt to give up on figuring out how to make a joker spawn a random joker 🙏
it cant possibly be looking for an .ogg, all the other .wav were fine so why that one in particular
work at a pizza place 🚬
that’s what the error says ¯_(ツ)_/¯
what is there to fix to make it work then? 😕
docs say .wav is supported
I am also using some .wav ones... just that they may have an incompatible encoding method.
solved, apparently I hadn't saved my main.lua 😮💨
bro ong i love Github CoPilot
What do you think is going wrong here?
I don't understand how the argument is nil
when the table isn't empty
I think understanding why it prints k would help
But I have no idea why it does that
should do G.GAME.FacePaint[k], currently you're doing the equivalent of G.GAME.FacePaint['k']
but it prints Clubs
It works for the first iteration
Is there a API documentation for Balatro?
why does the second one break
There's documentation for Steamodded
idk what's going on exactly, but you're defining a new entry in the table during the pairs loop
rn you're asking for a value called k instead of value 1
What's steamodded?
that can't be good
youre on the right track!
It's not a number if that's your question
its going to be big sets of jokers and consumables based on roblox places
whatever it is you're accessing "k" instead of it
k means key, lua can use strings as keys rather than an integer table
I thought table.key and table['key'] were equivalent (and, likewise, 'key' and ''key'')
I kinda need a starting point in learning how to make a mod for Balo
But I only find mod installation guides
Check the examples in Steamodded
i'm not sure they are
they are equivalent
are they?
you're doing table['k']
Most popular unofficial modding API
So how am I defining a new entry?
Thanks
which is why it's printing k
Wait it's interpreting k as 'k'?
yep
probably not possible, how do I check if any of the next Jokers after the current one (not previous) is X?
you need [k] instead of ['k']
you'll want to use bracket indexing for these things
Check Blueprint but use the key if you're looking for a specific Joker (vanilla uses names)
I mean you can see how I thought it would work using .
Everything else is equivalent
yeah i've made that mistake before
only if k = 'k'
except table[k]is the only one that actually reads the variable's value, the other 2 it interprets literally
Which it is
you can think of it like G['GAME']['FacePaint'][k]
and i believe that actually works
or say you define a variable g = 'GAME' then you could be goofy and do G[g]['FacePaint'][k]
but not G['g']
yep
ive been working on updating a bunch of older jokers to work with the current steammodded and I cant figure out how to fix this so that it doesnt crash when it the round ends
why are you using 0.9.8 code
I wrote this code back when it was what everyone used
I've been going through updating it but I wanted to try and fix any big errors before I redo the rest
SMODS.Joker works different now id recommend lookin at its implementation
I'm trying to make a consumable that converts one specific highlighted joker into another, but I don't have the slightest clue how to go about doing that 
Question: I know there’s a flushcalc for stuff like stone cards and whatnot, but are there other calcs for stuff like pair, 3OAK, etc?
iirc it's called get_X_same
I see, i wanted to play around with it to make it so i can do certain ranks to count the same
Example: In Hanafuda, there’s Multiple chaff cards, but they have different art for each
To work around it, i would make “Chaff 1-3 (since December has 3 chaffs)” and treat them all as the same “Rank” essentially
you'd want to have their get_id return the same value I think
Okay so I'm trying to make a hearts set for malverk but I have no idea what I'm doing
I should probably finish the art first though huh
malverk isn't for suit textures, use SMODS.DeckSkin for that
@shut sigil I can recommend #1284376286789111940 for that
Thank you sm
not strictly necessary but has some good guidance and templating
it's what I'm using
malverk covers everything except the playing cards
DSL should be able to do exactly what you want, it's pretty intuitive ^^
Thanks!
I saw that bsky post of someone making SIGNALIS spades and I wanna do something similar
fair enough
anyone able to help me in terms of how I could achieve something like this through SMODS? I'm not literate in lua so haven't the foggiest myself, and of course I can't just build this off of the same config as discards/hands/etc (at least I assume not?)
planned on adding a simple deck that just changes the checkered suits to clubs/diamonds lol
what happened to my hand
(not an actaul question lmao i was just tersting SMODS.Enhancement)
i think the following. idk for sure, im new.
SMODS.Back{
key = "id",
pos = {x = 1, y = 0},
unlocked = true,
discovered = true,
loc_txt = {
name = "Name",
text ={
"desc"
},
},
apply = function()
-- function in your image go here?
end,
}
@scarlet merlin 
I'll give this a whirl
Now I need some UI for the player to select what textures are pooled from
Would you like to help or can I steal fork malverk?
Is it possible to offset the card? I'm making a Joker and it's center of mass is a bit in a different place, so I wanted to account for that
-# "fork" as a joke
what do you mean?
So resizing cards accounts for that unless you grow up
I also need to figure that out, but a few days ago someone was trying to do the same
Yes, I mean that the center of mass is still in the center, but I want to change that
you can play around with it in the cardarea alignment
hey @wintry solar what do you say
I'm not too sure how that would be best layed out
I was thinking just showing a card with the texture and an "apply" button
Is there a tutorial on how to create a balatro mod?
Kinda. The order doesn't matter, and it needs one for each suit
I imagine if I just remove the if statement it might be fine?
Try the Steamodded wiki and checking out example mods inside Steamodded
¯_(ツ)_/¯
Anybody know how to view the game's source code on MacOS? When I right click balatro.app and click "show package contents," it seems to reveal different files that what I'm seeing in tutorials for windows
Maybe you forgot the function arguments
Can you unzip it? (Make sure to copy the executable and unzip the copy)
SMODS.Atlas{
key = 'tartanDeckAtl',
path = 'tartanDeck.png',
px = 71,
py = 95
}
SMODS.Back{
name = 'Tartan Deck',
key = 'tartanDeck',
atlas = 'tartanDeckAtl',
pos = {x = 0, y = 0},
loc_txt = {
name = 'Tartan Deck',
text ={
"Start with a deck containing",
"{C:clubs}26 Clubs{} and {C:diamonds}26 Diamonds{}",
},
},
config = {
hands = 0,
hand_size = 0,
discards = 0,
},
apply = function()
if self.name == 'Tartan Deck' then
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
return true
end
}))
end
end
}```
pretty sure it's just the self there
yeah "apply" probably needs arguments
at least self
maybe others
also dont think you need the if name = as it is already running on itself
yeah I was thinking that too
also not sure that event is needed for basic setup stuff. isnt events just for things to be animated?
@night pagoda Maybe this helps
apply = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
end
}
like this? *with fixed indents
missing event
so it does need event
huh, ok
apply = function()
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
return true
end
}))
end
just that with fixed indents
wonder why this didnt need event then
apply = function()
G.GAME.starting_params.joker_slots = 1
end,
trigger_effect = function(self, args)
if args.context == "eval" and G.GAME.last_blind and G.GAME.last_blind.boss then
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
end
end
After some further digging, turns out I have to click "show package contents," find Balatro.love, then unzip that.
np
splendid
This is what modding's all about
I might throw in two more decks for hearts/diamonds and clubs/spades
ooh
fucked up and evil checkered deck
might call them Charcoal and Saloon after some Tetris colour schemes
it got cursed with SWEDISH 🇸🇪 🇸🇪
AAAAAAAAAAAAAAAAAAAAHHH!!!
Does anyone know how to add challenges(by which i mean unlock requirements) to jokers, decks, etc?
For example my Antimatter deck is unlocked by you having 8+jokers in a run
See Bunco
its a mod
john bunco
Ditpyrc be like
trying to make a mod, copied stuff from ModdedVanilla & getting this
i saw someone else have this issue, the solution was "downgrade from lovely 0.6.0" so i switched to 0.5.0-beta7 and surprisingly it worked for a single launch, and now its erroring again