#💻・modding-dev
1 messages · Page 197 of 1
does something happen when you play a hand?
anemo, geo, and dendro characters will have synergy with all (or in dendro's case, all but cryo) suits
yeah i'm making a genshin mod :3
I'm driving myself insane trying to figure out how to implement a specific boss blind effect
lol, yeah, it gives me the money of the vale of my hand
i see now
you have to change joker_main for selling_self
i hate to bug again but could someone please help me parse this crash report
is there a funtion to see if the card is sold
cryo is spades, hydro is clubs, pyro is hearts and diamonds are just electro by process of elimination?
Essentially, when you play a hand it will score as the played hand, and remove the cards you select to play as normal. But it will score as if you had played the remaining cards, and the cards that you played will act as if they were the ones left in your hand
that was the thought process, mostly - i figured electro for diamonds would at least make sense because keqing's lightning stiletto is kinda shaped like a diamond, and she was the first electro main dps
for the record i'm planning to add a skin that at least recolors the main deck to have sensible colors xD
I was thinking that too
it works!
Would you make art for the face cards and aces
but, it still gives me a buck
someone else would have to make it. i am not an artist 
let me see if i cant set the sell value to 0 by defalt
I think this would be necessary lol
yeah absolutely
fair enough
the game does not like me screwing around with cardareas though
my initial idea is to patch what smods does to the area calculations and change the hand area for the play area and vice versa
idk how easy that is
I'll keep that in mind as an option
rarity = 4,
atlas = 'century_egg',
pos = {x = 0, y = 0},
sell_value = 0,
config = {
{extra = 100}
},
loc_vars = function(self,info_queue,center)
return {vars = center.ability.extra}
end,
calculate = function(self,card,context)
if context.selling_self then
ease_dollars(math.max(0,math.min(G.GAME.dollars, 100)), true)
return {
card = card,
color = G.C.MONEY
}
end
end
}
``` this shouldn't work erase is not even typed properly
lol
I might be able to create a temporary holder cardarea, and transfer the cards there as a holding place while I shuffle them around? We shall see
and while this sells double of what money i have, it still adds 1 extra buck
how would i get around that?
no idea if this will work but what if you do card.sell_cost = 0 after ease_dollars
if not then you might need to hook card:set_cost
it crashes is i correct my spelling mistake
wack
ill try what you suggested
it works
i also got rid of erase_money entirely
and just did this card.sell_cost = math.max(0,math.min(G.GAME.dollars, 100))
for some reason i thought that it was card.sell_value
so it did not work when i tried it
lol
now i got to make the sell value show the amount before you click it
thank you for your help!
if you change the sell_cost in add_to_deck instead of calculate it should do it but it's gonna get overwritten by card:set_cost so a hook might be the only solution
"ease" is an actual word meaning "gradually change", ease_dollars changes your dollars by the specify amount, it wasn't supposed to be "erase"
im dyslexic so when i compared the source code i thought it originaly said erase
lmao
lol
to be fair the source code does have some misspelled stuff too like consumeables so it's a fair assumption
I think this might be my easiest course of action
Is there a way to add a mult bonus for the next hand? From a consumable?
holy shit unstable dev we have an insane mutual server and friend
extremely unexpected
how would i make that hook
?
My immediate thought would be:
Consumeable spawns a tag -> The tag triggers at the next hand, which adds mult bonus.
This is how I make one of my jokers that, after you sell it, disables three following boss blinds.
i tried ```local old_set_cost = Card.set_cost
function Card:set_cost(...)
old_set_cost(self, ...) -- Call the original set_cost method
if self.ability and self.ability.name == 'Century Egg' then
self.sell_cost = math.max(0, math.min(G.GAME.dollars * 2, 100))
end
end
did not work
can you print self.ability.name just before the if
I'm trying to find how a tag would trigger during scoring, but I can't find the specifics. Is there a link to your version so I can see a working example?
here right?
local old_set_cost = Card.set_cost
function Card:set_cost(...)
old_set_cost(self, ...) -- Call the original set_cost method
if self.ability and self.ability.name == 'Century Egg' then
print("Updating sell_cost for Century Egg:", G.GAME.dollars)
self.sell_cost = math.max(0, math.min(G.GAME.dollars * 2, 100))
end
end
is there no documentation on deck making with smods
oh my god I just noticed, yeah that's insane lol
no, before the if
I'm pretty sure self.ability.name works differently for modded jokers but not 100%
i agree
Do we need to talk about which side is before and which one is after? (genuine question)
chill out my guy, i typed it wrong
anyway ^mult in steamodded when
no need for snark, I think they just misunderstood why I was asking
Updating sell_cost for Century Egg: 4
can you specifically print(self.ability.name)
wouldn't that just print the name?
yeah
I take it back, there are way too many things I'd need to patch and figure out for this
this actually sucks to implement
lol
it seems like an interesting effect I'll check out if I can do it tomorrow when I'm on my PC
I pray my best bet is to figure out how to swap the cards in the cardarea, and I'm just too tired right now to figure out how to do it properly
yes btw
given enough time I'm sure I can figure out, but sometimes it feels good to complain about things
you got a syntax error
so where else is it supposed to go then?
LAME
function Card:set_cost(...)
old_set_cost(self, ...) -- Call the original set_cost method
if self.ability and self.ability.name == 'j_nscabm_century_egg' then
-- Update sell_cost dynamically
self.sell_cost = math.max(0, math.min(G.GAME.dollars, 100))
end
end
-- Hook into G.modify_money to update sell_cost when money changes
local old_modify_money = G.modify_money
function G.modify_money(amount)
old_modify_money(amount) -- Call the original modify_money method
-- Update sell_cost for all Century Egg cards
for _, card in ipairs(G.playing_cards) do
if card.ability and card.ability.name == 'j_nscabm_century_egg' then
card:set_cost() -- Force update the sell_cost
end
end
end
this works now at least, Nomad_00 — Today at 11:33 PM
looks like trash though
welp lol
G.modify_money does not exist
i know right?
can you send the entire thing
AI just doesn't help with balatro specific questions
at most it will help you with lua stuff
i lied
You have a couple syntax errors near original_sheet = true
You have an extra } and ,
And orignal_sheet is outside the table
If you remove the }, above original_sheet = true line you should be fine
well I'll be
this probably breaks something and it doesn't make your played hand act as your remaining hand but it's half of what you want if I understood correctly
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "-- TARGET: adding to hand effects"
position = 'before'
match_indent = true
payload = '''
final_scoring_hand = G.hand.cards
'''
obviously that needs a check for your blind
IT WORKED THANK YOU 
thank you though! I really appreciate it
now i need to sleep zzzzz
oh and it doesn't evaluate the poker hand you might need to patch evaluate_play a bit earlier for that
Yeah, Back is a deck from what I understand (not messed about with it)
That is correct
someones using ai lets all point and laugh and shame them
I think the reason they're called "Backs" is cuz they're the back of the cards
ok i fixed i got rid of all the unnecessary code
function Card:update(...)
old_card_update(self, ...)
if self.ability and self.ability.name == 'j_nscabm_century_egg' then
self.sell_cost = math.max(0, math.min(G.GAME.dollars, 100))
end
end```
voilà
does ... actually work in lua
man AI actuly does suck
yes
clearly this isn't the way to debuff a blind that increases the base chip score, because it just crashes. The Wall has lied to me...
self.chips = self.chips/3
self.chip_text = number_format(self.chips)
return```
i saw what it was trying to do then did it myself
I think perhaps 1am is too late for me to be coding
samsies
might be talisman jank
i am always going to blame talisman for math not working
talisman?
this is just telling me that the field 'chips' is nil, so clearly I'm supposed to be accessing a different field but I'm too tired to sort it out rn so that's tomorrow me's problem
real
What are some mods to play with friends (multiplayer wise)
idk if it works with the multiplayer stuff but play my mod
what is it
shameless self-promotion for the win 🙏
theres like 50 jokers and almost 100 consumables
little dog, big dog, little cat, big cat, skeet, castle, blaze
What kinda hands are those
hands
Shit fair enough
oh yea and nice and twice nice
All i know is if I'm at a poker table and someone pulls out a tiger yea ill fuckin fold
extremely loud incorrect buzzer
Little cat is 1 ** ** ** ** ** ** ** ** ** ** ** ** ** ** card
feel like im doing something wrong
Big cat is 5 ** ** ** ** ** ** ** ** ** ** ** ** ** ** cards
Skeet is scram
Castle is 1 king 1 queen 3 jacks
Blaze is 5 ** ** ** ** ** ** ** ** ** ** ** ** ** ** cards
i've been having a lot of trouble with getting the game to find consumables of a specific type in my hand - i looked through here and apparently SMODS.find_card() is supposed to return a table, but attempting to get the length of the local var i assigned to it crashed balatro
i've tried several different implementations to no avail - this is just about the simplest i've gotten to it, all i really need is a way to reference specific consumables and have them send a message within the scope of a joker's calculate function
-- primary scoring mechanics
if context.cardarea == G.play and context.repetition and
not context.repetition_only and context.scoring_name ~= 'High Card' then
if context.other_card == context.scoring_hand[1] then
local SkillCards = next(SMODS.find_card('c_Impact_KQSkill'))
if #SkillCards > 0 then
for i = 1, #SkillCards, 1 do
card.ability.extra.repetitions = card.ability.extra
.repetitions + 1
SMODS.calculate_effect(card, {
message = "Again!",
colour = G.C.PURPLE,
card = SkillCards[i]
})
end
end
return {
message = "Don't Blink!",
colour = G.C.PURPLE,
repetitions = card.ability.extra.repetitions,
card = card
}
end
...
#nil =
Error
the next is checking if the table is populated or not and returning a boolean. SkillCards is acting as that boolean, not the table
im so confused 
I'm not familiar with localization stuff, wish I could help
I needed G.GAME.blind.chips...
well, it no longer crashes, but it:
- doubles the amount of repetitions expected; only 2 of these cards are in the deck, but it adds 4 retriggers
- completely skips the calculate_effect message
Can you show what you have now?
the first thing is weird but easy, just assign local var that's #SkillCards / 2
it is the exact same block as above but without the next() wrapper
i found it im just a dumb ass
Making mistakes is just a natural part of learning, don't worry about it
WRONG!!!!!!!! if you make a mistake you should be EXECUTED!!!!!!!!!!!!!!!!! 💀 💀 💀 💀 💀
Alright so what I think might help would be to use a local variable in calculate to track number or retriggers as opposed to a config variable since that persists
tbf relative to the message being completely skipped that's a fairly minor issue
and on the subject of making mistakes I've been trying ot figure out how to change the back sprite of a specific joker when flipped (for a single easter egg!!!!) and everything I've tried hasn't worked. Currently been trying a lovely patch but honestly I feel like I'm way in over my head.
version = "1.0.0"
priority = 0
[[patches]]
[patches.regex]
target = "card.lua"
pattern = 'self\.children\.back = Sprite.*'
position = 'before'
payload = '''
if _center.name == 'Okina Matara' then
self.children.back = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS["FinalBosses"], { x = 7, y = 2 })
self.children.back.states.hover = self.states.hover
self.children.back.states.click = self.states.click
self.children.back.states.drag = self.states.drag
self.children.back.states.collide.can = false
self.children.back:set_role({major = self, role_type = 'Glued', draw_major = self})
return
end
'''
match_indent = true```
this
Ah I see
i've got no idea what's up with the Again! message just not doing anything at all
blaze is five fces
castle is three faces and a pair
skeet is 2-5-9 with no pairs
i'd expect it to crash at least
speaking of custom joker backs, we are in desperate need of one for stencil...
i know it was the most obvious thing tho lol
Oh you know what, I think the card table comes after the content table, not before
oh my god touhou mod??
A final bosses mod, but yeah, I want to give Okina Matara a back door!
that's fucking sick
It does have 1 implemented and 1 planned joker right now
too bad it's final bosses only, i'd love to see reisen 
So it should be SMODS.calculate_effect({message = "Again!", colour = G.C.PURPLE, card = SkillCards[i]}, card)
fingers crossed
well it did sort of do something, though it's incredibly strange
oh?
That's kinda why I recommended this to handle repetitions lmao
you know what i think it's because i'm adding to the card ability
Are you forgetting to reset the card ability and it just keeps adding up?
yeah you're right that completely flew over my head. i thought the config var was temp for some reason 
lmfaooooo
i'll patch that and record what's going on
Yeah no that persists unless you explicitly reset it
What is the new calc's lowest version number?
I need that for listing dependency.
ALPLA-14??b or something
Just so you're tracking:
It looks like tags only triggers at the blind selection, so it can't be added mid round and have effects.
I'm currently looking into creating a temporary voucher that will vaporize after giving the bonuses, because vouchers are processed at the same time as jokers
Counter point: coupon tag, and edition tags.
That's fair. Wasn't clear about what I meant.
There's no triggers between blind selection and end of round cashout
Show me your code.
I don't have any. I've been dragging through the possible ways to trigger tags, and all the Tag:apply_to_run triggers are extremely limited and none happen during SMODS.calculate_context
Wouldn't be too hard to make a Debug Tag that prints out any triggers, but vouchers will definitely work, so I'm going that route
hey i downloded a mod took forever to get to work but now whenever i hit the first shop mods or no it crashes
You'll have to specify which mod.
Also you'll need to provide the crash log.
sorry took a sec to get the photo
Got a confirmation that vouchers can affect scoring.
Tossed this into my SMODS.Voucher(table) definitions:
calculate = function(self, card, context)
print("DEBUG PRINT: ")
for k,v in pairs(context) do
print("context [ "..k.." ]", type(v) =="table" and "table" or v)
end
end,
And got triggers for before, after, and everything in between
Is Balustro the only mod?
Yea a month ago ish voucher calc was added to SMODS.
Like proper voucher calc
Yeah, it's looking like vouchers can have joker-style effects
Smods and lovely is like, the base of most mods.
Try only have these two to see if it works, and then proceed from there.
I'm using it for a consumable that gives "+10 Mult to next hand"
post the whole crash
this the rest
It sounds like the smods lovely patches aren't getting applied. Make sure that your Mods folder is setup properly.
It should be Mods/smods/lovely.toml
wait lovly in smods?
Lovely is the base modding tool. SMODS is built on top of it to be a better modding toolkit
and i build on smods to make the most batshit insane shit
More of a consume it and get the slot back, and sometime in the future, get the effect
Tags don't have the calculation triggers unfortunately
then make them have them
Would have to add it in myself, and meh. Would rather use a builtin tool
Have you test that yourself...?
Since earlier you said you didn't code it as a tag.
tags arent cards
lovely.toml?
Not yet, but if they do, then they're magical. No code links to the tags during calculate_context calls
smods uses a lovely folder
I'll check tomorrow with a debug tag, but I'm probably going to create a tag to "show" the effect to the player, but hide the calculations behind a voucher
is there a way to make game.lua to agree with pairs?
It’s not game.lua that’s the problem. There’s a variable somewhere that’s passing in “nil” to a pairs() wrapper and that’s what’s causing your crash. What it is I don’t know
#1209564621644505158 message i wonder
also is it soppost to replay the same seed every lunch>
i get the smae hand and discard everytime
it says nosave_shop is nil should i have plad balatro before getting a mod?
OMG that was the issue i never did a run of regular balatro
thanks @sturdy compass for the idea to check for nil
👌
this is kinda fucked up
if I have it modify config.repetitions for the duration of the round and then attempt to reset it to 1 in joker_main or final_scoring_step, it just... doesn't do anything at all? which is like, incredibly strange
but if I assign local i guess i could reorder events to calculate n independently of the initial retrigger scheme but that's slightly annoying, let's give it a shot thoughn to 1 at the very beginning of calculate, there's no way to have that value persist across different context runs as far as I can tell?
yep, that's all i needed to do xD
fantastic, now it's fully operational, i'll show it off shortly
keqing now successfully creates two Lightning Stilettos (desc needs to be updated), and these stilettos successfully add 1 to her retriggers each
these are independent of blueprint/brainstorm for now as to not be too terribly broken, but i think perhaps i will change that?
I see the interesting thing happening with the messages now lol
oh no it was way worse before

it was just because i had two entirely different cards defined in calculate_effect, i.e. one was sending the message, the other was shaking
(i am a big dumb idiot)
right now it's actually working as intended consistently across rounds!
Huuuuuge
how would i disbale a hand?
in a blind?
and more precisely the most played one
by a joker
is there any particular way to dynamically check how many times a joker is being copied before scoring -- i.e. without iterating through each context check
With how Blueprint-like cards handle copying, I would guess no
that's a damn shame
https://github.com/BarrierTrio/Cardsauce/blob/main/jokers/werewolves.lua#L37 this is an example of a joker disabling a hand
determining the most played i don't know offhand but i bet you can find it in the vanilla ox code
Yup yup
yeah, it's the blueprint-like joker again. for whatever reason, after adding repetitions, those work just fine! ...but now, the tripled copy isn't working at all for non-retrigger jokers. (at first, it was also just straight up crashing if it didn't find retriggers because of a > 0 instead of a ~= nil which, uh, obvious fix. ;P
what're we missing here? the error itself seems to be the for loop itself (as it's only running once, not until the amount specified in card.ability.extra.funk), but heck if we know what the exact syntax is supposed to be in this case. it's just over 3:30 AM here, leave us alone... ;P
extra retriggers are now functional for copies of keqing, but blueprint/brainstorm will not allow you to gain extra retriggers from lightning stilettos
i also made it a bit less jank, "+1 Retrigger" shows up below each stiletto but juices up the card that's receiving the retrigger
for my first joker this has been weirdly complex but it has been very fun
Honestly going super complex for your first isn’t the worst cuz you learn a lot out of it that make the simpler ones that much easier
that's how i do pretty much everything when i learn something new
i start big, frustrate myself to no end, and thank myself months later
thanks!!
My first joker was the Fortune Cookie which has a decaying chance roll and spawns a random tarot card, so I got a lot of valuable experience of out that one
just a question, how do you do those?
I haven’t seen any other mod do anything with decaying odds so it was cool to work with
This is a part of my mod’s wiki page
oh ok makes sense
I'm doing the opposite :D
Jenga lmao
out of curiosity, how did you store the odds
It’s just held in the ability
it's because it's a tower that you stack with mult, but the more you stack, the more likely it is to collapse and reset to 4 mult
I take it this doesn’t work with Oops? Lmao
i dont understand the code i am way too stupid
it does work with oops, just negatively
Lmfao
if you want to double the chance that Jenga resets, be my guest
That’s devious
Instead of slowly pulling out a block you’re pulling one of those crazy karate chops that sometimes work lmfaooo
shaking the tower to get the block out
Goofy as hell
umm someone is playing jenga with paper and glue blocks
i liken Jenga to Misprint because both can be reliable mult, but can also completely screw you over
That reads
Anyways I finally reworked a card that needed reworking for awhile. I teased this in the Maximus server but never showed it off here
defaced joker my beloved 💖
i am scared now
You shouldn’t be tbh
in a good way i mean
Huh
how good is it gonna be????
Quite
Gotta make living with a Jimbo and this extra card for 3 rounds worthwhile
Not to mention you need Jimbo in hand for Coronation to appear in the first place
jesus this seems really op
Attempting to draw something with a stencil right now and I'm not sure it's doing it right
Everything on the entire screen to the right and bottom of the card with the stencil disappears while the stencil is being drawn, and the stencil itself doesn't seem to work
oh hey that's like 4x mult or smth. don't mind if I do
How would someone go about having a joker run a python script? I don't really understand this
anything is possible in the realms of arbitrary code execution
you can just call another program whenever you want
But how would I go about doing that?
I have it installed its just that I struggling to understand what I doing wrong with lua telling it cause it crashes balatro anytime I start it up
you need to require io
Io?
?
yo chat any clue why lovely "mod" is throwing an error?
do you have 2 steamoddeds
nah, just smods-main
should i get rid of -main?
it wants this function to have 'end'
i'm not gonna pretend to be an expert in lua, but is there something wrong here?
What you're looking at is the so-called "Thunk-style indentation".

ok i dont get it, but clearly you put a ton of work into this so great work
thanks :D
I'm making a new joker and idk why this is crashing - i even named the variable reroll_cost_ just in case i was shadowing a variable or smth (yes ik shadowing a variable doesnt make sense with that error message but who knows!) but i cant figure out why ability would be nil
It should be card.ability.extra.reroll_cost.
Emphasizing on the .extra part.
how would i check if any joker is sold?
context.selling_self
thks!!
In line:37, it should be config = { extra = { reroll_cost = 0, old_reroll_cost = 0 } }.
Anything outside extra might not be going to get carried into card.ability, I guess.
its really fortunate how jokers in other card areas dont trigger, else id need to rewrite most of my code
wdym jokers in other card areas
i added a new card area
i initially thought that if i were to put jokers in there then their calculation and allat would still work
only if you add the area to SMODS.get_card_areas
this also checks for consumables?
yes, the card being sold is passed as context.card, so you can used that to check if it's a joker
oh
sorry for being stupid but how?
if context.selling_card and context.card.ability.set == 'Joker' then
i hate when its that easy and i need to ask people
how do i add sell value to my joker?
try looking at the code of egg and giftcard (wait is that the joker's name)
oh
@frosty dock What is the lowest 4-digit version number (and one letter) for smods new-calc? I want to specify the dependency in my mod wiki page.
1306a, but i can guarantee you that you're not actually compatible with that version
i recommend you set the dependency version as what you developed it on
just to be sure, theres smt like :get_edition() right?
so this sets "value" to "value" + "extra" and then justs sets cost ? i dont undestand how "value" is used here
You need to look at what set_cost does, it uses the extra_value
oh
It adds extra_value and extra together, and then set extra_value to that sum.
i got that
...damn, thought it would simply return a string like e_foil
im not going throught that just to add sell value, imma search a mod that adds a joker that does that but thanks
get_edition is a scoring function
oh
if you just want the edition key, that's card.edition.key
thanks :D
What would it look like if you dont use Event?
Just, straight up context.other_card:set_edition(...) in your code.
it breaks the effect
hold
nah, it breaks it
What about, instead of applying it when scored, try apply it in context.before/after?
it triggers on all held in hand cards
at the start and end of round as well
its a mess
What about DNA's timing?
Got to say, your video is quite lagging at the edition-applying moment.
context.first_hand_drawn ig?
No, first hand played.
first_hand_drawn is for the jiggles.
Yeah, and it is in context.before.
And you only need to apply it once, so you might as well apply it before instead of during scoring.
???
Did I write something wrong?
it seems like you're returning the message on every context
when do you want it to trigger
Your return is outside of the if statement.
which return?
32x32 for 1x and 64x64 for 2x
i assume they have the 1 pixel padding right
I put it back in but the Joker doesnt function now
Instead of return true, you need to return the {} that has message, colour, and card in it.
like this?
(it still doesnt work)
yes. the atlas size is 34x34 including the border
Remove G.play check, individual check, and repetition check, you won't need them.
Oh and instead of context.other_card, you'll need context.full_hand[1].
like replace all occurances?
Yeah, so the second if condition would be if context.full_hand[1].ability.set = 'Enhanced' and not context.full_hand[1].edition then
Have you noticed that you typed context. twice in each occasion?
oh shoot
I didnt haha
now card gets edition BEFORE joker even start jiggles and pops a message
Then I guess G.E_MANAGER it is.
yes, you are doing it before any of the code that handles your return message. in fact you are doing it before the concept of your return message exists
delay is back😭
yeah, that's what Im saying
Then I have no idea how to help you further, since neither have I concurred over the timing issue. Sorry.
But why tho? its all inside the same if statement
All good, thanks for trying regardless
can someone explain to me why this doesn't seem to work ?
G.GAME[("Legendary"):lower() .. '_mod'] = 0.1
I took ownership of the legendary rarity and added a print in the get_weight, and the weight doesn't change; so my guess is the provided key is not the right one, but how am I supposed to know what's the correct key for vanilla rarities ?
put the set edition inside of a function in your return like so
return {
func = function()
...
end,
...
}```
if THAT'S also not what you want, try putting that func inside an extra table that you return from the same return statement. this makes it act like another, following, "return"
tried to hook into set_globals on my main script to add values to the colors table but i guess it doesn't apply the changes
should i just make my own globals
like so
return {
extra = {
func = function()
...
end,
},
...
}```
nope! the edition is still applied before Joker jiggles
oh shoot you wanna do that with an event mb
i was about to say
yeah but that causes an SFX delay
if the timing's off then an event can help control that
but you can use that to prime the event at different timing
So this is how it is now
so I should add a param under G.E.MANAGER?
for timing
i think it defaults to before which is what you want iirc
when I use event it causes delay :(
in sfx
also i don't recall what the set_edition arguments are, which do your nil, false, true correspond to
one sec
i think you want whatever one is "immediate"
So immediate then poll_edition?
as args
oh shit
thats poll editions args lol
im on my phone srry
i forget exactly but one of the args is immediate
i think it's (edition, silent, immediate)
so like (poll_edition(...), nil, true) maybe
I found it in games code!
Is there a mod, or maybe a debug function that allows you to choose your joker for testing purposes?
#1228149931257237664 mentioned
i've never programmed a tag before so i'm kinda lost on how to spawn in and open a booster :x
trying to check for matching cards when discarding
do i use full_hand or something else?
isnt working for now
What effect do you exactly want to achieve?
Like, what's your joker's description?
check if there are at least 2 cards of the same rank on discarded hand
how can i use custom colors on the info bubbles? i want the 1 in 2 to be the same custom color as Sacred Fire
thank you!!!
yes, you can use the same formatting in all descriptions
do the same as how you changed the color for X3 Mult
Does anyone know if Balatro will load localization files without Steamodded or Lovely? I'm wondering if it's possible to make it easier for people to download my Māori language mod
My immediate thought would be how Burnt Joker check the hand type of the discarded hand. Such as a Pair.
i think anyone who plays modded balatro should have steamodded and lovely anyways
but other than that, i dont think so
burnt joker gets the poker hands directly
imagine it revives gros michel
okay i made it work by checking the vanilla code but i feel like there's much better ways of doing this with smods
i just need to detect if onee or more cards share the same rank
if i used the poker hands there could be conflict with mods that add more card selection
im planning for it to be a selection of up to 10 jokers, i dont want these cards to troll for now at least
practically, no. it's possible to insert localization by means of modifiying the executable directly but that makes it harder to install
On unrelated note, I'd recommend not SMODS.has_enhancement(v, "m_stone") for non-stone check.
Where did you declare the found variable?
outside the if
the pre discard one that is
it does work when i check a played hand on before
May I see the full calculate function?
local count = {}
local found = false
if pseudorandom('jester_dice_play') < G.GAME.probabilities.normal / card.ability.extra.odds then
if context.before and context.scoring_hand then
for _, v in pairs(context.full_hand) do
if not SMODS.has_enhancement(v, "m_stone") then
local rank = v:get_id()
count[rank] = (count[rank] or 0) + 1
if count[rank] > 1 then
found = true
end
end
end
if found == true then
ease_hands_played(1)
return {
message = "snap!"
}
end
if context.pre_discard then
for _, v in pairs(context.full_hand) do
if not SMODS.has_enhancement(v, "m_stone") then
local rank = v:get_id()
count[rank] = (count[rank] or 0) + 1
if count[rank] > 1 then
found = true
end
end
end
if found == true then
ease_hands_played(1)
return {
message = "snap!"
}
end
end
end
end
end```
bit too big for a screenshot
Please use triple ` to braket the code you just pasted here.
woops
why doesnt discord have a send message button
enter was just jumping a line
You just need to edit the one you already sent.
you have to close the section with another triple `
it wont let you send one that is half open
Hit Enter when your cursor is outside the code block.
hacks
done
i still keep my moint about the send message button
you forgot the "lua" part, but its probably fine
you need to click outside the code block to send
print("wassup big dog")
r u sure your typing cursor is OUTSIDE?
it works for me
just make sure the typing cursor is outside
OK, there are... so many thing I want to run through with this piece of code, so I'll need to do it step-by-step. You OK with that?
omg
yah ok
im bracing
First of all, you put if context.pre_discard then inside if context.before and context.scoring_hand then, which are exclusive to each other.
oh
Second, you put if pseudorandom... then on top of EVERYTHING, which is not exactly bad, but I'm afraid this might bite your hind in the future.
i thought it might be fine since both cases are mutually exclusive
tbh drag me i deserve it lol
By putting if pseudorandom... then on top, you are equivalently flipping coins Every single time whenever anything is happening.
i can definitely change it
Third, if you're completely sure found is always a boolean value, you can use if found then instead of if found == true then.
And if you're not completely sure if found is always a boolean value, there's the classic if not not found
...
That'd also perform the if with any other truthy value e.g. 1
I'm pretty sure
Hence, I suggest:calculate = function(self, card, context) if context.before or context.pre_discard then local count = {} local found = false for _, v in pairs(context.full_hand) do if not SMODS.has_enhancement(v, "m_stone") then local rank = v:get_id() count[rank] = (count[rank] or 0) + 1 if count[rank] > 1 then found = true end end end if found then if pseudorandom('jester_dice_play') < G.GAME.probabilities.normal / card.ability.extra.odds then ease_hands_played(1) return { message = "snap!" } end end end end
Because both if and not probably use the same algorithm to force values into booleans
if i were to use, for instance:
local rng = pseudorandom("example")
then i compare rng >= 1/2, then it would be very slightly higher than 50%, right?
Shouldn't be
really?
yeah, but without the "=" it would ignore if rng was somehow exactly 0.5
Yeah
working now
Without the = it would be slightly less than 1/2
oh yeah, thats right
the probability of that is negligible
true, its probably like 0.0000000001% considering the number of digits rng has
The chances of that are so spectacularly low that you should definitely add a massive print log congratulating the user on winning the pointless lottery if that occurs
good idea, i will do just that
Also I've had an interesting idea for a mod that I don't actually think can be made
i don't even know why i did this, it's not even close to enough iterations to even have a considerable chance of happening within that amount of polls 💀
lottery simulator 😭
Is it 1 in 2^64 with Lua's double precision floats?
that seems like too many
Since fractions between 0 and 1 would be able to use the full mantissa range
the mantissa is 52 bits though
Fantastic news, your odds of winning the lottery are 4000 times higher than i thought
it seems there'd be about 2^62 doubles in the range from 0 to 1 in total
however my guess it that significantly less are actually possible as it has to be somewhat uniform
well, i mean, 99% gamblers quit before they win 🗣️
if its not 0%, then its theortically possible
given there's 2^52 doubles between 1/2 and 1, I would expect the lower end to use the same amount here, roughly
if it uses the full range there, it'd be 1 in 2^53
ive got this now but still the same error
that looks like a bad context check at the very least
That... doesn't make sense to me...
What does your loc_txt look like?
but also your loc_vars has wrong arguments
loc_vars args are (self, info_queue, card)
..ohh
Not return {vars={card.ab...}}, you need to just return {card.ab...}...?
wait, nvm. sorry
Wish i could read this
same
absolutely not
how do i score on an unscoring card?
i did something with unscoring for Sketch, but it wasn't on individual cards
you just replace whatever cardarea check you have with context.cardarea == 'unscored' and make sure you have the optional feature enabled
cheers :D
sorry, remind me what the optional feature is?
SMODS.current_mod.optional_features = { cardareas = { unscored = true } }
that just goes in your mod's main file
grand, thanks :D
hmm, no, it's not working :{
code:
if context.individual and context.cardarea == 'unscored' and pseudorandom('tennisball') < G.GAME.probabilities.normal / card.ability.extra.odds then
local target = context.other_card
target:set_ability(G.P_CENTERS.m_steel, nil, true)
G.E_MANAGER:add_event(Event({
func = function()
target:juice_up()
return true
end
}))
G.E_MANAGER:add_event(Event({
func = function()
play_sound("tarot1", 1, 0.5)
return true
end
}))
return {
message = "Steel",
colour = G.C.FILTER,
card = card
}
end```
smods version?
1.0.0~ALPHA-1326a? or is it 1.0.1o-FULL?
sorry, the former. yeah that's too old, unscored calculation was only added like a week ago
ah i see :D
neato!
getting this error after updating SMODS:
Oops! The game crashed:
Syntax error: blind.lua:353: 'end' expected (to close 'for' at line 351) near 'elseif'
Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~ALPHA-1426b-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.6.0
Platform: Windows
Stack Traceback
===============
(3) C function 'function: 0x28ffcf38'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 887
(6) global C function 'require'
(7) LÖVE function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x28ffa5a8 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x28ffa5f8 (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) LÖVE function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
inerror = boolean: true
deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
when I try to play a sound from my mod the game keeps checking the vanilla files resouces/sounds for the file (causing a crash since it can't find it) even though I defined the sound with SMODS.sound and it appears to work there
anyone got any idea why this wouldn't be working?
SMODS.Sound({
key = "s_tsun_probability_tm",
path = "lucky.ogg"
})
sound is played here
play_sound("s_tsun_probability_tm", 1, 1)
in a joker
why did you prefix the key yourself
sounds don't have a class prefix, so steamodded doesn't recognize that you prefixed it
so the real key ends up as tsun_s_tsun_probability_tm here
i just have a quick question: how does one update sell value to be a specific value? i'm trying to make a joker that has its sell value randomly change and i keep seeing that its sell value is 4 (which is most likely just the default because the buy cost is 9)
normally what you do is you don't prefix when creating it and just use the prefix when playing the sound
yeah that makes sense
I thought sounds would have a class prefix but i guess not
yeah it works now thanks
you can use card.ability.extra_value to modify sell value. it's additive on top of the base sell value (half the buy cost rounded down), so you have to subtract that if you want to set the real sell cost
what do you recommend for storing variables inside jokers? config.extra?
yes
then to recall them I use self.config?
preferably not, as that doesn't allow you to change the values without affecting other copies. Use card.ability.extra
10/15 done :3
https://gyazo.com/af19f1b4fae75e52829e054ba9bd7e6f
you can see how the hitbox of cards inside here is not aligned with the card itself (my laptop so bad gyazo bugged out 💔 oh, its a new card area by the way)
anyone encountered this problem before?
good time to hold G + A
apparently, adding "immediate" arg doesnt fix sfx delay :(
I was wrong
It's such a weird bug
That is not where you put "immediate".
Above func, place trigger="immediate",
how do i get the list of unscoring cards?
it didnt help unfortunately
delay persists
does anyone know if you can patch multiple of the same pattern in lovely instead of just the first instance in a file with just one patch
Yep! Use the times argument
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.SPEEDFACTOR = 1"
position = "after"
payload = '''
initSteamodded()
print('{{lovely:var_name}}')
'''
match_indent = true
times = 3
(bump :>)
tysm
if i do 9999 or something will it break or just do all of them
or is there a better way to do all of them
For clarity, you should probably count and specify the number, so that it doesn't show an error that it mismatched
again it replaces all instances of that pattern by default
Setting times to the right number will also help you recognise more quickly if your pattern is matching less or more than what you want it to
well i want it to work without changing it preferably even if balatro gets updates
Not necessary as CG said, but the extra sanity-check is helpful
oh does it?
idk why i thought it was only the first one
oh maybe i already had times = 1 on my other mod
is there an easy way to change the highlighted card limit of the game or should I keep screwing around with toml file etc ? I currently am doing this but it doesn't allow me to pick up more since it's all variable are attributed in the init function of cardarea
CardArea.config.max_highlighted where CardArea is whichever you want to change (technically this is still valid and changes the default but regardless)
so for example G.jokers.config.max_highlighted = 2
np
i couldve sworn by default it replaces all matching patterns unless you specifiy the amount of times
there's an optional smods feature that enables the unscored cards in the context as a cardarea but i haven't had it work yet
lemme attempt something rq :D
okay no i've got no clue =w=
i want it to trigger in joker_main, but i also need to access the context's unscoring cards too
you would probably have to enable the unscored cardarea feature. Try adding this to your code
SMODS.current_mod.optional_features = { cardareas.unscored = true }
Not entirely sure if that'll do it but it'll be something along those lines
i've done that, yep
hmm
i've used that for unscoring cards doing something, but i don't know how to check them, is the thing
Can you tell me what the general function of your joker is?
+1 hand if played hand contains an unscoring Ace (3 [3] uses each round)
And how exactly are you checking for it currently?
i'm not, currently, that's the problem :)
i don't know how to get the unscoring cards in context.joker_main
In my experience with Harmony patching over years of RimWorld updates, unless you're patching only a few things, and those things are extremely simple in a very stable or loosely-coupled class, it's almost certain that some of your patches will break between updates. There's just no a guarantee that variables will retain their names, or data structures will remain the same, or classes and functions will continue to exist at all.
If your mod is dependent on patches to the point where it will break down if a single one of your patches breaks, then there's also no point in trying to safeguard only some of them.
Sometimes failing early and in an obvious way is better than attempting to hide, sidestep or predict errors that might occur in the future. Only you can really gauge for your specific case, but something to think about.
though i used context.individual and context.cardarea == 'unscored' for when the game runs through the played hand
mm, i guess i could add those cards to a local variable? but i don't like that solution much
Ok then, what I would recommend then is looping through the cardarea context and using get_id() to check if the current card is an ace (ace == 14)
a for in loop would work nicely
precisely
i'll give that a go, thanks! :D
And if that bool is true by the end of the loop, do your function
was hoping there'd be a better solution that SMODS allows, but i guess this context was only added a week ago, so =w=
thanks again ^^
np, best of luck
wonky
that looks flames
we really need a custom area API
mostly so that dimserene's pack doesn't end with a dozen overlapping areas to the right of the screen
True
But tbh there's not a lot of room anyway
yeah but maybe we can have something with pages if it overflows
Yes, I suppose we have done the same fixes to seeds shaders mipmapping, threads and reimplement bitshifts
#⚙・modding-general message
Also had to fix lovejs like you, basically dumb undefined check the sound engine that caused crashes
What exactly are you trying to do? I’m sure there’ll be some smods tool I’ve added to help you out
-# iloveundocumentedfunctions
sorry to bother, this line's throwing an exception, what's wrong?
for cand in context.removed do
the error message says i'm indexing into a table value
is there a particularly easy way to add a 'use' button to a joker? i dont want to make a whole new cardarea just for one joker and would rather make it have 'charges' that can stack and be used while still sitting int he normal cardarea
is there a better way to check for boss blinds?
i approve of the switch to dark mode
you'd want for k, v in pairs(context.removed) do instead, where v is the current card indexed in the loop
I think broken glass cards find their way into that context so yes
coolio :D
is there a way to know how much the player spent on a reroll?
oh uhm, new, weird error
G.GAME.current_round.reroll_cost during context.reroll_shop
when calculating joker_main and before can you access the current blind?
thank you!
G.GAME.blind.boss
it's probably here:
if context.cards_destroyed and not context.blueprint then
local count = 0
for k, v in pairs(context.glass_shattered) do
if v:is_suit("Diamonds") then count = count + 1 end
end
if count > 0 then
card.ability.extra.current_xmult = card.ability.extra.current_xmult + (card.ability.extra.added_xmult * count)
return
{
message = card.ability.extra.current_xmult,
color = G.C.RED,
card = card
}
end
end```
Where did you get context.glass_shattered
I don't think that's a thing, loop through context.removed and do if SMODS.has_enhancement(v, 'm_glass')
In that case it's probably only used for Vanilla jokers
What is the error? Could you send a screenshot
_ _
I'm on phone
attempt to index local 's' (a number value)
maybe my code included a non-UTF-8 character?? no idea
Btw here's my method of checking for broken glass cards if that helps at all
stg = card.ability.extra in my case
Boop
Yeah yours would probs work better, this is an older Joker
oh, kay
It'd be worth changing to that, even if just for debugging
You're using an old version of talisman
So make sure to updatr before anything
oh, kay
maybe it's that? question mark??
i removed the bit about glass and it still threw
how would i have a joker retrigger the use of a consumable?
...oh, The Hanged Man broke it =w=
how to check the suit of a card?
for k, v in pairs(context.full_hand) do
if v.suit == "Diamonds" then
count = count + 1
end
end
v:is_suit("Diamonds")
or actually for starters how would i even have a joker retrigger something
For a joker to retrigger something you would return repetitions = [Number of retriggers]
As for cosumables though, I'm not sure if their use functions take a repetition
Unfortunately I do not off the top of my head
is it an extra thing or does it go by itself
the second one
thought so
Oh wait yeah I didn't even realize that was in locvars
curses
if context.opening_booster is true, would context.card.cost give me the cost of the booster pack?
This would make it attempt to retrigger anything anytime calculate is called. You should constrain it to certain contexts
most probably context.repetition
Yep!
Thank you!
update on this: we're at least at the point where retrigger jokers are working 100% fine, but the for loop for non-retrigger jokers is still busted for some reason and it's still not retriggering the target according to card.ability.extra.funk. what're we missing here?
i forgot to actually thanks
unless im foolish
You have your indentation messed up, but that debug message about returning without repetitions is inside the loop
So it's returning on the first iteration every time
I believe this will retrigger all playing cards with no rime or reason. I know you're just doing this to get a feel for how it works which is totally fine, I'm just trying to give you a sense of what it would do
ok cool that's what i thought
this doesnt seem to be working but it should from what i understand
whenever i buy boosters it doesnt do anything, but other cards and vouchers work just fine
yup!
did someone purge #💻・modding-dev
wtf
man i know 3 programming languages and i still dont know how to read 🥹
Trying to make the joker to the left of mine become negative but i can't seem to get it working
we can still read older messages, it might've just been a weird hiccup on discord's end
Use card (or whatever you named the 2nd parameter of your calculate func) instead of self
alright here's what im working with
would that be the right context param do you thtink
As I said, I don't believe consumable use functions can be retriggered
what about the effects of the consumables themselves?
Probably not since those are a result of those same use functions
darnnnnnnnn
unless you got patches, i dont think you can retrigger consumables
i guess i'll jsut have to go with the orgiinal plan of the double probability thing
oops, all 6s?
yes but only for specific cards
i think that SHOULD be possible?
What specific cards?
it is
i do the for probabilities yada yada thing or whatever and then constrict it to a certain set probably
make a custom global variable, like G.customProbability or something
probably the wheelcentric
got it
Ok yeah that'd be easy. You've just gotta take ownership of the card and apply your probablility to its prob check
i was originally wanting it to trigger again, like a retry of sorts
but patches,,,,
Been trying to figure out how to use a patch to give a specific joker a custom back sprite when flipped but no matter what I've tried, i can't seem to get it to work. Been heavily referencing how Joyous Spring does it but even then, I can't seem to get any result other than "nothing" or "game crash"
I think you could do that without patches by taking over the wheel and looping the check for however many of the card you have + 1 times
i'm guessing id set it to the value of probabilities at the beginning right
mhm
pseudorandom(blah blah) < "that global custom probability"/ the odds or something
i'll keep that in mind
is there a way to draw cards from the discard pile to the hand? there's a function for drawing from the discard pile to the deck and drawing from the deck to the hand but the cards aren't drawn from the discard to the top of the deck (unsurprisingly)
even after transplanting the for loop from the last version where we knew it worked, it's just, not, for some reason. it's 100% exiting the loop way too early, that much is clear. but what're we missing here that we evidently weren't previously??
probs not but I honestly don't see that being too hard to make
hook the discard function, put every card discarded into a table and do some wonky stuff, i think thats how you do it
where's that going actually
a separate section or no
yeah
I was looking in the game's code and there is just a draw_card function that draws cards from one area into another
but I have to figure out the signature
this is how gros michel does its rng stuff
This issue remains
Your return is inside the for loop
G.GAME.probabilities.normal is the "1", while card.ability.extra.odds being the "6"
so its 1/6
if you change G.GAME.probabilities.normal to your global variable, then you can freely manipulate the odds
i seeee
this isnt calculate is it or am i wrong
it is calculate
oh fm ig lmao
its fine lol
yup that worked lol
oh, THAT was what we were missing. for syntax is weird and our attempts to prevent infinite loops end up, counter-intuitively, Ruining The Purpose Of The Loop. ;P
and then in the if check itself id put the do kv pairs thing
mhm
you put what you want the joker to do if the rng check is done inside the if statement block
what i have so far
i just need to figure out how to make the context be when using a consumable
oh wait
oh, it actually should be G.GAME.farmerProb now that i think about it
and if G.GAME.farmerProb hasn't been set beforehand then its nil
well it was set to GAME.probabilities at the top of the code
so then it's fine right
so you want to do smt likee
pseudorandom('farmer') < (G.GAME.farmerProb or 1)/card.ability.extra.odds
oh, probably then
how would i add to the ante counter when a joker is sold
G.farmerProb is a table?
i just replaced the all6 probs with farmer's
also, the first if statement is wrong
it should be card.ability.name == "c_wheel_of_fortune", im pretty sure
oh i was going off of
card itself is an object
or just add to the ante counter
wait i literally forgot im stupid 😭
yeah its right, but you are comparing a human to a name basically, they aren't the same
you need to get the name from that human first
oh lol
card also refers to whatever object this calculate is on
pardon
You’d want context.consumeable to see what consumable has been used
So this is a joker looking for wheel uses right?
@sturdy compass sorry for the extra ping but how does the "kind" variable for boosters store its info?
for rn yeah
so it can double the probability
What do you mean by that?
like if i wanted to check if it was a tarot pack, would i do context.card.kind = 'Tarot'?
or is it an ID
This would be correct
So you’d do if context.using_consumeable like you have, then if context.consumeable.config.center_key == “key of wheel here”
Thank you!
np
ohhh ok ok
👍
They joker burns before saying its last words
Dont look at the top its my first time making mods
i mean it's just wheel_of_fortune right
well, it's already dissolving so its not gonna say anything lol
If you want the message to appear before it burns, you should put a SMODS.calculate effect() before the start_dissolve. It would look something like this
I want it to be like mr bones but it just dies
Thank you!
what am i doing wrong here?
im trying to increment the amount of selectable cards only in arcana packs by 1
Unfortunately you might need to do a patch for that functionality
Here are the two I have to change pack choice based on a modifier one of my cards changes
where do i add these?
Have you done anything with lovely patches?
Nope
So first imma refer to you to this part of Lovely's github. It basically gives you a rundown of basic patch syntax and what exactly it's doing https://github.com/ethangreen-dev/lovely-injector?tab=readme-ov-file#patches
This is mostly gibberish to me but i more or less understand the general happenings described in the example
So to give you a tl;dr of the tl;dr, Lovely patches are means of modifying or adding code to vanilla files
mhm,i got that
to start making them, you either want to make a lovely.toml in the root directory of your mod or a lovely folder that contains multiple .toml files. It's up to preference
i was using another mod as a template for mine and it seems to already have a lovely.toml
From memory it’s c_wheel
Huh, interesting. You should be fine to add onto that
so do i just add your patches to the file?
would i be able to use ★★★★★ in the joker's description lol
oh real? where do they keep the keys
You should base your patch off of this one but in its current state it will not work for you. You'll definitely have to make modifications
still gonna ask how do i add one ante when a joker is sold
ease_ante(1)
how can i edit the "ERROR" text? im learning.
please and thanks.
can I see the patch? I thought it was pretty straightfoward
if i understand this correctly, G.GAME.choose_mod is a global variable that i can increment to increase the amount of times a selection can be made in a pack?
choose_mod is a variable I created myself, hence why this patch will not work for you in its current state lmao
in your loc_txt add a label = "whatever" entry
I'd write out the patch for you but I'm boutta run out 
I can still provide assistance through text tho
version = "1.0.0"
priority = 0
[[patches]]
[patches.regex]
target = "card.lua"
pattern = 'self\.children\.back = Sprite.*'
position = 'after'
payload = '''
if _center.backsprite then
self.children.back = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS['FinalBosses'], self.config.center.backsprite)
end
'''
match_indent = true```
Currently testing this but having attempt to index field 'atlas'
that'd be great
alright I'll brb
if there's a FinalBosses atlas your mod adds, that needs your mod prefix
And on the joker side, MODS.Joker{ key = 'okinamatara', rarity = 4, atlas = 'FinalBosses', pos = { x = 7, y = 0 }, soul_pos = { x = 7, y = 1 }, --TODO: Make her have her back sprite have a door. oh god how do i do this. Sprite is at { x = 7, y = 2 } --god i'm gonna have to figure out how to use lovely to make a patch for a cute easter egg. #suffering. cost = 25, blueprint_compat = true, backsprite = { x = 7, y = 2 }, calculate = function(self, card, context) if context.retrigger_joker_check and not context.retrigger_joker and context.other_card.config.center.rarity == 1 then G.E_MANAGER:add_event(Event({ func = function() context.other_card:juice_up(0.5, 0.5) return true end })) return { message = localize("k_again_ex"), repetitions = 4, card = card, } end end, }
OH THAT'D DO IT
oh my god it works
it was literally just "i needed a prefix" lmao
lol imagine the Balatro modding landscape with no forced prefixes
This line keeps on crashing, any idea why?
if context.end_of_round and not context.blueprint and context.game_over and (to_big(G.GAME.chips) / to_big(G.GAME.blind.chips)) >= 0.5 and not card.ability.extra.death then
And the way I implemented it means I can actually give other jokers custom backsprites too
too many mods would clash tbh
my j_joker wouldn't work :(
so just like that?
ok
How do i add multiple jokers?
What do you mean by "multiple jokers"?
made one joker


