#💻・modding-dev
1 messages · Page 696 of 1
i finally got a consumable working without crashing but
thats... not supposed to happen LMAO
i can only drag it around
ill figure it out later i gotta go to an appointment
You prob forgot to add G.consumeables:emplace(card)
If you only call create_card it doesn't emplace it
how could I get a UIElements ref table in its related shaders send_vars?
also is it possible to disable to offset on text inputs
how would i dynamically change the colours of text? ive got a thing that puts cards into the descrioption and i wanted the colour to be the suit of the card but it just displays {C:spades}A{} for example
thanking you
does anyone know if there are symbols for suits that work in descriptions?
I have a vague feeling I've seen something like that somewhere
though you can also use {element:} controls to insert sprites now
yeah, it's on the one I sent 30 minutes ago
oh gas
how could i get an enhancement to make a card be every rank at once?
very carefully
graahh
?
how do i make a seal that generates a consumable if its the only card scored
any_rank = true methinks
making cards able to count as multiple ranks is a huge endeavour with dire implications
how can i do ts
holy gem
context.main_scoring and context.cardarea == G.play and #context.full_hand == 1 then?
and the area check
forgot that
1 check for the card scoring context, check if in G.play then check if scored_hand == 1 then
generate consumable
this
draw_card(G.deck, G.discard) always discards the top card of the deck no matter what. Is there a way to discard only those cards in deck that meet a given criterion?
the sixth argument of draw_card is the card to draw
i love functions with 11 arguments
how does one make pop ups like this
In loc_vars, there should be a variable infoqueue (or something similar); add to the table an item from G.P_CENTERS
Example: table.insert(infoqueue, G.P_CENTERS[item_key])
ive definately messed this up
-# (a bunch of people also do infoqueue[#infoqueue+1] = G.P_CENTERS[item_key] but - and don't tell them i said this - that's a kinda stupid way of doing it)
How is that stupid? I always thought that that was the only way.
kinda stupid to you but still functional
to be fair it's not objectively stupid but i don't like the semantics surrounding it
ego
it's not immediately obvious that table[#table+1] is an insertion - but table.insert is in-your-face obvious
it's immediately obvious if you know the language
i wouldn't be surprised if table.insert was actually slower too
and when modding a game that coined the term thunkism, i think having clear and readable code that minimizes code sugar is really important
ah, but that's the trick - performance does not matter until people start complaining about it
Bruh
I'm right
objective reasoning for using table[#table + 1]
as in, implementation is important before optimization

care I do not, you I shall mog
Having good readable code is one thing
Saying a basic feature from the language is stupid is something else
And optimization is always good especially when it's that simple
yea
question
whats the prefix for stickers
is it just m
like all other modifiers
?
:'(
Yeah, I was wrong to say that table[#table+1] is stupid (intended to be joke-y about it), it was very much a personal opinion, my apologies
none
m is just for enhancements
so just modprefix_id?
yes
So seals and stickers both have no prefix? Awesome 
anyways, displeasure talking to you
question
in what part of a mod are the prefixes added
for instance, curses for ortalab
and hexes for grab bag
they probably have custom prefixes
so where can they be found
?
i didnt understand why the conversation was so aggro
custom ones are done manually
or the creator sets up something to do it for them
when you extend the smods objects they can have a class_prefix field
where are they found, then
its done per mod I cant tell yoh
gimmie a sec
found it
the prefix for hexes are hex_
just letting this info out for anyone who needs it
nvm
you have to put it at the end
modid_id_hex
i'm about to lose it
how can i make my mod modify another file
😭
(from another mod, of course)
hi! im triying to make a joker that gives +300 score at the end of scoring but i dont know why its not working
context.final_scoring_step
after is after scoring, so a bit too late
although i dont know if that applies to score, make sure to have updated smods too
does anyone know if theres any symbols for suits that work in balatro?
i didnt found any when i tried in the vanilla fonts if thats what you're asking
ngl I hate this train of though
when its a base feature, you are expected to know what it means
sure to someone random its not as readable, but they arentnthe target audiance
is there a way for this to not happen qwq?
is this every single blind?
I think you'd have to hook/patch one of the UI functions
but t[#t+1] isn't necessarily a base feature - it uses base features, but it's just a developer's trick
every single blind minus the hook, the fish, the water, the serpent, and my 3 new blinds
it's not something you'd find in some "How to use Lua" guide
compare it to pythons [::-1]
this is not readable
(or at least the few Lua handbooks I've used don't remark it)
but any python programer should know what it does
it isn't a base feature but it uses base features
what
thats like everythinf
and also it intuitively makes since
yeah idk how to refute that nvm
Assuming that Python's indexing system is regularly taught beyond just using one argument
it should be ;-;
splicing is helpful
in c instead of doing array[index] do (array+index)*
instead of fried insertion, used grilled insertion
in js instead of doing array[i] do array[grilled chicken]
frick you beat me
i mean i think table[#table+1] is pretty obvious
it only works in lua i think tho because of 1dexing
yeah, I worded my opinion pretty badly
array[array.length] would work
but it'll frick things up
since array.push does some other stuff
I'm just a bit bothered by this reasoning; I can't imagine someone teaching Lua - personally or via a guide - would first say "you put items in lists with this line: t[#t+1]"; they'd point to the table library (I think it's a library?)
cant really say anything on this
I still haven't really learned lua
that's fair
ahh i see thanks
legit the only thing I've looked up is metatables lol
i mean its identical to table.insert with no index argument
everything has either been assumptions or looking at mod code
so it doesnt really matter
table.insert is only very slightly slower but its so insignificant that 99.9% of the time that wont matter
i'd start with t[#t+1] yeah, if we're talking just appending to the end and not inserting anywhere else
but i would also mention that table.insert does the same thing if you don't specify a position, in case my student finds that easier to remember
table.insert isn't "for" appending, it's for inserting
but also it doesn't matter what it's "for"
...ah
i dont like the overload in table.insert
the huh
like one is table, value and the other table, index, value
it's mostly a C++ thing
i mean i guess math.random also does it i think but i think it isnt as bad there
though you can recreate it in other languages
yeah this sucks ass
C++, not C
which is why i almost never use it for between-insertion
(actually it's because I almost never need to)
You do between insertion manually?
im fine with overloads, but i dont like that it changes the order
what are you suggesting
genuinely dont think i have ever needed between insertion
i have for ui : )
needs more bumpscosity
I thought you said you didn’t use table.insert, my mistake
bump
what context would i have to use to detect whether a joker has moved positions?
there isn't one for that
you would need to make one, i think Node.stop_drag is the function for it iirc
sad
i recall seeing something that lets me create a custom context but i dont remember where
i'm fucking going insane cleanse should be converting cards into purified cards
why is it not doing that
What is GB.Hex?
sticker works mostly, but it seems to have a few issues:
- if a joker stencil has the sticker + there are 4/5 slots filled, the burdened sticker reduces it to 0X
- negatives spawn with this sticker somehow
- as does riffraff and judgements and other joker summoning cards/jokers
@frosty rampart u helped make this sticker iirc, could u help me with this if thats oke
I'm out and about for most of the afternoon/evening unfortunately, but I'll take a look when I'm free
thats oke
ill ask potato patch for help in the meantime
i'm being told that "reset" on SMODS.debuff_card() is deprecated but what is the equivalent that i'm supposed to use now? i want debuffs to be removed regardless of where the debuff came from
"prevent_debuff" should override anything iirc
yesn't, i've noticed that sometimes the order you acquire stuff matters??
like, i have a joker that debuffs everything but 7s and one that prevents red sealed cards to be debuff. If I get the first one before the second, sometimes red seals will stay debuffed, it's kinda whack
i tried prevent_debuff but that seems to stop the cards from being debuffed in the future as well which i don't want to have
then you need to empty the table debuff_card uses, but thats bad practice
i think the idea is that if a card has a debuff from a source you shouldnt be able to remove it
because then it becomes an arms race
i would just stick to reset for now
can you have a card get debuffed without a source or does that also cause problems?
not with that function
you can with context.debuff_card
or setting card.debuff and calling recalc_debuff on it iirc
there are like 5 ways to debuff
yeah i usually avoid it lol
i found SMODS.current_mod.set_debuff to be the nicest imo
that's what i've been using too, i just put all my debuff stuff there so it's easy to manage
i did a lot of the abilities and stuff before knowing how annoying debuffs are which is for sure on me but we're here now i guess
what does the (next(context.card_effects[1]) or #context.card_effects > 1) check in the vremade for Mime actually do?
i assume its a check for whether or not the card has held in hand effects?
it checks if the card actually triggered any effects yeah
bump
You could also do this: https://github.com/Somethingcom515/SealsOnJokers/blob/dev/lovely/multirank.toml
How would I get a Joker's description as a singular string?
table.concat(localize({type = 'raw_descriptions', key = key, set = 'Joker', vars = {}}), ' ')
why not
negative burdened jokers kinda fuck things up
they basically remove the whole point of negatives with them
for example with the above screenshot, i would not be able to afford empty crown because it goes from 0 slots to 1 slot
making it impossible to purchase
so yeah
how do i exclude negatives from having the burdened sticker
in the sticker's should_apply, check whether the card is negative and if so return false
a card that becomes negative after would still work
note that running a should_apply function will override anything like a rate or necessary game flag in the sticker definition
so you'll need to manually check that if you don't already
it doesnt work
local default_check = SMODS.Sticker.should_apply(self, card, center, area, bypass_roll)
local shop_check = (area == G.shop_jokers) or (area == G.pack_cards) -- credit to Bunco mod
return default_check and shop_check
end,```
this is my current "should_apply" function
im guessing i do an "if card = e.negative" or?
idk
yeah in that case just check card.edition and card.edition.negative and return false if it is
would local negative_check = not card.edition.negative work?
return default_check and shop_check and negative_check (making sure to add this)
No, that wouldn't work, because stickers are applied before editions are applied in create_card
welp it crashed
oh that's unfortunate
what do i write then?
the other two checks work fine
no fucking idea, you're checking for something that hasn't happened yet
Maybe forbid the sticker from appearing on Negative cards as a workaround?
thats the plan, but im guessing id have to make a hook or something of the sorts?
You could hook Card:set_edition and remove the sticker if the edition is negative.
hmm okay
what would the hook look like?
im looking at the vremade wiki and im still unsure how id hook card:set_edition
anyone know a better way to do exponential mult return { mult = -G.GAME.current_round.current_hand.mult + (G.GAME.current_round.current_hand.mult ^ 2) }
what are you trying to calcluate here exactly
could you not just do
if context.joker_main then
return {
emult = G.GAME.current_round.current_hand.mult ^ 2
}
end
end
?
idk i may be wrong
return {mult = (-mult)+mult^2}
is emult a thing
no idea im gonna be honest
anyways fuck it
im giving up
ill let negatives keep the burdened sticker
the odds of finding a negative with a burdened sticker is quite rare without a tag anyways + i feel like theres no real way i can fix it
is there a way to stop the message + 'mult'
not within my own means at least
like the context?
oh ok
found it 😭
Use mult_mod instead.
oh ok i thought i tried that but i put mod_mult
thanks for the help it works now
-- Wheelbarrow
SMODS.Joker {
key = "wheelbarrow",
config = { extra = { odds = 7, xmult = 1, xmult_gain = 0.2 } },
pos = { x = 6, y = 3 },
cost = 7,
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_hatch_wheelbarrow')
return { vars = { numerator, denominator, card.ability.extra.xmult, card.ability.extra.xmult_gain } }
end,
calculate = function(self, card, context)
if context.stay_flipped and context.to_area == G.hand and SMODS.pseudorandom_probability(card, 'j_hatch_wheelbarrow', 1, card.ability.extra.odds) then
return {
stay_flipped = true
}
end
end
}
``` how do i make the code add x0.2 mult to every played facedown card?
like ik how scaling manipulation works but how would i make it scale played cards that were initially flipped down?
-- Wheelbarrow
SMODS.Joker {
key = "wheelbarrow",
config = { extra = { odds = 7, xmult = 1, xmult_gain = 0.2 } },
pos = { x = 6, y = 3 },
cost = 7,
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_hatch_wheelbarrow')
return { vars = { numerator, denominator, card.ability.extra.xmult, card.ability.extra.xmult_gain } }
end,
calculate = function(self, card, context)
if context.stay_flipped and context.to_area == G.hand and SMODS.pseudorandom_probability(card, 'j_hatch_wheelbarrow', 1, card.ability.extra.odds) then
return {
stay_flipped = true
}
end
if context.individual and context.cardarea == G.play and
G.hand.cards[i].facing == 'back' 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
}```
current code, it gives me a nil value error
if context.press_play then
local count = 0
for k, v in pairs(G.hand.highlighted) do
if v.facing == 'back' then
count = count+1
end
end
if count > 0 then
SMODS.scale_card(card, {
ref_table = card.ability.extra,
ref_value = 'xmult',
scalar_value = 'xmult_gain',
no_message = true,
operation = function(ref_table, ref_value, initial, scaling)
ref_table[ref_value] = ref_table[ref_value] + scaling*count
end
})
end
end
ah, i see
what does context.press_play do?
also i am not familliar with how SMODS.scale_card works yet
It's called when the play button is pressed.
could i just do
if count > 0
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain
or smth like that
No, you should use SMODS.scale_card
ah, i see
hey ive been just using pseudo random is there a way to make it afeected by oops
with psuedorandom, what if i wanted something to do 3 different things based on the outcome
i think its automatically affected
if you use the odds config
SMODS.pseudorandom_probability(card, 'seed', numerator, denominator)
if psuedorandom() < =1/3 or psuedorandom() < =2/3 and psuedorandom() > 1/3 and so on
thats how i do it anyway
thanks ill try it out
thats what i though
*thought
Make a table with 3 things in it, make it choose 1 randomly and do the thing you want associated w it
thanks
thats works to
what is (card)
i assume not like this then?
cause this is only giving me the first outcome
if context.joker_main and SMODS.pseudorandom_probability(card, 'sink_tv', 1, card.ability.extra.odds) then
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1("zebra1","why the hell is there a zebra in the car"),
config = {no_esc = true}
}
return {
xmult = card.ability.extra.xmult
}
end
if context.joker_main and SMODS.pseudorandom_probability(card, 'sink_tv', 2, card.ability.extra.odds) then
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1("cocacola2","nothin like a good ol fashioned coca cola"),
config = {no_esc = true}
}
return {
xmult = card.ability.extra.xmult
}
end
if context.joker_main and SMODS.pseudorandom_probability(card, 'sink_tv', 3, card.ability.extra.odds) then
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1("burger3","yum yum"),
config = {no_esc = true}
}
return {
xmult = card.ability.extra.xmult
}
end
end```
i am just starting to use SMODS.pseudorandom_probability(card, 'seed', numerator, denominator) before i just used pseudorandom() let me figure it out
mmk
maybe try this ```
local outcome = pseudorandom('sink_tv_choice')
if outcome < 1/3 then
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1(
"zebra1",
"why the hell is there a zebra in the car"
),
config = {no_esc = true}
}
elseif outcome < 2/3 then
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1(
"cocacola2",
"nothin like a good ol fashioned coca cola"
),
config = {no_esc = true}
}
else
G.FUNCS.overlay_menu{
definition = create_UIBox_custom_video1(
"burger3",
"yum yum"
),
config = {no_esc = true}
}
end
return {
xmult = card.ability.extra.xmult
}
end```
you dont have to use the local though
k hold on
wait what do i put in my config
cause i aint got nothing for psuedorandom(sink_tv_choice)
@zenith quarry u good bro 😭🙏
sorry wdym
sink_tv_choice is just the seed
you can use just sink_tv
is there a good way to draw a "soul" on top of a card without a shadow?
make your own draw function that doesn't draw the shadow
like hologram: https://github.com/nh6574/VanillaRemade/blob/b07ab88f94949bd48fe95fb09c83f2f44d5fabe5/src/jokers.lua#L1917
oh yup, that helped a lot, thank you!
i made a legendary joker
but like
the soul wont make it
nevermind
i was just unlucky
how can i change a cards name, for example a stone card, with a tarot card? i want the edition to still stay the same, just change its name.
You would have to hook generate_card_ui
why not some elaborate key return setup in loc_vars
can someone Help
Ok so im making a deck called glass deck
it makes all your playing cards glass but u have an eternal negative oops all 67s
the glass thing works fine but
when u get the oops all 6s its 1/6 joker slots for a second and then goes to 1/5 even though its negative
`SMODS.Back({
key = "glass_deck",
atlas = "glass_deck",
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function()
-- give oops
local j = add_joker("j_oops_all_6s", nil, true)
if j then
j:set_eternal(true)
j:set_edition("e_negative")
end
-- everything is GLASS
for _, card in ipairs(G.playing_cards or {}) do
if card.set_ability then
card:set_ability(G.P_CENTERS.m_glass)
end
end
return true
end
}))
end
})`
it LOOKS negative ingame and the sell value is increased as if it were negative also its eternal but the joker slot doesnt get added
So on ante 8 of white stake the base is 50,000
How can one edit the scaling code to reach 25,000 ante 8 base on a custom stake
Like the opposite of green stake basically, seeing as it's 100,000 on green stake
Why does it have to be negative tho
Like
Just change starting size of jokers area instead of doing that?
Probably by hooking this function and setting G.GAME.modifiers.scaling somewhere
then it can get another edition
which... is a benefit..
😱
idk
probably just most challenges in vanilla use negative instead of adding a joker slot
yes this exactly
I don't know a lot about changing joker slots honestly cause im dumb
so I just use negative joker instead since I recall some challenge decks doing that
but come to think of it it probably isn't even that hard
since black deck and painted deck already change deck size
I mean joker size
yeah its like some value in G.GAME.starting_params you can modify for decks
i forget what its called but probably just joker_slots
local j = SMODS.add_card{key = "j_joker", edition = "e_negative"}
--You don't need to do allat. Also, why tf is your joker key "j_oops_all_6s"??????
visually speaking tho it just looks better cause it's easier to know you have 5 slots besides the dice
oh yeah I fixed that
i was wondering why the game kept crashing so I checked the internal name and realized I made a silly mistake
add_joker is diabolical
no add is my name
oh okay
actually I'm not gonna lie im using a lot of tutorials since I'm bad at lua
so idk if that add was referring to my name or if its something to do with the actual code I don't remember what I was typing ngl
im a c# kind of person
earlier my entire computer crashed because I accidentally spawned an infinite amount of tung tung tung sahur jokers
amazing
triple j
say I'm thinking of making a really annoying challenge deck where your jokers are always face down
how does the Amber acorn do it
Also why are you checking if card.set_ability exists
It's not stopping anything but I'm just kinda confused
ur right
I keep forgetting this lua and not java or c++
dude wtf a giant light just flashed out my window
wtf was that
That was me sorry
the entire sky turned white for a second
new joker white joker
wait nevermind
wait I just got an awesome idea
I think Jimbo is already
grayscale joker +0.5 mult for every non enhanced card in deck
great earlygame
imma program that when I wake up tomorrow and after school
I don't think fractional mult is recommended tho
+1 mult for every 2 non enhanced
should i start modding tbh
CRAP
I ACCIDENTALLY REPLACED THE LUAS FOR MY CONSUMABLES WITH OLDER VERSIONS OF THEM
im gonna try and see if a file recovery can do anything
PLEASE I DONT WANNA RECODE VOID AGAIN
did you not use github
-# i forgot to install it
tfym install it
smth was buggy with it so i had to uninstall and was gonna reinstall but forgot

but yeah i may be royally cooked
ughhh
welp time to figure out the magic i did for void to work
hi is there a way i can change the main menu card?
i havent uploaded my mod to github yet but thanks for the reminder that the latest backup i have is a little outdated
Its not even that difficult to do idk why people dont do it
because if it is available on github that means i released it
and i dont think i have enough content yet
how would i generate a card of the same type that a specific booster pack generates?
calling the booster's create_card is the easiest way
although modded boosters don't necessarily have a type
nor do vanilla under some circumstances
if this is in context.skipping_booster(), would i do context.booster.create_card()?
nvm
ok
How would I slowly increse the music volume by 1 without bricking the game nor having it be instant in a single frame?
I know that I need to use G.SETTINGS.SOUND.music_volume
Probably set such in events?
How do Events work again?
Thank you :3
yeah no i have no idea how to even redo MIRROR bro im fucked
Someone remembers how to change the color of this red border in packs?
im trying to make a tag that makes the current voucher in the shop free, but it doesnt do anything when it triggers
?
i would need more than ? to determine what i need to elaborate on here
i dont know how to do that
local old_set_cost = Card.set_cost
function Card:set_cost()
old_set_cost(self)
-- It's recommended to use a unique field in order to not interfere with Coupon Tag
if self.ability.set == 'Voucher' and self.ability.voucher_couponed then self.cost = 0 end
end
ty
missing self
in the call
ah
Figured it out, forgot the ease_colour func
Is there any way I can see my cards with the shaders without having to port them to the game
Yea debugplus has a watcher func
I don't remember the exact syntax, maybe it's specified in the doc
"without porting them to the game" but yea debugplus have watch shader <path_to_file>
Where path looks like Mods/YourMod/shader.fs or whetever file is located
im trying to get a card to turn selected cards into a random face card but i cant get it to work
fixed it
how do i exclude an object type when creating a card? trying to create a random joker while excluding jokers in a specific pool
I worded this wrong, I meant see my custom card with the balatro shaders
it's not really possible with the api afaik, you would need to poll it yourself or make an objecttype/attribute for the other jokers
You can add a filter function to the poll
oh yeah
That would let you check for the excluded stuff and remove them
what would this look like? or at least where can i find documentation on it
I don’t recall actually using it in code though so I don’t have an example
filter = function(pool)
local all_unavailable = true
for _, v in ipairs(pool) do
if not G.P_CENTERS[v.key] or (G.P_CENTERS[v.key].pools or {}).objecttypekey then
v.key = "UNAVAILABLE"
else
all_unavailable = false
end
end
if all_unavailable then
pool[#pool+1] = {key = 'j_joker', type = "Joker"}
end
return pool
end
much appreciated goat
cause it's not downloading it, it's compiling it from source
hm
I have a lovely-patch (position -> "at") that has the pattern if score == 'defeated_by' then, but I also need to replace elseif score...
How would I go about doing that (without copy pasting the entire patch with the slight pattern difference)? ^w^
copy paste the entire patch with the slight pattern difference
afaik a patch can only have 1 target, so if you need the same payload on 2 different targets you need to do 2 patches
you can have a regex patch
i dont think theres a problem with copypasting the patch tho
ah yeah there's regex, but regex is annoyinh
I was just hoping that there might've been a, uh, prettier way than copy pasting it 
regex is the prettier way
-# And also not regexing it since it's not the fastest x3
But I guess I'll regex it then owo'
and i assume you'd want to replace a if by a if and a elseif by a elseif, which uh idk if you can do conditional payloads like that lol
If it's an if it was unpatched, if it's an elseif another mod (Wormhole) has already patched it owo
i think wormhole should be deleted
yeah but then if it's an if you need to replace it by an if, and an elseif by an elseif
jokers aside personally i dont like changing syntax when i patch, i try to make it respect the original to not break other mods
i love my balatro minded autocorrect
Yeah, I usually\¹ do the same.. In this case I just bite the bullet to stay compatible with Wormhole... It's my own fault¹ really lol x3
-# ¹ because I made the stupid decision to ignore this rule for wormhole o3o
nah, it didnt say jimbos aside
0/10 autocorrect
couldn't you have also used a wildcard?
actually probably not because the payload is also different
which only isn't a problem when using regex :drool:
yo if i have a retexturing of all four suits how would i go about using that sheet for deckskins
i'm having people getting vanilla jokers they unlocked, relocked when installing my mod
i don't understand how this can happen since there's nothing i'm doing to change that
Nope you're back, not seen you in a while
i've been taking a break from working on my mod after i finally released the new update a few days ago
that's good decision
the only thing i can think of that could cause people to have their vanilla jokers being relocked is that i'm making new tables in the profile
what type of tables
this is called at the end of both a Game:main_menu hook & a Game:load_profile hook, after the original function call
this is the only thing i could think of that's causing people's jokers to relock
doesn't look like you touch any of the actual save data here
i don't touch it anywhere. hence my confusion
this is the closest it gets
i've looked over my entire codebase, looked through my patches, nothing should be causing that to happen
i may be asking a dumb question (mainly cause idk) but
is there any way to track the last destroyed joker cause im trying to detect what joker was destroyed so i can spawn something else in its place
use your mod's global calculate function to save the key of that joker during context.joker_type_destroyed
just to make sure before i explain, you need to keep track of what the last joker destroyed was right
yes
so the reason i need to keep track of it is to see what rarity was destroyed so i can replace it with a random joker of higher rarity
im trying to detect what joker was destroyed so i can spawn something else in its place
this doesn't sound like you actually need to keep track of it
that's why i asked again lol
what effect does this
the joker's? another joker?
its a consumable
i should've prolly mentioned that too
basically how its set up rn is
select joker > destroy it > place new joker of higher rarity
you'd think that
i very much would
but when i try that it just
😭
doesnt work?
just save its rarity to a local variable before(!) destroying it
oh ok
obviously once you've destroyed it, it's gone
yeye
-# also just so you know, "doesn't work" isn't an adequate error description 100% of the time
welp time to stare at more words
mb!
i mean it crashes when it tries to locate the joker
or identify it rather
i would recommend taking a read at this too
https://xyproblem.info/
ok ill describe it as best i can cause i only have the current code which works on a technicallity (it just checks the selected joker's rarity, spawns a joker, then dissolves it)
(but that causes issues since if the joker slots are full it just doesn't spawn the replacement joker)
when you destroy a joker it does it in an event, which basically means it doesn't happen immediately and it's still in the joker slots until just after
the proper way to solve this part is to also create the other card in an event
(im assuming you're using start_dissolve from your wording but I'd recommend SMODS.destroy_cards)
alright, gotcha
how can i make the sell "tab" align with the joker? do i make a new atlas with different dimensions for it or do i do something else entieraly, like the wee joker to the right
Move it to the leftmost side of the sprite and put pixel_size = {w = widthinpixels} in your joker definition?
bump
how do i make this work (supposed to gain 8 chips if hand doesnt contain enhanced cards and reset the chips if it does)
config = {extra = {chips = 8, cchips = 0, cantrigger = true} },
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra.chips, center.ability.extra.cchips, center.ability.extra.cantrigger}}
end,
calculate = function(self,card,context)
if context.other_card and context.cardarea == G.play and SMODS.get_enhancements(context.other_card, false) ~= nil then
card.ability.extra.cantrigger = false
end
if context.joker_main then
if card.ability.extra.cantrigger == true then
card.ability.extra.cchips = card.ability.extra.cchips + card.ability.extra.chips
else
card.ability.extra.cchips = 0
end
return {
chips = card.ability.extra.cchips
}
end
if context.after then
card.ability.extra.cantrigger = true
end
this is config to calculate part of the code
if context.before then
local passed = true
for k, v in pairs(context.full_hand) do
if next(SMODS.get_enhancements(v)) then
passed = false
end
end
if passed then
SMODS.scale_card(card, {
ref_table = card.ability.extra,
ref_value = 'cchips',
scalar_value = 'chips',
no_message = true
})
return {message = localize('k_upgrade_ex'), colour = G.C.CHIPS}
else
card.ability.extra.cchips = 0
end
end
if context.joker_main then
return {chips = card.ability.extra.cchips}
end
is it normal for it to show up like this
works regardless though tysm <3
is there a simple way to detect a low-ace straight, taking into account shortcut etc? min size three if that matters
if ace and 2 or 3 are present
local straights = SMODS.PokerHandParts._straight.func(hand)
local passed = false
for k, v in pairs(straights) do
if #v >= 3 and v[1]:get_id() == 14 then
passed = true
end
end
```?
^ the above, but ofc you also need to hook SMODS.four_fingers to return 3 for the min length, and the straight doesn't get sorted by nominal, so you'd have to iterate over each straight's cards as well, instead of only checking v[1] for the Ace, plus you have to check that there isn't a King, Queen, Jack or 10, to make sure it is a low-ace straight.
SMODS.Back {
key = 'moodydeck',
atlas = 'deck',
pos = { x = 0, y = 0 },
-- unlocked = false,
calculate = function(self, back, context)
if context.setting_blind then -- and G.GAME.blind.boss
local raising_hand = pseudorandom_element(G.handlist, "Here's a little lesson in RNG.")
local falling_hand = pseudorandom_element(G.handlist, "This is going down in history.")
if not falling_hand == nil then
return {
level_up = -1,
level_up_hand = falling_hand
}
end
if not raising_hand == nil then
return {
level_up = 2,
level_up_hand = raising_hand
}
end
end
end,
}
Why isn't this working?
if context.setting_blind then
return {level_up = -1, level_up_hand = pseudorandom_element(G.handlist, 'Here\'s a little lesson in RNG.'), extra = {level_up = 2, level_up_hand = pseudorandom_element(G.handlist, 'This is going down in history.')}}
end
key = "bsod",
loc_txt = {
name = "Blue Screen",
text = "Crash the game if played hand is a {C:attention}Full House{} or {C:attention}Flush{}"
},
dollars = 13.9,
mult = 2.5,
atlas_table = 'blindsod',
pos = {y = 0},
boss = {min = 2, max = 6}
boss_colour = HEX("1270ae"),
press_play = function()
}```
I'm currently trying to make a blind that if any hand played is a Full House or Flush, it will crash the game
I'm not too sure how to do this
index a null value index a null value index a null value index a null value index a null value
calculate = function(self, blind, context)
if not blind.disabled then
if context.before and (context.scoring_name == 'Full House' or context.scoring_name == 'Flush') then
error('message')
end
end
end
ty!!
There is no extra in config, also I was the one who told you about getting a description as a string (#💻・modding-dev message)
how does ease_dollars work
It gives the player money and has an effect on the money counter.
math.max gets the highest number out of multiple numbers, math.min does the same but for the lowest number.
oh ok
thanks twinny
key = 'moneyprint',
loc_txt = {
name = "Yellowprint",
text = {
"Doubles money at end of the round",
"{C:inactive}(Max of {}{C:attention}#1#{}{C:inactive}){}",
}
},
atlas = 'moneyprint',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 8,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
config = { extra = { max = 1941131537 }, },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.max } }
end,
calculate = function(self, card, context)
if context.end_of_round then
G.E_MANAGER:add_event(Event({
func = function()
card:juice_up(0.3, 0.5)
ease_dollars(math.max(0, math.min(G.GAME.dollars, card.ability.extra.max)), true)
return true
end
}))
end
end
}```
error occurs when i hover over said joker
nvm but it doubles like 30 times
instead of just once
context.end_of_round and context.main_eval
is it possible to modify a vanilla poker hand?
forgot that was a thing lol myb
i also stole ownership of a joker card, would i be able to rearrange it in the collection to go to my jokers instead?
does anyone know why a modded enhancement would have card.ability as null for loc vars
ONLY when ur checking it before the run starts
in the collection
if (context.joker_type_destroyed or context.selling_card) and context.card.ability.set == 'Joker' and context.card ~= card then
if context.card.edition and context.card.edition.type == 'negative' then
if card.ability.extra.extra_slots_given < card.ability.extra.extra_slot_max then
G.jokers:change_size(1)
card.ability.extra.extra_slots_given = card.ability.extra.extra_slots_given + 1
end
end
end
if context.selling_self then
G.jokers:change_size(-card.ability.extra.extra_slots_given)
end
end```
i found an oversight in my code which is that this joker only resets the joker slots if it is sold, but not if it is destroyed. would adding if context.remove_from_deck be the better one to use?
bump
update: yes, yes it is
except not as a context
whats the formatting for money
like how if u wanna write xmult u would do "{X:mult,C:white}X67{} Mult"
whats th e one for money
Nevermind
67
Yuh
i'm getting an error saying that back.ability.extra.current_reroll_cost is a nil value despite me giving it a value in the config
ah ok
what's the dif between G.GAME.current_round.reroll_cost and G.GAME.round_resets.reroll_cost?
current_round is the current cost and round_resets is the base one iirc
so every shop starts at round_resets
howd ya do it
Who was a template I can use, I’m trying to make a mod that has more items in every category
As in art templates?
If so there’s a really good thread in #1456641762591510671 that has a lot of community made templates for stuff like jokers and tarots (and pretty much everything else too)
No, I have every art asset, I’m meaning code template for every item
I’ve seen some, but they have been separated and difficult to combine
if context.modify_shop_card then
if context.card:is_rarity("Legendary") then -- discount setting, only for legendaries and stacks with vouchers
G.GAME.discount_back_percent = G.GAME.discount_percent
G.GAME.discount_percent = G.GAME.discount_percent + card.ability.extra.discount
context.card:set_cost()
G.GAME.discount_percent = G.GAME.discount_back_percent -- necessary to prevent things from getting globally cheaper
end
end
Awsum thenks
npnp
This stake is trying to do +1 hand the same way vanilla blue stake does -1 discard but it's not working
G.GAME.starting_params.hands = G.GAME.starting_params.hands + 1
hey, been a while since i've modded anything balatro-related. how do i return current level of a select hand type?
nevermind, found it
how do i get context.mod_probability to work in enhancements?
wait i think i was making a mistake
separate from that
yea it works now i was being dumb
how do i get whether a joker effect is being retriggered? context.blueprint doesn't seem to be working
context.retrigger_joker
ty
I have this Joker, from which 90% of the code is "borrowed" from Cryptid's Oil Lamp, but it doesn't work as intended. (It is supposed to increase the values of the Joker to the right by 1.)
I'll work on using this later, thanks
how do i edit the name of a hand in this game
or make a mod to do so idk
i assume that's quite simple to do
i want to make "pair" say "pear"
make an smods mod with this localization file
return {
misc = {
poker_hands = {
Pair = "Pear",
}
}
}
tysm
Why does this shader not apply on floats, even though I set it to true?
key = "forgotten",
config = { odds = 60, changedOdds = false },
shader = "cstorm_forgottenShader",
in_shop = false,
weight = 2,
extra_cost = 0,
badge_colour = HEX("4B0082"),
disable_base_shader = true,
disable_shadow = true,
apply_to_float = true, --// FIXME: WHY IS IT NOT APPLYING TO FLOATS?! IT'S TRUE!
sound = { sound = "cstorm_forgotten1", vol = 0.7 },
--calculate stuff and so on```
All the shader does is change the transparency with a sine wave
+0 mult, -2 per round, insert $1 to add 5 mult
bit of a stupid question
how do you give jokers a "Use" thingy
i've seen many mods do it
also is there any way to change the background image(s) of the game while you're playing
i couldn't find any mods that do so
and i'd like to potentially make my own ones
You could look into the code of those mods. That way you have exactly their code an can analyze it and make it work for your own mod :3
Tangents does it, im not sure what the code is for that
wdym
Tangents is a mod https://discord.com/channels/1116389027176787968/1379136953307500645
Hey everyone, I am trying to make a boss blind that disables a Joker immediately after it triggers.
When putting the debuff function into context.post_trigger it works, but visually the Joker is debuffed immediately when the hand is played, instead of having it visually be disabled at the point where it triggers, meanwhile putting it into an event in context.post_trigger debuffs it at too late of a point. Any ideas?
you would need to hook or patch the debuff drawstep in smods to add a delay flag
honestly, it sounds like a good feature to add
gotcha thanks
Yo imagine being named Wakartuspen Borkus IV 😹😹😹😹😹
Is there a way to check if a playing card has a permanent bonus?
(card.ability.perma_bonus or 0) > 0
<@&1133519078540185692>
?softban 1326674881361870868
_aruathator_ was softbanned.
bam bam
ty
Bump
can that even be nil?
no idea, the docs imply that it can be
I don't think so but maybe I'm misremembering
im pretty sure it cant
the ui code for card descriptions has card.ability.perma_bonus > 0 and card.ability.perma_bonus or nil iirc
yeah it seems to not be
if it could be nil there would likely be constant crashijg
oh did you see i merged the localize docs
yep, ty
sry to bother but how do i do this exactly
idk lua and ive never made any mods before or anything
i dont rly understand :(
ik the file names and stuff but
idk the local thing or whatever
there's an empty mod example here https://github.com/Steamodded/examples/tree/master/Mods/BlankMod
you can just add a localization/en-us.lua with that code to it
what is localization tho
i cant see anything abt it on that site :/
it's just a folder where you add the translations https://github.com/Steamodded/smods/wiki/Localization
didnt you want to change the name of the hand?
yea
you need to change the english translation for that basically
oh
(well its not a translation but you know what i mean)
where do i put the localisation part then
i know absolutely nothing about lua sorry
localization/en-us.lua
you create it in that folder
yeah
does the lua file contain anything
the code i gave you
ohhh
i thought that was supposed to be in its own lua file
im sorry
does it need a regular lua file or no
and does the metadata,json thing need to direct it towards the en-us.lua file
it's just a text file with the .lua extension
no, redirect it to an empty file
i think
i never made a localization only mod lol
I'd think there's already a main file
but yeah it'd be empty if you just do localization strings
ok thank you
yaaay ty
im gonna make a cute icon for it in the modloader
for the 1x and 2x textures, when are 1x textures used?
is it if ur playing on 720p or whatever
cuz i see a lot of things focusing on 2x textures, or just only having 2x textures
if you have pixel smoothing off
you need both because it will crash if the player has the other pixel smoothing option
Bump
o ok
i made a 1x and 2x icon for the mod
how do i get it to show up
i have an assets folder with a 1x and 2x folder inside, and both are saved as "icon.png"
like the other mods that have it
ive looked inside of the other mods but cant rly find anything indicating how to do it
you need to make an atlas for it
whats that
in the main file?
sure
ok ty
how do i do it for a 64px and 32px icon
cuz i made two
and theyre in the 1x and 2x folder in the assets folder
do i need to put 32 still
yes
well
you put whatever the size of your icon at x1 is
but in theory it should be 32 by 32
oh
well yea the 64x64 icon has styalized 2x2 pixels
so the base one is 32
tysm
yaaay it works tysm
i know maelmc already gave a solution but the new better solution is to have "icon_path": "icon.png" in the json, you dont need an atlas
this will also show the icon when the mod is unloaded
oh ok ty sorry
ik what i did is basic and pointless and meaningless but i kinda want to learn some lua and make cool mods cuz pixel art and card game stuff is rly cool
and i heard that lua is relatively easy compared to other programming languages
yeah i think its a great starting language
it's not a coding tutorial but i really recommend my guide to start (biased)
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-start-making-balatro-mods
wait you can do that?????
was this a recent addition
i still have my modicon done with an atlas
bump
-- Love Letter
SMODS.Joker {
key = "loveletter",
config = { extra = {} },
pos = { x = 7, y = 3 },
cost = 7,
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
calculate = function(self, card, context)
if G.GAME.current_round.hands_left == 0 then
local eval = function() return context.end_of_round and not G.RESET_JIGGLES end
juice_card_until(card, eval, true)
end
if context.before and #context.full_hand == 1 and G.GAME.current_round.hands_left == 0 then
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
context.other_card:set_edition("e_polychrome", true)
card:juice_up(0.3, 0.5)
return true
end
}))
end
end
}```
its returning with the "other_card is a nil value" error
which is making me think i need to instead create some sort of variable to store the [1] card, and have the polycrhome edition apply to the [1] card
how do i do that
im guessing i use G.playing.card ?
oh or maybe context.full_hand[1] !!!
lemme try that
ok yeah that works
though ill have to figure out how to juice it up on the final hand
yeah this thing isnt juicing 😭
calculate = function(self, card, context)
if G.GAME.current_round.hands_left == 0 then
local eval = function() return G.GAME.current_round.hands_left == 1 and not G.RESET_JIGGLES end
juice_card_until(card, eval, true)
end
i want it to juice on the final hand
ill just do an active message instead
oops LMAO
ah well ill just remove it
people should be paying attention to that stuff anyways
bump
-- Graveyard
SMODS.Joker {
key = "graveyardshift",
config = { extra = { xmult = 3, faces = 5, condition = false } },
pos = { x = 9, y = 3 },
cost = 7,
rarity = 2,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, card.ability.extra.faces, card.ability.extra.condition } }
end,
calculate = function(self, card, context)
if context.discard and context.other_card == context.full_hand[#context.full_hand] then
local face_cards = 0
for _, discarded_card in ipairs(context.full_hand) do
if discarded_card:is_face() then face_cards = face_cards + 1 end
end
if face_cards >= card.ability.extra.faces then
card.ability.extra.condition = true
return {
message = localize { 'k_active_ex' },
colour = G.C.FILTER,
delay = 0.4
}
end
end
if context.joker_main and card.ability.extra.condition == true then
return {
xmult = card.ability.extra.xmult
}
end
if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
card.ability.extra.condition = false
return {
message = localize('k_reset'),
colour = G.C.FILTER,
delay = 0.4
}
end
end
}
``` small issue, this doesnt return with "active" when the condition of five discarded face cards is true
I don't know if this is something from my mod or from Smods or Balatro =/
SMODS.Joker {
key = 'jimbosinferno',
atlas = 'StarterPackJokers',
pos = { x = 7, y = 4 },
rarity = 2,
blueprint_compat = true,
cost = 2,
discovered = true,
config = { extra = { odds = 3, mult = 10 } },
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_stpk_jimbosinferno')
return { vars = { numerator, denominator, card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card:is_suit("Hearts") and
SMODS.pseudorandom_probability(card, 'j_stpk_jimbosinferno', 1, card.ability.extra.odds) then
return {
xmult = card.ability.extra.Xmult
}
end
end,
}```
trying to make it so that it has a 1/3 chance to DESTROY a played heart card when applying the Mult
like Lusty Joker + Bloodstone, but it destroys them instead of xmult
so it always gives xmult?
yes; but it has a chance to destroy the card
if SMODS.pseudorandom_probability(card, 'j_stpk_jimbosinferno', 1, card.ability.extra.odds) then SMODS.destroy_cards(context.other_card) end
and remove the pseudorandom check from the if you have
will it still give mult?
bump
calculate = function(self, card, context)
if context.joker_main then
return {
xmult = card.ability.extra.xmult
}
end
if context.individual and context.cardarea == G.play and SMODS.pseudorandom_probability(card, 'j_hatch_poisonivy', 1, card.ability.extra.odds) then
G.E_MANAGER:add_event(Event({ -- Juice Up Animation
trigger = 'after',
delay = 0.4,
func = function()
assert(SMODS.modify_rank(context.other_card, -1))
card:juice_up(0.3, 0.5)
return true
end
}))
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain -- Mult Manipulation
return { -- Localisation
message = localize('k_upgrade_ex'),
colour = G.C.FILTER,
delay = 0.4
}
end
end
}
joker works it just doesnt juice oh whats the point 😭
whether i do card:juice_up or context.other_card:juice_up it just doesnt work
istg if its "scored_card" ill actually lose it
it doesnt work
im killing myself
gang how are cards drawn different in the deck viewer than in game
deathed cards with flux also dont carry over the new suit
im currently using set_sprites
bump
someone playing my mod got this crash after switching profile, then opening mod settings and closing them - the crash was specifically on closing the mod settings.
i can't replicate this
yo im trying to check the cost of things when i buy them and im using context.card.config.center.cost, and that works fine, but it doesnt take into account discounts or price increases
context.card.cost
Hey, unless if I'm illiterate and haven't read the API properly (which is extremely possible) how do i:
- How do i give each joker their own pic using their own pic properly?
- how do i do the special font things in the text box?
I've only started programming literally 2 hours ago, I got the joker to exist but idk how to stylize it
hey, ive got a custom deck that starts with 6 cards. all of them are the same custom suit and have each have their own custom rank, and im using a hooked add_to_pool() to filter everything else out. I'm currently trying to add 3 more of each rank to the deck and i can using the apply func on the deck, however im not too fond of how the animation plays adding them after spawning in, is there a way to add them before the run starts or just remove that animation for the add_card()? If not, no worries, i kinda realize this is a specific thing lol
ohhhh they are all stitched together on a grid
oh does that remove the other suits/ranks from the pool too? I'm intentionally doing add_to_pool to remove the base cards from packs and such too
what no don't listen to me
oh i think someone deleted their message ngl
did you figure it out btw?
lol
the thing with how to get assets into one thing? Yeah
I didn't fully know you were supposed to stich them together in one sheet
you dont btw
you just have to make them all seperate atlases if you dont stitch them
i think it is slightly better on the computer tho if you do
I would rather try the stitching way because having each picture be it's own thing deeply troubles me
yeah no you def should, i am def not an expert lol, and it seems thats how it was intended in the first place
whats your current code
deck, hook, or the cards?
deck
key = "PictureDeck",
atlas = 'LuigiPoker', pos = { x = 0, y = 0 },
unlocked = true,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for i = 1, 3 do
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Star",
suit = "Milk_Picture",
}
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Mario",
suit = "Milk_Picture",
}
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Luigi",
suit = "Milk_Picture",
}
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Flower",
suit = "Milk_Picture",
}
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Mushroom",
suit = "Milk_Picture",
}
SMODS.add_card{
set = "Base",
area = G.deck,
key_append = "modprefix_append",
rank = "Milk_Cloud",
suit = "Milk_Picture",
}
end
G.GAME.starting_deck_size = #G.playing_cards
return true
end
}))
end,
}```
im sure there's a better way to do that in terms of condensing, but it was lowk the only way i found that wouldnt return an error
Probably another for loop.
ooh yeah actually
try this
G.E_MANAGER:add_event(Event({
blocking = false,
blockable = false,
func = function()
if not G.deck then return end
for i = 1, 3 do
-- your add cards code
end
G.GAME.starting_deck_size = #G.playing_cards
return true
end
}))
bump
aight bet, gimme one second
OMG yeah, thats totally it. Tysm!!
in the code of a joker, i'm trying to grab a joker's name. i have now learned that retrieve_joker_name does not work for my purposes lol
local text = retrieve_joker_name(G.jokers.cards[i])
what's the correct way to do that?
you could do
localize({ type = 'name_text', set = "Joker", key = G.jokers.cards[i].config.center.key })
to get their localised name
would the variable set be the name of the joker then?
no, if you do local text = localize({ type = 'name_text', set = "Joker", key = G.jokers.cards[i].config.center.key }) , the variable text will be the jokers name
ah ok
got it to work, thanks!!
so question, how do i change the values of values after they have been triggered?
Why doesn't this joker do anything
what should it do
this will never be true
it should be v.key
this will also not be true
because v is the id
i would recommend giving the variables better names than k and v to avoid confusion about this stuff
yo guys whats that mod that when u drag ur cursor over the cards it selects it
btw what's the difference between k and v there
k is the key v is the value
table[k] = v
in this case G.P_CENTER_POOLS.Joker is integer indexed and holds center prototypes so it's like G.P_CENTER_POOLS.Joker[1] = { key = "j_joker", .......... }
how do i put an image into the description of a joker
SMODS.Atlas {
key = 'hector',
path = 'hector.png',
px = 71,
py = 95
}
SMODS.Joker {
key = 'hector',
loc_txt = {
name = "Jimbo Salamanca",
text = {
"Plays a {C:gold}bell sound{} every {C:attention}click{}",
"If {C:attention}CPS{} is {C:attention}10+{}, {X:default,C:red}explode{}",
"{C:inactive}({}{X:default,C:red}Explode:{} {C:inactive}destroy self and adjacent {}{C:attention}Jokers,{} {C:red}ignore{}}{C:enhanced}Eternal{}{C:inactive}){}"
}
},
atlas = 'hector',
pos = { x = 0, y = 0 },
rarity = '2',
cost = 4,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
}```
??? theres no pool stuff here, am i wrong?
does context.card_added trigger if the joker that has it is bought?
dont think so
rarity should be a number
not a string
unless you made a rarity with key "2"
is there a context that checks when the joker itself is bought?
buying_self
i js realized it was in quotes 😭
ty!
if context.card_added or context.buying_self then
will this work? i can't test it cause debug log is weird
or should i have them in two seperate if statements?
the syntax is correct
i cant tell you if it will work for your effect because idk the context
fair enough
G.E_MANAGER:add_event(Event({
func = function()
for _, jokers in ipairs(G.jokers.cards) do
if jokers.config.center.eternal_compat == true then
jokers:add_sticker("eternal", true)
end
end
return true
end,
}))
end```
looks fine
and one more thing
how do i make it so something happens every time the player clicks
anywhere on the screen
nvm i think i got it
ah nvm
how to do 😭
hook Controller:queue_L_cursor_press
i used a custom context to trigger it, but it wont do what it's suppsoed to.
lcpref(self, x, y)
if G and G.jokers and G.jokers.cards and not G.SETTINGS.paused then
SMODS.calculate_context({ sink_press = true })
end
end
i put this in a return at the end of the jokers.lua
and this
if context.sink_press then
G.E_MANAGER:add_event(Event({
func = function()
play_sound('sink_bell')
return true
end
}))
end
end```
is the calculate?
that looks correct to me
i also defined the SMODS.sound already
if you add a print to the context does it work
yes
no im not seeing it print
can i see the whole file
calculate code for this is now
calculate = function(self, card, context)
if context.ante_change and context.ante_end then
local modspool = {}
local pooltocollect = {}
local validmodcount = 0
for k, v in pairs(G.P_CENTER_POOLS.Joker) do
if v.mod and not next(SMODS.find_card(v.key)) then
local found = false
for k2, v2 in pairs(modspool) do
if v2 == v.mod.id then
found = true
end
end
if found == false then
table.insert(modspool, v.mod.id)
validmodcount = validmodcount + 1
end
end
end
-- Get a random joker from each mod
for k2, v2 in pairs(modspool) do
local thismodlist = {}
local thismodjkrcount = 0
for i, d in pairs(G.P_CENTER_POOLS.Joker) do
if d.mod.id == v2 and not next(SMODS.find_card(d.key)) then
table.insert(thismodlist, d.key)
thismodjkrcount = thismodjkrcount + 1
end
end
if thismodjkrcount > 0 then
local randed_joker_for_this_mod = pseudorandom_element(thismodlist,
"The Shattering Circle, or: A Charade of Shadeless Ones and Zeroes Rearranged ad Nihilum" ..
G.GAME.round_resets.ante)
SMODS.add_card { key = randed_joker_for_this_mod, edition = 'e_negative' }
end
end
end
end,
andit's giving the error attatched
which one is line 120
If d.mod.id == v2 iirc
ah yeah not all jokers have a mod field, vanilla ones dont
you need to check if it exists first
if context.card_added or context.joker_type_destroyed or context.selling_card then
the context.selling_card seems to be the only context here that isn't triggering. i'll sell another joker and this joker won't trigger. am i misunderstanding how this context is used?
no it should work
The funnier way to fix this would be to find a way to remove every vanilla joker, but it probably just needs to become if d.mod and d.mod.id == v2
i mean the way to remove every vanilla joker would be to check for d.original_mod anyway lol
how can i make symbols that arent typically supported by balatro (such as these "【】") work in joker descriptions and such?
You would have to use a font that supports them.
i see. i thought it was a balatro limitation, whats the default balatro font?
m6x11plus
k
do i need to provide files with new fonts, and how do i do that?\
or is there a documentation for it i can read
Aure's cat
Hey does anyone have that one joker template aseprite file? I'm doing some joker art and I had it saved but I changed pc lol
is there a context check for a probablity triggering?
fuuck
SMODS.Joker{ --god what am i even fucking doing anymore
key = "payphone",
config = {
extra = {
payphonemult = 0,
payphonemult_plus = 5,
payphonemult_minus = 2,
payphonemult_cost = 1
}
},
loc_txt = {
['name'] = 'Payphone',
['text'] = {
[1] = '{C:mult}+#1# Mult{}, decreases by {C:attention}#2#{} every round',
[2] = 'Pay {C:money}$#3#{}.'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
cost = 5,
rarity = 2,
pos = { x = 5, y = 1 },
atlas = 'CustomJokers',
cost = 6,
unlocked = true,
discovered = false,
blueprint_compat = false,
eternal_compat = true,
loc_vars = function(self, card, context)
return {vars = (card.ability.extra.payphonemult, card.ability.extra.payphonemult_plus, card.ability.extra.payphonemult_minus, card.ability.extra.payphonemult_cost )},
end,
calculate = function(self, card, context)
if context.joker_main then
return = {
mult = card.ability.extra.payphonemult
}
if context.blind_defeated then
return{
card.ability.extra.payphonemult = card.ability.extra.payphonemult - card.ability.extra.payphonemult_minus
}
end
end
can_use = function(self, card)
return to_big(G.GAME.dollars) >= to_big(card.ability.extra.payphonemult_cost)
end
use = function(self, card)
G.GAME.dollars = G.GAME.dollars - card.ability.extra.payphonemult_cost
card.ability.extra.payphonemult = card.ability.extra.payphonemult + card.ability.extra.payphonemult_plus
end
}```
the calculate function is indented ?
missing a comma
thinking I might want to mod wurt into balatro
she's the best joker in Don't Starve balatro so now I wanna add her albeit nerfed
as stupid as it sounds, is there a way to determine is center can be used to create card?
Because, Aiko uses extension of SMODS.Center to create some dummy descriptions, and it's a problem
i dont think so, how do you handle editions or decks currently
I dont handle decks yet, for editions I have a check
yeah i can't think of a way honestly
I can create a base card, then set ability of center, if it crashes, discard this
there's only way I see so far
i think that makes the modst sense
is jokerexists() a thing
of course not
SMODS.find_card?
oh.. alright then
i think jokerexists is a yahimod thing
ohhh... what can i do to make a version of it
why would you want to
to forcefully change music everytime a blind of any kind is selected and you have a card based off lancer deltarune
ok use SMODS.find_card
look at this!
yes
dude.. sometimes my jokers are a bit blurry
if next(SMODS.find_card("j_key")) then
lmao
im planning to do something similar for the keyword glossary in my mod
find card works but i want it to be so that the card is in hand then do thing
hm...
👀
what do you mean
-# i swear i feel like i need to hand holded and i dont like that
ill fix it l8r
ui confusing me to all hell, how do i get whether a toggle is activated or not? trying to make settings to enable/disable groups of jokers
ref_table[ref_value] will be updated accordingly
ty lifesaver
balatro is screaming at me. it says theres something in line 31
wtf did i do wrong 😭
another day, another hatchet coding sess
the vars should be in {} not ()
idk i can't see your code
make sure all the fields in your table have commas after them, would be my first guess
it's in the replied msg
https://github.com/Naruyoko/ExpantaNum.js theoretically is this implementable in talisman (or I guess amulet now)
amulet is literally just talisman but it handles arithmetic between bugnum and normal numbers
also javascript is a different language to lua
this was decided against by talisman devs initially to spare mathisfun (i think) from needing to port this to lua
and theres also like no point tbh
how does the draw pile work? when you select a blind, does it determine the order of cards in your draw pile all ahead of time? and if so, how can you access and read those card values? (for example, if i wanted to grab the card 5th from the top of the draw pile?)
it shuffles ahead of time and you can get them by indexing G.deck.cards
ahh ok cool
G.deck.cards[5] would be the 5th from the top, for example
G.deck.cards[#G.deck.cards-4] since it draws from the bottom
so when the game draws new card after a hand or discard has been used, i assume it just counts how many cards need to be drawn and then add that number from the bottom of the deck to the hand
is there a way to edit which cards the game draws when you need to draw? like could you have a specification that it will draw the correct # of cards EXCEPT if one of those cards is a certain rank and then skip that one?
you can just reorder G.deck.cards, you can use context.drawing_cards for the correct timing
i was looking at that context, seems interesting
https://github.com/dlsdl/metanum oh look it GETS BIGGER SOMEHOW f_ε₀(9e15)

