#💻・modding-dev
1 messages · Page 460 of 1
we do it in terms which are normally like 6 - 8 weeks i think idrk
oh i only did 1 year in college then come september im off to go start working
I got to apply to a collage still 😅
Did you get your degree in CS or a related field, or is this just a hobby of yours?
I'd tell you to come to the school I go to, but the CS program is lowkey awful lmao
this is just a hobby i do mechanics
i have an SEG diploma in motorvehicle so i have the qulification to work on cars and motorbikes
that makes sense. Jobs like Mechanics, Welding, etc are what we call "trades" in the US and students typically take around 1-2 years in trade school if they go. 4 years/8 semesters is more typical of a Bachelor's Degree (academic field), which is what I'm doing
I know a lot regarding code, though its not what i want as a job. I'd like to be a electronical engineer, but in case i'm unable to i did take many classes in different subjects as backups.
ahhhhh
i was either going to do 1 of 3 things which were erm very different geology music or mechanics
in the end mechanics was my best option
but i do have my main hobby of being pc smart if its pc physical or software wise i know a fair bit
I decided to do Computer Science because after self-teaching myself JavaScript (mostly for Minecraft too lol) I realized I really like coding and working on projects. I started modding Balatro this summer because I missed having a coding project to work on, and this filled that for me perfectly, especially since I love Balala
I enjoy coding because you can make pretty much anything with it, and i quite like making things.
balatro became too much of an addiction for me, i was bored and saw it on my phone played a little then i havnt stopped in over 5 months
Don't i know it😅
Hey I'm trying to draw a shader on a card's soul sprite if it has a shader attached to it, but this is no good. Any ideas?
clearly everyone has the balatro virus from day 1
1310 / 11808 (hours since Balatro's release) = 0.11
Bro has been playing Balatro for 0.1% of all time that has passed since its been out
with a mix of my pc my laptop and my phone dont ask why but pc and laptop are different accouts im on around like 500 or so hours
I would also probably be addicted to Balatro if I didn't have this game
i love boi
I only have like 300 hrs on tbol
both lua
🥱
you'd be a demigod at modding balatro if you modded tboi and roblox before
im starting on balala and moving to roblox later
I tried modding TBoI but its wayy more complicated imo. The API is a bit difficult to understand since its so much bigger
I made some pretty cool stuff on balatro but balatro's the first game i've published mods for.
I'm also surprising good at balatros UI
imagine all the top like 5 balatro mod devs came together to make a mega mega mod, complete rehaul
would be epic
that's pretty muchy what SMODS is, a modding APi
worked on by alot of the Cryptid devs I'm pretty sure
I wonder who is considered the top five, personally I'm working on five mods two I'm the only dev.
wait so other people work on ur mods with u
helps get work done if you're making something big
Yea, AIJ and Balatro inscribed
oh damn i have me myelf and i and i know nothing coz i only descovered how to code lua 6 days ago
I felt that for well over half a year
i have around 33 jokers and 3 consumables including 2 joker types
i am going big
I made 30 jokers in a day for AIJ before.
Beat my record of 22
I'm making 11 Jokers today lol
i mean first day i made 15
oh no... he's here
that was my cap of most per day
i think my record is like 20
whos here
how do i make it so whenever i open a booster pack it doesnt say error in the bottom?
Went from 150 to 200 in like four days
HOW MANY JOKERS ARE IN YOUR MOD
add a group_name
There's 200 in AIJ though i joined a little later in development
i have 1 artist working for me they would cry if i said i wanted 200 jokers
and the guy in charge of joker ideas
he would cry
My plan for the TBoI mod is to add a Joker for every item in Isaac, which is over 600. Planning on doing it all myself over the course of <indeterminate amount of time>
then having to code all 200 i would die
Nevernamed made all the art over 400 jokers worth of art
DAYUMMM
that's crazy
yeah my artist is erm new to digital art....
i do have group name as "ShapePack" but it still says error
432*
where do you guys find artists? I'm looking for people to help me with the art for my mod
how would i code a joker to let me win the game if i put in the konami code
my group of 3, the ideas the coder and the artist all have no idea what we are doing
no idea i saw other people with the same problem, you might need to use a localization file
I work on the art for my personal mods
I only do code for AIJ and Inscribed
Both for Familiar and Sigil
wait i have a question for joker art how do you get the card to look like a card and not like a square
Does Pareidolia affect Familiar's rank pool?
As in, does having Pareidolia make Familiar possible to add cards with ranks other than JQK?
ah, how may i ask?
afaik no
Wdym like a square?
hold on let me show u
is there a way to make a joker detect if its in the boss blind to change the amount it scores that blind?
like this
https://github.com/nh6574/JoyousSpring/blob/a2630a0a7873651ec8280a97ac8652988c2e3cc6/localization/default/02Boosters.lua#L50
https://github.com/nh6574/JoyousSpring/blob/a2630a0a7873651ec8280a97ac8652988c2e3cc6/src/others/Boosters.lua#L24
just as a heads up, please don't copy my localization structure unless you want a headache
use a single file like normal
You remove the pixel corners, also usually the art size is 71x95
if G.GAME.blind and G.GAME.blind.boss
G.GAME.blind.boss
ok thanks
ohhh thank you so much you two
whatever behavior you want it to have for bosses only, put it here
This is helpful for references and the like https://discord.com/channels/1116389027176787968/1224362333208444989
thats what i have i use photopea to make my srite sheets but if i remove the corners i just get white for some reason
I'd recommend using drawstep and replacing card with self like I do here SMODS.DrawStep { key = 'cicuit_shader', order = 15, func = function(self, layer) if self.ability.in_between_circuit ~= nil and self.ability.in_between_circuit then self.children.front:draw_shader('foil', nil, self.ARGS.send_to_shader) end end, conditions = { vortex = false, facing = 'front' }, }
how do i go about triggering jokers on keyboard presses and triggering enhancements on mouse clicks
how do you redeem a voucher using debugplus
eval Card.apply_to_run(nil, G.P_CENTERS["v_modprefix_key"])
will it instant redeem or does it have the anim
It is instant.
damnit
I am not great at reading these logs. There seems to be a lot of missing data from the line numbers and function calls '?'. Is there a way to trace this back to the execution of injected code?
its my first time modding, where can i find balatro mods? (looking for cryptid and pokermon)
look for lines that say "at file" or "at line" and look into them. Usually there's a lot so it will take time, but that's always the first place I look
never added any other mods personally, but you can find the source code for most balatro mods by searching "Balatro <modname> github"
LocalThunk has a rule where modders need to have their mod's code public, and most people use GitHub, so I'd start there
ok, i found the cryptid mod, how do i install it?
balatro mod manager is easiest tho isnt it
thank you!
like I said, never installed any other mods personally. It probably is easier but since I like having control I just downloaded them all using git clone
I rarely see you chat, you mostly just lurk about and 🤔
Hy guys I was wondering is there any anime inspired balatro mod
u rarely see them bcoz ur looking at the wrong time
bro is always here
High card, though it's outdated T_T
yk what we need, a channel where people who dont know how to code can request jokers or features for mods for devs to take inspo
bcoz i make jokers so slow bcoz i dont have ideas
Thanks, how do I convert chunks to lovely injected files though>?
That holds me back occasionally as well
would be the most helpful thing for alot of us
anyone help?
you need talisman
Probably why i was fast at coding for AIJ, theres just a bunch of ideas and art
this is what i want 😭 ideas and art
you have lovely and SMODS
yep
is it the version needed for cryptid
only cryptid and talisman are enabled right now
should i just download the latest
What does it say when you hover over the icon?
Hover over the [!] icon. It'll tell you what's wrong.
I may be coding too fast though, there's only like 100 ideas left (not all stable effects) and almost half the jokers with art have been coded (200/432)
missing the right version of steammoded
Update SMODS
And theres 200/308 ideas
FOUR HUNDERED AND THIRTY TWO
Nevernamed is fast and good at art
wait so u have art for jokers that dont have ideas
Have you seen AIJ?
no...
Usually Cryptid comes bundled with its respective SMODS and Talisman.
gotcha
how do u have art for jokers that dont exist tho where was the ideas for the art
work now
Not made yet
oh
yall do the code then the art or the art then the code for Jokers?
I like doing art first bc I can't stand looking at placeholder cards
The prior tends to be what most of the mods i work on do
i mean i dont mind it, it was better than the blank white i had and my artist has only just yesterday replied to my lasr request for like 4 jokers they havnt even started
local stone_card = SMODS.create_card({
set = "Base",
enhancement = "m_stone",
seal = SMODS.poll_seal({ "Gold", "Red", "Blue", "Purple" }),
area = G.discard
})
trying to create a stone card with a random seal, but the seal isn't getting added, any ideas?
You mean the shine?
yeah
is force_update a thing?
No?
oh
how would I permanently change a card? I want to have a Joker that permanently adds $1 of sell value to Planet cards when you do something, but idk how I'd change planet cards like that for the rest of the run
whenever i add a booster pack or voucher it is WIDE, do i have to use sprite sheets to not make this happen?
and just to be clear I want this to apply to ALL planets, even ones you aren't currently holding. So if I proc this Joker's effect, I want a planet I find in the next shop for example to be impacted
Hook Card:set_cost()?
local set_cost_ref = Card.set_cost()
function Card:set_cost()
set_cost_ref()
if self.ability.name == "Jupiter" and BI.EXTRAS.jupiter_extra_value > 0 then
self.sell_value = self.sell_value + BI.EXTRAS.jupiter_extra_value
end
end
I keep crashing on launch now
nvm fixed it lol
so my game crashed
it happens whenever i try to click on a card in my hand
this is like 5 antes into a run, i don't know what changed
am i supposed to put this in a different channel?
did i do anything wrong?
Is there a way that Github Copilot just learned how to give +3 mult per card with a custom enhancement?
awful filename
so what do i do
you should approach this through a patch
wait actually how do you check if a card has a custom enhancement, I'm worried.
how
so i would create a global function somewhere, for example throwing it in your main file, that does essentially the same thing as the function you have up there
SMODS.has_enhancement(card, "m_modprefix_key")
worked
thank you
and create a patch that occurs everywhere reset_idol_card() does, assigning the card variables
since idol card changes every round, that'll get what you want done
Ok, what if the mod has multiple enhancements to check for?
(SMODS.has_enhancement(card, "m_modprefix_key") or SMODS.has_enhancement(card, "m_modprefix_key") or SMODS.has_enhancement(card, "m_modprefix_key"))
ill consider later
Ah... the same way I checked for Jokers.
patch game.lua, so after the line idol_card = {etc} you assign the base value your joker will take, so `joker_var = { suit = "Spades", rank = "Ace" }
THEN in functions/state_events.lua, patch after reset_idol_card() is called and call your function that sets global variables to a random rank/suit
i highly recommend you do so because your function structure is very strange and will probably still crash
-# if it aint broke, dont fix it
oops wrong one
this function calls from all ranks in deck, though you can easily use the function you did beforehand
it generates a random rank and sets it to a variable in G.GAME.current_round, and can be easily extended to suits
but setting it to a variable in G.GAME.current_round is how idol does it, which this copies from
So this isn't working. Am I missing something?
strings
you need quotation marks around your enhancement keys
otherwise, the game just thinks they're variables
...also, referencing card makes the game think you're referencing the current object, which i assume is a joker?
Yes, this code is for a Joker
context.main_scoring doesn't happen on jokers.
if its a Joker, try to avoid using card for any local variables, since card refers to the Joker itself
Thanks. Copilot didn't catch that one, apparently.
if you're looking to give +3 mult if a card has a custom enhancement, do something like
if context.individual and context.cardarea == G.play then
if (SMODS.has_enhancement(context.other_card, "m_modprefix_key")) --other enhancements go here, follow structure from before ofc
return {
mult = 3
}
end
end
i would recomment against using copilot for jokers
it has zero clue what it's doing
it basically got everything wrong
is it possible for me to change the type of hand manually? I want a Joker that makes every hand a straight, regardless of what cards are played
Yes.
THANK YOU
and I'd do that how...?
Hook evaluate_poker_hand
local evaluate_poker_hand_ref = evaluate_poker_hand
function evaluate_poker_hand(hand)
local results = evaluate_poker_hand_ref(hand)
if (next(SMODS.find_card("j_tboi_saturnus"))) then
results.top = results["Straight"]
end
return results
end
tried this, but I think I'm missing something
if i add a new entry to G.C can i use it in localization color tags or do i need to add something else
Good morning silly goobers
Good evening (local time 12:19AM lol)
you need to add an entry to G.ARGS.LOC_COLOURS i think
ah ty
maybe I need to hook get_straight as well?
No.
Hey everyone, novice balatro modder here.
I made a thread asking for challenge ideas and I instantly got one that seems pretty difficult.
Not to add another person in need of help to this discussion, however, I need help with creating a custom challenge rule that skips the shop after cash out and a custom challenge rule that makes the shop appear after skipping a blind.
My theory on how I'd do this? I would make it so when you cash out it instantly triggers the "next round button" before the shop comes up and I would add onto the function that adds the skip tag to make it bring up the shop.
The problem, I have no clue how to do any of that as custom rules are proving to be quite complex.
For the second one try looking at Home Delivery from Ortalab
I want it to make EVERY hand a Straight, but it seems to only make every hand that's lower in the handlist into a Straight
are there ways to remove boss blinds from the boss blind pool for a run?
like during the course of a run
Alright, I checked the ability and it looks like what I need.
I went to this page https://github.com/Eremel/Ortalab/blob/master/objects/coupons.lua and found it...
The only problem is... where is the code that actually does the thing it says it does? I've found this but I don't know if it's what I need...
?
Code?
Yes.
local evaluate_poker_hand_ref = evaluate_poker_hand
function evaluate_poker_hand(hand)
local results = evaluate_poker_hand_ref(hand)
if (next(SMODS.find_card("j_tboi_saturnus"))) then
if not results["Straight"][1] then
for _, v in ipairs(G.handlist) do
if results[v][1] then
results["Straight"] = results[v]
break
end
end
end
end
return results
end
Where is that? Looks like what I need.
I added
for _, v in ipairs(G.handlist) do
results[v] = results["Straight"]
end
to try to fix it, but it makes every hand into a Flush Five for some reason
lovely/coupons.toml
Ah, I see, thanks for the help.
cool. is there some kind of resource that mentions how that's done?
rad
But you’ll have to read
well ive been doing lots of that lol
im appreciative of the smods wiki and ive been using it lots, but ive had a hard time finding the bits of info that i need
Try looking at vanilla remadz
You can find 90% of stuff you’re looking for there
Also don’t let me catch you talking shit about the wiki
lmaooooooo
facts
i will say what i feel :3
trying to make my description works like misprint
but whenever i hover over the card, it just shows up for a millisecond before disappearing permanently
heko
help
Your lock vars isn’t updating properly
If you want it to spit random bullshit you can use pseudorandom
i did
here's the code
YOU SAID SEND THE CODE
Hey all, is there a way for me to make a joker take up multiple slots?
Yes
IM DOING WHAT MISPRINT IS DOING
where do i put this
Misprint has @ and gives you the id of the next card you draw
And also the suit
god damnit
THINK MARK THINK
Can you please elaborate?
I honestly forgot 😭 lemme think
you have to dynatext
You’re gonna use
im sorry for your loss
Add_to_deck
how would i go about causing cards to be counted as held in hand when played
Take ownership
I think
Miss fluff said you have to use dynatext
for god's sale
All my homies hate Dynatext
Math.random(#t)
that won't update in real time
@shell timber how do YOU use dynatext
#t is the size of the table
i dont use dynatext
Balatro balatrez
why would Jimbo do this?
Hey all, can someone explain to me how to make a joker take up multiple slots?
like wide??
yes exactly
soz idk
maybe it just needs to work like the opposite of the Negative edition, where it instead lowers the amount of slots that the cardarea has
but I feel like that might cause problems if you find it as a negative card itself
is there a Joker out there that does this already that you're taking inspiration from?
@formal parrot @shell timber figured it out
congratulations
Not that I know of
so... problem, I have no clue what .toml is, how to make it work, and how to make this function.
While this solution could work with enough effort... it looks like it's more complicated then copy, paste, and modify.
kinda
well that's a good start
How can I change the card that the "Again!" text appears under when I do a repetition?
return {
repetitions = 1,
message = "There ya go! :3c"
}
At least for joker repititions
if I don't include card as a key in this return, I crash the game by trying to juice_up a nil.
does using set_ability to turn a joker into another joker not change its cost?
if I do card = self I also crash the game trying to juice_up a nil.
card = card?
excellent, now stupid question, is there a way to do this and output a sequence of cards? Or will this require a lovely patch?
can you elaborate on what that would do
Like, I want to do 2 repetitions, the first highlighting card A, and the second highlighting card B
(neither of which is the joker)
is this repeating a playing card
(Context, I'm implementing this https://discord.com/channels/1116389027176787968/1384587940486840422)
if so, just do checks for context.other_card
The gist of the joker is that an enhanced card is retriggered once for every copy of the tarot that creates it exists in the consumeables.
So I'd like to highlight the tarot card that is doing the retriggering, rather than the joker.
I have everything else working now. Just lacking the highlight.
calculate = function(self, card, context)
if context.joker_main then
local shapecount = 0
for i = 1, #G.jokers.cards do
if G.jokers.cards[i].config.center.pools and G.jokers.cards[i].config.center.pools.Shape then
shapecount = shapecount + 1
end
end
card.ability.extra.xmult = (((shapecount * card.ability.extra.xmult_gain)/10)+1)
xmult = card.ability.extra.xmult
elseif context.setting_blind then
local e_real = math.random(1,10) -- randomizer for consumeable
if e_real <= 4 and ((#G.consumeables.cards + G.GAME.consumeable_buffer) < G.consumeables.config.card_limit) then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
SMODS.add_card {
set = 'Planet',
}
G.GAME.consumeable_buffer = 0
return true
end)
}))
elseif e_real > 4 and e_real <= 8 and ((#G.consumeables.cards + G.GAME.consumeable_buffer) < G.consumeables.config.card_limit) then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
SMODS.add_card {
set = 'Tarot',
}
G.GAME.consumeable_buffer = 0
return true
end)
}))
elseif e_real > 8 and e_real <= 10 and ((#G.consumeables.cards + G.GAME.consumeable_buffer) < G.consumeables.config.card_limit) then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
SMODS.add_card {
set = 'Spectral',
}
G.GAME.consumeable_buffer = 0
return true
end)
}))
end
end
end
}
can anyone help me? hes not multing it
do i really need the nil check for the jokers card?
As this is loc_vars... yeah.
if context.repetition and context.cardarea == G.play then
local retrigs = 0
for _,v in ipairs(G.consumeables.cards) do
if v.ability and v.ability.mod_conv then
if SMODS.has_enhancement(context.other_card, v.ability.mod_conv) then
retrigs = retrigs + 1
end
end
end
if retrigs > 0 then
repeat{
repetitions = retrigs
}
end
end
shii
this is what i would do 🤔
calculate = function(self, card, context)
if context.cardarea == G.play and context.repetition and not context.repetition_only then
local reps = 0
for i = 1, #G.consumeables.cards do
local tarot_enh = G.consumeables.cards[i].config.center.config.mod_conv
for enh, _ in pairs(SMODS.get_enhancements(context.other_card)) do
if tarot_enh == enh then
reps = reps + 1
end
end
end
if reps > 0 then
return {
message = localize('k_again_ex'),
repetitions = reps,
card = card
}
end
end
^ @manic rune that's what I've done above.
which is probably not the most... clean... implementation so far
mm it does look like it works, whats the issue here
So what I have has card = card in the return table, which cases the Joker to be highlighted and say "again", i.e. be subject to a bounce, but I'd like the tarot cards to do that.
can you make it so a joker gives itself an eternal sticker when added to deck?
I think there might be a "create_card" context, and you can check if other_card == card
(if there is)
if reps > 0 then
return {
message = localize('k_again_ex'),
repetitions = reps,
card = card,
func = function()
--save all the consumables in a table, and do v:juice_up() in here, probably?
end,
}
end
wait, the effect calls an arbitrary function?
dunno what timing you want, so it will have to be either outside the return or inside
oh man, this is so nice.
thanks, I'll see if I can make this work
is there a way for a joker to detect when a specific suit is destroyed, i want to make a joker that scaled when spade cards are destroyed
if context.removing_playing_cards then
for _,v in ipairs(context.removed) do
if v:is_suit("Hearts") then --change the suit to whatever you want
--do stuff
end
end
end
ohh thanks for the info!!
thank you bep is
Okay have completed my initial draft for a scaling context for SMODS. That was fun
whenever i add a booster pack or voucher it is WIDE, do i have to use sprite sheets to not make this happen?
what's happening?
I'm trying to make a face cards only deck but it is consistently making the deck into this, how might I fix this?
Here's my apply function:
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for _, card in ipairs(G.playing_cards) do
if not card:is_face() then
card:remove()
end
end
return true
end
}))
end,
I think that depends
wtf
return {}return {}
verify the files on steam maybe?
i tried that aswell
do you just have lovely or do you have steammodded as well
ru playing vanilla
cuz this is modding dev
wait lemme go check the game's files
all dlls for me
I was able to massage this into something functional. Thanks so much for your help! I had no idea that this existed.
and how do i fix it?
that's not the same code as what is reported in the error backtrace from @gaunt prawn, which suggests to me that something has happened with his files.
yeah
@gaunt prawn you'll probably want to backup and reinstall everything
i did that as well
these are the functions that give error
and no, you wont be able to edit em so
show us your balatro file
weird
Probably need to delete ssave file
did that as well
but ill retry
i only have this
in the carpet 1
somehow
deleting it now worked
thanks a lot for listening
wait what?
oh
thank you a lot man
yeah it was your save file
enjoy your day
well np then
bump
I need help fixing this function
function = TiredLink_add_random_tag
try this:
function TiredLink_add_random_tag()
if tag.name == "Orbital Tag" then
local _poker_hands = {}
for k, v in pairs(G.GAME.hands) do
if v.visible then
_poker_hands[#_poker_hands + 1] = k
end
end
tag.ability.orbital_hand = pseudorandom_element(_poker_hands, "TiredLink_orbital")
end
add_tag(tag)
end
ty
is there a way to define a poker hand using an enhancement? (for example, if a hand contains at least one of a certain enhancement, apply the poker hand)
<@&1133519078540185692>
mods seize him
this is 100% a scam
is there an easy way to index the cards in the consumable slots? i'm trying to count the amount of tarot cards held in consumable slots, but i can only count the total amount
every time i try to do something like "if context.consumeable.ability.set == "Tarot"" it tells me i'm indexing a nil value
I dunno why it took a while but I shot it
just look at his messages sent
ello egg
ty
yellow
how can i make a deck that's unlocked whenever i have an amount of jokers with the white sticker?
alright, step one, i'm trying to do ui shenanigans, specifically making each individual card clickable somehow
some help to get me in the right direction would be appreciated
specifically the goal is that when any card is clicked, to bring up a menu of actions to perform on that card
u can use debug plus method
could you elaborate
like ctrl +q/w/e for changing seal/enh/edition
What do you want to do exactly
i made new ranks (half-ranks) and i wanna make smiley face for them
No idea about custom ranks
is there a global to know what deck is currently in use?
What do you want it for
activate a custom rank when using a certain deck
I think there’s a name for deck
You can add the rank to the deck
To start with
yeah
i mean i figured i could but i was thinking perhaps i could do something else cause i got NO clue on how to add the suit to the deck when starting 😭
Check checkered deck reference
In vanilla remade
oh my god right
Should be the same
it changes the suits
i'll check it out
how do you use dynatext for badges
Go figure
How do i create a specific card?
This is how i do it
You can also use add_card
What if i wanted it to be a specific joker?
Key=
ah, ty!
This is the add_card
Is simpler because it saves you the emplace and add to deck
Got it, tysm!
-# WHERE THE FUCK HAS THIS BEEN???
Reading the wiki explains the wiki 😭
I thought that this was the only part to the wiki 😭 https://github.com/Steamodded/smods/wiki
I wonder who’s the smods cat
aure's kitty cat
it is important to use _mod on non individual scoring contexts or is it just best practices
I don’t think it’s necessary
I didn’t understand what you wish to do can you explain better ?
min is the minimum ante at which it appears, max is the max ante at which it appears, atlas is the sprite of the blind and idk about order
maybe the order in collection?
oh
what about their atlas
i saw their atlas have some
multiple blinds
in one row
does it do that automatically?
wait so if I want a blind to go in endless do I have to set max to a really big number
as per the smods.blind documentation max isn't even functional so you don't have to do that
oh
is there an equivalent of this variable (in SMODS.Back's apply function) for ranks?
are we going to talk about how you have to "choose 0.0001"?
Oh I only get a little rip of the card
That raises more questions than answers-
So you see the very little bit of corner on it yeah that's all I get it still works the same way though
v:get_id()
hello i am new here can someone tell me where to start making a balatro mods
i have many cool ideas
#⚙・modding-general has a pinned message with a starter thread
ok i find it thanks
hi folks
quick question
can i check seals types and counts in deck?
like can i read that?
you have to loop through all cards in G.deck.cards (or G.playing_cards if you're counting in hand and discarded too)
ive been getting error about the blinds im making
heres the atlas code
atlas_table = ANIMATION_ATLAS,
pos = { x = 0, y = 21 },
frames = 21,
atlas = "southamerica",
order = 21,
screen shot the whole code with line nums
can you post the atlas definition
line 11 of the vanilla files
the animation atlas stuff goes there
would set_seal work here?
frames also goes there
yes but replace that for "Red"
oh ok
set_ability can also just be a string
show new code
nah its southamerica
ik this doesnt work, but does it look about right for making a card show up in a jokers description?
thats odd
for the atlas
make sure the folders for different sizes are called "1x" and "2x"
animation atlas has to be a string
already did
oh what
?
no
a center is not an object
oh now it doesnt show up
Malaysia as in country? or other referance
i wish people would tell me bugs with vanillaremade directly instead of having to egosearch 😭
"if triggered once destroy but if triggered multiple times gives money"
Is this possible to code?
This but with any mod...
?????????????????
increment a value in context.post_trigger
does anyone here mind explaining how rng works in steamodded?
it's some pseudorandom thing that I cannot for the life of me understand so I keep using math.random instead
pseudorandom('string_seed') ensures the probability roll is consistent when replayed via seeded
that's how rng works in vanilla
Do I have to mark the cards first?
I'm trying to make a 1 in 4 script but when looking at some rng jokers in vanillaremade I can't understand shit 😭
if pseudorandom('string_seed') < G.GAME.probabilities.normal / card.ability.your_value then body end
so what does g.game.probabilities.normal do, does it default to 1
and the 'string_seed' part I noticed some stuff use a different string in there
ah
yea, just put an identifier string, unique to your object to set the probability roll inside its own queue
so basically I don't need to care about the string in pseudorandom, I can put my unique object in there and always use g.game.probabilities.normal
am I understanding that correctly
the string in pseudorandom ensures your object gets the probability roll in its own queue
how is that not important
but yea, that's the probability starter pack
ah I see
we don't talk about smods' new probability logic
jy bro i have many ideas but not know how to code in lua can you make some jokers for me
i have ideas for many anime inspired jokers
how do i see what hand a planet card is supposed to level up in code
preferably as a string
always nil check G.GAME.probabilities.normal
(G.GAME.probabilities.normal or 1)
I've never encountered a crash with attempt to index field 'probabilities' (a nil value)
¯_(ツ)_/¯
the value doesn’t always exist
i’ve had problems with it quite often
so i just do it to be safe
lol
it’s like 7 extra characters, it can’t hurt
that's already included in Game:init_game_object()
I could not find a case where it wouldn't exist
loc_vars
that's loc_vars thing
this is in calculate
but again, i’m just paranoid and do it to be safe
:b
the less chance of a crash the happier i am
dw I feel you
I used to put (G.GAME and G.GAME.alice_multiplifer or 1) anywhere applicable
the only way to crash I can think of would be some fools accidentally overriding Game:init_game_object() instead of hooking
ah
which then, why is that even in prod lmao
when i can, i never let a crash be left unfixed before i get off
if the game's crashing ill always try to fix it before relaxing
also me
how does take ownership work
can I just put cost = 9 and it will immediately change the cost of the object I took ownership of
is there a way to know if a variable was used?
SMODS.Class:take_ownership(key, table_of_overrides, suppress_mod_badge)
or, in your case:
SMODS.Class:take_ownership(key, {cost = 9,}, suppress_mod_badge)
you basically override features of the joker
SMODS.Joker:take_ownership('smiley',
{
loc_vars = function(self,info_queue,card)
info_queue[#info_queue+1] = {set = "Other",key = "char_txt_ochint_smiley"}
end,
calculate = function(self, card, context)
if context.remove_playing_cards and not context.blueprint then
for _, removed_card in ipairs(context.removed) do
if removed_card:is_face() then
card.ability.ext_ovr.faces_destroyed = card.ability.ext_ovr.faces_destroyed + 1
end
end
if card.ability.ext_ovr.faces_destroyed >= 10 then
CHAR.FUNC.overclock_proc(card,'j_charcuterie_ferocious_grin')
end
end
end,
add_to_deck = function(self,card,from_debuff)
card.ability.ext_ovr = {}
card.ability.ext_ovr.faces_destroyed = 0
end
},
true
)
here's one ive just done
what do you mean by this
variable??
if you want to see when a variable was accessed
i'd like to check whenever G.GAME.probabilities.normal is used in a calculation
so whatever I put in here, the in game values will be like this instead of the original values correct?
itll add on to
ah, thats hard then
thats not an easy thing to do
yeah i figured
i guess you can try and make a metatable that checks for __index but that means it'll also trigger on loc vars
im pretty sure you can hook the functions in it by having a reference to the original function in the center
this wont work with like calculate and stuff with vanilla jokers tho
figures
local hook = G.P_CENTERS.j_modprefix_key.calculate
SMODS.Joker:take_ownership("modprefix_key",{
calculate = function(self, card, context)
local old_ret = hook(self, card, context)
local ret -- put return stuff here
local full_ret = SMODS.merge_effects({old_ret or {}, ret or {}})
return full_ret
end
})
yes
why am i not surprised
At least someone should make them 
i hate matador
just found out some blinds set triggered to true but dont trigger it because of a bug
<@&1133519078540185692>
❤️
huh
taking away my free opportunity..
bots
I see
im winning it i can't have other people entering
im cancelling you on youtube
||modify G.SETTINGS.SOUND
||
thanks
if anything happens, its your fault
oh my god arustare
if anything happens, it's your suffering
shh
||G.SETTINGS.colourblind_option
after modifying that, call G.FUNCS.refresh_contrast_mode||
you know you can just, print out G.SETTINGS right
how would you add a card to the shop (to the likes of the rare tag & uncommon tag)?
🤔
let me learn
thanks
is it for a tag or something else
it is for a tag
im in the middle of adding them to vanillaremade :3
-- Uncommon Tag
SMODS.Tag {
key = "uncommon",
pos = { x = 0, y = 0 },
apply = function(self, tag, context)
if context.type == 'store_joker_create' then
local card = SMODS.create_card {
set = "Joker",
rarity = "Uncommon",
area = context.area,
key_append = "vremade_uta"
}
create_shop_card_ui(card, 'Joker', context.area)
card.states.visible = false
tag:yep('+', G.C.GREEN, function()
card:start_materialize()
card.ability.couponed = true
card:set_cost()
return true
end)
tag.triggered = true
return card
end
end
}
oh my god hell yeah
i was looking thru vanillaremade to see if you've added them
thank you 🙏
hi just here to say vanilla remade is amazing and i would not have continued my work if i didnt find this
i copied this from my other mod but havent tested it yet tho
what value is low contrast
1 or 2

@kindred warren Here's my starting bit exported from JokerForge
SMODS.Joker{ --Banana Man Test
name = "Banana Man Test",
key = "bananamantest",
config = {
extra = {
}
},
loc_txt = {
['name'] = 'Banana Man Test',
['text'] = {
[1] = 'Spawns a {C:red}Negative{} Banana to the left',
[2] = 'of this Joker when you play a hand with',
[3] = '{C:red}five{} face cards.'
}
},
pos = {
x = 0,
y = 0
},
cost = 6,
rarity = 3,
blueprint_compat = false,
eternal_compat = true,
unlocked = true,
discovered = true,
atlas = 'CustomJokers',
loc_vars = function(self, info_queue, card)
return {vars = {}}
end,
calculate = function(self, card, context)
-- Main scoring time for jokers
if context.cardarea == G.jokers and context.joker_main then
if (function()
local rankCount = 0
for i, c in ipairs(context.scoring_hand) do
if c:is_face() then
rankCount = rankCount + 1
end
end
return rankCount == 5
end)() then
end
end
end
}
Currently it doesn't have any actual effect, but the condition is playing a hand with five face cards.
G.C.FILTER
yeah
Returns in SMODS are very simple
But also you should just do a check for rankCount
This is purely template code, so you'll have to explain why I should/shouldn't do things, please.
SMODS does not take return. Remember you are inside a calculate function definition
I just started with SMODS, so things may not be obvious to me yet.
SMODS is waiting for a proper return that it understands
For example, lua if rankCount == 5 then return { Xmult = 2 } end
Also, JokerForge doesn't support the "Negative" text effect, so that's a simle thing.
I see, yeah. I left the Effect field blank in Joker forge.
Oh, I see
I want it in my text, the way it is in Balatro's UI for things that affect Negative cards
Thanks, that's what I assumed when you said the thing before, but I wasn't sure.
Yes
Also s for size and it’s lowercase
You can read text styling documentation in the future
My favorite thing from the Wiki, TEXT STYLING

Doing ['name'] doesn't do anything. This is equal to
loc_txt = {
name = 'Banana Man Test',
text = {
'Spawns a {C:dark_edition}Negative{} Banana to the left',
'of this Joker when you play a hand with',
'{C:attention}five{} face cards.'
}
},```
I also recommend putting your atlas and pos next to each other.
Edited for proper coloring
Also do you mean Gros Michel?
Trial and error will get you there useful resources
vanilla remade , featuring the whole game remade with smods ⬇️
https://github.com/nh6574/VanillaRemade
the smods wiki⬇️
https://github.com/Steamodded/Wiki
the smods mod examples ⬇️
how do i see the current amount satellite is giving
Not specifically. The effect I want to do is this (using pseudo-code):
if `player_has_joker('gros_michel') then
if rand(20) > 0 then
add_joker_to_left('cavendish','negative')
else
add_joker_to_left('gros_michel','negative')
else
add_joker_to_left('gros_michel','negative')
lame
🍋🟩
thats lime you fat fuck
Balatro uses pseudorandom() and related functions to do randomization
I know😭
ugh
You can still use math.random
:(
😠
😭😭
yeah
Yeah
Yes
can confirm
you can use it for non-gameplay related things maybe
coders when they see a single for loop
b b but my EFFICENCY
at least it doesnt do it in update
fair
coders when they see while loops
how would i check how many tier 1 vouchers ive redeemed?
(fuck cryptid compat btw idc about tier 3s possibly being counted as t1s)
blocking code pmo
i think you have to loop through G.GAME.used_vouchers and check manually
is there a specific condition for t1 vouchers or do i just hardcode it
im doing some programming WARCRIMES arent i.
feels fine if thats a boolean
you can maybe check not next(SMODS.Vouchers[key].requires or {})
why does this work to detect t1s? just curious
vanilla vouchers have this in their config if they are tier 2
oh ty
you could consider any voucher that doesnt require another one a tier 1 basically
For future reference lua pseudorandom('seed', min, max) -- 0 to 1 by default pseudoseed('seed') pseudorandom_element(array, pseudoseed('seed')) SMODS.pseudorandom_probability(trigger_obj, seed, base_numerator, base_denominator)
you dont need pseudoseed for element anymore
how does copy_card work? i have this: copy_card(G.deck.cards[1], new_card) and when i try to emplace new_card, my game crashes
Which of these do I use?
you can actually use that same logic to exclude tier 2 vouchers that have tier 3 upgrades too
Also using 'seed' passes the current run's seed?
Pseudorandom is fine. Just plug in a seed
like, tier 3 vouchers also have requires im guessing, so u might want to do a loop on that until it reaches a voucher with no requires
No, pseudoseed already uses the current seed. You don't need to plug it in manually
Use “car simulator 101” as a seed
Thank the SMODS gods
Me when i have to calculate something
So, can I just run pseudorandom(0,19) to generate a 1 in 20 value?
Or is it a float?
Lua is weird and I believe this is 0 and 19 inclusive
Correct me if I'm wrong chat
Yea
I was assuming it's inclusive. This would be 0, 1, 2 ... 19, for 20 values
and also that won't take oops all 6s into account
That's what I'm asking, how do I provide the seed
The seed can be any string
Eh, it's not a listed probability
Typically you feed in your joker name
How do I provide the seed of the current run
pseudorandom() handles it for you
that seed is like a secondary seed
Dont need it
so you dont interfere with the randomness of other cards
So it doesn't matter what string I actually use for the first argument?
Nope
as long as its unique yeah
It does, it should be unique to the effect for the most part
you could put the entire bee movie script in if you wanted to
Don't actually that would be slow
Most of the time is better to use the card's key
Strange, but I see. Now then, what if I want it to interfere with the randomness of other cards?
then you would be annoying to other devs
how do i check if a purchased card is a voucher in context.buying_card
thats bad design and you dont want to do that
context.card.ability.set == "Voucher" iirc
if you want to make an Oops you can change G.GAME.probabilties.normal
that's basically the only reason you would do this
¯_(ツ)_/¯
made five of them this morning, can confirm
also the probabilities are changing soon
yup
I love new SMODS content
oh whats changing?
idk specifically but its a full overhaul afaik
no more G.GAME.probabilities.normal
if you need examples:
https://github.com/nh6574/VanillaRemade/pull/20/files
ohh so its some sort of an upgrade from what we currently have
yeah it lets mods manipulate probabilities easier
G.GAME.probabilities.normal will remain usable though right? to avoid incompatibilities with older mods still using it
yes but it will be incompatible with any of the new contexts
alright
not next(SMODS.Vouchers[context.card].requires or {}) doesn't work to check for t1 vouchers
game crash
I forgot to tell you how to add cards ```lua
SMODS.add_card({key = 'j_gros_michel', edition = 'e_negative' })
oh maybe SMODS.Vouchers doesnt exist
Thanks, I was trying to read the documentation to learn how to check what jokers are already in the joker area.
You do need to check if there is room
That's why all the jokers have (Must have room)
Does that apply if it makes a negative?
I suppose not
you can tell the game doesnt do that automatically because cryptid's ://SPAGHETTI does not check for room
yes
negative invisible allows you to go over joker slots
then try not next(context.card.config.center.requires or {})
and if you do that you cant buy negatives
Is there a way to add a card at a specific index? I want to make sure that the banana spawns to the left of the joker.
it's a bit complicated but you need to sort G.jokers.cards
unless you want to pin the joker there
thats a lot more complicated
No pinning, just insert at a position. What data structure is G.jokers.cards?
it's an array of cards
That's what I thought. Hang on, reading Lua docs.
Dangerous!
this does not count t1 vouchers already purchased, how would i do that?
local vouchers = 0
for _, v in ipairs(G.GAME.used_vouchers) do
if not next(v.config.center.requires or {}) then
vouchers = vouchers + 1
end
end
https://www.lua.org/pil/19.2.html
If I can get the position of the Banana Man Joker, I should be able to use this, right?
v here would be a boolean I think.
No. There's complex emplace things going on
yeah im surprised it doesnt crash
yes
wait why is it a boolean here
ipairs
Just yes? No "Yes, but"?
thats what i would use at least
the structure of used_vouchers is like { v_omen_globe = true }
if i replace ipairs with pairs it crashes and says im indexing a boolean
yeah
wait how do i loop through vouchers then
You would do G.P_CENTERS[k] k being the key while using pairs
local vouchers = 0
for k, _ in pairs(G.GAME.used_vouchers) do
if not next(G.P_CENTERS[k].requires or {}) then
vouchers = vouchers + 1
end
end
hey what func do i have to hook when game ends
Winning or game over or both?
both
win_game(), Game:update_game_over()
Hi, so I'm used to retexturing with Malverk and replacing Joker Textures that way, I'm wondering if there's a way to add a sound to when a specific joker appears/is bought?
take_ownership and add add_to_deck field
since you're doing it on vanilla, make sure to include that joker's add_to_deck behavior
...i dont, really suggest doing take_ownership tbh
just hook to their existing add_to_deck function
what cards change to random rank and suit?
oh but i think you can hook inside take_ownership, so thats maybe fine 🤔
just dont override anything lol
I don't think that works for vanilla jokers
I mean spectrals
hooking a function in take_ownership should only be applied to modded jokers
Sigil and Ouija?
Yeah, those
🤔 you cant take ownership a vanilla joker? i thought you can just call a dummy function like G.P_CENTERS["smtsmt"].add_to_deck = G.P_CENTERS["smtsmt"].add_to_deck or function() end
but i never tried doing that before, only with vanilla consumables, so

they mean the center doesnt have an add_to_deck so you wont get the behavior by doing that
Card:add_to_deck doesn't use a series of elseif
I have no idea if overriding a vanilla joker's add_to_deck would remove their vanilla behavior
yeah no idea
I keep getting this error with several different jokers that activate upon being destroyed or destroy themselves. Why?
is it not supposed to be self?
oh, thanks
self refers to the declaration table itself, not card object
this is the main difference between vanilla objects and modded ones
can i do this
No
what if i assigned the return of caluclate = function to 'var' and did
mult = var
What is the goal?
No
keep track of all hands played this ante and update finisher blind score based on that
huh, what
you mean play count?
or total score?
finisher blind starts at 1.5x score, increases by 1.25x off base for every hand played in the ante
there are more stuff you need to do than just calculate
well then what do i need to do
card.seal gives the key of the seal right
is there a thing that checks if it has a seal in general
Card reference the joker
If you’re going thro played cards
You’d use v.seal
Depends on the variable you’re using in the For loop
yeah i know, i just said card cause it makes more sense to say that in my head
is there a way to check a joker's edition?
so the first one checks if the joker has an edition
the second checks for a specific edition?