#💻・modding-dev
1 messages · Page 384 of 1
Can I add my own localization language that you can turn on in the config and then my jokers have different descriptions from that language?
like
Funny Language: ✅
Joker1Description: funny description :D
Funny Language: ❌
Joker1Description: en-us normal description
take ownership and use get_weight(self, weight, object_type)
info_queue[#info_queue + 1] = {set = "Other", key = "tl_key", vars = {}}
-- localization file
return {
descriptions = {
Other={
tl_key={
name="",
text={
},
},
},
}
}
how would i take ownership in the code?
how can i randomize my seal type? so like at the end of the round , it randomizes the seal type etc etc but not sure how rng works with balatro
SealTypes= {
"Red",
"Blue",
"Gold",
"Purple",
"NOTHING"
}
local random_g = randomSelect(SealTypes)
card:set_seal(random_g, true, true)
formatting for this is horrible, pls don't just copy/paste ;-;
i dont have the randomselect func lmao
i still dont understand how i would use this to change the weights?
function randomSelect(table)
for i = 1, 5 do
math.random()
end
if #table == 0 then
return nil -- Table is empty
end
local randomIndex = math.random(1, #table)
return table[randomIndex]
end```
and the set seal func what is it? if u have it
it should be card:set_seal()
my bad
how do i take the joker name and text from a localization file?
not a standalone function ;-;
take ownership of the rarities rare and uncommon
then modify get_weight(self, weight, object_type)
uhhhh
does anybody know the keys to rare and uncommon?
i THINK it's just 2 and 3 but dont quote me on that
okay so like wait
im seeing this code as example:
SMODS.Joker:take_ownership('joker', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
cost = 5,
calculate = function(self, card, context)
-- more on this later
end
},
true -- silent | suppresses mod badge
)
what do i replace smods.joker with??
smods.rarity?
SMODS.Joker:take_ownership('joker',
{ -- table of properties to change from the existing object
rarity = 2 -- uncommon
calculate = function(self, card, context)
-- more on this later
end
},
true -- silent | suppresses mod badge
)```
maybe this?>
if you're trying to change that joker's rarity?
im trying to modify rarities themself
oh uhhhh
im adding a stake that makes uncommon and rare jokers 4x more uncommon
yeah it'd be SMODS.Rarity
then what would i change get_weight to
Is there a way I can change the order of my custom rank to be accurate to how big the number actually is?
with decimals i dont think so
does the pi card score pi chips?
Yes! ^^
3.1415?
Darn...
how can i show the cureent seal effect in my description?
how accurate
Just 3.14, originally it was DOOM's slightly inaccurate approximation, but then I shrunk it
how hungry...
what does your current description look like in-game?
umm what would be the type of localization a custom consumable would have? descriptions = { Other } ?
it just crashes when i want to look at the desc

The game crashes when selecting a blind I've disabled all mods and still. I have my mods from balatro mod manager
you dont have loc_vars
check the actual mods folder
who
bump?
have you tried a new run
What do I do from there
i do tho
yes
it depends on the type, if it's tarot it would be under Tarot, if it's spectral, it's under spectral, etc.
idk then
whats in it
i found it, if i make a custom consumable type i can just write the key of my type i made
that too
mf asked me about what to respond with and he sent exactly what i told him word for word
whats the rest of your code up until the config
lmao
❤️
0.25 times the base rarity (no i dont know what that base rarity is)
(hes my bf we're modding our own mods respectively)
i'm not making any mods atm
get rid of everything except lovely and steamodded
Why
well one of the mods is causing the crash
frankly id recommend modding manually instead of through a manager
you can put half of them back and binary search to find which one's crashing later
hey, does anyone know how I would use pseudorandom to instead of making a charm tag, make a random booster pack tag? (standard, charm, meteor, buffoon, or spectral?)
``` return {
remove = to_remove,
func = function()
for _, _ in ipairs(to_remove) do
add_tag(Tag('tag_charm'))
end```
I removed all and still''
update steamodded and lovely
Is it easy to understand?
ok
yeah you drag folders in to another folder
i think theres a different random thing for that
yeah but do i just do weight = weight * 0.25??
you could make a local table of tags and filter through them on use, perhaps?
ok, but steam modded do latest(could be unstable)? and where do I find lovely, dowload from the web?
thaat works
but question is how can i spawn a card with that seal
what prefix would a consumable have? like a joker is j_modprefix_jokerkey so what would a consumable have instead of j_
I recommend getting the DebugPlus mod and using the cheat menu to swap the seal
until it hits the one you want
i got it
but how do i swap it
just code -> download zip -> unzip it and drag into mods
card:set_seal()?
they're talking how to test the seal in-game I think?
yeah
Press CTRL + E until it shows up with DebugPlus
does anyone know the weights for rare and uncommon
welp uh
What line is that?
is it math.random?
No.
idk
check wheel of fortune in vanilla remade i think they use it there
fixed it
or aura
gang how would i make a card in the shop always appear with an edition
Like I can make it gain an edition when you buy it but thats weird
pseudorandom_element
why is there just a random spam of ❓ reactions
would i do ownership like this??
SMODS.Rarity:take_ownership('2', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
cost = 5,
get_weight = function(self, weight, object_type)
return .75 * .25
end
},
true -- silent | suppresses mod badge
)
SMODS.Rarity:take_ownership('3', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
cost = 5,
get_weight = function(self, weight, object_type)
return .2 * .25
end
},
true -- silent | suppresses mod badge
)
set_ability = function(self, card, initial, delay_sprites)
card:set_edition("edition", true, true)
end
```?
you need to define get_weight as a function
i did
yeah like that
i just realized lmao
Indentation is not required.
also remove cost = 5
installed both of them
steammodded and lovely
check file integrity on steam then reinstall steamodded and lovely
You mean the location of the card area?
So I can do and not card.area
0.9375% of jokers on maroon stake will be common
more chances for photochad? sign me up
Yes
Every individual collection page is in G.your_collection, it is not the card area itself though.
Because now it applies an edtion to itself when it's in the collection 😭
wait, when installing do I put the mods here?
C:\Users\username\AppData\Roaming\Balatro\Mods
i dont think the keys are right
Which is funny but i don't want it
cause i got 3 rare jokers in a row
I don't think there is an easy way to prevent that.
maybe ur just really lucky
no the jokers are spawning much more commonly than they shouls
when im trying to use the card with the seal it just crashes, idk what im douing wrong
maybe the weights are wrong?
Why do you have a function that gets a random element from a table?
so it ranomzies the seal effect at the end of the round
You know there is already a function for that?
I'm not sure why, but the title/name of the deck isn't getting localized properly
what is it
b_modprefix_lesbians
pseudorandom_element
they're modprefixing the lesbians now?
this doesn't change it
Code?
sent it already
No, I mean the changed code.
SMODS.Back{
key = "lesbians",
pos = {x = 1, y = 3},
loc_vars = function(self, info_queue, card)
return {
key = "lesbians",
set = "Back",
}
end,
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function()
for _, card in ipairs(G.playing_cards) do
card:set_ability(G.P_CENTERS["m_hime_himejoshi_lesbian"])
assert(SMODS.change_base(card, "Hearts", "Queen"))
end
return true
end
}))
end
}
Try removing the loc_vars function.
used that but my main problem still is there
[[patches]]
[patches.pattern]
target = 'blind.lua'
pattern = " elseif self.name == 'The Tooth' then
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
for i = 1, #G.play.cards do
G.E_MANAGER:add_event(Event({func = function() G.play.cards[i]:juice_up(); return true end }))
ease_dollars(-1)
delay(0.23)
end"
position = 'after'
payload = " elseif self.name == 'The Tooth' then
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
for i = 1, #G.play.cards do
G.E_MANAGER:add_event(Event({func = function() G.play.cards[i]:juice_up(); return true end }))
ease_dollars(1)
delay(0.23)
end"
match_indent = true
whats wrong with this patch?
How do I make a voucher redeemed on run start?
This is extremely likely to not work but try replacing everything with
local temp_card = {seal = self.config.extra.SealType, ability = {}}
return temp_card:calculate_seal(context)
Remove the mod prefix when defining the key.
Also the prefix not the mod id.
Removing the modprefix when defining the key results in this
Yes.
not sure if thats the proper tl key but
Replace what exactly?
Everything in calculate
Still have this error when selecting a deck
Alright I guess
is this writing fire or nah
yep it ddnt work
how does one check for a custom consumable type? im using card.config.center.set but it doesnt seem to work when i try to check for the consumable type's key or prefix_key
card.ability.set?
Try this instead:
local temp_card = {seal = self.config.extra.SealType, ability = {}}
local usedfunction = Card.calculate_seal
return usedfunction(temp_card, context)
```?
card.ability.set == '<key>' doesnt work?
nor does prefix_key again
actually wait lemme try smth
how does the game determine what joker comes first in collections tab?
It's what order you load them in.
thought so
ok nvm idk
im trying to make a patch to keep track of the last used consumable of a type im adding
but i cant get it to correctly check for the type
What does it do exactly? I have to remove my entire code for it , why?
It should run the specified seals code automatically, also if it doesn't work you can just undo it.
just to be sure if the consumeabletype's key is 'A' then i should do if card.ability.set == 'A' right
Yes.
well its not working
honestly even i dont know why
when i eval the card's ability.set it does indeed return the key
Maybe it is where you're patching?
does anyone know how i would make a sticker that gives +1 joker slot?
ive copied the code im basing it on (the way it tracks last used tarot/planet) and only changed the key its checking for
it still doesnt work
im gonna sanity check this thing rq
Yes, you put it in apply
ok so i changed it to check for tarots and turns out it just doesnt run at all
guess ill go figure out why
ok im stupid i jucked up the path for the file to patch, forgot misc_functions.lua is in its own folder
thanks anyway lad @daring fern
local pool = {
"The Hook",
"The Ox",
"The House",
"The Wall",
"The Wheel",
"The Arm",
"The Club",
"The Fish",
"The Psychic",
"The Goad",
"The Water",
"The Window",
"The Manacle",
"The Eye",
"The Mouth",
"The Plant",
"The Serpent",
"The Needle",
"The Head",
"The Tooth",
"The Flint",
"The Mark"
}
local selected = {}
for i = 1, 3 do
table.insert(selected, pseudorandom_element(pool, pseudoseed("fiasco")))
print(selected)
end
so its saying that theres
a bad argument to table.insert
what am i doing wrong??
its saying number expected, got string
Are you sure it is the table.insert?
yeah
if i do that it triggers whenever the sticker would appear (in a booster pack) and not when i get a joker with the sticker
Try table.insert(pool, #pool+1, pseudorandom_element(pool, pseudoseed("fiasco")))
I think it's because it doesn't know if what you gave it is a string or a number.
i fixed it anyways
bu just doing
selected[i] = blahblahblah
how do i recalculate what cards are debuffed by a boss-blind?
How do I redeem a voucher on game start?
Or how do I redeem a voucher at all? I was looking through utility and it was just for cards
ive been sitting here for the last 2 and a half hours waiting for a hand to be played/calculated
is this normal for late game cryptid?
yes
i would assume it's a retrigger heavy build
can i spawn a gif on the middle of the screen when a consumable is used? a consumable moves to the middle of the screen so i want it to spawn right there
is there a way to have 2 different odds?
Yes.
Probably yes.
wait ofc there is there's lucky cards lmao
You spawn a voucher then you do card:apply_to_run()?
How do I spawn a voucher?
where do i write a localization thing for messages? descriptions = { Other } ?
SMODS.add_card({set = 'Voucher'})?
Oh!!! Ok! I'll give it a try
has anybody here actually worked with stickers before? the documentation is not helping
whats up
Like this?
is there anything else I should add to the key?
how do i make a sticker that gives +1 joker slot?
you want negative editions as a sticker?
yes
my game crashed :(
No, you do lua cardd = SMODS.add_card({set = 'Voucher', key = 'modprefix_key'}) cardd:apply_to_run()?
misspelled deck
this mf types too fast btw
ohhhhh, ok!
Yes I told him to post it here lmao
hahaha hush you
the apply method of the sticker should handle it
No
if ur talking about something like this:
apply = function(self, card, val)
G.jokers.config.card_limit = G.jokers.config.card_limit + self.config.extra.card_limit
end
probably have to check when the card itself is removed as well because im sure that the game doesnt bother to unapply the sticker before destroying it
this doesn't work properly
don't use self
what should i use then?
It works!! But it also spawns it in here for some reason
yeah add_card is meant for jokers
did you check how negative editions work
No?
it should be in cards.lua somewhere
It’s meant for any card?
ahhhh
also apply is called for both applying (val is true) and removing the sticker (val is false) so you should check that
thats what the documen- wait nvm i dont trust the documentation
Yes then you dissolve it.
add_card can be used anywhere and not just for jokers specifically
that wouldn't really make sense
just specify the area
surely the scammers can do better than that
How can i make a config to allow for players to turn a specific music track off from a joker, i heard making a config file would do it but idk where to start making it
commynity
steamcommynity? really?
Ohhhhh ok!
base balatro defines it in card:set_edition and vanillaremade uses config = { card_limit = 1 }
neither of which really works for stickers
rn i have
apply = function(self, card, val)
if val then
G.jokers.config.card_limit = G.jokers.config.card_limit + self.config.extra.card_limit
else
G.jokers.config.card_limit = G.jokers.config.card_limit - self.config.extra.card_limit
end
end
cryptid does this i suggest looking it up
but this
1: makes the sticker disappear for some reason
2: increases slots whenever a joker with this sticker would be spawned (in a booster pack of 3 jokers with this sticker, +3 joker slots permanently)
where do i write messages in en-us.lua? in Other? and how do i use them in a Joker?
No, they go in dictionary
messages would be in dictionary and they'd be used in cases like where gros michel says 'Extinct!' or 'Safe!'
so in misc, i see, and do i use them in the same way i use info_queues?
in terms of position anyway
- youre overriding the "Sets card.ability[self.key] to val by default" mentioned in the doc implementation ehich keeps track of whethe the sticker is actually present on a card
so do that here toi
No, you do localize('keyname')
oh so like when i want to message chips or mult with a joker alright thanks
- oh yeah wait youre right huh
i should look back at my implementation but im not home
you might have to hook add_to_deck and remove_from_deck or whatever they were called instead
and apply only explicitly checks if card is in already in your joker area and a sticker gets added to it somehow
btw to anyone whose done this before would this work as intended (using the number of unscored cards to decide how strong the ability of the joker is) or do i need to move the math that decides what the variable is to the outside of the return
Tried but to not much avail
never check cryptid
i don't think this is right...
one of these is not like the other
What should i reference then, any pointers would help a lot
no i mean-
this is the code, it also triggers multiple times when I want it once
you need to set area in add_card
so put set.cardarea?
i mean it helped me a lot
It should do that automatically.
maybe because im selling the joker it's spawning in the joker area???
Is the set classified as a consumable type?
it should doesn't mean it does
crashes when trying to load the deck
should I change the Object type to consumable type??
No, you should change the way your choosing them.
o?
You need to put it in an event and check for G.jokers
ahh
how should I then?
For the top one you should just create that card, and for the other one you would get a random one and create it.
like this?
absolute noob to shaders here, are shaders very hard to code?
Probably yes.
fun
No, you would do key instead of set for the top one.
oki
how do i make a deck with less cards
You remove them in apply
card:start_dissolve()?
and also how do i use randomness, do i just use math.random? or something else
What is the function to hide and show these elements?
[Hide "Play Hand" or "Discard"]
I've looked at the code for a while and I can't really figure out what I need to call to make it happen
Edit: Figured it out!
You need to set the "G.STATE" to either "G.STATES.HAND_PLAYED" or "G.STATES.DRAW_TO_HAND"
You need to set it back to "SELECTING_HAND" at a later time, It's also important to set the "G.STATE_COMPLETE" to true and later to "false" again!
It's best to check out the "state_events.lua" => G.FUNCS.play_cards_from_highlighted
does anyone know why buying a joker with this sticker decreases instead of increases the joker slots?
ive hooked remove_from_deck and add_to_deck
local para_card_removal_old = Card.remove_from_deck
local para_card_addition_old = Card.add_to_deck
Card.remove_from_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker then
G.jokers.config.card_limit = G.jokers.config.card_limit - 1
end
return para_card_removal_old(self, card, from_debuff)
end
Card.add_to_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker then
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
end
return para_card_addition_old(self, card, from_debuff)
end
does anyone have a link to the thread in #1209506514763522108 for public art resources made by devs I lost it 💀 sorry lmao
I made something I wanted to put in there lol
I know next to nothing about hooking, but how would this be for tracking played hands in a round?
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
if context.before and context.main_eval then
G.GAME.willatro_played_hands[#G.GAME.willatro_played_hands + 1] = G.GAME.hands[context.scoring_name].played
end
return SMODS_calculate_context_ref(context, return_table)
end
doesn't the game already track played hands?
I want it to track just within an ante, resetting afterwards. not sure if there's another way to do that.
how do i use pseudorandom()?
is there a way for me to do the joker effect "earns $2 when a card is retriggered"?
my first thought is to do a hook but i'm not all too familiar with those
Anyone know of a way to configure music playing for a specific joker that isn't jimball
i can't seem to find any other examples that do so
like where you cang go to the mod config and do so
because i can't understand how cryptid does it even by looking into the code
im going to explode, bro
pseudorandom("seed") gives you a number between 0 and 1
pseudorandom("seed", min, max) gives you an integer between min and max
pseudorandom_element(table, pseudoseed("seed")) gives you the pair value, index of a random element in an array
Send a screenshot of the crashing line
why this doesnt work, just deletes all cards (im new to modding)
using center also crashes sometimes
please use loc_vars = function(self, info_queue, card)
what do i even do at this point
img 2 shows my poorly written code that i believe contains the point of issue
oh.
if pseudorandom("seed") < G.GAME.probabilities.normal/2 then
...i think i broke soemthing...
😭
what could you have possibly done
how do i fix this 😭
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
local _card = copy_card(v, nil, nil, G.playing_card)
_card:add_to_deck()
end
return true
end
}))
i think you didnt emplace it in the hand
how do i do that
i think G.hand:emplace(_card)
i dont remember if its G.hand or something else for the card area
uh
well, it went in your hand
nobody said it had to be in the round to work!
ah
i actually dont know about that since i've never used the deck for things like this
i rarely touch playing cards anyway
so uh
any help
try G.deck?
it does go into it, but it doesnt show up in the deck ui
mmm
anyone know if rarities you create spawn naturally in the shop by default or not?
so how would i like
fix that
cryptid (the card) does a couple more things maybe copy from that
when in doubt go check like cryptid code or something
(the card)
i was in doubt
checked cryptid mod code
cried myself to sleep
oops
regardless cryptid still is a very good source and also the spectral card does only create copies into hand, no?
yes but it does a couple more things when it copies that are probably what makes it show up in deck
also I disagree on the cryptid (the mod) part
idk ive found it relatively simple so far to just go off my own intuition plus checking cryptid & examplemod code when i am stuck
well it's not in your code
that error is usually when you try to create a card with the wrong key
i see
How can I make replace_base_card still draw the base card sprite?
wdym
like key = 'c_whatever' or 'c_whatever
OH HELLO
yo this joker should only be creating one tag per card destroyed, but for some reason every card destroyed creates a tag equal to the amount of cards destroyed, anyone know what could be happening here? here's my calculate:
if context.first_hand_drawn then
local eval = function() return G.GAME.current_round.discards_used == 0 and not G.RESET_JIGGLES end
juice_card_until(card, eval, true)
end
if context.discard and not context.blueprint and G.GAME.current_round.discards_used <= 0 and context.full_hand then
local to_remove = {}
for _, c in ipairs(context.full_hand) do
if c.seal then
table.insert(to_remove, c)
end
end
if #to_remove > 0 then
local possible_tags = {'tag_standard', 'tag_charm', 'tag_meteor', 'tag_buffoon', 'tag_ethereal'}
return {
func = function()
for i = 1, #to_remove do
local tag_key = possible_tags[math.random(#possible_tags)]
add_tag(Tag(tag_key))
end
play_sound('generic1', 0.9 + math.random() * 0.1, 0.8)
play_sound('holo1', 1.2 + math.random() * 0.1, 0.4)
return true
end
}
end
end
end,```
context.discard is called once per card
does anyone have an example code of how to configure a song to play in a mod config menu
i tried to reference cryptid but i cannot understand how it's coded
how do i allow spaces, commas, and other things in textboxes?
You type them
they dont show up
if i want to reference my config file, what should i use because i keep getting crashes here
if deck == "red" then
G.GAME.round_resets.discards = G.GAME.round_resets.discards + 1
ease_discard(1)
end
``` this doesnt save between runs
at the beginning of your code do sizi.config = SMODS.current_mod.config
yep, that was it. thanks :)
also don't use math.random for gameplay effects, use pseudorandom
do i replace the current_mod part with anything or keep it that way
heres what it looks like
keep it like that
what I have works fine rn, would it cause any problems if I kept it the way it is?
yes it will be inconsistent with the seed
got it, okay
ok i got a crash, for the line you mentioned in the "sizi.config", do i use the mod prefix to get the config
idk why this isn't working but another one with the same exact line does work
ok add a line just before that that's sizi = {}
anybody have any ideas?
what's the code
like this?
i need more context (no pun intended)
yes
sick, thank you
isn't other_context for post trigger or retriggers
oh
so question - the game differentiates between whether the hovered thing is a joker, consumable and with steamodded, a playing card for the negative tooltip.
how can i implement this for say, red seal?
so i tried saving it to G.GAME.FUSION_DECKS, but its still showing nil;
uh
can i get some help?
It just that its triggering them all, but I doubt there would be a run where you have several Chaplets
you can probably take ownership of the seal and change it with loc_vars
between runs or between reloads?
between reloads it is G.GAME
but between runs you need to save to the profile
i dont remember the syntax for that
yeah cause what im doing is
im checking for red
and adding one discard via G.GAME.round_resets.discards = G.GAME.round_resets.discards + 1
ease_discard(1)
yeah it's not going to be saved until the game saves
okay time to see if
my fusion deck works
i added blue and yellow
OH HELLO
okay now uh
green will be a bit hard to impliment
wheres the code for green deck??
...will that bypass everything that happens in generate_card_ui()?
because in there, when you hover a card, it adds the center of the seal to info_queue.
hello! How would i call for the color from JimboGrad?
self is needed here btw :3
SMODS.Gradient {
key = "JimboGrad",
colours = {},
cycle = 10,
interpolation = 'trig'
}
update = function(self, dt)
self.boss_colour = ???
end
im pretty sure, yes
it does for jokers
why does this only decrease my joker slots instead of increasing? (the sticker only appears on jokers in a booster pack of 3 items where you pick 1)
local para_card_removal_old = Card.remove_from_deck
local para_card_addition_old = Card.add_to_deck
Card.remove_from_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker then
G.jokers.config.card_limit = G.jokers.config.card_limit - 1
end
return para_card_removal_old(self, card, from_debuff)
end
Card.add_to_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker then
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
end
return para_card_addition_old(self, card, from_debuff)
end
i think it's because when the boosterpack is closed the 2 cards i didnt pick are "removed" but i dont know if im missing something
SMODS.Gradients.modprefix_JimboGrad
and i also dunno how to fix that
ah, thank you
add_to_deck would only work if the card starts with the sticker
it does
wait, how do i get the card the seal is on, from inside of the seal's loc_vars()?
uhh it's mentioned in the localization docs but you can check Misprint or Blueprint in vanillaremade or Arrival Cyberse in JoyousSpring(tm)
thanks, lemme check if i still have vanillaremade github link
card?
no idea never made a seal
okay it's definitely this
skipping the pack reduces slots by 3
how do i check where a joker is when it's removed?
Wait, is update(self, dt) called every frame?
pretty much
self.area and self.area == G.jokers maybe but the card might be removed from the area beforehand
how do i give the player a voucher from the get-go?
hm, it doesnt seem to be updating my thing
what area is the inside of a booster pack?
G.pack_cards
in a deck?
yeah
if the game is paused then it doesn't
i mean dt is just straight 0
config = { vouchers= { "key" } }
i think
why does my function hook not remove a joker slot when the joker is sold?
local para_card_removal_old = Card.remove_from_deck
local para_card_addition_old = Card.add_to_deck
Card.remove_from_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker and not self.area == G.pack_cards then
G.jokers.config.card_limit = G.jokers.config.card_limit - 1
end
return para_card_removal_old(self, card, from_debuff)
end
Card.add_to_deck = function(self, card, from_debuff)
if self.ability.para_negativesticker then
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
end
return para_card_addition_old(self, card, from_debuff)
end
hi n
i dont have access to config from where im at rn
wdym
hii
(ex: typing in red1blue1yellow would combine red, blue, and yellow deck respectively)
search for config.voucher in the backs code and do what that does
v_crystal_ball
my code is messy, suffer >:)
im not the one that needs to read it all the time
bump
yeah but some people get really disgusted at seeing i code in notepad
yeah that includes me
i'm surprised you don't
the blue consumes
EVERYTHINGS BLUE
where do i begin with making a little area to show stuff, like the card area?
is that the ukraine deck
its a placeholder for my deck
if you're asking for tutorials you're out of luck
just, like the basics of where to start
my mod has a cardarea on the side and one that opens with a button
they are created here
https://github.com/nh6574/JoyousSpring/blob/1f60413b8a13267634fa8e9945dfa37358f40c04/src/extra_deck.lua#L255
magic, checkered, and black work :)
bump
because G.pack_cards is nil when not in the booster
no, that's not it
not a == b is almost always false == b
use a ~= b
how on earth do i take ownership of a red seal? neither SMODS.Seal:take_ownership('red'... nor SMODS.Seal:take_ownership('red_seal'... work
the key is Red
hey one question, im learning now how to make blinds and i want to recreate psychic but with 4 cards, but idk whats wrong
this doesn't fix it
condition is self.ability.para_negativesticker and self.area ~= G.pack_cards
wouldn't that have the same issue if i sold it in another booster pack (like an arcana pack)?
nope. the entire content of card in loc_vars(self, info_queue, card) when you hover is:
fake_card = true,
ability = {}
no you're just checking if it exists before checking if it's in the area
makes sense
it does that for tooltips
what are the keys for planet and tarot merchant?
search them in the localization files
self.ability.para_negativesticker and self.area ~= G.pack_cards and G.pack_cards ~= nil still doesn't decrease joker slots on sell
try self.ability.para_negativesticker and (not self.area or not G.pack_cards or (self.area ~= G.pack_cards))
that should work i think but if that has the problem where leaving a booster decreases again then that means self.area is removed before remove_from_deck
...wait, wtf?
i'm looking at common_events.lua and i'm wondering if the decision to add tooltips for editions and seals is based on the badges the card has?
what function is it?
generate_card_ui
It seems like it
how do i make it so a joker only appears in the pool when a certain hand has been played?
talisman was the mod that made yggdrasil hard crash
return (G.GAME.hands[key].played or 0) > 0 in in_pool
tysmm
hello
im makin a tarot card and i want to make it so when you use the tarot card you get a $1 increase in reward money from blinds
whats the best way of doing this
heres where i ask how to mod the game?
yes
like make mods
yes
how do i get started
i want to make custom jokers
i only know the game is written in lua
So, I've been testing the Dodo Chaplet card, every time I spawn it, it creates 50 base events and I cannot figure out why
check the pinned post in #⚙・modding-general and you can ask questions here if you have any problems
ive got a timer that increments every second from the beginning of the game, is there a way i could reset the timer to 0 under a certain condition and still have it increment afterwards?
have a variable that holds the current time, that's your time 0, and when you want to check the current timer you do getTime() - variable
bunp
this is the code im working with, it's supposed to increment chips by 1 per second from game launch, and decrement chips by 1 per second if you haven't clicked in over 60 seconds
but i think ive done it incorrectly
the logic makes sense to me, you just need to have ast.idle as the last time they clicked
and check if anticheat > 60
so like this?
anticheat is set to true if ast.idle is greater than 60
when you do ast.idle >= 60 you should be doing anticheat >= 60
huh why
thats the function setting the anticheat to true
unless im missing something
ohh wait
i see
nvm nvm
oh and context.cry_click should go in calculate right?
you need to set ast.idle = getTime() there
well, theoretically you could exit to the main menu and idle there then to get around the anticheat
no but context doesn't exist in update
it does though
the joker increments in the main menu
so this is how i should do it?
no, in calculate instead of anticheat = 0 do ast.idle = love.timer.getTime(), you want that to be your time 0 (and also you can't read a calculate local in update)
ah 😭
I'm facing a strange problem, apply_to_run doesn't seem to work with vouchers without cryptid, but works when I have cryptid?
does someone know a fix to this?
ok i did this very wrong
Vouchers uses redeem
If you mean vouchers don't show up in your deck, you can init them in the config table like Zodiac Deck does it here config = {vouchers = {'v_tarot_merchant','v_planet_merchant', 'v_overstock_norm'}}
so I'd use card:redeem()?
Yes
G.FUNCS.use_card works too but it might have weird behavior
this is broken, what did i do wrong? when the timer hits 60 seconds it instantly becomes -120, regardless of whether or not i clicked
Especially if gotten during booster packs
i was thinking of hooking into something but im not sure where to hook into
i couldnt find the function setting the amount of money you get from each blind in blind.lua
if it works after 60 seconds then the logic is ok, i think the problem might be in cry_click?
cry_click happens whenever you click, this is supposed to set the timer back to 0 when you click
does it happen tho
i dont think so
try printing something
This might be a bit confusing so lmk if I need to clarify but I have a card that triggers when a two pair of face cards is triggered, but the way I have it written right now a hand like (KH KH QH QH 3H) wouldn't trigger even though it is supposed to. So is there a way to specifically get the cards that are in the two pair or is there a better way to do this?
for some reason it doesnt work
which is weird because its always worked before
WAIT
i know why
it's cry_press
Is there a way I can make it so that it doesn't make me pay for the voucher?
not cry_click
either way it still goes into the negatives instantly whenever the anticheat is true
which isnt supposed to happen
Add this to the card ability card.ability.couponed = true
or card.cost = 0
with card:set_cost() afterward
context.poker_hands["Two Pair"] is a list of all the two pairs contained in the hand, so you need to check if any of them has all faces
its only supposed to decrement
so would i do for _, playing_card in ipairs(context.poker_hands["Two Pair"])?
you're setting it to negative the time, you would need to use the current chip value to decrement
I'm trying to make the config menu show options to turn music for a joker on or off but it isn't working
anyone have any idea what's going on?
yes BUT it wouldn't be playing_card it would be poker_hand and then you do a nested loop on poker_hand
ok got it, thank you
eeeeugh
is table.contains a thing or did you define it
its a lua thing
actually, is it
i never defined it
im gonna cry if its from a mod 😭
a lot of mods use table.contains
so im pretty sure its a lua thing
i assume you replace all center with card but card.children.center is what you want there
there we go, much better
i dont see it
does it define it
oh wait nevermind
seals on everything defines it
:3
and malverk too
bleh
thought it was a lua thing
im honestly very surprised that its only reported now
sob
everyone uses malverk lol
true
how do i add a tooltip to a joker?
info_queue
how can i make a joker debuff itself in a way that will be removed after the blind is over, but still retain that state if the run were quit out of and loaded?
i've used SMODS.debuff_card() before, but i don't know that it serves my purpose? 
the way i would do it is use SMODS.debuff_card and then hook SMODS.calculate_context to rebuff all of those jokers at end of round
what would be the context of beating a boss blind?
yeah a quick test of SMODS.debuff_card() proves my suspicion that any cards you debuff that way don't auto undebuff when the blind's over
yeah they don't
context.end_of_round and context.main_eval and G.GAME.blind.boss
is there a way to completely disable animations? I'm running game speed 1000, but it is still too slow
what are you trying to do that needs to go so fast
if it's scoring animations talisman does that
How can I check if a playing card has no enhancements?
not next(SMODS.get_enhancements(card))
Thanks! ^^
card discarding is too long for my run (60 rebates :D)
install talisman
turn on "disable scoring animations"
profit
why am i getting a compare table with number crash on this
no matter if i to_big the numbers or not
it still crashes
what's arrows
can i see the config
yeah you are still comparing a number with a table here
-1 basically means addition
yeah but it persists no matter if i to_big everything or not
you want to use to_big(card.ability.extra.arrows) too
does anyone know how to get the on-screen location of a joker
ideally the center of the sprite
I think that's card.T.x and card.T.y but this is from memory
here we go again
Spectral uppercase
ah
anybody have a clue what the problem here is?
Can someone help me out with this? I'm trying to track any hands not played at the end of an ante so I can level them up, and I don't have a hot clue what I'm doing.
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
local played_hands = {}
if context.before and context.main_eval then
played_hands[#played_hands + 1] = G.GAME.hands[context.scoring_name].played
end
return SMODS_calculate_context_ref(context, return_table)
end
you want to make it a variable in G.GAME instead of a local
And would I want this in with my other SMODS.calculate_context, or is it better to have two?
both work the same, it depends on how you want to organize it
Looks like your Deck Creator mod is misconfigured.
And how do I fix that?
Each mod's path SHOULD look like:
.../Balatro/mods/mod name < --- CORRECT!
.../Balatro/mods/mod name/mod name <--- Nested! (Bad)
If it's the Deck Creator mod I think you're using, they did something weird with how the files are arranged.
The strange thing is that I was unaware that I had a mod like that.
Then it's probably easier to remove it.
Good news. I fixed all of the mod paths and I don't get that error anymore, but now I've got a new error 😢
What mod is AxUtil?
I have no clue.
Screenshot and send your mod list.
I might deduce it from that alone.
Got the same error.
adjusted modlist^
Now with this code I get a crash, line 339 is the first line here.
calculate = function(self, card, context)
if context.end_of_round and context.main_eval and G.GAME.blind.boss then
if #G.GAME.willatro_played_hands then
return {
level_up = true,
message = 'Level Up!'
}
end
end
end
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
if context.before and context.main_eval then
G.GAME.willatro_played_hands[#G.GAME.willatro_played_hands + 1] = G.GAME.hands[context.scoring_name].played
end
return SMODS_calculate_context_ref(context, return_table)
end
Forgot to attach crash:
You may need the crash log (grabbed via doing CTRL + C on a crash) for someone to look through.
I found Util.lua
Got rid of the mod that contained it and got this instead.
I can just delete the mods that cause errors until it works, but I have a feeling that all of them might end up needing to be deleted
Yeah, probably just completely reinstall your mods.
Reinstalled the initial mod that was causing an error and it still gave the same error
have u tried starting a new run
yes
I fixed the other errors, but it seems there is an error with Lovely
that was alot fo text
i'm trying to make a joker give money but it keeps crashing at line 802
Won't let me copy and paste it like normal
Do you have LOVELY's .DLL set as an Exception in Windows Defender?
I do not
Set it as one. That DLL gets commonly flagged as an injector for a virus, thus Windows stops it from working.
(Thanks, Windows. Very cool)
I believe that I set it as an exception, but I'm still seeing an error.
and it still won't copy the crash log as a .txt file
Make sure it's set. If it is and you're still seeing errors, then something is horribly wrong. Maybe.
Is this correct?
Yep, you got it.
I've got no idea. You have a lovely and smods folder in your mod folder and the .DLL is set correctly.
Someone else may know what's wrong.
this does seem to get something position-shaped, but it doesn't seem to be comparable to the mouse position as retrieved from love.mouse.getPosition()
does anyone know a solution to this?
a quick search of the source is suggesting G.CURSOR.T
i'm going to try that
hmm. this somewhat works, but card.T and G.CURSOR.T aren't using the same coordinate system
how do i properly format the suits so that they are seperate as i am currently getting an error
i'm trying to make an econ joker but it keeps crashing when I try to make it give money at line 804
can anyone help me understand why it crashes?
Idk why it is printing nil
Because your not putting anything through loc_vars?
i keep getting an error at line where it says the value of dollars is nil
What line?
Try return {dollars = card.ability.extra.dollars}
it works yayyy
ok, so how could I reset the counter back to 0
You set it 0 in the if
It’s somewhere here
scroll a bit down and it’s in the second message
ty
would it be something like this?
yes it would cool
couldn’t you just do it inside the event right before returning true?
maybe idk lol
if it works it works right
No, I meant in the first if
surprisingly, the code I put works (just w/o the set)
set it to 0 right after increasing it by 1? isn’t is supposed to be 3 to work?
I meant the second if
oh yeah that’s what i said aswell
is there a way to just change a joker into another joker
trying to make a consumable that replaces all instances of one joker type with its corresponding other type
Yes.
that being.?
joker1key:set_ability(„j_modprefix_joker2key”)
if you want to change it to a vanilla joker you dont put anything into modprefix
Yes, but no it would be card:set_abilty(G.P_CENTERS['j_modprefix_key'])
probably a better question for here, does this feel balanced?
maybe, I don’t remember exactly but I didn’t use G.P_CENTERS in my code, what is that for
abilty :3
Your mod will crash with cryptid if you don’t do that.
would be better if its $2
then i guess i have to write cryptid as incompatible in my mod
I'll look over alternate ways to code this in the morning (its 1am lol), but is there a specific reason why this is running 4x times rather than once? I'm trying to have it so when the 'Wicked' card is drawn to hand it does -1 discard and discards your entire hand
probably because you drew that wicked card 3 times in a row
and it takes 4 discards at once because it probably calculates it all before actually doing all animations
Is it a problem within the shader?
Yeah I did end up drawing the card 3 times, but first one causing -4 discard i have no idea how to fix
Even before implementing the discard I used a print line and it did it 4 times rather than once
that was it, the shader had a different name internally to everything else
but it does -4 discards as whole or the first one does -4 and the others try to do -1
It did -4 discards as a result of the first Wicked card instance. The others do -4 discards as well, but in the case of the clip they don’t because 0 discards remaining
is the github wiki the best place for info on smods because I swear I can never find some basic info on things here
oh okay that’s weird, probably something in the for loop line
yeah it’s hard to find stuff in there at first but it’s the best place for everything
hmm alright, it just feels like there's not enough documentation past events and custom content, like how current hand is defined or referenced, or how to get an edtion.
though i could just be missing it..
there's unfortunately a fair amount of stuff that isn't documented yet, or documented well
people are working on that but it's slow going
yeah kinda lacking all the basic stuff like all G. stuff or just a list of all built in functions etc
thank you I wanted to so specifically the G. stuff but I thought I'd sound like a moron
1 year into a bachelors of compsci I can program A CLOWN CARD BY MYSELF
atleast theres a list of all the colors you can do
yay 
Don't forget to look through the pages on API documentation and Utility functions, people sleep on those but there are some hidden gems in there
yeah that has been helpful too
Also VanillaRemade > ExampleMod
https://github.com/nh6574/VanillaRemade/tree/64936206517d5cc132b14a117c15e1473e460a06
I have been using that too but sometimes I want to do things slightly not vanilla and then it gets tough
I hear the Cryptid mod has kinda done everything
But I have not played it nor have I really looked at it so I cannot confirm
yeah I bet it'd be a good resource but I haven't played it
But as a CS teacher with a bachelor's in CS, I feel this
This is certainly the best modding experience I've had though, easier to jump in with balatro
oh definitely
you teach counter strike? that’s so cool hell yeah
yeah cryptid did my 3 hours of work in literally one line
anyone know if/how I could make a joker remove the selection limit in booster packs?
You mean you can take more cards from a booster pack or you can highlight more cards in a booster pack?
anything is possible but that sounds wild
take more, like being able to use all planets, tarots, spectrals, jokers, and cards
wild as in busted or hard to do lol
the red card synergy goes crazy
that was the idea lol
bit of both
there's a joker in polterworx that does exactly that iirc
sounds like it will almost definitely require a patch
Try looking at Off By One from Cryptid?
I have another joker that destroys cards with seals and makes booster tags from those, I thought it would be REALLY funny to get that, this one, and red card
I'll check it out
the joker i mentioned doesn't seem to use a lovely patch, but it does hook the Card.open function
How do I run a context through a playing card (the calculate functions of Stickers, Seal, Edition, and Enhancement on that card)?
any chance you remember the joker name?
also is polterworx new alminac or smth?
Yes.
neat, wacky mod
?
yea it's that one
that sounds like the one
I couldn't find it at first, I thought I was getting it confused with almanac
and then I realized
Making my prized slug worth a joker could be cool..
Also I'm late to this but that feels very strong, you can just farm $5 per hand with basically no prerequisite, and it scales with retriggers
well only if you have splash
Wait it says played cards earn
But then when scored
So probably it should be worded scoring cards
I see what you mean
Which page in smods wiki has the guide of SMODS.calculate_context?
I think
There is a brief section about SMODS.calculate_effect, but no SMODS.calculate_context.
ah
None, because all you do is SMODS.calculate_context({modprefix_contextname = true})?
Then how do I get the return tables?
You do card:calculate_joker({modprefix_contextname = true}) for every card in a joker area?
Does find_joker include debuffed joker?
SMODS.find_card does if you tell it to.
does someone know why it don't show my high contrast atlas
yeah im doing a generic nothing suit
What does the atlas look like?
I dont think that’s the atlas
i used a function to auto generate atlases for me
No, I meant how did you define it compared to the low contrast one.
the key is supposed to be nosuit_hc
while nosuit_lc works
What if you did it manually, would that work?
nope did nothing
if the path was wrong it would give me an error
Also wouldn't it be ```lua
atlas = {...}
if v[4] then
atlas.atlas_table = ...
atlas.frames = ...
end
SMODS.Atlas(atlas)
huh
either way it still doesn't do anything
hc still shows the hearts suit for some reason
did something change with the parameters
no idea whats going wrong
oh
oh.
it was fucking misspelled
this is why you quadruple check people
...could I somehow sort specific cards in the deck to be always last for drawing?
Yes.
You mean at the bottom of the deck?
Hi guys
yeah.
DualSenseDude is streaming on youtube
You would just hook CardArea:shuffle I think.
...what exactly do with said hook? table.sort?
For this example, always have Bonus Cards be last...
table.sort(self.cards, function (a, b) return a and a.config and a.config.center_key ~= 'm_bonus' and b and b.config and b.config.center_key ~= 'm_bonus' and a.rank < b.rank end )
```?
I think you would do something like this but backwards: https://github.com/Aikoyori/Balatro-Aikoyoris-Shenanigans/blob/main/modules/hooks/general.lua#L1224
...this really shuffled a headache into existence.
how can I give a consumable that already has an edition
maybe remade perkeo will be of help actually..
SMODS.add_card({set = "Consumeables", edition = "e_modprefix_key"})?
also how can you do polychrome text
like it shows what polychrome does on the side, smods examples all seem to incorrectly use {C:dark_edition}Polychrome{}, which shows negative
wdym
oh is that a different thing
yeah all those pop ups on the sides are info queues
it adds the extra info boxes next to the description
bump
🤔 can you be more specific
what does that mean
ohh
dont modded seals have calculate built in though?
same goes fro stickers, editions and enhancements
And does SMODS.calculate_context guarantee to run through the card?
SMODS.calculate_context makes it so a new context is added, the timing is whenever its run
it should work for all calculate functions afaik
so yeah
All editions are dark_edition?
I misunderstood how it worked
got it now
Is there an easy way to have a joker debuff/undebuff itself
couldn't find many examples of that
depends on what you mean by easy
Yeah seems the main issue would be undebuffing itself
tried that and it doesnt do antyhing lmao
No crash or anything?
nope
Try keeping that and putting this in your code somewhere:
local oldcalcseal = Card.calculate_seal
function Card:calculate_seal(context)
print(self)
return oldcalcseal(self, context)
end
is there an SMODS method that counts Jokers with a particular key?
