#💻・modding-dev
1 messages · Page 633 of 1
yea
Nah two years ago was last time play vanilla, I only play mods now. Banner to block of all regular jokers
even playing modded you should know this
this is literally basic balatro knowledge
😭
bit cruel but yeah this is just like. baseline how it works
multiple editions isnt a thing at all i dont believe
okay cruel was the wrong wording
and the "negative polychrome" here is just how negative looks 😭
but like. yeah editions enhancements and seals you should know this just by playing modded
well neither of these work, maybe its the context? in these i did if context.setting_blind is thre a context timing better than that for changing the deck's order
i've not rly modified the deck order before so idk, my only experience messing the deck was a joker that let you see the top 3 cards
that was ages ago and i've since removed the joker
also i'm out rn 
DEAR GOD THIS DOCUMENTATION'S GOT HANDS lol
guess I'll take my time to see how I can make this work.
Damn that then idiot, oh well I have my suspension I was baffoon
???
I was referring to the fact that I swore I play mod where had negative polychrome cards but then have no evidence
So like damn did dream this
Or maybe old enough my memory fading
With that out the way could be possible to program double editions like double seal mod
Question question
Does anyone know how to darken everything behind the ui without using create_UIBox_generic_options
is there are way to make sure that certain jokers cant appear as long as an objectType exists
how would i go about adding a sprite to a uibox?
why can't it be create_UIBox_generic_options? it looks like that type of ui to me
It aligned in a fucked up way when I used create_UIBox_generic_options and frankly the background is the only thing that bothers me about it
fair 
looking at the code for create_UIBox_generic_options and i don't see an easy way to do it :p
Fuh
Where is it located at least? I couldn't find it myself lol
functions/UI_definitions.lua
how would i make the game just skip the shop entirely
I believe there is a mod that adds a boss blind to do that, maybe you could ask that mod's creator
why would a boss blind skip the shop
I have no idea
Anti-capitalistic blind
patch G.FUNCS.cash_out
It's from Bunco
That's an evil as fuck boss blind
just patch G.FUNCS.cash_out
replace G.STATE = G.STATES.SHOP with G.STATE = G.STATES.BLIND_SELECT
ty
Tbh I'd say The Paling is more evil
i still dont know how patching in this works, im used to using stuff like Harmony i have no idea if this is anything like it
lmao
ik but every time i hear the word something indescripable writhes in my brain telling me to use it in every line i possibly can from the stockholm syndrome curse harmony patching has placed on me
patching is usually avoided when necessary, in favor of hooks
-# it's necessary here though
must... harmony.... patch...
There is a worse way to do it that doesn’t require patching but it’s uhh. It’s a process
i've already done the one line patch
# Skip Shop on Café Frequent Challenge
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''G.STATE = G.STATES.SHOP'''
position = "after"
payload = '''if (G.GAME.modifiers.elle_no_shop) then G.STATE = G.STATES.BLIND_SELECT end'''
match_indent = true```
this hopefully isn't intrusive at all
yea, that's less intrusive
# Jubjub bird effect
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''G.STATE = G.STATES.SHOP'''
position = "at"
payload = '''
if G.GAME.jjb_cash_out and (next(Sagatro.find_active_card("j_sgt_jubjub_bird")) or Sagatro.vorpal_jubjub()) then
G.FUNCS.cash_out_into_boss_blind()
else
G.STATE = G.STATES.SHOP
end
'''
match_indent = true
just look at this crap of mine
chat how do i make an effect with an irl timer
im specifically wanting a thing where if you dont complete every condition within x time it resets
update(self, card, dt)
dt is deltatime ofc
you could use this to increment a variable to track time
and escalated speed as well (the one you'd normally find by adding more calc to a hand)
ah
love.update hook ig
wuh oh

what i exclusively play on nopeus 256 with ff everything enabled
wont that fuck it up

this will probably work
already got ruled out lmao
i would recommend you do the love.update hook instead
because that way you aren’t calling anything to get the dt
hooking either love.update or Game.update is fine
since love.update calls Game.update anyway
i dont know how any of these things work
is there a context for when money is spent? looking to make a joker where it creates a tarot card after X amount of money is spent
context.money_altered iirc
there is one its something like that
and inside that context you check context.amount for the amount of money
found it in smods, thank you!
you can see there are more specific contexts bound to context.money_altered, allowing more precise control of which type you want to trigger your effect
anyone know how to make undiscovered cards created with SMODS.create_card() display normally
I'm new to modding, and frankly-I find the introduction wiki a little lacking. How do I create a joker card, for all intents and purposes?
it's
definitely not lacking at all
Consider vanillaremade
As regerence material
I do t have link bevause mobile but someone can send it
set SMODS.bypass_create_card_discovery_center to true before calling SMODS.create_card
remember to set it back to nil afterwards
ty
i've been informed that i don't have to
i can just add bypass_discovery_center = true
docs don't mention it tho for some reason
do the docs ever mention anything /s
docs aren't real
why this over love.timer
love.timer is super easy and its not affected by game speed
don't have to make the api call
you just get the dt through the function args
does that really matter
i think im just gonna do love.timer
if problems arise i will switch to something else
but for what I need it for this should work
Is there a way to make a joker sprite go sideways ?
Like have it be sideways or turn sideways
having it sideways in game like this for exemple
is there any easy way to add a function for when you open a pack or do i have to make a patch/hook
???
yeaaahhh that'll be a hook
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
Give it its own atlas and it should be good
so i think i just hook the open_booster function and see if the booster being opened is the specific one and do some silly thingies when that happens we'll se
i think they mean rotating any joker, not just having a horizontal joker sprite
local reference_function = other_function
function other_function(args, ...)
-- code that runs before other_function
reference_function(args, ...)
-- code that runs after other_function
end
local reference_function_2 = Card.other_func
function Card:other_func(args, ...)
-- code that runs before Card.other_func
reference_function_2(self, args, ...) -- self IMPORTANT
-- code that runs after Card.other_func
end
Well they sent a horizontal sprite so
¯_(ツ)_/¯
i found the function and i think i might be a patch
okii
bc theres one function for redeeming opening using etc
:)
i hope i dont do something pointless that already exists but i thought it didint like yesterday
just have to figure out the stupid pack keys bc it always shows its invalid for some reason
I got it, thanks!
then I guess I was just too lazy to read it haha
my apologies
it's okay
also if you need examples
https://github.com/Steamodded/examples/blob/master/Mods/ExampleJokersMod/ModdedVanilla.lua
perfect, thx
https://github.com/nh6574/VanillaRemade/tree/main/src moddedvanilla highkey sucks you should use vanillaremade instead
moddedvanilla is quite outdated
and only has a small set of jokers
perhaps, but maybe it's best for learning. I am just dipping my toes in to modding, so I doubt i'll pivot atm
wait...
anyone know how to add a custom booster pack that only pulls from a pool of modded jokers? trying to code in a pack for a mod and it isnt appearing in game
nvm, I'm dumb haha
alr made a simple patch if this works im gonna be suprised
ok i forgot the second = in an if that doesnt count
ok i forgot to end an if somehow ||i promise im not that stupid|| that doesnt count
Does anyone know the command for the better debug menu mod that allows you to spawn in stuff?
it doesnt spawn in the vouchers
You need to be in the shop.
Oh
Also it seems to be bugging out the ui that has all the informations of the card whenever you hover over them
not sure if thats the mod's issue or a conflict with the my mod pack
nvm
bump part last if i cant figure out how to rig th deck draws lowk ill just stick to discarding then drawing and call it a day
Where are you trying to rig the deck?
where? wdym by that
where in the code
there i guess?
this discards then draws
but i would prefer if it somehow rearranged the deck so it doesnt have to discard
you need to do it earlier than first_hand_drawn then
yeah when i tried rearranging G.deck.cards i was doing it in setting_blind
it will immediately shuffle the deck after that
you could use context.drawing_cards and have an internal flag that you reset at the start of each blind so you only do it the first time
Yes.
awesome, thx
so like this?
yeah
if this just to move one card to the top of the deck or does it do multiple cards?
can vary (this forces you to draw your most played hand so if its high card its a 1, but if its a flush its 5 cards)
oh your rigged tracking looks wrong
let me rewrite it for you, hold on
for _, _c in ipairs(cards) do
_c.rigged = true
end
for i = #G.deck.cards, 1, -1 do
local _c = G.deck.cards[i]
if _c.rigged then
_c.rigged = false
table.remove(G.deck.cards, i)
table.insert(G.deck.cards, _c)
end
end
return {
message = 'Rigged!'
}
try that
unfortunately dosnt work, no errors it just draws normally despite it ringing the rigged message
? what does that mean
it's an issue on SMODS's side and will be fixed in a later update
so my current code should work when that happens alright then amma just save this and revert to my old discard then draw and when the fix drops amma release the deck rigging one
Tryna make a joker that does this, but I haven't been able to figure out how to count the number spectral cards in the consumable area
local count = 0
for k, v in pairs(G.consumeables.cards) do
if v.ability.set == 'Spectral' then
count = count+1
end
end
if you are working on the dev branch of smods this is fixed now
i mean im just using regular smods so ig i dont have access to that yet until i hop onto it, but i dont think that will be very good since most players will just have regular smods
you can use it for testing, should be a new release by the end of the week 🤞
main
well glad to say it actually works!
how do i change the description of a card based on context?
In loc_vars return key to redirect it to a different localization entry.
i don't understand, could you clarify?
actually let me clarify myself
i have this joker in my mod
SMODS.Joker {
key = 'spinner',
loc_txt = {
name = 'Spinner',
text = {
"Retrigger all {V:1}#1#{} cards,",
"suit changes every round"
}
},
config = {repetitions = 1},
loc_vars = function(self, info_queue, card)
return {vars = {
localize((G.GAME.current_round.spinner_card or {suit = 'Spades'}).suit, 'suits_singular'),
card.ability.repetitions,
colours = { G.C.SUITS[(G.GAME.current_round.spinner_card or {suit = 'Spades'}).suit] }
}}
end,
blueprint_compat = true,
perishable_compat = false,
eternal_compat = true,
rarity = 2,
atlas = 'jokers1',
pos = { x = 0, y = 1 },
cost = 5,
calculate = function(self, card, context)
if context.cardarea == G.play and context.repetition and not context.repetition_only then
if not context.other_card.debuff and context.other_card:is_suit((G.GAME.current_round.spinner_card or {suit = 'Spades'}).suit) then
return {
message = 'Again!',
repetitions = card.ability.repetitions,
card = context.other_card
}
end
end
end
}
if card.ability.repetitions ~= 1, i want to change the card's description to
{
"Retrigger all {V:1}#1#{} cards",
"{C:attention}#2# additional times{},"
"suit changes every round"
}
do you know how could i do that? @daring fern
afaik you need to use localization files for that
how do you change the name of a joker?
dynamically i mean
or like have two seperate localization files for a joker and swap between them manually
In setting up VScode, is hover text supposed to be what is seen when mousing over a variable?
did you mean this
Yes
I have written a basic function with comments, and this style of text has not appeared. This text also has not appeared with built in Lua functions either. Would this have to do with formatting?
running into an expected but nonetheless bizarre issue where this joker DOES work as intended, and wild cards count as glass cards, but when a wild card breaks it doesnt properly "shatter" for glass joker. how would i go about fixing that? sounds a bit involved
I keep getting a crash when i try to change a card into a random face card
Are you using quantum enhancements?
Change .card_key to .key
Also it would be SMODS.change_base(G.hand.highlighted[i], nil, _rank)
yep
functionality is pretty much identical to alloy from extra credit
it does properly debuff cards though which is nice
What happens when you do eval SMODS.shatters(dp.hovered) while hovering over a wild card in the DebugPlus console?
it does give true
however it doesnt make the shatter noise either, just removes itself like a normal card
oh it doesnt work with el dorado from plantain either
Yes, because it doesn't use SMODS.has_enhancement
yup just took a look and it works with most others
including my wild card related jokers which is huge
this is called LSP (Language Server Protocol) definition
look it up online
Yes.
i have all the boosters on seperate atluses cuz that's kinda how i draw assets, not on one spritesheet like other mods
thing is
it was working before
now it isn't
waiittt
might be cuz i have x set to 1
not 0
lol
i was referencing vanilla remade's code and forgot that it would reference assets on a spritesheet atlus through changing x and y coords
yeah i was gonna say, set x = 0
no way someone else doing horoscopes 
How do i make playign cards appear in a booster pack?
wait is it draw_hand = true?
LMAO
but how can i change the background color to red?
ease_background_colour = function(self)
ease_colour(G.C.DYN_UI.MAIN, colour)
ease_background_colour({new_colour = colour, special_colour = other_colour, contrast = contrast})
end
but what about setting it to a specific hex color number?
HEX('hex')
i'm aware of that i use it in my og code but where in the function you sent if you don't mind me asking?
colour and other_colour
You need to change the first colour as well.
thank you so much!!
ok how do you run some code when a joker is added to a pool
How do I get the variable value of a Joker's sell value, when it's being sold?
card.sell_cost
You mean context.card.sell_cost? Here's why I'm asking.
hey so it seems like the inject code just isnt running at all, help
inject_card = function(self, card)
print("INJECTING RUNNINGGG\n\n\n\n\nn\n\n\n\n\n\n\n\n\n\n\n\n\n")
SMODS.ObjectType.inject_card(self, card)
print("post inject")```
Yes, if context.card is the card you want the sell cost of.
anyone know what to do?
ive also tried inject and inject_class
What is the goal?
add a badge to every joker in the pool
No, hook Game:main_menu and iterate over G.P_CENTER_POOLS.poolkey and set the set_badges function.
oh
i have a card that randomizes the ranks of discarded cards, but it sometimes picks the same rank as the card, thus doing nothing. does anyone know what i should be adding to this?
cant quite wrap my head around the logic
what is the signature of it
local ranks = {}
for k, v in pairs(SMODS.Ranks) do
if v.id ~= context.other_card:get_id() then table.insert(ranks, v) end
end
local rank = pseudorandom_element(ranks, 'seed')
seems to work perfectly, tysm!!
how would you dynamically add a line to a jokers description
in like a seperate box
like what ortalab does
Tryna use mod.calculate for this
Select UNIK joker, sell Awakening, destroys UNIK joker, spawn stronger UNIK joker I made.
How do you check for highlighted joker and then selling a specific consumable?
vanillaremade campfire
Specific
context.card is the card being sold
if context.selling_card and context.card.config.center.key == 'j_modprefix_key' and G.jokers.highlighted[1] and G.jokers.highlighted[1].config.center.key == 'j_modprefix_key' then
G.jokers.highlighted[1]:set_ability('j_modprefix_key')
end
look at Ortalab's source code
it just has multiple tables in its loc vars
but like what i want to do is dynamically add it to another card
why arent things registered with my sticker extension being added to G.shared_stickers?
how do you check for if played hand contains a scoring 7?
loop across context.scorring_cards
why did this happen? it should be an uncommon now :(
It's still in G.P_JOKER_RARITY_POOLS[3]
wow, i didn't know rarity and appearance where different
how would i change that?
You would remove it from G.P_JOKER_RARITY_POOLS[3] and put it in G.P_JOKER_RARITY_POOLS[2]
G.P_JOKER_RARITY_POOLS.j_obelisk = 2
that's my guess
ok plan's been changed, it's now gain ^chips for every card converted into a specific enhancement, as in it gains ^chips when it does become this card now.
fun
No, you would use SMODS.insert_pool and SMODS.remove_pool
oh, new territory for me, i'm going to look at the documentation :)
thank you so much!
No, it's not in the documentation.
where would i learn about this then lol, or a mod i can take reference from
Well fuck you too, it is closed on line 95 you piece of shit
SMODS.remove_pool(G.P_JOKER_RARITY_POOLS[3], 'j_obelisk')
SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[2], G.P_CENTERS['j_obelisk'])
Code?
if context.setting_blind then
local card_front = pseudorandom_element(G.P_CARDS, pseudoseed('add_card_hand'))
local base_card = create_playing_card({
front = card_front,
center = pseudorandom_element({G.P_CENTERS.m_gold, G.P_CENTERS.m_steel, G.P_CENTERS.m_glass, G.P_CENTERS.m_wild, G.P_CENTERS.m_mult, G.P_CENTERS.m_lucky, G.P_CENTERS.m_stone}, pseudoseed('add_card_hand_enhancement'))
}, G.discard, true, false, nil, true)
G.E_MANAGER:add_event(Event({
func = function()
base_card:start_materialize()
G.play:emplace(base_card)
return true
end
}))
return {
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 = { base_card } })
end,
message = "Added Card!"
}
local card_front = pseudorandom_element(G.P_CARDS, pseudoseed('add_card_hand'))
local base_card = create_playing_card({
front = card_front,
center = pseudorandom_element({G.P_CENTERS.m_gold, G.P_CENTERS.m_steel, G.P_CENTERS.m_glass, G.P_CENTERS.m_wild, G.P_CENTERS.m_mult, G.P_CENTERS.m_lucky, G.P_CENTERS.m_stone}, pseudoseed('add_card_hand_enhancement'))
}, G.discard, true, false, nil, true)
G.E_MANAGER:add_event(Event({
func = function()
base_card:start_materialize()
G.play:emplace(base_card)
return true
end
}))
return {
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 = { base_card } })
end,
message = "Added Card!"
}
end
if context.other_joker then
if context.other_joker.config.center.key == "j_cultpack_taph" then
return {
Xmult = 2,
message = "YURI!!!"
}
end
end
end
}```
ofc discord fucky wucky
You can't have code after a return.
ah.
one last question, if i have taken ownership of a joker, dose that still require editing the pool?
No, because it wouldn't be in the pool yet.
oh cool! thank you so much for helping me out :)
local g = variref(self, info_queue, card)
local lines = {}
for _, t in pairs(localize{ type = "variable", key = "[spoilers]", vars = {1} }) do
lines[#lines + 1] = {
n = G.UIT.T,
config = { text = t, colour = G.C.UI.TEXT_INACTIVE, scale = 0.2 }
}
end
g.main_end = {
n = G.UIT.C,
config = {juice = true, align = "cm", padding = 0.02},
nodes = lines
}
return g``` hovering over this crashes, it only started doing this when i returned this new column node instead of setting main_end to lines directly
this is in a loc_vars hook
its complaining about indexing local node (a number value)
this is like a turbo stupid question i think but, is there a quick way to check if a number is prime? i had a joker idea involving retriggering all scored cards if your money is a prime number but the logistics of actually calculating that sounds kinda stupid
well, yes, but no, but yes, but no
for small numbers you can just check if anything less than (or equal to) square root of number divides that number
for larger numbers there's no easy solution
you can keep a table of prime numbers but it consume large amount of memory
local function is_prime_and_reasonable(x)
if x < 2 or number_format(x):find('e') then return false end
for i = 2, math.floor(math.sqrt(x)) do
if (x % i) == 0 then
return false
end
end
return true
end
```?
Oh interesting ok
this will work up to some degree but when you hit millions it's just gonna be very slow
you didn't even skip even numbers
No, it seems to start taking more than a second at 17 digits, but at that point it would've stopped trying, because from the user's perspective, they wouldn't know if the number is prime, because it starts using e notation.
chat how do I check when a consumable is used
if context.using_consumeable
is thee a context in there that has the consumable info in it
i do need the type of consumable used too
context.consumeable
great thanks
i've been doing some research and now i have these
loc_txt = {
name = 'Spinner',
text = {
single = {
"Retrigger all {V:1}#1#{} cards,",
"suit changes every round"
},
multi = {
"Retrigger all {V:1}#1#{} cards",
"{C:attention}#2# additional times{},",
"suit changes every round"
}
}
},
loc_vars = function(self, info_queue, card)
local suit = 'Spades'
if G.GAME and G.GAME.current_round and G.GAME.current_round.spinner_card then
suit = G.GAME.current_round.spinner_card.suit or suit
end
local reps = (card and card.ability and card.ability.repetitions) or 1
return {
key = (reps ~= 1) and 'multi' or 'single',
vars = {
localize(suit, 'suits_singular'),
reps,
colours = { G.C.SUITS[suit] or G.C.SUITS.Spades }
}
}
end,
however the name and description of the joker just don't appear at all. how do i fix that?
i dont wanna look at cryptid code so uh
how do you debuff a specific rarity and only that rarity
Hi guys, I've just started creating my first mod and I'm adding some jokers. What's the easiest way to make them show up in game so I can test them? I had a look in the wiki and see G, assuming its related but still figuring out exactly what I need
If you declare a joker, you only need to make sure the file is loaded. You won't need to touch G at all!
Thanks!
is there a way to make jokers transparent
ik i could just animate the sprite
but if there was a function to increase transparency
it would save me some trouble
Can you use transparent sprites? I'm not sure, maybe that'll work?
Hey folks, I fell off the face of the planet for a few months. Came back to see that something is different between steammodded 1016c and the last version I had, 0509c
Anyone off the dome have an idea of why my mod won’t appear / load anymore on the newer version?
Easiest way to get started is to copy an existing mod like ExtraCredit. Then look at their file structure to see how it should be done, and add your joker to their files.
Then you can enable debug mode to force spawn your cards or give yourself extra cash to verify that it works
local g = variref(self, info_queue, card)
local lines = {}
for _, t in pairs(localize{ type = "variable", key = "[spoilers]", vars = {1} }) do
lines[#lines + 1] = {
n = G.UIT.T,
config = { text = t, colour = G.C.UI.TEXT_INACTIVE, scale = 0.2 }
}
end
g.main_end = {
n = G.UIT.C,
config = {juice = true, align = "cm", padding = 0.02},
nodes = lines
}
return g``` hovering over this crashes, it only started doing this when i returned this new column node instead of setting main_end to lines directly
do
g.main_end = {
{
n = G.UIT.C,
config = {juice = true, align = "cm", padding = 0.02},
nodes = lines
}
}
if card.config.center.discovered or card.bypass_discovery_center then
card.children.center:draw_shader('voucher', nil, card.ARGS.send_to_shader)
end
end```
how do I load an extra sprite in that
how do i make a card change its rank to a random rank, suit to a random suit, enhancement to a random enhancement and edition to a random edition?
local rank = pseudorandom_element(SMODS.Ranks, 'seed')
local suit = pseudorandom_element(SMODS.Suits, 'seed')
local enhancement = SMODS.poll_enhancement({guaranteed = true})
local edition = SMODS.poll_edition({guaranteed = true})
--local seal = SMODS.poll_seal({guaranteed = true})
assert(SMODS.change_base(card, suit.key, rank.key))
card:set_ability(enhancement)
card:set_edition(edition)
--card:set_seal(seal)
bumb
You mean you want to draw a sprite on that card?
yeah
like I already set the atls ans pos, I add the shaders and now I want to add a oter sprite on top
guys, isn't there an easy way to test mods, instead of relying to get the cards on a run? i saw a video of someone double clicking a mod element (a joker to be specific) and then it was added to his run
Yes, DebugPlus
You would hook Game:main_menu then put the sprite in a value in G, then do G.modprefix_sprite:draw_shader('dissolve', nil, nil, nil, card.children.center).
I forgot to mention im doing this on a seal. Would i have to make the code different?
No.
hhow do you align text nodes vertically in a column node
is there a context action that triggers when the shop is rerolled?
context.reroll_shop
ty :)
np
I'm not sure to understand what Im supposed to put in the hook
Thank you :)
G.giga_sprite = Sprite(0, 0, 71, 95, G.ASSET_ATLAS['modprefix_atlaskey'], {x = x, y = y})
oooooooooooooooh, thx man
Put each text node in a row
oh
What's the key for The Hanged Man Tarot?
c_hanged_man
Thanks
does anyone know how to get a playing card to retrigger without returning? Most methods I see have calculate = function () return {repetitions = 2}
I want to play a sound for each retrigger
No, sound = 'modprefix_key'
I'm looking to randomise the pitch each retrigger - is there a way to do that via the return?
pitch = math.random(min, max)
This Blind still gives the "Boss Disabled!" message on every scoring Diamond card, but it's only supposed to do that for the first such card. What do I do?
calculate = function(self, blind, context)
if not G.GAME.blind.disabled then
if context.individual and (context.cardarea == G.play) and context.other_card:is_suit(self.config.extra.suit) then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
blind:disable()
return true
end
}))
card_eval_status_text(context.other_card, 'extra', nil, nil, nil, {
message = localize('ph_boss_disabled'),
colour = G.GAME.blind.config.blind.boss_colour
})
end
end
end,
Is it possible to add an extra layer to jokers either above/below soul_pos but not directly on the base layer of the joker?
Set blind.disabled = true outside of the event.
look at how cryptid or entropy does it for exotic and entropic jokers, they add a third layer
it involves a custom SMODS.DrawStep
ah kk I'll check it out
What is causing this to crash? The SMODS.add_cards are fine because they're formatted like that earlier on.
And the IDs are correct as I grabbed them from another mod.
you sure yahimod's prefix is "yahimod"?
I mean... yeah?
It was the wrong one.
check the other ones too while youre at it
To do a math.random() for a chance?
no
Ok. New question:
Without any Talisman fuckery, how do generate number between 0 and 1
You're fine
Talisman doesn't change what you need to do
this is yahimod and only yahimod's fault
So I can't even generate a random number between 0 and 1 cause of Yahi's mod?
No?
the number is fine
a yahimod joker is incompatible with talisman
(twitch sub)
b r u h
target = '=[SMODS MoreFluff "MoreFluff.lua"]'
as example.
is there a way to convert a card's rank as an id into a key for the sake of localization? as in, what's the process of turning 11 as an integer into Jack as a key string
Now it doesn't give the pilfered Hand back when a Diamond card scores. What do I do?
calculate = function(self, blind, context)
if not G.GAME.blind.disabled then
if context.individual and (context.cardarea == G.play) and context.other_card:is_suit(self.config.extra.suit) then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
blind:disable()
return true
end
}))
card_eval_status_text(context.other_card, 'extra', nil, nil, nil, {
message = localize('ph_boss_disabled'),
colour = G.GAME.blind.config.blind.boss_colour
})
blind.disabled = true
end
end
end,
disable = function(self)
if not G.GAME.blind.disabled then
ease_hands_played(self.config.extra.mod_hands)
end
end,
im noticing a tiny issue with my mod
that thing in the top left is supposed to be the eternal sticker
why is it so small?
local key = ''
for k, v in pairs(SMODS.Ranks) do
if v.id == id then key = v.key end
end
thanks!
Remove the if not G.GAME.blind.disabled in disable
Still doesn't work.
how would i check if a card is being enhanced? for example via midas mask or a tarot card
Code?
calculate = function(self, blind, context)
if not G.GAME.blind.disabled then
if context.individual and (context.cardarea == G.play) and context.other_card:is_suit(self.config.extra.suit) then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
blind:disable()
--card:juice_up()
return true
end
}))
card_eval_status_text(context.other_card, 'extra', nil, nil, nil, {
message = localize('ph_boss_disabled'),
colour = G.GAME.blind.config.blind.boss_colour
})
blind.disabled = true
end
end
end,
disable = function(self)
ease_hands_played(self.config.extra.mod_hands)
end,
if context.setting_ability and context.old and not context.unchanged and G.P_CENTERS[context.new].set == 'Enhanced' then
seems to be the case
though i dont think that should happen if thats set as the actual atlas dimensions
its probably that the sprite is much larger but is displayed at about one fifth of its actual size, which causes the eternal sticker to also get scaled down
hey how do you spawn a joker from a specific pool
set = "<pool key>"
with or without mod key
To go further, here's an excerpt from Wraith:
SMODS.add_card({ set = 'Joker', rarity = 'Rare' })
no like a custom pool type
Without the mod prefix unless you added it yourself.
how would i get the card this is affecting? specifically for setting the enhancement and edition of it
context.other_card
oh LOL ok
hi i wanna make this joker self-destruct before scoring if the current blind is the water, but this only makes it self-destruct after scoring, any timing help
return { func = function() SMODS.destroy_cards(card, nil, nil, true) end }?
well it doesn't score anymore but it still happens after the scoring animation which is strange
Is there built-in functionality to have it so that rerolls also reroll vouchers and booster packs, or will I have to code that in myself?
Move the true to the third input.
that stuff i think cryptid? does where things in the shop are face down, is that difficult to do?
Yes, you have to do it yourself.
Okay, just checking!
In that case, I'm aware it's possible to change the number of booster packs/vouchers that can show up initially in shop with SMODS.change_booster_limit and SMODS.change_voucher_limit, but is there a number I can access for these?
just getting the booster limit or voucher limit
2+(G.GAME.modifiers.extra_boosters or 0) and 1+(G.GAME.modifiers.extra_vouchers or 0)
thanks!
how would I exponentiation into my mod? I just want a simple ^2 or ^3 but I don't know how I'd do it
mult_mod = (-mult)+mult^number
trying to set up a deck and it keeps crashing the second i try to go to the decks menu, it's giving me this error but that doesnt make much sense to me since it does have an extra field?
does anyone know any other decks that use probabilities within them? for cross referencing purposes
you have this: { extra = {...} } when it should just be extra = {...}
in the config line, remove the blue brackets
oh youre wise af good eye
ok next question 🔥 i didnt expect this to crash but i guess maybe theres some sort of extra steps needed to make something work from within a deck? it crashes at the context line because it cant index context
cus you're using the apply function
you want calculate
ohhhh omg right
works thanks :)
Is there a better way to get a single table item, where there's only 1 item in it, and it's formatted as:
{ Hearts = true } ?
Currently I'm just making a new table and inserting its name as the value instead. It's purposefully set up as the name, so that locating suits during processing is a lot cheaper.
Here's the code so far, where suitTable is an aforementioned 1 item table:
if suitAmount == 1 then
local single = {}
for key, _ in pairs(suitTable) do
table.insert(single, key)
end
return single[1]
end```
local key, value = next(suitTable)
oh sick! thanks!
this is probably very wrong but im trying to make a card that upon buying makes itself eternal, its a contract of sorts. How can this be fixed? It does nothing currently and is likely very wrong
add_to_deck should be outside calculate
it's a separate function that the joker owns
ah
Anyone know why this sticker just applies to all jokers? I have this should apply function, and I have rate set to 0.03, so I'd like it to apply to only 3% of all jokers.
should_apply = function(self, card)
if next(SMODS.find_card("j_willatro_monitoring")) and card.ability.set == "Joker" and not card.eternal then
return true
end
end
the rate is ignored if you have a custom should_apply function
you'll need to incorporate it into the should_apply (add and pseudorandom("seed") < 0.03 to the conditions in the if statement)
okay it adds eternal but can still be sold. is there not smods support for it yet?
stickers only do stuff on jokers i think
if you want a consumable type that can't be sold then you may as well add custom handling for that
No, hook Card:can_sell_card
eh this does its intended purpose
ok nvm
caused some unintended consequences, but ill see if your method works too
How would I reset the hands and discards to what they were at the start of the blind? Would I have to store the hands and discards values at the start for retrieval later, or is that already stored somewhere?
No, you would have to do it yourself.
figured out hooking, but how do i make it hook for a specific consumable type? this does not work
if self.ability.set == 'key'
Now, how could I prevent death without finishing the round?
how do i tell if a joker can be retriggered? would it be blueprint_compatible?
You can't.
a
okii
if i wanna do logic before a context.retrigger_joker_check, where would i put it?
wait hold on i got it lol
i'm dumb
i forgor variables exist lmao
how do i put a # in a card's name?
\# gives a crash
invalid escape sequence
hold on i found a modded joker that does it
..
they had to use a loctxt entry lmao
calculate = function(self, card, context)
if context.before then
card.ability.extra.target = pseudorandom_element(G.jokers.cards, "elle_41", {in_pool = function(v, args) return v ~= card end})
end
if context.retrigger_joker_check and card.ability.extra.target and context.other_card ~= card.ability.extra.target then
return {
message = "Again!",
repetitions = 1,
card = card
}
end
end```anyone know why this isn't retriggering?
wait
did i add the optional feature
ye i did
oh i'm fuckin dumb
this is what i get for recycling old code
~=
changing the ~= to == didn't fix it
wait
i was testing it with a joker that just didn't trigger i think
ok it did work
i'm dumb

