#đ»ă»modding-dev
1 messages · Page 26 of 1
oh
so it checks if the game speed is 3 and if so, selects the 5th option (which is game speed 3)
if the game speed is different, the check doesn't work
thank u for the explanation
np
Aure :((
you can put literally anything inside a gameobject constructor
Im gonna put you in a gameobject constructor
you could set arbitrary_value_24 = 24 in your constructor and then your gameobject will have self.config.center.arbitrary_value_24 and it will be 24
(assuming it is a center, otherwise accessible however appropriate for that object)
the whole point of the new constructor taking a table is so you can just cram whatever the fuck in there
SMODS.Joker{
...
AutumnMood = "yeehaw"
...
}
đ
that would work
CowboyMood
yeehaw.
im outside your window
*inside
how come I don't see you there
technically we're all outside your window
unless you're inside
When I read your text you're inside my head
everyone on earth is outside your window, even you
nobody has ever been inside your window. that would be foolish behavior.
gdi autocorrect making me seem british
did someone say foolish?
Ok but if you re between the window and the window frame are you inside or outside the window
you are in the void
Frick
no u
the fool's cousin, the dummy
Btw now I can officially call myself a Steamodded dev lol đ
very exclusive club
Where did you say the yatch was btw?
is it bad that my brain subbed in the Beleren font in that screencap bc im so used to seeing it in my game
the yatch?
tbf i am wearing sunglasses rn cuz its heathenously bright out today
The luxurious boat
getting back more ontopic here, should i be looking to release thac/oapi/emojiokers for 1.0 soon? or are there more breaking changes anticipated and i should just hold on a while
(its spelled yacht btw)
oh
i think we're mostly good on breaking changes, but you never know
except sound.lua, not quite happy with where that one's at
well, i dont touch sounds
so thats good
i do only have a few things left before thac is Ready and emojiokers is like 65% shitpost so
and i just dont want to get caught in a weird limbo state where it only works on like one alpha version yk
i dont know if that'll be an issue exactly; feder implemented the stamps as their own gameobject class (the main thing i have left is just integrating his ported code lol, so i dont quite know the intricacies of it yet)
shoutouts to itay for being awesome again
they could have a shared parent class like centers do, but that seems like it could work out either way
i dont know! one of the many great mysteries of the universe :^)
can anybody tell me the blind api commands for steamodded 1.0?
I haven't gotten around to writing docs for that yet, for now you can look them up in lovely/blind.toml
oh alr
Joker idea: Powerplant - for each joker you have, you get +2$
You're not invited
ok
main.lua L1926
bruh is this actually a harmless typo?
lke it should be planet_options right
Racket and Wheel suits?
k got it imma delete the code block
What rule was that
It's a historical deck
gold suit when
no redistribution of vanilla code
What were you redistributing?
I feel like if itâs small enough it doesnât violate the rule, since I imagine itâs to prevent from straight up redistributing the source code
i dont even know if its injected by steamodded but whatever
I think if someone would reconstruct Balatroâs source code it would be by unzipping it
even steamodded contains some code that's basically taken unmodified from vanilla code
i believe lyman was referring to rule 3
as cryptic and beyond mortal comprehension as it is
even less so then... sending a code snippet does not qualify as debugging
ah yes, some code...
stares at the lovely dumps
with steamodded 1.0 idk how to change the loc_vars when taking ownership of a joker
SMODS.Joker:take_ownership('green_joker', {
config = {extra = 1, mult = 0},
name = "cry-Green Joker", --will prevent old calculation code from working
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra,center.ability.extra,center.ability.mult}}
end,
calculate = function(self, context)
if context.discard and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then
local prev_mult = self.ability.mult
self.ability.mult = math.max(0, self.ability.mult - self.ability.extra)
if self.ability.mult ~= prev_mult then
return {
message = localize{type='variable',key='a_mult_minus',vars={self.ability.extras}},
colour = G.C.RED,
card = self
}
end
end
if context.cardarea == G.jokers and context.before and not context.blueprint then
self.ability.mult = self.ability.mult + self.ability.extra
return {
card = self,
message = localize{type='variable',key='a_mult',vars={self.ability.extra}}
}
end
if context.cardarea == G.jokers and not context.before and not context.after then
return {
message = localize{type='variable',key='a_mult',vars={self.ability.mult}},
mult_mod = self.ability.mult
}
end
end
}):register()
Here's the relevant code, but the localization doesn't work
Aure has commented their opinion that rule is about not attaching a debugger to the game, but incidentally patching a bug would be fine
not that I think it'd change anything, but in case it does, remove :register()?
nvm I know what this is
it wrongly assumes you're not touching localization and setting generate_ui to 0
it should work with loc_txt = {}, but it's something I should fix
didn't work with that, and this is what happened when I put a garbage key/value pair in loc_txt
updated Steamodded and now Stake API crashes
yippee
i moved some things around with the way stake text works
self.shared_sticker_perishable = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["cry_sticker"], {x = 4,y = 4})
and this line of code crashes the game again
the main description goes in loc_txt.description, and the sticker description goes in loc_txt.sticker
uhhh
local sticker_atlas = {object_type = "Atlas",
key = "sticker",
path = "sticker_cry.png",
px = 71,
py = 95
}
atlas code if that helps
this part of the code usually breaks every few steamodded commits so I'm used to it by now
same old attempt to index field 'atlas', a nil value
I'm putting this near the end of G:start_up()
just to be sure, after initSteamodded(), right?
yes
# New perishable texture
# Quartz Stake - register pinned sticker
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "set_profile_progress()"
position = "before"
payload = '''self.shared_sticker_perishable = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["cry_sticker"], {x = 4,y = 4})
self.shared_stickers['pinned'] = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS['cry_sticker'], {x=5, y=0})'''
match_indent = true
this was my patch file
oh wait
it's probably crashing becuase I removed the code that registers it
lmao
false alarm
yeah that was in my stake file which I just removed for now
ty for the help, works perfectly now
green joker description still isn't working, but I'm fine waiting for that bug to be patched
try with the commit I just pushed
SMODS.Joker:take_ownership('green_joker', {
config = {extra = 1, mult = 0},
name = "cry-Green Joker", --will prevent old calculation code from working
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra,center.ability.extra,center.ability.mult}}
end,
calculate = function(self, context)
if context.discard and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then
local prev_mult = self.ability.mult
self.ability.mult = math.max(0, self.ability.mult - self.ability.extra)
if self.ability.mult ~= prev_mult then
return {
message = localize{type='variable',key='a_mult_minus',vars={self.ability.extra}},
colour = G.C.RED,
card = self
}
end
end
if context.cardarea == G.jokers and context.before and not context.blueprint then
self.ability.mult = self.ability.mult + self.ability.extra
return {
card = self,
message = localize{type='variable',key='a_mult',vars={self.ability.extra}}
}
end
if context.cardarea == G.jokers and not context.before and not context.after then
return {
message = localize{type='variable',key='a_mult',vars={self.ability.mult}},
mult_mod = self.ability.mult
}
end
end,
loc_txt = {}
})

