#💻・modding-dev
1 messages · Page 475 of 1
so it should be
SMODS.Joker {
key = "universal_joker",
config = { extra = { h_mult = 1 } },
rarity = 2,
cost = 10,
blueprint_compat = true,
eternal_compat = true,
pos = { x = 1, y = 0 },
atlas = "placeholders",
demicoloncompat = true,
loc_vars = function(self, info_queue, card)
return {
vars = {
number_format(card.ability.extra.h_mult),
},
}
end,
calculate = function(self, card, context)
if context.before and context.cardarea == G.play or context.forcetrigger then
return {
G.GAME.hands[context.scoring_name]mult = G.GAME.hands[context.scoring_name]mult + card.ability.extra_h_mult
}
end
end,
}
actually hold on
there's a few things odd here
one moment
okay @real night what's the intended effect here i'm quite confused
Firstly, do if context.before or context.forcetrigger then, Secondly, move it out of the return.
i think it's meant to be cards held in hand
or something?
No, that is required.
weird; i was told that when doing stuff here
info_queue[#info_queue + 1] = G.P_CENTERS["e_crp_four-dimensional"]
i mean there has to be a reason it's h_mult
i think that's the example in smods docs/example mod or something
unsure
Then why are they checking for G.play?
that's true i mean we don't really know until poker answers
no h_mult is hand base mult ðŸ˜
alright then
this is good then
SMODS.Joker {
key = "universal_joker",
config = { extra = { h_mult = 1 } },
rarity = 2,
cost = 10,
blueprint_compat = true,
eternal_compat = true,
pos = { x = 1, y = 0 },
atlas = "placeholders",
demicoloncompat = true,
loc_vars = function(self, info_queue, card)
return { vars = { number_format(card.ability.extra.h_mult) } }
end,
calculate = function(self, card, context)
if (context.before) or context.forcetrigger then
G.GAME.hands[context.scoring_name].mult = G.GAME.hands[context.scoring_name].mult + card.ability.extra.h_mult
end
end
}
question how do I use debug plus to give myself my custom spectral card to test?
No, it's just 3.
oooh ty
by default in latest versions, it's ctrl+3
i disabled that, but that's the default afaik
last time i updated, ctrl + 3 was the default configuration
this is wrong but I might just leave it like this because it's funny
odd
ahh
No.
hey question before this gets heated how do I tell balatro when I want my spectral card to be used?
which is whenever there's dealt cards
end result is create 1 copy of each card in hand
- nothing's gettiong heated 😠(to put of the flames)
- you use a return on can_use
here i'll give an example
for example, this just checks if you have enough joker slots for an item
can_use = function(self, card)
return G.jokers and #G.jokers.cards < G.jokers.config.card_limit
end,
not entirely sure how it works but uhh it works
can_use = function(self, card)
return G.hand and #G.hand.cards > 0
end,
what did you want in specific though
this
well it should just be able to be used whenever there's cards to duplicate
i'm having trouble thinking of a situation where that's not applicable to be honest
oh yeah that's fair
okay I can now use it
but the code chatgpt gave me to duplicate the hand doesn't work (no shocker there)
Then you would seem to be on DebugPlus version 1.0.0 or before?
i mean i've updated after that situation but likely so lol
i didn't know it was so long ago ðŸ˜
use = function(self, card, area)
for i = 1, #G.hand.cards do
G.E_MANAGER:add_event(Event({
func = function()
copy_card(chosen_card, G.hand.cards[i])
return true
end
}))
end
end
okay got this, but that's cryptid replica code
is there any sample code that includes probabilities?
how do I simply duplicate the card?
ooooohhh yeah ty
thought of an idea for a mod i could make that will be my first non base game mod: challenge blinds, every big blind will have an optional challenge blind which is basically a buffed up boss blind that if you beat you get crazy money but if you lose it basically just sends you to the regular boss blind with no cash, like skipping the blind but no tag
i will also benefit from this thank you
Agreed. It'd be odd for the optional super-challenge to be less punishing than the normal Blind.
okay with my 5 minutes of lua knowledge I have hopefully cobbled together some working code
it crashes again dangit
What's the current code and error?
I think I got it
oh the error is extra in card.ability.extra.cards is nil
SMODS.Spectral {
name = "shen-duplicate",
key = "duplicate",
pos = {
x = 0,
y = 1
},
cost = 10,
atlas = "shen",
can_use = function(self, card)
return G.hand and #G.hand.cards > 0
end,
use = function(self, card, area)
for i = 1, #G.hand.cards do
G.E_MANAGER:add_event(Event({
func = function()
local _first_dissolve = nil
local new_cards = {}
for i = 1, card.ability.extra.cards do
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local _card = copy_card(G.hand.cards[i], nil, nil, G.playing_card)
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.hand:emplace(_card)
_card:start_materialize(nil, _first_dissolve)
_first_dissolve = true
new_cards[#new_cards + 1] = _card
end
SMODS.calculate_context({
playing_card_added = true,
cards = new_cards
})
return true
end
}))
end
end
}
oh wait that's easy
don't need that line
because it should only make 1 copy not x
Yep
IT WORKS
can someone help and explain what pseudorandom ness means in the context of some vanilla card
yeeeeeehawww
pseudorandom('vremade_gros_michel') for example
why does it have a string in it
and can that be called anything?
with 4 runs of this card I now have this
I don't know the exact reason, but it's presumably just some factor in whatever wacky math it uses to do randomness. The String can indeed be anything, pretty much all of my pseudorandom strings are just character quotes.
so its just like giving the randomness a name
its not based on anything specific?
is it just to use as reference
oh wait this with perkeo......
welp I never said it would be balanced
okay question do I need to do anything else to make sure the spectral card appears in shop/packs or is it fine already?
code here
a riff-raff just made another riff-raff didn't know that was possible
or at least how to apply them
it shouldn't
Not just a name. Rather, each character in the provided string is turned into a byte and filtered through math equations to create random outputs. (I just checked the code to be sure.)
The only exception is, if you just use 'seed', it'll use math.random() to create a random seed.
riff raff is uncommon right
but regardless i can name it anything right?
no it's common
Yes
just thought it would be an exception
it is? i thought it was uncommon
uh in debug plus mod what keybind is it to delete a playing card in hand?
t
went a little too overboard on my spectral card
You can hold Tab to bring up a menu that shows controls and keyboard shortcuts and stuff.
i have a question and its oddly specific but it bugs me
well I just spammed ctrl+r, and... good-bye save I didn't need you
that wasn't my run for the past 2 days
It can with a showman.
i didn't know it was common that's why
say i was playing the crypid mods and my card's value was changed, it's description mentioned it being able to retrigger card "1 additional time", it the 1 were to change to a 2, i'm assuming it would then say "2 additional time" (not plural)
is that avoidable
very specific but just wondering
No, it would say 2 additional times
Cryptid has a function for that.
"how can i make my joker blow up an orphanage"
"cryptid has a function for that"
No, if an orphanage is a card then there would be a vanilla function for that.
there's no blow up vanilla function
only dissolve
card:explode()
real?
Yes.
what does it do
It's used for booster packs.
to do what
Presumably it's for the opening animation.
if i put pseudorandom('dl_sticky_odds') < G.GAME.probabilities.normal / card.ability.extra.odds would that work without having anything else?
because my probability code isn't working
hard to explain hold on
if context.individual and context.cardarea == G.play and pseudorandom('dl_sticky_odds') < G.GAME.probabilities.normal / card.ability.extra.odds and context.repetition and context.cardarea == G.play then
return { repetitions = 1 }
end
end,```
here
why wouldn't this work?
wait i might know this one
Try without the additional context.individual check.
context.repetition doesn't need it.
alright
i thought the issue was how i was calling everything at the same time as the probability check
might be easier to do the probability check then follow with everything else?
so it doesn't seem to would could can't work on ist das jokersltras
Order doesn't matter that much in this case. It's really up to you.
Also, this won't be necessary for function, but SMODS recently added a function, which makes compatibility with probability modifying effects from other mods easier. You can use SMODS.pseudorandom_probability(card, 'dl_sticky_odds', 1, card.ability.extra.odds)
this is super handy
No, that's not released yet.
well when it does release
No, it would be better if you did the probability check last.
true
if i wanted this to also affect cards in your hand what would i put here
like steels
Remove context.cardarea == G.play
anyone here that knows lua in general, where in balatro code or SMODS is the code that makes for example "{C:green}" work?
It would only affect playing cards because jokers use a different context.
The loc_colour function.
is this in smods or balatro itself?
It's in vanilla balatro.
in the context of wording, do scoring cards include steel cards for example
and played being the ones you take out of your hand
played also counting as scoring cards ofc
i meant like, the {C:} and {X:} part isnt a lua thing, i meant where in the code it is set to work so it gives the colour to your text if it have the {C:} thing
"Scoring Cards" is exclusively for played cards.
Steel Cards and the like use "held in hand" instead.
i dont think so, steel would be held
how would i word it so it has a chance to retrigger played cards and card in hand?
is there not one word for both
Just say 1 in odds chance to retrigger all playing cards
No.
Jokers and Consumables are cards too.
No.
i don't know any vanilla card that uses the term playing cards in a reference like this
or modded even
(iirc)
No.
i'll just take your word for it, it makes sense i just haven't heard it used before
It's not totally clear what you're asking, but check localize, loc_parse_string and loc_colour in Balatro's functions/misc_functions.lua
i mean like, yk how you can use {C:attention} to make a text that yellow-orange colour? it isnt native from lua script, so somewhere in the code it is set that using it will give the colour to your text, i wanted to know where this is set
where would i find where balatro actually adds these?
looking to create a few simple custom rules but idk what the formatting is
Search for G.GAME.modifiers.no_interest and the other one.
Baby blueprint: Chance to retrigger any joker
That's not really any more clear, but it definitely is in the lua. It's a fairly convoluted system - loc_parse_string breaks down the input strings into part tables based on the presence of { and } characters, then localize does further processing based on what those parts contain. If you search for part.control.C in misc_functions.lua you'll find what happens to any input text that contains a colour modifier like {C:attention}
Wee blueprint
{
vec2 uv = fragCoord / iResolution.xy;
vec3 bg = texture(iChannel0, uv).rgb;
float speed = 0.0059;
float t = clamp(iTime * speed, 0.0, 1.0);
float borderPx = 0.5;
float thickness = borderPx / iResolution.y;
float freq = 50.0;
float flash = (sin(iTime * freq) * 0.025) + 0.5;
vec3 col = bg;
float borderPos = 1.0 - t;
if (uv.y > borderPos) {
float darkR = 1.0;
float brightR = 0.9;
col.r = mix(darkR, brightR, flash);
col.g = bg.g * (1.0 - flash * 0.8);
col.b = bg.b * (1.0 - flash * 0.8);
}
if (uv.y < borderPos + thickness && uv.y > borderPos - thickness) {
col = vec3(1.0);
}
fragColor = vec4(col, 1.0);
}```
i dont know balal shaders
idk how to convert
ye imma stick to love.graphics.setColor😠ty for explaining tho! really helpful
If you're just wanting to colour text, you need to pass a colour within a UIT.T element or a colours table to a DynaText, but this is feeling very XY-problem-esque. What are you actually trying to do?
im doing a separate project from balatro, just lua in general, and here i wanted to make only "fullscreen" be green
i dont knwo what im doing ðŸ˜
Maybe lead with that next time you're asking a question in a Balatro modding forum, but yes, setColor is what it ultimately comes down to with Love
yeah but i just asked here because here people would probably know about balatro codes so i could ask where they do that stuff, otherwise i wouldnt ask here
The question is fine, it just needed more context 🙂
please i need shader help here i have no clue what im doing
true
is there a vanilla remade for the booster packs? i cant seem to find it
thankss
but im not using editions
im tryna make an overlay
like the crt effect
this is what i tried
didnt work
as expected
No, that's where SMODS.Shader is.
Did you not see the link?
oh mb gang
so how would i load it as an overlay
does it automatically load into G.SHADERS
ðŸ˜
so sad
how can i
how can i do the thing
how can i get an smods reference to my shader
how would i program a joker that gives mult if you've only played spades or/and clubs
something i can plug here
im looking at it now
the vremade in question
thank you
we love smods
i had a solution if this persists
only shows if im holding the winodw
What function causes this to get rendered
how do i detect if there are a certain number of [rarity] jokers owned
oops what
GLINK
okay well ignore the reply; question still stands lol
not sure at all, i know cryptid jokers include something like that if you roumage around
Couldn't you use Cryptids function for that?
yeah
also whats going on why isn't my sprite loading here
everything is identical to the others
did you swap the 1x and 2x around?
probably
wouldn't apply here lol
game would've crashed if i didn't
yea
no i mean the images
sizes are in the right places
142 x 190 in 2x
71 x 95 in 1x
anything out of the ordinary here?
WAIT
pos is off
yeah
my bad guys
nah it just never destroys itself
SMODS.Joker {
key = "evil_riff_raff",
name = "EVIL Riff-Raff",
config = { extra = { cards = 2 } },
rarity = "crp_abysmal",
atlas = "crp_placeholder",
pos = { x = 0, y = 0 },
cost = 0,
blueprint_compat = true,
demicoloncompat = true,
loc_vars = function(self, info_queue, card)
return { vars = { lenient_bignum(card.ability.extra.cards) } }
end,
calculate = function(self, card, context)
if context.setting_blind or context.forcetrigger then
for i = 1, card.ability.extra.cards do
if #G.jokers.cards < G.jokers.config.card_limit or context.forcetrigger then
SMODS.add_card({ set = "Joker", rarity = "cry_cursed" })
end
end
end
if #Cryptid.advanced_find_joker(nil, "cry_cursed", nil, nil, true) >= 10 then
if not G.jokers.cards[i] == card and not G.jokers.cards[i].ability.eternal then
G.jokers.cards[i]:start_dissolve()
G.jokers.cards[i]:remove_from_deck()
end
end
end,
crp_credits = {
idea = { "wilfredlam0418" },
code = { "wilfredlam0418" }
}
}
how would you word an if statement to say "if all the scoring cards are clubs or spades"
if all scored cards are dark suits
or just
if all scored cards are spades and clubs
how would a caveman put that in code
Yes, i doesn't exist there.
ah right
AAAAAAAAA
great
SMODS.Joker {
key = "evil_riff_raff",
name = "EVIL Riff-Raff",
config = { extra = { cards = 2 } },
rarity = "crp_abysmal",
atlas = "crp_placeholder",
pos = { x = 0, y = 0 },
cost = 0,
blueprint_compat = true,
demicoloncompat = true,
loc_vars = function(self, info_queue, card)
return { vars = { lenient_bignum(card.ability.extra.cards) } }
end,
calculate = function(self, card, context)
if context.setting_blind or context.forcetrigger then
for i = 1, card.ability.extra.cards do
if #G.jokers.cards < G.jokers.config.card_limit or context.forcetrigger then
SMODS.add_card({ set = "Joker", rarity = "cry_cursed" })
end
end
end
if #Cryptid.advanced_find_joker(nil, "cry_cursed", nil, nil, true) >= 10 then
card:start_dissolve()
card:remove_from_deck()
end
end,
crp_credits = {
idea = { "wilfredlam0418" },
code = { "wilfredlam0418" }
}
}
hey its my first time working with creating a voucher and i have an idea but im kind of struggling to find out how to impliment it
can someone push me in the right direction with some advice?
i want my voucher to make a specific consumable card spawn in your consumable slots, kind of like how hallucination works, when opening a specific booster pack type
does anyone know what that would look like or what i need to make it work, do i need to define the objectype?
if context.open_booster and context.card.config.center.kind == "kind" then
SMODS.add_card({key = "c_modprefix_key"})
end
but wouldnt that happen for every booster pack?
clutch
so this just hard-crashes the game now though
...
if #Cryptid.advanced_find_joker(nil, "cry_cursed", nil, nil, true) >= 10 then
card:start_dissolve()
card:remove_from_deck()
end
...
if i use joker.card[joker.cards.size] would that be the last joker
that you have
out of all the ones you have
Yes, you need a context check.
so i replace the word kind with the booster key?
No, it would be G.jokers.cards[#G.jokers.cards]
thank you
No, you replace it with the kind you gave it.
oh i never gave my booster pack a kind
oh, i need one?
i want it to instantly (or at least as instantly as possible) die once the player has >=10 cursed jokers
Then you would put it in update.
so just
...
update = function(self, card)
if #Cryptid.advanced_find_joker(nil, "cry_cursed", nil, nil, true) >= 10 then
card:start_dissolve()
card:remove_from_deck()
end
end,
...
Yes.
ok thanks for the help ima try to make it work
you know what that's a feature
it keeps saying attempt to index local center, nil value error, and im not sure why
hmmmm
more testing needed
is it possible for a consumable to have a calculate function instead of a use function
Yes.
is there anything special i need to do or will it be okay just being formatted like that
All you need to do is define the calculate function like you would with a joker.
do the arguments stay the same? also side question but can they use context.joker_main
Yes
alr cool, coding this should be interesting then
😠this isnt working still im not sure what to do to make this work
it keeps saying the "center" of the consumable isnt being found correctly
is there a reason for this?
I'd need to see your code
bump 
I wanted to patch the run info and options buttons
key = 'Chum',
atlas = 'Extra',
pos = { x = 2, y = 1 },
loc_txt = {
name = 'Chum',
text = {
"Opening a {C:attention}Go Fish{} pack",
"adds a {C:attention}Bait{} consumable"
}
},
calculate = function(self, card, context)
if context.open_booster
and context.card
and context.card.config
and context.card.config.center
and context.card.config.center.kind == "Go Fish"
and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.0,
func = function()
local bait_center = SMODS.find_center and SMODS.find_center('FishingRodConsumableType', 'c_AC_bait')
if bait_center then
local bait = create_card(bait_center)
bait:start_materialize()
G.consumeables:emplace_card(bait)
end
return true
end
}))
return {
}
end
end
}
ill delete after cuz its big
SMODS.find_center doesn't exist.
omg i knew it, i thought i was going crazy omg 😠thanks
Why didn't you use the code I gave you?
i tried but it didnt work so i tried different approaches but it didnt work
SMODS.add_card({set = "FishingRodConsumableType", area = G.consumeables})
but how to i get a specific card from that set, thats kind of my problem
No, that creates a card of that set.
the fact that it's written consumeables pisses me off so bad
and they cant fix it cuz that'd probably break like every mod ever
is emult (^x) something that comes by default in smods?
I think you have to have talisman
i finally got it to work thanks everyone !
Was messing around with the new Probability stuff and came up with a method for tracking success and failure of probability checks. There might be a few weird timings with stuff like lucky cards but it works pretty well 👀
does anyone have an example of a custom deck that changes the shops to only have jokers of a specific rarity, like the shop is full of rare jokers only ? if not does anyone have an idea of how that would look like
will anything break if I make the key of my atlas just "Jokers"
sweet
All atlases you create are internally flagged as created by your mod so no need to worry about that 
Oooo this is pretty cool
Hey so my joker has a little issue, it does work as intended but for the score requirement reduction, it still shows the base score, is there any way to fix that ?
key = "sleepysybil",
loc_txt= {
name = 'Sleepytime',
text = { "{C:attention}Halves{} the current blind's score requirement",
"after {C:attention}#2#{} rounds",
"{C:inactive}(Currently #1#/#2# rounds)"
}
},
--atlas = 'Maidenregalia',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 5,
pools = {["pseudoregamod"] = true},
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
config = { extra = { current_round = 0, total_rounds = 3, round_max = 8 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.current_round, card.ability.extra.total_rounds,card.ability.extra.round_max } }
end,
calculate = function(self, card, context)
if context.setting_blind then
if card.ability.extra.current_round == card.ability.extra.total_rounds then
G.GAME.blind.chips = G.GAME.blind.chips/2
return {
message = "Well rested !"
}
end
end
if context.end_of_round and context.game_over == false and not context.blueprint then
if card.ability.extra.current_round == card.ability.extra.total_rounds and card.ability.extra.total_rounds ~= card.ability.extra.round_max then
card.ability.extra.current_round = 0
card.ability.extra.total_rounds = card.ability.extra.total_rounds + 1
return {
message = localize('k_reset') .. "..?"
}
elseif card.ability.extra.total_rounds == card.ability.extra.round_max then
card.ability.extra.current_round = 0
return {
message = localize('k_reset')
}
else
card.ability.extra.current_round = card.ability.extra.current_round + 1
end
end
end
}```
For exemple if the base score requirement is 200, the ui will still show 200 even if it'll be actually 100
that's gonna take work to make happen, i would make it so when the blind is being set, do the halving
it's already the case if context.setting_blind
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
Ur pretty cool
Ghchdhdhdhff
Thanks it works !
I'm working more on Blinds (since I've added some new ones), and I've outlined almost all challenges I want for my mod
Still trying to work out the achievements which is mostly just flavor stuff. I want them to be different ranks but I'm having trouble coming up with suitably JoJoy achievement levels aside from that the highest level is "Heritage"
Do you need a 2x for boss blind images?
Yes
I'm a little confused about making a Rarity, how do I make a Joker rarity that doesn't appear in shops
You don't put it in the joker pool.
set the rarity's default_weight to 0
yeah lol
sweet
Also where does it go in the localisation table
considering the other rarities are under like
k_rare for example
would it be k_cure
Or my mod prefix somewhere
Also how do I give a joker that rank, do I just use its key
You mean rarity?
Yes I do lmao
You would do rarity = "modprefix_key"
I need adjectives.......... I need grandiosity........ I need it to be bizarre........
wawa cat?
no
aw
i fixed the error but the joker just doesn't exist at all
no matter what the rarity is
also how do i move my mod to the top of the list in the mod menu how are they ordered
but yeah it's not in the collection whatsoever, and there's no errors
would go better as a #1209506514763522108 post or in #⚙・modding-general
#1209506514763522108 prolly
oh it's also not in the additions thing
Loading priority in the metadata
weird how this can't be changed ingame
most mod managers do this
like mc resource pack
No because the order seems to not care about that
see what i mean
Yes, mods with configs go first.
Oh
That makes more sense okay
Can you help me fix the actual issue I'm having
Okay so it appears in the Collection and stuff if I don't have them in seperate Lua files loaded with assert(SMODS.load_file())
s, mods
he can't keep getting away with this
Which is weird because in my other mod this works just fine
GRAAH why does this happen
I'm going to be adding a lot of jokers I can't have them all in one file
more detail
needed
Oh I'm. okay
I forgot to add an extra ()
assert(SMODS.load_file("test.lua")) -- bad
assert(SMODS.load_file("test.lua"))() -- good
another bump
please
the joker wasn't showing up in the collection unless I put them all in the same file but that was because I was loading them wrong
nativefs.filesystem.read or love.filesystem.read
for future reference this was the first result when I googled "read from file love2d" :p
balatro ain't made with love, it's made with flesh and horror
Is there an easy way to exclude a consumable from the shop but not packs? I know in theory I could do it by feeding the pack a table of all the consumables of that kind, but there’s gotta be a better way
soul maybe?
guys how do I listen for ingame events like when there's a new round
contexts
if context.setting_blind
thanks
their message didn't elude to a joker context tbh
globally? wdym
The slight problem here is that there’s 24 id want to exclude from the shop, and probably about 6-7 that I want in it
Outside of a joker or similar.
Making ~30 total
yeah outside a joker
make them all soil
nope
like checking for the event not inside a game object
I wanna do it globally
you would use a hook
@daring fern oh mr poly bridge
Then hook SMODS.calculate_context
teach them hooks
That doesn’t quite work if I want the whole set to appear in packs by default though does it? As soul replaces what originally would spawn I though
whats the code to activate at the end of the round before you get interest
if context.end_of_round and context.main_eval
what is main.eval?
idk the nachos that much
¯_(ツ)_/¯
I’ll see if I can’t fuck around with pools tomorrow
As that might be the solution
crap I can't figure it out, how do I do this?
What’s the intended outcome?
I js wanna randomize music after each blind selected
Are you familiar with lovely patches?
local oldsmodscalccontext = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
if context.setting_blind then
-- do things
end
return oldsmodscalccontext(context, return_table)
end
```?
thanks, I'll try it out
nope, I'm new to anything love2d related
anyone know why my joker that should have art is a default joker card
this doesn't look like a penny to me
does it have an atlas
does it replace the sound?
i see
SMODS.ConsumableType {
key = 'Spell',
loc_txt = {
name = 'Spell', -- used on card type badges
collection = 'Spells', -- label for the button to access the collection
undiscovered = { -- description for undiscovered cards in the collection
name = 'Not Discovered',
text = { 'Purchase or use',
'this card in an',
'unseeded run to',
'learn what it does' },
},
},
primary_colour = HEX('8f82d1'),
secondary_colour = HEX('8f82d1')
}
I'm trying to move the loc_txt to a localization file
where on earth do i put the stuff
and where do i put descriptions for the cards under this type
mod prefix is shark
noita mod?
??
i'm fuck
keep the shitposting in the chat channel haha
but i'm shit and they are posting
does xmult_minus do anything at all
🧮
that'd be why
Definitely do not use samplejimbos
actually wait it could be from the fact i haven't slept yet
nubby?
yeah that's prolly it mb gang keep posting things i sssume to be true
and use vremade
The goat to use is remade yea
where the _1
clearly not necessary
try it, that might be an error
why does that work?????????
did it work?
Yes
See Above
adding the _1 worked?
sir rt just verifying
because i'm about to summon the wizard
thank god you came in clutch i was just about to summon the wizard
what wizard
if context.end_of_round and context.main_eval and not context.blueprint then
xmult = card.ability.extra.xmult_minus - card.ability.extra.xmult_minus_mod
end```
i'm tired and stupid so
the vremade author
is context.other_card a thing
what did i do wrong
Yes.
hey don't say that
it's impossible to be tired when there's work to do
no like i am so tired and being tired makes me that way
stupid yes
this is supposed to lose mult at the end of the round btw and its not doing that
i was looking at Extra Credit for a joker that counts all played cards as Lucky Card if it has 7, but i dont think this is how it looks?
What is the goal?
my plan was
"played High Card now counts as Glass Card"
You need to use Quantum Enhancements
wouldn't you just do if its high card then 2x
No.
where can i see that
yes but no
xmult is just there
it doesn't exist
Then it wouldn't break also it wouldn't count for glass joker and similar.
oh yeah no return
yeah this
You mean like documentation?
no you did mint return
??
yes if there is one
no return need return go hot eat the food
There isn't currently.
return
oh that sucks, where do i find reference for it tho
guckle yournstself
except for maybe a message
I'm not sure but firstly, you have to enable it.
the problem is that this code is effectively saying "this random variable that just so happens to be called xmult is equal to this equation"
you need to target something
like card.ability.extra.xmult
or whatever the xmult value actually is
is it not x_mult as well
what does the config look like
bump, except i know where to put undiscovered and the individual consumables themselves, i just need to know where to put the name and collection
assuming somewhere in dictionary but what about the key
uhh
nevermind it's
b_prefix_consumable_cards
k_prefix_consumable
how to
oh ok gg
mayybe not
i was just looking at vremade and another mod
that's in misc.dictionary right
yea
hm
SMODS.current_mod.optional_features = function()
return {
quantum_enhancements = true
}
end
thanks
i gotta find a mod that does this tho
@faint yacht does your mod have quantum enhancement?
return card.ability.extra.dollars
x_mult = card.ability.extra.xmult_minus - card.ability.extra.xmult_minus_mod
end,```
is this plausible
if G.play and #G.play.cards > 0 and context.check_enhancement then
local text = G.FUNCS.get_poker_hand_info(G.play.cards)
if text == "High Card" then
return {m_glass = true}
end
end
```?
ill try this and see
no config or loc vars for this?
Yes.
why is this incorrect this is exactly what vremade does
this is the only thing definining the consumable type
No, it's not, VanillaRemade doesn't use the prefix.
?
Because ObjectTypes and ConsumableTypes don't have mod prefixes.
right here
Yes.
Oh
I swear I tried that earlier and it didn't work
Whatever it works now thank you so much
is message = localize('') the message under the card
i just wanna make sure so i dont mess anything up
guys how to check whether the game's currently in the main screen where you play cards or discard them?
G.STATES doesn't seem to have that
if G.STATE == G.STATES.SELECTING_HAND
are there docs for the partner mod
I think they have a wiki section in their github not sure
Otherwise just read the code in the mod
Is it possible to track what happens in the game after a consumable is used and apply changes to the game at that stage, such as when a blind is defeated? Would this require lovely patches?
that didn't really help
Shows up in the collection
idk what I'm doing with this mod lmao
Yes, no.
Can you show where you're calling that?
which line it crashes at
the first line
i just copied code from the partner mod itself
and yes i do have it enabled
in the mod there's this on like the first line
idk if I can like
get variables from the other mod like that
How would that be done?
Hook Card:use_consumeable and Blind:defeat
I'm unfamiliar with the concept of hooking, could you give an example or link me to an article that contains that information?
okay so I just had to make the priority less than the partner mod's priority
which makes sense but still annoying
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...
bump
No.
is there one for when you resume that screen? like after you leave to the main menu and go back to that screen
local blind_defeat_hook = Blind:defeat(silent)
function Blind:defeat(silent)
return blind_defeat_hook(self, silent)
end
Would something like this be a start? Looking at this has me worried because self isn't defined, and neither is silent.
No.
You can it's a global, what's the priority of your mod and the one of PartnerAPI
any possible reason the blind image isn't showing up when i play it then?
Yes.
silent is very clearly defined in the function parameters
and self is the Blind
what are the reasons?
Are you saying that the problem is that I'm not getting the blind from G.GAME.round_resets.blind_states[blind_type] = blind then? Or is modifying the class OK?
No.
I am trying to hook into a blind's events
local blind_defeat_hook = Blind.defeat
OH right
since you're not calling the function you're just getting the function itself
local blind_defeat_hook = Blind.defeat
function Blind:defeat(silent)
blind_defeat_hook(self, silent)
end
So this then?
I'm just being absolutely sure
I believe so at least
It's been a week or so since I made a hook I have bad memory
Looks right to me tho
And as they say
https://tryitands.ee
Ok, then here's another conundrum. I'm creating consumables that hook into blinds, but when I set an arbitrary value using SMODS.Consumable { }, I get an error. To get around this, am I required to create a new hook for every consumable?
Here's an shortened example: SMODS.Consumable { can_use = ..., use = ..., blind_start = ..., blind_defeat = ... } (specifying blind_start or blind_defeat causes a crash)
guys is there a way to check for this?
this was working, now it's not and i have no idea how please help
Show the full code.
I'm sorry for not providing enough support for regular creations, I'll make up for it when I can.🥺
for some reason it doesn't work
oh wait I'm dumb, I meant this mb
?
BlindStation.Case = SMODS.Consumable:extend {
required_params = { 'key' },
set = 'BlindStationCase',
class_prefix = 'BlindStationCase',
pools = { 'BlindStationCase' },
atlas = 'BlindStationCaseDefault',
pos = { y = 0, x = 0 },
set_card_type_badge = function(self, card, badges)
badges[#badges + 1] = create_badge(
localize('k_BlindStation_Case'), HEX('b6b6ba'), G.C.WHITE, 1.2
)
end,
unlocked = true,
discovered = true,
config = {
allowed_blind_types = { 'Small', 'Big' },
blind = 'bl_big'
},
loc_vars = function(self, info_queue, card)
return {
vars = { localize {
type = 'name_text', key = self.config.blind, set = 'Blind'
} }
}
end,
can_use = function(self, card)
local blind_type = BlindStation.FUNCS.get_next_blind_type(
self.config.allowed_blind_types
)
return BlindStation.FUNCS.can_change_blind_type(blind_type)
end,
use = function(self, card, area, copier)
play_sound('BlindStation_BlindStationCaseUse', math.random() * 0.01 + 1, 0.9)
local blind_type = BlindStation.FUNCS.get_next_blind_type(
self.config.allowed_blind_types
)
if blind_type == nil then
error(
'Blind type is unexpectedly nil from `can_use` to `use` method of case \'' .. self.key .. '\''
)
end
BlindStation.FUNCS.set_blind(blind_type, self.config.blind)
end,
-- TODO: Implement (adding this function causes a crash)
--[[ reward = function(self, card)
end ]]
}
All BlindStation.FUNCS functions you see I have extensively tested and fully work
your sins will never be forgiven, you will be punished with ante 7 plant

yeah that thing

if i put a dependency in my json does the game actually scan for if you have that dependency
i made a joker that works like mr bones but for when it saves the run for losing it says error, how can i fix this?
you accomplished more than what the multiplayer mod could do good on you
simon be typing
isnt it just put saved in thecalculate? how can multiplayer mod do that wrong
You need to return a key to an entry of localization.
oh that makes sense, thanks!
I think I'm doing something wrong again. Trying to hook into an instance of a class is giving an IDE warning
For anyone interested in Balatro Bot: Post about BalatroBot documentation https://discord.com/channels/1116389027176787968/1391371948629426316
Is this smth like TAS bot?
no just a refinement and docs addition to balatrobot mod. I'm planning to use to develop new balatro bots. yeah like TAS bot: program that given the game environment takes action.
BlindStation.FUNCS.create_game = function(game_table)
local game_config = game_table.config
game_config.extra = game_config.extra or {}
game_config.extra.allowed_blind_types = game_config.extra.allowed_blind_types or {
'Small', 'Big', 'Boss'
}
SMODS.Consumable {
key = game_table.key,
config = game_config,
can_use = game_table.can_use or function(self, card)
local blind_type = BlindStation.FUNCS.get_next_blind_type(
self.config.extra.allowed_blind_types
)
return BlindStation.FUNCS.can_change_blind_type(blind_type)
end,
use = game_table.use or function(self, card, area, copier)
play_sound('BlindStation_BSGameUse', math.random() * 0.01 + 1, 0.9)
local blind_type = BlindStation.FUNCS.get_next_blind_type(
self.config.allowed_blind_types
)
if blind_type == nil then
error(
'Blind type is unexpectedly nil in `use` method of BSGame \'' .. self.key .. '\''
)
end
local set_blind = BlindStation.FUNCS.set_blind(
blind_type, self.config.extra.blind_key
)
local blind_set_hook = set_blind.set_blind
function set_blind:set_blind(blind, reset, silent)
blind_set_hook(self, blind, reset, silent)
if game_table.post_set_blind then
game_table.post_set_blind(self, blind, reset, silent)
end
end
--Crash: Attempt to call upvalue blind_set_hook
I knew something was going to break. Seems like I can't set hooks inside a use method? How do I get around this?
Or is it just that I need to store these variables somewhere rather than them only being local variables?
where in the localization should i put it? i tried a few places and none were working
Localization > misc > dictionary
thanks
still cant figure out why tf this isn't working HELP
Do you have joker retriggers enabled?
is there a way to change the current atlas pos of a joker in its calculate function?
Yes.
how would you do that then?
what's the code to enable it?
card.children.center:set_sprite_pos({x = number, y = number})
thanks!
SMODS.current_mod.optional_features = function()
return {
retrigger_joker = true,
}
end
do i put that in Calculate?
outside thr joker
ah
can you do the same thing with Soul pos?
i think so
Yes, but it would be card.children.floating_sprite
yeah
whats the fix again for a joker that triggers for every cards held in hand
context.main_eval?
what it does again
Checks the joker and not the cards in hand
something like this?
yes
thanks doc
does anybody know what the line of code is to balance chips and mult
i know its a single line but i forgor
return {balance = true}?
i was thinking chips.balance lol, thank you
how could I modify the Xmult config, while the joker does something?
how would i change a card's seal sprite?
like, imagine i have a card with a seal, and i want from withing the seal's calculate change the position of the seal in the atlas
You would have to change the sprite in G.shared_seals["modprefix_key"] I think.
so something like G.shared_seals["modprefix_key"] = {x = x, y= y} ?
what do i do with that then?
G.shared_seals["modprefix_key"] = Sprite(0, 0, 71, 95, G.ASSET_ATLAS["modprefix_atlaskey"], {x = number, y = number})
ok thanks
does anyone knows how to fix that? its my first mod sorry if its a dumb question
can you send the full crash
also I don't think this is the cause but it's G.jokers not G.Jokers
?
card.ability.Xmult = number
so I am doing this but it crashes
oh wait nvm
I mistyped it lmao
oh it still crashes
here you go
Log?
thats the calculate function I have right now:
boost = boost - pseudorandom('SonstZuOpLMAO', 0.05, 0.15)
if context.joker_main then
return {
card.ability.Xmult = boost,
message = 'Geboosted!',
}
end```
did you restart the run before testing?
Move it out of the return.
oh shit no
Also it would be card.config.center.key not card.config.center.
what general structure should the main mod file have? the steamodded docs dont have anything on it and every mod seems to do something entirely different
I did that, but it still crashes :/
Heres the config: config = {extra = {Xmult = 1}}
and heres the calculate function:
boost = pseudorandom('FinusLSD', 1.45, 1.95)
boost = boost - pseudorandom('SonstZuOpLMAO', 0.05, 0.15)
card.ability.Xmult = boost,
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult
message = 'Geboosted!',
}
end
end,```
Remove the ,
Also add the , to Xmult_mod = card.ability.extra.Xmult
now it works (hopefully) thanks!
@daring fern which smods version that has the probabilities api?
The dev version.
latest then
Yes, the one from the code button.
alright
so it doesn't crash anymore but it doesn't add any multiplier
key = 'smoboost',
atlas = 'hdjoker',
pos = {x=0, y=0},
cost = 2,
pools = {['HDJoker'] = true},
config = {extra = {Xmult = 1}},
unlocked = true,
discovered = true,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
loc_txt = {
name = 'Mario Odyssey Boost!',
text = {
'Booste deinen Multiplier',
'zwischen 45% bis 80%'
}
},
calculate = function(self, card, context)
if context.joker_main then
boost = pseudorandom('FinusLSD', 1.45, 1.95)
print(boost)
boost = boost - pseudorandom('SonstZuOpLMAO', 0.05, 0.15)
print(boost)
card.ability.Xmult = boost
return {
Xmult_mod = card.ability.extra.Xmult,
message = 'Geboosted!',
}
end
end,
}```
Yes, because it would be card.ability.extra.Xmult
now it works thanks!
@tall wharf are you interact with rotating UI stuff or cards by chance?
Not by shader
uh no
so the value everytime is 1.4, I know why, but I do not know how to fix it, anyone have any ideas?
I don’t think you can pseudorandom floats
How can i change rank of a card as con?
hey guys how can i fix this ?
also it crashes the game when i play a hand (before i f ed up the joker even more)
so those numbers in your localization should be 1 and 2
not 5 and 0
they are the indexes in the return value of loc_vars
as for the crash i am not sure
Your config.extra is missing the gain you uee.
ooh yeah, that too
so i just shove "gain" in the config{extra ?
does anyone know where the greyed out sell buttons are held in ui_defs.lua?
Yes, right next to chips. That table is for any and all custom values your Joker uses.
button_callbacks.lua makes the buttons greyed
look for can_sell
Yes, also don't forget to fix your localization strings too.
im not sure how to do stuff
aight now it show "+nil" and then "(currently +5)"
nevermind
what
uhhh coding moment
What's happening now?
make sure to not accidentally swap the localization vars lol
wait a sec
so this part is fixed
ima try to play a hand
lowkey hardest part of the game
very nice it doesn't crashes
well thanks you guys
is there a way to return a message with an event?
Is there some sort of global var i can check to see if the whole process of discarding cards and new cards being drawn has finished?
im trying to make the new cards come in only after some new cards were drawn
this almost works but since the time it takes for cards to finish drawing and discarding is dynamic, a value of 4 doesnt always work out
are you trying to make a new consumeable type?
nvm i figured it out im a genius /j
i did figure it out though
For future reference, there is a context.hand_drawn that seems like it would help you.
SMODS.calculate_effect({message = "msg"}, card)?
ok nvm it's just doing it as it comes from the right of the screen
i guess so yeah
thanks
New Card type altogether
Not consumable
(It goes in Joker Slots)
II got it working thanks to someone else but idk how to get the collection to show up
is it in "other" already?
For some reason this dissolves the joker before scoring is started, even when I have it set to "context.after"
No. I don't want it Other regardless
(this is photoshopped but I wanna do something like this)
ALTERNATIVELY...
Move Seals over to Other
Nevermind, found the solution, card:start_dissolve() kinda sucks and I had to put it in a dissolve event
i would recommend SMODS.destroy_cards(cards)
Is it possible to apply a shader to a Back?
beta balatro did it
I wanted to make a joker that would create a random joker that you previously sold or destroyed after a boss blind has been defeated.
The question is... how can I check for every joker sold or destroyed previously?
In the "(#G.jokers.cards + G.GAME.joker_buffer)" I think I gotta change the first term to something else but I'm not sure what.
You have to store it manually.
like an array of sold/destroyed jokers?
Yes.
Why doesnt this edition work for jokers? It doesnt do any scoring when it's applied to a joker
if (context.main_scoring and context.cardarea == G.play) or context.pre_joker then
wait but how can I store the sold/destroyed jokers in an array?
And how do I make the array not limited but infinite since there's probably gonna a lot of destroyed/sold jokers?
You would hook Card:start_dissolve()
Thank you!
lua tables are already infinite by default. table.insert(previous_jokers, [some joker]) will add the given joker onto the end of the table
I... don't exactly know how to hook a funtion, I tried searching online but I'm still doing it wrong...
local old_card_start_disoolve = Card.start_dissolve
function Card:start_dissolve()
--Do stuff here
old_card_start_disoolve(self)
--Or here
end
how do you make it do an animation thats like the level up animation
where do i put the code for credits, again?
(overall credits found next to the mod's config tab)
current_mod.extra_tabs
awesome, thanks :D
Oh no, salty ghost attacked by slime
oh that's not slime
tis part of an Art Fight attack i received!! (these other OCs aren't mine)
guys i tried to install the cryptid mod but it shows this error what can i do??
key = 'Sol Flush',
loc_txt = {
name = 'Sol Flush',
description = {"Five sol cards"
},},
mult = 3,
chips = 30,
l_mult = 3,
l_chips = 10,
visible = true,
example = {
{ 'H_Q', true, enhancement = 'm_cymbal_sol'},
{ 'H_J', true, enhancement = 'm_cymbal_sol' },
{ 'D_9', true, enhancement = 'm_cymbal_sol' },
{ 'H_6', true, enhancement = 'm_cymbal_sol' },
{ 'D_3', true, enhancement = 'm_cymbal_sol'}
},
evaluate = function(parts, hand)
return parts._sol_flush
end
}```
Quick question but how do i make the poker hand work with my enhancements ? It's meant to react with 5 cards with that enhancement but it still treat it as a flush (because the enhancement is any suit)
check if you have other mods installed that could conflict with cryptid
i have but none of them are active
just talisman is active
maybe remove entirely the other mods folders just in case, maybe it can still mess up somewhat
make it give more chips * mult than a flush
would above_hand work too ?
no idea
i'll try that first to see, but thanks
didnt work 😔
ah, well not sure, i don't even really use cryptid, just said was seemed the most logical
where's the creator of jokerforge
maybe it's the smods version that is outdated
idk but thanks for trying
it does, the key for hands are the hand's full name
so just, above_hand = flush?
whats the context for detecting Ante raise
above_hand = 'Flush',
Two questions but I'll ask one at a time
The first one would be asking how I can make the "100" text centered inside the light grey bubble (like as though it just ignored the red bubble)
If I have them as separate nodes inside the grey bubble then it just places them next to each other
thanks, wanted to make so my hand wasn't too powerful for it
SMODS.Rank[whatever your rank's full key is, including mod prefix].id should get the ID properly I think
np
like this?
yea that should be right
well it DOES show itself on top of the flush but somewhat will still trigger itself as a flush, maybe the way my pokerhand is being made doesn't exactly match idk
Hello, I was trying to get this joker effect to work, but I can't figure out how to. The plan was to make the suit names get added to a table and then cards would have their suits compared against the ones already in the table
wdym
i'll record in video to make the thing easier to understand
wuh oh
bump
That should be the key so i dont know what went wrong
there isnt one, the best you can do with contexts is end_of_round + boss defeated
else you need to hook
this basically, it still consider it as a flush
oh my bad it's SMODS.Ranks, plural
ahh yeah that makes more sense ðŸ˜
are you checking for suit or enhancement in your hand's code
if G.GAME.blind.boss and context.end_of_round then ?
it's better to have a boolean here
so you have like
for _, scored_card in ipairs(context.scoring_hand) do
local suitPlayedBefore = false
for _, c_suit in ipairs(suits_scored) do
if scored_card:isSuit(cSuit) then
suitPlayedBefore = true
end
end
if not suitPlayedBefore then
table.insert(suits_scored, scored_card.base.suit)
scored = scored + 1
end
end
maybe i didn't, i was thinkingwith the exemple it could somewhat work
yeah, you should probably also add and context.game_over == false and context.main_eval
will do
i think
what is parts._sol_flush doing here
oops! my UI is busted, can you see where the issue is? will grab a screenshot in a mo
i just needed that for the evaluate, i was thinking that's just what i had to add
oh and. nvm i found it ;u;
tried doing like this but I'm not sure what should I put instead of G.jokers
sorry
lemme see where my hand code is and grab a screenshot for you rq
sure, i would have checked for pokerhands with enhancements on but i don't think i've found one yet
i have one that is five gold cards
(ignore the next(SMODS.find_card("j_joy_eld_angel")))
oh shit that's exactly what i need
thanks both, i'll try to make this work now
what should I put instead of G.jokers?
(to at least add the sold/destroyed joker to the array)
@pale holly thank u for your help i can play cryptid now. my files were outdated
if self.ability.set == "Joker" then
if not G.GAME.modprefix_previous_jokers then
G.GAME.modprefix_previous_jokers = {}
end
table.insert(G.GAME.modprefix_previous_jokers, self.config.center.key)
end
replace modprefix with your mods prefix
aight
Yeah I did have a Boolean before, but it didn’t work.
Let me try your code
simple things to check but heh, it do be working, glad it works now !
how is this only an epic joker
have u seen the legendary jokers in cryptid 
there we are!
bump 
fancy :3
Ok, this is new
did i typo
did you used the localization files for this ?
:is_suit ?
ah, partly
Hi, is there a way to detect when a card is used in a booster pack?
I looked at "Domino" from Bunco and that has context.getting_booster_card, but I've heard nothing about it
If anything that would be my typo
o
ah i see, i know i've tried to maje a proper description but apparently using n/ to skip line doesn't work in that case
that's because it's \n
but also, you should use multiple rows of text instead of newlines
but also, i'm pretty sure you can do that with a table like { "row a", "row b" }
but also i don't know for sure so
i think it was that i tried but still didn't wored, idk i should retry to see
It was a typo. It works now. Thanks @thorn furnace as well

i need some help
Here is Bunco's non-vanillacontext.getting_booster_card
joker won't update values
ok so to put the table in the jokers_to_create I must put the "G.GAME.modprefix_previous_jokers" instead of the "#G.jokers.cards" right?
it won't gain xmult or xchips upgrade
what's the effect
it is written in the comment in that screenshot
then it's fine how it is
you're missing the creating part
oh
bump
how do you draw a card from a card area into a different card area, again?
i'd like to draw from play into hand
i guess i was actually a fool, it does look better now at last, thanks
np!
so something like this but...
try draw_card(G.play, G.hand, 90, 'up', nil, card)
awesome, will give that a try

