#💻・modding-dev
1 messages · Page 168 of 1
do I just, run the game from Steam now?
is steamodded installed n everything?
ok well i looked through every lovely file and didnt find it
yeah the folder's in the Balatro files Mod folder, not sure if there's any further steps than that, didn't seem like it
wait nvm i thought of something
oop wait hold on
you launch balatro and the mod tab shows up?
my ass forgot the Lovely Injector step!!
yea thats the most important one lol
ok nevermind i searched through it for 'cry_booster_packs' and it still didnt work
I was looking through cryptid for how they resize jokers and saw they did it through lovley TOML shenanigans, is there a way to do it just through steamodded LUA files?
doubt it
game directory should look like this, data directory should look like this, and metadata should look like this, and the Joker is in the file that's declared as the main file
everything should be in order then?
looks right!
banger!
which is line 48?
fair enough, thanks lol
great question lemme open this in something that tells me
missing an end
place it after the first return
card.ability.extra.pool + card.ability.extra.pool + card.ability.extra.mult_add
return {
extra = { message = localize('k_upgrade_ex'), colour = G.C.MULT },
colour = G.C.MULT,
card = card
}
end```
do you have an atlas defined for the art?
ah, noo, it is currently just a single card png
where is it in the mod? and do you have an SMODS.Atlas defined so smods knows how to render it lol
in these as shown, and, I guess probably not, though how do I go about getting that set up
key = "atlas_name",
path = "filename.png",
px = 71,
py = 95
}```
i've got a whole bunch set up, you can have many cards per atlas
this is what my joker atlas looks like
it rendered!
and then when I hovered over it
you dropped config = { extra = { mult_add = 1, pool = 0 } }, this somewhere
its kinda important
what are your loc_vars set to?
lua starts arrays at 1
so
"scored face card",
"{C:inactive}(Currently {C:mult}+#2#{C:inactive} Mult)"```
is correct
🫡
might be in a lua file then
is it possible to have jokers do things while you're selecting cards?
figures
just trying to make it so a joker can tell you the mult it'll provide before you score it since it changes based on ur cards
to the game source
what determines contexts and the like?
what is this meant to mean?
implement the calculation into loc_vars
png not found
i see
so if the file is called "jokers.png" and it is in subfolder "assets", should the path just be "jokers.png"?
nvm still got the same error
am i also able to change the joker's text on the fly?
oh nice i think i can
hm, i can update loc_txt but the joker doesn't re-render
I'm trying to make every 4 scored give 4X mult but when I select a blind the game crashes and says,[SMODS GaryJOKER "main.lua"]:46: attempt to index field 'other_card' (a nil value) (Line 46 is if context.other_card:get_id() == 4 then)
can you send the calculate function?
maybe because i need a 2x and 1x folder?
calculate = function(self,card,context)
if context.other_card:get_id() == 4 then
return {
x_mult = self.ability.extra,
colour = G.C.RED,
card = self
}
end
end,
you're missing the part where you make sure you're in the right context
place this around everything else:
place this if statement first:
if context.individual and context.cardarea == G.play and not SMODS.has_no_rank(context.other_card) then
YEP, THAT WAS IT
i got joker working!!
only issue is the text isn't loading-
:0
how are you setting it?
main.lua
i'm basically going off of the ModdedVanilla example
relevant code is thus
It keeps telling me [SMODS _ "src/loader.lua"]:571: [SMODS GaryJOKER "main.lua"]:54: unexpected symbol near ','
loc_txt
bruh i fixed it nvm
thanks!!
Now it's saying [SMODS GaryJOKER "main.lua"]:49: attempt to index field 'ability' (a nil value)
card.ability.extra
as a rule of thumb, use card instead of self in steamodded
use card = card in the return as well
Can someone explain to me like I'm a dunce how SMODS.PokerHand and SMODS.PokerHandPart are supposed to interact to detect a custom played hand? Give me a blank example with the required params or something? Been bashing my head against it all day today...
This is unnecessary on new calc
How would I do it so it gives x2 mult and not +2 mult when heart faces are scored?
hell yeah
Change the return table to be xmult = card.ability.extra
makes sense
and it works!
Anyone able to give this a try on Steam Deck or OSX? Just want to make sure it's stable on all platforms over the weekend, since I won't have time next week to fix anything.
now the problem is drawing a hand with heart faces
also dumb question, do we have a list/reference of text formatting things? like how 'Played Face cards with Diamond suit give {C:mult}x#1#{} Mult when scored.' has {C:mult}
I tried looking in the .zip luas, no dice
#1# is to denote where a variable should be used (you would use #2#, #3#, etc if you had multiple variables)
{C:}/{s:} denotes the styling of the text
there are definitely more guidelines but that's the most basic explanation I can give
Yes
Do we have a reference of what does what
like how **this** does bold
That's what I'm asking
Specifically looking for the ones that does this text [with or without the suit symbol]
How do I check how many of a card I have in my full deck
Found what I was looking for. It was in the localization folder
It's in G.ARGS.LOC_COLOURS
under the loc_colours function in misc_functions
And you can add your own colors by adding to that list
so, I have an enhancement for a card where the individual card gains 1.5 Mult when played and unscoring, but it isn't increasing under those circumstances. is this calculate function correct for this?
I don't think context.unscoring is a thing
they probably defined that context in the mod
But it's not a thing in SMODS by itself
ahh okay i'll see where I can find that then
which file?
misc_functions, mentioned here
alright yeah, it's patched in
hmm
i'm blind as hell thanks
all good lol
what is the usage license for cryptid's code? this patch is pretty much exactly what I need, but I obviously don't want to just Steal it
any help?
The error implies it's an issue with Grim, but I can't tell for sure.
You probably shouldn't be enabling this many mods when trying to debug anyway
try reducing it to only your mod (and maybe debugplus or whatever), then making a minimum reproducible example that crashes
what?
Oh
what's unclear about that message 🤔
The repo has no listed license, which means all rights are reserved and you cannot modify or redistribute the code without explicit permission from MathIsFun0. I'd recommend messaging him to ask, or to see if he's willing to open up to a more permissive license
im just confused how
how i broke grim
like I said, I'm not even sure you did
look man I wouldn't be reading that crash screen unless there's less than 5 mods enabled
want me to disable everything
For some reason I can't get the example to show up for my custom SMODS.PokerHand. 🤔
What's your example code
example = {
{'C_14', true},
{'S_14', true},
{'C_8', true},
{'S_8', true},
{'H_14', false},
},
Could be
so i might be a bit goofy, but how would i add additional face card sets? Like, not an override of the default face textures but as a separate one [like how Among Us and Cult of the Lamb have their sets]
Oh yeah it's the first letter only
I know how to do it via texture override but not in adding sets
changed it to *_A for the aces, still not showing up. Not sure what's going on.
also tried _Ace
it is definitely _A
happy
example = {
{'C_A', true},
{'S_A', true},
{'C_8', true},
{'S_8', true},
{'H_A', false}
},
That's how it's written now. Same issue.
Does it take anything from PokerHandPart into account? Or just what's in example = {}?
Probably only what's in example
I am not sure what the issue could be
Did you start a new run, just in case
No, I'll try that. One sec.
I'm just trying to explain how I would approach debugging this 😅
have you gotten a chance to look at misc_functions.lua:1689 yet?
ye
hey there yall, so what do yall use in particular to mod the game itself? i am new to the concept as a whole so any way to get a start would help
Starting a new run did the trick. Thanks for the help!
wait
center.text_parsed
Take a look at SDM_0's mods, and the #1209506514763522108 section and download some mods. look up SMODS (Steamodded) and Lovely on github, that's what you'll need to install mods. Asking questions here is the best way to learn, tbh. I started modding about 2 weeks ago and the lovely people here have been incredibly helpful and respectful.
you misspelled labels
thank you so much! i really appreciate it
dunno if that matters but I noticed it
: |
right so center is a string when it's expecting a table
no it didnt
i didnt touch center though
center's definition is basically equivalent to G.localization.<group>.<set>.<center>*
oh
labels is not part of descriptions
its not?
honestly your loc file is a bit messily formatted
^ it's part of misc
and yes it goes to misc.labels
: |||
you even have this here
and yeah, you should probably make your indentation consistent
can you send your full generate_ui code
i dont know
yeah I've been looking at it and tbh I do not really understand what it's doing
I hate generate_ui code ngl
I have no idea what it's doing most of the time and I need to go 3 balatro files/functions deep to understand small parts
i just want to make a new gameobject that is like seals i dont understand
anyway, can't you fallback on SMODS.Center.generate_ui?
(that's what I do for my sleeves anyway)
maybe can i take a look at that code
oh and btw, don't forget to change the name of your obj to something other than SMODS.Sigil
(the SMODS part to be clear; Sigil is fine)
why?
it gives people the wrong impression that SMODS is providing the Object instead of you
I just do CardSleeves.Sleeve = SMODS.Center:extend {
Yeah don't put stuff on SMODS
so I suggest you do something like SigilsMod.Sigil or whatever you prefer as name
yeah il do that
alright I'm just going with a different "on discard" functionality, though I'm also seemingly messing up this as well, getting this error when discarding it
great
Oh
to specify a little more in case it isn't obvious, the intention is that individual cards with this enhancement will permanently gain 0.5 mult when discarded
use .ability instead of .config in calculate
(at least, that's how you do it for jokers; I'm assuming it's the same for enhancements?)
no idea what im doing
me neither tbh it just randomly worked out for me
alright, it no longer crashes but discarding still doesn't increase the mult on the cards
re-asking this cause I can't seem to reverse engineer it from anywhere
do the same for loc_vars
doing that caused it to crash
thank
use card not self
works now, thank you!
i just coppied ths seal generate ui because it works like a seal
that wasn't for you?
try taking a break, that's what I usually did when I couldn't figure out balatro's way too complex UI
have the exact code copy/pasted
im making a card that has a 1 in 10 chance to spawn a soul card. im adding the random element later, and trying to get the spawning working first. I can't get it to be usable though, and the use button is greyed out. all the consumables ive made so far are ones that only activate when selecting cards so im not used to coding for ones that just get used whenever. What am i missing?
o7
any idea why?
if the use button is grayed out then you need to define a can_use function
and you can define whatever custom logic you want in there
return true if it can be used
Also as a side note, you don't need to specify the set or area manually, it automatically detects it
if you want it to be hardcoded as a fixed 10% chance then yes
perfect
if you want it to be compatible with oops all 6s and other jokers like that, use G.GAME.probabilities.normal
which is usually the first number you see in many jokers that say 1 in x chance
and then you can just do pseudorandom < G.GAME.probabilities.normal / 10
also you need to pass a string to the pseudorandom function as a seed
i dont understand what you mean by that
pseudorandom("put whatever here")
why is the pseudorandom highlighed here?
do you have pseudorandom in a find box in VSCode? That's an IDE thing, not a code check warning
ah im stupid nvm
although you aren't using it right there now that I see
ok it works now
thanks so much
now i just need the wheel nope text lol
i added the nope text but it spawns in the top left of the screen
how do i fix that?
so. i don't know what i did but now the deck skin's invis. gonna upload relevant code one sec
^ relevant png
try changing 'lc' to 'def'
in palettes
if that doesn't do anything I can only imagine you setup your atlas incorrectly, make sure you have a 1x and 2x versions under assets and the path matches the file name
the key of the first palette
i'm not confident it'll do anything
but might as well try
and both files have the same name in each folder
do you have any other mods
i am not sure then, maybe a recent steamodded update broke it? I doubt it but it could happen
yeah I don't know what's wrong, hopefully someone else can help you
well that's new
what'd you change
how would i change the money by a multiple of 10 or set it to a flat value? i dont know what variable the money uses.
you might need to include your mod prefix when putting the key directly into palettes
Is there any way to check when a function is called?
For example, if smth were to trigger whenever a card is debuffed, can you check when Card:set_debuff is called?
i dont know about functions overall, but for debuffs specifically you'd do
if context.debuffed_hand and context.cardarea == G.play then
you can hook into the function to make your own context
Is there an example of hooking on the wiki?
It's more of a general Lua feature. This is a good explainer:
https://forums.kleientertainment.com/forums/topic/129557-tutorial-function-hooking-and-you/
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
YourMod.start_run_ref = Game.start_run
function Game:start_run(args)
--do things immediately before Game.start_run here
YourMod.start_run_ref(self, args)
--do things after Game.start_run is called here
end
``` Would allow you to hook the `Game.start_run` function, for example
Just don't forget to call start_run_ref in your replacement function and return a relevant value otherwise you'll be effectively deleting the original function
Welp. Noob question, again.
How do I make a joker add to mult, or xmult when calculate meets the joker's requirements? is it in the calculate's return{}?
this is by the guys who made eets? damn
that is a great tutorial dang
hooking seems like a very powerful tool! how would this work in the context of jokers?
like if I wanted to take a function and have it trigger a Joker, how would I do that without using the pre-existing context feature (when there isn't one for my situation?)
you can call SMODS.calculate_context with any context, including madeup ones you come up with
so hypothetically, if I wanted a card that activated once the Plasma deck balanced itself (and was only accessible in the plasma deck), I could insert an SMODS.calculate_context({balanced = true}) after the balancing happens using lovely?
well I don't actually plan to add any cards like that, it was just the first example that cropped up
i'd recommend keeping your mod prefix on the context name, like i did here
that way you dont bump elbows with other mods
(hopefully)
for sure
How can I get current handsize (after modified by G.hand:change_size) ?
-# (I'm fixing other mod's bug actually)
this enhancement calculate function adds 0.5 Mult to the card itself whenever the card is discarded, but for some reason it's adding it for every card I discard, so if I discard the ehnanced card alongside three other cards, the mult on it will go up by 2 instead of 0.5
I can kind of see the issue, but I'm not quite sure what to do in order to fix it
any ideas?
maybe check if the card discardeds ID is equal to the card itself id? all card objects (i think) have an ID value.
how can i get the current deck as a table?
G.GAME.selected_back
for the Back instance, that is
for the prototype, G.GAME.selected_back.effect.center
does that contain the cards that are inside of the deck?
oh, that isn't what I thought you meant
G.playing_cards is the table of all the cards in your full deck
G.deck.cards contains only the cards currently in your deck pile
Holy shit I can't believe I got that to work
wow you cut it very close with that small blind
honestly this is awesome
Incredibly
Big Number = Dopamine lol
balatros core principal
To the n-th degree now 
I genuinely can't believe I actually got this deck to work tho lmao
somewhat cursed idea but now I'm thinking of making a "Root Deck" where right before scoring, both your chips and mult are square rooted
Oh I hate it lmao
of course the blinds would have to be horribly scaled down
because it'd be literally impossible otherwise
or just start every hand at level 10 or something
I have a challenge that scales blinds by X8 that people have beat so I think you might be fine lol
root deck is also intended to be a shittier Plasma Deck
with that, your number becomes really big when the chips and mult balance out
with this, your number shrinks greatly lmao
i like this concept
maybe I can also have it so that planet cards level up everything by two instead of just one
Both of those honestly wouldn't be too hard to do
This deck is even easier than plasadeck I think. But the concept is vert cool ngl
i'd figured, but I never know cause I am still relatively new to balatro modding
You get bigger numbers than plas so 
it'd be like a scale
root deck is horribly underpowered
plasma deck is balanced (no pun intended)
nuclear deck is overpowered
What the root deck does
praying that talisman is a depo for the nuclear deck
if I have a joker, card what do I do to card in order to properly use set_sprite_pos?
card:set_sprite_pos({x = 9, y = 2}) didn't work
right before scoring, your chips and mult become their respective square root
I might have to do that 
sounds like a boss blind ngl
i feel like as a boss blind, it would kill most runs
maybe it appears after ante 5-8?
Hummm, yeah
making the root deck and I'm realizing I have no idea how the hell to use the new calculate function in the way I want to
can anyone provide a brief idea of how the calculate function works in the context of a deck, and how I can convert this to not use the depreceated system?
jetbrains user detected
how'd you know~?
syntax highlighting and font
yeah I like jetbrains
but also I want some help figuring out how calculate() works when it's used on a deck
yeah I'm scanning through the steamodded code and I'm still completely lost on how calculate() works when I use it on a back
I take it you saw this part of the Back documentation?
yup
dunno if the odds seem balanced
It looks to me you are trying to define your own trigger_effect function, which, as stated in the docs, is no longer supported
So instead of that, just check for context.context == ‘final_scoring_step’
correct, they're asking how to translate that into the new calculate feature
I just noticed my bad
yeah, but my main problem is that I don't know how to get the chips and the mult as arguments with this new format
with trigger_effect, there's a whole args thing built in, so that stuff's real simple
with this new calculate() function, i haven't found anything
context.chips and context.mult?
hand_chips and mult are global variables holding the current chip and mult values. I’d say try using those
context.chips is round score
ahh
it yells at me for trying to perform arithmetic on hand_chips as a table value
Ahhh talisman how lovely you are
Wtf lol
talisman moment
err
print(hand_chips)
prints a # for me
Oh, you’re making it a table then
why
does it think
it is
a
table
if i cant figure this out ill just use the depreciated system LMAO

i genuinely dont know what to do about this
Does the game actually accept that return?
It just won’t do anything with the hand chips part
I think you should just be setting those values as opposed to returning them
that actually seems to have fixed it! ty!
I honestly just assumed you had to return the values since that's how it works with Jokers
Nice
talisman_ready btw
this specific deck context is special because it's a vanilla context
you can use context.final_scoring_step instead if you want it to behave like joker calc
to_big = to_big or function(x) return x end
tried that, no cigar. but hey, I've got a working solution!
Oh of course that’s why it complained at a table
i had an inkling of what the issue was when I changed it to "return true" and it complained about it being a boolean
having trouble with it not counting the cards here
like. it should give +20 mult right out the bat right
source code?
key = 'j_dafisha',
loc_txt = {
name = 'Dafisha',
text = {
'Gains {C:red}+#1#{} Mult',
'for each {C:attention}8{} card in Full Deck',
'{C:inactive}(Currently {C:red}+#2#{C:inactive} Mult)',
},
},
atlas = 'Jokers',
rarity = 2,
cost = 3,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
pos = {x = 9, y = 0},
config = { extra = { mult = 0, mult_gain = 5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult_gain, card.ability.extra.mult } }
end,
calculate = function(self, card, context)
local eight_count = 0
for _, deck_card in ipairs(G.playing_cards) do
local card_id = deck_card:get_id() or (deck_card.base and deck_card.base.id)
if card_id == 8 then
eight_count = eight_count + 1
end
end
card.ability.extra.mult = eight_count * card.ability.extra.mult_gain
if context.joker_main then
return { mult = card.ability.extra.mult }
end
end,
}```
if you want the "Currently +0 Mult" to update in real time, then you should probably use update instead of calculate
What about #G.deck.cards ?
Wait
Yeah, you should iter G.deck.cards instead of G.playing_cards
update = function(self,card,dt)
local eight_count = 0
for _, deck_card in ipairs(G.deck.cards) do
local card_id = deck_card:get_id() or (deck_card.base and deck_card.base.id)
if card_id == 8 then
eight_count = eight_count + 1
end
end
card.ability.extra.mult = card.ability.extra.mult_gain * eight_count
end,
oh yeah, it should be deck instead
probably that, idk
for the calculate part, you can just leave the context.joker_main there
By the way, just curious: are you intentionally making your joker's full key be j_[mod prefix]_j_dafisha?
Odd, but not illegal.
I think I just some mod do it and just kept that
I was asking about the second j_ but OK.
wait, second j_?
by default, your jokers are already named j_[prefix]_[jokername]
if you name it j_dafisha then it's gonna be j_[prefix]_j_dafisha
SMODS automatically prefixes your joker with j_
Nah you could keep it, as a style.
As I said, it's not illegal, it'd be just mildly inconvenient for yourself.
Ok finally it works, thanks y'all
Please don’t put counting effects in update
Just do the counting within joker main and loc vars
I actually did this for one of my jokers on purpose, but it's literally to prevent update from running for 30 frames after you sell the joker
Thunk:
inb4 posts the code for cloud nine
Does that even do anything?
no need to make a new function, plus, don't detect Talisman from SMODS since it's not a dependency
I'd argue the code that aure posted, while efficient, is so condensed as to be nearly illegible, but that could be solved with a few newlines
so how would I use that line of code?
This basically does what your function does but much cleaner and without making a new function. You just throw it anywhere in top level
And then you just wrap stuff in to_big instead of your new talisman ready function
So in my general dependencies, I just chuck that line of code in
And whenever I refer to a number, just do to_big(number)?
(General dependencies is a bunch of functions I like to re-use wrapped up into one file. I reload it every time I load a file so it's functions can be easily used)
oh boy do i get to analyze some code
so basically that line reads as:
set to_big to itself
if to_big doesn't already exist, instead define it as the following function:
to_big = function(x)
return x
end
which effectively just means that it becomes a pass-through for the number,
since Talisman isn't loaded (to_big would already exist!)
there's no "big" numbers to embiggen a number into so it remains as-is;
your code will work the same way if Talisman is or isn't loaded
(as long as you don't need to do anything too complicated)```
hee hee hoo hoo 
i have solved nothing leaves
Ping me if you respond, but I just can't get this to work. Says it's expecting a }.
SMODS.Joker {
key = 'ethereal_j',
loc_txt = {
name = 'Ethereal Joker',
text = {
"Each played Planet Card gives",
"a Tarot Card"
}
},
rarity = 1,
atlas = 'vopjs',
pos = {x = 1, y = 0 },
cost = 6,
loc_vars = function(self, info_queue, card)
end,
calculate = function(self, card, context)
if context.using_consumeable then
if context.consumeable.ability.set == "Planet" then
local card = copy_card(pseudorandom_element('Tarot', G.consumeables, pseudoseed('ethereal_j')), nil)
return {
card:add_to_deck()
G.consumeables:emplace(card)
}
}
end
end
end
}
the return has two } when you only need one
You also don’t need to return those things
i have a question, is i in this case "musketeer"?
for some reason, it wont run even bother printing "Phase 2" which is making me tweaking rn 😭
Appreciated
show code
you have a second position value
the 2nd one
is it possible to make a booster pack which i can manipulate the odds of cards spawning in there?
no keep that one
OH

