#đ»ă»modding-dev
1 messages · Page 139 of 1
john smods came into the chat
I am quite hasty, I will admit. đââïž
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.mult, -- Current multiplier
card.ability.extra.multmod -- Multiplier per dollar
}
}
end,
Create a planet card if poker hand contains exactly 2 aces
"creates" and "create" is not the same in the grammar
again, it's targeted
no i know
that implies the planet is random
why is he black and white đ
ill be honest i didn't even think of that when i was asked to make that in #đă»server-chat lmao
so just change that to Mercury or whatever hte pair is
Cool art tho
but you can do it with Two Pair / etc. too
Create a Mercury card if poker hand contains exactly 2 Aces
thanks :D
me when im stupid lol
then ot's not "exactly"
that would be Create a copy of Mercury if ...
also
self.config.extra.mult = mult
is just as wrong
ah yes, mult = mult
Iâd word it as
When you play a hand containing exactly 2 Aces, create its Planet card
But itâs not necessarily thunk wording
local multmod = card.ability.extra.multmod
local mult = multmod * math.max(0, dollars) -- Ensure multiplier does not go below 0
card.ability.extra.mult = mult -- Store the calculated mult
But really why is it grayscale
its a mod, we dont have to exacly go by thunk
Blind people arenât in greyscale đ
it's to distinguish it from the other jokers ^^
then why is it called colorblind
eh?
otherwise it's Cool Jimbo
Colorblind also isnât grayscale
how will you see its colors?
Grey is a color; also neither black nor white is the absence of color
maybe he's from Grayscalia
i mean, technicly there isnt something that has no color
Ultraviolet radiation? Infrared? Microwaves? X-rays?
infrared is purple
Glass?
Depends on the glass I guess
or rather, it's technically a very very very minor color
because it'll still affect the light, just not noticeably
â transparecy â
Anyways I prefer âWhen [EVENT], do [THING]â for effects
miku
banger
You can use the Midas Mask tech
i am
The cards look like theyâre becoming Bonus immediately
Maybe itâs just the speed
But Midas avoids it
ah i see where i went wrong
don't need the event manager to play a sound without delay
miku crashed my game
I think with Steamodded you might be able to just return a sound
In the return table
Not sure
Only if itâs with a message
ok well
how would I go about flipping played hand here
trying to do it like ouija/sigil
Ah, the Bonus. đ€
tryign to flip the played cards so it's a bit more seamless
i'm flipping cards
Just
the wrong ones
card is composed of front, center, back
Flip the context.scoring_hand cards... you may want to also "chain" a bunch of events... flipping the cards first, then set the ability, then flip the cards again.
you'd think it'd be that easy
Holy shit that's incredible
Say I got a few questions about shaders, there are rotations and scales that you can modify, but what about transparency? Does draw_shader support it? I want to do fade in and fade out animations
This again? Hang on, SMODS version..?
wait this is fucking hilarious actually
What context are you using?
See #đ»ă»modding-dev message... they trying to flip the scored cards.
local percent = 0.85 + (i-0.999)/(#G.hand.cards-0.998)*0.3
G.E_MANAGER:add_event(Event({trigger = 'before',delay = 0.15,func = function() G.scoring_hand.cards[i]:flip();play_sound('tarot2', percent, 0.6);G.scoring_hand.cards[i]:juice_up(0.3, 0.3);return true end }))
end```
it's from ouija, i assume something isn't right here fo rwhat i need to do vs what it does
I shouldn't have gotten high
you don't need to patch
got it to flip the right cards
You can, yeah
How do I add them? Where do I start?
You have to add it to the args you pass to your shader
--- MOD_NAME: Yu-gi-oh Card
--- MOD_ID: Yugioh
--- MOD_AUTHOR: [elial1]
--- MOD_DESCRIPTION: An example mod on how to create Jokers.
--- PREFIX: xmpl
----------------------------------------------
------------MOD CODE -------------------------
SMODS.Booster = {
name = "Yu-Gi-Oh Cards",
slug = "t_yugioh",
cost = 4,
config = {},
pos = {},
discovered = false,
weight = 1,
kind = 'Standard',
atlas = 'con'
}```
making sure doing this right
slug = "t_yugioh", is meant to be the picture for the pack
sort out your indentation first for readability
why does this cause a crash?
SMODS.Keybind{
key = 'PlayCards',
key_pressed = '-',
action = function(self)
if G.hand and #G.hand.highlighted ~= 0 and G.hand.discards_left ~= 0 then
G.hand:discard_cards_from_highlighted()
end
end
}
that is not correct
ill grab the crash log in a sec
first of all delete the = in the SMODS.Booster line
you're assigning to the SMODS.Booster class instead of calling it's constructor
G.hand doesn't have a discard_cards_from_highlighted function
name "Yu-Gi-Oh Cards",
slug "t_yugioh",
cost 4,
config {},
pos {},
discovered false,
weight 1,
kind 'Standard',
atlas 'con'
}```
so more like this
what should i call for then?
I believe it's G.FUNCS.discard_cards_from_highlighted but I'd have to double check
G.hand.discards_left also doesn't exist
ah, FUNCs are something i havent heard of yet
G.hand is just a card area for the cards in your hand
it doesn't magically store random properties of your run
discards left would be G.GAME.current_round.discards_left iirc
my bad
You mean I can just put G.C.PINK = HEX("f7a6ca") in a file and it'll just... work?
yeah
G.FUNCS.discard_cards_from_highlighted
SMODS.Keybind{
key = 'DiscardCards',
key_pressed = '-',
action = function(self)
if G.hand and #G.hand.highlighted ~= 0 and G.GAME.current_round.discards_left ~= 0 then
G.FUNCS.discard_cards_from_highlighted()
end
end
}
SMODS.Keybind{
key = 'PlayCards',
key_pressed = '+',
action = function(self)
if G.hand and #G.hand.highlighted ~= 0 then
G.FUNCS.play_cards_from_highlighted()
end
end
}
so this should work?
gotta fix key pressed for Play Cards
you have two keybinds on the same key?
{
name = 'Yu-Gi-Oh Cards',
group_name = 'Yu-gi-oh', -- Pack group text while a pack is being opened, omit if using group_key
text = { 'Time to Duel' },
}
}```
this is the proper way of doing this right
discard works, but playing doesnt
did you read what I was saying? you're overwriting the value of the SMODS.Booster class
please look at some examples from other mods
wait, does G.FUNCS.play_cards_from_highlighted() exist?
I think that's what it's called? can't check rn
I mean it'll crash if it doesn't, so just try
I've looked at a couple both mods that i've checked don't use the Booster like the document says
it doesnt crash but just doesnt do anything
no worries
i noticed that G.FUNCS.discard_cards_from_highlighted() asks for a hook while G.FUNCS.play_cards_from_highlighted() doesnt
heres the code if anyone wants to take a crack at the issue
-- Keybind for discarding highlighted cards, this one currently is working
SMODS.Keybind{
key = 'DiscardCards',
key_pressed = '-',
action = function(self)
if G.hand and #G.hand.highlighted ~= 0 and G.GAME.current_round.discards_left ~= 0 then
G.FUNCS.discard_cards_from_highlighted()
end
end
}
-- Keybind for playing highlighted cards, currently isnt working
-- no crash, cards just arent played
SMODS.Keybind{
key = 'PlayCards',
key_pressed = '+',
action = function(self)
if G.hand and #G.hand.highlighted ~= 0 then
G.FUNCS.play_cards_from_highlighted()
end
end
}
i am currently trying to make a single-joker mod just to mess around and the mod is not even registering in the game
do you have a json file in your mod
negative
hi, small bug i can't locate - the game's saying my for loop has an invalid length:
local igo = Game.init_game_object
function Game:init_game_object()
local ret = igo(self)
ret.current_round.fainfol_card = { suit = 'Spades' }
return ret
end
function SMODS.current_mod.reset_game_globals(run_start)
G.GAME.current_round.fainfol_card = { suit = 'Spades' }
local valid_cards = {}
for i, j in ipairs(G.playing_cards) do
if not SMODS.has_no_suit(j) then
valid_cards[#valid_cards + 1] = j
end
end
if valid_cards[1] then
local chosen_card = pseudorandom_element(valid_cards, pseudoseed('fainfol'..G.GAME.round_resets.ante))
G.GAME.current_round.fainfol_card.suit = chosen_card.base.suit
end
end```
lemme grab the exact error
my asset tree rn
add a json file next to main.lua
ok that would explain why it keeps complaining that it can't find SMODS
Oops! The game crashed:
main.lua:1780: functions/state_events.lua:1158: 'for' limit must be a number
Additional Context:
Balatro Version: 1.0.1n-FULL
Modded Version: 1.0.0~ALPHA-1230d-STEAMODDED
LĂVE Version: 11.5.0
Lovely Version: 0.6.0
Steamodded Mods:
1: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.3~dev, Uses Lovely]
Break Infinity: omeganum
2: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely]
3: More Speed by Steamo [ID: MoreSpeed]
4: Phanta by GhostSalt [ID: GSPhanta, Version: 1.0.0]
Lovely Mods:```
looks like the game doesnt like you haaving a dynamic loop length
nope, that's not where the crash is from
its not your for loop i dont think
do you happen to have a card = self in your joker calculations
likely! lemme check
card = self, in the returns?
that seems likely
nope
still busted =w=
im still confused on how this guy got an error https://discordapp.com/channels/1116389027176787968/1329513078269677649
it works on my machines (laptop and pc)
to circle back to this, everything works like a charm now, tysm.
yw
is there any way to get intellisense on the SMODS namespace / balatro namespace though?
i'm using VSCodium
i can live with this but every time SMODS is mentioned i get a warning, which is a little annoying
i got something, give me a sec
try opening up the mods folder in vscode
works like a charm
tyyyyy :3
Discarding works fine but playing doesnt
does anyone know if there's any way while using the API to stop the sprite from drawing using the Card:draw() method?
would someone be willing o help me out one more time? i am trying to make a joker that increases it's XMult every time a food joker gets "eaten", but it's just not increasing it's mult.
the following should be all relevant code:
SMODS.Joker{
key = 'ari',
loc_txt = {
name = 'Aria',
text = {
'Increases multiplier by {X:mult,C:white}X1.0{}',
'every time you consume a food joker.',
'Current multiplier: {X:mult,C:white}X#1#{}'
}
},
atlas = 'Jokers',
rarity = 3, --rarity: 1 = Common, 2 = Uncommon, 3 = Rare, 4 = Legendary
cost = 150,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = false,
perishable_compat = false,
pos = {x = 0, y = 0},
config = {
extra = {
Xmult = 1.0 --initial multiplier
}
},
calculate = function(self,card,context)
if context.joker_main then
return {
card = card,
Xmult_mod = card.ability.extra.Xmult,
message = 'X' .. card.ability.extra.Xmult,
colour = G.C.MULT
}
end
end,
handle_food_expiry = function(self)
self.ability.extra.Xmult = self.ability.extra.Xmult + 1.0 --increase multiplier
end,
in_pool = function(self,wawa,wawa2)
return true --available in the pool
end
}
-- hook into the game's food expiry mechanic
G.on_food_joker_expire = function(food_card)
local joker = G.jokers:get_card_by_key('ari')
if joker then
joker:handle_food_expiry() -- increment multiplier by +1XMult
end
end
is G.on_food_joker_expire a thing?
I know it shouldn't be working, but is it possible to put emoji in joker description?
Yeah I figured
it's what i've been told gets called on expiry lmao
is there any documented way to achieve what i'm trying to do then?
nope
:c
what told you that? it's probably out of date
Google Gemini, so i'm not surprised it hallucinated that function lmao
should've known better but a central API Documentation would def help
đż
seriously tho is there any kind of docs for balatro modding or is it all just handed down knowledge?
https://github.com/Steamodded/smods/wiki for API docs
and the game source code
Just be careful with the wiki some stuff was outdated but it's a great resource regardless
maybe i'm overlooking something here
not entirely sure
at first lovely crash said it was because open brackets I closed them now this happens
oh I see the issue
you're missing loc_txt on some of those jokers
how does one go abt testing a mod?
was focused on the }
i dont really want to depend on shop rng to find the single joker i've created
but choosefirstshopjoker doesnt work
thanks!
Was curious what number would get_id() return if it's a stone card and this is NOT what I expected (but kinda reasonable)
i was wondering why but its to prevent 5oak with stones
key = "forbidden_one",
loc_txt = {
name = 'right leg of the forbidden one',
text = {
'An automatic victory can be declared',
'by the player whose hand contains this card with the',
'card with the Left Leg/Right Leg/Left Arm/Right Arm',
'of the ForbiddenOne.'
},
config = { payout = 4 },
loc_vars = function(self, info_queue, card)
table.insert(info_queue, SMODS.Centers.j_pencil_left_arm)
table.insert(info_queue, SMODS.Centers.j_pencil_left_leg)
table.insert(info_queue, SMODS.Centers.j_pencil_right_arm)
table.insert(info_queue, SMODS.Centers.j_pencil_right_leg)
return { vars = { card and card.ability.payout or self.config.payout } }
end,
rarity = 1,
pos = { x = 1, y = 0 },
atlas = "Jokers",
cost = 8,
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
add_to_deck = forbidden_part_added,
calc_dollar_bonus = function(self, card)
return card.ability.payout
end
}
})```
Do I have anything extra in here that shouldn't be there
sprite doesn't wanna load
oh
I see now
the } needs to close the loc_text
I just have it in the wrong place
indenting your code properly should help with seeing that easier next time
now my game is crashing saing lovely.dll was not found
i saw it a bit late but thnk you it worked
how do i voucher
i want to add a voucher to increase spawn rate of runes, how would i do that
Workshopped the visuals of the Glyphs a bit more. (from The Owl House)
Gains X.01 Mult for each scored [Diamond/Club/Spade/Heart].
Currently X1 Mult.
what is the equivallent of G.GAME.tarot_rate for custom consumable types?
key = 'Jokers', --atlas key
path = 'Jokers.png', --atlas' path in (yourMod)/assets/1x or (yourMod)/assets/2x
px = 71, --width of one card
py = 95 -- height of one card
})
SMODS.Joker({
key = 'derek', --joker key
loc_txt = { -- local text
name = 'Pot Of Greed',
text = {
'What does it do?',
'Gives you two additional',
'{C:attention}Joker{} Slots'
},
},
atlas = 'Jokers', --atlas' key
rarity = 4, --rarity: 1 = Common, 2 = Uncommon, 3 = Rare, 4 = Legendary
--soul_pos = { x = 0, y = 0 },
cost = 10, --cost
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
blueprint_compat = true, --can it be blueprinted/brainstormed/other
eternal_compat = false, --can it be eternal
perishable_compat = false, --can it be perishable
pos = {x = 0, y = 0}, --position in atlas, starts at 0, scales by the atlas' card size (px and py): {x = 1, y = 0} would mean the sprite is 71 pixels to the right
config = {
extra = {
card_limit = 3 --configurable value
}
},
loc_vars = function(self, info_queue, center)
return { vars = { center.ability.extra } }
end,
add_to_deck = function(self, card, from_debuff)
G.Jokers.config.card_limit = G.Jokers.config.card_limit + 2
end,
remove_from_deck = function(self, card, from_debuff)
G.Jokers.config.card_limit = G.Jokers.config.card_limit - 2
end,
})```
Lovely is saying G.Jokers.config.card_limit = G.Jokers.config.card_limit + 2 is a nil value but I haven't changed anything from this
and it worked before
insane
restarted now the mod works

