#💻・modding-dev
1 messages · Page 396 of 1
Screenshot if you need
replace cards = { new_cards } for cards = new_cards
hi n
yeah, it only works because there's an overarching pool of all consumeables
but the auto area determination doesn't catch it
Now hologram doesn't increase at all.
weird
hiii
sorry i just got jumpscared and starstruck by a youtuber i like randomly messaging me
hey does anyone know about pools
and how to remove things from them
im trying to prevent some vouchers from spawning when a joker is sold without using used _vouchers
i mean that would help
im pretty sure if i remove the voucher from the pool they cant spawn anymore
is there documentation on creating and adding cards to deck/hand?
why can i hear jimbo speaking infinitely and also can't actually see him say anything
para_youlost_old = Game.update_game_over
Game.update_game_over = function(self, dt)
para_youlost_old(self, dt)
if G.PROFILES[G.SETTINGS.profile].pineappledeath and G.GAME.round_resets.ante > G.GAME.win_ante then
local Jimbo = nil
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 2.5,
blocking = false,
func = (function()
if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then
Jimbo = Card_Character({x = 0, y = 5})
local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot')
spot.config.object:remove()
spot.config.object = Jimbo
Jimbo.ui_object_updated = true
Jimbo:add_speech_bubble('lq_'..math.random(1,10), nil, {quip = true})
Jimbo:say_stuff(5)
end
return true
end)
}))
end
end
SMODS.Joker {
key = "mattjoker",
name = "mattjoker",
atlas = "mattatlas",
pos = {x = 0, y = 0},
config = {extra = {Xmultamt = 1, Xmult = 0}},
loc_txt = {
name = "some guy",
text = {
"This joker gains {X:mult,C:white}X#1#{} Mult",
"whenever a {C:dark_edition}Holographic{}",
"card or joker is triggered.",
"{C:inactive}(Currently {X:mult,C:white}X#2#{}{C:inactive} Mult){}",
}
},
rarity = 4,
cost = 15,
pools = {["gcmember"] = true},
unlocked = true,
discovered = true,
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra.Xmultamt, center.ability.extra.Xmult}}
end,
calculate = function(self, card, context)
if context.other_joker and context.other_joker.edition and context.other_joker.edition.holographic == true then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmultamt
return {
message = "ENHANCE!"
}
end
if context.joker_main and card.ability.extra.Xmult > 0 then
return {
message = "NO SCORING MESSAGE!",
Xmult_mod = card.ability.extra.Xmult
}
end
end
}```
what is wrong with this?
whenever a joker scores (holo) it just doesn't increase.
it's context.other_joker.edition.holo, not ...edition.holographic
can you check if other jokers do not trigger like how you can check if cards dont score?
tyty
typically you use a booleen that flips to true when what you want to detect happens
please
i want to do something similar to certificate
but i cant understand what is going on in that code
you can just look at certificate code
the problem is that i cant understand it
i know what some things do
but others dont
probably due to my lack of lua skill
oh god i forgot how aids this is
local _rank = pseudorandom_element({'J', 'Q', 'K'}, pseudoseed('never_punished'))
local _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('never_punished'))
local _card = create_playing_card({
front = G.P_CARDS[_suit..'_'.._rank],
center = G.P_CENTERS.m_glass
}, G.hand, false,false,nil)
_card:add_to_deck()
table.insert(G.playing_cards, _card)
_card.states.visible = nil
G.E_MANAGER:add_event(Event({
func = function()
_card:start_materialize()
return true
end
})) ```
mmm anything you need to know about?
this is code to create a face card
also ho perkeo guy
could you explain a bit how this works please
i think i get everything except this
}, G.hand, false,false,nil)```
create_playing_card takes 5 arguments. the first one is a table, which contains values of front (the rank and suit of the playing card) and center (the enhancement of the playing card). the second argument is where the playing card goes (G.hand puts it into your hand). i forget what the others do but they're all false and nil so they don't particularly matter in your case lol
it's formatted a little weirdly, i probably would've indented the lines with front and center to make it clear that they're part of a table
--picks a random rank from the list
local _rank = pseudorandom_element({'J', 'Q', 'K'}, pseudoseed('never_punished'))
--picks a random suit from the list
local _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('never_punished'))
--creates the card
local _card = create_playing_card({
--sets the rank and suit
front = G.P_CARDS[_suit..'_'.._rank],
--sets the enhancement (glass)
center = G.P_CENTERS.m_glass
--tells the game to put it in hand
}, G.hand, false,false,nil)
--adds the card to your deck
_card:add_to_deck()
--i dont remeber what this is for but i think its just a table that tracks your deck or smth
table.insert(G.playing_cards, _card)
--set the card to be not visible
_card.states.visible = nil
G.E_MANAGER:add_event(Event({
func = function()
--plays the animation to reveal the card
_card:start_materialize()
return true
end
}))
i hate this game and vouchers
do you know how pools work
yes i know how they work somewhat, but no i dont know how to remove a voucher from the pool
beans
thanks
i hated piecing this together
why did i make balatro my first lua experience
i feel that in my soul
- being shit at writting code in general
but also im a python enjoyer
i should leave a bad review saying the game is too hard 
why does this spawn infinite jimbos
para_youlost_old = Game.update_game_over
Game.update_game_over = function(self, dt)
para_youlost_old(self, dt)
if G.PROFILES[G.SETTINGS.profile].pineappledeath and G.GAME.round_resets.ante > G.GAME.win_ante then
local Jimbo = nil
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 2.5,
blocking = false,
func = (function()
if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then
Jimbo = Card_Character({x = 0, y = 5})
local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot')
spot.config.object:remove()
spot.config.object = Jimbo
Jimbo.ui_object_updated = true
Jimbo:add_speech_bubble('lq_'..math.random(1,10), nil, {quip = true})
Jimbo:say_stuff(5)
end
return true
end)
}))
end
end
now ill permanently borrow this code
lol, code just goes wrong in the right way sometimes
is this the right way?
how do i set no enhancement?
m_base
thank you
For sure, what's better than infinite jimbos!?
infinite jimbos that have a chance to talk
how would i make it where a single mod folder could load multiple deck skins for different suits with different parameters [some changing just KQJ, some changing Ace, some changing all cards, etc]
has smods.font been added to the wiki yet?
i cant find it
i'm having some issues with it
steamodded has a font feature?
you define each deck skin for each suit individually, there's no special behavior in that regard to make things change across deck skins. it'll be a bit tedious to write all of them out depending on how many you have, but it is the default behavior that you can do that
as of like a day ago yeah
if only it were documented or something
me with everything in smods
so true
the implementation seems to have changed since i first started using it, so everythings all fucked up
oh the new art is crazy good woah
what you don't want W I D E joker names
ikr! tattered is an artistic genius

now its time for my favorite part of modding, trying random shit until it works™
somehow i just realizing i typed eanana instead of banana
eanana
eanana
wait are you still using a main.lua header
Why are you using headers instead of metadata 😭
blame tutorial i followed
you should https://github.com/Steamodded/smods/wiki/Mod-Metadata now
how do i check if a card has a seal
ask nicely
im still using a header 😭
i asked a question in the channel where you ask questions what do you want from me
stop whatever youre doing and fix that
hi one question
in shop_rate 1 is much rate or minimum rate?
srry i was joking about asking the card
idk myself
oh lol mb
if card.seal will be true if card (you should replace that with whatever variable refers to the playing card in question) has a seal
illustrated diagram
oh good i was gonna use if card:get_seal()
me when quantum seals
yea enhancements are the only card modifier that behaves like that
the fuck did i do
please no. please don't tell me quantum seals are a thing
wider
what happened to your joker's name 😭
#1355819401198178455 truly
SMODS.Font was recently merged and it is not documented yet, and they decided to change the implementation, meaning i have to trial and error the numbers
better
letters are a tad blurry though hm
great
good enough, welcome back old norse runes
F S X F R ∣⨯∣
so something like this?
key = "cllb1_hc",
path = "collab1_hc.png",
px = 71,
py = 95,
}
local atlas_hc = SMODS.Atlas {
key = "cllb2_hc",
path = "collab2_hc.png",
px = 71,
py = 95,
}```
followed by the standard SMODS.DeckSkin stuff for each suit, just swapping the Key for each separate skin [ex: "key = cllb2_h"] for Collab #2 of the Hearts Suit?
anyone know how to use this
ima dumbass 😭, the json file wasnt being read because it put it on the balatro folder sdanadslgjbdfg
hopefully now
it works
flawlessly
do i keep these colors?
ouuhhhhh no
make an atlas with the key modicon
32x32
34x34 with a blank one pixel border
does anyone have an example/solution to replacing joker names with smod?
your joker or other jokers?
how would i make an edition like this work on a playing card?
vanilla jokers
key = "testfiresr",
blueprint_compat = false,
loc_txt = {
name = 'testm',
text = {"{C:red}+#1#{} hand size,",
"Earn {C:money}$#3#{} at",
"end of round.",
"If {C:red}bruhio{}",
"is in your deck,",
"{C:red}+#2#{} hand size,",
"Earn {C:money}$#9#{} at",
"end of round."}
},
pos = { x = 0, y = 0 },
rarity = 2,
atlas = 'mindatest',
blueprint_compat = false,
cost = 6,
config = { extra = { h_size = 1, dollars = 3, h_sizetest = 2, dollarstest = 9, h_sizereset = 1, dollarsreset = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.h_size, card.ability.extra.dollars, card.ability.extra.h_sizetest, card.ability.extra.dollarstest, card.ability.extra.h_sizereset, card.ability.extra.dollarsreset } }
end,
calculate = function(self, card, context)
if context.card_added and table.contains(bruhio, context.card.config.center.key) then
G.hand:change_size(1)
card.ability.extra.h_size = card.ability.extra.h_sizetest
card.ability.extra.dollars = card.ability.extra.dollarstest
if context.selling_card and not context.blueprint and context.card.config.center.key == "j_bruh_bruhio" then
G.hand:change_size(-1)
card.ability.extra.h_size = card.ability.extra.h_sizereset
card.ability.extra.dollars = card.ability.extra.dollarsreset
end
end
end,
add_to_deck = function(self, card, from_debuff)
G.hand:change_size(card.ability.extra.h_size)
end,
remove_from_deck = function(self, card, from_debuff)
G.hand:change_size(-card.ability.extra.h_size)
end,
calc_dollar_bonus = function(self, card)
return card.ability.extra.dollars
end
}```
hopefully someone can figure out the solution to this 
currently the "bruhio" buff works only if "bruhio" is bought second, but not if "bruhio" is already owned. when "bruhio" is sold, the conditional to reduce the buffs back to normal doesn't get applied (debuffing itself already works, it just doesn't have a proper conditional)
it's meant to be +1 hand size $3 at the end of round at base, and +2 hand size $9 at the end of round when buffed
dynamically changing
does anyone know why my hook doesn't work? it crashes if i lose post ante 8 to the pineapple
para_youlost_old = Game.update_game_over
Game.update_game_over = function(self, dt)
if not G.STATE_COMPLETE then
para_youlost_old(self, dt)
if G.PROFILES[G.SETTINGS.profile].pineappledeath and G.GAME.round_resets.ante > G.GAME.win_ante then
local Jimbo = nil
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 2.5,
blocking = false,
func = (function()
if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then
Jimbo = Card_Character({x = 0, y = 5})
local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot')
spot.config.object:remove()
spot.config.object = Jimbo
Jimbo.ui_object_updated = true
Jimbo.para_jimbotalk_old(Jimbo, 'pineapple', nil, {quip = true})
Jimbo:say_stuff(5)
end
return true
end)
}))
end
G.STATE_COMPLETE = true
G.PROFILES[G.SETTINGS.profile].pineappledeath = false
end
end
what determines the checkered decks two suits? im looking at vs code, but theres nothing that would signify it. if anyone could help explain how it works, let me know
so let me get this straight, smods has no function for creating playing cards
does someone know why this deck dont work? i am new here, i am trying to make a deck with only negative joker,
but has one for removing things from pools
can i read the cards i currently have in hand?
it needs it to do all the pool logic so it makes sense
vanillaremade does this
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Clubs' then
v:change_suit('Spades')
end
if v.base.suit == 'Diamonds' then
v:change_suit('Hearts')
end
end
return true
end
}))
end,
wait does SMODS.create_card not work for playing cards?
thats stupid
oh nice, thank you, ill just install the mod lol
do not install vanillaremade
name = "Negative Deck",
key = "negative_deck",
pos = {x = 1, y = 3},
config = {cry_negative_rate = 100},
unlocked = true,
loc_txt = {
name ="Negative Deck",
text={
"All jokers are",
"{C:attention}Negative{}",
},
},
apply = function(self)
G.GAME.modifiers.cry_negative_rate = self.config.cry_negative_rate
end,
init = function(self)
SMODS.Edition:take_ownership("negative", {
get_weight = function(self)
return self.weight * (G.GAME.modifiers.cry_negative_rate or 1)
end,
}, true)
end,
}
its meant to be looked at only
You are better then i
bump
what is wrong here? i am new
oh- alright
this code was from cryptid i assume?
i was about to say
yes
i tried to copy to understand how things works
would it be best to copy-paste this code into vs?
cry_negative_rate is from cryptid and not in smods
yeah put it in the deck code
you can tell because it starts with cry_
but i changed the get_weight of the negative to 100 too and didnt work as well
cry_negative_rate isn't real unless you have cryptid
and the deck code is with the {} in the --backs area yeah? or is it in another place
thank u for explaing it
should be
alr, let me try
how should i do it instead?
idk
theres probably an edition rate somewhere but im kinda busy trying to fix my joker
okok, thank u for ur time
how do u remove the shadow from a joker? Like glass joker does?
card.no_shadow
wait actually i know what you should do
take ownership of negative and modify the weight based on the deck
I'm still a little confused lol 😭 like, do I just put this up with the atlas stuff as "card.no_shadow = true" or do I need to make a function of some kind? 😭
idk if there's a way to do it in the definition honestly
but setting no_shadow to true works so you might need to do it in set_ability
but maybe theres a better way
I was hoping this'd be more simple lol, I'm too tired for this jfdgknjh lmao, I really gotta deal with this issue my brains been having lately lol nfhdb can't find the energy for nothing as of late lol fdjkgdfn
para_jimbotalk_old = Card_Character.add_speech_bubble
Card_Character.add_speech_bubble = function(self, arg1, arg2, arg3)
if G.PROFILES[G.SETTINGS.profile].pineappledeath then
para_jimbotalk_old(self, 'pineapple', nil, {quip = true})
else
para_jimbotalk_old(self, arg1, arg2, arg3)
end
end
why doesn't my hook work?
if i lose pre-ante 8 it still doesn't show the right jimbo quip
trying to learn three things with 0 experience
how to change the suits of checkered deck to be diamonds and clubs
how to change the name of checkered deck
how to change the texture of checkered deck back
if anyone can help, wether it be directly telling me or sending me to a source lmk
the suit change should work like this?
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
return true
end
}))
end,
just take ownership of checkered deck
bump
I swear to god
this god damned mod
Is going to be
The death of me
that sucks
anyone know why this is happening?
i tried changing those values alone, but when i open the game they dont seem to have saved
code?
i dont have talisman on though
idk how to fix it without uninstalling talisman though
when does the crash happen
at the end of the round right before cash out screen
can i see the rest of the joker code?
This function should probably only return a number, not a table
seems like its all numbers tho
have u tried making a new joker, in case card.ability.extra.(x) is still a table?
wait
OHHH
They're returning a list of one number
para_jimbotalk_old = Card_Character.add_speech_bubble
Card_Character.add_speech_bubble = function(self, arg1, arg2, arg3)
if G.PROFILES[G.SETTINGS.profile].pineappledeath then
para_jimbotalk_old(self, 'pineapple', nil, {quip = true})
else
para_jimbotalk_old(self, arg1, arg2, arg3)
end
end
why doesn't my hook work? the quip never shows up
i think its the condition but idk why the condition is never true
it gets set to true
i dont think you need self in Card_Character.add_speech_bubble = function(self, arg1, arg2, arg3)?
also, make sure the func doesn't need to return anything just in case
so, i can see how it would take ownership of a joker, but how could i take ownership of a deck in this case
change out joker with back
okay
para_jimbotalk_old = Card_Character.add_speech_bubble
Card_Character.add_speech_bubble = function(arg1, arg2, arg3)
if G.PROFILES[G.SETTINGS.profile].pineappledeath then
para_jimbotalk_old('pineapple', nil, {quip = true})
else
para_jimbotalk_old(arg1, arg2, arg3)
end
end
``` just makes jimbo say nothing
keep self in para_jimbotalk_old
that crashes the game
because there is no self
i hate to ask, but do you know how i might be able to add that properly?
inserted this:
i usually use function Card_Character.add_speech_bubble(arg1,arg2,arg3) instead
SMODS.Back.take_ownership('Checkered Deck', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
cost = 5,
calculate = function(self, card, context)
-- more on this later
end
},
true -- silent | suppresses mod badge
)
SMODS.Back:take_ownership('wtf is the checkered deck key you find that', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
return true
end
}))
end
},
true -- silent | suppresses mod badge
)
thank you! so the part right after take ownership is just a name to help organize it right?
no you need to find the key (separate from the name) of the checkered deck
idk what it is
and put that there
wouldnt it be b_checkered?
fair
bump
also fyi, i put it into lovely instead of the root right?
or vise versa
no it goes in main.lua
main or game.lua
pasting the code into main breaks the game entirely
wait can you send me the mod folder
uh yeah
I am right on the brink of finishing this joker, but hologram only increments up once, instead of once for each new card added to the deck from this joker.
calculate = function(self, card, context)
if context.before and context.main_eval then
local new_cards = {}
for i = 1, 2 do
for k, v in ipairs(context.scoring_hand) do
if v.seal or v.edition or next(SMODS.get_enhancements(v)) then
G.E_MANAGER:add_event(Event({
func = function()
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local copy_card = copy_card(v, nil, nil, G.playing_card)
copy_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, copy_card)
G.hand:emplace(copy_card)
copy_card.states.visible = nil
copy_card:start_materialize()
new_cards[#new_cards + 1] = copy_card
return true
end
}))
end
end
end
SMODS.calculate_context({ playing_card_added = true, cards = { new_cards } })
return {
message = localize('k_copied_ex'),
colour = G.C.CHIPS
}
end
if context.destroy_card and context.cardarea == G.play and
(context.destroy_card.seal or context.destroy_card.edition or next(SMODS.get_enhancements(context.destroy_card))) then
return {
remove = true
}
end
end
put the calculate_context in the for loop
Already tried that, but then hologram shows text for each increment, instead of just doing text for the final count.
if discord won't let you you need to zip the folder first
but does hologram increment the correct number of times?
Yeah, but I don't like how it looks.
you could try taking ownership of hologram?
idk what you'd change though
considering the for loop's hardcoded: before the loop runs set a variable so that hologram doesn't show text and on the final loop reset that
is the steamodded github page imploding for anyone else?
oh ok i know what the problem is
you need to do cards = new_cards but you need to create the cards outside the event
oh more people are here
para_jimbotalk_old = Card_Character.add_speech_bubble
Card_Character.add_speech_bubble = function(self, arg1, arg2, arg3)
if G.PROFILES[G.SETTINGS.profile].pineappledeath then
para_jimbotalk_old(self, 'pineapple', nil, {quip = true})
else
para_jimbotalk_old(self, arg1, arg2, arg3)
end
end
why doesn't my hook work? the quip never shows up
(or do the opposite and put the loops inside the event, that might be easier)
i reset everything, so nothing is edited as of this moment
where is your mod
all i see is deck creator with no main.lua in sight
or any steamodded mod stuff frankly
Sorry, I really don't what I'm supposed to do.
so ive totally been doing that part wrong, im going into the steam apps and the root folder and editing the files there
oh
reinstall balatro, steamodded, and lovely
then use this #1349064230825103441 message
aye, thank you
try this
calculate = function(self, card, context)
if context.before and context.main_eval then
local new_cards = {}
for i = 1, 2 do
for k, v in ipairs(context.scoring_hand) do
if v.seal or v.edition or next(SMODS.get_enhancements(v)) then
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local copy_card = copy_card(v, nil, nil, G.playing_card)
copy_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, copy_card)
copy_card.states.visible = nil
new_cards[#new_cards + 1] = copy_card
G.E_MANAGER:add_event(Event({
func = function()
G.hand:emplace(copy_card)
copy_card:start_materialize()
return true
end
}))
end
end
end
SMODS.calculate_context({ playing_card_added = true, cards = { new_cards } })
return {
message = localize('k_copied_ex'),
colour = G.C.CHIPS
}
end
if context.destroy_card and context.cardarea == G.play and
(context.destroy_card.seal or context.destroy_card.edition or next(SMODS.get_enhancements(context.destroy_card))) then
return {
remove = true
}
end
end

Thanks so much! I just had to remove the braces around new_cards in the calculate context.
oh yeah forgot about that
im glad it worked
hehehehehe
tweening api + card movement api + custom button api
hehehe
not sure how to render a specific card on top of others but
(if anyone knows id be thankful c:)
all that done through this code in the frontend mod (backend is horrendous istg)
why is condition a never true when line b specifically sets it to true
for some reason my mod wont load in the second joker, how do i fix that?
show us the whole file
zoom out
unindent the end after loc_vars 2 times
place a second end (indented one less time than the first) after the end for calculate
indent after the else in calculate, then deindent and place an end after remove = true
and the bracket at the end of the return that returns the debuffed message needs to be indented one more time
also remove the very last indent
bump
so like that?
indent the very last end once
?
also remove the end in white
do the indents make that much of a difference?
yes
at least i think so
the ends i know matter
regardless its good practice to indent properly
the joker's still not loading in
and your other joker does?
yeah
send me the whole folder
do you have talisman
remove the number_format bits
also you should be returning xmult in joker_main
not xmult_mod
why?
dont need it
like i said, it loaded the first one fine with it
look idk either but something has to be stopping it and i know you dont need number_format
thats not whats stopping it though
this is so hacky but it actually works 
finally no more infinite hand size
now i need to figure out how to apply the damn debuff
come back to it when there's more people here ig
maybe someone else can help you
i'm derping out, how can i use string.sub to get the first 6 characters of a string 
why is condition a never true when line b specifically sets it to true
string.sub(text,1,6) ?
for me, it's just been sitting on this for hours, even after i refresh it or open in a new tab. it's just this and only this
does not load
working fine for me rn
meh, maybe it's client funkiness, i'll see what it's like tomorrow. but every other repo i've looked at has been fine, just steamodded
A bit of a weird request but uh
Is there a way to retrigger specifically seals?
Like if I wanted to retrigger the red seal or the blue seal
Or does it have to be indirect by just recreating the effect
how can i know how many discards did i make in a round?
G.GAME.current_round.discards_used?
Can you tell me to paint joker should use 3 x 3 px brush in aseprite?
#🎨・fan-art they might know better
sighs extremely loud
the difference between you and i is the fact that im dedicating way too much of my time to the dumbest idea ive been submitted so far
i have a whole list of things to do and the first one i do is "put minesweeper in a joker(????)"
the difference is that im still bad at programming so i cant go crazy with ideas 😔
you got this
honestly this is not so complicated its just a lot of seperate moving parts
i had the idea of making an orb of corruption that corrupted the joker to the left, but for that i would have needed to make a new edition, and i wasnt going thru allat just yet...
has anyone had an issue where blueprint doesn't work properly with a joker
instead of both blueprint and the joker activating, instead blueprint activates first and the actual joker does nothing
i thought the issue was blueprint_compat being in the code but it seems whether i set it to true or i remove the line it doesn't matter
ts aint working 😔
i wouldve done an edition already but like then i'd need someone to make a shader, or learn it myself
glsl isnt that bad it's just straight up not worth my time compared to how much i'll gain from knowing it
it doesnt crash
true
you are checking the amount of times they have discarded but not the amount of cards right
or is that unintentional
i dont believe there is a variable for it
you might have to just count it yourself
#G.discard.cards?
try adding one to a counter whenever context.discard is truthy and resetting at end of round
it works 😔
oh ok nice
key = "damndudesr",
loc_txt = {
name = 'testdrdn',
text = {"{C:red}x4{} Mult if",
"played hand contains a",
"{C:red}King of Hearts{} and",
"a {C:red}Queen of Hearts.{}",
"If {C:red}bruhio{}",
"is in your deck,",
"{C:red}x8{} Mult instead,"}
},
rarity = 2,
cost = 6,
pos = { x = 0, y = 0 },
config = { extra = { Xmult = 4, Xmulttest = 8, Xmultreset = 4 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if next(SMODS.find_card("j_srio_bruhiosr")) and next(SMODS.find_card("j_srio_damndudesr")) and not context.blueprint then
card.ability.extra.Xmult = card.ability.extra.Xmulttest
end
if not next(SMODS.find_card("j_srio_bruhiosr")) and next(SMODS.find_card("j_srio_damndudesr")) and not context.blueprint and card.ability.extra.Xmult == 8 then
card.ability.extra.Xmult = card.ability.extra.Xmultreset
end
if context.individual and context.cardarea == G.play then
for i = 1, #context.scoring_hand do
if context.other_card:get_id() == 12 and context.other_card:is_suit("Hearts") then
card.ability.extra.kings = true
elseif context.other_card:get_id() == 13 and context.other_card:is_suit("Hearts") then
card.ability.extra.queens = true
end
end
end
if context.joker_main and card.ability.extra.kings == true and card.ability.extra.queens == true then
card.ability.extra.kings = false
card.ability.extra.queens = false
return {
Xmult = card.ability.extra.Xmult
}
end
end
}```
this joker works as intended, except that blueprint and brainstorm don't work properly with it
i tried removing blueprint_compat = true and readding it but regardless of whether i do or not it's the same thing
is there something else i need to add or remove for blueprint to work properly?
the conditions all contain "not context.blueprint" that might be messing it up
Hii
howdy. new to Balatro modding?
removing the not context.blueprint conditions did nothing, blueprint still doesn't work properly
and i have doubts about where to make the pngs of the cards
if someone could recommend me something about that🍞
you can use any image editor, preferable one that specializes in pixel art because that's obviously what the game uses. I'm no artist but I've been using Pixelorama, its free and easy to use
also bro's playing Silksong?????
sjkjksksj
get me a copy of that bro
a god amongst men
confidential bro...
X229
thats crazy
comedy gold joker
when silksong releases (???) im going to significantly buff hornet because it'd be funny
has it really been 2290 days or is that just a goated joke
slightly more, but it rounds the number down due to significant figures i guess
not exactly 2290 but between 2290 and 2299
i bet everything on red that they announce a date in the summer game fest
according to the nintendo direct for the switch 2 it has a 2025 release year
mmmnm,,, i heavily regret promising tauic versions of every single vanilla joker
but yeah I bet it will have a realease date announced
sksjkskj, you have to update for each day that passes
i do not!
it updates by itself
you're telling me... I just started a mod where I'm making a Joker for every item in The Binding of Isaac
technically you can even catch it changing i believe
so what do you want on the obituary?
since it happens to check every time it runs and every time the loc vars update
I might get it just for the improved >= and the arrows
i've been using this font for just over 2y
genuinely can't imagine not using it at this point
i will try
I want this on my obituary:
i like it
iykyk
seems we both have an unreasonable amount of stuff to do
why on earth would you go for plat god 😭
i literally have 115 jokers in the tauic set left to make
i should probably update my deadline
yeah for sure. Don't wanna get burned out during a labor of love like modmaking
115??
i said i was going to make tauic variants of every vanilla joker
im going to deliver on that promise
i think im going to get raptured by myself
thankjfully some of them were combined like even steven & odd todd, or all of the xmult hand types
isnt that just called platinum god (or just triple dead god)?
how would i count seconds spent in the ante?
hook update and count deltatime
in the newest DLCs, platinum god isn't the final completion mark anymore, Dead God is. Dead God normally has a different file save image, but when you have acheived Dead God on every save file, you get this special one
ah right okay fair enough, im just misremembering it
speaking of, I need alot of Jokers that provide extra lives, and I wanna know how o replace the "Saved by Mr. Bones" text with my own
this is how i did something similar (not for counting time, just hooking update)
oops wrong ss
just set it to 0 at the start of the ante, by any other means
update runs every frame
I can count just fine i just dont know what the thing is for the start of the ante
ill see about it
awesome
maybe whenever ease_ante is called you can reset it?
you know im not sure what i did but i'm pretty damn sure there is not 8 mines there
i don't even wann know what is joker's file looks like 😭
i genuinely have a 3 sentence apology at the top of the file
I mean yeah
bro reprogrammed minesweeper for a damn joker
YO THAT GIVES ME AN INSANE IDEA
someone needs to make Doom on a Balatro Joker
probably doesn't even work with blueprint smh
most of the code isnt even in the joker lol
there isn't a single thing in its calculate function
i might even keep it that way - mostly its just ability consumables that interact with the data stored on the joker rather than actually being the joker itself
can someone link the patching API documentation
i'm still confused but less
there cannot physically be 4 mines around the 4 in the top right unless its counting the center spot which it shouldn't be
also there are multiple nonsensical zeros
hm.. seems like it pauses in the shop and crashes after you beat the boss blind
strange
! i might be done with minesweeper in balatro (assuming i add the movement cards and the win/loss conditions)
do I have this patch written correctly? when the card saves me in-game, the message during cashout is just "ERROR"
[[patches]]
[patches.pattern]
target = "en-us.lua"
pattern = '''ph_mr_bones="Saved by Mr. Bones",'''
position = "after"
payload = '''
ph_1up="Saved by 1 Up",
'''
match_indent = true
times = 1
is it because the patch is applied to one of the localization files?
Why are you patching the localization file?
You can just put that in your own localization.
that's where the mr bones message is contained
Yes, you can put that in your own localization file.
You cannot patch localization files at all
alright it worked perfectly, thanks
Feeling like I'm doing this wrong to make the additional "scoring" more consistent in terms of timing and trying to have them execute before "held in hand" abilities go off...
I think your tiles are double-counting top right corner and not counting top
yea the issue was it was double counting x-1, y+1 relative to each bomb, and not counting x-1, y at all
i just forgot to change the y+1 to y
classic Ctrl-C Ctrl-V bug
So no nested -1 to 1 for loop? 😔
unfortunately no
as much as i am not that bad at it
this is the first time ive used lua for a project before and as such i really dont like using for loops for things that isnt like. looping over a table
still adjusting to indexing by one
Valid, I only joke cause my students literally just did their final project on implementing minesweeper in Python
oh lmao
tbf this is exactly why i have the apology at the top of minesweeper.lua
my Intro to CS class did Connect 4
Connect 4 is far simpler
ay i just finished ap csa
I think it is anyway
Checking the win state would be more complex, no?
Unless you provide a good amount of detail in your instructions
I still have the assignment, let me look at it
entire file (including computer player) is only 327 lines
granted the computer is really dumb but still
def checkWinner(board, playerNumber):
# Gets the player whose piece we need to check for
piece = getPlayerPiece(playerNumber)
# Check for any horizontal sequences
for row in range(0, len(board)):
for column in range(0, len(board[0]) - 3):
if (board[row][column] == piece) and (board[row][(column+1)] == piece) and (board[row][(column+2)] == piece) and (board[row][(column+3)] == piece):
return True
# Check for any vertical sequences
for row in range(0,((len(board)) - 3)):
for column in range(0,(len(board[0]))):
if (board[row][column] == piece) and (board[(row + 1)][column] == piece) and (board[(row + 2)][column] == piece) and (board[(row + 3)][column] == piece):
return True
# Check for any positively sloped sequences
for row in range(0,((len(board)) - 3)):
for column in range(0,((len(board[0])) - 3)):
if (board[row][column] == piece) and (board[(row + 1)][(column - 1)] == piece) and (board[(row + 2)][(column - 2)] == piece) and (board[(row + 3)][(column - 3)] == piece):
return True
# Check for any negatively sloped sequences
for row in range(0,((len(board)) - 3)):
for column in range(0,((len(board[0])) - 3)):
if (board[row][column] == piece) and (board[(row + 1)][(column + 1)] == piece) and (board[(row + 2)][(column + 2)] == piece) and (board[(row + 3)][(column + 3)] == piece):
return True
return False
win condition function
Do they have to implement that or is it provided? Cause if they have to implement it then honestly I think minesweeper is easier. Granted, I provide a ui.py file and they just have to write the backend.
Returning that to how I originally had it, it kinda works, but Rover's deck-scoring gets briefly interrupted by "held in hand" abilities (being Steel Cards in this example)...
only the UI was provided to us. This win condition code is my own
insanely powerful jokers
I was curious when I was initially prototyping them... just wanting to refine their effect to be more consistent now, as they "currently" score cards as their joker_main effect.
maybe try switching it to something like final_scoring_step. Earlier I was experimenting with a joker that applies the Plasma Deck's balancing effect, and it seems that jokers that use the same context as Plasma:
context.final_scoring_step
apply their effects before the Plasma Deck's effect is applied
probably won't work, but just an observation I made while testing
Space Cadet's random rescoring of the scoring cards works as intended, more or less, it's just Rover that I need to get working so that it scores the deck before "held in hand" abilities kick in.
does anyone know how to get the UI boxes that pop up next to certain things to appear? like foil, negative, red seal, eternal all add UI elements next to the description of what they're applied to
Tooltips, you mean?
yes, thank you
would this joker be feasable to make?
Do side-quests.
For every 5 side-quests, make a negative tarot card.
For every 10 side-quests, make a negative planet card
For every 15 side quests, make a negative spectral card
For every 20 side-quests, spawn a negative legendary
only one reward at time or can be all?
can be multiple
so at 10, you'd get both the 5 and 10 reward
sounds cool, what type of quest you have in mind?
im thinking of having 4 different tiers/difficulty
and the harder the quest, the more it'll count as
so a tier 4 quest could be:
"One-shot a blind using a high-card."
and why don't you make the joker count "quest coins"?
the hard the quest the bigger the reward
spend 50$

sound cool man, like "play "two pair" three times"
maybe "score (2x? 3x? 5x?) the blind requirement"?
score between x and y chips with any hand
i wont be able to add any variable for now
lack of skill?
Ah hell yeah another "side-quest system in their mod" haver
no im just tired
oh ok
your jokers seems more like a "pasive", why dont add it like a deck?
they hate me
some jokers i add are passive
Pikuniku mentioned
i currently only have 2 passive jokers
we love pikuniku in this household
Pikuniku more like Peakuniko
i dont know your mod, can you share photos of the jokers?
tax in balatro
They dont have art done yet, but ill just say them:
Andrew - Be able to select, play, and discard six cards.
??? - Side quests
What if its sell value was more than $0
Literally Free Money!
!!
wait if i have 7 they will stuck in 6?
Is that a giant robot cutting down a forest in the distance????????????
no, as it calls the function again to check for any modifications
i dont see how thats relevant to the free money
oh cool
Shit you're right
heres my current list of quests
local quests = {
["Easy"] = {
"Play a Flush",
"Play a Pair",
"Discard exactly 2 cards",
"Play a hand with all 4 suits"
},
["Medium"] = {
"Spend $50",
"Play a Full House",
"Play a hand with all even-numbered cards",
"Trigger a Joker effect 3 times in one blind"
},
["Hard"] = {
"Score 5x blind requirement",
"Play a Straight Flush",
"Play a hand with 5 different ranks",
"Have all of your Joker, and Consumable slots full"
},
["Insane"] = {
"One-shot a blind using a High Card",
"Play a Five of a Kind",
"Play a hand made entirely of face cards",
"Reroll the shop 10 times in 1 sitting"
}
}
What are the payoffs?
i disagree with a few of these categorisations
Would "Play a hand made entirely of face cards" work if you just played 1 face card?
playing a hand full of face cards is objectively easier than a straight flush
even without the 1 face card cheese
"play a hand made entirely with face card”
thats easy ngl
and if you gear your build the right way you can oneshot most blinds with a high card
but yeah is there like. a way around this
the cards may have count to the quest?
I'd argue a five of a kind is significantly easier to play than a straight flush
ill probably swap those 2 then
like no amount of deck rigging makes them entirely consistent
what if you rig your deck to have only a straight flush
just 5 cards
Sorry if I expressed myself badly, do the cards have to score in the hand to be valid for the quest?
depends on the wording
but always assume scored
this is correct.
i mean yeah but a 5 card deck is suboptimal for a lot of reasons
someone give me another challenge to put in insane
why you dont add something like
play a family: 1King, 1Queen, 1Jack
I admit I was able to say that from experience 😭
reroll a single shop 5 times or more
sell 3 jokers mid blind 
wait you have that already mb
goes back one ante
HELL YEAH
i want the +Mult value to only increase when a joker in a specific table is in hand, how would i go about adding a check for that specific joker table?
(this is just abstract joker)
do you mean go forward one ante
cause this would be a good thing
play 4 debuffed cards in a single hand
yea thx, english is not my first lenguage
it's an unfortunate limitation, yeah. we might fix it at some point but there's not much of a reason to tbh
thats just a high card build +4 throwaways
debuffed cards need to be scored
wait
so like a Spade flush against the Goad has 5 debuffed cards
yeah no i mixed up debuffed and non scoring mb
@gusty iron what about "have 0 cards left in deck"
ill put that in medium
seems fair
Honestly yeah it's not worth "fixing" it when making your own loc file is just an infinitely better solution
destroy 3 or more cards in a single round
How would I send two unique messages from one return function? I have this to make my dog joker card woof, but I also want it to say something else
okay i think i have a good list
now
my only issue
is keeping track of which challenge is active
mmm, that would be easy with hanged man + the fool
i can probably do it via variable in the joker
extra = {message = "secondmessage"}?
getting this combination of tarots is rare enough i think itd be fair to put in insane
I want them both in the extra section, if I put it in return, the message plays above the card being scored, and not below the joker
if we talk in vanilla, probably that thing will play with another mods
its not that hard, even in vanilla
extra = {message = "secondmessage", message_card = card}?
facts

I already have one message in extra, but I want to put another, setting message card to card makes it play above the scored card
Then put the message in the extra in the extra?
is there a context function for when a card appears in the shop
{message = "message1", extra = {message = "message2", extra = {message = "message3"}}}?
Are you even able to put extra in extra?
Yes, extras are infinite.
i know it exist, because of the "editions", but i dont know how to name it
didn't know that
alright, im getting tired, its 4 am and i decided around 20 minutes ago as a little venture to go and try to fix the problems my mod has with talisman, but im unable to find any comparations that i havent replaced with to_big here so idk what to do to fix this one
🔥
soul is the spectral card that spawns legendaries yeah
what's the G.hand:change_size equivalent for discards?
context.reroll_shop
and is there a context for exiting the shop?
context.ending_shop
Giving discards or..?
yeah, giving discards
also
if i had a nickel for every time i found a srb2kart/ring racers modder modding balatro
I'm not an active modder of SRB2, Kart or RR anymore, tbh.
ease_discard(amount)
-# Especially when it comes to just SRB2 itself, I'm pretty much a one-trick pony with Windows.
how do i check the name of the hand playing?
context.scoring_name
Anyone know why my custom joker art is so much dimmer in game than the original image?
I implemented something like this and the tooltip simply says ERROR
Are you intending to point it to a "center" or just have custom text shown?
just custom text
I just a patch to inject my own edition into game.lua and referenced it, but got the error
that said I think the statement is written wrong here, since even referencing the lucky card one for example doesn't work
Why are you injecting them in instead of using SMODS.Edition?
If you want just custom text that's not a "center", do info_queue[#info_queue + 1] = {key = "prefix_key", set = 'Other'}... then point to your custom text stuff in the localization file.
the way it works isn't quite the same as other editions and I don't want it being applied to just anything like Foil or Holographic can be
Any way of having a gif as a jokers sprite?
You would split the gif into multiple frames and then use that as the sprite and animate it.
Is there an example of how to animate it?
is there a list of all contexts?
is it possible to use SMODS.find_card with a table?
No, but this has most of them: https://github.com/Steamodded/smods/wiki/Calculate-Functions

...well, no, but you could make your own function or hook this one.
You can search for SMODS.calculate_context in your lovely/dump folder, then make note of which context are called where, and what parameters are passed into them. Using Lovely patches and calling that function yourself can let you make your own contexts, too.
what im trying to do is make the joker free whenever context.thisjokerappearsintheshop happens, does that context exist
or is there a better way of bypassing the apparent price floor
Hook Card:set_cost()
Isn't it easier for thateyisofth to give you the money you bought it for?
(the price is set to 0 in the file and its just setting it to 1 anyway)
i mean yeah, but thats lame
Its because of the set_cost func
true
just set the cost to 0
🧠
.
types lua hook into google and spends an hour figuring out what this means
trying to make a joker that randomly selects a scored card to retrigger
if context.repetition and context.cardarea == G.play then
local _randomcard = context.scoring_hand[math.random(1, #context.scoring_hand)]
for i = 1, #context.scoring_hand do
if _randomcard == context.scoring_hand[i] then
return {
repetitions = 1
}
end
end
end
but it retriggers every scored card
Not sure how retriggers work, but why not use pseudorandom_element for choosing a card?
if context.before then
-- Select one before anything happens.
card.ability.extra.targetcard = pseudorandom_element(context.scoring_hand, pseudoseed('rngseed'))
end
if context.cardarea == G.play and context.repetition and not context.repetition_only then
if context.other_card == card.ability.extra.targetcard then
-- we pass the check for the earlier randomly chosen card, repeat!
end
end
if context.after then card.ability.extra.targetcard = nil end -- cleanup.
-# some stuff may be wrong, have not yet had any breakfast.
Mmh, that seems cleaner
Thank you
Hi, new to modding, why is the game crashing on load here and how can I fix it?
main.lua :
require "neuro_socket"
Is that your entire main.lua?
Use SMODS.load_file
it's hard to align these, there's some sort of distortion for the positions, i wonder what offsets these position values
xp? which mod is that?
thanks
i want to make a joker that creates a soul card when sold; how can I do this? thanks
SMODS.add_card{key = 'c_soul'} if context.selling_self.
what does implementing this look like
im not familiar with hooks 
local oldsetcost = Card.set_cost
function Card:set_cost()
local g = oldsetcost(self)
if self.config.center.key = "j_modprefix_key" then self.cost = 0 end
return g
end
i think this suits well
how would i force this selected card to be always highlighted
thanks 🫡
tysm!
this is to go in the calculate function, right?
Outside entirely.
ah 
You do G.hand:change_size(number) at the start of the round then you do G.hand:change_size(-number) at the end of the round.
okii
which context thingy triggers at the end of the round
context.end_of_round and context.main_eval
thank u :3
trying to see if there's a better way of implementing this without it stacking infinitely
the super hacky way i did this was to set the value to a variable value, then set that variable value to 0
this works fine if only two jokers are involved (and if i'm not doing discards, trying to do discards works at the cost of your ears), but if i want to implement three or more then i'd have to make hundreds of if statements to call for every possible combination 
i'm basically trying to replicate abstract joker's effects with specific jokers in hand instead of any joker
So you want this joker to give chips for the amount of certain jokers?
correct
Wouldn't it be card.ability.extra.chips = numberofchipsforeach * (#SMODS.find_card("j_modprefix_key") + #SMODS.find_card("j_modprefix_key2"))?
lemme try that 
you're an actual legend
thanks much 
i'll just have to scrap my +discard idea because it's bad and a pain to code, i'll just do something else lmao
is this card both negative and foil???
did i do somethign wrong?
and somehow it doesnt increase the joker slot count?
it's not negative. It is, however, showing the description for what the negative object does. What's your intent here?
kinda like stardust, always make it show up negative
What's the context thing I would need for a Joker to trigger after the cards have finished dealing
As in like
Before you select your cards but after the cards are finished drawing
I know there's context.first_hand_drawn
context.hand_drawn?
IS THAT GREED FROM BLOCKTALES??
im working on adding the block tale emotions in as boss blinds, here's fear https://cdn.discordapp.com/attachments/1209506360987877408/1376850921392443442/20250527-0911-51.6925400.mp4?ex=68382558&is=6836d3d8&hm=fb9a3e9ada953101440ed06e96e89bd936955949452dc79b43e71bb4968ba36e&
updated the video i replied with that's more up to date
holy shit thats so creative
lol
Hey guys, I am making a custom seal, why is this happening?
Code?
this is what is at functions/misc_functions line 1891
config = { extra = { xmult = 2} },
key = 'spoogie_seal',
atlas = 'SpoogieEnhancers', pos = { x = 2, y = 0 },
sound = { sound = 'woof_sound', per = 1, vol = 1 },
discovered = true,
loc_txt = {
name = 'Spoogie Seal',
label = 'Spoogie Seal is le epic'
},
calculate = function (self, card, context)
if context.main_scoring and context.cardarea == G.play then
return{
xmult = card.ability.extra.xmult,
}
end
end
}```
that's my seal
I have a feeling it is the calculate function
The sound needs your mod prefix.
forgot about that
that didn't fix it
it crashes when I hover over it in the collection
maybe a loc_txt error
You need text in loc_txt
oh wait I don't think I included text
I realized that right before you sent that lol
How do I calculate the seal bonus?
With calculate?
Some other mod I am looking at uses calculate_seal
Yes.
No, it's basically the same.
Ok
My thing is crashing, so I am asking
There must be something wrong with this
(Same result with card = context.other_card gone), idk why I added that
Seals would be card.ability.seal.extra.xmult I think.
ah, didn't know that, and the wiki is not very helpful about it
Question
is there a function that gives the word form of the rank of a card
As in giving like "Jack" instead of "11" for example
card.base.value
o
thanks
This appears to crash
Idk if I'm doing it right
calculate = function(self, card, context)
if context.first_hand_drawn then
local eval = function()
return G.GAME.current_round.discards_used == 0 and not G.RESET_JIGGLES
end
juice_card_until(card, eval, true)
end
if context.discard and not context.blueprint and G.GAME.current_round.discards_used <= 0 then
card.ability.extra.destroyed = #context.full_hand
G.hand.change_size(card.ability.extra.destroyed)
return {
remove = true
}
end
end
It's G.hand:change_size
I am trying to remove a diamond card played and add 1 to mult
But it crashes
Here is the code: calculate = function(self, card, context) -- Tests if context.joker_main == true. -- joker_main is a SMODS specific thing, and is where the effects of jokers that just give +stuff in the joker area area triggered, like Joker giving +Mult, Cavendish giving XMult, and Bull giving +Chips. if context.joker_main then if context.before and not context.blueprint then return { if context.other_card:is_suit('Diamonds') then mult = card.ability.extra.mult, -- This is a localize function. Localize looks through the localization files, and translates it. It ensures your mod is able to be translated. I've left it out in most cases for clarity reasons, but this one is required, because it has a variable. -- This specifically looks in the localization table for the 'variable' category, specifically under 'v_dictionary' in 'localization/en-us.lua', and searches that table for 'a_mult', which is short for add mult. -- In the localization file, a_mult = '+#1#'. Like with loc_vars, the vars in this message variable replace the #1#. message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } } message = 'Upgraded!', colour = G.C.MULT, card = card, remove_from_deck = function(self, card, from_debuff) -- Adds - instead of +, so they get subtracted when this card is removed. G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discard_size, G.hand:change_size(-card.ability.extra.hand_size) end end } end end end }
Here is the crash log:
Is : for methods and . for fields I guess
wdym?
ehh it's more like . is for static methods
but : is for everything that takes self
G.hand:change_size(amount) is the same as G.hand.change_size(G.hand, amount)
ohhhh
interesting
Wouldn't it be CardArea.change_size(G.hand, amount)?
it's a little tricky to get used to 
ok so basically i found out that this bit of code is found on overrides.lua on cryptid
which is bad cause i have no idea what any of it means
?
which is line 142?
You can add a set_edition to the joker's set_ability
Which will always spawn it as that edition
the first if
i think you cant put ifs inside return functions
check for them outside
joker_main is not an SMODS specific thing?
I got that part of the code from the SMODS example thing i think
but now it does not crash thx
hi this is my first time modding balatro but after I did the installation this error came up?
do i have to put it in as a return of the function?
wait nvm it works
key = 'thirtytwo',
loc_txt = {
name = '32',
text = {
'Destroy Cards with Suit {C:diamonds}Diamond{} and add 1 to {s:mult, C:red}Mult{}'
}
},
config = { extra = { mult = 0, mult_gain = 1 } },
-- loc_vars gives your loc_text variables to work with, in the format of #n#, n being the variable in order.
-- #1# is the first variable in vars, #2# the second, #3# the third, and so on.
-- It's also where you'd add to the info_queue, which is where things like the negative tooltip are.
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
-- Sets rarity. 1 common, 2 uncommon, 3 rare, 4 legendary.
rarity = 1,
-- Which atlas key to pull from.
atlas = 'thirtytwo',
-- This card's position on the atlas, starting at {x=0,y=0} for the very top left.
pos = { x = 0, y = 0 },
-- Cost of card in shop.
cost = 0,
-- The functioning part of the joker, looks at context to decide what step of scoring the game is on, and then gives a 'return' value if something activates.
calculate = function(self, card, context)
-- Tests if context.joker_main == true.
-- joker_main is a SMODS specific thing, and is where the effects of jokers that just give +stuff in the joker area area triggered, like Joker giving +Mult, Cavendish giving XMult, and Bull giving +Chips.
if context.joker_main then
if context.before and not context.blueprint then
if context.other_card:is_suit('Diamonds') then
return {
mult = card.ability.extra.mult,
-- This is a localize function. Localize looks through the localization files, and translates it. It ensures your mod is able to be translated. I've left it out in most cases for clarity reasons, but this one is required, because it has a variable.
-- This specifically looks in the localization table for the 'variable' category, specifically under 'v_dictionary' in 'localization/en-us.lua', and searches that table for 'a_mult', which is short for add mult.
-- In the localization file, a_mult = '+#1#'. Like with loc_vars, the vars in this message variable replace the #1#.
message = 'Upgraded!',
colour = G.C.MULT,
card = card,
remove_from_deck = function(self, card, from_debuff)
-- Adds - instead of +, so they get subtracted when this card is removed.
G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discard_size,
G.hand:change_size(-card.ability.extra.hand_size)
end
}
end
end
end
end
}```
Sooo, I have this code, what it should do is destroy any played diamond cards and add 1 to mult, but it does nothing. Does anyone have an idea?
context.joker_main and context.before and context.other_card do not happen at the same time.
oooh, ok so I removed the context.before and now it crashes heres the log:
context.other_card still doesn't exist.
huh
Just to fix a little oopsie I had here uhh
How do you make sure that it's specifically you discarding and not the boss blind
and not context.hook I think.
o
thanks :>
so how do I instead look for a specific suit that is being played?
context.individual
context.other_card:is_suit('Hearts') is what I used
gotta put card = context.other_card in return tho
No?
idk I just used the example thing
I did modify it
so maybe context.other_card isn't needed anymore
i think im done
this is incredibly cool
is there a way to make each repetition a probability check?
i want to make a joker that has a 1 in 4 chance to give x1.5 mult each retrigger (max 10 times, hence the retrigger cap)
i just realized i typo'd retrigger cap so ignore that lol
What should I do from here? I can't seem too find how I check the seal from that
nevermind i might've found an extremely hacky and ugly way to do what i want
truly
How do I add a seal to a card through a consumable?
You need to check the context then check the chance.
so do it the other way around, yeah?
Yes.
why doesnt smods.sound work?
add your mod's prefix to the play_sound call
you need to add mod prefix
and how do i do that?
eg play_sound("ModPrefixHere_SoundName")
yes
is your sound file in assets/sounds?
yeah
alr then ill test it
just checking
you're welcome
anyways, does anyone know how to add a seal through a custom consumable?
card:set_seal("modprefix_sealkey")
thank you
How do you do RNG stuff exactly
Like if I have a "1 in 2 chance to do so and so" thing
?
I do it with pseudorandom()
like here calc_dollar_bonus = function(self, info_queue, card) return pseudorandom('seed', -15, 15) end
Have an example https://github.com/nh6574/VanillaRemade/blob/6bb8d3df89a1b2af17280ba8b52a902729d66f58/src/jokers.lua#L2459
Contribute to nh6574/VanillaRemade development by creating an account on GitHub.
if card.seal == "modprefix_sealkey"
-15 to 15?
if pseudorandom('vremade_hallucination' .. G.GAME.round_resets.ante)
wait is that a seed
Yes
i don't think I've ever seen a string as a seed before
Someone's sent an example but to explain how it works simply, you basically just represent your chances as a decimal (eg 0.5 for you), generate a random decimal number, and do something if the random number is below your chance
yea
I don't really understand the whole question mark reaction thing
If you have a problem with smth I've said, explain it to me
I'm just trying to explain things to the best of my knowledge and if I've made a mistake just point it out so I won't make it in the future
i mean your explanation seems pretty standard as far as how rng typically goes
Yes, but most of the time you should be doing G.GAME.probabilities.normal / number Instead of a decimal.
I'm aware of that, it's shown in the example someone else gave
But I'm not going to assume their level of knowledge so I was just summarising what it actually means

definitely totally unrelated question (i will stop flooding this channel with questions eventually I promise)
how do you add additional temporary hands
I saw some ease_hands_played() function in the vanillaremade thing with burglar but wasn't sure if that did everything because there was other code
that's for temporary hands yes
Okii
Sooo, I am trying to make a joker that needs a specific suit to trigger (in this case diamonds) How can I see what suit is being played?
somebody already explained it i think
is this an effect that applies to individual cards?
for example jokers like the greedy joker give mult per card
if context.before and context.cardarea == G.play and G.GAME.current_round.hands_played == 0 and not context.blueprint then
if pseudorandom('silverchariot' .. G.GAME.round_resets.ante) < G.GAME.probabilities.normal / card.abilities.extra.odds then
ease_hands_played(1)
end
end
I don't appear to be using it correctly because it doesn't work ;-;
while other jokers check if your hand contains specific suits rather than being per card
what actually happens
nothing, even with Oops All Sixes to guarantee it
where is the explaination?
remove the cardarea check
below your original question
anyway can you answer my question so i can understand the effect you wanna make
I want to check if the played card is a diamond, if that is the case the card should be destroyed and the joker gains 1 mult
i love miles edgeworth from ace attorney
yaoi jumpscare
How do you get the amount of cards selected?
(And how to use can_use for consumables)
#G.hand.highlighted
#G.hand.highlighted?
You need the #?
my game crashes if I use that and play a diamond calculate = function(self, card, context) -- Tests if context.joker_main == true. -- joker_main is a SMODS specific thing, and is where the effects of jokers that just give +stuff in the joker area area triggered, like Joker giving +Mult, Cavendish giving XMult, and Bull giving +Chips. if context.joker_main and not context.blueprint then if context.other_card:is_suit('Diamonds') then return { mult = card.ability.extra.mult, -- This is a localize function. Localize looks through the localization files, and translates it. It ensures your mod is able to be translated. I've left it out in most cases for clarity reasons, but this one is required, because it has a variable. -- This specifically looks in the localization table for the 'variable' category, specifically under 'v_dictionary' in 'localization/en-us.lua', and searches that table for 'a_mult', which is short for add mult. -- In the localization file, a_mult = '+#1#'. Like with loc_vars, the vars in this message variable replace the #1#. message = 'Upgraded!', colour = G.C.MULT, remove_from_deck = function(self, card, from_debuff) -- Adds - instead of +, so they get subtracted when this card is removed. G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discard_size, G.hand:change_size(-card.ability.extra.hand_size) end } end end
Yes.
no
just checking, the thing is whining about commas
this is in the docs btw
I don't know where to look
can_use has no explination in the docs as far as I know
that I can find
can_use returns a bool
use doesn't return anything
I have seen that bit
i don't think it needs more explanation than that
yes
card:set_seal("sealkey")
Where do I put it tho?
I put in in use, and it didn't work
I did include the prefix
whats the crash
card is referring to the consumable.
card is the consumable in that case so you're giving it a seal and then immediately destroying it
I forgot that card refered to the consumable
so I would need to set card to the selected cards
G.hand.highlighted?
you need to loop through that list yes
hi, im new to modding balatro and wanted to make a joker that triggers if played hand is 3oaK and all played cards are hearts, how would I do that? I've already added the joker itself to the game, im just missing to make it actually work
or whatever the word was
What variable has the current chips/mult
I want to set the current chips/mult post-calculation to 0 and then store it in a variable
hand_chips and mult they're globals
hand_chips and mult
o oki
thanks :>
should start for loop with i=0 or i=1? I haven't touched lua before this
i=1
k
"Gives Chips equal to X1.5 of current Chips"
is that a good effect
look at the example i sent
the context should be if context.individual and context.cardarea == G.play and
context.individual is for effects on each card
it would be something like this in calculate
if context.joker_main and context.scoring_name == "Three of a Kind" then
for _, playing_card in ipairs(context.scoring_hand) do
if not playing_card:is_suit("Hearts") then
return
end
end
return { mult = 5 } -- for example
end
the cardarea thing makes sure its only played cards
missing quote after hearts
Just a question, does a # before a list mean the count of the list?
yep coding on mobile is awful
yes, only for arrays tho
ok thanks!
ok, I was wondering what the # was for

