#💻・modding-dev
1 messages · Page 123 of 1
what did you do?
Lovely patched to add a button
adding buttons to other buttons probably won't help much but fair
Should probably hook create_UIBox_HUD
How do I do that
however you hook anythng
idk how you would wnat to do it
but it's where the stuff on the left is defined
I don't even know what "hooking" is unless it's another way of saying Lovely patching or overriding functions
yes
it usually referes to overriding fnctions but it's kinda both
surely there's a function for "is this card actually in my deck or am I just hovering it from somewhere else"?
find card will find any joker with a certain key right? I specifically mean given some card ref determine if it's in my joker slots or shop/collection/etc
unless find_card can take a reference instead of a key?
Ah takes me back to the days of doing CSS
this is literally solved by display: flex
don't put relative on parent
some shit like that
Yeah this ain't it
idk
yeah ui stuff is kinda just aaaaaAAAAA
especially trying to fit stuff into existing ui
Throughts chat
would it be appropriate to put {C:attention} to Ace and 10?
it's in the latest master branch behind a config option if you want it
Where do I add the description here
is that..
uh
i--
here
SMODS.Joker {
key = 'claimhSolais', -- put the key as whatever you want, simplify it tho
config = {extra = {x_mult = 3, x_chips = 3}}
loc_txt = {
-- this is where the name (the one you see ingame) and the description are
name = "Claimh Solais",
text = {
-- whatever you want to put here as the description (multiple strings to get more lines instead of big horizontal)
}
-- the rest of it is (seemingly) completely fine so put the rarity, cost, blueprint_compat, etc where you had it originally
}
}
yeah but that isnt the format Im using
your code says "SMODS.Joker" when Im doing "local jokerInfo"
btw Im also having another issue, it shows in the code that I want to have it do 3X mult and 3X chips, but when I use it in-game, it only does the Xchips part
ok
still for the description, name and key you do smth like (with your format in mind)
local jokerInfo = {
-- imma only put the loc_txt and key and stuff thats important to your question
key = 'claimhsolais', -- put the key as whatever you want, simplify it tho
loc_txt = {
name = "Claimh Solais",
text = {
-- the description
}
}
}```
I dont know why it's doing this pls help
why does this code give me a crash about a card local being nil
if context.end_of_round and not context.repetition and context.game_over == false and not context.individual then
-- remove all crowd cards from deck
for i = 1, #G.hand.cards do
if (SMODS.has_enhancement(G.hand.cards[i], "m_bi_crowd")) then
G.hand.cards[i]:remove()
end
end
uhhhh try returning x_mult instead of XMult_mod
actually, can you verify that both are executed?
could be that lua only executes the last appearing calculate func
still doesnt work
^
just slap a differing debugMessage in both to check if both are actually being executed
what files are required for a modpack to be recognized by lovely? i have the assets themselves but idk what else would need to be added
the xchips is still the only one being executed
Hello, can I nest stuff in ['Other']?
If so, how do I access it?
I'm trying to do some logic in playing_card_added to the card that's added to the deck, but context.cards is just giving me a table with a single true boolean in it. Am I looking in the wrong field to get the added card?
I tried that, it works but only shows one message instead of separately showing the xchips and xmult messages
Yeah
hmm - in context.playing_card_added, when I buy a card from a standard pack, context.cards[1] gives me a real card. When I do it from DNA, it just gives me 'true'
could it be because DNA is returning {true} rather than the actual created card??
return {
message = localize('k_copied_ex'),
colour = G.C.CHIPS,
card = self,
playing_cards_created = {true}
}
i did it!
why did it do a fucking cartwheel
???
i cant tell what "it" is exactly but cool !
ok i scrolled up
thats super complicated
but also
really funny
unrelated question, but where can I get the deck skin you're using?
definitely great early
not done with them
no
i am just making what i want to
Okay but seriously how do I make the Xmult and Xchips messages appear separately instead of playing at the same time
oh god repeater seems awesome
I need help
great consistancy
Crimson Heart has been caught

please do not mind the art i am a programmer
same
i am that one friend who does art
the art of programming
please, I need help
whats the code
if context.joker_main and context.cardarea == G.jokers then
return {
message = localize{type='variable',key='a_xmult',vars={card.ability.extra.x_mult}},
message = localize{type='variable',key='a_chips',vars={card.ability.extra.x_chips}},
Xmult_mod = card.ability.extra.x_mult,
Xchip_mod = card.ability.extra.x_chips,
}
end
end```
is this eval_this moment
can you put that text between ```
but anyways, you cant use a return for two messages
-# or I think so
i love eval_this.png
SMODS.eval_this(card, {
-- the mult thing
})
how would you force skip an opened pack without being able to hit the skip button
if you wanna learn that you might have to tear open balatro’s code and see how packs themselves function
what does eval_this even do anyway?
allows you to evaluate multiple effect in the same context
-# better calc 2.0 makes it redundant in part since you can always pass multiple effects like you can in context.individual
may still need to be used if you want multiple custom messages though
i keep having a recurring but that causes immense lag and the inability to skip opened packs so i was curious
You can do multiple messages in better calc too assuming they relate to other modifiers
If I want to add a new color for formatting I would need to hook these 2 functions right?
to use it like {G:newcolor}{}
For formatting text descriptions?
You can do G.ARGS.LOC_COLOURS[‘nameofcolour’] = HEX(‘code’) too
Which should work, it might need a rogue loc colour call somewhere though I don’t remember
It might be working just not updating the display
https://github.com/Eremel/Ortalab/blob/master/objects/jokers/grave_digger.lua
I do it in here, might be able to adapt it
gameplay
wtf is that?
what do you mean by 'that'
uh... this?
I haven't worked with UIs at all
And plug my funny values if needed
when everything else fails, lovely.toml has my back 🫂
Added a new UIBox that can be accessed from a button, but for some reason I can only click it once, after closing it I can't open it anymore unless I play a hand, discard or start a new run
Any insights?
I'll provide code if needed, but it's a bit long
If you DM me the code I’ll take a look this afternoon for you
Alrighty then
i have a ui issue (seems to be a common theme tonight) where i have a consumable that increases the ante and the numbers on most places don't visually update
I think UIs need to be manually updated
As the displayed value isn’t the stored value
There’s probably some update or recalculate or whatever function that does it easily
i fixed this ui (this ui is updated on the spot, i was just missing a value in my code)
just to make sure, you don't have one_click = true right
rip
I just directly copied Run Info's UIBox
the one ui issue im still having is with the screen where you actually select blinds, which does have a create_UIBox_blind_choice function but that sounds like something i shouldnt be running myself
What mod can I download to have essentially a sandbox mode/creative mode?
To give myself specific jokers or consumables to test things, whether vanilla cards or modded
debugplus enables the built in debug mode (and adds a few more features), you can press tab to view the hotkeys
Awesome thank you
What issue
I remember messing with that UI but it was to add a tooltip to it
it doesnt update when all the other screens do
heres a video of the issue which is probably not very helpful unless my explanation is really just that bad lol
At what point should I make a thread for the mod I'm making right now?
People do one even for concepting so anytime
Yeah it's up to you. Some people start a thread when they have no art or code, only a concept. Some people do it when close to completion, and others do it when their v1 is ready.
Hola! alguien que hable español por aquí?
rule 2, english only.
sorry
ah, neat. I'm also thinking of a mod I'd like to make, changing the tarot textures for the cards in the Thoth tarot deck
who needs balancing
Did something change in the latest steamodded update? The enhancement I made now returns this error
Ah dang
Enhancement calculation now works like any other calculation
Ok it works now, but now it evaluates the card multiple times for some reason
What context are you using?
Use if context.cardarea == G.play and context.main_scoring then
ah, gotcha
Does anyone know of a way to destory a non scoring playing card before anything happens
So lets say a 22 88 K 2 pair, the king gets destroyed before anything happens
the enhancement is now working as expected. thanks!
im trying to upgrade the next played poker hand before scoring, where would i patch?
wdym the next played..?
like you use the consumable (its a consumable) then the next played hand is upgraded
i already have a global to know when to upgrade, and one that stores the upgrade, but im not sure where id patch
i want to add a seal to my mod but theres already like 4 mods that add some sort of spectral seal 
what does the seal do?
Hello, quick question: Do consumables have this calculate = function() -- stuff end thing? And if they do, when is it triggered?
the have an on use function
in vanilla, they trigger only for context.joker_main
but with better calc 2.0 they get all joker contexts
which can be used for this
what is better calc 2.0
i.e. keep the consumable when used but make it unable to be used again, then activate its effect and destroy it in context.before
idk tbh
new steamodded feature
I need this to trigger uh... as often as possible.
Or at least before any card scores.
context.individual doesn't uniquely identify any context
what do you want exactly?
so i can use contexts in my consumable?
i mean most spectral seals work like blue seal and only trigger if its in hand at end of round. i think for mine i would put it on scoring and make it forcefully add a spectral card, destroying a random (non-negative) consumable if you dont have an open slot
This card gains +5 mult for every card in your full deck (including used/discarded ones) with the same enhancement.
why dont you make the spectral negative
yes, assuming you're using latest steamodded
-# which currently a bunch of mods don't work with as of yet, so there's that
just count the cards before your main calculation and in loc_vars
i kinda want to have a downside to it tbh since spectral cards can be really good lol
im just gonna do my mod without new calc if most mods dont support it
nvm i really want contexts
they only dont support it because its new
and its only mods that do editions/enhancements/any talisman dependencies that won't work without changes
what are some examples of things that would need to be changed?
oh also any mods that inject into evaluate play or eval card
How can i recreate the blueprint/brainstorm ability in my own joker?
BUT OTHER THAN THAT they should be okay
what do they do that dont work without changes
any calculations
im not sure what thaat means
like anything that for example gives mult?
--glass
key = "SturdyGlass",
atlas = "Tatatro",
pos = {x = 5, y = 2},
unlocked = true,
discovered = true,
loc_vars = function(self, info_queue, card)
return {vars = {G.GAME.probabilities.normal, (card and card.ability.extra.DbfChance) or 5}, key = (card and card.config.center.key) or "m_TGTM_SturdyGlass"}
end,
config = {
extra = {DbfChance = 5},
x_mult = 2
},
calculate = function(self, card, context, effect)
if context.cardarea == G.play and not context.repetition then
if pseudorandom(pseudoseed("SturdyGlassDebf")) < G.GAME.probabilities.normal/card.ability.extra.DbfChance then
effect.x_mult = 1
else
effect.x_mult = 2
end
end
end
}``` is this ok?
no
here the context needs changing
that won't work
Is it a good thing
Good thing that Enhancements can be calculated much more easily, but bad thing that my current janky code used to circumvent limitations might go kaput?
the effect jank is gone
and it uses return values now
I did say to wait 😭
I didn't think it was THIS SOON
i can finally copper my cards!!!! yipeee!!!!
Oh god if I update my Steamodded now is everything going to break
yeah we've not updated the wiki yet
Wait so the effect parameter is just gone?
yup
calculate = function(self, card, context, effect)
if context.cardarea == G.play and not context.repetition then
effect.x_mult = 3
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = "Unblinded!",
sound = "fm_blind",
colour = G.C.BLUE
})
end
end
One of my examples, what should I replace it with then
Remove effect from the function parameters
And replace all instances of effect. to what?
how do i change enhancements of cards? i cant figure it out
so can enhancements use all contexts? (obviously not joker-specific ones, but you get my point)
return {
xmult = 3,
message = 'Unblinded!',
sound = 'fm_blind',
colour = G.C.BLUE
}```
that shoud replicate that
oh and the context to if context.cardarea == G.play and context.main_scoring then
im trying to make a card which will change 2 selected cards into glass
if you can find the tarot code, you should be able to use that
Like this?
calculate = function(self, card, context, effect)
if context.cardarea == G.play and context.main_scoring then
return {
xmult = 3,
message = 'Unblinded!',
sound = 'fm_blind',
colour = G.C.BLUE
}
end
end
i tried to find it
yeah that should work
but i couldnt
should be in card.lua? 
haha yeah
But Enhancements with no calculate function should just be fine right?
SMODS.Enhancement {
key = "circling_fish",
loc_txt = {
name = "Circling Fish",
text = {
"....."
}
},
atlas = 'Enhancements',
no_rank = true,
no_suit = true,
always_scores = true,
in_pool = function(self)
return false
end,
overrides_base_rank = true,
replace_base_card = true,
pos = {x=6, y=1}
}
yeah they should be fine
i searched glass there but it only shows the shatter code and glass joker function
or im just blind
I am not going to enjoy fixing all the bigger Enhancements
im 99% sure tarots are in card.lua
i mean nothing shows up when i search justice
if pseudorandom(pseudoseed("SturdyGlassDebf")) < G.GAME.probabilities.normal/card.ability.extra.DbfChance then
local x_multtt = 1
else
local x_multtt = 2
end
return {
xmult = x_multtt
}
end``` is this now good?
yeah that'll work
once you figure out how it changes it's a pretty quick fix
so what should i do?
how do i fix editions? do i put the return in connfig?
card:set_ability(G.P_CENTERS["m_glass"])
end```?
this sets the ability of all the selected cards to glass
i belive
lemme try
editions should also use a calculate now
So basically all not context.repetition should be replaced by context.main_scoring?
yes
Alrighty then
wait.. do all consumables use a calculate now???
And the calculate function actually uses a return function now, so all effects and parameters are dumped in there?
Forget my question it was stupidly worded but
Anything with effect.xxxxx and card_eval_status_text parameters are now combined into a return function?
Anyone know why card:start_dissolve() creates a ghost card but shatter() doesnt?
and if theres a correct way to use start_dissolve?
on-use effects still belong in a use function
but calculate can be used for anything a joker can do
there are 5 main contexts for editions now, though you can use any of them. You should probably use a combination of (context.cardarea == G.play and context.main_scoring) for scored cards, (context.cardarea == G.hand and context.main_scoring) for held card effects, ~~ context.joker_main for joker effects~~, context.pre_joker for effects before the joker itself triggers, and context.post_joker for effects after the joker triggers
yeah that's correct
Anything else belonging into the return function? Maybe card.ability.extra.xxxx?
no that modifies the values in your card
Righto
the return table basically adds it all to what effect referenced before
Here's a slightly more complex example:
calculate = function(self, card, context, effect)
if context.cardarea == G.hand and not context.before and not context.end_of_round
and card.ability.extra.hands_seen < 1 then
card.ability.extra.hands_seen = card.ability.extra.hands_seen + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = "Amplified!",
sound = "fm_amplified",
colour = G.C.BLUE
})
end
if context.cardarea == G.play and not context.repetition then
if card.ability.extra.hands_seen > 0 then
effect.mult = 15
card.ability.extra.hands_seen = 0
end
end
end
So I replace:
not context.repetitionwithcontext.main_scoringcard_eval_status_textwith a return function with those parameters in it- replace
effect.multwith a second return function underif card.ability.extra.hands_seen > 0 then, inside it ismult = 15only?
-# what is a return function
yeah that should work perfectly
if you have multiple things you're putting in effects in the same context, ofc these go in the same return table
but yes
yeah I get that, like this one
if context.cardarea == G.play and not context.repetition then
effect.x_mult = 3
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = "Unblinded!",
sound = "fm_blind",
colour = G.C.BLUE
})
end
and make sure it goes at the end of each block
So my ""implementation"" of post round effects are not nessesary?
2 conditions under the same context
like here you need to reset hands_seen before you return
Does anyone know how to recreate the blueprint/brainstorm effect in a custom joker?
woops, joker_main isn't an edition context
Oh so return takes last priority in a context if case?
return exits the function completely and passes out the values you give it
So that's a yes?
if that's what you mean, then yes
actually I think it's simply an error in lua to put statements after a return
yeah it just crashes
Ah
if context.cardarea == G.play and not context.repetition then
if card.ability.extra.rank_increase > 0 then
local original_rank = card.base.id - card.ability.extra.rank_increase
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
local rank_suffix = original_rank < 10 and tostring(original_rank)
or original_rank == 10 and 'T'
or original_rank == 11 and 'J'
or original_rank == 12 and 'Q'
or original_rank == 13 and 'K'
or 'A'
card:set_base(G.P_CARDS[suit_prefix..rank_suffix])
card.ability.extra.rank_increase = 0
card.ability.extra.last_hand_number = -1
card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Reset!"})
end
end
What about something like this, are the only changes I have to do are to turn card_eval_status_text into a return function and replace not context.repetition?
Sorry for asking basically the same questions I just need to really, really make sure lmao
can i make jokers have a use function?
card functions, etc, do they go in there?
anything on card stays the same
good old janky vanilla playing card logic
this falls apart horribly with any custom suits or ranks
well steamodded has APIs for this and custom suits/ranks aren't all that rare
-# well ranks are
speaking of
i should provide util functions to increase/decrease a card's rank
why does this not remove the cards like i want to :(
if context.end_of_round and context.game_over == false then
-- remove all crowd cards from deck
for i = 1, #G.deck.cards do
if (SMODS.has_enhancement(G.deck.cards[i], "m_bi_crowd")) then
G.deck.cards[i]:remove()
end
end
end
G.deck.cards[i]:start_dissolve()
It has an animation and I don't know if remove actually exists
And also proper card destruction handling
it does
?
not unless you make jokers able to be used like a consumable
wdym?
jokers don't have a use button that allows you to use them
if you make them have one, they can indeed have a use function
how can i make them have the button though
you'd need to lovely patch into G.UIDEF.use_and_sell_buttons
And that in itself is a can of worms
they stay in deck :(
but this works excellently
no playing or discarding when this card is selected :D
How did you figure that out
I was trying to do that for days but ended up scrapping the idea
maybe this is more an issue of G.deck not being what you want
it has only cards in your literal deck pile, i.e. ones you haven't drawn
a bunch of everything, searched "disable discard" found one message wanting to do this which pointed to a piece of code that had to be pattern patched
im looking to destroy cards that got copied to hand similar to DNA
G.playing_cards has all of your playing cards
I dunno if there is a special flag or identifier to denote that the card is cloned
ahh
no but it's possible to make one when creating the card
it had to be added to deck though to add it to hand
still applies?
local _card = copy_card(context.full_hand[1], nil)
_card:set_ability(G.P_CENTERS.m_bi_crowd, nil, true)
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, _card)
G.hand:emplace(_card)
_card:start_materialize()
add_to_deck doesn't add the card to your deck
?????
it just evaluates effect that happen when you obtain the card
the card was never in G.deck
assuming it can't get there (or to the discard pile), you'd just need to go through G.hand.cards
reposting this now that maybe more people are around who can help, how do i update this screen (referring to the "Choose your next Blind" screen) to have the correct values
im doing that too but on the selling_self context hahah
okay this works beautifully
YE IT DOES
Thank you so much john
maybe you want to move that to remove_from_deck... two questions:
- what's supposed to happen when the joker gets debuffed?
- what's supposed to happen when the joker gets destroyed?
oh right that can happen
it would seem the current version doesn't destroy the cards at end of round if the joker is currently debuffed, and the cards are permanent if the joker were to get destroyed during a round (and is the last one you have)
Thats a really really good point actually
I didnt consider those scenarios
if debuffed, it should just not give a multiplier
I tried this before and failed again, but is there a way to change a value before scoring?
if destroyed, id say destroy cards and draw new ones just like when you sell the joker
show code
interesting side effect: this will cause the cards to not be destroyed if the joker is sold in a debuffed state
the steamodded wiki isnt particularly vocal about it, does it cause the calculate function to not run when a joker is debuffed?
indeed no calculation occurs on debuffed jokers
remove_from_deck is also called when a joker gets debuffed (and add_to_deck when rebuffed) with an extra argument indicating this is from a debuff
I think you want the first flip and the set_base not in events
almost
ahh
okay so this might be a dumb idea but what if i manually call the calculate function with my own context for the cause
uh why
i dont see the context in the parameters and i'm unsure on how to detect selling in that case
i tend to overcomplicate things when i have no point to go from
Theres a context for selling, check Campfire
yeah but not in remove_from_deck judging from johns screenshot
for calculate theres context.selling_self
Sorry if you got this asked 100 times but what effect are you trying to do?
Trying to fix a few edge cases that john brought to my attention
What your joker does?
for every hand you play in a round, it spawns one Crowd card. Each crowd card adds +2 mult plus one additional mult for every crowd card on hand. It also blocks the card slot as it cant be discarded or played
Selling the joker removes all crowd cards and immediately draws an equal amount of new cards from deck
What if its removed during shop?
nothing happens, you get your money and thats that
looks like I'll have to call lovely for help
All crowd cards are removed from your hand after each round anyway
is it possible to add a new color for an addedk_xyz_ex value?
for example, add a new k_xyz_ex value that says something else and have the little square be purple?
oh you want it before hadn evaluation
wwhat contexts do consumables have?
I'll just failsafe it for now
context.using_consumeable = true
context.consumeable = card
from what I understand, consumables do not have calculate = function (without the use of lovely patches)
if you mean like in use = function idk if it has any?
you can return a colour in the return value of your calculate function
oh like that
previously joker_main only
now it's all contexts that jokers also have
so before is real?
they actually do even in vanilla, think of observatory
oh
also, how do i use the juice_card_until function
yea ill settle on a failsafe to remove all enhanced cards and reset variables when debuffed
what could go wrong 
i know dreadjoker's statements uses that, look into that
OH MY GOD!!! i can finnally remove the randdom joker i made!!!!
it takes a card to juice and a function. it will wiggle the card so long as the function returns true
once the function no longer returned true (or you exit the run), it will stop juicing the card
speaking of, is it a bit too resource heavy to iterate over every highlighted hand every frame
yes
whats the reason for it?
there's probably a better way
disabling the play/discard button
with this absolute monstrosity
# Helper
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = 'G.FUNCS.can_discard = function(e)'
position = 'before'
match_indent = true
payload = '''
G.FUNCS.has_crowd = function()
if #G.hand.highlighted > 0 then
for i = 1, #G.hand.highlighted do
if SMODS.has_enhancement(G.hand.highlighted[i], "m_bi_crowd") then
return true
end
end
end
return false
end
'''
# Crowded Discard Disable
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''
if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
'''
position = 'after'
match_indent = true
payload = '''
elseif G.FUNCS.has_crowd() then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
'''
can't you hook into add_to_highlighted and remove?
or at least add a flag in those functions
very very likely but i have no idea about hooks, they arent very well documented
just emplace the playing cards to G.jokers and then they cant be discarded 
nuh uh
they are supposed to take a standard card slot away
can someone give me a quick rundown of hooks 
you create a refrence of the original function, then you override the function, making sure to execute the original function, profit
local hook = functionnamehere
function functionnamehere(original, args)
-- insert code before here
local ret = hook(original, args)
-- insert code after here
return ret
end
very basic skeleton here
so you can add your own code either to the beginning or the end of the original function without modifying it
for your case, I'd create a global count of the card in the highlighted hand, raise it in add_to_highlighted and lower it in remove_from_highlighted, then in your initial lovely patches you can just do if globalCounter then bla bla bla
that already helps so much thank you :D
could you lovely patch other mods?
so if i had a joker already, could i copy the whole calculate function into the consumable?
technically yes but it's currently broken on lovely's end
if you build lovely from source or wait for 0.7.0 (which should hopefully come this week), this is possible
funny
[at least if we can take meth's word](#1214591552903716954 message)
I think you should be able to hook calculate_context too, right?
im completly new to this stuff, so i dont really understand.
wouldnt i need to make new UI code or something? cuz all the k_xyz_exs are just in the dictionary and use the same animations
No, you just add the colour variable.
you just add it to the return in your calculation
the k_xyz_ex variables are literally just text. you just need to return the colour variable with your message
i guess so
where do i put the hook though
i.e.
{
message = "PURPLE GUY",
colour = G.C.PURPLE
}
i understand that, but im trying to change the color of the orange square
just in your lua file
yeah
not inside something else 😆
ofc hahah
i think technically its anywhere that has a global context but yeah basically
Alrighty
something like this or am i dum
my head is friend basically at this point
wait
set the wrong value but otherwise
it needs to +/- not set
otherwise if you select 2 then deselect 1 it'll let you play
so G.bi_crowded_highlighted = (G.bi_crowded_highlighted or 0) + 1
got it :D
also in your case, you can condense the last two lines to just return hook(...)
and the original args bit and function names will need correcting
I think they're CardArea:add_to_highlighted, which would mean you'd need to check if self == G.hand too
rebalance?
i think k_nope_ex is the only purple one
the localization entries have no associated colors
return {
message = "This can literally say whatever you want",
colour = G.C.PURPLE
}```
yeah so im trying to figure out how to make a k_ex effect that has a purple square, not make one that has purple text
oh okay
diamond pickaxe maybe? but netherite seems pretty fine actually
that is a huge amount of chips
maybe 100
got confused cuz the formatting is a little different, but awesome thanks
enchanted edition when
Silk Touch adds every Boss you defeat to your deck, so when you draw them you fight them again
No bonus hands tho
i mean
it's no longer called Aikoyori's Jokers
so i can add literally anything in it
I’d have thought it’s the other way around
If your mod isn’t named after yourself then you can’t add to it
can you make a bedrock edition toggle which solely disables QC
😭
It’s not aikoyori’s it’s now Bob’s
some guy's shenanigans
It overwrites yes
ok
I think i found how i can lovely patch the names so i can use whatever i want for the name of a playing card
I'm gonna test it out in a minute
I don't get the hook :(
It replaces it sure but I can't seem to get my logic to work
Yeee
Did you type it correctly
Wdym
what’s bi crowded
Should be, it's the original function in hooking right below there and it matches
a custom enhancement
Ah a global variable
What do you want it to do
it's not formatted correctly
replace add_to_highlighted with CardArea.add_to_highlighted
Elaborate
the function is stored within the object CardArea
so when you try and replace it by just using add_to_highlighted, it doesn't exist
@quaint latch is it something like this
How might i go about changing the background shader?
it has an effect on discards tho
How can I get a list of what jokers are being held?
G.jokers
G.jokers and not G.joker.cards?
I tried that last time and the game kept crashing
Nop
How did you use it?
You might have to check if G.jokers exists beforehand
I had to concat it to make it a string so I could Tprint it
Uhhhh
It’s been a while since I used Lua so I am quite rusty
And this crashes my game on selecting something by having a nil center
Most people just use print(inspect(table))
Oh, that sound so much easier
So you can substitute table with G.jokers.cards
Still waiting for an answer on this
Is there a scoring context for whenever playing cards are destroyed? (i.e. would be triggered by glass card shattering or by trading card)
Tried cards_destroyed but doesn't seem to be working
put hook(self, card, silent) and change the . in the function line to a :
See Canio
are there any mods that I can look at for an example of changing existing decks? I'm wanting to change Black Deck to start with the +4 Mult Joker already equipped
I fiddled around with the source code to have it start with the Hieroglyph voucher as a substitute, and it works, but the localization's a bit weird
-Heirogypth hand every round
-heiruryhth hand every round
Probably wrong loc_vars
I put this line in line 59 of back.lua (where the Black Deck is)
elseif name_to_check == 'Black Deck' then loc_args = {effect_config.joker_slot, localize{type = 'name_text', key = 'v_hieroglyph', set = 'Voucher'}}
As I said
loc_vars
Like the name of a Joker?
Name of a playing card
[[patches]]
[patches.regex]
target = 'functions/common_events.lua'
pattern = '''elseif specific_vars.playing_card then'''
position = 'at'
match_indent = true
payload = '''
elseif (specific_vars.playing_card and (_c.name ~= 'Stone Card') and (_c.suit == 'Others')) then
full_UI_table.name = {}
localize{type = 'other', key = 'playing_card2', set = 'Other', nodes = full_UI_table.name, vars = {localize(specific_vars.value, 'ranks'), colours = {specific_vars.colour}}}
full_UI_table.name = full_UI_table.name[1]
elseif specific_vars.playing_card then
'''```
What I did was to give it a weird name then check for the weird name and replace it
Unless I'm supposed to lovely patch in the freaking localization
When assembling the tooltip
Hm?
@wooden nexus for the Credits
I have various weird strings then I identify which one is which to replace the name with Credits and some other string for the body
Yeah, canio checks for context.cards_destroyed, but that flag never seems to be true in my joker's scoring method
I just wanna remove the "of Others" from my "Others" suit
How are you testing
It needs small adjustments but it works, thank you!
Should I bump it to uncommon?
screw it, I'm gonna lovely patch it into localization to see if it that works
I just have this right now as my scoring method:
calculate = function(self, card, context)
if card.debuff then return end
if context.cards_destroyed then
print("worked")
end
end
I've verified that it's getting called
You don’t need to patch localizations
Well you shouldn’t
But it’s bugged right now
Which is why I'm patching the localization until then
@frosty dock 🥺 fix pls
the "Not Allowed!" boss blind alert also isn't localised
that's just vanilla game tho
wtf, it's still not working, am i just doing the wrong function or something
I was trying to edit the generate_card_ui function for now
Using trading card to destroy cards and see if that "worked" message gets printed. Canio procs as expected, by my joker doesn't
patching localization is not possible and not needed
neither is it if my concern
smods supports localization files which is all you should need
is there any like... documentation on talisman? im curious as to the fine details of what it provides beyond "bigger numbers" and how I might make mods compatible with it
I'll add something into steamodded to take care of names for playing cards though
That’s what’s bugged
As we talked a few days ago
not if you don't use default.lua
only the default.lua vs en-us.lua right?
I guess but I do use that so
then don't
I think big numbers are tables
its being replaced by a metadata field to choose which lang to use as default
then is function generate_card_ui not the function i want to edit playing cards for now?
looked into the search bar a bit on talisman and i think i saw stuff about it adding x_chips as a possibility is that true
im kinda curious as to whether that ability could be balanced properly
yeah talisman adds x_chips
x_chips is functionally the same as x_mult apart from 2 specific situations
I mean, it's just x_mult most of the time
wouldnt it just work like mult in that you get +chips first then x_chips
how is it different with that 🤔
generate_card_ui HAS to be the function I need because there's nothing that uses the localization of playing_card... lemme try something again
say you have a foil joker that you really want to put last
[patches.regex]
target = 'functions/common_events.lua'
pattern = '''elseif specific_vars.playing_card then'''
position = 'at'
payload = '''
elseif (specific_vars.playing_card and (_c.name ~= 'Stone Card') and (_c.suit == 'a_other')) then
full_UI_table.name = {}
localize{type = 'other', key = 'bazinga', set = 'Other', nodes = full_UI_table.name, vars = {localize(specific_vars.value, 'ranks'), colours = {specific_vars.colour}}}
full_UI_table.name = full_UI_table.name[1]
elseif specific_vars.playing_card then
'''
Strange. I even tried making it a random word to try and make it that
unless it's not _c.suit
its better game design to only have a multiplier on one of the values imo
yeah im not sold on the idea of it but im kinda hitting the wall of inspiration for ability ideas i suppose so i was just like "ooh shiny new ability" at the possibility of xchips
i have a stupid idea
thing im wondering with the compat is like'
what if someone doesnt want to use talisman
Welp, i'm hitting my head off a brick wall, I don't get it
is there a fallback
if talisman else
that's the second part
then define to_big if it isn’t defined
that's what you define to_big for
ah gotcha
you just set it to return its argument as-is
you might want to try to find a mod with talisman compat (but no dependency) to see what they do exactly
i will turn balatro into something more kid friendly
yeah i imagine a mod like uh, bunco or something is compat
(education)
i added sigma (summation) chips, just pick a random sum or formula and you can probably come up with something interesting
how can i check if G.jokers.cards exists before calling for it?
SMODS.Keybind{
key = 'CheckJokers',
key_pressed = 'm',
action = function(self)
if G.jokers.cards then
print(insepct(G.jokers.cards))
end
end,
}
wdym by that
sumamtion is adding every number in sequence, essentially factorial but additive instead of multiplicative
just checked some mods, seems like LobCorp has proper support (but no dep)
so &4 chips is 10 chips in total, since 4+3+2+1 = 10
basically just come up with the stupidest formulas and do funny things with them
that
eh not really something i think would fit in cardsauce thats a bit needlessly complicated no offense
like i may as just like have it be +10
That should do it. Is that not working?
im mainly using it for scaling jokers or jokers that can change their inherent values (see raised fist)
someone make this real
im crashing whenever i press M
With what error message?
let me grab it rq
wdym it is real
😭
localthunk will add this 
im trying to comprehend this
it is glory
oh, it only crashes on the main menu
i mean all you gotta do is change every single card texture to GROS MICHEL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
which makes sense
Probably because G.jokers also doesn't exist on the main menu. So if you wanted to avoid that outcome, just also check if G.jokers exists
how helpful...
myst the goat
I mean thunk did it too
Nice
Okay, if i want to check for a joker's existance, should i be checking its Alias or Name
Key
Okay, thanks
@frosty dock , 90% sure custom jokers never have their calculate method called with context.cards_destroyed set. context.removing_playing_cards gets set instead, which isn't something I ever see in vanilla code 🤔
context.cards_destroyed was never real, I don't think
the base game pretends to use it for canio and glass joker but it's never called anywhere
which looks better, left or right? or some other variation?
(these are supposed to be weird fishes)
left
maybe im making it uncommon
this too strong?
I had a secondary idea that would be sorta like monolith, where it reset when you play a flush
as a flush stan, i hate this card 😭
Also this counts for all flush hands: flush, straight flush, flush house, flush five
AAAAAAAAAAAAAAA
hm?
Why the ping then?
the jack of spades looks similar to that character that's it
Yeah can confirm this, I just copied contexts over from base game and added a few extra values to some to help distinguish them


it was stupid
How can i delete a joker when a certain thing happens?
wrong video here is a new one
oh wait theres an example on the wiki huh
i mean
so it didnt flush, did you mean for it not to flush
score stone first then break it apart
ah ok
so ig its good right
HATSUNE MIKU???
should the stone cards get a random suit + rank when you break them?
They already have a suit and rank underneath
also out of curiosity, how do you do the drag selection
func = Lua function '?' (defined at line 906 of chunk main.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"])
something out of here is wrong
a mod called Handy
._.
i love hatsune miku
sure
could do that
i dont know what is wrong though
also anyone has bit of simple mods? so i can invesitage code and make my own with bits
https://github.com/Eremel/Ortalab
ortalab best mod for looking at examples of code
-# shameless self promotion
btw whats that Retrigger API for, i assume retriggering stuff (which i need for my joker)
its good promotion lol
also what the hell is an atlas
return { vars = { card.ability.extra.chips, card.ability.extra.mult } }
end,
calculate = function(self, card, context)
if context.other_card:get_id() >= 2 and context.other_card:get_id() <= 9 then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
card = card.other_card
}
end```
this is the code which causes the error but i dont know what it is
^
basically its an image with a bunch of textures
i wonder, why one of ends has "," but not the other
i am may be wrong cuz i am new to this still
no thats not it
other card is dead
Your context check isn’t correct
it used to work 2 days ago
This will never have worked
let me see if i can find old versions of my code
oh yh mb
i removed something on accident
i will try to add marbles into the game
gl
is there a faster way to reload my mod than literally restarting the game
Depending on what you're doing there is https://github.com/WilsontheWolf/DebugPlus/blob/master/docs/dev.md#watch
also is adding "joker" into sprite is really neccesary?
Heyyyy! Would anyone be up to test my joker for bugs (play a few rounds with it) :D
From my limited testing it seems to work fine but I wanna make sure it's field tested
pov: trying to draw a marble without talent
ohh i didn't even see the watch stuff, cheers
how would i draw a "soul" on top of a joker without it also drawing a shadow
i can set a soul_pos just fine but the shadow makes the card look really messy lol
hey guys - messing around with some mod dev
how should I include smods for my lsp?
oh this is gonna be good
its like c with no lsp or internet, just manpages, and every time your code errors out you delete it
you might be able to get away with just cloning yhe smods repo somewhere your lsp is aware of and if you pray hard it might work
ok chat how do i override joker effects, looking to make smeared joker work for custom suits
you can take ownership but I belive smeared doesn't actually have it's effected tied to itself
its in Card:is_suit() iirc
whuh
hmm
so then i would need to check if smeared joker is in play and then edit it from there?
you think if i just make an lsp override to ../smods itll work?
take a look at how Card:is_suit works
¯_(ツ)_/¯
how do i figure out if played hand contains 2 specific ranks
those are suits
loop through the played hand and check get_id() on cards i think?
lovely patch or hooking
you see you assume i know what im doing at all
what if instead of lovely patches we used ```lua
local pattern = "function c(b)"
local replace = "function c(b, d)"
local function hook(line)
local filename = debug.getinfo(2).short_src
local file = NFS.read(filename)
local repl = string.gsub(file, pattern, replace)
NFS.write(filename, repl)
end
debug.sethook(hook, "l")

wouldn't work for the games files
big scam
lsp works
how do i properly destroy card in hand
im so cool /s
idk tickle the ram
silly
(now extract balatro's files into the same spot to get the LSP to work with balatro's globals)
(im on mac rn i cant decomp the file)
Not entierly sure btu the game doesn't like it in certain contexts
open the app and extract the game.love
mac can't extract zip files?
if anyone here is curious how i did it
it doesnt recognize as a zip file
rename it
i tried
ask the OS nicely
or use the temrinal
ive been tryin
SMODS.Joker {
key = 'jjj',
loc_txt = {
name = "J. J. Joker",
text = {
"Retrigger entire hand",
"if played hand contains",
"an {C:attention}Ace{} and a {C:attention}10{}"
}
},
rarity = 2,
atlas = 'atlas',
pos = {x=3,y=0},
cost = 7,
calculate = function(self, card, context)
if context.joker_main then
local has_ace = false
local has_ten = false
for _, card in ipairs(G.hand.cards) do
if context.card:get_id() == 1 then
has_ace = true
elseif context.card:get_id() == 10 then
has_ten = true
end
if has_ace and has_ten then
break
end
end
local result = {}
if has_ace and has_ten then
for _, card in ipairs(G.hand.cards) do
table.insert(result, {
message = localize('k_again_ex'),
repetitions = 1,
card = card
})
end
end
end
end
}
guys i dont think my balatro likes it when i have 5 j j jokers and i play a hand with an ace and a 10
did you use the right file?
it has a weird formatting iirc
oh hey
obviously it's not gonna be a fucking exe am i silly
I mean it is on windows
this isn't windows
lemme add it
I should figure out text completion on nvim
I just migrated over and been writing code manually for a while
language server protocal
(i do not know how to do jokers)
ve seen it in a few places
my luals is really terrible in terms of performance for some reason
it might be that it looks at non-lua files for some reason or some weird shit
it's usually useless anyways so it's fine
ok well now sixsuits has a problem with me WHY
this is new
did you move the Balatro.love?
yeah lol
Balatro Minus Balatro
_ _
houuughhh i dont wanna learn how to edit functions i dont wannaaaa
you went and lost your game 💀
i just want smeared joker to work with custom suits 😭
there was never a game
wrong dimensions
goty edition
true
its actually really easy
what
You can hook #💻・modding-dev message or use lovely patches https://github.com/ethangreen-dev/lovely-injector?tab=readme-ov-file#patches
hook is simple
how does he just do that
mainly the forcing a fucking sharks jaw shut that's what im confused about
nose is weak point
probably wrong key for adding chips
what's the context.cardarea for checking played cards (checking if each card is a different suit in a 4 card hand)
function is_suit(Card:is_suit, suit, bypass_debuff, flush_calc)
if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds' or self.base.suit == 'Stars') == (suit == 'Hearts' or suit == 'Diamonds' or suit == 'Stars') then
return true
end
local ret = hook(Card:is_suit, suit, bypass_debuff, flush_calc)
return ret
end``` why do i have a gut feeling that i didnt do this right at all
function Card:is_suit(bypass_debuff, flush_calc)
if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds' or self.base.suit == 'Stars') == (suit == 'Hearts' or suit == 'Diamonds' or suit == 'Stars') then
return true
end
return Cardis_suit(self, bypass_debuff, flush_calc)
end```
it works perfectly thank you i love you forever
it also really helps that i have some sort of template/basis to branch off of
this is what i did for wild card functionality on my hook
screenshot is weird because i'm on my phone
still why is the chips added after the hand
hello gang are we allowed to put wip screenshots in this channel or is that somewhere else
I havent published it yet so I dont think I do
Hi yall! I'm a LEGO youtuber and I used to make minecraft texture packs, so this idea kind of fell into my lap. I'm LEGO-fying balatro, my aim is to change as much as Im able into lego, sound effects, animated blinds, all the deck backs and everything in between. been working on this since just before christmas, making great progress. heres some of my favorite things so far
Does SMOD have anything for Code Completion or the little menu that drops down that shows you available options
oh do i have a thing for you
scroll up around here
I saw and I was hoping there was like a public version
How’d you do it because I honestly can’t tell lol
ok those legos are peak
agreed i fkin love the lego
create a .luarc.json in your mod folder
{
"workspace.library": ["../smods", "../../BalatroGameSource"],
}
chat
if anyone knows why my seals arent working that would be so helpful. I think I just havent got the reference path correct, because the centers work
is sixsuits broken or did i fuck up my mod so badly that its interfering 😭
Not gonna lie to you, I got no idea what I’m looking at lol
do you need any extension
_ _
like specific one
oh i just realized i fucked up
i put SMODS.Joker = { when making my joker
my dumbass
I knew there would be some non-scuffed way of getting separate workspaces to work w/ VSCode (others were having trouble with this).
Completely forgot that lua lsp works for vscode lmao
im on a mac, anything else lags the fuck out lol
I’m seeing double (hello other Astra)
aanyways this is my first attempt at making a joker does this are have the work or na
joker.calculate = function(self, context)
-- if played hand has 4 cards
if context.cardarea == G.play and #context.scoring_hand == 4 then
-- and each card has a different suit
local suits = {}
for _, card in ipairs(context.scoring_hand) do
suits[card.suit] = true
end
if #suits == 4 then
-- then multiply the score by 4
context.score = context.score * 4
end
end
end
ANOTHER ME???
Lmao
there we go
dear god there's more of me
omg i want to draw a hand of specific cards
QUICK CALL THE SCP FOUNDATION
for VS Code you need this
Wait your status is Outer Wilds we really are doubles 
Oh my god yes
What’s the code?



