#💻・modding-dev
1 messages · Page 179 of 1
Same concept
i tried setting it there but it didnt do anything
Also you should use pseudorandom so ingame seeds are applied
What'd you try?
is there a way to watch a file with debugplus in my code?
I get kind of tired typing the thing in
i think i have an idea
Good luck
hey, it's me again. uh. i realized it wasn't giving chips earlier but couldn't tell you why. i think i narrowed down why, but is there a better answer to it than just. a second line in the calculate function?
-- Tests if context.joker_main == true.
-- joker_main is a SMODS specific thing, and is where the effects of jokers that just give +stuff in the joker area area triggered, like Joker giving +Mult, Cavendish giving XMult, and Bull giving +Chips.
if context.joker_main then
-- Tells the joker what to do. In this case, it pulls the value of mult from the config, and tells the joker to use that variable as the "mult_mod".
return {
mult_mod = card.ability.extra.mult,
-- This is a localize function. Localize looks through the localization files, and translates it. It ensures your mod is able to be translated. I've left it out in most cases for clarity reasons, but this one is required, because it has a variable.
-- This specifically looks in the localization table for the 'variable' category, specifically under 'v_dictionary' in 'localization/en-us.lua', and searches that table for 'a_mult', which is short for add mult.
-- In the localization file, a_mult = "+#1#". Like with loc_vars, the vars in this message variable replace the #1#.
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } }
-- Without this, the mult will stil be added, but it'll just show as a blank red square that doesn't have any text.
}
end```
nope still nothin
i tried setting the values as variables in a function and running the function each time in apply_to_run but it still has the same issue
back?
"back" is the internal name used for decks
the 2nd parameter of apply to run, should be your deck instance
bump
i did not
i didnt know that was a thing you could do
this is what i tried originally
it successfully randomized the initial variables but it just picks the same numbers every time until you restart the game so that was a bust
why c is 0.8 instead of 0, 8
idk if your patch will work but the way you do conditions in tables is
condition and value_1 or value_2
typo but i dont think thats the reason ist not working ol
Try the apply to run thing
i put the function in apply to run though it didnt work
o
Might not be structured like that exactly
And I thought it was apply to run, not just apply
in smods documentation its apply
is that your code or an example?
that is from my code, yes
Do you have debug plus
yes
(tho i mean. it's an edit of a sample mod dfgjks)
replace the return with this and see if it works
return { mult = card.ability.extra.mult, chips=card.ability.extra.chips }
okay, what am I doing wrong with the event manager?
this calculate function (for a seal) is supposed to score all cards, apply random seals to all cards except the card it is on, wait a moment, destroy the card, wait a bit more (to show you what happened), then the cards go away as normal. instead, it waits a bit, applies the seals, destroys the card, and instantly ends the hand, making it really hard to tell what's going on
You have your inner add event outside func
well now neither chips or mult works???
i think i did it correctly now but i guess is not working because this values are defined at the start or smth like that
What steamodded version
You need to update
yeah that's probably only run when the game starts
do you want to change the chance?
I would probably patch out where it calculates the probability
but i can not find where it calculates the probability 😭
pseudorandom function prob?
off topic but I love seeing how many different ways mods do credits
i think there was a shatter function? try looking for that maybe? I'm not on my pc to look myself sadly
holy shit
i figured it out
config is basically entirely worthless here
what i actually have to do here is modify G.GAME.starting_params directly
the shatter function is for the animation, it doesnt calculate the probabilities there
i know, I mean look for when it's called
okay, THAT much worked. for whatever reason though, on scoring, it displays an extra mult pop-up that's yellow??? NO idea what that's about, frankly.
oh!
uh. what if i want a custom one on purpose though. (this may have given me a dastardly idea to replace the duplicate +1 Mult with just. "Paul.")
well in that case yes
if you change them to mult_mod and chips_mod they don't get the automatic message i think
would i just replace the two specified messages with like. what, message = 'Paul.'?
trying to find what other starting params there are though because it doesnt seem to be listed in game.lua where i thought it'd be
try it and see if it works
okay this works now, but how do I keep the cards onscreen? the card does wait a bit before destroying itself, but it does so off-screen after the played cards have already left
maybe after the dissolve you can put a delay(0.5) or something?
lovely patch the condition to add the joker check
This might be a bit of a technical question, but how would I get DebugPlus to spawn a card with a custom set in a new card area? (Art is a placeholder, it is not a Planet card in code)
i don't think you can without modifying it but i would also like to know if there's a way
The waiting game we shall play then lol
i just give myself infinite rerolls to find my custom cards lol
IT WORKS
FINALLY
basically if anything is super large it comes at the cost of another stat
I mean, the cards go offscreen as soon as the seals are applied, which is also an event with a delay, by the time the dissolve happens the cards are already offscreen
delay(...) isn't doing anything no matter where I put it
I think the patch is not able to get the scoring hand
should i put it inside the joker?
this is the patch btw, i dont know if its right:
G.FUNCS.evaluate_play = function ()
if not G.GAME.blind:debuff_hand(G.play.cards, poker_hands, text) then
for i=1, #G.jokers.cards + #G.consumeables.cards do
for i=1, #scoring_hand do
if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and self.base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then
destroyed = true
end
end
end
end
end
is there a nice way to make a joker automatically win a blind?
yeah you're just deleting the entire function
a hook is going to be hard, you should try a lovely patch
why would you want that
Three pair?
honestly, i dont know how to do that
oh I know this one
I have a deck that lets you play 6 cards lol
today i made my first patch and it was a very small function so i dunno how to patch bigger functions
local emplace_ref = CardArea.emplace
function CardArea:emplace(card, location, stay_flipped)
if self == G.consumeables and card.ability.set == "Weapon" then
G.weapons:emplace(card, location, stay_flipped)
return
end
emplace_ref(self, card, location, stay_flipped)
end
this is what I use
just add your set name
Same
It's a great concept
I have that but as an injection. Still no go tho
I have both
Oh I see
and it works that way
Gotcha
i know it should be something like this but i really have no idea
something like this
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if destroyed then"
position = 'before'
match_indent = true
payload = '''
if scoring_hand[i].ability.name == 'Glass Card' and (SMODS.find_card("j_toyr_four_leaf_clover") and scoring_hand[i].base.id == 4) then
destroyed = false
end
'''
whats exactly the pattern?
I tried to do this by setting the scored chips to the blind amount, but then the cards score after that and bring it back down
pattern is where you want to put the code, so I put it right before the destroyed check
and should i put the patch just like a hook in the main.lua?
no, you make a .toml file
so uh, stupid question. how do i make a joker give an extra joker slot (like it's negative, even if it isn't actually negative)? is that a function in smod, orrrr? (asking because i have a good few ideas that involve joker slot shenanigans)
G.jokers:change_size(1), I believe
I mean... kinda?? 😭
oh!
i guess i can also do one file lovely.toml instead of putting it in a folder?
in terms of cards, we have no cards
no idea
no idea how that happens 😭
Who knows, maybe (probably) there's a part of the CardArea that I messed up
is there a mod i can look at that has a joker/card that checks wether something happens at any point in the game (like a card that needs three tarots to be played for it to work) or something like that
Here are the three injects I'm doing for it (not counting the hook that you just recommended to me)
[manifest]
version = "1.0.0"
priority = 15
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/utils.lua"]'
pattern = "-- TARGET: add your own CardAreas for joker evaluation"
position = "before"
match_indent = true
payload = "table.insert(t, 1, G.weapons)"
# Emplace weapons in their own area
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''
elseif card.ability.set == 'Booster' then
'''
position = "before"
payload = '''
elseif card.ability.set == 'Weapon' then
card:add_to_deck()
G.weapons:emplace(card)
play_sound('card1', 0.8, 0.6)
play_sound('generic1')
dont_dissolve = true
delay_fac = 0.2
'''
match_indent = true
# Add Pool and Global Object
[[patches]]
[patches.pattern]
target = "main.lua"
pattern = '''function love.load()'''
position = "before"
payload = '''
FVB = {}
FVB.cards = {}
'''
match_indent = true
this is my whole toml file 😭
Change the type of your area
Oh my goodness LOL
I’m pretty sure the cardarea functions don’t support new types without rewriting them
so this patch should work?
[manifest]
version = "1.0.0"
priority = 0
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
position = 'at'
match_indent = true
payload = '''
"if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and self.base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
'''
But you also shouldn’t really need a new one
what calculate function do i put that under--or do i even put it under one at all?
What to? Does it matter?
I think jokers will be fine
alr
Changing it to that still left me with this
okay, i'm back on this. cards i've just played in a hand keep leaving the screen, even when an event I've started hasn't finished?
here's the current code (on a seal), which is trying to, after all cards are scored: apply seals to all cards except the owner of this seal, wait a bit, destroy the owner of this seal, then delay a bit longer.
but the played hand won't stay on screen long enough, and the cards go offscreen even though an event is still happening
Unnest them
I don’t remember the type keys, it might be something else
fully? someone else just told me to nest the second event inside the func of the first one
No if you do that it’ll only add it to the event stack when the first event is run, so it goes after all the following events
You want to add them consecutively
ah yep it was
Oh huh that's a weird one lmao
ahh okay that makes sense, it's working now, thanks
$1
ignore how long it took me to do that
lmfao
uh, sorry to nag about this; how can i make a joker give an additional joker slot or otherwise influence joker slots? like, where would i put that in the code of the joker?
key = 'paulJoker',
loc_txt = {
name = 'Paul',
text = {
"{C:chips}+#2#{} Chips",
"{C:mult}+#1#{} Mult",
"+1 Joker Slot",
"Paul."
}
},
config = { extra = { mult = 1, chips = 1 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult , card.ability.extra.chips } }
end,
-- 1 common, 2 uncommon, 3 rare, 4 legendary.
rarity = 1,
atlas = 'StellationJokers',
pos = { x = 0, y = 0 },
cost = 1,
-- G.jokers:change_size(1), --idk if i put it in the right place lol
calculate = function(self, card, context)
if context.joker_main then
return {
mult = card.ability.extra.mult,
chips = card.ability.extra.chips,
message = 'Paul.'
}
end
end
}```
You should probably add an add_to_deck and remove_from_deck function
Change the size there
okay... this is a bit odd, but i'm now getting smods related crashes? in this video, I have two debugplus savestates. I load the second one, play a hand with the beige seal, and then load the first save state, which crashes the game
it's crashing at line 304 in smods src/utils.lua, which is the SMODS.find_card function
okay so i'm gonna be going to bed rn so i'm putting some code here, could someone unscrew this because I am too tired to learn how to refer to the length of a lua array
What is supposed to go in the main.lua type file referenced in line 8 of the example code of https://github.com/Steamodded/smods/wiki/Mod-Metadata ? Looking at examples that's where people seemingly put their Atlas, but also I've seen other things loaded in there as well
the name of your main file
if your name file is called projansky.lua, then you put that there
Oh sorry, I didn't mean what file to put in line 8 of that example code, but like, how to actually write that main file. Right now all I'm really seeing is that the Atlas should most likely go in that projansky.lua file
well, under whatever calculate function you want to trigger the effect with
i believe you mentioned a joker?
if you are starting, you will probably put there everything related to the mod
jokers, seals, editions, etc
while you learn and you write more code, youll figure out if you need more files and how to use them
Putting all code for custom jokers/seals/etc. in this one file rather than managed in separate folders such as a 'cards' folder or an 'assets' folder? I mean it just seems messy for now but if it's the way then sure
there are different styles of organization. some people have individual files for each joker, others have one file for everything. i use the middle ground solution of separating joker files by rarity
yeah, this is a passive ability for a joker. if you own it, you have +1 joker slot. (yes this is a fundamentally useless ability beyond letting you have the joker for free, this is part of the joke)
i dont really know Lua so that way is how i do it for the momment, but if you manage to do it better just go for it
Hey you and me both
as im learning how to code ill organize everything, but for now im not doing that big of a project
i just have this
oh
so there's an add_to_deck and remove_from_deck function on your joker
that's where you'd put it
you'd just put G.jokers:change_size(-1) in the remove_from_deck
add_to_deck = function(self, card, from_debuff)
-- Changes a G.GAME variable, which is usually a global value that's specific to the current run.
-- These are initialized in game.lua under the Game:init_game_object() function, and you can look through them to get an idea of the things you can change.
G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discard_size
G.hand:change_size(card.ability.extra.hand_size)
end,
-- Inverse of above function.
remove_from_deck = function(self, card, from_debuff)
-- Adds - instead of +, so they get subtracted when this card is removed.
G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discard_size
G.hand:change_size(-card.ability.extra.hand_size)
end
so wait, smth like
if context.joker_main then
return {
jokers:change_size(1)
}
end```
and obviously an opposite for this?
And then have some loading code in that main.lua file? some line like assert.load_file(jokers/common.lua)?
i assume not EXACTLY this syntax
here's how the merry andy card remake changes the hand size in the steammodded examples
what you're after is basically the same, except for joker slots
that's how I do it :)
are you new to Lua or to programming at all?
add_to_deck = function(self, card, from_debuff)
G.jokers:change_size(1)
end,
-- Inverse of above function.
remove_from_deck = function(self, card, from_debuff)
G.jokers:change_size(-1)
end
this, essentially
Lua, though this is my first time attempting to mod any game. I've used C++ in the past, and use python all the time for work. Enough to know my way around a github repo well but Lua still reads like greek to me
lua's ~= thing still annoys me, even though I'm a few hundred hours in 😭
good luck then, lua is pretty easy but you have to get use to a lot of singularities
like this one
or arrays starting at 1
also that their exponent operator is the caret symbol
which makes the most sense of anything I've learned so far
but it's still of
i was able to settle into Lua fairly easily because I'm coming off of a few years of C# experience
thats pretty common
I must've missed every language that did that then 😭
what other way did you do it?
How would you apply a shader effect to the entire screen, like if I wanted to put like a sepia filter on somethin?
wuh oh
here's source with line numbers for reference
I remember python's is x ** y
rust is x.pow(y)
you forgot a comma after the calculate function
the caret symbol is usually bitwise stuff for my choice languages
For the record, using a carat is an accepted way to represent exponents if you're doing like real life paper mathematics
yeah
that's why I said it makes sense, technically
that is also how I wrote one of my cards' description
[manifest]
version = "1.0.0"
priority = 0
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
position = 'at'
match_indent = true
payload = '''
"if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and self.base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
'''
Is this patch correct?
delete the quotes before the if and after then
in the pattern or in the payload?
or both?
in the payload
oh payload
glass 4s still break 😭
check the lovely dumps to see if the patch worked
how?
oh and it should be scoring_hand[i].base.id
lovely folder in your mods folder
that worked! last question for tonight, i promise (unless of course i have issues implementing this). is there a way to like, check for how many copies of the joker you have?
no, not your specific mod
mods/lovely
that one
ah okay
it just dumps all the code, but with all patches applied
#SMODS.find_card("yourjokerkey")
wait as a final thing for now y'all, is there a guide/method for making the png file used for the atlas for custom jokers (aka, the files in asset folders)? I understand that there's a single png that stores all custom card sprites, but is there a template/guide for actually making that file?
should balatro be open?
You just need some sort of thing to compile all of your PNGs together
The best method I (and I'm sure others) use is importing all your files as keyframes in Aseprite, then exporting the spritesheet
... is there a version that isn't 20 bucks or nah
the state_event that lovely dumps is like 300 lines shorter
there is an open source version called libresprite
lfg thanks y'all, really appreciate the help
stupid question but i am so rusty with lua. how would i put that into an equation? like, if i wanted to try and find out if there are more than 1, would i use if #SMODS.find_card("yourjokerkey") > 1?
yes
im going to sleep for tonight, thank you for all the help
probably tomorrow ill figure out about the patches and the glass 4s
rather unsurprisingly the game did NOT like this but it honestly complained far sooner.
(yes, i am trying to make it so that, if you have multiple paulJoker, they exponentiate your mult based on how many paulJoker you have. i didn't say this idea was balanced, or smart, just that i wanted to do it)
you can't put if in tables
the syntax is condition and value1 or value2
also you need the full joker key i think so j_youmodsprefix_paulJoker
mult = card.ability.extra.mult ^ (#SMODS.find_card('...') > 0 and #SMODS.find_card('...') or 1) is probably what you want
so j_cwsstla_paulJoker? i read smth about it only looking at the first 4 letters for the prefix tho so i might be off-base
yes that's correct, that was for the default prefix idk if it's still like that
also, what's the API for exponent stuff, come to think of it? if there even is one, mind you.
talisman
i mean like, displaying exponents as their own thing
not. Handling exponential numbers in score. (unless the former is also handled by talisman)
you mean like giving ^mult?
like ^mult, yeah. ik a few mods have cards with exponential effects (both for chips and mult) and they all use the same sorta desaturated purple color to depict that.
vanilla, although talisman expands that support to omeganum
see talisman/big-num/notations/balatro.lua
i think they meant exponentiation not scientific notation
yeah, exponentiation in the actual calculation.
since what i'm trying to do is, on top of the +1 chips and +1 mult, it gives ^(the number of paulJoker).
USUALLY, this will resolve to be ^1. But it will be very funny when it doesn't thanks to smth like Showman or Invis Joker or Third Example Of Duplicate Jokers.
and in mods like cryptid, when an exponent is calculated, it displays that exponentiation as like, its own message (square pop-up).
okay. the display on the card text works, but the calculation... doesn't. it just doesn't display an exponential mult, and it doesn't calculate one either.
if context.joker_main then
return {
mult = card.ability.extra.mult,
chips = card.ability.extra.chips,
mult = card.ability.extra.mult ^ (#SMODS.find_card('j_cwss_paulJoker') > 0 and #SMODS.find_card('j_cwss_paulJoker') or 1),
message = 'Paul.'
}
end
end,```
delete the first mult
if your mult is 1, no matter how big the exponent is, it's still going to be 1
it's meant to add 1 mult, and then after that, check how many paulJokers there are. then, exponentiate the current mult by how many there are.
thusly, if you play a hand of exactly 1 mult, it gets boosted to 2, then exponentiates off that.
so the entire current mult? you need talisman for that
ah, that makes sense. how would i go about that?
(adding talisman as a requirement ain't a dealbreaker just bc i use it anyways fgdsjk)
ah i can't really help with that, I would ask in the cryptid discord maybe
how do i check the type of card that is purchased from the shop, like when a joker is bought?
Quick question, how to see modded jokers after launching game?
is there a way to have a card's sprite be larger than normal but still have the same hitbox as a normal card?
do you have mods installed?
ye i loaded my own basic joker that is just negative and cost $10
do you have the mod turned on?
check ur mods list and see if its enabled
i just used the lovely loader no modded client
what modded client do people use?
steammodded
ok
tytytytyty ❤️
@worn belfry PLEASE DOWNLOAD FROM THE SOURCE
Do not download from Releases, that is a severely outdated version
been scared of making joker art but i'm proud of this art i made :>
Is there anything I should know in terms of setting up a github page for a balatro mod?
What's the global variable for the final round score chip amount during context.end_of_round?
okay. having transplanted some code directly from how cryptid handles giving exponents, i at least ended up with. Whatever this is? (exponents currently set to 5 as a placeholder)
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult , card.ability.extra.chips , card.ability.extra.Emult } }
end,
-- 1 common, 2 uncommon, 3 rare, 4 legendary.
rarity = 1,
atlas = 'StellationJokers',
pos = { x = 0, y = 0 },
cost = 1,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
message = localize{type='variable',key='a_powmult',vars={number_format(card.ability.extra.Emult)}},
Emult_mod = card.ability.extra.Emult,
colour = G.C.DARK_EDITION,
message = 'Paul.'
}
end
end,```
ig my questions are twofold:
- what am i doing that's causing it to fail to actually grab the number of Emult?
- how can i set the variable "Emult" to be equal to the amount of
paulJokers?
For #1, pay attention to when it show's an error. I believe that return shows messages in order on your joker. I'm not 100% sure on that one.
For #2, you'd have to count how many times your joker's key j_[prefix]_[key] shows up in G.jokers.cards.
i mean, for 1, the issue isn't just that it's failing to grab it for the message, it's also not calculating it at all. as far as it's concerned, there is no exponent.
Ah, i have no idea, then. /shrugs
do you have any idea how to count for j_stla.paulJokers in G.jokers.cards as a variable, at least?
I do something similar for a joker that destroys other jokers. Hang on.
function getCardKey(card)
if type(card.key) == "string" then
return card.key
elseif card.config and type(card.config) == "table" then
local center = card.config.center
if center and type(center) == "table" and type(center.key) == "string" then
return center.key
end
end
if type(card.label) == "string" then
return card.label
end
return "unknown"
end
local paulJokerCount = 0
for i = 1, #G.jokers.cards do
local current = G.jokers.cards[i]
if getCardKey(current) == 'j_stla_paulJoker' then paulJokerCount = paulJokerCount + 1 end
end
I don't know if there's a SMODS internal way to grab the string of the key of a target card, but I made my own function for that. Using the above code, you could push paulJokerCount back to your loc_vars or directly back to your card.ability.extra.Emult
where would i put this in the lua? :o
in your calculate
I'm trying to make a joker similar to raised fist when the game selects the lowest ranked in your hand but for some reason this code either doesn't work or it targets every single card instead of the lowest ranked one
can someone please help me?
Might be a concurrent modification issue
hm?
do you have talisman? emult isnt built into balatro/steamodded, so you'll need to implement it yourself or use a mod as a depo (talisman)
i do have talisman, yes.
talisman should also be set as a dependancy, in fact. i'm starting to wonder if it's somehow not calling for it, though???
What’s the joker supposed to do?
do you have the mod priority above talisman? (i think this is how it works)
i think it's meant to give 1 emult for each copy of the paul joker
What’s the joker supposed to do?
what's talisman's priority?
first, flat +1 chips and flat +1 mult, and afterwards, exponentiate mult by how many paulJokers you have.
idk but just set it to like 99999 for testing
Not u someone else
it selects the lowest ranked card held in your hand and destroys it
When?
at the final hand of the round
Before or after scoring finishes?
after
it's 100% an issue with talisman not being recognized; having slapped the paulJokerCount to the flat mult, it works just fine
Use context.end_of_round. Find the lowest rank card. Destroy it. context.destroy_card is not what you’re looking for I believe
Yeah and if that hand loses then the joker shouldn’t trigger anyway
G.GAME.current_round.hands_left == 0?
.
So at end of round, see if hands left is 0
is there a context for the start of a round? i dont remember what it is off of top of my head
i set priority WAY up high and WAY down low, and it did nothing? "priority": 2147483647, "priority": -2147483647, either way, Emult_mod does nothing...
like. am i doing this wrong somehow?
"id": "CWS-Stellation",
"name": "Stellation",
"author": ["Camwoodstock"],
"description": "An intentionally zany mod made as a companion to Cryptid. Adds a new class of jokers, and some other stuff too.",
"prefix": "stla",
"main_file": "Stellation.lua",
"priority": 2147483647,
"badge_colour": "cc00ff",
"dependencies": [
"Steamodded (>=1.0.0~ALPHA-1225a)",
"Talisman (>=2.0.0)"
],
"version": "0.0.1"
}```
How do I check that the blind is a boss blind at the end of round?
Ok quick question, is there a way to recolor the pre-existing blinds? I see the color code in blind.lua about editing the existing colors to have more black hues, but not the info on the base blind colors themselves
Like in terms of these text boxes and the background colors
sorry to nag! out of curiosity, do you know how to call paulJokerCount in the loc text?
"{C:chips}+#2#{} Chips, {C:mult}+#1#{} Mult, +1 Joker Slot",
"{X:dark_edition,C:white}^#1#{} Mult for every Paul",
"{C:inactive}(Currently {X:dark_edition,C:white}^#1#{C:inactive})",
"Paul."
}```
in your calculate you can set card.ability.extra.Emult = paulJokerCount after my previous code and will update the current joker every time calculate is run. in your loc_vars, you pull card.ability.extra.Emult as the 3rd variable, so it would be #3# in your 3rd text line instead of #1#
just wondering what happened to the 1
Oh thats weird lol, I didnt notice that
Maybe just a default for the collection screen since theres no odds in place atm?
I'd hook get_blind_main_colour(blind) in misc_functions.lua and return a custom colour, depending on what kind of behaviour you're after
Something like:
local get_blind_main_colour_ref = get_blind_main_colour
function get_blind_main_colour(blind)
local original_colour = get_blind_main_colour_ref(blind)
--example changing result
if blind == 'Big' then
return G.C.RED
else
return original_colour
end
end
If you just want to change boss blind colours, then just modify G.P_BLINDS[blind].boss_colour
G.P_BLINDS['bl_pillar'].boss_colour = G.C.EDITION, for example
Do I need to prevent it from pulling a blackhole or the soul?
is there a calculate function for blinds?
hey all! i'm trying to figure out how to make a joker that destroys unscored cards in the first hand, and there's such limited explanation in the calculate tutorial that i'm kinda just fucking around and finding out
this is how much progress I've made so far, and it's not quite where I want it to be at. any tips?
Someone help pls
G.GAME.blind.boss
So basically I insert
if G.GAME.blind.boss then?
yea
still trying to figure this out
Ok i neeed to figure out how to destroy a joker
JOKER:juice_up(0.8, 0.8)
JOKER:start_dissolve({ HEX("63f06b") }, nil, 1.6)
That's inside an event right?
SMODS.Joker({
calculate = function(self, card, context)
if context.after then
local safes = {}
for s_idx = 1, #context.scoring_hand do
local c = context.scoring_hand[s_idx]
table.insert(safes, c.ID)
end -- full_hand
for c_idx = 1, #context.full_hand do
local c = context.full_hand[c_idx]
local found = false
for _,id in pairs(safes) do
if id == c.id then
found = true
break
end
end
if not found then
G.E_MANAGER:add_event(Event({
func = function()
if G.jokers then
c:juice_up(0.8, 0.8)
c:start_dissolve({ HEX("63f06b") }, nil, 1.6)
return true
end
end,
}))
end
end
end
end
})
this code is kinda bad, but it partially works
the visual of the card dissolving happens before the scoring animation finishes, so add that to the event manager EDIT: made it listen to the event queue
yeah? i dont think it really matters as long JOKER is a card-like value
So in SMODS.Joker > calculate function I would replace JOKER with self right?
yeah, you would replace JOKER with the card you'd like to destroy
@plush cove
Weird. The joker doesn't crash the game but doesn't debuff by 0.25X
SMODS.Joker {
key = "letter_h",
loc_txt = {
name = "H",
text = {
"{X:mult,C:white}X#1#{} Mult,",
"loses {X:mult,C:white}X#2#{} Mult every {C:attention}Ante{}"
}
},
config = { extra = { Xmult = 3, lostXmult = 0.25 } },
rarity = 2,
atlas = "alphabet_atlas",
pos = { x = 1, y = 0 },
loc_vars = function (self, info_queue, card)
return { vars = { card.ability.extra.Xmult, card.ability.extra.lostXmult } }
end,
calculate = function (self, card, context)
if context.end_of_round and context.cardarea == G.jokers then
if G.GAME.blind.boss then
if card.ability.extra.Xmult > 1 then
card.ability.extra.Xmult = card.ability.extra.Xmult - card.ability.extra.lostXmult
else
G.E_MANAGER:add_event(Event({
func = function ()
self:juice_up(0.8, 0.8)
self:start_dissolve({ HEX("63f06b") }, nil, 1.6)
end
}))
end
end
end
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = localize { type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult }}
}
end
end
}
@rose dragon
works for me
probably just gotta restart the run
Still doesnt work...
ty for this! ideally I would want to be using context.destroy_card because that's the inbuilt functionality, but with all the trouble that I've been getting out of that, i'm happy enough to have this as a plan B!
I probably just need to switch to steamodded main
Ok smods main makes the joker work
btw i forgot to add the hands_played == 0
dw, I got that end covered
i actually did have my code at a similar state earlier, but i ended up dumping it because I was running in final_scoring_step (aka the timing I want to have), but then I'd try reloading the game and it would crash and give me an error
hence why I sought to rework it into the new context
Yooo!!! Do you use the cryptid placeholders? Me too. 
Also I think this joker should be rare because oh my god it seems OP for deck thinning
What if the deck is all aces? Will it destroy random aces?
I feel like it would be racist to diamonds
for some reason there's a bug in the code that i actually cant find that leaves it with like 6-12 (typically 8) cards left i cant figure out how to fix it so now it's a "balancing feature"
anyways im really struggling with ideas for my mod "alphabet jokers" since there's not much ideas that can come out from a single letter
can anyone think of ideas for the joker "i"?
all boss blinds are "The Eye"
is this a joke
yes
then can you make a non-joke idea
What are the existing examples?
do i really have to share all the code of my jokers in your dms
i mean
sure
No, you don't have to.
Sorry, I didn't saw your letter_h up there.
just send screenshots of the tooltip?
ok
x3 mult for each card of [[RANDOM SUIT]] (suit changes each round
loses x0.5 mult when reading the tooltip
A - +10 mult
B - 1 in 2 chance to retrigger an uncommon joker
C - X2 mult
D - Retrigger each played 4
E - +30 chips
F - destroyed cards give 3 dollars
G - 5 dollars when you beat a round
And the H is what you saw above
gains +1 mult for each 3 cards scored
My thought is to either go with i for icecream, i for idol, or i for invisible.
K, implemented it
What about J now?
update: I cut down on a few lines by using the new "in_scoring" function that SMODS has (as part of the unscoring calcs)
if context.after and G.GAME.current_round.hands_played == 0 and not context.blueprint then
for c_idx = 1, #context.full_hand do
local c = context.full_hand[c_idx]
if not SMODS.in_scoring(c, context.scoring_hand) then
add_event(function()
if G.jokers then
c:juice_up(0.8, 0.8)
c:start_dissolve({ HEX("63f06b") }, nil, 1.6)
return true
end
end, nil, nil)
end
end
end```
awesome
copies a random joker for one round? (as in it chooses a joker, then swaps to another joker at the end of round)
Maybe copies a random joker, then self destructs?
maybe copies the ability of the leftmost and rightmost joker and expires in 5 rounds?
Uh oh, when the H joker tries to juice up, it crashes the game
Oops! The game crashed:
[SMODS alphabet_jokers "main.lua"]:217: attempt to call method 'juice_up' (a nil value)
Additional Context:
Balatro Version: 1.0.1n-FULL
Modded Version: 1.0.0~ALPHA-1415c-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.6.0
Platform: Windows
Steamodded Mods:
1: Alphabet Jokers by Runtem [ID: alphabet_jokers, Version: 1.0.0]
2: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely]
Break Infinity: omeganum
3: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.1, Uses Lovely]
Lovely Mods:
Stack Traceback
(3) LÖVE method at file 'boot.lua:352'
Local variables:
errhand = Lua function '(LÖVE Function)' (defined at line 553 of chunk [lovely debugplus.console "console.lua"])
handler = Lua function '(LÖVE Function)' (defined at line 553 of chunk [lovely debugplus.console "console.lua"])
(4) Lua field 'func' at file 'main.lua:217' (from mod with id alphabet_jokers)
Local variables:
(*temporary) = nil
(*temporary) = table: 0x3938cf70 {alerted:true, loc_vars:function: 0x3939f7b8, _saved_d_u:true, original_key:letter_h (more...)}
(*temporary) = number: 0.8
(*temporary) = number: 0.8
(*temporary) = number: 5.90174e-06
(*temporary) = string: "attempt to call method 'juice_up' (a nil value)"
(5) Lua method 'handle' at file 'engine/event.lua:99'
Local variables:
self = table: 0x3bc03cc8 {start_timer:true, timer:TOTAL, blockable:true, trigger:immediate, func:function: 0x3967cf28 (more...)}
_results = table: 0x3978dde8 {blocking:true, pause_skip:false, time_done:false, completed:false}
(6) Lua method 'update' at file 'engine/event.lua:182'
Local variables:
self = table: 0x38e4a2c0 {queue_last_processed:745.18333333298, queues:table: 0x38f4dc78, queue_dt:0.016666666666667 (more...)}
dt = number: 0.013352
forced = nil
(for generator) = C function: next
(for state) = table: 0x38f4dc78 {unlock:table: 0x38f4dd68, other:table: 0x38f4de08, tutorial:table: 0x38f4ddb8 (more...)}
(for control) = number: nan
k = string: "base"
v = table: 0x38f4dd90 {1:table: 0x391a0878, 2:table: 0x3bc03cc8, 3:table: 0x39105b18, 4:table: 0x3b5dd6c0 (more...)}
blocked = boolean: false
i = number: 2
results = table: 0x3978dde8 {blocking:true, pause_skip:false, time_done:false, completed:false}
(7) Lua upvalue 'gameUpdateRef' at file 'game.lua:2631'
Local variables:
self = table: 0x38dd9c10 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x39bcf3a8 (more...)}
dt = number: 0.013352
http_resp = nil
(8) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84'
Local variables:
self = table: 0x38dd9c10 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x39bcf3a8 (more...)}
dt = number: 0.013352
(9) Lua method 'update' at file 'main.lua:1761'
Local variables:
self = table: 0x38dd9c10 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x39bcf3a8 (more...)}
dt = number: 0.013352
(10) Lua upvalue 'oldupd' at file 'main.lua:996'
Local variables:
dt = number: 0.013352
(11) Lua field 'update' at file 'main.lua:1788'
Local variables:
dt = number: 0.013352
(12) Lua function '?' at file 'main.lua:935' (best guess)
(13) global C function 'xpcall'
(14) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '?' (defined at line 906 of chunk main.lua)
inerror = boolean: true
deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
maybe just remove that part? it's only a visual effect, not necessary
did you self.juice_up() instead of card.juice_up()?
Which letter A looks better than others?
leftmost looks best imo
first but make the T thicker
you should also kern the T a pixel or two closer to the A
kern on the kerb
scrumptious
Shout out to reiruka
is it me or the bottom text isnt in the middle?
actually never mind, its probably meant to be closer to the black line
?
oh dang, my bad
art is too cool for an effect that simple
How would you suggest instead?
not every joker needs a five page essay for an effect (and in fact most should be as simple as possible)
it's a glorified greedy joker
and? onyx agate exists
"the thunkster" was lazy when coming up with the idea
disagree
that cycle defines what makes the suits unique in vanilla, and onyx agate gives clubs quite a clear one
It's up to me, and I decide to keep its effect this way for now.
End of discussion.
But I might tune it down to Common instead.
my mod cant relate 💔
wikipedia incident
(but also a plurality of jokers are uncommon, they make the core of the game)
Hey, I'm trying to create a joker that effective just makes glass cards go from a 1/4 shatter chance to 1/5, but I can't seem to find a way to affect the probability of only glass cards
Would anyone have any knowledge on where to start?
You'd probably need to make a lovely patch. The code for Glass Card Chance Checks are in functions/state_events.lua
thanks! I'll give it a look
I'm making a new joker for the first time, how can I find it in game to test it works properly?
download DebugPlus, hover over your Joker in the collection, and press 3
Anyone have any examples of mods that support both Balamod and Lovely/Steamodded?
but no one cares about or uses balamod these days
Bit of a vicious cycle, that one
it appears that the newly implemented unscored calculation crashes the game if you beat any blind while it's enabled
what were you using the unscoreds for?
balamod being incompatible with Lovely doesn't help
it doesn't matter if I use unscoring cards or not, just having the optional feature enabled causes blinds to crash the game when beaten
the actual unscoring calculation itself works perfectly as far as I've tested, it just also happens to crash the game when beating a blind
i was using it to try and destroy unscored cards, but it crashed the game
but i thought that was mostly because of what I was doing because the game also crashed if I destroyed unscoring cards in the final_scoring_step (for some reason. even if I do the exact same thing in the after context, it doesn't crash)
- who wants to develop for an unmaintained, lesser featured loader when there's something better
john balamod is going to be very upset when he hears this
Should I use context.main_scoring and context.cardarea == G.play
or context.individual and context.cardarea == G.play?
Hey, how's that fixed release going?
old calc isn't being promoted to a release
cryptid refactor should be getting promoted to main shortly anyway
Here's a weird thing I'm running into. SDM_0 gave me this implementation so I'm a little confused as to why the button is lining up so weirdly
Show your consumable's code?
(oops) yea
There's no other modification you do on your consumable/button?
nope, just the hooks
Mmh, maybe I forgot to give you something for that
What's the consumable type atlas size?
71 x 95
If you got a github for it rn I can look at it and submit a pr to fix it, wouldn't want to ruin your sleep scheldule
I do, but be warned it's quite the hell to trudge through. Just need to push rq
Here we are https://github.com/the-Astra/Maximus/blob/37ef6697d5eb1f174d0c651095ae2702a5f6cd77/lovely.toml#L2901
I appreciate ya 
@wintry solar i'll just go ahead and ping you on this, since you implemented it
crashes on function SMODS.calculate_end_of_round_effects in src/utils.lua
@sturdy compass Uhm I dont see the consumable type
eremel can you also check this out to see if there's a way I can do it with context.destroy_card for better timing?
Did you fork from dev?
@wintry solar
Oh oops
Lmao
Didn't know there was another branch
All g
minimus

Oooh I didn't know it was in its own cardarea, maybe it's what screwing it up
Ok found a fix
Change the padding value here between -0.2 ~ -0.25 see which you prefer
Will do. Thank ya plenty
Huh I’ll see what I can do to fix that when I’m on my pc later
Can you screenshot? Mobile code blocks are shit to read
Use context.destroying_cards and check if the card is in scoring or not
@scarlet spire never mind, should be fixed now
works like a charm! ty!
will check in the morning, thanks
does this need rebalancing?
-# ??? is a placeholder for the suit that changes
-# will adjust rarity later
That’s at most a 2X for one round that then decays
And you have no way to check what the suit is without making it worse
that's the point
you kinda have to look at the tooltip to even buy it lol
without the decay this is good wild card support
Yeah I don’t think it needs the end of round decay at all
This does give me the idea for a Joker where it permanently gives x3 Mult to a certain suit, but you don't know what suit it is until you buy it
And once you buy it, the suit never changes
help the shit is not doing the shit
im pretty sure it should be ipairs
I'll try.
pairs is fine, it's just gonna be unordered
Another question: Is there a way to check the player's chip score after everything has been calculated?
I need it for a joker
woo shit is not working i don't know anymore
i have no clue why it doesnt work tbh, everything seems fine
Exactly.
Did SMODS got updated in the past 2 weeks or so?
With mod-breaking changes and stuff?
I wanna make a planet card that tracks the amount of Stone cards played during the current ante and lvls up the its hand for each scored stone card respectively
Do I need a lovely patch for this?
i always put loc_vars below loc_txt, idk if thats the issue
do decks have calculate function
Can someone tell what's the issue here?
return { vars = { (G.GAME and G.GAME.stonesscoredthisante or 0) } }
end,
use = function(self, card, area, copier)
local scored_stones = copier or card
--Get amount of Stone cards scored this run or set to 0 if nil
G.GAME.stonesscoredthisante = G.GAME.stonesscoredthisante or 0
--Add +1 to amount of stone cards scored this run
G.GAME.stonesscoredthisante = G.GAME.stonesscoredthisante + 1
--level up once for each stone card scored this run
level_up_hand(scored_stones, neutronhand, nil, G.GAME.stonesscoredthisante)
update_hand_text(
{ sound = "button", volume = 0.7, pitch = 1.1, delay = 0 },
{ mult = 0, chips = 0, handname = "", level = "" }
)
end,
bulk_use = function(self, card, area, copier, number)
local scored_stones = copier or card
G.GAME.stonesscoredthisante = G.GAME.stonesscoredthisante or 0
local handstolv = {}
local neutronhand = "n/a"
for i = 1, number do
G.GAME.stonesscoredthisante = G.GAME.stonesscoredthisante + 1
neutronhand = "Stone Ocean"
handstolv[neutronhand] = (handstolv[neutronhand] or 0) + G.GAME.stonesscoredthisante
end
for k, v in pairs(handstolv) do
update_hand_text(
{ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 },
{
handname = localize(k, "Stone Ocean"),
chips = G.GAME.hands[k].chips,
mult = G.GAME.hands[k].mult,
level = G.GAME.hands[k].level,
}
)
card_eval_status_text(
scored_stones,
"extra",
nil,
nil,
nil,
{ message = "+" .. tostring(v), colour = G.C.BLUE }
)
level_up_hand(scored_stones, k, nil, v)
end
update_hand_text(
{ sound = "button", volume = 0.7, pitch = 1.1, delay = 0 },
{ mult = 0, chips = 0, handname = "", level = "" }
)
G.E_MANAGER:add_event(
Event({
trigger = "after",
func = function()
handstolv = nil
return true
end,
})
)
end,
}```
Pretty sure the rank should be a string
They do
using cryptid's code is just 😭
What are you struggling with?
there's plenty other things to reference
-# reference my mod
I just need a planet card lvl up a its hand 1 time for each stone card scored this ante
sure let me check other mods first
How are you tracking stone cards scored?
is there a wiki?
no lol
cryptids code just tracks how many times this planet card was used this run
Im just trying to modify it
But that’s an entirely different situation?
mb??? Idk
How could I know??
Im just trying everything
Because using a planet and scoring a stone card aren’t the same thing
Why would you think they are?
Because everything is possible
idk how Balatro functions
everything is possible but everything is not the same
truly
someone should turn this gif into a joker ngl
thats my single braincell
+1 chip
same 😭
and since i'm the one you're parasitically attached to at the moment i guess i have to explain how to think
you need to tally every time that a stone card is scored
98% of Balatro players can't think?
this needs to happen even if you dont have the planet card, so you need to do this outside of the planet card itself entirely
thats not wrong, most of us only know that big numbers = goog
Sorry, what's «tally»? I don't know this word
Count
"count"
tnuoc
Thanks!
you'll need:
a global variable to serve as the counter that gets saved to the save file (anything put in G.GAME gets saved iirc)
a function that hooks card calculation in some way to count each stone card that gets scored to the above counter
another function that resets that counter at the end of a boss blind (when the ante increases)
then you can use that global variable to be the amount of times you level the hand
there i think that's everything
code part's up to you kid i'm not writing your mod :)
😢 autumn why you so mean
"kid"
Im a 24 yo med student bruh
wee bab
so I'm practically an infant-?
yes
im my dad's sperm
life's just started
about to participate a race soon
thats diabolical
heard its life-changing or smt
everything before this was just lore
i aint wrong tho ❤️
I think I might just not exist yet
Thanks regardless, you at least gave me the blueprint of what should I do
You actually really helped me with just explaining how planet cards work
your dad's body is still generating you in his ballsack, patiently wait for ur turn pls
actually, am i gonna get banned for that diabolical statement
💀
if I'm not real
worse
i'm silently judging you
damn.
(well not silently any more)
steamodded is still on 0.7.1 or some shit like that
if aure didn't exist imagine the balatro modding community
it would be like
bunco
or something
crazy timeline
could have been balamod if there never was a 1.0 rewrite
whats the difference between balamod and steamodded anyways
raw lovely
People would modify the exe and every mod would be a standalone 
if there wasnt any john smods, we would all be coding using ngl
I mean 0.9.8 was dominant enough but I already had plenty of influence at that point
Hmmm, should I make shop functionality for smods today? 🤔
we'd be diverging off 0.7.1 which is total infancy
Just wondering Eremel is the returning level up calculate still on your todo list? 🙏
It is, was wondering the best way to do it, I think a separate return value of level_up_hand would work best?
I guess, as long as the UI doesn't break I'm happy with anything
Oh that bit too
Yea 😅
ooh nice
Can I use var:lower() instead of string.lower(var)?
i think its funny asf
hello guys
bump just in case there are any teto fans who can make the teto balatro cover
hi vichum!!
"if your entire deck has more cards with Diamond suit than cards with non-Diamond suits."
How do I word this better?
"than other suits combined"
I'm taking that part
"if Diamond cards in your entire deck are more than other suits combined"
How about this?
i'd say to do "if more Diamond cards" instead of "are more than"
idk might otherwise think to add up the values of each card or something?
"if your entire deck has more Diamond cards than other suits combined"
yeah thats good imo
Since the context would be at end_of_round, "entire" might be unnecessary.
I'd go with "full deck"
create_card = function(self, card, i)
local rng = pseudorandom('void_pack')
if rng > 0.9 then
return {
set = "Enhanced",
area = G.pack_cards,
skip_materialize = true,
no_edition = false,
enhancement = "m_fm_transcendent"
}
else
local void_enhancements = {
"m_fm_overshield",
"m_fm_volatile",
"m_fm_devour"
}
local selected_enhancement = void_enhancements[math.random(#void_enhancements)]
return {
set = "Enhanced",
area = G.pack_cards,
skip_materialize = true,
no_edition = false,
enhancement = selected_enhancement
}
end
end
Trying to make a custom Booster Pack that only spawns my mod's enhancements, it works, but for some reason it doesn't grant any editions or seals whatsoever, anything I'm missing?
does somebody know why this patch is not working?
[manifest]
version = "1.0.0"
priority = 0
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
position = 'at'
match_indent = true
payload = '''
if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and scoring_hand[i].base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then
'''
i know balatro detects it because ir gave some error that I resolve
but if i check the dump in the lovely folder there is nothing in there
is teto a vocaloid artist or something like that?
how's your mod folder structured? If it's not in there, either the pattern's already modified by another inject, i think
this is how the folder looks
should i just give it more priority?
Smods deletes almost the entirety of the default calculation code
is that why the dump is like 300 lines shorter?
Probably yeah
every time i try a new approach to do the effect that i want, it gives me a different reason to make it undoable 😭
are there any good examples of the usecase for the quantum enhancements?
Is there a function to make cards count also as other ranks?
There isn’t
:(
the idea of this joker is that it checks the cards played for unique ranks each cycle
it's only checking once for some reason
(haven't implemented the mult function yet though)
maybe I'm misreading something but I think it'll never enter the for loop
it will always be for x=0, 0 do
oh no, sorry it will do one loop
I think you might need a while loop for your case
you do need a while loop
over which for loop?
also if numberarray == {} never hits
im trying to make a joker that gains 2 mult for each 2 scored but it keeps crashing when i play a 2 ("attempt to index field "other card" [a nil value]
this is my code rn (be nice pls, first time coding anything xd)
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_mod } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
mult_mod = card.ability.extra.mult,
messege = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } }
}
end
if context.other_card:get_id() == 2 then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
return {
messege = 'Upgraded!',
card = card,
mult = card.ability.extra.mult
}
end
end
you can't use a for loop while modifying the array you're looping over
please put that in a codeblock
```lua
-- code here
```
anyhow you're missing a context check before accessing context.other_card
in your case, if context.cardarea == G.play and context.individual and context.other_card:get_id() == 2 would be the correct check
also you misspelt message
(your current code also gives mult both when the joker triggers and when the 2 scores)
oh because of the context.joker_main ?
does smods allow for changing a consumable set's materialize color? i don't see it documented but i figured i'd make sure before resorting to patches
is there a context for when you enter the shop?
then this effect is impossible?
i mean i cold do an ENORMOUS patch to it to make effect
but if i can not even do the glass card patch i doubt i can do this yet
the way rank is checked doesn't allow for the same effects as pareidolia or wild card unfortunately
i see
in theory it could be changed, but then it would require a patch to every part in the game's code where a rank is retrieved and checked
and it would make incompatible with other mods
yeah but you probably wouldn't be able to do it in the first place
bc of smods very likely patching over some of those parts
it's unfortunate but it is what it is
im currently having a even more simple problem because of that
i trying to patch a function in state_events but smods seems to cut like 300 lines of code in that file
yeah i've run into the same problem before
it's possible to work around it, what do you have in mind
you should check what the new code looks like and just apply the patch to that
this is the effect that im trying to do
the glass part, ive already made a hook for the lucky card part
ah, that's tough
ive wrote this patch
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then"
position = 'at'
match_indent = true
payload = '''
if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and scoring_hand[i].base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then
'''
but that part doesnt exist in the lovely dump
yeah, bettercalc stuff i think
maybe this actually works? i've never tried it
bettercalc stuff indeed
patching works if your prio is higher
yes smods changes that part of the code @past forge
smods moves card destruction checks to its own util function
is there a mod i can take a look at that has some kind of a "quest" that is constantly checking for its conditions to be met?
SMODS.calculate_destroying_cards, that's what you need to patch (target: '=[SMODS _ "src/utils.lua"]')
what's the better calc version for this?
what is this condition of yours
because you don't want to constantly check if possible
What are you trying to do?
i wanted to make a quest type card that gets activated after you change the suits of 3 cards
Just store the progress in a extra var for the card tbh
Make cards with a certain ability score, like stone cards.
is that a reply to me or the other guy sorry im not so proficient in this
neither because i realize thats not what you were asking 💀
hahahahaha
Hook SMODS.always_scores
this will make my two jokers that act on unscored cards very happy
i imagine you'd need to hook card:set_base or something
dunno if that'd cover all methods to change cards like that?
like making a patch to the dump?
How would I go about checking to see if a card is facing down? self.facing == 'back' ain't working for me.
function Card:init(...)
original_card_init(self, ...)
if G.GAME.selected_back ~= nil and true then
self.sticker = get_deck_win_sticker(G.GAME.selected_back.effect.center)
end
end```
ill try now
For the glass effect you can just handle it in your jokers calculate function
(..."and true" is a placeholder for self.facing == 'back')
You don’t need to actually change the roll, you can just force destroy them
Oh it’s never break
Nvm
card.init is called when the card is created (not facing down)
How can I do that to these?
do what aure said
why do I see so much card.SMODS.thing
Yes, but I want to affect just the backs of the cards
...or actually now I think about it, that doesn't work like that, does it. Aight, ta.
No you hook the function to return true when the card has the suitless property
This text feels a little awkward..
[X1] per hand and discard
Sets hands to 1 and discards to 0 for the blind
(Currently [X#])
Any ideas?
so this should work?
[manifest]
version = "1.0.0"
priority = 0
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/utils.lua"]'
pattern = "if scoring_hand and SMODS.has_enhancement(card, 'm_glass') and not card.debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(card.ability.name == 'Glass Card' and card.ability.extra or G.P_CENTERS.m_glass.config.extra) then"
position = 'at'
match_indent = true
payload = '''
if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and not (SMODS.find_card("j_toyr_four_leaf_clover") and scoring_hand[i].base.id == 4) and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then
'''
"When you select a blind ..." is how I'd rephrase that
When blind is selected,
Lose all Discards and all but 1 Hand
Gains X1 Mult for each Hand or Discard removed
(currently x)
When Blind is selected, sets hands to 1 and discards to 0
+X1 Mult for each hands and discards removed this Blind
(Currently X1 Mult)
reword if scaling
DONE IT
nice! that must feel cathartic after trying to figure it out for so long, haha
Settling on this for now, thanks Myst and Marie
yea makes sense, how could i check for cards that only change their suits and not their ranks?
the function takes strings like "H_2" right?
just grab the number part and compare to the same on the cards card_key?
maybe that'll work?
ohhh thanks so much
Destiny 2 reference????
Excellent
i am making a destiny 2 mod if you wanna check that out
oh hell yeah i'd love to
It's called Fatemaker you can find it in the modding forum
i'm still fighting burglar on the extra hands which is annoying
Where does the game save G.playing_cards to file?
Is there a way to disable and enable Suits accordingly to the chosen deck ?
how can i get started modding? i know java and python, and have never modded before
thank you!
no way bro is john steammodded
where should i code it? notepad, visualcode?
thanks!
vsc 🗣️
yeah vscode works well enough, make sure to install a lua extension
thanks, any links to a lua extension i can get from ghere?
you can just search for lua in the extensions tab
kk
Before I just make a new Strength, is there a way for me to modify the original strength to make it so that if it's a certain suit and rank to go to a different one.
Example: For Mahjong, can I change it so that instead of 9 -> 10, it's 9 -> 1?
I guess you could change the rank's strength effect on the fly, maybe that needs a more flexible system too
what does nominal mean here (conntext: its in the card:set_base function
base chips
so how would i do that? A lovely patch?
Hi guys, just wondering would making an addon mod for a mod be possible/easy
like i mean using rarities, types and other things from another mod
i guess so, just modifying rank data won't cut it because that's not run data
Yes just make sure to add the other mod as a dependency and set the priority so that your mod loads after the original
o thanks
Also, is it possible to just disable the suit-changers? I think I could just do the banned items like in a challenge deck but thought I'd ask
Or like... "If Rank = Invalid" then make it impossible to use
Where does the game save G.playing_cards to file?
true
now im trying to figure out if there is a way to show a message on the joker card when it prevents shattering or when it triggers the lucky card
that should be really doable if you've managed to already do those checks
just check if the joker's present and pop a card_eval_status_text()
card_eval_status_text() works the same as the message?
no, it'll contain message
i have my editor closed, so I can't grab a quick example, but if you look for it, there should be good examples in the lovely dump!
done, it was easier than I though :)
Great
What's the mod you're working on btw? Just joker ideas you've had, or is it themed?
well, by the moment is just joker ideas, but keeping it pretty vanilla. Im doing a pack for practicing because I met the artist (toyrapple) in the fanart channel of this server
he knew how to draw, i knew how to code, and we teamed up to make this set of jokers
wasn't prepared for this to force me to figure out lovely patching 😭
that was me yesterday
i was scared to patch
but now, im patched
(i just wrote 17 lines in the .toml)
It's luckily not that difficult, it just seems scary, haha
at some point i gotta learn lovely patches too
it's pretty easy just gotta find where to put your act of vandalism
true
the worst part about patching is that smods does patch the code before you, so youll have to work like you are working a patched code
SMODS.Joker{
key = 'twostep',
config = { extra = { mult = 2, mult_mod = 2 } },
loc_txt = {
name = 'TwoStep',
text = {
'Gains {C:mult}+#2#{} Mult',
'for each scored {C:attention}2{}',
'{C:inactive}(Currently {C:mult}+#2#{C:inactive} Mult)'
}
},
atlas = 'twostep',
pos = {x = 0, y = 0},
rarity = 2,
cost = 6,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_mod } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } },
mult_mod = card.ability.extra.mult
}
end
if context.cardarea == G.play and context.individual and context.other_card:get_id() == 2 then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
return {
message = localize('Upgraded!'),
colour = G.C.MULT,
card = card
}
end
end
}
i got the joker to work as i wanted it to, but how do i update the mult in the description? also the message thing doesnt work.. sorry to bother u again :s
welcome to the world of variables!
just pray you're trying to patch a piece of unpatched code :^)
you should put #1# in the second variable i think
yea sorry im new to all this, i tried using some of the examplejokers but cant really find out how
dw, we are here to help
so #1#, #2# and so on are the order in which the variables appear in loc_vars
OHHHhh
so #1# would be the mult, and #2# would be the mult_mod
text = {
'Gains {C:mult}+#2#{} Mult',
'for each scored {C:attention}2{}',
'{C:inactive}(Currently {C:mult}+#1#{C:inactive} Mult)'
}
I think you want your description to be like this
yeah that worked thanks alot :D
uhh,, adding custom calculate_joker calls shouldn't break anything using correct context checks right (i apply a custom context variable)
if context.cardarea == G.play and context.individual and context.other_card:get_id() == 2 then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
return {
message = localize('Upgraded!'),
colour = G.C.MULT,
card = card
}
```lua
any idea how i get the Upgraded to pop up when 2's are scored?
a lot of people helped me here, so dont fear to ask your dumbest questions
question for y'all; how are you debugging jokers/spawning them in?
DebugPlus go to your mod and press ctrl + 3
DebugPlus mod, go into colleciton and CTRL + 3 to spawn it
there is a localize message for it, let me look for it quickly
card_eval_status_text
message = localize('k_upgrade_ex')
If you use this one, is the one already made in the source code, and it will be translated if you have the game in another language
i also have toomanyjokers mod
if you press T, it would give you a menu when you can spawn any card by hovering it and pressing c
i like card flippy :)
https://awoo.download/qTu2LBh04.mp4
my timing on flipping, changing ranks and messages is horrendous
btw, how do you guys screen record? my obs just lags the shit out of my humble laptop
it's pretty jank but hey it looks cool 😭
would this not be how to make 1/2 odds, and display it properly? This card seemingly repeats 100% of the time atm, and also displays as "1/+nil"
Gotta love attempting to create a new joker for the first time just to test to make sure I actually am able to, and getting an error when I try to hover over it in the collection. Didn't crash unitl I added the loc_vars bit, got the following error:
attempt to index field 'extra' (a nil value)
SMODS.Joker{
key = 'Rekoj',
loc_txt = {
name = 'Rekoj',
text = {
'Gives {X:mult,C:white}#1#{} Mult'
}
},
atlas = "Rekoj",
pos = {x = 0, y = 0},
cofig = {extra = {mult = -4}},
loc_vars = function(self,info_queue,center)
return {vars = {center.ability.extra.mult}}
end
}
Thanks, got the joker fully working now. Starting to understand everything a bit better now haha
you can give minus mult to cards?
Not sure. Still crashed when I made it positive though
this is jank
what i did to fix that is to put the actual card change before the unflip call
Slap a delay(0.1) on that thing
-- effects :3
local percent = 1.15 - (i-0.999)/(#context.scoring_hand-0.998)*0.3
scored_card:flip();
play_sound('card1', percent);
card:juice_up(0.3, 0.3);
-- Flip the card back
G.E_MANAGER:add_event(Event({
trigger = "after",
blockable = false,
delay = 0.2,
func = function()
SMODS.change_base(scored_card, nil, new_rank)
play_sound('card1', percent);
scored_card:flip();
scored_card:juice_up(0.3, 0.3);
return true
end
}))
return true
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.14, func = function()
v:set_base(G.P_CARDS[suit_prefix .. rank_suffix])
return true
end}))
local percent = 0.85 + (i-0.999)/(#G.hand.cards-0.998)*0.3
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0, func = function()
v:flip()
play_sound('tarot2', percent, 0.6)
v:juice_up(0.3, 0.3)
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.15, func = function()
v:flip()
play_sound('tarot2', percent * 0.9, 0.5)
return true
end}))
this is what i did
maybe is the order?
should the fist flip be before the set_base?
your first event where you change the base, gets called first
it waits for that to return to call the second, and then the third
if you remove the first G.E_MANAGER:add_event and move the v:set_base to the last G.E_MANAGER:add_event (before the v:flip) it should work
Debug returns this as the problematic line:
return {vars = {center.ability.extra.mult}}
Hello, quick question: Is there a way to access vanilla balatro's files from a mod?
in what way? code? assets?
you can access the vanilla files without mods, by unzipping the application with 7zip
Just call them the same way the base game does?
If I try to call it by the file name the path isn't right.
What are you trying to do, play a sound?
its just like this play_sound('paper1')
I need help figuring out card areas and ui elements they make no sense
since the matter is on the table
how do i play a sound that i have in my assets>sounds folder?
You add the sound
problem is:
It looks in my mods directory instead of balatro's.
why is it trying to open paper_1.ogg instead of paper1.ogg
did you put the name right?
because i stupid
happens
key = "key",
path = "file_name.ogg",
})```
That’s also not your mod directory path and if your mod is structured that way it won’t work anyway
thats for custom sounds, not vanilla ones
Oh
ah it works now ig?

Paper_1 is a vanilla sound?
my bad then
how?
sorry for the inconvenience
paper1 is
Oh
@past forge
thanks
I love typing when I think I have the search bar open
in: 💻・modding-dev g.STATE
be like
Bu t yeah I'm going crazy
Card areas are stupid
Yeah indont understand why it decides it needs to have gravity
Code?
Ok get the mods
this was us rn
what were we talking about
ah yes
i dont have that in loc
oh wait
the problem is the message, not the sounds
Localisation also why a table just make it a string
ngl should i work on an API to simplify the additions of animated images (through sprite sheets)
Tables are for multiple values
That would be epic
is there a way to apply a sprite directly on top of a joker, without it floating above like a soul sprite
i guess you could just update the whole sprite
well the issue is that i want the sprite to be partially off of the joker itself
but i still want the hitbox to be that of a normal sized card
so i either need to apply the sprite on top or figure out a way for a normal sized card to use a larger sprite
Remove the assets/sounds/ from path, it's added automatically
i did that before and it crashed the same way
its looking for a resources instead for an assets folder
registered where? i just put it there in the main.lua
then i access it like this
