#💻・modding-dev
1 messages · Page 198 of 1
Just add another SMODS.Joker{} in the same file
You can do that
Yep
Oh sweet
cant be stickers put on localization? it has to be with loc_txt?
i doubt it, how it is please?
to put it in your localization put it under misc.labels.modprefix_key
that's for the label only
to put the name and description it goes under descriptions.Other.modprefix_key
Alright something came up so I won’t be able to help for about another hour but I’d still be more than happy to when I can
ill still be up by then
thank you
Why
what did you change in lovejs
all i changed was something to make it fullscreen
also did you end up getting seeds to be identical to love2d balatro
oh yeah for sure i just wanted to change as little as possible between updates
why does this crash the game on startup?
hello! i am making a joker that draws a steel card from your deck after you've drawn cards or would have if your hand was full. i tried using context.hand_drawn, but if your hand is full it does not trigger, and i have not found another context that works with that same timing but regardless of if you've drawn cards or not. does anybody know a workaround/context that works here?
question! how do we change the ratio of a joker's card back, like square joker does? we have one joker that's stubbier than the others and we think it'd be fun if that smaller size appeared properly for amber acorn
G.GAME.probability does not exist on startup, G.GAME is a table of run-specific data
are there any docs?
ty
aure do you have a macro for the smods wiki
I tried using calculate_effect to make text appear when the card dies but it just crashes the game
nah but good idea
so i would move this inside of the joker then?
Is there another way to do this?
I appreciate that you asked about the docs first
so based
depends on what you're doing, you haven't explained that
<@&1133519078540185692>
🔫
ty header
Best thing to do when getting started
phishing links are the bane of my existence
wow i cant believe they giving out steam gift cards 
right you werent here mb
having a joker double the probabilities of a certain consumable (rn it's wheel)
🤑
AW DANGIT
wait why are the mean moderators taking all of the free steam gift cards... 😢
i missed free money
they're hoarding it
im rich yall, buying a lambo rn 🤑
buying ajimbo rn
think of the steam card like an egg
You'd need a specific lovely patch to add directly to card.lua, I believe. I could give you a rough draft if you want?
i forgot to send the code im stupid
$20 steam giftcard giveaway
.com
what the heck is a stencil buffer
I hate this
Has anyone here actually used the love2D stencil functions for a mod? Attempting to find specific examples for balatro, expectedly, leads me to many pages about Joker Stencil
oh I see. I think the most straightforward approach would be to hook Card:use_consumeable to change the probabilities before calling the function and changing them back afterwards
frick I've never even heard of that
Ah damn
i lost my house to 
:(
im still really bad with hooks how would i start setting this up
I'm basically attempting to procedurally create a negative space in whatever texture I pass into it and I should be able to use the built-in stencil functions for that, but I'm getting really weird results probably because of other stuff that's built in to prepare graphics drawing
will continue research
local foo_ref = foo
function foo(params)
local result = foo_ref(params)
... (extra code here)
the idea is that you get the result from the original function and then do some extra calculations and then return the result
I was getting crashes due to sound effects. I think we should not discuss about that topic too much though, at least not here 😅
Yeah I'm pretty sure LOVE has a lot of tools that Balatro doesn't use for this kind of stuff.
local cuc = Card.use_consumeable
Card.use_consumeable = function(self, area, copier)
local odds_mod = 1
for _,v in ipairs(SMODS.find_card('j_mod_yourjoker')) do odds_mod = odds_mod * v.ability.extra.odds_mod end
if self.config.center.key == 'c_wheel' then G.GAME.probabilities.normal = G.GAME.probabilities.normal * odds_mod end
cuc(self, area, copier)
if self.config.center.key == 'c_wheel' then G.GAME.probabilities.normal = G.GAME.probabilities.normal / odds_mod end
end
something along the lines of this
Based off a basic search I don't believe any mod does. Most mods don't touch rendering
flying blind is fun
So i'm trying to make a matador+ luchador hybrid but it doesn't work... if I just do G.GAME.blind.triggered, it increases cur_hands to 3 already, but if i do this, it doesn't increase at all. Any advice?
if context.debuffed_hand then
if G.GAME.blind.triggered then
if card.ability.extra.cur_hands >= card.ability.extra.hands then
if G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == 'Boss')) then
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')})
G.GAME.blind:disable()
card.ability.extra.active = true
end
else
card.ability.extra.cur_hands = card.ability.extra.cur_hands + 1
return{
message = localize("pm_upgraded"),
card = card
}
end
end
elseif context.cardarea == G.jokers and context.before then
if G.GAME.blind.triggered then
if card.ability.extra.cur_hands >= card.ability.extra.hands then
if G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == 'Boss')) then
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')})
G.GAME.blind:disable()
card.ability.extra.active = true
end
else
card.ability.extra.cur_hands = card.ability.extra.cur_hands + 1
return{
message = localize("pm_upgraded"),
card = card
}
end
end
end
then you'd need to setup a custom loc_vars function that does similar things for the wheel so it actually displays
There's a whole Shape API (prob for love.physics)
Somone should add physics to moveables
moveable physics
oh good lord
as opposed to stationary physics-?how does that work
internal potential energy
I'm talking about the physics itself being moveable/stationary
exactly
is it possible to render 3D objects in balatro
Not easily
drop love3d
i mean, ive seen 2D stuff rendering 3D
Pretty sure this (sorta) exists already
drop love4d
would we even be able to comprehend that
no
drop love5dchesswithmultiversetimetravel
peak
loveoopsall6D
cba
hh
what
what
chess battle advanced
hello hello

