#💻・modding-dev
1 messages · Page 410 of 1
what do you currently have in loc_vars and config
it does save dw
you fixed it?
it already saved before, the problem is that it wont show the current value
loc_vars should show current value
:/
No, they are refering to how it doesn't show the current values of the joker it is replicating.
ah
Are there some references I can look at for how hooks work
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
can i make a rainbow text or smthing
Yes.
SMODS.Gradient?
Can I read a .txt to use for declare vars inside my mod?
how does this work
Can I use fetch to use a API?
thgank you
You put SMODS.Gradient in a variable and you refer to that.
Code?
How can I make a card polychrome in the shop by default? And force polychrome when it's added to G.jokers?
{C:rainbow}{}
from what I know you don't have to put the gradient as a variable as it auto registers with it's constructor, using the rainbow key should work normally
nah didnt work any way
You need to do modprefix_key
:/
set_ability = function(self, card, initial, delay_sprites) card:set_edition("e_polychrome") end
still not working
Code?
interpolation = 'linear'?
o
what would be the way to go about making it so only a couple cards of a rarity can spawn in the shop?
the easiest idea i can think of is just making two rarities identical except one can spawn in the shop but that seems. jank at best
You make the in_pool of the jokers that don't spawn return false.
darn. I was hoping it could be the other way around because there would be fewer jokers that will be in the shop (so it would be less work to do the ones that will spawn.) but alas
{C:ub_rainbow} in the text variable
yo if you just have texture mods and stuff do u not get achivments
nothing to do with gamplay like
youll prolly have to go into the settings and change this
ah ok thanks
np
im kinda new to balatro and i finally got gold stake done just changed the thing and now i have to do gold stake again to get the achievement😭 🙏
😭 I havent even done gold stake non modded gl out there
(im just here for the chaos)
so this works in terms of triggering the context, but now space joker doesnt level up the hand
What does it look like in the lovely dump?
Detecting "level ups" of hands, assuming?
whenever a probability hits
crypted mod my beloved
should I trigger the calc context after the return instead?
ok phew I thought so
what do I do instead then
man 😭
oh Yk what
What if I put it in an event
Actually yeah thats probably it
space is the only one that hasn’t been in an event
no wait bloodstone
why isn’t this working then hhh
maybe it’s a bug and I just have to reboot
if (context.other_card == G.jokers.cards[this_joker - 1]) or (context.otherCard == G.jokers.cards[this_joker + 1]) then
return {
message = localize('k_again_ex'),
repetitions = 1,
card = card
}
else
Why does this code snippet only repeat the Joker to the left of the current Joker and not the Joker to the right
context.otherCard doesn't exist.
oh
other_card does
thank u
my eyes are silly
Which you did for the left yeah
I'm too used to camel case
save it for variables
After generating the shop list, it seems that despite my best efforts, real cards are made and still take up processing power, tanking my fps. I tried to use the Card.remove() function to delete the card after I take a note of it, but alas it still exists somewhere. Any thoughts?
What is creating the card?
I made an alternate function that emulates Card.create_card and have been removing parts as needed, but otherwise it is exactly the same as Card.create_card
That method is called by a copied version of create_card_for_shop if that matters
What is the purpose of creating the card if it only causes bad things?
I am making a mod that functions like The Soul and the only way I could accurately generate the shop list was by doing it the same way the game does 😅
Thinking about it, I probably can just get the center and skip the part about actually generating the cards.
function SMODS.has_no_rank(card)
if card.seal and card.seal == 'charcuterie_obscure' then
return true
end
if card:get_id() > 10 and next(G.jokers.cards, 'j_charcuterie_aphantasia') then
return true
end
return smods_has_no_rank_ref(card)
end
okay ive fucked something up terribly
it softlocks when i do card:is_face
and crashes so hard when i do this that it doesnt even show me a stacktrace
It was not a bug space joker no longer levels up the hand
do I have to put the calc context IN the return?? That doesn’t make sense
maybe I should try after just to see
were you giggling while making this
what’s the correct way to do it i’m so confused
maybe the one without the yellow line
well on the is face function
i think it’s referencing another method on the card?
idk
What is the goal?
to make face cards not have ranks whenever a joker is active
wait
then
if they don’t have ranks
how will the game know if they’re face cards
fuck
hey chat why is context.card.config.center.key not the key for the joker and what can i use instead? (cav is my prefix)
It is the key.
i’m gonna rework this to apply a seal to played face cards that then makes them rankless
wait how do you put cards in a booster pack?
i guess the issue is something else then ty
do you have any idea why? the detection of the probability hitting and subsequent mult gain works fine, but now the level up itself won’t trigger
When a booster is opened add a card to G.pack_cards?
Is the warning to say that you can tell whether or not it's a played or discarded hand by checking if scoring_hand is nil or not
oh my god is it because space joker triggers in context.before
how do i draw a specific card from the deck? do i use draw_card or SMODS.draw_cards?
Probably.
baller
What is the goal?
i have an enhancement (honey) that when drawn has a chance to draw another honey card. my code currently selects a random honey card in the deck, and i just need to find a way to have it drawn to hand.
You would probably use draw_card then.
ok chat so i want to make a joker that gives X3 mult when a debuffed card is scored
one issue is
debuffed cards aren't scored on context.individual
how would i go about fixing this
Try looking at It is forbidden to dog from Aikoyori's Shenanigans
right
great observation
i'm looking at the bunco source code and the one thing i can't figure out is wtf does percent mean in this context
percent what?
It's the pitch of the draw card sound I think.
It is, yeah.
hi can i ask whats the modifier i add to the joker to remove it from the shop pool?
THis has made htem not spawn at all. I want them in a booster pack 😭
That did the trick. No more frame drops! It also solved another issue (that I had a poor solution for).
is there a safe way to use draw_card? it's creating evil ghost cards
tried this
mult gain still triggers
level up still does not
ew (not at nick's code I SWEAR)
oh brother
do we ping moderators or smthn?
<@&1133519078540185692>
🔥
the evil has been defeated
Now i look so mean 😭
it was just a scam lol
ah
steam scammer again
Maybe patch in the return with func = function() SMODS.calculate_context({chudhit = true}) end?
ill check rq
G.playing_cards or G.deck.cards for cards currently located in the deck.
it crashed because of the end do I remove it
Did you add the ,?
I… did not
Take 2
ok no crash
now does it work
HECK YEAHHHHHH
Something youre goated tysm 🙏
how do i make this recursvely draw cards (when honey card B is spawned by A, B should call this code again to potentially draw honey card C)
is it something to do with calculate_context?
because i need to reevaluate context.hand_drawn
You could do chosen_card:calculate_enhancement({hand_drawn = true}) maybe?
how do I make a value round to the nearest whole after an increase
Ok just to be sure, getJokerID(card) can be used in order to detect the placement of my joker, and using something like G.jokers.cards[getJokerID(card)+1] can detect the card on the right then ?
I'm trying to do a joker that works like blue print with a few changes so i want to be sure if this what i could use in order to make my blueprint like joker work
like if I multiply by a decimal and the result isn’t a whole number, how can I make it automatically round to the nearest whole number?
local decimal = number - math.floor(number)
if decimal >= 0.5 then
number = math.ceil(number)
else
number = math.floor(number)
end
```?
Probably.
so will this work or no
I'll go give it a shot, i'm looking trough Yahimod's code in order to see how i can remake a blueprint like joker since i don't think i saw any vanilla remake one in smods or something
when the drawn card calculates its enhancement, the code fails at line 18 because it's trying to perform ipairs on context.hand_drawn, which equals true instead of the table of drawn cards
It should.
i need help, where i read smods documentation? i forgot is page
thanks
Hi aure’s cat
Why do you need to loop over it anyway?
when a card is drawn with draw_card i don't think it calls hand_drawn
Yes, but why are you iterating over context.hand_drawn?
because that's when the enhancement happens?
Why not just check if it's located in hand?
because i only make the check to draw another honey card when the honey card first gets drawn to hand
which happens in and only in hand_drawn afaik
chosen_card:calculate_enhancement({hand_drawn = {chosen_card}})?
that crashes the game with no handler screen
what is "misc"? just miscellaneous that you can add if you want?
nvm it spit this out
hmm
i also want to recalculate hand_drawn because i use that for joker effects
and i want those to trigger/increment when i draw a honey card
Maybe put it in an event?
you can just do math.floor(x+0.5)
still crashes the game
oh
what if I wanted it rounded to the nearest ten though (so I don’t get stuff like 19)
(math.floor((card.ability.extra.xmult*0.1)+0.5)*10)?
I’d probably divide by 10 first, do the floor, then multiply by 10
i'm not sure what context.hand_drawn is supposed to be, on the wiki it says true but then how can i use ipairs on it??
it's a list of the cards drawn from deck to hand during a blind
Is hand drawn even on the wiki?
I really need to finish updating that page 😭
so this correctly updates hand_drawn?
No
i dont know what calculate_enhancement is even
how do i do UI with pages and such
testing,,,
like the stuff in collections
i would recommend looking at how the collection does it
i have a recreation of the collection in my mod
is that also in ui_definitions 
it worksssss
i dont have the code rn but here's what i do for my custom collection https://github.com/nh6574/JoyousSpring/blob/5b7ff91500a4f947161fa10f7ff80b312af580d5/src/mod_info.lua#L378
i just want to recalcuate the honey card effect when it's drawn by another honey card, because context.hand_drawn doesn't reevaluate when draw_card is played
cant you make your own context
Is the idea that when you draw one honey card it will draw the rest?
if you draw a honey card, 1 in 2 chance to draw another and it's recursive
got everything but that last part working
what if i want pages of UI elements and not (at least, exclusively) card objects
Then you cry and think of something easier to do
start a wiki page
i mean i imagine you would just listen to the callback from create_option_cycle
is there a reason to not use tabs?
how might one get an enhancement to use a shader instead of a card back texture
SMODS.DrawStep
🙏
How do i. make some cards in a rarity appear in a booster pack while some can appear in the booster pack AND shop
my only guess as to how is maybe make separate rarities? I'd rather keep them all on the same rarity for thematic purposes but art and feasibility will always be at heads
I guess getJokerID(card) wasn't working or do'nt exist, it instantly crash when loading the card in the collection
see? not recalculating context.hand_drawn with the new drawn card causes issues like this, where honeycomb doesn't increment because it doesn't check to find the second honey card
How do I get sell value of the Joker/Consumable that was added (context.card_added)?
My Joker changes sell values of all Jokers and Consumables when context.card_added is true, but problem is that the sell value of the Joker that was added does not change
Then use SMODS.calculate_context({hand_drawn = {chosen_card})
Hook Card:set_cost?
Like .current_round.added_card.ability.extra_value?
No?
I just don't understand how hooking a set_cost would work, it's not a variable (like in Castle 2 example). (I don't fully understand how hooks in general work to be honest)
wait wdym 2 in 2
that's 1 in 1
which is 100%
oh ok
What's the problem exactly?
it's fine, after using calculate_context i'm reasonably happy with the behaviour
You would set self.sell_cost at the end?
So, I need to make a hook function that activates when a joker/consumable is added and change the sell cost in this function with the help of .self?
No, I'm talking about Card:set_cost
can i make an enhancement loc_txt's name diff color from usual? (aka using {C:red}{})
cuz this is happening to me
no
the key might be wrong
Wait, I think I'm on the right track
I need to hook "function Card:set_cost()". It activates when a card's sell value is being changed. Inside the hooked function, I need to change the card's ".sell_value" with the help of ".self"?
local oldsetcost = Card.set_cost
function Card:set_cost()
local g = oldsetcost(self)
if conditions then self.sell_cost = number end
return g
end
```?
Should work, thanks
you can have multiple atlassas in one file right?
You mean multiple images?
Yes.
alr thanks
Is there a way to create a pool of destroyed Jokers?
You mean a table of keys or a table of cards?
anyone familiar with immolate.dll? I'd like to edit the brainstorm mod to find instant chicot instead of instant perkeo, but looks like the latest version of the brainstorm mod that does this just passes some args into Immolate.dll and idk how exactly all that works and what I would have to change to make it look for chicot instead
Does it have a chance to prevent a joker from being destroyed or does it just bring back a dead joker some times.
brings back a dead joker
Do you want the values to save?
yes
thanks
You would probably hook Card:remove and check if its a joker and it was added to deck then add it to a table with the format of {self.config.center.key, self.ability}
Okay so can I make it so the create card function uses keys from a list?
I currently have a function running to pick the key. It put it in the create card function and had it return the key?
You can generate the cards yourself for your booster though
That's basically what I'm trying to do 😭
This list is all the cards that can be generated.
Pick an item from the list
Put that in the key =
if i get what you're saying then yeah
you can also make an objecttype for this
True. I do actually have one made I think I've been at this so long I lost the plot LMAO
Or I forgot why that didn't work??
this should work just fine
Oh my god 😭 < dissociation moment
We solved that part but the thing I needed help on was the select_card BCS now it crashes when I select one 💀
But I can't. Select the card with the custom button
whats the crash
what type of cards are they?
Let me go see
I got up to eat and that's why the fuckin. Dissociation moment happened 😭
jokers. I used N' s code to put a custom use button on one. it no longer has a select button on the pack opening screen but the others do
if I dont have select_card in there i can select the others fine just not that one
i can also. see the sell button on it so I think its something to do with the code i used from N. likely missed something 😭
add an area check to where you alter the buttons
honestly that was one of the first things i did in my mod so i dont remember any of it
thats what i thought. just like self.cardarea == G.jokers ?
mood
i cant remember my code 5 seconds after making it 😭
all my button code has area checks
in fact i have a type of card that changes buttons in a booster (i dont know if thats what youre referring to)
OH. yeah i see it now
when i was originally looking at it I hadn't played joyousspring at all so I did NOT know what extra_deck etc. meant 😭
so I just disregarded it
play joyousspring!!
but yeah thats kinda the hard part of using my code for examples haha
can someone tell me why this does not work. "attempt to call a nil value"
at what line
It might be something wrong with loading the file. Sometimes I get weird things like that if my file has an error in it (like not closing SMODS.joker{
I only changed something about the highlting cards and now I'm only getting the same card in every pack
(two of the same card, not the same card every pack*)
weird
Oh wait nvm I'm dumb and quite unlucky LOL
^ it just rolled onto the same card multiple times I just need to add the can't have multiple logic to my randomness if
Ig
And you can now select the card YAY
how do i check the current deck
ohh
this is good for debugging
it basically is checking to see if it returns true
its asserting that it will always return true
and if the assertation fails then it will panic and crash
DHY = {}
DHY.FUNC = {}
DHY.G = {}
DHY.G.MODPATH = SMODS.current_mod.path
local NFS = require("nativefs")
function DHY.FUNC.RequireFolder(path)
local files = NFS.getDirectoryItemsInfo(DHY.G.MODPATH .. "/" .. path)
for i = 1, #files do
local file_name = files[i].name
if file_name:sub(-4) == ".lua" then
assert(SMODS.load_file(path .. file_name))()
print("Loaded " .. path .. file_name)
end
end
end
function DHY.FUNC.RequireFolderRecursive(path)
local function scan(currentPath)
local fullPath = DHY.G.MODPATH .. "/" .. currentPath
local files = NFS.getDirectoryItemsInfo(fullPath)
for _, fileInfo in ipairs(files) do
local fileName = fileInfo.name
local fileType = fileInfo.type
local childPath = currentPath == "" and fileName or currentPath .. "/" .. fileName
if fileType == "directory" then
-- Recursively scan subdirectories
scan(childPath)
elseif fileType == "file" and fileName:sub(-4) == ".lua" then
-- Load the Lua file with proper relative path
assert(SMODS.load_file(childPath))()
print("Loaded " .. childPath)
end
end
end
<@&1133519078540185692>
this creates 2 functions
one that loads a folder
and one that loads a folder and also any folders within that folder
ohhh
i use this in my mod
so now, make a folder in your mod's root called 'items'
then after those functions, add this line
DHY.FUNC.RequireFolderRecursive("items")
then put jokers.lua in items
alr
Try removing the ./
im setting my guy up with the good stuff
because imo all mods that get large enough need to load stuff like this because it makes it 20x easier to bugfix when you know exactly what broke
just loose under all the ends?
i just dont make code that crashes
hm?
yeah
even better
so anything i put in items will load?
show me your lovely logs. now
any .lua files, yes
Honestly all of this feels unnecessary, but you do you
i delete them sorry
you are fraudulent
ugh how do i check to see what deck is being used
G.GAME.selected_back
why am i getting the same crash wth
chat how i make it so the logo is not over there
and this is gonna be a key
something is wrong with your file i think
i don't think so
oh cus i didnt save
make sure your file is saved
im too smart
yippie
i have realised the error of my ways i didnt understand how the sprite call worked
add an extra end
where?
before you call the function
move the call to line 40 and put the end in line 39
the function
it starts up
the mods dont work
in items i put jokers.lua and decks.lua @midnight coyote
hm
Did this not work
i can try it but this way is nicer (if it works)
how do you check if a specific mod is enabled?
otherwise ill try removing the ./
SMODS.find_mod
cheers ^^
You'd do if next(SMODS.find_mod('paperback')) then for example
tyty :D
how would i forcefully start a shop
i need to start one at the beginning of the game
for a back
maybe check cryptid's code card
nope
What is your mod file structure
it specifically crashes by the second line
the first one is fine
My Mod file and in there the lua files
now it's not in items
yea
What's your jokers.lua file
wdym whats it
Since the decks.lua one works fine then the problem is with thst file
What's in it
ohh
it started doing this after i added this
wait let me delete this and see if it works
You're missing commas in each line of the loc_txt description
ah.
You should wrap each of these in assert()
im trying to get this joker to subtract the score of the first hand of round from the required score, but the best ive been able to do is this, which has the issue of also triggering when you discard and draw new cards after the first hand. ive tried a lot of ways to try and limit it to only happening once per blind but ive gotten nowhere 
if G.GAME.current_round.hands_played == 1 and G.STATES.SELECTING_HAND and context.hand_drawn then
G.GAME.blind.chips = G.GAME.blind.chips - G.GAME.chips
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
return {
message = {'Calculated!'},
}
end
end```
Hi I want to make my mod joker as a default starter joker.
So once player starts the game, the joker is on the slot in use already.
Is there a way for this? Can anyone point me to the documention or the function? Thanks!!
Try if context.after and G.GAME.current_round.hands_played == 0
Not sure if it'll work
i tried context.after, that doesnt work
What happens?
the reason the if statement is like that is because that seems like the best way for me to get the right timing since it needs the round score to finish calculating before it can do what it needs to to the blind requirement
Makes sense I guess
hence the very ugly if statement
And hand_drawn triggers on each discards?
yeah
cuz its whenever cards are, well, drawn to hand
that includes discards
ive tried to set up some counter that increments by 1 every time the if statment is true and if its exactly 1 the rest of the calculations happen, but it never actually incremented
That's probably the way tho
Set a flag on your joker if it has triggered
And only do the subtractions when it hasn't (in your current context)
And reset the flag at the end of round
Is this for debugging or just a feature of your mod
It is a feature for the mod
And you want it to happen on every single run? Or is it tied to a deck for example
I want it to happen on every single run. If it is not possible, binding to a deck also works
It's possible, it'd require hooking the blind apply to run function
But idk if you're familiar with hooking or looking at the game's source
The deck apply I mean
You've heard "All women are queens". Now get ready for:
hmm i want to make a joker that gains chips when wheel of fortune fails but i don't know anything about hooking, what's the easiest way to implement this joker
I don't think you can do that with hooking, it'd have to be a lovely patch
what if you just take ownership of wheel and check for your joker
That's not a good idea, taking ownership would mean redoing the entire wheel code
is there any good documentation on ownership? idk where i'd even start with that
Even if you copy pasted it you'd break other lovely patches made by other mods
problem is that i cant seem to find a way to reliably set the flag
Can I see what you've tried
I am okay with reading source code but I am just starting learning game modding.
So I am not familiar with the Balatro source code. Is hooking part of the smods API or I need to work with the source code directly?
Hooking is a part of lua itself
You just add some of your own code to an existing function
not at my computer rn so i cant get it directly, but basically directly after the “then” i did
“local triggered_count = 0
triggered_count = triggered_count + 1”
and then i checked if triggered_count was equal to 1
yeah that won't work cus local variables only exist within that scope
You'd need to add a flag to your joker's config
And modify that
hooking is a programming concept
Thanks I am also new to lua. I just look it up it seems like callbacks or event handlers in cpp
ok i found the wheel code i think, how would i patch it so this joker gains chips when it fails? can i create a new context?
does anyone have a tutorial on lovely patches
Yes you can create a new context
I think there's a wiki page in the smods wiki about lovely patches
But i don't remember
Is there any easy way to display an attention_text at an arbitrary pixel position (ie, love.graphics.getDimensions()/2)
There's maybe a tutorial in the lovely GitHub
there's information but its confusing and definitely isnt a "tutorial"
in the sense that if i already knew how it worked and forgot, for example, a variable name i could go back and understand it but the barrier to entry is high
what's the basic syntax for making a new context? can i just define context.fortune_fail and set it to true or is it deeper than that
SMODS.calculate_context {your_context_name = true}
Any additional information you want in your context you include in that table
speaking of, can you trigger it with something like business card?
you can add a context anywhere you want yeah
its just finding the right place for it and patching it in
ok cool in that case here's my real issue
it's not patching
like here's the patch
but when i load the game up nothing happens to card.lua
Did you copy that from the lovely dump
what's your priority?
Looks like talisman is patching that too
0
Keep in mind the pattern is character sensitive, so even a missing space could break it.
I'd try taking ownership instead
what's your mod name?
Taking ownership would break lovely patches on that card by other mods wouldn't it
define "work"
The code do be patched
thats literally pasted in though
Like the other patches
This then
you’ll never guess
(Hyperfixation)
But also if two mods want to modify the same Joker they might want to do so in a way that's not compatible
then your patch will never hit
H is before T indeed
change your priority to 1
ok
Also your patch depends on talisman being enabled
oh my god it’s alphabet sensitive too
so it's a bit of a moot point
So if you don't want your mod to be dependant on talisman you'll have to change the pattern
TRUE I’ve gotta go back
is there a reason you need it in the return table?
I remember somehow missing a space in the middle of a patch I made. I'm not sure if it got formatted out or what exactly happened
is it as simple as going config = {flag = false} and then checking if flag is false or is there something im missing
if i wanted to patch the round ending to disable mr bones (and similar) under specific circumstances how would i do that?
like, why can't you just target the pseudorandom line?
no reason actually
the last one I patched (space) needed the func version to actually do anything so I was just trying to avoid anything else
but I guess in this case i don’t need it
if you did config like thar you'd check card.ability.flag
@wintry solar @willow plinth also I'll try to open that issue we had discussed tomorrow
im so sorry
In fairness I only noticed it hadn't patched by coincidence while debugging something else
Ohhh
that one space..
it seems that all it does is change the offset of those pop-ups, and it's for a mechanic I haven't implemented much
is that bad?
Usually for Jokers you'll do Card.ability.extra.…
not necessarily, most people do config = {extra = {flag = false }}
I hate typing code in phone
which when using the constructor SMODS.Joker
is done by assigning config = { extra = {…}}
i see
Reposting: anyone familiar with immolate.dll? I'd like to edit the brainstorm mod to find instant chicot instead of instant perkeo, but looks like the latest version of the brainstorm mod that does this just passes some args into Immolate.dll and idk how exactly all that works and what I would have to change to make it look for chicot instead
Hey guys, how’s it going? I just need some help creating a Joker mod.
Can someone help me?
ok so i now have config = {extra = {triggered = false}}, how can i interact with this
I am 90% sure they built their own version of immolate with a custom filter which uses those args. If you want to achieve the same result, you have to write a filter for immolate.
how can i make so a consumeable isnt destructed after being used?
how would one go about changing the colors of the main menu background swirl?
i wanna store a joker on it to then whenever you sell it it respawns
dont ask if someone can help just ask the question
Trance
IIRC
make the consumable create itself?
fr go straight to the point
with no creation animation it might work
how would i format this, because while something's setup works with whole numbers, i'm now stuck with 19.99K instead of a smooth 20K
or i could just figure out why it triggers the gain twice
SMODS.create_card({area = G.consumables, skip_materialize = true, key = "c_modprefix_consumablekey"})
okk
ty
might want to check for negative so it can recreate itself as negative then
no need for the parentheses
math.floor((x/10)+0.5)*10
yeah good idea
if you can check for negative do this to recreate it as negative: SMODS.create_card({area = G.consumables, skip_materialize = true, key = "c_modprefix_consumablekey", edition = e_negative})
got it
will this get it to the 20k or will it just do the same thing
how can i use the flag?
like is there a difference between multiplying by .1 and dividing by 10 here (times .1 is what I had before)
the same way you'd use other variables saved in the Joker
i meant moreso in the way that like cryptid does it, where just having the mod causes the background colors to change to the blues n such
card.ability.extra.triggered
I change it during Boss Blinds so I imagine you could have it work similarly elsewhere
it depends what number you're putting in, but it should do yheah
well the base xmult is 2, and as a work around for it double-gaining, I have the xmult gain set to math.sqrt(10)
So 2 will actually go to 20
But as it keeps going instead of keeping that 2
crashed D:
joker code for reference:
key = 'calculator',
loc_txt = {
name = 'Calculator',
text = {
"Reduces required score by score of first hand of round"
},
},
config = {extra = {triggered = false}},
rarity = 2,
atlas = 'CosmicTomfoolery',
pos = {x=3,y=0},
blueprint_compat = true,
loc_vars = function(self, info_queue, card)
return {
vars = {}
}
end,
calculate = function (self, card, context)
if G.GAME.current_round.hands_played == 1 and G.STATES.SELECTING_HAND and context.hand_drawn and not card.ability.extra.triggered then --currently bugged to trigger whenever you discard after the first hand played
G.GAME.blind.chips = G.GAME.blind.chips - G.GAME.chips
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
return {
message = {'Calculated!'},
}
end
end
}````
what's your code that double gains?
I'm trying to make a Joker mod. I know the basics, but the rest wasn't working, so I deleted the code and now I want to start over.
Get a new copy of your joker
oh ok
what do you mean?
that's probably what's screwing up your numbers
thanks!
but not the same as the double gain right
thats a different thing
Start a new run or sell your joker and spawn a new one
that fixed that
yeah, the double gain must be from where you're calling the context
ok so now i just need to set triggered to true afterwards and then when the blind is defeated it gets set to false?
like where im putting the calculate context?
yeah
i seee,,

ty
IT WORKS
thanks a bunch for the help 
so it's essentially x2 mult on your first hand
basically, but there's jokers that care about the round score so it sort of synergizes with those
oh thats cool
or i guess as it stands right now antisynergy since most of them want you to go under some percentage of blind requirement
also it does make it easier to hit stuff like mr bones
(i think)
it should
also its very satisfying seeing the blind requirement go down
makes me feel powerful 
if you score naneinf what happens to the blind score
good question
oh i think the game would crash right
cuz youre doing arithmetic with a nil
it can handle naneinf score and nan blind score
its floating point i think itd just make the score naneinf
which might make the blind impossible now that i think about it
lol
how would i make this only trigger once at the end of the round no matter how many towers you have? (assuming you have at least 2)
calc_dollar_bonus = function(self, card)
local towers = SMODS.find_card("j_para_tower", false)
if #towers >= 2 then -- I need to check if this is the first tower (or last, it just needs to only trigger once)
return card.ability.extra.money
else
return nil
end
end
as in, it only gives the bonus money one time?
yup
you'd have to put a flag on your card to mark when it has triggered
and then give money only if it hasn't
flags dont save across jokers i think?
you put it in the config of the joker
hold on
holding on
what i mean is:
- you have some amount of towers
- you earn $20 if you have at least two towers and it doesn't stack
- otherwise you get nothing
I'd still go the flag route, just that you'd have to check that if any other tower has the flag then don't give money
how would i do that?
oh another thing that sets this joker apart from being just a x2 on first hand is that if you end up getting more than the new blind score the round doesnt end
i tried just calling end_round() but that was a whole buggy mess lmao
based on your current code, you'd only give the money if after looping through towers none of them have tower.ability.extra.triggered as true, and right before returning you set card.ability.extra.triggered = true is what I was thinking of
and then probably in context.starting_shop set the triggered flag to false
Tbh I'd do this with a lovely patch cus it's much more elegant
but I know you're not too familiar with them
how do I write something that applies an edition to a random joker you own
have you heard of wheel of fortune
how do I do that cause idk where to start with that
is there any way to have my joker cost money but always sell for 0$?
set sell value on purchase
what is the check on purchase function called?
in calculate context.buying_card and context.card == c1
thank you :)
context.buying_self exists now iirc
also add_to_deck would be better probably but i would still cause problems when set_cost is called on it
i feel like there should be a better way to dynamically change the sell cost of a card without changing the cost with extra_value or anything like that but idk what it should be
Anyone have any ideas as to how I would apply shaders to a standalone sprite object? I would like to make this Maximus logo bounce like The Soul does
so apparently the double trigger of my mult gain is because of how i'm calling my calculate context? is there something i should look out for to see if i need to remedy it?
send us the code
you mean like with draw? cause im p sure vanillaremade has that
when is context.chudhit true?
when a probability succesfully triggers (i have to do this manually)
show us an example
example 1: ownership of wof
example 2: patch on business card
Nvm! I got it!!
60 fps,,,
try and not context.repetition?
idk
why would context.repetition even get called 😭
idk but i dont know what other issue there would be
hope it works then
ok so i did some more analysis
the FIRST instance the xmult triggers, there's no double trigger
A -> B
but the SECOND time and onward?
B -> C -> D
so there's something about triggering the mult gain a second time that's causing it to register it as two triggers?
use print ig?
find out if the double trigger happens the first time and something prevents the mult gain from happening
right
how would i set that up?
you have debugplus right?
yup
whenever context.chudhit is true run print("triggered") and triggered should appear in the console when your joker triggers
how would you go about checking the enhancement of a card thats been played? for more context, im trying to make a joker that makes bonus and mult cards retrigger
so do i just put if context.chudhit then sendDebugMessage("triggered") in the main file
SMODS.has_enhancement(card, "m_bonus") for example
gotcha, thank you
sendDebugMessage doesn't go into the console afaik
and ideally you'd put it right before the mult gain
what's the one that appears ingame
is it just print
k
i just wanna say rq that a solution ive used is hooking the pseudorandom function
because from inside the hook you can pull the G.GAME.probabilities.normal and the odds and calculate there if it will succeed and call the context
basically all chance abilities use the same variables (apart from lucky cards)
its worked for me so far
why isn't this applying negative to anything noedition = SMODS.Edition:get_edition_cards(G.jokers, true) eligible = pseudorandom_element(noedition, pseudoseed("Bordbcv")) eligible:set_edition(negative, true)
another,,, hook,,, where can i find it
uh oh
was that the first time
yeah
this is even more confusing
i think you have to make the edition a string
maybe "e_negative"
double confirmed cause i used the sqrt of 10 instead of just 10
2->20 after a high card
but it triggers twice later as well?
no no i just messed up earlier
oh
i can give you what i use in my code however it might not be the best solution
its worked for me so far but it hasnt been extensively tested
local _pseudorandom = pseudorandom
function pseudorandom(seed)
local result = _pseudorandom(seed)
local odds = nil
local extra_odds = nil
local self_ref = nil
for i = 1, 10 do
local name, value = debug.getlocal(2, i)
if name == "self" then
self_ref = value
break
end
end
if self_ref and self_ref.ability and self_ref.ability.extra then
local success = pcall(function()
extra_odds = self_ref.ability.extra.odds
end)
if not success then
local success = pcall(function ()
extra_odds = self_ref.ability.extra.odds_1
end)
end
if not success then
local success = pcall(function ()
extra_odds = self_ref.ability.extra
end)
end
odds = G.GAME.probabilities.normal / extra_odds
if result >= odds then
print("Ability failed for seed:", seed, "result:", result, "threshold:", odds)
SMODS.calculate_context{probability_failed = true}
end
end
return result
end```
the odds_1 is cos thats what i used for the second lucky card ability in my patch for it
the pcall thing is to prevent crashes
debug.getlocal pulls the locals of the function calling it
key = 'trees_that_move',
blueprint_compat = true,
loc_txt = {
name = 'Trees That Move',
text = {
"Retrigger each played",
"{C:attention}Bonus Card{} or",
"{C:attention}Mult Card{}"
}
},
config = {extra = { repetitions = 1 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.repetitions } }
end,
rarity = 1,
atlas = 'votdjokers',
pos = {x = 7, y = 1},
cost = 4,
calculate = function(self, card, context)
if context.repetition and context.cardarea == G.play and SMODS.has_enhancement(card, "m_bonus") then
return {
repetitions = card.ability.extra.repetitions
}
end
end
}```
can someone point to why this joker's function isnt working? i havent implemented the mult retriggering yet but focus on the `calculate = function` section
and SMODS.has_enhancement(context.other_card, "m_bonus")
In my example card was the card you wanted to check. In this case card is the joker, not the played card
ahh icic
was this a bad idea to add
yes
do i have to define what is the other card somehow? im not very good at coding sorry for my ineptitude .w.
no context has that
,,, i somehow managed to forget to add context. 🤦♀️ im so great at this
is there a way to allow a joker to spawn duplicates of itself in the shop without showman? (only itself not other jokers)
something fishing minigame loosely based on mdrg
how do I make a joker card not select itself when choosing a random joker
How could I make this change for each run? Trying to start with one random card for a challenge deck.
local SMODS_calculate_context_ref = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
split_suit = pseudorandom_element({"S", "H", "C", "D"}, pseudoseed("split"))
local _rank = math.random(2, 14)
if _rank < 10 then
split_rank = _rank
elseif _rank == 10 then
split_rank = 'T'
elseif _rank == 11 then
split_rank = 'J'
elseif _rank == 12 then
split_rank = 'Q'
elseif _rank == 13 then
split_rank = 'K'
elseif _rank == 14 then
split_rank = 'A'
end
return SMODS_calculate_context_ref(context, return_table)
end
so what do i do to use it
how do I synchronize applying an edition and a text popping up
I somewhat know what im doing, but beyond this I don't understand how to hook what Somethingcom said
maybe I want a card instead of keys
No.
ah
Do you want it to also create sold cards?
no, not sold
I meant something like this: ```lua
local remove_ref = Card.remove
function Card:remove()
if self.added_to_deck and self.ability.set == 'Joker' and not G.CONTROLLER.locks.selling_card then
if G.GAME then
G.GAME.destroyed_jokers = G.GAME.destroyed_jokers or {}
table.insert(G.GAME.destroyed_jokers, {key = self.config.center.key, ability = self.ability}
end
end
return remove_ref(self)
end
This does not go in loc_vars also it is case sensitive.
if i wanted to check for a specific rank in the played hand during context.joker_main i'd have to run a loop to check through the played hand, right? if so, what's the right code to use inside the loop?
Ignore that everything is a heart for the new suit and all that
I'm actually trying to REMOVE the 2-Ace from this suit
Remove ;
Yeah no, this goes outside of the SMODS.Joker use
So put it before SMODS.Joker is even used or after you close the } corresponding to it
Also you accidentally removed the C from Card.remove in the declaration of remove_ref
like this?
Remove the , on card.remove also the c in card needs to be uppercase.
ah
It seems fine.
what should I do for the joker then?
You would make it get a random joker from that list and create it then remove it then set its ability when you want it to do that.
I want to start getting into modding balatro, would someone be able to point me to a video to get the basics of where to start please
making mods or downloading?
Making mods: https://github.com/Steamodded/smods/wiki/
making
there is one
Also read the lsp_def folder in Steamodded once you've downloaded it, it helps lots with function definitions
someone here made one recently, one sec
@manic rune made it but i can't find it :(
It's at the bottom of https://discord.com/channels/1116389027176787968/1349064230825103441
bump
but yeah i'd also recommend reading too, this way you can reference stuff from the wiki
What is the goal?
like this?
Start with a single random card.
No, because table isn't a valid operator.
what should I set it to then, set?
No, you would use pseudorandom_element
I doubt this is correct but:
bump
You are correct about it being incorrect, it would be something like: ```lua
local random_joker = pseudorandom_element(G.GAME.destroyed_jokers, pseudoseed("seed"))
SMODS.add_card({key = random_joker.key})
What can I use to determine if I am in a run or not? I have parts I need to not run if I'm not in a game.
if G.STAGE == G.STAGES.RUN?
?
like in the collection?
In the collection would be fine, mostly just caring if a run is actively ongoing
to do list uses card.area and card.area.config.type == 'title'
this
that will tell you if you're in a run
might be G.STATE tho
not stage
I can't remember
state changes all the time so probably not that
Thanks
bup
bump
You would also probably put the card in a variable and add: ```lua
for k, v in pairs(random_joker.ability) do
card.ability[k] = v
end
Also you would need to remove it from the table.
No, that goes where you create the card.
...why is it in loc vars and not calculate?
it is now
Code?
You need to do local card = SMODS.add_card({key = random_joker.key})
as a new line or updated line?
Updated line.
oki
Question: If i have a custom rank, how do i disable it from changing suits?
Hook Card:set_base?
calculate in lowercase
Idk how to hook. heh
that's because you've put calculate inside loc_vars
In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...
oki, got it now
Would it be possible to check from context.post_trigger if it has triggered on a specfic scored card?
How would I set a card's suit?
SMODS.change_base(card, suit key)
Also nice name 
lol
I could say the same to you
(I'm new to modding) what do you mean by suit key?
how would I set it to heart for example
SMODS.change_base(card, 'Hearts')
that code will change your joker's suit to hearts
which doesn't make much sense
SMODS.change_base(context.other_card, 'Hearts')
Does anybody happen to know how to make a Sprite object clickable?
oh lol
bup
is there a way to modify another joker's loc_vars without using the absolute mess that is cryptid's misprintize function
you can take ownership of a joker and modify the loc_vars function as you need
I'm assuming she means on the fly
yeah
I don't think misprintize does anything with loc_vars
I must be doing something wrong lol
that's not actually modifying the loc_vars of a joker afaik
just modifying its ability values
that's what i mean lol
im trying to see how misprintize does it but i cant make anything of it
its completely over my head
I assume they just recursively loop through card.ability and find numeric values to modify
im trying to simplify it to make a easier and more flexible value manipulation function (that actually works with operators other than multiplication)
yea it crashed lol
what's the crash
No, because then it would increase xmult and xchips
Isn't that what they do though? Randomize all values
xmult and xchips are present on every card.
bump
That wouldn't do anything with most of the vanilla jokers.
heyo modding dev chat
currently debugging the showdown mod, yada yada yada it has a mechanic that, if i understand the code correctly, should update the sprite of the vanilla Joker joker to a random position on the showdown_joker_variants atlas every time G.GAME.showdown_JVA updates
i changed the code quite a bit, especially reduced the update interval so i can debug better, but don't understand why it's still seemingly only updating the sprite pos once, and then just stays at that pos for ever
first image is the current code, second image is the atlas in question
for some reason it just gets stuck on the green variant (x=1,y=0), even though the log below print("SETTING SPRITE POS") shows a different pos every time
currently, implementing value manipulation is really complex and also broken, for example additive value manipulation with misprintize only works on vanilla jokers, but is calculated as multiplication on modded jokers
Then I guess you'd have to account for the "effect" value thunk uses too
I can see how it'd get complicated
and also the calculate functions tend to look really messy and complex (oil lamp for example) is there a reason you shouldnt be able to just target a i + 1 and return a value?
but then again i dont know much
that would be greatly appreciated, i put the stuff above in my main.lua and got this error so far
but this really seems like it should be way easier
uhm can you show your entire joker definition
seems like disabling the SoulEverything mod fixed it being stuck on the green variant, but now it's still just stuck on the first variant (x=0,y=0)
i see you're not using SMODS.Joker anywhere here, you must be doing something weird with it later on
?
you must be using a really old mod as a base to make your own
oh?
i think thats just localization
is it not
if there's a newer template do let me know 🙏
does anyone know how to change textures on mac?
idk what you're referring to
cryptid does something similar
yes that's fine by itself, but look at the 2nd screenshot they sent
and no, that's not localization only
Vanilla Remade can be a good reference too, but that's for later
is there a way to make your mod intentionally fail to load
my mod requires a consumable stacking mod but works with either incantation or overflow so id like it to fail if either aren't installed, but afaik you cant have either/or for mod dependancies
https://github.com/Steamodded/smods/wiki/Mod-Metadata and there is an or for mod dependencies
it's there in the wiki
does that work with setting a dependancy that is "either x mod OR y mod, but both arent required" or
ok thank you
bump
blah blah
You can set one mod to act as a standin for another, but forgot what field that was for the JSON file
You want a challenge that just starts with one random card?
Something I do wish we had tho were non-required mod recommendations
Why are you hooking SMODS.calculate_context then?
Could make a pop-up on mod load that checks for the recommended mods
This is something some Beat Saber maps do and I think it'd be great here too
Or something in the tabs for the mod
I can't figure how to do this stuff inside the challenge code, so I figured it'd be easier to do it this way.
bump
bump
Line?
"Go Fish" taken literally
peak
What happens when you have click = true in the config for it?
I don't know because it's just a sprite 😭
hrrrrmm
Dumb idea would be to make a button with the Sprite texture
Coarse Joker
- Gains +3 Mult at the end of the round IF your Pixel Art Smoothing is Off
Since we know that accepts clicks and hovers
can you even get the games settings?
You definitely can
But better idea would be understanding why clicks and things don't work with sprites or other objects
I got this?
it doesn't seem to do anything tho
Why is it in loc_vars?
i-
that's my bad
this sets all cards in hand to hearts lmao
good to know it kinda works tho
You need a context check.
Yes.
how do I get the animation lol
You mean have it flip?
