#💻・modding-dev
1 messages · Page 378 of 1
i saw somewhere a line related to that, so may be i can just patch that
How would I go about creating a card that's one of my own consumeables? I'm trying to do it based on Judgement / Emperor logic, but it doesn't wanna work, it just throws an error instead
what is G.STAGE?
isn't it c_ather_...
Class letter first?
yes
Yeah, I'm kinda dumb
any how i can make this joker idea ? it basically gives + mult the wider your hand is so lets say:
1 played card = +1 mult
2 played cards = +2 mult for each card
3 played cards = +3 mult for each card
4 played cards = +4 for each card
5 played cards = +5 for each card
Do you know how to make mods and / or jokers?
return { mult = #context.full_hand }?
It seems like G.STAGE is similar to G.STATE but for pausing and screen transitions, like a layer above
interesting
wait i forgot to add smth lemme retryt rq
it gives only +5 mult
oh you want +(hand size) mult per card
in that case you want the square of the hand size
you need to be more specific
i thought i was specific in the idea
no you weren't
like i meant if you play 2 played cards it gives +2 mult for each played card
etc etc
well you didn't say each played card
anyway my thing also does that
you need to use it in context.individual
return { mult = #context.full_hand ^ 2} if you want the +mult to trigger on the joker
or that
card.config.center.key
Is there a way I can have a special effect when a custom rank is played, not by any voucher or joker, but just naturally?
i did and it aint what i wanted lol
pretty new to modding,is there a way to get the current game speed?
tried going on the source but speedfactor doesnt work
i can't play videos rn but i assume cards in hand are giving mult too?
@minor magnet
What do you mean by current game speed
the current speed that scoring is being processed
like when you retrigger too much and the game starts speeding up
It is speedfactor
when are you trying to access it
but when are you trying to access it
im not familiar with it but wouldnt G.GAME.SPEEDFACTOR only change during the animation and not calculation
At which moment are you accessing it
AFAIK it's only used during a specific phase of scoring and only under some conditions, so it might not exist otherwise
heres the screenshot i think its easier
Oh so you're doing it in update

yea im gonna use a timer after a finish the code
its just to test if it gets the time right
You only need to access speedfactor when you actually use it
So, once during calculation, and once when generating the description
Second, as I said before, SPEEDFACTOR is only used at specific moments
So outside of those specific moments, it's possible it doesn't exist
yeah i think the problem is that calculations are before animations
That too
Calculations always before animations
thats what i was thinking
since the calculation doesnt care about how fast the animation plays, its just for show
its already done by then
maybe you could theoretically calculate what the speedfactor would be at that point as a substitute? but i wouldnt even know where to begin there
would it be better to use draw = ffunc or update = func for jokers that change sprites?
update
yeah thats what i was hoping for since i have little experience with draw lmao
hmm, i think this error is happening at SMODS.add_card(). to clarify, if i wanted to add a card with key "purple_rain", and my mod prefix is "gb", it should generate the card if i provide the key "gb_purple_rain", right?
No, it would be j_gb_purple_rain
Is there a template mod I can start from? The example mod I've been using has far more things than expected and takes some effort to rename the variables and whatnot.
I absolutely hate how blinds are currently handled lmao what a pain
there are a lot of good examples in here
https://github.com/nh6574/VanillaRemade
but idk that there's necessarily a "template"
but so far so good
just had some frustrations trying to get my blinds to be recognized
it's all good now, as you can see by the image above
I'm changing how the Barbara joker works to be when Big Bling is started, would I have to put something like blind.big for it to sense a big blind being started?
calculate = function(self, card, context)
if context.destroy_card and context.cardarea == G.play and context.destroy_card == card and pseudorandom("stain") < G.GAME.probabilities.normal / card.ability.extra.odds then
return {
remove = true
}
this isnt working for some reason
where is this code located and what is the goal?
in an enhancement, want it to work like glass
just do nothing, the odd doesnt work 😕
if you remove the random check does it work?
what do you mean
if i use like the rigged thing from cryptid to test it works, but otherwise just never
I already said above, just had a lot of fun learning how it works
context.destroy_card is a boolean
I don't see your message explaining what you dislike about them
what do i change for it to work?
Eh, I think it was more like a skill issue on my part, being unfamiliar with lua
wait maybe I was wrong
is there some sort of coroutine in lua?
it's not a boolean
nothing that uses pseudorandom from my mod is working
what does the config of your joker look like?
My bad, I thought it'd use other_card or something
its an enhancement
config = {
extra = {
x_mult = 2.5,
odds = 5
}
},
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.odds,
card.ability.extra.x_mult,
(G.GAME.probabilities.normal or 1)
}
}
end,
bump, not ultra important but would like to know if i misunderstood something
wym?
this currently isn't appearing in spectral or arcana packs, am i misreading the SMODS.Consumable docs?
"hidden = true"
I think the checks could happen outside of the Event. It might not make a difference (besides objects possibly not existing and such)
yeah it's a soul-like card
if its hidden it doesnt show in collection im afraid
try setting hidden to false
that's no_collection, no?
im not sure
i dont remember exactly how i arrived to this structure, but i iterated 1st all outside and it was a big weird as the first ifs would happen at their rythm, and the elses at their own too, didn't have that cohesion of 1 Nope 2 Edition 3 Nope 4 Nope 5 Nope, was more like 2 Edition 1 Nope ,etc
set:edition happens turbo fast
I mean, you do need to time Events correctly
But knowing whether the effect succeeds or not doesn't need to wait
like (pseudorandom(...) < division here)
Maybe the loop structure works better in terms of timing
ooh, gotcha, okok, 1 sec!
so, taking off the 1st event and trying again?
its workingg!! tyty!
Is there a way I can make text appear in the corner of the screen for a short amount of time?
does anyone have experience with soul-like cards? i can't think of a mod off the top of my head that would use these
ok yeah i remember, 1st event is so the joker doesnt get stuck in its "getting sold" position which is akward, and 2nd event is the delay except it adds it before, and i want it to add after the even happened
yes
and putting the card_eval in a event is ew
Yay! ^^ How can I do so?
I want there to be a minecraft chat message in the bottom left that says "Null joined the game", and then disappears after
Sounds doable
Gonna ask again since it got bumped away
first instinct is to modify the max_highlighted in the ability of each tarot/spectral when it's obtained and also when the joker is added/removed
take_ownership will work as well but it's more work
how do i make something not show up in shop/packs?
something like this
#💻・modding-dev message
but 'ar1' depends on the pack you want to ban it from
do i change it to the pack key?
no, it's a specific string depending on the type of pack
ar1 is tarots in arcana, buf is buffoon
ar2 is spectrals in arcana
i dont know the rest
How do I add a flag into a save? I'm attempting to have a joker only appear once a card dies, sort of like gros michel, but it can still appear in shop later
where can i find it?
card:open i think?
tyty!
can anyone help me on this?
i think the code is fine i just dont know how to get the suit of the playing card
playing_card.base.suit
but also insert doesn't do what you want here
you want to do foundsuit[playing_card.base.suit] = true
kay ill try that thanks
also does anyone know if its possible to get like
the autofill tips
idrk how to call them
im just not sure i setup the thing correctly
you can add SMODS to your workspace and it has a bunch of them
i think you also need to enable indexing? idk
like here?
sry idrk all that much about vcs
no, go to file > add folder to workspace
i think you need to have a folder open for that
like this?
whats the easiest way to see if the score has been reached while in a calculate function? i have a joker that retriggers itself until the required score is reached, and im guessing i might need to "predict"/calculate the current score myself but how do i get the required score
yes
oh that works thanksomuch
hand_chips * mult
that's the hand score
do i need to put anything before those variables or is it just those on its own
and what about the required score?
they're globals so just that
G.GAME.chips is the current scored chips (i think)
G.GAME.blind.chips is the requirement
until((hand_chips * mult) >= (G.GAME.blind.chips * G.GAME.blind.mult))
would this be right or is G.GAME.blind.chips the entire score requirement?
for some reason this dosen't do anything which i'm guessing is because the table is empty
chips is the entire requirement, there's no mult requirement
?
chips being used interchangeably to mean chips as in blue score but also the entire score requirement depending on context
how can i check the size of a table then
i mean you need points to beat a point requirement
loop through it and count manually
Sorry for the repost, but my message got bumped a but,
is there a way I can make a joker that appears when a card is destroyed, like Cavendish, but, the destroyed card can still be picked up in the shop?
shucks allright
ofc that makes sense, i just thought itd be called like score or smth separate
yes
Oh! How so?
N's mod might help as a reference
Yay! ^^ Where can I find it?
Thanks! ^^
just copy what Cavendish does in in_pool without copying what gros michel does in there
Okie dokie, thank you!
works now :-) thanks for all the help
should be my last question, what should i change here to circumvent the problem that returning the mult prevents it from looping?
if context.joker_main then
print("final step")
repeat
if to_big(G.GAME.dollars) - 1 >= to_big(G.GAME.bankrupt_at) then
print("mmm money")
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) -card.ability.extra.dollars
return {
xmult = card.ability.extra.xmult,
dollars = -card.ability.extra.dollars,
func = function() -- This is for timing purposes, it runs after the dollar manipulation
G.E_MANAGER:add_event(Event({
func = function()
G.GAME.dollar_buffer = 0
return true
end
}))
end
}
end
until((hand_chips * mult) >= G.GAME.blind.chips)
end
im guessing its about the context im using but im not sure which would be better
or how else to trigger the mult effect
calculate the xmult and dollars separately and return once after the loop
or if you want it to be multiple animations then append a bunch of extra tables
didnt know that was possible, how roughly does that look
nevermind
missed it on the wiki
It works!!!! Thank you!
is there any documentation on unlock things?
is there a not-annoyingly-coded blind .lua file that i coudl reference anywhere?
hey guys! I wanted to change the name of a voucher on balatro, how could I do that? I wanna make some other things too but I need some help in how start doing it!
How does one make a custom joker set like Cryptid's M jokers?
I need a set to give to create_card() because otherwise I would have to completely re-implement the rarity system and duplicate tracking
this is what object types are for
im trying to make the card be destroyed on use, would this work?
calculate = function(self,card,context)
if context.cardarea == G.play and context.main_scoring then
return {
x_mult = card.ability.extra.x_mult
}
end
if context.destroy_card and context.cardarea == G.play and context.main_scoring then
return {
remove = true
}
end
end
}
no, main_scoring is a different context
This seems very unclear unless one is specifically making a new consumable type
remove that and you should be good
look into how localisation works on the smods wiki
all the text is controlled by 1 file, so you can make a new localisation file in your mod and add the entry for the voucher you wanna change and alter the text
okay! tysm! 
tyty!
What does it mean that there's such few parameters?
How does one make a joker part of that type?
the page needs some work, but it's no different than how it works for consumable types. i.e., you create the ObjectType and either provide the keys you want in the object type as cards or use pools on the objects being created (I should check if that's documented elsewhere?)
then use the key as the set being passed to create_card
I think I might get it
yeah, pools is indeed documented on the joker page. should put it on the ObjectType page as well smh
what funciton would i call to create a spectral pack?
Further question: jokers of this type are supposed to appear in buffoon packs but not in the shop unless a specific voucher is redeemed
Can I streamline this with a set or do I have to implement the same in_pool for every joker of this set?
that sounds like a bad timing to have a spectral pack opened. you'd be better off creating a tag for that (add_tag)
I already wrote the in_pool for the 2 jokers that test the functionality of this set and it works
would it be done with this? lua add_tag = etherial tag
or is this completely wrong?
not directly, being part of the ObjectType doesn't affect it showing up in places not affected by the ObjectType. Best I can think of is to hook the ObjectType's inject_card to change each added object's in_pool function
yes, add_tag is a function
Seems like I'm still better off copy-pasting the same in_pool then
you use it like add_tag(Tag('tag_ethereal'))
no need to copy-paste it, really
you can just define it once as a variable and then put that reference into each object
what if you want to change it in the future
something tells me thats not the right way to create an etherial tag
(it's just a simple find and replace so no big deal, but not defining the same function in multiple places prevents inconsistencies emerging)
i already told you it isn't
that also just isn't how lua works at all
.
oh, i didnt see that
It's unlikely that I will, and if I do I don't think it'll be too much of a problem
SInce again, the logic is all implemented within one line
more of a general code style thing than potential for a problem with this function in particular
up to you
cool that fixed it, thanks
np
local return_table = {
xmult = card.ability.extra.xmult,
dollars = -card.ability.extra.dollars,
}
for i = 1, triggers do
return_table.extra = return_table
end
print("made table with extras")
return_table.func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.GAME.dollar_buffer = 0
return true
end
}))
end
print("added func")
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) - (triggers * card.ability.extra.dollars)
print("buffer")
return return_table```
is this the correct way of using extra tables to stack the same effect repeatedly?
if so, why does it cause stack overflow when i return the table, and if this is a bad method should i instead try to retrigger the joker or smth?
Yes, I know basic programming principles and am making a personal decision not to follow them in this specific example
Thanks for the suggestion anyways
And thanks for the help with object type
this is an issue of not understanding how lua tables work
sounds about right ðŸ˜
you've basically referenced the table within itself
so when steamodded looks for extra tables, it will keep recursively finding the same table because it keeps referring back to itself
how do i set it so that my joker only triggers if the points scored are exactly whats required for the blind? right now it seems like its only more, or less
G.GAME.blind.chips = 1
returns an error
and </> is too broad
should be == right?
ohhh
something along the lines of this
local ret = {
xmult = card.ability.extra.xmult,
dollars = -card.ability.extra.dollars
}
local head = ret
local copy = copy_table(ret)
for i=1, triggers-1 do
ret.extra = copy_table(copy)
ret = ret.extra
end
-- do dollar buffer stuff here if you need to
return head
couple things going on here, note that extra returns work like linked lists. if you need more tables, you need to attach them at the end of the list (to the most deeply nested table). also using a fresh copy for each layer so no self-reference can happen
and ret already contains one trigger, so if you want triggers amount of triggers, you need to do one less than that for the loop
i was gonna do the last part but forgot
out of interest why does it need to be copied so many times?
the table i mean
the first copy is just so i have a free dupe that's not gonna change if i mess with the return table
then i copy that copy again each time i attach it to the return table as not to have the original copy modified when i continue adding tables to that copy
Hey!
oh one more thing, it's safer to use SMODS.shallow_copy instead of copy_table for this in case you ever have cards in your return table. cards really don't like being deep copied
thank you for explaining this to me
I'm having trouble with getting a playing card to move from one area to another. What method would I use to get the specific playing card I attached a button to to move to another card area?
i know it sounds confusing
you return head but ret is the one thats changed?
could use some better naming there haha
is that intentional because wouldnt head be the original table or am i wrong
head points to the start of the list
ret however points to the end of the list
in linked list language, it's the tail
basically there's two different references i need to have
one has to contain the topmost layer of return tables, containing all of the extra tables within. this top layer is the head, and its reference doesn't change
What's going on here?
one has to point to the bottom layer, the one that currently doesn't have any extra tables attached. i need this one because it's the only table in the whole list that can have another extra table attached to it
but it holds no reference to the outer layers, which is what i need the head for
i think im understanding this
just explaining returning multiple calculation effects
so despite not making any changes to head, it still gets them because youre changing ret or smth like that?
apologies if i got it wrong
my brain is a little fries
I see. Afterwards, could you help me figure out how to make a joker that increases the max_highlighted value on consumables that use it?
been trying for a bit to no avail
i was gonna go to sleep after this, it's getting late
yeah same
RIP
i didnt even notice i put fries instead of fried
Bump for anyone who may be able to help
Never getting this joker completed at this rate
before entering the loop, head and ret are the same table. they don't just have the same context, they point to the literal same exact piece of memory
at that point you have two references to the same memory
when you set ret.extra, that change is happening to both ret and head because they are the same
in then changing ret to ret.extra, ret is now the same as head.extra
do that again, now you have ret and head.extra.extra being the same
i think i just about get this
very interesting tbh
it works btw, thank you so much
and for taking the time to explain it all
how can I spawn a voucher with debug plus?
by the way, this is what == checks for when used on tables (given they don't have metamethods for equality)
for future reference, does this sharing-memory thing apply when you set any variable to be another one? sorry if i didnt explain that right
i just wanna make sure in other areas where ive tried to copy a variable, i dont mess with the original
i dont know what that means 😠sorry
press 3 on the voucher in the collection while you're in the shop and it will spawn in the shop
a == b where a and b are tables only returns true if they are the same table in the way I've described, it will be false if they're just copies of each other
ty!
ohhh i see, makes sense
that applies to tables and functions, essentially
though functions are immutable I think, so it only really matters for tables
How does saving work in Balatro? Where is all of the data that is being saved per run get stored to?
it gets compressed and saved to a profile-specific save.jkr file
noted, thank you so much
im sorry if i asked any stupid questions but i did learn a lot from this
if you decompress it, it's just lua code that looks like return { [massive table here] }
what else but massive table
lua consists of nothing else
Where can I find the table to add my own things?
G.GAME
What I do after I extract balatro and edit the files I wanted? I dont know how to apply into the game
generally you shouldn't just edit files, just make it a mod
See this wiki page for how to do that with steamodded
Okay! I will take a look! (Sorry btw Im kinda dumb on this type of thing)
Also, is there a way I could have an effect happen when a certain rank is played?
Not as a joker, but as the rank itself?
you don't really need to. you can use DebugPlus to inspect the G.GAME table at runtime if you want to, and other than that you just put your values in there and they get saved
Oh cool! ^^ ok!
planned, but not easily doable as of yet
doesnt almanac do that?
Oh, alrighty ^^
Is there a way I can implement a "secret" joker of sorts, that acts behind the scenes but doesn't show up? So it's just always there?
how do i debuff a joker after a certain ante?
if G.GAME.round_resets.ante >= 4 then
card.debuff = true
yeah that's not too hard. one way is to make it a voucher and just have it be redeemed at the start of runs
Ooooooo ok! ^^ Thanks!
Is there a way to make sure the voucher doesn't show up in the collected vouchers page?
Is apply() the tag equivalent of calculate()?
I need a tag to store last blind's reward money and tags seem to be not cooperative
tags are one of the few things left that don't have support for calculate yet. so apply is all you get smh
Can I do that through apply?
it only supports what vanilla tags need
Or do I have to do someting convoluted?
you probably do, or wait for tags to get support for calculate
that's a side effect of using that method, there's other ways to do it, but probably there should just be a streamlined way on smods' end to make mods have effects not tied to some imaginary object. this was suggested a while ago but i have no capacity atm to implement new features. so not happening for a bit unless someone else does it
well i'm too tired to explain and gonna go to sleep now
ahhhhhh, that's fair
Thank you! ^^
makes cents
have a goodnight ^^
can someone help me figure out why this is only giving me regular mult instead of xmult?
because youre returning mult??
return Xmult = instead
Is there a way I can modify values of a SMODS.Rank mid game sort of like how you can with jokers?
how could i make a blind have a chance to destroy a played card?
use this and use smth like pseduorandom('customblind') < G.GAME.probabilities.normal / card.ability.extra.odds then context.other_card:start_dissolve()
you can use calculate with context.destroy_card
what contexts would be used for obtaining a joker (specifically itself)
Should I keybinds system I'm using for Handy mod transfer into separate mod with convenient API at some point?
the add_to_deck function, not a context
to check for when its obtained sorry
idk if thats still the same
add_to_deck runs when the joker is obtained
ah ok cool
whats the variable for the amount of chips you currently have? G.GAME.hand_chips returns a nil value
i think i tried hand_chips before but ill try again
mightve done G.GAME.hand_chips
ah, seems like chips still dont wanna be altered during context.before
what file are contexts stored in again
as in where contexts are defined
and how does one do lovely patches
^ experiencing the horros
How does one allow for a specific sound effect to play when a joker triggers
play_sound
Should i use the filepath for the sound effect when using that function
read the docs
blehhhhh i cant find anything on how to patch on the lovely wiki or smods wiki
thats the love2d wiki'
how would i destroy a random card from the played hand
Is there a built-in toggle for "if the player has the upgraded version of this voucher, do not calculate" or should that just be done manually by searching for the upgraded voucher
e.g. Voucher A gives $5 every round, Voucher A2 gives $10 every round and is only available if A is already purchased(with requires:). Since the player would have both voucher A and A2 would it award $15 total?
by vanilla's wording, it could be either $10 or $15. while both handy and nacho tong, as well as wasteful and reyclomancy, say they all give +1 hand or discard, liquidation instead says 50%, overriding its inferior voucher
more examples of varying contradiction
Fascinating
does anyone see any bracket related errors the game crashes on launch saying it excepted to close a bracket but i dont see an error
bump
did you use the balatro how to make a joker video as a reference
loc txt
cause thats a bit outdated
missing a ,
aah ok
I wasn't using the make a joker video i was using the api docs, small knowledge of lua, and using other mods as a ref
you should install the lua extension for vscode
it will highlight syntax errors like that
loc vars should be loc_vars = function(self,info_queue,card) and your variables within it should read like return {vars = {card.ability.extra.[VARIABLE NAME]}}
like this
the game is now telling me that a comma is excpected after a hashtag
can you post a screenshot of the crash
trying to screenshot doesnt work
it just unfocuses the window when i press either screenshot key
once you launch the game you should set it to windowed so it doesnt do that lol
is there a way to tell when a card is added to a cardarea?
any card? or a specific card type
a specific card type
here
i've tried adding a add_to_deck but the card doesnt seem to have a .area in it
which card type then
a specific consumable
what consumable >.>
ah nvm
bump
For I equals 1, hashtag context scoring hand. Missing a comma there.
What are the names of the per-suit high contrast settings (or is this a mod thing)?
not the global setting
fourth time asking. can someone please explain to me why boss blind screen looks like this
hey gang how do I make a joker that retriggers itself a bunch of times
if it's your fourth time asking and no one has given you an answer, it's probably because no one knows the answer. But by the looks of it you have a lot of mods installed, I would suggest disabling them one at a time until it gets fixed and then seeing what's wrong with that mod
Disable a random half of them, see if anything changes
If it doesn't then do it again
And repeat until you've found the section its in
my game is crashing without certain mods, so how do I renable them without booting the game?
i disabled them
remove the .lovelyignore in the folder
where is that?
in the mods folder that you disabled
is there a setting that makes it so steammodded doesnt sort disabled mods into seperate groups in the mod menu
there's no context.other_card, issa blind
no
;(
bump
is there any way I can hook specific game events, like perkeo's ability?
so wait, press_play or calculate
calculate
what are the args for blind:calculate
same ones as a joker's
you can hook any function in the whole game if you can find the right one to hook
that's what I'm concerned about though, I don't want to hook: "G.E_MANAGER:add_event(Event" in general, I have no idea how to hook a specific event like that
not familliar with patching, how would I go about that
but also what is the X to your XY problem, what do you want to do
maybe there's an easier way than whatever you're thinking
trying to make a copy effect joker that deducts the sell cost when it returns the ability of that copied joker. problem is, there's some jokers that just don't return a table or have a calculate function at all, like marble joker, cartomancer, perkeo, burnt joker, etc
it works fine for literally any other joker, there's like 8 of them that work like this lmao
it's really annoying
yeah you would need a patch or take_ownership for that
but also all vanilla jokers return at least nil, true as far as i know, is there no way to check for that?
yeah that's what I tried to do at first, however those jokers return nil like eighty times when their abilities are copied for some reason
hold on, i might have a clip. it's really funny
i mean yeah every calculate call returns nil
you need to check for the , true part
but if you ask me for my opinion I wouldn't even bother to patch the jokers, just make a table of which jokers have problems and do it manually
not like the solution would be very mod-friendly anyway
Hey, N
Could I get some help on my poker hand, again?
-# please
that's what I have rn lol, it still doesn't work and I'm not sure why
you have 10 minutes before i try to go to sleep again
can i see
sure, just a sec
Dang
uhhh
It just won't appear.
For context, it's a Flush Five made with a specific card, i want it to show "Why"
I make the Flush Five with the cards, it shows Flush Five and not the other thing
flush five is probably higher
In value, or?
yeah
how could i make it display a message on the card when it's destroyed?
Nope, i changed the chips & Mult values. Still returns flush five
does adj.key work even?
shouldn't it be adj.config.center.key == "j_certificate" for example?
no idea then, i would have to test it
Hm.
{ message = "message", remove = true }
One sec.
yeah, that works for checking the key of the card object
Last line in Wasteful.lua
I tried that too, still didn't work
I guess I should check by printing the jokers key
let me try that real quick
what's the difference? I thought they did pretty much the same thing
it does a couple more things to update the text
also you would be setting the dollars to 0 even if you're in the negatives
should it be doing that based on my code? cause it doesn't
well i think it doesn't reach that part of the code at all so it makes sense
oh another thing, if left_joker is nil I don't think ipairs will go through both
i might be wrong tho
I did have that issue at one point, I don't remember what I did to fix it
I don't think it's an issue anymore?
ok, again I'm looking at the part of the code you say isn't working
ah you may have been right up here, it's returning the key as nil
that's what I meant to forward
I made some jokers use update to change their sprites dependent on the high contrast setting, but update updates every frame so that feels wasteful
how do i get my mod to recognize the json prefix in order to play a sound from the assets’ sound folder
Read up on the smods api documentation but i’m feeling a bit lost atm
i think it's fine honestly, many graphic things update each frame
the other option is hooking into the button function that changes that setting
how would I make a joker which made a certain rarity be more common while held? Such as "Uncommon jokers are x3 as common"
not sure wording on this idea, lol, but, how would I make it?
would i need to specify that card = context.other_card in the return
wait
actually, do you think this'd be better as a voucher? that may be interesting, as I've never made a voucher before
OOO, OR WHAT ABOUT BOTH? HAVE IT BE MULTIPLITIVE?
you don't need card = anything in any return
Wondering how that would interact with copies of itself, or other things that adjust rarities. It might not be as simple as storing the rarity values before or after the joker was added. Hrm.
i think you can change G.GAME.uncommon_mod in add_to_deck
hmmm, ahh, so, uhm, I was using uncommon as an example, hehe uhm, so, I wanted this for a custom rarity I had, so, uhm...
sorry, lol, should have been clearer on that, lol
ahh, sorry 😠the docs are wrong so often I've kinda stopped checking some times, adbfsjhsf
chat, i forget.
if i HAVE to start from a joker's self, how do i get to config.extra? 
or is it ability
because i'm working on implementing something that starts from Card:calculate_seal(context) and looks for a function in self
it's very funky 
self there refers to the Card object
this is dissolving and TRYING to display the message but the message only displays where the card was a little bit after it gets dissolved
ok that's what i imagined
in that, self refers to a card object so it's self.ability.extra
that's what i was wondering about, yeah. since self here is the joker
that seems like a bug
oh wait
remove the start_dissolve
awawa is a good testing message 
bump again
Just idly theorizing here, but would it work if the return message had a func as a parameter, containing the context.other_card:start_dissolve() in the function?
Ah
not destroying now
it's also showing ERROR! instead of Burned! but that's a diff issue
i said context.destroy_card
not individual
and it's not going to say burned if you don't have a k_burned_ex in your localization file
i do
it seems to be inside descriptions
where would I find this in the docs? I would've assumed it to be in Rarity, but I can't see it there, hmm
this isn't working either
rarity
ahh thank you
1.0.0
more specific
i'm trying to have a specific sound play for failing a probability but it keeps crashing when i try to play it even if i have everything set up for the sound to play for the joker i'm making
if anyone has any tips let me know
bleurgh whys it keep saying its incompatible when im defining it as compatible in the code (doing blueprint = true)
hell im even hard coding in blueprint interactions
sizimod_bob
updated, trying it now
wait why are none of my jokers blueprint compatible
blueprint_compat = true
will try that
can i see your code
OH
WOOO it works
saturday...
here, this creates the consumables
triple bump
oh i just wanted to see the blueprint thing but squidguset already answered by the time i typed it
i c
well i think i know the issue neways
pov you were just about to ask if theres anything other than soul_pos you need to get soul sprites working and i read soul_post on my screen 💀
ok, so, how do I translate this into actually usable code? what do the .. represent?
String concatenation
Got a crash
it's saying that you need to use the key in lowercase + _mod
hmm ok, so, that'd be... let me try this
no idea sorry
maybe the path is wrong
Probably
like this? Well, I mean, I'm still missing something ofc, as it's still red lined lol
this is where i have it
yes, if you do = 2 it makes it twice as likely to appear
should be assets/sounds/file.ogg
ahh ok, thank you
how would one reverse this effect afterwards? like, as in, if the first way was the Add_To_deck effect, how would one have the Remove_From_deck undo the first effect?
yes
the better way would be
G.GAME[...] = not from_debuff and (G.GAME[...] or 1) * 2 or G.GAME[...] in add
G.GAME[...] = not from_debuff and G.GAME[...]/ 2 or G.GAME[...] in remove
mmmmmh, I see, thank you
Ah heck, forgot to think about debuffed cards for Axy's code
what does [...] do
nothing, i didnt want to write this
It's just shorthand, replace it with your own values in actual code
have I understood this right? :3
i see 
yeah that works
now that i think about it the from_debuff stuff doesn't do anything, im just too sleepy
Ouh
fair lol, I just took a midday nap not too long ago, woke up at 8 pm lmao
in this case you want to change it when it's debuffed
but anyway the code you sent is ok
would you be able to change an atlas position in an if statement and if so what function would it be done in?
theres a way to make animated ones i think
surley you could switch the frames with one of those
Is there a way I can make a custom consumable appear more often?
is there any way to add a message to this function? as in, the card creating this event has a little message below itself when it triggers
SMODS.calculate_effect should help
nightmare nightmare nightmare nightmare
unrelated does vs code have a find and replace tool
click the arrow on the find box
so, im trying to have it only sense if the Big Blind is started, so how would I set it up, cause I know theres setting_blind.boss but that would only be boss
ive tried boss.big but it crashed
What happens with setting_blind.big?
You're doing if context.setting_blind and context.setting_blind.big, yes?
Not sure how that context is like
Should read the docs prolly
Prolly need to change some value in G.GAME
Would get out of bed to check the code, but lazy...
context.setting_blind is a boolean, why are you trying to index it?
G.GAME.blind:get_type() == "Big" iirc
Is there a way to set a rarity to a consumable?
Add that to the calculate?
to the if condition yes
Oki
ive been trying to figure out ui but i have no clue where to start
i peeped around the documentation and some other mods code but nothing really makes sense to me
trying to add a crossmod deck skin with paperback's stars, why the hell is my deckskin's loc_txt being set as the base? (for reference pic #2 should say "PEPPERED")
i may just go ask them but wanted to see if you guys knew
oki, now Barbara finally works
it might just be easier to recreate the game from scratch with what i want
how would i check what the key of a sold card is?
hiii where can i start on getting decompiled balatro?
currently trying to do it like this but it does not work
im just trying to see how balatro makes the deck based on seed
you can use 7zip to extract it iirc, thats how i did it
how do i run it though?
idk
._.
i just use that to look at code for how vanilla does things
you can use 7zip to open the exe archive; then look through the code to see how it does what
you can also edit the code and save it to the archive to make changes to certain things (i.e make a deck function differently)
for that last part you should probably use lovely for that
but yeah
probably
Hi, I'm trying to change the rank of cards in a deck. What value do the numbered cards like one have? It doesn't seem to work whether I have it as "1" or "One" but if I put "Ace" it successfully updates the cards?
14
1 doesn't exist
it goes 2-14
the UnStable experience hits hard
For two or the other numbers would it be Two or 2?
2
Thanks!
Ah, right. Speaking of card changing effects, Axy wanted to change just the displayed sprite of a played card into a blank one, but not change it's functionality like rank or bonus or the like. Not sure which field should be changed in a card to do that. Guessing it would be restored in a remove_from_deck function as well, but not certain yet.
does this line make the erratic deck?
-- game.lua line 2342
if self.GAME.starting_params.erratic_suits_and_ranks then _, k = pseudorandom_element(G.P_CARDS, pseudoseed('erratic')) end
btw how would I make it so when I sell a joker, it creates a new joker that isnt already in hand
I wanna make it so that when I sell a joker, it creates a new joker that the player doesn't already have
I would assume it's somewhere around where that is if not that, not entirely sure tho
Is there no way to cancel a specific event or do I need to resort to either fiddling with timers on my own or patch the event queue
only thing like that seems to be clearing an entire queue which sounds like a nuclear option
you could try adding an if statement that returns early if a boolean is true
but also I do not have an intimate knowledge of the event system so that might simply not work
mm
I was trying to use trigger = "after" with a delay set
and have the event be cancellable within said delay
reasonable
trying to add a crossmod deck skin, why the hell is my deckskin's loc_txt being set as the base? (for reference pic #2 should say "PEPPERED")
ignore the jank of the deckskin palettes code
Honestly how did you actually add a new suit?
i'm just trying to add a deckskin for a suit from paperback, see here for how they did it https://github.com/Balatro-Paperback/paperback/blob/main/content/suit/crowns.lua
it's pretty simple
Shouldn’t loc_txt be a table?
now its time for the difficult multi layered one
deckskin can (or at least is supposed to be able to) take either a table or a string for loc_txt, because it's only ever the name of the deck skin that you're defining
setting as a table never seemed to work for me, i just accepted it lol
i still have no clue why it's setting that as the base deck text, and giving a placeholder for the one i want it to be on
i wonder if maybe it's a priority issue
maybe? both mods have either no set priority or 0 though
yea, so try setting your mod's priority to 1
didn't do anything 😔
Log?
Hey! I'm working on a balatro mod but I cant seem to get it to trigger at all, what am I doing wrong?
SMODS.Joker{
key = 'jokerkaite',
loc_txt = {
name = 'Kaite',
text = {
'Gains {C:red}+2 {C:black}Mult every time {C:gold}High Card {C:black}is played.',
'{C:green}1 in 4 {C:black}chance to upgrade {C:gold}High Card {C:black}when played.',
'{C:inactive}(Currently {C:red}+#1# {C:inactive}Mult)'
}
},
atlas = 'Jokers3',
pos = {x = 0, y = 0},
config = {
extra = {
base_mult = 0,
growth = 2,
}
},
rarity = 3,
cost = 8,
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra.base_mult}}
end,
calculate = function(self, card, context)
local message = 'A'
local color = G.C.BLUE
if context.hand and context.hand.hand_type == 'High Card' then
card.ability.extra.base_mult = card.ability.extra.base_mult + card.ability.extra.growth
local message = '+2'
local color = G.C.RED
if math.random() < 0.25 then
---UPGRADE HIGH CARD
local message = 'Upgraded!'
local color = G.C.PURPLE
end
end
end
if context.joker_main then
return {
mult = card.ability.extra.base_mult
}
end
end
}
You can’t just do local message =
okay got my dumb idea working
Imagining this with a misprint deck
Do I have the stuff for the high card only working tho?
nevermind, i was copying files wrong. this worked!!
Play cards in time to the music, or they get debuffed
context.hand.hand_type doesn’t exist?
wait this is cinema
its peak cinema
I need to make more jokers .....
ok yeah i honestly have no clue what im doing this is my first time making a joker with a restriction like that ðŸ˜
what would I put instead
ive been stuck on 2
one i just can't execute and the other i can't balance properly

me taking a screenshot with sharex and constantly getting a black screen not noticing my canio is fucking gone until it works
this one
I have 0 clue how to make it work
holy shit fellow Dr Who thingy
skill issue im afraid
i actually fucking hate how sharex or any fucking screen grab app does that btw
i have no idea why
im on borderless
sorry im a poser i actually never watched dr who i just wanted this effect and didn't want to call it scp-173
lucky for you i have a slideshow :)
haelp 
oh good, i was stumped if that didn't work lol
if context.scoring_name == 'High Card' then
return {
message = "whatever",
mult = 10,
}
end
this what you were looking for
quick question, how do i make a joker self destruct after however many rounds?
mmm
This is triggering the message whenever I select high card, not play it
what are you trying to do
i see
if context.before and context.main_eval and context.scoring_name == 'High Card' then should work
Ill try that
context.other_card doesnt exist in context.end_of_round
oh fun
what do u want to do here?
doesnt seem like it needs context.end_of_round
is this how to properly check if a sold consumable is a certain consumable?
use this instead
context.card.config.center.key == "c_world"
thank you
How can I make a message pop up before the return function
SMODS.calculate_effect({message = "..."}, card) --card refers to which card the message will pop up on/below
-# use it outside return btw
somethingcom you are poking literally all of my messages sob
whats weird is that other card/context has worked before with another joker
context.other_card only exists for some contexts
ah
this is the problem line
if not context.repetition and context.game_over == false and not context.blueprint and context.other_context.ability.extra.is_dalek then
change
if not context.repetition and context.game_over == false and not context.blueprint and context.other_context.ability.extra.is_dalek then
to
if context.post_trigger and context.other_card.ability.extra and context.other_card.ability.extra.is_dalek then
Yaaaay no more crash
I wish more people played my mod, feels barren sometimes in my thread 😔 who shall I ever ask balancing questions too, lmao, hehehe nhfhsdjhb sorry this is all nonsense aint it? I'm so tired, I shouldn't be up rn, it's almost 3am bnjhbfjhsd
share thread
^
Just gotta let the Katarina explode and have it create planets
yippeee, tho, notes to be had here
1: It requires both talisman and fusion jokers, tho, it is preeetty vanilla balanced other than the fusion jokers I'd say, hopefully
2: It's pretty work in progress atm, so some art might be placeholders, lol
https://discord.com/channels/1116389027176787968/1371935681592426556
thank you for checking it out if you do! hehehe, I'mma head to bed rq tho, I'm so tired lmao, have fun!
IT CRASHED WHEN I REROLLED WITH FLASHCARD WHAT
card.ability.extra doesn't always exist and its not always a table.
yeah i forgot it can be a number or just anything instead
if context.post_trigger and context.other_card.ability.extra and type(context.other_card.ability.extra) == "table" and context.other_card.ability.extra.is_dalek then
change the thing i said to that
There were go, much better
Took 5 antes to be destroyed but it gets destroyed by the Dalek!!
Ok, now how the hell do I make this woman make Planets when she explodes
SMODS.add_card({set = "Planet"})
Which section should I put that, and 2 of them (if they have room)
GYAHAHA IT WORKS
I still need to figure out how to create 2 instead of just one
SMODS.add_card({set = "Planet"})
SMODS.add_card({set = "Planet"})
how would i made it so a joker makes a card act like any suit? kinda like smear joker
Why when one buys a booster pack with negative cost, no money is gained or lost?
i keep getting an error when trying to play specific music when having a specific joker
Log?
Your key can't have spaces.
im pretty sure you return a number in select_music_track
priority stuff, idk
really?
No, you can return anything, a number just means it'll have priority.
does returning true automatically consider the music track as having the highest priority
i removed the space but i'm still getting an assertion error
No.
14 working jokers >:)
The one with highest returned number.
‎
I commented it out for now and everything is working fine i just need to figure out what is causing an assertion error
Do i have to have the prefix infront of the key?
for the joker
like j_prefix_jokername?
Why dosen't it print anything when i buy any card
calculate = function(self, card, context)
if context.buying_card then
print(card.cost)
return {
}
end
end
mainly looking at the find card function
Where are you using the key?
that's the key for the joker i'm working on
Oh.
Yes then.
ok will try that now
If I want to make a one-time power up consumable that has a unique effect for every joker, would that be hard to make or could I maybe write a function for every joker, like WhenPoweredUp(), and the consumable would only call that function and done (I have 0 modding experience so I don’t even know if I can make my own function for a Joker)
Yes.
That would take way too long.
It would probably be better to make a custom context though.
What is that
is this correct or should it be 4 of a kind?
That is not correct it should be "Four of a Kind"
If i had a voucher that awarded money at the end of round (similar to Golden joker or Investment tag) would it just be a return = {dollars = N} in context.end_of_round?
card:is_suit("Hearts")
the commented out method is causing an assertion error, tried to do a jimball thing with playing the dk rap when getting a specific joker but i'm getting nonstop crashes
might be doing something wrong but i tried to look at the jimball code but couldn't find the portion that plays the music
No it wouldn't but yes it would because calc_dollar_bonus doesn't seem to exist on vouchers.
You need j_modprefix_key
tried that and it still causes an error
Code?
Also your returning a table I think because next() returns a table.
why does this not work,?
A card cannot be multiple suits unless it is wild?
idk which portion to show
Also it's xmult not Xmult
that code will only run if the Joker is Hearts and also Diamonds and also Spades and also Clubs, of which it cant be any
might be wrong but pretty sure "card" there the Joker?
oh
bwa
how do i check if theres every suit in the played hand
context.scoring_hand[i] will give you the i'th card that is scored
Was mainly referencing this when searching for jimball stuff to reference
i'th ?
as in
context.scoring_hand[1] = 1st scored card,
context.scoring_hand[2] = 2nd scored card... etc
check each of the cards scored and check to see if there's one of each suit, keeping in mind what Somethingcom said that a wild card will return true for all of those suit checks
wait would this not look for these suits in this exact order?
if context.scoring_hand[1]:is_suit("Hearts") and context.scoring_hand[2]:is_suit("Diamonds") and context.scoring_hand[3]:is_suit("Spades") and context.scoring_hand[4]:is_suit("Clubs") then
why would something like this not work then? seems to never issue the money
It would
Where are you sending context hooked from?
how would i check to make sure each suit is in the played hand without looking for a specific order
custom context for destroying jokers, that part seems to be triggering correctly so not the issue as far as i can tell just provided for context. if i understand your question
Can you send it
the idea is check for if the scored cards contain every suit & is a four of a kind
use a for loop that runs from i = 1 to i = #context.scoring_hand(the size of the scoring hand), and replace the 1,2,3,4 in your previous code with i.
That would then check the first card for which suits it is, and then the second card, etc. You'll need some internal logic/variables to make sure each suit exists, that way one wild card wouldnt just pass through the whole thing, if you would want that to be prevented/
tryna figure out how to make a joker play music similar to jimball but i'm getting assertion errors rn
pretty directly from paberback but variables renamed for locality
referenced some code from others in this channel but i'm kinda stuck atm
It's SMODS.find_card
had that earlier and changed it to find.joker cuz i thought it would change smthn but it didn't unfortunately
I’m not 100% then. Does it work if you remove the line that resets it back to 0?
This is because I have a joker that makes money used on cards in the shop not spent but earned, but booster packs are different they leave no money returned.
nah, i also get this in debugplus log if that provides any helpful context
alright new question
how do i make it so when my joker is sold, it creates a different joker (that isnt held in hand)
i wanna make it so when the left card is sold, it creates the right card
if context.selling_self then
SMODS.add_card({key = "j_modprefix_key"})
end
alright n now how do I make a joker destroy itself after scoring
if context.after then
card:start_dissolve()
end
yayy :3
i keep getting assertion errors when trying to play music and i removed the next() because i assumed it wasn't doing anything, tryna see how i can play the music somehow
don't know why the errors happen even if i use the mod prefix and the right key when using find_card
ah okay, it's awarding the money now. it just tosses it onto the current money instead of in the summary a-la Golden/Investment Tag, but sounds like that would require me patching calc_dollar_bonus into Voucher context yeah?
last question, how do I make it do that idle shake that like ,, DNA does when its active?
wait and how do I make it not show up in shops
in_pool = function(self)
return false
end
using j_modprefix_key doesn't work me when using find_card function
uh this doesn't seem to work
Code?
context.selling_self
ough
still doesn't work
Code?
I assume by mod prefix you mean this
and the jokers key is saviour2
I'm trying to make a joker that keeps track of the number of type played, like fortune teller, but struggling to figure out where to keep track of that, and how to increase it when that card type is scored
Is that the correct key?
It's self, card, context not self, context, card
ok the selling function works now
new issue
the new card instantly dissolves without scoring
does anyone have an example of how jimball plays music when selected
If you mean when Jimball is held, then I have some code from TWC to show how.
Please do
Thank you so much
if context.after then
G.E_MANAGER:add_event(Event({
func = function()
card:start_dissolve()
return true
end
}))
end
replace the second if statement with this?
Yes.
sorry for asking so many questions hh
Hope this helps.
You need the key thing.
It can be .ogg also the key requires music in it also sync means it syncs with other music.
That too. Thanks
i have a question, do we have to set the "j_" portion of a joker name somewhere because it think that's what is causing assertion errors for me rn
this is what i had before
j_MODPREFIX_JOKERKEY
It's SMODS.find_card and you need music in the key.
I only have a few more questions then i'll stop bothering u ><
- how do I make a card shake like DNA when its ready to activate,
- how do I play the sfx that plasma deck plays when it does the "balanced" thing
1. juice_card_until()
2. play_sound("gong")
also for the play sound, how do i make that happen when it adds the mult? it seems to do it immediately no matter where i put it
sound = "gong"
i did implement it but music doesn't play
might be missing something
like this? this seems to do nothing
