#💻・modding-dev
1 messages · Page 609 of 1
tks bro <33
figure out which mod it is
But you can also employ what I call The Sims method:
Take 50% of mods and set them aside in a separate folder, test. No crash? Add some mods back in. Rinse and repeat until your bad mod is found.
im using the balatro mod manager, i can just turn off the mods right?
yep!
thanks
is it okay if I load it as it's own file after another?
You can have a UI.lua file. That's acceptable.
is fixed on later versions of handsome devils
do you know if there's any way to see the chips of the currently played hand before it's added to the total score? bcause if that's possible I could just add them up in my check and that should fix it.
what if you just multiplied chips and mult
theres a function for it now
since scoring calculations exist
i forgor what its called exactly
Wait, I think I have it in the wrong file
(couldn't read it)
apparently not
So, I'd want a custom spectral card to remove a joker slot when used, how would I go about that?
SMODS.calculate_round_score()
G.jokers.config.card_limit = G.jokers.config.card_limit - 1
Can I have some help?
{n = G.UIT.R, config = {w = 400, h = 100, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test', colour = G.C.BLUE, padding = 0.15}}
}
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test again', colour = G.C.BLUE, padding = 0.15}}
}
}},
{n = G.UIT.R, config = {w = 400, h = 100, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test once more', colour = G.C.BLUE, padding = 0.15}}
},
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test for the last time', colour = G.C.BLUE, padding = 0.15}}
}
}}
}}```
Says the following error
what would I want that in? 1st time modding a consumable 😅
yeah thats an issue with your code not it being a seperate file
The use function definition.
you forgot a bracket somewhere
or did some other wierd thing
but ui is nested table hell so its hard to read where the issue is
Its just a reworking of the UI example in UI guide... How'd I break it?
Might not know about n?
n is near {
like this?
use = function(self, card)
G.jokers.config.card_limit = G.jokers.config.card_limit - 1
end
well that isnt going to cause issues
Well I don't know the issue, the bracket's closed.
nothing's before it
That's the localization file
I meant my json file
Should be, yeah.
gimme a second...
assert(SMODS.load_file("src/Challengecode.lua"))()
assert(SMODS.load_file("src/config.lua"))()
assert(SMODS.load_file("src/Elemental.lua"))()
assert(SMODS.load_file("src/Pack.lua"))()
assert(SMODS.load_file("src/Edition.lua"))()
assert(SMODS.load_file("src/just_the_splapp_boss.lua"))()```
7th line here
this and the json file are named the same, barring capitalization
which 2 variables would that be then? I've tried a few variatons of G.GAME.chips, current_round.current_hand.chips, chips_total etc. but none of those seem to be the right one.
found them
Yeah, and the json file's fine. I just stressed myself and said that instead of this
also here you have some double closing brackets after some configs which should be moved to the end of nodes
well one of them
Which one
every G.UIT.C
tks bro
{n = G.UIT.R, config = {w = 400, h = 100, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test', colour = G.C.BLUE, padding = 0.15}}
}}
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test again', colour = G.C.BLUE, padding = 0.15}}
}}
}},
{n = G.UIT.R, config = {w = 400, h = 100, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test once more', colour = G.C.BLUE, padding = 0.15}}
}},
{n = G.UIT.C, config = {w = 150, h = 50, colour = G.C.WHITE, padding = 0.15}, nodes = {
{n = G.UIT.T, config = {text = 'Just a test for the last time', colour = G.C.BLUE, padding = 0.15}}
}}
}}
}}```
Like so?
where?
after the first G.UIT.C
also do you not have the vscode lua extension or smth
it should definitely tell you that
STILL BROKE!!!
how so
well it broke a line earlier so like idk
it doesnt appear like you changed anything there
All I did was clear the opening blank line. It breaks on the first character, it might be the n
it always has a red line under it in the editing software...
that n at the top
well
theres clearly something wierd going on
since it should be green normally
as in the text colour of every table element
none of the other n's have that
How did I break it? I copied it from the UI guide!
yeah your issue is that you arent assigning the whole thing to a variable
currently youre just dropping a random table in the code
Oh. So remove the outmost paren?
like ui_v?
what
you said set it to a value, can I set it to that?
variable
i meant assign it to a variable
its your mod though you can name your variables whatever you want
Set that first in the file?
just start the file with <something> = <the whole ui table>
Okay, Balatro is opening. How do I check if the UI works as it should?
Because, if it's half the nested table hell you claim it to be, I should check it every edit!
i mean its more just dont ever hit format document or vscode expands the entire thing to all hell
it shouldnt be an issue outside of being hard to read
Well, how do I see if my UI coding works?
idk how to just create ui though all ive done is like a mod config tab
though you could just return it in SMODS.current_mod.config_tab for testing ig
probably not the best method but thats all i know
You know anyone versed in UI?
I'll ask around. (and try not to be a bother)
Sorry to jump in but my consumable is not working, I'm trying to make it so it enhances a playing card to my modded enhancement
config = { max_highlighted = 1, mod_conv = 'm_DRY_oddity' },
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
return { vars = { card.ability.max_highlighted, localize { type = 'name_text', set = 'Enhanced', key = card.ability.mod_conv } } }
end,
Hmm. I think I have similar consumables, hang on.
local xiferp_up_a_step = SMODS.poll_enhancement({guaranteed = true, type_key = 'shuffletheseed'})
local card_to_change = pseudorandom_element(G.hand.cards, 'shufflethedeck')
G.E_MANAGER:add_event(Event({
func = function()
card_to_change:set_ability(xiferp_up_a_step, nil, true)
return true
end
}))
end
}```
Mine looks like this, but this changes a random card to have a random enhancement
how's this?
What part isnt working, it looks just fine
I click on the card, and can use the consumable, but does not apply the enhancement I need. I know they key is right though because I reference it earlier
Does it just apply a different enhancement?
It doesnt apply one, from what I can see at least
Does hovering over the enhanced card show anything
No
Huh
I use it, applies its use function, but does not change the enhancement
the use function works, but the applying part doesn't?
there isnt a use function because it uses the built in functionality i assume
It does the reverse, does the use function but not using earlier code
I'll check without the use and see what happens, hold on
Its the use function.
If I have a card changing enhancement and also has a 'use' built in it bugs out
???
Well adding a use function overrides the default automatic mod_conv functionality
So that might be it?
Has to be
i had an idea for a joker but i dont know if it would be possible so uh...
is it in anyway possible to get lovely to detect webcam data?
How would I go about putting that same code in use then, since that seems to be required
Uhh probably, but why, if I may?
I was gonna make a joker where you had to express a certain emotion, and it gives mult based off of how accurate you were
If youre doing something else alongside enhancing you could copy over the enhancing code that vanillaremade has for the enhancers (should be in the commented out use functions)
That.. seems impossible, or at least seems like a lot of coding.
I mean software for detecting expressions already exists tbf
I'll check that out, thank you!
then how about making Balatro see your face in real time?
🤷
I would (most likely) have to make my own RNN and train it, or find one coded in lua
Webcam is probably the hard part but i cant imagine its entirely impossible
I mean, it's an app. Jokers have seen other apps before.
(There's a joker in one mod that gives xmult per crash log)
thats FILES, not apps
-# i too have a joker which accesses, and actually deletes files if you have them in a folder it tells you to make
-# it then gives ^mult based off of file size
-# good joker goodness!
i would need to find some sort of camera library
does someone have the link for that github page that explains how to publish your Balatro mod?
I need it cuz there's also some other information I need for my mod
like what exactly?
works, thank you! :)
Can't wait to see Scienceful!
this is not the page that explains how to publish your own mod
it's an introduction page on how to make your mod
https://github.com/Steamodded/smods/wiki/Mod-Metadata You need mod metadata?
I'm pretty sure you can just like... upload it to github and that works?
It's not that but there was a specific QnA of that page where I could get more info about some of the SMODS functions that aren't in the documentation
I have no idea where I should be looking
how would i do sin cos and tan in talisman?
Anything in specific you're missing?
How to immediately make a specific joker lose the run
there was that info in the FAQ
Oh. That's, easy. I don;t know what that command is, but I know it's somewhere. Lemme try to find it
I don't know where to find it
What is the default in a SMODS.ObjectType? It cant be an icon, is it?
there ya go, thx
it was this page
yw! can't wait to see the mod!
thx!
yw!
does the game keep track of a list of jokers sold in a run?
afaik no
You can check if a card is sold though
i noticed jokers in the cryptid mod call G.GAME.jokers_sold but that seems to be a list made by the cryptid mod
This crashes whenever I get to the end of the shop. I think the problem lies at the SMODS.add_card, but I'm not entirely sure.
It also fucks up rendering too when it crashes, probably because it makes a Negative
is the game coded so that the first shop always has a buffoon pack?
I think so
I have created a joker that stores sold jokers. The joker is functional except that it crashed when duplicated through means such as ankh or invis. The sold jokers are stored in a table in the config
config = { extra = {sold_jokers = {}} }
This is the section that adds jokers to the table
if context.selling_card and (context.card.ability.set == "Joker") and not (card == context.card) and not context.blueprint then
card.ability.extra.sold_jokers[#card.ability.extra.sold_jokers+1] = context.card
end
The error code is a stack overflow, there is some infinite recursion or loop. Do you know why this is happening, or how I could avoid it?
can you send crash screenshot?
all good, im just lost, maybe the copycard function breaks if theres too much in the config
will work on a workaround implementation
did you test it with the ankh?
ankh and invisible joker
because invis joker being sold and your joker copying it might be a problem but if the ankh also does it than thats not it
So I got a general idea how the change information on a card, yet for some reason my game crashes on open. Any help??
key = 'manufactured_darkness',
set = 'Spectral',
loc_txt = {
name = 'Manufactured Darkness',
text = {
'Enhances {C:attention}#1#{} selected',
'card into an',
'{C:attention}Oddity Card,{}',
'{C:red}-1{} Joker slot'
}
},
atlas = 'oddity_card',
pos = { x = 0, y = 0 },
config = { max_highlighted = 1, mod_conv = 'm_DRY_oddity' },
loc_vars = function(self, info_queue, card)
if #SMODS.find_card("j_UTDR_shadow_crystal") > 0 then
return {
key = "c_DRY_manufactured_darkness_crystal",
vars = { card.ability.max_highlighted }
}
end
info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
return { vars = { card.ability.max_highlighted, localize { type = 'name_text', set = 'Enhanced', key = card.ability.mod_conv } } }
end,
-- So the name changes
key = "manufactured_darkness_crystal",
loc_txt = {
name = "Manufactured Darkness",
text = {
'Enhances {C:attention}#1#{} selected',
'card into an',
'{C:attention}Oddity Card{}',
}
},
no_collection = true,
in_pool = function(self, args)
return false
end,
can you send full joker code?
you can dm it to me if its easier for you
yeah
SMODS.Joker {
key = "oath_of_vengeance",
blueprint_compat = true,
atlas = 'dnd',
rarity = 4,
cost = 10,
pos = { x = 1, y = 1 },
loc_txt = {
name = 'Oath of Vengeance Joker',
text = {
"This Joker copies",
"the abilities of all",
"{C:attention}sold Jokers{}"
}
},
config = { extra = {sold_jokers = {}} },
calculate = function(self, card, context)
local effects = {}
if context.selling_card and (context.card.ability.set == "Joker") and (not (card == context.card)) and (not context.blueprint) and context.card.blueprint_compat then
card.ability.extra.sold_jokers[#card.ability.extra.sold_jokers+1] = context.card
end
--edited out for debugging
--[[
for index, joker in ipairs(card.ability.extra.sold_jokers) do
print("Adding effects")
effects[#effects+1] = SMODS.blueprint_effect(card, joker, context)
end
return SMODS.merge_effects(effects)
]]--
end,
}
okay so i checked the copy_card thing
and i think its just too much to copy a whole card
maybe try storing only the sold joker key
on your joker
and then use the key
you shouldn't be storing whole cards inside other cards anyway
maybe look into how ortalab handles pinkprint (it copies the effect of the most recently sold joker)
haha
do you guys know if there is a way to use lovely patch to patch into every line that matches?
with the pattern
i think that happens already?
Any help here? I have done something similar with Jokers and it was just fine. This one's not working for some reason though
wait what do you want to do exactly?
you make to want a new card thats called manufactured_darkness_crystal
?
remind me, do i call SMODS.Game_Over() to instantly force gameover or 
i forget how to do
nvm, you just set the state
This is a spectral card, I just wanna change the name and description
In my case that wouldn't work, I wanna change it when a specific joker is in your joker slots (this being the shadow crystal in the code)
delete them and write what you want it to say
oh i dont know if you can dynamicaly change the name / key so im useless here sry
So if the player doesnt have the Joker, its the base I have. If they do have it, I wanna change what it says, hopefully that clears up what i mean
move to localization files
all good :)
then you can have the normal key and the special key separately
I have had that recommended but I also found an easy way with Jokers, so figured I could copy paste that. That being:
-- Card 1
loc_vars = function(self, info_queue, card)
if math.random() < 1/615 then
return {
key = "j_DRY_Westville",
vars = { card.ability.xmult_gain, card.ability.xmult }
}
end
return { vars = { card.ability.xmult_gain, card.ability.xmult } }
end,
--Card 2
key = "Westville",
loc_txt = {
name = "Not Westville :D",
text = {
"Gains {X:mult,C:white}X#1#{} Mult for",
"{C:attention}each{} discarded card",
"{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)"
}
},
no_collection = true,
in_pool = function(self, args)
return false
end,
there's no reason to initialize a whole other joker though. localization files are what you should be doing anyways
Noted, thanks
Hi friends! I'm getting this crash every time I click the options button for the Talisman mod. Is there a way to fix it?
how old is deckcreator and esz's pokelatro
wait thats your mod nvm
how old is deckcreatpr
try disabling that
still crashes
update talisman and debugplus
i installed talisman pretty recently
well i reinstalled debugplus and it still crashes
where does your mod mess with ui
wdym "mess with"
do anything with ui
i don't think my mod does anything with UI at all
disable your mod
unless joker descriptions also count as UI
still crashes
although mind you it doesn't crash on startup
it only crashes when I select "config" for talisman
ok another interesting development
so i've been having trouble with the game's intro playing the audio tracks one at a time
and the audio acts weird when i open the game
but when i disable MY mod it stops doing that
which is veeeeeeeery interesting
you probably have some code somewhere messing with audio
if i sent you a copy of the mod, do you think you could figure out what's making it happen?
what
Oops! The game
gen alpha officially btfo'd
This line crashes the game if I hover over the Joker outside of the game, because #G.vouchers.cards is nil
Defining it as (#G.vouchers.cards or 0) also crashes it
u need to check if G.vouchers exists prior to checking G.vouchers.cards
In the loc_vars area?
yes
Makes sense
so
local voucher_count = 0
if G.vouchers then
voucher_count = #G.vouchers.cards
end
There should be more jokers that do something when you buy vouchers
true
in general, within loc vars functions you should never assume that a card area you are checking is not nil
is it possible to make a skip tag not appear twice in the same ante?
Oops! All games
Anyone know the sound code for glass breaking?
You ain't the only one.
Making a piggy bank joker and I want it to make a shattering noise when its sold or destroyed
I've been rooting through Balatro's files, and all I could find were six files named glass1.ogg through glass6.ogg. I don't yet know what event calls them forth.
Interesting, so maybe the game picks randomly every time glass breaks
I'm just gonna pick the one that sounds the most like a piggy bank
Right now glass2 is looking pretty good
are redeemed vouchers stored in a cardarea and if so whats it called
unless it is g.vouchers and i just did something else wrong hold on
Hi friends. Is it possible to hide a joker from the collection?
to make it not show up in the collection?
exactly
no_collection = true
Say, any button-coding tricks?
Or any mods that mess with the UI?
you need to be SO much more specific
is there any way to check if a red seal actually retriggers anything when held in hand at end of round? it works just fine when a hand is played if the card isn't steel (doesn't return a trigger) but it always returns a trigger at end of round even if no effect is actually triggered
this is an existing cardsauce feature but I pushed it in an SMODS PR because it requires overriding vanilla code and it might as well be centralized
Making a chip version of Loyalty Card, how would I get the number of hands remaining to work in the text? #2# returns 1 greater than every and #3# returns an error
key = "Martlet",
loc_txt = {
name = "Martlet",
text = {
"{C:chips}+#1#{} chips every",
"{C:attention}#2#{} hands played",
"{C:inactive}#2# remaining{}"
}
},
config = {
extra = {
chips = 134,
every = 1,
birdbrain = 1
}
},
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.chips,
card.ability.extra.every + 1,
localize { type = 'variable', key = (card.ability.extra.birdbrain == 0 and 'bird_play' or 'bird_forgot'), vars = { card.ability.extra.birdbrain } }
}
}
end,
Hotfixes galore......
is there a simple way to set the Showdown Blind of a Challenge to a specific blind?
for example, i have a challenge themed around moving jokers around all the time, so i want the challenge to always end with Amber Acorn or Sorrowful Styx. i know i could ban all the other blinds, but that doesnt account for blinds added by other mods
I was curious is there is a way to reverse pareidolia so that face cards score as nonface cards, (10s) but I can't find anything
Prosopagnosia is an Uncommon Joker which causes all cards to count as number cards.
hey guys i made a deck using jokerforge how do i port it into the game
G.GAME.perscribed_bosses[G.GAME.win_ante] = "blind key"
put that in the challenge's apply function
you may have to put it in an event to make it wait until prescribed bosses exists
i don't think anything in vanilla actually uses that feature, but it's completely assembled and functional
???
i dont speak spaghetti code someone help LOL
what does this mean
it means you typed your brackets and/or commas incorrectly
i didnt code anything myself i just exported the thing from jokerforge
or possibly you put an equals sign in the wrong place
okay, then joker forge did that
you might want to actually look at the code somewhat
i opened the script that was shitting itself in vscode idk what any of this means
as you can tell idk shit about lua or any programming languange lmao
on line 19, you should -
what exactly is that supposed to be doing, actually
it looks like it's trying to reduce the money per hand by 5% of the money on hand
the deck has the gimmick of every round a negative card gets added to your slots at the cost of removing 20% of your round profits
this is what i coded it to do
okay well
that code's syntax is entirely wrong (you can't do variable assignment inside a return), and also wouldn't do that if it was fixed (you are modifying the "you get $1 per spare hand" variable, not the cash out total)
ohhhhhhh okay
thanks i'll try that
so i shouldve used this instead right
no, that just changes money directly, like hermit or wraith does
i don't think the thing you're trying to do is within joker forge's capability
o
ill try it anyways
since its set to when the round ends
oh wait that fixed it what
no it didnt LMAO
the game opened but when i tried going to the deck i made it crashed
you defined an atlas wrong somewhere
did you define an atlas named "Deck" anywhere in your mod
found it
do you know what the phrase "create an atlas" refers to?
idek what an atlas is LOL
assume you didn't do it, then
it's looking for the atlas yourmodprefix_Deck and not finding it
presumably because you never created it
so i should replace it with this
no
did any of what you did look even a little bit like what's going on here?
lemme read this rq
are you asking does the file structure look the same between the doc and the files?
because if so then yeah
does the text SMODS.Atlas appear in any part of your mod's code
yeah
okay
is that all of them? because none of them are "Deck"
seems it yeah
one of them is CustomDecks
did you, perhaps, want that one?
i assume that is what would allow the deck to be functional so yes
well it's an atlas that exists, instead of an atlas that doesn't exist
so i should replace this with CustomDecks?
well, i specifically drew your attention to that one, so i'm thinking probably
y'know, unless you gave your atlases misleading names on purpose
okay so it worked but uhh LOL
yeah you gotta put your own line breaks in
please invest in linebreaks
okay aaand in playtesting the decks abilities doesnt even work
awesome
man this looks so fucking sick
it's redundantly checking for the back key (it's in the back's calculate function, other decks will never get to that point anyway) and checking for the wrong key (it's using jokerforge's default placeholder mod prefix instead of your actual prefix)
so how do i fix dat
do you like
know what an if statement is
remove the if statement i described, which is both unnecessary and broken
(also remove the corresponding end, because that's how lua formats if statements)
are you talking about this
yes
holy fuck it worked
lfg
thats awesome dude
oh yeah i should probably make some art for this
Watch negative deck kinda works by genevanougat and millions of other Balatro videos on Medal. Tags: #balatro
im so happy
the money removing doesnt work but omg i love this
That's certainly some localization
okay im realizing now with how easy it is to get money anyway with the negative jokers by selling them i think i should just remove all post round profits
like
its actually a joke lmao
okay i changed up the coding a bit
i decided to make it so the money just gets set to 0 at the end of a round
if need be i can change it no problem
uhhhh what did i fuck up
i tried investing in likebreaks and it linebroke the entire thing
did bro just get hacked or smth
@terse merlin @mystic river hlep
you have to put commas between items in a table
which in this case refers to the individual lines
so like that
yes
except not in the last one i assume
some languages would freak about an extra comma at the end but lua is fine with that
okay so im not entirely sure why the money resetting isnt working
this if statement should be handling that but it doesnt for some reason
actually wait a sec
nvm
okay i changed it to this but it didnt fix anything
soooooooooooo idk
better ss
Is the context actually called shop_is_entered?
It wont crash if a bool is false
shop_is_entered is set to true tho
context.shop_is_entered isn't a thing
okay thatd explain my dumbassery
you could check for when stuff in the shop is generated and then do something depending on if thats what you need
yea but minor problem
or you could check for if G.STATE == G.STATES.SHOP
this is the first time ive ever coded w lua
so i have next to no clue what im doing
well what are you trying to do?
for the deck im making im tryna set the money to 0 when the shop is entered
since the gimmick of the deck atm makes it a joke to get money
then id go for
if G.STATE == G.STATES.SHOP then
--code to set money to 0
Im sure theres a context for entering the shop but I dont have SMODS code available rn
wait so how do i make a variable change its value in an if statement like this
is this correct
Also lua tip, to check if a boolean is true, typing "== true" is redundant
For == false you can do "and not context.blabla"
i assume this would be good right
Shouldnt it be >= 1 if you're checking for greater or equal?
G.GAME.dollars is the value for the money btw
yea im tryna set the value to 0
current_dollars is G.GAME.dollars
Oh wait im stupid
Context.main_eval will always be false if you're checking for entering shop
Remove that context check
ohh okay that makes sense
The game over one is useless too
me when i game over in the shop so i can't lose all my money
^
no dice
code update btw
Replace the whole boolean check by "if context.starting_shop then"
Watch oops by genevanougat and millions of other Balatro videos on Medal. Tags: #balatro
i felt like thatd be funny enough to get a clip of
this was the error
chat help me
one of my jokers is ignoring eternal
like you can sell it even when its eternal
and i dont get it
@maiden phoenix
i think this whole thing could be simplified to just this if its always going to remove your money
if context.entering_shop then
G.GAME.dollars = 0
end
yw
ty
it kinda does it in a weird way where there isnt an animation for losing the money it kinda just
immediately sets itself to 0
but thats a problem for future me
No, ```lua
if context.starting_shop then
return {dollars = -G.GAME.dollars}
end
yeah that would fix the display thing
anyway how do i use these new localization things for editions
do i just remove text and then put those in the localization somewhere or?
well i thought it would
@daring fern
Do you have Talisman installed?
i guess you could do the thing you were doing before and get the current_dollar value then ease_dollars(-current_dollars) instead of doing the return thing
yea
Thats why its crashing
i see
It turns G.GAME.dollars into a table
nice
holy fuck im so happy rn lmfao
this is the first thing ive ever coded to actually work
w
well it wasn't that
Editions are set in their own table under descriptions
return {
descriptions = {
Back={},
Blind={},
Edition={},
Enhanced={},
Joker={},
Other={},
Planet={},
Spectral={},
Stake={},
Tag={},
Tarot={},
Voucher={},
},
ah
so why is it not showing the playing_card text?
I assume it's due to the sprite being larger than the default 32x32 a blind is, but I'm not sure how to resolve this issue of scaling. Anyone have any insight?
It does properly scale on the blind selection and the blind collection screen
would it work to just scale it down to blind size?
I'm not sure how I'd do that with it only affecting the blind during the round
I suspect I'd just need to patch something as the file gets loaded with an incorrect preset somehow, with the 32x32 being hardcoded in somewhere
It'd really mess up the sprite, so I'd have to redo it, but I could maybe look into having the hands be separate sprites, and just faking it 🤔
damn
what am i doing wrong here?
does anyone know how to make gradients
What is your SMODS version?
SMODS.Gradient {
key = 'key',
colours = {
colour1,
colour2,
colour3,
},
}
so heres my entire to-do list for this mod that is very much not finalized so much more is gonna get added onto here
why am i getting this crash?
SMODS.Blind {
name = "myBlind",
key = "myBlind",
discovered = true,
atlas = "blindatlas2",
pos = { y = 13 },
dollars = 5,
mult = 2,
boss = { min = 2 },
boss_colour = HEX("67533D"),
calculate = function(self, blind, context)
if not blind.disabled then
if G.play.cards and context.before then
for i, c in ipairs(G.play.cards) do
local t = pseudorandom('bc_mule', 1, 2)
if t == 1 then
SMODS.modify_rank(c[i], 1)
else
SMODS.modify_rank(c[i], -1)
end
end
end
end
end
}
quick question, if this is the context for creating a card then whats the context for destroying a card?
@maiden phoenix you know your shit with lua help me out here pls lmao
context.remove_playing_cards
okay gotchu
context.removed being the list of removed cards
that didnt work lol
whats the code
probably because youre calling it as a function
do i add context. before it
im tryna make it so when you play a card it destroys a random card in your deck
while giving xmult
yeah thats what i asked for up here
also create_playing_card isnt a context its a function
i misread this lmao
i need it so i can destroy the random card
if you want the function for destroying a card then its SMODS.destroy_cards(cards), with cards being either a single card or a table of cards
alr thanks
so would i have to do smth like this to destroy a random card in the deck
or hand rather
where is random defined
sry if im asking too many questions i literally have never touched lua a day in my life before this
nowhere i just assumed random was a universal variable since the game works off rng
use pseudorandom_element(G.hand.cards, "seed") to get a random hand card
seed being whatever as long as its unique
so i can literally put seed as a random set of numbers and letters and itd be fine
yeah
alr
though usually people do have an actual naming convention for seeds
also if theres anything in vanilla with a similar function to what youre trying to do you should check it out on vanillaremade https://github.com/nh6574/VanillaRemade
oh for FU
probably remove the whole thing in the ({ after the destroy_cards call
because thats probably not doing what you want it to be doing
can you just show the full code
also you should probably get the lua extension for vscode if you dont have that yet
i added the things back since those messed it up more
i should prob do that
its pseudorandom_element(G.hand.cards, "seed")
oh wait do i need those "" around the seed
theres also
a bunch of stuff from when you still had create_playing_card there
also you should definitely do all this https://github.com/nh6574/VanillaRemade/wiki#3-set-up-the-lua-lsp
ok but its very useful when youre new to coding
okay with the lua extension it now says the 'G' is an undefined global???
yeah read further in the thing
G is something from balatro and it doesnt know about things from balatro
thanks vscode
how tf did i miss those LOL
idk lmao
but then you should be able to go into your mods folder and copy paste the file paths for steamodded and lovely/dump into there
and then replace all the slashes because windows uses the opposite one for some reason
where exactly
in place of the path to smods and lovely dump
you can click on the file path at the top of file explorer to copy it
is the file complaining about the slashes by any chance
this is my mods folder what do i have to move into where
oh
i havent even ported the things over yet
no like the balatro mods folder
copy the file path of lovely/dump and steamodded
okay then what
then put them in that settings file
what settings file im so confused lmao
the one you created
this one
oh right yea
because for some reason windows uses backslashes in file paths
well idk if its a windows thing
but its annoying regardless since JSON considers backslashes an escape character
i just did it manually
it should be okay now right
works too lol
yeah
it might take a short bit but itll eventually recognize more variables
okay back to the variables to the jokers i think the problem might lie in these
you should be able to do just SMODS.add_card{ set = "Default", area = G.hand } in the event and itll do all the emplacing and G.playing_card stuff automatically
im gonna lose it
show the full code
remove all of this
how theres this
show more
what is above that
all dis
alr
also SMODS.add_card should be inside the function of the event here
oh gotcha
also you can remove the G.playing_card stuff and the emplace and materialize
since SMODS.add_card does basically everything related to creating cards for you
yeah just remove all the stuff thats doing things with new_card
since it doesnt exist anymore
yeah it does?
SMODS.destroy_cards doesnt return anything
also probably remove the SMODS.add_card because i thought you were still trying to create a card
well its more like
SMODS.destroy_cards doesnt pass out any value to assign to new_card
okay how do i disable this annoying ass backspace system
hit insert on your keyboard
do i get rid of that entire line or
just the add_card
yeah the whole line
anything else
there shouldnt be
IT WORKS
YIPPEEEEEEEEEEEE
tysm dawg i appreciate you putting up with with my tiny square brain
joker made 🎉
its alr lmao
Watch hitman joker by genevanougat and millions of other Balatro videos on Medal. Tags: #balatro
note to self: learn lua before trying something that requires having learned lua LOL
i mean first time for everything
fair
you only get better at it from here
quick question:
how do i make it that it gives the same amount of money as the number of round winned with the first most used joker
local temp_count = -math.huge
for k, v in pairs(G.PROFILES[G.SETTINGS.profile].joker_usage) do
if G.P_CENTERS[k] and v.count > temp_count then
temp_count = v.count
end
end
return {dollars = temp_count}
ok ill try it
is there a table where all the cards in the shop are
G.shop_jokers.cards, G.shop_vouchers.cards, G.shop_booster.cards
ty
i thought it would give me 41 dollars, not 50?
joker_usage still has data from mods you no longer hav installed iirc
that's true
but is there any possibility to make it that it check's if the first most used joker exists?
you can check if its key exists in G.P_CENTERS i think
would this work for a gradient
am trying it
also dont put another if
soo like this?
it should just be G.P_CENTERS[v.key]
ok
im tryna make a gradient that goes between pink and red
(also do gradients work in descriptions?)
No, just put the HEX in the colours
Yes.
uhhhhh....
like this?
ok now it works
now i just need it to put the entire code like this:
😨
because am adding global stats gamevars to Joker Forge
will it work?,
let's find out
No, you need to return temp_count
my edition's shader seems to be hiding the rank and suit of playing cards its applied to?
so now it works right?
No, outside of the for loop.
alright
now it works
thank all of you at the moment
and now i need to figure out how to do that with the most used joker in the middle
?
It's just c not c[i]
how can i access the cards created from booster packs
Besides gimp or photoshop, does anyone recommend any software for creation for joker sprite sheets?
aseprite or libresprite
LibreSprite is a free and open source program for creating and animating your sprites.
G.pack_cards.cards
ty
Anyone know how to make a button?
create_UIBox_generic_options
...that all? Do I add a function?
its a function
that makes a button?
heres a snippet of code that should allow you to understand a bit more
back_delay is incase you want the button to be disabled for some time
back_label is for its text
the contents.config is to determine what it will close
if its a back button
n is the type
you can see more types in G.UIT
I just want a basic button that either ends the game on the spot or disables the boss it's in.
any changes?
it needs a button value in the config
which is a string reference to a function in G.FUNCS
and determines what happens when you click the button
yeah
and like you can get it to pass arguments into the function with ref_table or ref_value or whatever but idrk how that works
Got it. I already made the base UI to stick the buttons in, so... that's almost everything handles for the Impossible Boss
(just need to make sure G.FUNCS points to the right value, make sure the buttons show up and work)
(and also disabling any scoring hands, but that's the Psychic extende)
how can i temporarily lock the game speed at X ? (for a blind)
for that i think i should use the value "order"
Hey guys heres something a bit complicated, what if i want to make a stat that manipulates certain cards/enhancements description and stats
check how yahimod does it (VIBE is a boss blind that sets game speed to 0.25)
alr
No, that's just where it is in the collection.
ah...
then how do i do that?
my edition's shader seems to be hiding the rank and suit of playing cards its applied to? what might be causing this/how could i stop it?
it's count then?
How would I get a random consumeable type and a random consumeable from that type pool?
i think SMODS.ConsumableTypes has all of them
but also there's the Consumable pool that does that
pool is called Consumeables iirc
Trying to set up a soundtrack to play if a specific deck has been chosen, but oops
the key and the filename have to start with music
(i don't think it's actually both but i'm pretty sure it's at least one of them)
filename does i think unless its cryptid doing things for no reason
its not filename, all my music tracks start with mus_
i think it mught need a sync property?
No, it needs to contain it.
oh fair
It was music_ before at least one of them, but I just did botht o be save, haha
Is there a way to see how many total runs you have attempted on a specific profile?
I know I'm probably doing something basic wrong but dont know what
i think it might be returning 1 greater than every because youre adding 1 to every in the loc_vars
Unfortunate
Yeah, which is a good thing cause I want that for one of them...cant figure out how to not for the other
that would be the 'birdbrain' variable, its return doesnt work though
why dont you just return card.ability.extra.every again but without adding 1
I need it to track like loyalty card does for how many hands are left, every isnt the thing changing, birdbrain is
oh i see
how can i modify the chips of a card
but 3 returning error would be because the localization entry doesnt exist
like hiker?
dont think so
what is the goal
you can also do that
but i ultimately want to multiply it
well if you multiply based on the base chips value too then just card.ability.perma_bonus = card.ability.perma_bonus + (card:get_chip_bonus() * <multiplier> - 1)
No, you just put it in G.PROFILES[G.SETTINGS.profile]
Confused how that is the case, I do return a 3rd to my knowledge. Am I just identifying it wrong?
i said the localization entry doesnt exist
how can i check if a card is a playing card
you need to have a localization entry with the key youre using localize on in dictionary
ahhh
or v_dictionary i forgot
ty
still trying to solve why the blind gets rendered like this during the round. It's 54x54 instead of 34x34, and the slices in the animation here are definitely 34x34, so I guess it's hardcoded somewhere, but I haven't found a way to solve the issue yet
it works but its that i specifically want to modify the CHIPS themselves, not the extra chips
Put it on card.ability.bonus instead.
so would I need a localization file for this or would I be able to get by without it? If needed, would there be a way to replace localize with anything else?
bump
Is there a way to display arbitrary text in a config menu using localization such that stuff like {C:attention} or {X:mult,C:white} will apply their visual effects to the text?
you would need a localization file
im pretty sure theres some jank with modifying the chips directly which is why i gave the workaround solution thats effectively the same
but then you just do card.base.nominal = card.base.nominal * multiplier
if you want specifically base chips
I'm trying to set up a hook that triggers only if a file is deleted. Since the function that does so also handles the warning prompt, I only want the hook to trigger when the warning text is up. This is what I have, but I got a crash saying it doesn't understand what e is. What am I missing?
-- hook.lua
local delete_profile_ref = G.FUNCS.delete_profile
function G.FUNCS:delete_profile(e)
local warning_text = e.UIBox:get_UIE_by_ID('warning_text');
print("Pressed deleting profile button");
local actually_deleting_profile = warning_text.config.colour == G.C.WHITE
if actually_deleting_profile then
print("Actually deleting profile")
else
print("File not being deleted yet")
end
local ret = delete_profile_ref(self, e)
-- print("Doing something after the original code")
return ret
end
-- button_callbacks.lua
G.FUNCS.delete_profile = function(e)
local warning_text = e.UIBox:get_UIE_by_ID('warning_text')
if warning_text.config.colour ~= G.C.WHITE then
-- warning text appears
else
-- profile is deleted
else
local tab_but = G.OVERLAY_MENU:get_UIE_by_ID('tab_but_'..G.focused_profile)
G.FUNCS.change_tab(tab_but)
end
end
end
It's . not :
for the function call, or getting the warning text, or both?
for the function creation
because using : is equivalent to creating a function with self as the first argument
Can that be changed that on the vanilla wiki?
no
Card:add_to_deck should have the :
yeah
Card.add_to_deck does actually have self as the first argument
because it is a method
No as in it's correct, or no as in nobody can change it. I'm very confused
no as in its correct
it can be changed, but it's correct
it could be turned into Card.add_to_deck(self, from_debuff) but its effectively the same
so theres not really a reason to
you could ask them to add a comment or explanation, but you're also getting very into explaining Lua at that point
I'm getting the same nil error as before with this code. Unless you're saying I need to add self as a the first paramter as the function. Sorry, I'm still learning lua while trying to mod at the same time
local delete_profile_ref = G.FUNCS.delete_profile
function G.FUNCS.delete_profile(e)
local warning_text = e.UIBox:get_UIE_by_ID('warning_text');
print("Pressed deleting profile button");
local actually_deleting_profile = warning_text.config.colour == G.C.WHITE
if actually_deleting_profile then
print("Actually deleting profile")
else
print("File not being deleted yet")
end
local ret = delete_profile_ref(self, e)
-- print("Doing something after the original code")
return ret
end
the self in delete_profile_ref(self, e) doesn't belong there
well the hook seems correct
how are you running the function
a function definition or call with : basically just means "define/call with the first argument being self"
are you using debugplus eval or actually pressing the button?
I am pressing the button
what do people think about the reworked config UI
wtf are you guys on about
that shouldnt have the self either
also i can't do multibox here for some reason
info.., i love info,
im so informed
tis very cool
Any good way of playing a sound when a playing card is retriggered ? I'm going with context.repetition but it's only playing the sound once (when the repetitions starts i assume)
context.repetition happens only when the number of times to retrigger is calculated
so you would have to manually set a flag in context.individual on the card and then check if thats already there to see if its a retrigger
Makes sense, which of course is only once. What would be a possible context for the sound playing? if there even is one
and then reset it for all the cards after the hand
Dang, that sounds too complicated for a simple sound effect.
im in
Tho I am going to need a bit of a hand here, how does one set flags to individual cards?
Add sound = 'jsm_retrigger1' to your return table
I'll see if that works. If it doesn't then i'll try Eris' idea, thank you!
It should work
It only seems to play the sound once i play a hand, but not when the retriggers happen
Can you show the code?
Of like, the whole thing? The code i got rn is this
Of what you changed it to
Changed it to this! i removed the added event and just placed it in the return table
I tried adding the event in the return panel because I thought that would work, but it just crashed the game so I'm guessing it's not possible to do that
That’s not what I said though
Oh, what would it be like then?
This
If it doesn’t work I’d have to hop on my pc and check the code again, I am working from memory
I don't doubt that this works! But would I still be able to play a random sound? I want to play between 5 audio files i have
It’s a bit more complicated that I’d definitely need to check to make it random each time
It worked! Though it obviously isn't random since it's looking through a singular audio file
I'm gonna experiment a bit see if I can get it to be random, but if you're able to, i'd love to have you give me a hand there
It’d be putting in in a func = … instead
Can try moving this function into the return table instead, doesn’t need to return true if it’s not in an event
I don’t remember if it needs the event or not
what makes controller input hover show tooltip
I'll give this a try!
Unfortunately putting the function with the play_sound in the return table does the same thing as before and plays it only when calculating the retriggers, not when it actually retriggers
Yeah the sound key doesn’t play a sound
It replaces a scoring sound
Very unintuitive
So I had to change the function I attached the hook to bc delete_profile makes everything null, and calls load_profile. This code works how I want it to. However, I am now not getting the warning text when I press the reset profile button. It just does resets immeadlty. I'm not sure what I did considering this i all I have in src/hooks.lua I have already verified the files of the game
-- todo When the game loads, set games_played for all profiles to be 0 if it is nil
-- todo When the profile is deleted, set the games played to 0 for that profile
local load_profile_ref = G.FUNCS.load_profile
function G.FUNCS.delete_profile(delete_prof_data)
local ret = load_profile_ref(delete_prof_data)
if delete_prof_data then
print("Actually deleting profile")
print("Profile set is " .. G.SETTINGS.profile)
G.PROFILES[G.SETTINGS.profile].career_stats.games_played = 0;
print("The amount of game played on this file is now ".. G.PROFILES[G.SETTINGS.profile].career_stats.games_played)
end
return ret
end
-- todo When the player starts a new game, increment games_played for that profile
Currently having the issue of where if I use a specific consumable during a blind, the game disallows me from doing anything after (can't play or discard, can't use other consumables, etc.), and if I reload back into the save I'm returned to before I used the consumable. Weird thing is it works perfectly fine when used from like a Booster Pack or something. Is there any way to prevent this from happening?
or at least force it to give back my controls
Do you have an Event
it's an overlay menu
If it’s not an Event issue then Idk but I imagine you’re either not properly managing the player controls or the game state
gotta confess this is literally just the 'All in Jest' "select a card" ui function thing pasted onto a Spectral Card
and it works in every single other scenario except when used through a consumable during a blind
@gilded narwhal can you help
Put it inside an event in that function then
actually just came up with the dumbest "solution" imaginable, so it's fine. Just stopped it from pausing the game like every other instance of this mechanic does. For some reason the unpause step doesn't run in this one specific exact scenario. This definitely won't have repercussions later.
you can put events in return tables?
No, the function you put in the return table, put the event inside that
Something like this then?
Sort of
Take all of this as your event
And put it inside the function
Soo... like this?
(I'm a tad confused so please excuse my attempts, if you want I can copy the code and you could move it around to show me how it would be)
Yeah paste the code and will arrange it for you
if context.repetition and context.cardarea == G.play then
func = function()
G.E_MANAGER:add_event(Event({
return {
play_sound("jsm_retrigger" .. (math.random(5)), nil, 0.40)
repetitions = card.ability.extra.repetitions, -- This gives the amount of retriggers the card holds
message = 'Again??',
}
end,
}))
end ```
Here!
if context.repetition and context.cardarea == G.play then
return {
repetitions = card.ability.extra.repetitions, -- This gives the amount of retriggers the card holds
message = 'Again??',
func = function()
G.E_MANAGER:add_event(Event({
play_sound("jsm_retrigger" .. (math.random(5)), nil, 0.40)
return true
}))
end,
}
end ```
Badly typed mobile code might be jank
mobile code my beloved 🧡
This is much appreciated! I'll update you on the results
What is wrong with this code within the main script? the error is occurring on the if statement
-- todo When the game loads, set games_played for all profiles to be 0 if it is nil
for i = 1, 3 do
print("index is ".. i)
if(G.PROFILES[i].career_stats.games_played == nil) then
print("profile " .. i.. "'s games_played is nil. Setting it to 0")
G.PROFILES[i].career_stats.games_played = 0
else
print("profile " .. i"'s games_played is " .. G.PROFILES[i].career_stats.games_played)
end
end
This has been crashing. I want to give a Negative Food Joker at the end of a shop. I am using Cryptid's Food Joker pool.
it seems that career_stats is nil when this code is reached. Does anyone know a function I can hook this to, or a way to wait until it's no longer nil
Follow up, I now have my localization file but its still bugged out saying 'error' on me calling #3# even though one exists in the localization.
-- Return
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.chips,
card.ability.extra.every + 1,
localize { type = 'variable', key = (card.ability.extra.birdbrain == 0 and 'bird_active' or 'bird_inactive'), vars = { card.ability.extra.birdbrain } }
}
}
end,
-- Localization
return {
descriptions = {
Joker = {
j_DRY_Martlet = {
name = "Martlet",
text = {
"{C:chips}+#1#{} chips every",
"{C:attention}#2#{} hands played",
"{C:inactive}#3#{}"
}
},
}
}
}
It's set not pool
istg if that is the problem
it was
i am going to crash out rn
is there a way i can set a custom game over death reason
saved = 'reason'
how do i make a joker change the language of the game while you own/buy it
Why does it create over the limit
add this on your creation
now im not entirely sure if thatll work
its what i do and it works for my guy
it doesnt work
except i'm causing a game over, not a save from game over
G.STATE = G.STATES.GAME_OVER
G.STATE_COMPLETE = false
...what do you mean by "reason", exactly?
It look like that now
the 'defeated by' message, i guess
Ah, UI antics... see create_UIBox_game_over() for the UI table that's returned.
that affects all luck jokers
does it work? mb cant read
What do you mean a stat?
no 😢
what exactly does the for i = 1, self.config.extra.card, 1 do, do?
im not the best at this so maybe it makes sense
im just curios what it does here
guys is 5 blinds per ante able to be modded in
asking for a friend
This is how Cartomancer does it, you're missing a buffer check
if self.ability.name == 'Cartomancer' and not (context.blueprint_card or self).getting_sliced and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
G.E_MANAGER:add_event(Event({
func = function()
local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, 'car')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end}))
card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE})
return true
end)}))
end
Should have prob sent the VanillaRemade one..
like discards
or something
a global variable
oh yeah
and i meant all luck related things
it supposed to make like thing when your playing with things that alternate value
(please help me im a victim of scope creep)
so how do you apply that here?
ohh wait
i think i might know what you need
can I use SMODS.add_card
if #G.consumeables.cards < G.consumeables.config.card_limit then
G.E_MANAGER:add_event(Event({
func = function()
SMODS.add_card { set = "Tarot" }
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
return true
end
}))
end
i use this
for my tarot added
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
i think youre missing this line
Yes, what I sent was mostly to show how the consumable check is done and to not forget to add the buffer
It doesnt crash, but it also doesnt trigger. The idea is to have a 1 in 2 chance of getting a Negative Sol card when using a Planet, but it isnt triggering, unless I am stupendously unlucky, and failed 7 coinflips in a row
And yes, that is really the key for Cryptid's Sol, I looked in the source code
Random story: I remember someone struggling with Riff-Raff creating Jokers with stickers on it not too long ago. Today I faced the same issue and found out it's because the should_apply from my stickers was not checking for the proper CardAreas where stickers should be allowed on the Joker. Vanilla stickers are allowed only on Jokers in the shop's and booster packs' CardAreas. Hope it helps that bro and anyone else not lose their sanity.
i did something like this
