#💻・modding-dev
1 messages · Page 277 of 1
Do you have the lua extension in vscode?
so
what. the. fuck. does. it. want. me. to. fix.
i did not know that
Replacing prefix with your mod prefix.
i am about to just send the lua file and have people figure out what i did wrong that's making the game whine about it
either that or i lose my mind
The lua extension tells you if there are any syntax errors.
sumireko
ok so i know how to make most of the stuff like enhancements, seals, jokers, consumables etc but where do i even start on the code itself? by making the thing i want? by setting something before?
mhm. that helps.
just put the code inside a folder in your mods folder
no yeah, that i already did, i mean like, where do i start in the code itself, what do i do first?
never making a consumable again this took me 2~ days
like that giant code with 8k lines in most mods
what does the board do?
you can just make an SMODS.Joker object and it will work without any other setup other than the .json metadata
okok, ty!
gives the blue bullseye (1 in 3 chance for +50 chips)
ooh, thats cool!
yeah a little
how would i go about adding a joker from another mod to my ObjectType?
i would do something like this
local SMODS_injectItems_ref = SMODS.injectItems
function SMODS.injectItems()
SMODS_injectItems_ref()
v = G.P_CENTERS["j_key"]
SMODS.ObjectTypes["key"]:inject_card(v)
end
but maybe theres a cleaner way
whats v supposed to be
oops wrong code
there sorry, forgot to copy
question for you gamers: is it possible to change the text/name of a joker once it has been bought?
yo, i got an idea, u should add spell and trap cards as consumables
yes
k
ooo could you point me to a resource or example?
for the text you can return set and key in loc_vars
that might work for the name too
if not then you can use generate_ui
ok, cool thanks!
local clubs_pack_inject_hook = SMODS.ObjectTypes.clubs_pack.inject
function SMODS.ObjectTypes.clubs_pack.inject(self)
clubs_pack_inject_hook(self)
self:inject_card(SMODS.Centers.j_ortalab_abstemious)
self:inject_card(SMODS.Centers.j_ortalab_pitch_mitch)
self:inject_card(SMODS.Centers.j_ortalab_basalt_column)
end
this seems to work pretty well actually
ok I updated it to use the new stuff
I still have the same issue of not being able to detect when I'm selling a card and not itself
the calculate for the joker has just this code and when I try selling itself or any other card it always says false
so is there another way of checking for the joker being sold not being itself? (I've tried context.selling_card ~= card and it also doesn't work)
wait what should the atlas be? im a little confused
having a slight issue...
it does not render in game
try context.card ~= card
like he is just gone
if context.selling_card and context.card ~= card then
ty
jim-gone
oh nice it worked! ty!
i have it laid out like this
what am i doing wrong
does the y value need to be negative since it's going into the row below the top one
what are you doing?
pillar john
i just want them to render in game but they're invisible
can you show
odd
what should the px and py be in the atlas? ik what they do but im not sure how i should set it
i don't think anything is wrong with my pos or soul_pos variables
depends on the object but for cards its px = 71, py = 95
here you go
SMODS.Atlas{
key = 'jokers',
path = 'Jokers.png',
px = 71,
py = 95,
-- 2x is 144 by 190
}
basic template for jokers
yeah it should work, make sure each card in your sheet is actually that size
okok! ty
quick thing I found, when using find_card you need to use the full key, j_prefix_key
unrelated to your current issue
jus make sure path is set to the name of your textures png
like this
the -- 2x is 144 by 190 thing is a bit distracting here
you don't need a separate atlas for 2x
dear god please indent your code
wait i downloaded a placeholder and it is 63x93, so i should chance the px to 63 and the py to 93 right?
that's just how discord does it idk
now that i have it downloaded it looks better lol
it'll probably look weird ingame but sure, ideally they're always 71x95 tho
Does context.other_card:get_id() return a string?
number
idk why its as 63x93, i downloaded from here, thought it'd be 71x95
What about for the face cards and aces
Gotcha
thats the literal size of it visually but you need to leave empty space to fill the rest
"undefined global SMODS"
ooh okok
do you have smods installed?
yeah
I loaded it with a different atlas and it worked fine.
here
does anyone know where one could get a data set of the jokers and their effects and all that?
if you make a file that just says sendDebugMessage("hi") what happens
what the
balatro wiki 🙂
what exactly do you need
by accounts this should work
wha
hm like a data file a csv or json. ill even take an xml
undefined global sendDebugMessage
why is mine evil and scary and not working then
huh
can i have a zip copy of your mod tp debug it btter
alright let me bundle it all in a zip rq...
have you installed other mods before?
what's inside Smods
is your atlas the wrong size
yeah, some
it shouldn't be
the atlas looks fine
bunch of stuff
it looks like mine
okay that looks fine
do you want me to dm it to you or
sure
good morning chat
unrelated but does smods still use glass_shattered as a context, or was that lumped into destroying_card?
morning bepis
hi bepis
hi belis
hi craig
hi bella
i think its just context.destroy_card now
destroying a card through context.destroy_card seems to still have the glass shatter effect
can you post the crash log
which is nice
[{
"resource": "/c:/Users/eurea/AppData/Roaming/Balatro/Mods/I might be making a mod/a.lua",
"owner": "generated_diagnostic_collection_name#0",
"code": "undefined-global",
"severity": 4,
"message": "Undefined global sendDebugMessage.",
"source": "Lua Diagnostics.",
"startLineNumber": 1,
"startColumn": 1,
"endLineNumber": 1,
"endColumn": 17
}]
look at me learning hwarhwarhwar
awr awr awr awr
I DIDNT UPDATE MY NAME
if this is an editor warning you can disregard it
editor warning is that little "!" sign right?
yeah you can put SMODS in your development folder if it annoys you
oh okok, ty!
(or rather open a folder with smods in it, dont put smods inside your mod)
hi guys
hiii basil
i just strapped smods and the sorce code to the lua thing in vs code
bells and whistles complete
anyone eversee this before
bringing this back to implement now
just making my game on the godot
baking lighting takes like 3 minutes so i’m just lazing off
different smods versions? or something wrong with the asset file
i want to make a tarot card where you can choose 2 different cards that have different editions (like one king wiith steel and one queen with lucky) and fuse those 2, i would need to make both be destroyed then add one king with the edition that would be steel+lucky to the deck right?
looks like the easier way
at least to me
that would get rid of any other stuff on them but if you're fine with that then yeah
theyre restarting thierpc
yeah thats fine, there will be different jokers for seals and things like righed, eternal and etc
and one to fuse everything from both, but thats for later wwhen i get to spectral cards
so i would need to set the fusion result of all the fusions id want to have (like the editions i would add) first and then do the tarot things right?
the 1x and 2x are diffrent
when you turn on pixel art smoothing they stop rendering
i keep mine off
Then there must be something wrong with the 2x file.
calculate = function(self, card, context)
if context.before and not context.blueprint and not context.retrigger_joker then
for k,v in ipairs(G.jokers.cards) do
if v.config.center.rarity == 'csmr_preserver' and v.ability.set == 'Joker' and not v.debuff then
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain
G.E_MANAGER:add_event(Event({
func = function()
v:juice_up(0.3, 0.4)
return true
end,
}))
return {
message = localize({
type = "variable",
key = "csmr_xmult_gain",
vars = { card.ability.extra.xmult_gain },
}),
colour = G.C.MULT,
}
end
end
elseif context.joker_main then
return {
message = localize({
type = "variable",
key = "a_xmult",
vars = { card.ability.extra.xmult },
}),
colour = G.C.MULT,
Xmult_mod = card.ability.extra.xmult,
}
end
end
now it is only taking the first joker and ignoring the rest?
lock in bepis, you can do this
2x (left) 1x (right)
that completely stops the loop from running at the first joker
oh
okay
im going to
use SMODS.calculate_effect instead
your... atlases... arent the same?
what does this do
notmine
its like returning, but doesn't interfere with ur code ig
so i replace return with that?
ex:
SMODS.calculate_effect({xmult = 1.5},card)
gotcha
can i return a message as well
increases mult by x1.5
yeah
format in {} is exactly like how you would return stuff
the atlases shoudl still match 😭
what do yall think
no clue what that is :3
so then this is a glass counter right
its an art
but looks cool, the blue inside could be darker tho
ok
nop
looks cool
post it in #🎨・fan-art so the art guys can say something
SMODS.calculate_effect({xmult = 1.5, message = localize({type = "variable",key = "csmr_xmult_gain",vars = {card.ability.extra.xmult_gain }}),colour = G.C.MULT,''},card)
like so?
killing me
ok
if context.destroy_card then
if SMODS.has_enhancement(context.destroy_card,"m_glass") then
--do stuff
end
end
actually, thats wrong
uhhhhh
no wait i remember stone
check how glass joker works, i completely forgot how to check whether the card is being destroyed or not 💔
this will return the xmult earlier
this is loc vars man... checking glass joker is why i asked 😭
earlier?
oh.
what is it supposed to do again
:333
like you're going to be giving xmult in before and also in the main joker scoring
glass joker (surely you couldve guessed)
surely
so i can just remove the xmult line from smods.calculateeffect
yeah
oh
What might smoke cards do?
3
3
1
1.5X mult but dissolves after 3 rounds
use context.glass_shattered then
also as a side note you can do return { xmult = card.ability.extra.xmult } in joker_main and it will do the same thing you're doing
:3
so i dont need all the message stuff?
awesome
yeah it does it for you
Why??? Am I a mega goober?
key = 'singular',
loc_txt = {
name = 'Singularity',
text = {
"Squares the Mult",
}
},
config = { extra = { Xmult = 1 } },
rarity = 1, -- Rare rarity
atlas = 'singularityatlas',
pos = { x = 0, y = 0 },
cost = 1, -- Adjust cost as needed
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { squared_mult } },
mult_mod = squared_mult -- Apply squared multiplier
}
end
end
}
Bruh I cut down the vid, why is this the uncut version...\
whats squared_mult
i'm a bit silly okay i didn't realize i didn't do my procedure of making a 2x image
good thing i asked for the whole mod lol
also as a side note you can do return { xmult = card.ability.extra.Xmult } in joker_main and it will do the same thing you're doing (x2)
mfing spacebar misbehaving
Oh you right
I'm still learning lmao
I'm forgetting
i needto setup the returns for my jokers
If I'm doing ```lua
SMODS.ObjectTypes["Joker"].rarities[4].weight = 0.02
also one of the jokers is not working properly
great... 🥹
i scaled the 1x up by 2 using a website why is it so blurry
"i scaled the 1x up by 2 using a website"
yes idk how to do it otherwise
one line was so big i had to split it across 2 screenshots but anyway
probably used bilinear or something
you need nearest neighbor
whatd you make it on
it works now, thank you!
imageresizer
it's just.. not detecting the cards
i dont know aanything about krita 
how could you
why is the joker text so blurry
idk 
look up smtn like "krita nearest neighbor resize"
because by default it will use something like bilinear and bicubic and those don't work too well for pixel art
what sin have i commited against jimbo
i personally recommend libresprite for pixel art
its free
if you have over 20 bucks to spend you can get aseprite
you can also compile aseprite yourself
yeah that too
I think
that too
if you don't want to spend over 20 bucks on it
someday i will do that because im a penny-pincher
or you can use ms paint
ill check that out
does it have an upscale thingy on its own
I use paint.net but I should get aseprite
krita also has a resizing feature
just so you know
is it something to do with the get_id thing i used or