hrm
i was gonna say you shouldn't be storing a card in another card but it's all happening within a single hand so the issues probably won't pop up
(it can cause save/load problems)
also i've just added card.ability.extra.target = nil before the return
was about to suggest it lmao
Is there even a way to do the prevent death mechanic without ending the round? I'd like to reset hands and discards if chips scored are at least 50% of required chips at the end of the round.
non-zero chance you can just call ease_hands_played(number) and ease_discards(number) and it'll work out fine? you'll definitely have to do more work if you also want to reshuffle the discard pile and the player's hand back into the deck
Check the score against blind requirements in context.after and if you ran out of hands, do what "Reboot" Code card does.
An unbalanced Balatro mod. Contribute to SpectralPack/Cryptid development by creating an account on GitHub.
Would context.other_card:set_ability(G.P_CENTERS.m_PREFIX_ENHANCEMENTKEY, nil, true) work to apply a custom enhancement?
...as long as context.other_card is valid, yeah.
I'm making something that works with the Partner API but the unlock screen has the loc vars listed as nil
Where do I find mod samples
Explain "mod samples"?
Sorry i meant examples
I don't really know where to start other than using joker forge
Here are some good spots to get something going
^ vanillaremade is fantastic
it reimplements basically all vanilla content in SMODS for reference purposes, and the wiki has a bunch of good resources too
And there's always digging through other mods' code to figure out how they do things
Aight thanks
how do I prevent this so it create a mars and the mars it the 8% on first card and at the end mars reapear cause it wasnt in the pack
You could set a metatable on G.GAME.used_jokers or you could patch get_current_pool.
if card.area and card.area == G.consumeables then
local other_consumeable = nil
for i = 1, #G.consumeables.cards do
if G.consumeables.cards[i] == card then other_consumeable = G.consumeables.cards[i + 1] end
end
end
local compatible = other_consumeable and other_consumeable ~= card and other_consumeable.config.center.blueprint_compat
return { vars = { card.ability.extra.slots, main_end = {
{
n = G.UIT.C,
config = { align = "bm", minh = 0.4 },
nodes = {
{
n = G.UIT.C,
config = { ref_table = card, align = "m", colour = compatible and G.C.GREEN or G.C.RED, r = 0.05, padding = 0.06 },
nodes = {
{ n = G.UIT.T, config = { text = ' ' .. localize('k_' .. (compatible and 'compatible' or 'incompatible')) .. ' ', colour = G.C.UI.TEXT_LIGHT, scale = 0.32 * 0.8 } },
}
}
}
}
} } }
end,```
can you guys help me figure out why the compatible/incompatible ui bubble isn't showing up in my consumable?
question: how do i make a joker upgrade a hand by several levels
SMODS.smart_level_up_hand(card, 'modprefix_key', nil, number)
ah
so something like this
calculate = function(self, card, context)
if context.before then
SMODS.smart_level_up_hand(card, 'modprefix_key', nil, 3)
end
(?)
No, it would be return {level_up = 3}
ah
huh
so
calculate = function(self, card, context)
if context.before then
return {
level_up = 3,
message = localize('k_level_up_ex')
}
end
or do i add return { level_up = 3 } here
Yes.
huh
You're missing an end
update: fixed
...i just noticed that
Is there a way I can move the text (with the diamond in the background, e.g. "Nope!") to any location I want?
I'm making a Joker that gives Mult for each time the Joker on the left triggers
I want it to say "+2 Mult" under the triggered Joker, and not the Joker I'm making
If i wanted a consumable to be able to adjust any joker associated with money in some way how could I?
how so?
message_card = the other card in your return table
Thank you!
Why's your mars so sparkly?
how can i remove a voucher from the shop?
I mean the shop area
When i remove it from the round vouchers it wont appear in the next shop but it remains in the current one
so i need to also remove it from the current voucher area but idk how
Cause its an variant of mars called astral mars
How could I set the sell value of all owned jokers to 0?
local sc_ref = Card.set_cost
function Card:set_cost()
local sc = sc_ref(self)
if (condition) then
self.sell_cost = 0
self.sell_cost_label = self.facing == 'back' and '?' or self.sell_cost
end
return sc
end```
Is there a way I could do this from within a joker?
Yeah, do something to set the condition to true and call every joker's set_cost function
Hmm, I've got something like this for my calculate:
calculate = function(self, card, context)
if context.after and G.GAME.chips / G.GAME.blind.chips >= to_big(0.5) and G.GAME.current_round.hands_left <= 0 then
G.GAME.willatro_saved = true
for i = 1, #G.jokers.cards do
G.jokers.cards[i]:set_cost()
end
end
end
and this for my hooked set_cost:
local oldsetcost = Card.set_cost
function Card:set_cost()
if G.GAME.willatro_saved == true then
self.cost = 0
self.sell_cost_label = self.facing == 'back' and '?' or self.sell_cost
else
return oldsetcost(self)
end
end
But it doesn't work, anyone know why? I know for sure the calculate condition is being met, so G.GAME.willatro_saved should be getting set to true. Other than that, idk.
any way to make a boss blind's description change depending on whether its being viewed from collection or in a run?
much like the ox's
Playing a (most played hand) sets money to 0. (in collection)
Playing a High Card sets money to 0. (in run)
i tried looking at vanilla remade, but im not entirely sure how it writes the rest of the description
You modified self.cost instead of self.sell_cost
Also you might want to make the condition be a value that each joker has in its ability table, cus right now after your ioker triggers, all cards will have a sell cost of 0 when their cost updates
What do you mean?
For example, inside the loop do
G.jokers.cards[i].ability.modprefix_some_name = true
And in the set cost hook do
if self.ability.modprefix_some_name
The description of the blind is in the localization file btw
i seriously don't understand this wiki
it's so complete yet so incomplete
or idk how to navigate through it
for example
I know that SMODS.is_eternal is to check if a joker is eternal
however
I don't find a function that is called SMODS.is_negative or smth similar
and i don't find where this is documented either
also why can't i just do smth like
G.jokers.cards[index]:is_eternal()
instead of SMODS.is_eternal
isn't this object oriented programming?
Because is_eternal is on SMODS not Card
that's my point
why are they separated
usually it is best practice to put functions for a mod inside of a seperate table, which is probably why they did that
you could argue that SMODS is a different case but you can talk to the steamodded devs for that
is there a context for a Joker being destroyed? (not sold)
context.joker_type_destroyed and context.card.ability.set == 'Joker'
this is for the Joker being destroyed only, right?
No, it's any joker being destroyed.
Put it in remove_from_deck and check if not G.CONTROLLER.locks.selling_card
how do i get if i'm in a challenge run
how would i get the rank and suit of a stone card y’all?
G.GAME.challenge is nil if not in a challenge
ty
card.base.id and card.base.suit
thankers
Is there a way to align the label of UIBox_button
Like it's aligned to cm be default I think
my probability description works normally in the collection but not ingame, why is this?
Code?
You should be using SMODS.get_probability_vars not G.GAME.probabilities.normal
I tried that beforehand with the same result
You're returning the main_end by itself, without vars
combined both returns into a single line and now I'm having the opposite problem (works ingame but not in collection)
Hi, is there a way to discard cards in deck? The function G.FUNCS.discard_cards_from_highlighted is only for cards in hand, and I want a boss blinds that discards half the cards in your deck when you enter the blind
Code?
alright, that was the problem, everything is working now
thank you for your help
can you call G.GAME.joker_usage to get the amount of obtained jokers like how you can call G.GAME.consumeable_usage?
No, because it doesn't exist.
how exactly does the atlas function work for SMODS? ik it sets a key and a path but i have no idea what the px and the py are (i'm assuming they're coordinates but the numbers seem really arbitary, is it like the size each sprite is?)
ah, i saw this in the game object function being used for tracking jokers for profiles, so i thought that it could be used
how can i change the rate of booster packs during a game?
trying to count jokers, but not sure what i'm doing wrong here
@daring fern, I'm patching draw_card(G.play,G.discard, it*100/play_count,'down', false, v) from functions/state_events.lua, and I want to tell if a card in the played hand was or wasn't part of the scoring hand. Could you help me?
The Hill
Extra large blind, scored cards return to deck
No, hook G.FUNCS.draw_from_play_to_discard
That's where I'm taking it from. And I'm sorry, but I meant "patch" but typed "hook".
G.FUNCS.draw_from_play_to_discard = function(e)
local play_count = #G.play.cards
local it = 1
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
end
end
@daring fern?
hey its my first time making a mod in balatro and everything works as intented except for the X multi message that instead says ERROR
code?
in a min
something annoying about lua:
despite the key names being exactly the same, the order still counts, meaning that these two are completely different tables
No, every table is a different table.
i guess i'll have to start sorting these types of tables in order to properly compare them
uhh
SMODS.Atlas {
key = "Jokers",
path = "Jokers.png",
px = 71,
py = 95
}
SMODS.Joker {
key = 'housejoker',
loc_txt = {
name = 'Dr. Full House',
text = {
'This Joker gains {X:mult,C:white}X#2#{} Mult for each',
'scoring {C:attention}Full House{} played',
'{C:inactive}(Currently {X:mult,C:white}X#1#{C:inactive} Mult)'
}
},
config = { extra = { Xmult = 1, Xmult_gain = 0.25 } },
rarity = 3,
atlas = 'Jokers',
pos = {x = 0, y = 0},
unlocked = true,
cost = 8,
loc_vars = function(self,info_queue, card)
return { vars = {card.ability.extra.Xmult, card.ability.extra.Xmult_gain} }
end,
calculate = function(self,card,context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = localize { type = 'variable', key = 'a_Xmult', vars = { card.ability.extra.Xmult } }
}
end
-- Displays the Upgraded! message when Full House is played.
if context.before and next(context.poker_hands['Full House']) and not context.blueprint then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
return {
message = 'Upgraded!',
colour = G.C.MULT,
card = card
}
end
if context.joker_main then
return {
card = self,
Xmult_mod = card.ability.extra.Xmult,
message = 'X' .. card.ability.extra.Xmult,
colour = G.C.RED
}
end
end
}
idk how to send code as in code and not this
i will delete this message if needed
Instead of message = 'Upgraded!', try message = localize('k_upgrade_ex').
And you can enclose lua code in backticks thus. Try it for any code you share in messages.
still displays the error
the upgrade part works but the x mult says error idk if there should be anything else in the code for that to work as intended
Instead of Xmult_mod, you need only return xmult. Apart from colour, delete the other return statements. The messages handle themselves.
Remove the card = self
Also, it pleases me to see another modder squeezing in a pop-culture reference for a modded Balatro item.
What's your return statement look like now?
-- Displays the Upgraded! message when Full House is played.
if context.before and next(context.poker_hands['Full House']) and not context.blueprint then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
return {
message = localize('k_upgrade_ex'),
colour = G.C.MULT,
card = card
}
end
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = 'X' .. card.ability.extra.Xmult,
colour = G.C.RED
}
end
not sure exactly what you mean (if its not this)
return {xmult = card.ability.extra.Xmult}
im still getting the same error message
ok no need found a fix
Basically you have an if statement that will only load the content if the mod is found
if (SMODS.Mods.ChDp or {}).can_load then
Challenger deep mod was the example here
i put this in the first line?
if next(SMODS.find_mod('modid')) then
SMODS.Joker({...})
end
Or you could just do dependencies = 'modid' in the joker.
Or dependencies = {'modid1', 'modid2'} if it requires multiple mods.
Code?
You're missing the end
where?
For the first if
what?, could you tell me specifically where? i dont know much about code, so i didnt understand
@daring fern

