#💻・modding-dev
1 messages · Page 461 of 1
if G.jokers[x].joker.edition and G.jokers[x].joker.edition.key = "Negative" then
--insert effect--
end
does that work or do i just refer to the joker as G.jokers[x].edition?
whatta i need ta do
can someone explain to me why the thing in joker_main works but the thing in before doesnt ```lua
if context.joker_main then
print("AAA")
return { message = "AAAAAAAAAAA"}
end
if context.before and context.cardarea == G.play then
print("1")
end
it genunely just feels like smods hates me
You don’t need card area in before
for i = 1, #G.jokers.cards do
local joker = G.jokers.cards[i]
if joker.edition and joker.edition.key == "e_negative" then -- joker.edition.negative also works
-- effect
end
end
ok thanks that worked
have you heard of this great resource called vanilla remade
no i need the vanilla way specifically
i need to see it's variables
i dont need it done to smods spec
i need to see how the base game does it
search for it in the code?
what file would i look into
What’s the reason for specificsllly needing the vanilla way?
im probably gonna have to patch this in 🫠
i need to get the current mult, and do something during the scaling/reset process
so i needed to know how the game handled it
im modifying vanilla jokers rn
lovely patching saves the day
[[patches]]
[patches.pattern]
target = 'card.lua'
pattern = '''local last_mult = self.ability.mult'''
position = 'after'
match_indent = true
payload = '''
if last_mult >= 25 then
CHAR.FUNC.overclock_proc({card=self,key="j_charcuterie_metro_lines"})
end
'''
works
wonderful
#G.jokers.cards
i didnt actually look at the error give me a sec
can i see how the code looks like now
it's the exact same but line 471 is now for i=1, #G.jokers.cards do
dunno how i didn't pick that one up
i literally already have a joker that adds hand size
im trying rly hard to make a joker that has text that dynically updates as the joker scales, but im struggling to make the text update, any advice? i looked at the Vampite example joker but im not quite getting there
i'm trying to make it so a tag has a certain chance to generate a joker in shop and while the "generating a joker" part works i can't figure out the probability one - if it does fail, it shows "nope!" but retries until it generates a joker. how would i make it so it doesn't retry?
tag:nope()
there might be things you wouldn't understand right away, I recommend looking at other mods' code first:
- hook
Game:init_game_object()and add your own variable to track hands played per ante - hook
Game:update_hand__played(dt)and increment your variable here (make sure it only happens once because this method is called every frame during a hand scoring) - depending on how you define your per ante logic, hook the correct function (e.g.
ease_anteif any ante change resets the count) - finally, in your blind's
set_blindfunction, transfer the extra value toG.GAME.blind.chips(do the math yourself)
another thing: if you intend to have the blind update its required score when you're facing it, even more hooks are needed
yeah
damn my bad
can i see the code you have rn?
Is it a variable that changes or the whole text?
Would dynatext help here?
how do i write it out in code on discord without it looking like a text block
dynatext is mostly to do animated text or stuff like misprint that has preset values
```lua
```
Beat me to it
Ah
i did it wrong oops
G.STATE == G.GAME.round_resets.ante is a very bold choice
like, it has no relation whatsoever
ughhh
i'm very new to modding as you can se
ohhh
extra = {
xmult = 1.0,
xmult_gain = 0.2
}
},
loc_txt = {
name = "Frog",
text = {
'{X:mult,C:white}+{V:1}{} Mult per {C:spades}Spade{} destroyed',
'{C:inactive}Current Mult: {X:mult,C:white}X{V:2}{}'
}
},
loc_vars = function(self, info_queue, card)
return {
vars = {
string.format("%.1f", card.ability.extra.xmult_gain),
string.format("%.1f", card.ability.extra.xmult)
}
}
end,```
you don't need to format the string yourself
#1# in loc_txt would correspond to xmult_gain and #2# to xmult
see: https://github.com/Steamodded/smods/wiki/Localization#loc_vars
ohhhhhhhhh
{V:1} is for color
only for color?
I recommend starting with jokers
your showdown blind idea is just too overwhelming for a starter
thank you for all the help, ill work on it !
how would i check (in an unlock condition) if ive beaten a specific deck on gold stake?
this return isnt returning the xmult part because of the function after, how would i fix it? ```lua
return {xmult = card.ability.extra.xmult, func = SMODS.destroy_cards(context.other_card)}
i think @wintry solar forgor to update stable branch
Are you sure you need to put the function in the return
func = function()
SMODS.destroy_cards(context.other_card)
end
but also save context.other_card to a local first
thanks both of you!
Me when i give hits so you try to fix it an learn instead of giving solutions LMAO
that makes it so the card is destroyed after the xmult message
bump
in the uh
deck skin example
what is the icon thing for?
not sure why but when you open the game, the first card is an ace of spades in the middle of the balatro logo and starts shuffling through cards, whenever it changes from the ace to another card, i get this error:
card.lua:268: attempt to index local 'center' (a nil value)
key = "solSister",
loc_txt= {
name = 'Sol Sister',
text = {
"{C:green}#1# in 7"
}
},
--atlas = 'Maidenregalia',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 6,
pools = {["pseudoregamod"] = true},
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
config = { extra = { odds = 7, additional = 0} },
loc_vars = function(self, info_queue, card)
return { vars = { G.GAME and G.GAME.probabilities.normal or 1 , card.ability.extra.odds } }
end,
calculate = function(self, card, context)
local prayluck = 0
if context.using_consumeable and not context.blueprint then
if context.consumeable.ability.set == "Tarot" then
prayluck = prayluck + 1
elseif context.consumeable.ability.set == "Spectral" then
prayluck = prayluck + 2
end
end
if context.end_of_round and context.game_over and context.main_eval then
if pseudorandom('cymbal_solSister') < G.GAME.probabilities.normal + prayluck / card.ability.extra.odds then
prayluck = 0
return {
message = "Prayers answered.",
saved = 'The prayers have been heard.'
}
end
end
end
}```
Hey so i've 2 questions :
How do i make the loc_vars to update the probability depending of my prayluck ? (right now prayluck does increase the probabilities of my joker but won't update it in its description)
And how do i make the Saved part NOT saying 'saved by Mr bones' ?
right now prayluck does increase the probabilities of my joker but won't update it in its description
does it? I don't think the logic there will work at all
And how do i make the Saved part NOT saying 'saved by Mr bones' ?
return a localization key to an entry in your localization file
what's actually happening is that
G.GAME.probabilities.normal + prayluck / card.ability.extra.odds
will always be
G.GAME.probabilities.normal + 0 / card.ability.extra.odds
which is equal to G.GAME.probabilities.normal
pemdas stuff
is there a way to do the opposite of forced_key (in a booster) and create anything but a certain rarity?
well i was thinking it would considering prayluck is a set local before just that, adn it seemed to actually work as far as i tested, though maybe i should do it differently for it work, not sure
also thanks for the localisation file, didn't even used one yet, probably should
local variables reset every time you call calculate so it wont keep the value
it's a bit complicated, you would need to do what SMODS.poll_rarity does but exclude the rarity you want
yeah, save it to card.ability.extra.prayluck
you can also use that in loc_vars
you will also need to fix the line (G.GAME.probabilities.normal + card.ability.extra.prayluck) / card.ability.extra.odds
couldn't i just repeat SMODS.poll_rarity until it isn't said rarity to exclude? its weight is really low anyways (.0005) but it still appears too frequently in boosters
probably
i'll try that then
is there an easy way to count the number of tarot cards you have in your consumables? i've been able to count the total amount of consumables, but the documentation for checking for tarots that i've found only applies when using or creating them
wouldn't i need to then set prayluck in config tab ? I know i originally tried to do this but since prayluck wasn't an actual think it was crashing when using a consumables, unless in this case i just need card.ability.extra.prayluck without needing it to be used in the config part
yes you would
local count = 0
for _, consumable in ipairs(G.consumeables.cards) do
if consumable.ability.set == "Tarot" then
count = count + 1
end
end
thank you omg
sorry had to correct something
but basically something like this then should work ?
what are all the contexts/
yes, but you're missing the card.ability.extra when you reset it to 0
is there any way to redirect destroying cards? (like, if the ceremonial dagger is about to destroy a card, it destroys a different joker instead)
I think you can do that with the new destroying context
Oh yeah right, corrected it, thanks i should see if it works now
do i have to update lovely or smods?
you would have to use smods dev yes
i would wait a couple of days for the release tho
😭 I did
The new context would allow it to be blocked, I guess you could destroy a different card within it too
yeah thats what i was thinking
also how can i make a joker that gains mult when any joker is destroyed?
also with the new context :3
been digging around but couldn't find any examples off the top of my head, but is there any way to have it so an enhancement can't be debuffed?
i.e.
Enhancement Name
X1.5 Mult
Immune to debuffs
Rare Enhancement Custom badge I made here at the bottom etc etc
maybeeee a bit too much, but this is what i did
SMODS.debuff_card(card, "prevent_debuff", "source") in set_ability
oh that exists??
yes
sob
yep that worked perfectly thank you lmao
I had to tweak a bit the loc_vars in order to properly display the odds with prayluck, but it works now ! Thanks again !
can the context context.destroy_cardbe used with jokers?
no
do only jokers have the ability to save runs?
like i'm thinking about making a seal that does the same thing that mr bones does
a seal that if it's the last hand and the total is less than the blind requirement, it'll take the first scored card of the hand, save the run but also remove the seal from the card
tested in a blind and it worked so i dont see why a seal wouldnt
you might need to enable the discard optional area tho
sorry but what does that mean
is pseudorandom only a straight range, or can i make it select only the odd numbers of a given range?
like if i said (1,10) can i make so it only picks 1, 3,5, 7 or 9?
SMODS.current_mod.optional_features = { cardareas = {discard = true}} maybe?
cards dont calculate in the discard area by default and thats where the card with the seal would be
but idk maybe not
no, you can do modulo probably
local rand = pseudorandom("idk",0,4)
rand = (rand * 2) + 1
🤔
thank you bepis for being good at math
i wish i could say the same for myself
can this go in a calculate’s return still?
not the local part ofc but
its a number
I can confirm
How do I put multiple deck skins into one Lua?
quick doublecheck
...why is that in return
not too sure why that crashes
SMODS.modify_rank, i mean
it gave errors when not in it
idk either???
well im still coding it lmao
but here
peak new context
no idea how deck skins work but can you not just
do it again under the first one or no
I've tried multiple ways of that
try assert(SMODS.modify_rank(context.other_card, rand))
bet
put it outside return btw
hi guys how diabolical is it to use math.random instead of pseudorandom for a heavy seed dependent game like balatro
id abuse reentering the run until i get the good rng
}
SMODS.DeckSkin {
key```
and
``` },
key```
with it being continued after that
evil.
ik dw it worked
this wont affect the mult will it
depends on what you use it for
doesnt look like it, no
nice
was considering giving it to a boss blind
how would you even replace a math.random(val1, val2) with pseudorandom?
math.random chance to get 3 effects all of which are bad
pseudorandom(seed, min, max)
srockw beat me to it
yes that's the mod i used as a base
yeah, what they said
👋
hi dilly
hi dil
Hi hi
okay so i've used a localization file to make my string but, how do i actually make it work ? i've tried like on the right but didn't work
do you mean multiple of the deckskin function or like multiple skins?
you should only need one of the function
and then different skins go in palettes is what it looks like
that should target misc -> dictionary -> j_cymba_solSister, no?
i want multiple skins
well
one per suit
that match
god whats with vencord making it so the reaction notification is x10 slower
return {
misc = {
dictionary = {
"j_cymba_solSister" = "your localized text"
}
}
}
this is what it'd look like for your localize call to be valid
yall no
I..guess ? I never used the localization setting before
Thanks !
also the key "j_cymba_solSister" can be anything you want
I'd recommend putting your mod prefix in the key so that there aren't any conflicts
i hate each and every one of you. :3
I'm trying to remake vanilla decks
the first one, being red deck is called scarlet deck but im having trouble thinking of ideas to make it interesting does anyone here have any ideas (I'll credit you)
true but i prefer to keep it for my joker in case i would ever need to make another one close of that type
fax
i would ask in #⚙・modding-general if you havent, there are more people there usually
the mod prefix is already in the key, but thanks
I did ask once and I didn't want to be annoying so I stopped lol
I only started asking again til now
I know, I'm just saying it doesn't have to be the key of your joker
ah alright, thanks
i just really never used the localisation before so this is why, was expected saved could be edited too
+1 bepis when bepis is present per ante
now take over yggdrasil so i can finally rest, thanks
My shaders arent even that kool
i forget if pseudorandom skips the min or the max
They're like 3% epic
it doesnt skip
You however are like 20573857272929% epic
oh was that fixed I swear it used to
😭 nowhere close, but thanks
else pseudorandom("idk",1,2) would break lol
youre missing a few 0s at the end
true lmao
My bad, 3.00%
calculate = function(self, card, context)
if not context.end_of_round and context.individual and context.cardarea == G.hand then
local temp_mult, temp_ID = 1, 1
local clenched_card = nil
for i=1, #G.hand.cards do
if temp_ID <= G.hand.cards[i].base.id and G.hand.cards[i].ability.effect ~= 'Stone Card' then temp_mult = G.hand.cards[i].base.nominal; temp_ID = G.hand.cards[i].base.id; clenched_card = G.hand.cards[i] end
end
if clenched_card == context.other_card then
if context.other_card.debuff then
return {
message = localize('k_debuffed'),
colour = G.C.RED,
card = card,
}
else
return {
h_Xmult = 2 * temp_Mult * 2,
card = card,
}
end
end
end
end
}```
what the heck did I do wrong ?
who told you to add that .