everything works but doesn't seem any effects but head works for now
Did you want to avoid drawing the base card?
how do i make a voucher that increases the rate of my consumable type in the shop?
fletch is going crazy on the shaders lol
gosh darn you codex arcanum!!! why must you be so wierd!!!!!
got the card area working 
ive run out of conumable card mods to look at
what is this for
Is there away to get a debug to show if something isn't working
even if the game isn't crashing?
new thing, relics
plenty other mods add consumable types
SMODS.Joker.super.inject(self) is there a version of this for enhancements?
SMODS.Enhanced.super.inject(self) didn't work
it's SMODS.Enhancement
Thanks
Make them 10x bigger and put them across the screen 
I'm curious what you need it for though? You should only need to refer to parent classes when you're extending a class
if you're just trying to build something around the default inject function for enhancements, you should use SMODS.Enhancement.inject(self)
yeah
Hey question about this does debug menu allow u to test the insta win or do u have to get lucky and get the lastpiece for it to trigger
just wanna make sure not my poor coding or if it's just debug menu
can't tell because everything else seems to work
multipliers and all
and I add the function as well
I think there's an option somewhere when defining the
Edition or Enhancement or whatever it is
to request the base not be drawn
it might depend on the object type
its a card
So an Enhancement?
There are ways to do it with Enhancements and Editions at least
Itâs just a property on the card iirc, you should be able to set it whenever
oh uh... thats new
Yeah, I was looking at the code
The way that Enhancements do it have secondary effects, I think
But Editions might not
does { xchips = card.ability.xchips } not work anymore?
although I don't really understand how Editions do it
key = "left_arm",
loc_txt = { -- local text
name = 'left arm of the forbidden one',
text = {
'A forbidden left arm sealed ',
'by magic. Whosoever breaks ',
'this seal will know infinite power.'
},
},
config = { xchips = 2.5 },
loc_vars = function(self, info_queue, card)
return { vars = { card and card.ability.xchips or self.config.xchips } }
end,
rarity = 1,
pos = { x = 3, y = 0 },
atlas = "Jokers",
cost = 6,
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
blueprint_compat = true,
add_to_deck = forbidden_part_added,
calculate = function(self, card, context)
if context.joker_main then
return { xchips = card.ability.xchips }
end
end,
})```
for some reason everything here works but the xchips multi
I donât think enhancements do it
Editions just turn off the base layer from being drawn
Are you sure its just a property on the card?
thats better, now time to get them working
printing all properties at depth 1 gives this:
Should be card.ignore_base_shader = {âsealâ = true}
where seal is the key to the seal?
It can be any reference
And this stops rendering the card if the condition in the table is met?
Itâs just so you can turn it off again afterwards
No, it stops rendering if the table has anything that is true in it
Editions apply and remove it automatically if you specify a property
But you should be able to manually set it in a set_ability function
Excellent, thank you!
how does one add the lil tooltip on the side of jokers? i'd like to add a custom one
like this
adding to the end of the info_queue in loc_vars (see the signature in the Steamodded wiki)
can anyone explain to me how to "loop the played hand for queens"? i cant find anything on how to check for that
Not the correct formatting for variables
This is a Joker right
would anyone know the resources i can learn about lovely patching for my mod or generally know how i can go about it
it is for a joker, this is an image that someone sent to me to try and explain how to do it
Should be config = { extra = { queen_check = false } }
.
It does say to âreturn it as card.âŠâ so Iâm not sure thereâs another layer here
If that does get saved to config.extra (also known as ability.extra) somewhere else then itâs fine
Anyways, the cards in the hand would be G.hand.cards if I remember correctly
So you can loop over the cards in hand in that table
Is there a lovely wiki?
How could i make every joker into a negative one
thank you!
Try printing to see if the block executes to try and identify where the error happens
Iterate over them and set their edition
cheers
Also you should access the variable inside extra to save and retrieve it
I also think youâre missing a check
am i? this is what the actual code is looking like
would appreciate knowing whats wrong with it
What is create_joker
ah, so the tutorial in SMODS wasnt working out entirely for me (the joker had no custom texture and all the numbers in the description said nil) so i tried coding following bunco's code, apologies
you are missing some ends in the calculate function
oh i know, i was going to get to that later
ok mb
Is there a way for me to make it to where only one Joker in a lua file is able to appear in the shop per run?
considering sometimes a joker will never appear in your run, god forbid you
global value & use in_pool
yeah well they're all common and I want them to stay that way but I also only want one of them per run because they all BASICALLY do the same thing (and that's by design)
why you have multiple if they all do the same thing?
how would I go about using this
actually i'm a little confused
whats the point?
Each gives chips based on the year the album came out, but they each play the album instead of the balatro music
you can just... make it dependant who is leftmost?
I want them to be common enough that you can use them, but also I don't want 4 of them appearing in one run, replacing slots that other Jokers could've used
the sounds don't overlap
So it'd be like Cavendish but reversed
makeing so only 1 out of 4 cards appear per run makes people like needing alot before they see everything out from mod, more than they need
this is a wild opinion that i honestly do not care about
i'm making this for me and my friends, when did i ask for the opinion on how i want it to work
There are several vanilla jokers that only appear in the shop at certain conditions, maybe start from there.
yeah I'll try looking at cavendish and gros michel
why can i not find a simple voucher that does 2x the chance a consumable type in the shp[
does anyone know how to use the new joker sizing thing added to SMODS so that i can set one of my jokers to the same size as the square joker
every mod is all wierd
Also Stone joker, Steel joker, Glass joker, Golden ticket, and Lucky Cat.
sorry to everyone (except newcat) for being rude, I didn't appreciate having 4 messages in a row that were just negative about what I'm working on
so you only want 1 album joker to show up?
yes
and no albums show up while there is one in a joker slot
yeah
whats your mod prefix
MUSC
7th Heaven (Common)
Art: Jimbo with an angel halo and wings
Effect: Retrigger each played 7
Random question for whoever wants to answer, for a common card that retriggers a card of one specific rank and no other qualifiers, do you think it should retrigger once, or twice? Trying to make it vanilla-balanced
in_pool = function(self, args)
for i = 1, #G.jokers do
if G.jokers[i].rarity == "MUSC_album" then
return false
end
end
return true
end
try that
i'd say once
it feels like i have to do a patch, or hooking but it seems like this is too much of a common thing to not have a specific function for this
two retriggers on every 7 would be insane especially with an idol
cause this would also stack with stuff like hanging chad, red seals
literally just G.GAME.(consumable set)_rate = G.GAME.(consumable set)_rate * 2
how do you split up mod code into several different files?
I have sets of jokers in my mod and having different files for each set would be preferred
So it seems like using_consumable is never true, even though it definitely should be. And i thought it had something to do with my hook on the Card.use_consumable function, but i commented out anything that wasnt just returning the default return values and it still didnt help
oh my god
im crying right now
tbh i didn't know it was the docs i just had to look at other mods lol
where is this?
blame this one on thunk
it's using_consumeable
where do i put this
there is no consumabletype section in the docs?
oh my god its just the letter e i was missing??
Under ObjectType
and does the MUSC_album target everything in the lua?
in where you make the SMODS.Joker{} stuff
like that
Wait what's the difference between what you and I did
The British send their regards
so put it in every joker?
yeah
ok
i knew about the colour instead of color but i had no idea they spell it with an extra e
they don't
Then why đ
because 

do i then change rarity to MUSC_album on the jokers?
same reason that we had caino, I presume
And then how do I get that rarity to appear in shop
At least thereâs Cain
no, i only put your mod prefix at the beginning because mod prefixes are appended to rarities
the global thunk strikes again...
it should if you just reroll
they're currently just rarity 1 though
oh
so this would work for a voucher right?
rarity = "album"
you do need the prefix here iirc
i could make it prefixable tbh
wait so what do i do to make it appear in the shop as its own rarity
not what i meant to say there đ
you can give a shop rate to your SMODS.Rarity by defining default_weight
I'm looking at https://github.com/Steamodded/smods/wiki/SMODS.Rarity rn but I'm not understanding how to implement the default_weight
It should function as a common, just with the code we have to not allow the others in the same pack at the same time
I'm not following, do you want them to be in the same rarity pool as commons and have a separate pack where only these can spawn?
then you don't need a rarity
you need an ObjectType
I don't really care one way or another about the pack part
I just want them to be in the same pool as common, but unable to be in the shop if you own another in the modpack
i have this joker set up to do some experimenting with face cards and chips but whenever an applicable card is discarded the game crashes with "engine/text.lua:114: functions/misc_functions.lua:1808: attempt to index local 's' (a number value)"
doesn't have to be booster packs or anything
looking at the game src for those two doesnt really clear anything up unfortunately
is there something obvious im missing?
You can use in_pool
yes we have this part
in_pool = function(self, args)
for i = 1, #G.jokers do
if G.jokers[i].rarity == "MUSC_album" then
return false
end
end
return true
end,
the joker's display works fine, it shows +0 chips before any kings or jacks are discarded (also is that the proper way to check for kings/jacks? view the ranks?)
That is set when the Joker is created anywhere
but as soon as any king/jack is discarded the game dies
I am lost
I will return to this after a break
I will play some Rivals for a little bit while I can and then come back to this
you can just check with any other property, like some config value that's shared between your jokers
I don't think their config values are the same
They all give different chip amounts
Depending on the year the album came out
They all use atlas = 'albums' though?
Again just set a global variable
That also avoids two showing up in the shop at the same time
But how do I do that đŠ
stressed, will return
Idk why this suddenly stopped working (it was working earlier and i dont think i really changed anything) But my consumable card isnt duplicating cards. It prints out the right card key, but it never duplicates it. any idea why? p.s. i only included the consumable and hook in this file
omg im sutpid
found my issue.
yes I'm saying you add a config value that's shared between those jokers
how to defeat the wheel
maybe {C:attention} the 2X
if i have a en_us, can i not use loc_txt?
no
whats wrong
it's just name and text, there is no label
use set_card_type_badge if you want to change the Voucher badge
why, is there something wrong with it?
It might be better to use the SMODS.Joker way of making Jokers - I think it's the way mostly used so you'll be able to find help easier
question how do I look for the context of a played card with a specific enhancement basically just want to +mult for each played card with x enhancement
You can use if context.other_card.ability.name == /enhancment/ then and then return the relevant flat mult in that branch
does it work with an enhancement i have added myself?
sorry i dont think i was clear
i want a joker to trigger that
So it depends what you have named it, you will need to add the mod prefix underscored before the name. If your mod prefix is 'mymod' and the enchancement is 'toxic' then you would replace the /enhancement/ bit above to 'mymod_toxic'
I assumed this was a joker effect anyway
just goes in the calculate function for that joker
make sure you are checking each card individually as well with context.individual
perfect thanks
working?
Is there a way to save config to files?
yep thanks
no
man
just saw this while searching - it's my mod, but it's not currently available, I plan to remake those cards and add them to a new modpack I'm making
what are you trying to do?
spawn a consumable on boss blind enter
ok cool
it's gonna be in #1329163669501644914 , so I'll let you know when I add it
ok
do i have to do like globals or something?
a voucher that spawns a consumable on entering a boss blind?
yes
yeah you'd need to patch in a check for your voucher and then do the creation
darn
where should i patch? i was thinking of the calculate function but that seems volitile
you need it in the function that starts the blind
I have returned equally as confused as before
This is what my album jokers look like right now (each one is just edited from this one)
How do I set the global pool to make each of the album jokers not appear in shop if you already own one?
I want them to be common rarity, or at least functionally the same, but you can only own one per run
Or is this just going to function as I want it to but with extra steps?
You may want to patch into get_current_pool in common_events.lua to create a new gate as opposed to setting a pool
That's how jokers like Stone and Glass are set to appear whenever you have the relevant enhancement in your deck
I've created a few new ones to check for jokers in hand, editions, seals, and collections of some of those, I think you could do something similar
I have a question myself now. I'm interested in creating a new card area, just a simple 1-slot area for a new card type. How would I go about doing that?
if context.scoring_hand and not context.other_card.debuff and context.other_card:is_suit(G.GAME.current_round.castle2_card.suit) and not context.blueprint then
How do I make this specifically Diamonds? (code comes from Castle2 is the examples thing)
Is it just replaced is_suit(G.GAME.current_round.castle2_card.suit) with is_suit(diamond) or something?
is_suit("Diamonds") i believe
Thank you!
Also is it possible to patch into Steamodded yet? It keeps hijacking functionality I would like to change and it's getting on my nerves
im sure this has been asked before, but whats the best place to start when learning to make your own jokers, with having 0 coding experience?
Use G.play.cards to access the array of cards that are played or context.scoring_hand to only access the scored ones.
would anyone know how i can copy the functionality of Jolly joker cant seem to find anything in the actual balatro source code for the calc of it
requires talisman
yes, although the dialog takes a second or two to appear
Check the if branch at line 3660 in card.lua
thanks
Ah so it's a custom mod
that is where those types of jokers are being calculated
I'll just change it to a multi or something
Anyways to increase the odds of a card showing up so not hoping to get the last card
So I can test make sure it works
you can summon all 5 with debugplus
Then I guess it's not working on my end because I added all 5 to joker slots nothing happens
Try both on the card but screen and in middle of a game
what code do you have right now?
yeah it does those ones quite scattered, the t_mult value is defined in the config in game.lua then during the main joker eval bit it checks if t_mult > 0 (not nil I suppose) and then it knows that it's one of the 5 "flat-mult-for-hand-type" jokers. Pretty sure line 3660 is what you want.
It's on my steam deck in bed right now
Essentially I just have a slightly modified version of what u had
Are all the internal tables that hold information about consumeables and such hashed? Would there be any way to manipulate their orders and refer to them without them being jumbled?
did you change the joker keys in the function
Only thing I really changed was the name and sprite
No everything should be the same
The only thing I changed was adding description and name to the cards
And the sprite coordinates
guys how do i install a mod thats a .lua
Actually hold on I think I have the latest Lua on my phone I made
yeah forbidden_part_added has the joker keys that it checks for listed inside it
so you need to change those to your jokers
.
nvm got it but how do i show fps
its a setting in the smods config
in game
'show hud information' or something like that
np imma get it
Wilsonthewolf
where do i get it
kk thx
whast the save loader mod?
is using the balatro calculator mod cheating?
or not
nothing's really cheating as long as you're having fun and others aren't losing out
how do I get an enhanced card to destroy itself like glass cards without it triggering jokers like Canio twice
kk
ah its a site not a mod thats a shame
Thanks it also has the seeing double effect which I'm also trying to use
is there any qol mods that i should get
the debugger will be plenty tbh
nope check again, it's a NOT equals
If you mean line 3653
Trying to get my joker to basically add mult to itself when hand contains a pair and at least one heart
what does mipmap do
It's checking that seeing double is not included so that it can return x mult freely without needing seeing double's condition
SMODS.Joker { key = 'light_glyph', loc_txt = { name = 'Light Glyph', text = { "Gains {C:x_mult}X0#01#{} Mult", "per played Diamond,", "{C:inactive}(Currently {C:x_mult}+#3#{C:inactive} Mult)", } }, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, config = { extra = { x_mult = 0, x_mult_mod = 0.05 }}, atlas = 'ModdedVanilla', pos = { x = 5, y = 0 }, loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.x_mult_mod, card.ability.extra.x_mult, }} end, calculate = function(self, card, context) if context.scoring_hand and not context.other_card.debuff and context.other_card:is_suit("Diamonds") and not context.blueprint then -- extra.mult_mod = 0, -- Mult to add card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.x_mult_mod return { message = localize('k_upgrade_ex'), colour = G.C.CHIPS, card = card } end if context.joker_main and card.ability.extra.x_mult > 0 then return { message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.extra.Xmult } }, Xmult_mod = card.ability.extra.Xmult } end end }
So, trying to make this increase by 0.05 per scored Diamond,
Is this, like, the right direction?
use triple backtick for multi-line codeblocks
(you can then also do the ```lua for the language highlighting)
?
so yeah it's not working cus your jokers will have a different mod prefix
what's this in context with?
well it's an image processing technique to reduce aliasing
Still trying to figure this out do I need to set the key to Derek like the pot of greed card
I don't think it's anything to worry about
kk
no it should be the keys for the 5 parts of exodia
I assume a higher level just means higher processing required
would anyone be willing help someone make their first joker mod? Im following this youtube video but it totally doesn't account for someone having 0 coding experience which i dont blame it
the mod prefix is set to pencil, needs to be xmpl
this is what happens when i try to use the SMODS guide and the other one is when i use my current one
so it could affect frame rate although I doubt it, it's not incredibly intensive
not sure why
So I changed j_pencil to j_xmpl?
yup
Alright I do that tomorrow and see what happens
the nil returns if it can't find the vars anywhere, so it's likely they were named/referenced incorrectly when you tried to insert them into the card text
wait, i just found the issue, nevermind
Just a quick tip with the text, you could probably change the opening sentence to "If played hand contains at least one Queen" without the king bit - considering the kings will always have to be there to give the Xmult anyway (capitalised King and Queen as well).
How about "X1.5 Mult per scoring King if played hand contains at least one Queen" - a bit more concise.
So uh, for some reason, when hovering over 'the fool' after using this card the game crashes, for some reason finding center.ability.extra.cards inside loc_vars being nil or something, idk. Is there a fix for this?
SMODS.Consumable { -- Summer
key = "summer",
set = "Tarot",
atlas = "tarot",
pos = { x = 1 , y = 0},
config = {
extra = {
cards = 3
}
},
loc_vars = function(self, info_queue, center)
return {
vars = {
center.ability.extra.cards
}
}
end,
can_use = function(self,card)
if G and G.hand then
if #G.hand.highlighted ~= 0 and #G.hand.highlighted <= card.ability.extra.cards then --if cards in hand highlighted are above 0 but below the configurable value then
return true
end
end
return false
end,
use = function (self, card, area, copier)
for i=1, #G.hand.highlighted do
G.hand.highlighted[i]:set_ability(G.P_CENTERS["m_sbc_fire"])
G.hand.highlighted[i]:flip()
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.5,
func = function()
G.hand.highlighted[i]:flip()
return true
end
}))
end
end
}
yes, there is no card available when there's just a tooltip being made
I provide you with a fake card on latest steamodded, so I think this should no longer crash if you update
i still dont know how to do this and im afraid of asking over and over
It doesn't implode now.
whatever i try the game either freezes hard or the joker does not work at all
this is a very me thing to say lmao
ive just been stuck on this for days
Use G.play.cards to access the array of cards that are played or context.scoring_hand to only access the scored ones.
yay, something completely unrelated broke. What am I doing wrong here?
Speaking of being stuck on something:
I still don't know how to get these Jokers into a global pool.
I just want them to be common rarity, but I don't want you to be able to grab multiple of them in the same run, so I want only one from this mod to show up in each run.
context.other_card won't work here because you haven't punched in using context.individual
other_card isn't populated otherwise
so it's trying to index a nil value
why tf did it work like a few versions ago then?
how to make a config tab
do i like, add context.individual to it and run with it?
Should work, it''s how I've fixed problems liek that in the past
ok
Anyone know the code for this?
I was told in.pool(global) I think, but I still don't know how to work that
im playing the negative deck, but almost everything i do makes my game crash, is there something i can do about this?
chat how do i make it so a card detects a certain rank of card no matter if it's played or unplayed
can anyone please just give me an example so i can learn from it? i want to understand what im doing wrong
is there a way that I can give a Joker like, two rarity squares in its description? I don't want it to have two rarities for RNG, just so that I can do something like this:
If you're asking what I think you're asking, this is how Midas Mask checks for face cards
im only checking for queens specifically
so change v:is_face() to v:get_id() == 12
ok, ill try that
IT WORKS
THANK YOU SO MUCH
does anyone here know how to code a blueprint type joker?
cus im trying to make one that copies a random joker every round and at this point i dont know what im doing and need help
the game doesnt crash when i try to use the guy, but he doesnt actually copy anything either
desc
I would try
return other_joker:calculate(context)
Returning whatever value is returned by calculate is important
I know this sounds like a weird solution but instead of not other_joker == nil try other_joker ~= nil. Changing that ordering around has fixed things a surprising amount of times for me
what is ~= ?
Also yeah there's no return
i keep seeing it and being confussled
i see
You can just do if other_joker, nil evaluates to false
used to it being != in other languages
same lmao
so its still currently not working but this part is fine right?
Also instead of checking for specific joker names, I'd recommend checking for not context.no_blueprint since that checks for cards that act like blueprints. I'd recommend taking a look at vanilla blueprint code to see how that's set up and implement it into your Joker too
Don'
Don't put other_joker:calculate(...) in brackets
ok
It's already returning a table
Was gonna say, you're returning a table with the calculate inside
got it
there's still a problem outside of it though
i have something telling which joker is copied tied to the desc
Also 90% sure it should be context.blueprint and not G.Game.context.blueprint, but that shouldn't keep it from working
What does your loc_vars look like
You're setting the randomJoker variable at calculate
So it won't show until after calculating
hey fellas! i need help figuring out how to make probabilities
Yes. Since you're rotating the joker every round, you'll want to create a new global variable that holds your target joker and hook into reset_game_globals to have it rotate every round (like an Idol for example)
like, im looking over here at the modded vanilla gros michel. im just looking at the text and i understand that the #2# is refering to the extra = {..., odds = 6} in the config, but where's the #3# come from?
scroll down, there's a loc_vars function
wait is there modded implementations of every joker
right, is it somewhere in here?
no, just some
ok
loc_vars
got it
(example mods were moved to a separate repo recently, so it won't be in your smods folder if you're on latest)
Your loop that picks a joker also has faulty logic. Should be something like:
for i,v in ipairs(G.jokers.cards} do
if v.name ~= 'Blueprint' or v.name ~= 'Brainstorm' or v.name ~= 'Mimic Joker' or v.blueprint_compat then
jokerList[#jokerList + 1] = v
end
end
well this is what i have on my end, what have i done wrong?
blueprint_compat is actually only cosmetic
v.name however doesn't work, it'd be v.ability.name
(this is on a playing card, so the (self, info_queue, card) might be just for jokers or something)
i thought #[array] was just the length?
all i want for now is for the text to reflect the 1 in 4 odds i want, and change with oops
baby steps đ
use self.config.odds here
this is one of those things where you figure it out for the first time and it takes like an hour but you just know what you did wrong for the rest of your life
actually this is bad advice because it doesn't work with values that need to be changed
crashes when i hover over it now
you put a comma instead of a .
card.ability.seal.odds is better

saying myArray[#myArray + 1] = xyz means "add the value xyz to the very end of myArray". But also see what john smods said about some errors in the example loop I sent you
understood and replaced :3
is there a list of contexts i can check out?
mr. smods I have a question while you are here, is it possible to patch into smods yet? Stuff I wanna change keeps getting hijacked by smods first lol
Awesome ty
among a couple other things this lists just about every joker context
You can always set your patch's priority to be after smods' and then have your pattern look for whatever smods changes the code to
there's also this which is currently incomplete
It's not smods' patches I'm concerned about, it's moreso stuff smods explicitly takes ownership of
how do i hook into resetgameglobals?
when i tried putting that instead of self.config.odds it crashed so i put it back and-
success!
well, thats the text, now to do the actual functionality
(and making a global variable is just doing 'global thing = 'xyz' ' right?)
I apologize but it's not actually a hook, it's an integrated SMODS function. iirc there's a page on it that I can get you
right, seal things. i don't think you actually get the card
that means its actually getting there
actually just thing = 'xyz'
i see
(i wanted to make it as a sticker first, because i want it to also be able to stack with seals but :( )
HOLY SHIT IT COPIED SOMETHING
i however dont think its doing so randomly
in a test it copied the same joker 4 times in a row
i have three compatible jokers
so a 1/3^4 chance
I actually cannot find the page so I just took the liberty of writing it out for ya:
function SMODS.current_mod.reset_game_globals(run_start)
local eligible_jokers = {}
local new_target = [TARGET JOKER VARIABLE]
if #G.jokers.cards <= 1 or not next(SMODS.find_card([YOUR JOKER KEY])) then
new_target = nil
else
for i = 1, #G.jokers.cards do
if G.jokers.cards[i].config.center.key ~= [YOUR JOKER KEY] and G.jokers.cards[i] ~= new_target and G.jokers.cards[i].config.center.blueprint_compat then
eligible_jokers[#eligible_jokers + 1] = G.jokers.cards[i]
end
end
if next(eligible_jokers) then
new_target = pseudorandom_element(eligible_jokers,
pseudoseed([whatever you want]))
else
new_target = nil
end
end
[TARGET JOKER VARIABLE] = new_target
end
and in your loc_vars you can check if the variable is nil
mhm
rq is this part set up right?
cus i dont like thinking i got a 1/81 chance to roll the same joker 4x in a row
5x even i think
The block I just sent handles no repeats
im talking about my joker selection
well ur using the same roll every time
you need to use pseudorandom
you think that'd be covered by pseudorandom_element
Not if you're using the same key every time
pseudorandom is the illusion of randomness, in reality it's either taking or creating a key and putting it through an algorithm. So if you're putting the same key through the same algorithm, you'll get the same result
hey quick question, im looking at the lucky card code and got a little lost, how does pseudorandom and G,GAME.probabilitie-
well perfect timing then
You should be good to put the same seed in every time
Every example in the vanilla game code has the same seed every time đ€
Creates a random float between 0-1
The condition checks that that value is less than the normal probability (1) divided by 15
Meaning that the probability of it landing within that threshold is 1/15
oh, so if you have oops it just does that automatically
Oops increases the normal value
yeah
From 1 to 2
so its double as likely
Looks like when you're using pseudorandom_element you might have to wrap your seed in pseudoseed()
pseudoseed, not pseudorandom
i see
Is there a visual interface or something like that to make balatro jokers? Something like clickteam?
yes actually! https://www.balaui.dev/joker
im not using it because i want to understand how everything works, but it very much is here!
ok
it selects a random joker now
just need for it to tell what joker it's copying
ive been staring at my pc for like two hours and i havent done anything 
all ive done is just the text
so where do i put this code block?
im trying to figure out how to do this but i think im just missing something
like im looking at the vanilla lucky card code and i cant figure out how to check if a card scores
like literally just scores
thats all i need rn
baby steps and all
context.cardarea == G.play and context.individual maybe?
well, it doesnt scream at me when i put it in so thats a good sign
also for some reason i cant do if statements
it just doesnt recognise the word if
another thing, what should i be replacing [target joker variable] with
little confuzzed
what IDE are you using?
vsc
Your global variable you defined to hold the joker info
Do you have the Lua extension?
yes
Huh
can you send a screenshot without the big popup in the way?
You don't have your calculate function defined
oh right
oh so the global var goes outside of the joker even
Yes
i wasnt sure where exactly to put it
but i was expecting within the calculate function
im trying to figure out what piece of code just goes "hey! the card's scorin'! "
also is this right for the calculate function
like is this the right function
no
mm
after loc_vars, you want to have something like this:
calculate = function(self, card, context)
-- ALL JOKER CALC CODE WITHIN THIS FUNCTION
end
Oh I see
i think seals still get calculate, but it works differently
It looks like that is still correct though
from my limited knowledge
gl!
thanks! long way to go..
From there on though I don't know how to guide ya, as I haven't implemented a seal. I'd recommend rummaging through Cryptid's code for its seals as reference. Here's a link to where some of that code may be https://github.com/MathIsFun0/Cryptid/blob/main/Items/Misc.lua
yeah i have lol
this should just make it do the little bloop animation when it scores, then?
Not when it scores, you don't have a context defined
hello! i have a question, how would i make a joker destroy a random card of a specific rank, rather than destroying each card of that specific rank?
right, how would one do that?
oh
wait
its just 'if context.card whatever" right?
where can I find the documentation on the G/G.GAME object so I can see what all is callable?
probably the Smod docs!
I was looking through there, and didn't find it. it's all the SMODS functions and such
I donât think it has anything on that
right
I donât think that exists
ok so, first off the [JOKER KEY HERE] is this key right?
I assume it's looking through the lua game files to find it then
I once again am not sure where to go from here due to my own lack of experience with seals
No. [JOKER KEY HERE] represents the key of the joker you're rolling for. IIRC you called it a mimic? If yes, the mimic's key is what should be in that
This way it doesn't pick up a mimic to copy
ooooh that key
mb mb
wait what's going on in these blocks?
this is from the code block you sent me
@sturdy compass bc i forgot to make the above a reply
also current status, the global var works before i enter a game, which i can check by looking at the collection, but not after
That first loop goes through your joker hand and adds them to the eligible_jokers table if A.) It's not a mimic, B.) it's not the same card as last round, and C.) it's a blueprint compatible card. After that, it checks if eligible_jokers has anything in it. If it does, it populates new_target with a pseudorandom_element from eligible_jokers. If not, new_target becomes nil
also your mimic key should be 'j_[MOD PREFIX]_mimic'
Yes
Dang, this is some premium spagetti code.
ouch
Nah, because I understand ZERO codin
dawg đ
Good work btw.
this looks like pretty normal code tbh btw
one note btw, and ill just implement this myself, the joker also blacklists blueprint and brainstorm
I don't know any code of this game so that's probably why.
where can i find the keys for vanilla jokers?
game.lua
how do you make it so certain scored cards give you money ive tried returning money = card.ability.extra.money but that does not work
you wanna use ease_dollars(card.abililty.extra.money) instead
Not in the return btw
somewhere before the return
Actually I just remembered, instead of ease_dollars you could just return dollars = card.abililty.extra.money
That's probably an easier solution
ill give that a go
I still don't know how to do a global pool if anyone is able to help me finish up my album jokers
sanity check, this is how you get the name of a joker in string form right?
well, yeah by the looks of it
cus thats how it works in an earlier part of my code
ok hold on lmao
You want G.localization.descriptions.Joker[other_joker.config.center.key].name
That way if the target is a modded joker it gets the actual name
lol my shit just crashed now what that should just work says that its a nil field for ability
G.etc after or replacing other_joker.
and my mod is like 40 lines long
bruh spelling mistake moment hahah
not your file
yeah i assumed so
replacing
functions/stateevents
hm
probably in SMODS
right
its a lovely problem?
state_events.lua is in lovely > dump > functions
ok so here's the deal, the line i posted is in the mimic joker's code block, because i just want the targetJoker global var to remember the name of the joker chosen by mimic
hmmmmmmm
the lovely dump is essentially the new code the game runs after injecting mods
not for it to choose the joker the mimic is trying to copy
because thats all i added, and now it crashes whenever i try to play a card with the seal
context.cardarea == G.play isn't a unique context
i believe you also add 'and context.jokers'
how do i fix :<
i think
i see you're on old calc?
yeah
you check for both of these
isn't this not a joker?
oh wait
It's a seal
dur
its a seal yeah
for better calc it's context.cardarea == G.jokers and context.main_scoring
here's the api for seals
you don't need to show me, I wrote that
(for the other guy :3 )
which translates to... what exactly for old_calc? context.cardarea == G.play and not context.repetition?
i can just switch SMODS version
that's defo the better thing to do, the less code still getting written for old calc, the better
I should finish my calculate guide
I hate to butt in, but how would I go about editing something that SMODS took ownership of? This edition in game_object.lua for example, I want to edit what's being returned slightly
WAIT
IT WORKED
alright
we're getting somewhere
(i cant believe the problem was a wrong version of smod im jumping off a balatro shaped building)
Do I just copy paste that code with my change? I'm sorry if this is dumb, I just never took ownership of smthn yet
you need to put only the function/value you're changing
ah ok
the rest will stay put
Ok, but what about for a function itself, i.e. random_destroy? There's something in that I need to edit as well
oh, that's a local function to game_object.lua
yes
that should maybe be made a global util function
oh wow that looks amazing
hopefully lovely 0.7.0 is soon, in which case you'll be able to patch into it
Ah that's what I'd be waiting for, alright
other than that, you'd have to redefine your own version
did you add the unique identifiers yet aure?

