#💻・modding-dev
1 messages · Page 345 of 1
forget how to read your own crash logs it seems
this is literally the most clear crash log that you can get in balatro modding 😭
like, this (?) sorry
yea that looks right
if that doesnt work try adding your mod prefix before the atlas key your giving the joker
what does this mean
oh wait
you put atlas == ryan in the atlas aswell lol
right here
it should just be in the joker
what does this mean? i am slow sorry
good news we can see the golden sticker bad news it's still not 😭
i love leaving easter eggs in code
6 DOLLAR SRIMP SPECIAL
are you telling me a shrimp fried this rice
me when diamond
MINecraft parody! enjoly!
reminds me of this gem
https://www.youtube.com/watch?v=3dLkZ1gagIE
t h r o w a w a y
Free Download // https://www.mediafire.com/file/35j55bh0hf05b46/Mine_Diamonds_(Naz3nt_Remix).mp3/file
Instrumental // https://www.mediafire.com/file/jd86vdc38k8632m/Mine_Diamonds_(Naz3nt_Remix)_[Instrumental].mp3/file
Hit Me Up:
~ Join the discord // https://discord.gg/ywmryFp
~ Soundcloud // https://soundcloud.c...
i used to listen to this when i was 13 💔
im sure it was fire at the time
at the time...
alr guys i got a couple of questions before i head to bed for a joker i'm making
- how do i make items free in a shop (like they were generated through a joker-generating tag)
- is there any way to disable rerolls
- is there a context for entering shop?
boost
- look at coupon tag in the source code
- if you mean just not allow it there is not a vanilla way of doing it but you can just hook whatever function checks for if you can reroll
context.starting_shop
set the reroll price to somthing absurd
@glad osprey sorry 4 the ping, the code still isn't working do you have any idea why that could be? 😭
no lol
oh okay ty regardless
what is that
is that the joker?
i'm trying to replace the texture of red card with another png but it doesn't seem to work, it just makes the joker into jimbo
look at the BU language mod
I mean... probably pssoible with draestep, definitely with love.draw
if you mean all at once
yea
i am using a drawstep just to be able to draw the shader (deck stuff) but idk how i would go about doing every shader
is there no example or mod that at least uses 2 shaders at once?
or editions whatever
all i can think of is blueprints ability to draw shaders on top of the blueprint shader
I mean... I'm pretty sure you can just do 4 drawsteps in succession?
blueprint predates drawstep I'm pretty sure, so must do it more manually
I think badge_color expects a hex value?
hmm... lemme look at the docs
docs just say
badge_colour: Colour of the rarity's badge.
i can just put the hex code, i guess
then they say "must be a valid hex color"
i see
the only issue is if you want it to sync with Trance
but I don't know if trance actually changes the values in the tables anyway
true
I guess it must
very fair :3
wait I take some of that back
I was loooking in the wrong place
had a brainfart
oh?
yeah I was being a doofus and looking atr the mod badge
for for rarities, you do seem to be able to just use G.C.[]
how did you do it tho? plain string or HEX("#000000")
well for the mod badge, a plain string works? that's still how it's listed in the docs. But yeah for game objects, which I haven't tried to do yet really, it makes sense it'd be the latter
oh whoops then maybe i'm completely wrong
yeah, I actually have no idea why this doesn't work
I have a mod with a rarity that uses G.C.Purple
and that works afiak
i mean, maybe it's because it's specifically calling G.C.Rarity which fucks it up or something?
dunno
maybe this is how you have to do it?
pretty sure printers use the Rare color too
and that's what this is
this could be the case
Printer from Revo's
yeah,
SMODS.Rarity({
key = "rare2",
badge_colour = G.C.RARITY[3],
})
works
generally vanilla uses indices to indicate rarities so it would make sense for it to just be a normal array
bump
it does say that Smods is what adds G.C.RARITY.Rare to it
but I guess it doesn't work in all cases for some reason
can someone check this?:
i can send the code in dm and shi for help
Does anyone have any ideas for rarity names between Rare and Epic? Curious what other people can come up w here
Bump
anyone have a good starting point for animating jokers?
to be specific, I want my joker to switch from a still sprite to an animated sprite under a certain condition
...I have a Joker that is animated, but not in the Collection, fwiw?
Though, https://github.com/SpectralPack/Aura exists or you can manually change the currently displayed "frame" of the Joker, which is what I do.
so CiaaiK wants ti reskin all Aces, but just the Aces
from what I understand
And the proper way to do that is deckskin objects, right?
This is its first time making a mod
is this how i patch another mod's code
no
'''=[SMODS modid "source/file.lua"]'''
got it working, thank you so much!
oh, so if reverie's mod id is Reverie, then its like this?
mm icic, thanks
key = 'acespades',
suit = 'Spades',
loc_text = 'NewAce Spades',
palettes = {
{
key = 'lc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacelc',
pos_style = 'deck',
colour = ,
},
{
key = 'hc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacehc',
pos_style = 'deck',
colour = ,
}
}
}
SMODS.DeckSkin {
key = 'acehearts',
suit = 'Hearts',
loc_text = 'NewAce Hearts',
palettes = {
{
key = 'lc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacelc',
pos_style = 'deck',
colour = ,
},
{
key = 'hc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacehc',
pos_style = 'deck',
colour = ,
}
}
}
SMODS.DeckSkin {
key = 'aceclubs',
suit = 'Clubs',
loc_text = 'NewAce Clubs',
palettes = {
{
key = 'lc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacelc',
pos_style = 'deck',
colour = ,
},
{
key = 'hc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacehc',
pos_style = 'deck',
colour = ,
}
}
}
SMODS.DeckSkin {
key = 'acediamonds',
suit = 'Diamonds',
loc_text = 'NewAce Diamonds',
palettes = {
{
key = 'lc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacelc',
pos_style = 'deck',
colour = ,
},
{
key = 'hc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'pfx_newacehc',
pos_style = 'deck',
colour = ,
}
}
}```
so this is most of what you'll need
you can change the names keys, they're just placeholds
and you need to set up the atlas too
and the mod itself
I reccomend looking through the smods wiki
alright, thank you
np :3
also, just for due dilligence, template cribbed from the deckskins in @heady siren 's mod aether jokers
is there a way to determine where a function is defined globally?
or even a variable
im getting tired of looking through each lua files in the mods
open the lovely/dump folder in vscode and shift+F
or if you're a menace like me you just keep your whole mods folder open and get results from your other installed mods
^
how do i check if a specific boss blind is active in an if function
how do I open the folder in vscode?
" use the global variable G.GAME.blind to refer to the current blind." is a way to refer to the current blind according to the steamodded docs
but idk how to get the components
if G.GAME.blind.in_blind and G.GAME.blind.config.blind.key == "key" then
yeah i want to check for certain boss blinds and do different things for different blinds
thank you
tysm
is it possible to replace a boss blind with a different one when entering the blind
a little switcheroo
just started trying to make a mod for the first time like an hour ago and i don't know lua, so probably a stupid question, but:
key = 'air',
loc_txt = {
name = 'Air',
text = {
'Played cards with',
'{C:diamonds}Diamond{} suit give {C:blue}+25{}',
'Chips when scored'
},
},
atlas = 'Jokers',
pos = {x = 0, y = 0},
config = {
extra = {
chips = 25
}
},
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.chips}}
end,
calculate = function(self,card,context)
if context.main_scoring and context.cardarea == G.play then
if context.card:is_suit("Diamonds") then
return{
chip_mod = card.ability.extra.chips
}
end
end
end
}```
why doesn't this work? it's meant to just give +25 chips when a diamond is scored (everything about the display works, it just does nothing when I play a diamond, but i'm leaving in all the code just cause)
I also had it as context.other_card:is_suit earlier because that's what i saw in a tutorial but that didnt work either so yea
am i stupid why does ts not work
tried this, it didn't work, so I just made a shader that combined all of them
I think you should use context.individual instead of context.main_scoring
that worked ty
is there anything in the game that gives -chips
G.GAME.blind:set_blind(G.P_BLINDS["key"])
I might just yoink the flint effect instead
-chips should just work tho?
cause I was thinking about having -chips +upside but I wasn't sure how to handle the case where your chips go negative
I think the game just sets chips to 1 or 0 then
key = "Alex",
path = "Alex.png",
px = 71,
py = 95
}
SMODS.Joker {
key = 'Alex',
loc_txt = {
name = 'Alex',
text = {
"{C:green}Deletes{} a random",
"card each hand.",
"{X:mult,C:white}X#1#{} Mult and",
"{C:chips}+#2#{} Chips (1-10000)",
"{C:inactive}(This hand only)"
}
},
config = {},
rarity = 5,
cost = 9,
discovered = true,
unlocked = true,
eternal_compat = true,
blueprint_compat = true,
atlas = 'Alex',
-- attempts to randomly remove a card from the deck (BROKEN)
pos = { x = 0, y = 0 },
loc_vars = function(self, info_queue, card)
local mult = card._alex_last_mult or "?"
local chips = card._alex_last_chips or "?"
return { vars = { mult, chips } }
end,
calculate = function(self, card, context)
if context.joker_main then
local deck = G.deck.cards
local candidates = {}
for _, c in ipairs(deck) do
if c ~= card then table.insert(candidates, c) end
end
if #candidates > 0 then
local chosen = pseudorandom_element(candidates)
G.deck:remove_card(chosen)
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
delay = 0.2,
func = function()
chosen:juice_up()
chosen:remove()
return true
end
}))
end
-- random mult and chips
local rand_mult = pseudorandom(1, 10000)
local rand_chips = pseudorandom(1, 10000)
card._alex_last_mult = rand_mult
card._alex_last_chips = rand_chips
return {
xmult = rand_mult,
chips = rand_chips
}
end
end,
}
``` wtf is wrong
with the remove random card logic
what does it do now, if anything?
shouldn't this work in theory? it just does nothing
i dont think so, no
it's probably firing too late
after you're already in the boss blind
you probably want to hook instead
if I had to guess
wdym
does anyone know why the XChips is not working properly? the chips are not being multiplied during scoring but the mult is
how would i do that
hook to the function that runs when you press Select Blind
then do the stuff
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
i am not smart enough for this 😭
if you're running talisman then this is a talisman issue
hooking is basically letting your code run in the timing of when another function runs
either before or after the original code
do i need to disable talisman or something else?
just update talisman from the master branch
do i just download the latest release?
Anyone know how to get a text field rendering before create_text_input?
green code button
and make sure to unest it and rename the folder to be just Talisman
how do i change the size of a joker, like photograph?
i'll try that rn
look at how photograph does it
no, sorry.
oh yeah i forgot you can do that
SMODS makes it easier than that.
i assumed there was a smods implementation but i couldnt find it
oh i only did one at a time
half joker is
display_size = { w = 71, h = 95 * .7 },
pixel_size = { w = 71, h = 95 * .7 },```
wee joker is ```lua
display_size = { w = 71 * 0.7, h = 95 * 0.7 },
pixel_size = { w = 71, h = 95 },```
With this, and vanilla code, you should be able to get photograph
thanks, it works now 😁
this goes in the config line, right?
because nothing happened
yeah i dont understand hooking at all this doesnt make any sense to me
also im not trying to get the same size i just wanted to get that effect
It goes on the base, like where you define config, loc txt, calculate
Like redefining a function? It lets you wrap code around the original function
it's all coming together 😎
i'm currently trying to replace a boss blind with a different one upon entering, but this doesn't work, and someone suggested hooking, which i tried researching and i dont understand it at all
does it matter if its before or after any lines
its still not having any effect
function og_func(arg1)
return arg1+5
end
local old_og_func = og_func
function og_func(arg1)
if arg1 < 0 then return nil end
return old_og_func(arg1)
end
old_og_func(5) -- returns 10
old_og_func(-1) -- returns 4
og_func(5) -- returns 10
og_func(-1) -- returns nil```
Show the code
(yes i know its a tiny size difference idk why my friend drew it like that)
They need to be w and h
⬆️
hooking goes like this:
local target_function_ref = target_function
target_function = function(e)
do my code here first
return target_function_ref(e)
end
you grab a copy of the function you want to hook
you make your own function that replaces it
your function does a little code
then it calls that copy that you made earlier so that the original function still gets called
(usually you also return the result of whatever comes out of the function)
thank you kind stranger
👆
how would i apply it to this situation?
blinds have "bl_" prefixed before them
You gotta add that, if youre going to compare the keys
oh i see
You shouldnt need to
go dig through the codebase and find whichever function moves you onto the next blind and then hook it so your code gets called at the right time
you can 100% do it well with a calc function
^ or someone else that knows what they're talking about answers with a better solution
what should i do instead then?
^
added the bl_ prefix and it still seems to do nothing
If you add "bl_" to your code rn, it should work. I just tested it
Show the full code
ok how the hell do i pair vouchers
ayy nice
is it before or after the mod prefix
before
this should work then?
yea
I would recommend adding some contexts to it, so that it doesnt run every single time
though, then again
AA
nevermind. if the if is ever true, its instantly changed to a different blind
Mention
Just don't expect them
ah, fair, I don't expect them either, but I personally like them. makes me feel relevent
You say that you require the previous voucher on the last one.
And people don't usually mention me for like, any reason, it feels weird for people to be mentioning me when I'm not directly involved in the conversation
what does [SMODS _ "src/loader.lua"]:571: [SMODS cici_fancy_aces "main.lua"]:34: unexpected symbol near '}' mean?
(relevant snippet of code)
key = 'acespades',
suit = 'Spades',
loc_text = 'Fancy Ace of Spades',
palettes = {
{
key = 'lc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'fancyLC',
pos = { x = 1, y = 1 },
},
{
key = 'hc',
ranks = { 'Ace' },
display_ranks = 'Ace' },
atlas = 'fancyHC',
pos = { x = 1, y = 1 },
}
} -- line 34
}```
how to make this Rename button appear on the left side, hmm
i already did
yeah I think it's a habit I picked up back in tight knit telegram groups
display_ranks is missing an opening bracket on both
is there a way to make an else function trigger if any of the previously stated if functions don't trigger
loc_txt is not loc_text, and its supposed to be a table
ok
else will only run if nothing before it in the chain hit
if cond1 then
elseif cond2 then
else
end```
yeah but
code 1 and cond2 must be false for else to hit
can i have it run after multiple if functions
instead of just one
so
if none of those trigger
if cond1 then
if cond2 then
end
end```?
i think i understant ty
how do i make it a table? this is my first time modding so i am clueless :P
in my lua file, i wanted to make the mult random and the chips random when using this joker, but the random value is always .32 not in the range of (1-10000) additionally it does not change hte random value after each round can sm1 help a fella out
loc_txt for a joker should be
name = 'XXXX',
text = {
"XXXX",
"XXXX",
}
}```
That is not how pseudorandom works
aight thanks ive never coded in lua be4
You use pseudorandom('identifier') and it always give you a number from 0 to 1, so do
math.ceil(pseudorandom('identifier') * 10000)
And it's a Balatro specific thing, not lua itself
i got it to not crash on startup! (by removing the loc_txts for each. it cant error if it doesnt exist right)
No, you can do pseudorandom('identifier', 1, 10000) and it'll give a random whole number between 1 and 10000.
could i use math.random()?
That would make it incompatible with seeds
I did not know that, I've only ever seen it done the way I did it
yh idc abt that lol
You should, rule of thumb, use pseudorandom over math.random if it's gameplay related
uhhh, heck no
thats a lil too much owrk
Why is it a problem for you to use it?
work*
Just replace it with this pseudorandom('seed', 1, 10000)?
If changing one tiny bit of code is too much work for you, you probably shouldn't make a mod, being honest
copy and pasting too much work tbh (thx tho)
how do i make a dynamic name for a joker? i want the name to change every time you hover over it
why doesn't this work?
the first part works fine, but the else doesn't
wait actually
can i just put
loc_txt = {
name = card.abilty.extra.name
}
No.
worth a shot
i think ik whats wrong
i dont know how ill detect when the joker is hovered
idk if this will work
no its supposed to be the big blind
can i call loc_txt in the calculate function?
No.
the intended effect is to replace the clock with the trick (which works) but if it's any other boss blind, replace it with a big blind (which doesn't work, and i know why but i need to figure out how to code it)
You could return a key in loc_vars that has a different name?
can i add conditions after "else"?
that's what elseif is for p sure
the game no longer crashes immediately, but the card textures don't show up in game
is it just G.GAME.blind.boss?
Yes.
thank you!
im trying to get the card to signal that its effects are being triggered, but I don't see anything happening. what is wrong? I have reduced motion off so the juice_up would work, but idk why i dont see anything
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.dollars, card.ability.extra.increase_per_hand} }
end,
calculate = function(self, card, context)
-- Tests if context.joker_main == true.
-- joker_main is a SMODS specific thing, and is where the effects of jokers that just give +stuff in the joker area area triggered, like Joker giving +Mult, Cavendish giving XMult, and Bull giving +Chips.
if context.joker_main then
-- Tells the joker what to do. In this case, it pulls the value of mult from the config, and tells the joker to use that variable as the "mult_mod".
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.4,
func = function()
card:juice_up(0.3, 0.5)
play_sound("tarot1")
return true
end,
}))
card.ability.extra.dollars = card.ability.extra.dollars + card.ability.extra.increase_per_hand
return {p_dollars = card.ability.extra.dollars}
end
end
}
What's the current code?
alright, this just hard crashes the game, what did i do wrong here
was there an error message?
no, just closes out of the game
You don't put in a pos, you put in a pos_style, which can be 'deck' if you have all cards from 2-Ace, or 'collab' if you only have face cards
ok
how do i modify joker slots?
G.jokers.config.card_limit = number
what i'm trying to do is to set the clock to the trick, and set any other boss blind to the pin (all of these are placeholders)
the first part of the if works just fine, but the elseif crashes with no error
forgotr i had talisman on (7 hours gone)
we are winning
might have made a slight oopsie in my code
you are in the future
lmao
welp
that's hilarious
good morning/night
night ig
i've replaced the poses with pos_styles but it still isnt showing up in game
domain expansion: infinite joker slots
how do i fix this
here's the current code
are you making a mod or just trying to play them?
making
is C1 a local in your mod?
no
but it doesn't crash without your mod?
its my boss blind
hmm... somehow you're making a variable you didn't create nil when it shouldn't be
specifically a table I think? because index
idk if this summons a table
i just made this enhancement and it technically works but it just creates the random number at startup and then sets the mult for all glimmering cards in the future to that, which i think is a level of jank balatro does Not need yet
is there an easy way to make it set the random number just whenever the card is created/enhancement is applied?
key = 'glimmering',
config = {
extra = {
mult = math.random(1, 10)
}
},
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.mult}}
end,
atlas = 'Misc',
pos = {x = 0, y = 0},
loc_txt = {
name = 'Glimmering',
text = {
'{C:red}+#1#{} Mult',
'{C:inactive}(Random +1 to +10){}'
}
},
calculate = function(self,card,context)
if context.main_scoring and context.cardarea == G.play then
return{
mult_mod = card.ability.extra.mult
}
end
end
}```
well yeah that's what it does
config is the initial state of the card's ability table
also you shouldn't really use math.random here anyway
yes but idk what the alternative would be to just trigger when the enhancement is created (this is my first time modding btw)
oh is it on_apply?
Anyone know why create_text_input hides text in surrounding nodes until you click on it?
@daring fern are you gonna actually interact or just leave reactions
wht is the function to end the run
like, winning the run?
they talk sometimes
he just.. likes to lurk and react I guess, lol
from my experience with text inputs this is because they are Suck and Not Good and Work Not
Debug plus implementation:
G.FUNCS.DT_lose_game = function() if G.STAGE == G.STAGES.RUN then G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false end end```
Straight up.
ty hb
why doesnt this work?
bl_blind_pin and bl_cry_pin?
update: i've discovered that the game crashes when you scroll fully to the right on this screen (or any of the other suits' screens)
so now i have to figure out why my mod makes it freak out
colour 1
thanks
Assuming its this function
Hey wilson, have you ever had any issues like this with create_text_input?
the atlas might need your prefix
I've never used create_text_input
but I do know it's buggy
damn.
The text appears fine if the node is after the text input
but not if its before.
this is really driving me insane, this code seems completely straightforward to me, i cant tell why its not working
hm ok
never seen this before
ok
Are you creating a blind?
yes
What are the values that you are setting it's colors too?
i dont have anything setting it
thought it would have some default
is this the proper place to ask for help trying to install mods?
i keep getting a crash error installing lovely or something
I dont know but probably https://discord.com/channels/1116389027176787968/1209506360987877408
ty
game still crashes :P
set some
k
is there a way to use an atlas from another mod, but set the atlas to something else if that mod isn't installed?
how do i set a card enhancement? i noticed the base game does stuff like v:set_ability(G.P_CENTERS.m_gold, nil, true) but whenever I try that I just get card.lua:262: attempt to index local 'center' (a nil value)
idk if this will send right but code
how can i get the size of the game window
also ignore me not having fixed this, i want to make the tarot card work so it's easier to test it first lol
i want to make a sprite that scales to the size of the game window
how do i detect whenever a message in sent in debugplus' console
love.window.getDesktopDimensions?
does that do it in balatro standards though?
like what is the number it returns in
I don't know what your trying to say but I have this:
oh ok
im pretty sure that alone returns the size of your monitor 🤔
can someone help me understand why this patch is not working?
this is my first time patching SMODS
this should create a joker with the key "j_mills_monster" right?
does triple " work? 🤔
Just use SMODS.add_card({key = "j_mills_monster"})
bump
some mod wants the score to be negative. even i have plans for the score being negative
oh, tyty!
my mod puts an exponent on the chips, negative chips break exponentials
does it
well for one thing it makes the negative chips positive
What if you temporarily made it not negative then made it negative again?
can you send this as text
the top part
so does multipluing 2 negatives together though? so idk it seems as intended as any math
x, y, displayindex = love.window.getPosition()
d_width, d_height = love.window.getDesktopDimensions( displayindex )
```?
if the exponential isnt a whole number, does it cause the negative chips to become an imaginary number or something
-# sorry if i sound dumb, i havent studied till that part yet ❤️ or i mightve forgotten
exponents aren't limited to intergers
I didn't think?
I meant to get a real number
this is probably what I'll do
improves mod compatibility
I'd still like to know how to patch SMODS though lol
yeah no this was WAY too zoomed in
play around with the numbers lol
i dont think he understands
Do you want the rest?
ok now im confused
im trying to make the width and hight of the sprite() to be the size of the screen
That gives the size of the window, no?
it does but i dont think balatro goes off those numbers
is there a way to make a blind never appear naturally?
To solve my issue with create_text_input, I had to add a G.OVERLAY_MENU:get_UIE_by_ID("ID").UIBox:recalculate() where ID is the id of the text field.
sorry for the ping cheese person, but did you ever find an answer to this?
what are you trying to do with it?
like, during normal gameplay, it would never spawn by itself
Use in_pool instead for advanced conditions.
from the blind wiki
in_pool(self) -> bool
For implementing advanced restrictions on when a Blind may appear in a run. This puts boss.min and boss.max restrictions out of effect.
Unless ignore_showdown_check is set, this function will not be evaluated in the following cases:
A showdown Boss Blind should appear, but this Blind is a regular Boss Blind.
A regular Boss Blind should appear, but this Blind is a showdown Boss Blind.
i just want it to not be in the pool at all
?
in_pool = function () end
i see, ty!
oh god i haven't played balatro in like 6 months, let me see if i can remember what i did
Did you ever give your blind colours? Cause Im pretty sure the error is that its trying to mix colors that dont exist.
well how do i do that
boss_colour = XX
this deckskin is going to be the death of me
same error.
i realy dont know how localthunk got this render scale
yes
whats suit_icon used for
2.0487...... Wild
for card_w
like i have no idea what "1" is size wise in this game
what did you set boss_colours to?
That
W = 1
yeah so how do i get W and H of the screen in the misterious unit called THAT
fixed it.
can you show the full crash log
les go
because yeah thiis crap is WILD
@willow plinth sorry are you on mac or windows?
if you aren't on mac i might not be able to help you
im looking into it. all of ui is bullshit
lmao
the jokers slot in the shop's width is set to math.min(G.GAME.shop.joker_max*1.02*G.CARD_W,4.08*G.CARD_W)
which is probably the least odd
4.08 is 4x1.02
Wait you're alive?
what? no...
oh yes, you were the one that helped me with this right?
uhhh
i don't really remember
like 6 months ago or more recently
i've been inactive for like a year lol
do you have lovely? you might actually have a 0.98 smods patched exe
oh wait yeah i think so. should i send it here?
hy cheese
no need, it's just pretty rare nowadays for someone to have a patched exe
welcome back, we've grown a lot
i would think so
one question, has localthunk added any sort of modding support in the time i've been gone?
nope! lovely and smods is the way to go nowadays
thought so
See his statement on such here: #🎙・server-chat message
i guess it makes sense since modding is already so well established
first party iOS mods could never be a thing anyways
to actually answer, i've just had a really intense period of time with school stuff and mental health, and the last thing i remember was getting burnout trying to keep my mod up to date
thx guys!
I vaguely remember you from ages ago, glad you've come back ❤️
things have changed a lot
i'm really surprised people remember me at all
Hello chat
the full release of steamodded was around the corner, and i was trying to port all my code across
ah yeah, right, just around the corner
what do i use to make like 2 layers in a card? like legendary cards?