ignore that I accidentally pasted the image 4 times
can lovely inject into the shaders?
oh nvm i see what's going on
i got my os and objs mixed up
fixed
it works
this is why i just give my variables overly descriptive names
m
me when i card.config.center.extra.arachnei_sap.base_stats.mult
i should probably hide my variables and stuff in a table so they don't conflict with other people doing the same thing as me
i might do it too much but yea its good practice
I think you forgot a config there
I do that for Ankh, but for Cryptid I just prefix them or load them from a file
Thatâs what I do
do I understand correctly that this injection should allow me to use remove from deck function in joker's constructor?
EDIT: tried and yes it does allow me
i still don't understand how the loyalty card works, i'm trying to use its code for a joker i'm doing but idk what is wrong
here is the code of the joker i'm trying to make using loyalty card as base by replacing the Xmult with chip_mod
SMODS.Jokers.j_cheesecake.calculate = function(self, context)
if context.loyalty_remaining then
if self.ability.name == 'Cheesecake Bomb' then
self.ability.loyalty_remaining = (self.ability.extra.every-1-(G.GAME.hands_played - self.ability.hands_played_at_create))%(self.ability.extra.every+1)
if context.blueprint then
if self.ability.loyalty_remaining == self.ability.extra.every then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}},
chip_mod = self.ability.extra.chip_mod
}
end
else
if self.ability.loyalty_remaining == 0 then
local eval = function(card) return (card.ability.loyalty_remaining == 0) end
juice_card_until(self, eval, true)
elseif self.ability.loyalty_remaining == self.ability.extra.every then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}},
chip_mod = self.ability.extra.chip_mod
}
end
end
end
end
end```
What are you having trouble understanding about Loyalty Card?
hm, see the if context.loyalty_remaining?
its already there
the joker will only activate if context.loyalty_remaining is true
so, check where in the code calculate_joker is called when context.loyalty_remaining is true
is reloading after crashes (by pressing r) broken for anyone else?
gonna apologize for using the socratic method on you, you probably just want help. -> context.loyalty_remaining isn't ever set by the game, so your function is basically one giant if false
IIRC itâs just a number. The Joker remembers the remaining loyalty, and when it reaches 0 it grants the benefit, then resets
so if context.loyalty_remaining true?
er, no
I mean, they didnât show the definition of their Joker
Your Joker only has the default Joker variables and the ones you define
context never has loyalty_remaining
What you want is to track the number inside your Joker
your card does^
If you defined it, that is
ok this is just getting confusing
I only want the joker to give 350 chips after i played 3 hands
change line two to if context.after then
Is that the context Loyalty Card uses?
yes
I never know whatâs after and whatâs neither before nor after
wait no
it's not after
I misread my collapsed code
it doesn't look at context
it's literally the first one in the stack
so just delete line 2
it doesnât look at context
pic shows it looking at context
what does else means
it's in the if/else chain
and whatâs the if condition in the chain?
if context.before then do collapsed stuff, elseif context.after do collapsed stuff, else do loyalty card
that boils down to context.joker_main
So what does that imply about the condition when Loyalty Card executes?
I think thatâs only used for Telescope
Or Observatory
I forget the name
I donât think joker_main matters at all here
But context.before and context.after do
run it and print out context
i mean this is the entire sequence
it'll have joker_main, it's just not explicitly named
I mean, itâs there, but it isnât used
But AFAIK so do other calls
yeah but other calls won't get that far
the block is defined by the fact that it isn't any of the above
Exactly
which breaks when you add other contexts
loyalty card is in the bucket of things that don't need to happen at other contexts
the truth of the matter is that it needs to happen in joker_main, the game just doesn't say that
Thatâs why context.before and context.after are looked at by Loyalty Card
it says it's none of the above
Because if Loyalty Card runs those are not true
Itâs in the bucket of things that are context.cardarea == G.jokers and not anything else
yes
So it does care about context.before and context.after
no
yes
it specifically doesn't want context.before or context.after
It doesnât run when context.before evaluates to true
there are 7 different calculate calls with cardarea = G.jokers
Therefore it cares about it evaluating to not true
one is remove_playing_cards, which is somewhere in the above stack
Idem for context.after
one is before
oh I see what you mean
one is edition
it should be not context.before and not context.after and context.joker_main
one is also remove_playing_cards
The last one isnât necessary
one is debuffed_hand
one is after
and one is joker_main
the only one that reaches is joker_main
Itâs if context.cardarea == G.jokers and not context.before and not context.after
At least natively
if context.joker_main then works
it's not equivalent when there's other context calls, but that's when the vanilla code breaks down
I think it still needs the cardarea check
no
yes
this gets executed in line with jokers in joker_main
aka the else block of doom
speaking of the else block of doom
for custom editions how am I supposed to hook their calculation into it
I prefer localthunkâs if-then-elseif Tower of Babel
I'm actually using the incorrect patch in steamodded as of now, now that I explained all that
I need to change that else to account for joker_main and added context just aren't an issue
By the way, I think a short paragraph on how to add contexts would be helpful
Or at least âafterwards hook this function and add your context to itâ
end_calculate_context?
THAT'S WHAT I JUST WENT ON ABOUT
that function is useless
it's a dumb inverted check that boils down to context.joker_main
I mean except it can have not context.joker_main
Oh cool
the tower of if statements is annoying. I have been thinking of doing a scoring overhaul instead of just messing with enhancements and Stone Cards
just gotta come up with a good structure
excluding custom contexts makes it slightly less annoying, but yeah it's pretty bad
ah, I'd support adding custom contexts. I want mutual exclusion though
the thing with overhauling is that every update of the game requires changes on our end
ah, I mean making sure custom contexts don't infiltrate the joker_main section, which is what I just did
I see
ok, desired requirements: I want it to be easy to tell when a joker will activate, and easy to write a joker that just does one thing in one context
it's always been possible to just use context.joker_main, it's just that we didn't notice
I wonder what that context name means though
joker_main ah yes of course thunk
it means the plain old regular joker scoring phase where things like mult on jokers themselves triggers
take jimbo's +4 mult
that's what happens there
but yeah the name is bad
Except not there there because AFAIK they donât use calculate
They just have a non-extra variable
that is in fact false
the meaning of config.mult is void, the implementation is up to you
similar is not true of config.h_size
But why didnât thunk define functions for individual Jokers rather than the endless tower;_;
anyway was thinking about doing something like calculate_joker.context_A.sub_context_B or something. use the context as a key ensures mutual exclusion
But donât you need to manually increase and decrease hand size?
you could ask why thunk used if statements in EVERY FUNCTION
eh. not the worst, it's forgivable still
rationalize all centers
Iâm just curious about calculate_joker because it seems like the obvious use case for what I said
christianize all the kingdoms /ref
so what do people think of using context as a keying structure instead?
imo it's less readable than
calculate = function(card, context)
if context.whatever then
end
end
What do you mean?
you have to keep in mind some jokers need multiple contexts
Iâd like if Lua had Juliaâs type system
if you want typing in Lua... actually you can get it with annotations and the lua language server on vscode right now
not Julia but hey
Thereâs a trick where you can define a type and then a function with the same as another function, but that takes that type as an argument, as a way to select for cases without using ifs
ok, how about having a context.type field containing an 'enum'
(w/ annotations)
type args, ha
no
I think overhauling the calculation system can wait
For now Iâd rather have it working
appreciate the joke there
Whatâs a type args?
nah
man I haven't programmed in a static typed language in ages
at a basic level, List is a "function on types", like given int as a type, List<int> would be a type
and T is a type parameter / type argument
i mean a context.type sort of enum-driven system can work, but I think it's fine as is and can wait for now
yeah
the fact we have calculate functions separated out for each center is already so much more readable
So a parametric type rather than a parametric function?
To be fair I donât remember the name for the Julia functions that can depend on a type like that
I just called it parametric like parametric types
actually both use "parametric types"
tbf parametric functions are similar
just in different ways
so yeah, a copy(x) function taking x of type T and returning type T, the T would be another example
the actual syntax might like copy<T>(x: T) -> T or something
Is that Java?
...no
...
java is awkward
Ah wait is that a Julia anonymous function
I donât exactly recognize that syntax
I donât remember ever typing anonymous Julia functions
Is that even possible?
that's not an anon function
the syntax isn't even the point here
I don't mind reading that as pseudocode even if it's valid in some lang
Is it valid in some language or not?
I thought it was
But I just didnât know which
it would be valid in Rust, maybe, but I'm just using the most common notations
it doesn't even really matter if it's valid, if we understand what it means
:p
the idea is, in my fantasy programming language, you'd call that thing as copy<int>(5). or just copy(5) most likely, the int argument will be inferred
Iâm still not sure because it looks close to Julia but isnât Julia so itâs messing with me
it's not Julia at all
I got that already
now why would you copy an int
But my parser is guessing itâs Julia to try it first in a naive optimization heuristic and failing, then getting too confused to revert to parsing it the traditional way
you may want to read https://docs.julialang.org/en/v1/manual/types/#Parametric-Types then
however julia's docs seem quite complex, so
Itâs been a while since I used Julia frequently
Current place uses Python (unfortunately for me)
(though still better than other options)
oh, my example actually works perfectly in python
Eh, except for macros which I never learned the rest was ok
just replace <> with []
Huh
Iâve never seen that in Python
Is that new?
Or is it like
funnily enough Python's bolted-on type system is in some ways better than some other languages' actual type systems
Cython
it's type hints, technically
much like typescript, which won't help you at runtime, but forces you to write cleaner code instead... but then again js by itself is a crime against humanity
okay, i think i got a better idea for the joker that doesn't involve the loyalty card... i guess
did you not try context.joker_main?
i did put it in the start
idk if it worked
like this?
SMODS.Jokers.j_cheesecake.calculate = function(self, context)
if context.joker_main then
if self.ability.name == 'Cheesecake Bomb' then
self.ability.loyalty_remaining = (self.ability.extra.every-3-(G.GAME.hands_played - self.ability.hands_played_at_create))%(self.ability.extra.every+1)
if context.blueprint then
if self.ability.loyalty_remaining == self.ability.extra.every then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}},
chip_mod = self.ability.extra.chip_mod
}
end
else
if self.ability.loyalty_remaining == 0 then
local eval = function(card) return (card.ability.loyalty_remaining == 0) end
juice_card_until(self, eval, true)
elseif self.ability.loyalty_remaining == self.ability.extra.every then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}},
chip_mod = self.ability.extra.chip_mod
}
end
end
end
end
end
end```
oh my god, i'm feeling so dumb right now
SMODS.find_card is a nice addition
:( angy with myself
no longer do I need to put prefixes in my joker names
did it work?
in fact you don't need internal names at all (for the most part, except for cases like green joker earlier where you need to get around the original code)
yes

now i cant make the loc_def work >:(
the infamous loc_def
function SMODS.Jokers.j_cheesecake.loc_def(card)
return {card.ability.extra.every + 1, card.ability.extra.chip_mod, localize{type = 'variable', key = (card.ability.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive'), vars = {card.ability.loyalty_remaining}}}
end```
what doesn't work about it?
are there any changes to SMODS.end_calculate_context(context) in joker's calculation? I thought I saw commit about that on github
Tried creating a new account
Idk but earlier aure mentioned one can just check for context.joker_main
@night pagoda
would that be the same thing essentially?
by that I mean do I just replace everything with it and it should be fine without any additional changes?
ty!
hm. after working on enhancements a bit more, I feel that making a calculate_enhancement function is somewhat misguided. What kinds of enhancements do people want to make?
something like X-Card, for example, modifies getting the card's rank, it doesn't need calculate_enhancement
thunk why
Can I DM you
wait nvm I am dumb
do mod versions print in the error screen of Steamodded 1.0.0? or if not, is there a way to make them print?
position = "after"
payload = '''end'''```
getting an error on this in lovely, any tips?
this is generating this crash how do i fix this?
function SMODS.Jokers.j_cheesecake.loc_def(card)
return {card.ability.extra.every + 1, card.ability.extra.chip_mod, localize{type = 'variable', key = (card.ability.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive'), vars = {card.ability.loyalty_remaining}}}
end```
WHY ITS TRYING TO CONCATENATE A NIL VALUE

one of your values doesn't exist
like
its all correctly set
but its giving this error
:/
Man i love when "after ERROR hands played this joker gives +ERROR chips. ERROR"
this is the only part of the loc_def that crashes the game when i hover the joker
localize{type = 'variable', key = (card.ability.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive')```
Animation speed: Ï
Arbitrarily large
game be like "nope, no animations
"
what is that deck
Deck of Equilibrium - anything can appear anywhere
with the same chance
why is its back two lines on a graph
Instead of a Blind, you get a volume slider
The UI object holding your number of hands is replaced with a single square particle that immediately vanishes out of existence
When you check the list of hands for this run, it has been replaced with the sound gong
so what its trying to concatenate a nil value?
concatenating is putting things side by side
In this context it means concatenating strings
which is text
except one of the values isn't a string, it's nil, so the operation fails
either the localize call is going wrong, or what the return value is used for
its the loc_def
it just doesn't work
the chips and the every works fine
but the message saying how many hands are left doesn't feel right
Again
either the localize call is wrong or what the return value is used for
You could test it by temporarily remplacing the localize call with something else
so, q: if you wanted to duplicate and modify an existing joker, is there a better way of doing that than "copying the code for it out the original game and modifying it from there", especially if it does something that isn't just chips/mult/xmult
looks like the issue is the localize
when its removed and i left only this its stays like this
card.ability.extra.chip_mod, card.ability.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive'```
well, unless you defined an ability.loyalty_remaining that doesn't exist, s card.ability.loyalty_remaining == 0 is always false
so do i actually need to put a context or a name change in the config?
that looks like it's working to me?
Contexts are only relevant when calculating Jokers
i tried everything
i changed the remaining in the config to loyalty_remaining and it does not work
have you added it to the localize tables properly?
see
But does the card's ability have loyalty_remaining?
It won't have it unless you defined it
i'm starting to get coo coo crazy
So, due to inconsistent nomeclature you can imagine that the config and the ability are the same thing
But you can see that this is config.extra.loyalty_remaining and not config.loyalty_remaining
So you have two options:
- Define
config.loyalty_remaining; - Replace
ability.loyalty_remainingwithability.extra.loyalty_remaining.
how do i define it? đ
do option 2
in this
i already tested it
i did put the card.ability.extra.loyalty_remaining
it still crashes
đ
What's the crash message
did you put localize back in
where?
where it was before you removed it to test
i did, but when i remove it i get this
Because you hadn't done
this
here is the code rn
function SMODS.Jokers.j_cheesecake.loc_def(card)
return {card.ability.extra.every, card.ability.extra.chip_mod, localize{type='variable',key = card.ability.extra.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive', vars = {card.ability.loyalty_remaining}}}
end```
localize is used so the game can display text in multiple languages. If you don't care about that, you can usually get away with just writing text
just remove the localize again
or that
that probably works?
because card.ability.loyalty_remaining is still nil and you're using it as the variable
still crashes i already tested
when i fully remove the localize it works
but it shows the remaining_active and remaining_inactive
the literal words
btw
is there a way to atleast track how many hands it needs, to appear in the custom message?
does anyone know how to modify G.E_MANAGER so it can process multiple events in one frame?
does anyone know how i can save custom game data
to the save file
cause im pretty sure the game does not save my deck config
What are you trying to save?
highest ante reached
Doesn't it?
basically my deck does something if you reach a new highest ante
Hmm⊠I think if you save to G.GAME it should work
Lemme see
engine/events iirc has EventManager logic
I mean it works for my Joker
yea i think decks just do not care about config
cause every single deck effect is static
I haven't looked into it so I have no clue wtf anything in that file does but if you need to edit E_MANAGER logic it's probably through there.
trying to save it in GAME rn
Oh that's what I said
it sounds logical but just thought i'd ask if there's a smarter solution
(also i haven't had it work yet)
I did this
oo i think that finally made it work
I made it EVEN FASTER
I should again ship this as a separate mod for competitive players
they all work!
True. Also should make a toggle for it so you can turn it on and off on the fly
is it possible to create a joker that copies a random joker ability?
i just found the most cursed line of code in Balatro (this is for Yorick calc)
already did
fuck no...
certified thunk moment
I dunno, this is a pretty cursed way to handle edition calculation
does anyone know where the code that makes the plasma deck purple scoring is?
yay
Although I did forgor to remove soul_pos
But I have loc_vars for Disenhancements now
why did you make a worse glass card
oh it's a disenhancement. is this just to nerf standard packs
They don't spawn from anything yet
Haven't made that part xdd
Also why tf will this not patch
I used the wrong slash LMAO
ok finally it does
All the stuff you've been doing with editions is super cool, its inspired me to work on some shaders
that's cool, if you need to test them in game send them my way in DM or I can send you a playground mod to try them out
is there a way i can make a card name be the same color as the polychrome badge?
thanks!! For now I've just replaced the shader on foil so I can see the changes in game
{C:edition} or {C:dark_edition} in the name
yw
relating to that, where do the C:example functions draw their colours (or function like dark_edition) from?
thereâs a function that maps those to colors
where can i find that?
misc_functions.lua
thanks
i checked in misc_funcitons.lua, but dark_edition only links to G.C.DARK_EDITION, and the value for that in globals.lua only has {0,0,0,1} as its value. where is the code that controls the colour cycle?
i think itâs in Game:update iirc?
self.C.DARK_EDITION[3] = 0.6+0.2*(1- math.sin(self.TIMERS.REAL*1.3))
self.C.DARK_EDITION[2] = math.min(self.C.DARK_EDITION[3], self.C.DARK_EDITION[1])```
this?
i love this color effect frfr
how would i change these values in my code?
the x3 should probably be white
i tried
it doesn't work if i put a normal color in the X:mult space
like X:blue or X:red
but if i put X:mult it will appear a second X in the X3 mult space
{X:red,C:white} X#1# {}
hey, i have a simple question. I make youtube videos, and i want to make a simple balatro mod that just changes what the talking joker says, would anyone have any idea how to do that?
actually; i can just use debug mode
nevermind
Donât write a space
I have a stupid idea, that might actually work
What if we added more than just cards to a collection
Like, added info about specific things
Or changed the layout of the collection
Idk
what
Cards, consumables, vouchers?
Or smth entirely different like whole mechanics, like seals and enhancements
what else would be in a collection but cards
Yessss
balatro: legacy
Is this so you can categorise collections by where theyâre from instead of it all being together?
So you could see everything a mod adds in one place?
Adding CardAreas to the Collection
Tags
thanks
can you use loc_vars to dynamically change the name/description/infoboxes of a joker's local loc_txt?
based on conditional statements and such
Hidden lore
little treats...
yes, you can even use a completely different description text by including a key field in the return table
Iâll make placeholder art for them eventually
i think the issue w/ using collection for stuff is that it pulls from g center pools
unless ur making a new page
i guess thats what you mean actually
this is a #âă»modding-general question, ill answer it there đ
how would I go about setting a deck to only use the "checkered" suits? hearts/spades only
I'm trying to change a modded deck (all 8s), it already iterates through all the cards for its normal effect but I was wondering how to approach this with the suit change as well (not used to lua, appreciate any help)
also this isn't for a release it's just for me to test some other stuff
check out how checkered deck itself does it - you can simply extract the game executable with 7-zip
thank you I didn't know about this yet
np
not sure if this is the right place to just share ideas for mods but im trying to learn pixel art and made this with the idea that it's a rare consumable that randomly shows up in tarot / spectral packs (same idea as black hole / soul rarity), and the functionality is that it combines two COMPATIBLE jokers into one slot to free up space / combine joker effects into one joker. Obviously you have ectoplasm already to make more room for jokers but the rarity of this consumable would justify not adding the hand size penalty and im sure you could get some cool effects by mashing the sprites of 2 jokers together
this is the channel for actually developing mods sorry
is there a way i can make a joker always be in a edition?
yeah, by injecting in create_card
seemed like the other modding chat is for discussing / troubleshooting mods that already exist so that didnt seem like the best place to put it either, my b
i mean, its always in that edition even in the menu.
like, when it spawns or appears its always polychrome
You could probably inject into set_ability or something
how tho? i don't know how to do this sorry
Wouldnât injecting into create_card and calling set_edition if a certain name work?
i'm trying to make a joker that creates a random polychrome card. is it possible?
Yes
A joker in my mod has a relatively similar effect (creating a specific negative card)
hmmm
what code have you got so far?
I'd really recommend learning what your crash logs mean
Thereâs a mod that adds fusion jokers
@mellow crag Steamodded already has a set_ability hook, just check the Steamodded wiki on GitHub
The example they give is exactly how to make a Joker always have an edition
o really? XD
i didn't know that
This is the second time in two days that someone doesnât know Steamodded has had a set_ability hook since 0.9.8
Also Iâd like to correct myself: at least at the moment the example in the wiki isnât about setting oneâs own edition, though that isnât difficult
I think it mustâve been a tutorial I followed that had it as an example
Either mystâs or the other tutorial
Use the set_ability hook as exemplified in the Wiki for 0.9.8 but instead of whatever it is doing call set_edition inside
Search the gameâs code for the definition of set_edition to learn how to use it
The wiki currently has information about the 1.0 alpha release, but you can find the relevant information in âCreating new game objectsâ
Nice
one thing that is funny, i got the hang of this because of perkeo's negative code
it was so easy to understand
TIL curinga and coringa might be different
But I thought it was coringa
coringa is the name of The Joker from DC comics here
Curinga is the name used in baralhos
Apparently some dictionaries classify them as different words; my guess is that people use them interchangeably hence in contemporaneity theyâre synonyms
Also meme Joker
Brazil mentioned
applying editions is very simple tbf
now for the joker ability....
btw, the shader of the polychrome in this card looks awesome
wait why'd I make this so inconsistent
clearly this should just be center:set_ability(self, initial, delay_sprites)
can i make a joker spawn cards but with a loyalty card counter?
nvm
idea scrapped
well, final product is done
do you mean playing cards?
I think you can just say âcardsâ
i think it looks better like this
why am i so inconsistent with arguments đ
where can I see examples of using load?
NFS.load?
You can also use require instead of NFS.load
no not like that, like jokers saving and loading their internal variables between game closures
how does the source code handle that
It handles it automatically currently but otherwise I donât have much to say besides âread the codeâ :<
I think it saves and loads recursively but also that it creates new card objects whenever it loads
So references to specific cards are lost
how would i change the values for the self.C.DARK_EDITION functions in game.lua? would i use the take_ownership function with a specific tag? or is it simpler than that?
I wouldnât change it but create a new one
Unless youâre just making a mod that changes colors and textures
yeah just simple changes like that
In which case you could probably just hook or overwrite it directly
how would i do that? i'm not familiar with this section and how to call for it
I donât know whatâs the best way to do it, but you can overwrite any variable by assigning something new to it
self.C.DARK_EDITION = âHello, world!â
``` would overwrite it with the string âHello, world!â, breaking a lot of things in the process
Well, that syntax is probably incorrect unless itâs in the appropriate place
I imagine self is either G or G.GAME
But that G is different from the global scope G right?
hmmm
Game:init() literally has G = self
when i use G.C.DARK_EDITION[1] and change the variable to something like 0, nothing in-game changes. i feel like the game isn't reading it properly
there is never a game instance that isn't G, and it would break things if there was
But is that overriding the global scope variable? I canât tell if G is Lua syntax for the global scope, albeit unprotected, or if itâs just a common example
the global scope is _G iirc
It updates every frame
Are you changing the function that sets it or just changing the variable?
Thatâs why
G is just a global var
If you donât change the function then itâll be overridden when updated in the next frame
oh i see
I thought it was G but I could be wrong
Thatâs not so cursed
i changed the function to G.C.DARK_EDITION[1] = 0.6+0.9*math.sin(G.TIMERS.REAL*5.0) which is very different from the original, but it's still showing the same colour cycle
brb putting _G._G._G._G._G._G._G._G._G.G somewhere in mod code
Whatâs your code
Make it a lovely patch
only showing what's important
function SMODS.INIT.Colors()
local greyscale_mod = SMODS.findModByID("GreyscaleTextures")
G.C.DARK_EDITION[1] = 0.6+0.9*math.sin(G.TIMERS.REAL*5.0)
G.C.DARK_EDITION[3] = 0.6+0.6*(1- math.sin(G.TIMERS.REAL*5.0))
G.C.DARK_EDITION[2] = math.min(G.C.DARK_EDITION[3], G.C.DARK_EDITION[1])```
how would i do that
I mean I imagine it shouldnât be necessary to make it a patch
You didnât write a function
So you didnât fix your problem
Itâs still being overridden each frame
doing it in init changes something for all of one frame
You need to find the function that sets it each frame and change that, or if it happens to be stored coordinate-wise here, write it correctly
i'm not very familiar with lua, i'm learning just by looking at other people's code, sorry
Do it as an addendum to Game:update
that function is Game:update()
a function definition will look something like
function(vars)
foo(vars)
end
one way you can do this is with a lovely patch, but that seems unnecessary here
basically you can modify a function like this
What you have is just a function call, so itâs executed exactly once then overridden
local update_ref = Game.update
function Game:update(dt)
update_ref(self, dt) -- call the original first
self.C.DARK_EDITION[1] = ...
-- ...
end
Which can be defined outside of INIT
classic case of 'it doesn't matter'
update_ref(self,dt)
Anyways, this is a hook. You first save a reference to the original function, then you override it, but you call the original somewhere inside to make sure other peopleâs code still works
Whenever you want to make a change that can go before or after an existing function you can use a hook, otherwise use a patch
yeah, i managed to get it to work in the end. it also makes more sense with how the game works. thanks, you three đ
i'm still trying to figure out why this upgrades but doesn't give the chips after
SMODS.Jokers.j_lea.calculate = function(self, context)
if context.cardarea == G.jokers then
if context.before then
if self.ability.name == 'Spheromancer Pride' and next(context.poker_hands['Two Pair']) then
if context.scoring_name == ("Two Pair") then
card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex'),colour = G.C.BLUE})
self.ability.extra.chip_mod = self.ability.extra.chip_mod + self.ability.extra.chips
end
if SMODS.end_calculate_context(context) then
if self.ability.extra.chip_mod > 100 then
return {
message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}},
chip_mod = self.ability.extra.chip_mod,
card = self,
}
end
end
end
end
end
end```
do these look good?
uhh
stickers
idk why anyone would wan to make a joker rental
or perishable
but that's why they're bad ideas
if the rental one like applied to your next shop maybe
like "all jokers in next shop are rental"
i just saw this in cheesyjokers
local function edit_scoring_hand(event, line)
if line == 603 and debug.getinfo(2, 'S').short_src == 'functions/state_events.lua' then
local n, v = debug.getlocal(2, 5)
(truncated)
debug.setlocal(2, 5, v)
elseif line == 778 and debug.getinfo(2, 'S').short_src == 'functions/state_events.lua' then
local n, old_scoring_hand = debug.getlocal(2, 5)
(truncated)
debug.setlocal(2, 5, new_scoring_hand)
end
end
(truncated)
im kinda afraid itd f things up with lovely
yea nothing much. that joker just wont work
yeah that absolutely doesn't work

cheese mentioned it before and was advised to just use lovely instead
yeah ill just stop using it for now before the migration. and it breaks reverie too for some reasons

tasty
wooooo using 10 of these can give you a naneinf XD
who needs X-Chip when we can have ^-Mult
^-^mult
Expo-Mult
naneinf was never as easy
nannyinf
i get what you're saying here but also i cant see anything but ^-^
that is the point
ah
Albiet, how does that work? I'm trying to remember how exponents exactly work in this case
thought the dash represented an actual number or smth
nuh
mult/chips ^ the value
or you didn't mean the expo mult/chips
So, in this case, if the ending Mult was 100, it'd be 100 ^ 2, which is 10,000?
yes
Oh, that is a REALLY fast scaling effect, and I love it for the chaos factor of it.
Oh, nice!
feder will there be -Blind
For blind goal?
Sure
a unified way to reduce blind req
I can do that
so maybe if stuff can trigger off/otherwise affect blind reduction
like a joker that doubles all blind reduction effects
thatd be slick
idk just thinkin aloud
Hey everyone! I'm new here and I'm trying to make some mods đ
Any suggestions on where to look for on how to extend UI?
good luck
nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].nodes[1].
looks about right
how do i add tooltips
depends on what you're adding them to
i need one on a consumable
Currently the plan for this api thing is:
X chips
Held x chips
Expo (^) mult
Held expo (^) mult
Expo (^) chips
Held expo (^) chips
X gold
Held x gold
Might also do:
Blind%
Blind% and -Blind? :)))))))))))
Blind% will also enable -%
I mean, thatâs what it will do probably
It says %, but it cuts a percentage from the blind size
how do i add a tooltip to a center
first you must create a universe
but that's a lot of work so just use the one we have
secondly, loc_def is passed info_queue as the second parameter
or loc_vars if youre on 1.0
info_queue handles tooltips
just put centers in there or check how vanilla stuff handles info_queue for special stuff
^ Gold when
i don't really care
this is gonna be so ridiculous lmao
I made some code that animates the Blind size change while inside the Blind (like the Hand and Discard ones), if youâre interested
I havenât done it for the Blind screen (where you either play or skip) but I imagine itâs possible
I have something for that already for codex
Oh I donât talk about these as well
Hmmm⊠although mine is in an event so technically it can fire before the UI exists. I put a lot of delay on it but Idk a smart way of circumventing it (as in, waiting until the UI exists)
Send it to me anyways, I will see how you did it and compile the best option
Here's what it looks like
and here's the code
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.8, func = function()
local new_chips = math.floor(G.GAME.blind.chips * self.ability.extra.difficulty)
local mod_text = number_format(math.floor(G.GAME.blind.chips * self.ability.extra.difficulty) - G.GAME.blind.chips)
G.GAME.blind.chips = new_chips
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
local chips_UI = G.hand_text_area.blind_chips
G.FUNCS.blind_chip_UI_scale(G.hand_text_area.blind_chips)
G.HUD_blind:recalculate()
attention_text({
text = '+'..mod_text,
scale = 0.8,
hold = 0.7,
cover = chips_UI.parent,
cover_colour = G.C.RED,
align = 'cm',
})
chips_UI:juice_up()
play_sound('chips2')
return true end
}))
For reference, ```lua
self.ability.extra.difficulty = 1.5
I think a way to circumvent it is to create one of those events that apply constantly (like DNA pulsing) but make it exist while the UI doesn't exist, then when it dies it creates the event that changes the Blind UI
is this alright? I didn't find any later versions
You have to download steamodded's code zip instead of the release
alright thanks
Dont forget to update lovely too
Also the zip or whats in releases?
for lovely, you want the latest release 0.5.0-beta5
One of my jokers that always spawns as a Polychrome crashes my game when it spawns lol
Is there a way to fix this?
Why does it crash?
You need to read the rest of the error trace
Itâll tell you where in your code itâs struggling
I'm not home tho
Well weâre going to struggle to fix that then
When i get home i will try to fix it
But youâre not assigning an edition properly somewhere
My set_ability in the joker is like this
card:set_edition({polychrome = true}, true)```
you're missing a quotation mark
I don't think you need the quotes actually
card:set_edition({
negative = true
})
This is how I have it set up in my code
Its like this
But its polychrome, and idk if that additional true adds something?
Can you test something real quick, i think that additional true that is in my code is crashing my game
Can you try testing if its the additional true
Bc im not home rn
And i can't do it myself rn 
The additional true makes it silent or immediate
I donât remember the order but it wonât affect it
So I guess that the card youâre checking and the card you set the edition of are different
If thereâs event shenanigans the lack of immediacy (or its presence) could cause a crash
i should start adding indicators like this to alpha versions
please do
are there any other Steamodded 1.0 ported mods besides Cryptid, SDM_0 dev branch and MystBlinds? Want to test the interactions with multiple mods loaded
I should release a port of SixSuits, I've basically done half of the porting already for testing things
My mod isn't updated to the latest Steamodded changes, I heard some parameters got changed somewhere, will try to pull something quick
#1219749193204371456 message
here is the list of changes
Oh I didn't know center objects had added_to_deck and removed_from_deck too that's cool
Alright pushed something quick to make it compatible with the latest SMODS build, should be good to go (tho I left some sendDebugMessages)
the crash related to my joker rn
he is always polychrome, but when it spawns the game crashes
in shop?
shop, or even spawned by soul
the joker is a legendary btw
but when it spawns he crashes the game :)
His set_ability
function SMODS.Jokers.j_polychromereactor.set_ability(card, initial, delay_sprites)
card:set_edition({polychrome = true})
end```
yeah it happens with those two spawnings
it's because of the set_edition in set_ability
where do i put it then?
:/
if i wanted to rig up a really jank mod that just prints an internal game variable to the screen, is there something as simple as an update loop for steamodded or do i need to hook onto something else
you'll need to hook onto the game's update loop i'm pretty sure
you might be able to override poll_edition to always return polychrome for your card
poll_edition wouldn't work if you directly spawn the card tho
if i spawn the card with a debug menu it works fine
but when it spawns in a shop, pack or sould the game crashes
Does anybody just have a list of every context used in balatro and what it does?
tried my hand at shaders - fluorescent edition, I think I want more colors than just radioactive green
Where are those fallout Jokers?
đ€
Ooh settings?
in this case, no
there's still only hiding mod badges there
Oh I see
I wonder what other settings you could add?
Maybe if steamodded ever adds base game features, you could toggle them there
Btw @frosty dock I wonder, how can you place UI objects in the mod menu?
lmk if custom hands crash with talisman
I haven't really touched that system, I know there's a function that lets you do it though
Interesting. I will look into that. I wanna try and do some fun stuff with that menu
no issues here
I see that spectrum XD
Hey, I'd like to make it so a card changes it's name/description at some point
How would I do this?
I was assuming i an use loc_vars "key" return and just like adding my own loc_txt into the game using
SMODS.process_loc_text(G.localization.descriptions[self.set], changed_key, loc_txt2)
return {key = card.ability.extra.broken and changed_key or card.config.center.key, ...}
this errors out somewhere in localize
oh this doesn't parse it

decided to supercharge Brainstorm
move the process_loc_text call to the process_loc_text function of that object
will try
hmm
it doesn't work
here's what im trying
it does this ingame
why is that 7 of Spades Eternal for one frame
prob pressed the debug button for make eternal on accident
hm what is ominousmirror defined as here?
I figured out why this wasn't working. I wasn't giving the folder to the lovely patch
because I didn't know I had to give the folder
idk
try putting the function directly in the SMODS.Joker constructor
oh wait
no, the object is just wrong
I also made a new color (based on @golden lake's code)
remove the loc_txt = {} layer of nesting
The effect was inspired by a Reddit post. I'm trying to contact the person who made it but I implemented it for now because I already had had ideas that would require the same backend as this anyways
this would only work if the selected locale is loc_txt
that's a start
might honestly be my fault
does it just not use name in loc_txt
I'll see what I can do
Worst-case you can manually change the tooltip
hm that makes sense, names happen in a different spot than descriptions do
shouldn't be too bad to fix
I mean you can also manually change the description
Then why am I doing it manually đ€
any suggestions on where to hook into the event that gets fired when you add a joker to your run?
Card:add_to_deck()?
the original function is Card:add_to_deck, meaning there's an implicit first argument self
it's just syntactic sugar, but it makes quite the difference
[redacted]
oh wait no self shoul be center
im confusing myself cause it is broke but it's prob just me

oh im dumb
im confusing the class center with like some sprite called center

yea
either make the function with a : which adds self automatically
or write self as the first argument
awww
the load function of jokers is called at like the start of it
meaning all the stuff hasn't been set and it'll change ability
@frosty dock any chance that can be moved to the very end of it
i feel like making sure the sprite of a card is correct is not a stupid idea for using load() in joker right

