#đ»ă»modding-dev
1 messages · Page 344 of 1
Brain did stupid again
At the top of every lovely file there something like this, the priority means the order lovely will take when patching.
Higher numbers go last.
ah, so it's literally just arbitrary number set, gotcha
Jen with his infinite priority
I see why that would be annoying for mod compatibility
(Or is it negative inf?, there's benefits to going first an)d last
Tbh i think he had to change it anyway
It says naneinf so I assume last.
Tbh I think everyone patching blindly into the same code base is exactly what a modding api like smods is supposed to prevent
There's a reason even lovelydev says patches should be a lost resort
If youâre sensible about it, patching is fine
Fine sure, but inherently less ideal imo
Thereâs a lot of things that you canât do without patching
err yeah it's counter intuitive
but it makes sense in my head so
does anyone know why it's crashing?
yeah, use patches judiciously and it'll be fine most of the time. good patch hygiene also helps quite a bit.
what error are you getting?
Whatâs good patch hygiene
i did send the error
ah mb
here

which would then break a patch which targets the line that was overwritten
Obviously
that's one of the good used of at patching
But without an API for such specific lines itâs not easy to handle it well
yeah it's unwieldy
An alternative are multiple patches trying to mimic a logical operator
Like nesting an if inside another for and
But is multiple patches better than one?
It also depends on other factors, since you canât always do that neatly
so, can u tell what's causing it? bc it looks like nothing should be wrong
it's all about using the right tool for the job. in general if you can avoid an at patch in a way that is convenient then please do so, otherwise it's fine.
no clue! sowwy
I'm just the patch guy
fair
I'm also on mobile so my debugging ability is pretty limited
once again thank you so much for making lovely so we dont have to manually patch the exe every time we update
ah
Metheuwul
yeah. smods did similar-ish patching to the game but that functionality wasn't exposed
which was really limiting if you were making a mod
fun times
i remember scrapping at least one joker because it would have required a patch
In the future when we have Quantum Ranks and the Great Joker Supercollider: âForsooth, we were such caveclowns once in the past.â
back then I guess your only option was to copy what smods was doing and write a weird powershell injector
caveclowns as a word goes fucking hard
i dont remember anyone doing that because that would have been Horrible
haha yeah
lovely patches aren't easy per say but they at least make it a viable thing to do
im still shocked that codex arcanum worked without any lovely patches
although I've also been really happy with how good the patch format has held up over time. it's been pretty flexible, all things considered.
really? jeez
that's impressive
yeah but that led to some issues with crossmod compatibility iirc?
actually i know that happened because that's the reason colour cards weren't in the shop pool originally
the old crash had other mods that may be interfering. here's a newer crash log with just my mod enabled
back then we had .98 and a stick and we liked it
1 million downloads is actually mind boggling, thanks guys
wow
the scene has definitely come a long way haha
and it's remained really strong which has been cool to see
I guess that'll always be true without smods rewriting the entire game to make it fundamentally modular and expandable, patching it in, and exposing every api imaginable. Which would of course be mikelyyears of work and break everything that already exists
Maybe when balatro is a retro game in 20 years
And not a living codebase
maybe in a couple of years
it'll be interesting to see how things break when the game updates
would checking how many cards are not scoring be something like #G.play.cards - #context.scoring_hand ?
Back in methâs day they coded uphill both ways
how would you go about writing the effect for this?
Return swap = true
hey, does anyone happen to know where the buy and sell values of each card is stored?
card.cost and card.sell_cost respectively.
oko
right uh what else do i need to do to make it work
right now it just prints hello
i might just be completely misinterpreting what the swap function does
Do it in context.joker_main
ah ok
i wanted to have it do the swap before chip/mult scoring jokers activate, is there a context that would work for that
i just tested joker_main and it did it after mult scoring
#context.full_hand - #context.scoring_hand
Or you can loop in full_hand and use not SMODS.in_scoring()
oh i see it does it before xMult interesting
ok so whattup someone was showing me how to do multiple deckskins in one file
but i gotta set the atlases up for multiple suits in one png
OH thats what deck style means i am a gemius
ok so, obviously im an idiot, what do i wanna set key and loc_txt to for a suit
idk what theyre used for
Do you mean for the palette?
Key is an internal identifier
loc_txt is for the localization. I think for DeckSkins itâs the name displayed in-game
does that mean when selecting it or does it like, replace instances of that suit's name
Selecting
How difficult would it be to make a Balatro mod which adds a few new jokers, with zero experience? Obviously, it would likely depend on how complex the jokerâs functions are but if weâre speaking generally?
Iâve got a bit of HTML experience from school but really nothing else outside of it lmfao
I'm currently in the process of doing that myself and it's not awful
Plus they're really helpful here whenever I get stuck
well id suggest checking out #1349064230825103441 :p
and if you have any problems, feel free to ask here
i personally think its not too hard, since lua is pretty straightforward
Hi
Yooo that's insane
i mean i started a few months back now? and i've made all this stuff so like id say as long as you like use resources like the balatro source code and look at how other mods did some things you'll get the hang of it
how would i make all cards of a certain type be âconsideredâ as a different card
hiya! i'm making a Planet card â what goes in loc_vars?
can't find where the game put the planet loc_vars
you can look at what potassium does
just remove the Glop stuff
ah thanks :D!
can you elaborate?
i want to make a joker that makes all face cards be considered queens, without changing their rank
in a similar fashion to how paradolia does it, for example
i'd hook get_id()
you might want to hook get_id for that
you'd need to hook into get_id
damn triple jinx
so would i check for presence of the joker in the hook?
SMODS.find_card
The "Maximized" Joker from the Cryptid mod does something similar, I had to reference it for my own one
whereâs the doc for that
it's in the wiki under utility iirc
Anyway how would I go about destroying a random card in my full deck, not held in hand
go through G.playing_cards
And I reckon context.destroyed_cards also works within the full deck?
i think so :p
what does get_id take?
the id of the playing card
I guess no one is daring enough to nix cards in the full deck yet
it takes self
thanks
đ€
destroy_card works with G.deck but it's an optional feature
if i do SMODS.find_card(âfoobarâ), will it return true if found and false otherwise
Optional?
yes you need to enable it because calculations in deck are performance heavy
SMODS.current_mod.optional_features = {cardareas = {deck = true}}
provided a card with the key foobar exists
put that at the top of your code
for your effect you don't need destroy_card tho because you don't need to do it during scoring
Ah, I guess that's why the effect isn't common
it returns a list of cards, use next(SMODS.find_card(...))
o alright
just like that or replace the elipsis with the key of the card i want to be found
and iâm guessing that would return nil if it canât find anything?
nah, you dont need that if you destroy them when blind is selected
i have this and i dont use the optional features
Fucking awesome
exactly
alrighty
iâm getting better at this lua stuff
outdated code but
Hi :3
what does get_id() return?
does it return a string
int
When I get home, I'm going to take a break from Pikmin and instead work on Pronouns for playing cards in Balatro
ids above 10 are jack, queen, king, and ace respectively
2-10 for 2s-10s, J 11 Q 12 K 13 A 14
so 11, 12, 12 and 14
12, 12
whats SMODS.get_id? đ€
j_modprefix_key
checks the id of a card
o
-# wait why did i forget that, i literally just answered above
now to actually make the joker
bepis
this shouldnt be too hard as ive already defined what it does
just gotta make a fun design, write some loc_txt and call it a day
im gonna make a ritual card like the crooked coin from tboi
One question, i wanted a Joker to display a timer in its textbox, do i have to update the textbox every frame to make it display in real time? How can i do that?
didnt you want only face cards
you're so right actually
should i use the og function to check for the card's actual id
add a UI element with main_start/main_end
dont do is_face or you will get an infinite loop lol
Alright, thank you
can i do if smods_ref_get_id() == 11 or 12 or 13 or is this really stupid
wait
ykw
lets try it
yes
yes but only if it's coded properly
meaning?
yes: x == 11 or x == 12 or x == 13
no: x == 11 or 12 or 13
I couldn't tell if that's something you already knew so I felt it was important enough to point out
ohhh
alright
so how do i make this work with paradolia
do i just adjust wording
instead of face cards iâll say âmakes all Jacks and Kings be considered Queensâ
you can just hard check for it
that works I guess
you could also do the same thing Astra did #đ»ă»modding-dev message
I've been making a card that reduces blind requirement by 19% and it works well but when you have more than 1 or it's being copied by blueprint/brainstorm all the reduction happens at once and I sort of want it to happen one at a time like when mult is added or smth similar. Is there any way I can do this? (video of card and code I made attatched, card.ability.extra.blind_dec is set to 19)
oh yeah
but face cards in general seems op to me
so iâll restrict it to kings and jacks
for balance
The event manager?
sorry, im new to this, but now the message wont appear and it still all happens at once, have i implemented the event wrong?
Use SMODS.calculate_effect for the message and return true at the end.
same problems again, have i formatted the calculate_effect wrong or something?
SMODS.calculate_effect({...}, card)
omg teto balatro mod
I've got this and the message is appearing but the blind still decreases all at once
ive tried both replacing the context.setting_blind with context.cardarea == G.jokers and combining them into 1 statement (if context.setting_blind and context.cardarea == G.jokers then) but neither make it work how Im trying to get it to. Just incase I wasn't clear earlier I want the blind to decrease when each individual joker activates instead of decreasing all at once at the start of the round
I think you can keep the message in the return and just use the event for changing the number
It should queue the message immediately after the number change (which takes no time so it seems st the same time)
I'm confused by this math btw. This isn't even 19% reduction?
oh wait 800 base blind size
ohhhh
i dont know if this is what u meant but I tried it like this and it still all decreased at once
wilson meant a return outside outside the event
Like you had before
you could also try delaying the event with an after, or changing the context to be on round start instead since I suspect it's setting the blind size outside your visual view
this one worked for me, thanks everyone!
new to modding, not sure why my joker isn't triggering
supposed to give x2 mult when light cards are scored
Try card = card, never use self most of the time.
Also card.ability.extra.Xmult
Can you refer to an SMODS joker's calculate function? Gotta be stored somewhere in it's card right?
is that related to what i'm doing or is that just a question
Nah just a question sorry
ah ok
You can get it from G.P_CENTERS[card.config.center.key].calculate you can't modify it or anything you can only run it.
just a guess as I'm also new but because you've referred to your card as center elsewhere (like in the variables section), wouldn't you have to refer to it as center when calling your variable?
also also I don't think the next(SMODS.has_enhancement(...)) does anything when put there Liv
That should work, thank you!
what should i do then?
I don't think card.enhancement is a thing that exists?
I don't think so either. You should has the has_enhancement to see if... the card has the enhancement
so like this?
No, just do if SMODS.has_enhancement(context.other_card, "m_cry_light" then also you need to be in a context.
Also you need to return x_mult = card.ability.extra.Xmult
??
Put that in a big if saying if context.individual and context.cardarea == G.play then
put what
Put everything inside the calculate function in that if.
ah
did you figure this out cause im trying to do the same with one of my enhancements and this does not work
still nothing
how do i decompile balatro's code again?
open the exe in winrar
What extraction software do you use?
7zip also works
i dont have one, which one should i use?
What if you looked if any of those jokers are present and changed a value in them?
i use 7zip personally
Probably 7zip
aight
- set
card.[var_name] = truefrom inside the card when it triggers - check for
context.other_card.[var_name]in the joker
(btw how do yall make the text look like that)
`like this`
i'm not sure what could be wrong now
so card.brick_trigger = true and context.other_card.brick_trigger?
yea
yippee
does increasing priority of my lovely patches make it so it happen first?
No, it makes it happen last I think.
ack
card.lua
and then what do i search?
What are you looking for?
you can also color it per language with
code = function()
--comment :>
end
just the base +4 mult joker
i tried searching for "joker" but theres like 300 results
self.ability.name == 'Joker'
this?
the use of both 'text' and "text" bothers me in the games code, i wish the search feature had an option for counting ' and " as the same thing
jimbo!
is that really all the code it has?
ok fair but it doesnt look like it would +4 mult
and where would i find that?
good quesiton, im trying to find it too
I believe it happens later for lovely patches
cuz i wanna make a test joker that just does +4 mult but ive never made a functional joker
Are you talking about this?
wait are you using smoded?
yess
actually, how do i make a joker that just does x1.25 mult?
You would return xmult = 1.25
they have a regular jimbo in there, its a perfect place to start
okay im probably just bad at lua but why is G.hand.cards[0] yielding nil when there is an active hand
wait because lua is indexed at 1 i forgor baffling language
yeah
Wait until you see my js code that's using 1 indexing
i love the first mover advantage!!!!!! i love how terrible design decisions become the industry standard because it was the first option on the market!!! woooo!!!!
i like indexing starting at 0 because from a computer standpoint it makes more sense, 0-9 instead of 1-10 to save on digits, etc
i this how i patch all (area.cards) to (area.cards or {})?
To be fair in C 0 indexing makes sense since an array is just a pointer and indexing is just pointer arithmetic
Regex has special meaning for ()
yeah this is the reason, a[n] could be reduced into basically a simple add $a, $n; load $a instruction
You'll need to escape them
\{\}
ahhh icic, thanks
"escape" sounds way more awesome than any other alternative
so something like \(\area.cards\)\?
\(area.cards\)
you dont need to surround them
you just need slashes before
do i have to do that for payload too?
I don't think si
oh my god it lives, thank you guys so much
regex is fun! its literally knitting instruction syntax + 60 years of hacky workarounds and legacy cruft!
:3 looks as fun as trying to understand shaders, thats for sure
whatd i do wrong đ
--- Joker Test ---
SMODS.Joker {
key = "jokertest",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25{}"
}
},
config = { extra = { mult * 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "Jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
mult_mod = card.ability.extra.mult,
message = localize { type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }
}
end
end
}
main.lua.lua
mult * 1.25
should be mult = 1.25
Did you end up figuring out of getting help with your mod desx?
i want it to xmult, not +
sadly not
mult_mod only does mult, you would need xmult_mod ( i think thats what its called)
Why is your file called main.lua.lua?
oh wait nvm, that was from my old patch
turned out it didnt work
old-ish file
Did you ever do this?
that was a mistake i made then and i forgot to fix it
Try escaping the .
no, i was infact not online
Damn lying green dot
real
...i really have no clue how to do this
is it xmult instead of mult_mod?
Just put a backslash before it
idk why the examples use mult_mod instead of just mult
mult, Xmult, and chips all do the same thing as the _mod versions, but they call the game's functions so there is a little animation too
didnt work
Regex terrifies me but is actually quite useful. There are websites online that will let you check your pattern to see if it'll work
Try checking the pattern itself, if the pattern is fine then you may need overwrite = true in your patch
okay it works, but it displays the image twice, one red and one orange
(from the smods wiki on github in the calculate function section)
What image?
Mult mod is the modifier usually used for scaling jokers
nvm fixed it
oh you dont need to return message, returning Xmult does that for you
yep
yea the _mod stuff its useful to know, but not to start with
i checked the website, everything seems fine
now i hope this question doesnt make yall mad considering the F situation but how do i play a sound?
(and what file format should it be?)
use SMODS.Sound to add the sound to the game, and play_sound(key, pitch, volume) to play it
.ogg preferred, .wav is okay
okay why did it replace the last occurrence, not everything
what should i put in here?
thats for if you are adding sounds, are you?
I pressed keys and paths and stuff
like, new ones to the game
WHY IS IT NOT WORKING
Do you understand what it says on the wiki? If not what's confusing?
Show your patch again
not really, i cant find out if it says what i need to put there or not
nor where
According to the wiki, required parameters are key and path
Seems pretty straightforward?
same as any object (that references a file)
oh mb
Whoa what is that target saying
It might be correct but I've never seen that syntax
its targetting src/utils.lua from SMODS
why does it give an error?
im pretty certain thats correct, unless target in patches.pattern works differently compared to patches.regex
normally i dont have to put a comma there
As for format, use ogg. I'm sure there's a reason if says not to use mp3 despite bent supported, abs wave is unessacarily big
yeah i am
Do you have a meow.ogg, with an unstandard capital M is /assets/sounds?
yup
how would I add a sprite to my mod's config tab? would i useG.UIT.O?
yes
Here's a regex patch I wrote, I remember it being weird and funky so maybe you need to do the single quote thing like I did
[[patches]]
[patches.regex]
target = "functions/state_events.lua"
pattern = 'hand_chips\*mult'
position = "at"
overwrite = true
match_indent = false
payload = "hand_chips^pow*mult"
i will try
You still didn't lowercase your folders
And why do you have extensions hidden?
But I'm not sure either of those things would cause this
What if you put the comma it wants?
Tbh I think we need the whole file
whats the error
A bigger screenshot would be helpful
whats the card field determining if something is flipped over or not
i.e during wheel or water
nvm found it
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: xmpl
--- Atlas ---
SMODS.Atlas{
key = "Jokers",
path = "JokersTest.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.Sound{
key = "Meow",
path = "Meow.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokertest",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25{}"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "Jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = card.ability.extra.mult,
Sound = Meow
}
end
end
}```
Sound needs to be lowercase?
That doesnât matter
can someone tell me how to add an edition that uses a scribbled.fs shader??
I see why it says you need a comma after the sound def.... you just do I think
Well, it does matter, but thatâs not why itâs crashing
Is there a crash report?
Your return is incorrect
You need to put the key of your sound as the return value
Clearly it does lol
Your sounds folder being /Assets/Sounds instead of assets/sounds can't be ideal
Not the crash
But still
yeah i changed it
I believe the key is probably "prefix_Meow"
In quotes
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: mod
--- Atlas ---
SMODS.Atlas{
key = "jokers",
path = "jokers.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.sound{
key = "meow",
path = "meow.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokertest",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25{}"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "Jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = card.ability.extra.mult,
sound = "mod.meow"
}
end
end
}
well this doesnt work
mod_meow
SMODS.Sound
Oh he had that correct before
bumping this but now as a general question
Atlas needs to be jokers
Code?
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: testmod
--- Atlas ---
SMODS.Atlas{
key = "jokers",
path = "jokers.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.Sound{
key = "meow",
path = "meow.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokers",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25 {}mult"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "Jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = card.ability.extra.mult,
sound = "testmod_meow"
}
end
end
}
So the atlas field in your joker is still capitalized
But the key of your atlas is lowercase
so change line 39 to lowercase
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: testmod
--- Atlas ---
SMODS.Atlas{
key = "jokers",
path = "jokers.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.Sound{
key = "testmod_meow",
path = "meow.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokers",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25 {}mult"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = card.ability.extra.mult,
sound = "testmod_meow"
}
end
end
}
still doesnt work
quick question is that atlas working now
no, visual
this one works if you're talking abt that
ok cool
can you put parentheses around the brackets in the sound one just in case that is it
around thr brackets
??
theres like 10 brackets in the code
the ones in ther sounds atlas?
cuz that just gives an error
Sounds donât work with automatic messaging iirc
i just realized ur using an auto message
so how do i do that then
return it manually
You need to add remove_default_message = true too
to where?
outside of calculate im p sure
like this?
try a localized message instead so you don't have to type out a string
how do i do that?
regular +mult version of what i mean
though in your case itd be x_mult i believe (do xmult if it doesnt work cause i tend to get them switched up)
it works, but i want it to be red, and it displays ERROR
send code
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: testmod
--- Atlas ---
SMODS.Atlas {
key = "jokers",
path = "jokers.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.Sound {
key = "testmod_meow",
path = "meow.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokers",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25 {}mult"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
sound = "testmod_meow",
remove_default_message = true,
message = localize {type = "variable", key = "x_mult", vars = {card.ability.extra.mult}},
}
end
end
}
Why did you remove the xmult?
And it should be a_xmult
yeah thatd do it
got them switched again đ„
its still yellow tho
nice
--- STEAMODDED HEADER
--- MOD_NAME: Test Mod
--- MOD_ID: TEST
--- MOD_AUTHOR: [CebeeDrawz]
--- MOD_DESCRIPTION: Test Test
--- PREFIX: mod
--- Atlas ---
SMODS.Atlas {
key = "jokers",
path = "jokers.png",
px = 71,
py = 95
}
--- Sounds ---
SMODS.Sound {
key = "mod_catsalad",
path = "catsalad.ogg"
}
--- Joker Test ---
SMODS.Joker {
key = "jokers",
loc_txt = {
name = "Joker Test",
text = {
"{X:mult,C:white}X1.25 {}mult"
}
},
config = { extra = { mult = 1.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = "jokers",
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
sound = "mod_catsalad",
remove_default_message = true,
colour = G.C.MULT,
message = localize {type = "variable", key = "a_xmult", vars = {card.ability.extra.mult}},
xmult = card.ability.extra.mult
}
end
end
}
``` well i changed the sound and now it doesnt work
Remove mod_ when defining your sound.
i do it with the mod prefix on both and it works fine?
@daring fern
are we fr
made a new save file and it crashes whenever the joker activates
That's from the games files.
yeah
That means there is something wrong with the sound.
maybe cause theyre using old header method?
What does your sounds folder look like?
Is that an ogg file?
is it acrually an ogg fi- yeah
yep
Your sounds folder needs to be in assets
oh
how do i play a sound from balatro again
i think you just use the base game's sound key?
Look in resources/sounds from the main game files and look at the file name and that is the usually the key.
Use play_sound multiple times.
simply do it again
Your overwriting the old sound.
use play_sound
how do i make it not do that
oh okay
like this?
that still overrides it doesnt it
play_sound
oh
this was used in an event though i dont actually know if you can call it straight up in the return
well it works but it plays it whenever i play the hand, not when it activates
that would have to be a different context though wouldnt it
how do i do that then
maybe?
like this?
try it
No, try doing ```lua
func = function()
play_sound('multhit1')
play_sound('mod_catsalad')
end
In the return.
true just making it func is way easier
That's because you don't have it enabled and you don't need it enabled.
It's better to keep it off unless you do.
like this?
Yes.
that just plays it when i play hand again
You need an event
question answered then
Me am very not understand.
Whatâs your set edition look like?
example of a card changing into another using an event
Ok, I was in fact, stupid
choose when you want yours to trigger
delay if any
and then put the func you just made into there
mood
you need to return true for events to end
alright, how do i make the sound pitch higher each time like how the mult hit does?
no
hm
if i've read the docs correctly, this should be 1:1 the same, right?
fucked up syntax???
typescript yeah
yes except start materialize
...why are you making mods in typescript
lua isn't good but typescript is definitely not better
how are you even making mods in typescript
i don't like lua and i write javascript every day
quirked up
typescripttolua
that exists????
that's.. oddly specific
...
holy shit
fucked up and evil do not use this
hi akai
True...
but why do both create_card and add_card take a skip_materialize option then? đ€
ts (typescript) pmo
real
đ„
idk
man i feel like garbage
idr smods create card having materialize but i could just be a dumbass
Sometimes you wanna skip the materialization animations, sometimes you don't.
how would i make a card retrigger each stone card played?
yeah but then this is wrong, no? #đ»ă»modding-dev message
But it's not?
bruh đ
whatever then, typescript is bad and create_card has a useless skip_materialize param, thanks guys lol
typescript has its uses this is not it
But skip_materialize is not useless
typescripttolua is such an oddly specific project?
are there any other projects that convert languages to lua
or vice vers
a
My past employment was using typescript and honestly I like it a lot
Can recommend
it would be if add_card had no start_materialize by default
pythontocpp when
being able to write mods in different, especially more popular languages, is a net positive, but anyway, i'll ask here again once you guys are over that lol
SMODS.add_card is just small upgrade over SMODS.create_card
i don't really care it's just an interesting decision
So both of them uses skip_materialize
jstobash trust
The response was weirdly negative yeah
Have fun with it, Typescript is cool
I've thought of doing Rust for fun but I'd basically have to write the classes inside of it too in order to properly work.
And I'm too lazy to bother
im a fake hater i just thought itd be funny
(also requiring you to put a dll in your game folder)
JS my beloved 
rust is real and good but overhyped
nah i dont really care lol
Personally I don't like JS on its own, though after having used Lua, I'd probably be more open to it. TypeScript's better tools and type safety spoiled me
But Lua has me doing shit with a lot of lack of intellisense
Type safety is a myph 
yes...i feel like you arguing my point :/
me ask: are these the same: (vanilla create_card + set_edition + add_to_deck + emplace + start_materialize) -> create_card({area, edition, key, set})
myst says: yes except start_materialize
me think: why would they accept a skip_materialize param then, if there is no start_materialize inside of SMODS' create_card/add_card?
that's all i'm saying but i think i misunderstood something
Well yeah that's not a good description on my part, TS doesn't have type safety, but the information gives by its types guides programming better
There's isn't a start_materialize param to begin with.
i never said so?
(SMODS source code could really use some comment function documentation though)
how would i make a joker that retriggers each played stone card?
I wonder if it'd be a fun project to do it myself
In context.repetition check if SMODS.has_enhancement(context.other_card, "m_stone") then return the amount of repetitions.
who knew that smods has built in functions to increase the voucher slots and booster slots overstock-style? I didn't, until I had already attempted to implement it manually
i've used them for a while now
I'm not complaining or anything, I just find it neat
since then I check the smods code every now and then for cool functions I may have missed
wait yeah it was two months ago lmfao
How do I add an Edition?
no like make a new one
Resources here!! 

im slow
it's pretty similar to an enhancement, but for shader stuff that's a lot more complicated
The page describes the use of the SMODS.Edition() function to add a new edition
So you call that function with a table containing arguments to create your edition
not the gotcha you think it is lol
i actually dived into vanilla create_card now and the actual unexpected thing is it only using start_materialize when the card is a consumeable
but you are right, i could've looked there in the first place to avoid this clownfest in here
how can i make a joker trigger an effect of some other joker?
i have a cardarea that that is spawned by a joker being added to deck, i can emplace a card into it but for somereason the card doesnt show up in the cardarea, even though you can see that theres a slot taken up and there is a joker in the area
look at blueprint maybe?
no idea if thats helpful lol
Yeah, I'm not 100% certain the reason for skip_materialize other than just what I assume is some weird event delays stuff. Most of the times i've implemented create cards, I've manually triggered the materialize afterwards myself (mostly following vanilla examples)
Booster packs iirc
.....did you not call start_materialize?
Yeah all the booster pack use it because it produces that bug with particles if you don't.
ive never had to call start_materialize when emplacing even into custom card areas...
I miss being able to dev
no dice.
i want to make a table of jokers and have a single joker trigger the effects of all jokers in that table
the effect sounds like 'copies the ability of 3 last sold common jokers'
tried this but it doesnt work

You're formatting that incorrectly and it's not using the contexts correctly either
I said In context.repetition
Also you need to return repetitions = number
yeah i have no idea how to do that
how do i quickly restart balatro
alt+f5
m
thx
Notice that the third prameter of the calculate function is context. It's a table containing various flags and card references based on the timing of certain things during scoring
You need to check for a specific context in order for it to play correctly (so if context.repetition and context.cardarea == G.play)
context.repetition and SMODS.has_enchancement...
if context.repetition then
-- do code
end
Which are the values set on the context table when the game checks for repetition
did you look at https://github.com/Steamodded/smods/wiki/Calculate-Functions? the example mod here could also help https://github.com/Steamodded/examples/blob/master/Mods/ExampleJokersMod/ModdedVanilla.lua apart from it being a bit outdated
Similarly, you need to wrap those values you want to return inside a table. So
remove_default_message = true
colour = G.C.MULT,
-- etc
}```
im gonna be honest i have NO idea how to do that...
do a local card = in the line before SMODS.add_card
then run card:start_materialize() if i understood your code correctly
can someone make a mod that replaces royal flush with HOLY CRAP A ROYAL FLUSH!
store the return from add_card into a variable like created_card, then do created_card:start_materialize()
I don't know if that's the issue obv, but test it anyway just in case
like...just the text? :D
still no workie
Oh!! Actually this is the issue probably
Because it only calls materialize on consumeables
What is this supposed to be doing?
yeah
i just want to make it sound more suprising
lol
lmao
well i don't know if there's an easier way, by like just replacing the localization i guess
but there's definitely this you can take a look at https://github.com/Steamodded/examples/blob/master/Mods/RoyalFlush/RoyalFlush.lua
it should emplace my card in the cardarea below my joker, it does do that but it doesnt show the joker in the cardarea
hmmm i don't want to restart the fight but actively calling it should still do it, right? :D
So when you use your card it destroys itself and makes a new version?
Did you only add start_materialize() to the use code? What about add_to_deck which also adds a card?
it destroys the highlighted card and emplaces it, can_use doesnt return true if you try to emplace the joker with the cardarea tho
that seems to work fine but thats just my control for moving a card into the joker's cardarea
WHY NO WORK PLS HELP
Should be?
is there a context for when an enhancement is applied individually?
Okay yeah I see, that one works fine because it's a consumeable and not a joker
i believe bunco has some custom editions. you can look at the code there
And consumeables materialize automatically
wahts bunco lol
mod
Canât it just move the highlighted card instead?
Logically that would be a better option yeah
Destroying and creating might have unintended effects
i mean, on a card (either from midas or magician)
or whatever applies an enhancement
bump
Thereâs not
i tried that but i had the same problem
type = 'joker' lowercase
this was the issue ty!!
this looks hilarious tho
how do i download it
like this
I changed it to match bunco mod. It still doesnt work
oh sorry, i misread your first message, i thought you wanted make a mod
since you guys were devs i thought you guys knew like a mod to do it đ€Šââïž
you should copy bunco's code and start from there
for i,v in ipairs(joker_table) do
v:calculate_joker(context)
end```
Or something like that
quick question, is v.vampired a local? or is it set in another script than card.lua?
I'm not at my computer so that might be the incorrect use of calculate_joker
Just running calculate_joker isn't going to do anything.
Its on an object so it could be set by anything with access to v
so probably SMODS.calculate_context then
No, you have to return it.
I've made a patch to trigger a custom context whenever set_ability is called, to detect when a card changes enhancements. how can I stop this from triggering when you open the deck view, which live-creates the cards and spams the context with fake cards?
And put every joker after the first one in extra.
would this not work though?
calculate_context calls all other calculate functions, that's not what you want here
card:set_ability(G.P_CENTERS.c_base, nil, true) crashes my game, have i missed smth on how it's done on smodded?
trying to replicate vampire's unhencement effect
Code?
if context.cardarea == G.jokers and context.before and not context.blueprint then
local enhanced = {}
for k, v in ipairs(context.scoring_hand) do
if v.config.center ~= G.P_CENTERS.c_base and not v.debuff and not v.punked then
enhanced[#enhanced+1] = v
v.punked = true
v:set_ability(G.P_CENTERS.c_base, nil, true)
G.E_MANAGER:add_event(Event({
func = function()
v:juice_up()
v.punked = nil
return true
end
}))
end
end
end```
just replaced vampired by punked
heh?
relaunched the game, didnt crash this time
am i crazy
ok doesnt crash anymore wtf
what do i use to create jokers?
SMODS.add_card
tyty
How would I go to add a new button to all jokers?
im trying to get the card to signal that its effects are being triggered, but I don't see anything happening. what is wrong?
config = { extra = { dollars = 3, increase_per_hand = 1 } },
...
calculate = function(self, card, context)
if context.joker_main then
ease_dollars(card.ability.extra.dollars)
card:juice_up(0.8, 0.8)
card.ability.extra.dollars = card.ability.extra.dollars + card.ability.extra.increase_per_hand
card:juice_up(0.8, 0.8)
card.sell_cost = card.ability.extra.dollars
end
end
you can hook into G.UIDEF.use_and_sell_buttons(card)
how can i remove a card area? using G.'cardareaname':remove() gives me this error
hi, i'm new to modding i have a question, what would be needed to have the .lua file formatted correctly to make modifications to the enhancers textures?
What?
how do i make something like that for a custom consumable page?
That reminds me, how do I remove that text? ^
im trying to modify the textures of enhancements but we do not know how the .lua file needs to be formatted
Use a code editor?
i dont understand
If you use a code editor it formats the code for you?
still cant figure it out, anyone know why my joker isnt triggering when a light card is scored?
is there a check for editions?
?
if card.edition?
like there would for ability == 'Lucky'
like how can i check if edition's precisely a foil?
tried edition == 'Foil' but no
if card.edition.foil
im trying to understand why the code i wrote isnt working, and what im trying to make it work into doing is retexturing enhancements
if card.edition and card.edition.foil
is there a way to fully replace a file with another using lovely
???
why not đ„ș
question: did i mess up the contexts for this (the joker giving money is not intentional)
What do you want it to do?
the joker destroys all lucky cards in hand and gives $5-15 for each
đ
so is just no one gonna answer my question
show the entire joker code
key = 'ashbaby',
loc_txt = {
name = 'Ash Baby',
text = {
'{X:mult,C:white}X#1#{} Mult when a',
'Light card is scored.'
}
},
atlas = 'ashbaby',
pos = {x = 0, y = 0},
config = {
extra = {
Xmult = 2
}
},
loc_vars = function(self, info_queue, center)
return { vars = { center.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if SMODS.has_enhancement(context.other_card, "m_cry_light") then
return {
x_mult = card.ability.extra.Xmult,
card = card
}
end
end
end
}```
so what doesn't work here
btw what version of smods are you using
Don't iterate over the hand cards and do it in context.destroy_card
It's supposed to give x2 mult when a light card is scored, but doesn't
1.0.0~ALPHA-1304a-STEAMODDED
whats the debug line to debuff a playing card?
SMODS.debuff_card?
like this?
how do i remove this lmaooooo
wrote as is in the log?
Replace _card with context.other_card
wow
eval SMODS.debuff_card(card, true)?
what mods do you have
i type this in log while selecting a card, doesnt do anything
eval SMODS.debuff_card(G.hand.highlighted[1], true)
ok so this didnt work
still doesnt do anything :c
am i doing it wrong maybe?
same result as before
how can extend the Card class in my mod's file?
Put the lovely dump in your workspace?
the Card class is defined in vanilla's card.lua. Is a lovely patch the only way to add new functions to that class?
No? You just do function Card:functionname(functioninputs) I think?
hmm doesn't seem to work...
I don't think you would need to do that anyway you could just change your functions to function rename_card(card)
Is there any way to fix this?
Talisman?
Yes
well, it's that I want to make a custom button in a card, and in vanilla the func and button functions are stuff that's inside Card (check third line)
if card.area and card.area.config.type == 'joker' then
sell = {n=G.UIT.C, config={align = "cr"}, nodes={
{n=G.UIT.C, config={ref_table = card, align = "cr",padding = 0.1, r=0.08, minw = 1.25, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'sell_card', func = 'can_sell_card'}, nodes={
{n=G.UIT.B, config = {w=0.1,h=0.6}},
{n=G.UIT.C, config={align = "tm"}, nodes={
{n=G.UIT.R, config={align = "cm", maxw = 1.25}, nodes={
{n=G.UIT.T, config={text = localize('b_sell'),colour = G.C.UI.TEXT_LIGHT, scale = 0.4, shadow = true}}
}},
{n=G.UIT.R, config={align = "cm"}, nodes={
{n=G.UIT.T, config={text = localize('$'),colour = G.C.WHITE, scale = 0.4, shadow = true}},
{n=G.UIT.T, config={ref_table = card, ref_value = 'sell_cost_label',colour = G.C.WHITE, scale = 0.55, shadow = true}}
}}
}}
}},
}}
end
@daring fern
You can change the ref_table?
hmmm, interesting - to what? just remove it?
Put your mod in a variable and put the function in that variable.
cant wait for that
key = "vouchername",
loc_txt = {
name = "VoucherName",
text = {
"When {C:attention}small blind{} or {C:attention}big blind{} is selected,",
"Upgrade your most played poker hand",
"by 1 level"
}
},
atlas = "Vouchers",
pos = {x = 0, y = 0},
calculate = function(self, card, context)
if context.setting_blind and not context.blind.boss and G.GAME.used_vouchers.v_testmod_vouchername then
for l_hand in G.GAME.hands do
if most_played == nil then most_played = l_hand end
if l_hand.played >= most_played.played then most_played = l_hand end
end
local text,disp_text = G.FUNCS.get_poker_hand_info(most_played)
update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(text, 'poker_hands'),chips = G.GAME.hands[text].chips, mult = G.GAME.hands[text].mult, level=G.GAME.hands[text].level})
level_up_hand(self, text, nil, 1)
update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''})
end
end
}```
Anyone with knowledge of vouchers and hand levelups able to tell me what's wrong with this? Cause I know it doesn't work
Calculate() code is the result of patchwork from Obelisk and Burnt, am I having this issue because I did the patchwork without understanding the meaning behind it or is calculate() the wrong place to put this?
what's it supposed to do?
It's right there on the text part of loc_txt
oh yes
hmmmmmm
if context.setting_blind and not context.blind.boss then
-- do most_played calc here
return {
level_up = true,
level_up_hand = most_played
}
end``` I'm pretty sure
the display will be jank for now, but I have a fix incoming soon
So one thing is that I didn't know that was a way to level up hands
And the second thing is why aren't the functions taken from burnt joker working?
Is it because of how calculate() is implemented for vouchers?
ok so i think i am doing something a bit too advanced (by setting a base suit and ranks for jokers/consumeables/stuff) and i have no idea how to remove this badge from appearing on all jokers
probably because you don't initialise most_played
does it crash or does it just not do anything?
It doesn't do anything when I select small or big blind, even when redeemed
Does Lua have dynamic typing?
yes
But wait
the for loop isn't correct either
should be for l_hand, _ in pairs(G.GAME.hands) do
you could use G.GAME.current_round.most_played_poker_hand instead though
you have to use pairs or ipairs to make the table iterable: key, value in pairs if it's a dictionary and idx, value in ipairs if it's an array
though I think this only updates at the end of each blind
Didn't know it was that easy
Should work anyways
so
if context.setting_blind and not context.blind.boss then
return {
level_up = true,
level_up_hand = G.GAME.current_round.most_played_poker_hand
}
end```
what are you doing? If you're using take_ownership there's a parameter you can pass true to set it to silent (no badge)
i am not using take_ownership
Yep that works
literally no clue what is causing this crash, other than it being caused by a joker effect in a mod i'm making
the joker's code:
return {
name = "Alexi",
key = "alexi",
atlas = "joker_atlas",
pos = {x = 0, y = 0},
soul_pos = {x = 1, y = 0},
rarity = 4,
cost = 10,
blueprint_compat = true,
calculate = function(self, card, context)
if context.end_of_round and context.cardarea == G.jokers then
local other_joker = nil
-- if there's only 1 slot the for loop will cause a crash, so prevent that
if #G.jokers.cards > 1 then
-- find joker to the left
for i = 2, #G.jokers.cards do
if G.jokers.cards[i].ability.name == "Alexi" then other_joker = G.jokers.cards[i-1]; print(other_joker.ability.name) end
end
if other_joker and other_joker ~= self then
card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')})
G.E_MANAGER:add_event(Event({
func = function()
local card = copy_card(other_joker)
card:set_edition({negative = true}, true)
card:set_eternal(false) -- remove eternal sticker
if not card.ability.perishable then card:set_perishable() end -- don't do it if it's already perishable
card:add_to_deck()
G.jokers:emplace(card)
return true
end}))
end
end
return {
cardarea = G.jokers, -- G.hand, (G.deck and G.discard optionally enabled)
end_of_round = true,
game_over = game_over -- true or false
}
end
end
}
crash log:
Oops! The game crashed:
functions/common_events.lua:1020: attempt to call method 'juice_up' (a nil value)
Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-0408c-STEAMODDED
LĂVE Version: 11.5.0
Lovely Version: 0.7.1
Platform: Windows
Steamodded Mods:
1: Vocalatro by Aikoyori [ID: vocalatro, Version: 1.0.0, Uses Lovely]
2: Signalis Deck Skin by Snqwblind [ID: SignalisSkins, Version: 1.0.0]
3: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.4.1, Uses Lovely]
4: Alexi's Finisher Blinds by invalidOS [ID: AlexisFinishers, Priority: -2147483648, Version: 1.0.0]
Lovely Mods:
Stack Traceback
===============
(3) LĂVE method at file 'boot.lua:352'
Local variables:
errhand = Lua function '(LĂVE Function)' (defined at line 575 of chunk [lovely debugplus.console "debugplus/console.lua"])
handler = Lua function '(LĂVE Function)' (defined at line 575 of chunk [lovely debugplus.console "debugplus/console.lua"])
(4) Lua field 'func' at file 'functions/common_events.lua:1020'
Local variables:
(*temporary) = nil
(*temporary) = table: 0x0230ecc8 {alerted:true, _saved_d_u:true, original_key:alexi, mod:table: 0x01e93bb8, _u:true, soul_pos:table: 0x0230f600, rarity:4, cost:10, order:151, _d:false (more...)}
(*temporary) = number: 0.6
(*temporary) = number: 0.1
(*temporary) = string: "attempt to call method 'juice_up' (a nil value)"
(5) Lua method 'handle' at file 'engine/event.lua:93'
Local variables:
self = table: 0x01f4afa0 {start_timer:true, timer:TOTAL, blockable:true, trigger:before, func:function: 0x01cebde8, delay:0.9375, complete:false, time:44.958815166707 (more...)}
_results = table: 0x01dca080 {blocking:true, pause_skip:false, time_done:false, completed:false}
(6) Lua method 'update' at file 'engine/event.lua:182'
Local variables:
self = table: 0x020b0cd8 {queue_last_processed:16.6, queues:table: 0x020b12d8, queue_dt:0.016666666666667, queue_timer:16.60823375568}
dt = number: 0.0133556
forced = nil
(for generator) = C function: next
(for state) = table: 0x020b12d8 {unlock:table: 0x020b1300, other:table: 0x020b1dd0, tutorial:table: 0x020b14f8, base:table: 0x020b14d0, achievement:table: 0x020b1da8}
(for control) = number: nan
k = string: "base"
v = table: 0x020b14d0 {1:table: 0x02456128, 2:table: 0x01f4afa0, 3:table: 0x0205a248, 4:table: 0x022aaf58, 5:table: 0x022ac6b8, 6:table: 0x022af1b8, 7:table: 0x022b5260 (more...)}
blocked = boolean: false
i = number: 2
results = table: 0x01dca080 {blocking:true, pause_skip:false, time_done:f
seems to suggest it's trying to copy a non-existent joker but idk how it would be doing that
actually i think i have some idea of what's going on
yeah
Is there any way to fix this?
Is there also a way to use this to level up multiple hands?
you'd have to add this to the return
extra = {
level_up = true,
level_up_hand = "different hand"
--can add another extra table here to keep going
}```
im trying to get the card to signal that its effects are being triggered, but I don't see anything happening. what is wrong?
config = { extra = { dollars = 3, increase_per_hand = 1 } },
...
calculate = function(self, card, context)
if context.joker_main then
ease_dollars(card.ability.extra.dollars)
card:juice_up(0.8, 0.8)
card.ability.extra.dollars = card.ability.extra.dollars + card.ability.extra.increase_per_hand
card:juice_up(0.8, 0.8)
card.sell_cost = card.ability.extra.dollars
end
end
Ok thanks
Is there any way to make it go away?
How do I destroy a playing card?
Consumable selects two cards and destroys one and modifies other destroying isnât working
card:start_dissolve?
HOW TO FIX THIS PROBLEM
bro might be getting ignored lol
Thanks!
Is there a context for selecting big blind specifically?
@quick kraken should be
if context.setting_blind and context.blind == G.P_BLINDS.bl_big then
what's the function in UI_definitions that makes a card's information to show up?
ohh might be function G.UIDEF.card_h_popup(card)
Anyone know where the colour value for the debuff shader is set?
Has anyone made a tool where you can make ui easier? Or is it still painful?
still painful why
im trying to do something with ui :pain:
is there a way to replace a specific boss blind with a different one when the blind is selected
i wanna do an xml to balatro ui tool at some point
probably at the point i do anything ui because it IS pain yes
So for modify rank it seems the amount needs to be a integer is there a way I can link it to a function that basically gets the amount of 2 cards selected and modfiys it to be difference
its crashing on modify rank and thin kits not picking up on it being an integer anyone got an idea?
this is the define for ranks it calls
or maybe a program where you can build the ui and see how it looks, and it gives you the code afterwards?
yeah that's a tad more complex haha
but i get what you mean, would be awesome
how possible would it be to draw all (base game) editions on a card
i tried to change red card's texture into sum else and it straight up became jugglar is that normal
i mean you changed red cards texture to something else so
but thats not the right texture đ
How do you use the watch command lol
i think (?)
C:\Users\setht\AppData\Roaming\Balatro\Mods\ScribbledMod\shaders\scribbled.fs is the shader i want to watch
watch shader Mods/<folder_name>/assets/shaders/<shader> for shaders
shaders should be in assets
assets/shaders/shader.fs
not in the joker it seems