you just gotta resize it to double its original dimensions and use the nearest neighbor algorithm
and you'll be good
-# def didnt lift it off the cryptid github
I use kirta for art and resizing
"m_key" has to be replaced with the key of the enhancement
oh
i.. want it to detect all vanilla enhancements
worked, i didnt know that!
nice
which jonkler
if you need to detect if it has an enhancement then next(SMODS.get_enhancements(context.other_card))
much better
crazy how diverse the modding community for this game is
so where do i put that
are added jokers automatically able to be bought in the shop
instead of SMODS.has_enhancement
yes unless it's legendary of course
oo
alright
if its legendary its pulled from soul right
yeah
alrighty then
oopsie
accidentally deleted the then
yay it works!
i put enchanced instead of enhanced 😭
username checks out
this feels a little...weak for legendary
why just even, make it every enhanced numbered card
you know what?
you may be right...
wheres the fun in b a l a n c e
omg
What is the name for the value of the current mult when scoring?
I'm as lost as a wet spoon rn
wet spoons are not lost
mult
i picked even number cards because even numbers are like happy and stuff
and enhancements are like colors and fun
so when I config Xmult = mult for the calc, that should work, right?
odd numbers are plenty happy :(
wdym, show me your calculate function
didn't you hear what happened to 9?
wait I'm testing it
it just needs to be better prepared for 7
...what
are you doing xmult equals to current mult
My friends say I sometimes use weaponised incompetence, but rn this is just straight up incompatence
yeah
i guess
mmmmm it gave me x1
i'll just make it every enhanced number card then
yay
config = { extra = { Xmult = mult } },
rarity = 1, -- will be Rare/legend rarity
atlas = 'singularityatlas',
pos = { x = 0, y = 0 },
cost = 1, -- Adjust cost
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if context.joker_main then
local squared_mult = card.ability.extra.Xmult ^ 2
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { squared_mult } },
Xmult_mod = squared_mult
}
end
end
}
wait why have I local'd my square
idk
alright how do i check for number cards
take me back to signal analysis
yo this resize python script go crazy
not is_face()
so would it be context.other_card:not is_face()
not card:is_face()
no i dont think that works
what they said
just wanted to come back and say thank you for the help since i disappeared after you made the suggestion 🙂
what does a negative playing card mean
this shit is rare type shit
+1 handsize
errr rarity should be 3 for rare i think, but please just use talisman
imgoing to make a perkeo rarity
:0 is there an overflow? like does it physically increase handsize or does it just bring one from deck but go over handsize
again: i'm a little silly so expect me to have done this wrong
it just lest youdrawmore cards
card is your joker im assuming
so it should be context.other_card:is_face()
alright
not context blah blah
so this, then
maybe should work, try it
Is there a way to store values onto a Blind like the config for Jokers? I don't see that on the Wiki.
other than just adding an attribute to it at declaration
i put shit in blind debuff
I guess that would work lol
yay it works!!!
yay
now i need to change the description hang on
new idea for joker brb
yay!!
if self.ability.name == 'Stone Joker' and self.ability.stone_tally > 0 then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra*self.ability.stone_tally}},
chip_mod = self.ability.extra*self.ability.stone_tally,
colour = G.C.CHIPS
}
end
``` this is the implementation for stone joker in Balatro, but is self.ability.stone_tally something i can use in my mod with
```card.stone_tally```?
is there a good way i can make a blind take note of the scored hand and then either subtract that amount, make it 0, or leave it untouched?
im attempting to make a blind that rolls against the player and if the blind wins then the chips are instead subtracted from the total chip count instead of added, if the roll ties then it makes the scored hand worth 0, and if the player wins its the normal score of the hand
you can modify the G.FUNCS.evaluate_play function so that it backs up the score before playing the cards then at the end of the function restore the old score value and get the hand points by subtracting after - before
Looks like you can access custom defined attributes like this lol
G.GAME.blind.config.blind.odds
actually you can hook right before this event is scheduled and get the hand score
functions/state_events.lua:1049
So it's apparently scoring the queens again after the round ends and the score bleeds over to the next round
its funny because im already storing the hand value but i just couldnt seem to implement it into the blind properly because it keeps saying the score is 0
cause i use this for some of my jokers as well
This is so janky but it actually works lmfao
evaluate_play changes hand_chips to 0 before exiting
you need to patch into it or diff G.GAME.chips before and after
breaks if u use ankh then sell 1
i think
yea ill have to look into which works better and go from there
i am probably shrimply tired rn and just not comprehending shit as i should
Shit you're right
Just gonna check if there are any duplicates then. Thanks for the catch
why am i making this many enhancements 
Maybe a basic question, where can I find the names of all the different hand types and jokers etc?
Specifically High Card hand
how can i check if a card has a seal 
holy shit im in the wrong chat
im dumb
i will keep this here as a reminder that im dumb
lmao no prob

i can add things like a way of knowing some card is a specific thing, like there are "food" and "candy" cards in cryptid to playing cards?
without those things being enhancements itself
print(card.seal)
im making close to this amount
im making fusion of all the normal enhancements
oh thats cool
like, bonus+bonus, bonus+mult, bonus+wild and it goes on
im rn seeing what the things could make
i like that
thats why i asked this, id make some cards that are like ores, for example, glass+steel its obsidian, stone+gold is Goldstone and more, and there is a card that is a cave, that have 1 in 4 chance to create an ore card when scored
i just dk what wild+wild could make yet
do you know how i can apply a seal to a card? and if that method works on jokers
i imagine it should since jokers have the same structure as cards 
check how basegame does it 
i think card:set_seal("Purple") should just work
or debugplus
that's the thing, i looked and found nothing 
card.lua:1178
functions/common_events.lua:2173
calculate = function(self, card, context)
if context.joker_main and card.ability.extra.stone_tally > 0 then
return {
mult = card.ability.extra.stone_tally * card.ability.extra.mult_mod
}
end
if context.before and not context.blueprint then
card.ability.extra.stone_tally = 0
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_stone then
card.ability.extra.stone_tally = card.ability.extra.stone_tally + 1
end
end
end
end
why could this be making my joker file unrecognizeable? is there any mistake in this code
Is there an error or crash report?
i see
i was looking to see how the spectral do it, but couldn't find their code that calls the function
just said my main file cannot file the joker file and the game crashes
they might want the full crash log 
local mod_path = '' .. SMODS.current_mod.path
local function load_folder(folder)
local files = NFS.getDirectoryItems(mod_path .. folder)
for i, file in ipairs(files) do
SMODS.load_file(folder .. '/' .. file)()
end
end
load_folder('src/joker')
well what's line 96 in cosmere.lua
line 96 is SMODS.load_file(folder .. '/' .. file)()
so my lua file is not compiling or something?
yeah seems like a syntax error
whenc checking poker hands what is the name for High card? Surely There's somewhere that has all this stuff listed...
cannot for the life of me figure out whats wrong though, i checked every loop, if statements, etc
send the whole file
--Hammond: This Jokers gains +4 Mult for each Stone Card in your full deck
SMODS.Joker {
key = 'hammond',
atlas = 'scadrial',
pos = { x = 0, y = 0 },
rarity = 'csmr_preserver',
cost = 4,
unlocked = true,
discovered = true,
blueprint_compat = true,
config = { extra = { mult_mod = 4, stone_tally = 0 } },
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.mult_mod,
card.ability.extra.stone_tally * card.ability.extra.mult_mod,
}
}
end,
calculate = function(self, card, context)
if context.joker_main and card.ability.extra.stone_tally > 0 then
return {
mult = card.ability.extra.stone_tally * card.ability.extra.mult_mod
}
end
if context.before and not context.blueprint then
card.ability.extra.stone_tally = 0
for k, v in pairs(G.playing_cards) do
if v.config.center == G.P_CENTERS.m_stone then
card.ability.extra.stone_tally = card.ability.extra.stone_tally + 1
end
end
end
end
}
This is the only new thing in this file
How do you know this is the joker that's causing it?
every other joker worked, i keep adding to the file as and when i get new ideas
this is the one that broke it
is there a way to get a table of all the jokers in the game? (i'm looking to get all the keys)
I think G.P_CENTERS holds them all (along with all consumables)
any ideas as to what could be breaking the file?
Have you tried removing the file from your folder just to experiment to see if it really is that causing the issue?
If you can 100% confirm it's this file that's the problem it will help a ton
belis loves to assert dominance
youre so right, i shouldnt be so confident in my old code :3
i removed a condition in an if statement and forgot to remove "and" from that condition

sigh
new question, the joker only calculates stone cards in context.before
but
what if the user adds new stone cards, the joker description wont auto update to reflect the new stone cards
like the stone joker does in real time
what context would i use?
You wanna do that in an update function instead of calculate
theres an update function??
Check the API methods
I wonder if I could make a joker that just rips wheels of fortune
Like a specific number
oh wow, dont know how this page went unnoticed
thank you
It's how I have my Minimalist Joker up and running
np np
do you mind sharing your update function :3
update = function(self, card, dt)
local stg = card.ability.extra
if G.STAGE == G.STAGES.RUN then
stg.chips = stg.base_chips
for k, v in pairs(G.playing_cards) do
if next(SMODS.get_enhancements(v)) and stg.chips > 0 then
stg.chips = stg.chips - stg.dChips
end
end
end
end
goat
Should be able to pretty easily adapt that to check for stone cards
i just took what i had under context.before and put that under G.STAGE == G.STAGES.RUN
That should work I think
whats the stg
for
That's just a way to make accessing card.ability.extra more convenient for myself
ah i see the use for it now
awesome
so I'd just have to type stg instead of card.ability.extra
makes sense
Thank you random person in chat like a month ago for enlightening me
hey for the context.selling_card how do i get the sell value of the card being sold? im only seeing it for the joker that owns the calculate function
it worked!!!
thank you so much :)
im guessing its stored somewhere in context but im not seeing where it would be on the wiki
thanks will try this
good morning everyone
gm
thanks jerome that worked
please call me astra lmfao
you got it maximus astra
😭
i said it correctly
Close enough ig
hi john
hello bepis/belis/craig/bella
hi mark
did i do it right,,,, this is within calculate this time NOT loc vars like an idot
Hi bepis
i mean it's chips
i think
context.destroy_card will cycle through every card in your playing hand, hand and deck (this is an optional feature)
since, yk
returning true will destroy it
so,,,, i did it,,,? glass joker transplanted,,?
(i mean of course theres the other contexts but PLEASE
it's just pairs but for arrays
so iteration through an entire array instead of just a table
also ipairs does index
(hence the
the i)
How do I check current deck again?
ahhh
is there a way to make debuffed cards score?
you can do that?
it MIGHT be G.GAME.selected_back.name?
nane NEGATIVE inf
bump
how the flip do you accomplish this
...i can't do this like this? 
oh, i didn't notice the malformed property, why did it not paste the full G.GAME.round_resets.ante when i copied it wtf
Why do your screenshots have aura wtf lol
funny sharex post-image processing
lost my shit
imma be real i have no idea how for loops work, how would i fit a destroy into this?
under what condition do you need the destroy to occur 
G.GAME.round_resets.
You have a hanging . Lol
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.scoring_hand then
if context.other_card.debuffed then
if pseudorandom('cladent') < G.GAME.probabilities.normal/card.ability.extra.odds then
--WHAT DO I DO HERE? I NEED TO MAKE THE CARD UN-DEBUFFED
end
end
end
end
any ideas?
That probably requires a patch.
wdym
yeah just noticed it 
You need to use lovely to patch code into the game but im not too familiar with patching so I can't help with that.
ah
alternatively
is there a way to remove the boss blind for a hand played
and add it back
since that would remove the debuff anyway
can you disable the content of other mods for your own custom challenges?
Btw if it does work for Jokers do tell cuz I do wanna do something with that
you mean adding a seal or if the seal itself works? because i have just tested adding the seal and adding the seal works. yet to see if the seal itself works though
Adding a seal. Ok cool good to know
it's very funky though, it like, adds the seal graphic before doing the animation on the joker 
and if i call :juice_up() beforehand, it feels a little off. not sure what's going on there
bepis,,,,,,,,,, how do i,,,,,,,,,,,,,,, do this for remove_playing_cards,,,,,,,,,,,,,,,
if the played card is a heart
I don’t think set_seal goes on an event basis. Try wrapping it in an event manager
ah, will do
well i'm no expert on destroying cards, but try card:start_dissolve() 
might probably need to be in an event manager first
start_dissolve actually does work on an event basis by default lmao
We love inconsistency
thank you localthunk, very cool
if it works it works
has anyone tried to do this before?
G.GAME.selected_back.effect.center.key, actually. ⛓️💥
calculate = function(self, card, context)
if context.setting_blind then
if pseudorandom('cladent') < G.GAME.probabilities.normal/card.ability.extra.odds then
if G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == 'Boss')) then
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.5,func = function()
card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')})
G.GAME.blind:disable()
return true end }))
end
end
end
end
h e l p
Can't you just put them on the challenge blacklist or whatever
...why are you using self?
Maybe if such is integrated into the mod itself?
I don't see a place in the SMODS.Challenge documentation that would let me do that. And it would probably be easier to figure out how to whitelist my own mod instead of trying to blacklist others
honestly the best implementation I can think of is to either hook or patch the get_current_pool() function directly and remove things from the pool there
it makes it even worse 
restrictions is a challenge blacklist.

Prob doesn't cover everything by itself but most vanilla-based objects are covered.
Show code
local jkrsToSeal = {}
local finalSealChoice = nil
for i, jkr in ipairs(G.jokers.cards) do
if not jkr.seal then
table.insert(jkrsToSeal, jkr)
end
end
if #jkrsToSeal > 1 then
finalSealChoice = pseudorandom_element(jkrsToSeal, pseudoseed('randJokerSeal'..G.GAME.round_resets.ante))
else
finalSealChoice = jkrsToSeal[1]
end
if finalSealChoice ~= nil then
finalSealChoice:juice_up()
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.005,
blocking = false,
func = function()
finalSealChoice:set_seal(card.ability.extra)
return true
end}))
end
end```
Would you mind sending it via screenshot? I’m on mobile 😭
this reads like I would have to manually list out every card, tag, and blind from every possible mod, which I cannot do if I don't know what mods people have installed
I want to make it so that only my mod's content can appear during my challenge run
speaking of, is there like, a table of every single say, joker key that is in the game, that i can just iterate through 
for localization with localization files whats a clean way to not have to rewrite default.lua to be en-us.lua
like does lua have a built in #include like in c that just expands the file given into the source of the calling file
Technically G.P_CENTERS... but it has everything.
I’m curious of what would happen without the juice up call
Could also check for the set
that would probably be a better implementation
oh uh yeah then you'd have to write extra code for that.
yeah
Where would I look to figure out how to have a joker destroy itself and turn into another joker? Similar to Ghost, except it turns into a spcific card.
Probably just setting each table with a __index metamethod that always returns true if it's not a part of the curated object list.
see what i mean about the seal appearing before the anim?
...or is that how set seal goes normally and i just never noticed 
I can probably just hook get_current_pool()
Probably more advanced than needed
Double check with a Deja Vu rq
Cuz idk either lol
(about metamethod not get_current_pool)
does the core game/SMODS allow consumables to be perishable?
No clue but it’d be worth testing
doesnt seem like :set_perishable works on them like it does for jokers
Have you taken a look at the code for that function? It could be specifically checking for set == joker
yeah, the seal is definitely with the anim when deja vu does it
i feel correct about it being off in this instance
Suuuuuper weird
I’d check the code for set_seal myself to see what gives but like I said, mobile :(
yeahh it checks to see if the card is perishable_compat. I went around it by just setting perishable = true which successfully gives them the stickers, but it might cause an unavoidable crash
Ah that makes sense. Honestly though I could see it working out fine
well i'm wondering about the args here - set_seal(_seal, silent, immediate) - do you know if, when called, immediate is true by default?because i don't see any indication that it is
i'm wondering if deja vu calls it with immediate being true
Ykw I don’t think it is true by default. Try that
Ouch
yep, calling it with the immediate arg as true fixed it 
Ofc LOL
save me astra im begging you
i started a blind
Do you have anything checking for that?
no
Hrrrm
the crash:
What is that line in utils.lua
and now i have a function problem - when scoring, the red seal on any joker basically just acts like seltzer
Ok so it’s happening because something is trying to add mult when you’re setting the blind I think??
You’re probably gonna have to take ownership of the seal and specify the functionality it should execute depending on if the card it’s on is a joker or a playing card
but none of my contexts are setting_blind....
What Jokers did you have in hand at the time of the crash (if any)
nah i was right it crashes
Damn
just the one im trying to do
where can i find the default functionality of seals 
(im transplanting glass joker)
This is firing off every time calculate is called because it’s in an else block, and thus context.setting_blind triggers it
so i need to do an elseif [whatever] then ?
Just search “[COLOR] Seal]” in card.lua
Actually calculate_seal would be better
What function do I use to transform one joker into another (I.e. it turns into a different Joker)
It depends, when are you trying to have this trigger?
card:set_ability
card:copy_card I believe
Check the death code
it's set_ability
where is said death code
that else statement is supposed to be during scoring when the xmult value is greater than 0
Well the way you have it set up currently has it trigger if it’s not context.joker_main and not xbase <= 0
So you need a second set of conditionals within the context.joker_main conditional to handle the xbase comparisons
Or you could just make it easy and check if xbase is > 0 in the same line and ditch the else lol
Hello! New to modding and was hoping for some help with my first mod
I have made the json file with the drag and drop info from the Steam modded documentation but I can't get the mod to appear in game
this is what I have in json file
I had a similar thing, removing badge colour and text colour fixed it for me
i was having lunch, im sorry 😭
did u fix it
here with astra doing exactly that
i have no idea
ok granted this is a different issue
I’m being Joe Helpful 
❤️
I'm ngl I can't seem to make this work
unfortunately that didn't fix it, Tried removing the info and deleting the lines as well
why ping me if you’re using the death method 😭
I'm not
Can you show the contents of your mod folder?
I'm talking about set_abilityu
oh well in that case whaddya have
was gonna say, have you got the mod folder layout down
does using_consumeable use context.removed in the ipair
Nothing so far, I can't make sense of how set_ability is used
crying
well you wanna put it in an event
Nothing immediately sticks out as wrong here. I wish I could cross reference with my mod but I cannot
SMODS.Joker {
key = 'stellar_collapse',
loc_txt = {
name = 'Stellar Collapse',
text = {
"After {C:attention}#2# High Card{} hands,",
"collapses into {C:legendary}Singularity{}.",
"{C:inactive}(Currently {C:attention}#1#{C:inactive} hands played)",
}
},
config = { extra = { high_card_count = 0, high_card_limit = 20 } },
rarity = 2,
atlas = 'collapseatlas',
pos = { x = 0, y = 0 },
cost = 6,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.high_card_count, card.ability.extra.high_card_limit } }
end,
calculate = function(self, card, context)
if context.before and next(context.poker_hands['High Card']) and not context.blueprint then
-- Increment count
card.ability.extra.high_card_count = card.ability.extra.high_card_count + 1
-- Check if it should transform
if card.ability.extra.high_card_count >= card.ability.extra.high_card_limit then
return {
message = "Gravitational Collapse!",
colour = G.C.LEGENDARY,
card = card,
action = function()
card:set_ability -- NO CLUE WUT TO DU
end
}
end
-- Normal progress message
return {
message = "Collapsing...",
colour = G.C.ATTENTION,
card = card
}
end
end
}
Imma hail mary it and hope you guys (smart people) can help out
i'm thinking i maybe need to patch calculate_seal() instead? this is kinda melting my mind, i don't really understand
like, at all
i kinda get that it's calling calculate and acting like the seal is on every card?
i was saying set_ability cause it's what ive been doing for like,,,, oh my god its been a month,,,
A month?
oh my god beta whomp
(joker im working on)
I see
Actually I wonder if that function got overriden by SMODS
the screenshot is of the dumped card.lua
how do i check when a tarot card is used in my calculate function?
how do i save stuff in a blind that wont get reset when i re-enter a run
dang, thanks anyway
it'll be under context.consumeable
Where do I store a sound in the mod folder? I hadn't considered that, but now I want to do it. Also, does it have to be initialised beforehand?
thanks, overlooked that. how can i check that the consumeable is a tarot?
I’m aware but I suspect it’s something to do agnostic of patches
I just can’t find it tho
either this doesn’t work or i was supposed to do elseif
context.consumeable.ability.set == "Tarot" should work
What does it look like now
Ouchie
my pc sucks
did my discord crash on opening
there we are
there we aren’t im in a loading l—
i should close balatro
Yes
wait i don’t need to show the transform code it’s just taking up screenshot space
much better
So no matter what it should give xmult during joker_main?
yes
@sonic cedar I tried using your structure and got this when the event should have happened
...hghh, so if i take ownership of the red seal, should i be doing calculate = function(self, card, context) or calculate_seal = function(context) 
Anyone got any bright ideas as to why this puppy would be crashing with "attempt to index local card (a nil value)" ?
just calculate
what did i miss this time
can you send
assets/sounds/filename.ogg + SMODS.Sound
I gurentee I am the one who goofed it
-- Check if it should transform
if card.ability.extra.high_card_count >= card.ability.extra.high_card_limit then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:set_ability(G.P_CENTERS("j_LSingle_singular"))
card:juice_up(0.3, 0.3)
return true
end,
}))
end
And it just doesn’t?
I’d ask you to hand over the code so I could start digging if I could do work on it lol
but…?
nvm i read with my eyes
deleted the comments (or what I assume are comments, I have no experience with json) json file and now its being detected, just figured I would let you know in case anyone else asks lol
and LSingle is your mod prefix right
It is now
IT IS NOW 😭

