#💻・modding-dev
1 messages · Page 359 of 1
what is the overall goal?
never made a dummy joker but I'm assuming you need to add it to a hidden cardarea and add it as a calculation area to SMODS
how do i apply a random enchancement to a playing card?
I'm just trying to learn the basics of joker calculations. I just wanna understand the mechanics.
here @shut crater
use set_ability with SMODS.poll_enhancement
would that work for seals and editions? i know they use different functions
are you adding the joker to your jokers area?
I'm actually not sure
hmm just had a joker idea, x0.1 for every achievement in balatro unlocked
I guess not, from what I was given, all I see is that it's registered. The main lua file just includes the jokers so I assume that's all you need (basically my first image) https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua#L1728C5-L1730C8
time to cook
iirc it's set_seal and SMODS.poll_seal and set_edition and poll_edition (no smods)
metalinguistic joker!!
yeah but to get the joker to score the player needs to own one
lol read that as "metal linguistic" instead of "meta linguitsic" at first
that adds the joker to the shop and packs to buy but you need it in the area to do stuff
I was under the impression that a "fake joker / dummy joker" is one that fires universally
do you want the basics of how jokers work or do you want to figure that out?
there is no concept of a fake joker in vanilla as far as I'm aware
you need to do this ^
Earlier I mentioned that I found it difficult to know how to do universal events using the main Game:update loop. Someone said people use fake jokers. I guess as a way to have better context for the game (idk).
Oh I see. This info is like gold dust. Apart from the SMODS wiki and here, are there any more general docs on Balatro modding methods?
Not really no
Oof
I learned all of that by reading the code and being here
That's impressive
why is this throwing an error
Are you missing an end on line 5?
card:set_x(key)
i need to go make a mod actually it seems fun and cool
which page?
utility
How can you get the localized name of a joker?
someone should pin docs or something idk
Well, modded joker in particular
Vanilla "name" variable works fine with vanilla, but is just the key on modded
localize{type="name_text", set="Joker", key=key}
Okay, I guess I gotta go find an example of a dummy joker. I don't wanna clog up this with crappy questions, should I start a "Darren is dumb" thread lol
do i need to define local card? or does context.induvidual do that
context.other_card
instead of context.induvidual
I would look at Victin's mod
does anyone know if it's normal for the debugplus console to close when you run things?
and then you have to reopen it to see the output
it's annoying for eval
no, it's a value in context.individual
it's that what that 'show new log messages' or whatever setting is for?
Ohh. I didn't know of these other game refs you can use.
i think so?
Why does no_edition not do anything when using SMODS.create_card/SMODS.add_card?
it does for me, why?
Thanks!
i just found out i mispelled "enhance" as "enchance" like 7 times in my code
Wow, all it took was this
how I make a joker spawn table to SMODS.add_card ?
this line keeps crashing my game if pseudorandom('wildfire') < G.GAME.probabilities.normal / card.ability.extra.enhance_odds then
"attempt to perform arithmetic on field "enhance_odds" (a nil value)"
the error is on line 425
yeah I was gonna suggest hooking, but it wasn't clear what you were trying to do lol
oh weird
but it worked
Sorry haha. I'm the kind of person to find out how to do whatever I wanted, just so I know how I can take full control of the game. Instead, I should just build my mod and tackle things as they come
Now for adding text to the UI 🙃
hmm i cant get one to spawn
maybe some mod breaks it?
G.playing_cards, it's not an area like those tho it's a list
G.deck.cards has the cards remaining in deck
@shut crater You were right...when I sell a consumable i can create a Joker
what's the best way to correct it?
because it's annoying to have to reopen the console
that's all
it might be that one setting
lemme try it
oh that wasnt a reply to you lol
oh, it seemed like something thought it was too
based on their reply
lol
oh i guess not
sorry i'm blind
I just saw all the blyw text not going away but that was dioderent blue text
so yeah my b
yeah
can I specify context.selling_card to be jokers only?
context.card.ability.set == "Joker"
it'll be like context.selling_card and context.card.ability.set == "Joker"?
ye
thanks
hello and sorry for interrupting and wall of text, but i can't comprehend contexts and the docs aren't helping a whole lot. specifically, i want to see the cards that are being played and iterate through them to run a func, before scoring. i haven't been able to do any progress because i can't debug anything:
tried sendTraceMessage(context.scoring_hand) which crashed the game. tostring didn't help a lot and just printed table 0xhexvalues
I think i'm on the right track but it's hard feeling in the dark without proper docs and not a lot of lua experience
thanks for coming to my TEDTalkthe help :>
Try downloading debugplus and using print
But if there's anything particular you want to know about contexts I can help
sure, thanks
get back to you in a bit
What is the best way to create a Joker pool to SMODS.add_card?
So a pool of specific jokers? Is it always the same?
only specific jokers can appear in the smods.add_card
how does one juice a card?
can you elaborate?
card:juice_up()
I have a Joker that when you sell a Joker, it have a chance to create a Italian Brainrot Joker...
ty
if the pool is always the same then you can make a SMODS.ObjectType and call SMODS.add_card{set="objectypekey"}
hey so my unlock isnt working? as in the joker isnt unlocking. for people that weren't here earlier, the joker is supposed to unlock once you beat crimson heart 10 times (i have it set to 1 for testing, but once the run was won no unlock happened?)
it's in the docs
try return true instead of unlock_card
got it
so wait it's because of how it's set up?
cause i used unlock_card on the others and they work
but since the way this unlock works unlock_card wont work?
am i getting it?
oh then no idea never messed too much with unlocks
I suspect you don't want crimsonCount on G.GAME (which only lasts for one run before getting fully reset)
it's a variable that shouldnt ever reset
since it's for an unlock
yeah, G.GAME is reset in Game:start_run() (meaning that variable gets clobbered)
😭
like this?
what should i do instead?
no, the key is for the name of the object type, like Joker or Tarot
G.PROFILES[G.SETTINGS.profile]?
so like this?
yeah, i think so
and them the SMODS.add_card is this?
I don't think this is what objecttype is for? I thought it was for adding entirely new types of objects
not sets of existing ones
but maybe not
it might need a modprefix but i dont remember
it is
aaa I was away sorry
oh hi youre fine 😭
I was just surprised is all, people giving varying advice, ha
can someone help me with shaders and editions and such
it's very chaotic in here
i could always open a thread if it's too much lmfao
Is crimsonCount in the base game? I've never seen it. I am not sure how you would persist a new global variable like that over multiple plays
but yeah, just set it directly on the profile table G.PROFILES[G.settings.profile] or whateverwas stated
it is not
I know all about it
Generally speaking it's for making a set of objects you can pool through using get_current_pool.
It can be used for completely custom ones that aren't consumables, and also a subgroup of already existing ones.
I mean... you just add it to the profile
like they're doing
the profile is just a table and you can inset a new index just by defining it
so that's not the issue
wait am i not doing that already
Maybe try echoing out the value of g.game.crimsonCount, see if it is being preserved. It looks like you're setitng it to nil in one of those snippets you pasted, I'm not sure why you're wanting to do that'
Hellooo, i'm trying to make a joker that converts every hand played into High Card, but i'm a little bit lost as to how to do it ;;
https://discordapp.com/channels/1116389027176787968/1365420874269720630 can u help here so its less noisy lol
wait... isn't it G.PROFILES[whatever].crinsomcount?
putting it in the game state won't work
to be clear: the only thing you actually need to set/check is the value in G.PROFILES[G...].
it saves automatically
though it doesn't write to file automatically, it must in normal gameplay but not in debugging
oh right, I keep forgetting. listen to them
you won't be able to do that through smods alone. You can patch get_poker_hand_info I think
EDIT: are you trying to turn the hand's ranks into something? or make every hand count as the hand type High Card
ok so i have this in my main file right
G.FILE_HANDLER.force = true```
these are the commands to save it to file for debugging purposes, but i think they run wheber a run is exited anyway
so you shouldn't need them in the actual finished code
under functions > misc_functions, there's a function evaluate_poker_hand that decides what poker hand any given hand is. just hook to it and check if the player has your joker, and return high card if so
ohhh okay, i'll try that, thanks
you shouldn't even need that line if you're using the or 0 trick; in fact you might be overwriting the value w/ 0 each time the game's loaded
ohhh ok
How I make SMODS.add_card only add cards from an ObjectType?
wait but im doing that in a game function, and i need it to not be G.GAME... unless that doesnt change anything?
i was gonna ask, is there anything new in steamodded that organises jokers that have variables which change every round, like mail-in rebate, or is it still the vanilla code?
organizes in the collection? or what do you mean
they added a function you define on your mod object I think
try checking docs, I can't recall the name
organizes as in they're not all seperate functions in state_events
it's kind of annoying to reload the game every time when it takes so long but oh well...
how do you destroy a card? is there a specific function for it?
for i, v in ipairs(scoring_hand) do will iterate through all the cards in the scoring hand. v is the pointer to the card, right? that means this is the parameter to pass into the function for destroying cards, i think.
yeah this
So i should use the context before the scoring like this?
if context.before and context.cardarea == G.play then
I'm new in this thing of modding and I'm guiding myself with things like this
wait but doesnt initgameobject use G.GAME? does that mean i should take it out of igo, since it's a profile statistic i want to track?
v:start_dissolve() BUT don't do it during scoring, use context.destroy_card for that
yes, you don't need to set anything in G.GAME. and yes, take it out of igo. sorry I wasn't clear before: just use the profile variable like any other, it'll be saved
contexts are used to decide when jokers trigger. your joker doesn't trigger as such, it just has an effect on scoring, so you don't need a context check
what happens if i do 😟
wait i will try it xdd
it creates ghost cards
and then also replace these (left) with this? (right)
wait like they're in the deck but destroyed?
yeah
schrödinger's King of Hearts
the cheese gote is so back
cheesyjokers is high on my lsst of mods I'm curruntly missing real bad due to not being updated in months
so idk how well it works currently
only months and not a year because elbe is also a gote
ohh okay, thanks, i'll try to do what i can, srry if i'm annoying with my questions hahaha
wait, how do i use it again? is it a function that i pass params onto, or do i call it onto the card object?
you're overthinking things; the profile variable is a variable like any other, and as a bonus, it's saved! just pretend G.GAME doesn't exist
it's a context similar to individual where you can return { remove = true } to remove the card after scoring
does anyone know how to make a consumable that changes a playing card's suit to a different one? i've been trying to make a consumable that changes up to 5 cards to Spades suit like The World tarot
oh so
i'm still kinda lost... 😅 i don't really understand contexts other than gamestate ones
the smods documentation kinda lacking rn
that'd be G.PROFILES[G.SETTINGS.profile].crimsonCount instead
I really should bookmark that and tell it to everyone. you've made a great resource
thank you ❤️ I still need to finish some stuff first but I was planning to see if we could add it to the smods examples
wait you're telling me there's a whole repo for ALL the vanilla jokers translated into smods?!?!?! and i'm here working with nothin!!?!?!?
i'm going in goodbye
cya in an hour 😆
no
it's onlu like 5
i made it this week : )
some cards might be wrong tho i still need to test them more
my mod has 350 jokers of course i can make half of that in a week
alright I'll get it into smods now-
i still need to finish some things like i said
might be useful to pin both smods and vanilla translation cards to the channel tbh, who has the ability to pin messages?
How do I check that a card is of a specific suit again?
only modds, egg is our pinning mod
it can wait until stuff is finished ofc
ok so they do have a method but they didn't incorporate the vanilla jokers into it 😮💨
he might be up for it
card:is_suit("Hearts") for example
but yeah when shit's finished
card:is_suit(suit)
are you gonna fusion dance with bepis once it's ready
why bepis
i want to fuse with aiko
dont tell me you forgot 
speaking of fusion, an entirely different type, i need to work on DeFused
it'll be a bitch for me, a very new coder to port it to 1.0
to be clear: this will alleviate the headaches of countless people which is why I'm putting in a link (with a wip disclaimer) in the smods wiki. Are you ok with being linked?
of course! thank you
I'm probably not doing it myself but I might push other people to contribute the other object types, I'm mostly only comfortable with jokers for now
https://github.com/GayCoonie/DeFused
https://github.com/wingedcatgirl/Fusion-Jokers
Can someone look at this and tell me how much of a bitch it'd be to get the jokers in DeFused that aren't in Fusion to the standards of the current Fusion code base?
anyone know if patches like this can work with other mods that arent smods? if so what does 'SMODS' in the target represent, like what would i replace that with if i wanted to patch another mod
target = '=[SMODS _ "src/utils.lua"]'
target = '=[SMODS Cryptid "path"]' works for cryptid for example
thats how that works?
yeah
ofc, for the jokers in Fusion I'm just gonna use those and re-DeFuse them, because it's quick to do
i think so yes
how can I stop the negative edition from inverting colors? can anyone help with this?
drawsteps? probably
idk though
any takers?
not to do it for me ofc, just to tell me what I'm in for
Just want to say that I had not heard of Fusion Jokers before and I think it's a great idea! And I also like the art I'm seeing in your repo as well Coonie
it isn't mine, it's just other related fusion mods
and me defusing their jokers
the repo's mine I mean, just not the art or even really the code
I just wanted to play with the jokers from fusion mods without having to deal with the fusion mechanic
Wow this page looks great! https://itayfeder.github.io/Fusion-Jokers/
I really regret already using my github.io site
was just gonna say, lol
https://gaycoonie.github.io/DeFused/
I used the template to make one for the DeFused jokers too
you can have one for each repo?
Ohhhh now I had no idea!
Thank's again!
np :3
this is all the content from a very very old version of my modpack
made with @dense jasper 's card exporter
I was wondering how you made it, it is really good looking
which uses a modified dyanmic form of notmario's template
I like how this is the semi-official Mod style
unforutnately the card exporter mod no longer works, so I can't make one for my new modpack
yeah, lol. it's a really good way to make a mod site
We scared off everyone else.
nah, it's chill, lol. the chat always does this
oops
Why is it always you two!
nope, i'm still here just minding my business...
anyways, the thing is WORKING!! as INTENDED!!!! it just lacks the same oomph as castle. here's the problem. the joker destroys cards and upgrades from it. but right now, it upgrades first and then destroys the card which isn't pleasant to look at. instead, it would be better if it upgraded in tandem with the cards being destroyed. I think it has something to do with events but haven't managed to make it work
i feel like i have the blood of this chat in my hands now 😳
is it possible to make jokers or consumables add consumable slots? if so, how?
look at extra credit's forklift
yep, events can do what you want. but it's not a one size fits all solution, you'll need to code a bit
i think i'd like a crash course on events... tried following the documentation to no avail :(
events in the game mostly just run one after another. in Balatro all the scoring math happens before all the animations do because all those calculations were just creating events which run later.
For your case you'll need to know blocking and blockable; if your event is blockable it'll wait until the previous blocking events are all done. You'll need to make one of the events (upgrading or destroying) have blockable = false
Actually you kinda want to start upgrading when the cards get destroyed; you probably want to create an event to upgrade when the cards get destroyed, say
What's the smods thing like change_base but for making something an enhancement?
uh, it's getting complicated. sorry there's not really an easy way to do things
that'd be set_ability (vanilla)
Thank you
yeah, i figured
i'll put it away for now, maybe i'll come back later when i've {E:1,C:edition}improved my skills{}
IT WORKSSSSSSSSSSSS HAHAHAHAHAHAH THANK YOU GUYS 
Hi yall! Might have something to show off soon:3
Hope it's cool!!!
I've gotten buttons working on playing cards, but for some reason, I can't get them working on a specific suit.
Weriddd
I had no idea a booster might pick a locked card!
I'm trying self:is_suit AND card:is_suit, neither work
Do I need to say it needs to equal true?
can i see the code
I'm trying to get the first bow joker in the joker slots to detect when an arrow is used, but firstBow is returning nil. What is wrong?
hmm that looks like it should work
are you sure the key is correct?
Do I use the regular key or card_key?
it should be modprefix_suitkey
so, I'm trying to debug elbe's old exporter, and there's a crash which says that this function from balatro plus is being passed an integer for "args" when it expects a table. I can definitely see why it expects a table, but not sure if it's balatro+ or the card exporter that's doing something wrong
try card.config.center.isBow
okay
here's my whole log from that try
what command could i use to increase the joker slots through the game’s console? i’m not a dev, just messing around
it works! thanks. I'll look into why in a bit
type help in debugplus
or download debugplus if you haven't
when you add a value to the SMODS.Joker directly it adds it to the center, not to the card
if you want it on the card it needs to be in config
Does Lua really not have a native where function!
i mean yea makes sense
sorry if you did and joker slots aren't one of the things built in
is there a way to make the "Sword & Shield" part appear on a second line?
thanks
Could it be an old SMODS bug cuz I have yet to update mine?
no but one of the mods I installed directly lets me execute commands into the game’s console, allowing me to do basically anything
but since i’m not a dev, it’s basically useless
no idea, maybe
Wow, this is an incredible idea
what does where mean?
is that not debugplus?
not normally, you need to patch the code for that or use generate_ui as far as I know
where is a filtering clause
jokers.where(x=> x.unlocked == true)
yeah you just have to iterate
which is how a lua where would work anyway
why does this show "1 in nil"
dang
Wow, I am so used to working in fully developed languages, I imagine lua is one where you'd actually have to implement a sorting algorithm too
I mean you can just make your own where function? as i said it'd just be iteration even if it was in built
did you start a run again after updating the values?
because of how lua tables work
if you modified a variable value, and an instance of the joker / card was already in your inventory, that instance will not be updated. Try giving yourself a new copy of it
it also shows like that in the collection but ill try
nono it’s another mod, but yea i’ll try debugplus
from what I understand at eleast
curious what mod you mean ngl
I'm not saying it's bad, I'm only used to being pampered!
i started a new run and it still shows nil even though i gave it to myself
here's how I do it in my mod if it helps
https://github.com/nh6574/JoyousSpring/blob/40e7f90f4a6b0e8db15fed29f43f08d6b2e34065/src/card_ui.lua#L260
Nope, but. Wouldn't it crash if it was an issue with the key? It's not crashing, it's just not appearing on ANY suit. Which is weird.
entropy, it’s an add-on for cryptid and it adds something called « inversed code cards »
and turns out the inversed « crash » code cards straight up gives you access to a menu where you can type any command, and it’ll input said command into the game’s console
for example : add_joker("j_joker")
would create a normal joker
so i’m curious what else it could do
You did restart the game too, right? You have to do that. DebugPlus only updates art atlases, it doesn't check for card loc var changes
i dont remember how is_suit works but it might just check if it's equals and not if the suit exists
yes i restarted the game
did you save the file? i honestly have no idea looking at the code
oh i was saying it to Dantuch0
i dont know what the issue with yours is either no
oh god. This has happened to me too
yeah i saved the file
ah yeah that's its own thing
Could you be working on a copy in a different directory?
How do I make set_ability actually work, because so far it just crashes for being a nil value
you'd have to ask the dev what the commands are, though they're probably listed somewhere
show me what you're trying?
ohh yea ok i get it
might just be the debugplus console ngl
card:set_ability("m_gold") for example
No, other changes to the mod render
I'm starting to see what my issue was
Maybe you have two copies of this joker in your files? Last man standing wins
any ideas on this?
I'll be right back
M refers to the enhancement?
No, no. I'm adding buttons to a suit, but it's not working for whatever reason
yes
Mkay
I added the buttons normally, but now that theyre restricted to only appear on a specific suit, it's not working
very weird. The same thing would happen if you mistakenly had two items using the same key. Something I did once
if you print(card.base.suit) what does it say
I thought that's what watch was for? like... including for code
I think I might have figured out my problem but I'll know for sure when it's done
Odd question for load_file
Andddd it's still a nil value, I'll write the relevant code
Is there a limit how deep i can have a file?
Like can i have a folder in a folder and then smods can see it?
I bet my code itself is also wrong
path limit is 256 characters for load commands i think
yes for this but idk the limit
might be path name limit on windows or something
the path length being a single byte is interesting
I see. idk why smods is being weird then
does it crash
No it just doesn't load
are you putting the right command to load?
omg, I am just so happy with how this card turned out
I mean the path limit on Windows is by default 256 characters lol
SMODS.load_file(path)()
makes sense
The goat
no that should work
You have to activate him by playing the G.Game.to_do_hand and then he deactivates at the end of the round. I got it to flip sprites too!
G.E_MANAGER:add_event(Event{(trigger = 'after',delay = 0.1, func = function() SMODS.set_ability(G.hand.highlighted[i], 'm_spinnyenh', nil);return true end }))
@quartz ravine shouls make yugi a goat because of the animal theme of the mod
the assert is just so it crashes if it doesn't load it
goat sona yugi when?
this is really weird
It's in the location, so idk
don't "that's not yugi" me btw
Yugi is my only non animal card!
Well...like, one of very few non animals
I don't give a fuck
lol
this was in case it was not yugi technically but whatshisnuts
idk yugioh
do you have an extra config somewhere? idk
haven't watched it since i was like 5
But yeah, I'm adding some mod support/ports and i still have no idea why
well what i said would fix that :P
ok that was the best response ever i somehow missed i had 2 loc_vars
anyone know what could be causing this?
if you add a print to the potassium file does it work
I feel like it's probably rude to ask for help again so fast, but does anyone know what I'm doing wrong here?
What just putting "print("banana")"
yeah
hmm
it's not SMODS.set_ability
oh of course ;-;
is it because i have smods.atlas commands in Potassium.lua?
G.hand.highlighted[i]:set_ability
Thank you
so I haven't modded the game in 5 months and suddenly a bunch of my old inject code is no longer working (SMODS shenanigans). How would I go about making a boss blind destroy cards after scoring (similar to glass, 6th sense, etc.)?
no, i have atlas in mine too and they work
I hope this works
all i did was try to port the enhancement from Potassium
blinds can now have calculate functions so you can use context.destroy_card
oh nice
This time it didn't even give me a crash message ;-;
what does "card" represent in that case? the blind instance?
i think so? i havent used it yet lol
odd, the enhancement doesn't load in the normal one either
time to find out lol
Oops, I just noticed that I forgot to turn this test off
so what does the crash without a crash message usually imply...?
if the game closes then it's usually a stack overflow
trying to make a joker that makes a random joker holo, but I want it to not target jokers that already have an edition (im not sure what to put for it to recognise that the jokers have an edition)
I see
oh i'm an idiot
i put smods.enhancement = {}
instead of SMODS.Enhancement ({})
I think that's my issue
if not v.edition
Nvm! It was Prism messing with something
thx
The last thing it did before that crash thing was spin the card half-way, so I'm not entirely sure, but I think the problem might now be with the spin thing
new calc is great. Works like a charm
Oh come on game
I'm also starting to think my SMODs needs an update
You fixed your 1 in nil error? Awesome!
different person
Almost perfect
Doing a Collection of Consumables based in Epic:The Musical, trying to mix with Arcana Cards art style...did this fits it?
for i=1, #G.hand.highlighted do G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() G.hand.highlighted[i]:set_ability(G.hand.highlighted[i], 'm_spinnyenh', nil);return true end })) end end }
I don't know what, but something here is causing the stack overflow that N mentioned
you have a colon there, so you don't need G.hand.highlighted[i] a 2nd time?
whats the difference between G.STATES.NEW_ROUND and G.STATES.ROUND_EVAL?
You're right
So just take that out?
this looks really nice
It's peak :0
I recommend just searching for wherever what you're looking for is used in vanilla Balatro.
what is the colon in lua? does lit like... keep the same relative place in a table chain or smth?
its very confusing, the state is used sparingly in various weird code sections related to blind disabling and update_hand_played?
a:func() is the same as a.func(a)
it automatically puts the calling table as the first argument. it's for object-oriented call style
yeah I can vaguely understand that
haven't done much with functions yet
only tables themselves with the like... 3 debugplus scripts that make up my lua expereince
is this a duplicate or a taken ownership card?
okay, seems like new_round is a strange transitional state to round_eval/game_over
Duplicate
i wonder how balatro's code was ever was able to work on a daily basis
I got permission from MathisFun to port Potassium to Archived's add-on section
I kinda forgor what Potassium is
it sometimes doesn't. well, we all love to criticize balatro's code in modding-dev
The april fools mod that was "1.1"
I cut the second "G.hand.highlighted[i]" but there's still a problem here, somewhere
ah i see
I was a part of it too
I only just arrived, can you share your full code
I happened to be away at that point, from the community and all that
I guess
not for any reason, just unstable hobbies
the badge is to show what version it's from (and in this case Potassium is literally just one version and done)
Also for authenticity, I decided to use custom colors to match that OF potassium's chips and mult for the added content, but may have something for the full mile, idk
set = "Tarot",
name = "Spinny",
loc_txt ={
name = 'Spinny',
text = {
'Enhances 1 Card to be {C:attention}Spinny{}'
}
},
key = "SpinnyTarot",
pos = { x = 0, y = 0},
cost = 3,
atlas = "Atlas3",
can_use = function(self, card)
return #G.hand.highlighted <= card.ability.extra.max_selected and #G.hand.highlighted > 0
end,
config = {extra = {max_selected = 1}},
loc_vars = function(self, info_queue, card)
if card then
return { vars = { card.ability.extra.max_selected}}
else
return {vars = {0}}
end
end,
use = function(self, card, area, copier)
local used_tarot = card or copier
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function()
play_sound('tarot1')
used_tarot:juice_up(0.3, 0.5)
return true end
}))
for i=1, #G.hand.highlighted do
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() G.hand.highlighted[i]:set_ability('m_spinnyenh', nil);return true end }))
end
end
}```
quick tip, triple ``` opens a code block
This whole process is hurting my brain :(
Oh thanks
I didn't know that
guess i'm gonna do the bump thing
Well, I like it!
hm, it seems ok on first read. what error are you getting?
I didn't see a terminating error, just some warnings. I'm not sure
did you click up in the reply chain?
I posted the function it was having the error on
patch for shaders to update in realtime:
[[patches]]
[patches.pattern]
target = "engine/sprite.lua"
pattern = '''G.SHADERS[_shader or 'dissolve']:send("time",123.33412*(_draw_major.ID/1.14212 or 12.5123152)%3000)'''
position = "at"
payload = '''G.SHADERS[_shader or 'dissolve']:send("time", G.TIMERS.REAL)'''
match_indent = true
here;s the traceback part of the log
I really can't tell what all is wrong because of all the failed lovely patches- but one thing to definitely do is go to that line in balatro plus and see what's going on
I'll check again in a moment
i ltierally did
this
Does anyone know why the second card destroyed here doesn't create a jack/run the code at all?
I'm using the same method as vanilla (Canio)
The last joker it processed was j_jokerhub_forbidden_fruit @brisk rose
Does that joker do anything odd in it's Loc_vars or loc_txt?
In the call chain, it's trying to append {1:ortalab_greyscale, card_type:Joker}, so I am also not sure but it could be something to do with that edition
key = "forbidden_fruit",
config = {
extra = {
x_mult = 1,
scaling = 0.1,
rank = JHUB.pick_new_rank(0)
}
},
rarity = 3,
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.x_mult, card.ability.extra.scaling, localize(card.ability.extra.rank, "ranks")}}
end,
atlas = "atlas_jokers",
pos = { x = 0, y = 0 },
cost = 8,
pools = {
Food = true
},
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = false,
perishable_compat = false,
calculate = function(self, card, context)
if not card.debuff then
--Upgrade/Reset
if context.cardarea == G.jokers and context.before and not (context.individual or context.repetition) and not context.blueprint then
local reset = false
for i = 1, #context.scoring_hand do
local rank_check = false
if next(SMODS.find_card('j_mxms_perspective')) and (card.ability.extra.rank == 6 or card.ability.extra.rank == 9) then
rank_check = (card.ability.extra.rank == 6 or card.ability.extra.rank == 9)
else
rank_check = (context.scoring_hand[i]:get_id() == card.ability.extra.rank)
end
if rank_check and not context.scoring_hand[i].debuff then
reset = true
break
end
end
if reset then
card.ability.extra.x_mult = 1
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
card.T.r = -0.2
card:juice_up(0.3, 0.4)
card.states.drag.is = true
card.children.center.pinch.x = true
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false,
func = function()
G.jokers:remove_card(self)
card:remove()
card = nil
return true; end}))
return true
end
}))
return {
message = localize('k_eaten_ex'),
colour = G.C.RED,
--card = card
}
else
card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.scaling
if next(SMODS.find_mod("Maximus")) then SMODS.calculate_context({scaling_card = true}) end
return {
message = localize('k_upgrade_ex'),
colour = G.C.MULT,
card = card
}
end
end
--Scoring
if context.joker_main and not card.debuff and card.ability.extra.x_mult ~= 1 then
return {
Xmult_mod = card.ability.extra.x_mult,
message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.extra.x_mult } },
card = card,
}
end
--Pick rank
if context.end_of_round and not context.repetition and not context.individual and not context.blueprint and not next(SMODS.find_card("j_mxms_stop_sign")) then
card.ability.extra.rank = JHUB.pick_new_rank(card.ability.extra.rank)
end
end
end
}
here's the full code for that joker
@brisk rose sorry I got lost in the replies.
card.lua:319: attempt to index field 'config' (a nil value)
I have no clue why this is an issue all of a sudden, and it's not even where the thing I'm working on is
could you say again which line it was?
(3) Lua global 'localize' at file 'C:\Users\Adam\AppData\Roaming\Balatro\Mods/balatro-plus/src/bplus\override.lua:165'
Local variables:
args = number: 14
misc_cat = string: "ranks"
(*temporary) = C function: type
(*temporary) = nil
Could be that function is throwing? Maybe try commenting out that one jonkler
the line in question is like the second line of that function i posted
I'm trying to make this work, but the first value isn't changing and the $ is never earned lol, any help?
I DM'd you btw @brisk rose
I'm a slight bit of a noob here lol
here's how I tried to do this
knowing me, it's probably a spelling error lmao
I think I'm going to bow out. apologies
too tired
It also says there is set_ability at this line which I don't believe there is
no worrie's it's a bit of a clusterfuck anyway. lotta moving parts
for now I think I'm gonna try spriting this thing lol
while I wait for a response
I can't understand why it would say there's a problem in a place there very much isn't, but for some reason it seems to think there is :(
Try capitalizing diamonds to Diamonds and spades to Spades?
is it the capitalization of the suits
thank you lol, hehe, it's always a spelling error w me lol
Yw!
nvm, I had to add an S
Hi everyone, sorry to ask but is there a mod creation FAQ or setup guide anyone could point me to?
I'm not sure how to find out the Lovely edits I need to do for the desired outcomes
Oh thank you!
accidentally made "flashbanged joker" instead of "brown joker" lmao
still trying to figure out what's wrong here, any ideas?
What is not working as expected?
this
https://github.com/Mills-44/FusionCookbook/releases/tag/V1
new drop with more stuff and fixed bugs 🙌
.....huh
I took ownership of Luchador in order to redo the condition for its badge and... it doesn't prevent the default badge from appearing...?
Are you using the same Info queue object or whatever it uses?
Yeah
Went the same name?
Like as long as all the variables you're using are named the same it should overwrite it
Afaik
Since it's a vanilla item, it doesn't have a loc_vars function by default. Instead, its loc_vars are determined in Card:generate_UIBox_ability_table()
But it's...weird to me then that it wouldn't prevent vanilla changes to the description nodes since the modded loc_vars supports doing those itself
oh these are gonna be a BITCH
Can't you blank out that function for the card? Prolly boy I'm really new to this but that'd be my intuition
Does it? I think there's a way to do it in set_abikity or something
Okay no, it should ignore the default one.... which is why it makes this really odd
Wow that seems pretty strong
But maybe that's just cause I'm coming off of a roffle blue seal video
Maybe lmao
?
oh, where was that
oh
crap
i think thats the only place i never checked, for some reason 😭
thanks
im sorry little one
with take_ownership() do i have to do anything to specify what file im taking ownership from? or do i just put the key in the brackets like its in the same file
No, you just put the key.
🫡 thanks
Is the image aligned to the top left of the "card" on the atlas?
You're changing both pixel and display size.
im not supposed to do that?
Using only pixel_size myself.
:3 i looked into pixel joker's code from morefluff and saw it using both, so i assumed i needed both of them
thanks guys
how would i make this only count all cards as non face cards when the joker is there, currently it always is non-face cards
Wrap the SMODS.find_card call in a next() wrapper
There is no return true condition
Also you need a mod prefix in the joker key
so i put the mod name _prosopagnosia?
j_modprefix_jokerkey
should i use caps for modprefix
You should put it how you typed it
Not unless it is in caps.
Does your prefix have caps?
Then yes
Or rather you need to return the original function call after your condition
That looks right
j_prefix_j_?
But you still didn’t wrap the find_card call in a next() wrapper
Oh true
Remove the 2nd j_
I mean... change that now before you bake it in too much?
k
That’ll get annoying in the future but you do you lol
You should define the joker with its shorthand
The game auto puts the class and mod prefixes
The game in this cause being smods
Unless you predefined it, or set it not to. But don't do that unless realllyyy neddessary
:P
Yes
crashing due to an unexpected symbol near 'if' on line 19, im pretty sure this is syntactically correct?
steamodded is my favorite video game
fr though it does become part of the game by being injected by lovely
and i'm being an ass
Firstly, that wouldn't do anything if it did work.
That’s not how take_ownership works lol
If statement in a table
ive got this other function that seems to do that just fine
is it the calculate that makes the difference?
That's an if statement in a function
You define the calculate value of the table as a function
an if statement in a function in a table
And then have the if inside that function
ah i see
I also don't think even if you could find where that table is stored in memoey, editing it directly would do anything
but i may be mistaken
im a little bit just making this up as i go along and hoping it works 
G.P_CENTERS
And it does
that table being the enhancements original decleation,
m_glass?
ah fair
I've iterated over pcenters, and got custom code running on every joker like that
line 651 of game.lua 
That's valid
take_ownership('glass' is mentioned there.
not m_glass.
That's also the one specified to be working
"ive got this other function that seems to do that just fine" @daring fern
if you're editing the table in centers, what is take ownership even doing?
i don't see the point to be doing both?
Are you trying to say that taking ownership with a prefix doesn't work?
im not really sure 
I'm saying that the code being commented on supposedly works, and you seem confused at that
the other function that does work was made for me so i dont entierly understand it
oh i get it, it's justto put the code on the object
i think they just like to 🤔 react to everything
which is a place it makes sense to be ig
I'm on about the❓️ reactions
and the same 
though wouldn't it make more sense just to be on the joker object?
when the actual modifications to glass aren't treating it as a smods object?
this still makes everything non-face cards even without the joker being present
What outcome are you trying to achieve with this
Wrap it in next()
im trying to change the xmult that glass cards give
Bruh
Lols
ill annotate the code rq to try to explain my reasoning
btw even if you are editing the center table directly, you don't have to redefine every value
just the one you're changing
Oh then setting the value like gc says should work
i assumed that take_ownership was entirely replacing the thing i was taking ownership of
Take ownership is like changing a specific function of a vanilla feature
the more things i try to do the more things i realise i dont understand
But not everything about it
this?
Yea
which is what im trying to do 
Yea
you could define it in the normal cmods config table
i think
i dont think i know what that is 
well now it considers them face cards even though i have the joker
like how jokers and other smods objects have a config: {} parameter
ah
Show your mod.json or header
Shouldn't be no
so itd be someting like config = "glass.config.Xmult=1.5"?
use a json metadata file instead, it's just as easy to make and more modern
that but with actually correct syntax
Your prefix is xmpl not Exipnos.
it'd be like
SMODS.take_ownership(m_glass)
{Config = {Xmult = }
}
but with the correct syntax
Xmpl for example
:P
🫡
Change it first, im pretty sure that's the example one
btw, whats the difference between SMODS.take_ownership() and SMODS.Enhancement:take_ownership()
Thought I'd change the blue to red for classic villains >:3
YO
i really like these
The first one is the general one, it takes a prefixed key, the second one is just for enhancements and doesn’t need the prefix
and so many more to come
gotta add some tarots and spectrals for some of them to work as intended tho
y'know i don't think I actually like take_ownership for this
Oh dog the moment Jokers are going to be crazy to make
you said you want to change the xmult of glass cards when you have that specific joker, right?
yeah
to reiterate im just kinda guessing on how to implement everything
so if theres a better way do tell
I'd just something like this in your joker's add_to_deck:
G.P_CENTERS.m_glass.xmult = [value you want]
and change it back in the remove_from_deck
also there may be another layer between P_CENTERS and m_glass
idk
minor issue with that
i plan to have a second joker that sets that value to another different value
and if you have voth of them?
the jokers are "glass cards give less xmult but dont shatter" and "glass cards give more xmult but always shatter"
so with both itd probably be "glass cards give more xmult but dont shatter"
that's very solvable, lemme think of it for a second, do you have the shattering thing figured out?
only the dont shatter one is implemented at the moment but its functional yeah
ok, are there any examples of adding a planet card?
the heirophant?
no, I mean a new planet card
okay then that shouldn't complicate beyond what i'm gonna say
so, let the joker that increases the mult but they always shatter be joker 1 and the other be joker 2
Instead of putting this in the add_to_deck, it can be in the calculate function, You can do what I said there instead, and nothing else would need to be done there. Keep the setting it back in the remove_from_deck. Set it to only do the always breaking glass cards if joker 2 isn't present
For joker 2, set it to only change the xmult if joker 1 isn't present, also do this in the calculate function. And in the remove_from_deck, set it to be normal unless joker1 is present, the same way
@burnt cairn sorry had to edit it a few times
If they're deleted simeltanously this should still work? because there's no way it's literally simaltanious
but definitely test that
im not sure i follow
okay, I was wrong about calculate, it should actually happen in update
limme type out a quick, probably malformed example
i have a mental model of the logic of implementing it thats not much of an issue
i just have no idea of the lua / smods syntax
like the always shatter joker sets the chances to 1 in 1 and the never shatter joker removes the shatter check outright
the never shatter joker sets the xmult to 1.5 and the always shatter joker overrides the xmult with a 3
the removing the shatter check is already implemented
{
key = 'joker1',
update = function(self, card, dt)
G.P_CENTERS.m_glass_xmult = [new value]
end,
remove_from_deck = function(self, card, from_debuff
if not SMODS.find_card('j_joker2' then)
G.P_CENTERS.m_glass_xmult = [original value]
end
end
}```
.
🫡
Why is that in an update
I couldn't figure out the best place to put it besides that due to the interaction between the 2 jokers
joker 2 will only change the xmult if joker 1 isn't present
so i have symetrical design at mind i guess
and i didn't want it to only happen when blinds started
and that's the most general contezxt there seems to be
I don't like the take_ownership approach as much because it might interfere with other mods
but it's Bev's joker not mine
so they can do as they want
i know how i want to do it
i just, dont know how to implement it
there's a million ways
i dont care about mod interference i dont plan on releasing this
but like.. what is your logic you're after
then give your logical flow and someone can help translate it to lua
and i dont know enough about smods for any of them 🫶
random question, im new to balatro modding (was more focused on doing the card art for it up until this point) and was wondering if its possible to make a custom rarity that has an effect on all jokers of that rarity, or if id have to manually implement the effect in the code of each joker
_ _
I mean... yeah this is compatible with that
but so is taking ownership of g;ass, though if you even play other mods that might touch glass, even if you don't release this, it might be a pain, but that's just my priorities
the thing is... idk how to rewrite the calculate function for glass
this I know how to do, lol
so what ive got is
SMODS.Enhancement:take_ownership('m_glass', { SMODS.take_ownership(m_glass) m_glass = {max = 500, order = 5, name = "Glass Card", set = "Enhanced", pos = {x=5,y=1}, effect = "Glass Card", label = "Glass Card", config = {Xmult = 1.5, extra = 4}}, })
im just after the syntactically correct way of implementing this
it's the function you'd need to change
not the values in G.P_CENTER
to do it that way
i mainly just want to have a gros michel-like destroy function for that rarity
does that need to be its own rarity
it could just be like a sort-of-category-but-not-really like food jokers
i mean i dont wanna clog up the descriptions of the jokers
theyre already conditional as is
fair
what eremel wants you to do is this
{
calculate = function(self, card, context)
write shit here
end
}
🫡 sweet
but you'd have to figure out, from the perspective of the glass card, how to do all of this
which i don't know
and what context to use
ive got half an idea
ive been looking around all the glass functions and shit ill get there
Idk who that is but I like the art
cooking, baking, grilling and barbecueing
hi anyone know how to localize with different language a mod, i know that is with a localize folder but it doesnt work
am i missing something
SMODS.Enhancement:take_ownership('m_glass',
{
config = {Xmult = 1.5, extra = 4}
},
true
)
```?
So your mod badge doesn't show on glass cards.
ah
the mod badge is the thing that appears when you hover things that say the name of the mod right
Yes.
Something like this:
yeah
its working 🫡 thank you
apparently i saved the 2x image file without upscaling it 🦭
smol jokers...
Tiny jokers
if you have debugplus then everything will be printed into the console of the game
print("print")
yeah but like it doesnt show up in console or anythin
wait
is it just not going
😭
istg
its going
NVM IM JUST STUPID
BROOOO IM LOSING IT
DHASUFKADSULFHASDOFJADSUOFDJSA

if context.before and context.cardarea == G.play then
TS IS NOT LIKE
GOING
apparently it is never context.before and context.cardarea == G.play
calculate = function(self, card, context)
if context.before and context.cardarea == G.play then
print("TungTungTungSahur")
local enhancement_types = {"glass", "steel", "stone", "gold", "lucky"}
for i = 1, #scoring_hand do
local played_card = scoring_hand[i]
-- Choose random enhancement
local random_enhancement = pseudorandom_element(enhancement_types)
played_card:set_ability(random_enhancement, nil, true)
-- Choose random seal
local seal_roll = pseudorandom()
if seal_roll > 0.75 then
played_card:set_seal('Red', true)
elseif seal_roll > 0.5 then
played_card:set_seal('Blue', true)
elseif seal_roll > 0.25 then
played_card:set_seal('Gold', true)
else
played_card:set_seal('Purple', true)
end
end
end
end
It does happen but only for enhancements.
wa
SMODS idiot check extension for vs code when? /j
its not printing tungtungtungsahur :((((((((
What type of object is this and what is the goal?
its a joker, trying to work like Midas Mask
give random enhancement and seal
but the context is never goin
Remove the context.cardarea check.
OK
PROGRESS I GOT AN ERROR INSTEAD LETS GOOOOOOOOOO
ok but i thought that scoring_hand was the hand
hmm
whats the played hand called chat
context.scoring_hand
Lua: the land where everything is a table in another table
sry im dumb whats the dump
/mods/lovely/dump
It's where the pre patched code lives
ok
Well it's where lovely puts the code after patching it I mean
That's what the logs refer to
Np :3
Hmmm
:3
Show code
calculate = function(self, card, context)
if context.before then
print("TungTungTungSahur")
local enhancement_types = {"glass", "steel", "stone", "gold", "lucky"}
scoring_hand = context.scoring_hand
for i = 1, #scoring_hand do
local played_card = scoring_hand[i]
-- Choose random enhancement
local random_enhancement = pseudorandom_element(enhancement_types)
played_card:set_ability(random_enhancement, nil, true)
-- Choose random seal
local seal_roll = pseudorandom()
if seal_roll > 0.75 then
played_card:set_seal('Red', true)
elseif seal_roll > 0.5 then
played_card:set_seal('Blue', true)
elseif seal_roll > 0.25 then
played_card:set_seal('Gold', true)
else
played_card:set_seal('Purple', true)
end
end
end
end
Your keys are wrong, they need prefixes
You need to add m_ to all strings in the table.
ts...
Wait
...wouldn't SMODS.poll_seal be easier?
Why are the enhancements hard coded
...this is a thing?
im gonna lose it bro
where are you guys getting ts
Why is any of this hard coded? All it does is limit it to vanilla stuff
The documentation?
I just randomly came across it whilst searching through code... I used in booster pack generation of playing cards as local _seal = SMODS.poll_seal({mod = 10})
And there's already a table with / all/ the enhancements
gah
Ooh enhancements can be polled too
Nice
The reason to poll and not pick randomly from the table that has all them is if they're not pollable there's a reason
I don't think enhancements have weights though
It also respects weights and pool checks
If not defined, weight is 5.
Yeah the pool is mostly what I meant by reason
i cant find ts in the docs
Ah they do have weights. Didn't know
It’s on the utility page
is ts not the docs
It is
Yeah there's a lot of stuff :3
:3
Hehe its punctuation for me ngl
real
without type ~= string, this crashes when playing cards face-down. how can i fix it?
Use hand_chips and mult instead
G.GAME.current_round.hand_chips?
realised it was applying universally instead of with the joker. tried to fix that and now the joker is back to not changing the xmult to begin with
Just the values I posted
Yup
wow, that easy
also, i have a joker that retriggers other jokers and context.final_scoring_step seems to be not retriggerable. how can i fix that?
am i missing commas somewhere i feel like thats the issue
It’s because you don’t return anything so the logic doesn’t know your joker has triggered
You need to write it as you would write any other calculation, you don’t need to do anything with the config
if i remove the whole calculate and if thing it works completely as intended
except its universal and not tied to the joker
so it shouldnt break just because i put it in an if statement should it?
That’s because you’re doing two entirely different things and trying to compare them
this pops up only some of the time and the seals dont ever even show up
what is next() doing here? I thought that was to find the joker to the right of the joker you are
calculate = function(self, card, context)
if context.before then
print("TungTungTungSahur")
scoring_hand = context.scoring_hand
for i = 1, #scoring_hand do
local played_card = scoring_hand[i]
played_card:set_seal(SMODS.poll_seal(stdseal,1,true), nil, true)
played_card:set_ability(SMODS.poll_enhancement(std_enhance,1,true), nil, true)
end
end
end
oops.
stdseal and std_enhance should be a string.
or am I just reading too much into the name and that's just how find_joker workds?
fak