#💻・modding-dev
1 messages · Page 428 of 1
hi bepis!!
hii
does anyone happen to know why this happens when adding custom UIBoxes?
bepis you need to get off forsaken
you added it wrong
hey why aint my silly mod loading
where metadata
no metadata
no metadata?

metadata?

hi aure’s cat
yeah i was wondering how it would get the name
is there a different way I should be adding it?
I have to draw the uiboxes manually anyways
yall are a huge help ngl thanks
It's what this channel be for
(I don’t know nearly enough about uiboxes I was just stating the obvious for the funny)
modding-chat however


Oh my god lsp def is actually competent now
insane
Im so stupid smh
yall can i input a specific color into joker texts?
more specifically i want this color
yes
awsome
I need opinnions on wich one would fit better a Joker, here is the pitch:
[Lucky Seven][Rare]
- Playing a seven gives random permanent bonuses
Bonuses can be:
+7 chips
+7 mult
+0.07 xmult
+0.07 xchips
and 10% chance to "Jackpot" and give all 4 bonuses
And here are the contenders so far for what to draw (those are mockups with google images):
Option A is mostly as is, just pixel-arted with gold chips in the background
Option B is stacked dice, showing a 6 and a 1 in a dark room
Option C is pieces of the 4 suits of 7's stitched together
Holy fuck im stupid, i forgot scope and was wondering why my program was crashing
I made an ObjectType for some modded jokers I made that belong to a specific group, and certain jokers should treat the cards in that ObjectType differently. How do I check if a card is in that ObjectType? Is there a better way to do that?
first opinion: xmult is essentially functionally the same as xchips
I enjoy plasma deck shenanigans :'>
So long as you're okay with it not feeling very vanilla as a result, I see no problems with it then. I would possibly just skew it to not be 55% chance of stacking x score. (10% jackpot, half of the remaining 90% = 45%)
I like the dice option. The 6 1 is subtle but good I feel. Optionally you could put 7s on each side, but I think that's worse.
atlas needs to be lowercase
Someone help me?
I want to make a joker that when another joker is destroyed, it gains chips, but I don't know how the joker will identify when a joker is destroyed.
I cant draw dice
I've looked everywhere for how to do this but I haven't found anything about it.
How could I detect if a played hand has suits different from
A. a set list of suits
or B. (ideally) suits other than the starting suits of the deck
What do you mean by starting suits of the deck?
i.e a played hand has clubs on checkered deck
that would be a suit other than the starting suits
may be hard since the game turns the other suits into spades and hearts so it may think it has all 4 to start that's why I consider just a set list
A set list might be better, since you can manually define which suits are considered 'normal', and then the mod can check if the played hand has any suits that aren't in that list
From what I understood, that’s what you meant
bump
if im trying to account for modded suits can i still just look in card.base.suit or is modded that has_no_suit still
Is it possible to add a custom badge to a vanilla joker?
Can i not use commas here?
what are you even trying to do
remove every non vanilla joker from the pool
Hi, I am slowly piecing together the smods wilki and looking at other mods and examples for reference. I am wondering as to what files you typuically use
I know localization is for the descriptions of things in said language (ex: en-us = english.) But what about the other ones?
for loop and add keys to banned_keys
lmao
Ok, I just want to make sure I have this right where I want this to destroy and replace a joker, I feel like im missing something with the destroy function
Hi Jovbau, I believe they're tagged with IETF language tags https://en.wikipedia.org/wiki/IETF_language_tag
An IETF BCP 47 language tag is a standardized code that is used to identify human languages on the Internet. The tag structure has been standardized by the Internet Engineering Task Force (IETF) in Best Current Practice (BCP) 47; the subtags are maintained by the IANA Language Subtag Registry.
To distinguish language variants for countries, regi...
I was just using the en-us as an example. What I mean by the files is the files for a mod
It's just that one file!!
en-us.lua is the entire english localization for the game
Oh like every file
main.lua is the lua standard for the entry point file of a program
Why would anyone want to play an effect like this if they’ve downloaded mods?
Balatro requires assets/1x and assets/2x when it comes to setting up its visuals
Otherise... it kinda depends on your organization
Yes, I've also noticed that in other mods there's a lib, config, and other folders.
For SMODS, you'll also ideally need a json file names [mod-name].json which is your metadata
What I am trying to get at is, which folder is used for what thing. (Example: localization is language.
Libraries depend on your purpose. If people have a lib folder, it typically means a library of additional modules or functions they need for their mod
For main.lua and your .json files, those all go in the root mod folder
The documentation folder is JSON
is there a template for for loops?
there are three types of for loops in basic lua
- basic arbitary for loop: Iterates
max - minnumber of times.iis the index, which is the number of iterations
-- code
end```
- indexed list for loop: Iterates over the elements in a given list, provided those elements are indexed with sequential numbers (`1, 2, 3, 4, 5...` and so on). `i` is the index, and `v` is the value assigned to the index key
```for i, v in ipairs(list) do
-- code
end```
- key-value loop: Iterates over the elements of a non-indexed table. `k` is the key, and `v` is the value assigned to that key. If you need an index, you can either declare one yourself and then increment it each loop, or use one of the others
```for k, v in pairs(table) do
-- code
end```
Something like this?
No
root is the uppermost folder. that folder you've named root isn't uppermost--it's inside the root folder itself
hm i see
ive always avoided these because of how complicated they are
but im forced to actually learn them now
I would not really call loops complicated
They’re a pretty basic part of any programming language 
Functionally a loop is simple: whatever code is inside the loop block is run multiple times. Then the program moves on once the loop has finished
well i havent learned them yet 😭
i am trying to make a deck that removes every modded joker from the pool
i was told i should loop through G.P_CENTERS and check for original_mod
this is proving very difficult
yep yep. Though I will say that specific task isn't like the absolute easiest or anything, it's totally doable
You probably want to hook the vanilla function get_current_pool
Do you know how to hook functions?
Okay, then first you hook get_current_pool. Store the existing version of the function in a local variable, then redefine it;
function get_current_pool(_type, _rarity, _legendary, _append)
end```
Then, you need the values that the original version of the function returns, because that includes the pool to modify. So you call your stored version of the original function as a function, and pass in the arguments:
function get_current_pool(_type, _rarity, _legendary, _append)
local _pool, _pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
end```
Now, if we want to modify specifically the joker pool, we want to check if the type being accesed is 'Joker'. As well, since you said this is a deck effect, we also need to check that that deck is currently active
yeah, it's just the joker pool
as for checking for the deck, can i not just put the hook in an apply function?
thats what ive been doing
That would mean you hook and redefine it every time the deck is chosen, which means over multiple runs in a single game session it would indefinitely nest the hooks
i see
However, the easiest way to do this modification is to use the Back's apply function to set something like this:
G.GAME.modifiers.no_modded_jokers = true
Then, in the hook, you can use that:
function get_current_pool(_type, _rarity, _legendary, _append)
local _pool, _pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.modifiers.no_modded_jokers then
end
end```
Now is where you loop through the pool. The pool given by get_current_pool is an indexed list of joker keys (meaning all the entries in the list look like this)
Everything in Lua is structured as "tables" which are boxes of data where each object has a key (which identifies it) and a value (which is the actual data being stored). In this case, the keys are those numbers, incrementing from 1
yeah, makes sense, so this is how the pool data is stored?
Mhm. It's basically just a giant list of those entries counting from 1 to however many jokers you have loaded total
Since it's an indexed list, you can use the second for loop type I mentioned before that's specifically built for it
-- code
end```
i see
Well... actually, you should use the first one, but this is maybe slightly easier to learn?
so should this also go in the hook?
yeah, ive seen this one more often
never seen the first one before
yep yep:
function get_current_pool(_type, _rarity, _legendary, _append)
local pool, pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.modifiers.no_modded_jokers then
for i, v in ipairs(pool) do
-- code
end
end
end```
In this case, your list is pool
alright this makes sense so far
Since we're not using the arbitrary for loop, we're going to have to construct a second list to store the actual data we need. I.E. you want to return a version of pool that only has vanilla keys. That means you can either take them out of the one that already exists (which the first one allows you to do), or just move them to a new one
So instead, declare a new table first:
yep yep:
function get_current_pool(_type, _rarity, _legendary, _append)
local pool, pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.modifiers.no_modded_jokers then
local new_pool = {}
for i, v in ipairs(pool) do
-- code
end
end
end```
How would i be able to tell if a card gains an enhancement during scoring?
Now, the for loop is iterating inside every key and value inside the pool. v, or the value, is the string key of a joker in the game, all of which are actually used to index the card data in G.P_CENTERS. The way tables work is that if you know the key, you can just provide the key to the table to access whatever value it has stored in that key
So on the first iteration of the for loop, i equals 1, and v very likely equals 'j_joker' since that's the first joker in vanilla. This means you can get the data for that joker by doing G.P_CENTERS[v], which is equivalent to doing G.P_CENTERS['j_joker']
alright alright that makes sense
man what the fuck does that mean
Save the cards in a table in context.before and check the cards again and compare them to said table ig
coding is gonna be hard
Lastly, there's a shortcut to adding new entries to indexed lists. If you do #list on an indexed list, it gives you the number of entries currently in the list. And if you want to add a new entry to the list, you just need to do list[key] = value. So, if you do list[#list+1] = value, you're adding a new value at the next sequential index in the list
So for your new table, you want to just keep adding entries to it of the vanilla jokers you find, which would be new_pool[#new_pool+1] = v
How would one draw a sleeve on a sleeve?
So you build your table with all your vanilla jokers by making sure they're vanilla, by doing like you said and checking the center for original_mod, and then adding them to the new pool
function get_current_pool(_type, _rarity, _legendary, _append)
local pool, pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.modifiers.no_modded_jokers then
local new_pool = {}
for i, v in ipairs(pool) do
if G.P_CENTERS[v].original_mod then
new_pool[#new_pool+1] = v
end
end
end
end```
What this ends up doing is that any joker that's modded is not added to the new pool, so its relative size (and number of entries) goes down by 1. If Greedy Joker was modded, then it would end up like this:
Greedy Joker is never added, and Lusty Joker is added at the index of 2 instead. Every following item in the list is added at 1 less as well, and that just keeps happening as you exclude more from the table
makes sense yeah
Now all that's left to do is return your new pool. The easiest way to do it is just overwriting the old pool, and then returning both the original return values
function get_current_pool(_type, _rarity, _legendary, _append)
local pool, pool_key = ref_get_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.modifiers.no_modded_jokers then
local new_pool = {}
for i, v in ipairs(pool) do
if G.P_CENTERS[v].original_mod then
new_pool[#new_pool+1] = v
end
end
pool = new_pool
end
return pool, pool_key
end```
And that should be it. If you've selected this deck, no modded jokers will be available
Which line is 138?
No G.P_CENTERS uses string keys
OP
I KNOW WHY
You're gonna have to also check that v ~= 'UNAVAILABLE'
Or maybe it's in lowercase
along with the type and modifier check?
get_current_pool sets keys for jokers that you can't get (due to not being able to find duplicates or whatever) to that value
or the original_mod check
In the same line but before original mod check
meow
or should it be or
Nope, and is correct
G before .P_CENTERS and ur set
I believe the nil access is because it tried to look for G.P_CENTERS['UNAVAILABLE'] which is not valid
So that should prevent that
You would do lua G.E_MANAGER:add_event(Event({ func = function() if not G.jokers then return false end SMODS.add_card({set = "Joker", stickers = {"eternal"}}) return true end })) In apply.
thanks :)
hm yeah still not working
could you elaborate a little more?
couldn't i theoretically make that set dynamically when selecting the first blind of the run so it has automatic support for modded stuff (like drafting deck and such) instead?
Oh duh
It would be not G.P_CENTERS[v].original_mod
Since you need to check that it doesn't have a mod
I believe what the current code does is only give you modded jokers lmao
Something like this perhaps:
If every joker you encounter now is Jimbo, that means we're looking in the wrong place for original_mod
Yay!!!!
no clue, ig look how sleeves are normally applied in game and then just copy paste that? sorry idk other mods
for reference if i wanted to exclude all modded cards, (I don't, this is just for learning) would i simply remove the "Joker" check?
or would it be more complicated than that
No yeah it should genuinely be that aimple
awesome thanks
It wouldn't exclude Tags, Suits, or Ranks though
Since those aren't "cards" internally
Have fun!!!!! Also mrrp 🏳️⚧️
Didn't really work...
setting local values in calculate outside of context checks will reset them
Save the table in card.ability
guys how do i give the player money if they have set joker?
Hi if I wanted to detect if the player has the crystal ball voucher how would I go about doing that i know you can do other_consumable but idk if other_voucher is a thing lol
context.other_voucher does exist but you should do if G.GAME.used_vouchers["v_crystal_ball"]
Thank you gamer 
How does one make seals on cards on the title screen be the right size?
@tall wharf here's much better check for nested folder
if SMODS.current_mod.path then
local normalized_path = SMODS.current_mod.path:gsub("\\+", "/"):gsub("/+$", "")
if not normalized_path:match("/Mods/[^/]+$") then
local mod_folder = require("lovely").mod_dir:gsub("\\+", "/"):gsub("/+$", "")
local last = normalized_path:match("/([^/]+)$")
local correct_path = mod_folder .. "/" .. last
error(string.format(
[[
Mod installed incorrectly.
Right now it's placed in %s, which is called "Nested folder".
To make it work properly, move mentioned folder in %s,
so result mod directory should be %s
]],
normalized_path,
mod_folder,
correct_path
))
end
end
Can you tell me how to make it possible to draw more than 5 cards?
Like how the Palette voucher does it, or some other way?
There's also this function, but haven't personally tried it.
What are the conditions for drawing additional cards?
...crashlog?
i mean maybe it's an ipairs/pairs thing
somehwair in all that code
It was a hard crash, but sometimes it's a stack overflow.
Almost definitely an infinite loop or recursion problem, then, though I can't see it in the code you posted
The only difference between SEALS.recursive_extra_for_non_jokers and SEALS.recursive_extra is the non-joker one doesn't have a while loop.
how would i use this to put cards into the consumable slot?
select_card = "consumeables"?
alr lemme try that
just wasn't sure on the exact terminology
i have a few fun ideas for a mod, could someone or a few people just give some tips on how to mod balatro? i have little to no experience with modding or coding
im trying to make my consumable give the player +1 hand size for the round when the consumable is used, how would I go about doing this?
You would have to set a game variable saying how much hand size to remove at the end of the round.
Is there a section for decks in the steammodded documentation, I can't find it
yes, SMODS.Back
🤔 will this crash with talisman
nope
what context would i use to check if the player is in a round is it just context.in_round?
for some reason it's saying there are "missing coressponding "end"s"
elseif, not else if.
context.selling_card and context.card.
check the set
heyo people, sorry for the potentially dumb question but been trying to follow some tutorials for balatro modding (mainly the video in the forum post of the modding starter pack) and I think I copied it pretty one to one yet my lil test mod isn't showing up in the mods list nor is the test joker showing up in the game at all, anything I may have missed?
Huh
follow my tutorial to get mod loaded in instead...
link it and I'll do
dont use steamodded header, use a metadata file
oh the your first mod github thing?
that works too, and i meant https://www.youtube.com/watch?v=tCdZJuZI_ls
is there a way to set the cards a deck will have?
also goated miku cursor
thanks :3
Might be failing due to a simple typo -- STEAMODDED HEADER instead of STEAMMODDED HEADER. But yes, try using the newer .json metadata instead
imagine using header in 2025 smh
imma see if that is covered in the tutorial because I am quite new to everything programming related so don't have any reference on what that is or how to do it
For now, just removing one M should be enough to get it recognised and loaded by Steamodded
Oh, and MOD_DESCRIPTION instead of MOD DESCRIPTION

a
that could also be it
this is only spawning tarot cards with an unceasing purple square effect
🤔 whats math.fmod
returns the remainder
it's so the first slot is a tarot
the second slot a planet card
etc.
Apparently MOD_AUTHOR also requires square brackets around the author, so MOD_AUTHOR: [ Cyro ]. But yes, definitely better to learn the updated better way of doing things
I am attempting to add a new enchantment and have a joker apply this enchantment to any card played. Can someone tell me what is wrong with my current implimentation that is resulting in the crash: Oops! The game crashed: Card.lua:251: Could not find center "backstabbed"
my guesses is that it's doing the first one first, understandably
then just
filling the rest of the slots
with tarots
because it's returning the set
it should be m_(mod prefix)_backstabbed in :set_ability
How can I loop through all playing cards after pressing play?
Im going to try this, thank you very much
for _,v in ipairs(G.play.cards) do if you meant played cards, theres G.playing_cards too if you want full deck 🤔
i forgot to reply
that should be in #⚙・modding-general
usually if it shows which mod is causing it ill put it in the right mod chat
but this one doesnt specify
it would still be in #⚙・modding-general since its not related to mod development lol
lol sorry :(
ill try that ty
is there any way to have a booster pack contain multiple types of card
where in #⚙・modding-general ?
^
just to verify, if my mod prefix is mbm it should be:
target_card:set_ability('m_mbm_backstabbed', nil, true)
And should this change also occur in this line?
info_queue[#1116390750314307698_queue + 1] = G.P_CENTERS['backstabbed']
oh, thanks a lot
yes, im pretty sure it should be G.P_CENTERS["m_mbm_backstabbed"] too
what is the check for a player being in a round?
G.GAME.blind.in_blind?
is there somewhere i can see all the like checks and stuff in a list?
nop
im always having to search thru other jokers logic for checks and its annoying
Help how do I remove perma_debuff after it has been set
im pretty sure its not in ability, its just v.debuff and v.perma_debuff
It sets it just fine if I do v.ability.perma_debuff = true
slight bump
I'm using G.playing_cards, but it gives me an error
huh
omg i had this error for like a solid 2 hours last night i cant remember the fix but you got this champ 
whats the code
make sure to use events if this is in apply btw
I already have those
whats the code
Here it is
what do you mean by event?
i sent this above btw
I tried to put a sound effect for when my joker upgrades but for some reason the game crashes.
I followed all the steps from the documentation but the results are the same...
Is there a way I can fix this?
how does your file look like
Try matching the key and path (without the ".ogg" for key)
like this
try setting the key to Dodgeball_sfx, probably
tried like this but it gives me the same error
oh wait
you just said the key
What's the point of the path parameter if it searches using the name of the key anyway? Odd
aaand it still gives me the same error
is it still trying to search for Dodgeball.ogg
yeah
The sell context doesn’t work work for me for some reason
if it has this little dot then the file hasnt been saved yet
whats the code
I saved it but for some reason it still crashes
I want to make a card pack have multiple types of card (tarot, spectral, etc)
but i want it to use a specific pool for each slot
how would i go about this?
because this code only gives me tarots
can you show me the crash again
Thanks, it works now, but it gives me another error saying it can't call destroy
use SMODS.destroy_cards instead, probably
Hello again, I am having 2 problems with this enchantment if someone could help that would be very appreciated
- the resulting -mult or -chip is always 0 regardless of the original chip value for the card when added to the card
- when the enchantment is applied to the card before scoring the visual part of it isn't shown, but it is shown in the deck
whats the code 😭
inside my mod, in assets and in sounds it is located there
looks like its checking resources for some reason
SMODS.Joker { key = "qr", blueprint_compat = true, atlas = "jkr", loc_txt = { name = "QR CODE", text = { "{C:blue}+#1#{} hand size every time a card is sold", "{C:inactive}currently {}#2# {C:inactive}hand size", "{C:inactive}scan me", "DO NOT SELL" } }, unlocked = true, discovered = true, rarity = 1, cost = 4, pos = { x = 7, y = 0 }, config = { extra = { h_size = 0, add = 1 } }, loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.add, card.ability.extra.h_size } } end, calculate = function(self, card, from_debuff) if context.card and context.selling_card then cardarea = G.jokers, selling_card = true, card = card card.ability.extra.h_size = card.ability.extra.h_size + card.ability.extra.add G.hand:change_size(card.ability.extra.add) end end, remove_from_deck = function(self, card, from_debuff) G.hand:change_size(-card.ability.extra.h_size) end, }
Bepis help😭
i actually dk, i set up my SMODS.Sound like that too
oh...
wrong order, probably
card=card should be at the end
it should be if context.selling_card and context.card then
and also
remove all of this
The cards are destroyed, but now I can't look at my deck and this pops up
ex:
cardarea here means context.cardarea refers to G.jokers/G.hand, etc etc
selling_card here means context.selling_card is a bool value
card here means context.card refers to the card thats being sold
I aint very good with modding yet, but maybe try this
card.ability.extra.h_size = card.ability.extra.h_size + card.ability.extra.add
G.hand:change_size(card.ability.extra.add)
return {
message = localize('k_upgrade_ex')
}
instead of
cardarea = G.jokers,
selling_card = true,
card = card
card.ability.extra.h_size = card.ability.extra.h_size + card.ability.extra.add
G.hand:change_size(card.ability.extra.add)
Oh
So i’m stupid
Hey bepis, do you think you could help me with this?
its context.selling_card only i think
Could anyone help me with this, please?
could be because chip_value is always 0
Anyone know how to make a joker card set money to zero? I currently have config = { extra = { money = 0 } }, as the very first thing in the part that does all the calculating stuff, but I'm not sure it's going to work. It's my first time trying to make mods, and I know it's maybe a little ambitious for doing it for the first time
oh
yeah the context is set up wrong here
ease_dollars(-G.GAME.dollars, true)
should be context.cardarea == G.play and context.main_scoring
Do I have to replace what I sent with that?
and use card instead of context.other_card
you don't need anything in config.extra if you just want to set the money to 0
Bepis it won’t work 🥺
again
could use some help here
amazing
What's going on is, after I press play I remove most cards and once I do that, I can't take look at my deck
So where do I put it then?
you would put ease_dollars(-G.GAME.dollars, true) in your calculate function, under whatever context you want it to activate on
How can I modify another mod's blind? I tried this but got an error cause it couldn't find it:
return not (G.jokers and G.jokers.cards) and false or RGMC.funcs.jokers_greater_than_rarity(G.jokers.cards,"cry_epic",true) > 1
end
SMODS.Blinds['cry_pin'].recalc_debuff = function(self, card, from_blind)
return card.area == G.jokers
and not G.GAME.blind.disabled
and RGMC.funcs.greater_than_rarity(card,'Legendary',true)
end```
I'm trying to edit The Pin so it counts only certain rarities
@formal parrot you gave fromdebuff in calculate=function instead of context
Noway
Omfg
I tried deleting the lovely mod but still remains the same.
I'm not sure what to do at this point so Il'' scrap the sound idea for later...
So do I put it in calculate = function(self, card, context) or if context.joker_main then? or is it somewhere in mult_mod = card.ability.extra.mult, or message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } }?
hi bepis
Omfg thank you so much i would’ve never found that
bump
It worked 😭
im trying to write an essay while having to keep an eye on my sister right now 😭
turned out having to write something while being screamed into your ears isnt a fun experience at all
hiii
bepis
hi dilly
hi
Just realized that I forgot in my main question that it would trigger the money set to zero when you play a High Card. Hope that doesn't make it more complicated 😭
I ain't sure how or why that should be the case, I am trying to access the cards current chip value and use that
sent the message early mb
calculate = function(self, card, context)
if context.joker_main and context.scoring_name == "High Card" then
return {
mult = card.ability.extra.mult
dollars = -G.GAME.dollars
}
end
end
your calculate function should look something like this
returning mult and dollars like this automatically creates messages for them
nope
what i do
op- didn't see that, thx
fixed
yup
sorry for spreading misinfo
me when i purposely spread misinformation
i haven't actually needed to do that myself yet somehow
Thank you man
also bepis now that you've seen the innards of grab bag did i do a good job or not
looks more organized than yggdrasil thats for sure
idk if that's saying much or not
how can i destroy played card?
if context.destroy_card and context.cardarea == G.play then
return{
remove = true
}
end
ok thanks
context.destroy_card == [whatever card you want to destroy] if you only want to destroy a specific card
depends on how highly you think of yggdrasil :3
idk i haven't poked around into the codebase yet
-# please dont
My entire computer just almost died when I tried to copy the text😭
i know my code is way more organised than bunco's but i like that mod a lot
i didn't put MY ENTIRE MOD IN ONE FILE for one
mfkaa
i'm sure pwx is perfectly fine under the hood
after all jen is so proactive in accepting community feedback and making their mod as stable as possible
so true
Morning everyone
morning winter
Bunco's organization makes me cry
morning BepisFever
Morning Winter Bepis Math fever
hey bepis, i tried changing the context for this enchantment and I am still running into the same problem, this is what I have now after a few bajillion iterations of nothing working:
SMODS.Enhancement{
key = "backstabbed",
loc_txt = {
name = "Backstabbed",
text = {
"{C:chips}-#1#{} chips",
"{C:mult}-#2#{} mult"
}
},
atlas = "centers",
pos = {x = 0, y = 0},
order = 100, -- Higher order means it appears on top
loc_vars = function(self, info_queue, card, specific_vars)
if not card or card.fake_card then
return { vars = { "2x Chip Value", "1x Chip Value" } } -- Show multipliers in collection
end
local chip_value = card.base.nominal_chips or 0
return {
vars = {
-2 * chip_value,
-chip_value
}
}
end,
calculate = function(self, card, context)
if context.cardarea == G.play and context.main_scoring then
local chip_value = context.other_card.base.nominal_chips or 0
return {
chips = -2 * chip_value,
mult = -chip_value
}
end
end
}
use card instead of context.other_card
71x95y
?
and also, you might want to check if base.nominal_chips actually exists 🤔
That should exist for every playing card
yeah cool, just wanted to be sure
-# hi eremel
Hi bepis
I just noticed loc_vars = function(self, info_queue, card) and return { vars = { card.ability.extra.mult } }. Do I have to do something with that too or not?
how i can make card give more chip and mult?
thanks for that
if you have a localisation file or a loc_txt variable, you can put #1# in your joker description and it will display the value defined in card.ability.extra.mult when hovered over, even if it changes
`SMODS.Joker {
key = 'beggar',
loc_txt = {
name = 'Beggar',
text = {
"Sets money to $#0#",
"if played hand",
"is a {C:attention}High Card{}"
}
},
config = { extra = {} },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 1,
atlas = 'TRBMod',
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main and context.scoring_name == "High Card" then
return {
mult = card.ability.extra.mult
dollars = -G.GAME.dollars`
This is all I have with the card, so point out what needs to be done if anything
I believe he can remove that correct? as its not being used by the joker
oh, if you don't want your joker to give mult then yeah
also the first line of your description should say "Sets money to {C:money}$0{}",. you don't need the hashtags unless you're calling a value from loc_vars
Hey Bepis, I tried what you recommended and its still giving -0 mult and -0 chips to the card
SMODS.Enhancement{
key = "backstabbed",
loc_txt = {
name = "Backstabbed",
text = {
"{C:chips}-#1#{} chips",
"{C:mult}-#2#{} mult"
}
},
atlas = "centers",
pos = {x = 0, y = 0},
order = 100, -- Higher order means it appears on top
loc_vars = function(self, info_queue, card, specific_vars)
if not card or card.fake_card then
return { vars = { "2x Chip Value", "1x Chip Value" } } -- Show multipliers in collection
end
if card then
local chip_value = card.base.nominal_chips or 0
return {
vars = {
-2 * chip_value,
-chip_value
}
}
end
end,
calculate = function(self, card, context)
if context.cardarea == G.play and context.main_scoring then
local chip_value = card.base.nominal_chips or 0
return {
chips = -2 * chip_value,
mult = -chip_value
}
end
end
}
alright, thanks
odd
card.base.nominal_chips does not exist, so chip_value defaults to 0. i think you're looking for card.base.nominal
😭 i was gaslit thinking it existed
i use .nominal like all the time lol
i use :get_chips_bonus()
if you want it to account chips bonus too, then yeah
OK, i changed it to card.base.nominal, it is properly being added to the card, but it isn't being used in scoring
wait wait wait, let me check something
yeah no its still not being used in scoring. Could it be the same reason the card has the original + chips and then below that it has the - chips and the - mult?
should it be just get_chips_bonus or the adding base.nominal and get_chips_bonus
this just in, this is not proper synatx:
chips += -2 * chip_value,
mult += -chip_value
how can i use that?
one thing i realized about coding my mod in vscode is that if i have the actual balatro source code open in a different tab, it will allow me to see and autofill different variable and function names
which is turning out to be very helpful
what is the "effect" variable that is in the source code of the game for when the jokers are declared? what does it do?
yes its not
its just chips = ...
idk what that is but you probably shouldnt mind it
j_jolly= {order = 6, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 3, name = "Jolly Joker", pos = {x=2,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 8, type = 'Pair'}},
8 out of 11 times SMODS will have you covered.
what is the name of the sound that plays whenever a joker has been upgraded?
where does vanilla remade have all of like the display text for the jokers? cuz i dont see it with the actual joker code
try searching in lovely dump until you find it idk
oohhhh ok
hello
hi magic
how would i make a joker spawn in shops naturally?
i set the rarity and i refreshed the store like hundreds of times i got every joker but mine
either it aint working or my luck is saddening
it should spawn naturally if you the rarity is set up right, and you didnt mess with in_pool
this is what ig ot
it looks good in the collection
ill set rarity to 1 and look for it again
I require debug wizards :'3
calculate = function(self, card, context)
-- We want to re-calculate this pretty often (?) to to avoid moving the joker shenanigans I suppose
card.ability.extra.value_left=0,
card.ability.extra.value_right=0, --This is line 398 from the Error
-- Using ceremonial dagger as the logic here, we start by declaring a pos variable
local my_pos = nil
-- Now we iterate through the jokers from the very first, if we catch that its ourselves stop.
-- Otherwise, add it to the value on the left
for i = 0, #G.jokers.cards do
if G.jokers.cards[i] == self then
my_pos = i; break end --This also stores our position
else
card.ability.extra.value_left = card.ability.extra.value_left + (G.jokers.cards.sell_cost or 0) --Adding value to the left count
end
for i = my_pos+1, #G.jokers.cards do --Now we check the jokers on the right with my_pos+1
card.ability.extra.value_right = card.ability.extra.value_right + (G.jokers.cards.sell_cost or 0) --Adding value to the right count
end
-- Calculate the difference
if (card.ability.extra.value_left > card.ability.extra.value_right) then
card.ability.extra.difference = card.ability.extra.value_left - card.ability.extra.value_right
else
card.ability.extra.difference = card.ability.extra.value_right - card.ability.extra.value_left
end
if context.joker_main then
return {
if(card.ability.extra.difference < 5) then
xmult = card.ability.extra.xmult - card.ability.extra.difference
else
extra = { message = ('Unbalanced'), colour = G.C.GOLD }
end
}
end
end
Joker functionality TLDR;
Checks value on the left and right of the joker, if the values are balanced, x5 mult, -1 for each difference
please download it
Wich one 🥲
the one made by sumneko
Does that exist in Netbeans?
netbeans?
i
No idea
I guess this is my call to change to a different IDE
Time to install it
i can entrust everything to people with "neko" in their name
bepisneko
they call em dilneko
😭
This is what the code looks to me btw
I don't even have highlights on the variables
💀
Oh
and this should be card, not self
swap doesn't work, like it swaps but when doing something else it reverts
this probably doesnt exist too
yeah it doesnt work in context.before afaik
I yanked that from Swashbucler/Dagger
Is there a way I can use something alternative to swap?
You can archieve your dreams with enough elseif statements 🪄 ✨ (please dont)
:3 idk
ok so i have an idea for a joker called mini fridge, where it gains 1 Xmult for each food joker purchased (resets if a food joker naturally perishes), i am also tempted to make it give 0.5X mult per perishable joker purchased, should i just stick with the first bit?
thats because they are iterating through the G.jokers.cards table, which will return individual jokers
you can check sell_cost from them
and also
please reference from vanilla remade instead :3
You are asking a lot for someone that didn't have VSC and was coding with rocks and sticks untill things worked
(I will look into it, thank you 💛 )
fair, fair
the second half effect doesnt really make sense, i think just the first half is good
just the first half? okie!!
You could make the second half into a second joker even
"Binge eater" gains mult for each perished food joker
Encourages rerolling for things like popcorn to keep stacking it
How does the "replace" option actually work?
I'm trying to replace the sound the joker makes whenever he does the mult sound but it keeps doing the default one.
what is the best word to describe food jokers naturally dying? eaten? expire?
consumed perhaps? idk they all have like different texts
could anyone tell me if its possible to make a blind that translates the game to a language (im making a french blind)
is there a way to spawn in jokers/vouchers/tarohs/etc for testing?
change G.SETTINGS.language directly
download DebugPlus
i have debug plus but i only see functions that give extra hands/discards/chips/mult/rounds/money/etc
unless there are keybinds im unaware of
open up the collection menu while in run
hover on a joker, voucher, tarot etc
press 3
you can also press Z and 1, 2 and 3 to create save states that persist between game shutdowns
Does someone know how to make this work?
how do i swap in context.before?
So... what went wrong?
Check line 41, says there may be a } missing
LUA EXTENSIONNNNNNNNNNNNNN 🗣️
`SMODS.Joker {
key = 'beggar',
loc_txt = {
name = 'Beggar',
text = {
"Sets money to {C:money}$0{}",
"if played hand",
"is a {C:attention}High Card{}"
}
},
config = { extra = {} },
loc_vars = function(self, info_queue, card)
end,
rarity = 1,
atlas = 'TRBMod',
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main and context.scoring_name == "High Card" then *
return {
mult = card.ability.extra.mult
dollars = -G.GAME.dollars
}
end
end
}`
Here's the entire thing with a star at line 41
Well it excludes the atlas and mod info
so not really everything
Add a comma on the return after card.ability.extra.mult
Still don't work
New error or same?
sob
Its haunted
show the code again
Use the Lua extension to unhaunt it
How would one do that?
I mean I have lua installed, but I couldn't get it to work properly
how can i make this work?
I just have lua, like I think the normal basic lua
you are literally putting SMODS.Atlas inside SMODS.Blind there
ok so in my actual joker context function, how do i detect when a joker is purchased?
bro thinks he coding in python
Plus: what's that program in the picture? I feel like I've seen the icon before
france is "fr" btw
If Bepis had one mult for every person who didnt know Visual studio code existed today that chatted in modding-dev, they would have 2 mult
visual studio code
+2
ooooh yeah
on top of changing G.SETTINGS.language, run init_localization() too, i think
I'm an idiot, line 41 was the one below the line I put the star at 💀
Line 41 is return, {
Not if context.joker_main and context.scoring_name == "High Card" then
its return {, not return, {
oh
makes sense
GOD DAMN IT
STILL LINE 41
I HATE THIS SO MUCH
I EVEN PUT THE COMMA THE CORRECT PLACE THIS TIME
It works now...🥲
ok so in the steamodded documentation on github, the example G.joker gets used a lot when explaining returns and context n stuff, what exactly is that being used in place of? /gen
this is an example
what do you mean in place of
G.jokers refers to the jokers tray
it works but I have to restart the game for It to work
ok, cuz i am trying to figure out how to detect when you buy or acquire specific jokers
and i am not entirely sure how to go about it
if context.buying_card and context.card.config.center.key == "card_key" then
I have an enchantment being applied by a joker that adds negative mult and chips. it is being applied before scoring, but the image doesn't show up until after its put back in the deck and it doesn't use the scoring added to the card. If I play the card that has the enchantment in a different round, it works.
Can someone help me figure out why it isn't scoring and the visual isn't being applied
will it work if i try and initialize a joker mid run
Bepis good news I have VSC now, but I have no idea why it yellow : ^)
Im getting this crash with this code, whats wrong with it? lua if context.setting_blind and pseudorandom("seed") <= (G.GAME.probabilities.normal * card.ability.extra.base)/card.ability.extra.odds then SMODS.create_card({set = "Joker", key = "dog"}) return {message = "woof"} end
beep
remove these
key = "j_(modprefix)_dog"
thanks!
**oh, thank you 😭
I'm trying to display some simpleish custom graphics on the screen (current attempt is via :draw_shader, and while it's not crashing, and I'm certain the shader fires, it's not showing up). I'm currently just trying to get a white line to go across the screen. Does anyone have any resources to help with this? Or just any examples they know of I could try to learn off of?
did it work
ill test it
try putting this outside the event
how would I make this just change the language immediately instead of me having to restart in order for the game to change languages?
I think I’ve figured out how I want the contexts to be set out in the docs
:3 can i see
Are you capable of seeing into my brain
making a Joker that has a 1/5 chance of destroying cards and adding a 10th of their value to its Xmult and I was wondering if theres a way to get the id of card in a way that works for this. I know that the "context.destroy_card" for the for loop is incorrect but I was just throwing stuff against the wall
That's what I did but it doesn't change the game's language and just has me closing the game and reopening it for it to actually change
I will type one up later and show you
( i fixed the en_us thing)
I can't even use it
OH WAIT
change G.SETTINGS.real_language too, my bad 😭
i just saw it existing in the game's code
I'm trying to have it select a ramdom yet specific set of jokers to replace with it with another random but specific set of jokers
maybe change both real_language and language
im checking the game's code rn to see if theres any more stuff you need to change
hey bepis
can i use some of your bar thing from your mod code?
not everything
also ill add credit
What context should I use to calculate how much the jokers on the left/right cost, considering, it should be recalculated every time the jokers are moved
oh, this is more complicated than i thought it would be
it wouldnt translate stuff thats already in English to French
you want to use G:set_language()
put it in calculate without any context
mhm, sure
tyy
Thats where it is :'>
For both or just for French?
😭
G.SETTINGS.language = "fr"
G.SETTINGS.real_language = "fr"
G:set_language()
alright
i made this for a joker that gives more mult depending on how many "joker" you have but its not working, whats wrong? lua for i=1 , #G.jokers.cards do if G.jokers.cards[i].key == "j_joker" then result = result + card.ability.extra.upg end end
yeah the for loops are set up wrong here, one sec
Thankies 💛 ;V;
for _,v in ipairs(G.jokers.cards) do
if v.config.center.key == "j_joker" then
result = result + card.ability.extra.upg
end
end
Thanks!
actually you only needed to fix G.jokers.cards[i].key to G.jokers.cards[i].config.center.key but i like using ipairs :3
needs another quote after j_joker im assuming
are you being shrekphobic rn
I'll say it again if I have to
(hi bepis)
i have returned from my slumber to bring my issue!
this works, the card does in fact do a transformation, but it seems like it does the transformation twice
as in
it'll start the animation, then get overwritten by restarting and finishing the animation the second time around
how do i fix?
where is the image
is that just me
hi
whats the image, i just came back from the bathroom 😭
ok there it is
welcome back
can you put a print in there to see if it runs twice
oh duh
also
you might want to wrap to_big around context.card.cost too 🤔
idk
just to be sure
I can't even tell if I need the psudorandom element because theres no random chance, just random selection
if its like "picking a random (x) from (y)" then you need it
is it possible to make a joker that is stronger or like scales if its adjacent to a copy of itself?
yeah
for the love of god
this checks what cards are next to it?
I just had that problem too sending my current code
i think Discord is dying
is discord dying
click it
try adding a context.main_eval to see if it works?
no
got it
you want to check the adjacent jokers' key
did it crash or smt
No, the use button is just grey
not yet
you need it 😭
ok i cant send my image discord might be dead
you need to return true in there for the consumable to actually be usable afaik
the image was unrelated to my current issue but yeah discord is dying i think
gang sorry to barge in, im trying to make my first joker, and this popped up, what can i do ?
parj_Smiley is i suppose my joker
Oops! The game crashed:
[SMODS _ "src/game_object.lua"]:410: Failed to collect file data for Atlas parj_Smiley
i have my assets, my main.lua with no visible errors and my icon.png
(my images can't send if i could i would send screens)
still grey, even when using Wheel of Fortune's
ermmmmm awkward
weird
I think its cause I don't have the localize of WoF
it did not
also i found out it triggers when i hit 0 dollars?? instead of that being the minimum???
whats even going on with discord rn
If I wanted to check Cryptid's configs from my own mod, how would I do it?
Trying to make sure I dont break anything with cross modding
uhhh hm, why does it even run twice
p sure it shouldnt do that
also can you even do this to contexts
ill try it now
no crash or anything it jut
didnt work
calculate = function(self, card, context)
if context.buying_card and not context.blueprint
and to_big(G.GAME.dollars) - to_big(context.card.cost) <=
to_big(card.ability.extra.dollars) and context.main_eval
then
print("guh")
hpfx_Transform(card, context)
end
end
function hpfx_Transform(card, context)
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:flip()
return true
end,
}))
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:set_ability(G.P_CENTERS["j_hpfx_ijiraq"])
play_sound("card1")
card:juice_up(0.3, 0.3)
return true
end,
}))
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:flip()
return true
end,
}))
return true
end
current code
bumpity bump
what am i looking at
temperance (vremade code)
it works fine in the main menu, but when i open the collection page mid run it crashes because of bad argument
how do i format text like this? /gen
```lua
is there an easy way to cancel the consumables from disolving? like for letting use it again
oop
at the top
ooohhhh
if context.buying_card and not context.blueprint then
if context.card.config.center.key == "gros_michel" or context.card.config.center.key == "cavendish" or context.card.config.center.key == "popcorn" or context.card.config.center.key == "ice_cream" or context.card.config.center.key == "ramen" or context.card.config.center.key == "egg" or context.card.config.center.key == "turtle_bean" or context.card.config.center.key == "seltzer" or context.card.config.center.key == "diet_cola" then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
return{
message = 'Stocked!',
}
--end
end
```lua
code
```
ok so uhm, this code is supposed to detect when i purchase a food joker
then scale my joker
but it doesn't properly detect the jokers
im not sure why it isn't
try taking context off of the center key
sorry to repost it so soon, but i'm really struggling
parjSmiley is i suppose my joker
Oops! The game crashed:
[SMODS "src/game_object.lua"]:410: Failed to collect file data for Atlas parj_Smiley
i have my assets, my main.lua with no visible errors and my icon.png
(my images can't send if i could i would send screens)
do you have 2x and 1x images in your assets in subfolders
file structure issue
yeah
is your atlas too big maybe
does your atlas path have the same name as the actual images (and are the images the same name)
maybe that's it,
ima test it
your 2x images and 1x images need to have the same name for SMODS.Atlas to be able to read it properly
it was ineed this thing on a missclicked letter
crazy
that resulted in an error
this suggestion
why did you comment out one of the ends
it is commented out because i was testing soemthing and forgot to uncomment it out before sending it here
still doesnt work if the end is in
change it to _ then? like context.card.config.center_key
maybe you do have to change out context.card. for c. then
what version are you on
smods?
it says that c is a nil value
yeah
530b
oh right did you set c equal to context.card (as a local)
no i did not, i will try that
530b has the deckview bug
how would i go about doing that? /gen
what deckview bug
game no like when you view deck
maybe applies to collection
local c = context.card
do i need to wait for next smods release then
if you're modding just use the commit
if there's a crash in the collection it's more likely to be your custom joker
deck view and collection are quite separate structures anyway
yeah no that didnt work either
except its for temperance
how
discord moment
Oh i tought it was only me, I have been trying to upload a video for 20 mins 💀
use your words
servers are dying
🔴
Ah that doesn’t make it big
i took ownership and replaced the code with vanillaremade code
so it is your code
and it still works on main menu just not in game
you said it was a joker. i corrected you
the whole convo around it implied it was an issue with smods lol
scroll up harder lmao
Im having some issues with the display of the price on left/right sides, what I noticed was that blueprint does the check inside loc_vars, would that work here?, or do I need to move the math to somewhere else? x-x
Update: I fixed it by doing as blueprint, moving all the logic that calculates the display numbers into loc_vars
what set is your joker in
i mean consumable 
wdym what set
temperance is tarot
in your code
Game crashed after clearing the blind
whyd you take it to moddingdev then 🥀
wdym
Am i supposed to take it to modding chat?
sdm crash
unless you were modding and this happened yeah
cause this looks like a crash with a diff mod
what does this mean
you took ownership of a tarot yes
I believe you need to fallback to self instead of card in some cases, like the collection? I'd like to see the error first though
yes
if we could have images this would be 1 billion times easier
i did not change the set
ok carry on then
it's probably lars' thing since balalala uses self
When exactly is a UI element method func called? The wiki says when it is being drawn, but is it called every frame then?
@manic rune
how does this look?

give me a sec because when the code here #💻・modding-dev message says bad argument to min its apparently because its giving a table and not a number
it's... it's so peak
Do you have Talisman installed by any chance?
its in a folder elsewhere (not in my balatro mods folder)
Weird. In that case I'd still like to see the error haha
lemme get back to you on that after my sisters done dragging me to the store to get groceries
ik i wasnt asked but since its here, i love this
I think it's more helpful than the current version, right?
is there anything you think it could have extra?
i think that approach is much better than the current one
putting one joker's "why is the function triggering twice" on the back burner to ask another's
"why isnt this triggering at all actually"
only other thing i could think of is a section summarising some of the different variables (like context.scoring_hand for example) and maybe a summary table of all the contexts and their uses
all of the contexts for real this time
you dont return anything
it's always the simplest answer huh
thats already here lol
then as far as im concerned this is gonna be a good guide 🔥
i do think a summary table would be good depending on how long the page ends up being
also im not sure if SMODS.calculate_effect was ever covered properly? if not then thatd be very helpful
ok now my joker is scaling when i purchase a food joker, but the game crashes when reloading, saying its attempting to index the value "card"
local c = context.card.config.center_key
if context.buying_card and not context.blueprint then
if c == "j_gros_michel" or c == "j_cavendish" or c == "j_popcorn" or c == "j_ice_cream" or c == "j_ramen" or c == "j_egg" or c == "j_turtle_bean" or c == "j_seltzer" or c == "j_diet_cola" then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
return{
message = 'Stocked!',
}
end
end
specifically happening on that first line
context.card doesn't always exist.
im guessing the solution is to move the first line to be inside the if statement?
so do i need an if statement to check to see if it exists first?
yeah all the util stuff is already done, I'm just rewriting the context documentation now
what do you mean by a summary table though?
maybe literally just a table of the different contexts names and the descriptions for them
so its easier to see which context you might need to use
that'd be sick actually
can I modify the effect of another joker through post_trigger? does changing context.other_ret work?
would try it myself but not home yet just brainstorming some ideas and trying to figure out how annoying this kind of thing would be to implement
<@&1133519078540185692>
have you tried reading the smods wiki
wdym by modifying the effect?
that would be enormous
change the joker's return table
and just replicating information

