#💻・modding-dev
1 messages · Page 519 of 1
remember, hooks are global and can be accessed anywhere
but it doesn't it like it when local variables are defined outside of a function or something
oh nbm
nvm
it has to be outside of the smods bracket
i was boutta say ur still inside a table lmao
need to do it outside of everything
why is the joker activating twice? it's only supposed to activate once after a boss blind is defeated, but I see nothing out of the ordinary
calculate = function(self, card, context)
if context.end_of_round and (not context.blueprint) and G.GAME.last_blind.boss then
local jokers_to_create = math.min(1, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer))
if jokers_to_create <= 0 then return end
G.GAME.joker_buffer = G.GAME.joker_buffer + jokers_to_create
G.E_MANAGER:add_event(Event({
func = function()
local card = create_card("Joker", G.jokers, nil, nil, nil, nil, pseudorandom_element(card.ability.extra.jokers, pseudoseed('chef_joker')), "chf")
card:add_to_deck()
G.jokers:emplace(card)
card:start_materialize()
G.GAME.joker_buffer = 0
return true
end
}))
card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Bon appetit!"})
end
end
need context.main_eval with the context check
thank you! this was driving me crazy
what exactly is the difference with context.main_eval vs without
so if context.end_of_round and not context.blueprint and context.main_eval
k wow that was literally it
i myself dont know much about it other than the fact that it prevents any duplicate triggers at end of round
good to know
it's because end_of_round is also called with individual and repetition
got it got it
ease_background_colour = function(self)
ease_colour(G.C.DYN_UI.MAIN, HEX("cc3b49"))
end,
create_card = function(self, card, i)
return { set = "Shape", area = G.pack_cards, skip_materialize = true, soulable = false, key_append = "btct_ShapePack" }
end,
in_pool = function() return true end
}
How can i make the background color correct?
Could someone help me with this function? I'd like jokers to shake when a particular consumable is owned, kinda like invisible joker. I'll add more parameters, just want the basics working first.
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
if G.jokers and SMODS.find_card('c_willatro_boost') then
for i = 1, #G.jokers do
local eval = function(card)
return not card.REMOVED
end
juice_card_until(G.jokers[i], eval, true)
end
end
return SMODS_calculate_context_ref(context, return_table)
end
Why are you hooking SMODS.calculate_context?
Also it's G.jokers.cards
idk where else I'd put it, and changing it to G.jokers.cards didn't make it work.
You would probably put it in the add_to_deck of the consumable.
remind me again how the path system works within the lua code
say i wanted to refer to image [a variable for X image file] in folder custom
would it be Wash.path .. "custom/" .. image
-# Wash being my mod thing too btw lol
or am i missing smth here
i think if Wash.path is referring to ur mod directory then ur fine
oh wait i think i know what i did wrong
if you're using an atlas you need to put it in a pseicifc spot and just use the file name (see https://github.com/Steamodded/smods/wiki/SMODS.Atlas)
you'd have to do Wash.path = "" .. SMODS.current_mod.path or something at the top of ur file
i dont remember the exact name of the function that gets ur mod directory
No, because it's not a function.
It's SMODS.current_mod.path
oh right
not at my laptop so i dont quite remember the way to get the mod path
fixed it
No, it's SMODS.current_mod.path not SMODS.current_mod_path also remove the "" ..
interesting reaction but what am i even doing wrong
huh, i saw that little "" .. SMODS.current_mod.path pattern in a lot of other mods
You need to put card.ability.eternal = true in a function.
put what in a function? sorry if this is really dumb i havent coded in a while
card.ability.eternal is not a valid key
(you can just put eternal = true in your config and it will be put in the ability when created)
((i think))
you could probably do smth like card:set_eternal(true) if nothing else id reckon tho youve probably have to attach it to other stuff like add_to_deck
-# or self:etc i forget which would work best for the consumables, depends on if IT or the card it affects is eternal
something like this?
no
sorry i'm trying my best but this is still confusing
How do i do custom loc_vars with planet consumables?
Anyone know why this makes the joker only shake once? I want it to continue shaking like invisible joker.
local oldaddtodeck = Card.add_to_deck
function Card:add_to_deck()
if self.ability.name == 'Boost' then
for i = 1, #G.jokers.cards do
local eval = function(card)
return not card.REMOVED
end
juice_card_until(G.jokers.cards[i], eval, true)
end
end
return oldaddtodeck(self)
end
No, I meant the add_to_deck function of the consumable.
Will that actually change anything though?
Yes.
It wont break when other cards with the name of Boost are added to deck.
For my efforts the past few days, artist crediting for decks
hey how do you make decks?
in the github there is no information about how to code them
Incorrect fwiw https://github.com/Steamodded/smods/wiki/SMODS.Back
because thats what they are called internally
oh
how do i check if a specific voucher is being used?
I've been trying to make a deck for the past three days but i still haven't managed to find a context.voucher_use or anything similar
please help 🥺
the deck in code referes ussually to your cards, where as the back is what effects you have
context.buying_card should be called when buying a voucher I think
No yeah they're referred to as "backs" in the game. For the purpose of organization in my mod, I have all my folders and stuff refer to them as decks and then my loading helper function just does this to call the SMODS API
if item_type == 'Deck' then smods_item = 'Back' end
OH
How would I make a Joker that spawns a random Joker and then destructs itself? By a random Joker, I mean literally any Joker in the collection.
How do I make this stop? The jokers continue shaking after selling or using the consumable.
add_to_deck = function(self, card, from_debuff)
for i = 1, #G.jokers.cards do
local eval = function(card)
return not card.REMOVED
end
juice_card_until(G.jokers.cards[i], eval, true)
end
end
You would name the card input in the eval function something else.
you should use the contex.on_sale or the remove_of_deck
context.on_sale doesn't exist.
i didnt write it accurate, but i remember that exist, is what use the diet cola in the vanilla recreation to give you the double tag
It's context.selling_self and that doesn't cover using it.
also, how do you make the code appear in that black square?
`Code here`
oh, sorry, i just started to mod the game, so i dont know much about coding
lol same
still trying to figure out how to actually tell when a specific voucher gets bought
making great progress though
Sorry, I don't understand what you mean by this.
add_to_deck = function(self, card, from_debuff)
for i = 1, #G.jokers.cards do
local eval = function(card2)
return not card.REMOVED
end
juice_card_until(G.jokers.cards[i], eval, true)
end
end
Ah, that makes sense
what its the use of for i = 1, #G.jokers.cards do and local eval = function(card2) ?
for i = 1, #G.jokers.cards do is so it loops over every obtained joker and local eval = function(card2) is so juice_card_until knows when to stop juicing.
would happen something different if i put card1 instead of card2?
No, because card2 is unused.
No, the reason for it is to not declare the same name as the card passed into the add_to_deck function
local eval = function what is it use apart from the card shaking thing?
Nothing.
so why is there?
For the card shaking.
srry if im being repetitive so local_eval is only for the shaking, or does nothing?
can i use it for other things?
It's just declaring a local function for the purpose of the card shaking, it does nothing on its own.
ooooohh
another code question, how i can modify the talk jimbo (things like the sprite or the dialogue or the sounds)? like cryptid with the jolly joker
Is there something similar to this like that doesnt exist
selected_card:get_seal() == "Red"
ok thx
Is there a way to just give a booster pack a table of joker keys to choose from?
hey folksies!! so this bit isnt working (ive already sent this before but it still aint workin unfortunately). any ideas?
What isn't working about it?
well, it aint doing anything.
i redeemed it once in a run and whenever i used tickets again, i got no money at all
Are you using NotVanilla.Tickets instead of SMODS.Consumable when defining the tickets?
no, not really
they all have their set as NotVanilla.Tickets, but i make them using SMODS.Consumable (see this image for example)
balatro modding ate my dog
dont become one
that is all
is there a way to get both the card being sold and the joker itself in the same context? I'm trying to make a joker that gains mult equal to the card's sell value but I don't have a reference to both the joker and sold card at the same time since card is only ever one or the other
Yes, you need to use NotVanilla.Tickets instead of SMODS.Consumable
the sold card is context.card
yeah, but that means there's no reference to the joker so I cant scale it
No, card is the joker.
card is always the joker.
Unless you overwrite it.
got it. card vs context.card was totally confusing me
mehhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
that makes it so much clearer thanks
so instead of writing
SMODS.Consumable{
key = 'blahblahblah',
...
end
}
i should write
NotVanilla.Tickets{
key = 'blahblahblah',
...
end
}
?
Yes, but you wouldn't have to include set
oh, so i can just remove the set
sweet
doesnt that interfere with SMODS.add_card() though
No.
oh nice
You set the set in NotVanilla.Tickets so it sets that for you.
They did, I think, they just didn't want to write the same use function for all of them.
makes sense
it's still weird to make a consumable group where all of them use the same use but i can see it
on the money
How would I detect how many rounds its been?
speaking of which
oops
okay i made it so NotVanilla.Tickets = SMODS.ConsumableType{} however
No, change it back.
Did you define it before making the tickets?
oh, okay
im assuming the ConsumableType doesn't do that automatically
No, I mean is the NotVanilla.Tickets = SMODS.Consumable:extend line before or after you're defining the tickets?
oh, after
let me put it before
nothing changed
hold on
might be something to do with the replace thing i did
oh it was
sweet
thanks Somethingcom515
youre a real one
alright i can now ship the update! :]
my dice all have the same use function: they just roll themselves, disable further using, and then go back to the consumable cardarea. the fun stuff is in their calculate functions :3
we call it not writing 200 lines for something that takes 10
maybe i should go set up dice as an SMODS.Consumable:extend now that i think about it
(i just made each consumable's use function call a single helper function and do nothing else, but it'd probably be a little cleaner to do the extend instead)
how does one make zee mod god this is tricky
why luaaaaaaaaaa 😢 🤚✋