why is your M uppercase if you’ve been using lowercase
In your return
it’d be really funny
why isn't this joker creating another joker?
make it eternal :3
or hook Card:can_sell_card
Hi N
in calculate
alright
is there a context for a joker being added?
And I mean, not this joker, i mean like
if a different joker is added
where dafuck do i put the card: ?
context.ub_foolish == card
oh ok
this doesn't work but where would i enable the discard optional area
context.card_added and check if the card is a joker
i use this for that (change the key, and the requirements for the return false)
it's context.game_over lowercase
also local variables are reset between calculate calls
heres an optional features example: https://github.com/BarrierTrio/Cardsauce/blob/8094b1603f6fb2f24e6c93c87619f832f2ade69b/main.lua#L4
here's what i do since it's for a sticker
oh someone posted it alr
? i don't wanna make a sticker
yeah just remove the sticker part 😭
the logic is the same
return false
im just lost wth do i put and where ?
:3
wdym?
hello, quick question, is there a way to change a sound by a mod and not modifying the game files?
never sure enough
wdym?
sure u can
just that you take ownership of the sound
i cant find any mods that do that so idk how to
ok thanks
if you're aiming to replace the bgm instead of sfx, there's a way
what is bgm?
background music
whenever i add a booster pack or voucher it is WIDE, do i have to use sprite sheets to not make this happen?
and dumb beginner questions, how do i know my variable ? and how do i check for my joker ?
to check if the card is a joker
would i follow up with and card.joker then?
context.card.ability.set == "Joker"
... help
I would help but I have no idea, sorry brother
thanks...
i'm trying to make a wraith-like consumable that creates uncommon cards from my joker pool and it starts out okay-ish but three jokers in it starts generating random jokers of all rarities
wdym
oddly enough it still doesn't work
another thing
i wanna check the edition on that specific joker that is being added
is there any way to reference this joker?
hmmm maybe it's because of the set?
so far it just checks if a card is being added and if the card is a joker
context.card
ah
perhaps, though i think it's correctly defined
each joker has pools = {["BalatrezAddition"] = true} to insert it
how do i know what to put in the red circles ?
never used objecttypes too much but maybe you need this
i'll try it out
yourvariable is fine as is, you can name it something else if you want
if self.config.center.key == "j_[your mod's prefix]_[joker's key]" would be the condition
what syntax errror did i make ?
fuck
Also no , after can_sell_card
i thougt it was [ with the writing
And a "then" after the if cond
lol
For the function line only btw
so like this ?
without that comma at the end but yes
and in the jokers def i put
sellable = true/false
no
???
return false inside the if condition
What are you trying to achieve? Make the card unsellable?
yeah
update -- the create_card function seems to be okay? the problem resides in the get_current_pool where it thinks the poolkey is both the pool itself & the rarity combined in one string
Add return false in the if block
no thats normal, thats the pseudorandom seed
oh okay
so i found create_replace_sound but i have no idea how to use it
Actually idk if the func is a return or if its button config
well the main crash is a bad argument to ipairs apparently
it's a return
Cant check
i'll look into it
Ty N
where do i put the return false exactly i fell like i can't understand anything ?
Between the "if" line and the "end" below it
'k thanks
x)
but likethe entire thing is outside of anything, is it okay ?
yes
how does one deal with jokers not being joker sized? either the sell/buy part of the ui is stretched and weird or the actual joker is stretched to fit, i gotta be missing something simple
modding on none sleep
that will be called when the game calls card:can_sell_card
so if i need another joker to be unsellable i just copy it and change the joker check ?
you can do that but the cleaner way would be to update that same function by doing something like
if self.config.center.key == "key1" or self.config.center.key == "key2" or ... then
i don't wanna complicate things, if it works, it works no matter how ugly it is
rather than ugly it's to avoid future problems but ok
where the heck is k_blabla_ex stored??
localization?
does anyone know how to use it? i cant find an understandable guide
You can make it look simpler by having it this way
local awak_unsellable = {
["j_awak_ca"] = true,
...
}
if awak_unsellable[self.config.center.key] then
so that your code looks better and all you have to do to add a new entry is add it to the table
i can still sell it T-T
you need to check if G.jokers exists in loc_vars
so then which is the “saved by mr. Bones” part? like what if i wanted it to say a different joker’s name
If ... or chains are an eyesore
it's in misc.dictionary
make a file called resources or videos or whatever you wanna call it
make your video file a .ogv
put the video in
is the key correct?
so before the loop
put it in an if statement that says something like if G.jokers.cards then?
tysmmmm
just if G.jokers then
You return a localization entry for saved.
use this code
yeah ik that part dw i just wanted to know where it is
yeah
misc > dictionary
is that an ad skip 😭
it was xD
Can anyone help me understand why my voucher does not seem to exist in game?
remove the = in the first line
ima bother y'all one last time, but i can't get the grey line under the glitchy text
wanna make it play when a joker is sold? i have no idea how! search up a mod with this code!! i stole the ad code from yahi!!
is there also a context for if an edition is added/removed?
uhh it's a bit hard to explain UI structure in text but you want something like
-- pseudocode
column node = {
row node = {
-- glitchy mult text
},
row node = {
-- gray text
}
}
like this ?
In computer science, pseudocode is a description of the steps in an algorithm using a mix of conventions of programming languages (like assignment operator, conditional operator, loop) with informal, usually self-explanatory, notation of actions and conditions. Although pseudocode shares features with regular programming languages, it is intende...