That worked!
ty!
dumb lookin little guy
I wonder if there is a way that I can like
use the dissolve looking effect to make it look like the card is turning to stone
instead of what it does now
rn it just turns the card stone and says Stoned! under the joker
but the effect I have in mind is like, that dissolving-in visual the main card on the title screen does, over the card itself, giving way to the stone card texture
And potentially make the Stoned! pop up above the face cards themselves
maybe you could something similar to mida's mask
I considered it, but I wanna try and give it that specific creep-in effect
Make it look like the stone is spreading onto it, yk?
fair enough
I just can't find anything in the steamodded api documentation that would let me do something like that

so if anyone has any idead/solutions for how to do this, I'd be happy to hear em
I'm not aware of that being possible
destroy the card in hand with that effect and quickly add a card to the deck which is the one that is going to be played
maybe it doesn't work since I haven't read the documentations myself, but I feel like it's possible
My assumption was actually something like that!
I assumed the function for the main menu card exists somewhere in the game, so it would be possible for me to make it do that effect into a stone card, have that card placed directly over the face cards in hard with some sort of jank overlay, and then as soon as it's finished, it deletes the original face card and then stores the stone card into the deck
But that feels a little beyond smn that can be done with the current system
feel like it's gonna be a mess to code, but still possible nonethanless
that's not going to play nicely with effects that look at cards being added/removed
I figured as much
If I can't figure it out, I'll probably just go with the Midas style effect like Market suggested
if i want to add a global variable, i assume i will need a patch for this?
Depends when you need that global, sometimes you can init it yourself
I have an idea but first I need to know, are you able to apply shaders to seals?
Someone already made once a card that renders another sprite on top of itself
So you could play the card
Draw sprite
Turn card to stone
Dissolve sprite somehow
Tada
How do I check how many cards of 1 rank I have?
got this error message when trying to look at a deck that was part of the mod
i know this is the offending code because when I removed it the mod worked normally
i think u could js do G.whateverglobaluneed = value...?
what u want to add, btw
where is line 76 at
that's the odd thing
line 76 in this file is completely irrelevant
well is it a joker?
yea
but this error occurs upon looking at a deck
i think this might be because i'm using the T: indicator to bring up the pop-ups
Any idea where that code is so I could take a look, or who did it so I can ask them for assistance?
actually
why would it be
i tried looking at the other deck which doesn't have these and i got the same error
oh yh its in engine so its in main
maybe the deck isnt added properly?
idk.
maybe its bcuz theres no methods like calculate?
like i think its bcuz of apply method missing
since most of the decks have it
like +1 hand, +1 discard, or getting a voucher/consumables
probably
every joker has some sort of caveat to it
js put smth like apply(self,back)
end,
to the deck ur trynna add
`SMODS.Joker {
key = 'glyph_draft',
loc_txt = {
name = 'Glyph Draft',
text = {
"Gains {C:chips}+#2#{} Chips",
"if played hand",
"contains a {C:attention}Flush{}",
"{C:inactive}(Currently {C:chips}+#1#{C:inactive} Chips)"
}
},
config = { extra = { chips = 0, chip_gain = 10 } },
rarity = 1,
atlas = 'PowerOfTheGlyphs',
pos = { x = 1, y = 0 },
cost = 4,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.chip_gain } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chip_mod = card.ability.extra.chips,
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } }
}
end
if context.before and next(context.poker_hands['Flush']) and not context.blueprint then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
message = 'Upgraded!',
colour = G.C.CHIPS,
card = card
}
end
end
}`
If I programmed this right, it's "gain 10 chips everytime you play a Flush"
Gonna test it, but is there any obvious glaring flaws?
prob bnot
help i've resized a joker but the stickers doesn't resize, i've done everything like wee joker and i don't understand what's the problem
Is there a way to get/set chips/mult directly?
yh
u can js use mult ig
but beware
if ur using talisman its a bignum
doesnt matter?
which could cause problems if ur wanna alter them in sum way ig
but in most cases it works fine
you can either do some math to get the chips/mult difference or use hand_chips and mult globals
i tried to alter it once
almost died
from what i got told in cryptid server, normal operations work fine with bignum
oh, they're global, I didn't know lol
okay so how do i unfuck the decks, we went from being able to play the game as long as i didn't look at them to not being able to play at all
two new decks
one makes the mod's jokers more common
the other gives a bunch of stuff
-Eternal "Oops! All 6s"
-Two copies of Wheel Of Fortune
-Tarot Merchant
-starts you off with -10$
(yes, you start in debt with that deck)
that's literally the deck, omg..
What's the safest way to change ingame sprites and then be able to revert it?
Can I see your code?
oh hey it’s the guy who made showdown
hi!!!!
context.discard is for discarding but what is used to check if card is scored?
WAIT
MAYBE I NEED TO GIVE THE THING A CONTEXT
context.scoring_hand
Yes you can
I want "money" var to lose -1$ each time you PLAY a card. Am I doing it right?
On the joker?
yeah
to recap
this code causes this error
can someone help
still getting this error when trying to do the card skin part of the mod
Apparently it checks for SCORED cards but I need it to check for PLAYED cards
what is the context?
ok, the first deck is to make the mod's jokers more likely to appear
the second deck adds a bunch of stuff, an eternal joker, two wheels of fortune, the tarot merchant voucher and starts you off with -$10
and when i copy the code exactly as the example mod had it, blanks
You need to add the apply function properly then
There isn’t an individual context for played cards
Is there any way to make a joker only apply it's effect AFTER a card is scored?
Like, if I wanted this to score the face cards, then turn them to stone before they go back into the deck
how do i check if the played card has an enhancement or not? i have a joker which gives scored cards a random enhancement, but i dont want it to work if the card already has one
how would I go about doing that
@prisma loom
what variable do i use to change the player's money?
The same way you add functions for any other object
just checking here from the example mod, from where does the mod call for the #2# there?
okay but i'm looking through the api and i'm getting no clues
variables like #2# are set/called in loc_vars, if you'll look the base probability isn't set for a joker variable - it's set as a value the game itself has, to account for when odds are doubled by jokers like all 6s
handhold me as much as necessary, i'm sorry
ok is there a context or way to just count how many cards were played?
like The Tooth boss
i don't remember what exactly the base probability is but it should be the second item in loc_vars
got it
When do you want the effect to happen?
^?
config declares the variables themselves, while loc_vars is what actually sets the variables for use in text descriptions by the game - so you could set a text variable to a value that isn't explicitly declared by the joker, it can be arithmetic or maybe the value of a function to do with other jokers or cards
when hand is played, each card is a succession jiggles and says -1$ (Just like vs Tooth boss)
idk how this timing is called
ig just right when hand is played
what file do i mod in
context.other_card.config.center.set ~= ‘Enhanced’
right after i figured it out. Thanks though
eugh lua 😭
So even on unscored cards makes it a bit trickier, can you wait until I’m on pc and can type easier? 😂
how do i get the code to mod does it work from the steam .dll files?
no problem lol im just here sitting here and eating away your time folks
I think this could work but the context is wrong
uh this doesnt look right
yeah, thats what im sayin
Yeah you won’t get any unscored cards using context.individual
extract files from here via 7zip
(folder on the top is where all code and assets are gonna be)
is 7zip a program i download
after extraction
yes
how do i extract
i only have compress
"Open Archive"?
idk what that means lol
if u try to use this code and copy it 1:1 it wont work
BRO WHAT IS LUA
coding language
WHAT IS THIS WEIRD SYNTAX
ok but where does it define the powers?
those are the cards wheres where it defines the joekrs abilities
index starts at 1
ew...
except the times programmers decide it starts at 0
-_-
like x and y on atlas
do you know what file the jokers abilities are in
game.lua
yk what i shoud ctrl f to find it
and card.lua
P_CENTERS
i see where it defines the jkoekrs but it doesnt bvioe them the powers there
then ure lookin for card.lua
yeah thats defiuning the jokers but it doesnt give them the powers
what so i crtl f for the jokers here
Caino
no results
im gonna do a get used by nintendo speedrun and put all of their IP in the game
oh i found it
i live caino
wtf does this mean
what does what mean
said by the last face card in the deck
the code 😭
like what part of the code does what
do i go from
if self.ability.name yap yap yap then
yap yap yap
if self.ability.name ~= 'Seeing Double' and self.ability.x_mult > 1 and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then
return {
message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}},
colour = G.C.RED,
like how does the game know how much mult to give for this?
A better question is what are you trying to achieve
just how to create new jokers and what i change to change the chips/mult/multipler/econ/creation
i just kinda need to understand what the code does to udnerstand how to change it
fyi i have no experience with lua :3
Looking at the game source code isn’t really going to help then
You need to look at smods and see how modded items work
can i not just copy and paste the joker declaration and change the stuff
If you’re only working personally I suppose you can modify the direct source code sure
But it’s more complicated than using the modding tools that have been made for you
I’d recommend playing with mods before looking to create them
Then at least you are aware of the systems they use
but thats so much effort 😭
If you’re not prepared to put effort in I’m not sure making a mod is going to be something you enjoy
i perfer coding then actually playing the game 😭
cuz im like hyperfixated on coding a mod rn and i cant get myself to do anything else like play a video game 😭
Then go and read the information about the modding tools
is their a link you can give me?
yeah you're not going to make a mod easily without checking the tools people use to do that lol
everything ive googled gives me instructions to download mods not to make mods
cause modifying the source code is very different from making a mod
i didnt knwo their were special tools for it
i just kinda guessed
i mean i'm not sure how else people would make mods lmao
i thought they edited the source code ngl
if they did that, there'd be no easy way to distribute mods and have multiple installed
does text formatting color support arbitrary colors
or better yet, could i set up a custom one
mostly for convenience
ok i downlaoded that stuff what now
read the github wiki page
i did
like how do i mod it now
i have it all installed but what do i do to start modding
do i just change the soruce code now?
the wiki should tell you how to make a mod
No, you make your own mods.
Your First Mod ► https://github.com/Steamodded/smods/wiki/Your-First-Mod
the whole right bar on the wiki is PACKED with info on how to make mods and what you can do with SMODS. Read that and try your own solutions before you come here, please.
it just says to do it and doesnt say anything else
ohhh
otay
how do I modify a sound such that it sounds normal while it's in balatro
game fucks with the sound ingame so it sounds different
is there a check for if a card is Enhanced? I'm surprised the example Jokers don't have stuff like Vampire and Bloodstone as examples you can look at. Right now I just have the empty context and I'd like to have it check if the scored card has any Enhancement, and then score some XMult if it is
You can always look at the base game code to see how vampire or bloodstone work
to answer your question tho, in your situation you can check with
context.other_card.set ~= "Enhanced"
I haven't quite figured out how to navigate the base game code aha
to check whether a card has no enhancement
Most of the logic for jokers is in card.lua
You can ctrl + f their name to quickly find it
and if I want to check if it does, swap out the ~ for another =?
this is vampire, for example
correct
if Visual Studio wanted to run it'd be real handy 
okay so I think that's right, so now I just need to find the applying mult code
goody
oop!
I see
so in theory, this, should do what I'm hoping?
not quite
you have to return those values in a table
return {
values go here,
comma separated
}
like so?
right, like that
also for reasons i don't actually know you want to use card in smods wherever vanilla uses self
so that makes the card = self redundant yeah?
i think card means two different things in that context? but also smods makes card = card default anyway iirc
alright so this should work, and if it doesn't I should probably uncomment the card = self
Just xmult = card.ability.extra.Xmult is needed here
Though this won’t trigger
Because of the cardarea check iirc
oh?
alright sweet time to
hopefully get this Rare card in a run so I can make sure it works. :)
you are in fact correct
it did not trigger
for the love of God please use a code editor that isn't notepad 
context.other_card.ability.set is what you need for the set
yeah, that line
context.other_card.ability.set == 'Enhanced'
hell yeah
okay well this is really convenient to make sure copying works
and it does, sweet
for some reason this just. deletes the entire score instead of adding anything?
extra = {
chips = 0, chips_gain = 1,
mult = 0, mult_gain = 2,
Xmult = 0, Xmult_gain = 0.3,
odds_chips = 2, odds_mult = 3, odds_Xmult = 4
}
},
loc_vars = function(self, info_queue, card)
return {
vars = {
(G.GAME.probabilities.normal or 1),
card.ability.extra.odds_chips,
card.ability.extra.odds_mult,
card.ability.extra.odds_Xmult,
card.ability.extra.chips_gain,
card.ability.extra.mult_gain,
card.ability.extra.Xmult_gain,
card.ability.extra.chips,
card.ability.extra.mult,
card.ability.extra.Xmult
}
}
end,
calculate = function(self, card, context)
if context.after and context.cardarea == G.jokers then
if pseudorandom('j_roxanne') < G.GAME.probabilities.normal / card.ability.extra.odds_chips then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chips_gain
card_eval_status_text(card, 'extra', nil, nil, nil, {colour = G.C.BLUE, message = 'Chip!'})
end
if pseudorandom('j_roxanne') < G.GAME.probabilities.normal / card.ability.extra.odds_mult then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
card_eval_status_text(card, 'extra', nil, nil, nil, {colour = G.C.RED, message = 'Mult!'})
end
if pseudorandom('j_roxanne') < G.GAME.probabilities.normal / card.ability.extra.odds_Xmult then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
card_eval_status_text(card, 'extra', nil, nil, nil, {colour = G.C.RED, message = 'XMult!'})
end
end
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
Xmult = card.ability.extra.Xmult
}
end
end
}```
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult_add, card.ability.extra.pool } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and not SMODS.has_no_rank(context.other_card) then
if context.other_card:is_face() then
card.ability.extra.pool = card.ability.extra.pool + card.ability.extra.mult_add
return {
extra = { message = localize('k_upgrade_ex'), colour = G.C.MULT },
colour = G.C.MULT,
card = card
}
elseif context.joker_main then
return {
message = localize { type = "variable", key = "a_mult", vars = { card.ability.extra.pool } },
mult_mod = card.ability.extra.pool
}
end
end
end
}```
After having a chance added and then removed, this no longer scores its stored Mult
what variable is tied to the money? Im trying to make a joker that changes your money but cant find the variable it uses.
XMult is 0
I'm trying to make a Boss Blind that randomly disables 1/4 of the full deck. Anyone have any ideas as to why none of the cards are getting disabled?
man this is like identical to the code from yesterday, what the helll
Im going to bed soon
ah right I'll do it now 👍
no I mean like I might not respond XD
dont rush urself for that
it's fine I'm on my pc now
can you send the full joker for me then I can get variable names correct?
and what do you want to happen?
it decreases whilst still charging right?
charging?
the 3 round count
how do you add temporary discards
ease_discard(1)
if context.before then
for _, played_card in pairs(context.full_hand) do
card.ability.extra.money = card.ability.extra.money - 1
SMODS.calculate_effect({
message = '-$1',
colour = G.C.RED,
message_card = card,
juice_card = played_card
}, card)
end
end
if context.end_of_round and context.main_eval then
card.ability.extra.coffee_rounds = card.ability.extra.coffee_rounds + 1
if card.ability.extra.coffee_rounds == card.ability.extra.target then
card.ability.extra.active = true
local eval = function() return card.ability.extra.active end
juice_card_until(card, eval, true)
end
return {
message = card.ability.extra.active and localize('k_active_ex') or card.ability.extra.coffee_rounds .. '/' .. card.ability.extra.target,
colour = G.C.FILTER
}
end
if context.selling_self and card.ability.extra.active then
return {
dollars = card.ability.extra.money
}
end
this should work
is there any reference sheet on common/needed balatro code and what they do? I'm having trouble misunderstanding what a lot of this stuff does and why this is needed
Hello, i have this error, could you guys please help me?
It happens when perkeo duplicates a tarot card i have if i then sell the non-negative card.
Hm, most likely Saturn is not compatible with better-calc or smth
does saturn stack the negative and non negative cards?
It definitely stacks negative cards
it doesnt stack them together
better-calc?
Treat it as "new versions of Steamodded"

