#💻・modding-dev
1 messages · Page 568 of 1
dont know what card area to use either
Yes, because forced_selection only works with G.hand, also card is the joker, also G.shop_booster is the boosters in the shop.
youre looking for G.pack_cards probably
alr
how would i go abt keeping the selection forced then
You would hook CardArea:remove_from_highlighted
Is there an event/easing thing I could do to make it so that my joker rotates 180 degrees when triggering?
can someone tell me why this does not work
What exactly is not working
it does not do anything to cards held in hand
idk
what does get_letter_with_pretend do
yeah i dont see the problem either sorry
does it work for played cards?
it does
How your filter function works
does it
it does
It shouldn't
and when you print cards_matching it has the hand cards in?
because that seems like it might cause gaps
it does
You treat table as object, not array
You need to check key type and if it's a number, insert it, else set
you can probably also just use pairs on cards_matching
also works
a?
i think your rarity is wrong if youre using a custom one, or one of your pools if youre using that
Calculation screen ?!?
im stupid. i put ' around 4
im still strugging on implimenting custom rarities, so im just using the vanilla legendary rarity
welp. that's that done, just gotta make the art for this section
oakey doakey
stupid question generator output: how do i set the cost of a joker? i've searched around docs and file, i've tried card.cost and card:set_cost. What do I do?
It should be card.cost, you just set it like card.cost = 2 or something
https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua#L3897
check Egg and Gift Card
Double-checking about rotation; what value controls the base rotation of a card? I've seen card.children.floating_sprite.T.r floating around but that gets me a nil reference when putting it in an event
G.E_MANAGER:add_event(Event({
trigger = 'ease',
ease = "quad",
ease_to = card.T.r + 180,
ref_table = card.T,
ref_value = "r",
delay = 0.5
}))
(the event in question)
(not card.sell_cost) maybe i needa try removing the card:set_cost()
card:set_cost is going to reset the cost
you should use card.ability.extra_value if you can else i would recommend hooking set_cost
also quick q: what is the "correct"/general way of naming modifiers? is it enable_mod_key or stake_mod_key or what?
(diagram of what I mean)
figured it out.
why does it say "applies gold stake" tho instead of all stakes? (i'm using loc_txt cause i'm too lazy to find out how to make text smaller
applying all stakes would have to account for other mods I don't see how that could be a good thing
But applying one previous stake also applies all other stakes before that though
So its just visual
why is this like this?
SMODS.Stake {
atlas = "stakes",
key = "supernova",
pos = {x = 2, y = 0},
applied_stakes = {"gold"},
prefix_config = {applied_stakes = {mod = false}, unlocked_stake = {mod = false}, above_stake = {mod = false}},
sticker_pos = {x = 3, y = 1},
modifiers = function()
G.GAME.modifiers.enable_supernova_in_shops = true
end,
colour = HEX "d8beed",
shiny = true,
}
not exactly, some modded stakes dont add gold stake
nvm found how to hook showman
but
do i replace card_key with anything?
so having it say "appleis gold stake" rather than "applies all previous" is good cuz who knows the stake order
it's applying the actual sticker sprite when it should be applying the stake sticker sprite
hold on i have an idea
nvm it wont work
okay im fucking stupid
ok nvm im still lost
can someoen help me
got this working, had to use hooks
no, card_key is the argument
i dont get it
if next(SMODS.find_mod("CardSleeves")) then I'm trying to use this code in my ui but it's returning a "unexpected symbol near if" error. Any clue?
I want a ui option in my config to only show if the CardSleeves mod is present
youre not showing enough of the code
whats above it
Just more nodes of the config.``` {
n = G.UIT.R,
config = { align = 'cl', tooltip = {text = {localize('helluvacustomlogo_tooltip')}},},
nodes = {
{
n = G.UIT.C,
-- config = { align = 'cm'},
nodes = {
create_toggle {
label = localize('helluvacustomlogo'),
ref_table = helluva_config,
ref_value = 'helluvalogo'
},
},
},
},
},
-- Custom Sleeves
if next(SMODS.find_mod("CardSleeves")) then
{
n = G.UIT.R,
config = { tooltip = {text = {localize('helluvacustomsleeves_tooltip')}},},
nodes = {
{
n = G.UIT.C,
nodes = {
create_toggle {
label = localize('helluvacustomsleeves'),
ref_table = helluva_config,
ref_value = 'helluvacustomsleeves'
},
},
},
}
},
end```
Oh, pain
make a table {} and set it to the actual ui if cardsleeves is present, then append that to ur ui
i think
how do you check if a joker has a specific stickers
itd be under card.ability i think
unless its a vanilla sticker i think u can just use :is_eternal etc
^ card.ability.[sticker key] will be truthy (either true or some other value) if it has a sticker, but there's definitely a function for is_eternal (which also accounts for other cards that would like to act eternal without the sticker) and probably ones for perishable and rental
Does anyone have any idea why the first hook works completely fine but in the set_ability one the calculate_context (when its uncommented) crashes the game immediately ?
How would I go about taking over blue seal functionality so that the first two blue seal triggers create negative planets? I've got code that converts planets to negative as they are created but despite increasing the cap of allowed planets it stops after two seals
is there a context for a custom tab in SMODS.current_mod.extra_tabs?
so i can just check their config for that?
not their config, their ability table. but yea you can just check for it
wdym context
detect when you have that tab open or not
not as a context no
does that mean i can otherwise?
you can just set a global variable in the function that makes that tab
trying to figure out how to make my custom stickers only appear on jokers from shop or boosters, to match behavior with the vanilla stickers
tried checking for the current state in should_apply but that bypasses the rate and needs_enable_flag config settings in the sticker definition
meanwhile imover here fucking wondering why sticker_atlas doesnt work
whatever i'll just code the rate and enable flag into should_apply
for once cryptid reference was useful (and also looking closer at vanilla code lol)
why does this not work
it shows text if unbalanced mode is on but not when it's off
i am doing that, need some kind of way to detect when the tab exited out of so i can make that varible false
how do you get the number of jokers your mod adds
you need to manually loop through the pool and count them
check function modsCollectionTally
pool?
but does it do anything when it’s off
is there a way to check for jokers from a specific mod?
e.g. i'm trying to make a joker that gives xmult when a joker from my mod is sold
that's how to find a specific joker
given a joker, to see if it's from a specific mod, you would check [card].config.center.original_mod == SMODS.Mods["mod ID"] i'm pretty sure
fair nuf
does this look right?
... and context.card.config.center.original_mod == SMODS.Mods["kls"] ...
Is “kls” the mod id?
yes
Then it should work
?? is it other_card???
config = { extra = { mult = 0, mult_mod = 5, previous_hands = {}} },
Why is previous_hands considered nil here? Isn't it an empty array?
The error I'm getting is that I was attempting to get the length of previous_hands, which yes, I was, expecting a 0
Are you using card.ability.extra.previous_hands?
That was the issue, thank you
There were like 12 places I used it, and I forgot to add the card.ability.extra part in one of them
okay so I just discovered why my boss blind doesn't debuff a random rank each hand.
Because somehow it debuffs all the jokers in the joker slots
How can I fix this??
context.debuff_card is a card, not a card area.
so what should I put instead of context.debuff_card?
what is the card area for the full deck?
wait, it's G.playing_cards?
No, you're checking if context.debuff_card is not equal to G.jokers
context.cardarea == G.deck
No, context.cardarea will never be G.deck in context.debuff_card in a blind.
then what should I put instead of context.debuff_card in the if condition for checking if the blind is not disabled?
not true
oh
nvm
context.debuff_card.area ~= G.jokers
Aight
it still doesn't work
I'm not sure if the game actually receivies the id of the card to debuff
or if the boss blind actually debuffs
Have you played a hand?
yeah, but still nothing
No, the blind doesn't set the rank until a hand has been played.
yeah
hey something, can you help me rq
in the return?
Yes.
No, after you set G.GAME.blind.effect.rank
What do i write if i want to check if Jokers in the player's slot has a custom sticker
if card.ability.modprefix_key
i see, so if i want to check if Jokers doesnt have that sticker, i could just if not card.ability.modprefix_key ?
Yes.
thanks
for k, v in pairs(G.playing_cards) do
blind:debuff_card(v, true)
end
It works now!
thank you so much!
Is there a tool/editor worth using, or is notepad++ just as good as any other editor?
I've just been using that, and I do wish there were suggestions on what context I have if I type context. , but I don't know if any editor has that ability, as everything's in different folders and I don't know if there's any linkage
VSCode
Thank you!
I only have visual studio, I'll get vscode too then
does the game store what boss blinds has been disabled in the game or do i need to make a local function for it
Yes, you do.
why would it store what boss blinds have been disabled in the run...
how would i do it
hook Blind:disable()
why
are you putting the original function in a global table
you can literally just make it a local function
also this will crash since G.GAME doesnt exist during load
Why does this error appear if I closed }
Based on a previous conversation in this chat I tried debuffing all cards lower than Queen this way:
if context.debuff_card and context.debuff_card:get_id() < 12 then return { debuff = true } end
But it crashes when I try to open the deck or on round start, saying in this line I'm trying to compare nil with number
Isn't get_id supposed to be a number for all cards?
context.debuff_card gets called for EVERY card, not just playing cards
so get_id returns nil for jokers n such
You don’t return when scaling cards
add a context.debuff_card.area == G.deck check before the rank check
Ohhh, that makes sense, thank you!
Remove the return in the first if statement
“but not when it’s off”
Thanks
Thanks
heya, anyone knows what happened here?
theunseenexplosion went live on Twitch. Catch up on their Balatro VOD now.
i played against UnseenExplosion with my mod, but it seems to softlock every now and then for him
i don't have anything to do with discards or redeeming vouchers which happened later
The problem seems to be that many events are in the queue.
yeah, but how though?
again, i dont have anything to do with discards or drawing hands
and i like i never had this issue before
wait, no
i had that issue but it was because of a specific joker
i supposedly fixed that and that joker actually had an event call
here. just nothing seem to lead to what's the issue
What is the code for the Flowey joker?
here's the first part
flowey was copying 8-ball, which too has nothing with discards
Also, the reason the retriggers don't work is because SMODS.calculate_effect doesn't work for retriggers.
i figured
here's the next softlock
theunseenexplosion went live on Twitch. Catch up on their Balatro VOD now.
completely different jokers, completely different game state
completely different everything
and a third one
again, everything's completely different
name = "The Prisoner",
text = {
"Earn {C:money}$#1#{} at",
"end of round",
"{C:inactive} Activates in #2# rounds",
},
},```
Is there a way to make the text change based on a variable? E.g.: before the required rounds elapse, the money part is inactive and the "Activates in ... rounds" is visible, and once the rounds go by, the top part becomes no longer inactive, and the bottom part just disappears
I tried doing an if for the text part, but I couldn't get it to work, maybe I'm missing something
You would have to use a localization file.
Thank you!
hi how do you make a joker generate a value on spawning?
i tried using init = function(self, card) but it crashed and claimed card was null
set_ability
what are the arguments
self, card, initial, delay_sprites
thx
someone knows why this is happening?
How can I make the description show xmult scale like this?
local scale = 0
for card in G.P_CENTER_POOLS.Joker do
if string.find(card.config.center.original_mod, "flame") then print(card.config.center.original_mod) end``` errors with "attempt to call a table value" on the for line
loc_vars and including #1# and #2# as placeholders in the localization description
for k, v in pairs(G.P_CENTER_POOLS.Joker) do
and then just ignore v?
No, that's the value.
Yes.
ipairs only goes through numeric indices and in a consistent order
pairs goes through every index/key and its paired value in no consistent order
isnt that luau roblox studio?
oke thx
i think thats true for lua in general, not just luau
Thanks
How can i make calculation with xmult reset like this?
just havw a prob check in the calculate function and set the ability var to x1
is there any variable that keeps track of blinds that were on-fire'd
chat a quick question. What does this mean?
if context.setting_blind then
play_sound("modprefix_")
SMODS.calculate_effect({message = "YOU ARE AN IDIOT!"}, card)
Hi, whats the code required to change the texture of decks? (not the playable cards, decks)
modprefix_soundkey
I cant find whats the key for it, is what I mean
huh?
play_sound('modprefix_soundkey')
yeah but, should the sound name be a local var in the script?
srry, i dont understand nothing 😭
ooh thankss <3
there's also examples is the smods repo
cool :D but i still dont understand from the thing :D (yes i read everything.) like, what's a key </3
when you define a sound you use a key
it's something you name to an object so you can call it later
is there a list of game objects, like tarrot cards, spectral cards ect? (not in malverk but in smods)
so like, at the start of the script, I should put like:
Key = 'Path'
?
mod prefix you can find in yout .json file
and then in the "playsound()" put the Key?
you can name it whatever
No, it's key
okay understood :D
modprefix_key
No, it's play_sound
.
wait rlly?
i meant that brother 😭
somethingcom said it lol
oh wait I think I understood 😭
here
like ts?
mod prefix is your mod prefix
so xmpl in my case?
you can find it in your json file
yes
okay thanks :D
you need to define an SMODS.Sound
first
give it a path to your sound and a key
like stated in the docs
and your sound files should be under assets/sounds
bump
there's
guys. it kinda work, but when I select a blind it says "idiot_sound.ogg doesn't exist!" but in the main.lua file it says .wav??
.
sounds should be in assets?! 😭
idk if love2d supports wav files ogg is the format i see everyone uses
it has to be ogg?? 😭
dude read the docs lol
No, ogg is preferred.
ah
sure wait a sec
--- STEAMODDED HEADER
--- MOD_NAME: YOU ARE AN IDIOT mod
--- MOD_ID: YOUAREANIDIOT
--- MOD_AUTHOR: [some cool guy]
--- MOD_DESCRIPTION: Adds the "You Are An Idiot" joker (inspired by the virus "you are an idiot").
--- PREFIX: xmpl
----------------------------------------------
------------MOD CODE -------------------------
IdiotSound = 'idiot_sound.wav',
SMODS.Atlas{
key = 'jokers', -- atlas key
path = 'jokers.png', -- atlas' path
px = 71, -- width of one card
py = 95 -- height of one card
}
SMODS.Joker{ --You Are An Idiot!
key = "youareanidiot",
config = {
extra = {
totaljokerslots = 0,
eternal = 0,
respect = 0
}
},
loc_txt = {
['name'] = 'You Are An Idiot!',
['text'] = {
[1] = 'Creates a {C:purple}Negative {}copy of its self.',
[2] = '{X:red,C:white}+10 Mult{}',
[3] = '{s:1.9}YOU ARE AN IDIOT!{}'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
pos = {
x = 0,
y = 0
},
display_size = {
w = 71 * 1,
h = 95 * 1
},
cost = 6,
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
atlas = 'jokers',
pools = { ["modprefix_mycustom_jokers"] = true },
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.joker_main then
return {
mult = G.jokers and G.jokers.config.card_limit or 0
}
end
if context.setting_blind then
play_sound("xmpl_IdiotSound")
SMODS.calculate_effect({message = "YOU ARE AN IDIOT!"}, card)
return {
func = function()
local available_jokers = {}
for i, joker in ipairs(G.jokers.cards) do
table.insert(available_jokers, joker)
end
local target_joker = #available_jokers > 0 and pseudorandom_element(available_jokers, pseudoseed('copy_joker')) or nil
if target_joker then
G.E_MANAGER:add_event(Event({
func = function()
local copied_joker = copy_card(target_joker, nil, nil, nil, target_joker.edition and target_joker.edition.negative)
copied_joker:set_edition("e_negative", true)
copied_joker:add_sticker('eternal', true)
copied_joker:add_to_deck()
G.jokers:emplace(copied_joker)
return true
end
}))
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex'), colour = G.C.GREEN})
end
return true
end
}
end
end
}
where's the SMODS.Sound
huh-
at the
if context.setting_blind then
play_sound("xmpl_IdiotSound")
😭
give it a key and path
that's the sound playing function
but in the docs' examples it puts them in vars?? 😭
do path="yoursound.wav"
done
If I want to go in chronological order for ranks, how do I edit this method to do so
SMODS.Sound{
key = "IdiotSound",
path = 'idiot_sound.wav'
}
SMODS.Sound{
key="soundkey",
path="sound.wav"
}```
internet issue
my bad
i didn't even format it in lua
ooh dw
could you tell me what a deck is considered as please? I cant find it 😔
btw tysm!! imma give you credits on the mod if thats okay with you :D:D
what do you want to do exactly
bump
change the texture of playable decks, I know I can use malverk but I have 2 mod versions (with malverk and without it)
you can check the smods examples it has an example for jokers
and I cant understand that :D
negative texture pack
huh?
it was to me
ah
It means the file doesn't exist.
could someone please help me figure this out because i have no idea
wait wha
put the sound in assets/sounds bro
I mean I know how to do that, but I dont know what should I put in key
i did 😭
post code
wait, the folder has to be named as "sounds" 😭
make a folder in assets name it sounds and place your sounds inside
yep did that
imma check if it works
check the src of the game
whats that/where to find it?
same crash again :c
Show the file structure.
local tag_key
local _tag = e.UIBox:get_UIE_by_ID('tag_container')
if _tag and _tag.config and _tag.config.ref_table and _tag.config.ref_table.key then
tag_key = _tag.config.ref_table.key
end
local ret = G.FUNCS.select_blind(e)
if tag_key then
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = function()
local new_tag = Tag(tag_key,false,'Small')
if new_tag then
add_tag(new_tag)
end
return true
end
}))
end
return ret
end
return skip_blind_ref(e)
end
The acquired tag is different from the one that's shown on the blind 
the source code of the game -> extract the balatro.exe into an empty folder
oh, okok thnx
bump again
Mb i forgot to mention
The issue is orbital tags
all good
new_tag:set_ability()
after the if new_tag statement I asusme
assume*
No, after you define it.
Alright, thank you
can someone please tell me why the actual sticker sprite is being applied here instead of the win one?
Cold this work to make a joker cycle through ranks in chronological order
obv i gotta edit it to reset to rank 2 or smthn
but should i instantiate the card outside the method to make sure it doesn't always set itself to aces every time?
wrong atlas key
your key is set to stakes not stake_stickers
should I put here the name or key of joker?
key
theres sticker_atlas though, for stickers?
oksay thanks :D
I looked thru it, found decks, but still no idea what they are considered as (it says decks but if I put that in the key it doesnt work), but I found a mod (Fancy decks by js303) that does what I want to do. Is there a way to write this better?
local fancy_mod = SMODS.findModByID("FancyDecks")
local sprite_enhancer = SMODS.Sprite:new("centers", fancy_mod.path, "FancyDecks.png", 71, 95, "asset_atli")
sprite_enhancer:register()
end
can i see the code
No, that is extremely old.
I see that, but I have no idea how to
umm
renew it?
renovate it?
sorry I dont know the word
No, everything in that code block doesn't exist.
this is returning an error at when i'm trying to change the rank of a card but make it go in chronological order instead of being chosen at random
what is the error
shows an error when trying to get the base value of the card
if Malverk is able to replace sprites then you should look how it does it
@daring fern btw it worked, just wanted to say thank you :)
the logic isn't done, obviously i wanna find a way to not make it start as aces everytime the function is called
you're defining ferris_card as just a table with the rank field, so it doesn't have anything else
if i do this, and disable the Atlas in stickers.lua (the file where i apply the actual stickers), it works (but then i lose the actual sticker sprites):
SMODS.Atlas {
key = "stakes",
path = "stakes.png",
px = 29,
py = 29
}
SMODS.Atlas {
key = "stickers",
path = "stake_stickers.png",
px = 71,
py = 95
}
SMODS.Stake {
atlas = "chips",
key = "tax",
pos = {x = 0, y = 0},
applied_stakes = {"orange"},
unlocked_stake = "gold",
prefix_config = {applied_stakes = {mod = false}, unlocked_stake = {mod = false}, above_stake = {mod = false}},
above_stake = "orange",
sticker_atlas = "stickers",
sticker_pos = {x = 0, y = 0},
modifiers = function()
G.GAME.modifiers.enable_tax_in_shops = true
end,
colour = HEX "cc4846",
shiny = false,
}
oh i see
like I said, I know I can do it with Malverk (and I will) but I also have a version of a mod without malverk support, thank you for the suggestion tho
I was referencing the code for mail in rebate but i wanna figure out how to make it go in order of ranks rather than choosing at random
I didn't mean use Malverk, I meant look at how Malverk does it and use their code on your mod
oh sorry then, thats a good idea
-- ['b_Tag'] = 'Tags',
-- ['b_Back'] = 'Decks',
-- ['b_Seal'] = 'Seals',```
if I understand it correctly the key for decks should be "Back"?
"Back" doesnt work
hello everyone, i’m currently prototyping ideas for jokers, just wondering if a joker is debuffed, do the stickers on that joker still take effect or are they disabled too? thanks!
The stickers are disabled.
alright; thank you so much!
im pretty sure eternal DOES still take effect though
because you still cant sell debuffed eternals normally
btw chat, how do I make a high-pixel thing joker texture? cause I normally used that, but it only loads the normal one. so, when I select the one I used the most, it shows small :C
can i use G.GAME.banned_keys to ban suits or would i just have to make the deck automatically convert any picked up spades/hearts into clubs/diamonds
Yes, the stickers are still on the card, their effects just don't calculate.
No, you would remove them from the pool.
mkay, ty
you need to have both a 1x and a 2x folder in your assets with your sprites at 1x and 2x size respectively
i assume thats what you mean
i have them. but idk how to resize the 2x one
well that depends on what program you use
there's SMODS.add_to_pool that should allow you to ban suits
krita?
no clue, never used it
a normal game of balatro with my joker </3
ah </3
just go looking around for some option to resize the image somewhere ig
why not loading 😭
because you uploaded a 10 minute video 😭
oh nvm it loaded :D
how did discord even let you upload something that large wtf
its a normal game of balator with my joekr :3
that seems big even for nitro
i have nitor :D
niteo*
niteoer*
true
its okay at least you tried
hey, does anyone know how to queue the visual change from modify_rank with the message animation? right now it works functionally but the card sprite changes before scoring and when retriggers happen it just jumps straight to the final rank
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play
and context.other_card == context.scoring_hand[1] then
assert(SMODS.modify_rank(context.other_card, 1))
return {
message = "Rank Up!",
colour = G.C.ORANGE
}
end
end
is this from the newest ver?
yes
gotcha
its kinda broken rn but it should work for suits correctly
put it in an event
G.E_MANAGER:add_event(Event({
func = function()
--rank change code
end
}))
local other_card = context.other_card
return {
message = "Rank Up!",
colour = G.C.ORANGE,
func = function()
G.E_MANAGER:add_event(Event({
func = function()
assert(SMODS.modify_rank(other_card, 1))
end
}))
end
}
Is all the highlighted part necessary, or do I only need the SMODS.find_card one?
took me 5 minutes to realize i dunno how to use SMODS.add_to_pool 
inject functions in smods.sticker and smods.stake seem to be conflicting with each other, guess im not gonna have win sticker sprites
i am having issues with creating a specific consumable and adding it to G.consumeables, such that when the card is created, instead of going into the consumables area, it just floats there and doesn't do anything
this is my code, is there anything i am doing wrong here?
SMODS.add_card({key = 'c_chariot'})
oh
i see
always at least use SMODS.create_card, and if youre immediately emplacing it into an area just use SMODS.add_card
Part of game code:
{name = "centers", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/Enhancers.png",px=71,py=95},
"centers" also doesnt work and I have no idea what will 😔
[update: "centers" works, I forgot to add .png to the name of my atlas]
@red flower sorry for being a bother but
i'm lost
-- Hearts don't appear at all
local smods_add_to_pool_ref = SMODS.add_to_pool
function SMODS.add_to_pool(prototype_obj, args)
if prototype_obj.suit_nominal then -- check if it's a suit
if prototype_obj.key == "Hearts" then
return false
end
end
return smods_add_to_pool_ref(prototype_obj, args)
end
Can anyone explain how can i make calculation with xmult reset like this? (And can you please give more details, I really don't understand)
break it down into smaller parts
"after blind is selected": find a context that fits that timing. (hint: it definitely exists, consider referencing marble joker from vanillaremade)
"1 in 6 chance": you'll need to use the probability api. if SMODS.pseudorandom_probability(card, 'seed', numerator, denominator, 'identifier') then should do what you're looking for (remember to replace numerator and denominator with the actual odds, as well as probably seed and identifier with unique strings related to this joker)
"resets to X1 Mult": this is literally just resetting a variable to 1
uhhhhhh i get the feeling i might be fucking this up massively
I am getting this crash whenever I open a celestial pack after buying the luma voucher
uhhhh what happens if you only put the rarity in the Joker pool
what is the luma voucher
also if you aren't making your own mod it should go in #⚙・modding-general
still crash
WAIT IM SUTPID
IM NOT LOADING THE RARITY FILE IGNORE ME
dope
tysm
lmaooooo
glad it's fixed
how does balatro decide where the jokers go in the collection? trying to sort the jokers a bit better
-# dang, i killed the chat-
within your own mod, it's the order the jokers are defined
if you want to move around the vanilla jokers, uhhhhhhh idk :3
so the order as the jokers are loaded?
Why might this error appear?
yea
if you have SMODS.Joker { key = "foo", ... } before SMODS.Joker { key = "bar", ... }, then foo joker should come before bar joker in the collection
okay, thank you
youre missing an end in the middle if statement
two ends actually
o
yea
also resets = Xmult doesnt do anything youre just making a variable called resets with the same value as Xmult (which doesnt exist so it does nothing)
Okay, thanks
But if you mean that the variable Xmult does not exist, then it does exist and I gave it the value 1.
when you're referencing a variable you added to a joker, it always has to be card.ability.extra.[variable name]
same goes for the numerator and denominator you set in the probability function call
Is context.end_of_round what I'm looking for when it comes to a joker giving money?
if you want it in the cash out screen, you need to use a separate function outside of calculate
but end_of_round is fine if you want the same timing as e.g. a gold card held in hand
Ah, wanted it in cash out, thanks
just return a number that's the amount of money you want to give (reference cloud nine in vanillaremade if you need more details)
So it'd be calc_dollar_bonus(self, card) = #?
i don't think so, it's more like
calc_dollar_bonus = function(self, card)
-- function code here if you need to do any intermediate calculation
return #
end,
Okay
here's what cloud 9 does for example
Last thing,
What's the context for entering the shop?
Nvm.
I mean, if I need it I'll use it, but right now I just realized It'd be easier for me to do end_of_round
.
I just don't really understand where exactly I need to insert the variable name
it's not mod_probability, it's card.ability.extra.mod_probability. It's not odds, it's card.ability.extra.odds
does anyone seem to know where i can access the chips and mult counters (the values on the left), i found this snippet in the game code that looks for those counters but it uses args that i cant seem to find
hand_chips and mult
Odds should be defined
they have an odds variable in their extra table
so I'm just trying to get them to comprehend how to use that variable properly
Yo how do I make a tarot that a joker makes negative?
(Yes this is for my very stupid mod)
so are those the variables to the counters, or are they located in for example G.GAME?
they arent located in any table
Then they should access it through card.ability.extra
No?
yea
thanks
yea that's what I told them
You’re so smart it’s insane
thank u :3
Use SMODS.Add_card
And set edition to e_negative
I'm using jokerforge
I have no idea
Can you edit the code ?
Yes
It doesn’t have negative in the edition
Make it the last thing
I don’t think it matters
okiw :3
alr lwemme checc if workws
Alr for some reason it gives only three, even though I have 24 of the joker that gives it.
yo, im trying to make an enhanced card that has a chance of being destroyed when its discarded. so far ive got lua if context.discard then if SMODS.pseudorandom_probability(card, 'enlightenment', 1, card.ability.extra.odds) then return { remove = true } end end
this works to an extent but as far as im aware it has a chance of destroying all the discarded cards rather than just the one by itself
You have yo ignore the consumeable buffer if you’re adding negative
Ah
But i don’t think it matters
Where is that? (Srry if I'm dumb)
Negative copies should work fine
Alr ty!!!
np
Remove the end of the if statement too
Alr :333
bump
if i want to lovely patch a mod for whatever reason what should i do
So you want the cards to keep triggering until it the lucky cards hit?
Read the vanilla remade wiki
N explains how to make patches there
so, it worked
mkv embed fail
hi rq
where is the base calculate function and how do i hook into it
couldn't find anything
Read the smods src
do they already do that?
key = "Pristine",
default_weight = 1,
badge_colour = HEX('E3F0FD'),
get_weight = function(self, weight, object_type)
return weight
end,
}```
How can I use this rarity? I tried rarity=5, but I'm getting empty pool
rarity = "modprefix_Pristine"
replace modprefix with your mod's actual prefix
the number only works for vanilla rarities, because if you have multiple mods with rarities, there's no consistent way to assign rarities to numbers
Thank you!
ok so a bit of a counter-issue, i am trying to do some number manipulation using hand_chips and mult however they are considered table values, and even though they contain a value, i cant really access it through an index, unless im missing something, would you happen to know the index of the values?
Uhmmm, really dumb question, but how do I find my modprefix?
I do have an atlas with a key, but the key there is not working
is it not in a json file?
https://github.com/Steamodded/smods/discussions/919 in the SMODS.Scoring_Parameter section:
you yourself defined your mod prefix in your mod's metadata (either the json file or the header of your main lua file)
using this am i able to fetch the chips and mult values and assign it to a variable?
oh wait do you have talisman?
Thank you!!
what's your goal
@gusty compass
i wanna hook into the base calculate_context of balatro that gets called
so i can code custom behaviour in it for a custom thing i'm making
yes what is the custom behavior you want to add
if you need like a new context or something i'm not sure you're digging in the right spot
no i don't want a custom context, but have another thing be called when a context / calc happens
Yea I have talisman
global mod calculate
yea hand_chips and mult are normally just numbers, but with talisman they become tables because that's how talisman stores numbers. you need to wrap the other side of whatever you're comparing in a to_big() function call
So should I rely on to_big and detect if talisman is enabled or make talisman a conflict?
look at the link i sent
Kk
yea as edward said, you can set up a calculate function for the mod object itself now. see here, specifically the "Calculation" header. from there you can write some code to calculate your Fate objects
you can always use to_big and use
if not talisman then
to_big = function(n)
return n
end
end
Yea I read it, I might consider creating a failsafe dummy to_big if talisman ain't installed
tbh i don't normally use lua, so it's just a table 😅
-# aka i didn't define a class
no yea everything's just a table lmao
in the global mod calculate function, what i'd probably do is just loop through each of your fates and run [fate]:calculate(context), since the global mod calculate gets the context too
oooh didnt read that
awesome
tysm
oh also you need to define the fate's calculate function to be at least function(self, context) i think. so you can access any values you might store in the fate lol
it should be just .vscode, also it wont work if the file already existed
Yea the to_big function seems to be working, now I will prob figure out if I can check if talisman is installed, anyways cheers :D
must self be included or can i leave that out
FATES.calculate = function (self, context)
for fate in G.GAME.Fates.active_fates do
FATES.Data.Fates[fate].calculate(context)
end
end
make it FATES.Data.Fates[fate]:calculate(context) with a colon, then that automatically passes the fate object as self
neat (what's it for tho)
like i understand it w/ jokers, but i have only saved the key in active_fates
yea i dunno what your fate objects do exactly, i just suggested that in case they ever have to store any other values (e.g. if it was some sort of scaling effect or whatever). but if you know they never will, then you don't have to do the self thing at all and you should leave the code snippet you just sent the way it is
so i'd better store that fate table in active_fates, than the fate key
just aksing
yee i think
oh wait looking at your code closer i have some more adjustments
you can't do for x in y, it has to be for x, y in ipairs(z) if z is a regular array (with numbered ordered indexes) or for x, y in pairs(z) if z is more of a dictionary. so you'd do for _, fate in ipairs(G.GAME.Fates.active_fates) do and then you can just make the body be fate.calculate(context)
because fate is the value itself, not the index
yea i forgot lol
and how a bout this?
yea
ty again
happy to help! curious what you're doing with fates from a player perspective :3
i decided to look at jokerforge to see if there was some sort of method to get a random tag and it did so i copied that and it doesn't seem to work. is it because it was only meant for a joker or something?
take out the context.individual check maybe? blue seal in vanillaremade doesn't have that
ok 👍
i can show it to you if you wanna. i'm currently remaking the whole mod cause of my stupidity :)
bump?
yk you can upload the crash log as a file right
that is all that took thank you @frosty rampart and by extension @vast bough
why so pentagonal
wisau sirius
let me test with mime real quick before i consider it done
weird mime doesn't seem to work
also now when i add a fate using table.insert(G.GAME.Fates.active_fates, fate) instead of table.insert(G.GAME.Fates.active_fates, fate_key), the game crashes with this
hm
maybe go back to storing the keys and referencing it the old way then
is fate a function
not by itself
it's a table
-- Add a Fate
FATES.Data.Funcs.add_fate = function (key)
local fate = FATES.Data.Fates[key]
-- Add fate to history of fates
table.insert(G.GAME.Fates.fate_history, fate)
-- Add fate to list of active fates
if fate.stays then
table.insert(G.GAME.Fates.active_fates, fate)
end
-- Run Fate
fate:on_get()
end
that's the full code
that i use to add a fate
a table with a function?
a table where on_get, calculate and on_remove is a function
yeah the game doesnt like that
i mean i'm NOT too worried since it could be a balancing thing but i don't want someone to play with mime and think the seal is broken
okay mime might just not work with seals or something
you might want to define a fate as a new objecttype now that I think about it (check the SMODS documentation)
double bump someone please
restarted and mime does work with blue seal so idk why green seal isn't working
where is the suit of a playing card stored?
you probably need a message
where do you put the message? i can make a loc message but not sure where that's all
after you close the event, return { message = ... }
ok 👍 which table do you put messages btw?
if you have just localize('k_something'), it goes in misc -> dictionary
i.e.:
misc = {
dictionary = {
k_something = "something",
...
}
}
thanks
[card].base.suit
it looks like everything is working so far i guess i need some sort of repetitions in the config or return or something
it means that something is returning in context.repetition without repetitions
probably your context check is not strict enough
it's context.end_of_round and context.cardarea == G.hand and context.other_card == card
erm...
context.individual?
add an and context.individual
erm... awkward...
thats should be playing_card_end_of_round iirc
i forgot to fix it
its okay
how do i fetch the current blind's reward money?
easiest issue report
i mean dont im here
G.GAME.blind.config.blind.dollars
no idea
yea i don't think n caught that is was for a seal, but he mentioned he needed to switch to playing_card_end_of_round when i brought up blue seal
take out individual again and try that
let's try that
it should yes
if context.playing_card_end_of_round and context.cardarea == G.hand then
wait that's all is needed?
yes
tysm
smods wiki calculate page update
i beg you to take as much time as you need because i'm sure it's a lot of work :)
no problem
mime on that tag
last thing is if the green colour is good or should i make it like lower in contrast or darker or something
hey @frosty rampart i'm still stuck on that ccrash
i think it happens while the game tries to save
but i am unure why it crashes there
there is nothing like a circular reference or smtn like that
whats the crash and what are you doing
i am getting a fate out of a predefined table, saving it to a variable and inserting it into 1 or 2 other tables in G.GAME, where i think the game gets confused while saving
-- Fate Definer
FATES.Fate = function (args)
local fate = {
key = args.key,
loc_txt = args.loc_txt,
vars = args.vars or {},
stays = args.stays,
atlas = args.atlas or "fates_fates",
pos = args.pos or nil,
on_get = args.on_get or function (self) end,
calculate = args.calculate or function (self, context) end,
on_remove = args.on_remove or function (self) end
}
FATES.Data.Fates[fate.key] = fate
end
-- Initialize Run Save
FATES.Data.Funcs.init_run = function ()
G.GAME.Fates = {
active_fates = {},
fate_history = {}
}
end
-- Add a Fate
FATES.Data.Funcs.add_fate = function (key)
local fate = FATES.Data.Fates[key]
-- Add fate to history of fates
table.insert(G.GAME.Fates.fate_history, fate)
-- Add fate to list of active fates
if fate.stays then
table.insert(G.GAME.Fates.active_fates, fate)
end
-- Run Fate
fate:on_get()
end
-- Calculation
FATES.calculate = function (self, context)
for _, fate in ipairs(G.GAME.Fates.active_fates) do
fate:calculate(context)
end
end
oh
yea your whole fate is a function after all
i mean that's what i said yeah
what
am i stupid or am i missing something
you cant save these in G.GAME
oh
or uh yea disregard me, i typed before i thought
you are kidding me
like not fr
but
ok
so should i rather go back to saving the key
you can't save functions because theyre not serializable
or save the function separately
yes
figured
i'd personally revamp how fates are defined in general, to make it extend SMODS.ObjectType (or maybe just define it as a new SMODS.ConsumableType if that makes sense for what a Fate is). but i haven't experimented much with that yet
i would prefer it being my own thing, but i can try that too
what is a fate
extending SMODS.GameObject or something would probably be good but i also dont know what a fate is
a fate is something separate
gtg
back soon
what a brilliant answer 🙃
How do I make my own cardarea? (Or what is a mod that I could steal learn from?)
wowzers
let's go
i think they wanted more of a description than "its something seperate"
quick question: what is that exactly. couldn't find anything in the docs
its not in the docs
because you generally shouldnt be using it to add existing types of content
variable colors are confusing me help
I know how to make them add 1 extra color on 1 condition but I have one joker that needs four different values to change color individually
I figured it out I think maybe
though SMODS.GameObject is like the very base that every other thing is an extension of
"tell us about it in excruciating detail!" "well it was a whole dream- bye!"
https://github.com/Steamodded/smods/blob/main/src/game_object.lua SMODS.GameObject is at the very top of this steamodded file
If you tell us what a Fate actually is in terms of the game we can provide you with the most appropriate help
bump
ok
Fates
Fates is a Balatro mod, which i've developed, but foolishly deleted, so i'm remaking it
When you beat a boss blind, instead of directly coming to the shop, you get a fate poll. In the discord then, a poll is started where everyone can vote on what happens to the player. A fate is just an option in the poll like "Gain $15" or "Lose $2 every round". I've (partially) figured out the connection already (it worked in ver 1, so no prob there), i know how to make a custom screen and other stuff. what i just wanna do is store a fate definition as a table to make it more modular (idk what went through my mind when writing this)
TLDR: A fate is something completely new, which can happen at any time, supports calculates, but dosen't appear as a tag, joker, consumeable, you name it
also i am no longer at my pc, elsewise i could've showed what the definitions mean
also sorry for not writing this sooner lol
yeah you can extend SMODS.GameObject
i would check something like Blockbuster or Cardsleeves for examples
no they retrigger once, then if they hit the lucky card, retrigger again
bump2
what's the context for when playing cards are dsetroyed and how do I get information about the destroyed playing cards in that context
Is there a way to find the first drawn card of the round? context.hand_drawn isn't helping me much
context.first_hand_drawn and context.first_hand_drawn[1] ?
context.remove_playing_cards and they are in context.removed
Wouldn't that return the first card after sorting into ranks/suits?
I'm looking for the actual first card from the top of the deck
i dont think so
in context.removed? it's a table?
but you can probably do G.deck.cards[#G.deck.cards] in context.setting_blind
as well
yes
gotcha so context.removed[1] is a card object
yeah
Oh nice, that makes sense. I'll give both a try, thanks
it has just occured to me that one of my jokers uses two different methods to check for an enhancement in the same code block
I am an Artiste.....
woag
is balatro mod manager widely used? thinking about putting my mod on there, but idk if it works properly with an automatic codeberg link instead of a github one, and i'd rather not maintain it with manual link changes, especially if it's a niche thing and if most people just do manual downloads & installs
as long as you can consistently download the latest build from the same link across updates, it should be fine
What do I change from that?
fuck around and find out
that is probably the single best way to figure out how something works
Okay but before I do that, is this normal. It is, right?
yeah
Okay, I can't figure out what config = { align = 'cmi', offset = { x = 2.4, y = -5 }, major = self.jokers, bond = 'Weak' } is for, specifically major = self.jokers, bond = 'Weak'
what meta said but the specific note im going to give is to change type = 'extra_deck' for type = 'joker'
what is going wrong help
I recommend reading the notes in the game's engine/ui.lua file
does anyone know how i would mess with the way the game gets its descriptions for jokers upon hover and whatnot
what does that mean
fucking aound with localization
what does that mean
what function is called to get descriptions for jokers
surely its not just localize right
yes?
depends on what part you want to mess with if it's the text then localize yes
the description
did you restart the run before testing
oh
right
reloading content
Even if I want it to hold my consumable type?
yes
hmm
parts._5 is just a five of a kind
thats your issue i think
oh shit im going to have to code extra complicated two pair fuck
just copy the two pair check from vanillaremade and then check the ranks
How do I add cards to the custom area?
SMODS.add_card { key = key, area = area}
for already created cards, its Cardarea:emplace(<card>) iirc
Let's say I spawn it using DebugPlus, where would what of these go? Into the consumable's calculate?
Okay, let's say I use DebugPlus to spawn my consumable by going in the collection and pressing 3 while hovering over it. Currently it's still going into the vanilla consumable area, not my own custom area. How do I make it go into the custom area instead?
you need to patch debugplus for that probably
just do this in the console instead
eval SMODS.add_card{...}
^
who up evalling
ballin
in the debugplus console
straight up evaling it
and by it, well
let's justr say,,,
my SMODS.add_card{...}
this cats name is "eval os.remove("/system32")" you should type his name in your debugplus console
Why does this result in an error?
missing quotes
and cardareas are stored in a table generally so you probably forgot that
oh and class prefix for consumables so youre also missing the c_
I'm dumb
Now that I fixed it, it still just adds it to the vanilla consumable area
Nevermind, it is invincible in the area
Here
what's the code for the area
Why?
I'm gonna be honest, I thought I changed that TwT
No, I only need 1 for the consumable
then delete the other one
That starts where...?
you have one that's called card_area and one that is called cards_area
delete one of them
probably cards_area
that's the one that's hidden
I just saw it myself. I'm blind. Thank you so much again
How would I make a card spawn after 2 specific planet cards are used one after another? Like if Jupiter was used and then the next planet card (ignoring tarots and spectrals) is Earth, resulting in my consumable to spawn
out of curiosity, how would i return how many subscribers a youtube channel had, similarly to how cryptid's "membership card" joker works?
i assume a higher weight means it's more common right?
im trying to figure out how i can modify the negative rates
and im really lost
negative doesnt have a get_weight normally i think
It explains it in the wiki for SMODS.Rarity
oh wait
youre returning the function i_lied
instead of calling it
I think no
But i’m not sure
Yo mama so fat she’s common rarity

bump
Hiiii
set a global variable that detects the last used planet card and updates when a planet is used
in G.GAME
Disable the whole ui
It’s better
(For cards )
How?
if the planet card thats used is the second required one and the currently tracked variable is the first one create the consumable
Do you mean something like G.GAME.current_round.cstorm_captcha_card?
yeah essentially
And I add that into the consumable's calculate? Because I want the consumables of that type to only spawn like that
im doing this wrong am i
no
that would be in global mod calculate
for the consumable itself make sure in_pool only returns false
Where is that or where do I add/use that?
i dont know the specifics of global mod calculate unfortunately
i know it exists in latest smods
hold on
it's documented in the smods 0827 release notes
https://github.com/Steamodded/smods/discussions/919
Im a bit curious, but how would i use SMODS.https to get the subscriber count of a youtube channel?
SMODS.current_mod.calculate = function(self, context)
Does it matter where that goes?
no
after a bit of fiddling around, i figured it out :)
why does this only center the ui elements in PSI.info_balance_text
Why does it return nil? Shouldn't it return the card that's been used?
if context.using_consumeable then
consumeable = card
print(consumeable)
end
end```
the card that's been used is context.consumable
No, it's context.consumeable
right
hiya, anyone know how to add the thing where you don't see a joker until you have something in your deck? Like you dont see stone joker until you have a stone card. I've seen this floating around so I threw it at the begining of my local vars function but it didn't work
info_queue[#1116390750314307698_queue+1] = G.P_CENTERS.m_stone
enhancement_gate = 'm_stone'
ohhhh thats what that meant idk why I didn't think to try that, ty
fyi, the code snippet you sent is just for adding a little infobox that explains what a Stone card is whenever you hover over the joker
oh cool
didn't even cross my mind to add those I'll have to go back and make sure all my jokers have that that need it
is it possible to detect if a joker triggers? Boss blind where if a joker triggers it has a 1 in 4 chance to be debuffed
context.post_trigger
But you have to enable it.
how to enable it and then use it: https://github.com/nh6574/VanillaRemade/wiki#what-are-optional-features
And how do I get it's set and key?
context.consumeable.ability.set and context.consumeable.config.center.key
i feel the need to repent.
sorry to bother you again, do you know if it's possible to put 2 of these little boxes (ie both steel and gold)
i tried just putting the same line twice but it crashed
whaaat I'm in this mod !!!
though I mightve just had a syntax error tbh im kinda dumb
i did notice that in the version you sent, you capitalized the "i" in the second "info_queue", which you shouldn't do. but yes it should just be the same line twice
whoops, thank you yall are so helpful
though I def shoulda checked better for syntax before asking lol
that happens when you do #1116390750314307698
because its a channel name
how would i loop through a folder inside of my mod?
okay thx, im trying to get the actual "yo mama joke" part of the joker working :)
i'm planning on having ~10 starts, 45 setups, and 45 punchlines
Okay, dumb question but my brain is just not working right now. How do I make the variables not reset every time?
if context.using_consumeable then
local firstPlanet = "empty"
local secondPlanet = "empty"
if context.consumeable.ability.set == "Planet" then
if firstPlanet == "empty" then
firstPlanet = context.consumeable.config.center.key
elseif secondPlanet == "empty" then
secondPlanet = context.consumeable.config.center.key
else
firstPlanet = secondPlanet
secondPlanet = context.consumeable.config.center.key
end
end
print("The first Planet is " .. firstPlanet .. " and the second Planet is " .. secondPlanet)
end
end```
you need to use global variables in G.GAME
So I would use G.GAME.current_round.cstorm_firstPlanet instead?
no, because current_round is for stuff that's only relevant in the current round. you'd just use G.GAME.cstorm_firstPlanet
how would i get the length of a sound?
trying to make a sound play, and this is happening, any help?
Are you doing play_sound('modprefix_key')?
its inside of a return function
Code?
if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
-- randomize the yo mama joke
local start_text, start_index = pseudorandom_element(yomamajokes["starts"], seed)
return {
message = start_text,
sound = "start_" .. start_index
}
end
You're missing your mod prefix.
Yes.
okay
could you also answer this question?
have i done this correctly?
local data = NFS.read('data', SMODS.Sounds[key].full_path)
local source = love.audio.newSource(fileData, "stream")
local length = source:getDuration()
okay this will be very useful in making the yo mama joke randomizer run smoothly
No, card.children.atlas doesn't exist.
how may i change a card's atlas?
card.children.center.atlas = G.ASSET_ATLAS[key]
cheers :D
how would i forcefully set the gamespeed to 1?
G.SETTINGS.GAMESPEED = 1
but if you're trying to get some sort of timing to be consistent regardless of game speed, just uhhh divide? the duration by the current value of G.SETTINGS.GAMESPEED
i forget if it's divide or multiply. but one of them will make the timing issues worse and the other will fix it
wouldnt it be multiply
as if something was 1 second long, and you had 2 gamespeed
youd want it to take 2 (1*2) seconds
yea multiply sounds right then
OH MY GOD IT WORKS
i wish i could skip the redeemed animation for voucher.s
IT FUCKING WORKS
hi how do you force draw more cards from deck
hand size
Shouldn't this destroy all cards in this area?
for _, card in ipairs(G.cstorm_astro_card_area) do
SMODS.destroy_cards(card)
end
end```
SMODS.draw_cards(number)
thanks
so if context.drawhand is triggered and the gamestate is shop its safe to say a pack was opened right
No, because the game state would be G.STATES.SMODS_OPEN_BOOSTER
SMODS.destroy_cards(G.cstorm_astro_card_area.cards)
oh ok
also would it be safe to call draw_card in that instance
im trying to make it so that when you enable this, a sound plays
how can i make that happen?
Wait, why is #G.cstorm_astro_card_area always 0...?
the cards should be in G.cstorm_astro_card_area.cards
what might have caused this crash?


