#💻・modding-dev
1 messages · Page 661 of 1
hi i am lily
hi lily
which is rly confusing
have some aqu code
--returns a movable's pixel position (center)
function aquill.get_movable_pixel_pos(mov)
return {
(G.ROOM.T.x + mov.VT.x + mov.VT.w * 0.5) * (G.TILESIZE * G.TILESCALE),
(G.ROOM.T.y + mov.VT.y + mov.VT.h * 0.5) * (G.TILESIZE * G.TILESCALE),
}
end
ty
this particularly works for cards but it should technically work for any movable element, though im unsure since ive never had to test it
Hey I don't wanna jump in mid conversation but I wanted to just say that I've been trying to make a mod all day and I've finally gotten to a point where all the art is finished.
I've followed multiple tutorials, copied multiple mods and tried to copy what they do, but mine doesn't work. The mod loader sees it and it's in the mod list with my custom icon, but the deck doesn't work. Originally I was trying to make it work like the Collabs so I just changed the face cards, but I ended up replacing the entire deck. I don't get any errors, the textures just don't load and going into "Customize deck" doesn't have any new options.
If I don't reply to anyone its because I need to dip for a bit :)
that format's old af
Darn
I've tried to go through the mods I have that are working but idk how to read any of them
I have to go for a bit but I'd appreciate any help
I HAVE BEEN SEARCHING FOR THIS AND I COULDN'T FIND IT
i got this right after i clicked "play"
share code
is this a mod you're making
no
oh alr
oh kk
i'm still kinda stumped on how to adjust the rotation pivot point for a sprite, as i've tried changing all sorts of vars but can't find it
(the dot in the sprite is where it's pivoting from instead)
bump
Those anyone know who the person behind Luna Enchantment mod? I saw once looking for it again and can't find it
Question about context.press_play, is there a way to get scoring cards from it? Because context.scoring_hand returns nil
In G.FUNCS.can_discard = function(e), just what is passed as the argument e?
not super easily; the full hand is G.hand.highlighted because it hasn't been drawn to G.play yet, so you have to take that full hand and manually calculate what the scoring hand would be and which cards make up that hand
The discard button ui element
You mean this?
local discard_button = {n=G.UIT.C, config={id = 'discard_button',align = "tm", padding = 0.3, r = 0.1, minw = 2.5, minh = button_height, hover = true, colour = G.C.RED, button = "discard_cards_from_highlighted", one_press = true, shadow = true, func = 'can_discard'}, nodes={
{n=G.UIT.R, config={align = "cm", padding = 0}, nodes={
{n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}}
}}
}}
That discard_button, is that a global variable that I can call up in any old function call?
the little local right next to it seems to indicate no
How do I make it call-able in any circumstance?
i think it gets saved as part of G.buttons or something, but i dunno the exact details off the top of my head
bump
What might I do with this, then? I want to make a function that grays out a given button, which takes that button as its sole argument.
Do I just pass G.buttons.definition.nodes[3]?
i'm curious, what's the use case for being able to arbitrarily disable any button at all? i feel like unless you genuinely need to do it for a bunch of different buttons, it might be better to just hook/patch into whatever determines the state of the button(s) you need to modify
[I tried that](#💻・modding-dev message). It didn't work.
Nvm we figured it out
in the patch:
local calc_returns = {}
local disable = false
SMODS.calculate_context({
LAPSEMS_should_the_discard_button_be_blocked = true,
full_hand = G.hand.highlighted
}, calc_returns)
for _, v in pairs(calc_returns) do
for _, w in pairs(v) do
if w.disable then
disable = true
break
end
end
if disable then break end
end
if disable then
if (G.GAME.current_round.hands_left >...
in the calculate function, replace return true with return { disable = true }, and just remove the return false entirely
yo sophie is bad asf 
Just what is calc_returns populated with?
by passing it to the calculate_context function call, it gets populated with all the return tables from all the objects that calculate in-game
i can confirm that this works because i have the exact same setup in my own mod for my own custom contexts
What things do you use it for?
for my custom dice consumables, i have a context for modifying the value of a roll (much like how modifying a probability works in smods), a context for triggering rerolls of the dice, a context for modifying what a die's min and max values are (so e.g. i have a voucher that guarantees all dice roll in the upper half of their usual range, by setting the min to the die's max / 2), and a simple "post_roll" context that triggers after the die finishes rolling and goes back to the consumables slot
How do you add new collabs so I can reskin all the collabs to have a colour for each suit?
it's called a DeckSkin internally, here's the documentation. you'd make your own mod and add all the recolors using this object
https://github.com/Steamodded/smods/wiki/SMODS.DeckSkin
how could I get the number of chips a card scores before any extra effects, and permanently modify it if possible
im trying to make jokers that apply probabilities to every card in the played hand but it's not exactly how i want it
for k, scored_card in ipairs(context.scoring_hand) do
if SMODS.pseudorandom_probability(card, 'prefix_joker', 1, card.ability.extra.burn_odds) then
--effect in here
end
end
if i put the for loop inside the pseudorandom_probability, then the game does one roll for all the card, but as it is right now, it rolls for every card but only applies to one, when i want it to roll for all and apply individually
so if two cards in the same hand land a 1 in 5, i want them both getting it, but rn only one does
Are you returning during the loop?
ah
well now i feel dumb for not catching that sooner lol
nvm i got somethign else working
but now the message that's only supposed to pop up whenever the card triggers pops all the time
i've tried changing every value i could find
i'm losing my mind
just asked her and it turns out she'd given up
I mean theres no variables to adjust rotation point
Draw function do calcs how to translate and rotate itself
i'm already doing draw functinon stuff
the tilting and shit is shader stuff
i can't touch it
there's no way to with normal shader stuff
the offset shit doesn't even seem to work
Now i see, dot placed in a center of soul sprite of regular size
How did you do a sprite this big size
What a convoluted way to do that
because there's no easy way to do it
Isnt should be easier just override set_sptites function and create floating sprite of correct size
well,,
the dot is centred
and it's not doing the tilt stuff either
since it's a new sprite
so this is even further from what i want
😭
I'm trying to create a Joker that has a chance of making Jokers in the shop and booster packs Negative. The booster pack part seems to work, but the part for the shop only seems to work on the initial Jokers in the shop. Any Jokers after that (like from rerolls) aren't affected
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''
G.shop_jokers:emplace(create_card_for_shop(G.shop_jokers))
'''
position = "after"
payload = '''
local new_shop_card = G.shop_jokers.cards[#G.shop_jokers.cards]
SMODS.calculate_context({my_singing_jokers = {
change_shop_cards = true,
card = self,
shop_card = new_shop_card
}})
'''
match_indent = true
calculate = function(self, card, context)
if context.my_singing_jokers and context.my_singing_jokers.change_booster_cards and context.my_singing_jokers.before_cards_added then
for k, v in pairs(context.my_singing_jokers.pack_cards) do
if v.ability.set == "Joker" and v.config.center then
if SMODS.pseudorandom_probability(card, 'mysingingjokers_permatorch', 1, card.ability.extra.odds) and ((v.edition and v.edition.key ~= 'e_negative') or v.edition == nil) then
v:set_edition({ negative = true }, true)
v:set_cost()
end
end
end
end
if context.my_singing_jokers
and context.my_singing_jokers.change_shop_cards
and context.my_singing_jokers.shop_card then
print("card")
local v = context.my_singing_jokers.shop_card
if v.ability.set == "Joker" and v.config.center then
if SMODS.pseudorandom_probability(card, 'mysingingjokers_permatorch', 1, card.ability.extra.odds)
and ((v.edition and v.edition.key ~= 'e_negative') or v.edition == nil) then
v:set_edition({ negative = true }, true)
v:set_cost()
end
end
end
end
}
I've been trying to fix this for like 3 hours and I'm starting to fall into despair
Question about blind loc vars. How can I make the hand_mod value show up in the collection? It shows up in a run just fine, but returns nil in the collection
config = { hand_mod = 1 },
loc_vars = function(self)
return { vars = { self.config.hand_mod } }
end,
collection_loc_vars = function(self)
self:loc_vars()
end,
there's another loc vars for the collection
how do i make a mod change the in-game music
kitty
lovely question: What's the difference between dump and game-dump?
Just a guess, but I'd imagine game-dump is the vanilla game files pre-patches being applied
oh wait i should have checked if one or the other has been depreciated, i didn't clear my lovely dir before updating to 0.9
wonky
i've never seen the game-dump folder tbh, it's not a lovely thing
do you have frost's utils mod installed? i have a hunch it's something that i previously suggested gets added to it, but i haven't updated it in a while lol
Installed but disabled
hm i see
does it stop generating game-dump if you move it out of the mods folder?
It's a lovely thing. That directory name is in the rust source code too
i dont have frosts utils and i have game dump folder
its new
Checking the lovely code, the only difference I could find was in the debug json files. The actual patch outputs have the same argument and should be identical
Then again, I'm not a lovely maintainer (or even rust programmer) so this is just advanced guessing
would this technically violate modding rule 8
Ah that makes sense
decompilation ~= distribution
(at least last i checked)
yea fair, i realized that like right after i sent the message
it won't provide the source code unless you've already purchased the game, since it only generates it at runtime
is it possible to get the default config = { extra = { } } values of a joker that is not currently in play? I heard something about self.config earlier but I don't know how to set that up, so any help would be greatly appreciated.
G.P_CENTERS.j_modprefix_jokerkey.config should do it i think
yeah it was a port from some testing code that I implemented for the sdk and then was broken and forgotten about
not super super high importance to get it fixed since nothing really uses it yet
but it is pretty ugly
i see
yeah just a dumb mistake on my part :P
smh i have to do this now
is the rotation unit in balatro degrees or radians?
Radians
thank you
actually how do you rotate attention_text?
tried rotate arg and it doesnt work
...oh, rotate takes 2 or truthy
So for a consumable that turns specific jokers into other specific jokers, is it possible to make it happen without editing the code of the vanilla jokers
I'm afraid that if the vanilla jokers are edited then it'll conflict with some other mods that also edit them
Actually let me reword it
Using a consumable that transforms jokers into other jokers, is it possible to assign vanilla jokers a specific joker to turn into without touching the code of said vanilla jokers
is there a built-in way for the collection card of an edition to be a playing card or do i have to just make an atlas of a fake card
I'm confused, wouldn't that just be a big look-up table? Like
Joker -> Card Sharp
Greedy Joker -> Rough Gem
Lusty Joker -> Bloodstone
etc...
I'm not a coder, I'm just asking to see if it's possible
for an extremely stretched definition of "not touching vanilla code", you can take ownership and add a custom trait that exists solely for this use
e.g.
SMODS.Joker:take_ownership{"joker", {
bizarrlo_upgrade = "j_stuntman"
}, silent)
All I wanna know is if it's possible to do it without going into every vanilla joker and adding code to it
Yeah
big lookup table, then
Whar is a lookup table
you need some method of taking the card you have as input and getting the card you want as output
a big table that says "if input is x, output is y" for all the values of x you might care for
in lua it'd look like
MOD.empower_chart = {
j_joker = "j_stuntman",
j_greedy = "j_rough_gem"
-- ,,,etc
}
or anywhere the consumeable can access it
I'd make it public so other mods can theoretically access/edit it, but it'd be used in the consumable code yeah
color grading except each pixel is transformed into a joker rather than a different color using a LUT
So it doesn't matter if the table is part of the consumable code or the joker code?
thinking
and the consumeable would have a line something like
local orig_key = card.config.center.key
local new_key = MOD.empower_chart[orig_key]
a table like this wouldn't make sense to put in the joker code
you wouldn't define every individual joker effect on jimbo
I meant like "if [consumable] is used then turn into [joker]" type of stuff
my java brain ass just said "yeah put that in an enum"
im so uncooked
But on every joker thus spreading the table across every affected joker
How could I add like, "tags" to a joker/consumable/whatever, that other cards/jokers/consumables can check for? Like pokermon energy types but with multiple at once ?
you could add them to pools
you don't need to define the entire collection on jimbo and on greedy joker and on stuntman etc
you either define the entire collection in one central place, or you define each joker on that joker
Ohkay
Or you could just have a table in config.extra like
config = { ability = { extra = { tags = [tag1, tag2, tag3]} } }``` or something
oops sorry @hoary spear
Okay, config table was kinda what I was thinking to
Then how would the searching them work?
you'd probably do something like {tag1 = true, tag2 = true, ...} and then just check if the key exists
Mhm
something like next(SMODS.find_card("j_jimbo").config.ability.extra.tag[tag1] or something
actually, i dont think thats valid but i hate lua so i can never remember how to do stuff like that
yeah that'd right lars
Thanks y'all:)
yuh
A comment in SMODS.Edition suggests setting atlas does something. No clue if that's true or not
setting atlas to a custom suit kind of works, but it only renders the front, not the center
oh unless that's what you already meant with "atlas of a fake card" lmao
yeah
any advice on how to not be scared to start trying to make smthn? ugh i have smthn i want to make but like i'm scared of trying for some reason 😭
mood lol
wanna talk about what you're trying to make? positive reinforcement from others might help
-# yeah nvm i'm too shy for that i should probably give up like i do with everything else in my life
It's a fandom largely built on making things, there's not much real pressure outside of any you create yourself
fair
If you do make something, then cool you get to show it off and built on it if you want
Though if not then there's nothing for people to care about and you end up complaining about your virtual stage freight in a dev channel for nothing
This is gonna sound kinda mean but know I'm not trying to make you feel bad, it just needs to be said bluntly
Nobody cares if you do or don't make something, in the event you do itg will rightfully be subject to constructive criticism, if someone is mean about it that's their fault for lacking the maturity
This goes for me to, I quite enjoy yapping back n forth
But please don't make the fate of your hypothetical project our problem, you can request help but emotional support is not obligate
Changing the background color with ease_background_colour{} resets the color after a Hand/Discard is used. How do I make it stick instead?
fair, sorry for the bother
state shenanigans
you'll want to find the various update functions in-game and then patch them to not reload the custom background color if you have one set. they should be in game.lua iirc?
How might I, instead, modify the value that the reset-values look for? Changing G.GAME.blind.config.blind.boss_colour didn't suffice.
Any ideas why my patch might not be patching?
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''ease_to = G.GAME.chips + math.floor(hand_chips*mult)'''
position = "after"
payload = ''' + math.floor(G.GAME.mtg_bonus_chips)'''
match_indent = true```
Targeting this part of state_events.lua:
```lua
G.E_MANAGER:add_event(Event({
trigger = 'ease',
blocking = false,
ref_table = G.GAME,
ref_value = 'chips',
ease_to = G.GAME.chips + math.floor(hand_chips*mult),
delay = 0.5,
func = (function(t) return math.floor(t) end)
}))```
You're missing the ,
Does it have to be the whole line?
ye
"after" patches have to match a whole line and will inject a new line, they can't add onto an existing line
you probably have to do an "at" patch instead
got it, thanks!
isn't it about pattern vs regex?
how do you rotate a ui element?
edit: add to the node's config table func="exampleFunc", then create the following function:
function G.UI.exampleFunc(e)
e.T.r = number
end
a regex patch would be able to find the line without a full match, but it still would inject on a new line unless it was an at patch anyway. plus regex patches are much less efficient
What? I'm pretty sure you can do a patches.regex with "after" without it inserting newlines
well i'm using at now and it's still not working. I've checked smods and it doesn't look like it changes this line (and the only other loaded mod is debugplus, which doesn't alter it either)
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''ease_to = G.GAME.chips + math.floor(hand_chips*mult),'''
position = "at"
payload = '''ease_to = G.GAME.chips + math.floor(hand_chips*mult) + math.floor(G.GAME.mtg_bonus_chips),'''
match_indent = false```
the wording on the lovely injector documentation implies otherwise but I could totally just be reading it wrong, I don't have any experience with it
the efficiency point still stands
might need to escape the * with a \? Not 100% sure, I can try it
I'm pretty sure the lovely documentation never explicitly says you can only use pattern for full lines, but I do believe it's the case
And I remember that being such a pain to find out myself by trial and error
Well you don't need to escape it. Your patch works fine for me
Actually, where does it say that in the lovely docs? 🤔
Am i misunderstanding this warn message then?
No, you've got that right 🤔
I'm using the dev branch of smods...?
do you maybe have any other mods that could be patching around there?
or maybe yea dev smods could be doing that too
that could be an issue? doubt it but could be
No, it's because the line would be ease_to = G.GAME.chips + math.floor( SMODS.calculate_round_score() ),
yea that sounds like something smods would patch in
oh you're so right
oh I'm testing this without smods lmao
[patches.regex]
target = "functions/state_events.lua"
pattern = "^(.*)hand_chips\\s*\\*\\s*mult(.*)$"
position = "at"
payload = '''$1 SMODS.calculate_round_score() $2'''```
I was looking for ease_to when i checked smods, so i missed this
how do i make a card with a static base layer, but with an animated soul layer? is it possible to use two atlases (one ASSET_ATLAS, and one ANIMATION_ATLAS) on an object?
idk if thats a supported feature by default, but if its not you could prolly just apply the soul layer via drawstep
How would I go about having a Joker's art change when it's spawned in shop? I want to have a funny rare chance a joker art is different when its spawned
In the set_sprites function, you would do card.children.center:set_sprite_pos({x = x, y = y}), assuming the alternate sprite is on the same atlas.
Thanks!
Is there a P_CENTER_POOL for Blinds?
G.P_BLINDS
Thx
how would i make all planet cards (modded included) have something extra in their definition since im tryna make them all have the base rarity of common since im making planets have different rarities
the lack of the value itself gives you that information
is pseudorandom ran on set_sprites?
No, pseudorandom is a function, it can be ran anywhere as long as it exists.
A joker that you made or a specific joker?
my own joker
Then yes, it is the set_sprites function, if you want it to change when it is created.
does that function have any special effects or is it instant
not necessary at all it would just feel better to me
It's instant.
Alright, I ask because what I'm trying to do doesnt seem to work, even when I set pseudorandom('smsn_easter_egg') < 1.1 so that it hits everytime
card.ability wont exist when set_sprites is first called.
That seemed to do it, thanks!
||Insert joke about Pokermon Shiny edition here.||
Hi, guys. Super quick question.
How do I make this round the money up after halving.
ease_dollars(-(G.GAME.dollars / 2))
math.ceil() i believe
math.floor() for rounding down
Thanks. That was useful. 
I'm trying to make a joker that debuffs all cards except hearts. This example here works, but it doesn't un-debuff cards converted with The Sun Tarot card, and also doesn't un-debuff the other cards when the joker is sold. How would I go about implementing these?
whennn is this function being triggered
is it constantly updating or does it just work once when the joker first loads
Is there an easier way to make a deck that changes all joker's to use the next highest operation in their calculate function than to remake all of them by hand, I just cannot think of how I would do it if it even is possible
Not even to mention the localization text too
return {
mult = card.ability.extra.mult
}
-- Turns into
return {
xmult = card.ability.extra.mult
}
As an example
Changing the localization probably isnt happening
But you can hook SMODS.calculate_individual_effect to convert the effects to the next operator
just once when the joker loads
but you can call card.children.center:set_sprite_pos elsewhere
icic
Hey again guys.
Do you know if I can reduce the appearance rate of specific cards? Like boosters.
So making a specific tarot or Odd Todd less likely to appear for an example.
patch qol requests? issues with the workflow? I humbly request lovely feedback
Individual object weight is in the work in SMODS iirc
If I take ownership of a vanilla card and define its calculate method, will it still do its normal things if my calculate method doesn't return anything?
is there a way to check the players current money and use that in a cards config?
like for example, im tryna make a joker that does a thing after the player spends half their total money
ight thx
add_to_deck = function(self, card, from_debuff)
card.ability.extra.original_money = G.GAME.dollars
end,
calculate = function(self, card, context)
if context.money_altered and G.GAME.dollars <= card.ability.extra.original_money/2 then
-- Do a thing
end
end
it's just returning nil
Code?
local bankroll = SMODS.Joker{
atlas = 'joker',
key = 'bankroll',
pos = { x = 0, y = 1 }, soul_pos = { x = 0, y = 0 },
set_badges = function(self, card, badges) badges[#badges+1] = tss_badges.Goob() end,
discovered = false,
unlocked = false,
rarity = 2,
cost = 6,
config = { extra = { original_money = 0, cost = 0, attempted = false } },
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.cost
}
}
end,
add_to_deck = function(self, card, from_debuff)
card.ability.extra.original_money = G.GAME.dollars
end,
calculate = function(self, card, context)
if context.money_altered and G.GAME.dollars <= card.ability.extra.original_money then
card.ability.extra.cost = card.ability.extra.original_money / 2
end
end
}
i'm trying to get it to display in loc_vars too, which is probably where the problem is coming from
how would I check for each unique enhancement in a played hand?
It should be if context.money_altered and G.GAME.dollars <= card.ability.extra.original_money/2
sadly makes no difference to fixing the nil problem, but fixed
local enhancements = {}
for k, v in pairs(context.full_hand) do
SMODS.merge_defaults(enhancements, SMODS.get_enhancements(v))
end
local countable_enhancements = {}
for k, v in pairs(enhancements) do
table.insert(countable_enhancements, k)
end
local count = #countable_enhancements
do you need mod prefixes for pools?
No.
If one has a shader that makes parts of a card invisible how could one prevent editions from making the invisible parts visible again?
you can't
cardshaders and editions don't seem to be compatible
they draw over each other
for example, here's my cardshader healhbar being drawn over by the holographic shader
how do i make an info_queue show a joker's locked requirement description?
does anyone know how can i take a life off of the player in multiplayer neither MP.UI.ease_lives(-1) or MP.GAME.lives = (MP.GAME.lives or 0) - 1 actually keeps the life gone when they go and lose a nemesis fight
try asking in the mmultiplayer server
#help-desk seems like the right channel to ask in
did and got absolutely no response
like i want to make some multiplayer content for my mod because some people are playing it in multiplayer pretty regularly recently but nobody will answer any of my questions about multiplayer support
just ease lives may be not enough, you need to make sure you to sync it with server
do you know how to sync it with the server?
I'm trying to look into how the pseudorandom works, but I'm running into an issue with math.randomseed(seed) in pseudorandom. Namely, pseudoseed seems to return a number between 0 and 1, while math.randomseed expects an integer as far as I can tell. What am I missing?
bump
why're you looking inside pseudorandom? what're you trying to accomplish
oh nvm this is [probably?] my answer
want to look into seed searching and it's more fun to try to do it myself tbh
oh omnipotententity has more useful content sweet. apparently luajit has an entirely different random seed
if i had a penny for every person that needed this information this month i-
i also asked about how to do server related things in the multiplayer discord but nobody answered me like how am i supposed to add support for multiplayer bruh
have you tried looking at the code for existing multiplayer jokers?
i mean yes? but its not really clear how to get any of the information
took like multiple days just to figure out how to get the opponents score in the nemesis blind for items like this because nobody will answer me
heyho, how could i check the first scored card? thank you
Patch generate_card_ui and set card_type to 'Locked' in the info_queue you want.
context.scoring_hand[1]
thank you!
ty
it's not working
Code?
g
No, card_type is an input for generate_card_ui, you need to change that.
ahh
How would I create a card without discovering it...
how would i add this to my existing patch?
if _c.card_type then card_type = _c.card_type end
where would i put this,,?
id assume youd put it where you set upgrade_center.card_type currently
ah ok
though i may be wrong
No, you would put it outside of the if (card).
It can be either.
It would actually have to be in a hook before the original function runs.
oh
wouldn't you also need to use locked_loc_vars here
how do i make the text say locked instead of the joker's name, like this
Set full_UI_table.info[#full_UI_table.info].name to localize{type = 'name', set = 'Other', key = 'locked', nodes = {}} in the hook after the original function runs.
ty
not working
local generate_card_ui_hook = generate_card_ui
function generate_card_ui(_c,full_UI_table,specific_vars,card_type,...)
if _c.card_type then card_type = _c.card_type end
local ret = generate_card_ui_hook(_c,full_UI_table,specific_vars,card_type,...)
if _c.card_type == "Locked" then full_UI_table.info[#full_UI_table.info].name = localize{type = 'name', set = 'Other', key = 'locked', nodes = {}} end
return ret
end```
hai i asked about how to get started on making my first ever mod and i was given this link (https://github.com/Steamodded/smods/wiki/Your-First-Mod) and this channel to discuss further topics about it
the thing is
i read the page and it just seemed like tips more than a tutorial
and i did not understand much..
does anyone else know any other or just a similar but clear way of understanding how to get started
that is the clear way of understanding how to get started
oh :(
Steamodded documentation
- Check out the Mod Metadata page for how to get your mod detected by Steamodded.
- Check out the API Documentation page for information on the basics of Steamodded's api.
- For adding content, check the Game Objects part of the sidebar, which lists every object SMODS can create.
i'm just repeating verbatim a part of the page you linked
@daring fern 
seems like i didn't pay enough attention
Try using ret instead of full_UI_table
ok
still nothing
i think maybe it's bc of name_styled?
also the snippet you gave me will only do the last ui element
Yes, which is the info_queue
ah ok
still, that doesn't fix it
it seems it'll have to be a patch or smtn bc it uses dynatext
full_UI_table so scary even I dont use it at all
anybody happen to know why i get a decode crash when i play a sound?
there is honestly so much here, what if you make the use function just the set_ability call in an event and leave the rest commented our or smt
that will at least tell us if the problem is the rest of your code there or smt else
send crashlog?
yeah sure, give me a second
or i could make a minimum reproducible example
just for pedantry's sake, here's that repro'd with just that and debugplus
Does anyone know which color shift to apply to these areas to get these effects in pack sprites?
could try experimenting with multiply and darken only blend effects
iirc theres a set of the booster shading layers in #1224362333208444989
I'm currently having a bit of an issue, a mod I'm making isn't actually showing the custom deck. I did everything exactly the same way as my mod from yesterday, but today I got an error saying it couldn't decode the PNG and CRC can be disabled. I re-exported my PNG, the error is gone but my deck is just a renamed default skin.
I just switched off pixel scaling and now it's crashing for 1x files so I have no idea why the PNG isn't working
found this #1224362333208444989 message thx
it works for me...
I did the same thing as you
with your mod
"couldn't decode" type errors sometimes happen when you don't have enough system resources available
could well be that
also happens when the file extension doesnt match the file data right
or if it doesnt exist i think
But then why is it that when it doesn't give that error that my cards are just default?
How would that happen?
I don't think that's the same error
Did you save it as something other than .png and remame it to a .png
idk, show your code and file structure
I'm on the latest smods release by the way, 1224a
yeah that's a valid point
1x is the same
I did not, I exported it straight out as a PNG. I was using GIMP
I tested the mod I made yesterday and switching to 1x gives the same crash
both repros show me being on the latest release. i'll ask with some of the people playing my mod if unlocks work for them and it's somehow just a me issue
in that case, i don't mind if it's just me - if it actually works for the people playing my mod, then that's fine
is it because the run is seeded?
I just noticed that
i don't actually know if that matters but might as well try
oh right, i should try to repro with unseeded 
unlocks are disabled on seeded runs...
Yeah seeded run block unlocks
oh well that's why then
Dupid
What image editors do people use when exporting for balatro?
personally libresprite
Have you ever had a decode error?
i don't think so
i use gimp myself
This is so weird
the mod just isn't displaying, it's just the default balatro textures
I genuinely don't get why its doing this
players confirm that jokers unlocked via set_ability remain locked in collections
when i attempt to load an image i get an error saying that it couldnt open my image in mode r
msg = string: "[SMODS edensmod \"edensmod.lua\"]:3: Error reading file 'jokers/customimages' for mod with ID 'edensmod': Could not open C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods/edensmod/jokers/customimages in mode r
full log attached
thanks in advance if you know
i have no idea what mode r is, i've searched in this channel for it and the only piece of advice i've found is close whatever is using the file, but i dont have anything open that would be using it afaik
how do i use card_to_draw
i want to increase the number of cards to be drawn
but from what i see in the example code there's only a way to overwrite the number
Yes, you would do cards_to_draw = context.amount+number
thank you
loc_vars = function(self, info_queue, card)
local emptyCount = math.max(0,((G.consumeables.config.card_limit or 0) - ((#G.consumeables.cards or 0) + (G.GAME.consumeable_buffer or 0)))) + math.max(0,((G.jokers.config.card_limit or 0) - ((#G.jokers.cards or 0) + (G.GAME.joker_buffer or 0))))
return { vars = { emptyCount, card.ability.extra.gold } }
end,
okay which one did thunk misspell the misspelling again
consumeable is the bane of modding this game
No, it's because G.consumeables doesn't exist outside of a run.
if i set consumable type shop rate to 0, it wont be able to show up in the shop right?
where do lucky cards store their chances to trigger?
i believe it's somewhere in G.P_CENTERS.m_lucky
ok so can I put consumables in the same lua file i program jokers?
Can SMODS.poll_rarity return "legendary"?
figured
could I access it in here?
like via card.ability.something
do you want to try that image again?
my phone camera sucks
They don't, it's hardcoded.
Win + shift + s
have you heard of Windows key + Shift + S
it lets you take a screenshot
and copies it directly into your clipboard so you can paste it into discord
Or print screen key
Astra I swear you should know this by now 😭
I dont have wifi
phone hotspot?
I have my own server I lurk in not this one
sucks
yes I have
plug your phone into your computer so you can grab the screenshot that way?
okay that's kind of annoying but makes things easier
I forgot my cord
I typically bring one for that purpose but I left it at home
have you tried holding your phone with two hands when taking a photo
I do
okay i think I got it working
ok so i managed to get the basics of implementing a consumable but now
how do i get a consumable to have a unique image?
cuz right now it's using the default fool image
the same way you do it for a joker
same way for jokers
Or any other object
define at atlas
okay it works but the regular effect is still happening ;-;
the thing is, i did it like i normally do for the jokers
i put an icon in assets, then i put an atlas position
whats the consumables code look like?
key = 'canarycry_token',
set = 'DCBalatro_Token',
pos = { x = 0, y = 0 },
config = { extra = { planets = 2 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.planets } }
end,
use = function(self, card, area, copier)
for i = 1, math.min(card.ability.extra.planets, G.consumeables.config.card_limit - #G.consumeables.cards) do
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
if G.consumeables.config.card_limit > #G.consumeables.cards then
play_sound('timpani')
SMODS.add_card({ set = 'Planet' })
card:juice_up(0.3, 0.5)
end
return true
end
}))
end
delay(0.6)
end,
can_use = function(self, card)
return G.consumeables and #G.consumeables.cards < G.consumeables.config.card_limit or
(card.area == G.consumeables)
end
}```
it's just the high priestess
but i changed the key
and set
you never set the atlas
what error
oop
it's showing now
@dreamy thunder rn I have something along the lines of
store original calculate
take ownership of lucky card
overwrite calculate
check main scoring, scored cards, and specific joker present
return {mult = 4, dollars=1.3}
return original calculate
lucky cards dont have a calculate function
its incase some other mod added one
change its name
vanilla objects determine their effect with one big central function doing if-then on their name
like change its key?
that is, the center's name field
it shouldn't off the top of my head
you might have to reimplement its loc_vars and some other vanilla features
ideally the localization is based on the key, but i wouldn't put it past
to do that sort of thing by name too lol
iirc localization is key based, vars are name based
ah
do I just put name in the take ownership section
yes
k trying it out now
That will stop it from working without your joker
still fired twice
hm
that does make some difference :v
nope still twice
I imagine the check isn’t based on the name because of quantum enhancements
ah of course, thunk did the same thing two different ways
so would take ownership using effect work?
what are we trying to do
should
though you may have to reimplement the normal calculate as eremel said
disable the regular calculation for lucky cards when I have a specific joker
already did that

shouldnt it already do that
a lot of vanilla stuff is hard coded in a way that can't be directly overwritten by taking ownership
I thought I could do it the same way as vanilla jokers but apparently not
but smods does take ownership
in the dump it looks like its still using .effect to check
okay well let's go look at that first before assuming it's all vanilla then
the weird thing is that my effect is triggered, and the default effect
ah no its just for loc vars
you are reimplementing lucky anyway
why not just patch it out
^
whats the file name?
card.lua
card.lua search for "Lucky Card"
thx
ok so i want my joker to create a specific consumable when triggered
how would i go about that?
SMODS.add_card({key = 'c_modprefix_key'})
bump
It should be context.debuff_card:is_suit('Hearts', true)
You know the “hand will not score” message?
How do you display that without the hand being debuffed?
what does lovely do if multiple locations match a pattern?
patch each location
unless you add a times value to the patch, then itll only patch the first times matching patterns
any idea why this wont patch then?
i am
key = "blackcanary_joker",
config = { extra = { poker_hand = 'Straight' } },
pos = { x = 0, y = 0 },
rarity = 2,
cost = 6,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
atlas = 'blackcanary_joker',
soul_pos = nil,
loc_vars = function(self, info_queue, card)
return { vars = { localize(card.ability.extra.poker_hand, 'poker_hands') } }
end,
calculate = function(self, card, context)
if context.joker_main and next(context.poker_hands[card.ability.extra.poker_hand]) and
#G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
SMODS.add_card ({dcbalatro_token = 'c_sj_canarycry_token'})
G.GAME.consumeable_buffer = 0
return true
end)
}))
return {
message = localize('k_plus_spectral'),
colour = G.C.SECONDARY_SET.Spectral
}
end
end,
}```
effect keeps displaying error message :[
im trying to make it generate a specific consumable when a straight is played
Log?
you mean this?
use key not dcbalatro_token
Yes, it should be SMODS.add_card({key = 'c_sj_canarycry_token'})
bump
:0
Is this file called lovely.toml or in a folder called lovely and in your mod's folder?
shouldn't pattern be in normal quotes?
lovely/simplex.toml
No, it can be ', " or '''
the triple quote format is just standard syntax, no issue there
Ah
i guess that makes sense, I guess i've only ever seen single line patterns so there's never been any need for it :P
yay it worked
the line has a space at the end
Yeah, was gonna say i dont see that in my card.lua?
unless the lovely dump strips those
it doesnt
ohhhh
the first doesnt have a space
lolll
that doesn't explain why the first line wasn't patching though
still no luck
neither patched
last thing to bring it all together, how do I give this a unique message instead of "+1 spectral?"
Change localize('k_plus_spectral') to 'message'
stil didn't change anything
is there a context like context.card_added that runs for the card being added?
you should use the add_to_deck function instead
does that work for stickers?
only seems to trigger the other jokers
You could hook Card:add_to_deck and Card:remove_from_deck and check for the sticker there
I guess
yeah guess I'll have to do something like that
unrelated, anyone know why this blind has the wrong texture specifically in the challenge restrictions screen? looks correct everywhere else
I'd normally check if steamodded does some patches that makes the pattern unrecognizable, but the only patch it does over this piece of code doesn't change the pattern
okay so I completed restarted balatro and it started being recognized
weird
but somehow the original code is still firing
firing with not FooBar.average_probability() false?
Lovely has a bug where the dump doesnt get updated if you use the restart hotkey instead of fully quitting out and relaunching
So that probably was the issue
argh, what? now i have to account for this too?
I have a question: I can add my own menu in the settings through just 2 patches, but I want to do the settings possibly in my own config. How do I achieve that?
ooooh
yeah
I tested in the console and FooBar.average_probability() was true
I don't use the console, what I'd do in this situation is make average_probability always return true/false and test it, maybe it becomes true/false right after the check you make because of some context synchronization is my guess
its a helper function for if the simplex joker is present
which it is
ohh so just next(SMODS.find_card("j_MODid_joker")) functionality
yeah
and does the conditional statement misfire with the next(...) function, or is the average_probability returning in one line the next(...)
lemme check
SMODS.find_card already doesnt count debuffed cards by default
ok i just realized my consumable needs a description text, how do i give it that?
ummm, why [1], seems off to me
Gets the first found card
ohh first card
normally i go in the en-us file and add in the parameters
oh didn't know that
either way that wouldn't change my code from not working
the card isn't debuffed
do i need a seperate section for consumables? and do I use the j_(mod prefix) for the consumable?
If its a custom type it should get put in a new category with the consumable type key as the category key
and its c_modprefix_key for consumables
oh wtf
okay so the actually cards effect is being triggered twice
its not the default
okay i'm now more confused
where are these numbers coming from
im definitely doing something wrong, the consumable still doesnt have the text in game
I have a single consumable but it works like this:
SMODS.Consumable {
...
loc_txt = {
name = 'name',
text = {
'descr'
}
}
...
}
genuinely gonna crash out why is this not working
OOOOOOH
i think I foundn it
since i'm taking ownership of the card, I"m assuming its now subject to all of SMODS stuff
so the built in p_dollars in the config is now being treated as a value to always return
ah yes

YES IT WORKS
so, most tutorials to make balatro mods are to make jokers, so i wanted to ask: i want to make a mod that prevents jimbo from appearing (for example, if all legendaries were gotten and jimbo is about to appear, it changes to a rare), so, can i ask where could i get the resources of how to do it?
you would need to patch/hook get_current_pool/create_card most likely
what would the info_queue entries for foil, holochrome, and polychrome be?
there's a new feature for modded rarities that does something like that so it could be repurposed i think
G.P_CENTERS.e_foil etc?
thx
i forgor
okay wheel of fotunre should theoreticly work
nope
nvm it does work i forgot i had 4 oops
I have a question about how SMODS works.
In Joker's default constructor, there is a function called inject, which will add this joker to all the ingame pools.
and this function will be called from the obj_table and obj_buffer
that are a part of the GameObject class
but. how do objects get added to obj_table?
because doesnt all this thing does basically create a table? how does this table end up in a global class array
doing SMODS.Joker({...})
calls the GameObject register function
(smods classes use a metatable so you can call them like a function)
okay i see that register is appending to the obj_table, but how is register called then?
like i dont see any register call in the __call
is the key for holographi cards just "holo" or something?
thank you so much, i now understand the structure of SMODS

does this description make enough sense?
Yes, blind.effect
thx
Yes.
Thanks!
woah
first time in in here
how do i view the voucher source code?
i cant find it
i assume youre looking for how vanilla vouchers are coded?
use VanillaRemade, it remakes basically all vanilla content as if it was modded. It's a much better reference than actual vanilla code
https://github.com/nh6574/VanillaRemade/blob/main/src/vouchers.lua look for it here
tysm fellas
I LOVE THUNK CODE
love yall
happy to help
game recongises game
Anyone know why this calculate function doesn't work? I'd like this seal to give additional xchips for every scoring card that has that same seal, e.g. 1 scoring card of this seal gives 1.1x chips, 2 scoring cards of this seal each give 1.2x chips, and so on but it currently does absolutely nothing
calculate = function(self, context, card)
if context.cardarea == G.play and context.main_scoring then
local love = 1
for k, v in ipairs(context.scoring_hand) do
if v.seal == "Love" then
love = love + card.ability.seal.extra.xchips_inc
end
end
return {
x_chips = love
}
end
end
is it entering the context, you should always try adding prints to if statements
from what i see the problem could be that the seal is missing the mod prefix
Is it possible to implement a shader that goes over the entire game when a certain condition is met, like a vignette? if so, how would I achieve this?
there's a feature for that in the next smods version
Contribute to real-niacat/Wiki development by creating an account on GitHub.
I have smods-1.0.0-beta-1224a, is this a feature in this beta release, or should I wait?
it's not in that release, no
gotcha
It should be if v:get_seal() == 'modprefix_key'
Thank you!
what if i did a manual check for unlock call behind a check for unseeded run, plus a save progress
even just to patch it over so that i don't have to immediately untangle my code from half a year ago to figure out a fix
did you tell them to go to an unseeded run
they were most likely doing unseeded runs since they weren't trying to debug and actually play the game 
hi guys. Do you know how to make the finisher blind have a score multiplier?
I wanted to make a stake that makes them be x1.5.
Tried to look around for a starting point but couldn't find any.
what do you mean
i believe its mult =
Having the finisher blinds require 50% more chips. So on ante 8 if the boss blind would require 200k chips base it now would require 300k.
you want to change the base multiplier right
like are you looking for the 2x base?
yeah I guess it would be times 3 in that case.
mult = 3
but only for the finisher
you want to make a showdown blind right
no, modify the current ones. it's for a new stake
G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) * 2
this multiplies the base
for all blinds
idk if it affects boss blinds but it probably should
ante 1 will stay the same though
that's fine. do you know if I can make this only affect ante 8?
and 16 and 24 and so on
add a check for ante modulo 8
and u can do the scaling = 1 + ante modulo 8
i think
thats where i would start at least
np
For people that have set up timers through events, what would be the best way to make timers continue when the game is restarted?
How could I modify the cost of a specific joker during a run
card:set_cost()
thx
Contribute to nh6574/VanillaRemade development by creating an account on GitHub.
does it update it for all future occurrences or no
no
how would I do that then?
when ever it appears in shop it should double
oh wow
inflation 👍
You can hook set_cost() and rely on a global variable. If you check whether the card where the cost is being set is the right one, you can intercept and double it
Thx
what file is set cost in?
I'd reckon card.lua?
honestly i would try to do a global that resets on new run
and then set the card cost as that global
yep found it
thats what im doing yah imma use G.GAME
good luck
yeah, good point. That's what I meant, but I should've probably made that clearer, haha
hmm okay actually it might be easier to patch instead of hook
Why's that? A hook should be fine for that function
the function calculates some stuff at the end that I would prefer to not take into account
oh wait actually there's some more jank
imma hook instead
In that case, you can mess with the price before, no?
printscreen technology was forgotten once again
I'm having issues with an animated joker where after running for a couple seconds it goes black, I've tried putting it all in one line as opposed to a grid but then it's a weird red and white block like the polish flag?? Any ideas of where I screwed up? It could also just be that the animation is far too long because it is around 8000 frames but idk
no it wasnt
also any idea why the code won't work?
increasing inflation like this is definitely bad idea since set_cost called pretty often in various cases
So i figured out it is because the png isn't wrapping back to the left side for the animated joker, are all animated joker sprites one line as opposed to multiple rows?
what would be a better way?
wait nvm I know one
okay it works thx
what is the limit of frames per animated joker?
calculate = function(self, card, context)
if context.final_scoring_step and context.cardarea == G.jokers then
if context.scoring_name == "Pair" and #context.scoring_hand == 2 and not (G.GAME.hands[context.scoring_name] and G.GAME.hands[context.scoring_name].played_this_round > 1) then
local c1 = context.scoring_hand[1]
local c2 = context.scoring_hand[2]
local suit = pseudorandom(pseudoseed('merge_suit')) < 0.5 and c1.base.suit or c2.base.suit
local rank = c1:get_id()
[... card enhancment, edition grabbing code, ...]
local merged_card = create_playing_card({
front = new_front,
center = new_center,
}, G.play, true, false, nil, true)
merged_card.ability.perma_bonus = rank_to_chips(rank)
merged_card.ability.felijo_stk_stitched = true
if new_seal then
merged_card:set_seal(new_seal, true)
end
if new_edition then
merged_card:set_edition(new_edition, true)
end
G.E_MANAGER:add_event(Event({
delay = 0.3,
func = function()
c1:start_dissolve({G.C.MONEY}, true)
c2:start_dissolve({G.C.MONEY}, true)
return true
end
}))
G.E_MANAGER:add_event(Event({
delay = 1,
func = function()
merged_card:start_materialize()
G.deck:emplace(merged_card)
return true
end
}))
My joker is not deleting playing cards correctly, it can still be drawn to hand
when i look at G.hands.cards[x] it says added to deck = false, removed = true, being_removed: true
SMODS.destroy_cards(cards) instead of whatever the fuck you're doing
cards is a table or a Card
it works thank you
my game crashed when i used the better hanged man card but the crash references an SMODS file and not my own. i know my code has to be the issue but i have no idea what happened
Code?
let me check something
@daring fern how is your shader applied
this is ash card enhancement from aikoshen, with negative edition
ash card isn't a shader tho, it's just the texture
oh
i guess apply the shader last?
isnt there a layer system? i remember seeing such a thing when working with stickers
am i blind or is the game blind
Move the play_sound out of the return
it's saying that you're missing a comma before chips
but the play_sound shouldn't be in the return at all
so it should be after the return right
No, before.
ah right
(good i double checked)
now the issue i have now is how do i make it so the sound plays when the chips animation happens and not when the cards are played (since that's what's happening rn)
Put this in the return:```lua
func = function()
G.E_MANAGER:add_event(Event({
func = function()
play_sound('modprefix_key')
return true
end
}))
end
anyone happen to know why when i play a sound it crashes? im using my prefix but it cant find resources/sounds/eden_outro.ogg
mult = self.config.extra.mult,
message = strings[math.random(#strings)],
sound = "eden_outro"
}```
"prefix": "eden",
Did you define the SMODS.Sound?
ahh i forgot to do that, that's definitely it! thank you
is there a context for checking when a boss blind is beaten?
ik there's context.end_of_round but that goes for all blinds
checking, not that I'm aware of
there's context.blind_defeated if you just want the timing
yeah, that works
is there a way to check the name/key of the blind to go with it then?
I'm sure it's in some global variable, but i can't recall the name offhand
actually, come to think of it, i can probably just put a calculate function in the specific blind with context.blind_defeated, cant i?
probably!
G.GAME.blind:get_type() will get you the type of blind that was being faced.
G.GAME.round_resets.blind_choices.Boss == "bl_kino_xenomorph" will get you the key
Oh, didn't remove my own key from it
context.end_of_round and context.beat_boss
No, G.GAME.blind.config.blind.key is the key.
i think i got it now
my main problem is jsut figuring out how to make an achievement that triggers when this boss is defeated
which i realise should've been the first thing i asked .w.
does anyone understand why in the generate_starting_seed function there are lines about legendary joker??
when the boss is defeated, call check_for_unlock{type = "custom string"}, then define the achievement's check for unlock to return true if args and args.type == "custom string"
yeah, i had done that, but it's not working
that calculate function doesn't appear to be part of any object
yeahh idk where to put it tho, outside of inside the related blind which doesnt feel right
No, you should put the check_for_unlock call in the defeat function of the blind.
the blind would've worked fine (you could even put it in the blind's defeat function)
but yeah mod calculate also works
i see
it worked! 
tyyy
is there a way to take ownership of Game:init_game_object() in SMODS?
No, but you can hook it.
would there be a way to make a "playstation platinum trophy" kind of achievement? where you only get it if you have all other achievements?
when the game is doing a save/load, how can i save and load modded data? its a global parameter and not part of any specific item
putting it in G.SETTINGS would work
G.SETTINGS[G.SETTINGS.PROFILE] if you want it to be profile specific
if it's just for that run save it to G.GAME
that as well
thanks
No, for profiles it would be G.PROFILES[G.SETTINGS.profile]
right, those words
may i ask how? and maybe an example?
local oldinitgameobject = Game.init_game_object
function Game:init_game_object()
local g = oldinitgameobject(self)
g.modprefix_variable = value
return g
end
thank you!
How can i change the seal label's text colour
text_colour = HEX("FF0000")
i dont think you can
text_colour is only on consumable types (and i would know, i implemented it)
it would certainly be nice to have it on other badges like this tho, i'll keep that in mind for when i get my laptop fixed
It didn't work thanks anyway i also tried badge_text_colour also didnt work
too slow im working on it rn
500 smods PRs 🙂↕️
smods delayed by yet another week
yeahh mb, i noticed you were talking about seal labels a little too late, my mind autopiloted thinking it was about custom badges lol
murphy will never get his xmult
I can change the seal's name colour with {C:red}{}, its very strange i cant do the same with seal's label
because they dont use the same formatting system
ohh it makes sense
it's like using a hammer on a nail vs using a hammer on a screw
i should fix that to remove formatting as well since im pr'ing it
yes, but i don't think it's an easily toggleable setting or anything. iirc ego gifts in the dev branch of paperback remove the use button
"pr"?
is that an acronym im not enough of a dev to understand?
yes :3

Pull request
ah, i see
it's pull request, when you ask for them to add code to the repository basically
yeah
so I might look in that ig
got it :3
if i wasnt so obsessed with ultrakill, i would've understood sooner instead of just thinking p-rank lol
does this need to do all the loops every time it needs to get the badge colour lol
good lord
Hey guys. Back again.
Do you know how to make the score scaling affect only an specific ante?
I can't figure it out. fr.
Specifically to have the ante with the finisher blind require more chips.
i mean, you can just do mult = 8, in the blind itself
idk about a whole ante though
Yeah, I have not been able to find any examples of that.
Hook get_blind_amount and check if any of the blind choices are the specific showdown blind?
if i wanted to replace a card within a booster pack as it's generated, what would be the best way to go about it? currently i have card:set_ability bound to an event that fires immediately within an context.open_booster calculation, but you're able to see the original card briefly before it turns into the new card. is there a more seamless way to do this? if i remove the event, i get a crash telling me G.pack_cards is a nil value, which i presume means the code is then running before the pack cards actually exist.
(i am aware of hidden and soul_rate but from testing this causes the card to be able to be capable of appearing in spectral packs regardless of soul_set which is undesired, i only want these cards to replace tarot cards)
Maybe, I also thought about only modifying the showdown blind. That could work.
Hook CardArea:emplace
worked like a charm, tyty
Im not sure where to look for that, I checked every file that has ego gift in it
oh it's three patches, lovely/ego_gift_buttons.toml
(it's three patches because two of them are for controller buttons and the other is for keyboard/mouse buttons)
oh ok
also the patches use a custom function that checks if a given card is an ego gift, you'll have to reference that function or do your own work to determine if the card is of the consumable type you're working with
btw, guys. Does this work to indicate I want the ante with the finisher blind?
G.GAME.round_resets.ante = G.GAME.win_ante
I swear I saw it before
it should be == for comparisons, but that looks right otherwise
ooh, thanks
No, it should be (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2
oh that doesn't work if the win ante is modified
but yea clover's original one doesn't work for finisher blinds in endless mode
Yeah I saw that
what does the % mean?
it should be G.GAME.round_resets.ante % G.GAME.win_ante == 0 so that it works if the finisher blind appears in endless mode
% is remainder division
wow, never seen that, let me try it
Oh this is cursed
modulus, basically just remainder
if x % y == 0 then x is evenly divisible by y, which is the condition for finisher blinds to appear (in vanilla balatro that's antes 8, 16, 24, etc)
I see, thanks. 
Also, thanks. 
thx @frosty rampart
Guys... What's foiling my incredible rework?
SMODS.Stake:take_ownership('stake_blue', {
modifiers = function(self)
if (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and
G.GAME.round_resets.ante >= 2 then
G.GAME.modifiers.scaling == (G.GAME.modifiers.scaling or 1) * 1.5
end
})
It looks fine to me.
you only have an end for the if statement, you need one for the function too
you have == instead of = in G.GAME.modifiers.scaling == (G.GAME.modifiers.scaling or 1) * 1.5
also missing a end ya
wow, that's what I needed.
Thanks.
no prob
and now i can't reproduce the issue under normal gameplay conditions at all 
May I ask how I could go on about changing it or improving this?
It doesn't seem to be quite working. It kind of gets ignored.
chat, whats the difference between save_run() and G:save_progress()
Cant rn, but it’s an enhancement with no special code
Think stone card but no chips
Code?
if next(SMODS.find_card("j_TBC_joker1")) or next(SMODS.find_card("j_TBC_joker2")) == true then
end
am I overcomplicating my line of thought? can I just put math after the "true then" and then connect it to a variable?
if you want to see if you have one of those two jokers then that's correct except for the == true, next doesnt necessarily return a boolean
save_run saves just the current run
G:save_progress saves all progress
so the == true is redundant?
such as achievements and stuff
here it is wrong rather than redundant, but == true would be redundant in an if in most cases
also i am setting my custom parameter in G.GAME, but it isnt being loaded on load 💔
i see
where is this and what is e.config.event_data
e.config.event data is a custom table im passing on button press, i checked with print and its not null
what does the table have
GameObjects cannot be saved
modifiers = function(self)
if (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and
G.GAME.round_resets.ante >= 2 then
G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) * 2
end
end
})```
Afaik
recursive tables wont be saved properly
gotchu
same with functions
modifiers is only called when the run starts.
ok i got side tracked by the badge colour thing instead of working on my mod
is there a reason why this error pops up, i even added "gros" as second argument just in case
here's the lua files
does any other process have that file open
outside of vscode(?)
Why are you using pcall and assert?
do you have it opened in vscode on its own or did you open the folder
i think the folder option i can close out of vscode
error catching you can ask @modern kindle as he was the one that programmed it


