#💻・modding-dev
1 messages · Page 671 of 1
ok so the reason for it just being a free-floating card is that apparently even though despite i specify the area to create the card in, it just doesn't put the created card in the area. the card's area is nil following creation.
so there's something wrong with my cardarea if both add_card and create_card don't like it and forcibly emplacing it causes it to disappear entirely.
for some reason it's kind of off centered now
tried putting "cm" in the loc_vars but the result is the same
try type = 'joker' in the cardarea
cm should go in the column
it worked 
but why? i do everything joyousspring does regarding the custom objecttype
do the objects have to be force injected
ah
the area type is how it displays the cards so it doesnt have anything to do with the set
i dont even use my objectypes theyre just there because
i see
how do you score one card but have its effect text appear on another card?
message_card = other_card
how do I catch the type of consumable created. like ik if context.card_added then catch if a non-playing card is add
context.card.ability.set
oh ok
Sorry for the late response but it doesn't change anything if I put alignment = "cm" in the column
more like that ?
if context.card_added.ability.set == 'Artefact' then
try the rows too
btw i recommend just adding stuff to the config based on the ui guide lol, most of my ui work is trial an error
Hook card_eval_status_text
No, it would be context.card.ability.set
okok
I was just thinking too deep
So if context.card_added and context.card.ability.set == 'Artefact' then G.GAME.giga.artefact_create = G.GAME.giga.artefact_create + 1 end
so if card == whatever then card = x?
uhh and are you sure that function is just for the visual effects on the card
Yes, also you would need to set extra.focus to nil if it exists.
No, you should still change card in case someone else hooks that function.
oh
Is it possible to make a marquee but with cards
wdym
i mean, if the x and y vars for your sprite position takes floating point numbers, i guess you could do some janky thing with the spritesheet and just constantly loop the co-ord while calling set_sprites each time 
i think that works yeah
instead of scrolling text i want to have scrolling cards
like automatically scrolling
this works ^ with set_sprite_pos
i havent touched my mod since may 2025 and almost all of it doesnt work with newest smods edition, should i try to fix it or do i just put the fries in the bag and start it all over
there wasnt any big api change so it can probably all be fixed somewhat easily
ive tried looking into it a few months back but the random chances changes got me
i mean that should still work if you're using the old method, it just wont support other mods
but it wont crash with them
small question: if I make a repo from visual studio for my mod, and since I'm the owner of it, I can still access to it from different devices?
a github one? yes
as if there would be a case that I need to change something about my mod but I'm in another pc
if it's local then no obviously, those are on your machine only
but if it's a github one then yes?
aight, that's what I was aiming for, thx
https://docs.google.com/document/d/1lVCNsp_S2EqppyH2hI8tU7IFCVAhCXB9kjq7Cp9vKTM/edit?usp=sharing gamers i need ur thoughts
Balatrodex WilyJoker (Grass) → ZanyJoker (Grass) → TheTrio (Grass) CraftyJoker (Fire) → DrollJoker (Fire) → TheTribe (Fire) SlyJoker (Water) → JollyJoker (Water) → TheDuo (Water) CreditCard (Bug) → GoldenJoker (Bug) → Rocket (Bug/Flying) Banner (Bug) → Gratification (Bug) → MysticSummit (Bug/Rock...
why make lucky cat dragon type
ah. not doing fairy types? fairy feels like it would have made more sense
nope
smeared being normal also feels a little off and imo would be a perfect fairy candidate 
i know 😭
I wanted to publish a balatro mod repo but visual sudio code for some reason says Git:Remote: repository not found
maybe it's because I made it private?
but the repo shows up in the github website.....
....what???
I FORGOT CLOUD 9 😭
is there a way I can fix this?
Does your mod folder have a hidden .git folder in it?
it has one .git folder
how do i code mods? (without jokerforge)
why do some jokers have #1# instead of the real value
what should I do then?
Is there any way to retrigger what goes into context.final_scoring_step? Here's why I ask:
if its an enhancement from your mod then why dont you just put this in the enhancement code
It's not. It's a cross-mod guest star with Ortalab, and works off of its Sand Cards.
Here's what I got. Y prints, but not X.
if not G.GAME.blind.disabled then
if context.repetition then
print('Y')
if
context.final_scoring_step and
(context.cardarea == G.hand or context.cardarea == G.play) and
SMODS.has_enhancement(context.other_card, 'm_ortalab_sand') and
not next(SMODS.find_card('j_ortalab_sandstone'))
then
print('X')
return {
repetitions = 1
}
end
end
if context.destroying_card and context.destroying_card == context.other_card and context.other_card.ability.extra.x_mult < 1 then
return {
remove = true
}
end
end
Other than that, the code does nothing.
well yeah context.repetition only happens for main playing card scoring
which context.final_scoring_step is not
It also looks to me like context.final_scoring_step knows nothing of context.other_card.
yeah
because it isnt calculated with an other card
you could just patch into sand cards though
How, something like this?
if (G.GAME.blind.config.blind.key == 'bl_lapsems_broom') and not G.GAME.blind.disabled then
return {
repetitions = 1
}
end
Well, I mean, put something like that within the patch.
this is just the same thing except outside the blind and in every context
well no
sand cards also wont retrigger themselves outside of main playing card scoring
you should just patch the reduction and double it if the blind is active
how do i create the bare-bones folder to code my mod in
That was what I meant, do I patch in that aforementioned condition at the end of the Sand Cards' code?
<@&1133519078540185692>
<@&1133519078540185692>
no
Bam
you directly patch the line where the reduction happens
<@&1133519078540185692>
Late
late ahh
It ain't a single line.
if context.final_scoring_step and (context.cardarea == G.hand or context.cardarea == G.play) and not next(SMODS.find_card('j_ortalab_sandstone')) then
card.ability.extra.x_mult = card.ability.extra.x_mult - card.ability.extra.change
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = function()
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize('ortalab_sand_crumble'), colour = G.C.GOLD, instant = true})
play_sound('ortalab_sand', 0.8+ (0.9 + 0.2*math.random())*0.2, 0.5)
if card.ability.extra.x_mult and card.ability.extra.x_mult < 1 then
SMODS.destroy_cards(card)
end
card.particles = Particles(1, 1, 0,0, {
timer = 0.015,
scale = 0.3,
initialize = true,
lifespan = 1,
speed = 3,
padding = -1,
attach = card,
colours = {G.C.GOLD, lighten(G.C.GOLD, 0.4), lighten(G.C.GOLD, 0.2), darken(G.C.GOLD, 0.2)},
fill = true
})
card.particles.fade_alpha = 1
card.particles:fade(1, 0)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 1,
func = function()
card.particles:remove()
return true
end
}))
end
I wanted to replicate the "Crumble!" effect, and I thought that taking advantage of the repetition feature would be an easy solution.
patches can be multiple lines
and again, repetition is not for the purpose you think it is. it's specifically for retriggering cards during their normal scoring
if you want to repeat everything then just patch in the start and end of a for loop
around the code
Would it even be possible, though, to patch for another mod's files?
also unrelated but like the makes me wonder
because it requires the mod id is it even possible to patch a lovely mod
it's called running your patch on the vanilla code after the other lovely mod's patches run
ah
hm
=[lovely modulename "path"]
this is new right? i think its from 0.9 or 0.8
name
i think
oh i see
bump
idk how vscode github stuff works sadly
I tried to publish it by vscode
the private repo is now on github but for some reason the publish option in vscode still shows up
try cloning the repo from github and see if it works
if context.final_scoring_step then
for _, area in {G.play, G.hand} do
for __, card in pairs(area) do
if SMODS.has_enhancement(card, 'm_ortalab_sand') then
-- Would something like this work?
end
end
end
end
idk if it will work for what you want because i havent been following but pairs(area.cards)
I tried but nothing changed
like in the cloned repo?
doubt you're still online by now but uhhh it's not rly working
ooohhhh, that makes more sense
yeah
in vscode the publish button still shows up and when I click it it says the same thing as before
are you like properly logged in to github in vscode
also you need to return true outside the condition
or just return the config value itself
ok so outside of applying eternal, how can i make a joker unsellable? 
tyy
and in the case of a custom joker, i can just write a definition for can_sell_card? or no
no
only hook, alright
yeah, I signed in in vscode with my github account
not a bad idea tho
huh
do you want me to show the log error?
is there a way to replace the sell button on a card?
at some point i want to make a deck where you can't sell anything and you have to use what is basically a manual and targeted ceremonial dagger
i mean i guess
but you already said what it says right
you would need to hook/patch G.UIDEF.use_and_sell_buttons
does opening the shown link actually take you to the repo
yep but it's... empty
the create a new repo on the command line or push an existing repo from the command line?
latter
somethings broken then lmao
probably has to do with login stuff
maybe make it public for a bit and then private it?
I'll try publishing my mod from a different device then
I have another git account on this device so this may be the problem
tiered tarots
how do i add the steammodded tag shown in the mod menu?
at least, I think that's what you're asking
right. and do i put it in the main file or a different one
doesn't matter as long as the code is run somehow
how would i add a sprite and map it onto my jokers?
attempting to map this sprite, but my joker looks like Drunkard: ```-- Joker
SMODS.Joker {
key = "dejoker",
pos = { x = 1, y = 1 },
rarity = 1,
blueprint_compat = true,
cost = 2,
discovered = true,
config = { extra = { mult = 4 }, },
loc_txt = {
name = "Doker the Fifth",
text = {
"{C:red,s:1.1}+#1#{} Chips"
},
},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
mult = card.ability.extra.mult
}
end
end
}
SMODS.Atlas({
key = "modicon",
path = "icon.png",
px = 32,
py = 32
})
SMODS.Atlas({
key = "dejoker",
path = "dejokers.png",
px = 71,
py = 95
})```
from the link i gave you
you need to have atlas = "dejoker" in the joker definition
(also keep in mind that the position is zero-indexed, so if the atlas only has one sprite on it it needs to be x = 0, y = 0)
why dont the joker desc numbers get hardcoded?
how would you make a scaling joker if they were hardcoded
true
also its just bad practice, best to be able to just change 1 variable rather than editing a variable AND a string to change a joker's values
just wanted to say another thank you for pointing to this, i'm able to do a bunch of things that i never thought i'd be able to do in a reasonable amount of time
that's a pretty brick color
what would be a good starting place for me to look for adding ui buttons on selected cards in booster packs? i want to make it possible to keep cards from boosters instead of using them immediately
do you want to add a keep button alongside the use button or replace use for keep?
cryptid does that for code packs iirc, you can look into that
thanks!
How could I make a joker that can only be removed by selling?
replace card.ability.star_immortal with card.config.center.key == "j_modprefix_jokerkey" (where modprefix is your mod's prefix, and jokerkey is the key of the joker in question)
this goes as its own code in the main file or whatever, not inside the joker definition
this makes the joker count as eternal as long as whatever's "checking" if it's eternal isn't the sell button
@wild escarp
Cool, thanks!
why my sell button weird
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-make-a-new-card-area
check align buttons
he's doing just fine.
could i actually just add a use button to a joker, or would that still need the hook
the how to add a button to the card?
yes
good mod joker idea
Freddy fazbear
When purchased, you must play five nights at Freddy’s (if owned on steam). Each night survived gives x5 mult
(if game not owned, joker gives only x3 mult for 5 rounds, then destroys self)
api or smth
How would I change the name (and only the name, not the description) of a vanilla Balatro card using take_ownership?
You wouldn't.
Really? You can't just do something like
SMODS.Joker:take_ownership('blueprint', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
atlas = "jokers-new",
pos = { x = 0, y = 0 },
-- welcome to the land of the hypothetical (PSEUDOCODE STARTS HERE)
loc_vars = function(self, info_queue, card)
local ret = original_loc_vars
ret["key"]["name"] = localize("mod_j_blueprint_new")
return ret
end
-- thank you for visiting the land of the hypothetical (PSEUDOCODE ENDS HERE)
},
true
)```
(hypothetically)
You can just override the localization with your own localization file though
that is what I'd like to do, I just don't want to touch the original descriptions
and I'm guessing excluding a text variable will just make them blank
Yes
I mean you can use SMODS.current_mod.process_loc_text
To change locs after theyre loaded
See how steamodded uses it in game_object.lua to change the description of The Wheel
fair
Got something started using this, though for whatever reason it's not recognizing the new localizations (shows up as "ERROR" for the name)
thismod = SMODS.current_mod
local thismodid = thismod.id
function get_new_key(key)
return thismodid .. "_" .. key .. "_new"
end
SMODS.Joker:take_ownership('blueprint', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
atlas = "jokers-new",
pos = { x = 0, y = 0 },
process_loc_text = function(self)
print(G.localization.descriptions.Joker[self.key]["name"])
print(get_new_key(self.key)..": "..localize(get_new_key(self.key)))
G.localization.descriptions.Joker[self.key]["name"] = localize(get_new_key(self.key))
SMODS.Joker.process_loc_text(self)
end,
},
true
)
return {
misc = {
dictionary = {
modid_j_blueprint_new = "Orangeprint",
},
}
}```
very close actually, what you want is ret.name_key
that's not in the docs for some reason, I should change that
fair enough
i've actually got progress on my method here, the issue is it's not recognizing the new localizations for whatever reason
yeah that makes sense because you're not having them parsed. this is needlessly complicated, though iirc just passing a name and no text in a loc file won't touch the text
soul_set doesn't seem to be working for me
i have this, but it won't appear in Hanafuda packs
SMODS.Consumable {
set = "Spectral",
key = "partisan",
pos = { x = 1, y = 4 },
atlas = hanafuda_atlas,
config = { extra = { hanafudas = 2 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.hanafudas } }
end,
can_use = function(self, card)
return count_consumables() < G.consumeables.config.card_limit or card.area == G.consumeables
end,
cost = 6,
use = function(self, card, area, copier)
for i = 1, math.min(card.ability.extra.hanafudas, G.consumeables.config.card_limit - count_consumables()) do
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
if count_consumables() < G.consumeables.config.card_limit then
play_sound('timpani')
local new_card = SMODS.create_card({ set = "phanta_bright", key_append = "partisan" })
new_card:add_to_deck()
G.consumeables:emplace(new_card)
card:juice_up(0.3, 0.5)
end
return true
end
}))
end
delay(0.6)
end,
hidden = true,
soul_set = "phanta_Hanafuda",
soul_rate = 0.006,
can_repeat_soul = false
}```
How are you creating the cards in the Hanafuda packs?
so ive modified m_stone and now its info shows the chips of the rank under the stone effect. it scores as expected. there's just the extra text visually. is there something i need to do to make that not happen?
success :3
they come in four flavours
the Chaff cards are the weakest, and are similar-strength to Tarot cards
the Bright cards are the strongest, and are similar to Spectrals, or perhaps stronger in some cases
the Spectral creates two random Bright cards :3
neat
anyone know if there's a vanilla xchips feature i can tap into or do i need to make my own?
smods already provides one
base game doesn't have it
neat, can i just return xchips in a calculate_joker?
ayup!
god i hate the English language TwT i spent way to long trying to figure out why this wasn't working 😭 why is it spelled dif depending on where you live qwq
is it from the return table of loc_vars
oops
"consumeable"
ive missed the e in consumeable so many times
that's not a matter of where you live that's just a
moment
"localization"
that one i have personal beef with
at least there's no instances of "localisation"
but there's an instance of "consumable"??? /lh
how do custom quips work? (quips with custom joker sprites and text, that trigger when specific things happen in a run)
cheersies :3
Is it possible to give a bonus in the next run if you lose the previous with a specific joker or something?
store the bonus in profile, trigger it the next run before removing
why because why not
a joker that changes effect based on what day it is sounds kinda cool
lol
||you have no idea what Cold Beans has to offer||
cold beans?
basically alternative Hot Potato
The real life game or a mod i'm not aware of
lol
trying not to copy ideas that's already been done
a mod you're not aware of, rip
well, ||it's been done in Cold Beans, but in a different way dw||
as little spoilers as I could give
well, can't blame you
jokerforge really made modding a child's play
The TTV mod I worked on kinda started out as a forge mod
atleast for jokers
It's ok to to cobble together a joker for basic stuff
I've used it here and there for a base
1 making a sprite sheet manually is painful
1 pixel off throws everything off
I don't blame forge I blame too many people not wanting to put more effort into mods
forge like many other modding tools is supposed to help beginners out until they branch off into more advanced stuff
I just wish someone would make a sprite sheet tool lol
only thing I really used forge for now is just the sprite sheet since it'll make both a x2 and x1 version
i use paint
real pros use a script
I have 2 scripts, for scaling and removing anti-aliasing
i need to fix the script so it doesnt shit itself when it sees pdns
oh btw the twitch mod is up on github now if u still wanna peak at it
cool
I am trying to figure out how to do editions and really struggling
Is it possible to have non visual edition? Like not shinny or black but instead like ! or some other symbol?
yes, but not directly with the edition api since that's only equipped to make editions with shaders
you would need to use a custom SMODS.DrawStep
Ah so it always need costume editions, with shadder
You can have one without a shader
And then do sprites or whatever you want to do with a drawstep
Im trying to make a Joker display its Xmult live on the top row and this is what I've got so far. But for some reason the "Mult" text isn't appearing at all
Theres probably an easier way than all this but like idk
SMODS.localize_box:
oh
And how does it work
i dont think localize box takes ref_table
does anyone know how to add extra text to the title screen like this?
this mod just does it with a single atlas from what i can tell but i wanna make sure that's all it is to be safe
it uses it here
https://github.com/icyethics/Kino/blob/8f5cf81728a8b3ca987b71e1731de0fb304daa3b/lovely/current.toml#L966
a balatro mod for movie dorks. Contribute to icyethics/Kino development by creating an account on GitHub.
uuuhhhh
is there an easier way that doesnt need patches? .w.
you can just copy that patch and change the numbers
and kino_splash_screen for your atlas
true
Okay I tried making the first node bigger and found the problem I guess, Even tho the first node is G.UIT.R the "Mult" text gets put under the red box
And the reason why I didn't see the "Mult" text was that it was perfectly aligned with another "Mult" text on the row underneath
bro changed the first one to G.UIT.C and it worked
balatro ui code weird ¯_(ツ)_/¯
balatro doesnt understand your layout if you dont put rows in columns and the other way around
damn
so it basically didnt know where you put your rows
guess that kinda makes
does the version in a patch file's manifest matter at all?
nah not really
only for your development tracking if you choose to follow some form of versioning to form some kind of development timeline so you can more easily pinpoint when a certain problem occurred, etc.
In fact the entire manifest besides the priority doesn't matter
in anycase, the splash screen patch works, now to just figure out how to make it appear on top instead of behind
dump_lua is also obsolete
oh fun!
when i make a joker change sprite, it often changes back into the initial sprite when loading a saved run
what's the correct proper fix for this?
i've tried some jank sounding solutions that didnt work
change it in set_sprites
if the specific sprite relies on a value in card.ability somewhere, do it in an event in set_sprites, as the function runs before card.ability is populated with its values
like this?
yeah
how often is set_sprites called
when the card object is created
and i dont mean in a run, i mean when its shown on screen
so when you reload
question about that
say when this card shows up in a shop
does this triggers before the animations starts playing
and can i hijack this to run some stuff before it becomes visible in the shop
or is there a better method
wdym by animations
what's your actual goal
the fading in animation thingy when it shows up in shop
ahh not sure lol
ok so i just got an silly idea for a joker based on a ktane module called Impostor
when it shows up in shop it initially disguises itself as a vanilla joker
but the sprite is slightly incorrect
like for example it's Reserved Parking but its sprite says Reversed Parking instead
or like Hanging Chad has the J tab hanging instead of the O tab
i would probably look at how spy did that before it got removed from cryptid
oh what did spy do
basically exactly that except without any tells, and then when you bought it it revealed itself, became eternal, and gave X0.5 Mult
it was the cursed rarity lol
that should be possible with this by checking the area afaik
but yea i assume set_sprites will be sufficient for that
well i dont wanna punish the player too hard for buying it but i want to reward them for identifying it
give it a try and if it doesn't work then we can dig into vanilla code to figure out when the proper timing is
the event might be mandatory if the area is not set immediately
no yea my point is the way spy disguised itself should be a good point of reference for your goal
...I'm gonna be honest, I'm not sure what else should I add...
maybe the number of jokers?
or generally say that it has jokers and lots of enhancements?
if you guys made a vanilla-like mod what would you put in the README file for description?
how to install
paperback has a big-ass image with the mod logo and a bunch of joker sprites in the background, and a link to the balatromods wiki page
how to install?
well... it doesn't require anything special to install so... should I put the link to the repo website to find where to download it?
people are dumb, they wont know what a lovely or smods is
or that they shouldnt drop and replace the mod
i have this in mine
ooooooh now I get it
i can get rid of the unzip part next update probably
I was looking of some of the readme's from other mods like aikoyori's and MoreFluff's and noticed that both have HUGE differences
Another question: what's the mod's priority value for?
yeah people put in a readme file whatever info they think makes sense for the end user to need. for example here's menthol's https://github.com/wingedcatgirl/MintysSillyMod/blob/main/README.md
higher number = loaded later
it's not super relevant unless for some reason you need another mod's code to run first before yours, or you need your code to run before other mods
my mod doesn't have something revolutionary and super complex so.... I think it's the best if I leave it to 0
yea 0 is perfectly fine most of the time
aight
I'm somewhat of a yapper, as you can see from my readme
the main thing i can see for people who need to adjust the priority is if they're doing some weird shenanigans with like overriding SMODS.Joker or SMODS.Sticker or something and they wanna make sure other mods load with the modified stuff instead of the regular smods stuff
also cross mod content
and apis
that's.... that's a lot of stuff
oh uh, what's this "conflicts" and "provides" in the json file
conflicts are mods you know won't work with yours, so your mod won't load if they're active
provides are for cases like Amulet which is meant to replace Talisman
"conflicts": [
"Talisman (>=1.1) (<<2~)" // Same format as for dependencies, except alternatives (|) are disallowed.
], // ! No mods in the list (that fulfill version restrictions) may be installed, else this mod will not load.
"provides": [
"SomeAPIMod (1.0)"
], // ! Use this if your mod is able to stand in for a different mod and fulfill dependencies on it. This allows the usage of a different ID so both mods can coexist. If you don't specify a valid version, your mod's version is used instead.
I see...
(for now I haven't tried if my mod crashes other mods so I'm kinda nervous...)
although It shouldn't
i think its a fools errand to put every single mod that crashes in conflict
conflicts are more for issues that aren't really able to be resolved, or very high effort, rather than incidental crashes. Talisman is a very reasonable conflict, but a random other content mod that crashes due to it patching the same function as you is probably not worth tracking down. If it's an issue, it'll get reported at some point
yea conflicts are mainly for problems that can't or won't be fixed
Amature coder here, unscored cards ain't scoring, how would you fix this?
you can use context.cardarea == 'unscored'
that and context.individual
What should the both of them replace?
use if context.before and not context.blueprint and context.individual and context.cardarea == 'unscored' then idk if it was your question
I have a joker that give mult for unscored card
if context.individual and context.cardarea == 'unscored' then and this will loop through all unscored cards for you, no loops needed on your end
the unscored card will be context.other_card
yeah
Also why not context.blueprint
or her idk
idk weird stuff here
So I remove that?
how do I set up a gitignore file?
I still haven't made my mod public but I want it to have everything it needs for to be published
create file named .gitignore
then each line will be used as a file/folder name to ignore all instances of
for git
this will also not affect any files that git is already tracking
What's the difference of making a private and a public repo?
a private repo is well, private
only collaborators can view it
and yourself of course
so it's best if I should set it private for now?
I mean I want my mod to be accessible for everyone (in terms of gameplay and not coding)
well if you want everyone to see the mod then it should be public
yea people generally distribute mods by posting the github link
github or vscode has a way to auto generate
How would I reference this Gradient in-code like how I would do with G.C.MODPREFIX.COLOR? I know that I can reference it as {C:modprefix_rainbow} for descriptions, but I can't figure out how to use it in code.
SMODS.Gradients.modprefix_rainbow
alternatively you can also store the created gradient in a variable by doing whatever = SMODS.Gradient { ...
Why aren't the unscoring cards giving Mult?
because of and not context.scoring_hand
also it should be context.cardarea == "unscored" for unscoring cards
if using cardsleeves, is the current sleeve stored in G.GAME, like in G.GAME.selected_sleeve or something?
Yes.
if context.playing_card_added and SMODS.pseudorandom_probability(card, pseudoseed('fuhdekun'), card.ability.extra.odds, card.ability.extra.chances) then
local _card = context.card
SMODS.calculate_context({ playing_card_added = true, cards = { _card } })
return {
message = 'Coppied !',
colour = G.C.SECONDARY_SET.Planet
}
end
so im doing this but it doesnt work like it sepossed to copy the playing card added, I know it can copy infinitely but thats a problem for later
just calculating playing_card_added doesn't actually do anything to copy the card
adding to what meta said
tables in lua are passed by reference, this doesn't make a copy, it makes a new object that refers to the same card
use copy_card(card) to actually copy it
okok I'll try
i recommend checking DNA instead of going at it blindly tho https://github.com/nh6574/VanillaRemade/blob/f1cc39c18475a3aa866817d579caefb6a53dca40/src/jokers.lua#L1300
oh shoot I forgot about dna
i mean there are also a couple other copiers lol
ok so I have that but it create a card but its not place in deck
it is missing all the other stuff
you would use this code but with G.deck instead of G.hand if you want the deck
Is it possible to have stake stickers from one set of stakes be paired along with stake stickers from another set of stakes
i dont think it is possible with the api
The stickers wouldn't be covering eachother of course
if you mean if its possible at all then yes, you would need to change whatever drawstep draws the stickers and add some logic to check multiple
hell yeah its working now
If I change the part of the card where the sticker shows up will they be able to coexist
For the extra set I mean
Or maybe I can make certain jokers only allowed to have stickers from the one set
Well not me since I'm not the coder but you know what I mean
yeah its just a sprite overlaid on a card
yeah
theres probably one in the wiki or something but in code they just do G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) + 1
So if I wanted to do the opposite I would have it instead do
G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) - 1
(Yes I know you're gonna fly through these antes but they're thematically accurate)
i think, idk if lowering it to 0 breaks anything
Idk what the code means I just wanna know how to do what I want it to
It'll make it easier for the coder to do their job
anyone know how i can exclude specific textures from an object with malverk?
like, I have individual files for some of the jokers, and the others are in the default sheet arrangement
key = 'teal',
atlas = "Decks",
pos = {x = 0, y = 1},
discovered = true,
unlocked = true,
apply = function(self, back)
local hands = {}
for k, v in ipairs(G.handlist) do
if G.GAME.hands[v] and G.GAME.hands[v].visible then
hands[#hands+1] = v
end
end
for _ = 1, 7, 1 do
level_up_hand(nil, pseudorandom_element(hands, pseudoseed('Teal')), nil, 1)
end
end
}```I dont see why I crash
- Wrap that in an event.
- Use
SMODS.is_poker_hand_visible(handname)instead of checking for.visible.
ok nice
how do you make Xchips score in an enhanced card?```lua
config = { Xmult = 2.5, Xchips = 2.5, extra = { odds = 4 } },
apparently it can only register fucking "x_chips" as a valid xchips argument
you could also just use a calculate function?
remove_from_deck = function(self, card, from_debuff)
if not from_debuff then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = function()
SMODS.add_card({ set = 'Tarot' })
G.GAME.consumeable_buffer = 0
return true
end
}))
return { message = "Tarot", colour = G.C.GREEN }
end
end,
iam trying to make a seal that upon its own destruction gives a consumable (tarot for testing) but i cant really understand why this doesnt work
remove_from_deck = function(self, card, from_debuff)
if not from_debuff then
upon some testing its this that doesnt work but i dont know why
Playing cards don't have remove_from_deck
then what function do i use on destruction for seals?
in the mod calculate function, you can check cards on context.removed and if it has the seal then you do your stuff?
i don't really have a codding issue but i would like to know if someone could help me understand this from VanillaRemade, how does the code works to make it recognize a straight ? the exemple states it but nothing else really defines a straight on itself
if context.remove_playing_cards and you check if context.removed contains card
You use G.SETTINGS.GAMESPEED to get the value of the current speed setting?
Yes.
is there a way to give SMODS.scale_card a scaling val not in the extra table?
rn im scaling my card like this:
bits_gained = function (card, data)
print("bits: " .. data.bits)
card.ability.extra.bitts = card.ability.extra.bitts + tonumber(data.bits)
attention_text({
text = "+" .. data.bits,
scale = 0.75,
hold = 1,
fade = 1,
major = card,
colour = G.C.PURPLE,
})
end,
but iv learnd of the SMODS.scale_card func so im updating all my jokers to use it but this one scales with a value thats not in the card.ability.extra table. is there a way to give the scale func this value directly? making a new val in the extra table and then clearing it seems needlessly complex
wait nvm im just dumb
data is a table so i can just use the scalar_table lmao
my custom consumeable's label doesnt work properly and i'm honestly not sure why, i followed the advice of everything on vremade but nothing
i usually just look up tarot in the vremade loc file to see where i need to put the labels
i did and i saw it put in misc = { labels = {} }
unless there's something i'm missing?
you need an entry in dictionary, not in labels, no?
I think for Kino, I only use the labels table for stickers and seals. For new consumable types, it's in dictionary
that makes enough sense, sure
what ice said, but i mean that if you ctrl+f you can find it in multiple places
it's a common tripping ground, tbh, and I don't even know if there's logic behind it
ill add it to the docs
i was actually about ask if there's a dedicated page for ConsumeableType or not
yes, but it is under the ObjectType one
how should i start coding
start small. try making basic stuff first. try making just Joker to start then move up from there
any idea whats up with yorick? I tried setting him to a Spectral, using soul and soul_keys, and even just having a second AltTexture for the skull. closest i got was the skull loading directly below the card
SMODS Wiki is a great place to get started and if you dont know how to implement something VanillaRemade is a create place to see how the vanilla jokers are made
also check out the vanillaremade wiki too
omg this would have been so helpfull when i got started O: wish i know of this lmao ya check this out
does anybody have a set of placeholder icons i can use?
stuff like jokers, packs, blinds, etc
i have a set
one moment
let me remove all the stuff thats only relevant for my mod real quick
is there a way to alter the likely hood of cards showing up in the shop/packs? i wanna make a joker that makes rarer cards more common and common cards more rare
here
i also have blinds though theyre on a seperate spritesheet
You could use G.GAME.common_mod with the rarity you want to modify
its possible for rarities, for consumable types its a bit jankier though
and for individual cards isnt possible at all as of now
Has anyone had lovely patch duplication? I think everytime the game builds it adds another line and removing the patches from the code doesn't remove them
Or are they meant to be permanent
lovely is a runtime patcher, they don't persist
how is it used? i dont see it in the game dumb and trying to find shit on the wiki that dones have a page is just hell
what do you mean by the game building though? that's not something lovely does
there is a G.GAME.rarity_key_mod value for each existing rarity which acts as a multiplier to its spawn rate
1 by default obviously
Oh I see, it's just what I assumed because when I check in the game-dump I find this which happens even if I remove the related patch
... how
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'after'
pattern = '''for i=1, hand_space do --draw cards from deckL
if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then
draw_card(G.deck,G.hand, i*100/hand_space,'up', true, cards_to_draw[i])
else
draw_card(G.deck,G.hand, i*100/hand_space,'up', true, cards_to_draw[i])
end
end'''
payload = '''draw_extra_effect_lilith(hand_space)'''
Not really sure how this happens 😭
game_dump is before patches, so that's weird
like so?
you should multiply the values rather than setting them
yip yip
also you said it cant be done for individual cards right? so there isnt a way to make soul and black hole more common?
not without patching create card iirc
i made something for that
https://github.com/Steamodded/smods/pull/1193
but it's in waiting until smods adds the weights api
I could have sworn it was 8 lines at some point
If I disable the mod it removes one line and if I reenable it it adds it back
damn. oh well, that would have just been nice to haves lol
do you have 8 copies of your mod installed maybe lol
check if there aren't any zips or anything like that in the folder
oh 😭 nevermind
:'3
lol
incredible...
is there any way to automatically assign card to the correct area? joker to G.jokers and consumable to G.consumeables
or a way to check center's type
vocaloid deck spotted🔥
anyone got any ideas?
Is it possible to change the name of the joker when calc_dollar_bonus happens?
i have a pr for that
https://github.com/Steamodded/smods/pull/1244
Oh awesome
cause I really wanna fix this lol
You can add the rows manually for now
anyone know why using soul_pos is crashing the game when the card is loaded?
also ftr raw_key is really not doing anything when its true or false which is why i left the mod prefix for the atlas
what is the crash
this
well the key is invalid because of raw_key lol
well when soul_pos isnt defined it works fine?
and removing the prefix also breaks it
well removing raw_key worked anyway 😭
how do i make this trigger before any joker scores every hand? it's currently triggering only after every joker is scored
if context.before then
if #G.jokers.cards > 1 then
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.2,
func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.jokers:shuffle('aajk')
play_sound('cardSlide1', 0.85)
return true
end,
}))
delay(0.15)
G.E_MANAGER:add_event(Event({
func = function()
G.jokers:shuffle('aajk')
play_sound('cardSlide1', 1.15)
return true
end
}))
delay(0.15)
G.E_MANAGER:add_event(Event({
func = function()
G.jokers:shuffle('aajk')
play_sound('cardSlide1', 1)
return true
end
}))
return true
end
}))
end
end
end```
remove the event that wraps the other events
thank you it now works!
what is the context for checking if the blind has been completed in 1 hand?
(probably the one that checks if the score is set on fire but I'm unsure)
i don't think there's a context for this, just a global variable. something like SMODS.last_blind_oneshot, but search the code to be sure
It uses the built in poker hand part _straight for evaluation. https://github.com/Steamodded/smods/wiki/SMODS.PokerHand#api-documentation-smodspokerhandpart
The code for this is part of steamodded https://github.com/Steamodded/smods/blob/2294ccb5ec06fc7575f66fcc81ce7341a77ce4c2/src/game_object.lua#L2829-L2832
Ah alright, so it basically use what smods has that defines a straight, so it's more of an extension of it
yeah and I think smods just calls into vanilla code (at least partially)
actually it might have complelty overrode the vanilla code
barely, it's heavily patched
Ah alright i see, it's just when seeing the code of vanilla remade i was thinking there would be a way to for exemple explain if a straight had to be coded, how would it work and such
that's actually not that simple of a problem when accounting for custom ranks, I think that's just out of scope
Also it'd have to be kept updated when the smods implementation changes
is there a way to have a collection with custom dimensions or does it strictly have to be the default card sizes?
the collection UI code is a method on the consumable type that you can overwrite, there's no built-in way to tell it what size your cards are
that's probably a good idea to add though
for the cards themselves to have to proper size, you can use display_size/pixel_size
(unless you did that and somehow this collection doesn't respect it, which would be bad)
if you're just curious how a straight implementaiton might work, the simplest way would be to sort the cards, then check if they are sequential
balatro has a looot of edge cases that make this real funny (especially modded)
theres the concept of "sharp edges" where the ace can both start and end a straight (but not be used in the middle of one) which has to be handled
balatro allows you to have more cards played than cards needed (four fingers) so you have to handle duplicate ranks
balatro can allow holes in the straights (shortcut) which menas you need to handle gaps
theres also been some work to make "quantum ranks" (think wild card for ranks), and that adds a whole bunch of complications
it slows down the algorithm a lot
where would i add that exactly?
just so i dont flounder about trying to figure it out myself lol
if it's uniform across all consumables, you can set it in an inject_card function on the ConsumableType
else you could add it to the consumables individually
yeah, i just saw that even making a hand for enhancements ask a little extra to it, so that's fair
I made a joker that gives +1 hand every time a blind is completed in 1 hand (aka score catches on fire) and resets the quantity of hands when it doesn't happen anymore.
I tried doing so with a variable that store the quantity of hands added to then use it for resetting the hands to the previous amount but for some reason it crashes the game.
is there a way I can fix this?
Log?
yup, that's good! ty :3
(probably dont need the width line but i'll keep it to be safe)
it says that handsQuantity is a nil value despite I set it to an integer
you defined it in loc_vars and then tried to access it in calculate
that's out of scope
is there a reason it's a local variable and not stored in the card?
no reason at all, I actually wanted to know how to store said variable in the joker card
that's what card.ability.extra is
oh I see
there's a way to replace the default undiscovered/locked images with your own right? i swear i saw documentation of it somewhere in the wiki and i forgot where
i've been waiting for malverk to add locked/undiscovered sprite support for about a year now
it was confirmed, but i don't know when eremel plans to implement it 
damn -w-
there is probably some way you can do it via steamodded, but i don't know if it's some kind of atlas overwriting or something
i mean, i see a potential way to do it, but not one i'm confident in lol
i am greatly interested in this, please let me know your findings
welll dont hold your breath lol
i'm still pretty new to modding, i barely understand patches, so i can safely say i dont have the skill to make it possible, at least not immedieately .w.
You can create custom undiscovered sprites for consumable types
And thats it afaik?
And entirely custom center types too i think
of course. feel free to reach out about anything you don't quite understand, that's generally what this channel's for - but personally this specific area of spriting code is largely unknown territory for me 
oh, we'll that's good to know!
but how tho? if not through patching smods
Create an SMODS.UndiscoveredSprite with the same key as the consumable type
And then atlas, pos, and soul_pos for the usual sprite stuff
I am struggling to find the file path for the default balatro assets??
I've found it before but holy hell I cannot find it again
omfg, UndiscoveredSprite, i KNEW i had seen it before!!
what assets specifically?
resources folder?
like the images
in the exe
Its inside the exe
ah
You need to open/unzip it with something like 7zip
I gotcha okay that makes sense
Or just copy and rename the copy to balatro.zip
Make sure to have file extensions displayed turned on in file explorer for that though
yeah, that's always amused me
just being able to open up the game like that, it's the easiest i've ever seen a game be breakable lol
iirc hades is the same
i wouldnt know, havent played the game, as much as i want to
careful or i'll gift it to you when i get paid next 
i have lots of power through you being friended on steam
ooohhhh noooo, the hoorrooooooooorrrr
whateverrrr will i dooo to avoiiiidd such a teerrriiblleee faaateeeeeee
:3
:3
the horror is you doing what i did when i bought hades (play it once and then not touch it again)
...undiscoveredsprite? and it's only for consumables?
why wouln't you be able to do it for joker or back types?
Probably because its decided per set value on a center/card
you underestimate my ability to hyperfixate
i have been doing nothing but balala modding for the last week lmao
true
Rather than just being in a specific pool of G.P_CENTER_POOLS
Also backs are never undiscovered so like
this joker I made is supposed to increase all listed probabilities by 1 if the score catches on fire on the 1st played hand of the round
yet it doesn't do that
and it should reset when the score doesn't catch on fire on the 1st hand
but instead it crashes
how can I fix this?
card.ability.extra.handsQuantity does not exist
Also most of these contexts do not calculate at the same time
My coder says that even though I put the stake stickers in a different place on the card it still only displays one sticker, I was told I can display stickers from multiple stake sets if I just don't make them overlap
If you want to display multiple stake stickers you would have to draw them manually with a SMODS.DrawStep
What is drawstep
ah oof I forgot to change it, also wdym by most of these contexts do not calculate at the same time?
context.mod_probability and context.after are never simultaneously true yet youre checking for both
so how do I exactly change the listed probabilities in context.after then?
man why isn't your coder the one asking for help
it'd be a lot easier to talk to them directly
change the value stored in the card.ability during context.after, and just use that stored value during context.mod_probability
the calculate function is called many times over the course of even a single hand
ooooh okay that makes sense
Primarily because they do a majority of the work and I try to help them in any way I can
The other reason is because their english isn't the best so I can translate what I get from here into the formatted speech I use when reporting logs
ah, that's fair
The main reason is the first but the explanation is the second if that makes sense
whats the point of Card.from_tag???
its checked here but i also dont get this
oh is this just for stats
This was because context.check_eternal is called every frame for every joker and consumable that is highlighted.
strange question, let's say hypothetically, what if I wanted a joker that when 2 of this same joker exist, both get destroyed and spawns a different joker ;]
SMODS.find_card("j_modprefix_jokerkey") returns a table of all copies that you own of the joker specified. you can call it in the joker's add_to_deck function to check if you already have it (i'm not sure if it'll count the one currently being added or not, so it'll either show 1 or 2 copies of the joker when you want to spawn the different joker), and then if the condition is met, call SMODS.destroy_cards to destroy the jokers and SMODS.add_card to add the new joker
does anyone know a proper way to trigger a booster pack opening?
if i give player a tag it works perfectly, but if i trigger the same code that tag triggers, the state ends prematurely
local create_booster_pack = function ()
-- local lock = 2081
-- G.CONTROLLER.locks[lock] = true
local key = 'p_arcana_mega_'..(math.random(1,2))
local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2,
G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true})
card.cost = 0
card.from_tag = true
G.FUNCS.use_card({config = {ref_table = card}})
card:start_materialize()
-- G.CONTROLLER.locks[lock] = nil
end
NVM the tag doesnt work either, its something on my end then
my menu needs to do something when Escape is pressed, how do i do that?
Hook Controller:key_press_update and check if your menu is open and key == 'escape'
thanks ^u^
is there a way to create a card and have that card not block itself?
i'm getting a very weird Death Note bug
ah i see
smods allows that
nevermind, i misread what that parameter did
wdym
like as if you had showman or something else
ya so the reason I ask is, Death Note's consumables menus seem to maintain the cards they had when leaving
so I'd love either a way of fixing that, or a way of creating cards that don't block themselves
does it open a menu with cards in them?
ah yeah thats a bug i had to fix in my mod
one sec
it happens if you create cards before the overlay menu is opened
can i not set the Pinned sticker to have a visual by just changing its atlas? do i need to also modify Card:draw or something?
not getting there with this. what's wrong?
SMODS.Sticker:take_ownership('pinned', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
atlas = 'balatro-revalanced-stickers',
pos = { x = 2, y = 0 },
},
true -- silent | suppress mod badge
)
the problem is that the sticker drawstep checks for card.ability.sticker but pinned is an exception since its in card.pinned
you would need to patch or copy this
could i just set it to also have card.ability.sticker set to 'pinned'?
sorry, by that i meant that it expects card.ability.pinned
but yeah you could
you would need to also copy the rest of the apply function
which is not a lot lol
yeah that works. just needed to add
apply = function(self, card, val)
card.ability[self.key] = val
end
liftoff! thanks, N!
the deathnote?!
:3
does it still work tho, thats missing the pinned application
it should be
card[self.key] = val
card.ability[self.key] = val
not working right no... it borked the localization cuz it's actually pinned_left in vanilla
it will break many more things without the card.pinned
will try doing both like you say
yeah pinned is really weird 😭
yeah its not actually appearing on the pinned knife in Knife's Edge challenge
astra how did you do it?
I said I saw it done before, not that I've done it lol
oh sorry, misread
all g
personally i would have patched the drawstep
yeah im thinking that might be easier.
im trying to set up the sprite, but it's not able to grab the atlas. is this not how im meant to do that?
local shared_sticker_pinned = Sprite(0, 0, G.CARD_W, G.CARD_H, SMODS.Atlas["balatro-revalanced-stickers"], {x = 2, y = 0})```
you should be using SMODS.create_sprite, and also yea you need to access it from G.ASSET_ATLAS
local shared_sticker_pinned = SMODS.create_sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["balatro-revalanced-stickers"], {x = 2, y = 0})```
changed to this. it crashes for trying to concatinate atlas key
It should be modprefix_atlaskey
oh right my bad
create_sprite takes just the string of the atlas key, not the atlas object itself
and yes what somethingcom said
No, it takes both.
its saying my atlas key is invalid (it works with my other stickers just fine)
are you adding your mod prefix to the atlas key?
i tried both ways twice
what's the code that creates the atlas
SMODS.Atlas{
key = "balatro-revalanced-stickers",
path = "stickers.png",
px = 71,
py = 95
}
ok and what's your mod's prefix
vb
so it should be "vb_balatro-revalanced-stickers"
yes, i tried it twice already
so what's the exact crash message then?
how odd
i agree lol
is your atlas loading
my other stickers appear correctly
wtf
Where are you running this?
yep, just commented out what im working on and loaded into the game to confirm. the atlas is working normally
local outside of any function. i figured i didn't want to run it inside drawstep. do i need to put it into a Game:start_up hook?
No, you would do it in a Game:main_menu hook.
yea you can't do it until the atlas actually exists properly
okay, that part is compiling now. my hook for SMODS.DrawStep isn't right though. my attempt:
local original_draw_stickers = SMODS.DrawStep['stickers']
SMODS.DrawStep {
key = 'stickers',
order = 40,
func = function(self, layer)
if self.pinned then
G.shared_sticker_pinned.role.draw_major = self
G.shared_sticker_pinned:draw_shader('dissolve', nil, nil, nil, self.children.center)
G.shared_sticker_pinned:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center)
end
return original_draw_stickers(self, layer)
end,
}
it's not correctly grabbing the original draw step. so im guessing i can't grab it that way
oh, im dumb
tried to add .func but that didn't help lol
How to check for “each discarded card”
local oldstickersdrawstepfunc = SMODS.DrawSteps['stickers'].func
SMODS.DrawSteps['stickers'].func = function(self, layer)
if self.pinned then
G.shared_sticker_pinned.role.draw_major = self
G.shared_sticker_pinned:draw_shader('dissolve', nil, nil, nil, self.children.center)
G.shared_sticker_pinned:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center)
end
return oldstickersdrawstepfunc(self, layer)
end
if context.discard and not context.other_card.debuff then
ohhh, .stickers.func not ['stickers'.func thanks
i feel like you shouldn't need the debuff check but idk
depends what you're checking
i dont actually know im just intuiting that Things calculating on debuffed cards by default and the same as other cards seems wrong
mail in rebate doesn't work on debuffed cards for example
No, the problems were that it's SMODS.DrawSteps['stickers'].func not SMODS.DrawStep['stickers'] and you need to modify SMODS.DrawSteps['stickers'].func directly.
oh i guess you do have to check for debuff yea i just checked
that's strange
finally
code to add sprite for pinned cards in case anyone searches this later
local original_main_menu = Game.main_menu
function Game:main_menu(change_context)
G.shared_sticker_pinned = SMODS.create_sprite(0, 0, G.CARD_W, G.CARD_H, "modprefix_atlaskey", {x = 0, y = 0})
return original_main_menu(self, change_context)
end
local oldstickersdrawstepfunc = SMODS.DrawSteps['stickers'].func
SMODS.DrawSteps['stickers'].func = function(self, layer)
if self.pinned then
G.shared_sticker_pinned.role.draw_major = self
G.shared_sticker_pinned:draw_shader('dissolve', nil, nil, nil, self.children.center)
G.shared_sticker_pinned:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center)
end
return oldstickersdrawstepfunc(self, layer)
end
Do i use context.other_card on set_ability?
to do what?
No, set_ability doesn't have context
Unscoring cards become Steel, Discarded cards become Nanotech.
if context.discard then
context.other_card:set_ability('m_modprefix_key', nil, true)
elseif context.individual and context.cardarea == 'unscored' then
context.other_card:set_ability('m_steel', nil, true)
end
i also used this for a cycling enhancement that has a chance to refund the discard when it gets discarded, but didn't want it to do that if debuffed
can you return chips/mult/etc in a mod calculate or sticker's calculate?
Yes.
is there a context i can use for at the end of a round but before gold cards and blue seals are calculated?
if context.after and G.GAME.chips >= G.GAME.blind.chips?
oh smart
follow up question, do mod and sticker calculates not have access to the individual context? trying to run the following code to make a sticker that applies to playing cards and grants xmult and it doesn't seem to work in the sticker's calculate nor the mod calculate. not even the print line runs.
if context.individual and context.other_card.ability.wafflemod_cerulean and context.cardarea == G.play then
print("scored")
return {
xmult = 3,
message_card = context.other_card,
}
end
it should work on mods
are you trying to make a sticker that just gives xmult when played?
pretty much. why, does the standard config (i.e. not the config.extra) work for stickers or something?
thats the wrong context
it's just context.main_scoring
and cardarea too
although im not entirely sure if everything works correctly for stickers on playing cards
it's not actually working for some reason :(
whats the goal?
you probably need G.GAME.chips + SMODS.calculate_round_score() >= G.GAME.blind.chips i think
wait, context.end_of_round should be happening before the gold cards and blue seals according to end_round()
will do more testing
ok update the mod calculate seems to run the print statement with context.individual but the actual return doesn't work
also context.main_scoring and context.cardarea == G.play doesn't seem to do anything
yep, i was just mistaken before. context.end_of_round gets calculated before gold cards and blue seals
the return works fine for me
main scoring in stickers also works fine for me
something is broken on your end
let me just make sure i've got an up-to-date steammodded
okay, just updated steammodded, the return here still doesn't do anything even if the print runs weirdly enough
if context.individual and context.other_card.ability.wafflemod_cerulean and context.cardarea == G.play then
print("scored")
return {
xmult = 3
}
end
actually let me just try SMODS.calculate_effect rq
i copied that code without the sticker check and it worked fine idk
that is incredibly weird then
SMODS.calculate_effect works but displays the effect before the "+(rank) chips"
Yes, the effect has to be in the return if you want the timing to be correct.
i would check if there isnt code in your mod that is messing with returns
because that could probably be a pain in the future even if you do a hack now
did this and found the issue, sticker works now 
ty for the help
I'm working on a back atm that I'd like to be able to swap the sprite of at the end of every round. How would I go about changing the initial pos in the atlas during gameplay?
how do i reference the consumeables area?
G.consumeables? the cards within the area are in G.consumeables.cards, just like other cardareas
does self.area.config.type == 'consumeable' accomplish that given self is a card?
no, that's the card's type
No, it would be self.area == G.consumeables
yep, that's the one. just got there myself. thanks <3
for k, v in pairs(G.I.CARD) do
if v.children.back then
v.children.back:set_sprite_pos({x = x, y = y})
end
end
Worked perfectly, thx
Did you ever find a solution to this
It happens whenever you pass a y offset apparently
very noticeable here and dunno what to do
I didn't find a perfect solution, but I did find something that fixes most of it: #💻・modding-dev message
Also it happens when you apply any offset at all.
that makes sense, I only ever used very small x offsets so it wasn't noticeable there
How do you get the hand of your currently selected cards (while selecting cards, not during scoring)?
The first output of G.FUNCS.get_poker_hand_info(G.hand.highlighted)
thank you
spawns Mr. Hilgard when a joker that is not Marie or Mr. Hilgard is destroyed.
if context.joker_type_destroyed and context.card.ability.set == 'Joker' and context.card.config.center.key ~= 'j_modprefix_key' and context.card.config.center.key ~= 'j_modprefix_key2' then
SMODS.add_card({key = 'j_modprefix_key2'})
end
is not working
Code?
SMODS.Joker {
key = "marie",
unlocked = false,
atlas = "bb_legendary",
blueprint_compat = true,
pools = { ["bustjokers"] = true },
rarity = 4,
cost = 20,
pos = { x = 2, y = 0 },
soul_pos = { x = 2, y = 1 },
config = { extra = { } },
loc_vars = function(self, info_queue, card)
return { vars = { } }
end,
calculate = function(self, card, context)
if context.joker_type_destroyed and context.card.ability.set == 'Joker' and context.card.config.center.key ~= 'j_busterb_marie' and context.card.config.center.key ~= 'j_busterb_hilgard' then
SMODS.add_card({key = 'j_busterb_hilgard'})
end
end
}```
How do you beat a blind when using a consumable
I should really just start checking Vremade before asking
||time-related is a known concept in Cold Beans, but I won't judge since it's meant to be hidden until release||
This is lunch from GOTCE coded
wouldn't say it's hidden it's built into the lua coding language
one thing i'm trying to figure out is this
I think its built into Physics actually
I can't get it to use the jokers name
what I meant is that Cold Beans' content is hidden from the public until release
are you using localize
Trying to use Localization but doesn't want to work
Not sure if it's related to a custom ui box or not
you should use localize{ type = "name_text", key = key, set = "Joker" }
For getting the name
worth trying I guess
key = joker key
where joker key is your joker's key (j_modprefix_whatever)
localize{ type = "Mods", key = j_ttv_mods, set = "Joker" }
where you modprefix is "ttv" and joker is called "mods"?
yes
then it should probably work
its not a string
oh yeah
oh
Doesn't work :/
Tryna make a profanity filter for my mod and while the toggle works it just seemingly doesn't change the setting
if this is in a localization file you would need to reload localization first
?
debugplus hotkey that i forgot or change language
for testing yea
just tell your users that it's a toggle that requires restarting the game
ah
the proper way would be to do it in loc_vars rather than in the localization file, to avoid restarting
yeah ig that works too
been a while since I've done anything to crazy w balatro modding, so question, how would I make a "variable rarity"? Idea I had for it was simple, a rarity that only shows up during endless, or rather, ante 9 and beyond would be the actual definition probably
You can actually check if youre in endless i think(?)
G.GAME.won is set to true after winning the run and therefore starting endless
hmm, I see dsfjk
well, I think I'll still use ante simply cuz I was planning on maybe having it scale, like, having the chance be like, 5% on ante 9 but like 20% or something at ante 20, you know?
did I understand it's usage right here?
used a bit of help from the vanilla remade thing too
also, I know that "ante" here isn't right lol, but I wasn't sure what the right one was lol sdfnkj
probably something like current_ante I'd assume?
G.GAME.round_resets.ante
thank you!
welp, I messed something up here lmao nsdfjk idk what tho, clueless here 😭 knowing me it has to be a typo of some kind lol sndfjk
sorry, more context ndsjk
haven't been thinking well lately lol dnsfk, sorry if I'm not doing this well rn lol sdfds
oh, damn, how I forgot to put the number part in when that was the main reason I tried the screenshot idk lmao, sdfnkj, line 10 should be the SMODS.load_file("Items/rarity.lua")()
looks that its not finding that file
I'm not sure why, the file is in the right location, hmm smndfkj, is there something in the rarity lua I'm missing or something? tho, I'm not sure why that'd matter if it's not even detecting it's existence sdfnjk
yes, I even went a little crazy and resaved the same file like 9 times without even making changes because, as they say, the definition of insanity is trying the same thing over and over and expecting something different to happen, lmao sdnfjksd 💀
local text, _ = G.FUNCS.get_poker_hand_info(G.hand.highlighted)
if text == card.ability.extra.hand_type then
card.ability.extra.me_debuffing = true
return {
debuff = true
}
end
end
```little help with this, please! when about to play the hand, it tells me it wont score and then scores anyway
You should check context.scoring_name instead of using get_poker_hand_info
is there a way to dynamically update a joker description during scoring? this doesn't seem to work
local numerator = SMODS.get_probability_vars(card, 1, card.ability.extra.current_odds, 'fgc_EWGF')
return {
vars = {numerator, card.ability.extra.current_odds, card.ability.extra.Xmult}
}
end,
calculate = function(self,card,context)
if context.individual and context.cardarea == G.play and not context.blueprint then
if SMODS.pseudorandom_probability(card, 'fgc_EWGF', 1, card.ability.extra.current_odds) then
card.ability.extra.current_odds = card.ability.extra.current_odds + 1
return {
xmult = card.ability.extra.Xmult
}
end
end
if context.final_scoring_step then
card.ability.extra.current_odds = 3
end
end```
I could just send a message on each card with the updated odds but I want to see if I can get it to update in the description first
all parts of scoring calculate immediately after each other, so the reset will have already happened by the time the hand actually animates
You would probably have to reset the value in an event, but even then it would instantly show the final value it reaches in scoring
return statement it is then
return {
message = numerator.." in "..denominator.." chance",
xmult = card.ability.extra.Xmult
}```
How does one give a random joker that must have two specific pools
eh i just made a pool for both
would it be possible to make a joker that, when owned, disables enhancements from working? like the card still scores, but the enhancement doesn't?
i managed to get something working earlier where if the card has an enhancement, it just doesn't score whatsoever, but that's not exactly what i'm looking for
i tried it the other day but it was annoying so i scrapped it but it seems possible
sorry, took a small break lol, now that I'm in a better mindstate, here's some more info to help debugging whatever's going on here lol
it's bizarre tho, like, what piece isn't working here? lol nsdkfj
like, how does it detect my jokers.lua fine but not the rarity.lua dnsdfjk
you're short an end
so when it tries to load the file, it gets an error instead of a chunk
how would i put an atlas sprite into a card's description text
oh thank you!
that's such a classic issue from me lol smndfjk
yeah, I added the "if/then" without adding an "end" to accompany it right?
but like,, in the middle not the end



funny meme joker