no i swear i understood what cba was, and totally didnt just send random letters
Is the game able to handle multiple suits per card ? Or should I turn to something like seals to add additional attributes to cards
can you can buy cavendish by having gros michel expire in another run in multiverse time travel balatro
No hut you can take that runs Cavendish and put it in your run
cards can act as multiple suits just fine. but they can only have one base suit
you create another timeline for every lucky card triggered
you would somehow buy both cavendish and gros michel in which case, as there's another timeline when both are hooked to each other, so you brought the two jokers from two different timelines into one
(See wild card)
when glass cards shatter, reality shatters too
cards can also only have one seal, something that can stack is stickers
whats stickers
Like eternal, perishable and rental
extension of eternal perishable and rental
never seen those yet imma look them up but stickers might be what im looking for
idea is adding elements (fire air etc) to individual cards through tarots and whatnot but without taking a seal spot or changing the base suit (tho changing base suit could be an idea)
so stickers could be good
i swear someone added elements before
since they stack
probably
TheAutumn uhh something
yeah you want stickers if they should stack, but be warned they're still a bit jank on steamodded's side
I guess I gotta implement and see what makes the most sense
stickers ?
wheres that from
though its completely fine if you still want to add your ideas, even when they r already done by someone else
its your mod after all lol
with how many people are modding this mf chances are having a totally original idea is slim, so may as well just do your best to incorporate your own idea :D
add a time sticker so i can say by the card of agamotto
i know ive had the same idea as a few other people but it aint stopped me, i just do it a bit diff
Nah I only put original ideas ebeyome steals their ideas from me
grrrrrr
joke tuah
mine is different tho trust, its j_hawktuahgold
mult on that thing
can we close #💻・modding-dev
😭
we could try but it depends who claimed it first
development tomorrow
development pauses tomorrow.
implementing pluey into balatro rn
development continues until morale improves
now thats the spirit
That's the secret cap, as long as there's development there can never be any morale
@sturdy compass 👉👈
Joyous 
I added the patch you showed me to the lovely.toml, i dont really have much context on how it operates so i couldnt do much from there
gotcha
So if I'm interpreting correctly, this joker will increase the number of cards you can choose from Arcana packs?
Mhm
hey will this use the odds_mod? in the return?
Would multiple copies of the card in hand increase it further?
yeah
ok cool
no, it would either change and unchange the probabilities value or just change the variable for the odds by multiplying by it
FYI im not going to allow this to be blueprint compatible
I imagined so
so i'm working on a consumable that draws 2 random diamonds to deck - it's just about fully functional & even properly checks to make sure there are diamonds to draw before attempting to draw each one, sends a message and ends otherwise
issue is that, exactly once per testing session among like 5, one of the cards drawn ended up being a phantom card like this. I have exactly no idea how this is happening
use = function(self, card, area, copier)
local DiamondIsUnbreakable = {}
for _, k in ipairs(G.deck.cards) do
if k:is_suit('Diamonds') then
table.insert(DiamondIsUnbreakable, k)
end
end
local j = #DiamondIsUnbreakable or 0
if j > 0 then
for i = 1, 2, 1 do
if j == 0 then
SMODS.calculate_effect({
message = "No Diamonds?",
colour = G.C.PURPLE,
card = card
}, card)
break
end
local selection = pseudorandom_element(DiamondIsUnbreakable,
pseudoseed('KQSkill'))
if selection then
draw_card(G.deck, G.hand, nil, 'up', false, selection)
DiamondIsUnbreakable = {}
for _, k in ipairs(G.deck.cards) do
if k:is_suit('Diamonds') then
table.insert(DiamondIsUnbreakable, k)
end
end
end
j = j - 1
end
else
SMODS.calculate_effect({
message = "No Diamonds?",
colour = G.C.PURPLE,
card = card
}, card)
end
return true
end,
...
Ok try this on for size. Replace anything you might want
# Apply modifier to pack choice
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "G.GAME.pack_choices = self.ability.choose or self.config.center.config.choose or 1"
position = "after"
payload = '''
local cards = SMODS.find_card('YOUR JOKER KEY') -- local variable name can be changed
if self.kind == 'Arcana' and next(cards) then
G.GAME.pack_choices = math.min(G.GAME.pack_choices + #cards, self.config.center.config.extra)
end
'''
match_indent = true
times = 1
will do
so what do you mean exactly by doing the same thing for the wheel? im lost there
To give you a more technical explanation, "cards" holds a table of cards that are in your hand and match the given key. Afterwards, it's checking if the pack being opened is of kind 'Arcana' and if "cards" is actually populated. If both are true, it will add #cards to G.GAME.pack_choices. There's also a math.min that makes it so the choice count can't go over however many cards are in the booster
I'm currently programming a Boss Blind that will generate 3 Cursed (will always harm you in some way) Jokers on blind selection. Problem is, it keeps on spamming Jokers after selection (quickly spawning Jimbos instead cause there are only 4 Cursed Jokers, 3 in Cryptid, one made by me), where it should just spawn 3 on select. Is there a method to avoid repeating this function or is Spawning Cursed Jokers out of the question for Boss Blinds outside of Hooks or Patches? Here's part of the code for the Boss Blind:
SMODS.Blind{
key = 'unik_purple_pentagram',
boss = {min = 1, showdown = true},
atlas = "unik_showdown_blinds",
pos = { x = 0, y = 0},
boss_colour= HEX("7b00ff"),
dollars = 6,
mult = 2,
config = {},
set_blind = function(self, reset, silent)
if not reset then
G.GAME.unik_killed_by_pentagram = true
for i = 1, 3 do
local card = create_card("Joker", G.jokers, nil, "cry_cursed", nil, nil, nil, "unik_pentagram_curse")
card:add_to_deck()
G.jokers:emplace(card)
card:start_materialize()
G.GAME.blind.triggered = true
G.GAME.blind:wiggle()
end
end
end,
I'm saying take ownership of the wheel of fortune and give it a custom loc_vars function that changes the odds variable
ok that's the part i dont get
taking ownership i mean
how do i make consumable set not give Jimbo by default when nothing is valid in the pool
it made 3 no issue
why did i laugh at that 😭
i won't lie it was incredibly funny
Not sure if exactly related, but I think checking for next(DiamondIsUnbreakable) and doing a k, v loop might be a much more efficient way of going about this. Something tells me the phantom card has something to do with the janky "loop?" thing you've got going on
never in my life have i seen so many jimbos
imagine there really was a boss blind like that, and the description is just
"Annihilate your PC"
suppose I could try that
In my case, it should just spawn 3, not spam much more after selection endlessly (as funny as it looks initially)
should I just use hooks/patches to manually add a one-time function linked to this or can it be (somehow) done just inside SMODS.blind?
Use logging to log deck state when determining it can pick a card
okay, that was not a good idea - next() doesn't exactly return a key like i need it to
I'm pretty sure set_blind isn't supposed to run continuously?
im on phone so i cant read your code 😭
i think that it's somehow getting a null reference and drawing that
which... shouldn't be possible?
stale reference more like
How exactly were you using it?
it iterates through every diamond in the deck and adds that to an array, then it randomly selects one diamond from this array and draws that card
after drawing a card, it completely remakes the diamonds array such that it won't include the one that was just drawn, just as a failsafe
what i'm failing to understand is how at any point it's drawing an invalid card
Yeah this function normally runs only once. Try updating steamodded and disabling other mods and see if it still happens
are you able to have it print an entire array...?
that'd be sick tbh
You could iterate through array elements and print them...
see https://github.com/Steamodded/smods/wiki/Utility for some funcs that can stringify a table
would not be too hard but i am overwhelmingly lazy 
I'd also like to mention I am very annoyed every time I have to code in a language that doesn't even have a function like that built-in
i'll do it
a += 1
the only language i learned before this was c++ so believe me i understand how you feel
function Utils.tableToString(tbl, indent)
if not indent then indent = 0 end
if type(tbl) ~= "table" then return tostring(tbl) end
local str = ""
for k, v in pairs(tbl) do
local formatting = string.rep(" ", indent) .. k .. ": "
if type(v) == "table" then
str = str .. formatting .. "\n" .. Utils.tableToString(v, indent+1)
else
str = str .. formatting .. tostring(v) .. "\n"
end
end
return str
end
sendDebugMessage(Utils.tableToString(), "Logger")
i got that. should work ?
though tis for tables
Lua doesn't have arrays, strictly speaking
the built-in ones should also be good enough for 99% of use cases
its all tables
:3
(╯°□°)╯︵ ┻━┻
TETO
banger
the observer is judging you
what do the redstone jokers do?
they allow joker to the right to function
not exaclty redstone
these are individual component
looks like redstone
sorry for taking so long to respond something came up
ur fine
i tried this with multiple keys but it doesnt seem to be working
i tried the one i use for localization "j_snaz_tealeaves" and the one from the joker itself "tealeaves" but neither worked
the first one should be the one you use. Can I see the edits you've made?
Also try self.config.kind instead of self.kind
i dont think i changed any after i changed the name itself
nope, doesnt work
hmm
do i need to add something to the joker itself?
no you should be fine with just this
Take a look in your logs, double check that the patch is being applied properly
try self.config.center.kind and definitely use j_snaz_tealeaves
I just bruteforce that stuff
real
💯
@sturdy compass works perfectly!
hell yeah
oh, it was self.config.kind? nice
@sturdy compass if i wanted to do something similar but for pack size, how would i do that? you said pack choices is a custom variable so im not sure how exactly that fits into the packs changing?
I said choice_mod was custom, pack_choices is vanilla
Finally fixed it -- so for some reason, draw_card must have some kind of delayed "remove from deck" effect, which I was relying on. I added an and k ~= selection condition to the diamond array loop directly below draw_card and now it works perfectly as intended!
so it would be pack_extra for increasing the size of it?
Ah that'll do it. Event timing are wonky
Lemme check rq
Ok no, the variable you'd want to change to modify pack size is self.ability.extra, and do that before changing pack_choices
np
reposting this, would really appreciate some help on this 🙏
why is this crashing?
yes
baaaaaaaaack!
wb
Logs?
Tyty
Yeah that's not an atlas issue. It looks like one of your blind colors are not properly defined
hokai, still trying to figure out the error, and i think it's here:
elseif context.remove_playing_cards and not context.blueprint then
local count = 0
for k, v in ipairs(context.removed) do
if v:is_suit("Diamonds") then count = count + 1 end
end
if count > 0 then
card.ability.extra.current_xmult = card.ability.extra.current_xmult + (card.ability.extra.added_xmult * count)
return
{
message = card.ability.extra.current_xmult,
color = G.C.RED,
card = card
}
end
end```
specfically here:
elseif context.remove_playing_cards and not context.blueprint then
local count = 0
for k, v in ipairs(context.removed) do
if v:is_suit("Diamonds") then count = count + 1 end
end```
does it stop happening if you remove that code
what's your error again?
_ _
^
lemme give that a go
your message isn't a string
that's why it's complaining about the string being a number
...oh =w=
I was wondering if that was the case
where's the code that did work?
if context.cards_destroyed and not context.blueprint then
local count = 0
for k, v in ipairs(context.glass_shattered) do
if v:is_suit("Diamonds") then count = count + 1 end
end
if count > 0 then
card.ability.extra.current_xmult = card.ability.extra.current_xmult + (card.ability.extra.added_xmult * count)
return
{
message = card.ability.extra.current_xmult,
color = G.C.RED,
card = card
}
end```
also yaaaaa it works now! :D
thanks ^^
probably some jank with adding 0 to a number
oh observing how it acts now, it didn't work before, but it didn't crash
It probably "worked" because return was never triggered
I don't think context.glass_shattered ever triggers
i've observed it triggering just now
oh actually yeah it says > 0
huge
confused as to why it's in yellow though, did i get the wrong colour name?
oh ya nevermind i did =w=
yeah glass_shattered isn't a thing
so your count never incremented
which is why it wouldn't crash
i'm so used to using the american spelling that i forgot how it should be spelled :)))
colour 
there is no bug.
if it wasn't it'd crash by passing nil to ipairs
isnt glass_shattered a vanilla thing
oh yeah you're right, i was mistaken somehow :P
yeah it most definitely is a vanilla thing
and its used for canio
yeah but smods removes it
oh
hey, i'm trying to make a challenge where you start with 5 debuffed stencil jokers and from ante 2 onwards, beating a boss blind will undebuff one - but i'm having trouble trying to detect that the challenge is active to trip my (un)debuffing code? because checking for G.GAME.modifiers.(my challenge id) doesn't work, so i don't know what variable i can look at to see the currently active challenge
does anyone have any advice
G.GAME.challenge
...i see.
and do i check that to see if it's equal to my challenge's id?
exactly
actually, context.glass_shattered isn't even a vanilla thing from what I see in my local code
maybe glass_shattered is the friends we made along the way
exactly
oop you already got a response
my bad
it is
aight i wanna try to implement this challenge... think i chose something a wee bit complex for my first attempt at one tho lol
it isnt
it's never created and sent to the calc functions
theres lots of remnants there that don't exist anymore

must be a timing issue then
...does it double straight from ante 1
i have a joker that creates and destroys glass cards in one hand
but that didn't trigger my other joker
yeah but you get a free legendary to start with
i can also just make it lik 1.5x or smn
if i can even figure out how to implement it
start simple
I feel like adding a multiplicator to score amount is the simplest (The Wall exists)
oh and it doesn't crash from the nil table in ipairs because context.cards_destroyed also isn't a thing that exists
i think the joker that creates and destroys the glass does that in joker_main, but my other joker also scores there
i have a different one that just gives money and doesn't score, and it works
ohhhhhh so i guess it's returning before it's incremented itself
right. ughhh.
whats the intended effect?
glass created > Eraser gives XMult > glass breaks > Eraser upgrades > Coiny gives money
what actually happens:
glass created > Eraser gives XMult > glass breaks > Coiny gives money
oh no it triggers here instead [Blocky]:
if context.destroying_card and context.destroying_card.ability.name == 'Glass Card' then
also it's weird that Coiny gives his money before the cards break
context.destroying_card is for marking cards as destroyed
lemme take a recording
not for them actually breaking
ah =w=
use this to check for destroyed cards
key = 'bearmarket',
loc_txt = {
name = 'Bear Market',
text = {
"{C:green}#1# in #2#{} chance to give {C:money}$#3# {}at",
"the end of round",
"{C:red}SELF-DESTRUCTS{} in #4# rounds"
}
},
config = {extra = {odds = 2, dollars = 1, extra = 4}},
loc_vars = function(self, info_queue, card)
return { vars = {(G.GAME.probabilities.normal or 1), card.ability.extra.odds, card.ability.extra.dollars, card.ability.extra}}
end,```
is there any existing var similar to `card.ability.extra` that can be used to just store a value that counts down? i can't use `card.ability.extra` because it then displays as a table when playing.
oh i'm already doing that in both jokers
Blocky uses it to actually destroy the cards
if context.destroying_card and context.destroying_card.ability.name == 'Glass Card' then
G.E_MANAGER:add_event(Event({
func = function()
if card.ability.extra.will_play_sound then
play_sound("bfdi_blocky", 1, 0.75)
card.ability.extra.will_play_sound = false
end
return true
end
}))
return {remove = true}
end```
your values in config within your joker definition are the initial values of the actual card which are stored in card.ability
So anything you put in config will be in card.ability and will be stored along with the joker
So what I'm saying is... just add another value to extra which is the counter you want
ah, so adding smth like countdown = 4 as the 4th value in extra will make #4# pull 4?
Not at all
That is entirely based on the order you return values in loc_vars
So if you wanted a countdown in your card do something like config = { extra = { whatever else was here before, countdown = 4 } }, then in loc_vars you pass card.ability.extra.countdown
oh damn i can call a card.ability whatever i want? i misinterpreted card.abilities as smth the game already had defined and that you had to pull from an existing card.ability or make a new one yourself in a directory somewhere.
got it, makes sense now. tysm!
yea its just a table
i pull a lot of my programming/modding knowledge from emerald-decomp, where if you wanted to add a var that was pulled universally you needed to add it to a #globals directory.
besides im pretty sure you can add whatever you want to any table in the game
that's super sick
(cause lua)
lua goated
okay got it working! i reordered everything, and used a status text call instead of a return
thanks!
hey so uh i assume you can make your own custom rules for challenges? what's the best way of going about it
Where would I figure out how to affect the editions of cards that show up in the shop?
Looking at existing challenges
rules = {
custom = {
{id = 'debuff_all'}
},
modifiers = {
{id = 'dollars', value = 8},
}
},
i mean yeah but where do i actually implement the rule
the custom thing doesnt do anything by itself... its just for you to use, and also to create a text reference to insert text
https://github.com/ascriptmaster/Balatro-Nihility/blob/main/nihility-1.0.0.lua this makes use of custom
Contribute to ascriptmaster/Balatro-Nihility development by creating an account on GitHub.
so the custom doesnt really matter by itself (unless you attach a value), you just write code for the challenge itself
Like, similar to how Astronomer would affect the prices of an item in the shop? I'm brand new to even attempting to mod this game so I want to try and make something relating to this as a test card
i think that might be a bit complex for a first card
That's sorta what i'm going for yea
like usually i'd recommend trying out a classic mult type joker to get used to working with the smods framework
then you can go for more original stuff when you get a grasp of whats possible
You can also use code pathcing with lovely.toml or hooks directly to add any custom code you might need
as a beginner that might also be a bit much unless you have good experience with programming other stuff
so i guess if you feel confident go for it
I don't think what i'm going for is particularly too complicated
It's just something I want to do where I check for a specific card in a shop and if it's there then I want to change it's edition
(protip: you are allowed to look at other mods source code. cryptid does a lot that can be used as template)
(cryptid also does a lot that you should not use as template)
maybe dumb quetion but whats the context steel cards score in? im trying to make an enhancement that gives an effect while its held in hand like steel cards
context.individual and context.cardarea == G.hand i think
does anyone have the structure of a joker as it appears in the G.jokers.cards table?
for some reason, G.jokers.cards[#].key is always nil despite there being jokers present and i feel like i'm doing something wrong
haven't checked in a bit but try G.jokers.cards[#].config.center.key
...ahhhh
thanks
yeah the structure of cards is a bit of a maze sometimes
it's because a card object is made up of a lot of different things
sadly this does not work
i think that might work for a joker triggering on cards in hand but not enhancements
oh wait ur doing an enhancement mb
that i am
if context.main_scoring and context.cardarea == G.hand then
iirc
yea i havent worked with enhancements before but readin thru the wiki and i was about to suggest that
i think it should work
if context.cardarea == G.hand
ah yes thats it thank you
no worries
But if you want a steel card enhancement-like thing, steel cards set h_x_mult in card.ability
but i guess you want custom stuff
calculate gives you more control
true
Lemme reword this a bit, I want it so if I HAVE a specific joker then a specific joker in the shop will change it's edition when it appears, if anyone can help w this
How would I do ^2 mult/chips in my joker code?
Edit: it’s Emult_mod and Echip_mod
chip amount = chip amount * chip amount, mult = mult * mult
Okay how do I set them? Do I just return them?
im pretty sure emult exists now doesnt it
not sure for chips though
I don’t think that worked.
Also how would I get the chips/mult amount? I’m not exactly sure how.
GAME.current_round object
(i believe0
game.current_round.current_hand.mult and game.current_round.current_hand.chip_total
what the fuck have i done
alr I’ll check
pairs vs ipairs moment
tell that to the base game code
like i have no idea where the fuck this came from
current_round is nil apparently
all i know is it's caused by me adding this to my localization table
its a table but it should be nil during a round
also theres a g.
ah okay well I need it during the round to calc mult
oh okay
Anyone to help ? I'm trying to figure it out via reading other things but nothing I can find seems to tackle this
i forgot the brackets ... 
why is my challenge called ERROR
no title ?
check your loc_vars
did i write somethin wrong
*loc_txt
im using a localization file rather than loc_txt
ok well I thought you still needed to do that iirc?
not with a loc file no
ah oke
you do need loc_vars for dynamic variables & colors & info cards
Also, I think I was wrong on the mult variable. the one I linked you was for the hand type being played, the mult amount is calculated and changed dynamically when evaluating play
in G.FUNCS.evaluate_play thats where joker effects (and card effects) are applied, updating local variable mult... you'd have to use lovely toml code injection stuff to mess with it I think ?
how do i hook into card functions? I wanna do something like
local get_chip_mult_ref = get_chip_mult
function Card:get_chip_mult()
local result = get_chip_mult_ref()
but i don't think that's how it works. if I do
local get_chip_mult_ref = get_chip_mult
function get_chip_mult()
local result = get_chip_mult_ref()
then it doesn't do anything
it's c_modkey_key
you need to include the original functions variables plus a "self" variable at the very start
so like
local get_chip_mult_ref = get_chip_mult
function Card:get_chip_mult(self)
local result = self:get_chip_mult_ref()
Card:get_chip_mult() is the same as writing Card.get_chip_mult(self)
there you're passing 2 self
also wrong lol self doesn't have a get_chip_mult_ref
Wait you can reference functions from Balatro's code in your mod like that? How do you do that
incredible showcase of my thinking skills
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
I'm not sure why the game crashe dhere. It said that it expects a '}', but the } is at the end of the code. Does anyone here see the problem?
missing a comma after loc_txt
Ah, that'd do it
yeah
Me when I'm trying to make a Joker that modifies booster packs in a similar way to Cryptid but lovely says theres no match 😦
target = "card.lua"
pattern = "G.GAME.pack_choices = self.config.center.config.choose or 1"
check the lovely dumps
bruh i knew i was forgetting something
this might be one of the recent booster changes
I see that the set cost function uses #find_joker('Astronomer') > 1 to check if you have Astronomer in your current joker slots, right? Is there a way to check what Jokers are in your shop however
iterating through G.shop_jokers probably
So how would I check a joker's name through that?
remember the mod prefix
and class prefix
(My experience in this is very low)
for _, card in ipairs(G.shop_jokers.cards) do
if card.config.center.key == "j_key" then
check by key, not by name
congiof
But i'm looking for one specific joker?
im bad at typing
And the game itself checked a joker by 'Astronomer' up here
thats a
ism
Ahhhh gotcha
will cause issues if multiple mods have a joker with the same name
also name isn't a required parameter in smods
here
Ah gotcha it's the translation key
yeah
gluttenous joker my beloved 
anyone has the show the crash log sticker
The crash log has my name in it 💔
Nah i'll show it I just gotta censor the irl name in it
Log
What I wrote (I expect this to be highly incorrect in every way possible but i'm just not understanding it so far)
yeah, I'm not sure how to do what you want but that's not it
Yeah I definitely knew i'm doing a million things wrong
what do you want to do?
I want to set all Diet Colas to turn negative when they appear if you have the Joker I made
Just as a test
you should be able to do something like that using the shop and booster contexts in a calculate function
Thing is I know nothing about that kind of thing
So this is what i'm using to learn
I have 2 questions, as I'm writing my first Balatro mod.
- How can I find the most played hand (like Supernova), or will I have to track that myself?
- Is there an easy way to force my new joker when I start a new run, or some way to disable other jokers so that I can test it without having to play a run and rely on RNG?
well hooking set edition is almost certainly not the function you should be using to do that
does anyone know why this doesnt work?
Fuck well now i'm lost
Probably hook into set_ability instead
if Card:set_debuff returns true, does that mean a card is debuffed?
just throw it in a calculate function that checks the shop when it loads/rolls
set ability works too
Well that only takes into account if they're in the shop
what if it gets spawned with judgement
for example
that is true
isnt there a context to check if a joker gets added to your joker area
What would I do there though ?
or maybe im confusing it with smt else
I know Nothing quite literally
You can hook into CardArea emplace and check self == G.jokers
I do not think there is one in smods tho
oh, thats a good idea
I don't remember adding one unless aure added it
its probably just me mixing it with the context which adds playing cards
call set_edition on the card if it's diet cola
...that one actually exists right
yes
phew, good to know im not just making up new contexts right on the spot
And how do I check if it's diet cola? And how do I check if I have my custom joker?
you pretty much got it here, you'd just check self.config.center.key and instead of find_joker use SMODS.find_card
just without the loop through shop jokers
I'm trying to write a card that gains +Mult equal to the number of Hearts cards in your deck. Is there a variable in the code that tracks this by default?
So would I put #SMODS.find_card('Negative Cola') or ? ('Negative Cola' is the custom Joker)
Alr!
not afaik
Ah, I see
I'm not sure how to implement that then. Maybe I'll just switch it to where it gains Mult every time a Hearts card enters your hand.
Check how the vanilla jokers do it
like cloud 9
but check for suits instead of rank
Something like this?
Oops forgot to replace the
?
Keep the #?
wait no im stupid and cant read
make sure to properly copy the parameters of the original function
i wonder how i can modify a steel card's X mult 🤔
Also card would not be defined there, use self
So type those three down?
bruh.
also the first then should be an and
in like a joker's ability cause I wanna add to specifically played Steel card's XMult so eventually when they're in hand they multiply more
Alright
set the value in the card's ability table
So this ?
At this point we're just making the code for you lol
actually here i would reccomend SMODS.Joker:take_ownership
remember to call card_set_ability(self, center, initial, delay_sprites) after
Sorry i'm just trying to find out what does what
so kinda like
if c.config.center == G.P_CENTERS.m_steel then c.config.center.config.h_x_mult = c.config.center.config.h_x_mult + card.ability.extra.xmult_gain end
you don't want to modify the center
oh
right, use the ability table like i said
also steel cards update their xmult in the update function so setting their ability won't actually work
since it will get updated like immediately
c.ability.h_x_mult
?
u also prolly dont want to edit the default steel card value
goated it works!
when you hook you need to call the original or it will break the game
Where do I call it?
at the beginning for set_ability probably
So do I just put.. local card_set_ability(self, center, initial, delay_sprites) above the if statement .. ?
no local, you're calling a function
Alr
yeah also depends on whether you want to call the original before or after
I think before ?
Probably before for set_ability
Would this work?
you need to pass self as the first argument when calling the original
Looking at the code, this function seems to be what keeps track of the tally. If I wanted to replicate this in my code, I'd keep the for k,v (G.playing_cards) bit, right? I think the suit equivelant for get_id() would be is_suit(), correct?
So replace "center" with "self"?
correct
Okay yay
i can grant a card h_mult the same way right?
no, just add self before center
card_set_ability(self, center, initial, delay_sprites) ?
yes
also to set the edition you need to do self:set_edition('e_negative')
try it and find out
Crash !
what's the crash
what's the code?
Tis right there
you don't need the = true
Alr
Oh seems I also needed a second end
Is there something I can use to test this joker by giving it to myself or something?
Ty
Also also, if I were to add this to my code, where should I do so? I see this line of code up here too, is this important for my implementation?
no, you probably don't want to do exactly the same as that because it does it every frame
You can do it in joker_main
and in loc_vars so the tooltip updates when you hover
(you don't need anything from the second screenshot because smods already checks for that)
Got it. Like this?
This crash seems to be caused when any Diet Cola card is on screen
Wait no not like that my game crashed
the first sock_mult shouldn't have a comma
and you need to return it in vars
Oh right, I forgot to change that one
and it's card, not self
and you should probably modify something in ability.extra rather than just ability so it stays between loads
it's find_card not find_joker
What do you mean? Also, my game crashed when I tried to hover over the card in my collection.
self is not a card, that's why you have a different parameter called card
how do i change the mult and chip values before totalling
now that it's in extra you gotta do card.ability.extra.socks_mult
i wanna round the mult down to the nearest multiple of six and multiply chips by six right before it gets totaled
no, and h_x_mult is specific to steel cards
For some reason the mult counter isnt right. Did I forget something?
you only put the extra in one place
Oh right
ok yeah makes sense
Nevermind, it turns the diet cola in the collection negative.. but not diet colas from the shop ?
Its working perfectly now! Thank you all so much for the help!
also if you want to do the count there you could use a local variable
how do i get the chip and mult count
It's only turning colas negative if they're in the collection or spawned from debug, for some reason ??
hand_chips and mult
ok follow up how do i set the chips and mult
same
i actually have a library mod that adds custom chips and mult operators
https://discord.com/channels/1116389027176787968/1338044836087070740
just mult
This is what is written, it's supposed to be turning all Diet Colas negative if you have the specific Joker, but it's only turning the ones you can't really obtain negative
And then the one in the collection is negative for some reason
Ended up being easier just to bake it into the shader itself I guess 🤷♀️
The point of the stencil being the skull shape that appears on the replaced joker, so I don't have to make a unique texture for every joker to which it applies
why is this not setting mult to 1
Quick question. I'm writing a card similar to Caino. Do I need to include the if context.remove_playing_cards or am I only supposed to include the for k, val in ipairs()
Is there an easy way to check what hand the cards that are being discarded make?
you do need the context check
Got it
There is a function to update the text that you need to use
Why is this happening ??
update_hand_text or smt
check the code for Burnt Joker
hi, i went out to dinner after posting this, and now i've realized upon returning i just didnt explain what the code is supposed to do? the joker itself starts with a base 30 chips, and gains 3 with every consecutive hand that triggers the Boss Blind. Not only does it not do that, but it doesn't even give me the chips either. Or, if it is, it isn't providing notice. How can i fix this?
that's why im,,, here,,,, because i dont know what went wrong
idk maybe remove your 0 check and do mult = math.max(1, mult - (mult % 6))
I am not sure why mult isn't getting updated but chips are
how on earth do you read your code my friend
oh i didnt know that was a thing
Same I don't know what went wrong with mine either :(
you did say all colas lmao
to make a joker give chips you need to
return { chips = value }
Well yes but it's turning the wrong colas negative
The ones in the collection and the ones spawned by debug, but not the ones in shop or pack
very helpful jokerdisplay from me
thank you for that
huh? i already have that on there last i checked
oh you’re kidding me
was this meant to be a video
it’s outside of the message
also you're using SMODS.calculate_effect instead of returning
also its written like old calc
you reminded me i wrote this while i had old calc oh my god hold on let me update the code itself
Does anyone know exactly how get_straight works? I've been staring at it for like 10 minutes and I have no idea how it's comparing numbers within its IDS array
I'd still really like help on what could have gone wrong as I have quite literally Zero clue

you should take ownership
How so
?
So do I hook create_card, take ownership, or both ?
take ownership is probably cleaner but I've never done it 🙂
Alr
to add extra cards to a custom deck would i just use the create_card thing
use SMODS.add_card
cool
I don't think it does either
thats a base balatro function
i know
still undocumented
some of them are documented at least
like I would have had a much harder time if the UI ones were not documented lol
Is the collection one supposed to be unaffected?
yes
And ones spawned by hitting 3?
ive fixed the chip giving, but it still doesn't gain the chips when i play a debuffed hand. i dont THINK this has to be newcalc updated but i could be wrong.
Yea i'm testing it rn i'm just getting bad luck on rolling one lol
please tell me there's an easier way of doing this
i just want to add 14 6's to the deck
nvm i just got it
just ctrl c with debug mode?
automatically
ah
what's the difficult part
Oh god I didn't know about ctrl + c with debug mode
thats what she said
clearly not when she saw you
i have never seen a woman
thank you
yro'ue
misprint
but yeah do you know what's wrong then? or do you mean you "get it" like you understand what it says
no, I got what you said
no idea what's wrong
can I see the entire joker
are you on pc or mobile
pc
ill just paste then
SMODS.Joker{ --Iscariot/Judas
key = 'iscariot',
config = {extra = {chips = 30, chip_gain = 3}},
rarity = 2,
atlas = 'IsaacJokers',
pos = {x = 4, y = 1},
cost = 3,
unlocked = false,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
ScoreReset = true,
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.chips, card.ability.extra.chip_gain}}
end,
calculate = function (self, card, context)
if context.joker_main and (to_big{card.ability.extra.chips, card.ability.extra.mult} > to_big(1)) then
SMODS.calculate_effect(context.blueprint_card or card, {
} )
return{
chip_mod = card.ability.extra.chips,
message = localize{type = 'variable', key = 'a_chips', vars = {card.ability.extra.chips}},
card = card
}
end
if context.debuffed_hand then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
ScoreReset = false
return {
message = 'Silver!',
colour = G.C.CHIPS,
card = card
}
end
if context.end_of_round then
local blind_keys = {
bl_window = true,
bl_head = true,
bl_club = true,
bl_goad = true,
bl_plant = true,
bl_tooth = true,
bl_pillar = true,
bl_flint = true,
bl_eye = true,
bl_mouth = true,
bl_psychic = true,
bl_arm = true,
bl_ox = true,
bl_final_leaf = true
}
if blind_keys[G.GAME.blind.config.blind.key] then
if ScoreReset then
print(ScoreReset)
return {
message = 'Oops!',
card = card
}
end
else
print(ScoreReset)
return {
message = 'Greedy!',
card = card
}
end
ScoreReset = false
end
end
}
damn im sleepy
youre killing me 😭
remove the SMODS.calculate_effect in context.joker_main
does the message appear when playing a debuffed hand
i think it's just leftover yeah there's nothing in it
which boss are you testing with
the club
if i had a nickel lmao
The calc effect is backwards
and also still old calc
No?
chip_mod is definitely old calc
no?
It’s fine to use chip mod you just have to do the message yourself
yeah i need it for the message
im sorry what
if you use chips it does the message for you
I mean you’re just creating the message yourself anyway you don’t need chip mod
yeah but it's a custom message
its a copy of the default one
it's supposed to be it just
doesnt/
what is to_big{card.ability.extra.chips, card.ability.extra.mult}?
talisman
you havent defined card.ability.extra.mult anywhere
i forgot to change it back to chip_gain....
instead of self?
where are you looking
ok but what do you guys mean by backwards
the effect goes first, then the card
whats this check for
talisman
yeah I got that but why
ignore the mult part i forgot to change it back to chip_gain
You don’t need that check anyway
I'm asking genuinely, I don't understand why you're checking if it's bigger than 1
it makes the things work with talisman
the game crashes without it
prolly cus ur calculate effect is wrong
I'm looking for some help with working in get_straight. The effect I'm trying to get is allowing any Ace or Face card to fill a gap in a straight. This is what I currently have, but it's not being detected as a straight, most likely due to my confusion with how the function is structured in general. Anyone have any ideas?
Are you patching the smods override?
ok but it did the same thing with this guy who functions properly
Helping people mod this game would be so much easier if talisman didn’t exist
well they dont have the broken calculate effect
I didn't realize smods had an override for it 😭
and idk wtf theyre doing
also the conversion function
remove the weird talisman crap and SMODS.calculate_effect(…)
You shouldn’t need to ever check a value is bigger than 1
but then it wont work with talisman
wrong.
wdym "wrong"
what your saying isnt true
This isn’t even to do with talisman
You’re just randomly checking your values are bigger than 1
sooo if you don't have talisman installed it will crash because it's comparing a table with a number?
You’re not comparing them with anything that talisman deals with
talisman changes how mult works so if i dont deal with that itll crash because
yes comparison table with number
so your mod NEEDS talisman to work
is that the error you get when you remove it?
Show me the crash
no
ok
Have you tried that joker without talisman
yes it works fine
I'm getting this error, and I'm not sure whats causing it. Does anyone see the problem?
6
most balanced balatro mod:
removed the to_big thing from the functional joker and tried using it. works fine with talisman enabled.
does a different crash, now. but it’s because of a function someone helped me create for a different joker. (no to_big on scoring joker, no talisman enabled)
6
I'm getting another error. Am I not supposed to use 'context' in this situation?
correct, loc_vars does not get any context passed to it
there's no context in loc vars
I see. So what should I be doing instead for it to do this when a card is destroyed?
update it in calculate
Not do it in loc_vars
Okay
btw the other one you posted before you also had to do the calculation in calculate if you didn't
the hearts one
yes, if you only calculate the hearts in loc_vars it's not going to update unless you hover it
you need to do it in both
that function in question is THIS one, which is used for this effect on a different joker
Do you put this in the if joker_main statement or before it?
right before you use the value
different crash but still an issue
what's in line 268
why didnt i just
if (to_big and to_big(new_mult):lt(to_big(last_mult))) or (not to_big and new_mult < last_mult) then
the first one should probably be Big and blah blah
instead of to_big
to_big is always true because you created a dummy one
replace the to_big's with "Big"?
yeah, not entirely sure but I think that was the tasliman table
has it changed since then?
i dont think so
sorry, I meant only the first one
so just if Big
leave the others as to_big
if (Big and to_big(new_mult):lt(to_big(last_mult))) or (not to_big and new_mult < last_mult) then
if (Big and to_big(new_mult):lt(to_big(last_mult))) or (new_mult < last_mult) then
would i be able to make a new variable to store into the Card class and then use that for later? Cause I want to implement bonus mult specifically for one joker and I think I've seen other mods do something where they make a new variable somehow
no, that's never true because you have a dummy to_big
oh ok
yes it is very balanced its all 6
can you explain what the effect you want is?
For some reason, whenever I use Hanged Man to delete a Hearts card, it doesn't add to the mult. I'm not sure whats causing this
joker_main and remove_playing_cards are not true at the same time
Oh
so i already have it set up where i hook into get_chip_mult() and it'll return the value stored in the new variable i want. All I have to do is just have Card store this new variable in itself then i can reference it whenever i want
i wonder if i can just lovely inject it 🤔
Then am I supposed to put this part before the 'if context.joker.main' part?
thank u bro now the accidental dependence is gone
I assume so. You want to scale the joker in destroy_playing_cards and give the mult in joker_main
Like this?
wait but now the guy the function was made for doesnt work hold on
no, all of it should go in the remove_playing_cards except the event
and you should replace that event with return { mult = card.ability.extra.skull_mult }
Like this?
ok actually im an idiot i just need to get the bonus mult to display on the card tho
remove_playing_cards is correct
joker_main should just have the return I wrote in the other msg
Okay, then if everythings fine I'll just do the same for cards_destroyed too then
Ok now I'm even more confused. I've come up with this but now everything's being calculated as a straight. I probably just have no idea how this SMODS straight override works
what
how do i make this work
never mind it fixed after i held r
you should look into making the editor highlight syntax errors
is there a good definition of what is in context somewhere?
with talisman reenabled. works without it enabled.
based on other examples I've seen thats missing a bit of info
the only info it's missing are very new contexts that you can probably only find looking at the code
or asking here
Anyone know why this is the case? im trying to make a joker that eats other food jokers, it works perfectly when i put in jokers from the main game but does not when I try to effect my own
the keys should be j_modprefix_jokerkey
where's the j_modprefix
damn
bump pls hlep
I want to trigger an action when the most played hand (similar to the Telescope) is discarded, is the most played hand data somewhere accessible?
Is the type of hand being discarded available or do I need to figure out the hand type myself?
but yeah this crashes it now, in conjunction with this calculate effect
calculate = function (self, card, context)
if context.joker_main then
return{
chips = card.ability.extra.chips,
card = card
}
end
if context.hyperfixation_mod_mult_decrease and (to_big(card.ability.extra.chips) > to_big(1)) and not context.blueprint_card then
card.ability.extra.chips = card.ability.extra.chips + (context.hyperfixation_mod_mult_decrease*10)
return{
message = 'Soul...',
colour = G.C.CHIPS,
card = card
}
end
end
oh right i was supposed to send that crash to eremel
the actual crash
you need to calculate both yourself I think
the hand data is in G.GAME.hands and context.discard has context.full_hand
hmm maybe the not was necessary
but not Big instead of not to_big
oh ok
I did not think about how involved this would be to implement when I came up with the concept
The Blank - Triggers a different Boss Blind effect every hand (not compatible with all)
bump
no crash but now he doesnt work
obviously testing this with 
idk what it's supposed to be doing so I can't help on that front
you didnt see?
I don't understand the code
When I tried to use a planet card, the game crashed. I'm not sure what 'juiced_up' is for.
juice_up shakes the card a bit, it's called in card_eval_status_text
You passed self which is not a card to card_eval_status_text
I need to store a value for the full run and reset on a new run, should I store that on the joker itself or is there somewhere better?
