#💻・modding-dev
1 messages · Page 632 of 1
That's kinda what I have thouht about though I know it really wasn't ideal but thought would be an interesting addition besides that unlock all exists in modern balatro
No because stakes can have branching paths so that terminology outside of the initial stake chain doesn’t make sense
I see though I still want to like make a thing where basically it's more of a expansion.
Just let it tag as applied gold stake
It’s a tiny comprehension step to understand what that means
And if you’re using galdur (which you should) it is very obvious what is happening
foilgraphic? which mod is that?
Yeah.. I have not considered about galdur since I wasn't aware of it's existence
Balatro: Director's Cut / The Archives
That I'm amking
that looks awesome
Is there way for a joker to change the stat of a different joker that are both from the same mod or do i need to do a take ownership kind of thing ?
tried to do something as dumb like
SMODS.Joker {
key = "boostPower",
loc_txt= {
name = 'Indignation',
text = { "DreamBreaker'mult ",
"increase by {C:attention}#1#%{} ",
},},
atlas = 'regaliadeck',
pos = { x = 2, y = 2 },
rarity = 1,
cost = 5,
pools = {["pseudoregamod"] = true},
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
--- the function
config = { extra = {percent = 75}},
loc_vars = function(self, info_queue, card)
return { vars = {card.ability.extra.percent } }
end,
add_to_deck = function(self, card, from_debuff)
if next(SMODS.find_card("j_cymbal_dbreaker")) then
j_cymbal_dbreaker.ability.extra.xmult = j_cymbal_dbreaker.ability.extra.xmult*1.75
end
end,
remove_from_deck = function(self, card, from_debuff)
if next(SMODS.find_card("j_cymbal_dbreaker")) then
j_cymbal_dbreaker.ability.extra.xmult = j_cymbal_dbreaker.ability.extra.xmult*0.75
end
end,
}
but ovciouslydidn't work, so if anyone knows how i should do it, please let me know !
if its from the same mod then you already know what the value will be called
so you wont need take ownership
just for _, c in ipairs(SMODS.find_card("j_cymbal_dbreaker")) do c.ability.extra.xmult = c.ability.extra.xmult * 1.75 end
also you probably want to just divide by 1.75 in the remove_from_deck
well the code for the concerned joker is :
SMODS.Joker {
key = "dbreaker",
loc_txt= {
name = 'Dream Breaker',
text = { "{X:mult,C:white}x15{} when there's",
"{C:attention}3{} hands and",
"{C:attention}3{} discard left or less"
},},
atlas = 'dbreaker',
pos = { x = 0, y = 0 },
rarity = 3,
cost = 15,
pools = {["pseudoregamod"] = true},
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = {extra = { xmult = 15}},
loc_vars = function(self,info_queue,center)
return {vars = {center.ability.extra.xmult}}
end,
calculate = function(self, card, context)
if context.joker_main and G.GAME.current_round.hands_left <= 3 and G.GAME.current_round.discards_left <= 3 then
return {
xmult = card.ability.extra.xmult
}
end
end
```l
oh i see, i can try that thanks
So basically since it's in the same mod, i only need to make my joker find the concerned one to modify it without taking ownership ?
Thanks btw it does work now, is there just a way to change the loc_vars to display the new mult the joker would give or not ?
it will already do that
well
it would if you used #1# in the description
for the xmult
since you already have the loc_vars
thats
not the issue here
the description just has plain "15" in it
instead of #1#
I have been having an issue with vscode and functions. When I hover over a function, no tooltip appears. I have set up the LSP with a luarc.json file. Is there anything that could be causing this and how I could fix this?
how would i make a uibox button with multiline text
hi uhh i tried to make a generic lockup-prevention function
its not working
-- returns true if we're in a potential lockup
G.nflame_lockup_prevention = function(frame_tolarance, trigger_tolarance)
frame_tolarance = frame_tolarance or 150
trigger_tolarance = trigger_tolarance or 10
G.NFLAME_IDRFIRE = G.NFLAME_IDRFIRE or G.FRAMES.DRAW
G.NFLAME_IDRCOUNT = G.NFLAME_IDRCOUNT or 0
if G.NFLAME_IDRFIRE + math.floor(frame_tolarance / 2) < G.FRAMES.DRAW then G.NFLAME_IDRCOUNT = 0 end
G.NFLAME_IDRCOUNT = G.NFLAME_IDRCOUNT + 1
if G.NFLAME_IDRFIRE + frame_tolarance > G.FRAMES.DRAW -- this triggered less than x frames ago
or G.NFLAME_IDRCOUNT > trigger_tolarance -- this triggered more than x times
then
print("LOCKUP POTENTIALLY HAPPENINGG")
return true
end
..since the uibox_update function only takes a config table

in_pool = function(self, args)
for _, c in ipairs(G.jokers or {}) do
if next(SMODS.find_card("j_cymbal_dbreaker")) then
return true
else
return false
end
end
end,
tried to make my joker only appear if a certain joker is owned but it crashes instantly and does this
in_pool = function() return not not next(SMODS.find_card("j_cymbal_dbreaker")) end
ah alright thanks
SMODS.Joker {
key = "boostPower",
loc_txt= {
name = 'Indignation',
text = { "The {C:attention}Dream Breaker{}'s mult ",
"increase by {C:attention}75%{}",
},},
atlas = 'regaliadeck',
pos = { x = 2, y = 2 },
rarity = 13,
cost = 10,
pools = {["pseudoregamod"] = true},
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
--- the function
config = {},
loc_vars = function(self, info_queue, card)
return { vars = { } }
end,
in_pool = function()
return not not next(SMODS.find_card("j_cymbal_dbreaker"))
end,
add_to_deck = function(self, card, from_debuff)
for _, c in ipairs(SMODS.find_card("j_cymbal_dbreaker")) do
c.ability.extra.xmult = math.floor(c.ability.extra.xmult * 1.75)
end
end,
remove_from_deck = function(self, card, from_debuff)
for _, c in ipairs(SMODS.find_card("j_cymbal_dbreaker")) do
c.ability.extra.xmult = math.max(15,c.ability.extra.xmult / 1.75)
end
end,
}
```l
got the same error
whats the prefix for using :setAbility for enhancments? im trying to set an enchancement for a card idk what im doing wrong i literally dont remember changing anything in some tarots code but now it doesnt enchance cards for some reason
_card:set_ability(G.P_CENTERS['m_tws_mystical'])
its literally that
key = 'tws_mystical',
the key of the enhancement
13 is not a rarity.
Crap didn't properly replaced it my bad
what's the prefix of your mod ?
tws
well in that case if the key of your enhancement is 'tws_mystical', the ability set will be something like 'm_tws_tws_mystical'
i remember trying that already wait maybe im dumb and didint save the file or smth
you could also just remove the tws_ from your enhancement key, that way it should work too
burh
bruh
the prefix should be good
idk why its a nil value
I want to display a +mult effect above the played hand, not on a card but the same position some boss blinds use to tell you their effect( Like the Psychic's "Not Allowed"). What should I put in message_card?
G.play?
can anyone help?
can you show the code
play_area_status_text(string)
also i think somewhere whatever thing you set as 'center' wasn't defined and should be replaced by card, but first we ened to see your code
No, that crash usually means that they used the wrong key.
Yeah, most probably, i just know there's sometimes center being used and the card, the problem being if it wasn't defined then it'll simply render nil
should be an easy fix anyway
calculate = function(self, card, context)
if context.selling_card or context.joker_type_destroyed and not context.blueprint then
if not next(SMODS.find_card("j_cymbal_dbreaker")) then
SMODS.destroy_cards(card, nil, nil, true)
end
end
end,
last help for the night i promise, just trying to make so my joker removes itself if the other joker gets removed (destroyed or sold), tried to do a check to see if it can find the card but apparently that isn't working
if (context.selling_card or context.joker_type_destroyed) and not context.blueprint
function SMODS.current_mod.calculate(self, context)
if context.reroll_shop or context.buying_card or context.open_booster then
G.GAME.current_round.twistedDandyOdds = -1
end
if context.ending_shop then
G.GAME.current_round.twistedDandyOdds = G.GAME.current_round.twistedDandyOdds + 1
end
if
context.end_of_round and context.game_over == false and context.main_eval and context.beat_boss and
G.GAME.current_round.twistedDandyOdds >= 2 and
(G.GAME.current_round.twistedDandyOdds >= 10 or SMODS.pseudorandom_probability(self, 'dw_twisted_dandy', G.GAME.current_round.twistedDandyOdds, G.GAME.current_round.twistedDandyChance))
then
G.FORCE_BOSS('bl_dandy_dandy')
end
end
Anyone know how I can change the store text from "Improve your run" to something like "Don't ignore me" if G.GAME.current_round.twistedDandyOdds is greater than or equal to 2?
Hook localize
i think the problem comes from checking if j_cymbal_dbreaker is still there since rn my joker won't disaper when Dream Breaker is sold
if context.card.config.center.key == 'j_cymbal_dbreaker'
idk why it gets stuck like that, when i'm using vanilla code as reference (which doesn't do this)
-- Reroll shop func callback, copied from vanilla callbacks
function G.FUNCS.elle_rebecca_can_reroll(e)
if ((G.GAME.dollars-G.GAME.bankrupt_at) - becca_menu_card.ability.extra.cost.reroll < 0) and becca_menu_card.ability.extra.cost.reroll ~= 0 then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
--e.children[1].children[1].config.shadow = false
--e.children[2].children[1].config.shadow = false
--e.children[2].children[2].config.shadow = false
else
e.config.colour = G.C.GREEN
e.config.button = 'elle_rebecca_reroll'
--e.children[1].children[1].config.shadow = true
--e.children[2].children[1].config.shadow = true
--e.children[2].children[2].config.shadow = true
end
end
-- Custom shop reroll button
function G.FUNCS.elle_rebecca_reroll(e)
stop_use() -- This was in the vanilla reroll callback for some reason
ease_dollars(-becca_menu_card.ability.extra.cost.reroll)
becca_menu_card.ability.extra.cost.reroll = becca_menu_card.ability.extra.cost.reroll + 5
becca_reroll(becca_menu_card, true)
end```
Once again, thanks to you, my joker properly works now
Sorry for not responding, something came up.
G.play puts the mult message bellow the scoring cards, not above.
Where do you find the arguments for it?
functions/misc_functions.lua
Ah thx
How do you make it so a calculate function only triggers when buying booster packs
like only the boosters from shop
hey y'all, how could i disable and reenable the play/discard buttons? at least visually
bump
can someone explain to me message_card? I'm having trouble understanding it.
which card the message appears on
Then there's no way to change the location of score messages arbitrarily, it needs to be tied to a card?
Yes.
it can be tied to CardAreas as well
but it will always appear below the given object
if you want a message to appear in any arbitrary position then attention_text function can do that i think
attention_text? wait I'll search the docs
No, it's not on the documentation.
then how does it work?
I've been wracking my brain on what should be easy.
SMODS.has_enhancement(card, key) -> bool
I was thinking of some custom Jokers that do funny things based on card enhancements; specifically one that reacts when you play a gold card (since those normally trip when held in hand).
But I can't seem to find out what the value of key should be for a gold card.
'm_gold'
Right 😮 Should it be in quotes?
Yes.
Right, I'll try that, thanks. Is there a comprehensive list for these? I feel like an idiot, but I couldn't find that specific one anywhere.
The Joker was ideally going to react to steel cards and glass cards being played as well; maybe cards with a gold seal too.
Is it just m_steel, m_glass, etc?
Yes, and gold seal would be if card:get_seal() == 'Gold'
this is a dev sided question as someone whos not a dev
would it be possible to have aces dynamically rank as both 1 or 11 depending on a case by case basis when scoring for rank
aka for example like a blackjack mode where 4+ace+6=21 (where ace is 1)
or ace + ace + 9 (where one of the aces is considered a 1 while the other is an 11)
Yes
I actually did this for my blackjack, I just made it so if an ace is detected and would breach 21 it is considered 1 and applies for multiple aces, 1 ace can also count as 1 while another counts as 11 in the same hand
Alright thank you for confirming it is possible
Thanks 😄 😄

Another potentially silly question, is there an easy way to track X amount of cards in the player's deck? For example, a joker that gets stronger the more gold cards are in the deck rather than when they're played/scored.
local count = 0
for k, v in pairs(G.playing_cards) do
if SMODS.has_enhancement(v, 'm_gold') then
count = count + 1
end
end
G.playing_cards, right. Thanks. 😮
I still have a lot of figuring out to do, but you've helped a ton. 😄
do you want in the full deck or the not-yet-drawn deck?
how do i get this to behave correctly????
localization file: lua misc = { labels = { MDJ_corrupted = "Corrupted", k_MDJ_veryrare = "Very Rare", } }
is there a way to put "#" in a jokers description without it counting as a variable?
Yes, return '#' as a variable in loc_vars
wheres the docs that say what the different variables do in create_playing_card?
What are the parameters for this ?
t
Is there a reason you're using create_playing_card instead of SMODS.create_card or SMODS.add_card?
but how do I get the type that wants to be create and the key too
its what certificate does lol
do i just use that instead and dont add anything else?
reference vanillaremade, not the actual vanilla code
https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
You should be hooking create_card not SMODS.create_card
well damn i wish i knew this existed like a year ago lol
wait why is it generating in G.discard?
for animation purposes
it spawns in G.discard and then the event makes it do the drawing animation when it moves to the player's hand
Im trying to make a joker play background music on loop replacing the music, does anyone know the error?
Yes.
You need music in the key.
why isnt it on the wiki smh
what am i doing wrong here?
It would be G.GAME.blind not context.blind
gotcha
okay it appears the cards im generating are showing up as face down next blind
nvm lemme try some stuff
card.states.drag.can = false
okay hmmmmm. i thought this would work, but im trying to have the joker description update along with the 'level' its at, anyone know why its not working
cool
and how can i do to the card retrigger adjacent cards?
Use the mod calculate and:
if context.repetition then
local retriggers, my_pos, full_hand = {}, 0, CardArea.is(context.cardarea, CardArea) and context.cardarea.cards or context.full_hand or G.play.cards
for k, v in pairs(full_hand) do
if v == context.other_card then
my_pos = k
end
if v:get_seal() == 'modprefix_key' then
if k > 1 then
retriggers[k-1] = {repetitions = (retriggers[k-1] and retriggers[k-1][1] or 0) + 1, card = v}
end
if k < #full_hand then
retriggers[k+1] = {repetitions = (retriggers[k+1] and retriggers[k+1][1] or 0) + 1, card = v}
end
end
end
if retriggers[my_pos] then
return {repetitions = retriggers[my_pos].repetitions, message_card = retriggers[my_pos].card}
end
end
not work
do nothing
wait i didnt read right
explodes after finish scoring
i fixed it by manually updating it inside the code each time it changes
SMODS.Joker {
key = "mus_theory",
loc_txt= {
name = "Musical Theory",
text = {
"Negative cards can now appears",
"#1# more",
},},
atlas = 'locations',
pos = { x = 2, y = 3 },
rarity = 3,
cost = 10,
pools = {["pseudoregamod"] = true, ["cymbal_books"] = true},
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
config = { negative_rate = 300000, extra = {}},
loc_vars = function(self, info_queue, card)
return { vars = {self.config.negative_rate } }
end,
add_to_deck = function(self, card, from_debuff)
SMODS.Edition:take_ownership("negative", {
get_weight = function(self)
return self.weight * (self.config.negative_rate or 1)
end,
}, true)
end,
remove_from_deck = function(self, card, from_debuff)
SMODS.Edition:take_ownership("negative", {
get_weight = function(self)
return self.weight / (self.config.negative_rate or 1)
end,
}, true)
end,
}```
the weight change for negative spawnrate won't change at all (using 300000 just to test), i did do the take ownership, but not sure what exactly is wrong
AH
i think i get it
the or 1 made that, i changed to 300000 and now it does work
...though now i do wonder why the self.config.negative_rate won't work
add_to_deck = function(self, card, from_debuff)
G.GAME.modifiers.cymbal_negative_rate = self.config.negative_rate
SMODS.Edition:take_ownership("negative", {
get_weight = function(self)
return self.weight * (G.GAME.modifiers.cymbal_negative_rate or 1)
end,
}, true)
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.modifiers.cymbal_negative_rate = self.config.negative_rate
SMODS.Edition:take_ownership("negative", {
get_weight = function(self)
return self.weight / (G.GAME.modifiers.cymbal_negative_rate or 1)
end,
}, true)
end,
```
OKay i managed to find how to fix, just creating `G.GAME.modifiers.cymbal_negative_rate` and it works now
Just would like to know if there's a different and better way to do it or that works as it is ?
Yes, move the take_ownership out of the joker.
I see but if i do wouldn't that be a problem to then change it if the joker is added/sold ?
like, how should i do ? just taking the smod edition take ownership outside ? but what i do for add/remove to deck ?
local oldenegativegetweight = G.P_CENTERS.e_negative.get_weight
SMODS.Edition:take_ownership('e_negative', {
get_weight = function(self)
local weight = oldenegativegetweight(self)
for k, v in pairs(SMODS.find_card('j_modprefix_key')) do
weight = weight * v.ability.negative_rate
end
return weight
end
}, true)
So i then use oldenegativegetweight as way to restore the old negative rate in remove_from deck for exemple while for add to deck i just my regular code ?
oh wait
No, you don't need add_to_deck or remove_from_deck
Ah i see, i think i get it, all i do need to do is just replaced the j_modprefix_key by my joker key and then it will do the work by itself right ?
Yes.
Alright thanks !
does anyone know where the relevant code is to make the blind select button not clickable when it is not the current blind
nvm found it i just overlooked it earlier
so my acrobat rework, currently gives Xmult every hand instead of the final hand or after final discard, but the juice_card_until WORKS EXACTLY HOW IT'S SUPPOSED TO!
i don't understand why the independent part works but the dependent doesn't, but i'm hoping someone can spot what i missed
key ='witch',
set = 'Tarot',
atlas = 'ConsumablesPlus',
loc_txt = {
name = 'Witch',
text = {
'Enhances up to {C:attention}#1#{} cards to {C:attention}Mystical{} cards'
}
},
config = { max_highlighted = 2 },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.max_highlighted } }
end,
cost = 3,
use = function(self, area, copier)
for i = 1, math.min(#G.hand.highlighted, self.config.max_highlighted) do
local _card = G.hand.highlighted[i]
G.E_MANAGER:add_event(Event({func = function()
_card:set_ability(G.P_CENTERS['m_tws_tws_mystical'])
return true
end}))
end
end
}```
key = 'tws_mystical',
atlas = 'ConsumablesPlus',
pos = {x = 0, y = 0},
shader = 'negative',
loc_txt = {
name = 'Mystical',
text = {
'after scoring {C:attention}#1#{}{C:inactive}[#2#]{} times',
'add a random edition to this card,',
'and {C:attention}remove{} this enhancement from it.',
'{C:inactive}(Negative excluded){}'
}
},
config = { extra = {triggered = 0, required = 2 } },
loc_vars = function(self, info_queue, card)
return {
vars = { card.ability.extra.required, card.ability.extra.triggered }
}
end,
calculate = function(self, card, context)
if context.main_scoring and context.cardarea == G.play then
return {
func = function()
card.ability.extra.triggered = (card.ability.extra.triggered or 0) + 1
if card.ability.extra.triggered == card.ability.extra.required then
local edition = poll_edition("modprefix_seed", nil, true, true)
card:set_edition(edition)
card:set_ability(G.P_CENTERS.c_base)
end
end,
message = 'Shiny!',
colour = G.C.MULT
}
end
end
}
if your Consumable is meant to enahnce you can simply just place mod_conv = 'm_tws_tws_mystical' in your config instead of the whole use function part
yes but theres also a joker whose meant to enchance all played cards into an enchancement
thats the main issue
its an issue with enchancing overall
Like, the fact the joker can do the enhancement when you want only the consumable to do it ?
i get the same error every time
For now, your consumable on itself can be simplified with mod_conv = 'm_tws_tws_mystical', instead of the whole use part, but keep it, just inactive with --[[ ]]
as for your enhancement, replaced card:set_ability(G.P_CENTERS.c_base) by card:set_ability(Default)
wait
actually
replace by card:set_ability(Default) instead
what does the 'Default' do?
your enhancement remove itself right ? Default simply does that, the 'default' enhancement
Hold on
wait
i think i got it wrong for default, you should try
card:set_ability('c_base', nil, true)
c_base is the key for default card
still when i try to enchance a card into the 'mystical' enchancement the game says that the pool is nil
do you have the error message ?
so same error message ?
wait, did you did the mod_conv i told you about
and disabled the use function ?
well it doesnt crash but still wont enchance
the cards just stay the same
wait i think i know why
???
you need to add effect = "Enhance"
i'm sharing my own tarot for exemple but i noticed yours didn't had an effect on
it seems that whenever anything tries to interact with the enhancement the game crashes
ill try to enchance into something from the base game to see if the mod is an issue
you could try replacing your custom enhancement by m_stone for exemple
that way you'll see if it's the tarot or the enhancement iself
yea i did it
it works if i change the enhancement to steel for example
so the modded enhancement is the problem
but the key should be fine so idk why it isnt in the enhancement center
try replacing your ```lua
local edition = poll_edition("modprefix_seed", nil, true, true)
card:set_edition(edition)
`card:set_edition(poll_edition("tws_mystical", nil, true, true))`
i also noticed you never modified your modprefix_seed
ok so i used debug ++ right
so if you press ctr + W it changes the enhancement
and
the custom one wasnt there
so it isn't in the pool/center for some reason
ok i realised it IM SOO DUMB
SORRY FOR WASTING YOUR TIME
OMFG
assert(SMODS.load_file("Jokers.lua"))()
assert(SMODS.load_file("Empowered.lua"))()
assert(SMODS.load_file("Tarot.lua"))()
assert(SMODS.load_file("Spectral.lua"))()```
\
i think you can see whats wrong in this part
IM SO DUMBNBBBB
i lost all hope for this mod
wait so basically the mod enhancement you made simply didn't load ?
i feel like from the way you explained to me and from i get, you either didn't saved your enhancement n the good folder, ooor forget to save it as lua
what is lua arent the mods written in javascript??????
nah ill try to figure it out
by myself
at least the cards now start the enhancing animation before the game crashed
fixing one frame at a time
i'm being honest, i don't have much more knowledge in modding, i still fight for my life sometimes to do some simple sounding jokers
just shared what i knew from my own modding experience sooo
maybe what i did shared will still make things easier
yea i also dont know that much
and sometimes the wiki
is
just
not helpful
well it is but sometimes its hard to get what you want
have you checked vanillaremade ?
yes thats mainly where i get resources from
oh okay
the smods wiki kinda sucks for lacking documentation and exemples on what to do and how you can do it, which vanillaremade really does better at the job
also it has a mod example for everything EXCEPT the enhancements
best thing you can do right now ist just check arounds
the enhancements are such a pain
you could try to use G.E manager, a bit tricky but once you get it ti should maybe help
like for edition its card:set_edition for seals its card:set_seal but for enhancement you have to use set_ability and get it from a pool
wait no thats SMODS example mods
ill se vanilla remade
yeah
well not much i can do rn outside for asking help later or looking other mods that does an enhancement similar to yours
ok i got it to work
is it possible to make clearance sale percents go negative
question: how do i make all cards count as a single rank
you would be best to hook Card.get_id
and make it return a different value if you own whatever card makes things count as another rank
to what now
a hook is when you override a function with itself plus additional functionality that you add
a simple example would be
local original_function = do_something
function do_something(arguments)
print("this runs before the original")
local return_value = original_function(arguments)
print("this runs after")
return return_value --important! some functions return values and you may want to preserve their original values or alter them in some way
end
so for example a simple hook that does nothing other than printing when you get the id of a card would look like this
local get_id_hook = Card.get_id
function Card:get_id() --note the colon, this is important, otherwise you would have to specify "self" as an argument
print("getting id of a card")
return get_id_hook(self) --self is implied by using : in the function def, instead of ".", it refers to the table calling the function, so the card itself
end
ah
hmm
would this work
local insanity = Card:get_id() == 14
function Card:get_id()
return insanity(self, from_boss) or (self:get_id() and next(SMODS.find_card("j_tcg_insanity")))
end
the == 14 in the first line is making it a boolean which you then attempt to call as a function afterwards
or do i have to make it return the 14 instead
yes
also note to set insanity to Card.get_id, the difference between . and : is important
. is used to refer to the function itself and may be used to call it, but for objects like cards, : is always used for calling the function and can not refer to it as a variable
Why the hell is my game stuck on this screen
Someone has the link to the invisible pixel remover script?
how would i go about syncing this custom store's contents with a joker?
Manually, unfortunate
Is it requied to make shop in menu?
and how would i track when cards are bought?
i'm already able to track when i reroll since that's got a button callback
Theres other problems
Probably rn when you open a shop game is paused
Which means selling a jonkler in your shop will not be replicated in slots
And even if do, effects will not
In other words a lot of caveats so consider how utilize real joker slots
How do I keep track of when a song ends so I can swap it with a different one?
I don't think you need to, you can just keep the areas around
wouldn't that mean that the shop is shared between multiple copies of the joker?
actually i think i like that more than what i was doing before
is there a way to do like
if the chosen card for a spectral is a specific type
then it turns into something else
?
local dessert = {j_ice_cream, j_cavendish, j_gros_michel}
local appetitizer = {j_turtle_bean,j_egg}
local meal = {j_popcorn, j_ramen}
local drink = {j_diet, j_diet_cola}
if i want to have 4 result for each local, do i need to 4 pseudorandom_element for each or is it possible to make it in one like like this ?
pseudorandom_element(appetitizer, meal, drink, dessert, "cymbal_restaurant_book")
I want to make my joker create 4 different joker based of each local but with a random result
you have to make 4 pseudorandom_element calls
Is there a way to make an explosion effect when a card is dissolved
why do you have j_diet and j_diet_cola
also those should probably be strings
do you mean an actual procedural explosion effect or just smtn like 
as for how, i'd suggest maybe hooking the Card.dissolve function
oops, wanted to use j_selzer
ah alright thanks
if i'm gonna be separating things from the joker, then where would i store values like reroll cost, and how would i make the shop reroll between antes (which i would've just put in the joker's calculate)
i've never added stuff like this before so i'd like to know where to start lol
you can still store them in the joker
what if i have 2 of the same joker
if the cards in the shop are handled separately from the joker then i'd rather everything else be too
also that still isn't an answer for where i'd actually store them
How do I keep track of when a song ends so I can swap it with a different one?
Procedural, with particles
Though that explosion would be cooler tbh
well the
would just be an animation, which could be done with an atlas and texture drawing
Screw it I'm just gonna do janky stuff with timers
local dessert = {j_ice_cream, j_cavendish, j_gros_michel}
local appetitizer = {j_turtle_bean,j_egg}
local meal = {j_popcorn, j_ramen}
local drink = {j_selzer, j_diet_cola}
SMODS.Joker {
key = "restaurant_book",
loc_txt= {
name = 'restaurant_book',
text = {
"",
},},
atlas = 'locations',
pos = { x = 3, y = 2 },
rarity = 2,
cost = -1,
pools = {["pseudoregamod"] = true, ["cymbal_books"] = true},
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = { extra = {}},
loc_vars = function(self, info_queue, card)
return { vars = { } }
end,
calculate = function(self, card, context)
if context.selling_self then
local beforefood = pseudorandom_element(appetitizer, "cymbal_restaurant_book")
local mainfood = pseudorandom_element(meal, "cymbal_restaurant_book")
local sidefood = pseudorandom_element(drink, "cymbal_restaurant_book")
local finafood = pseudorandom_element(dessert, "cymbal_restaurant_book")
SMODS.add_card { key = beforefood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = mainfood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = sidefood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = finafood, edition = e_negative, skip_materialize = false }
end
end,
add_to_deck = function(self, card, from_debuff)
card.ability.extra_value = (-card.sell_cost) + (-25)
card:set_cost()
end
}
well my joker will crash upon selling it
And the full error message
your lists at the top have identifiers instead of strings
assuming you don't define those variables anywhere, that's like having a list of nothings
oh wait you mean the locals before the joker ? i was thinking i could set them up early
j_ice_cream refers to a variable named j_ice_cream
not the string containing that
that's "j_ice_cream"
yep
otherwise you just have a bunch of variables there that don't contain anything, making these lists empty
and you can't pick a random element from an empty list
Oh yeah, i should have went instead like local dessert = {"j_ice_cream", "j_cavendish", "j_gros_michel"}
anyone know why my hook isn't working? it says G.GAME.elle_rebecca_reroll is nil
-- Init game hook
local game_hook = Game.init
function Game:init()
local g = game_hook(self)
G.GAME.elle_rebecca_reroll = 5
return g
end```
what is this hook meant to do btw ?
add a custom value to G.GAME
ya exactly lol
and you can't assign it to anything in G.GAME because G.GAME doesn't exist yet in init_game_object, you add it to the table that's being returned which is what becomes G.GAME
at the start of the run
and how do i do that in the hook
wait would i uhhh
g.elle_rebecca_reroll
no hang on lemme grab a good reference
okii
oh wait actually yea, i missed that you use g as the return value
i did say g not G lol
yea it'd literally just be
local igo_hook = Game.init_game_object
function Game:init_game_object()
local g = igo_hook(self)
g.elle_rebecca_reroll = 5
return g
end
yippee
well i still got the same error for some reason
local dessert = {"j_ice_cream", "j_cavendish", "j_gros_michel"}
local appetitizer = {"j_turtle_bean", "j_egg"}
local meal = {"j_popcorn", "j_ramen"}
local drink = {"j_selzer", "j_diet_cola"}
SMODS.Joker {
key = "restaurant_book",
loc_txt= {
name = 'restaurant_book',
text = {
"",
},},
atlas = 'locations',
pos = { x = 3, y = 2 },
rarity = 2,
cost = -1,
pools = {["pseudoregamod"] = true, ["cymbal_books"] = true},
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = { extra = {}},
loc_vars = function(self, info_queue, card)
return { vars = { } }
end,
calculate = function(self, card, context)
if context.selling_self then
local beforefood = pseudorandom_element(appetitizer, "cymbal_restaurant_book")
local mainfood = pseudorandom_element(meal, "cymbal_restaurant_book")
local sidefood = pseudorandom_element(drink, "cymbal_restaurant_book")
local finafood = pseudorandom_element(dessert, "cymbal_restaurant_book")
SMODS.add_card { key = beforefood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = mainfood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = sidefood, edition = e_negative, skip_materialize = false }
SMODS.add_card { key = finafood, edition = e_negative, skip_materialize = false }
end
end,
add_to_deck = function(self, card, from_debuff)
card.ability.extra_value = (-card.sell_cost) + (-25)
card:set_cost()
end
}
though this time, they're actually strings as set i the local
Local variables:
self = table: 0x06760e90 {alerted:true, loc_vars:function: 0x06761098, _saved_d_u:true, original_key:restaurant_book, _discovered_unlocked_overwritten:true, loc_txt:table: 0x06760eb8 (more...)}
card = table: 0x04d5b710 {click_offset:table: 0x04d269f8, static_rotation:false, rank:1, parent:table: 0x06737578, T:table: 0x080f6590, last_aligned:-1, extra_cost:0, highlighted:true (more...)}
context = table: 0x06f1f8b8 {selling_self:true}
beforefood = string: "j_egg"
mainfood = string: "j_ramen"
sidefood = string: "j_diet_cola"
finafood = string: "j_gros_michel"```
it has picked the keys
well it did picked the keys, but then i guess it couldn't just use them ?
yea
Same error somehow
uhm, this should be unnecessary, but can you try adding set = "Joker" to each add_card call
hmmm`
worth to try
maybe cuz of a local it doesn't use the string
well correctly i mean
because from what i read in the error, it can get one string first, but seems to crash from there
seems like it work, gotta see if it is random or not now
I think another one of your mods is messing with the process
yep, yep it is
I'd try testing with only your mod installed
cus adding this should not be needed
I know for a fact this should've worked fine
no you don't need to, I'm not going to test your mod in my pc
just saying there's something going on that's not supposed to happen with all the mods you have
local dessert = {"j_ice_cream", "j_cavendish", "j_gros_michel"}
local appetitizer = {"j_turtle_bean", "j_egg"}
local meal = {"j_popcorn", "j_ramen"}
local drink = {"j_selzer", "j_diet_cola"}
SMODS.Joker {
key = "restaurant_book",
loc_txt= {
name = 'restaurant_book',
text = {
"Give this joker 25$",
"by selling to get a negative menu",
"an appetitizer, meal, drink and dessert",
},},
atlas = 'locations',
pos = { x = 3, y = 2 },
rarity = 2,
cost = -1,
pools = {["pseudoregamod"] = true, ["cymbal_books"] = true},
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = { extra = {}},
loc_vars = function(self, info_queue, card)
return { vars = { } }
end,
calculate = function(self, card, context)
if context.selling_self then
local beforefood = pseudorandom_element(appetitizer, "cymbal_restaurant_book")
local mainfood = pseudorandom_element(meal, "cymbal_restaurant_book")
local sidefood = pseudorandom_element(drink, "cymbal_restaurant_book")
local finafood = pseudorandom_element(dessert, "cymbal_restaurant_book")
SMODS.add_card { set = "Joker", key = beforefood, edition = "e_negative", skip_materialize = false }
SMODS.add_card { set = "Joker", key = mainfood, edition = "e_negative", skip_materialize = false }
SMODS.add_card { set = "Joker", key = sidefood, edition = "e_negative", skip_materialize = false }
SMODS.add_card { set = "Joker", key = finafood, edition = "e_negative", skip_materialize = false }
end
end,
add_to_deck = function(self, card, from_debuff)
card.ability.extra_value = (-card.sell_cost) + (-25)
card:set_cost()
end
}
probably, i'm on the last version of SMODS so i don't think it's that, and yeah here's the code, feelfree to tell me what's wrong
maybe it is because it's local upon local, would be weird tho i do agree
how do you add autocomplete to vscode for steamodded again?
I don't really know actually, only started using vscode just two days ago
you could just edit the prefix of the mod (cymbal) to something else, using a different mod or something
or i can make an export build
follow step 3 here (should jump directly to it)
https://github.com/nh6574/VanillaRemade/wiki#3-set-up-the-lua-lsp
sounds silly but iirc it's "Consumeables"
caino moment
-# i genuinely have to correct myself every time i write consumable bc i keep adding the extra e
can't wait for 1.1 to fix all the internal spelling errors and watch a bunch of mods just implode
surely not
selzer moment
thunk has no reason to do that
Selzer
yea i doubt it'll actually happen lol
but it would be funny
if thunk wanted to correct them, that would have long happened already
I think that’s right
yeah that's right
i haven't done balatro modding in a while is this what having dementia feesls like
oh yeah the lua extentsion, kinda got this by myself lol
-# forgot the smods tutorial for that

tho rerolling makes the game stop taking mouse inputs outside of the pause menu
idk why
it didn't before
custom store ui let's goo
:cat_owl:
also the shop contents don't seem to save
yeah they don't do that naturally
it seems to be getting stuck on the reroll function i made
sounds like it might have to do with a missing return?
wait i think i see my mistake
nope i changed a value in a copied over for loop without thinking about the consequences
nvmd
that wasn't it
no worries if you can't figure out why, i'm just happy my joker just works lmao
srly, i feel like everytime i want to do something simple it'll screw me over
ok idk what it is bc i've not missed a return
also it's exiting the reroll function fine
and the print("done :3") is right before the return true in the event
state or lock issue maybe?
hmm
lemme try uhhh
commenting out the save_run() event afterwards
nope that wasn't it
also the cards don't have the buy buttons under then despite the cardareas being type="shop"
debugplus event queue tells me that it's not getting stuck on an event or anything
uploading a vid rn
info_queue[#info_queue+1] = G.P_CENTERS.negative_menu_desc
tried to make a custom info queue bubble but it won't appear, how should i fix it please ?
wdym the thing i thought would be the hardest to implement into the game just worked on the 2nd try 😭
booster voucher
yes
i modified the SMODS.add_voucher_to_shop
now i have to make it appear along with the voucher each ante with a patch probably and make it stay between rouds
and make it so that if you buy the pack the voucher gets sent to the shadow realm
i figured out that the reason the cardareas were being emptied upon closing the shop was bc the cardareas get initialized every time you open the shop... but when i put the cardarea init stuff in the first open check it crashes upon reopening the shop instead
so basically opening the shop would do a soft reset and make it useless to reroll
isn't there a way to store the info of the current store items and change every reroll action?
i'm talking about this, not the vanilla shop
oh wait yeah i misswatched the video sorry
isnt there a way to save the shop items and load the same ones every time you reopen it
that's what i've been asking
earlier
but then i was told to not bother bc they'd stay in the cardareas
oh ok
so the problem seemed to be that the cardareas were getting reset every time i opened the shop but
when i fixed that it now crashes when i reopen the shop
im kinda new to modding so idk
what's the error that happens ?
is there a way to modify which cards get drawn?
good ol nil error
i don't really know either how to fix this, maybe you should make a different way to store the cards of your own joker's store
does anyone know where the function that spawns the voucher at the beggining of each ante is located? i cant find it and i want to patch it
or like any function that handles the ante voucher basically
i swear to god
i left in one of the controller lock functions from vanilla's restock code
how do i make the cardareas persist when i close the custom shop ui
like a way to put it at th top of the draw pile before it gets drawn or sth, just any way to rig it, othrwise do i just discard then draw?
also i found from crytpid you just need to use a custom key like this :
info_queue[#info_queue+1] = { key = "negative_menu_desc", set = "Other", specific_vars = { aaa, bbb } }
How do I layer the sprites udner the menu?
how can i position a UIBox in the center of the screen?
show code and file structure
in the config field do
config = {
major = G.ROOM_ATTACH,
type = 'cm'
}
ooh thank you
nah i found it nvm
how would i do an effect where a joker gives chips equal to the difference between rank and 15
return {chips = 15-card:get_id()}
produces a crash
ask if full log is needed
(yes, my context is that general, and that part dose work lol)
It's context.other_card not card
anyone here happen to know of a qr generator that can generate a qr that fits in a joker texture
turns out this doesn't work because it centers it according to the actual screen, which is way out of bounds of the canvas i'm rendering to lmao
YES!!!! THANK YOU SO MUCH!
this is gonna get silly >:0
hmmm doesnt seems to work ? Can anyone help me
You should be hooking Card:set_ability
Why this I want to have 5% chance to replace mercury by my planet, its just a question, I want to understand what Im doing so its easier next time
So that when a card is created, you can change the center from mercury to your planet.
trying to find a way to make a volume slider but can't find documentation of create_slider anywhere so any help
local config = SMODS.current_mod.config
SMODS.current_mod.config_tab = function()
[...]
local voice_slider = create_slider({
label = localize('fnaf_va_volumeslider'),
ref_table = FNAF.config,
ref_value = 'volumes', -- what var does this button match
callback = function()
FNAF:save_config()
end
})
return {
n = G.UIT.ROOT,
config = {
r = 0.15 ,
minw = 8 ,
minh = 6 ,
align = "cm",
padding = 0.1 ,
colour = G.C.BLACK
},
nodes = {
voice_toggle,
voice_slider,
}
}
end
also config.lua
return {
voices = true,
volumes = 100,
}
btw you should use pseudorandom instead of math.random
yeah I know its just for testing
alr mb
Card:set_ability
What is the issue?
crash
So what's the crash log
when do you define FNAF.config
didn't defined yet, but I used FNAF.config for a toggle
okay, remove the callback from the slider, and just replace FNAF.config with config on every ref_table of the ui elements
FNAF.config is just the prefix that I use to keep track of the config
but I gonna try anyway
the value in ref_table can be the config of your mod directly, so since you have local config = SMODS.current_mod.config there you can just use that
and the callbacks are not needed cus it updates it automatically
ok sure but how do I use this to make a volume slider for voicelines, like I have fuction to play voicelines and I want to my mod to have the option to change the volume seperate
Voicelines = function(audio)
volume = FNAF.config.volumes
if FNAF.config.voices then
play_sound(audio[math.random(#audio)], 0, volume )
end
end
FNAF = {}
FNAF.config = SMODS.current_mod.config
if you have something like this as the first thing in your main file, you can just access the values anywhere using FNAF.config.volumes for example
yeah I know, I kinda already did this
you said you didn't define FNAF.config earlier tho
that's how I got the FNAF.config.voices working
can you show how you defined FNAF.config then
I didn't "define" for the slider
FNAF = SMODS.current_mod
FNAF.save_config = function(self)
SMODS.save_mod_config(self)
end
local config = SMODS.current_mod.config
SMODS.current_mod.config_tab = function()
local voice_toggle = create_toggle({
label = localize('fnaf_va'),
ref_table = FNAF.config,
ref_value = 'voices', -- what var does this button match
callback = function()
FNAF:save_config()
end
})
local voice_slider = create_slider({
label = localize('fnaf_va_volumeslider'),
ref_table = FNAF.config,
ref_value = 'volumes', -- what var does this button match
callback = function()
FNAF:save_config()
end
})
return {
n = G.UIT.ROOT,
config = {
r = 0.15 ,
minw = 8 ,
minh = 6 ,
align = "cm",
padding = 0.1 ,
colour = G.C.BLACK -- this will define the background of the menu
},
nodes = {
voice_toggle, -- the option itself
voice_slider,
}
}
end
how do you add a modded joker via add card?
i do this in a deck after making a smods.joker whose key is openingact and the mod.json prefix is Dapper
error btw
j_modprefix_key
oh i thought modprefix replaced the j part not added onto it, mb
and with this code you're still getting the crash?
yes
I think its because of my create_slider but I don't know how to config it
The crash is cus for some reason FNAF.config.volumes doesn't exist
Can you go to AppData/Roaming/Balatro/config/yourmodid.jkr and see what it has
okay well i might be fucked because my unreasonably complicated joker isnt doing anything and isnt erroring 💔
lemme rq put ts up on github
Yeah, I found it and "fixed" it
I think I just brute force to the config rather than fixing it
like
bump, I am getting a crash on line 71
does anyone know how to use the create_slider(arg)
you are using it right
It doesn't look like it
and when I click it it crashed too
I think I didn't define a limit or something
yeah i might be fried
https://github.com/dervorce/Dapper-s-Opening-Act
Try setting the max value of the slider to 100, (the default is 1) I suspect this is why it looks long
Also if you're getting a crash and are looking for help you should send it
Okay if I had to guess you'll need to change 'center' to 'card' and also change line 69 to be Card:set_ability like the function name
changed some stuff, now i get this error
im now trying to discard cards equal to whats needed for most played hand then draw that many cards but it aint goin well
No, center is a center, not a card.
im not sure if i even know how to draw cards from deck to hand properly this is what i do for it
highkey don't know what's making this trigger twice
should probably post the whole thing
also the thingy doesnt update it always says high card regardless of the hand i actually played most,
local oldcardsetability = Card.set_ability
function Card:set_ability(center, initial, delay_sprites)
if not center then
return nil
end
if type(center) == "string" then
assert(G.P_CENTERS[center], ('Could not find center "%s"'):format(center))
center = G.P_CENTERS[center]
end
if center.set == 'Planet' and center == G.P_CENTERS['c_mercury'] then center = G.P_CENTERS['c_giga_astmercury'] end
return oldcardsetability(self, center, initial, delay_sprites)
end
context.repetitions doesn't exist.
ohhokay :)
You're litteraly the goat
He do be the goat
it still triggers twice
Code?
over here @daring fern
No, the full code.
Fixed it, but it doesn't seems to crash whenever I touch it
callback is not meant to be a function, it's meant to be the name of a function located in G.FUNCS
apparently
i don't think you need a callback to save the config btw, I believe it automatically saves
lol
lmao
hooking love.resize to address an issue that most people will probably never see (rebuilding UI when the game window changes dimensions so the UI stays the same size and position in terms of absolute pixels)
EVIL FUCKING LOVE.RESIZE HOOK
is there more i have to do to my pull request (https://github.com/skyline69/balatro-mod-index/pull/497)? ive seen like two other mods be posted and accepted to the index but mine hasnt been approved yet
which is weird bc its just a deckskins mod so im not sure why its taking so long
or like did i submit it right?
i thought after i opened the pull request thats all i have to do
guys how do i make a joker retrigger consumables that have a calculate effect (not a use effect)
these consumables basically act like jokers
context.retrigger_joker_check
it works on consumables?
Yes.
When drawing with LOVE, how can I make it draw under the pause menu
Patch Game:draw
still haven't found a way to fix it, does anyone know?
I can't seem to be able to use my "volume slider"
evertime I touch it it crashes
wait do i have to request a review
What does your code look like now
Voicelines = function(audio)
local volume = FNAF.config.volumes
if FNAF.config.voices then
play_sound(audio[math.random(#audio)], 0, volume )
end
end
-- ui.lua
FNAF = SMODS.current_mod
FNAF.save_config = function(self)
SMODS.save_mod_config(self)
end
local config = SMODS.current_mod.config
SMODS.current_mod.config_tab = function()
local voice_toggle = create_toggle({
label = localize('fnaf_va'),
ref_table = FNAF.config,
juice = true,
ref_value = 'voices', -- what var does this button match
callback = function()
FNAF:save_config()
end
})
local voice_slider = create_slider({
label = localize('fnaf_va_volumeslider'),
min = 0,
max = 100,
step = 1,
w = 5,
ref_table = FNAF.config,
ref_value = 'volumes', -- what var does this button match
callback = function()
FNAF:save_config()
end
})
return {
n = G.UIT.ROOT,
config = {
r = 0.15 ,
minw = 8 ,
minh = 6 ,
align = "cm",
padding = 0.1 ,
colour = G.C.BLACK -- this will define the background of the menu
},
nodes = {
voice_toggle, -- the option itself
voice_slider,
}
}
end
-- config.lua
return {
voices = true,
volumes = 100,
}
remove the callbacks
is there like
a real-time mult
that gets adjusted as calcuations come in
G.GAME.current_round.current_hand.mult doesn't update after every calc
I think either the global variable mult or SMODS.Scoring_Parameters.mult.current if that's what you're asking
How do I remove a card from deck before deleting it, to avoid that gap glitch?
No, that means you tried to destroy a played card without using SMODS.destroy_cards or context.destroy_card
So SMOD.destroy_cards({ card })?
No, SMODS.destroy_cards(card)
both work
No, SMOD.destroy_cards doesn't exist.
Good news, I fixed the bug. Now I just need to try and get them to not disappear at the same time I think
Added a delay function, it all works smoothly
Tyvm for the help!
you're so funny
So I have a question; I'm transforming a joker through set_ability into a different joker; how would I go about keeping its config (for context, the joker starts as a weaker form of the other joker; so they have the same configs; I just want to transfer the values)
You would save card.ability before you call Card:set_ability
No, in a local variable using copy_table, then change it back after you call Card:set_ability.
i've never used copy_table so im not sure how to change it back
local ability = copy_table(card.ability)
card:set_ability('j_modprefix_key')
card.ability = ability
really late update: i tried this and the game crashed
local insanity = Card:get_id()
function Card:get_id()
if next(SMODS.find_card("j_tcg_insanity")) then
return 14
end
end
update 2: nvm FIXED
it works now 💀
if context.other_card == G.consumeables.cards[1] then
return {
repetitions = card.ability.extra.repetitions,
message = "N'ata vota!",
colour = HEX("12a0d7")
}
end
end```
this is not working
basically copied the code of chad from cryptid but replaced the area with consumeables
Do you have retriggers enabled?
uhm no how do you do that?
SMODS.current_mod.optional_features = function()
return {
retrigger_joker = true,
}
end
tnx
does anyone know in wich file the function that handles spawning vouchers could be located? i need it for a patch but i cant find it
in the current way im doing it the code executes too soon, and it cant access the shop field, and crashes the game
im tryna make a joker that gains 0.15+ mult per scored card and i got that part but i also wanna make it so when you hover your cursor over the joker it shows you your current multi can anyone help me with that?
nvm found it
it was game.lua
function UpdateShop
bruh no matter what i try to do it says that no matches were found for the pattern
i just copy pasted the exact line from the file and it says its not there
WARN - [♥] Pattern 'G.shop_vouchers:emplace(card)\n' on target 'game.lua' for pattern patch from ConsumablesPlus\lovely\empowered.toml resulted in no matches
anyone?
how can i give a card a random seal (there is no seal pool)
there is?
v:set_seal(SMODS.poll_seal({key = 'supercharge', guaranteed = true}), true)
oh thanks i just couldnt find it then lol
Make sure you're looking at Mods/lovely/dump/game.lua for it. Also can you send your patch?
bump + explanation
so currently, i suffer from:
G.GAME.current_round.most_played_poker_hand not actually being the most played poker hand due to it not updating at all for some reason so its always high card at the time of getting it (which is the beginning since i made a testing deck that starts with it) so even after playing like 20 pairs it doesnt show pair in either localization text or in its effect
speaking off, currently it selects amount of cards equal to whats needed to play the most played hand, discards them, and then tries to draw a specific poker hand, that poker hand being the most played hand, but from what i see, while it does discard 1 card (because it thinks its high card) it fails to properly draw 1 random card from deck
holy yap fest i made
this is what i do for drawing btw, i copied it from dna joker from vr since its the only time i see something get drawn to hand
???
if i dont know that then thats the error'
make sure to look where?
version = '0.1.0'
priority = 0
[[patches]]
[patches.pattern]
target = 'Mods/lovely/dump/game.lua'
pattern = '''G.shop_vouchers:emplace()'''
position = 'after'
payload = '''
print('Adding empowered pack yepeee')
local key = get_pack('shop_pack').key
G.GAME.current_round.voucher.spawn[key] = true
G.GAME.current_round.voucher[#G.GAME.current_round.voucher + 1] = key
local _card = Card(G.shop_booster.T.x + G.shop_booster.T.w/2,
G.shop_booster.T.y, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty,
G.P_CENTERS[key], {bypass_discovery_center = true,
bypass_discovery_ui = true})
create_shop_card_ui(_card, 'Voucher', G.shop_vouchers)
_card.ability.booster_pos = #G.shop_vouchers.cards + 1
card:start_materialize()
G.shop_vouchers:emplace(_card)
G.shop_vouchers.config.card_limit = #G.shop_vouchers.cards
'''
match_indent = true```
heres the code
No no, the target should be 'game.lua' as you had before
What I meant is, when looking at the source code look in Mods/lovely/dump
If you weren't already
how do i make a patch replace the target pattern
position = 'at'
ty
peak lovely patch,,
# Fix Card:load()
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''self.VT.h = self.T.H'''
position = "at"
payload = '''self.VT.h = self.T.h'''
match_indent = true```
peak
yea so it does crash the game
but in like a way that the game stops so i dont see the crashlog
yeyea i read the logs i have to slightly change the position
the patch is inside a for loop and it turns out it makes it go forever
for _, key in ipairs(G.GAME.current_round.voucher or {}) do and it adds a new card to the voucher slot
made a smods pr
hi, so am i missing anything here??
to add onto this image, this is High Card btw (simplest one) and the one that is being tested and breaking
i assume G.playing_cards is the deck and whats shown in the previous image is how to draw so why dont this work
art :3
how do i add the buy button stuff to my shop cardareas
is there something in particular im doing wrong? are the cards in G.playing_cards not the same type as the ones in G.hand? or am i just using the wrong functions? what am i supposed to do here to properly draw a random card from the deck into the hand
How do you evaluate Two Pairs?
I love this idea, what a comical coin
when should/shouldnt i use nested events for creating cards? i see vanillaremade doing an event inside of an event to create the card for cartomancer, but doesnt do this for sixth sense
Look at vanilla remade
did you forget to return true in an event
How come the Russian and Korean translations of Balatro use a different font?
probably bc they use different symbols
How do they do it? I'm making a localization file that uses characters that don't show up in the normal font.
But how do I get mine to use that different font, that's the question!
Pretty sure you can use SMODS.language
bump
Not sure if SMODS.font specifically exists
G.hand is your current hand, G.playing_cards is all cards in a deck
Also idk about drawing yet
Maybe ask the others
I used an auto-searching Python file to look for any instances of SMODS.language in the smods folder; didn't find anything.
Also it's SMODS.Language so mb
SMODS.Font
Thanks to the both of you, though I'm sure to not figure it all out by tonight.
How do I iterate over a table of more tables? Trying this produced a crash.
for _, area in {G.deck.cards, G.hand.cards} do
--
end
do for _, area in ipairs({G.deck.cards, G.hand.cards}) do
or do you want to concatenate the tables
Not necessarily.
guys does ANYONE know how to draw a card from G.deck.cards to G.hand
the loop thing just bricks with this:
SMODS.draw_cards(1)
Alternatively, SMODS.draw_cards(1)
this is a thing? i heard someone complaining in vc the other day about SMODS.draw_card not existing
uhh what does up and 90 here do
wrong reply mb
i meant to the one above
Draw cards isn’t that new
Looking at where it is in the file it seems to be as old as changing the play limit
cant use the smods one because i need to draw a specific card and im noticing only the draw_card() one has the parameter for card
git blame is calling
The code you shared selects a random card though
thats just for high card
what the flip wheres me text
well
I've seen a whole bunch of mods include an extra button under the sell button but looking in the code, i do not understand it. Does anyone know a clear example I can look at?
ok so say i want a joker that scans every card on the field for a suit. (i.e, look in scored and unscored hand for Hearts); how would i do so
i attempted to do this myself, with this code
key = 'careful_fool',
loc_txt = {
name = 'Careful Fool',
text = {
'{C:mult}+#1#{} Mult for each {C:hearts}Heart{} on the field'
}
},
atlas = 'Jokers',
rarity = 1,
cost = 6,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
pos = { x = 2, y = 0 },
config = {
extra = {
mult = 4
}
},
calculate = function(self, card, context)
if context.joker_main then
local diamond_count = 0
for _, c in ipairs(G.play) do
if c and c:is_suit('Diamonds') then
diamond_count = diamond_count + 1
end
end
return {
card = card,
mult = card.ability.extra.mult * diamond_count,
message = '+' .. (card.ability.extra.mult * diamond_count),
colour = G.C.MULT
}
end
end
}
but it didnt work
any ideas on how i can actually make it work?
so now what
pseudorandom_element returns two values.
oh shit, which one is the actual selected element?
the first
the .key? so like this?
drop the .key and that line is fine
Or local c = (pseudorandom_element(candidates, 'openingact') or {}).key would work?
i see the first one would go to the variable but it doesnt work for my high card because it just drops it in a list immediately
you can just do card = pseudo...; cards = {card}
just had to do this
yeah that
now for the last issue, most played hand aint most played hand'ing
so regardless of what hands i play, it always says High card, and always acts like it, and im using G.GAME.current_round.most_played_poker_hand
that only updates at certain points, it's not fully dynamic
oof
gotta count it manually then
Is it possible to put enhancements in a pool like you can Jokers and Consumables, or does that require some other workaround?
it is possible, as an SMODS.ObjectType can contain any kind of centers
though it wont work as a pool for poll_enhancement if thats what youre trying to do, just for create_card/add_card. poll_enhancement already has an options field that allows defining a specific pool of enhancements
hi guys i am currently trying to redo the code for "soul of hatchet" and i have no idea what im doing
"soul of hatchet" is a consumable that upgrades the base joker "hatchet" into a new joker known as "divine hatchet" and said new joker has the divine edition
SMODS.Consumable {
key = 'soul_of_hatchet',
set = 'divine',
pos = { x = 1, y = 1 },
config = {
extra = {
destroy_count = 1
}
},
loc_txt = {
name = 'Soul of Hatchet',
text = {
[1] = 'A mysterious card with',
[2] = 'a {C:enhanced}unique effect{}',
[3] = '{C:inactive}(Cannot be used on',
[4] = '{C:inactive}stickered Jokers){}'
}
},
cost = 3,
unlocked = true,
discovered = false,
hidden = false,
can_repeat_soul = false,
atlas = 'CustomConsumables',
use = function(self, card, area, copier)
local editionless_jokers = SMODS.Edition:get_edition_cards(G.jokers, true)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
play_sound('mega')
SMODS.add_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_hatch_divinehatchet")
card:juice_up(0.3,0.5)
local _first_dissolve = nil
for _, joker in pairs(G.jokers.cards) do
if joker == 'j_hatch_hatchet' and not SMODS.is_eternal(joker,card) then
joker:start_dissolve(nil, _first_dissolve)
_first_dissolve = true
end
end
card:juice_up(0.3,0.5)
return true
end
}))
end,
can_use = function(self, card)
return true
end
}```
this is the code as of current but i can tell theres all sorts wrong
i genuinely have no idea what i m doing
um
maybe dont redefine SMODS.add_card for starters
every other mod that uses SMODS.add_card will blow up if you do
😰 i was following the vanillaremade documentation on hex
you're talking to someone who isnt educated in code in the slightest - i can barely make a simple joker
what is the key of hatchet
oh
j_hatch_hatchet
oh i got the key for divine hatchet wrong
that would be a good catch
its supposed to be j_hatch_divine_hatchet
the error i got specifically was an undefined center
which tends to normally mean ive added a variable that isnt defined
first of all i would suggest making it so that this cannot be used if you do not own a valid target for this card
yes - in a previous version of this consumable, it was sorta working but it blew up a random joker held in hand rather than the hatchet itself
idk how valid targets work
again, complegtely new here
ok not completely new but i didnt start modding until october
I have four others I have yet to make art for
this was the old code
it mostly worked, the only real issue was the fact it would evolve a random joker held in hand rather than the joker i wanted
this error i got in v1.4.3
not what i want
so
local has_target = false
for i, joker in ipairs(G.jokers.cards) do
if not SMODS.is_eternal(joker, card) and joker.config.center.key == "j_hatch_hatchet" then
has_target = true
break
end
end
will check for a valid target
oke
you can modify the conditions as you need
so if there are further restrictions on the hatchet that can be transformed, add them i the if statement
ill give this a shot
put this in the can_use function and return has_target
oke
i think im sticking to the old code since it mostly worked the way i want to, and ill add ur additions to it
here we go
Is it possible to change the green flash when upgrading for a specific planet
ok i have to do some other stuff
so sorry i wish i could help more
but the low temperature legumes beckons me
its okay, it moreorless works like a charm now
bizarre new error with the cudgel boss blind
i get this error for some reason
this is the code
SMODS.Blind {
key = "hatch_cudgel",
config = {
extra = {
currenthandsize = 0,
hand_size = 1
}
},
dollars = 5,
mult = 1,
pos = { x = 0, y = 3 },
boss = { min = 1 },
boss_colour = HEX("a652c0"),
atlas = 'CustomBlinds',
loc_txt = {
['name'] = 'The Cudgel',
['text'] = {
[1] = 'Decrease hand size',
[2] = 'per played hand',
},
},
loc_vars = function(self, info_queue, blind)
return {vars = {((G.hand and G.hand.config.card_limit or 0) or 0)}}
end,
calculate = function(self, blind, context)
if not blind.disabled then
if context.before then
return {
func = function()
G.hand:change_size(-1)
return true
end
}
end
if context.end_of_round and context.game_over == false and context.main_eval then
return {
func = function()
G.hand:change_size(current_hand_size)
return true
end
}
end
end
end
}```
note: it's meant to appear in ante 4 at minimum, but i set it to 1 here for testing purposes
uh
i thought this would be easy but my pareidolia clone isnt working at all
the idea is that it converts face cards into 2s
but even as i use the default vanillaremade code without altering it, it still doesnt work
the default pareidolia code
function Card:is_face(from_boss)
return card_is_face_ref(self, from_boss) or (self:get_id() and next(SMODS.find_card("j_vremade_pareidolia")))
end```
hm
if what eris says is correct, lemme remove the "vremade pareidolia" part thingy
ok that works
so ive got this
function Card:is_face(from_boss)
return card_is_face_ref(self, from_boss) or (self:get_id())
end```
how do i make it so that every face card plays returns a 2
bump
key = "jiren",
loc_txt = {
name = 'Jiren',
text = {'{X:mult,C:white}X#1#{} mult','Gains {X:mult,C:white}X#2#{} mult when playing {C:attention}High Card{}','{C:inactive}Strength is absolute{}'}
},
discovered = false,
blueprint_compat = true,
rarity = 3,
cost = 9,
config = { extra = {xmult = 1, xmult_gain = 0.25} },
loc_vars = function(self, info_queue, card)
return { vars = {card.ability.extra.xmult, card.ability.extra.xmult_gain} }
end,
calculate = function(self, card, context)
if context.scoring_name == 'High Card' then
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain
end
if context.joker_main then
return{xmult = card.ability.extra.xmult}
end
end
}```
Guys this wont appear in game, what did i do wrong?
another
you don't have a texture for it
that's probably it
key = "senzu_bean",
loc_txt = {
name = 'Senzu Bean',
text = {'play a hand to gain a {C:blue}hand{}', 'and destroys itself', 'sell this to gain a {C:red}discard{}'}
},
discovered = false,
blueprint_compat = true,
rarity = 1,
cost = 3,
calculate = function(self, card, context)
if context.selling_self then
ease_discard(1)
end
if context.joker_main then
ease_hands_played(1)
SMODS.destroy_cards(card, nil, nil, true)
end
end
}```
this one appears
are modded items added to G.P_CENTERS, and if so can i just access them using the same key as i would for the localization
yup and yup
how do i change the description of a card based on context?
Can you uhhh, make a thnickel joker?
https://thick-coins.net/
perhaps
Jiren shaped bump
Hey so I have a card that once you have 1 hand left, it draws a 3 more cards, however for some reason it's pulling some like ainvisible card, like this weird visual bug, I don't know how annd why is it happening
SMODS.Joker {
key = "jackie",
atlas = 'Joker',
pos = { x = 8, y = 0 },
blueprint_compat = true,
rarity = 2,
cost = 5,
config = { extra = { cards = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.cards } }
end,
calculate = function(self, card, context)
if context.drawing_cards and G.GAME.current_round.hands_left == 1 then
for i = 0, card.ability.extra.cards do
draw_card(G.deck, G.hand, 100, 'up', true)
end
end
end,
}
JIREN SHAPED BUMP PT2 (PLEASE GUYS I NEED THIS)
I've seen a whole bunch of mods include an extra button under the sell button but looking in the code, i do not understand it. Does anyone know a clear example I can look at?
I think that happens when it tries to draw a same card more than once
SMODS.draw_cards(hand_space) btw
Unless I miss something that's the function you need
hand_space is amount of cards to draw
So you don't need to do a for loop
How can i make a consumable permanently give hands and discards, everytime a blind is reset it doesn't keep the added resources
so i have a weird problem, for some reason, one of the cards this draws is some wierd ass nothing card? deck has 6 aces of hearts btw
doesnt happen with any other thing btw, its specifically with the flush five
Modify G.GAME.round_resets.hands and G.GAME.round_resets.discards
as in like set those variables equal to the config vars?
figured it out
like this?
How do I make this work if not G.SETTINGS.paused and center.set == 'Planet' and math.random(25) <= 2 then local astrals = { c_mercury = 'c_giga_astralMercury', c_jupiter = 'c_giga_astralJupiter', c_pluto = 'c_giga_astralPluto', c_eris = 'c_giga_astralEris', c_planet_x = 'c_giga_astralPlanetX', c_saturn = 'c_giga_astralSaturn', c_earth = 'c_giga_astralEarth', c_mars = 'c_giga_astralMars', c_ceres = 'c_giga_astralCeres', c_venus = 'c_giga_astralVenus', c_uranus = 'c_giga_astralUranus', c_neptune = 'c_giga_astralNeptune' } if astrals[center] then center = G.P_CENTERS[astrals[center]] end end
Yes.
it didn't change the amount when i use the consumable
Cause it was like that before if center == G.P_CENTERS['c_mercury'] then center = G.P_CENTERS['c_giga_astralMercury'] end if center == G.P_CENTERS['c_jupiter'] then center = G.P_CENTERS['c_giga_astralJupiter'] end if center == G.P_CENTERS['c_pluto'] then center = G.P_CENTERS['c_giga_astralPluto'] end if center == G.P_CENTERS['c_eris'] then center = G.P_CENTERS['c_giga_astralEris'] end if center == G.P_CENTERS['c_planet_x'] then center = G.P_CENTERS['c_giga_astralPlanetX'] end if center == G.P_CENTERS['c_saturn'] then center = G.P_CENTERS['c_giga_astralSaturn'] end if center == G.P_CENTERS['c_earth'] then center = G.P_CENTERS['c_giga_astralEarth'] end if center == G.P_CENTERS['c_mars'] then center = G.P_CENTERS['c_giga_astralMars'] end if center == G.P_CENTERS['c_ceres'] then center = G.P_CENTERS['c_giga_astralCeres'] end if center == G.P_CENTERS['c_venus'] then center = G.P_CENTERS['c_giga_astralVenus'] end if center == G.P_CENTERS['c_uranus'] then center = G.P_CENTERS['c_giga_astralUranus'] end if center == G.P_CENTERS['c_neptune'] then center = G.P_CENTERS['c_giga_astralNeptune'] end
Change astrals[center] to astrals[center.key]
but center.key make me crash
Log?
Astrals...
does anyone know how to properly check when we highlight a joker, i get a crash at the can_use func
I just happen to know something with a similar name
but it add 12 planet
oh
mine are astrals planet
It's G.jokers.highlighted
Like Astral Pluto for example
Yea i think the thing i know is different to that
I already tried this but it crashes
changing it to that results in it saying it is comparing to something that is nil
Huh what
Like, it ccrashes so bad that it closes
Code?
Could you like show the way you did it
SMODS.Joker {
key = "jackie",
atlas = 'Joker',
pos = { x = 8, y = 0 },
blueprint_compat = true,
rarity = 2,
cost = 5,
config = { extra = { cards = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.cards } }
end,
calculate = function(self, card, context)
if context.drawing_cards and G.GAME.current_round.hands_left == 1 then
SMODS.draw_cards(card.ability.extra.cards)
end
end,
}
You're drawing cards in context.drawing_cards
Oh right
so how do I fix this? do I just remove it, like, I want to draw more 3 card once
Use context.hand_drawn instead.
Yeah context.drawing_cards happens for every drawn card if I remember correctly
it worked to well, I need to implement a condition
Why did it do that
trying to index a selected joker but i assume since the game only allows one to be selected at once then it should be only the G.jokers.highlighted var, but doing that causes a crash
it's cus you're taking the length of it, remove the # from the chosen_joker line
it detects that the hand is being draw and that it's one the last hand, so its gonna keep drawing until the deck runs out
A!
that causes errors for some reason
can you send the full crash log
ok
also I'm trying to make something to prevent it from retriggering it but it doesn't work, let me try a bit more asking for help
Shouldn't like a boolean work
I already tried but it didn't work
if context.hand_drawn and G.GAME.current_round.hands_left == 1 and not card.ability.extra.triggered then
card.ability.extra.triggered = true
return {func = function() SMODS.draw_cards(card.ability.extra.cards) end}
end
if context.end_of_round and context.main_eval then
card.ability.extra.triggered = false
end
thanks
dunno
I was trying to make a check where the joker doesn't drawn more cards if the number of cards holding was higher that the limit, but this might be better
The error seems to be coming from trying to make a copy of the highlighted joker?
Yes, it would be G.jokers.highlighted[1]
is there a list of all the possible g.states somewhere? i can't find it on the wiki
lovely/dump/globals.lua and search for self.STATES = {
how would i change the backround color?
would if P_STAKES == stake_gold then work?
You mean you want to check if the current stake is gold stake?
Current stake is G.GAME.stake
I think you'll need to use a number for that instead of a key
is there a way for me to change the background swirl's color anytime?
something about the number isn't right, everything else is fine if i remove the stake part
i'm getting an error where i increment the destroy count because it says i'm trying to perform artihmetic on a nil value
well this won't matter anymore because i changed my mind on how i want things to work :)
Did you start a new run?
let me try that rq
it worked but the consumable isn't deleting cards of a random suit like it should
Yes, it would be G.hand.cards[i]:is_suit(_suit.key)
is this how you check a card's rank properly in a loop?
You should do
for i, _card in ipairs(G.hand.cards)
I think
That way you check every element in G.hand.cards
And _card is each element
So the first time _card will be the first element etc.
At least i think maybe i dont remember correctly
if G.hand.cards[i]:get_id() % 2 == 1
Oh yea maybe its that i didint read the problem correctly nvm xd
Thanks!
bump
nvm i figured it out
is there any way to change which card gets drawn? like rigging the deck and putting some cards on top of it? i would much rather do that than having to discard then draw cards
I wonder if it's possible for the game to check for a specific joker in your joker slots,
If I can explain it a bit better, this is the description of my card (I don't intend on balancing this, it's for fun anyway, I mean I have a joker which has a 1/10000 chance of giving a straight up game over)
yea that's kinda easy to add
-# uhhh how do I make my own mod
read smods documentation
got it
good way to start is Joker Forge I'd say. It's similar to Scratch.
Ooo ok
If a Joker were to gain x1 mult for each different editions in playing card, like let say you score a negative polychrome stone card, it give x3 mult but those nothing for vanilla. Would would code read like
Some mod allow for 2 or 3
Ok, can you explain
cards can literally only have 1 of each
bumping part 29
What about card that glass polychrome or lucky polychrome
<cardarea>.cards is a table, just move the cards
does it draw from last to first or from first to last?
not really
There polychrome wild and
also balatro app store images are from back in the beta
you. should really play vanilla cuz its sounds like you havent played
once again, wild is an enhancement
please look at the collection
Ya I haven't play vanilla in ages