what kind of code would I set up in the main file to load all the jokers with a setup like this
do you need a setup like that?
ah
just cause with how i'm testing my joker
it's not adding the hand size when the a joker is added, but turns negative
i probably need to add some sort of check between current hand size and the benefit but it would probably involve collateral with other hand size decreasing things (Merry Andy, Ouija, etc.)
idk
having everything in the main file gets cumbersome
so I wanna split it apart
then don't
use a normal set up
like this https://github.com/nh6574/VanillaRemade/
splitting is good, but that cryptid-like set up is too complicated for most mods
can anyone help me I need to change a G.GAME variable after an hand as been played
i'll probably create a global that tells the game the hand increase the joker provides, and if the two don't match, just correctly add?
elaborate?
i'm trying to make it so that the deck of playing cards is checked once a round is over and removes a specific seal from the first card it finds but it removes more than one
add and not context.individual and not context.repetition
somthing like that but at the end of each played hand instead of each round (code from the ExampleJokersMod)
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
if context.after then
G.GAME.your_variable = value
end
return SMODS_calculate_context_ref(context, return_table)
end
here?
yes
gotcha
@red flower like this ?
this STILL doesn't work and i'm at a loss of solutions
no
ok
i dont know how to explain it better sadly
and idk how to understand it better too x)
try rarity 2 again maybe?
where / how should i define such variable
and how can i modified them in the calculate part of a joker ?
re-asking my question since I sill dont know, how to use create_replace_sound
you dont need to define it beforehand, for example if it's a counter you can just do
G.GAME.your_variable = (G.GAME.your_variable or 0) + 1
and it will update it if it exists or create it if it doesn't
okay thx perfect
does context.update just check every frame? is there even a context.update?
i just want something to adress discrepancies
no but there's an update function that checks every frame yes
ah good
i'll use that then
so, you can't help me at all ? (no worries about that no one can fully help)
this comma shouldnt be there
theres maybe something else i cant see in the screenshot
awesome news: after looking at other mod's codes i've managed to actually make it work but the jokers don't actually count and go in the joker slots?
G.jokers:emplace(card)
right thank you
SMODS.Joker{
key = "know",
loc_txt = {
name = "{C:dark_edition}The Forgotten One",
},
atlas = "sm",
soul_pos = {x = 0, y = 1},
rarity = "awak_know",
pos = { x = 0, y = 0},
cost = 50,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = { extra = { max = 100, min = 0.1 } },
loc_vars = function(self, info_queue, card)
local r_mults = {}
for i = card.ability.extra.min, card.ability.extra.max do
r_mults[#r_mults + 1] = tostring(i)
end
local loc_mult = ' ' .. (localize('k_mult')) .. ' '
main_start = {
{ n = G.UIT.T, config = { text = ' X', colour = G.C.MULT, scale = 0.32 } },
{ n = G.UIT.O, config = { object = DynaText({ string = r_mults, colours = { G.C.RED }, pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.5, scale = 0.32, min_cycle_time = 0 }) } },
{ n = G.UIT.C, config = { padding = 0.15}, nodes = {
{ n = G.UIT.T, config = { text = ' Dimensions shift, reality itself trembling under a weight unseen.', colour = G.C.DARK_EDITION, scale = 0.32 } },
{
n = G.UIT.O,
config = {
object = DynaText({
string = {
{ string = 'rand()', colour = G.C.JOKER_GREY }, { string = "#@" .. (G.deck and G.deck.cards[1] and G.deck.cards[#G.deck.cards].base.id or 11) .. (G.deck and G.deck.cards[1] and G.deck.cards[#G.deck.cards].base.suit:sub(1, 1) or 'D'), colour = G.C.RED },
``` (i had to cut it it was too long for discord and to big for a screenshot)
slight problem
this happens even when you're looking at her in the collection
indeed it was
yeah update runs always
what are you trying to do?
how do I make my modded jokers auto-discoverd
discovered = true
basically
adds hand size for each negative joker in your joker slots (including this joker and copies of it)
hmm yeah thats a bit complex
i would try doing it in contexts if you can but if you want to do it in update then you would need to check if it's in the joker area
is it possible to add a function that can be used in any part of the game ?
i've only got the update part because when a joker becomes negative the hand size doesn't increase
i've got my own custom booster pack to show up in game but im wondering how i would get it to choose only jokers from my mod. does anyone know how i could do this?
you have to make an SMODS.ObjectType and then in create_card you return { set = "objecttype_key", area = G.pack_cards}
Would it not be easier to hook set_edition and check if e_negative is the target edition and call a context that's specific to this Joker?
wouldn't know how to create my own context
SMODS.calculate_context({editionchange = true, targetcard = self, targetedition = edition}) in the hook.
Something like such.
if context.cardarea == G.play and context.repetition and not context.repetition_only then
if context.other_card:is_suit("Hearts") then
return {
message = localize("k_again_ex"),
repetitions = card.ability.extra.repetitions,
card = context.other_card
}
end
end
end```
how do i make it so the joker itself also shakes when the card said "Again!"
i really don't know how to do hooks it is arcane sorcery for me
sorry to bother but could you help me out with how to structure one?
Point card to card, but set message_card to context.other_card?
put card:juice_up() in an event
but also the joker is usually the one that says "Again!" is that intentional?
so kinda like this???
yes but the cards list needs to be a list of keys
and how do i do that? (I cant find practicly anything abt changing sound in balatro other than replacing the file by hand)
okay so i tried adding that but it didn't work so then i tried doing this, and it removes the seal of the last scored card with the specific seal before the round ends
Is it? Its my friend that plays balatro the most, im new to balatro. If so how would i make the joker do that?
it works but then when i try it again the next round, it doesn't remove any seals
what does adding local in front of the code do?
i dont recommend using global variables to do stuff at all but also returning soultrigger and destroyed at the end will not update them
remove the message = and the card = lines
no, the earlier syntax was correct
the keys have to be like j_modprefix_key = true
Oh ok thanks
ah ok
yeah
so like
j_modprefix_canny cat = true,
etc,
yeah that's probably the problem, what do you recommend doing instead ?
save it to card.ability.extra.soultrigger and dont update variables in a return
alright that sounds good
trying to enter a cryptid run with suit deck (hearts) and infinity sleeve on white stake
this is more fitting in the cryptid or cardsleeves threads or #⚙・modding-general
...now the game crashes when the pack is about to open
local set_edition_ref = Card.set_edition -- set up reference.
function Card:set_edition(edition, immediate, silent, delay)
SMODS.calculate_context{edition = edition, card = self} -- execute context call.
set_edition_ref(self, edition, immediate, silent, delay) -- call original function.
end
-- in the Joker
if context.card and context.card.ability.set == 'Joker' and (context.edition == 'e_negative' or context.edition.negative) and not (context.card.edition or context.card.edition.negative) then -- check if target edition is Negative and the given Joker is not negative...
-- add hand size
elseif context.card and context.card.ability.set == 'Joker' and context.card.edition and context.card.edition.negative and not (context.edition == 'e_negative' or context.edition.negative) then -- check if target edition is NOT Negative and we are Negative...
-- deduct hand size
end
-# Take with a grain of salt-
OKOK I FIXED IT
now the game is spawning cards
but its all fuckin jimbo
i think i can fix this ez
how do i find whats the object key?
i'm very stupid when it comes to hooks
can someone help?
i think it's working now but the only thing is it removes all the seals of the last scored card (ex: a two pair with all the scored cards having the specififc seal i'm trying to remove), meanwhile i'm only trying to remove the seal from one card
uhh, what did I do?
anyone know what i missed here? trying to set up custom decks with smods.back but i'm not entirely sure what i'm doing
ok i cant fix it
the reason the atlas doesn't match is because i had it as PortatroBack and it wasnt working so i just tried a different atlas i was already using
ok i fixed it
is it ethical to scower every mod on the modding wiki to see if any jokers have a similar effect to a joker im making if im not going to release it? I have no clue how i would implement the ability since i have no idea what to do beyond the basics
i mean yea you can look at how people do stuff, if you take their code directly you should probably ask them
What's the best list of all enhancements, including modded enhancements?
ok
if they have a license look at it, that will tell you what you can and can't do with their code
if they don't, ask
I guess I'll give an opposing voice here and say stealing is cool so you should do it because that's how you learn
im also for it but its just a rule in here at least that you need express permission
so i figured it wouldnt hurt to state it
if you're not going to publish your mod publicly sure, no one will ever know you used their code
thats also true
yeah, im not gonna release it i just want to see if the idea in game
private mods may as well be free game
Yeah like I don't even believe in intellectual property of public code. You're basically asking to be absolved of thoughtcrime
Thoughtcrime is not real, do what you want
but im thinking of crime right now
whatcha gonna do smt, gonna report me? (also hi)
okay, let's say I take all your code, obfuscate it and start selling it under a new name
would you be okay with that
im so confused why is a vanilla joker is causing a crash when my consumable that only effects my coffee jokers is used
the joker in question was onyx agate
what is the crash exactly?
Ye
hold on let me get it bak up
.ability.extra is a number on some vanilla jokers.
Ah, some vanilla jokers don't have extra as a table, but rather a number
so you should do the same check you do in can_use with type
bump on this
no im lost
I only see Glass and Lucky taken ownership of, so does that mean they're the only two that fall under SMODS.Enhancement?
G.P_CENTER_POOLS.Enhanced
hello gentlemen does anyone have any resources on how to start adding custom sprites/jokers
Oh! Thanks!!!
i've looked online and couldn't find any good guides
explain wat im supposed to be doing bcoz i am a lil lost
Just do (type(v.ability.extra) == "table" and v.ability.extra or {})
also i'm using balatro mod manager because it's the easiest, but for testing my own mods i assume i'll want to download steamodded + lovely separately right
Yep yep!!
cool thanks
it suddenly unfixed itself
ive looked at litterally every mod on the modding wiki and nothing is at all like my idea's ability : (
What is the goal?
To make played steels count as held in hand
no idea, im not good at that
i checked that code and there were dev notes saying steel woudlnt work with it
i suck with hooks
could someone help me make it so that the added hand size updates when a card is given an enhancement
It does.
i've got the keys identical and it just spawns the default joker instead of any of the modded jokers
Whilst you have copied the Joker stuff, you've not even set up a hook yet.
local set_edition_ref = Card.set_edition -- set up reference.
function Card:set_edition(edition, immediate, silent, delay)
SMODS.calculate_context{edition = edition, card = self} -- execute context call.
set_edition_ref(self, edition, immediate, silent, delay) -- call original function.
end
where is that in cryptid
any idea why the card wont respawn if i destroy it using a vanilla joker (aka ceremonial dagger), but it does respawn if i destroy it using a modded joker?
lovely/misc_joker.toml
Firstly, keys can't have spaces, Secondly, it needs to be like j_modprefix_key
oh you gotta be kidding me
thanks : D how do i make add that to a smod file thing
You make a lovely.toml file in the mod folder.
so if you made it like
j_funnycats_canny = true
the square brackets aren't entirely neccessary in my experience doing a similar thing
...so this should work?
Then put something like this in it: ```toml
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if context.cardarea == G.hand and context.main_scoring then"
position = "at"
payload = "if (context.cardarea == G.hand or context.cardarea == G.play and next(SMODS.find_card('j_modprefix_key'))) and context.main_scoring then"
match_indent = true
...do you want their ability to also be retriggered by Mime?
yeah, like baron, mime, blue seal kinda stuff
is that all that i have to do?
...would that not also need overwrite = true?
at automatically overwrites i think, doesnt it?
If you want it to be retriggered by mime then it would need a bit more work I think.
And, honestly, this does sound like something I've already have done currently.
it does?
ok so now that i have this
what next
You should try getting some Jokers to be set Negative then.
added tags, boosters, planets and poker hands to vanilla remade :3
https://github.com/nh6574/VanillaRemade
how can i give a card a sticker?
your wording is throwing me off slightly
could you rephrase please?
why is this not creating etheral tags after boss blind?
dang you did
it needs to be edition = edition or every edition will count as negative
also set_edition is not always called with the edition key
would it be easy to port that into a joker?
i see
bump
SMODS.Stickers["modprefix_key"]:apply(card, true)
when i use set_ability on a joker does it keep its original card.ability.extra table
no
hmm
It does, if nothing overwrites it, I think.
how could i save those values
oka
im working on overclocks
so now that i have the hook
idrk what to do next, sorry for being so high-maintenance-
and i want certain scaling jokers to keep their scaling
bump
...the way I do it doesn't involve calculate on the Joker actually doing it - instead, I have hooked SMODS.calculate_main_scoring and check for context.cardarea == G.hand, then iterate on cards in other playing card areas. In your case, you'd have to just check for and iterate over context.full_hand, then SMODS.score_card(card, context).
Because jokers don't calculate when getting removed if card.getting_sliced is true
oh
So the modded jokers you are testing with aren't setting that.
how can i make so it doesnt affect this specific joker?
Put that in remove_from_deck
how would i got about starting that? i am very new to programming
if not G.CONTROLLER.locks.selling_card then
and does this also mean i have to change the keys of the actual jokers themselves or?
ok thanks
Yes.
like add the j_funnycats
oh ok
No, just remove the spaces.
k
I tried to make a Joker that spawns Negative playing cards but the game crashes when i select a blind
SMODS.create_card{ set = "Playing Card", edition = "e_negative", area = G.discard}
also k_plus_negative_card doesnt exist unless you define it
so if i want to check when a joker becomes negative
how do i use the hook
How do i define it?
ive done that and everything is turning up jimbo
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/e60af444900c3227a4f78c5dd34c7f8ce9f283ac/togastuff.lua#L548-L556 See this hook of mine and the togabalatro.heldinhandscoring function above that is called by it.
what did you set as the default for that object type
...i dont think i set one, mostly cuz i didnt know what to set it as
i ended up adding an argument to my overclock function that would save the old card's values in old_extra
try doing
inject = function(self)
SMODS.ObjectType.inject(self)
-- This for each joker you want to insert
self:inject_card(G.P_CENTERS.j_prefix_key)
end
instead of using cards
put it in the localization file in misc.dictionary
or you can just get rid of localize and put the string directly
genuinley help
i am so lost
if context.edition and context.edition == "e_negative" or (type(context.edition) == "table" and context.edition.negative) then
thank you :}
where exactly would i put this?
how can i make so if i win a blind i actually dont win it and your score resets to 0?
inside your object type
did a small fix
so i would do something like this?
i still don't fully understand how to inject things into objecttypes
Yeah
with inject_card!
what's cards for then
idk it seems unused by smods
weird
the mods prefix would be the same as the mod_id in the steamodded header right?
no, do you have a --- PREFIX?
I think if you're using headers it takes the first 4 letters of your mod id
you should really be using json metadata tho
oh
yeah no, it's properly used, I swear it wasn't before
so cards would work fine
I've not setup a localization file yet, so ima just remove the whole string in entirely til i get a localization up
Or with pools.
is there a way to mod on phone? if so can somebody help
#📜・modding-rules rule 4
alright, i changed it to json metadata and that fixed it
(this isnt with the inject card stuff btw)
👍
Hi. I've been searching for a long time, but i just cant figure it out. How can i check if the defeated blind is a boss blind, when hooking Blind.defeat (not in a calc func)
G.GAME.blind.boss
self.boss probably also works there but I'm not sure
ye that was too obvious to bwe true 😭 thx
another q
i have never done a completely custom ui in balatro (liike i've done it in extra_tabs and config) so how could i make it so instead of going directly to the shop after defeating the boss blind, show another screen first (with a countdown)
that's something i need to figure out myself haha
the UI part of it should be all the same (see the UI guide in the docs if you haven't) the problem is messing with G.STATE
which probably isn't that hard but idk how
i really dont know why this is happening, does anyone know why?
maybe a filter? i dont code so i cant really be for sure
Pretty sure it's because of the CRT filter
@frigid cargo Try doing this in the settings and see if it helps
iimma look at how the multiplayer mod does that stuff
it has a custom screen afaik
im only talking about it being cut off on the side
what's your atlas definition
SMODS.Atlas{
key = 'MegaGeoPackCraig',
path = 'MegaGeoPackCraig.png',
px = 71,
py = 95,
}
is the image 71x95
yes
dunno then
ill try respriting
Probably an issue in your spritesheet
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if not context.other_card:is_face() and not context.other_card:get_id() == 10 then
return {
chips = card.ability.extra.chips
}
end
end
end
No matter what it never gives the chips?
am I stupid?
I have a question: how do you remove the debuff from a card that previously had a debuff?
you could check vampire
maybe idk
if context.before and context.main_eval and not context.blueprint then
local enhanced = {}
for _, scored_card in ipairs(context.scoring_hand) do
if next(SMODS.get_enhancements(scored_card)) and not scored_card.debuff and not scored_card.vampired then
enhanced[#enhanced + 1] = scored_card
scored_card.vampired = true
scored_card:set_ability('c_base', nil, true)
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
scored_card.vampired = nil
return true
end
}))
end
end
if #enhanced > 0 then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain * #enhanced
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.extra.Xmult } },
colour = G.C.MULT
}
end
end
if context.joker_main then
return {
xmult = card.ability.extra.Xmult
}
end
end,
this is vampire's code (kinda, it's vanillaremade but still)
not a == b is always false if a is truthy (in this case)
do a ~= b
??
Thats a pretty good question
SMODS.debuff_card(card, false, "source")
"source" what does it mean?
mmm
ok i got balatro on pc how i mod
does anyone know how i can go about allowing gaps of more than 1 for straight calculation (i actually would prefer it to be any amount of gaps not just hardcoded to 2)
ty
wh yis brainstorm mod crashin my game
How would I create a restriction for a challenge that limits the total amount of money you can hold?
Probably hook ease_dollars
So How do i properly create an Atlas that works with both Sprite smoothing on and off?
Do i need like two different Atlases? Like a 1x Atlas and 2x Atlas?
yes
alright, i'll just wing it
x2 just needs to be double x1
yeah
the way i do it personally is by drawing each card at 1x scale, then when i'm ready to export, create the 2x atlas by doubling the width and height of the image
you only need one smods atlas, but 2 actual image files
function ease_dollars_ref(mod, instant)
--what do i put here--
end```
is this correct so far?
No.
ah alright
It should be function ease_dollars(mod, instant)
and as for the function's contents?
okay
what do i put in the function?
How would I select a random card in my deck?
pseudorandom_element(G.playing_cards, "seed")
G.deck.cards if you want the current deck
if conditions then
mod = math.min(mod, moneylimit-G.GAME.dollars)
end
``` Maybe?
so
something like this?
No, conditions was supposed to be checking if the challenge is active.
so
how would I go about checking the current challenge?
You would set a custom rule then check for it in G.GAME.modifiers I think?
?
yeah i realised
now how to reference the value in the hook
because
i'm setting the money limit value to 10 in the custom ruling
how do i reference the value?
?
would this be correct?
i see
thank you
this just prevents me from getting money altogether, i should probably re-add the condition as an "and" condition
No, you need to return the old function.
return ease_dollars_ref(mod, instant)
Trying to do a joker that changes the values of Glass Cards upon being picked up. I'm having trouble getting it to work and I assume it's because SMODS takes ownership of it?
G.P_CENTERS.m_glass.config.extra = card.ability.extra.glass_break
for _, v in pairs(G.I.CARD) do
if v.config and v.config.center and v.config.center.key == 'm_glass' then
sendDebugMessage('updating glass cards')
v.ability.extra = card.ability.extra.glass_break
v.ability.x_mult = card.ability.extra.glass_mult
end
end```
I keep getting strange results, such as how after selling it, it only resets the chance value but not the xmult value
is there something weird about config.Xmult?
card.ability.extra.steelmult = (((shapecount * card.ability.extra.steelmult_gain)/10)+1)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(context.other_card, 'm_steel') then
if context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
else
return {
xmult = card.ability.extra.steelmult
}
end
how do i make it so if its steel and is a diamond suit card, it returns x_mult and steelmult
hiya! i'm trying to call this function in my script, outside of any functions:
ArtBox.add_collectible('m_phanta_ghostcard', { atlas = 'phanta_PhantaCollectables', pos = { x = 0, y = 0 }, soul_pos = { x = 1, y = 0 }})
however, ArtBox doesn't seem to exist yet at this stage. how can i call it when this function exists?
[the function is part of another mod]
Hook Game:main_menu
okie doke! thanks :D
that's the same thing tho 🤔
Oh I didn't see the if statement
thought you were referring to the G.GAME.modifiers["money_limit"] part
i finally did it
there is no sprite because uh
i can't draw
yet another gacha themed mod for balatro, coming uh, soon?
How do you make decks?
local ed = ease_dollars
function ease_dollars(mod, instant)
if G.GAME.modifiers.money_limit and type(G.GAME.modifiers.money_limit) == "number" then
mod = math.min(mod, G.GAME.modifiers.money_limit-to_number(G.GAME.dollars))
end
ed(mod, instant)
end
to_number simply returns its only argument if Talisman is not installed
I've been working on a mod that satisfies both non-Talisman and Talisman players
it's in my blood now lmao
does changing the suit of a card apply to context.playing_card_added? i'm trying to set up a joker that triggers an effect if all cards of a certain suit in your deck become a certain other suit
no
i dont think so
you could add your own context
that's a bit hard
yeah i was thinking about that but how would i even do that for something like this
is it "one suit vanishes from the deck"
aka "you got rid of an entire suit"
hi
let's say your deck has any number of the other suits and hearts
if you turn all the cards in one of those suits into hearts, even if it's just one
the effect triggers
hi
even if it's just one?
isn't that simply "when a card changes suit to a certain suit"
like if i just have one diamond and i change it to a heart, the conditions are met
however, if i DESTROY that diamond the effect won't apply, because now it's not
"hearts is all that's left because i turned all my cards into hearts" it's "hearts is all that's left because i took out everything else"
yeah, but it has to factor all of them for the effect to apply
which is why i'm stuck
hook Card:change_suit and SMODS.change_base
Ortalab does something similar like that
do you remember what it is so i can see how they did it?
local card_change_suit = Card.change_suit
function Card:change_suit(new_suit)
local change = self.base.suit ~= new_suit
card_change_suit(self, new_suit)
if not change then return end
local scaling_joker = SMODS.find_card('j_ortalab_mill')
for _, card in pairs(scaling_joker) do
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.gain
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.extra.xmult}}})
end
end
local smods_change_base = SMODS.change_base
function SMODS.change_base(card, suit, rank)
local change = suit and card.base.suit ~= suit
local card = smods_change_base(card, suit, rank)
if change and not Ortalab.harp_usage then
local scaling_joker = SMODS.find_card('j_ortalab_mill')
for _, card in pairs(scaling_joker) do
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.gain
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.extra.xmult}}})
end
end
return card
end
this is how Mill scales its Xmult when a card changes suit
just do your check there
Hii, back, sorry, this might be like, a very simple thing but I'm silly and Very new to coding
I asked this earlier and the consensus was just to add an "Add to Deck" thing
So it's for Cavendish, and Cavendish doesn't Have an Add To Deck thing
key = "cavendish",
add_to_deck = function(self, card, from_debuff)
play_sound('Wake_up_Cyn', 0.7, 0.55)
end,
}```
Would this be correct to have in the main.lua file?
The sound is spelled exactly as the .ogg is in the assets/sounds folder
Like, is it really this simple?
because the check only runs when a card changes suit, you don't have to worry about destroying card accidentally triggering the effect
ahhhh
card.ability.extra.steelmult = (((shapecount * card.ability.extra.steelmult_gain)/10)+1)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(context.other_card, 'm_steel') then
if context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
else
return {
xmult = card.ability.extra.steelmult
}
end
how do i make it so if its steel and is a diamond suit card, it returns x_mult and steelmult
Also, if I have the mod on, cavendish doesn't appear, at least in seeded runs where it's supposed to
- did you declare
SMODS.Sound{key = "Wake_up_Cyn", path = "Wake_up_Cyn.ogg"}? - use
take_ownershipinstead:
SMODS.Joker:take_ownership("cavendish", {
add_to_deck = function(self, card, from_debuff)
play_sound('modprefix_Wake_up_Cyn', 0.7, 0.55)
end,
})
I'll try this, thank you
replace modprefix with your actual mod prefix
Yeah in this case it's homies 👍
I will report back
Works, thank you!
Learning, learning
And it appears when it's supposed to
Thanks so much!!
can anyone help me?
What should the joker do?
it give chips and xmult per diamond card scored, and it also gives a different xmult if card scored is steel. My friend wants the two xmult to activate at different times and not together when a diamond steel is played
also thats not the full code, theres another set for just diamond cards
I think there is a syntax error
huh?
`
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.x_mult, localize(card.ability.extra.suit, 'suits_singular'), card.ability.extra.steelmult } }
end,
calculate = function(self, card, context)
local shapecount = 1
for i = 1, #G.jokers.cards do
if G.jokers.cards[i].config.center.pools and G.jokers.cards[i].config.center.pools.Shape then
shapecount = shapecount + 1
end
end
card.ability.extra.steelmult = (((shapecount * card.ability.extra.steelmult_gain)/10)+1)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(context.other_card, 'm_steel') then
if context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
else
return {
xmult = card.ability.extra.steelmult
}
end
elseif context.individual and context.cardarea == G.play and context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
end
end
}```
heres the entire code
card.ability.extra.steelmult = (((shapecount * card.ability.extra.steelmult_gain) / 10) + 1)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(context.other_card, 'm_steel') then
if context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
else
return {
xmult = card.ability.extra.steelmult
}
end
end
it works, its just that idk how to add the other xmult
i dont know how apply code mode
function CHAR.FUNC.reset_bunker_suit()
local _suits = CHAR.FUNC.check_suits_deck()
local picked_suit = pseudorandom_element(_suits,pseudoseed("pfjpjfio9wejfpjaurgbhtphivg" .. os.time()))
CHAR.G.current_bunker_suit = get_key_for_value(_suits,picked_suit)
end
does anyone know why this would disproportionatly pick spades or is the game just fucking with me
because it keeps picking spades
until i remove every spade
from the deck
then it stops
CHAR.FUNC.check_suits_deck = function()
local cards_of_suits = {}
for i=1,#G.playing_cards do
if not SMODS.has_no_suit(G.playing_cards[i]) then
cards_of_suits[G.playing_cards[i].base.suit] = (cards_of_suits[G.playing_cards[i].base.suit] or 0) + 1
end
end
return cards_of_suits
end
`card.ability.extra.steelmult = (((shapecount * card.ability.extra.steelmult_gain) / 10) + 1)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(context.other_card, 'm_steel') then
if context.other_card:is_suit(card.ability.extra.suit) then
return {
chips = card.ability.extra.chips,
xmult = card.ability.extra.x_mult
}
else
return {
xmult = card.ability.extra.steelmult
}
end
end
`
it should work like this
this is what it returns
when there arent any spades
i surely have to just be unlucky right
huh? theres a second part to it
as shown here
ok
take a guess /lh
oh why did money double
I'm genuinely scared of your shenanigans
a bunch of random contents, suitable for mod hoarders
not to mention their self-insert legendary
that gets stronger the more mods are installed
i don't know
i come in peace

also this isn't shenanigans mod
shouldn't it say SMODS.suits
it's about your forwarded video
oh alr
yeah this isn't shenanigans mod
log _suits before you use it
it's called Playbook
the behavior of the function is known to me
me thinks that's the problem
it returns a table of every suit in the full deck
ive tested this
multiple
times
but ill give it a shot
still feels like your shenanigans
because, like
it plays tetoris?
👍
so I got confused there
oh
all the values are identical
that makes alot of sense actually
i used a function that would grab a key from a value
but i never accounted for the fact that in a 52 card dec
all the values would be identical
so it would probably just pick one
good old UD
love it
glad I could help lol
so technically speaking i should probably salt the numbers in the table when i get them back
probably just add a random number from 0 to 1
i dont need the number of cards in the deck, so its worthless to me to keep them 'accurate'
did your file save
hit control S for me
always get the stupid things out of the way first
catches me all the time lol
ah
Gonna bump this b/c I'm still really confused what the difference is
I looked in the collections and it was working
I think because I changed it from chips to mult without making a new one it forgot to set
YEP
these ones work
xd
what does Xmult_mod do?
the _mod versions of keys allow you to supply unique messages
whereas x_mult/Xmult automatically shows a message for xmult
ah i see thanks
technically you don't really need to that anymore with the introduction of xmult_message and remove_default_message
some vanilla jokers still use the _mod counterparts to print the exact same thing as non-ones
which is funny because thunk
how can i return 2 different variables of xmult one after another
works like a charm now

SMODS.calculate_effect() is your friend
y not extra table
who me
hi everyone! sorry if this is a kind of basic question, but ive been staring at the wiki and examples for a bit too long now and cant figure out what im doing wrong :/ i'm making my first mod, right now i just have one joker and i want to test what i have so far. but steamodded doesn't register the mod and im not sure why :O
any help is greatly appreciated
calculate_effect isn't gonna work for every situation
return {xmult = number, extra = {xmult = number}}
also the description references 2 variables (#1# and #2#) but you've only given it card_limit in the local variables
ah ok thanks
Perhaps the mod is just not enabled?
Nothing immediately jumps out at me
unless im missing something obvious, it doesnt show up in the mod list to enable?
could we also get a crash log?
oh 💀
can we see the metadata
Does it print anything in the console about failure to load the mod?
the variable in loc_vars is questionable
oh yup! sure enough! the metadata file is invalid the second screenshot here is the entire metadata json file
oooh ok, that one i copied from another mod! will have to look into that
oops 🤦 thanks LMAO
can we see it
now your mod loads but the game crashes
"NAME.json"
guys 1 thing at a time, the metadata is failing
this is the json file!
ok ive fixed the typo there!
"badge_colour": "32A852",
"badge_text_colour": "FFFFFF",
"display_name": "Cardsauce",```
Some other fields you would need I think
it's loading now! yay! and hasn't crashed yet :D thank you all for the help
but it shouldn't be G.consumeables.config.card_limit
your joker's variables seem to be the ones related to probability
oh true :P admittedly my process for writing that was a bit all over the place. it currently doesn't do the probability, just creates the planet card when the face card is scored (or at least, in theory. haven't tested it yet)
and hey! there's the crash! at least it's loading now 😅
do vars = {card.ability.extra.plan_chance, G.GAME.probabilities.normal}
G.consumeables is a card area that doesn't exist in menu
if you access the collection from there and try to hover the card, it crashes
like I said, set the variable to something else

Oook gotcha! Making that change now. Thanks 
So... how do you check for enough consumable space instead?