NOT YOU TOO
Insane
oh nvm we good
bumpsies
Still the same error
P_CENTERS seems to be the error cause for some reason
gifted_card is being instatiated within the scope of the conditional statements and therefore doesn’t exist elsewhere in the block. Define the variable before assigning it a value in your conditionals
is the joker you’re transforming into one that you have in existence
In existasnce?
yes
wait
would it being a legendary mean anything? I wouldn't think so...
no that’s fine lmao
thought so
and what’s the id of the joker you’re transforming into
'singular'
and NOT the joker you’re transforming FROM right
no, Joker I'm transforming from is 'stellar_collapse'
I don't think so
Sorry man I just started learning lua yesterday
My base of knowledge is using python and MatLab lmao
yeah i think the problem is with calculate_seal(). it doesn't really matter what i do to the seal itself, since as i showed in the calculate_seal() screenshot, i think it's being run on the card side? and is checking the type of seal itself? and just repeating if it sees a red seal somewhere in the calculation? because this is what i wrote to try and make it not do what i showed
and not only did it keep doing what i showed, it didn't print either of those things once
ok so when do you want this to trigger
Once 20 high card hands have been played
i think what i need to do is patch calculate_seal and have it differentiate between the seal being on a card and being on a joker.
Wait so yes, it is in a context
if card.ability.extra.high_card_count >= card.ability.extra.high_card_limit then
You can try that and I wish you luck. I hope you get it to work. I’m just really sketched out by how it just works on a Joker like that
that’s not a context 😭
joker_main is the main scoring step for jokers
Oh okay
well I have put it in if context.before and next(context.poker_hands['High Card']) and not context.blueprint then
Like the card functions correctly right up until it should transform
So I think it's the transforming that blows it all up
Yea... I feel real bad for you having to put up with my noobiness
it’s chill
after fooling around with it for a while, I feel like it's too much work to force disable other mods' content for my own challenges...
SMODS.Joker {
key = 'stellar_collapse',
loc_txt = {
name = 'Stellar Collapse',
text = {
"After {C:attention}#2# High Card{} hands,",
"collapses into {C:legendary}Singularity{}.",
"{C:inactive}(Currently {C:attention}#1#{C:inactive} hands played)",
}
},
config = { extra = { high_card_count = 0, high_card_limit = 20 } },
rarity = 2,
atlas = 'collapseatlas',
pos = { x = 0, y = 0 },
cost = 6,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.high_card_count, card.ability.extra.high_card_limit } }
end,
calculate = function(self, card, context)
if context.before and next(context.poker_hands['High Card']) and not context.blueprint then
-- Increment count
card.ability.extra.high_card_count = card.ability.extra.high_card_count + 1
-- Check if it should transform
if card.ability.extra.high_card_count >= card.ability.extra.high_card_limit then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:set_ability(G.P_CENTERS("j_LSingle_singular"))
play_sound("CollapseBoom")
card:juice_up(0.3, 0.3)
return true
end,
}))
end
-- Normal progress message
return {
message = "Collapsing...",
colour = G.C.ATTENTION,
card = card
}
end
end
}
have you considered using the Potatro mod for balatro
true, just less of a hassle having everything open in one place
sounds like someone has 8 gigs of ram
Wait this counts high cards played before this joker is aquired doesn't it...
I think...
It shouldn't.
not possible
wait
@rapid stag quick question, do you know how to get the key of the consumeable that's used? seems to be nil for context.consumeable.key and context.consumeable.ability.key.
no
LEmme test, I have no idea what I'm doing
I don't believe it does
It should only be calculating when the joker is present.
card = card is redundant btw
i don't, but you can do print(tprint(context.consumeable)) and that should output the entire table to the lovely console so you can find the key 
AWESOME
hes checking the total times highcard is played in the run no?
thanks that's so useful i didn't know that existed
so it will count those instances of high cards being played
The mod examples on smods github says it has a purpose? Idrk... I trust you tho
it would only count the ones before if you did something with G.GAME.hands[k].played
ah nvm
i misread his code
i knew i wasn’t crazy
it has a purpose if youre doing an action on a card that is not your joker, since by default it happens on your joker anyway
Also, i think you should use context.scoring_name == "High Card" instead of next(context.poker_hands['High Card'])
ahh
for example if your joker is putting a message on a played card, it would be card = v (assuming you made a loop where v is the played card)
What would that change? It works atm.
just good practice
valid
have you tried playing something other than a High Card with it?
Your current code checks if your hand contains high card, the modified code is only high card.
If i have I dont remember
every hand contains a high card
did you want it to contain or be
ooooooooh
the point is, it will trigger everytime you play a hand
if BE a high card yeah use the modified code
if contains a high card leave it how it is
im sure OP doesnt want it to be "contain" since he wouldnt need the check anyway
everytime hand is played just do effect lol
it’s the first day let em cook 😭
true
Nah he right though
did you end up using talisman @tawny narwhal
I've really been modding this game for a month and a half now...
In the pursuit of good practise, what would I do for it being only a single card scored?
don’t remind me,,,,
Nah I changed the whole concept of the card
real
Dependency is a next week kinda thing
the modified code
yall get this good in a month?? i have a steep learning curve to look forward to then...
I literally started the day I joined the server. I literally joined the server because I wanted to write a mod
who is this yall you speak of
I also have a bachelor's in CS so uhhhh
skyward
oh valid
im a pesky business major that loves coding and wishes he went into CS instead
One message removed from a suspended account.
nested if statement
i mean, it makes sense because jokers and cards basically have the same structure - but it's weird that it behaves like that.
anyway, this is what i patched calculate_seal() to be and this is where it got me.
but now i need to work out how to make it retrigger the joker 
One message removed from a suspended account.
One message removed from a suspended account.
recursive functions
NO
now how were YOU gonna run it 😭
NO RECURSIVE FUNCTIONS UNDER MY WATCH
I wrote a recursive function to make my Omnirank enhancement work
One message removed from a suspended account.
bad skyward bad
i have no idea what the use case would even be in balatro for recursion
am i just stupid
Probably have to do some shenannigans with the optional joker retriggering SMODS option
on another note, i have 70 hours in the game and the last 20 hours are just creating mods...
love opening and closing the game 15 times for minor changes
I wanna say at least 95% of my hours were spent modding
whats your total time
I created a card that can count as any rank, and I needed a way to iterate through the possible values regardless of how many there were in the played hand. However, this grows exponentially with the number of cards, so it does something different if four or more of them are played, because by the game's logic there's only a few hands you can make because it always picks the highest scoring hand
scary.
80 hours
doesnt this break the game, i swear i saw someone talk about it in #1155557846805643434
wow
break the game how?
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/20a4d9d2d930cb22daa22c01930aaafb67656daf/togastuff.lua#L1336-L1399 2 of recursive them.
not functionally, just like playability since its to powerful
ohhh like balance-wise
yeee
idk
too late for my brain to comprehend code
I did it because I thought it would be fun
do you have it uploaded on a mod, id love to see it
I also had to patch literally every base-game joker that does something with ranks
yikes, what happens when someone adds mods that adds other jokers
I've put this in but the lua checkerator says I can't assign boolean to parameter table
not compatible with those lol
rip
Where?
You need to remove the next()
What the base game does when it wants a rank is it uses if card:get_id() == 14 for something like Scolar. And there's no useful way to override get_id() for Omnirnak so I had to edit the base game code
how do you edit base game code?
every instance of card:get_id() I replaced with a boolean function is_rank(card, {2,3,4}) to compare against all necessary ranks
with these things called patches
you can also hook functions which is less intrusive and less likely to have issues with other mods
omg how long does this even take 😭
you have to go through the entirety of the cards.lua file and pick out every joker and other abilities therein
don't worry about it 🙃
I had gotten Completion++ by that point so I more or less already knew which jokers did things with rank
i have much to learn
jesus how many hours do you have in the game
Okay guys.... I swear I'm making progress
When it goes to trnasfrom, I'm still getting this
ALSO
Got C++ at around 236, and since modding it says I've had the game running for 427. But most of that additional time is just idle because I was too lazy to close it while coding
Debuffed cards still count, how I stop that?
send your code again?
wow, respect
SMODS.Joker {
key = 'stellar_collapse',
loc_txt = {
name = 'Stellar Collapse',
text = {
"After {C:attention}#2# High Card{} hands,",
"collapses into {C:legendary}Singularity{}.",
"{C:inactive}(Currently {C:attention}#1#{C:inactive} hands played)",
}
},
config = { extra = { high_card_count = 0, high_card_limit = 20 } },
rarity = 2,
atlas = 'collapseatlas',
pos = { x = 0, y = 0 },
cost = 6,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.high_card_count, card.ability.extra.high_card_limit } }
end,
calculate = function(self, card, context)
if context.before and context.scoring_name == "High Card" and not context.blueprint then
-- Increment count
card.ability.extra.high_card_count = card.ability.extra.high_card_count + 1
-- Check if it should transform
if card.ability.extra.high_card_count >= card.ability.extra.high_card_limit then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:set_ability(G.P_CENTERS("j_LSingle_singular"))
play_sound("CollapseBoom")
card:juice_up(0.3, 0.3)
return true
end,
}))
end
-- Normal progress message
return {
message = "Collapsing...",
colour = G.C.ATTENTION,
card = card
}
end
end
}
theres a context for debuffed hand
how exactly does the SMODS.create_card function work? im using it to create a tarot card but its not putting the card in my consumeables
i can just drag it around the screen and everything
You can just do card:set_ability("j_LSingle_singular")
what is line 92 here?
im specifying the area field for the table
card:set_ability(G.P_CENTERS("j_LSingle_singular"))
what the other person said
Legend
what is that specifically
I'm being hard carried rn
honestly dont know this lol, i tried to implement it for something today, ended up scrapping it. might reimplement it at some point later
no clue, I don't use SMODS.create_card, I do
card:add_to_deck()
G.CardArea:emplace(card)```
time for me to sleep