let me see if I can reproduce
Her'es a thing
3 mods = same crash
My mod definitely not intersect with editions
Removed saturn not fix an issue
So problem with Brainstorm
probably then
yeah I don't get that crash
without brainstorm (in same run)
i tried removing only saturn then only brainstorm, am doing for both
btw, those crashes happens in the same run, they might not happen if i start a new run idk
it doesnt happen in a new run without every mod
@primal robin do you use Saturn and/or Brainstorm ? might i ask you to send me the version you have for each of those QOL mods you use and dont have the crash with? that'd be great
it seems like one of them is tainting the cards
i believe it is saturn
None of them. I'm not playing a game, only developing mods
minor bug but it "repeats" -1 on first card for some reason
oh okay hold on
try this
if context.before then
for _, played_card in pairs(context.full_hand) do
card.ability.extra.money = card.ability.extra.money - 1
SMODS.calculate_effect({
message = '-$1',
colour = G.C.RED,
message_card = card,
}, played_card)
end
end
tracked down the saturn thing, it sets the card.edition to an empty table instead of nil if it's not present
Tried my hand at writing one independently
key = 'revolver',
loc_txt = {
name = "Revolver",
text = {
"Every {C:attention}sixth{} card scored",
"gives {X:mult,C:white} X#1# {} Mult {C:inactive} [#2#] {}"
}
},
rarity = 1,
discovered = true,
cost = 5,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
atlas = "jokers",
pos = { x = 2, y = 0 },
config = { extra = { Xmult = 2, cardTrack = 1 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult, card.ability.extra.cardTrack } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if card.ability.extra.cardTrack == 6 then
return {
x_mult = card.ability.extra.Xmult,
--card = self
}
card.ability.extra.cardTrack = 1
else
card.ability.extra.cardTrack = card.ability.extra.cardTrack + 1
end
end
end
}```
If I could get a once-over to see if I've properly written it
need to move the reset above the return
kk, fixed that
rest looks good
didn't crash when loading!
All good now!
Huge thanks for help

no problem!
does this set cost to zero?
did you help make the process_loc_text function for steammodded
becaus ei need a lot fo help
worked exactly how I wanted first try let's fucking gooo
On a joker, are you supposed to increment a multiplier before or after scoring? Like if a card starts at X1 but gains X0.5 when Two Pair is played, do you increment after scoring the X1? or is that all based off how the ability is written?
both are possible, but i think it's usually before the hand scores
I do t think you need to process loc text in that situation
seals needed too
huh anyways this wont work either
Seals don’t need you to
its a seal like object
but is not a seal because its its own game object
hm, i have a tag that creates a booster pack, but unlike the vanilla tags multiple of them are able to trigger at the same time and it breaks everything
i'm unsure what prevents this from happening
Hmm maybe it does, let me compare to my new object
Can you show a sigil definition?
All credit to ya! Card in action:
this ?
Add _sigil to the key
: |
Could it be adding insc_ before it?
il try
Do you have any lovely patches regarding this?
uh maybe not sure
if i did i dont know wher ei would patch in
i have this one for badge
didnt work
Cool I have a couple of others that I think relate to it but I don’t remember
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''local seal = G.P_SEALS[v] or G.P_SEALS[SMODS.Seal.badge_to_key[v] or '']'''
position = 'before'
match_indent = true
payload = '''
local curse = Ortalab.Curses[v] or Ortalab.Curse.badge_to_key[v] and Ortalab.Curses[Ortalab.Curse.badge_to_key[v]]
if curse and curse.generate_ui ~= 0 then
local t = { key = v, set = 'Curse' }
info_queue[#info_queue+1] = t
if curse.loc_vars and type(curse.loc_vars) == 'function' then
local res = curse:loc_vars(info_queue, card) or {}
t.vars = res.vars
t.key = res.key or t.key
end
end
'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''elseif _c.set == 'Joker' then'''
position = 'before'
match_indent = true
payload = '''
elseif _c.set == 'Curse' then
localize{type = 'descriptions', set = 'Curse', key = _c.key, nodes = desc_nodes, vars = specific_vars or _c.vars}
'''
should be able to adapt these
don't remember what they do lol
How can I know in code which deck/back the player is using?
can you tell what value is nil
not without your dumps
Any idea on how/why this happens? I keep trying to do the deck skin part of the mod and it never works.
Actually. I think I see what my problem is now
wait i found this patch
wait nvm thtas the new one this is the one i found
How do we set the mod prefix again?
iirc it had to do with something in the mod header
--- STEAMODDED HEADER
--- MOD_NAME: Astarion - Joker
--- MOD_ID: ascendant_joker
--- MOD_AUTHOR: [shadowfelled]
--- MOD_DESCRIPTION: Adds a matching Joker that gives X2 Mult when Diamond face cards are scored.
----------------------------------------------
------------MOD CODE -------------------------```
that part
--- PREFIX:
thank
what was the line that crashed in the dump?
misc_functions.lua:1974
yeah I'm not scrolling through your dumps
ok I give up, the function of it upgrading works (I think?) but it just doesn't wanna give me the score to it
I think the newer .json meta format is preferred
https://github.com/Steamodded/smods/wiki/Mod-Metadata
gotcha
whats the problem?
it just doesn't. add the amount the joker has to the calculation
did I accidentally made it random?
I'd need to see more of the code
got it hold on
and how are you testing it?
by....playing it with the debug mod?
because the first time you play cards this will do nothing, and then randomly upgrade some of the values, but if it doesn't upgrade all 3 it'll continue to not trigger
how would I modify the ability.set to check for both Stone and Steel cards?
so you're kind of just waiting for it to upgrade all of them at some point before it will do anything
any idea why this is whats crashing
Oh
what set are you giving it?
oh that would make sence
you can change the equality checks to be >=
which one?
or is it as easy as
if context.other_card.ability.set == "Stone" or context.other_card.ability.set == "Steel" then
all of them
context.other_card.config.center_key == 'm_stone' or context.other_card.config.center_key == 'm_steel'
ahh
?
no
oh ok
btw @wintry solar in the current implementation of the select_card thing for boosters
is there a way for the select to work for different types of cards in the same pack
how do you mean
well for my mod, I have some consumables that go to the consumable area, and some that go to my custom cardarea
no
whats the custom type with an area?
I have cards that go on the right here (G.weapons in the code)
in mimicking the source game, the booster pack has a lot of different types of cards in it
I can maybe add that functionality then
if context.individual and context.cardarea == G.play then
if context.other_card.config.center_key == 'm_stone' or context.other_card.config.center_key == 'm_steel' then
return {
mult = card.ability.extra.multWM,
card = context.other_card
--card = self
}
end
end
end```
So when I was using `mult_mod` it worked but didn't have the +Mult message, but then I read the Example Walkie Talkie which uses `mult` because that comes *with* the +Mult message, but when I implemented that, it doesn't score at all now
remove the card = line
I know that won't fix it, because it wasn't there the first time I tested mult
is your config table set to multWM?
why dis no work
yes!
also i got erh text to work thanks Eremel
are you sure it's not working?
I'll test it again but pretty confident
there's no reason mult_mod would work and mult wouldnt
the only thing I can think is that putting card = context.other_card is messing with where the message would go because of how contexts have been reworked slightly
hi, i'm new to balatro modding. how do i add my own hand card style like the collabs?
I'm gonna try the mind-blowing solution of just, checking if instead of a variable, I just, put mult = 18
i have smods set up (i think), some lua experience, and texures for the face cards
I recommend the Deck Skin Template example mod
this worked
you might jsut need to respawn your joker
thanks. i wasn't sure as it seems to contain the whole 2-a suit
You can just add less ranks, although if you want to use a different format for the atlas you also need to change the setting for that
i think i saw where in the lua to set that
I think I have a working example
thanks
how would i check for how many fours there are in the deck?
Quick bump to this one
pls can u send,,
Create a tally variable to keep track of the number, do a for k, v in ipairs(G.playing_cards) and iterate your tally variable if v:get_id() == 4
local four_count = 0
for _, v in pairs(G.playing_cards) do
if v:get_id() == 4 then
four_count = four_count + 1
end
end```
working on a dynamic blind scaling system (https://github.com/DigitalDetective47/strange-library/tree/90920c5660c81889e4905144d32b7720af6e195f) and am getting an error that i can't seem to debug
get_blind_amount just returns nil for no reason??
what's the way to get the chip value of the card being scored?
hmm, ssssomething with these?
indeed, context.other_card.base.nominal assuming you're accessing it in individual context. else replace context.other_card with whatever the scored card is

