#⚙・modding-general
1 messages · Page 4 of 1
I just renamed my modloaded .exe to balatro-modded.exe, it created its own folder in %appdata% separate from my main, unmodded game
close to getting a joker in but cant seem to get the localization text to load
check my gist above, or myst's rkey mod
good idea i gotta remind myself to do that
here's myst's rkey mod https://github.com/Mysthaps/rkeyjoker/blob/main/RKeyJoker.lua
I did something slightly different (so I wasn't overwriting the base/core Jokers.png, or using that asset atlas for my art), it's not 100% perfect or done, but it does load in my card's art without touching the rest of the jokers (so it would play nice with other joker mods): https://gist.github.com/theVDude/d6dab9f8ec49091616b7248d84489111
matelote also make a joker mod and the localization part of it is available
the problem is that it does technically touch the rest of the jokers
i'm currently not fully convinced that my jokers are showing up, so i'm setting the banned cards to almost all the jokers so I can try to reroll for my custom ones
do they show in collection?
yeah
but after over 100 rerolls in the shop, with them set to common, I didn't see them not a single time
yeah, they're 100% not showing up in the shop
I just banned everything except the primary joker and lusty/gluttonous/greedy/wrathful, picked those 5 up, and rolled the shop, which should give me any other valid joker but there's nothing it will give me but normal joker. Buffoon pack also has jokers.
so i'm missing something somewhere
i think you have to add them to their P_JOKER_RARITY_POOLS
i will test and let you know
Ahh, I just copied from the rkey mod, I didn't actually look at how they're selected
same lmao
this line in game.lua is what im going to replicate
if v.rarity and v.set == 'Joker' and not v.demo then table.insert(self.P_JOKER_RARITY_POOLS[v.rarity], v) end
ahh, makes sense. let me throw that in and see if it works (since i've already added basically every joker to the ban list)
-- Add Jokers to center
for k, v in pairs(vJokers) do
v.key = k
v.order = #G.P_CENTER_POOLS['Joker'] + 1
G.P_CENTERS[k] = v
table.insert(G.P_CENTER_POOLS['Joker'], v)
table.insert(G.P_JOKER_RARITY_POOLS[v.rarity], v)
end
worked for me
yup
now I can actually copy the effects over
well, actually, now i can call it a night, i'm sick of looking at vscode
I shared a bit of code that makes photograph/wee/half joker all not do their size stuff, i get it
Install https://github.com/Steamopollys/Steamodded the mod loader (follow instructions on github), look at examples on github or from the #1209506514763522108 channel
ah, thats why a couple of the jokers looked weird when i was messing with it
yeah, i think i included a comment that says "you could do this for just your custom jokers but i'm lazy", don't be lazy and only reload the sprites for the custom jokers
Ok I think I found a way to fix this
Might be able to finally get to making art
wait why is htr not scoring
Please code please leave me be let me have a functional joker
i need some help with the deck creator mod. wont shop ou in the mods list
nvm got it working
OKAY FINALLY
I think I can say that this joker works
Time for the art
Note that it doesn't include the hand scoring part that people thought it had cause I still can't figure that out
why avoid overriding calculate_joker?
So if someone mad their own custom joker it doesn't run the risk of incompatibility.
i made half joker only count as 0.5 jokers for stencil and abstract, they both work correctly and stencil displays correctly but i can't get the text on abstract to match. any ideas on how to get the localization stuff to match the calculations in the card function?
Alllright
yes, you have to override generate_UIBox_ability_table
it's a weird function to override, i got it to work in my mod but it's not pretty and may cause issues i haven't done enough testing to be sure https://github.com/lusciousdev/LushMod/blob/main/LushMod.lua
time to try fixing this ability'
I'm not sure how to reword this
i think its doing the whole suit check and set before activating the ability
what is the intended effect?
Text is here
It needs to store the first scored card's suit, then on the next hand, check the suit, and if its different, trigger the ability
you probably need to check if you're in the hand after checking if the context is individual
if context.cardarea == G.hand then ...
wait G.play not G.hand
in the played cards
its just the first card
i said hand meant played cards
ah
in card.lua it goes
if context.cardarea == G.play then
...
end
end```
that might not be the fix but it might prevent a bug down the line
and then context.other_card is the card it's checking in the calculate_joker call, you could look at something like the idol code. check if the context.other_card equals the first played card then check if the suit is different than the suit saved in the joker's data
do i need to throw context.scoring_hand in there at all?
Sorry i'm very new to this whole coding thing i'm pretty much trying to build it with context
since you're checking if the first scored card is a different suit, yeah
oh of course cuz you're looking in the hand
would it look anything like
if context.scoring_hand > 0 and context.other_card ~= context.scoring_hand[1].suit then
if context.other_card == context.scoring_hand[1] then
if not context.other_card:is_suit(self.ability.extra.suit) then
<do the mult>
end
self.ability.extra.suit = context.other_card.suit
end
end```
that's my best guess of how it would work
context.other_card == context.scoring_hand[1] checks that we are looking at the first card in the scoring hand
oh i had scoring hand in there twice
my brain didn't register that scoring_hand[1] was already looking at the scoring hand
that's my best guess at what the code would look like you can test and tweak it if it's not working
Also you don't need to have all those if statements you can just check if they're all true.
Basically all the jokers ingame are handled in this manner
which ones?
context.other_card == context.scoring_hand[1]
and not context.other_card:is_suit(self.ability.extra.suit) then
<do mult>
end
self.ability.extra.suit = context.other_card.suit
end```
ugn doscord format
why
well you want to set the suit even if the watercolor effect is not triggered. that's why it's in the same block as the check that we're looking at the first card
oh yeah
you could combine the ability name check and the first card check
wait AHH
It is to late to code
damnit
At least the first two if statements can merge and the last one can stay
ended up having to also rework how abstract functions under the hood but it worked
nice
Cuz mult doesn't go off. Is there a way to check if the suit is being stored when the hand is played?
it's still functionally the same just now it supports exceptions to its rules
if context.other_card == context.scoring_hand[1] then
local last_suit = self.ability.extra.suit
self.ability.extra.suit = context.other_card.suit
if not context.other_card:is_suit(last_suit) then
return ...
end
end
end```
i think that would help. the self.ability.extra.suit = context.other_card.suit has to come before the return or else it'll never happen. so you need to create a local variable to hold the value before you overwrite it
Ah okay
also, you have an error on the line
if context.other_card = context.scoring_hand[1].suit then,
the equals sign needs to be a double equals and the .suit needs go get removed. it should be
if context.other_card == context.scoring_hand[1] then
does it give a visual indication when the card triggered?
it doesnt trigger
I found the reason for your custom joker atlases not working, just sent a PR to steamodded that should fix it
if you look at the return in the idol code it looks like
x_mult = self.ability.extra,
colour = G.C.RED,
card = self
}```
you could try copying that but with self.ability.extra.xmult
(this, specifically, and the problem is that the atlas is preset here for jokers and vouchers)
Except idol procs it on the card doesnt it?
not on the joker?
interestingly enough, idol doesn't function
No jokers seem to function
i may have a larger issue
maybe i put return calc_ref in the wrong spot
yeah, i moved it a bit and jokers seem to work now
yeah, if you put your code under elseif context.individual then ... it's going to be triggered on a card.
if you want it triggered on the joker you need to put it in the else condition of that big if...elseif...else statement in calculate_joker and then under if context.cardarea == G.jokers and then in the else statement of the if statement there.
this introduces some other issues, one I ran into is that the context.scored_hand value isn't set in that block. it gets a little technical.
arg
if you look at my mod code https://github.com/lusciousdev/LushMod/blob/main/LushMod.lua
go down to the end of calculate_joker there's a card called "The Buffer", it checks if there's a 5 in the played hand, not the scored hand
i am still not sure if it's possible to get only the scored cards in that context
this one here
yeah, it just loops through the played hand and increments a counter when it sees a 5
then adds +15 mult if the 5 count is >=1
i see
the issue is played_hand is not scored_hand and idk how to work around that yet
local value 'fives' is 0, if in context.full_hand is a 5, set local 'fives' to 1
if fives is 1 do mult
i see
so context.full_hand is played hand not scored hand
yeah, so the 5 doesn't have to score
hmmmn
let me test this cause the more i look at the code the more i think scored_hand should be assigned
the closest i can think of is Photograph
That's still individual though
oh wait
i thought walkie talkie
Midas Mask goes through full hand
but that applies it to the card not the joker
ok scoring_hand is set idk what i was doing earlier
oh on the joker
So i just need to move it from individual to joker
i guess?
but it still doesn't seem to proc
even on the card
something's wrong...
anyone know how the debug messages work
no, but for clarification which ones?
local last_suit = self.ability.extra.suit
self.ability.extra.suit = context.scoring_hand[1].suit
if last_suit ~= nil then
if context.scoring_hand[1]:is_suit(last_suit) then
return {
message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}},
Xmult_mod = self.ability.extra.Xmult
}
end
end
end
anyway this was my attempt at making the watercolor joker to work but i couldn't get it working
Run Steamodded\debug\tk_debug_window.py
I've picked the worst first joker to try mod apparently
all messages sent via sendDebugMessage() will appear in that window
tyvm
it's basically print() but clearly you can't print to a console here
if context.scoring_hand[1]:is_suit(last_suit)
is this right?
i guess it should be not is_suit(last_suit)
that's the only part that stands out to me
okay now that i'm done with my thing can someone recap what we're trying to do
i wish i could contribute more to this
i was just trying to help itsmythie with a joker
i've been working on some small, mostly QoL stuff, here's what i've implemented so far:
- Madness gains the multiplier of another Madness if it eats it
- Half Joker counts as half of a joker for Abstract Joker and Joker Stencil
- Voucher Tag, Handy Tag, and Garbage Tag don't appear before ante 3
- Boss Tag doesn't appear before ante 2
- Burnt Joker and Sixth Sense shake when active
- Dusk and Acrobat shake when active
if anyone has some similar ideas i'd love to hear. took a lot of these from suggestions
can you send your .lua file over
I want to try to mod in at least some of the ideas I made in https://discord.com/channels/1116389027176787968/1210093881459216414, but I have no modding experience...
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.
Sure. i was trying to understand how make it a joker ability and not an individual, but im not quite wrapping my head around it
i've also got the wrong mult ability in there
i figured something out
when you get the context.scoring_hand[1].suit it should be context.scoring_hand[1].base.suit
local last_suit = self.ability.extra.suit
self.ability.extra.suit = context.scoring_hand[1].base.suit
if last_suit ~= nil then
sendDebugMessage(self.ability.extra.suit)
sendDebugMessage(last_suit)
if not context.scoring_hand[1]:is_suit(last_suit) then
return {
message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}},
Xmult_mod = self.ability.extra.Xmult
}
end
end
end```
this triggers for me. not sure how if it works with wild cards though.
also i spelled watercolor the american way in my code so watch out for that
yeah that elseif context.individual should just be an if
oop, now i need another end
if you look at the code on github i shared earlier i included all the if...elseif statements from the balatro source to prevent any unintended contexts reaching the final else statement. my game was crashing before i added that
this is what i just got
what, adding all the elseifs?
yeah
essentially you just want to avoid a calculate_joker call that wouldn't make it to the else statement in the official game from making it there in your code
cause they all have different contexts and some may not have all the variables you rely on defined. like scoring_hand
all of those empty cases can't have any effect, regardless of context
not sure what you mean
yeah i think in this case all the elseifs are needed
Triboulain't
if calculate_joker gets called with end_of_round set to true but you don't have that case defined it'll fall through to the else statement. and all the jokers get evaluated at the end of round. so it's gonna call the joker ability but the end of round context wont have a scoring_hand
you could also check that all your context variables are defined/not nil i assume. i've never used lua so i don't know the specifics
i believe this is the context for Flower Pot which should have the same conditions as Watercolo(u)r Joker
{cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}
so yes all the elseifs are required
how do i pull up the debug messages?
.
run as in
uhhh windows+r run?
or different run lmoa
at the risk of seeming like a bigger idiot
.. do you have Python installed?
you will need to install the latest version of Python to be able to run the .py script that opens the debug window
yup, i got python
yea you can now run that script and it will open the tk window
man i'm so not a coder
:p
maybe someone can see why this doesnt trigger, cuz i sure cant
context.individual should be elseif
killed itself when playing a second suit
i'm sorry, does that say an issue in line 135?
thats the xmult return
define the Xmult in the extra field at the top
idk anything about modding for this game but the error suggests that in the return message string "message" you are trying to pass a nil value, and when it tries to concat (combine) the strings to become one message, it crashes
this
meaning some variable following the message = is nil
have Xmult = some value in the extra table
oh this one up here?
mhm
ah i getcha
thanks
i was wondering where the number for the bonus came from
makes sense
i've put this in and it has the same issue
suit doesn't exist either
it doesnt?
ah shit
oh man do i have to define suits like seeing double does
which suit doesn't exist? i'm confused
cuz it's mentioned in other cards
oh
oh
cuz it says self.ability.extra is suit
i get what you mean
dammit same ccrash
does suit need to = something
just put like "None"
Huzzah
the effect works
thank you everyone
fuckin carried my ass there
One thing left to do for that card
and that's to fix the description so it displays the suit
i have an error
it does not trigger in order with other jokers
it just goes first
this is some code that's from a deck example, i'm trying to edit it so aces are glass, not all cards, though i don't know how to do that, could i have some help? 😅
if more info is needed i can give it, though i don't know what information is needed to understand the problem. this is not my code.
you probably are interested in the for loop, that loops thru every card and sets it ability to glass
you want to make a check if the card rank is ace then set it to glass
instead of every card
look at other code examples that check/modify rank to see how you might determine the rank of the card
Is there something i have to plug into my code to make it wait for other jokers before playing?
Cuz even if the card is on the rightmost it still plays first
no clue
Maybe its because it's individual?
Ah idk
The effect works
Accomplishment enough for now
I should probably test it with wild cards too
Thanks a bunch for your help myst
Isn't watercolor joker supposed to work like photograph (photograph procs when card is scored, before any other normal joker) ? If that's not the intended effect, I think the xmult shouldn't be applied in context.individual
Its supposed to work like card sharp
Or any of the normal xmult cards
The order the family etc
I'll work out what its supposed to be tomorrow
if one wished to get into modding, what would be a noob's guide to modding
or like first steps to take
the game is still new so there aren't many resources to get started with modding yet
if you had prior experience with a programming language then lua os pretty easy all things considered, you can check the source code or existing mods to see how lua works
imo lua is so much harder than other conventional languages, its a mess getting to understand someones elses code
I doubt that's really about the language itself, more so your style and what you're used to reading
array indices starting at 1 is mad tho
thts not that bad
everything being a table is very annoying tho, basically no static typing at all
comparing python and lua python is def cleaner, even tho they both serve simmiliar purposes
eh, dynamic typing is fairly useful for modding
im 1 hour new to modding 🙆♂️ i have no idea what im doing
We’ve gotta make cards mista white
this deck will be so fucked up to play
i imagine this snowballs very well in late game but it will kind of force you to change strategy mid early game
thats the first come that come up to my mind for a basic to code deck
right now its not entirely functional i need to figure out the inner workings a bit more
but its coming fast 💪 💪 💪
It’s a pretty unique idea
I would try my hand at making some stuff myself but I have zero experience with Lua
me too :x im just making shit up
i think this one wouldn't be too bad to setup tbh
Commiting to the bit has lead me to places I wouldn't even go with a gun
imagine getting hologram joker with this deck 🙆♂️
Real hero behavior here!
So it’s constantly the glass challenge but without the glass and instead meth?
Downside: You’re losing the 2x mult per card.
Upside: You get more joker slots thanks to “Oops All 6s” not being there
And it’s breaking bad
the discard gimmick can be gamebreaking
it can go insane yeah
that's just real life
yeah, as soon as the PR goes through it should Just Work - in the meantime if you want to copy the code within my PR there shouldn't be any issues from it being duplicated
just recalling set_sprites in set_ability is working for now, but it's good to know that it shouldn't be necessary once the PR goes through
yeah, in effect the PR is doing a similar thing, just in a less janky position
(wrapping around set_sprites where the issue lies rather than set_ability)
no discussion of debugging the source code.
looking at the combination of this and the collection menu with annoyance
collection is bugged?
I think if you find a bug via code you can still report it. Just explain the bug in plain terms rather than showing code or explaining with code examples?
if it is a "this code isn't optimal" kind of thing, I wouldn't say that qualifies
aha
Yep; I did this with seed searcher multiple times
because yeah, what I found is stuff like the tarot collection using math.floor instead of math.ceil, and spectral cards going off of the number of tarot cards you have instead of the number of spectral
(and also math.floor for spectral)
i still have no clue what counts as debugging source code
it doesn't matter for the vanilla game because the number of cards is always set, but it instantly pops up once you start adding tarot or spectral cards
I could see those being purposeful implementations. I don't know if those qualify as bugs
math.floor prevents there from being a new tarot page until there are 11 new tarot cards or more
I think the rule is in the spirit of "please don't rip my code apart and tell me why you think that doing it your way is better". just my guess
and, again, the number of pages for spectral cards is based on the number of tarot cards you have, in a way that is DEFINITELY not intentional
ic
because it uses 9 instead of 11, when 9 is meant for spectral and 11 is meant for tarot, based on the rest of the code
I would say find a practical way to reproduce this, and if you can do so without using code as an example, it is fair game to post to bug-reports. fwiw I have seen people comment about "bugs in the code" that weren't actually bugs.
Not saying you aren't correct, but put yourself in thunk's shoes. Repro it in the game and I think you can bubble it up to bug-reports
So if it's not possible in vanilla I can't report it?
because it strictly cannot affect vanilla because the number of cards in the collection is static
it'll only affect thunk if they try to add more cards, which they may or may not
Ah I see, yeah, I would say keep this in your back pocket in case more cards are added in the future where you can repro in vanilla, and/or create a fix for this for people playing modded and post about it in the #1209506514763522108 channel
I would give thunk the benifit of the doubt that they would address this if/when more cards were added to the base game
yeah, I'll be making a fix mod, it's just gonna be really destructive coding which I don't like to do
right, that thing...
same thing for planets applies
except it's just not paginated at all
adding 4 planet cards it would show 12/16 with exclam, but you can't get to the last 4 cards
yeah, same with enhancements and seals as well, but that's at least more understandable since base game only needs one page
I'm mainly frustrated by the fact that I can't report the typos, because they are typos from copying and pasting code
i ended up changing planets to 8 per page in six suits because I didn't want the second page to be that empty
so long as this isn't fixed, I guess it'd be better to have a fix mod instead of each mod that needs it destructively making that change
the thing with spectral and tarot means that the number of spectral card pages LITERALLY depends on the number of tarot cards
yeah, that's what I'm working on rn
probably going to just put it all in one function that gets called by all the menus rather than the copy/paste job that it's currently set up as (and no hard feelings about it being a lot of copying/pasting, but uhh yeah I'mma make a nicer version for myself)
i have some stuff for the planet collection in #1210728178201526373 if that helps
absolutely cursed thought but has anyone made a new hand type
still potenially unbalanced though
ah yep you did basically exactly my idea
i'm thinking about adding a handful of rocks (5 rocks)
actually I wonder if that would be a 5 of a kind
damn
as stones specifically have no rank and suit
woulda been funny if it was a 5 of a kind (the kind is Nothingness)
id love to see a 5 rocks hand with the related planet being asteroid belt
search my history ive said it before, months ago haha
been in the back of my mind since
not surprised other people have thought about it lol
kuiper belt makes more sense as it has a proper name
in the same way that a royal flush is a straight flush, there could be some specific hand like aces full of kings or kings full of queens that could be a special type
if someone feels like implementing a whole system, there was talk about a "subhand" system months ago
@rare hill (half joking)
which would change the way planets work, making some of them more broad and adding more specific ones for nicknamed hands
like jupiter would have a significantly reduced effect but buff all flush related hands
subhands could be moons...
yeah you could do a flush moon that is w eaker but buffs all flush related hands
same with straights, pairs, etc
Yeah, definitely seems possible but that'd be a bit of a system recode probably
i mean i do have royal spectrum, that's the straight spectrum equivalent of royal flush
oh yeah its an entirely new system
other way around, the planets are the blanket buff, the moons are the subhand specific buffs
ah gotcha
although not really "hard", just needs some messing around to see how destructive it needs to be
but yeah implmenting subhands in the right way could negate the issues of adding new hands
subhands would be quite a chunk more work than #1210728178201526373 already was
which then allows adding potentially dozens of nicknamed hands that could all score differently
this kind of coding is literally my home turf, so I'm not that worried about that tbqh
a saturn subplanet card for the great hexagon could be cool
oh wait, actually, I just realized that subhands are a different thing than I thought you were talking about
yeah on my part it's more just putting time I don't always have available to commit
oh also if anyone wants more ideas, id love a pack of planet cards that are more generic than single hand, somewhere between black hole & planets
ive made the suggestion to localthunk a few times over the time ive been here
I was thinking a system for stuff like the "includes a 3 pair" jokers, but if it's just a "hyperspecific hand" that should be totally fine to just wrap the functions and do
like all flush types, all straight types, all pair types, all "of a kind" types?
well the idea is you change the way the whole poker hand leveling system works so its more generic, and less targeted
I mean, you could just make them star cards if you want the easy route
which then allows you to add more specific hand types that dont get screwed by needing a hyperspecific planet card
i thought this would go hard on the hand calc, but that's the easy part here
more so the way hands are managed and the planet system
oh yeah that makes sense
constellations?
like a planet that specifically benefits nicknamed hands with low cards, like wheel (12345 straight) or one that benefits high value cards (royal flush)
TRUE
that's easy to add
im sure it is, just sorta stream of consciousness remembering all the suggestions ive made lol
it would just require splitting the hands
and probably making levels from the base hand carry over to the subhand
or maybe a card that buffs named subhands in general would be cool
imagine seance "if played hand is a royal flush"
yeah thatd be lower effort and interesting, just a single celestial card that buffs all nicknamed hands, which would currently only be royal flush but could be expanded
and that buff would be stacked on top of the actual hand it pulls from
adding hand nicknames isn't out of the question, it's just a thing of whether you'd need to pass additional information to be able to check the displayed hand name against the actual hand name
no wait that doesn't work
because loc
just add a "subhand" variable
almost everything is passed by table, I doubt this is an exception
yeah we can probably pass that somewhere in an args table
shouldn't bee too big a deal
Looks like the generic implementation idea's gonna work out
ok, joker and tarot collection menus are reimplemented
gonna take a break to fix tarot sprites because that's what's bugging me now [edit: oh. That was a typo on my fix specifically in the mod. It's working now, and the PR had it fixed anyway]
oh god generate_card_ui is gonna need a full recode (within a mod) at some point, since there's no clean way to hook into it
at this point Steamodded's gonna have a ton and a half of extra stuff just to make things work smoothly
are you gonna ship of theseus the entire game gepsi
Possibly, given enough time and incentive
if I may ask, how difficult is it to mod Balatro currently?
I kinda wanna try making a small mod, but the size of the mods (and the fact they're all just one file) kinda scares me lol
i've just been directly modding the source and it's pretty easy with knowledge of programming in general
Depends on what you want to do.
Reskinning is pretty easy. Creating new decks/jokers is harder and you'll need to spend time learning how the original code works
ah alrighty, I wanna try creating new stuff so I might have to spend some time learning the codebase yea
I have some code that's gonna make adding jokers a LOT easier
Oooo can't wait for that then
I'm just trying to finish up the actual mod part first, because it has a few fun ideas I've been asked to make
https://github.com/GoldenEpsilon/ShamPack/blob/main/ShamPack.lua
There we go, what you'll want to check out are the add_item and refresh_items functions
i'm going to swap these on my client
this is from the scoring function, +mult on cards in hand triggers after xmult. idk if this is intentional but i'm not a fan
common_events.lua, around line 830
shouldn't need anything more than swapping the order of those
yeah you probably can, i just haven't bothered to figure out the modloader api since the source is so simple and i'm mostly modding for myself 😅
otherwise i'd post a patch myself
can you add enhancements to cards in example hands (in the hands table)?
by modifying create_UIBox_hand_tip, you could
what do i need to add here to add a specific joker to that deck?
what file is this in?
functions/UI_definitions.lua
thank you
I have a small unresolved issue that's been puzzling me.
I'm trying to implement a joker that mostly works like erosion, meaning it depends on the number of cards in your deck. The scoring part works well, the joker works as intended during gameplay. Generating the description is a bit harder though, when I look at the joker description through the collection in the main menu, game crashes because G.playing_cards does not exist. I mean, it kinda makes sense because I haven't started a run so I don't have any deck yet.
However, when I look at the original generate_UIBox_ability_table function, erosion uses :
elseif self.ability.name == 'Erosion' then loc_vars = {self.ability.extra, math.max(0,self.ability.extra*(G.playing_cards and (G.GAME.starting_deck_size - #G.playing_cards) or 0)), G.GAME.starting_deck_size}
It clearly uses G.playing_cards, and checking erosion description through the main menu does not crash the game. I'm not sure what happens here
Can you show what yours looks like to compare?
It looks like it checks if G.playing_cards exists, and if it does then it takes starting size minus playing cards, but if it doesn't, then it sends 0
oh so that's why it uses or 0 , I was so confused on this part. That means evaluating G.playing_cards does not actually crash the game but trying to display it does.
I feel so stupid lmao
I've never coded anything in LUA, so I mean you can take it with a grain of salt, all my familiarility is in other languages.... but just from using that knowledge, it's what it -looks- like it's doing to me.
yeah it makes sense
That way it can display a value if g.playing_cards doesn't exist (you don't have a deck yet) or if it does exist it displays based on the deck's count.
Checking the deck's count when it doesn't exist -can- cause a crash because you're trying to access a nil (or null) value.
But checking if it exists at all, doesn't crash it, because you're only looking to see if it is there or not.
Problem solved, thanks 👍
yeah, there's a lot of really clever bits that use the "something and (do thing with it) or value", G.playing_cards is nil, so it doesn't evaluate the and and jumps to the or
Something ternary operators in other languages are great for
That tracks.
I was confused as to how the logic is evaluated here
nil is falsy
all my homies hate nil
Is anyone working on mods for the switch version?
check pinned
My mistake. Will repost my question in general.
And on unrelated note. How do you see pinned messages on mobile? Haven't been able to do so since they changed it.
all modding discussion should happen here or in #1209506514763522108
click the channel name, then 3rd tab will be pins
with that said, thunk laid out the rules, so no discussing modding on anything except PC, please
Clearly false. If I can't discuss switch mods here.
switch modding isnt allowed at all
read my follow-up comment. the dev made specific rules for modding channels, and only discussing PC mods is one of them.
The rules forbid me from speaking about switch mods here. I haven't seen the rule about discussing it elsewhere. Can you point me to that rule?
Or statement by thunk.
sure, it is rule #11
Kay. Makes sense. I can see that.
Has anybody managed to make a modded Seal yet? ;0
hey chat, newb question here, but where would i find the image files for the different cards in the game? i have a super simple idea for just replacing some textures i wanna try out
Open the exe as a zip , should explain itself from there , there's a texture folder
it should theoretically be similar to modded enhancements
ty, got it
didnt know that was possible
okay now i just need to find the heritage for the future tarot cards lol
Quick question, is there a readily accessible list in JSON, CSV, etc. with the different assets like jokers that displays cost, rarity, description etc?
well this is how i found out you can just extract a Love2D project with 7zip and get the lua back
getting an error here
it's in game.lua iirc
plays nice with 7z
aight will try
yeah everything is in there plus the localization files
just need to cobble them together into what i'm looking for
does the same to me with 7zip its weird
that part should have what you want
it literally just worked for me with 7zip, right click the exe, extract to balatro/
init_item_prototypes() in game.lua:215
yup, i think i'll knock together something repeatable because i suspect things will get tuned with time
i don't know the first thing about lua but i'm pretty decent with grep and sed 🙃
interesting, it appears to pull random ones
let me try it without spawning the legendaries in with debug
yeah
jimbo secret legendary confirmed
in one of the demos (maybe both) once the shop ran out of jokers to make it just froze the game
now it just spawns a normal joker
good fallback
there are fallbacks for pretty much everything now
⚡
spectral is incantation
i decided to actually try and make a custom sprite for one
oooh
The sixth legendary joker, Jimbo
it looked like this originally i decided to make it from scratch
I had an interesting idea
What if i imported 6KT to Balatro while i’m working Hanafuda
I have the full version
wonder why spectral is incantation
since all the other fallbacks are the most basic in that group
like pluto for high card
fool is pretty obvious since its tarot 0
and the base joker cause
its the base joker
but spectrals dont really have a basic one
which one is incantation again?
it's because it's number cards
adding number cards is the most basic thing the spectrals do
immolate could end your run
Immolate is really busted
yeah a seed searcher is absolutely insane 
both Immolates
umm its cuz it starts with I . that means 1 . duh ||/j||
The one thing I hope with that is people don’t use it to backseat streamers in endless
I'd say its probably the most tame / reasonable, it can kinda happen in any scenario too
“Oh, you should open this spectral pack, the first one in ante 11 has soul!”
Or “you should buy this bad joker so the redraw gives you Blueprint in two antes!”
Immolate is amazing until every time it’s offered all the important cards you want to keep are drawn first.
I still remember that gold ghost deck loss w/ Baron where two immolates were available in spectral packs and both drew all my kings.
i'm trying to make a joker that adds +25 chips for every ace in hand. Turns out the spot in the code that checks all the cards in hand only supports adding mult, multiplying mult, and adding money
i think i'd have to fully override G.FUNCS.evaluate_play
that's wack
but tbf that's the only kind of effect that was intended for the game so someone's going to have to make a mod for that
you can do it manually
check the jokers in shampack
oh, wait, in hand
I'll have to take a look at that, that's an interesting one
yeah it's why I nudged you about this one
in hand is the issue
I'm gonna send a Nightly build with the Joker API in a matter of minutes
And I will need some testing
oh?
I should probably like, play with mods
so I'll DL that and play ShamPack along with it
back coding in windows because Balatro and i forgot how comparatively finicky it can be. not a bug i'm looking for help with, just having a moan
It will be ready when this build finish: https://github.com/Steamopollys/Steamodded/actions/runs/8074587206/job/22060123907
line 825 of state_events.lua, loops through the table returned by calculate_joker(cardarea = G.hand ...) and only checks for x_mult, h_mult, dollars, and message
def main():
print("wtf?")
return 1
> python wtf.py
Process finished with exit code 0
I wonder if that table could just be expanded with minimal issue
probably not
you can put anything in the table when you return it. issue is it doesn't know to look for what you added
Alright, that the Pre Release for joker API: https://github.com/Steamopollys/Steamodded/releases/tag/0.7.0-PRE
If some modders could test it so I can know if it is good enough for now. Little example mod with it:
i put the full evaluate_play func in a new lua file and added the chips handing from the played card code to the in hand code and it works fine
obviously not ideal but it does work
context.individual in Card:calculate_joker should already let you hook on it.
Thanks for your hard work Steamo 🙏
i am adding my joker function in context.individiual, context.cardarea == G.hand
but adding chips to the return table in that block does nothign because in evaluate_play the effects handling never checks for chips
for ii = 1, #effects do
--if this effect came from a joker
if effects[ii].card then
...
end
--If hold mult added, do hold mult add event and add the mult to the total
--If dollars added, add dollars to total
if effects[ii].dollars then
...
end
if effects[ii].h_mult then
...
end
if effects[ii].x_mult then
...
end
---------------------------------------
--- NEW CODE TO SUPPORT CHIP EFFECT ---
---------------------------------------
--If chips added, do chip add event and add the chips to the total
if effects[ii].chips then
mod_percent = true
hand_chips = mod_chips(hand_chips + effects[ii].chips)
update_hand_text({delay = 0}, {chips = hand_chips})
card_eval_status_text(G.hand.cards[i], 'chips', effects[ii].chips, percent)
end
--------------------
--- END NEW CODE ---
--------------------
if effects[ii].message then
...
end
end```
that's what im adding to the evaluate_play function
yep
i copied my addition from G.play lol
it's not a thing that happens in the base game so im not that surprised
Isn't this what reserved parking does? If so, maybe check how it wokrs
reserved parking adds money
while you're rewriting the function you should consider swapping these
what function is that in
that doesn't actually effect the scoring result, that function gets called by evaluate_play and just shows the text for what's happening
yeah, looks like their orders are different
if you look in evaluate_play for calculating the played cards it goes chips -> mult -> x_mult
i guess my chips handling should go first in my code to match G.play
Whats the opposite of context.individual btw? If i want my joker to proc in order at the end of the hand playing
Cuz atm it procs when the first card scores
Look at the Joker API
Example mod
Wait which one?
Does anyone have a semi-reasonable grasp on the events? I'm trying to clean up some of my code, and what I need is to wait for Card:start_materialize to finish, so I can set the card back to .state.hover.can = false. I've tried just using add_event as is (assuming that it would queue them and call my second event when the first finished) but no such luck.
@carmine flare thanks for all your help last night btw
I managed to get it triggering, just triggering at the wrong time
np
I'll sort that out and test it with smeared and wildcard when im home
Switch it from context.individual
This is probably a silly question coming from a non-modder, but is it possible to recreate the backgrounds of the game in any software so I could make my own with the shaders in Balatro? Or would I need extensive dev-type knowledge.
nvm i was overthinking it and using events where i didn't need to now that i'm cleaning up my code
Hey, so how are you supposed to use custom atlases with this?
because replacing the base joker atlas means you can only have one joker mod at a time
Like said in the PR, it will be merged after the Joker Pre Release. This one is only their to test the Joker API.
Not to be production ready or anything
ah, so only to test the parts such as calculate_joker?
That makes sense. I do want to point out a second direction for possibility, which is making functions that add Any type of card/item (such as what I do in ShamPack), mainly because with how this api looks right now it's what I'd probably keep using even with a finalized version of your api
but that's more preference than anything
thankfully the way it works isn't destructive at all
You can write every ShamPack effect in the calculate callback
And avoid over referencing/overriding the source code with it
yes, and your api does that better, but I was referencing how it's one set of functions for jokers, tarot cards, enhancements, etc
I also personally prefer the way sprites are handled for mine from an api standpoint, but I understand that multiple atlases aren't preferred for efficiency
Generic "Cards" functions will come later, or maybe I will just make it more flexible I don't know
Wdym ?
instead of messing around with the position of the sprite on the sprite atlas you just tell it what sprite you want and it loads the files for you
I need to look to see if love2d has atlas stitching, but if it does that can be used as a way to simplify the whole process while limiting the number of atlases needed
but yeah, I think my tl;dr is that it seems like a good api for getting people into modding the game, but I personally don't think it's generic enough for what it might want to be expanded into in the future and that it could abstract away a little bit more of the busywork
That's the plan for custom sprite
To use whatever Sprite you want, atlas or not
If you look at the previous Sprite API that what @white scarab and I were doing
But I have to put priorities sadly
So you've made it so this Joker api works with steamodded
The Joker API is part of steamodded, the Example mod (or JAPI) is simply there to demonstrate a basic usage
is there any way to make a mod that uses different deck art for the challenge deck? should i just unzip the game, switch the art around in the png, and zip it back up again, or would that mess everything up?
you need to grab the 1x png file of the decks
replace the one you want with yours
and then export that in both 1x and 2x
yeah i know how to do the art bit i just don't know if i'd be able to run it as a game in steam again
why wouldnt you be able to
idk i just wanna be super sure 
okay cool thank you ❤️
:)
ayy, i've rewritten the basics for my seer/oracle joker effect, i've got it tied to having the joker, now i just have to fix it so it goes away when you aren't in a run, and actually shows correctly if you continue a run
Messing around with ranks
It won't be Infinite chips, but something like 100 chips
am i understanding this right?
probably not cuz it doesnt seem to update the joker
don't have the {} around all the inputs
oh i can just true, true, true
ye
does the JokerAPI just use the base jokers.png
yeah, for now, it's WIP
ah okay
more for testing than product currently I think
Ah si
i'm not sure what context i need to use to make this work properly
none of the jokers in card.lua seem to have a context unless they activate in a different way
I'm starting to learn how to mod games, starting with Balatro. Anyone have advice on how to debug your code?
join the club
is it possible to perma just unlock all the decks/stakes in the normal game with mods? or would it have to run on its seperate version forever and not in the actual game if it was updated or files verified
no way to get the game to think its been completed and have them agree its actually unlocked
Ah i'm lost again, i think context.scoring_hand[1].base.suit is falling through or something
that's the line i have issue with
funny selecting
there's a debug console listener thing in the modloader repo that you can run that will allow you to do sendDebugMessage(str) to get some output, but it's mostly just figuring out how things work and testing to see if you get what you're expecting
Or if i take it back to what it was with the wall of elseifs
it will trigger the joker before any chips or anything
i think i need like, end_calculate_context or something
no
if you run it from console you can just use lua's print()
printing is like the simplest method of debugging in any language
I'm not sure what's causing it to do this
trying it without the effect in there to see what happens
Now it triggers 3 times
but only 1 real time
hey how do i repackage the game after im done switching the art around? or is there a way to replace the art while it's still together
ohh okay i must have just . not been pushin the right buttons i think i got it
you're the best 
yaaaay thank you
not sure im a fan of the lil bits that peek out so i might just get rid of those
Why does the save file let me do this????
Anyone know if the UIbox override involves colours?
I think i may need a hand on the uibox stuff, trying to get it to specify the suit that its on
game is silly
HAh
YES
i'm so good
Also whoever wrote the uibox override you deserve head
Now i just need to work out how to add the colour of the suit that it currently is
YIPPIE
What’s even going on here??
How do you have so many jokers?
How are there celestial packs where your jokers go.
shanagnigans
well the game is unmodded but I modified the save file
you can put any card (joker, playing, booster, voucher, consumable) in any area
yes
Oh
Hey Myst is there anything particular i have to do to make jokers work correctly with blueprint?
ohhh i know why it doesnt work with blueprint
blueprint sets the last_suit when it triggers, and then the joker checks and sees the last_suit as current suit and then doesn't trigger
Hi not really modding but I have a question is there a way to only view the background in the game the spinning circle is just so hypnotizing i love looking at it would love to put it in wallpaper engine
Oh nice. I'll try it this evening after work
love the receipt texture
Thank you, its one that i'm most proud of
turned out really well
yeah that's sick
i've just been putting the art, names and rough descriptions in
modding chat what yall think about this idea?
i'll work on the abilities later
rng hell
wait i read that as 1 not -1
i mean its somewhat dependant on rng but i see it as more of a challenge
challenge version of plasma
somewhat
i cant imagine trying to do this with gold stake ontop of everything already on
We need a Joker with w 1000 yard stare
• Scored cards in your first poker hand get a rank up.
smth like that
1000 card stare
balacing is more powerful the later it happens though. Say you have 100x3000 after all jokers (Xmult X2 X3 X5), balancing will turn that into 1550x1550 or about 2.4 million. Balancing 100X100 does nothing, then the Xmult will up that to 100x3000 all the same, like no balancing happened at all
I mean I just thought about it making chips jokers more viable with xmult joker
If you have like 200x15 and a xmult joker it won't help you as much
Might have to rethink this idea
hello , how can i download the mods ?
hi all - we have refreshed the modding forum rules and i would urge you all to take a look
additionally - because we can only have one pinned post - i am happy to put additional critical resources inside the pinned post for easy access. if there are a couple things that are foundational to the work of the folks in this channel please come up with a short list and i will incorporate those there
i've included the starter guide linked above already
I have no issue with OSS licensing and our server rules exist on top of that.
So i just realized this is gonna be a larger task than i thought
I thought i had every card
I definitely do not
They came out with half suits, something called “Dozenal”
They have french rankings, they got whole different sets of cards under the name
There K6T, iRB, ovalia, etc
Hello! Little reminder that you can still test the Preview of the JokerAPI there: #⚙・modding-general message
If you do think this is not covering enough possibilities and/or this is not practical, please let me know.
Okay so i may not have to worry about dozenal
It’s the same deck just in base 12 instead of base 10
I'm curious about #5 and #6... if all mods are to be open source, that inherently implies permission to be redistributed and modified?
Open Source simply mean that the source have to be open and visible to everyone that want them
That is not what that means by any common definition.
For the forum rules I would personally appreciate a more detailed description than "don't debug source code". It's broad to the point where while it could mean just "don't bug the dev about bugs", it could also mean "don't make mods that fix issues", which would be much worse, and I'd rather not have to assume and possibly get burned on the line being interpreted differently than I think
And yeah, no, open source means free to redistribute and reuse
If it is supposed to mean that your source code be available and accessible for viewing, I understand that; but if I am confused about it, so many others will be too.
You're right, open source definition also include Redistribution and Modification
also I'd much rather people feel free to just Use my code rather than worrying that they're not "allowed to" and having to track me down to ask
I fully understand having source accessible for viewing to ensure that no malicious code is being distributed through the Discord, it makes sense that you would require that the code be viewable. I only asked the question because #6 implies expressly permission for #5.
You can write it in the main post
fair, I guess
I think it does the trick? That's what they are doing in other modding community as far as I know.
I'm not a native english speaker so I might be wrong, but "may" means it's a possibility in this definition or am I wrong ?
"may" in this case basically means "can" yeah
the may in the definition above is permissive - the intention is that code be available for viewing for the safety of other users
its still good practice to denote that you are okay with code being redistributed
even if open source 100% meant you are allowed - its still nice to make sure the original creator is okay with it
i can come back and do a clarifying pass on the rules - i'm not opposed
as to the question about "do not debug" - that has been effectively verbatim in the pinned channel rules for a while. for now can we just use our best judgment please.
we don't want to be overly prescriptive, we do just want to avoid issues and promote safe practices
I know that's how it's been in the channel rules, I was just requesting because the rules were being overhauled in the first place - fair enough, though.
like I said - I'm open to a clarifying pass in the rules, particularly the new ones
I don't think it could hurt to clarify that you meant that the source code be viewable or available, and not that all mods are inherently required to adopt an open source license.
All mods must be open source - this does not mean licensed under an OSS license but that the source must be available and viewable to other users.
I have changed it to this
(I am not a particularly technical person and am doing the best I can)
That should clear up any confusion. I do greatly appreciate it.
i appreciate your feedback and clarifying suggestion as well - thank you
👍
A question about this - my SpeedrunTimer mod uses source code obfuscation as one of the ways to prevent cheating. Should I share the source code to follow the rules but make the mod less secure, or am I okay to leave it like that?
let me take this to a mod who is more technically versed and get back to you with a specific answer in your case
ty
is there a modding guide somewhere
oh i meant more in the sense of authoring mods
here are some templates for making your own colored deck
to replace these textures in the game you'll need to rename Balatro.exe to Balatro.zip and replace the /resources/textures/1x/8BitDeck.png and /resources/textures/2x/8BitDeck.png files with yours
note that you will have to make another copy of your image and upscale it with No interpolation to 2x for the second one
go nuts
you'll need to rename Balatro.exe to Balatro.zip
wait you mean you can just . do that?
yeah
i did it on linux with peazip
you can use 7zip as peazip is just a shell for 7zip
is it doable on windows
yeah
it's the exact same process
i was pleasantly surprised since this is the first game in a long while on which this trick works
usually only old games store their assets like this
i feel like i shouldn't be scared to do this but i've never tried changing a file extension so i kind of am lmao
you can always delete the file and have steam check for file integrity
it'll redownload it but your save data will not be lost
save data is stored in appdata
i'll create a backup just in case
let me get you the 2x deck too
here
you can test it out with these 2
first one goes into 1x folder second into 2x
the game will use either 1x or 2x textures depending on the resolution of the game
ah
not sure what triggers the behavior
best to replace both to be safe
i wish there was a simple mod to swap assets out on the fly but im not going to go out of my way to learn lua for it
i know they don't exist in the normal game so i'm a bit curious
if modded in, do negative playing cards actually work? and if yes, how do they work
but yeah changing the extension from .exe to .zip worked perfectly fine
which suprises me
i mean if they're separate ranks i assume they would just be treated as such
oh wait
negative as in adds a slot
i meant edition, not negative numbers
mb
i dont think they exist but id imagine theyd just not count towards hand size
why would you want negative chips anyways
if localthunk added that specific behavior in
not sure what the code looks like so i can't say
it could be in there by default by way of how the code is organized
it does make sense if it would work the same way as jokers/consumables
i dont think consumables have editions
by effectively adding 1 to the total number of slots
a negative tarot would be interesting though
i'm guessing you haven't seen all legendary jokers yet?
doesn't one of the legendary jokers add negative to consumables
i havent played the game too much
im a casual player
bought the game two days ago
ah
well, this
it's called perkeo
so That's what that does
although it's not fully accurate
what it actually does is make a negative copy of one of your held consumables
so, for example, you're holding the fool and trigger perkeo? now you got a fool and a negative fool
also works with planets and spectrals
so, did it work?
oh i haven't tried it yet hang on
was trying to just make ugly textures but instead made somthing cool and made the background more chill for motion sickness
ye was not trying to make anything cool, hell was trying to do the opposite
i can't add the files
winrar
winrar in 2024?
winrar is okay but i still recommend 7zip
yeah let me get that rq
it's small it's fast it's free it'll never bug you
and it'll work on balatro.exe
i'd remove the images first and add them later to be safe
i think you can direct replace but i was trying to walk around any corruption
i tried replacing the files in 7-zip and it didn't work
it just redownloaded the game when i tried launching it
"Happy accident"
whattt
ok we really need like an easier depack-repack tool then
if you want i can slide you mine
or apply any changes you need made
ok i tried just running the application instead of launching it from steam and that worked
Remember to close the game before updating the SFX archive
of course
And only 7zip can, Winrar can open it but is not capable of editing without breaking it
are there any plans for a simple texture loader mod yet
wow! i didn't realize winrar sucked
No it's amazing, 7zip is just better at SFX than winrar
when i use windows i still use winrar
That already online, example mod: https://discord.com/channels/1116389027176787968/1210420314316738632
if winrar is so amazing, why isn't it open-source
it's the nostalgia and making rar archives for me

very cool, i'll get onto making my changes into a mod
i guess i did something wrong the first time because now i can launch it from steam with the changes just fine
Some other texture packs already exist, you can look at them to have a better idea on how to use it 👍
it's easy enough to understand
I mean, even if not open source, It's still a very good tool
fair
Quick question, modding the thing I want to do isn't going to be hard. I really just need the variable that retrieves the current maximum hand score for the run. Wondering if anyone can just hand me that info.
i don't think it calculates the final score for a hand until you actually play it
Yeah, after is fine.
oh i see what you mean now
It might be stored somewhere since since it's used by the game at the end of a run
Like the score you see in the postgame screen?
Yeah that.
Maybe look at the content it's using
You migth find what you need
I was looking at this yesterday, I'm not at my pc rn so I can't check what it's specifically called but it's one of the UI handlers for the game over screen
I'm not a big Lua guy, and was hoping to avoid too much searching 😅
How would you look into it? Debugging it?
Nop with the source code, but I'm not infront of my Windows I can't check now 😦
I can give it a shot. Thanks.
i was looking through the files and apparently more than half of the entire game's filesize is from the font it uses for some non-english languages
that tracks honestly
how do I fix this error? I'm trying to use the Steamodded modloader but I keep getting this error
Are you using the .exe or the python version ?
the .exe
Which one are you using ?
Last official release is this one: https://github.com/Steamopollys/Steamodded/releases/tag/0.6.2
I know why, old on a moment
is there a specific 7zip version I need?
A changed a link
Can you try again ?
i decided to make my own colors