omg don't tell me
soul_pos
tyty
ofc!
We yearn for the corner reaching.
finally got this sucker working, now to code roughly 50 more inverted blinds...
chicot enjoyers in shambles
this is supposed to prevent the joker from spawning with an edition, right?
i am on mac yes!
i changed my sh to this:
#!/bin/bash
gamename="Balatro"
defaultpath="/Users/$USER/Library/Application Support/Steam/steamapps/common/$gamename"
export DYLD_INSERT_LIBRARIES=liblovely.dylib
cd "$defaultpath"
./$gamename.app/Contents/MacOS/love --fused "$defaultpath/Balatro.app/Contents/Resources/Balatro/"
and everything works but the game has the wrong save directory
like even though it's fused it still takes '/Users/nnmrts/Library/Application Support/LOVE/Balatro'
yo gifs are back???
Prolly should round down.
oh that is manually uploaded
this only happens upon reopening a save, but youre probably right lmao
any ideas on how to shuffle played/discarded cards back into the deck?
G.FUNCS.draw_from_discard_to_deck()?
how do i makee the second layer go poioioioioing like soul card?
i'm not sure how to do that, ik what you mean though
oh, tyty!
sewer
oh yeah totally forgor, tyty!
mhm!
@willow plinth i just realised i did end up having to just build the project and couldn't run it directly from the source code, i had two seperate versions with steamodded and just vanilla. super sorry i can't help
all gucci
it may be possible nowadays but you'll have to ask someone else
the way i did it is a bit archaic but somewhat simple - first off, remove soul_pos from your card entirely!
then, you need to define this function... somewhere (replace c_fmod_soully with your card key and { x = 2, y = 2 } with the pos to the soul)
local set_spritesref = Card.set_sprites
function Card:set_sprites(_center, _front)
set_spritesref(self, _center, _front)
if _center and _center.name == "c_fmod_soully" then
self.children.floating_sprite = Sprite(
self.T.x,
self.T.y,
self.T.w,
self.T.h,
G.ASSET_ATLAS[_center.atlas or _center.set],
{ x = 2, y = 2 }
)
self.children.floating_sprite.role.draw_major = self
self.children.floating_sprite.states.hover.can = false
self.children.floating_sprite.states.click.can = false
end
end
tytyy!
then, add this to your card's file, changing values as you see fit (i honestly just changed them randomly until i liked the effect enough)
SMODS.DrawStep({
key = "floating_sprite",
order = 59,
func = function(self)
if self.ability.name == "c_fmod_soully" and (self.config.center.discovered or self.bypass_discovery_center) then
local scale_mod = 0.05 + 0.05*math.sin(1.8*G.TIMERS.REAL) + 0.03*math.sin((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*11)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3
local rotate_mod = 0.1*math.sin(1.219*G.TIMERS.REAL) + 0.07*math.sin((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2
self.children.floating_sprite.role.draw_major = self
self.children.floating_sprite:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6)
self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod)
end
end
})
my god this is uhh
ofc! it should work perfectly, just mess around with those numbers and it'll have different visuals
can i set this function in the "use =" part of a consumable?
unfortunately not from my experience lol
how does gateway do it?
are you wanting it to.. only bounce when used?
oh god
not really, but its the only part that have function in a consumable that i see here
you don't need to put it in a consumable, that codeblock is a hook so you can just throw it in your main file
the second codeblock will go in whatever file holds your consumable, but separate from any other code
wait, this part?
yup, the first can go into your main file at (basically) any point
thoughtt it was a function for the consumable
and the second codeblock, this one, will go into your consumable's file
nope, it's a modification to a base game function so it goes into your main file
i should have been more clear about that, mb
why is my boss blind animation too fast
so this codeblock: goes into main file, main.lua or similar, not attached to any other code
this codeblock: goes into your consumable's file, independent of any other code
and just fiddle with any of the various numbers in the second codeblock to change speed, size modulaton, etc
Okay it's just weird imo that this ican't also spawn as a spectral imo
(i don't actually know what the different numbers do, i just kinda did shit until it looked alright)
If you stuck to that decision
its workingg! tyty!
oh yeah, forgot about that
that could be fun
ofc! it took me way too long to figure that out so i'm glad you didn't have to search so long lol
(I hate swipe typing sometimes. How did 'just' become 'busy')
i'm trying to add a custom colour card, but it crashes the game when the round counter's supposed to go up
SMODS.Consumable {
object_type = "Consumable",
set = "Colour",
name = "col_ellepink",
key = "ellepink",
pos = { x = 1, y = 2 },
config = {
val = 0,
partial_rounds = 0,
upgrade_rounds = 3,
},
loc_txt = {
name = "ellepink.",
text = {
"Converts a random card in",
"hand to a {C:attention}Slimed Card{} for every",
"{C:attention}#4#{} rounds this has been held",
"{C:inactive}(Currently {C:attention}#1#{C:inactive}, {}[{C:attention}#2#{C:inactive}#3#{}]{C:inactive})"
},
},
cost = 4,
atlas = "consumables",
unlocked = true,
discovered = true,
display_size = { w = 71, h = 87 },
pixel_size = { w = 71, h = 87 },
can_use = function(self, card)
return #G.hand.cards > 1
end,
use = function(self, card, area, copier)
local rng_seed = "colours_ellepink"
local blacklist = {}
for i = 1, card.ability.val do
local temp_pool = {}
for k, v in pairs(G.hand.cards) do
if not v.config.center_key == "m_elle_slimed" and not blacklist[v] then
table.insert(temp_pool, v)
end
end
local over = false
if #temp_pool == 0 then
break
end
local eligible_card = pseudorandom_element(temp_pool, pseudoseed(rng_seed))
blacklist[eligible_card] = true
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.15,func = function() eligible_card:flip();play_sound('card1', 1);eligible_card:juice_up(0.3, 0.3);return true end }))
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.4,func = function() eligible_card:flip();play_sound('tarot2', percent);eligible_card:set_ability(G.P_CENTERS.m_elle_slimed, nil, true);return true end }))
card:juice_up(0.3, 0.5)
end
delay(0.6)
end,
loc_vars = function(self, info_queue, card)
local val, max = progressbar(card.ability.partial_rounds, card.ability.upgrade_rounds)
return { vars = {card.ability.val, val, max, card.ability.upgrade_rounds} }
end
}```
-# (most code was copied from orange)
where are the colors for each vanilla boss blind stored?
game.lua
ty
btw i got it working by symlinking: ln -s '/Users/nnmrts/Library/Application Support/Balatro' '/Users/nnmrts/Library/Application Support/LOVE/lovegame'
ok so i can make new consumables but can i make like a different page in collections for enhancements? i have a special type of enhancement that i wanted to have in a different page
there are four stages of crashes
stage 1: basic gray screen
stage 2: game closes without any crash screen
stage 3: blue screen (you fucked up)
stage 4: original love2d crash screen (what the fuck did you do)
i have never seen 3 or 4
only had 2 stages so far🔥
I've gotten the elusive black crash screen before
I've only ever seen stage 4 once and that was someone else's game
ooh nice! i might try that myself now that i have to go and update everything
stage 4 used to happen in almost every instance you see the blue crash now
i wanna see what stage 3 and 4 look like
btw just to keep here in case someeone else needs something similar, i just did
if SMODS.has_enhancement(G.hand.highlighted[1], 'm_mult') and
SMODS.has_enhancement(G.hand.highlighted[2], 'm_bonus')
or
SMODS.has_enhancement(G.hand.highlighted[1], 'm_bonus') and
SMODS.has_enhancement(G.hand.highlighted[2], 'm_mult') then
stage 3 just looks like the windows blue screen
and stage 4 is what you see when a normal love2d project crashes
stage 4 happens if you have a syntax error in main.lua (or conf.lua)
Stage 3 happens if it crashes before colours are initalized
(usually syntax errors in other files)
I could have made it the same colour as the normal crash but I figured it would be nice so you know it crashed real early
I've gotten the "instant crash because of segfault" screen a couple of times
stage 2 I want to fix
I didn't know that there were different stages. that's interesting
I'm pretty sure stage 2 is just the game wanting you to touch grass
I am completely pulling this out of my ass lmao
theres also the lovely panic stage
stage 0?
but there are different types of crashes
or is that stage 1
theres also the cryptid crash card
the love handler shows up before the crash handler can load (it's injected in the begnnning of main.lua so barely ever)
The blue one is just a fallback for when the colours couldn't be got
the insta close is usually a stack overflow but I'm not sure why
So when we customizing the love.errorhandler crash screen?
probs the backing native allocator giving up
adding the Argyle Deck to the error screen
beginning of main.lia
I've gotten stack overflow with an error message before
I think it's actually the stack trace, stack overflowing but I couldn't seem to catch it
I wonder if it happens with luajit2
when i get a crash without a message it's usually because I've created an infinite loop (like when i had a blueprint and leftwards blueprint target eachother)
it may just be a hardware thing
no it's not machine dependant
it's a bug in either the crash ahndler or some lua weridness
so it's not because of the 2gb object limit
we all hate the 2gb object limit
stank
FOR MY EXIT 8 FANS
who the fuck is that
one of my friends
oh ok
oh I found the replicatable test case
eval function _G.live_test() _G.live_test() end then press space
would it be possible to change a joker's loc_text from a joker
wdym
is that a silent crash?
yes
jolly edition from cryptid would be your best bet
an idea for an anomaly i had was it obfuscates a joker's description, would that be possible?
you could profile the game with valgrind
I'm not sure
valgrind doesn't seem to like me
I've had trouble with it too haha
i think i have an idea
I just use x64dbg
how do i get the jokers again
oh actually I think it just slows down lovely a ton
its G.GAME.Jokers right
it's not exsiting with a non-0 status
same it's similar to gamepass
I think its an issue with some lua code
not sure if it's ours or love's
somehow doubt it
or is it tail call optimized
if i remove the smods error handler it does print this ```
INFO - [G] Error: [string "DebugPlus Eval"]:1: stack overflow
stack traceback:
[love "boot.lua"]:352: in function <[love "boot.lua"]:348>
[string "DebugPlus Eval"]: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
[string "DebugPlus Eval"]:1: in function 'live_test'
...
engine/controller.lua:909: in function 'key_press_update'
engine/controller.lua:244: in function 'update'
game.lua:2691: in function 'gameUpdateRef'
[SMODS _ "src/ui.lua"]:84: in function 'upd'
main.lua:1897: in function 'update'
main.lua:999: in function 'oldupd'
main.lua:1930: in function 'update'
main.lua:938: in function main.lua:909
[C]: in function 'xpcall'
but still silently closes
not sure if I removed it the wrong way\
maybe it's love2d explicitly handling stack overflow errors?
this should be pcallable
it gets it, emirt a debug message, and then exirs
I'll need to look through love2d and see what other kinds of crashes it handles. it's made debugging the gamepass version really hard haha
where would i find that in the code?
Reasonsable performance
anyways ```
==250342==
==250342== HEAP SUMMARY:
==250342== in use at exit: 108,737,512 bytes in 47,560 blocks
==250342== total heap usage: 3,755,310 allocs, 3,707,750 frees, 1,341,094,282 bytes allocated
==250342==
==250342== LEAK SUMMARY:
==250342== definitely lost: 1,844,385 bytes in 74 blocks
==250342== indirectly lost: 368 bytes in 4 blocks
==250342== possibly lost: 10,473 bytes in 59 blocks
==250342== still reachable: 106,882,286 bytes in 47,423 blocks
==250342== of which reachable via heuristic:
==250342== newarray : 220,672 bytes in 84 blocks
==250342== suppressed: 0 bytes in 0 blocks
==250342== Rerun with --leak-check=full to see details of leaked memory
==250342==
==250342== For lists of detected and suppressed errors, rerun with: -s
==250342== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
4:54 shorty@Shorty-Laptop:~/projects/DebugPlus:master *>
seems pretty normal? idk how to really read that when I'm this sleep deprived
...actually, on that topic, iirc mods could add something to a given error screen or something?
Yeah
Oh I misunderstood that message I replied to there
However that colour changing mod does change the crash screen colours
Was not speaking of colors changing, but something about adding custom text?
is there anyway to change the name of a blind via code?
I think its part of the localizations
how would i access that?
Idk i just translated stuff before hence why i know
Its a line in the localization file
For each language
Hope that helps
How does take_ownership work on enhancements?
like if i wanted to rework wild cards with a "take ownership" do i have to program everything from scratch with them? or can i just change the "calculate" function and they will keep their name etc
They inherit all old values you font change
oh nice so if i say
wanted wilds to have a 1 in 2 chance of retriggering all i would need to do is just provide a calculate function and change the loc text?
use events
You set it to math.max(1, hands - number)
i see
and not use ease_hands?
good morning Modding Dev
awesome thank you
whats good bro
hey also is there a way to stop things from being debuffed ever
like "wild cards cannot be debuffed by boss blinds" type shit
or would i have to go into the actual boss blinds and work on that
there's a smods function for applying debuffs and it has a key that allows you to turn a card immune to debuffs
hmm, in documentation?
ye
hmm, okay
excellent info, its possible
time to scavenge
masn
i cannot find it
anyone have experince with smods.debuffs?
wait
we good
is there a way for a joker to check what stake youre on
G.GAME.stake?
or something like stone joker except it only appears if you have an eternal joker
hmm
ill see
thanks
you guys can see what im trying to do here yeah
im trying to prevent debuffs if a card is a wild card
but im calling debuff_card wrong
not sure how to actually read this in
That's been done way too many times, have you tried looking at other mods?
or where it should go tbh
wait deadass lol
hmm, i havent yet, not sure where exactly to look
let me paruze
Hook set_debuff?
would this work?
havent played around with hooks yet :wince: how do those work
isnt exactly checking for stake but should work for what your looking for i think
stakes set those as im aware
yeah jic a mod does it
the fire effect, when you one shot a blind
where is that coded
or
more in line. what game object checks your played hands score?
i used three hooks for this one
i figured it out thankfully nw
this is literally all that was required 💀 you cooked tho
No, you should be using SMODS.has_enhancement
oh fr? this isnt really my code so not sure how far it reaches
i dont even think anything can debuff my wild cards at this point 😭
oh hmm
someone else out there has an upgraded lovers
that makes wild cards that cant be debuffed
but regular ones can?
its funky
the humble verdant leaf looking at this unstoppable object
🤔 thats actually not so hard, the upgraded lovers can put a flag on the cards, which the code will see to ignore debuffs
yep
the indomitable wild cards spirit
better?
i might need to check but i think this should also work
def not as in depth as your solution
im gonna test as many boss blinds as possible i guess
whats the default for blueprint compat if i dont set it
@mintymechanic isn't SMODS provide a way to prevent debuff?
iirc true
yeah but those gotta be naturally assigned to cards
besides
we good
they do infact be working
anyway bump
like if your score is 230,000k but your last hand scored you like 200,000 of that
how can i check that 200K value
cause C.chips is set to 230K rn
im trying to check if you one shot the blind
hand_chips * mult, i guess?
nah wait
nvm idk, some mods replace * with ^, some others add new variables like POW to be calculated too so thats definitely not the best way
Hello, question: Is there a way to make so the info queue of any given card is not recursive?
wonderfull thanks fellas
i got no clue, sorry lol. Im sure someone around here is smarter than me tho
Yes.
...and how do?
maybe you can iterate the info queue to see if key already there?
You set it to {key = "keyofthing", set = "setofthing"}
I have this. (the key is the key of the joker itself).
I assume it crashes because it tries to generate the info_queue of the same joker, which in term generates the info_queue of the same joker and so on...
No, it's literally just hand_chips
And mult
I'm pretry sure hand_chips is global
{key = "j_fg_test", set = "Joker"}
That's not the problem
Then what is?
The problem is that it works, but because of that, it tries to generate the info_queue again because the joker has also the info_queue entry.
Let me explain.
You should also be setting info_queue[#info_queue+1]
idk, the fool, for example
ikik, that's not the problem here
Let's say you used the devl before the fool.
That means that the fool, will have in its info queue the devl, but the devil in term has in its info queue the description for gold cards.
Thus, when hovering over the fool, it generates BOTH 'elements', and not just the devil description.
I need something that does just that. Adds the entry to info_queue but not subsequently whatever you added might have in its info_queue.
I provided you with the solution?
try
local contains
for _, q in ipairs(info_queue) do
if q == G.P_CENTERS.j_key then
contains = true
break
end
end
if not contains then
info_queue[#info_queue+1] = G.P_CENTERS.j_key
end
checking
No?
nope
{key = "j_fg_test", set = "Joker"} should grab the localization for the joker and show it, but not get the other info queues?
Game freezes because it seems to repeatedly generate (and add) new entries to the info queue
if not card.fake_card then
The problem is that that logic is done inside the generate_card_ui function, which is what I believe responsible for making all these things work.
Literally at the very end of the file.
~line 2740
.
wat
rq yall know how to get rid of that "+5 chips"
its not even scoring the 5 chips it just says 5 chips lol
holdon
perma bonus maybe?
owers
Did you try it though?
nah its cause its a 5 of spades enhanced to a stone card
like i said its not even doing the shit
...that function is inside balatro so uh... that is my guess.
Knowing how it applied retroactively.
I have no clue what you're trying to say but it definitely works:
azaming
then idk
info_queue[#info_queue + 1] = G.P_CENTERS[this_joker_key] did not work
Yes, but that's not what I'm telling you to do?
@stiff locust
this is the ssecond time i'm being pinged for this
yeah yeah i get it anti tsunami
i have no doubt it will happen more times
Want to be pinged a third time?
Now more questions: Is there a way to use this function without nuking the target card's previos values?
-# i.e. I just want to add a line to loc_vars
In what way?
SMODS.Joker:take_ownership('joker_key',
{
loc_vars = function (self,info_queue,card)
-- my own bs code
end
-- Somehow keep here the card's original code
},
true
)
idk
Maybe you could patch it instead?
^ dumb idiot brain right here
Or are you thinking that all of the cards code will be overwritten if you just change the loc_vars
As far as I know, that function nukes what was previously there and replaces it with the new bs you tell it.
In that case, it would just noke loc_vars completely.
As long as you only replace loc_vars it will only change loc_vars?
But I kind of want to keep every card's original loc_vars
I just want to add A single line of code.
Patch it?
no fucking idea how to patch
what is the enhancement version of set_seal?
Probably just set = "Tarot" | "Planet" | "Spectral" | custom by your mod
If I am getting it right.
set_ability?
it works the same way right?
No, you put G.P_CENTERS["m_key"] instead.
ok, but how do i work poll_enhancement in there?
card:set_ability(SMODS.poll_enhancement({})) I think.
aight, thanks
is this the correct way to load mod files? I have no idea
those are consumable sets? I don't see the connection
Why are you passing a second input?
seems to think files need keys?
yeah.... they don't
wait...
I didn't read it
uh I saw this in the smodded repo
what does that even mean?
Also why do you have a JSON and a header?
why is it all the same?
the id is passed on its own I think
but I'm talking out of my ass again
it's for smods to load the main file of mods
is it possible to get multiple shaders to appear on a card, mind you i have no idea what im doing but this is my code it doesnt error but nothing happens, and im betting i should use drawstep or smth but have no clue onhow to do that
honestly I forgot where the json come from already
SMODS.curent_mod.load_file()?
oh yeah if you're looking in smods code, make sure you're actually looking at the function defintion
not just where it uses its own function
No, It's just SMODS.load_file()()
alright so what do I have to do to load all my mod files?
just load them with SMODS.load_file(path)
pretty sure
SMODS.load_file() return is a function maybe?
is there an easy way for me do read balatros code so i can get an understanding of how jokers and stuff work
like lua loadfile() result
could you give an example of what path can be?
it's relative to the main folder
lole it'd just be "xyz.lua" if it's in the main folder
or "/src/xyz.lua" if it's in a folder called src
the leading / might not work in lua, idk
i'm used to writing it in linux
so based on this it would just be SMODS.load_file("BalatroTweaks.lua")?
and you need to ad () to the end we learned
so SMODS.load_file("BalatroTweaks.lua")()
I think that caused my game to crash
Yes, but no because that's the file your loading them from.
oh yeah you don't load itseld
itself
you put the main file in your json metadata
there's a field that asks what the main file of the mod is
that's where you put "BalatroTweaks.lua"
And in BalatroTweaks.lua you load everything else
My ass thought that :add_to_deck() would return cards to the current deck but it actually moves them to the full deck. Is there an intented way to move cards to the current deck?
and it's fine if that's all the file is
oh yeah. I did not have that json file
No? That function is used when the card is obtained?
as in it's fine if all your main file does is load the actual files
Where do you want to move them from?
Baaah wordiing. I used it to return cards from hand to deck but it functionally discards them
once you have the json file set up, remove the mod header
it's redundant and will break things
question, does your metadata file have to be titled [id].json, or will it just pull from whatever json is in the root?
I guess it won't even know the id without reading the json
so the filename can't matter?
My metadata file is named... ||metadata||
so my original implementation? minus the 2nd param #💻・modding-dev message
yes, and adding the () on the end
and removing the header
it's what myst said so I just repeated it
i don't assert
what's asserting?
If something inside assert() returns false it will force crash the game.
It's usually to know if something didn't load right.