practice makes better :)
heres a good question... how would you make a card that adds like 2 mult every round you dont play hearts? 💔
something something
if context.individual and context.other_card:is_suit("Hearts") then
card.ability.extra.mult = 0
return {
message = localize("k_reset_ex")
}
end
something something
if context.joker_main then
return {
mult = card.ability.extra.mult
}
end
something something
if context.end_of_round and context.other_card == card then
card.ability.extra.mult = card.ability.extra.mult + 2
return { message = localize("k_upgrade_ex") }
end
i typed all that from memory so some of it might need double-checking against actual documents
Bump
i believe that's G.GAME.rounds
#1228149931257237664 is useful for finding this kind of thing
G.GAME.round
Thanks
is there a conceivable way to override another mod's atlas with your own cus i cant figure it out
Yes.
I'm trying to have a joker detect if a foil joker is present, but I don't think its detecting properly. Could anyone help?
if context.joker then
if context.other_card.edition and context.other_card.edition.type == "foil" then
return {
mult = card.ability.extra.mult,
play_sound = ('btct_MichaelKaboom'),
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.3,
blockable = false,
func = function()
card:remove()
return true
end
}))
}
end
now balatro hates my .json.
how are those usually made?
context.joker doesn't exist.
Oh, that explains it. Thanks!
how would i do that ?
SMODS.Atlas{
key = 'modprefix_key',
path = 'path.png',
raw_key = true,
px = 71,
py = 95
}
it didnt work
SMODS.Atlas({key = 'bunco_jokers', path = 'Jokers/Jokers.png', px = 71, py = 95}) - original mod's code
SMODS.Atlas({key = 'bunc_bunco_jokers', path = 'Bunco Repainted/Jokers.png', raw_key = true, px = 71, py = 95}) - mine
is there something i'm typing wrong ?
(to clarify it didn't crash it just didn't apply the change)
Is there a Bunco Repainted folder in both 1x and 2x?
why is it crashin....
Log?
one sec
I'm trying to make it to where when my joker detects a played foil card it self destructs, which works properly, but if the played hand doesn't have a foil card, it crashes the game with the below error:
Oops! The game crashed:
main.lua:3651: [SMODS Batrocities "items/jokers.lua"]:1383: attempt to index field 'edition' (a nil value)
Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-0615a-STEAMODDED
Here's my code:
elseif context.individual and context.cardarea == G.play and context.other_card.edition.foil == true then
return {
message = 'NOOO, MICHAEL!!!',
play_sound('btct_MichaelKaboom'),
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.3,
blockable = false,
func = function()
card:remove()
return true
end
}))
}
end
add and context.other_card.edition before the and context.other_card.edition.foil check, you need to check that edition itself exists on the card (if there's no edition it doesn't exist)
Oh, okay. Thank you!
damnnn bro i just wanna put toothpaste in balatro
ignore the author, thats my steam name. i still made it.
SMODS.blueprint_effect calls Card:calculate_joker() which is the function you're hooking.
did what the debug menu told me to do and did take_ownership
SMODS.Atlas:take_ownership('bunc_bunco_jokers', {path = 'Bunco Repainted/Jokers.png'}, true)
and it gave me this error
well crap
Perhaps try checking not context.blueprint?
Does Bunco Repainted/Jokers.png exist in both 1x and 2x in the assets folder?
would it make sense for me to copy this and use the hook instead of calculate_joker
yes i said this already and it didn't do anything different
No, because that and SMODS.blueprint_effect are basically the same.
like this?
Yes.
Have you tried removing recursive_check and just running it once?
it shouldnt affect anything, but i will check later, thanks (i got classes to go rn)
How do I make a joker a custom rarity and a legendary
And rarity = 4
Yum
Cause I made a Teto rarity but I also made a Teto Legendary
I want to have a pool of tetos but have that legendary come from a soul and not a shop or pack
Any Idea where I can check how SMODS.calculate_repetitions work?
There is not wiki for it as good as I know, but where can I look up the code of it?
Oh wow! Thanks :D
how would one make a custom deck? my dumb idea is “Chessed Deck” where it’s just checkered deck but with Clubs and Diamonds instead of hearts and spades
key = "checkered",
pos = { x = 1, y = 3 },
unlocked = false,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Clubs' then
v:change_suit('Spades')
end
if v.base.suit == 'Diamonds' then
v:change_suit('Hearts')
end
end
return true
end
}))
end,
locked_loc_vars = function(self, info_queue, back)
local other_name = localize('k_unknown')
if G.P_CENTERS['b_black'].unlocked then
other_name = localize { type = 'name_text', set = 'Back', key = 'b_black' }
end
return { vars = { other_name } }
end,
check_for_unlock = function(self, args)
return args.type == 'win_deck' and get_deck_win_stake('b_black') > 1
end
}```
idk how much this helps but here's the vanilla remade code for it
(checkered deck)
im assumign you could just swap the suits to make it like this
key = "chessed",
pos = { x = 1, y = 3 },
unlocked = false,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Spades' then
v:change_suit('Clubs')
end
if v.base.suit == 'Hearts' then
v:change_suit('Diamonds')
end
end
return true
end
}))
end,
locked_loc_vars = function(self, info_queue, back)
local other_name = localize('k_unknown')
if G.P_CENTERS['b_black'].unlocked then
other_name = localize { type = 'name_text', set = 'Back', key = 'b_black' }
end
return { vars = { other_name } }
end,
check_for_unlock = function(self, args)
return args.type == 'win_deck' and get_deck_win_stake('b_black') > 1
end
}```
.
it was indeed the case
im sorry for doubting you somethingcom
sob
Somethingcom, red x mark react this person
i think i can easily fix this though, just, not use calculate for increasing mult gain and stuff
Bet you wish that operator pr was implemented
true
Yes, because you're passing in t instead of vv
testing changing the rank of cards with this code but its currently doing a boatload of nothing
isnt it Q and not Queen
Have you put a print in there to check if anything there is actually triggering
oh nevermind its Queen, hm
ill try it
card here is the joker.
It would be context.other_card
Oh yeah
In the change base function
I'm very observant /s
same
god damn it. same thing as last time!!
like this?
Yes.
how do you add tooltips for tags
info_queue[#info_queue + 1] = G.P_CENTERS.tag_negative
?
I did it like this
info_queue[#info_queue + 1] = { key = 'tag_EF_small_plant_pack_tag', set = 'Tag' }
Idk maybe both work
this is vanilla tag tho
fuck me
Can't you test it
Be at least somewhat independent of modding dev
im independent alright
actually i have no idea what that word is
besides decolonization
thanks
is G. customizable?
looking at this code, i wanted to give a joker a long message like this joker
yeah, you don't need to save it to G tho unless you need to reference it in other places
just save it in a local
G is a table after all
if you still wanna use p_centers mode (for example tags with unique info, like orbital) this is not the right way to reference a tag center
all tag centers are in G.P_TAGS
thanks
i see
alright
so like, how would i do it
instead of G.beemoviescript = ...
you do local beemoviescript = ... before the joker code
oh in yahimod
its saved in here
so i just do local inside of the loc?
no, it needs to be in the same file
if it's in another file it does need to be saved to a global table but I would recommend you use Tangents or something if you have one
but it doesn't need to be saved to localization
and it's actually weird that it is lol
that mod is a wonder
fair
alright
for his first mod id say its super impressive already :3
you cant expect a first-timer to know how we usually do stuff
are you proud of me? 🥺
asides from the naming, yes
NO!!!! /j
D:
Why don't you put it in your global mod variable?
im deleting tagnets
(If you have one)
magnets??
metalheads
bru
Wdym which
Yea why do you assume you have multiple ones
Prediction: "I'M NEW"
IM NEW
nxkoo....
My init of a global table looks like this
local function EF_table_init()
return {
vars = {
jokers = { grapevine = {}, },
minigames = { minesweeper = {}, parlor = {} }
},
FUNCS = { UIDEF = {}, UI = {}, minesweeper = {},},
}
end
EF = EF_table_init()
Don't ask me why it's a function
mine's a mess
At least you somewhat use your variable unlike a certain someone
all my things are directly in the global table, i cant be bothered to remember if something is in funcs or utils or whatnot
this is why single file mod wins
hmm
With how messy your code is I'm not surprised
DAMN
Just use auto complete smh
N' if i were you, i wouldnt take that
it's true
I didn't mean to be rude 😭
I do the same thing anyway
N have you ever checked Siralim Balatro's code?
i dont like reading other people's code sorry
Fair
yes
don't use mod
if you need to change the message there are proper ways to do that
such as
xmult_message
I have so many questions
= { message = "message", colour = color }
Thanks N
G.C.RED
no no like
Like what
please use for loop
these mustard related settings are terrifying
:3c
Whats the Mustard thing
its for
something
EITHER WAY I NEED HELP
it crashes
Idk what you want to accomplish
what does anything have to do with balatro
Honestly that’s a good point
[i’ve been waiting inline for the past 5 minutes] to buy a figurine
its a warning
"kendih" beautiful
KENDRICK IS COMING
so like
i want to show this as the xmult message
and here's the code
Xmult message only returns once i believe
What does nxkoo_dies contain
This should work in theory .. have you checked the code of yahimod ?
bee joker jumpscare
the global
its like
hold on
god i have to install the mod again
I think that’s the inspiration of nxkoo
correct
same code from yahimod
btw
what's the issue
The entire script
it doesnt show up the message
it doesn't crash?
do you load the file with the text
the what
the file that has the G.whatever
G.nxkoo_dies
if context.joker_main then
for i = 1, #G.nxkoo_dies do
card.ability.extra.xmult = 3
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
blocking = false,
delay = 0,
func = function()
card_eval_status_text(card,'extra',nil,nil,nil,{message = G.theworldcrispiestfries[i]})
return true
end,
}))
end
return {xmult_mod = card.ability.extra.mult}
end
what N' meant is, did you load the file that has G.nxkoo_dies
it has to be loaded else that doesnt exist
its not nxkoo_dies tho
it's the fries one
shouldnt it be G.nxkoo_dies.theworldcrispiestfries?
OH
do u think i know what tangents organization structure is
LMAO
same, im just assuming though
since this seems like its being stored in a table
and i would fucking crash out if its not G.nxkoo_dies
😭
GOOD
IM NOT THAT BAD
you do seem like the kind of person to make like 10 global tables for no reason 😭
where do i put this
what.
what
replace the G.beenoviewhatever in the original code with that
nxkoo you fell off in my heart 🥀
IM ENEW
im emu otori
Wonderhoy reference out of the blue
oh now its not giving me the mult
whats the code
hold on
also its xmult_mod so there wont be a message to tell when it gives xmult
oh
so what do
calculate = function(self, card, context)
if context.joker_main then
for i = 1, #G.nxkoo_dies.theworldcrispiestfries do
card.ability.extra.xmult = 3
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
blocking = false,
delay = 0,
func = function()
card_eval_status_text(card,'extra',nil,nil,nil,{message = G.nxkoo_dies.theworldcrispiestfries[i]})
return true
end,
}))
end
return {xmult_mod = card.ability.extra.mult}
end
end
if you are asking about the message then use xmult instead
:3 you know you can use for i,v right
the message will still appear right
yes
doesnt work
nevermind
im dumb
nxkoo found dead in the alleyway yesterday
D:
How do I make a joker that multiplies the values of the joker to the right? I’m looking to make one that looks for certain values within a joker, then multiplies them by a certain amount. (also yes, this is in the joker code too)
It also ignores any values within “immutable” or whatever.
I don’t think they’re active
I "had" a Joker that multiplied all values on a given Joker, save for ones that have .immutable attribute, but then I changed it.
Did it have original code?
iirc I did write most of it manually, if not all of it.
Like it doesn’t use the cryptid’s own code?
Don't think so, despite Cryptid being the idea for it back then.
Here's the snippet from 1.7.1d of it.
ok so i'm not nerdy enough to completely understand this joker
...that's fair, and I'm not exactly in any mental capacity to explain things currently. 😅
im doing my english practice test rn but uh
function table.modify(table1, modifications, exclude, from) --Changes all the values of a table.
local ret = table.clone(table1)
for i,v in pairs(ret) do
if not table.contains(exclude or {}, i) and not (type(v) == "number" and v == 0) and not (type(from) == "string" and from == "immutable") and not (tostring(from) == "ability" and type(i) == "string" and (string.find(string.lower(string.gsub(i,"_","")), "xmult") or string.find(string.lower(string.gsub(i,"_","")), "xchip")) and (v == 1 or v == 0)) then
if type(v) == "table" then
ret[i] = table.modify(v, modifications, exclude, i)
elseif type(v) == "number" then
ret[i] = ((v + (modifications["add"] or 0)) * (modifications["multiply"] or 1)) ^ (modifications["exponential"] or 1)
end
end
end
return ret
end
BalatroSR.modify_ability = function(card, modifications, exclude_add) --My version of a function that changes Jokers' ability table. :3
local exclude = table.add({"order"}, exclude_add)
local modified_ability = table.modify(card.ability, modifications or {}, exclude, "ability")
card.ability = modified_ability
return modified_ability
end
this is what i do
oh, im missing a few functions
function table.clone(table) --Clones a table.
local ret = {}
for i,v in pairs(table) do
ret[i] = (type(v) == "table" and table.clone(v)) or v
end
return ret
end
function table.add(table1, table2, all_add) --Adds/replaces all the value of table2 to table1.
if not table1 or not table2 then return table1 or table2 end
local ret = table.clone(table1)
if all_add then
for i,v in pairs(table2) do
if not ret[i] then
ret[i] = v
else
if type(v) == "number" and type(ret[i]) == "number" then
ret[i] = ret[i] + v
elseif type(v) == "table" and type(ret[i]) == "table" then
ret[i] = table.add(ret[i], v, all_add)
else
ret[i] = v
end
end
end
else
for _,v in ipairs(table2) do
ret[#ret+1] = v
end
end
return ret
end
table.add isnt as menacing as you think, its just adding stuff to a table
So what's the requirements for a joker to be able to modify any value of a selected joker?
that's why "immutable" is a category
mhm, which my function should already account for shrug
my test will end about an hour later, if you are still free by that time then i would be happy to help
sorri
it's ok
hey uhh im trying to make a deck spawn jokers but it keeps crashing, any fixes?
you need an event
go smods documentation and search for event manager if you dont know how to make one
kdsma'
either i wanna make my own code or i can snatch from an existing source.
otherwise, scratch the whole idea altogether and move on without any value manipulation jokers.
If I wanna make my own code, that would require me to read through the entire lua documentation AND the entire steamodded api documentation. And I have ADHD so I will be spending maybe a year or two, without doing anything at all.
If I wanna snatch from an existing source, I would probably be called out for plagiarism.
Take the risk or leave it?
//nvm it just decided to work lmao
Lua is a very easy language
Didn't follow any tutorials at all, just improvised using my python experience
The other documentation isn't bad either
Python guy talking to bitchass who doesn’t even know how to CSS
i second this, ive only been using lua for about 2 weeks and its the easiest bit of programming i have ever done in my life
I barely know python either
Don't know much CSS
It's genuinely a very accessible language which is why balatro is made in it
The lua extension is very helpful as well
And the people here are lovely and knowledgeable
i dont even know what a CSS is
the hard part is the balatro quirks
Is it “So easy even Chowder can write code for a food joker” easy?
yeah
i would say lua is pretty straightforward once you understand its shenanigans
once you get the hang of it you can fly through it. i made like 20 jokers in a couple of days
food jokers shouldnt be too hard, unless you are digging into more complex mechanics that would need to interact somewhat with the base game code more
It's the data that determines styles for websites
also, i think paya has a joker you are looking for?
ah
it multplies all values of adjacent jokers by twice
Yuppers
Or you can use JokerForge (I have not used it but I've heard good things)
It’s simple really, all I really want is to make a “value manipulation” joker, nothing more, nothing less.
Like Gemini
Dongtong
i hate it
i tried it and it was too limiting
Whatever the fuck y’all made
with all of this said, value manipulation is kinda hard tho
like you can just copy what someone else made but understanding it as a beginner is a bit more complicated
^^^ sounds simple but messing with values across jokers is a bit tricky I can imagine
value manipulation is very much prone to unintended bugs too
;3 thats why i made a function to do that but never used
this is why i try to not touch jokers that are not from my mod
if you stick to being self contained everything is easy
anyways i got an essay and a graph left, i will see yall later
go study
So I should drop value manipulation altogether?
what do you want the joker to do?
im just giving you information for you to make informed decisions, it's your choice
Multiply the values of the joker to the right by #.
The more consistent and less buggy you want it to be, the more effort and time you'll have to spend on making and testing it
Paya's definitely has the most straight forward implementation, but yeah, the reason it's hard to set up has to do with crossmod compatibility. Though, even with vanilla jokers, you'll have to hardcode in the exceptions. The issue you'll have is that the way balatro's set up means that values aren't separated by changable or unchangable, nor by internal vs player facing, so you need to choose an approach to deal with those
The issue is also that value manipulation in that method is based on copying and storing values, which has quite some overhead, and means you need to ensure your code's set up to deal with it, because it's very easy to get a stack overflow that way
Mayhem really likes it’s Planet Cards.
Ok then I guess i’m sticking to uhh… I guess make the specific joker a cross-mod joker
Where it only shows up when cryptid is installed.
I'm planning on making my own value manipulation system an API mod at some point, but it's got the classic issue of needing mods to put in quite some effort to be properly compatible
Hope to use it someday.
'tis why I might've overproofed(?) my value manipulation functions back when I used 'em. 😅
Yeah, same reason mine's only compatible with my own jokers, haha
Imagine the api only works with vanilla and mods that have the api
...although mine wasn't restricted like that-
Any other mods with their own value manipulation are left untouched.
that'd be how I'd implement it, I reckon. It's either that, or Cryptid's approach, I've not found a way to marry them
yo why is my editor showing a type error
Unless it’s like cryptid and entropy, where they have specifications.
this is indeed how to apply enhancements correct?
Um
yeah, that should work. It probably does not recognize that string as a proper key
if you hover over it it will tell you the problem
spoiler: there is no problem, ide doesn't know
How I do it currently in Kino is that my value manipulation doesn't work unless Cryptid's installed, as far as the jokers for other mods. With Cryptid installed, it's able to convert the type of manipulation to Cryptid's type and work from there
do you have that vanilla balatro lsp
yeah
it seems to not have the smods changes to the function
I wanna be able to do it with yahimod at some point.
BURN talisman
I think I’ll just wait until Ice’s Value Manip API is released
i see, though i do wonder if eremel would even merge it 🤔
I plan to make a voucher for making fantastic jokers show up in the shop.
I believe it’s weight manipulation that gets it done.
Good schmorning chat
Morning dilly
How are you winter
Mmm
I laid down at like
2 or 3 qm
Am
well thats decent enough lol
It depends how jank it makes programming
Hello everyone
Hi eremel
hi dilly
Hello, is it possible to change the name of the regular suits through modding? I made a custom set of cards and right now, the suits don’t match the artworks so it’s confusing
Hi N!!!
I hope one day you will spot me
Got a technical question, what is the best way to refer to a custom rank in a joker. c.getID is what normal jokers do, but they don't work for customs.
loc_vars = function(self, info_queue, card)
return {vars = {}}
end,
calculate = function(self, card, context)
if context.pre_discard and not context.blueprint then
if ((function()
local rankCount = 0
for i, c in ipairs(context.full_hand) do
**if c.base.value == "rfCAV_Tradesmen" then**
rankCount = rankCount + 1
end
end
It's just the bolded part I need help with. When you discard the tradesmen then you should proceed.
meanwhile i made a new mod lmao
I only just got here
“Creates a random consumable for each unscoring card”
Balanced as a fantastic joker or nah?
Come work for me bepis ill give you 100 to fix my mod
naw
Lmao
i would probably take that if i were still playing hsr 😭
card.base.value
patch lines..........
hooks do NOT exist in his head whatsoever..............
do you believe in pirates dilly
yar har
Is e_dollars a valid value 😭
i dont think so
i have to figure out either how id turn some stuff into hooks or if someone at some point would be nice enough to get rid of my patches that can be hooks
how do I make a consumable that does /4 chip requirement and -1 hand size only for the round
Patches are for when you need to change how something works or add a step midway through a process
Hooks are for things that run before or after the whole process has completed
Idk if that helps at all
i know what theyre for, im just inept
My guess is that you make it so it sets a global variable to true
And you check when the blind begins if that variable is true, if so then reset the variable and change the required score
That's my guess
Ah fair
Good luck
Look at my hard work Dilly
That said I'm gonna need to add this same credit to Galdur unless it already has some framework for it, since lots of people use Galdur
also how do I make a joker that guarantees that my custom consumable with soul_rate spawns in all booster packs that could contain it
youre so freaking hot and beautiful and awesome
this looks fantastic
you should add gradients to the art
text
like the artist credits themselves
so if the artist credit is thewintercomet
thewintercomet is a gradient 
That’s cool but I wouldn’t put that in galdur like that
bump
I just think it looks a bit wonky like that
the only mods ive ever had besides my own installed are kino, and tomas mod
both were to help fix them lmfao
Though I dislike the general rounded bubble aesthetic the game provides as a whole
I don't mind it much. I tried to make the bubble edges less round though I was having issues
Regardless I'll probs just end up basically doing the same thing, thinning the description box if present and adding the credit underneath
........
I think I just realized that, if multi boxes are supported for this, I might not have needed to do this at all
Fuck it we ball
The benefit of the added node is the added title, whereas multi boxes would require a more standard organization and just saying "Deck art by [name]" without any additional formatting
And it would also run into the same minimum height problem I think, since I forced the text to be really short
yeah it looks better with the title
Hmmm yeah I'll stick with it. Ill probably test to see what happens if you use multi boxes though
holy schmoly guys my orbs are waiting
dont play with your orbs dilly
Bump?
i dunno how to do that, sorry
im straight up pondering my orbs
Dilly you promised you wouldnt orb it anymore
yumby orbz..................
they beckon me........
but what if it was always meant to be me.......
DILLY NOOOOO
if i want to make a joker with an animated texture do i do the same thing boss blind textures do
no
you need to do it manually in an update function
i would recommend looking how other mods do it
For now
are you merging that aure pr
:3 i remember giving nxkoo the function to have animation triggers
thunderedge had a pretty good bit of assistance provided for a variation i also use now
what's the trigger for the start of the round?
context.setting_blind?
look here, i have a pretty good solution if u dont want to deal with hooks
https://github.com/ThunderEdge73/Multiverse
specifically misc/util.lua
hey youre the fellow i complimented moments ago
should work for jokers and consumables
and anything that isnt compatible with an animated atlas
sry imma need to learn how to do uis before i help with ur uis
sob
the secret to ui is to not do it
@modern kindle I've got your 240 finally btw
dont say sike rn
How do you use create_card() to create a negative joker?
more like SMODS.mid_card
SMODS.add_card{ set = "Joker", edition = "e_negative" }
FUCK NO I MISCOUNTED ITS A 238
what
im selling winter
+$4
how do I use this to make a specific joker?
add key = "your joker key"
Sorry I thought with the spare tally it was 248 after the tenth
thanks gang
It’s only on my todo list for now
how long is your todo list
Uhhh
sigh
i say this noting id be lucky to break 100 points
eremel working on ortalab, smods new documentation and managing prs at the same time:
You say that with the confidence that I’m working on documentation
nobody needs documentation anyway if you think about it
the documentation is your own brain
thats what im sayin
I'm still up to help with documentation Eremel 😔 what isn't being handled by Gauntlet and co anyway
what is gauntlet and co
Gauntlet appears to be a contributor to the wiki and co are other people I've seen do documentation PRa
This is my attempt at making the second card retrigger by altering the code for hanging chad:
if (context.other_card == context.scoring_hand[2]) then
return {
message = "So Charming!",
repetitions = self.ability.extra,
card = self
}
end
end
It keeps crashing, and I'm sure there's a way better way you guys know of
oh flowwey
remove card = self
and just, dont use self :3
replace self with card
I mean, feel free to write stuff Winter, I just don't have the time nor motivation to review wiki PRs
if you are copying effects from vanilla jokers then id recommend doing so from vanillaremade instead
Winter my goat
trying to make a face card skin, but this keeps happening, any help?
the line of code that seems to be breaking is
if v.config.card_key ~= suit_data.card_key..'_'..SMODS.Ranks[d_ranks[i]].card_key then
Oh is that flowwey?
ye
holy flashbang
SMODS.add_card { set = "Playing Card", rank = "King" }

ohh ok on the smods docs it doesnt show the {} it has ()
SMODS.add_card({ set = "Playing Card", rank = "King" }) works too
but the argument is a table
got it
is there a way i can make it do an animation when the card is created like marble joker?
@modern kindle are you happy now
nooooo youre supposed to give me all the answers!!!!
:3
how to do shaders theres no doc on Steamodded wiki
i simplified it for vanillaremade too
Youre nothing but perfection
The ground you walk glistens and turns to gold
All you are and all you ever will be is beyond that of mortal comprehension
The examples repo would probably be a place to start
examples repo?
still having this issue, any help??
where I find those
oh I found
wth is that
this is a shader
Where I can actually learn about making shaders?
are these open gl shaders?
oh its open gl shaders
I'mma read documentation about it
Should I do a lovely patch or hook a function to make booster packs have 0 options when I have a certain joker?
hook
or lovely patches whatever u wanna do
I just find lovely patches weird
i was asking those who have a clue
I have a clue
then why did you respond by saying nothing
Because it literally doesn't matter
the whole thing guhhhh
Just stop wasting ur time and do whatever u find best
hey, how can i make a joker to debuff certain cards?
And yeah Love2D shaders are GLSL shaders with a slightly outdated version of the language by default and some strange aliasing for certain functions
It's like version 1.2 or smth?
You can force it to use GLSL 3 with a preprocessor directive while I had to do for a couple of mine, but supposedly it's not recommended for device support
I was reading the latest version 💀
now im getting this error??
can i see where ur atlas is defined?
which cards and when
SMODS.Atlas{
key = "GooberlandsSkin",
path = "GooberlandsSkin.png",
px = 71,
py = 95
}```
https://github.com/Steamodded/smods/wiki/Utility search for "SMODS.debuff_card(card, debuff, source)", this should give you some useful info!
example, aces, numbered and faces, and whenever that joker stills in yours slots
idk how to use utilities function
huh, can i see where u are trying to use the atlas then
I would use context.debuff_card check if the card is one of those and return debuff = true
for _, s in ipairs(suits) do
SMODS.DeckSkin{
key = s.key,
suit = s.suit,
loc_txt = {
name = "Gooberlands",
text = "Goobering my lands!!"
},
palettes = {
{
key = "hc",
ranks = {"Jack", "Queen", "King"}, -- only skin these
display_ranks = {"Jack", "Queen", "King"},
atlas = "GooberlandsSkin",
pos_style = {
fallback_style = "deck", -- i think this is how you do it???
Jack = { atlas = "GooberlandsSkin", pos = {x = 0, y = s.row} },
Queen = { atlas = "GooberlandsSkin", pos = {x = 1, y = s.row} },
King = { atlas = "GooberlandsSkin", pos = {x = 2, y = s.row} },
},
}
},
colour = s.colour,
hc_default = true,
}
end
that is to debuff cards or for check if the cards are debuffed?
to debuff
this is my first time making a deck skin, so i have 0 clue where im going wrong
like this?
calculate = function(self, card, context)
if context.joker_main then
if context.other_card:get_id() == 14 or
context.other_card:get_id() == 6 then
return {
debuff = true
}
end
end
end
}
yo put ur mod prefix before every time u mention ur atlas
so "mod_prefix_GooberlandsSkin"
replace joker_main and other_card for debuff_card
ok ill try
beta males want to sit on the adults table
ALPHA males want to sit on the 0x0699d968 table
you need label = "Gooberlands"
in loc_txt
i think
this is funny tho
how to get mods
i used your code, even understood some of it, and now i have a scary king
IT WORKS, thanks man
can i see
local chrank = pseudorandom('rabbits', 1, 1)
if chrank == 1 then
local king = SMODS.create_card { set = "Playing Card", rank = "King", area = G.discard }
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
king.playing_card = G.playing_card
table.insert(G.playing_cards, king)
G.E_MANAGER:add_event(Event({
func = function()
king:start_materialize({ G.C.SECONDARY_SET.Enhanced })
G.play:emplace(king)
return true
end
}))
return {
message = 'Its a boy!',
func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.deck.config.card_limit = G.deck.config.card_limit + 1
return true
end
}))
draw_card(G.play, G.deck, 90, 'up')
SMODS.calculate_context({ playing_card_added = true, cards = { king } })
end
}
end
are u looking for a place to explore mods? then #1209506514763522108 is a good spot
i want to get mods
but i don't know how to add them
in what context did you do this
after
yeah that is going to cause problems with this
does it need to be in after
you can do it in context.drawing_cards
the problem is that the animation relies on G.play being empty
ahh ok
is the label still showing weird memory addresses or is it fixed?
no i don't want to make mod
i want to add mods
still showing adresses
ok i just looked at the docs again and apparently u need a loc_txt inside palettes
i have it both in deckskin and in palettes
did u add it to this code in the palettes table or am i going crazy cuz i only see 1 loc_txt entry when i think according to the docs there should be 2
yeah
i added it
heres my new code
for _, s in ipairs(suits) do
SMODS.DeckSkin{
key = s.key,
suit = s.suit,
loc_txt = {
label = "Gooberlands",
name = "Gooberlands"
},
palettes = {
{
key = "hc",
ranks = {"Jack", "Queen", "King"}, -- only skin these
loc_txt = {
label = "Gooberlands",
name = "Gooberlands"
},
display_ranks = {"Jack", "Queen", "King"},
atlas = "JCJ_GooberlandsSkin",
pos_style = {
fallback_style = "deck", -- i think this is how you do it???
Jack = { atlas = "JCJ_GooberlandsSkin", pos = {x = 0, y = s.row} },
Queen = { atlas = "JCJ_GooberlandsSkin", pos = {x = 1, y = s.row} },
King = { atlas = "JCJ_GooberlandsSkin", pos = {x = 2, y = s.row} },
},
}
},
colour = s.colour,
hc_default = true,
}
end
huh, strange, i dont know whats going on then, sry
havent messed with deck skins myself so i dont have any personal experience with fixing deck skins
is there any way to keep these as high contrast?
anks
i should probably document my anim code more clearly if more people are going to reference it lol
cause its kinda hard for me to tell the difference on a whim, and i just enjoy playing with high constrast in general
does the high contrast setting restart when u open balatro or something??
also that screenshot is of high contrast cards
hc diamonds are yellow, these are pink
WHY ARENT THEY BLUEEEE
No high contrast?
yeah i have high contrast turned on, but they're still the lc colors
I had this issue some time ago
I feel like it might have something to do with a settings mismatch if you mess with the front sprite setting code?
Because I edited something, fixed it, and then changed the original code back and it was fixed
So it wasn't actually my code that was the issue apparently
this is using deckskin
check the docs because they are super helpful
learn how to organize things so that your main lua file doesnt have over 5K lines
wow 5k lines must be a lot. im barely scraping 2k and im not the best at optimising
here's some good resources to reference while you take a look at lua docs
https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
https://github.com/Steamodded/smods/wiki/Your-First-Mod
theres is an error with my code, the cards that this joker suppose to give Xmult 1.5 are not working
if you need joker art feel free to hit me up id like to say im pretty good 😏
goes for everyone actually lol
sick art
thank you
yo wait i might actually contact u later to maybe ask u to make some art for my mod lol
feel free!!
here's the mod if u wanna take a look at it
https://github.com/ThunderEdge73/Multiverse/tree/main
someone help?
Xmult is not supposed to be capitalized
so return xmult = value_here
Xmult works
this first link, is this like a template?
the problem is the nesting of the if conditions im pretty sure
its like a reference to how you would implement the vanilla jokers with SMODS
what do you mean by "the nesting"?
finally got this working
can i see the deck lol
i want to see the art
the second if context check is inside the first when it shouldnt
we'll miss you table: 0x0699d968
BUT WHY IS IT STILL LC
still having this
IM GETTING ANGRY AT THIS 😡
are you trying to edit the atlas of bunco?
how it should be then, when i try to move, the visualcode tell me that is in the wrong place
can you paste it here
yeah? with my own mod
calculate = function(self, card, context)
if context.debuff_card then
if context.debuff_card:get_id() == 14 then
return {
debuff = true
}
end
if context.individual and context.cardarea == G.play then
if context.other_card:is_face() then
return {
Xmult = card.ability.extra.Xmult
}
end
end
end
end
did you try using malverk
you probably should
calculate = function(self, card, context)
if context.debuff_card then
if context.debuff_card:get_id() == 14 then
return {
debuff = true
}
end
end
if context.individual and context.cardarea == G.play then
if context.other_card:is_face() then
return {
Xmult = card.ability.extra.Xmult
}
end
end
end
so, let's pretend i never worked with lua before, do i have any chance at all?
For sure
did you work with any other language
you should probably learn basic syntax
have you programmed before at all?
lua is pretty easy to get into, its a good beginner language
oh, i needed the "then", thanks, im gonna credit you when i finish my mod, thanks again for the help
As long as you have some basic knowledge of how code is structured you should be fine
i have a somewhat good understanding, yes
Lua is a good beginner language as N said, and SMODS has become a pretty friendly API to use as well
if you know basic logic (what are if statements, what are variables, etc.) then u shouldnt worry too much about it
i didnt add anything, i just moved the second if block outside the first
ive gone through this far without it and i think its way too late for that
again, its just getting used to lua's syntax and how it marks if blocks and functions
if its not working then you didnt get too far
oh, srry if i a bit dumb, balatro smods is the first thing i code
yup. i will say, back then all i really learned was java LMAO, shit was ages ago, but i do know this yes
Then yeah you'll be fine!
Also you are more than welcome to come here to ask for support if you get stuck
i think it was eclipse what we used?
oh i didn’t say that i got the entire vanilla game working without using it
i don't want to seem annoying lol
Trust me, it's very hard to do that
HEY GUYSSSSS
i will say one of the most important concepts of lua is tables, which is essentially a java hashmap but with more freedom to put anything inside (to some extent)
i must ask, i see this word a lot: hash
what is that?
hashing isn't really something that needs to be worried about when it comes to Balatro modding
we did tables, but again, i'd have to refresh my memory on it
oh ok so think of a table as a mapping
{a: 1, b: 2}
maps the value a to 1 and b to 2
so if we do t = {a = 1, b = 2}
then with lua syntax we will get 1 when accessing t.a
yeah essesntially
the t would stand for table, yes?
Yeah hashing isn't some advanced level thing. Lua tables are hashmaps by default. Most lower level and non-scripting languages have to implement them in some specific structure, but Lua's front-facing script is just built on them in general
Also correct
yeah
also another note: you do not have to specify the type of a variable in advance in lua, unlike in java
<@&1133519078540185692>
<@&1133519078540185692> ban
oop
wtf
i want to learn coding, not gooning
get tf out
simply incredible show of intelligence
Bots be botting
thanks mods
Bottling 💔
yeah, i remember this was annoying
https://www.lua.org/pil/2.5.html heres some info on tables
It's mind bottling, really
i'm already a pro at one of them
🤝
is this "for dummies 101"? lol
so basically you can also change the type of a variables at runtime
its just some info on how tables work in lua
got it, i'll look into it
here is some info on tables https://www.ikea.com/us/en/cat/tables-desks-fu004/
"runtime" is when your code/program is running?
You seem to have your head on your shoulders so I think you'll pick up the structure of mods pretty quickly
Youre beautiful
Yeah non strictly-typed variables are kind of a jump when you're used to strongly-typed languages. I got frustrated at them a lot at the start because they can unfortunately hide a lot of errors
(you'd be surprised, whenever we asked basic questions, we'd get made fun of by our teachers)
yes so consider the following
local foo = 1
foo = {}
this is completely legal
Jeez
yeah, not fun
this is the whole t= and t, stuff you explained to me?
btw local is just another way of saying to the progam "hey, i'm not accessible globally from other functions"
what do you pass into info_queue to display gold seals?