before the first SMODS.Joker
above it
how do you check if a card is always scoring
if SMODS.always_scores(card)
Anyone know why add_tag(Tag("tag_orbital")) doesn't choose a poker hand to upgrade, and how I can fix it?
Anyone know how to add more quotes for Jimbo to say on game over?
And have him say certain things if you die under certain conditions?
You need to manually set the actual poker hand.
when is context.destroy_card called
It is called for every playing card after scoring.
oh
Ok, I need ask a question but going to be careful this time cause I don't know if my memory playing trick on me. But vaguely remember a mod, where you could give editions like steel, stone, bonus and lucky to your Joker or did I dreamed this
Thank you with that being said, would anyone know if I may use this feature?
hi im having some difficulty crossmodding with finity
im assigning my blind to the global table but checking in debug plus its not there
it cant be a file not being loaded issue bc the joker thats defined in the same file is loading
Code?
1 FinisherBossBlindStringMap = FinisherBossBlindStringMap or {}
2 FinisherBossBlindStringMap["bl_nflame_jpenguin"] = {"j_nflame_jpenguin", "Jade Penguin"}```
What priority is your mod?
help
context.other_card.lucky_trigger = true doesn't trigger Lucky Cat for some reason. What do I change it to?
Code?
sorry, I hit the 2000 character limit
Here's the relevant parts of the code:
(I'm still very new to Lua so I learned via seeing how other modders do it)
Are you trying to make it so jokers are like lucky cards when they trigger?
this gives me a plan
if context.post_trigger then
local passed
for k, v in pairs(G.jokers.cards) do
if v == card then
passed = G.jokers.cards[k-1] == context.other_card
end
end
if passed then
return {func = function()
local old_ability, old_center, old_center_key = copy_table(context.other_card.ability), context.other_card.config.center, context.other_card.config.center_key
context.other_card:set_ability(G.P_CENTERS['m_lucky'], nil, 'quantum')
SMODS.score_card(context.other_card, {cardarea = G.play})
context.other_card.ability, context.other_card.config.center, context.other_card.config.center_key = old_ability, old_center, old_center_key
end}
end
end
```?
I'll try that and see what happens
yeah now it doesn't do anything
I'll try to find something that helps it work
I think I fixed it.
YEAH IT WORKS
Thank you so much!!!
I can't believe that much code can replace what I had
I really need to learn more lua
staring at the smods documentation for an hour and still having no idea how to add ui to the game
what kinda ui do you want
like the area where consumeables are stored, but for a new consumeable type
ah, a cardarea
idk how to add to the vanilla ui, but
if you look at the vanilla code, look for CardArea
i'd help more but i'm not at my pc rn
How would I get started on my making my own joker texture pack, like actively replacing all of the current joker designs?
malverk
I thought you said smth in Norwegian and then looked up and saw it was a mod...
Thanks though
theres also take ownership 🥰
im looking at github page for instructions, it aint really clear imo
do i gotta make my own file and link every joker to each retexture?
aight
...it'd be even more tedious without malverk btw
ye I know, well off to make the art
info_queue[#info_queue + 1] = G.P_CENTERS.m_steel
local steel_tally = 0
if G.playing_cards then
for _, playing_card in ipairs(G.playing_cards) do
if SMODS.has_enhancement(playing_card, 'm_steel') then steel_tally = steel_tally + 1 end
end
end
return { vars = { card.ability.extra.xmult, 1 + card.ability.extra.xmult * steel_tally } }
end,```
Hey guys. I'm making a Joker similar to the Steel Joker so I was looking at it for reference, and it all makes sense to me except: *info_queue[[#1116390750314307698](/guild/1116389027176787968/channel/1116390750314307698/)_queue + 1] = G.P_CENTERS.m_steel*
What does that do? Is it important?
It seems to check for the steel enhancement in... something.
its that little box
gives the name and description of whatever's put in the info queue
Ohhh, so it's an information thing. Thanks! I guess the name info_queue should've given it away.
Still gotta familiarize myself with a lot of this stuff
so i figured out a way to add the ui
but uhh
does anyone know how to add onto the functions in the games code
with the mods code
and without anything inside the function
that's what lovely patches are for

if you only need to add something to the start/end of a function though, a hook should work fine
my two braincells hard at work rn
what would i use to check if a joker was added to the joker area through any way, like hologram but for jokers?
this for playing cards
context.card_area supposedly triggers when a joker is added?
cus i am trying to convert jokers that are bought or added into another type
?
if context.card_added and context.cardarea == G.jokers then
-- do shit
end
Should only trigger when a card is added to G.jokers.
(any card, though normally only jokers would go there)
Kk
how to check when you spend money on stuff
how does one skip a blind? im tryna find out how to always skip the big blind every ante
I'm making a custom challenge and deck just to test my jokers with, but the game crashes when I try to add them. I think it has to do with the fact that my jokers are in a separate folder but I'm trying to call them from the main.lua? The jokers themselves do work. Do I need more than just the key if the jokers aren't in the same lua file?
context.money_altered
yeah ik got the answer in another server
oof
what does skip mean in your context
as in "big blind select button doesn't work, getting a tag is the only option" or "hide big blind"
well i at first wanted the big blind to just not appear at all and thats the most ideal, othrwis i want it skipped with no tag
hiding is easy tho, vanilla already supports that iirc
set corresponding blind state to "Hide"
I recommend doing that before leaving the shop
context.ending_shop? or context.reroll_shop?
is it a joker effect?
challenge deck
I'm still stuck on adding mod jokers to a custom deck and challenge. 😮 It crashes, so it must not recognize the ID somehow.
can you send your code
The challenge is super basic, it's just
key = 'Chrysta',
loc_txt = {
name = "Chrysta"
},
jokers = {
{ id = 'mwj_chrysta' }
}
}```
also include the j_
so j_mwj_chrysta
Would that do it? 😮
i don’t think there’s a single instance where j_ is assumed haha
wait is that j in mwj part of the prefix or is the prefix just mw and you added j_ after it
That was it. Holy crap. How did I overlook that?
I have my own prefix (mwj for magicwritings jokers) and thought it replaced the other one.
How do you add localization to a challenge deck?
i can set the name but not the rules stuff
awesome
is that ourple guy?
not even vanillaremade has localization for them besides the names
how does it work
You can do this in your localization
misc = {
v_text = {
ch_c_customruleid = { "challenge description" },
},
}
little men that form part of a choir
thanks, idk why its like that but this worked
i'm gonna add an ourple guy joker to my mod now
is it possible to split a legendary joker so the the main sprite is on one atlas and the soul layer is on a different atlas? I feel like it should be possible but my brain is being especially smooth today
that's not currently a thing smods supports
it's definitely possible (the vanilla soul does this) it's just not implemented
ah, okay. I thought it might be one of those things where you could do it with some fancy variable work in a separate lua file like sometimes happens with animated jokers
why is this not working? ```calculate = function(self, card, context)
if context.shop then
if G.shop_jokers then
for _, card in pairs(G.shop_jokers.cards) do
if not card.ability.extra.activated then
card.ability.couponed = true
card:set_cost()
card.ability.extra.activated = true
end
end
end
end
if context.end_of_round and context.game_over == false and context.main_eval and context.beat_boss then
card.ability.extra.activated = false
end
end``` im trying to make a joker that gives a free joker in the shop each ante but it's doing nothing
context.shop doesn't exist.
i figured, but i couldn't find any context that worked
cant you just look for shop jokers by themselves?
by removing the "if context.shop then"?
ya
it still did nothing
wait
the for loop uses card for a singular joker in g.shop blah blah but your card ability check also uses card?
could it be that
right i did see that aswell, also it did something this time hold on
No, it's context.starting_shop
ok then what would i use to check the joker ability extra instead of card?
No, you would change the variable from card to something else.
you change the for loop's card so you use a different variable name for the joker cards
oh ok
ok it's working now thank you's
i hope you carry this knowledge with you on your coding journey
i will
also another quick question, what's the sound name that plays when a tag is triggered?
you can look around the vanilla code ig?
yeah im doing that rn
Late response but no it's the FNF mod of a funny Purple guy from FNAF.
hold on
what
i was telling you what was in the screenshot
but ok
Oh.
My bad.
I didn't know
I have not heard about "little men that form part of a choir"
I'll hae to look
sorry for the confusion
its a play on the words in the song title "little man choir"
song was made in a server im in and no you wont find it anywhere
I want to patch draw_card(G.play,G.discard, it*100/play_count,'down', false, v) from function/state_events.lua, 'cause I want to tell if a card in the played hand was or wasn't in the scoring hand -- for a new Boss Blind. Could you help me?
G.FUNCS.draw_from_play_to_discard = function(e)
local play_count = #G.play.cards
local it = 1
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
end
end
The Hill
Extra large blind, scored cards are shuffled back into deck
Additionally, playing a Pair with two non-scoring cards and quickly running eval #SMODS.get_card_areas('playing_cards')[1].cards returned 4, which means that it doesn't distinguish scoring cards from non-scoring cards.
Am I able to save data to a joker outside card.ability or is that not an option since it gets nullified when you load the save?
couldnt you use regular calculate function for this if im not mistaken?
then just place the cards back in deck
or am i stupid
I don't know how I'd do that. And the thing is, I want to replace draw_card(G.play,G.discard) with draw_card(G.play,G.deck).
are you sure youd like to patch that
you can do calculate = function(self, context) (i think?) and it'll do things like the normal joker calculate function
Sure, why not? I patched for another Boss Blind and it works peachy-keen:
The Poison
Cards scored this round will be debuffed in the next Ante
And I seek to change the function, not merely call it.
in the patch's position setting you can
Yes, I'm familiar with the position setting, and I'll include the original statement within so other mods that patch that statement will still work.
What I ask is, how in functions/state_events.lua does it determine which cards are or aren't in the scoring hand? If I play a Three of a Kind and two other junk cards, how does it know to include the three and exclude the others?
i didnt know state events did that
That's where hand calculation is governed.
Set a flag on scored cards in context.before, then check for that flag in the patch.
I took a look in smods\src\utils.lua and found out the SMODS.in_scoring() function; could I run that on each discarded card and have that work, too?
No.
How in context.before do I tell if a card scored?
if SMODS.in_scoring(card, context.scoring_hand)
huh?
It should be card:start_dissolve({G.C.HPR_STLR})
works now, but the cards it creates arent being made eternal
Put force_stickers = true in the SMODS.add_card
how was it possible to redefine functionality of an already existing joker?
take ownership 🥹
okay so apparently i was misinformed in thinking that eternal consumables worked by default, does anyone know how i can make them work? i tried looking at both cryptid and entropy for their patches that do this, but i could only find the patches for eternal playing cards there
ah I see and understand
SMODS.Take_Ownership
no, it is SMODS.whatever:take_ownership()
how do i make it so when a card with an enhancement score, every card (doesnt matter the enhancement for them) gets the same enhancement as the card?
am I missing something here? the game seems to exit when the card tries destroying itself (not a crash, seems to be a "clean" exit)
key = 'triceratops',
atlas = 'Jokers',
fg_data = {
is_alternate = false,
alternate_key = 'j_giga_triceratops_alt'
},
pos = {x = 4, y = 5},
cost = 5,
rarity = 2,
blueprint_compat = true,
eternal_compat = true,
config = { extra = {
odds = 1,
chances = 8,
interac = {
ptera_chance = 6
}
}},
loc_vars = function(self, info_queue, card)
local chances = next(SMODS.find_card("j_giga_pteranodon" or "j_giga_pteranodon_alt")) and card.ability.extra.interac.ptera_chance or card.ability.extra.chances
local numerator, denominator = SMODS.get_probability_vars(card, card.ability.extra.odds, chances, 'prob')
info_queue[#info_queue+1] = G.P_CENTERS.m_mult
return { vars = { numerator, denominator } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
local theChances = next(SMODS.find_card("j_giga_pteranodon" or "j_giga_pteranodon_alt")) and card.ability.extra.interac.ptera_chance or card.ability.extra.chances
if SMODS.has_enhancement(context.other_card, 'm_mult') then
if SMODS.pseudorandom_probability(card, pseudoseed('giga_triceratops'), card.ability.extra.odds, theChances, 'tcrtp_prob1') then
print("ok")
return {
level_up = true,
message = localize('k_level_up_ex')
}
end
end
end
end
}```
why it never level up the hand
i think you need to give a count
It can be true as well
nvmd
That works as 1 level
okii
print out theChances after setting it
i dunno what you're trying to do but you're definitely doing the probabilities wrong
how do i make a joker act eternal without the sticker
Hook SMODS.is_eternal
how does main_start and main_end work for multi-box descriptions?
it always gets put on the first box
and there isnt a way to put that stuff in any of the other boxes?
not that i know of
how would you force a joker to appear debuffed but it still calculates
im new to modding, does anyone know whats the best way to handle a simple true/false switch to a joker
i have essentially a blueprint clone and a boolean on the extra vars, and i want it to only check when it triggers to turn that boolean to false
actually how would you make a joker able to buff and debuff itself?
Is there any mod that allows for purchasing 1 voucher out of some like 2
You put
If card.debuff then
Simply you're checking for the debuff and because the game returns a nil for all of the other effects your action works only when it's debuffed.
wait how would you make a card debuff itself then undebuff at end of ante then
if the end_of_round context is nil
Why instead of debuffing you dont just, make it not do the thing?
why involve debuffing
anyone know why this doesn't work
-- Hide the cost
local sc_ref = Card.set_cost
function Card:set_cost()
local sc = sc_ref(self)
if (self.config.center_key == "j_elle_cassie2") then self.sell_cost_label = '?' end
return sc
end```
im pretty sure set_cost updates the cost label?
wait why are you overwriting Card instead of just putting set_cost in the jokers set_cost
the label is updated every frame iirc
so put it in the jokers update func?
that function runs before it's updated so you'll have to hook update and put it at the end
are you and slimestuff working in the same mod
hook Card:update
uhh no but im also a bit curious on how to do that
does anyone know how to deal with edge cases where you want to tell if a SMODS.blueprint_effect trigger happened but there is no return value to it?
you cant check for everytime it is called because it triggers on pretty much everything
edge cases in question are things like perkeo and abstract joker
No, the reason it doesn't return anything is because the joker doesn't return anything.
yes i know
but i want to have a joker that essentially acts as a blueprint but only activates once per ante
and the code i have works fine for everything except perkeo and abstract joker, and probably other edge cases i havent seen
Code?
calculate = function(self, card, context)
if context.post_trigger then
card.ability.extra.active = false
end
local other_joker = nil
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i + 1] end
end
local ret
if card.ability.extra.active then
ret = SMODS.blueprint_effect(card, other_joker, context)
end
if ret and card.ability.extra.active then
ret.colour = G.C.GREY
card.ability.extra.active = false
return ret
end
if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
if context.beat_boss and card.ability.extra.active == false then
card.ability.extra.active = true
return {
message = localize('k_reset'),
colour = G.C.GREY
}
end
end
end,
}
where card.ability.extra.active is a boolean
ignore the post trigger thing at the beginning of the block it doenst work
it is mostly copied from the vanillaremade source
Yes, you would have to hook card_eval_status_text and SMODS.calculate_effect and make it so they don't trigger until you allow them to.
how so?
gosh diddly damn dang darn, my frigign mod crashed
calculate = function(self, card, context)
if card.ability.extra.active then
local other_joker = nil
for k, v in pairs(G.jokers.cards) do
if v == card then
other_joker = G.jokers.cards[k+1]
end
end
G.modprefix_no_calculating_effects = true
local ret = SMODS.blueprint_effect(card, other_joker, context)
G.modprefix_no_calculating_effects = false
if ret or G.modprefix_failed_at_calculating_effects then
card.ability.extra.active = false
if ret then ret.colour = G.C.GREY return ret else
return SMODS.blueprint_effect(card, other_joker, context) end
end
end
if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
if context.beat_boss and card.ability.extra.active == false then
card.ability.extra.active = true
return {
message = localize("k_reset"),
colour = G.C.GREY
}
end
end
end
local oldcardevalstatustext = card_eval_status_text
function card_eval_status_text(card, eval_type, amt, percent, dir, extra)
if G.modprefix_no_calculating_effects then
G.modprefix_failed_at_calculating_effects = true
return nil
end
return oldcardevalstatustext(card, eval_type, amt, percent, dir, extra)
end
local oldsmodscalcindeff = SMODS.calculate_individual_effect
SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, from_edition)
if G.modprefix_no_calculating_effects and effect and next(effect) then
G.modprefix_failed_at_calculating_effects = true
return nil
end
return oldsmodscalcindeff(effect, scored_card, key, amount, from_edition)
end
```?
oh jeez hold on
oh wow it works man thanks a lot
hmm actually when i buy a joker it goes inactive
perhaps it is better to try to hook SMODS.blueprint_effect?
anyways i had no idea you could just override function like that ill try just forcing a return for every blueprinted copy
how would I be able to get the set_blind effects of vanilla blinds?
anyone know where the vanilla joker keys are stored in the source code?
or the wiki
Which part of the gold card's code actually determines how much money it gives? Changing h_dollars in center.config doesnt seem to change anything
changing center.config won't do anything to the actual card, you have to change context.other_card.ability.h_dollars
game.lua
Ah, that seemed to do it, yeah, thank you so much!
Anyone know how create_option_cycle works for the config tab?
Or the parameters?
create_toggle({
align = "tl",
label = "Epic Jokers",
ref_table = dandysworld.config_file,
ref_value = "epic",
callback = function(_set_toggle)
dandysworld.config_file.epic = _set_toggle
NFS.write(dandysworld.config_path, STR_PACK(dandysworld.config_file))
end
}),
create_option_cycle({
align = "tl",
label = "Epic Jokers",
ref_table = dandysworld.config_file,
ref_value = "epic",
}),
question: how do i make a joker make a specific consumable with a negative edition
SMODS.add_card({key = 'c_modprefix_key', edition = 'e_negative'})
the key is the key of the consumable right
Yes.
aight thanks
this makes 9 of em though 😭
i only want 2 to appear

