#💻・modding-dev
1 messages · Page 678 of 1
question about that, i can't use SMODS.has_enhancemnt inside context.check_enhancement cuz it will infinite loop (if im reading the documentation correctly), so how do i apply m_wild to cards with m_stone
if context.check_enhancement and context.other_card.config.center.key == 'm_stone'
oh, just check it using vanilla. okay lol
Is there an equivalent to the config = {} of jokers for blinds?
Yes, it's still config, but it's located at blind.effect
Can I not get it in the set_blind function, for example, then?
No, you can, you would just have to use G.GAME.blind
Yeah, just figured that out. Reading comprehension is key, it turns out.
I've noticed that the Challenge Deck modifiers have their value information directly sent into the localization strings, like the one for X-ray Vision with 4:
ch_c_flipped_cards={"{C:green}1 in #1#{} cards are drawn face down",},
How do I change what values are passed to that?
ch_c_LAPSEMS_only_boss_blinds = {"All {C:attention}Boss Blinds{} are #1#"},
G.GAME.modifiers.ch_c_LAPSEMS_only_boss_blinds.value takes a table of the valid Boss Blind keys, and I have a function that turns a table of strings into a list "string_a, string_b and string_c".
couple questions regarding quantum enhancements:
- do these cause lag? i'm getting a lot of slow down when they're in hand
- i have stone cards also being wild, and it automatically applies the wild sprite. how do i control what it looks like?
- when i use
set_abilityto remove stone, the wild sprite stays on the card even though it's not wild anymore. how do i fix that?
Yes, and everything after question one should be fixed on the dev version.
should i switch to dev or just wait for the next release?
You should switch to dev because your developing a mod.
i dont see a dev branch in the github. do you mean just grabbing the code from main instead of using the latest release?
The main branch is the dev version
great. ill grab that. thanks
im guessing there's not really a way to optimize the quantum enhancements to prevent the slowdowns?
this is where i solve the problem by creating a new problem
No, there is, it's what I use in my mod for quantum enhancements.
it's not just about the challenge value - it's about the fact that it reads the value raw
which mod is that? ill take a look
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = ''' game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {v.value}}}'''
position = "before"
payload = """
if v.akyrs_localized_value then
game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {localize(v.akyrs_localized_value)}}}
else
"""
overwrite = true
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = ''' game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {v.value}}}'''
position = "after"
payload = """
end
"""
overwrite = true
match_indent = true
this is what i did
and then when i put the rules in i do
{id = 'akyrs_all_blinds_are', value = "bl_akyrs_the_thought", akyrs_localized_value = {type = "name_text", key = "bl_akyrs_the_thought", set = "Blind"}},
hope this helps
anything in particular i should be looking for in here?
Is there a way to call a list of the keys for all the currently legal planet cards? Like to use pseudorandom_element to call a random planet key or something
G.P_CENTER_POOLS.Planet
ty
This was supposed to return a random planet key but it's returning a table for some reason? How do I make it return a planet key like c_pluto or something
Made some modifications, but they haven't quite worked.
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = ''' game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {v.value}}}'''
position = "before"
payload = """
--[[
Code adapted from Aikoyori's Shenanigans.
[#💻・modding-dev message](/guild/1116389027176787968/channel/1233186615086813277/)
--]]
if v.LAPSEMS_localized_value then
game_rules[#game_rules+1] = {
n=G.UIT.R,
config = {
align = "cl"
},
nodes = localize{
type = 'text',
key = 'ch_c_'..v.id,
vars = {
v.LAPSEMS_localized_value
}
}
}
else
"""
overwrite = true
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = ''' game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {v.value}}}'''
position = "after"
payload = """
end
"""
overwrite = true
match_indent = true
{
id = 'LAPSEMS_only_boss_blinds',
value = {
'bl_lapsems_mask',
},
LAPSEMS_localized_value = LAPSEMS.recursive_list_of_localized_blind_names({'bl_lapsems_mask'}, 'or')
},
Yes, each item in that table is a center, not a key.
so then how do I make it a key ;-;
random_consumable_result.key
There was some debacle I was dealing with where localization files weren't loading in correctly. Here I punched them in manually and there was no hassle.
Here's the link.
#💻・modding-dev message
Yes, the problem was you were running it before the localization was loaded.
How do I ensure that the localization doesn't produce an ERROR?
im using joker forge
i made a variable but i cant fucking use it
what does LAPSEMS.recursive_list_of_localized_blind_names({'bl_lapsems_mask'}, 'or') return
wait nvm i solved it
LAPSEMS.recursive_list_of_localized_blind_names = function(list_of_blind_keys, end_of_list)
local localized_table = {}
for _, blind_key in pairs(list_of_blind_keys) do
localized_table[#localized_table + 1] = localize {
type = "name_text",
key = blind_key,
set = "Blind"
}
end
return LAPSEMS.recursive_list_maker(localized_table, end_of_list)
end
LAPSEMS.recursive_list_maker = function(list_to_use, end_of_list)
--[[
k_lapsems_list_and = "#1# and #2#",
k_lapsems_list_or = "#1# or #2#",
k_lapsems_list_recursive = "#1#, #2#",
--]]
if not LAPSEMS.contains({'and', 'or'}, end_of_list) then
end_of_list = 'and' -- defaults to "and"
end
if #list_to_use == 1 then
return list_to_use[1]
elseif #list_to_use == 2 then
return localize{
type = 'variable',
key = 'k_lapsems_list_' .. end_of_list,
vars = {
list_to_use[1],
list_to_use[2]
}
}
else
return localize{
type = 'variable',
key = 'k_lapsems_list_recursive',
vars = {
table.remove(list_to_use, 1),
LAPSEMS.recursive_list_maker(list_to_use, end_of_list)
}
}
end
end
frankly i am too lazy to read can you send just the output 😭😭
eval LAPSEMS.recursive_list_of_localized_blind_names({'bl_lapsems_mask', 'bl_lapsems_final_cloak'}, 'or')
-- "The Mask and Chromatic Cloak"
{
id = 'LAPSEMS_only_boss_blinds',
value = {
'bl_lapsems_mask',
},
LAPSEMS_localized_value = 'The Mask'
},
hmmm
so it works with just string
i would suspect LAPSEMS.recursive_list_of_localized_blind_names({'bl_lapsems_mask'}, 'or') to not return string so try adding like parentheses and "".. to coerce it into string
LAPSEMS_localized_value = (""..LAPSEMS.recursive_list_of_localized_blind_names({'bl_lapsems_mask'}, 'or'))
why would this in my joker cause the game to crash on hover? works fine when this is commented out
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS.m_stone
info_queue[#info_queue + 1] = G.P_CENTERS.m_wild
end,
what's the crash
SMODS srs/util line 1001 config is nil
that's in the SMODS.has_enhancement() function
huh
oh, is it because of quantum enhancements?
i feel like the info_queue is just cursed for me. i've never gotten it working correctly
Manually setting the values does work.
i wonder if this is like
actually i think i kinda do know why it doesn't work
the challenge is initialised at the start of the game alongside the rules
that includes the value
i think that is why i localize it that way
so you'd have to put the function that gets the localization of the things you want in the patch
so it runs the function to get the text at runtime
when it comes to forge you're better of making custom stuff youself
ngl i encourage people to start coding
forge is ok if u wanna make a template for something but once you need to add custom stuff forge just sucks at it
I use it just to cobble together something that I want to do when certain stuff is met then just fill in everything else with custom stuff lol
to lazy to retype game conditions

okay, so it's because i was trying to dynamically change the description of stone cards with this particular joker
Is there a smod function to set a custom boss to show up at a specific ante
wanna make a custom boss always be the ante 8 boss
idts
I was advised, @tall wharf, to refresh the localization values with a hook instead, but this one just crashes the game when I try. What do I do, Noodlemire?
local LAPSEMS_game_main_menu_old = Game:main_menu(change_context)
function Game:main_menu(change_context)
--
return LAPSEMS_game_main_menu_old(change_context)
end
huh, okay... so i've been having an issue with info_queue where the things i put in it just don't show up. but then sometimes some things do and others dont for the same card. i just figured out what the pattern is: the last thing i add to my info_queue just doesn't show up.
so THIS, shows stone and wild. but only shows wild once. if i remove the second instance of adding wild to the queue, then only stone shows up:
loc_vars = function(self, info_queue, card)
info_queue[#info_queue+1] = G.P_CENTERS['m_stone']
info_queue[#info_queue+1] = G.P_CENTERS['m_wild']
info_queue[#info_queue+1] = G.P_CENTERS['m_wild']
end,
why would this be happening?
It should be return LAPSEMS_game_main_menu_old(self, change_context)
Still crashes all the same.
local LAPSEMS_game_main_menu_old = Game:main_menu(change_context)
function Game:main_menu(change_context)
--
return LAPSEMS_game_main_menu_old(self, change_context)
end
It should also be local LAPSEMS_game_main_menu_old = Game.main_menu
Are you modifying anything UI related?
local LAPSEMS_game_main_menu_old = Game:main_menu
function Game:main_menu(change_context) -- Here's the offending line.
--
return LAPSEMS_game_main_menu_old(self, change_context)
end
No, it's . not : on the line I gave you.
i don't think so other than adding custom buttons elsewhere
And with that, it's all lookin' shipshape!
how do i change a card's sprite dynamically? i'm using key in loc_vars to dynamically change it's description, but im not sure where to put the code for changing the sprite or what that code actually looks like
Use the set_sprites function.
that seems to accept a center and front but i want to change the sprite of a center dynamically. can i just modify card.config.center.atlas and its .pos directly?
or maybe instead, changing G.P_CENTERS['enhancementkey'].atlas?
no
you have to use card.children.center
you can change the sprite pos by calling card.children.center:set_sprite_pos({ x=x, y=y })
you do still have to take care of it being properly reloaded by saving the pos somewhere and reapplying in set_sprites
so what im trying to do is make all stone cards use my custom sprite when my custom joker is in play
where do i put it? update? current_mod.calculate listening for context for gaining and losing jokers?
add_to_deck/remove_from_deck of your joker should do
what do i use for the card ref in that context?
iterate through G.playing_cards
are add_to_deck and remove_from_deck a context or a method?
oh they're methods. okay
got it working. thanks for the help
there's some way to get localized card names for loc_vars. is it something like localize('name', card.edition.key)?
localize({type = 'name_text', key = 'classprefix_modprefix_key', set = 'set'})
ah, thanks
Hi everyone.
Do you know how to make a tag only appear on the big blind?
gimme like 10 minutes and I can check, but if not you could probably hook the function that generates tag keys
nvm
how might i be able to check if a certain key leads to an object ? specifically an SMODS.Sound object in this case
if SMODS.Sounds[key] then
question : when making spectral to apply custom seals, do you have to prepend the seal key with the mod prefix?
how do i animate Jokers?
In the SMODS.Atlas definition, add
atlas_table = 'ANIMATION_ATLAS', -- items using this atlas are animated.
frames = x, -- how many frames are there.
fps = y -- optional, how fast it animates.
and align the frames horizontally.
thank you very much!
and i would use a separate sprite for this?
All depends on the sheet you've made.
I did it for one of mine - https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/main/assets/2x/togajokerupdate.png
my cards are set out like this right now
ah, i see
thank you!
Although, if you want a specific part of the atlas to conditionally show the texture, you can do it in similiar vein as to how I "animate" Rover.
(card.children.center is the base card, whilst card.children.floating_sprite is the soul sprite)
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/d4cb0a94b9a4eca1d0d76faa0a410d1e0b9e7ce7/items/joker.lua#L1956-L1988
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/main/assets/2x/togarover.png
well, uhm. Many thanks to you!
✌️
you gave me way more than i'd ever need!
😅 My bad-
Oh ma gawd phighting, wheres banhammer
tried making a spectral card but it crashes when hovering over it
SMODS.Consumable {
key = 'fragility',
atlas = 'HangedMan_Spectrals',
set = 'Spectral',
pos = { x = 0, y = 0 },
config = { max_highlighted = 1 },
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = {key = 'hangedman_glass_seal', set = 'Other'}
return { vars = { (card.ability or self.config).max_highlighted } }
end,
use = function(self, card, area, copier)
local conv_card = G.hand.highlighted[1]
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
card:juice_up(0.3, 0.5)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
func = function()
conv_card:set_seal('HangedMan_glass', nil, true)
return true
end
}))
delay(0.5)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
G.hand:unhighlight_all()
return true
end
}))
end,
}
not even when used i jsut looked at it in the collection
does your info queue thing also need vars?
oh
yeah it has a "X in Y chance" thingy
so it crashes because the infoqueue is not getting the vars? do i have to return those as well or
are infoqueue with vars jsut not allowed
Not yet
hii, sorry i was wondering if anyone can help me with this joker. This joker gives x1.5 mult for each consumable card you have, but i want to make it so the cards get destroyed once the hand is played, i saw that i had to add 'remove = true', but its not working, what am i missing?
@frosty dock probably you was wanted smth like this right?
Or, super short super easy use
remove doesnt work in that context, add SMODS.destroy_cards(context.other_consumeable) before the return
idk why i said to
iirc you just want to add specific_vars = {vars table} in your info queue entry
and it's the same vars table as loc_vars returns
though i think there's a different key it can want sometimes for no apparent reason even though it's literally the same info for the same purpose
yewh
also same bit of code, the spectral crashes on use, which im suspecting is because im not using the correct seal key
is it not [modprefix]_[sealname] ?
log?
it is
that worked thanks so much :)
Or even like this
yeah love it
why the chained calling though 🤔
because you cannot do stuff like ```lua
{
config = {}
"string 1"
config = {}
"string 2"
}
Unless you're specifying array of inputs
i mean you could always call it twice, but sure
does it work the same way on other templates?
Benefit of chained calling that it does not override previous config but merge them
So you're basically extending previous call if you need this
So if you want keep everything but just change, for example, alignment, you can do that
wdym by this?
like can I do
PB.R({})({})
and have it be two rows
no, this treated as extending of single row, aka adding more config or more children
rather than creating multiple of it
so it's exclusively for loc boxes? alr
wait i'm confuzzled
searching this channel i can only find how it works with jokers, like pulling its config out from a centre
but i cant find how to do it with seals
you can add vars = {} to the table
PB.LOC_TEXT is basically PB.C, which parses text lines to actual UI to make them properly render
It's still a single node
also im pretty sure you can use G.P_SEALS?
so in this case there's no use in chain calling for config
well these values just apply to the node itself, not its children
so that wouldn't make sense anyway right
correct, unless you want to do smth like this:
-- usual ui work, collection, idk
local my_constructed_nodes = {}
-- global? conditional? anything
local my_config_1 = { colour = G.C.MULT }
local my_config_2 = config.centered and { align = "cm" } or nil
PB.C(my_config_1)(my_config_2)(my_constructed_nodes)
fair
So each call extend element
Same logic for loc_text element
It extends configs for SMODS.localize_box or row definitions, and adds new lines
While for PB.R there's no point of it
ok yeah i see
row_config == line_config?
I'm still not sure about namings
what if r_cfg
c_config, r_config, t_config
yay, more memorizing what things mean
imo things should be descriptive
ok hold on so is it something like specific_vars = { vars = {G.P_SEALS[modprefix_sealkey].loc_vars} } or sometinhg???
Makes sense
there are just no one in this server that has ever mentinoed doing it with seals
but line isn't all terrible either
everyone's doing it with jokers
i cant search for past solutions because there's none
what about loc_box_config, it is passed directly to SMODS.localize_box
btw what's the point of column_config, can't we have that top level
in which case fuck consistency because it's easier to understand that the text entries are lines than rows
🤔
hm..
don't love loc_box_config tbh, but I'm not sure how to do better
i mean info_queue[#info_queue+1] = G.P_SEALS.key
shadow, text_colour too
that appears to be all
ew, yea, should be separate probably
ans especially because of vars
Anyway, naming can be discussed, easy fixable
More important that it's working
+1
I have im plans implement element which creates full info_queue just like card does
I need it from time to time but generate_ui sucks
Want it be like ```lua
PB.INFO_QUEUE({
direction = "l",
crawl = true,
{ set = "Other", key = "", vars = {} },
{ set = "Planet", key = "Saturn", vars = {} },
{ set = "Other", key = "", vars = {} },
})
or smth like this
You get the idea
Oh.
Same can be done for blind, or card' description
Like make templates for commonly used UI as this components
good stuff
main problem is of courser generate_card_ui
I have no fucking idea how it works, especially w/o center
I guess good opportunity to take a look
it's a bit of a mess built on top of a giant mess
actually very important question
let's assume we add this as part of SMODS
SMODS.O SMODS.C is not happening for sure
SMODS.UIT.C too long, even SMODS.T.C kinda long
pulling some strings on full_UI_table should probably let you get past making the first description a main box
SUI.C
i don't necessarily see this living in the SMODS table
I'm using PB because PaintBrush
ronaldo reference
i don't mind taking UI actually
-# unless any existing mods use this as a global
if they do that's a shame for them
most generic thing you can ever imagine
Only Game can become closer
the alternative is naked globals
R { O(), T { text = 'hello world' } }
that sounds horrible icl
while it would be really cool and very short, but I dont see this happening
I was using initially SUI as SimpleUI, but as SmodsUI also may work
short/long form duality: SMODS.Column, S.C
I meann
actually it can be optimized, since I added getter
idk who said that phrase but he always right:
The most difficult parts of programming is cache invalidation and variable names
Just a simple Yes/No since I can't check atm.;
Is there a "Minimum Discard Limit"? - Ex. Setting it to "2" means you cannot just Discard one card.
I don't think so
you can probably implement that in the same place the maximums are implemented but it sounds like it would lead to soft locks
It's for a challenge so that's not gonna be too problematic 
Thanks for the quick response 
how would i use SMODS.scale_card to scale a card's extra value, as extra_value is in the card.ability table where i'd be putting the scalar value in card.ability.extra, a separate table?
there's scalar_table if they're in different tables
ah, missed that, mb
help me out here. the discarding thing does not work at all
i'm trying to send every card in hand to discard and then redraw the rest of the hand
the discarding part just does not work at all
if i put it in an event, the event just never happens and the game is softlocked
if i make a new event inside the for loop instead of the for loop inside one event it creates events indefinitely
isn't there G.FUNCS.draw_from_hand_to_discard or something along those lines?
@primal robin on the topic of simple UI, what do you think of autowrapping misplaced rows/columns where columns/rows are expected?
uh
apparently
hold on
Like check children, if first child is row, expect others to be row and if they dont, fix this?
This is definitely possible
yeah. mixed rows/columns as children of the same node are never wanted, right?
correct
but this introduces some moments with filling & aligning
Needs some experimenting with this, but better of course idk, avoid messing with them
does a column directly in a column have a use at all? (or same for rows)
I don't do enough UI to recall
yes, for coloring/outlines
this is technically correct UI
I'm doing a lot of R in R just to paint them
But I see your idea
Implement some idiot-proof mechanics
This makes sense actually
resolve R/C things, empty G.UIT.O, moments when you need nore or array of nodes
yeah it's just mixed ones then. but it's definitely in the spirit of making UI simpler
I'll think about this common issues
Rewarding idiots for be itiots is not cool tho
But maybe printing some things in console may be useful while making ui not crash, makes sense
eh, maybe it makes getting into UI easier if we clean up after idiots where we easily can
also kinda true
Need refine API for all of this first, implement proper extending and such
not sure how to do it properly yet
Basic things like hooking method works but not pretty
and due to lua stuff, I cannot index function, it crashes
kinda lame tho, in js I can do that
index function?
wait that's right, it's a function, not metatable
......oh
I made smth like this for not but meh, need more thinking on this one
probably instead of function it should be callable metatable with extending things
or just fuck it and use Object:extend() like everyone else do
I made a joker that draws a card before hand is scored, but this card doesnt seem to activate due to held in hand effects
calculate = function(self, card, context)
if context.before then
draw_card(G.deck, G.hand, 100/#G.hand.cards, 'up', nil, self.foobar_reference, 0.08)
end
end
try during context.press_play instead?
nice, it now works, thanks
is there like a documentation specifically for all context?
this one only lists 4 of them
??
5
it lists all of them
smh
guess I'll sell Blueprint
same thing, am I doing it wrong?
sorry i took forever to get back
i recommend looking at the code for The Hook
ooh yeah true
G.FUNCS.discard_cards_from_highlighted is the easiest way to discard
Except they're not highlighted
ohhh
wait i'm also literally so stupid
it should be G.hand.cards
oh whoops I should have seen that
yeah so like. this only discards five cards
and then if i send it again it does the rest
local old_limit = G.hand.config.highlighted_limit
G.hand.config.highlighted_limit= 9999
-- code
G.hand.config.highlighted_limit= old_limit
: )
ok clearly i am approaching this the wrong way. this causes lag spikes every time you draw your hand and also does not work and causes ghost cards.
its just meant to make editioned playing cards give +1 hand size
fuck it im just patching whatever code checks for card_limit
well only one person is ever gonna play this mod so
🫂
What do I need to create a custom card area?
I tried CardArea(0, 0, 2, 2 {}) and it crashed
you are missing a comma there but assuming that's not it what is the crash?
oh there's a comma in the code
there's a template for cardarea in vanillaremade
I got no clue I didnt get a traceback
tried following it and tis still crashing
ah
should I just insert the card there as is
its purely for cosmetic purposes and has no interaction (I hope)
put a card here
you can use copy_card
if i put a function in a custom deck, i should be able to access that via the G.GAME.selected_back table somewhere, right?
so if i wanted to get the func here:
SMODS.Deck{ ..., myFunc = function(...), ... }
i would do
G.GAME.selected_back.myFunc()```?
yippee
G.GAME.selected_back.effect.center.myFunc
What’s a syntax in coding? I got a syntax error and need help fixing it. Btw if there’s an experienced coder here, I’d really appreciate someone looking over my formatting
uhhhhhhhhh
syntax is the format you write the code in
I would HEAVILY recommend learning lua
syntax error is when the code is written incorrectly
like 5 + 5 = 10 is not valid syntax in code
Okay, so theres a formatting problem. Damn, Idk any of the formatting. Just been copying balatros base code
and altering it
this won't work
Heres the rest of this code
Tarot isn't defined
could you copy paste it into discord it'll be easier to help
i recommend looking at this instead https://github.com/nh6574/VanillaRemade
really appreciate it
sure
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight", Tarot} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=nil,
eternal_compat=true,
unlocked = true,
discovered = true,
effect=nil,
soul_pos=nil,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and context.cardarea == "Giraffe" and G.jokers and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands{self.ability.extra.poker_hand}) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = (function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end)}))
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot,
card = self
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand, card.ability.extra.Tarot }, key = self.key }
end
}
;-;
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight", Tarot} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=nil,
eternal_compat=true,
unlocked = true,
discovered = true,
effect=nil,
soul_pos=nil,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and context.cardarea == "Giraffe" and G.jokers and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands{self.ability.extra.poker_hand}) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = (function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end)}))
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot,
card = self
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand, card.ability.extra.Tarot }, key = self.key }
end
}
Making an animal balatro mod
okay so this is going to break
config = { extra = { poker_hand = "Straight", Tarot} },
Tarot isn't defined
blueprint_compat=nil,, effect=nil,, and soul_pos=nil, are unneeded
Okay
here's your syntax error
uhhh, how do I define tarot? Like assuming its already defined, what is the actual thing
if next(context.poker_hands{self.ability.extra.poker_hand}) then
what are you trying to do
uhhhh, good question
should be this if next(context.poker_hands[self.ability.extra.poker_hand]) then
okay so lets start with the syntax error then
awesome
oh I see now what tarot is
can you send the text in the localization file for this card
no need to check the cardarea or if G.jokers
Oh, I dont have it lol
thats a good start, one moment
okay thats another issue
j_Al_worm = {
name = "worm",
text = {
{
"This Joker gives {C:chips}+#1#{} chips",
}
},
},
j_Al_Giraffe = {
name = "Giraffe",
text = {
{
"When you play a Straight, create a{C:tarot} tarot{} card",
}
},
},
From the localization file
okay make that "When you play a #1#, create a{C:tarot} tarot{} card",
which one?
we're talking about giraffe, right
make the return in loc_vars output
return { vars = { card.ability.extra.poker_hand} }
j_Al_Giraffe = {
name = "Giraffe",
text = {
{
"When you play a #1#, create a{C:tarot} tarot{} card",
}
},
},
Like this?
yep
and make the config at the start of the joker
config = { extra = { poker_hand = "Straight"} },
Can you show me where exactly?
i did ;-;
oh okay
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight"} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=true
eternal_compat=true,
unlocked = true,
discovered = true,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands{self.ability.extra.poker_hand}) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = (function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end)}))
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot,
card = self
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand}}
end
}
so far I'm caught up
id also recommend making this a common instead of a rare
Apolagies about needing so much help. I've had minimal coding experience in the past but I love balatro so I wanted to give it a try
id recommend looking at vremade
.
anything specific I should look at?
whatever you want to make
got it
syntax error again
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight"} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=nil,
eternal_compat=true,
unlocked = true,
discovered = true,
effect=nil,
soul_pos=nil,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and context.cardarea == "Giraffe" and G.jokers and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands[self.ability.extra.poker_hand]) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = (function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end)}))
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot,
card = self
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand}}
end
}
where
somewhere in this lua
There error message shows you the line number
try this
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight"} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=true
eternal_compat=true,
unlocked = true,
discovered = true,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands{self.ability.extra.poker_hand}) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
func = function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end
}))
end
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand}}
end
}
Using this code, this is the error I got
oh mb i forgot a comma
add a comma after blueprint_compat=true
that shoudl fix it
np
I'm going to see if it works in game :)
WAIT
Then Im going to do the same code but with a spectral card instead of a tarrot
i left a issue
waiting
try this
SMODS.Joker{
key = "Giraffe",
config = { extra = { poker_hand = "Straight"} },
pos={ x = 0, y = 0 },
rarity = 3,
cost = 4,
blueprint_compat=true,
eternal_compat=true,
unlocked = true,
discovered = true,
atlas = 'Giraffe',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands[card.ability.extra.poker_hand]) then
local card_type = 'Tarot'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
func = function()
local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, nil, 'sup')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end
}))
end
return{
message = localize('k_plus_tarot'),
colour = G.C.SECONDARY_SET.Tarot
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand}}
end
}
what broke
this is for polishing but how do i check if the cards are done being played so i can add all the stuff together in this kinda code
nice pfp btw
thx
heres quagmire
context.final_scoring_step
it is
thats kinda rhetorical of course it can
What does empty pool mean?
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/e9d5aa208ebf800cc32da3e8f2ba1ead7cdebcf0/items/joker.lua#L1490-L1505 Consider such, just swap set = 'Consumeables' to set = 'Tarot'.
how do you make a joker which levels down a hand
and not specifically the played one
Can you steal the code from the bind that does it?
no problem lol. I just be thieving like crazy since I'm not very code savvy
what does crash message empty pool mean?
usually that the rarity/consumable type for your object doesn't exist
return { level_up = -1, level_up_hand = 'High Card' }
?
Do it outside of scoring, like context.before, context.after, etc.
why wont this work what did i do rong?
final_scoring_step and individual don't work together
your going to have to manually iterate
can i ask what your joker is supposed to... do?
add X3 mult
that too
but its a joke card based off a meem
...that's it?
yes, its built to be a joke card so its pretty much useless
unfortunately you overprogrammed this
D:
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = 3
}
end
end
if context.joker_main then
return { xmult = 3 }
end
i would suggest copying the regular joker from vanillaremade, and then swap the mult in the return table with xmult
or yea lol
damn
triple whammy
what about message]
(might i add the mult isnt even in the return table)
what about it
it's automatic, you only need that for custom messages
ye smods automatically handles standard scoring messages
true but it's good practice to have your variables set up like that anyway
oh..
yeah fair
the thing is, i get my code either from here or from the yahimod, i just read and try and use it, and it sometimes works
you only need message for things like this
i recommend looking at vremade
ohhh yea
please don't use yahimod as a reference lol
like i mentioned earlier, VanillaRemade is a fantastic resource, it remakes a bunch of vanilla content as if it was modded
https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
i made something like that
foo your mods are so fucking funny
so like, xmult exists but whats the version for chips
xchips
xch yeah
i use vanillaremade sometimes
smods docs + vremade is your best friend
if you can't figure something out from those, then come here
vremade wiki has a ton of tips too
the vremade wiki is so amazing
i NEED to try the project sekai one when it's done
you can try a very limited version of it with a horrible chart if you want rn
next thing i need to do on my list before making paper dolls is to add lancer, add programs to connect lancer and susie, and then finish robotic and soul
go to minigame.lua and comment line 194 and uncomment 195
paper dolls might have to add messages because when it adds up i want it to just say paper dolls, referencing stomach book
note that'll also put baguette in the pool
ill deal with it l8r
@median veldt
stomach book mentioned
i just know they exist
with what code 😭
the paper dolls card is gonna work like kindness luigi but if you play a lucky card then it adds ten chips
oh yeah that's easy
i worked my jokers out
so could i use context.other_card:is_suit('Hearts') and replace hearts with some kind of lucky card
lucky cards arent suits
they're enhancements
vremade + vremade wiki will have everything you need for that joker i believe
oh yea
ohh lemme find it
i have like god knows how many github tabs
where can i find enhancements
wdym?
the thing about enhancements and how to check
on the wiki
BUT WHERE THO
context.check_enhancement?
the wiki
okay that's. for quantum enhancements
:0
you dont need to worry about that
^^
uhh don't touch those
oh wow
are they gonna crumble like pillar john
Question, I've been getting an empty pool error message. Whats the proper format for spawning Spectral cards?
local card_type = 'Spectral'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
func = function()
local card = create_card('Spectral', G.consumeables, nil, nil, nil, nil, nil, 'sea')
i get a nice 15 fps, and 2 when selecting cards, with this incredibly resource intensive check
ive already looked at that, i have that bookmarked
foo how am i supposed to place flags in minesweeper...
click the reveal button
oh thats convient
no patches needed to fix that
its supposed to take you to the shop
i might change it for balancing though idk
uh huh.
what
idk u tell me
wait did you extract the zip or no
oh
why is the filepath like that
FooBar is the path on mine
yeah i can see that
I need to get the mod path
i've never needed to do file paths outside of load_file so idk if that's different or
yeah cool it's very scuffed but it works
I mean you just use SMODS.current_mod.path
ah
that doesn't look scuffed to me
anyhow there's little to no reason most of the time to not load png files with SMODS.Atlas, in which case you also don't have to deal with that
yeah i'm parsing it
shenangains
TBF
i specificly excluded this one from the pool since it wasn't ready
❓
i might have forgotten to specify that my "scuffed" comment was referring to foo's mod i just tried it
oh that makes more sense now
are they ever going to fix this
okay fixed it
not releasing a patch since, again this isn't in code someone coudl access without tampering
but heres what you need to change
line 95 in projectsekai.lua
replace it with
local name = SMODS.Mods["foobar"].path
local t = {}
for word in string.gmatch(name, "([^/]+)") do
table.insert(t, word)
end
name = t[#t]
self.ability.cover_path = "Mods/" .. name .. "/assets/covers/" .. self.ability.current_song .. ".png"
... wtf
what the fuck
what's this parsing nonsense
brother
its like One line of code
btw the mods folder is not guaranteed to be named Mods
oh
okay hang on lemme add more code to it ;-;
less
no
less code
less code
smods.current_mod.path
this is ran mid game
uh huh
wait does love.graphics.newImage work with absolute paths
me assuming things that might not be true
it understands both, like any reasonable system
okay replace line 95 with
self.ability.cover_path = SMODS.Mods["foobar"].path .. "assets/covers/" .. self.ability.current_song .. ".png"
the path is obviously constructed in such a way that it works™
wait no i haven't
Also this will absolutely drown so you should just make a proper hotfix
okay now it works
I will make a fix when I get to actually finishing the pjsk minigame
rn I"m waiting on a chart
your choice
a tear runs down my cheek
my guy I've never used Love2D before
neither have i, grins
any idea how to do this or no
to what
make it so you can't hit play hand/discard while its highlighting the cards lmao
cuz you can if you're fast enough
atlas.image
something along these lines might work
G.CONTROLLER.locks.skip_blind = true
G.E_MANAGER:add_event(Event({
no_delete = true,
trigger = 'after',
blocking = false,blockable = false,
delay = 2.5,
timer = 'TOTAL',
func = function()
G.CONTROLLER.locks.skip_blind = nil
return true
end
}))
thx
what does this even do
disables input
smods lsp def should tell you this too I think
my lsp is kinda stupid
sometimes it works, sometimes it doesn't
what ide
odd
nvm it doesn't
it should tho, I'll have to add that
can I have folders inside my 1x and 2x if I put it int he path
what's the delay in
sick
i feel like theres a better way to do this
seconds
yeah lowkey this barely works i'm just gonna add a comment to deal with it later
is this the path or an image object
how do i make a sell price of a joker?
only the sell price or the buy price too
like my rare joker sells for a doller, i dont think it should be
this is what you asked for, which isn't the path last I checked
did you get it for free
you set its price to $3
yea whats the thing for it
its in the joker config
like price = 3
cost, not price
things like this are in the wiki
@fading rivet hii im reviewing your pr, do you think it's ok if it crashes when no condition can be met? idk if thats intended behaviour
uhhh whats the intended behavoir if you don't provide any string at all?
then yeah
okay we almost there
wait im stupid I don't need to convert
oh hi n youre the genius person is there a simple way to do this
ight this works
whats up with the font anyway
idk
whatever localthunk did with his text rendering removes the blurryness with large upscales
no clue how he did it
i'll probably switch to balatro ui for this
what foo said didnt work?
eh, hardly
.
i'm not sure if i should change the code but like
wait wdym by hardly?
its either you can click or can't click
there were still a few frames where i could hit the button while it was selecting
at the start or end
start
hmmm
did you put the lock before the selecting code?
mhm
i;m wondering if i could remove all the after stuff and just put the evnet at the end of the code
the event to reset should go after the other event
i think it actually should go inside the other event at the end
that makes more sense
should i remove the stuff that isnt func?
yeah me neither
@frosty dock I did what you're asked: fixing R/C, allow arrays as input and auto-adding empty moveable for G.UIT.O
While system became more and more versatile, it starts to became messy in terms of what and how you can do stuff.
If you interested in some specific things, let me know. For now I'll leave this thing, have other mod in mind want to start on.
Does anybody know how to fix this? my game is crashing when i try to use a custom rarity for my joker. I made sure there's not a type in the key. (sorry if this is something obsious, this is my first mod)
Um, which one is that one? haha.
get_next_tag_key() iirc
My mod was working previously, but a new smods version broke it
Does anyone know what changed that could've broken it?
Thanks, will play around with it.
the key should have the mod's prefix
[mod's prefix]_pikminRarity
Thanks
looks like you werent passing a card to smart_level_up_hand
idk if thats the issue tho
I do have it as
for poker_hand_key, _ in pairs(G.GAME.hands) do
SMODS.smart_level_up_hand(nil, poker_hand_key, true, -1)
end```
But the documentation says: card - If included, juices up this card during the animation
can i give myself a lucky card to check if paper dolls works
yeah but the documentation also says its deprecated so something may have changed lol
when are you calling this?
i think the problem is the new context
apply = function(self) of an SMODS.Back
in an event?
G.E_MANAGER:add_event(Event({
func = function()
if G.jokers then
SMODS.add_card {
key = "j_princess",
stickers = {"eternal"},
force_stickers = true,
edition = "e_negative"
}
end
return true
end
}))
for poker_hand_key, _ in pairs(G.GAME.hands) do
SMODS.smart_level_up_hand(nil, poker_hand_key, true, -1)
end
G.GAME.pool_flags.stp_vessel_packs = true
end```
can anyone help? i downloaded the newest version
ah yeah thats the issue
do it in the event
You need the new lovely version
0.9.0?
Yes
you can do SMODS.upgrade_poker_hands{level_up = -1, instant = true} to recreate this btw also
Thank you so much, that fixed it!
the version.dll goes into the balatro.exe folder
this one?
no
?
the folder with the balatro.exe
follow this: https://github.com/Steamodded/smods/wiki/Installing-Steamodded-windows
this correct?
yes
i feel like an idiot, what did i do wrong now? (also the holographic luigi joker there IS paper dolls, i just didnt put a texture yet cuz idk what to make yet)
why does the card says it add chips but it has mult and then the scaling variable is called xmult
its cuz i copy pasted it over, so i never bothered to change that
FROM MYSELF
from myself
ohhhh ok
i'm vaguely recalling or misremembering that there was a way added to specify in a custom deck, what the deck of cards you actually get should be, like as a recent thing? - but i forget how to do that or where that might be documented?
or if i'm hallucinating and you still have to just do it in an event in apply
it is also in SMODS.Back's page
ok i'm just stupid, i was staring at SMODS.Back's page for like 10 minutes 
is this right?
...oh. initial_deck = { Ranks = { 'King', 'Queen', 'Jack' } } just gives me 12 cards total.
context.other_card:set_ability("m_lucky", nil, true)
if i wanted the deck to start with more cards, did i need to add them in apply?
yes
i am. forgetting how to do an x in y chance
it's in the calculate page im the docs
found it, though new problem, it seems to have created a ghost card
not sure why...
does anyone know where i can find a list of everything you can change with take_ownerships?
it is the same as the list of all the things you can make with smods
yeah taking ownership just makes the object into an smods object if it wasn't already and adds/replaces anything you put in it
ah, cool
yknow, probably shouldve been able to figure that out after doing a whole calculate function with one
there are some vanilla things that are hardcoded and take ownership doesnt work perfectly with but there isn't a list for that
what area should they be going into?
G.deck just leaves them on the screen free-floating, and G.playing_cards results in a crash
anything specific?
emplace them into G.deck and add them to the G.playing_cards table
or is it a shot in the dark?
i think lucky cards and blue seals effects are hardcoded? iirc
but other than that it's trial and error
this puts them in the deck but leaves them free-floating on the screen
code?
eh, nothing a lovely patch shouldnt be able to do?
apply = function(self, back)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
blocking = false,
blockable = true,
func = function()
local KQJ = { 'K', 'Q', 'J' }
for _s, cSuit in ipairs(CirnoMod.miscItems.cardSuits) do
for _r, cRank in ipairs(KQJ) do
for am = 1, 4 do
table.insert(G.playing_cards, SMODS.create_card{
set = 'Base',
area = G.deck,
rank = cRank,
suit = cSuit,
no_edition = true
})
end
end
end
return true
end
}))
end```
i had an idea for blue seal, but not lucky so idc about that one
use add_card instead of create_card
ah, and then i'd need to emplace manually?
no it does it for you, also don't insert them into playing_cards either because it also does it for you
but you said to add them to the playing cards table 
ohhh i mixed up create_card and add_card
because i imagined you were doing it with create_card so i gave you a solution for that
Oh man, my mods in a bad state. I keep getting an error about steammodded utils inset object "joker name" empty pool. It appears even when I remove all the code surrounding that joker. Now I can't get my mod to run at all and I'm not sure why. Any ideas?
could we see the full crash log?
does anybody know what could be causing this deck to crash when i try to start a run?
add_card is the deck one i believe
The deck is probably applied before the G.jokers cardarea is initialized. Put your add_card in an Event so it occurs after everything is ready.
post the whole code
SMODS.Joker{
key = "Okapi",
config = { extra = { poker_hand = "Straight"} },
pos= { x = 0, y = 0 },
rarity = 5,
cost = 10,
blueprint_compat=true,
eternal_compat=true,
unlocked = true,
discovered = true,
atlas = 'Okapi',
calculate = function(self, card, context) --define calculate functions here
if context.joker_main and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
if next(context.poker_hands[card.ability.extra.poker_hand]) then
local card_type = 'Spectral'
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
func = function()
local card = create_card('Spectral', G.consumeables, nil, nil, nil, nil, nil, 'sea')
card:add_to_deck()
G.consumeables:emplace(card)
G.GAME.consumeable_buffer = 0
return true
end
}))
end
return{
message = localize('k_plus_spectral'),
colour = G.C.SECONDARY_SET.Spectral
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.poker_hand}}
end
}
rarity 5 doesn't exist
4
that worked, but then i tried to make it create a specific joker using a key and now it's crashing again. do you know how to fix this
sorry if this is something obvious, this is my first time making a mod
key = "j_pikmin_olimar"
thanks! that worked
ok so i tried looking at vanillaremade's green deck to get ideas as to how i'd accomplish this, but it uses config values/G.GAME vars and not any kind of technical implementation
but basically:
i want to make an end of round dollar earn wherein you get $1 for every 10% of score overkill - as a deck effect.
i thought i did know the actual calculation to do, but it turns out i hadn't thought beyond G.GAME.blind.chips - G.GAME.chips and G.GAME.blind.chips / 10
i thiiiink i modulo, then floor that?
so math.floor((G.GAME.blind.chips - G.GAME.chips) % (G.GAME.blind.chips / 10))
i'm uncertain
but i'm struggling on the logistics of actually implementing it. at a cursory glance, it looks like i need to patch state_events?
you can just do it with the deck's calculate function i think
the documentation isn't the most helpful, so gimme a minute to figure out what you actually have to return
calc dollar bonus for decks soon(tm)
oh it's a function, not a return variable
is G:start_run called on starting a new run?
it is called when the run is loaded too
could i hook it and do some sort of check to make sure it's a new run
actually i'm overcomplicating this
do you just need a function for a new run or does it need to be that one
it can be any function
for the record if it helps im going to add a counter for using that button i've been adding, i wanted it to start at zero
you don't need to initialize counters in lua
I'm having a very specific problem, so idk if it's something people here can help with. I have a joker (olimar) that creates other jokers at the end of round, and the jokers it creates are meant to give +1 joker slot each. However, when a blueprint is copying olimar, only 1 of the created jokers gives +1 joker slot. Here's my current code:
would i have to like
for example
mult = G.GAME.my_counter or 0
or can i omit the or 0
i'm assuming you specified because some things will break if nil is passed
like if i tried to do math on it
yea anywhere you try to increment the counter should have or 0 attached to it
noted
you don't need the whole add_to_deck thing in each, just add card_limit to the config
i'd like to know if i have my formula right, though
i'm realizing now that i have been putting a lot of things in G.GAME.BALATROSTUCK2_
e.g. G.GAME.BALATROSTUCK2_can_ability
would it be cleaner if i made that first underscore a period and like idk G.GAME.BALATROSTUCK2 = {} at the start of a run (if i have to)
probably
thanks, i didnt know that
why is SMODS.calculate_context{round_eval = true} being called during a saved game load?
are you loading in round_eval?
oh, i thought i was loading at the start of a blind, but it might not be for whatever reason
round eval is the cashout screen
if its being called at the start then that might be an issue
ok yeah i was apparently loading during round eval 
Where is the number of consumable and joker slots stores?
ok, my formula for determining $1 for every 10% over blind requirement is wrong
i don't know what it should be
trying to come up with a deck gimmick for my mod, i want it to be like kind of vanilla-ish like extra credit or all in jest
even after testing and tweaking, i realise i'm in completely the wrong mindset with
(scored_chips - blind_req) % (blind_req / percent) 
is it closer to
(scored_chips - blind_req) / (blind_req / percent)...? or am i stupid
so far my only ideas are "all the cards are a new suit that cant form flushes BUT counts as any suit for a joker (one spirals suit card would trigger all 4 suit jokers)", "cards from my mod appear more, so do negative cards", or "randomize the suit of all cards at end of round" (this one sucks)
i had a very stupid idea once where the only thing told to the player regarding the effect is "welcome to whose balatro is it anyway, where the rules are made up and the suits don't matter" and then for every suit related check, suits are just completely randomised
math.floor((scored_chips - blind_req)/(blind_req*0.1)) ?
ah, wait, no. scoring 310 chips on a blind that requires 300 chips should yield $1, but that formula results in 0.3 recurring
should it be ceiling then
wait no i'm dumb, that's not 10% 
yeah lol
i know why it's not displaying the correct amount of cash out dollars - because the dollar amount needs to feed into the local dollars variable in G.FUNCS.evaluate_round, so i need to patch in it accepting a value it can increment the dollar amount somewhere, but i'm not sure where? my first thought was to make it parse a return table from SMODS.calculate_context()? but i'm wondering if there's a better.recommended way to try and get my value there atm 
i'm just gonna patch it to pass in the dollars variable, so i can influence it within calculate 🥴 goofy fix but should be fine this doesn't work 
this just gave me a horrible idea
joker that hooks Card:is_suit() to return a 1 in 2 pseudorandom check
worse idea: joker that hooks Card:is_suit() to return false every time
is suit? no
chudjoker but it fucks over flush builds
nah i'd say 1 in 2 is worse bc it's inconsistent
like,, what happens if you're in a suit debuff blind?
ok so what exactly is the point of being able to do add_round_eval_row in context.round_eval if we can't influence the cashout value
wait for my calc dollar bonus pr to get merged i guess
what should i do in the meantime? i've tried patching several different things to no avail
you can copy my patches
n: copy my patches
Does anyone have a list of select_music_track functions that would be applicable to the vanilla tracks?
i.e. I have a set of 5 tracks corresponding to vanilla tracks, I want those tracks to play in the same gameplay contexts as the vanilla tracks + some other conditional
Look at modulate_sound in functions/misc_functions.lua
nice, thank you
whats a bool value i can use to check if i'm in a game and not in like the main menu area?
(needed for checking collection)
if G.STAGE == G.STAGES.RUN
thanks
Huhhhhhh
can you see the symbol
ik im blind as a bat but i swear there's no other symbols there
It was fine before I seperated the descriptions from the Consumables.lua file
The }, there shouldnt be there
both
hii im trying to make a joker that acts kinda like a combination between gros michel and invisible joker. I want it to make so that the joker does nothing, you just have to wait 20 rounds. Past these 20 rounds, the joker gets "transformed" (it gets extinct and generates an specific legendary joker)
im looking through the code from gros michel and invisible joker but i really dont know how to start because im still learning modding
i just have this at the moment
if anyone could help me i would really appreciate it <:)
if context.end_of_round and context.main_eval then
card.ability.extra.invis_rounds = card.ability.extra.invis_rounds + 1
if card.ability.extra.invis_rounds >= card.ability.extra.total_rounds then
card:set_ability('j_modprefix_key')
end
end
so im trying to make my first mod
is there a way i can find like the key phrases used?
cus i know what to do i just dont know what phrases are used for what
for example im currently making a scaling x_mult joker that scales when a flush five is played
but i dont know the phrases used for making it scale when a certain poker hand is played
how to scale: https://github.com/Steamodded/smods/wiki/Calculate-Functions#step-2-logiceffects
how to detect when a hand containing a poker hand is played: https://github.com/nh6574/VanillaRemade/blob/1abd606dc26c46f0c7b281995f40fb25b1d54b4f/src/jokers.lua#L171
it's basically just looking at the documentation and the vanilla examples
thanksies
what does card:set_ability('j_modprefix_key') do?
transforms the joker
so im assuming i need to change the 'j_modprefix_key' by the name of the joker i want to transform it to?
yes
that worked!! thank you so much, tho i would also like to be able to make it appear only doing that and not using a soul card, would that be possible using a pool like gros michel and cavendish?
you can put in that joker
in_pool = function(self, card, args)
return false
end
that worked!! thank yo so so much <3
okay that worked
how do i make it require a vanilla voucher that has spacces in the name though
i don't see how having spaces would be a problem here
ah i didnt read vanilla
maybe i should have tried that first
nope
yes
requires = { "v_overstock_plus" }
didnt work "
:
this is the error im getting but it only occurs when requires is therte
`-- Overstock Plus +
SMODS.Voucher {
key = 'overstock_norm',
pos = { x = 0, y = 0 },
config = { extra = { shop_size = 1 } },
requires = { "v_overstockplus" }
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.shop_size } }
end,
redeem = function(self, card)
G.E_MANAGER:add_event(Event({
func = function()
change_shop_size(card.ability.extra.shop_size)
return true
end
}))
end
}
`
you're missing a comma after that line
oh


