#💻・modding-dev
1 messages · Page 682 of 1
I'll change the key
here
-# sorry i forgor
-# hotpot being my mod
-# also anegative is the name of the edition
where is your shader located because the path looks wrong
also i wouldnt recommend to name your mod hotpot haha
hotpot is throwing me off omg
like that, sorry Im not sure where I supposed to do things
oh wait fuck hot potato exists
rebrand time
yes, but key not args. return { key = 'j_raw_ritten', ...
change args to key and yeah
why are you doing this like this
imma trynna call the vanilla foil shader
just add your joker and remove j_joker from the pool at this point
probably collection shenanigans if i had to guess 🤷♀️
well, the code you posted is not from anegative, its from test
the one thats crashing is anegative
what is wrong in my code
i feel like there are better ways to solve that
this is not what take_ownership is for
they're asking why you're taking ownership of the base joker instead of just adding a custom joker and removing the base joker from the pool
oh oops, forgot to rename "test" to "anegative", these are both the same, what i'm struggling with is that it's crashing about anegative.fs, a file that doesn't exist, i'm just calling the vanilla foil shader
I didnt know I could do that
use the take_ownership to return false in in_pool and add no_collection = true
so theirs no way that the normals joker coul spawn
the only problem is that vanilla is hardcoded to give j_joker as a fallback so you need to change that too
nvm my issue is solved.
if you just want to prevent vanilla jokers you can hook SMODS.add_to_pool
Ill do that
so I need to patch it
something like this #💻・modding-dev message
this will prevent vanilla joker from spawning, nice
Hey, could someone please help me? I've been trying to get debugplus to work for help with mod testing, but for some reason the mod doesn't work, even though it is in the mod file, and the other mods in there work fine. Does anyone know what could cause this?
by "doesn't work" do you mean it crashes, or do you mean it doesn't do anything in game?
It doesn't do anything, it doesn't appear in the mod menu either.
what happens when you press TAB in game?
nothing
hold TAB
still nothing happens.
is Brainstorm also installed
Do you need it to use debugplus? if so then that's the reason it doesn't work then.
Brainstorm has its own debug toggle that may mess up with DebugPlus'
oh
does the console work
could we get your modpack?
heres my mod file, "Sargeant test" is my mod file that im trying to test if you are wondering.
ah yeah maybe debug mode is on
but no because they said it didn't appear in mod menu
that is correct.
lovely 0.9 should be able to handle nested folders iirc
why is debugplus not working 😭
wait
check debugplus folder, is it nested
what do you exactly mean with nested? im new with modding so i dont know all the terms and such.
like is there another folder inside of debugplus
that is also called debugplus
(or like debugplus-main)
Yes there is.
that's your issue
put the folder that was inside debugplus into your main mod folder
then it should work
Move the debugplus folder from the debugplus folder into the mod folder, okay
do i delete the other one then?
doesn't matter really but yeah
okay, i will see if it works right now.
Okay, it seems that doing that did not work unfortunately.
alr, just in case, check inside the new debugplus folder, maybe it's nested too X3
-# i don't really know what to try now..
this is the inside of the debugplus folder.
ok, I believe it's installed incorrectly
What do i do to fix it?
reinstall
this is how mine looks
looks shorter because I use git
well they are they same (beside the git) so i dont know why it doesn't work then.
The only other problem i could think off is a conflict problem with your test mod, unless something happened when you were installing smods
how does the lovely folder there look like
like this.
hmm idk my only guess is that the folder is still nested
-# btw i recommend you enable file extensions if you're gonna be coding
Done that
Okay, so how would i fix it?
Check if it’s nested first
If DebugPlus has a folder inside it or is inside another folder also called DebugPlus, then bring it out into Balatro>Mods
okay so then this should work
but it doesn't because i tried that
Well shit man, idk
Iike i said earlier
well, that file is just empty
Which file
the mod file i was working on
this is how smods look
Just to be sure, what's in your mod's json file?
Nothing, like i am not joking there is nothing in there.
yet it works.
how do these kind of things keep happening to me-
hey, quick question, how does the negative edition add a joker slot? can't find anything that does that in it's code
SMODS.Edition {
key = 'negative',
shader = 'negative',
prefix_config = {
-- This allows using the vanilla shader
-- Not needed when using your own
shader = false
},
config = { card_limit = 1 },
in_shop = true,
weight = 3,
extra_cost = 5,
sound = { sound = "negative", per = 1.5, vol = 0.4 },
loc_vars = function(self, info_queue, card)
return { vars = { card.edition.card_limit } }
end,
get_weight = function(self)
return self.weight
end,
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' and (card.config.center.discovered or card.bypass_discovery_center) then
card.children.center:draw_shader('negative', nil, card.ARGS.send_to_shader)
if card.children.front and card.ability.effect ~= 'Stone Card' then
card.children.front:draw_shader('negative', nil, card.ARGS.send_to_shader)
end
card.children.center:draw_shader('negative_shine', nil, card.ARGS.send_to_shader)
end
end
}```
Is your mod still the only one showing up in game?
Yeah, and i have no idea how it's working right now.
I can confirm, there is nothing outside the standard(i’ve been helping him privately for the last 3 hours)
Have you tried closing and reopening the game?
already did that multiple times.
config = { card_limit = 1 },
okay so restarting my PC did nothing
also quick question, is it normal for your mod to work with an empty file?
ty
Which file is empty, the Lua one? If so, yeah.
Ok then.
currently im going try and redownload debugplus and see if anything changes
Also did nothing.
What happens if you try to download some other mod?
uh let me see
the dependency is wrong but that would show up in game
well, the mod i downloaded also doesn't work
im starting to think it might be the mod file itself
I did fix that for him earlier, i forgot to say, sorry
-# but for the record how it is in the screenshot is exactly how it’s written in the wiki
in the wiki it says that it won't support betas
Oh yeah, missed that part
Okay this is getting ridiculous, i have removed the file from my mod folder and the mod still shows up in my mod folder.
like how
did you restart the game
I did
can you post this folder and inside the debugplus-1.5.2 folder with the address bar in it
you can obscure the user name if you need to
What was it then?
im testing smth rn
wrong mod folder probably
it might be stupider
I GOT IT!
okay let me explain what happened. So when i was setting things up, i made a sort of link to the mod file so i didn't have to look through all the files to find the mod. The thing is however that the link for some reason didn't update the actual files, meaning the mods i added/removed weren't in the real mod folder to begin with.
i feel stupid for not noticing that
🤦♀️
I wondered if it was somehow a "wrong mods folder" situation since nothing was changing, but had no clue what would possibly resulting in there being any other mod folder than just the one. That answers the 'how'.
welp, lesson learned. do not make links to mod folder because stuff like this would happen-
how would i make a joker's calculate retrigger all other retrigger effects an additional time?
or is calculate not the right place to do that?
either the post_trigger or retrigger_joker optional contexts can likely be used for that
can anyone helpp me make my 1st ever mod
this is a good place to start #1349064230825103441 message
does it work from balatro mod manager
it's unrelated
but i would recommend avoiding balatro mod manager, it tends to cause issues
I dont know how to use other mod thing
gee, step 1 of the link i posted would probably help you learn to install mods without balatro mod manager
you'll need to interact with those files anyway to be able to make a mod
k ty
I do this on main.lua right (im kinda new so idk)
is this a video
use these instead
https://discord.com/channels/1116389027176787968/1486847115127947374
ok thank you for helping me out
i think this is more advanced and hard I just want to like
do it from the easy way
I mean whats this?
this is the easiest way 😭
the other tutorials are not easier they are outdated
that's old af
have you tried joker forge?
are links allowed here?
yes
yea
yeah
alr tysm
I made this and now trying to find the function thing
It should be like this right?
ask in jokerforge disc
your smods is very old, you need to update it
so I download newest ver right
yea
what's inside smods
dont tell me there is another smods there
if there is, that's wrong
yeah there is
you'd want to move that out
I moved that out to the mods folder
now most likely it's gonna crash and you're gonna have to update lovely
awesomesauce
trying to get this modded joker to work,
(burnt, stunned, and actionable are custom enhancements, and their names are their respective keys)
what exactly is the problem? is it just not showing up?
it shows up in game, it just doesnt work the way id want it to
heres its rules
alright well for starters, i could be wrong
but i dont think it's a good idea to have an entire function inside a return
jokerforges fault ig, i only gave it 2 or 3 rules
never used jokerforge personally, i've heard it's not great :/
nah, that's fair, im not saying it's your fault!!
moreso the fault of whoever made jokerforge lol
yeah
well i did modify the code a little bit, i changes the enhancements keys into my custom ones so itd (hopefully) work properly
apparently it dont work like that so idk how to fix it
well luckily, vanilla remade and Steel Joker exists
https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
just ctrl + f for "steel" and base it off that, i can help a bit more from there if need be
ok gimme a quick sec
i gotta change the rules of the joker to be more in line with steel joker
aight, so you'd mostly wanna replace:
if SMODS.has_enhancement(playing_card, 'm_steel') then steel_tally = steel_tally + 1 end
with:
if SMODS.has_enhancement(playing_card, '[your_enhancement_key]') then
enhance_tally = enhance_tally + 1
end
and duplicate the SMODS.has_enhancement() part for each enhancement you want to check for
heres the new version with more returns, i didnt change the enhancements yet
it doesnt look like you changed anything
i can write it for you if you want and comment it to help you understand better
yeah thatd be nice
cool, gimme a sec :3
chatroom i need a little help i was like oh for sure i got this And then it crashed immediately upon playing a single card 😭🕊️🕊️
what was the error you got
well it did this
done! this should work, but i have no way of testing it myself
lmk if there's another problem
G.play.cards.base.nominal here's your problem. G.play.cards is the table of cards in your played hand. so it doesn't find base
you need to do G.play.cards[i].base.nominal
yeah no sorry it aint work
okay well what does the description say?
okay, how did you paste the code i gave you exactly?
i copied it and put the whole code into the balatro mod as a joker
copied the code into your fsness file right? and did you delete or comment out the code you had earlier?
i got rid of the old code entirely and renamed your code to the old files name
and then i replaced it
alr in that case, that's weird then
are you using a saved game or debugplus savestate?
i think they just need to replace the enhancment keys with their own ones
i do have debugplus installed but i didnt use savestates
i tried that originally
maybe i did it wrong
it's not just that though, because i rewrote the inactive line to be "(Currently +#2# Chips)" specifically incase this happened
so if you arent seeing the "Chips" at the end of that line, it's a save issue
ah
save file or save state
save state
im basically saying start a new run
is this the same one as yours?
or is this my old one
oh its MINE 😭
bruh
ok i tried yours this time, but its visually stuck at +20 and doesnt give chips
Hmmmm
same as last time
Honestly i aint sure what i did wrong from here
And sadly, im having dinner, so i cant fix it
SHIIIIIT I KNOW WHAT I DID WROOOOONGGG
so this did fix the crashing. however. new issue encountered: it isn’t resetting the Xmult when it should (the base value for the played cards going over 21)
these conditions are set up wrong:
if context.full_hand then
for i = 1, #G.play.cards do
BlackjackCount = BlackjackCount + G.play.cards.base.nominal
end
if BlackjackCount == 21 then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
end
else if BlackjackCount > 21 then
local last_mult = card.ability.extra.Xmult
card.ability.extra.Xmult = 1
if last_mult > 1 then
return {
message = localize('k_reset')
}
end
end
you want it like this:
if context.full_hand then
for i = 1, #G.play.cards do
BlackjackCount = BlackjackCount + G.play.cards.base.nominal
end
if BlackjackCount == 21 then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
else if BlackjackCount > 21 then
local last_mult = card.ability.extra.Xmult
card.ability.extra.Xmult = 1
if last_mult > 1 then
return {
message = localize('k_reset')
}
end
end
end
@fringe oxide whenever you get back, i think i've figured it out this time
why are we doing else if
it's supposed to be elseif
i sea i sea 🌊🌊
much appreciated
local _poker_hands = {}
for handname, _ in pairs(G.GAME.hands) do
if SMODS.is_poker_hand_visible(handname) and handname ~= card.ability.extra.poker_hand then
_poker_hands[#_poker_hands + 1] = handname
end
end
local selected_hand = pseudorandom_element(_poker_hands, 'YA_to_do')
card.ability.extra.poker_hand = selected_hand
for i = 1, 3 do
local hand = G.GAME.hands[selected_hand]
hand.level = hand.level + 1
end
i have this consumable that functionally levels up a random hand 3 times but it doesnt do it visually, how do i do it visually?
don't increase the level variable directly
that would also fail to change the chips and mult
use the level up function. it's somewhere in the smods code
oh yeah youre right
i didnt even notice
thank you fake balamod dog
no, it's april fool's day
opposite day is January 25th
is there a booster_create_flags for context.create_booster_card?
I believe so yes
fair enough
ive made a custom rarity and put a joker into it, but it's still not appearing in the shop
is zwp your prefix?
yeah
also if it's a seperate file do you have it set to load from the main
yeah its all set to load
interesting
it all shows up in game but not in the shop
like
if i go to mod additions its there and right
but the rarity isnt displaying?
hmmm that's interesting
i have the rarity set very high weight, but its not showing up in the shop
alr im back
i wont be online im in game club tho
i based mine off the ones in vanilla remade
hope you're having fun!
still aint work lol, same issue as last time
did you start a new run to be sure?
do you have it set to spawn in the joker pool?
i misunderstood what it was saying to do on smods wiki, its working now
i did not
yeahhhh
lmfao time to make another unnecessary mod
ok so ive gotten everything to function properly but then i tried to set up the mod in the same way shown in the Beginner’s Guide to Making Balatro Mods video (rather than having everything on a single main.lua file) and the joker is Not showing up?? 🥀 the mod is being recognized as it shows up on the mod list but the joker itself isn’t actuall showing up 🕊️
Is there any way to make an entirely dummy card and change its text through the card.config or card.children subtables? I'm trying to have multiple variants of the same card appear in a popup context menu with different descriptions, which means they need to be distinct cards otherwise as far as I can tell changing either will change both
is there a way to give a message a longer lifetime?
delay = number
im wondering if there's any way to make a joker appear in the same pools as legendary jokers (soul, cryptid legendary deck, etc.) while having a custom rarity
i lied actually im still having a very strange bug. for some reason the all cards scoring doesnt work the first time the joker activates. it works fine on all subsequent activations, but this one bit doesnt
what makes it so odd is that the other effects are working perfectly
the +chips and Xmult work fine on the first activation, it's just exclusively the all cards score that doesnt
almost forgot but here's the joker code. everything else is working so ive no idea what it is
im very confused (dont mind my placeholder texture
)
modify_scoring_hand might actually come before context.before, so it's actually using the blackjack status of the previous hand (and on the first hand, that's nil because the variable doesn't exist yet)
not related to the thing functioning, but you should probably store BlackjackCount as a variable in the joker's ability table instead of it just being a global like that
so then if i were to check for the chips value during modify_scoring_hand rather than before it should potentially work?
i think so, yea
well it fixed the scoring issue but now the chips and mult dont activate Ever
if context.before then
for _, scored_card in ipairs(context.scoring_hand) do
local seal_pool = {
"Red",
"Blue",
"Gold",
"Purple",
"seal_fent",
"seal_discord",
"seal_seal_seal",
"seal_scrumball"
}
local random_seal = pseudorandom_element(seal_pool, pseudoseed("rand_seal"))
scored_card:set_seal(random_seal, nil, true)
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
return true
end
}))
end
end
iam trying to make a joker that applies a random seal on a card.
currently i get the error card:618: attempt to index a nil value
is line 618 the pseudorandom call?
nvm i fixed it Yay
your help was much appreciated 
I'm trying to make a tarot card for my mod but it's not showing up in the additions section in game, or the tarot cards menu
never mind i accidentally put an = on line one
You should be using SMODS.poll_seal
oh I already figured it out
I was just calling the keys wrong
Yes, you should still be using SMODS.poll_seal
why?
it'll let you respect the new weights system
instead of assuming that all seals have the same chance to be generated
Should I put the message here as well?
is there a pool for the jokers that can spawn from a soul? I want to add a joker with a custom rarity that would act like a legendary
no separate pool, it literally just searches through the set of legendary jokers
so theres no way to have one with a custom rarity be spawnable by the soul?
you can take ownership of the soul to make it take from a pool instead of the legendary rarity
you could make one 
i dont know how to do that
im very new to this and know like no lua
SMODS.Consumable:take_ownership("c_soul",{
-- new use function here
}, true) -- remove the comma the the true to make your mod badge show on the soul
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-create-a-poolset
https://github.com/nh6574/VanillaRemade/blob/main/src/spectrals.lua#L865
@bold eagle in the SMODS.add_card in the soul use function make sure the set is the key for your pool you made
ok
so sould i just like, copy paste all the code from the vremade soul?
and make adjustments?
copy the use function and the key only and edit them as needed
is there easy way to make joker not crash when it's played in hand?
how would I make it pull from all available legendaries as well as from my pool
because i want to be able to use other modded legendaries with it
what does >=1.* mean
this is a malformed dependency string that wasn't ever supposed to work, but it used to
go into the mod's json file and delete whatever line says "Steamodded (>=1.*)", and you should be good to go
it crashed lol
yeah i dont need that mod to work
speaking of mods this one joker crashes the game
is the april fools' update that balatro no longer restarts when you press R on the crash screen
Even if it does it does not reload lovely patches iirc
@bold eagle apologizes for the late response but this should work
SMODS.ObjectType({
key = "placeholder",
cards = {
-- your stuff here
},
})
for k, v in pairs(G.P_JOKER_RARITY_POOLS[4]) do
SMODS.Joker:take_ownership(v.key, {
pools = { ["placeholder"] = true },
}, true)
end```
is there any way to include jokers from other mods? it didn't spawn any from another mod i have installed
make your mods priority higher than the mods then try, not sure if it will work but thats my best guess
it didnt work but thank you for all the help
i have a joker effect that, when glass cards break, they're immediately recreated with +1 chance denominator (1 in 4 -> 1 in 5, etc.), an additional X2 mult, but are debuffed until the next ante.
they don't appear to be being added to the deck correctly? what am i doing wrong here that the deck limit is doing this
The shader for tanzanite seal is the same as gold seal's yet looks too bright for some reason
This is the code for tanzanite seal
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
G.shared_seals[self.key].role.draw_major = card
G.shared_seals[self.key]:draw_shader('dissolve', nil, nil, nil, card.children.center)
G.shared_seals[self.key]:draw_shader('voucher', nil, card.ARGS.send_to_shader, nil, card.children.center)
end
end
Is that supposed to replace everything from line 15 onwards?
No, it's supposed to replace the draw function.
So only line 15?
No, line 15-17
It didn't work
It's still super bright
Unless I did something wrong
SMODS.Seal({
key = "tanzanite",
atlas = "BZR_Seals",
pos = { x = 2, y = 0 },
badge_colour = HEX '2E76FD',
shiny = true,
gold = true,
config = { shiny = true, gold = true },
calculate = function(self, card, context)
if context.discard and context.other_card == card then
ease_dollars(-3)
card.ability.perma_bonus = (card.ability.perma_bonus or 0) + 10
end
end,
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
G.shared_seals[card.seal].role.draw_major = card
G.shared_seals[card.seal]:draw_shader('dissolve', nil, nil, nil, card.children.center)
G.shared_seals[card.seal]:draw_shader('voucher', nil, card.ARGS.send_to_shader, nil, card.children.center)
end
end
})
bump
how would i apply a custom dynatext to a badge text
deck limit must be handled manually
look at DNA's code
pardon me if this is a silly question but. is it necessary to set jokers to be available in shops? ive been rerolling shops with debug for like 20-30 minutes and ive not been able to get it appear :(
Do you have DebugPlus
yeag
ive already tested everything else properly i just want to make sure it can actually appear in shop
You don't need to reroll for it
you can go to collections and press '3' while hovering over it to spawn it in
well yea i did that for testing the effects, again i just wanted to make sure that it is able to appear in shop and is purchasable nd stuff 
Oh I see
You don't have an in_pool function attached to your joker do you?
If you do not then that's fine
You're very likely just getting really terrible luck lol
do objecttypes actually check if the rarities in the rarities table exist before using them?
Anyone know why I can't use this spectral card? Heres the can_use code
can_use = function(self, card)
if G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] then return true end
end,
I don’t think you need the third argument tbh
Fixed it :D
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, localize(card.ability.extra.suit, 'suits_singular') } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and
context.other_card:is_suit(card.ability.extra.suit) then
return {
mult = card.ability.extra.mult
}
end
if context.joker_main then
for _, playing_card in ipairs(context.scoring_hand) do
if playing_card:get_id() == 12 then
for k, v in pairs(context.full_hand) do
if v.base.suit == 'Clubs' or v.base.suit == 'Hearts' or v.base.suit == 'Spades' then
SMODS.change_base(v, 'Diamonds')
end
end,
}```
something about this is crashing the game, the ends it seems, i've tried adding more and less but nothing is working
I have these context events that keep track of every card destroyed in a run. Whenever I destroy some cards, the game suffers a thread error a few seconds after I discard any cards. What do I do?
LAPSEMS.shallow_copy = function(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
--[[
Code adapted from Extra Credit's Ship of Theseus.
--]]
if context.cards_destroyed then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
G.GAME.LAPSEMS_cards_destroyed_this_run = G.GAME.LAPSEMS_cards_destroyed_this_run or {}
for k, val in ipairs(context.glass_shattered) do
G.GAME.LAPSEMS_cards_destroyed_this_run[#G.GAME.LAPSEMS_cards_destroyed_this_run + 1] = LAPSEMS.shallow_copy(val)
end
return true
end
}))
elseif context.remove_playing_cards then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
G.GAME.LAPSEMS_cards_destroyed_this_run = G.GAME.LAPSEMS_cards_destroyed_this_run or {}
for k, val in ipairs(context.removed) do
G.GAME.LAPSEMS_cards_destroyed_this_run[#G.GAME.LAPSEMS_cards_destroyed_this_run + 1] = LAPSEMS.shallow_copy(val)
end
return true
end
}))
end
ok i got it working
The error message is not informative.
Oops! The game crashed:
Thread error (Thread: 0x01e30c8e3c70)
engine/string_packer.lua:43: attempt to concatenate local 'v' (a userdata value)
stack traceback:
engine/string_packer.lua:43: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:69: in function 'compress_and_save'
engine/save_manager.lua:82: in main chunk
instead of LAPSEMS.shallow_copy(val) do val:save()
What does val:save() do differently?
It's what the game uses to save cards, selectively picking what stuff to save, you can look at it in the lovely dump in card.lua
what you were doing was the equivalent of trying to save the card object directly, just without the metatables
is there something to check if a repetition has occured. i need for something im making rn, i want it so that it does something every time a repetition occurs
how do you track the last sold joker?
my mod crashed (smashlatro) and idk why
its affecting the base game too even when the mod folder is removed
local oldsellcard = Card.sell_card
function Card:sell_card()
local g = oldsellcard(self)
if self.ability.set == 'Joker' then
G.GAME.modprefix_last_sold_joker = self.config.center.key
end
return g
end
how would i give the ability of the tracked joker to another? like pinkprint in ortalab basically, i want the joker to dynamically have the ability of whatever is stored
i have looked at how pinkprint does it, but ortalab has some of its own definitions and i have no idea how to actually do something similar
hey does anyone know how to fix this
You would do this: #⚙・modding-general message, but you would replace card.ability.extra.currentJoker with G.GAME.modprefix_last_sold_joker
loc_txt
oops.
does it update dynamically?
Yes.
what is context.setting_blind?
It's when a blind is selected, but you don't need that part.
hey does anyone know how to change like the round/blind number
ease_round(number)
what do i actually wrap this in?
if G.GAME.nmb_last_sold_joker then
local key = G.GAME.nmb_last_sold_joker
G.nmb_savedjokercards = G.nmb_savedjokercards or {}
G.nmb_savedjokercards[card.sort_id] = G.nmb_savedjokercards[card.sort_id] or {}
if not G.nmb_savedjokercards[card.sort_id][key] then
local old_ability = copy_table(card.ability)
local old_center = card.config.center
local old_center_key = card.config.center_key
card:set_ability(key, nil, 'quantum')
card:update(0.016)
G.nmb_savedjokercards[card.sort_id][key] = SMODS.shallow_copy(card)
G.nmb_savedjokercards[card.sort_id][key].ability = copy_table(G.nmb_savedjokercards[card.sort_id][key].ability)
for k, v in pairs({'T', 'VT', 'CT'}) do
G.nmb_savedjokercards[card.sort_id][key][v] = copy_table(G.nmb_savedjokercards[card.sort_id][key][v])
end
G.nmb_savedjokercards[card.sort_id][key].config = SMODS.shallow_copy(G.nmb_savedjokercards[card.sort_id][key].config)
card.ability = old_ability
card.config.center = old_center
card.config.center_key = old_center_key
for k, v in pairs({'juice_up', 'start_dissolve', 'remove', 'flip'}) do
G.nmb_savedjokercards[card.sort_id][key][v] = function(_, ...)
return card[v](card, ...)
end
end
end
return G.nmb_savedjokercards[card.sort_id][key]:calculate_joker(context)
end```
do i make it an external function and then call it in the joker, or do i put this in the joker itself
originally i was making it update when a joker was sold and then also when my joker was added to deck, because i needed it to update both while you have the joker and while you dont
That would go in the calculate function.
Hello. Can anyone help me about JokerForge because nobody is helping thru the forum?
#1456643405395398667 message still this? you need to update steamodded
I updated
I have another problem
actually its about the Joker Forge
how do i change the x / y positions of a sprite?
i'd like to move a sprite by a distance less than one pixel
youre goated ty
gonna try editing VT
could i get some help resolving this issue? i really wanna playtest my mod soon
figured it out ^u^ it's an argument of draw_shader()
Currently trying to implement a joker that will only trigger on scored cards with my custom enhancement
SMODS.Joker{
key = "propeller",
atlas = "placeholders",
pos = {
x = 4,
y = 0},
config = {
extra = {
xmult = 1.5
}
},
rarity = 4,
cost = 10,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and
SMODS.has_enhancement(card, 'm_zwp_whimsical') then
return {
xmult = card.ability.extra.xmult
}
end
end,
}
it will trigger on any card if I remove the SMODS.has_enhancement(card, 'm_zwp_whimsical') line, and thats the only way I know how to check for enhancements
That’s it?
Just change card to context.other_card?
Sweet it worked thank you
how would I make a joker both retrigger cards and give xmult, do I just use two calculates?
gotchu, thank you
currently trying to make an enhancement that will remove the enhancement and add a random edition, but the visual for the edition being added happens immediately upon playing the hand, and I want it to happen after the enhancement gets taken away, the effects of the edition don't go into effect immediately, only the visual
SMODS.Enhancement{
key = "whimsical",
atlas = "enhancements",
pos = {
x = 0,
y = 0
},
config = {
mult = 0,
extra = {odds = 10},
},
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'vremade_glass')
return { vars = { card.ability.mult, numerator, denominator, } }
end,
calculate = function(self, card, context)
if context.cardarea == G.play and context.destroy_card and context.destroy_card == card and
SMODS.pseudorandom_probability(card, 'zwp_whimsical', 1, card.ability.extra.odds) then
card:set_ability('c_base', nil, true)
local random_edition = SMODS.poll_edition { key = "modprefix_seed", guaranteed = true, no_negative = true }
card:set_edition(random_edition)
return {
message = "Evolved",
}
end
end
}
woah it formatted weird
oh nvm wraparound
move the set_edition call into something like this
return {
message = "Evolved",
func = function()
card:set_edition(random_edition)
end
}
that should adjust the timing i think
cool imma try that
it shows error lines under the function stuff
this was all the error stuff
odd
what's the error saying? it should be fine, unless i'm being stupid
ah good lol
okay so it still displays the edition before scoring
wait i have a really stupid idea
i moved the card set edition outside of and after the if statement, that way if it doesnt go through the if the variable random_edition never passes so it wont display until after
maybe
im trying it and if it works im gonna be shocked
it did not work
hm
i could maybe change some draw order? idk how any of that stuff works
set_edition(key, nil, nil, true)
wait i think im missing an argument
there
it crashes
nvm I was being stupid
oh my god it's working
thank you both so much
How could I change a cards sprite while its upside down?
right now this is causing infinite recursion
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''
if card.ability.repetitions and card.ability.repetitions > 0 then
ret.seals = ret.seals or { card = card, message = localize('k_again_ex') }
ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.repetitions) or card.ability.repetitions
end
if card.ability.perma_repetitions and card.ability.perma_repetitions > 0 then
ret.seals = ret.seals or { card = card, message = localize('k_again_ex') }
ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.perma_repetitions) or card.ability.perma_repetitions
end
'''
position = 'after'
payload = '''
SMODS.calculate_context({card_retriggered = true})
'''
match_indent = true
first time making a patch why does it specifically trigger when a card triggers outside of retriggers
hm. maybe this payload would work instead?
if ret.repetitions and ret.repetitions > 1 then
SMODS.calculate_context{ card_retriggered = true }
end
i figured it out
i didnt figure it out WHERE are retriggers applied
how do i put Sprites on the screen?
i assume this is mod jam related so i won't ask for further details
your best bet is probably a custom UIBox; somewhere in that UIBox should contain a G.UIT.O node with its object set to your sprite
okay
im trying to make a joker that destroys unscored cards, is there a way to detects cards played but not scored
context.cardarea == "unscored"
is there a guide anywhere on how to add your own mod to the balatro mod manager?
im assuming the context for when theyre played but like
and not (context check for played cards)
idk tho
https://github.com/skyline69/balatro-mod-index
note the "CLAUDE.md" file in this and the balatro mod manager itself tho, i hope you think twice about supporting a vibe-coded tool like this
so i can say if context.cardarea == "unscored" then
is the balatro mod manager itself vibe coded aswell?
ill look into it ig
if context.destroy_card and context.cardarea == 'unscored' then
return {remove = true}
end
probably not fully, at least these files were added at a point after creation
but it definitely makes use of vibe coding now
what is context.destroy_card
someone suggested it so i thought id look into how to do it
this does work though so thankyou
post your definition of the SMODS.Sound, as well as the place where you're calling the sound
no
don't do that
yo uneed to add your mod prefix to the sound key in the edition defintions
You're right, I was thinking of something else
ok thaks
ok i think i did something wrong
its modprefix_soundname right?
cause it still isnt working
What does your code look like now?
im so lost
sanity check:
if context.mod_probability ... then
return { denominator = context.denominator + [modifier value here] }
end
or
if context.mod_probability ... then
return { denominator = [modifier value here] }
end
first one iirc
lucky cards roll both of their chances at the same time and apply them both in the same context
so it makes a table, rolls the mult effect, adds that to the table if it succeeds, then repeats that with the money effect
and then it returns that table
probably not
peak
you can just return inside of the probability success
help
Now, a crash is produced for the one thing I implemented that list for.
set_blind = function(self)
local cloned_cards = {}
for _, card_to_resurrect in pairs(G.GAME.LAPSEMS_cards_destroyed_this_run) do
for i = 1, self.config.extra.copies do
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local cloned_card = copy_card(card_to_resurrect, nil, nil, G.playing_card) -- This is the line that produces a crash.
SMODS.debuff_card(cloned_card, true, 'bl_lapsems_final_ossuary')
cloned_card.ability.LAPSEMS_final_ossuary = true
cloned_cards[#cloned_cards + 1] = cloned_card
end
end
for i = 1, #cloned_cards do
G.E_MANAGER:add_event(Event({
trigger = 'after', delay = 0.05,
func = function()
G.deck:emplace(cloned_cards[i])
return true
end
}))
end
self.original_deck_size = G.GAME.starting_deck_size
G.GAME.starting_deck_size = #G.playing_cards
G.deck:shuffle('bl_lapsems_final_ossuary')
end,
Because card_to_resurrect is no longer a card object, so you can't pass it to copy_card
How do I make it such?
try this
local cloned_card = Card(0, 0, G.CARD_W, G.CARD_H, G.P_CENTERS.j_joker, G.P_CENTERS.c_base)
cloned_card:load(card_to_resurrect)
Got it working, and adjusted the first two values -- presumably coordinates -- so they don't pop out of thin air from on the screen. Changed 'em to 50, 0 'cause I hought that's roughly where Rouge Rose's cards come from.
How come context.other_card returns nil here?
calculate = function(self, blind, context)
if not G.GAME.blind.disabled then
if context.individual and context.cardarea == G.play then
G.E_MANAGER:add_event(Event({
trigger = 'after',
blockable = true,
blocking = false,
func = function()
-- ...
return true
end
}))
end
end
end,
You need to do local other_card = context.other_card and use that variable in the event.
Tried that in the interim, it worked.
is it possible to have a tag do an effect when you click it?
SMODS.destroy_cards
SMODS.destroy_cards(cards, bypass_eternal, immediate, skip_anim) <-- from the SMODS documentation
For example, I think the Vanilla Remade Popcorn uses it
SMODS.destroy_cards(card)
I mean like, when you click it once you own one, is it possible to do an effect?
Yes, try hooking Tag:click or Sprite:click
Awesome ty, I'll look into it
I'm unsure why this is crashing
how can i make a joker pinned to the rightmost slot?
and not (context.consumeable.edition and context.consumeable.edition.negative)
thank you
why my joker only score +1 mult when i didn't have any +mult and it didn't score ^mult?
Is there a list of all unqiue owned jokers in a run?
Are you creating G.GAME.ato_perm_mult with 0 as the starting value?
Also, ^mult is not a builtin return value, you need to implement it yourself or use a library that adds it
ok thanks:))
No, there isn't.
Is there a way to return cards to hand, like force draw them?
So this so far DOES print when you click the tag
local old_sprite_click = Sprite.click
function Sprite:click(...)
print("Sprite Clicked!");
return old_sprite_click(self, ...)
end
But I'm struggling to figure out how to get any info about the tag you're clicking
self.config.tag
ty
is there a way for me to know whats in these tables? Its hard for me to find information on it
Trying to figure out what is inside the "tag" table
And also I need to know what is in the "G" table because I want to check if this is a tag you actually own, and not a tag thats like, in the collection screen
But, yeah, I'm struggling to find documentation about what is in these tables and I don't know how to figure it out
I'm a bit new to lua and modding, so, apologies, struggling with this a bit
tags are a bit different compared to other game objects
if not G.SETTINGS.paused
Awesome that helps a lot ty
tags are stored in G.GAME.tags as an array
the visible tags you can see on the screen are their sprites instead
they don't have an area like cards do, they instead behave like a linked list, where given the first tag sprite's position, all subsequent tag sprites anchor at an offset
for i = 1, #G.GAME.tags do
local tag = G.GAME.tags[i] -- the tag object
end
ahh alright ty that is helpful to know
I was trying to see if I could add a function to tags to call whenever I click them, I think I'm almost there but its not quite working
can I just add my own function to the table for tags? Like putting this inside of my custom tag:
click_action = function(self)
print("Did an action! Yippie!")
end
then doing something like
if tag.click_action then
tag.click_action(tag)
end
but, it doesnt seem to work, I might be misunderstanding something here
this
unlike card objects (what you see is what you can interact with), tags only show their sprites to you
Are you saying that, self.data on the Sprite.click function is not the actual tag itself?
Like, I need to search through all the existing tags for the tag that matches the key of the one I clicked or somethin?
that would be the case
okay cool, that sounds doable
is there anyway to get the sprite instance from the G.GAME.tags that it draws and compare it with the one from Sprite.click?
just to make it so that the tag that gets used is the actual one I clicked (not a big deal if I cant)
Card class is inherited from Moveable
while Tag class is inherited from Object
I have absolutely no idea what
was thinking about it
the sprite is in the tag's children (I don't remember what key)
oh because it's not a Moveable?
Okay awesome
Is there any way I can like.. debug some of this information to see?
I been trying to use just the print() function for seeing what values are, but for whole tables I am not sure what to do
I wanna save yall the trouble of asking so many questions here lol, but I really appreciate the help
that's dumb
the better option in that case would be looking at lovely dumps to pick stuff up from the code
- set up a sprite field
- add/override several methods to it
- assign it to Tag object's
tag_sprite
I remember seeing this actually, I just forgot because of how dumb it is
how do I get the sprite I clicked on in the Sprite.click function?
is it just "self"?
the tag "area" being a hardcoded linked list instead of an actual area is another dumb thing
assign the click method to the sprite field using the following hook:
local tag_ui = Tag.generate_UI
function Tag:generate_UI(_size)
local tag_sprite_tab, tag_sprite = tag_ui(self, _size)
tag_sprite.click = function(self)
-- do your stuff
end
return tag_sprite_tab, tag_sprite
end
Sprite itself is inherited from Moveable, but due to the way the game handles Tag objects, it's better to just override click of that specific Sprite field instead of the whole class
Okay cool, sounds good, I suppose I can just do that instead
I'm trying to put a function on tags atm, and check if that function exists, and if it does, it'll call it called "click_action" but its not working and I'm not sure if thats even a thing I can do
I added
click_action = function(self)
print("Did an action! Yippie!")
end
to the custom Tag object and am trying to reference it
I can find another way around this, I just thought it'd be convenient to put the functions on the tags themselves
(This might be just a me not understanding lua very well sort of issue)
this is due to the tag prototype objects and the actual Tag instances not being thei same. Assuming you put that function in a SMODS.Tag definition, you can access the function as G.P_TAGS[self.key].click_action
Ahhh okay okay so it does work like most other programing languages then, sort of like a class, right?
THat makes sense
if you're asking for a convenient way to add click action to a tag object via SMODS.Tag, you can just modify the same hook to:
local tag_ui = Tag.generate_UI
function Tag:generate_UI(_size)
local tag_sprite_tab, tag_sprite = tag_ui(self, _size)
local obj = SMODS.Tags[self.key]
if obj and obj.click and type(obj.click) == "function" then
tag_sprite.click = function(tag_sprite_self)
obj:click(self)
end
end
return tag_sprite_tab, tag_sprite
end
and in your Tag object, simply add a click field:
SMODS.Tag{
key = "my_tag",
click = function(self, tag)
-- do stuff
end,
}
this has to be a convenient PR to SMODS ngl
note: there's no practical difference between SMODS.Tags and G.P_TAGS other than G.P_TAGS containing unmodified vanilla tags
I apprecaite yalls help a ton, I think I understand a little more
can someone helpl me sort thehse sounds out
something is wrong with this and i cant for the life of me figure it out
what is your mod prefix as per the metadata?
thats this one right
yuh that seems all correct. what happens when applying the edition and how are you testing it?
is there anyway you can make a joker pin to the rightmost?
the game crashes and produces a crash log only when the edition appears naturally, since applying it myself doesnt produce the sound
no readily available one. You'd have to adapt the code for the regular pinned sticker found in CardArea:align_cards and hook/patch that in
ok thanks for that:))
check if the sounds file is even getting loaded
Does your sound file work?
yeah they all play in file viewer
do i need to atlas it?
because its not a sprite so
What did you change to get this new error?
where is your sound file?
local function load_sounds_file()
local mod_path = SMODS.current_mod.path
assert(SMODS.load_file("sounds.lua"))()
end
load_sounds_file()
added this code to the main.lua
so i made a custom deck with the custom deck mod and i tried to make a glass cannon deck that bans jokers with enhancement related conditions to them and now anytime i get to the shop it crashes
sound file is in assets and the code is in the main mod folder
is it in assets/sounds or just assets?
assets/sounds
any idea of how I could implement that?
look at observatory in vanillaremade
when used...
hook Card:use_consumeable, check if the card is a planet card, apply additional mult. you can check level_up_hand to see how it's affecting the mult and chips of the hand
if this should affect level ups in general, you can also modify the level_up_hand method on the mult scoring parameter. otherwise the above
should affect level ups yeah
i still dont know precisely what a hook is, is it context.using_consumable for example?
look at vanillaremade wiki
to hook I need to write a toml file right
that is a lovely patch
ok so its a bit like a wrapper in python
and I just... throw a hook into the joker code?
ok I searched it up
local level_up_hand_base = G.FUNCS.level_up_hand
G.FUNCS.level_up_hand = function(card, hand, instant, amount)
local ret = level_up_hand_base(card, hand, instant, amount)
local privet = SMODS.find_card("j_florr_privet")
print("Test to see if it runs")
if #privet then
for i = 1, #privet do
privet[i]:juice_up(0.3, 0.4)
play_sound("tarot1", 1.0, 0.7)
G.GAME.hands[hand].mult = G.GAME.hands[hand].mult + math.floor(math.sqrt(G.GAME.hands[hand].level))
end
end
end
this doesnt print anything in the chat or do anything
That function you are trying to hook isn’t a thing
ah.
what is the correct level_up name then
wait yeah it isn't
this one
what made you think that was in G.FUNCS
Yeah but hooking that might get a little bit funky
¯_(ツ)_/¯
wdym
is there an easier way then?
You'd want to explore SMODS.upgrade_poker_hands for sure. 🖐️
Is there a way to use the sprite atlas from one mod in another?
if the other mod loads before, yes
you need to set prefix_config to not add the prefix to the atlas and then use modprefix_key of their atlas
I don’t think load order would matter
that seems to be working, thank you!
so I hook this? or I use it?
it would not
nice
Not sure, most likely use.
is there an easy function call that just forces the hand to sort itself by current sort order?
CardArea:sort() passing no method?
yes
looks like card areas have self.config.sort
yeah, sort uses whatever the one stored there is
works. thanks for the help
how can i make a new type of consumable that can have duplicate without showman?
why is my c:edition text turning yerllow
it does that
c:dark_edition
ah
scale_card is a something that you call from within the calculate function
So, like this?
no, it would replace what you currently have as line 29
And then, what would the context be for triggering it when the joker to the right is triggered?
use context.post_trigger, along with some additional work to make sure that the joker trigger that caught it was the joker to the right
note that post_trigger is an optional feature you have to enable
it's just a function that goes directly in your mod's main file
cool
and you only need to return post_trigger = true, not any of the other stuff (unless you want those features too)
I'll just leave them to be safe
(in particular, quantum_enhancements will probably cause a dip in performance)
also object_weights messes with vanilla seeding
and retrigger_joker and the cardareas also add additional calculations which slow stuff down
This is only supposed to have 2 uses but it had 3, I turned the config = {extra = {keep = 1}} into keep 1 though so now it's 2 uses
But the description is still 1 lower than the amount of uses left, on the last use it always says 0 left
bump
classic OBOE
keep on use n times <==> n+1 uses left
anyone know why this is giving me this error despite the shader having both functions?
local shader = love.graphics.newShader(SMODS.current_mod.path .. "assets/shaders/shader.fs" ) -- Gives me more control than SMODS.Shader
bad argument #1 to 'newShader' (missing 'position' or 'effect' function?)
oh it seems there's a compile error
idk why tho
i was missing an opening brace
What if the shader is EVIL
how do I make a booster change the music?
You would put this in the SMODS.Sound definition: ```lua
select_music_track = function()
return G.booster_pack and not G.booster_pack.REMOVED and SMODS.OPENED_BOOSTER and SMODS.OPENED_BOOSTER.config.center.kind == 'kind' and 100 or nil
end
ah thx
It keeps crashing when I look at my jokers or boss blinds even though the atlases should be correct?
can I see your config file
neonmod.json or something
and the type in the console
eval for key, _ in pairs(SMODS.Atlases) do print(key) end
figured it out 
So I just put this in the main.lua?
run it in the console
do you have debugplus
no
they're not there for some reason
it should be SMODS.Atlas {, not SMODS.Atlas = {
the first one creates a new atlas, the second one overwrites the whole definition of what an atlas is
Ah.
ive made jokers but ive never made a deck does anyone know how i would do it
they're called "Backs" internally, here's the documentation
https://github.com/Steamodded/smods/wiki/SMODS.Back
decks can have calculate functions just like jokers can, but also have an apply function that's called at the start of a run if that deck is selected
It doesn't crash when I look at or hover over the jokers anymore, but when I entered the shop it crashed for some reason.
(Hovering over the blind still crashes for some reason, but at least I can look at the icon)
okay the contect was a typo apparently
Every time i play a hand it says on the logs " DefaultLogger :: Found effect table with no assigned repetitions during repetition check", the joker effect works but idk why it says that
You need to add context.individual to the if
Trying to make this scale whenever the joker to the right triggers, but it's not working.
context.cardarea is not the joker that triggered
why
why are you even checking cardarea
idfk man
(insert "read the fucking docs" hamster here)
okay but now it's activating on literally every Joker?
you are actually checking if context.other_card is equal to other_joker right
How can stake stickers from multiple series' of stakes be shown simultaneously
can someone explain why this doesnt work for jokers?
i dont think editions can use joker_main
it should be pre_joker or post_joker
also holy shit why is joker forge like this just use the dollars return value 😭
this is possibly the dumbest way I have ever seen to add 1 dollar
oh wow
saving a global in a local for no reason
then the exact same global +1
then set added amount to x - y which is just dollars - (dollars - 1) which is literally just dollars - dollars + 1
insane levels of genius
and the manual message too
not even return message but card_eval_status_text with no localized message just manual concat of a +
not even a dollar sign
As someone who also doesn't know what I'm doing, true.
Speaking of which...
How much of this is fucked up?
post_joker is only for editions calculating after the joker it's on has calculated
and i think you meant to do context.individual instead of main_scoring
isn't blind.ability not a thing
idfk
or did we add that
its like
blind.effect
iirc
i think N added that he can probably confirm
if that doesnt exist just use self.config.extra
wait
meh i wouldn't go as far as recommending that
geez
that would explain why it crashes when I hover over it.
please use the lua extension code formatter
will make everyone's life easier
I already have it though?
right click on your code and click format code
or you can enable format on save in vscode settings
_ _
Visual examples
loc_vars on blinds only gets self, no other parameters
ah, okay
If this is impossible then is it possible to make it a config option to prioritize either the vanilla stickers or the ones from my stake series
Make an atlas with the sticker in the position you'd want em and use a SMODS.DrawStep to put them on a card (check SMODS card_draw.lua file for examples)
is there a way to apply xscore after the played hand has been calculated and added to the score 
context.after?
I imagine so yeah
hmmm, no. after is ever so slightly too early
calculate = function(self,card, context)
if context.before and context.cardarea == G.play and context.individual and SMODS.has_enhancement(context.other_card, nil)
and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
return {
context.other_card:set_enhancement("zwp_whimsical")
}
end
end
where is the draw function for center objects at?
blind.effect.extra.xmult
im trying to make a joker of mine give my edition to played cards randomly as soon as they're played, but this does nothing
im trying to figure out what set of transformations I need to apply during a drawstep
Either move the setting of edition under
return { func = function() context.other_card:set_enhancement("zwp_whimsical") end }
or put it outside of return.
yall know how to change the balatro bg
it still did nothing
...are you checking if card has any enhancements?
SMODS.has_enhancement(context.other_card, nil) wouldn't be the way to do it... next(SMODS.get_enhancements(context.other_card)) would be that.
ah
i thought it would have to have nil
ok thank you
it still didnt do anything
calculate = function(self,card, context)
if context.before and context.cardarea == G.play and context.individual and SMODS.has_enhancement(context.other_card)
and SMODS.pseudorandom_probability(self, 'zwp_pencil', 1, self.ability.extra.odds) then
return{
message = "silly",
func = function()
context.other_card:set_enhancement("zwp_whimsical")
end
}
end
end
wait nvm i misread your message
would i do == nil or just leave it blank after that
If you don't want the card to be enhanced, not next(SMODS.get_enhancements(context.other_card)) then.
cardinstead ofselfforSMODS.pseudorandom_probability.- There is no
context.individualforcontext.before- you'd want to iterate over the cards and roll the chance for each card separately.
how would I do that for 2
Do you want to count the full hand or scoring hand?
only scoring
for _, pcard in ipairs(context.scoring_hand) do
if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
pcard:set_enhancement("zwp_whimsical")
end
end
But then that makes this part out-of-place
For yours, you can have it self.config.extra.xmult, but for calculate, blind.effect.extra.xmult.
it crashes upon playing a hand
Again, log.
Where are the odds stored?
SMODS.Joker{
key = "pencil",
atlas = "woker",
pos = {
x = 2,
y = 0},
config = {
extra = {
extra = {odds = 2}
},
},
rarity = 2,
cost = 5,
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'zwp_pencil')
return { vars = { numerator, denominator } }
end,
calculate = function(self,card, context)
for _, pcard in ipairs(context.scoring_hand) do
if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
pcard:set_enhancement("zwp_whimsical")
end
end
end
}
damn it
i just realized
extra.extra
yep
Remember to spawn a fresh copy before re-testing.
I restart my run
it crashed again
Re-enter blind on new run?
...you removed the if context.before and context.cardarea == G.play conditions...
Got this when I rerolled onto it
i forgot about those 😔
...did you still keep the blind.effect?!
after adding them back it no longer crashes but still does nothing
config = { extra = { xmult = 0.9 } },
loc_vars = function(self)
return { vars = { self.config.extra.xmult } }
end,
calculate = function(self, blind, context)
if condition then return { xmult = blind.effect.extra.xmult } end
end
should work fine.
Tried without the probability roll?
i set the odds to 1/1
SMODS.Joker{
key = "pencil",
atlas = "woker",
pos = {
x = 2,
y = 0},
config = {
extra = {odds = 1}
},
rarity = 2,
cost = 5,
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'zwp_pencil')
return { vars = { numerator, denominator } }
end,
calculate = function(self,card, context)
if context.before and context.cardarea == G.play then
for _, pcard in ipairs(context.scoring_hand) do
if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
pcard:set_enhancement("zwp_whimsical")
end
end
end
end
}
Try just if context.before then?
:set_ability("m_zwp_whimsical"), that's on me-
hi, started modding yesterday, is there a tool that can help me make my sprite atlas without using online editors to align to a grid? lmao
Best bet is to make your own "grid" on a separate layer.
it finally worked thank you so much
just had the grand idea of sprite sheets lmao
Works mostly fine, but then whenever I play a hand that does more than like one thing ever, this happens. (Commented out the main_scoring one because it wasn't working how I wanted. Oh well.)
...curious, try adding card = context.blueprint_card or context.other_card or blind to return?
For reference, my Joker setup was Left Joycon, Portal Radio, and RIght Joycon, in that order
As in just slapping it inside of the return{}?
After message = '...', ye.
bump
Can cards be face down and debuffed at the same time?
yes
how would I cause the summary for an enhancement to appear next to a joker?
like with midas mask and gold cards
loc_vars = function(self, info_queue, card)
info_queue[#info_queue+1] = G.P_CENTERS.enhancement_key
end
cool thank you\
Okay, now it's working with the Jokers pretty well.
IT'S ALIVE! (I'll probably just scrap the playing card half of it and make the scaling harsher to compensate)
i don't believe so, no
I don't know, is there Zarcheus?
you could probably do something with custom colors though
make it the same as the background
that is surprising to here actually
'...',
' ', -- space is necessary
'...'```
ooooh
I didn't try a space
yeah, i have several localization text blocks that do this and this is most likely what @bold eagle is looking for. try that
cool, thanks
Trying to do this but it just isn't working with this (or the even earlier attempt at making it just force the packs to become Spectral)
Probably because I have zero clue what's actually occurring with the payload bs and what it would actually need to be doing to accomplish that
how would I go about making a custom message appear over a playing card when the joker condition is fulfilled? I can't think of any jokers that do something like this off the top of my head
return { message = "Something", message_card = whatever the playing card object is }
ty!
if you're in context.individual, i think the message will just be on the relevant playing card by default even
I guessed as much when the walkie talkie 2 example joker had to specify the message appears on the joker
do I need to set up a message variable to get this to work? or is there a message variable just in general that can get used
no, you can just return what i gave you
when you have { message = x } in a table, "message" is a key into the table, so you're essentially setting up the message variable right there
how would I check through the owned jokers for a custom rarity?
yep, add colour = something to the table. the colour value can be in the format HEX("FF0000") for an arbitrary color, or something like G.C.MULT for one of balatro's predefined colors (check the text styling page on the smods wiki for a full list of those colors)
loop through G.jokers.cards and check each card for whether card:is_rarity("modprefix_raritykey") is true
how would I move through multiple jokers
this is for checking things to add jokers to pools
for i, v in ipairs(G.jokers.cards) do
-- do something with v, which is an individual joker from the table
end
this is basic lua
ok I got the joker to work as intended, but is there a way that I can make the custom message entirely take the place of the message that is supposed to show that something gave x mult?
message = "..." iirc
add remove_default_message = true to the return table
yep
everything in lua starts at 1 actually
thats so dark and twisted
if you're familiar with coding already it's definitely something to get used to lol
well atlas co-ords start at 0
I'm new to balatro modding and lua but am quite familiar with coding lol
but yeah, going between 0-based and 1-based is weird
that is messing me up lmao
ok so currently I've absorbed some parts of jokers I've seen, does this look right? I didn't understand the setting up custom colors lol
I'm pretty sure I've done something wrong with the loc_vars setup
you're close
colours = { ... } goes inside the vars table right next to card.ability.extra.Xmult, and then it'd be {B:1} in the localization itself
ohh gotcha
if i'm reacting to another joker via context.post_trigger, how can i get any chips or mult returned by other jokers? 
oh, remind me how i make a use of scale_card not trigger calc_scaling? 
as per the documentation, during context.post_trigger, you'll get context.other_ret as the return table from the joker trigger
iirc it'll be a bit nested in some other tables, but it's in there somewhere i promise
and from the same page, you can block scaling manipulation by adding some part of this table to the scale_card call, but it'll always trigger the calc_scaling function for stuff that just wants to react to something scaling
you'll have to do it manually
you could probably make a patch to disable it
actually I might PR that, seems moderately useful and lightweight enough
yea if you don't want any calc_scaling to trigger at all, just skip the scale_card call entirely lol
my problem being that i have a calc_scaling function that calls scale_card and i just realised that this causes an infinite loop if i have two of that object
oop
admittedly, my first thought is to ignore objects with the same key, but
yeah i'd do it manually or make a patch for an option to disable it
ok so you should've led with that
calc_scaling passes other_card, you can check the center to avoid trigging scale_card on a copy of itself
this is really funny
yes i search for messages containing joker forge occasionally
do yall know how to change the bg swirl colors on balatros main menu?
do i paste this to the bottom of my mods main.lua
also,,, do the colors need a hex code?
y'all need to get more comfortable with trial and error smh my head /lh
