#💻・modding-dev
1 messages · Page 669 of 1
oh, it does? ok then
Also you shouldnt return the xchips in context.destroy_card since thats after scoring
is there a way to destroy a card as soon as it scores and then add xchips (if poker hand is empty afterwards)?
SMODS.destroy_cards(context.other_card) in context.individual
thank!
is there a way to "force" a card being held (e.g. by the cursor) to be unheld
sorry to bother, but how i should get all cards in currently playing poker hand? it sometimes gives me the [SMODS liroxfunstuff "jokers/jokers.lua"]:151: attempt to get length of field 'full_hand' (a nil value)
it doesnt exist in all contexts, where are you trying to get it?
right now if context.individual and not card.ability.extra.burnedcard then
then full_hand should work fine
it sometimes give me an error, and sometimes burns cards in main hand
do you have any other mods
qol mods, yahimod and cryptid
i would try without yahimod and cryptid to see if it does the same
k sure
it should always exist
also btw a couple of things in that code could be written with newer methods
for the return you can just return xchips
card_eval_status_text can be SMODS.calculate_effect({message = "message"}, card)
the pseudorandom check should use SMODS.pseudorandom_probability instead
ok it doesnt give an error but sometimes it deletes cards from the main hand, or even the rightmost from poker hand
SMODS.pseudorandom_probability? like SMODS.pseudorandom_probability(1, 2) is 50% true?
do you want to destroy any card played or just scoring?
scoring be better
then add context.cardarea == G.play to the context check, this will solve the full hand issue too
mhm, noted
im guessing it would be like the cerulian bell blind?
i wasn't able to test it, but i bet that
forced_card.ability.forced_selection = true disables highlighting, so it can force deselection if its not highlighted through code (not sure though)
and use G.hand:remove_from_highlighted(card, true) to force unhighlight. may be enough to do it once like in the Cerulian Bell blind, may call it in some calculate
Ah
Uhh, is this supposed to happen?
main.lua:2438: [SMODS _ "src/utils.lua"]:2722: attempt to perform arithmetic on local 'denominator' (a nil value)
i use it in only 2 lines, in loc_vars: local num, denom = SMODS.get_probability_vars(card, card.ability.extra.numerator, card.ability.extra.denominator)
and calculate: if ... and SMODS.pseudorandom_probability(card, '1ue999', card.ability.extra.numerator, card.ability.extra.denominator) then
do you have a card.ability.extra.denominator?
config = { extra = { xchip = 1, xchipincrease = 0.1, xchipempty = 1.5, numerator = 1, denumerator = 2, burnedcard = false} },
you dont
When i said card i meant like any sort of card not just the playing card variety and when you hold the mouse down and drag stuff around thats my bad
probably call card:stop_drag on it?
idk if it works
idk how to detect the card dragged either
G.CONTROLLER.dragging.target
some of the deck effects dont apply when i use
Back:apply_to_run()
in the first video i apply a blue deck but dont get an extra hand
and in the second video i apply nebula deck, only get the voucher and dont reduce my consumable slot amount
some decks change the starting_params and most of them are only applied at the start of run
like blue deck hands
oh.
here in vremade both voucher and consumable slots are in config, for me its wierd that its doing one half but not the other? or is it because vremade isnt replicating original code 1 to 1 here
vremade doesnt always recreate code 1 to 1 but in this case it is exactly how its done in vanilla
but i dont see why both being in the config means anything, they might be applied in different ways
yeah consumable slots use starting params while the vouchers are just added directly
apparently it doesnt?
return { Xchip_mod = card.ability.extra.xchip } and return { Xchip_mod = card.ability.extra.xchip, colour = G.C.CHIPS } doesnt do anything (no message nor chips)
but return { Xchip_mod = card.ability.extra.xchip, colour = G.C.CHIPS, message="a" } displays "a" and applies chips
i've looked through source code but i cant find anywhere where starting_parameters are used. like i see a lot of places where they get set, some places where they used for Challenge UI, but i dont see where it impacts the gameplay?????
Game:start_run
oh, why then mult works that way?
mult_mod will also not have a message
i mean Xmult_mod?
Xmult_mod will also not have a message
xmult (literal) will
k thank
also xchips accepts less variations so just Xchips doesnt work i think
xchips lowercase does
btw is SMODS.calculate_effect just return {} without ending the code?
yes
so i can add xchips to it, noted
yeah, although its not recommended for compatibility with other effects
like, post_trigger wont detect the xchips that way
i just shorten one of my joker's code like 3 times as much lol
hey btw is there more optimized way to find joker other than looping thru G.jokers.cards?
if next(SMODS.find_card("key")) then
i wouldnt say more optimixed because it basically just does that but its nicer
thanks!
why did it write butts
goofy autocorrect
what bout using the joker afterwards?
it appears it returns true or smth
the main.lua:2438: functions/common_events.lua:919: attempt to index local 'card' (a number value)
pls post the full log
yea that works
As an actual answer, xchips has less valid keys because it’s a completely custom addition, if I could adjust the keys without regards to previous implementations, each one would only have one key
my game.lua file was somehow deleted so i couldnt find this 
Is there any way to "simulate" using a tarot/planet card (without it actually doing anything)? For example right before poker hand is played on my new blind?
wdym by simulate using a card
like calculating joker effects for using a consumable and stuff?
whats the point of manually changing G.GAME.round_resets.blind_ante alongside using ease_ante
i see
When you use a consumable, it plays animation of some sort (takes the card at the center of screen and shakes it a bit for some actions) and then burns it.
Im gonna do weapon cards (that remove some required score, add mult to next played hand, etc) and I want my custom blind use those cards against player
copy all the animation stuff from G.FUNCS.use_card probably
well all of it thats relevant for using a consumable
which is just this because everything after is for other button functionality
dumb question, how do I change my mod's icon?
make an atlas with the name "modicon"
Oh alr thanks
same dimensions as a tag
hey, small question here, what's the sandbox?
i've been digging through balatro's code and found a sandbox stage, is it just something from the game that has been renamed since then or is it cut content?
-# (i've just started learning lua, but from my understanding there seems to be a whole UI coded for it as well as a maybe button to spawn and remove jokers with various editions)
It definitely seems like a whole unused sandbox
Considering the spawn joker button and edition option cycle
damn that's really interesting
is there anyway i could force the game to switch to stage 3 with a mod?
also if you wanna have a look at it yourself it's in the game.lua file at line 1270 (or just search for "sandbox" in whatever IDE you use i guess)
I wonder how possible it would be to restore it tbh
Is there any way to add something to event queue? i want to make a consumable that gives chips for next played hand (not right away but as soon as hand is played)
there's a lot of code around it so maybe it is possible out of the box, i'll try experimenting with it
I think G.STAGE = G.STAGES.SANDBOX should try to load the sandbox imma try
i mean the game normally does a big loading cut when changing between the existing stages
But maybe
Store the chips to add in some G.GAME value, then apply it and reset it in SMODS.current_mod.calculate if it exists and is greater than 0
or wait, is it possible to run lua instructions through the DebugPlus console?
yeah thats just the returned value
Setting a value doesnt return anything so thats why it says nil
ah alr
doesn't seem to have done anything tho
ah nvm
pressing play crashed the game
But since it doesnt appear to do anything you might need to patch into the existing new run button to make it work somewhat properly
Though if you do that probably start a run on a new profile
Because idk what thatll do
I think this is it failing to get the current blind
Which makes sense
Or
there is a Game:sandbox() function it seems
Idk actually
but it doesnt work
Ah
interesting to see thoguh
isnt that way it would just reset when i change hand type?
or where i should call SMODS.current_mod.calculate?
SMODS.current_mod.calculate gets called automatically
With other calculation events
It cant use context.joker_main though so youll probably have to use context.final_scoring_step or context.initial_scoring_step depending on what timing you want
i want it to add chips after the hand was submitted but before first card is scored
Store the chips to add in some G.GAME value
about that, that can be any value? likeG.GAME.nextchips?
yeah it can have any name
probably include your mod prefix somewhere though to avoid conflicts
ok where i place current_mod.calculate? after if context.intial_scoring_step then? then where should i place the context itself?
or other way around?
SMODS.current_mod.calculate is a global function so it should be defined outside of any other object
the context check should be inside the function
For reference its SMODS.current_mod.calculate = function(self, context)
And it acts like a calculate function on any other object
no
SMODS.current_mod is a table that updates to whatever mod is currently being loaded
Which will always be your own mod when its loading
so i just set this in my mod's main lua file?
Yea
Consumables can act like Jokers with calculate too.
so they are compatible with loc_vars?
They can use loc_vars yes
noted
And all the same return values work
Pretty much any object with localization has full loc_vars functionality
this is for a mod
SMODS.calculate_effect({chips=50}, card)
can this run without card? or is there any way to do it?
why
i want to run this right after player submits poker hand, but before first card scoring, i already have context but idk how to run calculate_effect without card
yes
wait it works that way?
yes
ok thank
by default the "card" is the top of the deck for mods
so if you want to recreate that with calc effect for some reason you can use that as the card
Or since youre doing this for a consumable effect, you could use G.consumeables as the "card" im pretty sure
which makes the message appear under the consumables area
And the consumables are box will jiggle
noted
yall is there a thing in joker forge that could make the card show text on the bottom of it
like fros michells extinct
but it can trigger when ever
?
i dont use this so idk if that works
dunno
you can use the random function to play a different message yes
it's a bit of a convoluted method but it works
chat did i cook with this artwork or is it ahh
i like the watch/timer but the dynamite(?) sticks behind are a bit wonky imo
probably because of the two pixel wide outlines and the shading
Make the seconds arrow spin lol
make the clock functional and synced to real time
:o
Even better
also, random suggestion, but you could make it like an actual bomb you have in your joker's tray instead of a card representing a bomb you know?
would be cool imo
also what do you mean by this?
hmmm lemme think how to explain better..
are you saying don't make it a joker and instead a different mechanic?
no no, like instead of the sprite representing a card that has a bomb drawn on it, you could make it an actual bomb that you use as a joker
you gave me an idea lol
oh no
@slim ferry can we pwease gwet sowme helwp on twhis pwease
-# i'm too bad at modding to help himm
you can use the draw function for that i suppose
And for extra sprite layers you can use a drawstep
alr imma put this here then:
https://github.com/Steamodded/smods/wiki/SMODS.DrawStep
k thank
i have a question about Back:trigger_effect and calculate
here return just returns one dictionary
trigger_effect is just wierd vanilla stuff
Im assuming it returns things differently
but here it unpacks an array??
well no
it puts the returned table into another table
then unpacks that table
if it isnt empty (so if anything was returned)
like this is (o) before unpacking
🤷
probably so that if you rreturn something like
return {balance = true}, 1
it gets turned into {{balance = true}, 1}
the reasoning behind that is beyond me but that's how unpacking tables works so
can anyone remind me of context after cards scored but before jokers scoring?
that does not exist
hm? after last card scored perhaps?
chat what do you think about a "squish and stretch" joker
-# i have no idea what it'll do tho
i love him
funny fella
face lift mario party
?
¯_(ツ)_/¯
nothing is calculated between playing card and joker scoring
sad
does current_mod.calculate executes before or after joker calculation
though you can just patch in a context calculation in between if you want
idk when mod calculate runs tbh
but it doesnt ever get calculated with joker_main anyway
ok so i haven't followed any of the conversation about the issue, but can't you like idk, put it as a joker effect that triggers first if what you want is to trigger between played cards and jokers?
-# nvm i used my braincell and read
ok another idea: how do i check if scoring card is the last one?
context.other_card == context.scoring_hand[#context.scoring_hand]
thanks!
though
if you need between playing cards and jokers i do recommend doing this
last card is enough for me
i can just make local ret and in addition to per_card add xmult and xchips
and return this
if im understanding correctly yeah you can
yes you are understanding correctly
also any values not in G.GAME arent saved with the run
What is this effect supposed to do?
is there a list of every color in G.C.?
its fine, i reset it as soon as joker scores
dont need it afterwards
the code
also, can anyone point on what am i missing here?
[SMODS _ "src/utils.lua"]:228: Attempted to insert object "c_liroxfunstuff_weapon_stick" into an empty pool.
SMODS.Consumable({
object_type = "Consumable",
atlas = 'weapon_stick',
key = 'weapon_stick',
name = 'Stick',
text = {
"Next played hand gives {C.chips}+#1#{} Chips"
},
config = {extra = {chips = 100}},
loc_vars = function(self, info_queue, card)
return {
card.ability.extra.chips
}
end,
pos = { x = 0, y = 0 },
cost = 2,
unlocked = true,
discovered = true,
use = function(self, card, area)
apply_weapon(card.ability.extra)
return {message = "Used"}
end,
can_use = function(self, card, area)
return G.GAME.blind.in_blind
end
})
missing set parameter for the consumable type
what should i set it to?
well the key of whatever consumable type it should be
should it contain mod prefix?
no
k
about this
SMODS.ObjectType({
key = "weapons",
default = "c_liroxfunstuff_weapon_stick",
cards = {
},
})
do i really need to set true for every weapon card?
no
so it does it automatically
you do set = "weapons" in the consumable
alr got it
also it should be a SMODS.ConsumableType
k thanks
oh wait also a consumable type needs a primary_colour (does nothing but is required) and a secondary_colour (the actual colour it uses)
ok so how do i make custom color that it can use? G.ARGS.LOC_COLOURS.WEAPON_PRIMARY = HEX('e62314') isnt working for it it seems
secondary_colour = HEX("e62314") in the definition
and the colour for use in text is added automatically
do you have a localization file entry or a loc_txt for it
what's your localized text setup look like
i dont
it seems i should
ty
also it seems chips are applying but after any change they are gone
function apply_weapon(extra)
for k, v in pairs(extra) do
Lirox.weapons[k] = Lirox.weapons[k] and Lirox.weapons[k] + v
end
end
function reset_weapons()
Lirox.weapons = {
chips = 0, mult = 0, xchips = 1, xmult = 1, dollars = 0,
percard_chips = 0, percard_mult = 0, percard_xchips = 0, percard_xmult = 0, percard_dollars = 0
}
end
SMODS.current_mod.calculate = function(self, context)
if context.intial_scoring_step then
return {
chips = Lirox.weapons.chips,
mult = Lirox.weapons.mult,
dollars = Lirox.weapons.dollars,
}
end
if context.individual and context.cardarea == G.play then
local ret = {
chips = Lirox.weapons.percard_chips,
mult = Lirox.weapons.percard_mult,
xchips = Lirox.weapons.percard_xchips,
xmult = Lirox.weapons.percard_xmult,
dollars = Lirox.weapons.percard_dollars,
}
if context.other_card == context.scoring_hand[#context.scoring_hand] then
ret.xchips = ret.xchips + Lirox.weapons.xchips
ret.xmult = ret.xmult + Lirox.weapons.xmult
end
reset_weapons()
return ret
end
end
same for mult
also i placed reset weapons in the wrong place lol
yea, even per_card mult/chips are reseting on any change
yeah youre resetting it when any playing card scores currently
i placed reset at the if context.other_card == context.scoring_hand[#context.scoring_hand] then
but the issue prob isnt in the reset_weapons(), it should only reset temporary stats
the issue persists even with SMODS.calculate_effect({}, context.other_card)
i can send a vid
im running into this issue where I cannot get my joker animated for the life of me
I have my sprite sheet with all the frames but something is just not working
is the atlas set as an animation atlas
it should have atlas_table = "ANIMATION_ATLAS" for animated sprites
no way it was that easy of a fix
stand by
wow
thank you i cant believe it was that easy
I've beeninterested in making balatro mods for a bit now, does anyone know of any way I can do it.
this is gonna assist you on the way https://github.com/nh6574/VanillaRemade/wiki
https://github.com/nh6574/VanillaRemade/wiki the first bit of this tells you pretty much everything
oh
yeah
Yess that one is the one ive been following. its helping a lot
Thanks a lot
its dangerous to go alone
take this
Don't be afraid to ask any questions you may have (after reading the VanillaRemade wiki)
ok I will thanks
uhh?
question here, how do other mods achieve the effect of only spawning certain jokers?
I cannot figure out how to get this joker to stop dancing around like this. It has a very specific trigger and shouldn't be dancing whenever a card is scored (especially because it's not triggering when a card is being scored)
uhh go check its source code ig
oh yeah i'm a dumbass ty
how could i add a color to G.C? would i just do like
G.C.bof_appetizers = HEX("123456")
G.ARGS.LOC_COLOURS.color = HEX('FFFFFF')
replace .color with your desired id
right
also it only needs to be in G.ARGS.LOC_COLOURS if youre going to use it in descriptions
which i'm not
usually its best to have it in both G.C and there too
i'm using it for the background of a checkbox
then only add loc_colour() it seems
elaborate?
or idk, not an expert
okay
okay they just look for "mult" in the joker description essentially lol
wing gaster
indeed
also G.C.GREY exists
noted
remember, while everything in-game is supposed to be the american version of stuff (hence, en-us), pretty much everything internally is canadian since localthunk is such
canadian english is the same as british english btw
i think at least
it might be american english words with british english spellings
yeah i know
getting somewhere with this content manager revamp
though some things are just flat-out misspelled internally like caino and selzer
consumeable is such a big one lol
uhh showman is ring_master but thats probably just an old name
ok so i looked it up and canadian english is british english spellings and BOTH british and american english vocabularies
gluttenous joker
also true
was about to say
yeah showman was called Ring master in the demo
which is one word btw
modded ring master joker that's just a direct copy of showman when
ringmaster
oh right, it was
i know it's one word, but it'd be funnier if it was still two
Ring Master, Lord Master of the Rings

Mrs Bones when
mrs. bones in balatro plus
when lady luck makes it ig
it kinda does something
when using the proper function
it seems more like for testing title screen stuff though i think?
interesting
oh wow
it does create a ui but
the vortex goes wierd
and stops spinning
its just a static background
i didnt actually test any of the buttons tbh
i saw some code that created jokers with specific editions and stuff
try to put a joker key in to see
(probably crashes cuz there's no joker tray)
also the size slider did work but when i made a very big jimbo it couldnt be dragged and i couldnt press any buttons anymore
lol
lol

messing around with a joker that removes cards. Looks like the game thinks the card is still there
Any ideas?
how are you destroying the card
start_dissolve() i believe
like the hanged man cards
except its not actually destroying the card. only making it invisible?
you have the card selected still
you should only be able to select 4 cards, right?
try using SMODS.destroy_cards
also check this one, not the one in the game files https://github.com/nh6574/VanillaRemade/blob/f1cc39c18475a3aa866817d579caefb6a53dca40/src/tarots.lua#L752
isn't start_dissolve() just for the animation?
like the card is still there just the burn animation as played and ended
but the card still exists
i believe so
thats what I was thinking too. I need to actually destroy the card
it does also remove the card
yeah just look at this
oh nevermind then
but everything that should happen when a playing card is removed isnt done automatically with start_dissolve
uhh anyone?
no it actually does destroy it, but it sometimes leaves ghost cards if you don't call it properly so destroy_cards solves that sometimes
cards I create with
SMODS.add_card { set = "Base", rank = ranks[i], enhancement = "m_wild", area = G.deck }
don't seem to have a texture until I save, quit and reopen the run. Is there some additional function that needs to be run?
smods bug
just a (already fixed on dev) bug, you can do ```lua
local c = SMODS.add_card({set = 'Base', rank = ranks[i], area = G.deck})
c:set_ability('m_wild')
to circumvent for now iirc
Thank you!! I was able to figure it out. It also made the animation of the cards being destroyed + joker being triggered a lot smoother too
yall in joker forge how do i give a joker obelisk like properties?
ask the joker forge discord
in joker forge you have copies of all vanilla joker to see and copy
ahh
question again, how do mods add a card to the title screen? (like entropy)
if you're using the latest smods release you can uhhh
SMODS.current_mod.menu_cards = function ()
return {
key = "j_joker",
no_edition = true
}
end```
ty you both!
yw
the second if doesn't trigger (and frankly idk if i'm doing the "remove all modifications" right anyway); why?
calculate = function(self, card, context)
if context.individual and context.cardarea == G.hand then
return {
mult = card.ability.extra.mult
}
end
if context.initial_scoring_step then
for k, v in ipairs(G.hand.cards) do
if v ~= context.card then
v:set_ability(G.P_CENTERS[v.base.suit .. "_" .. v.base.rank])
v:juice_up()
end
end
return {
message = "Erased!"
}
end
end
could someone help me with the buggy ass UI i made for my mods content manager?
every time i change the category or page the entire manager UI does whatever the fuck is happening in the screenshot
you're mixing up fronts and centers, there's no center with the key you're specifying. the unenhanced center is c_base. Also I don't think context.card exists here?
nvm i got it
ok cool i basically just copied from cryptid's vacuum is all so
well, it displays the message, but no cards are actually "erased"
if context.initial_scoring_step then
for k, v in ipairs(G.hand.cards) do
if BundlesOfFun.nil_check("v.base.rank") then
v:set_ability(G.P_CENTERS.c_base)
v:juice_up()
end
end
return {
message = "Erased!"
}
end
oh btw nil_check just returns v and v.base and v.base.rank
no?
it's v.base.value
okay then
oh 😭
you don't need that check at all
ok i just like making sure i don't crash to nil values
yet another question, how can i copy the ability of a random joker?
-# i've looked at the code for cryptid's speculo, but i really don't understand it
here's the code i don't understand btw
basically scan through all jokers once to find those with blueprint compat, then generate a random number and scan though all of those to find the correct one to blueprint
that's how i would do it anyway
are the game settings stored in a way i can modify mid-run?
i think only game speed can do that but idk
ok tell me if i'm correct:
this scans for blueprint compatible jokers:
if G.jokers.cards[i].ability.name ~= card.ability.name and G.jokers.cards[i].ability.set == "Joker" then
eligibleJokers[#eligibleJokers + 1] = G.jokers.cards[i]
end```
And this picks a random one and duplicates it(?):
```G.E_MANAGER:add_event(Event({
func = function()
local card = copy_card(pseudorandom_element(eligibleJokers, pseudoseed("cry_speculo")), nil)
card:set_edition({ negative = true }, true)
card:add_to_deck()
G.jokers:emplace(card)
return true
end,
}))
card_eval_status_text(
context.blueprint_card or card,
"extra",
nil,
nil,
nil,
{ message = localize("k_duplicated_ex") }
)```
do you want to copy the ability or the card itself?
because that seems to be doing the latter
the ability, i took example on speculo because that's the only "random joker effect" joker i know
i think speculo creates a copy of the joker, not copies its effects
yeah ik
yes, you just need to take care of saving them
i just don't know any other modded jokers that have an effect that picks a random joker
i know there are effects that do this but it's not straightforward
maybe look at pinkprint from ortalab
that doesn't do a random joker however but i think picking a joker is the easy part, copying a joker not-in-play is the hardest
oh do they not actually save if you try and modify them on their own
oh well i just want it to copy when a hand is played, picking a random joker passively would be annoying/weird(?) to implement
run data saves automatically every so often, settings don't. you have to call save_settings whenever you change something. normally this is done when you exit a settings menu, so you'd need to call it yourself if you're changing settings somewhere or sometime else
blueprint doesnt copy passive abilities anyway
alr thx, do you know where the actual settings are stored off-hand
erm one more question:
i put the remove modification stuff in an event so that it and the message trigger at the same time, but now if, say, a red seal is held in hand, it'll still be retriggered by the other effect
calculate = function(self, card, context)
if context.individual and context.cardarea == G.hand and not context.end_of_round then
return {
mult = card.ability.extra.mult
}
end
if context.before then
G.E_MANAGER:add_event(Event({
func = function()
for k, v in ipairs(G.hand.cards) do
if v.base.value then
v:set_ability(G.P_CENTERS.c_base)
v:set_edition(nil)
v:set_seal(nil)
v:juice_up()
end
end
return true
end
}))
return {
message = "Erased!"
}
end
end
G.SETTINGS in code, settings.jkr for the file it gets written to. I can't tell which one you mean
i just wanted to know what the variables were, knowing where they're stored is all i need to find them
local ret = SMODS.blueprint_effect(card, G.jokers.cards[1], context)
if ret then
ret.colour = G.C.RED
end
okay so this copies the joker in slot 1, how do i make the slot random tho?
create a list of all viable jokers (check if they're compatible), then run that through pseudorandom_element
ah now i understand lol
you can copy what speculo does yeah, but you need to add a blueprint compat check like aure said
loc_vars = function(self, info_queue, card)
if card.area and card.area == G.jokers then
local compatible = G.jokers.cards[1] and G.jokers.cards[1] ~= card and
G.jokers.cards[1].config.center.blueprint_compat
local main_end = {
{
n = G.UIT.C,
config = { align = "bm", minh = 0.4 },
nodes = {
{
n = G.UIT.C,
config = { ref_table = card, align = "m", colour = compatible and mix_colours(G.C.GREEN, G.C.JOKER_GREY, 0.8) or mix_colours(G.C.RED, G.C.JOKER_GREY, 0.8), r = 0.05, padding = 0.06 },
nodes = {
{ n = G.UIT.T, config = { text = ' ' .. localize('k_' .. (compatible and 'compatible' or 'incompatible')) .. ' ', colour = G.C.UI.TEXT_LIGHT, scale = 0.32 * 0.8 } },
}
}
}
}
}
return { main_end = main_end }
end
end
so that's a blueprint compat check?
the local compatible line is
Yes, you're removing the seal in an event, so the card would still have the seal during scoring.
any way to not have that happen? if it's not in an event, the message will be greatly delayed
set_ability has a second param to let you delay the sprite change
the others do too, iirc
so use that and not an event
wait what's a blueprint incompatible joker that would crash or cause weird stuff if it got blueprinted?
(to test)
it wouldn't crash
SMODS.blueprint_effect just does nothing when the card isn't compatible
ah okay, perfect then, i just need to figure out randomness now
-# *cries in 1 day old lua programmer*
that part is easy
you just do pseudorandom_element(tbl, "whatever") where tbl is the table of compatible cards and whatever is some unique randomness seed
<@&1133519078540185692> spam bot invite link
sanity check, context.full_hand exists in current_mod.calculate, right?
yes
Not everything gets calculated in every context but objects dont just randomly get less of a context than others
context.full_hand only exists in the contexts where it does
true…
i guess bro
The missile knows where it is at all times. It knows this because it knows where it isn't.....
i still don't know how to make my custom consumable's rate bigger i suck at coding please help me lads 
is it a custom consumable or a vanilla tarot/planet/spectral?
what does this part of Invisible Joker's loc_vars do?
loc_vars = function(self, info_queue, card)
local main_end = {}
if G.jokers and G.jokers.cards then
for _, joker in ipairs(G.jokers.cards) do
if joker.edition and joker.edition.negative then
localize { type = 'other', key = 'remove_negative', nodes = main_end, vars = {} }
break
end
end
end
return { vars = { card.ability.extra.total_rounds, card.ability.extra.invis_rounds }, main_end = main_end[1] }
end,```
custom
you can add a shop_rate = number to the ConsumableType
https://github.com/Steamodded/smods/wiki/SMODS.ObjectType
nono i mean like change it like the spectral deck
use get_weight
if you have a negative joker it adds "removes negative from copy" to the description
return some number if the deck is selected
ohhhhhh i see
Instead of 0
clever!
it is also described in the same place in the docs: G.GAME.[consumable type key in lowercase]_rate = number
having some weird behaviours with negative playing cards, in the deck screen, the negative shader doesnt render for the first negative card of each suit. And every time I open the deck screen each negative card animates and plays a wooshing sound. Is this bugged or just unsupported?
oooh i had to do it in lowercase, i was doing it with the normal consumable name which has caps
, thanks alot dude it worked
the wooshing stopped when closing and re-entering the run, but the visuals are still bugged in the deck screen
wait a second the deck function uses copy_card, I see how I caused this now
I want to randomize card's suit and rank. how i get poll them?
SMODS.change_base(v, random suit??, random rank?)
I know there are SMODS.Ranks and SMODS.Suits but i forgot how to select a random element of a dictionary thats not a center
i think you can just pseudorandom element (smods ranks, seed)
that will return a random rank object, which you can get the key from in the normal way i think
right i forgot about pseudorandom element thank you
what the heck
i've never seen assert in any balatro related codebase yet
vanillaremade uses it! https://github.com/nh6574/VanillaRemade/blob/f1cc39c18475a3aa866817d579caefb6a53dca40/src/spectrals.lua#L354

okay i made a behemoth of a lua function
its able to apply a deck during the run, because back:apply_to_run() sometimes only changes the starting parameters
Have you ever looked at deck redeeming functionality from hit library mod Spectrallib
you've gotta be kidding me
i would have told u if i knew lmao
wait whats spectrallib
i couldnt find it just by searching it up
actually i looked at it and i dont see exact implementation of what i need
also they have a list of vanilla decks as far as i see? and mine should work with modded decks as well
ankh doesnt properly remove negative from jokers it copies, I assume this is a smods thing because the only mod I have enabled is debugplus. Is this a known issue?
it removes negative but they still have +1 card limit as ability
yeah i think some things broke with abilities
maybe it is fixed in dev but reporting it doesn't hurt
yeah i think it works for its usecase, but it doesnt support custom calculates and checks for ability name of default jokers
looking at the code it seems to support custom calculates?
how we feeling about this artwork? thoughts?
it's cool but try to make it with other colors
what part? the whole thing?
the shadows under the crane? i adjusted them like this as a test
no as in use other color tones not make it darker 
how do i canvassprite on joker cards
are you asking how to do custom artwork for jokers?
no???
i said canvassprite
as in the new thing added in the latest smods release
that i don't think has any documentation
nvmd i found it
Oh my fault I have no idea what that is
it is a new feature
okay i still dunno how to use this outside of text
how do i create a mod
im tryna make a custom jokr that acts as the default joker for now
but it ckeeps crashing
you should update smods to the latest release version (1503a), and then post your code file here
Oops! The game crashed:
Syntax error: card.lua:5124: 'end' expected (to close 'function' at line 238) near '<eof>'
A mod you have installed has caused a syntax error through patching. Please share this crash with the mod developer.
Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-1507e-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.8.0
Platform: Windows
Stack Traceback
(3) C function 'function: 0x02852d88'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 914
(6) global C function 'require'
(7) LÖVE function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x0286caf0 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x0286cb40, gammacorrect:false, title:Balatro, externalstorage:false (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) LÖVE function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
inerror = boolean: true
deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
that's still not the latest release version (click on the releases in the sidebar on github, don't download the green code button)
and then pleeeease actually post the code file so i can read it and properly help you
the main.lua?
remind me what the check was to see if an enhancement removes a card's rank and suit? like stone
SMODS.has_no_rank/suit
the code your joker is in i suppose
I had Steamodded and smods both downloaded and that was causing me to crash upon launch. I deleted smods and now I only have steamodded downloaded and that has not given me any issues
@shy cobalt
that is not helpful for pikaquin's case, the crash is unrelated to that
ah I see
it looks like the config function is missing entirely for the joker to work in the first place
guys help me i genuinely don't know what's happening, from what i know it's just my deck's code 
where
delete that
also the path should be just the filename
I'm crashing out my discord is crashing constantly
anyway yes that
crowdfunding meta a new computer
for the second crash you posted, it's probably related to installing smods incorrectly
I just have to hold out until HP sends me my good laptop back 😭
i fixed it i was missing a singular } and some } ) placement fixes 
im pretty sure that doesnt look for your mod's folder
any reason youre not using an atlas?
canvassprite
it doesnt let you use an image from an atlas?
well that doesnt really answer my question, its not like balatro objects are in some other engine
idk how to draw atlas sprites
G.ASSET_ATLAS["modprefix_key"].image seems to be a love.graphics.newImage
??
wdym "??"
what do you mean extra stuff
an asset atlas contains more than just the image
like a key and 2 numbers?
ok
i tried but it still activates much before the message:
for k, v in ipairs(G.hand.cards) do
if v.base.value then
v:set_ability(G.P_CENTERS.c_base, true)
v:set_edition(nil, true)
v:set_seal(nil, true)
v:juice_up()
end
end
return {
message = "Erased!"
}
Try putting it in a func in the return.
hmm it still activates afterward
return {
message = "Erased!",
extra = {
func = function()
for k, v in ipairs(G.hand.cards) do
if v.base.value then
v:set_ability(G.P_CENTERS.c_base, true)
v:set_edition(nil, true)
v:set_seal(nil, true)
v:juice_up()
end
end
return true
end
}
}
here i'll record a clip
Move it out of the extra
oh ok
Also it should be v:set_ability('c_base', nil, true)
okie dokie
And v:set_edition(nil, nil, nil, true) and v:set_seal(nil)
Also the juice_up should be in an event.
what even are these inputs anyway
gotcha 😭
is G.GAME initialised in Game:start_run()?
ok i like how everything looks now timing-wise (including all of them juicing at once), but the modification removal seems to activate at different times
Code?
Yes.
i'm finally tackling the cardarea implementation i want to do, but i only want specific decks to have the new cardarea; i already know i need to check G.GAME.selected_back_key.key for my custom deck key, which means, i need to do that check which determines whether that cardarea is initialised or not - but i don't know where in my hook i should be making this check. i'm assuming immediately following when i call the original start_run func
return {
message = "Erased!",
func = function()
for k, v in ipairs(G.hand.cards) do
if v.base.value then
v:set_ability("c_base", nil, true)
v:set_edition(nil, nil, true)
v:set_seal(nil)
v:juice_up()
end
end
return true
end
}
putting the juice in an event made everything go left-to-right, and, while i like it, i'd want the removal to happen on every juice instead of all of them getting removed and then the juice happening afterwards since that seems to be what happened
theres a new function that has the correct timing for areas
SMODS.current_mod.custom_card_areas = function(game)
oh right
iirc the deck should exist by then
You missed a nil on v:set_edition
so i can just do the check in that function?
i think so
my preferred timing for everything is:
card 1 in hand gets all of its modifications removed and gets juiced, all at the same time -> card 2 has the same -> card 3 has the same -> ... -> card (last one) has the same -> joker returns my message
oh uh current code btw
return {
message = "Erased!",
func = function()
for k, v in ipairs(G.hand.cards) do
if v.base.value then
v:set_ability("c_base", nil, true)
v:set_edition(nil, nil, nil, true)
v:set_seal(nil)
G.E_MANAGER:add_event(Event({
func = function()
v:juice_up()
return true
end
}))
end
end
return true
end
}
Yes, if you want the seals to be removed on time you have to hook SMODS.DrawSteps.seal.func
what about eraser's message triggering before all the other things?
i assume that's an easy fix somehow
Put the message in an extra
oh right, will the func add it to evaluation or do i still need to patch that myself
it will not
does declaring an SMODS.ObjectType prefix the modprefix to the specified key?
no
it's SMODS.Back for adding custom decks, yes?
How can I re-enable the Jimbo tutorial?
G.SETTINGS.tutorial_complete = false
Thank you
is the game in this func the same as G.GAME? or is it G and i need to do game.GAME to get that 
it is G i just named it game because i couldnt think of a better name and i didnt want to use G
that was copied from my mod
Okay, I did eval G.SETTINGS.tutorial_complete = false into the console and got < nil as a result. For what I can tell, it isn't enabled? I got a couple of additional mods on (as well as debug plus to type it) if it is of concern.
that's just what dbp returns whenever you do a set in eval
you can check it by just doing eval G.SETTINGS.tutorial_complete
Checked it, it is still true for some reason. Hopefully it isn't one of my mods
i forget if there's something specific you need to do to change a G.SETTINGS var
Try also doing G.SETTINGS.tutorial_progress = nil
im interested in doing two things:
-
having the visual of a joker change based on some game information (to do list showing the current hand, castle showing the current suit, loyalty card showing how many more uses, etc)
-
having specific instances of cards have unique localized text based on game states (jokers, planets, or tarots having different text if they have an edition for example)
any good examples of things like this i should check out to learn how to do it?
can someone playtest my mod?
1: https://github.com/SpectralPack/Aura
2: Hook generate_card_ui
why is there a SpectralPack library for everything 😭
Aura isn't a library, it's a project to animate all cards in the game. It does what you're asking and you can use that code
for your other question, loc_vars is usually good enough as you can return a key to completely change the text to a different localization key
good catch, I replied wrong
.
i dont follow how i would do that
what part's unclear?
calculate = function(self, card, context)
local compatible = G.jokers.cards[1] and G.jokers.cards[1] ~= card and
G.jokers.cards[1].config.center.blueprint_compat
local ret = SMODS.blueprint_effect(card, G.jokers.cards[pseudorandom_element(compatible, "seed")], context)
if ret then
ret.colour = G.C.RED
end
return ret
end
am i doing this wrong? (probably yes)
this crashes when another joker is added
do you want to change the vanilla jokers or do you want to change your joker
because you could just return a variable and change the sprite
pseudorandom_element already returns the card
no need to index that on G.jokers.cards
i think my first question will have plenty of resources thanks to aura
i suppose so
thanks though
Also you need to actually create a list of the joker's that are compatible
not just copy the check if the leftmost card is
what are you trying to do
blueprint?
trying to make a joker that when hand played, copies a random joker that is blueprint compatible
something like
local compatible = {}
for _,v in ipairs(G.jokers.cards) do
if condition then
compatible[#compatible+1] = v
end
end
Also you should consider not randomly selecting the joker every time something gets calculated, that produces wonky results
dont forget to check for other_joker.config.center.blueprint_compat
Blueprint (VanillaR)
-- Blueprint
SMODS.Joker {
key = "blueprint",
unlocked = false,
blueprint_compat = true,
rarity = 3,
cost = 10,
pos = { x = 0, y = 3 },
loc_vars = function(self, info_queue, card)
if card.area and card.area == G.jokers then
local other_joker
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i + 1] end
end
local compatible = other_joker and other_joker ~= card and other_joker.config.center.blueprint_compat
local main_end = {
{
n = G.UIT.C,
config = { align = "bm", minh = 0.4 },
nodes = {
{
n = G.UIT.C,
config = { ref_table = card, align = "m", colour = compatible and mix_colours(G.C.GREEN, G.C.JOKER_GREY, 0.8) or mix_colours(G.C.RED, G.C.JOKER_GREY, 0.8), r = 0.05, padding = 0.06 },
nodes = {
{ n = G.UIT.T, config = { text = ' ' .. localize('k_' .. (compatible and 'compatible' or 'incompatible')) .. ' ', colour = G.C.UI.TEXT_LIGHT, scale = 0.32 * 0.8 } },
}
}
}
}
}
return { main_end = main_end }
end
end,
calculate = function(self, card, context)
local other_joker = nil
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i + 1] end
end
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.BLUE
end
return ret
end,
check_for_unlock = function(self, args)
return args.type == 'win_custom'
end
}
you should select one joker at the start of the hand and refer back to that until the end of the hand
I don't think that's too helpful, the part they're trying to solve rn is randomly selecting the joker
oh
actually
-- Copy Tool(Common)
SMODS.Joker {
atlas = 'rbxJokers',
pos = { x = 0, y = 2 },
pools = {
["FelisJokeria"] = true,
["Roblox"] = true,
["Building Tools"] = true,
},
key = "felijo_rbx_copy",
rarity = 1,
cost = 5,
unlocked = true,
discovered = true,
blueprint_compat = false,
config = { extra = { chips = 150, chips_mod = 10} },
calculate = function(self, card, context)
if context.setting_blind and not context.blueprint then
local jokers = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= card and G.jokers.cards[i].config.center.key ~= "j_felijo_rbx_copy" then
jokers[#jokers + 1] = G.jokers.cards[i]
end
end
if #jokers > 0 then
if #G.jokers.cards < G.jokers.config.card_limit then
local chosen_joker = pseudorandom_element(jokers, 'j_felijo_rbx_copy')
local copied_joker = copy_card(chosen_joker, nil, nil, nil,
chosen_joker.edition and chosen_joker.edition.negative)
if copied_joker.ability.invis_rounds then copied_joker.ability.invis_rounds = 0 end
if type(copied_joker.ability.extra) == "table" and copied_joker.ability.extra.invis_rounds then copied_joker.ability.extra.invis_rounds = 0 end
play_sound('felijo_rbx_copy', 1)
copied_joker:add_to_deck()
G.jokers:emplace(copied_joker)
return { message = localize('k_duplicated_ex') }
else
return { message = localize('k_no_room_ex') }
end
else
return { message = localize('k_no_other_jokers') }
end
end
end,
}
G.jokers:emplace(copied_joker)
return { message = localize('k_duplicated_ex') }
else
return { message = localize('k_no_room_ex') }
end
else
return { message = localize('k_no_other_jokers') }
end
ain't that to copy a joker card?
wait what's the effect of this joker?
-# would help in understanding the code
that's creating a copy of a joker
what's happening here is copying the effect of a joker, blueprint-style
oh wait can't i copy invis joker's random joker select?
two caveats, the selected joker needs to be blueprint-compatible, and you want to copy the same joker for a full hand/round
-# not for a full round, just for a hand
yeah but those are quite similar in effect
Yes, but in their example, the card wouldn't have to be from their mod.
that matters how?
bello 
loc_vars on an edition can't be used to change what the card it's on's description is.
yeah, but loc_vars on the card can. I'd assume an edition can't provide altered descriptions for every card?
SMODS.Joker {
calculate = function(self, card, context)
if context.hand_drawn and not context.blueprint then
local jokers = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= card and G.jokers.cards[i].config.center.blueprint_compat then
jokers[#jokers + 1] = G.jokers.cards[i]
end
end
local other_joker = pseudorandom_element(jokers, 'j_modname_joker')
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.BLUE
end
return ret
end
end,
they did say specific instances of cards
calculate = function(self, card, context)
if context.hand_drawn and not context.blueprint then
local jokers = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= card and G.jokers.cards[i].config.center.blueprint_compat then
jokers[#jokers + 1] = G.jokers.cards[i]
end
end
local other_joker = pseudorandom_element(jokers, 'j_cash_out_j0k3r')
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.BLUE
end
return ret
end
end
imma jump off a bridge why doesn't this workkkk
no crash, just does nothing
It's because you're only copying the effect on context.hand_drawn
tysm it works now!
sorry to bother ya but i got a quesion again so i've switched context.hand_drawn to context.joker_main, and it works great for jokers that trigger in joker_main like Joker but it can't copy the effects of Gluttonous Joker that triggers when a card is played, how could i fix this?
current code:
calculate = function(self, card, context)
if context.joker_main and not context.blueprint then
local jokers = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= card and G.jokers.cards[i].config.center.blueprint_compat then
jokers[#jokers + 1] = G.jokers.cards[i]
end
end
local other_joker = pseudorandom_element(jokers, 'j_cash_out_complex_joker')
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.BLUE
end
return ret
end
end
hand_drawn works for selecting the joker, but you need to keep it for copying in other contexts that follow
either in an ability value or an upvalue
actually no, upvalue doesnt work
calculate = function(self, card, context)
if context.press_play then
local indexes = {}
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] ~= card and G.jokers.cards[i].config.center.blueprint_compat then
indexes[#indexes + 1] = i
end
end
card.ability.extra.joker_index = pseudorandom_element(indexes, 'j_cash_out_complex_joker')
end
return SMODS.blueprint_effect(card, G.jokers.cards[card.ability.extra.joker_index], context)
end
something like this
is NFS a shortcut to love.filesystem? and is there a proper way to load everything recusively?
nvm i found it in love2d docks
use SMODS.NFS
@shy quest uhhh
i need help, this crashes the game
how can I get my icon to show up on the mod? the "logo" if you will.
create an atlas with the key modicon
@slim ferry what would I do without you
you'd have to hardcode every card, but yes
I have a card that kinda does this
take this card I made
then you get another card and now it looks like this
i just wrote continue and lua suggested me this... is this real???
we're using gotos now?
lua doesn't have a continue
insane
genuinely
Hello, guys, I have a question for you! So, I'm trying to make set of jokers that have three abilities each. How would I do that?
even then you can do it on the cards instead of the edition and that would be much better
that is super vague, what answer were you even expecting? calculate functions allow you to have as many effects as you want
do you mean like this?
Yes, exactly what I'm trying to state
in your localization file
do
j_modkey_cardkey = {
name = "name",
text = {
{
"box 1"
},
{
"box 2"
}
}
}
add more tables for more boxes
Why thank you for the explanation!
This pseudorandom_element() in a deck apply function always returns the element C, is there some issue with using pseudorandom here?
apply = function(self) G.GAME.starting_params.removed_suit = pseudorandom_element({"H", "D", "C", "S"}, 'cod_triangle')
there shouldn't be afaik
try doing it in an event?
I said nothing
properly random then, but seems to be too late for the deck creation process
deck apply is run before the run seed is set properly no?
so this will always have the same outcome
i never really tried it so i thought it was something like that yeah
how are you removing the suit?
or is this some base config I am not aware of
patch in game.lua start_run()
if self.GAME.starting_params.removed_suit and self.GAME.starting_params.removed_suit == _s then keep = false end
I could probably just move the random call into that function
yeah that works
or maybe not if it's also too early lol
if it doesn't just remove the cards in apply
erratic funtionality in there uses pseudorandom so should work
makes sense
how can i insert description of a different object into loc_vars?
description type crashes the game:
({type = "descriptions", key = event.ability.extra.deck_key, set = "Back", vars = {}})
raw_descriptions returns a multi line table
localize({type = "raw_descriptions", key = event.ability.extra.deck_key, set = "Back", vars = {}})****
but since its a table i have to unpack it, but then i dont know its length so i would have to put #1#, #2#, #3#, etc
you would have to do something with either main_end/start or generate_ui
alright very specific demand here, is there a way to completely remove a joker's tooltip/part of it (like remove the white rectangle in which the description is located, or the rarity/mod handle, etc)?
essentially i want a joker that as no description, but still as a tooltip that has a name and a mod handle when hovered, if that's not possible or too complicated, removing the entire tooltip is fine if necessary.
this:
i've tried removing loc_txt but it leaves an empty white rectangle
you may have to engage in generate_ui shenanigans
I've removed the mod and rarity tag before, but not the description box
actually, wait
what happens if you just write an empty generate_ui function in your joker
hmmmmmmmmmmmmmm
generate_card_ui has a hide_desc parameter, maybe that could be used
try
oh that could work
i was gonna suggest doing something like
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
SMODS.Center.generate_ui(self, info_queue, card, nil, specific_vars, full_UI_table)
end```
oh wait that seems to make it look undiscovered
another thing i thought of is that you could make your loc_txt.text be an empty multi box
and then you could try this
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
SMODS.Center.generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
if full_UI_table and full_UI_table.multi_box then
full_UI_table.multi_box = nil
end
end```
and if that causes a crash,
```lua
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
SMODS.Center.generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
if full_UI_table and full_UI_table.multi_box then
full_UI_table.multi_box = {}
end
end```
i feel like somewhere around here is the trick to getting what you're after
at least my intuition is confident that your answer is in some kind of generate_ui fuckery
-# talbe
i'm still waking up okay 
lol
is there a way to detect jokers being re-ordered?
do i just drop generate_ui into loc_vars like so?
loc_vars = function(self, info_queue, card)
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
SMODS.Center.generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
if full_UI_table and full_UI_table.multi_box then
full_UI_table.multi_box = {}
end
end
end
i have no idea what i'm doing btw
it is not a part of loc_vars
it is its own function
aaaah
multi_box will only delete the multi boxes after the main one btw
alr this option crashes when the card is hovered
how can i render a tag like this (not give it out, just show)
and these don't work-
welp i'm at a loss again
have an initial example map
then flip the steps column by column
revealing the 2 more steps once flipped
a tooltip right
ohhhhhhhhhhhhhhhh
did i find it?
now i need to figure out how to put this in my event
thank you
RUBBER DUCK JOCKEY 🗣️
yezzzzzzz
i wanna check out later how to do mod combos
like not dependancy because they can exist without each other
but if they're both enabled it adds stuff
i can give u a function
FELIJO.is_mod_loaded = function(var) -- credit aiko
if not var then return false end
return (SMODS.Mods[var] and SMODS.Mods[var].can_load) and true or false
end
uh
so for example
FELIJO.is_mod_loaded("felijo")
would return true
you do know SMODS.find_mod exists, right?
well now you do
lol
0.9.8 ahh function
if next(SMODS.find_mod("felijo")) then
Also there's an important feature yours doesn't support
a mod can provide for a different mod, e.g. amulet counting as talisman being installed
why next? because find_mod returns an array? isnt there only one mod?
because of the providing mechanism, the result isn't necessarily unique
that's why it returns a table
Also it's based on find_joker
i dont get it, arent keys unique in nature?
every mod has a unique ID
i remember seeing some code snippet in smallpox about that
but any mod can provide another mod ID and count that as being present too
but different mods can provide the same mod ID without it being an issue
in which case find_mod will give you both
how would that not be an issue outside of amulet
you can have multiple of a joker
these mods can and should conflict if it's an issue
it's not an issue naturally
yo i got an idea for a consumable
basically using it will put you to a screen where you choose between 3 random tribes among a selection(canine, insect, vermin, avian, human....) you choose one tribe and you get the joker corresponding to that tribe
is there a mod that did that? open a screen that shows three cards and you select one? preferably not a dependency
i do that in joyousspring but i still haven't made a selection screen that you can't back out of
i need to
tag generate_UI generaties UIElement
but here i have balatro.Node?
isnt that the same?
nodes are a very generic object that basically every other game object extends from. ui elements are an extension of Moveables, which are an extension of Nodes
So if you add a seal during scoring, you can't hover over your cards to see their description until the seal has been added. Is there a way to fix that?
ohhhhh i see
and i actually have a UIElement.Definition not UIElement
add seal on context.before
no, i want the seal to be added after scoring 20 cards, so that the 21st gets the seal
in the og if? yeah i guess so
yeah
Why would you need to do that?
why is it hiding there 
LMAO
do what
add context.other_card to the first if? doesn't really hurt to add it, and it's a failsafe in case there's no card for some reason
that literally physically cannot happen
there will always be a card in context.individual
unless some mod is calling context.individual without a card but they shouldnt be doing that
that would be stupid
unless someone does something catastrophically silly
and you shouldnt account for that
we're so back
UI is a PAIN
GUYS I NEED HELP
I fedded up
i installed balatro mods and now the saves from before are gone
are they still there?
On the base game, they should be
i use a launcher that starts the modded version
but idk why it starts when i wanna play normal
like with 0 mods installed, it should all be there
I assume you would have to uninstall the mods if you wanted to play vanilla?
take that with a grain of salt though
i uninstalled the mods
its still there
thank god
ye it sucks
i will find a way to do both tho
i just panicked
i assume cryptid?
it has its own profile slots
did you install cryptid
or entropy
also #⚙・modding-support
actually idk if entropy does it on its own but cryptid definitely does this
does pwx do it?
pwx also does it yes
I am once again asking for help with this joker since it still doesn't work, I'm probably missing something simple since I have 0 coding practice but I'm still asking for help since I've been workshopping and its still not retriggering. SMODS.Joker {
key = "Universe",
loc_txt = {
name = "Universe",
text = {
"retrigger all played cards {C:attention}2{} times ",
"if all played cards have",
"the {C:attention}same{} Enhancement"
},
},
config = {
repetitions = 2
},
--unlocked = true
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
Atlas = "jokerimage",
pos = { x = 0, y = 0 },
cost = 7,
loc_vars = function(self, info_queue, card)
return { vars = {context.repetitons} }
end,
message = localize('k_again_ex'),
repetitions = 2,
calculate = function(self, card, context)
if context.repetitions and context.cardarea == G.play then
local enhancement = context.full_hand[1].config.center_key
for i = 2, #context.full_hand do
if context.full_hand[i].config.center_key ~= enhancement then
return nil
end
end
return {
repetitions = card.ability.extra.repetitions,
}
end
end
}
its context.repetition, not context.repetitions
okay thanks, OF COURSE IT WAS AS SIMPLE AS MAKING IT PLURAL
Welcome to programming
it's also config = {extra = {repetitions = 2}}
what's wrong with my hook,,?
local text_input_hook = love.textinput
function love.textinput(text)
if G.jokers then
for _, v in ipairs(G.jokers) do
if v.config.center.key == "j_elle_wordle" then
submit_letter(v, text)
end
end
end
text_input_hook(text)
end```
oh ty
but that's not the main problem
it says there's a problem with me calling text_input_hook
hm
what's the actual crash?
line 127 is the text_input_hook(text)
odd
sorry i'm kinda clueless lol
i do see orig_textinput in the crash dump somewhere, are you sure the code you posted here is the same as the code in your file and that you saved it?
yes
i've just tried
local text_input_hook = love.textinput
function love.textinput(...)
text_input_hook(...)
end```and it did the same thing
ok i'm actually running into the same issue, i tried saving love.textinput as a variable in my own mod and it's coming up nil
even tho love.textinput is a function when i check it in debugplus midgame
weird