#💻・modding-dev
1 messages · Page 597 of 1
Can anyone help me with this?
Check for context.starting_shop, then look for .cards of G.shop_jokers, G.shop_booster and G.shop_vouchers and do what you want.
in theory we could load an smods stub first thing when we get access to lua state (so probably before boot.lua) that can do validation work and whatnot
but you'll be running in an environment with basically 0 love functions
Do tooltips for stickers not work? This is what I have right now
I think tooltips only work for centers and stickers are not centers
Ugh that's annoying
Is there another way to do it without an annoying amount of effort?
Probably not
Anyone know how to make config menus that actually work?
I'm trying to make a settings menu in my mod so you can enable/disable certain jokers but for some reason it won't save.
Here's the github for my mod so you guys can see where I went wrong
(I copied UTDR's system but apparently they have the same issue
)
I've been stuck with displaying values. I cannot get the joker to display freindyMult for some reason. I looked at a tutorial, and that has not fixed the problem.
the #2# should be #1#
Does the config table start at 0?
I'll try
It worked, thx
does anyone know how no_ranks works? i have this under my challenge description but it's not doing anything
deck = {
type = 'Challenge Deck',
no_ranks = { r = '7' }
},
wait
no it's not no_ranks = { {r = '7'} } either
oh
it's no_ranks = { ['7'] = true }
wait no its not what
You need to put the no_ranks table in deck = {}
Huh this is pretty weird
gn!
Can you disable Steamodded with a .lovelyignore file?
yeah
anyone else have any ideas
Ok so- For some reason this joker is supposed to only activate when cards are scored, but it activates at the end of the played hand for some reason, anyone knows why?
context.joker_main is what the context is after cards are scored and jokers start triggering
Oh, so what would be the correct way then? cause im honestly confused
..you already have it there as far as i can tell, context.individual
i figured this out btw
it was that i was putting it under the restrictions table when its its own table
ok so, i fixed an issue and got another-
from what i tested, it stopped activating at the end, but now it activates on ANY card played (only supposed to activate on kings/queens)
oki, i'll try to see if i can fix it
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and (context.other_card:get_id() == 12 or context.other_card:get_id() == 13) then
return {
((context.other_card:get_id() == 12 and e_mult) or e_chips) = card.ability.extra.power
colour = ((context.other_card:get_id() == 12 and G.C.MULT) or G.C.CHIPS)
card = card
}
end
end
try that
alright
did it work?
Just a second, im doing some things real quick-
ITS WORKING
🙏
nice
Thank you so much
no_ranks is formatted like this I think
is this written correctly to perform the following mechanic?
i mean. press start game and check yourself
i cant
damn
im not letting that stop me though
do u have full control of the chromebook
i think u can do some shit with linux
but apparently my CPU is like one of the ones that cant
yeah
and like
I own Balatro on here too
I use the mobile version
with my mouse
ah
it's very annoying
yeah theres no convenient solution for modding the mobile executable
i'm well aware brah,
from what i can tell this looks correct
formatting is a little wonky
oh also u should probably put the segment that increases the joker's xmult inside an if not context.blueprint to prevent blueprint doing an extra scale
oh yeah u right
so like this?
ur missing an end immediately after the blueprint check
does anyone know what investment tag is called in the files
tag_investment
ty
does anyone know how to add a new stat for the run and a box to the ui that displays it (like for money, ante, etc.)
ive looked at the docs but i think im too stupid to figure it out 😭
you need to use lovely patches afaik
like this?
yeah
actually in general how familiar are u with modding balatro
in particular u need to hook functions and save data to G.GAME
cuz this task also involves making balatro UI
ive added some jokers and tarots and all the easy stuff (before jokerforge so i at least know how to do that myself) but that's it
i dont wanna like
yeah i would suggest practicing UI for a bit by making a fancier mod config page before adding to the scoring ui
ok
because UI can be really scary if u dont know how it works
the config tab is the least complex spot to start practicing ui
i can redirect u to my mod which has some example code for this though if u really want to get this done and can handle undocunented code
look at thaumaturgy.lua, hooks.lua and the singular toml file if u do decide to look at it
ok ty
fortunately if u can add to the config page u can pretty much do whatever u want with the hand/discard ui
and etc.
can someone help me with something extremely minor? I basically just need to know how to do one specific thing in lua
what do u need to do
basically I need to know what lines I need to put into my NameOfMod.lua file in order to make my localization/en_us.lua, uh, activate? I don't know how to say it properly
ummm
there shouldnt be any extra lines of necessary code
is ur mod loading?
also check to see if ur localization file is set up correctly
lemme double-check, hold on
hm.
okay. disregard me. apparently it just works
I had to do extra stuff to make my sprite edits work but the text edit works immediately apparently! thank you for your help and for your patience 🤝
np
should i expect this to work or no
there's a saying to try it and see
https://github.com/nh6574/VanillaRemade/blob/d6fc351c28854b8b249289427df88f3a1b42790f/src/jokers.lua#L3120 you can see how mr bones does this (if you're trying to aim for that)
i really hope i stop having to explain this
they dont make steammodded for chromebooks
or steam, for that matter
then what are you trying to do
make a mod
im not just gonna let my hopes and dreams die because i dont have the tools
also im pretty sure you can enable linux on a chromebook
unless
i've tried.
i've tried so many things
i have spent hours on end researching
to try and find anything
but the CPU in this god forsaken hunk of junk isn't compatible with anything.
Hey I’m making a card that deducts chips if certain cards are scored and I’m working on a failsafe to ensure chip count never goes below 0. For some reason, hand_chips doesn’t update after the card gives its score.
Any way the joker could get the amount of chips granted by the card so that can be taken into account?
Code?
trying to make a card that adds .25 of first scoring face card's chips to xMult, this definitely looks like it wouldn't work but here's what I have so far
anything I'd need to do for this to work properly?
how do i make something display as xmult in the descripotion?
card.base.nominal does not exist in the config, just make Xmult_mod 0.25 and then multiply that by context.scoring_hand[i].base.nominal in the scaling
Somehow, my booster pack can't be spawned in, due to it not having an area to spawn in, for some reason.
eval SMODS.add_booster_to_shop(<p_modprefix_key>)
add that to the code or?
run with debugplus
Forgive me if this is a stupid question 🥹
you mean like displaying the number or the text formatting?
not working either, somehow
are you in the shop
no
consider adding a booster to the shop whilst in the shop
displaying the number
Like (currentlt 1x)
use (loc_vars)[https://github.com/Steamodded/smods/wiki/Localization#loc_vars]
okay that link formatting doesnt work on discord ig whatever
still not working
did you get the key right
thanks
lemme double checl
I'm seeing how it works with steel Joker I just don't know how to display it as xmult
Iirc colored text used {C:something} have I been doing it wrong the whole time 😭
yes
okay so you do mean the formatting and not the number
want me to show the pack code?
then its {X:mult,C:white}
yes
Oh tysm I'm stupid 🥀
and also whatever debugplus is saying when you run the command
key = "Elements_of_the_Round_Table",
path = "1357924680.png",
px = 57,
py = 93
}
SMODS.Booster {
key = "mendeleev",
weight = 0.25,
kind = 'xiferp_Element',
cost = 8,
pos = { x = 0, y = 0 },
config = { extra = 8, choose = 2 },
group_key = "k_element_pack",
loc_vars = function(self, info_queue, card)
local cfg = (card and card.ability) or self.config
return {
vars = { cfg.choose, cfg.extra },
}
end,
ease_background_colour = function(self)
ease_background_colour_blind(G.STATES.STANDARD_PACK)
end,
particles = function(self)
G.booster_pack_sparkles = Particles(1, 1, 0, 0, {
timer = 0.015,
scale = 0.3,
initialize = true,
lifespan = 3,
speed = 0.2,
padding = -1,
attach = G.ROOM_ATTACH,
colours = { G.C.BLACK, G.C.RED },
fill = true
})
G.booster_pack_sparkles.fade_alpha = 1
G.booster_pack_sparkles:fade(1, 0)
end,
create_card = function(self, card, i)
return {
set = "Element Card",
area = G.pack_cards,
skip_materialize = true,
soulable = true,
key_append = "xiferp_ele"
}
end,
}```
how do you add extra info to a mod for crashes like how talisman adds the current bignum setting
unexpected symbol by ]
thats just that you wrote the command wrong
oh. should I have left the <>?
and I did the rest right
steal talisman's code for it
ok but like im doing the hash thing right now and that would require doing something else
i asked here so that i could offload the searching to someone else while i do the harder thing
so true
eval SMODS.add_booster_to_shop(p_xiferp_mendeleev)
thats not a string
I made it a string, opened the pack, and then it crashed again
see above
of the cards or the booster?
yes\
set SMODS.current_mod.debug_info
thanks ya
this is what talisman does:
hash time
Also, while you're here, the ERROR text should be Element Cards. How do I fix that?
dictionary in localization should have it under <b_key_cards>
if youre using loc_txt, it should go under collection in there
I don't have dictionary in localization, should I put one?
yes, it should be under misc
Don't even have misc, do have labels
misc is also what labels is supposed to be under
Ah. Also, the pack has no text or the right image
booster text should go under Other
and the image?
read the coordinates from your spritesheet correctly
and did you make an atlas for it
where it should be
and yes
and are you using that atlas key
key = "Elements_of_the_Round_Table",
path = "1357924680.png",
px = 57,
py = 93
}```
Here's the altas part of the code (a different key than the jokers and the elements)
yeah, your booster doesnt even have atlas defined in your code
also boosters are also 71x95 like any other card
Oh.
So, set the element card key = b_xiferp_Element?
b_xiferp_Element_cards = <collection name>
main.lua:1961: [SMODS VSMODS "ModdedVanilla.lua"]:2133: attempt to perform arithmetic on a table value
line 2133 is card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_mod * context.scoring_hand[i]
wait
hold on
im pretty sure you can set like SMODS.current_mod.extra_info or something along those lines
i remember something like that existing
okay i checked
SMODS.current_mod.debug_info
apparently something is nil
main.lua:1961: [SMODS VSMODS "ModdedVanilla.lua"]:2133: attempt to perform arithmetic on field 'nomial' (a nil value)
Firstly, it's nominal but you should be using card:get_chip_bonus()
oops
Yes, you need a context check.
-# sorry really new to this stuff
card:get_chip_bonus should only be used if you want total chips instead of base chips iirc
ok ty
why does this effect still trigger when this joker is sold?
Okay. Uh, the button still says error and the pack's still showing the wrong image
localization keys should be all lowercase, did you do that?
also what image is the pack showing
the arcana pack
thing is, the key is xiferp_Element
and I have!
okay
and?
it should still be lowercased in localization
as for the atlas?
show the booster code
key = "Elements_of_the_Round_Table",
path = "1357924680.png",
px = 57,
py = 93
}
SMODS.Booster {
key = "mendeleev",
altas = "Elements_of_the_Round_Table",
weight = 0.25,
kind = 'xiferp_Element',
cost = 8,
pos = { x = 0, y = 0 },
config = { extra = 8, choose = 2 },
group_key = "k_element_pack",
loc_vars = function(self, info_queue, card)
local cfg = (card and card.ability) or self.config
return {
vars = { cfg.choose, cfg.extra },
}
end,
ease_background_colour = function(self)
ease_background_colour_blind(G.STATES.STANDARD_PACK)
end,
particles = function(self)
G.booster_pack_sparkles = Particles(1, 1, 0, 0, {
timer = 0.015,
scale = 0.3,
initialize = true,
lifespan = 3,
speed = 0.2,
padding = -1,
attach = G.ROOM_ATTACH,
colours = { G.C.BLACK, G.C.RED },
fill = true
})
G.booster_pack_sparkles.fade_alpha = 1
G.booster_pack_sparkles:fade(1, 0)
end,
create_card = function(self, card, i)
return {
set = "xiferp_Element",
area = G.pack_cards,
skip_materialize = true,
soulable = true,
key_append = "xiferp_ele"
}
end,
loc_txt = {
name = 'Element Pack',
text = {
'Pick 2 of 8 Element Cards to use later',
},
},
}```
yeah, you still dont have an atlas set for your booster
oh, typo
I have an altas set for it
still says error on the button, but the pack's right
button still says ERROR
you have b_xiferp_element_cards under dictionary, right?
assuming you are actually using a localization file
is it supposed to be b_xiferp_element_cards?
yes
oh.
It worked as just xiferp_element for the cards themselves
Woo! Eris, may I make a joker of you?
anything you want it to be or do? (5 2-letter words in a row, go me!)
oh
Well, while I'm here, might as well ask: how do you change two random cards in hand?
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(<cards to get>, #options) do
local roll = pseudorandom(1, #options)
chosen[#chosen+1] = options[roll]
table.remove(options, roll)
end
``` i have this for choosing x random cards from an area
from there you should be able to do your suit changing stuff on cards in chosen
so, where do I set the number?
<cards to get>
ah
how do i check how many cards are unscored in the played hand?
if context.individual and context.discard and SMODS.pseudorandom_probability(card, 'cymbal_remancedream', card.ability.extra.numeratwo, card.ability.extra.odders, 'dreemurr') then
context.other_card:set_ability(SMODS.poll_enhancement {key = "cymbal_remancedream", guaranteed = true})
end
Hi again, trying to make my joker give an enhancement to the cards i discard with a 1/6 chance each, prediscard and discard won't work so i'm not sure what is wrong
#context.full_hand - #context.scoring_hand
remove the context.individual check
ok thanks
ah ? I wanted the luck to apply for every single discarded cards and not all of them at once
yeah
thats what that would do
context.discard is already for individually discarding cards
pre_discard works the same ?
so, what do I put in the {}?
Alright thanks
ah.
do I change the whole table at once?
no you would do an ipairs loop over chosen
ah
like the one in the main code!
How do I select a random seal? just like... pseudorandom_element(seal keys)?
SMODS.poll_seal("seed")
alright! And I take it similar setups exist for enhancements and stuff like foil?
there is SMODS.poll_enhancement, but SMODS.poll_edition wont exist until next release so you'll have to use the basegame poll_edition
alrighty!
SMODS.Consumable {
key = "magnesium",
set = "xiferp_Element",
atlas = "Golden_Brick_Road",
cost = 3,
pos = { x = 0, y = 0 },
unlocked = true,
discovered = true,
can_use = function(self, card)
return true
end,
loc_txt = {
name = 'Magnesium',
text = {
'Gives 2 random cards a random seal',
'and adds +10 chips to your next hand.',
},
},
use = function(self, card, area, copier)
G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 10
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(2, #options) do
local roll = pseudorandom(1, #options)
chosen[#chosen+1] = options[roll]
table.remove(options, roll)
end
for _, c in ipairs(chosen) do
local seal_the_deal = SMODS.poll_seal("shuffletheseed")
local conv_card = chosen
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = function()
conv_card:set_seal(seal_the_deal, nil, true)
return true
end
}))
end
end
}```
I think I set something up wrong. It isn't adding a random seal to any cards, it's doing othing
Except give mult in a way I can fix
it should be local conv_card = c
any other changes?
anything else?
no
still didn't apply any seals
oh wait
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(<cards to get>, #options) do
local roll, i = pseudorandom(1, #options)
chosen[#chosen+1] = options[i]
table.remove(options, i)
end
made a small mistake
and it was...
i did not get the index from pseudorandom
Okay, ykw?
G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 10
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(2, #options) do
local roll, i = pseudorandom(1, #options)
chosen[#chosen+1] = options[i]
table.remove(options, i)
end
for _, c in ipairs(chosen) do
local seal_the_deal = SMODS.poll_seal("shuffletheseed")
local conv_card = c
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = function()
conv_card:set_seal(seal_the_deal, nil, true)
return true
end
}))
end
end
}```
What did I do wrong?
i dont see any issues
no seal are being placed
okay well idk then
Must be setting things up weirdly. you know anyone who could help?
not specifically
well send me anyone you think could help
is there a way to mess with rarity weight
and what are the default values for rarity weight
If I want to do rare, would it be 3 or Rare
rare
Add guaranteed = true to your poll seal table
Trying to figure out how to have the cards display temporarily in the info_queue box, but it seems they spawn permanently on the screen
is there a way to make it so that when a booster pack is opened, that specific booster no longer appears in subsequent shops?
if context.open_booster then
G.GAME.banned_keys[context.card.config.center.key] = true
end
``` i think this is what your looking for
how would I go about implementing this in SMODS.Booster?
yep
probably just put G.GAME.banned_keys[card.config.center.key] = true inside of the create_card
got it
I'm trying to make a sinner pack for my 7 deadly sins jokers
and it'd be like a deal you can say yes or no to
guys how do i check for current mult inside the calculate function
mult
hook Card:is_suit, look at vanillaremade smeared joker for reference
i looked at vanillaremade but the joker doesn't have any config = or calculate =
though it uses SMODS.smeared_check and i have no clue what that is
i think bunco does that with a joker and custom suits i'll check there
i just didn't realize that the check would be outside of the joker object
most jokers with more unique effects work like that
they just check if the joker is present in some other function
like shortcut or four fingers?
how to make an edition only appear for jokers and not playing cards?
pokermon also does it with shiny
and it has a config button to enable and disable that edition for playing cards
ok thx
Hello, what's collection_rows in SMODS.ConsumableType?
It says how many cards should be in each row in the collection.
that's a thing?
so it says num of rows and columns since it's a pair?
of the atlas?
No, it's the number of cards for each row.
in the collection..
ok. what's a collection I think Im missing key information
I'm checking the start run function because I'm running into some awkward save system bugs. Am I right in assuming that when a previous run is loaded G.playing_cards is filled by just going through every card area and adding existing playing cards into it?
yes, as long as they have a .playing_card value
Aaah, that explains things
I guess I'll have to disable that value when a card is abducted, then reenable it when abducting it
sorry if im disrupting anything here but would you know what is meant by this, using set_edition to set random editions to cards when the deck is selected?
show your code
alr
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
--enhancements work
if pseudorandom("messydeck1") < 0.5 and v.config.center.key == "c_base" then
v:set_ability(G.P_CENTER_POOLS.Enhanced[math.random(1,#G.P_CENTER_POOLS.Enhanced)])
end
if pseudorandom("messydeck2") < 0.15 then -- this outputs an error
v:set_edition(G.P_CENTER_POOLS.Edition[math.random(1,#G.P_CENTER_POOLS.Edition)])
end
if pseudorandom("messydeck3") < 0.05 then -- this outputs a different error (might be my issue)
v:set_seal(G.P_CENTER_POOLS.Seal[math.random(1,#G.P_CENTER_POOLS.Seal)])
end
end
return true
end,
}))
end```
seals output an error at Card.lua line 605 fyi
is there a way to have the array be dynamic and support other mods or would i have to predefine all of the keys?
poll_enhancement, poll_edition and poll_seal exist.
SMODS.poll_enhancement/SMODS.poll_seal to be accurate
soon SMODS.poll_edition too for consistency
alright, i will add those two, one sec
enhancements seem to be fine, but idk, G.P_center_pools may not support modded enhancements so might as well
oh, but might as well use poll for consistency?
yes, also don't use math.random
next time if you need to get something from a table use pseudorandom_element, you can also do pseudorandom("seed", min, max)
wdym
the poll functions give you 1 key
one key?
yes, they get a random element
is there something i can hook/patch to prevent endless mode from being gray
i think you want boss_colour in your SMODS.Blind?
it's not an endless mode thing
actually im not sure what the question is exactly
default background goes from green to grey in endless
the bg is forced to be gray during endless, i'm trying to figure out how to prevent that
oh odd
well now im a bit confused, since the poll functions are returning a function value
did you put the parentheses after the function
i would think itd be in ease_background_colour_blind buti do not see it anywhere
like (SMODS.poll_enhancement)?
i know how to use functions but im not sure how to access the random value inside the function, since lua print(SMODS.poll_enhancement) outputs "function and a hash"
( and its not a hash its the memory address of the function
SMODS.poll_enhancement <-this is just the function
SMODS.poll_enhancement() <- this runs the function and gives back the output
i see, thanks
which is also why i asked if youve ever called a function before
because
you do this for literally ever functio
yea i call functions in lua but i didnt know what the poll function was, so i got a bit puzzled
thanks anyways
alright, ill give it a shot
Hello am I missing any configuration here when creating a consumable type and consumable?
SMODS.ConsumableType {
key = 'support_spells',
default = 'c_support_spells',
primary_colour = HEX('cca652'),
secondary_colour = HEX('cca652'),
collection_rows = { 3, 3 },
shop_rate = 0
}
SMODS.Consumable {
key = "erebos_favour",
set = "support_spells",
loc_txt = {
name = 'Erebos, Black-Hearted',
text = {
"After scoring a {C:attention}Flush{}",
"lose {C:money}#1#${} and draw #1# at next draw"
}
},
config = { extra = { money = 1 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.money } }
end,
atlas = 'TherosBD_support',
pos = {x = 0 , y = 0},
Because Im getting this error and the collection name for the consumable type is ERROR which ya isnt a good sign.
your atlas key is incorrect
incorrect how?
also localization
documentation is pretty cool
showing this because i assume youre using loc_txt for everything
its under SMODS.ObjectType
i can't see how Legendaries handle their unlock conditions by looking at VanillaRemade — how do i lock my Legendaries like vanilla Balatro?
They don't have an unlock condition, they unlock themselves when they are obtained.
Yes.
Are you using V or B without returning any colours in loc_vars?
i'm using V, but providing a colour in vars
return {
vars = {
localize(G.GAME.current_round.fainfol_card.suit, 'suits_singular'),
card.ability.extra.xmult,
colours = { G.C.SUITS[G.GAME.current_round.fainfol_card.suit] }
}
}```
this crash does not occur when hovering over it when unlocked
You need locked_loc_vars
ah i see
my horrible awful hack to use SMODS.is_poker_hand_visible()
i've tried fixing this draw function for ages now, but no luck — the voucher shader only seems to tilt when hovering over a specific different Joker that doesn't have a soul
Have you tried using SMODS.DrawStep instead?
same bug
this looks like an SMODS bug because this drawstep looks almost identical to the one that applies editions to souls
or maybe my joker setup is wrong
here's one of my Legendaries
right lemme test something rq
oh, weird. polychrome works as it should
How do I change this to only focus on scored cards?
does anyone know how i could make it so that the code checks specifically for one card being retriggered and then once its done retriggering and the next card is same suit, rank, etc that it doesn't give the xmult on the next card
how its supposed to work:
how it works:
jack of clubs played
next card is jack of clubs (xmult)
or
jack of clubs played
jack of clubs retriggered (xmult)
next card is jack of clubs (xmult)
context.scoring_hand
Thanks, working now
want this to act like photograph, adds first scoring face card's chips * 0.15 to mult, but right now any hand that has more than one card and includes a face, it triggers for all cards and adds their chips to mult
anything i need to fix?
You'd want to use SMODS.scale_card to scale instead of return, perhaps.
can yuo dynamically add boxes to a joker description
like maybe it starts with 1 box, but then after it gains an effect it adds a second box to its description
like this
bump
Yes, it would be card:get_chip_bonus() not card.base.nominal
this joker uses base chips to add to mult instead of the total chips
i'm lowkey stupid as hell, i'm looking at https://github.com/Steamodded/examples/, are these already built in into smods or do i have to copy them for new jokers too?
What counts as total chips?
I have retrigger detection on this card here. You could probably extrapolate the rank/suit detection from there https://github.com/the-Astra/Maximus/blob/main/items/jokers/combo_breaker.lua
changed card.base.nominal to card:get_chip_bonus(), everything else works fine but xmult isn't being added
card.base.nominal with this crashes anyways
Is it showing the upgrade message?
yeah, but it's still stuck at X1 Mult
It's context.other_card:get_chip_bonus()
got it
this works, thank you
Is there a way to make a joker play a sound on repeat?
yes, are the effects predetermined or are they variable
<@&1133519078540185692>
Hi N’
hi
I am back
<@&1133519078540185692>
Bump cause yes
variable but it's added at fixed intervals (probably after boss blind)
and how many boxes can i add
Hello, i have added my sticker, and the small badge sho the text error do you know why ?
you need to localize it in a separate place for the badge
if you're using a localization file, it goes in misc -> labels, and it should be modprefix_stickerkey = "Ditto"
I cant figure out why the joker doesnt trigger the script that adds the mult to the joker. I play the hand, I added the return message thing, and it just doesnt trigger at all. I've looked at tutorials online and I have been stuck. I have tested the script for applying the mult, and that works just fine
The Joker isn’t triggering because the loop and variables inside calculate aren’t set up correctly. Make sure you use ipairs for context.full_hand, don’t reuse card inside the loop, and update freindyMult in the right context phase. Fixing these should make the multiplier work.
Bump
so like have a sound effect repeat every so often indefinitely
?
Yes
so not a music track, but a sound effect
then i think there would probably be some recursive shenanigans
Wait i misread, it is a music track
in that case they should autorepeat
is it staying silent after the song has finished
I have yet to code it but i want the song to randomly play if i own a specific joker
what do u mean by random
also music tracks can have a select_music_track function
or something
it's not very straightforward then, you would need to add the nodes to full_UI_table.multi_box in the joker's generate_ui
here's an example (this doesn't use the joker's generate ui anymore but it has the same structure)
https://github.com/nh6574/JoyousSpring/blob/e0cdbd2da1daeb698eb2ebe14693811e8ab59e65/src/card_ui.lua#L296
you can add as many boxes as you want but at some point you will run out of screen space lol
Ah ill look into it thanks
Like imagine youre just playing balatro and out of nowhere the song starts playing
hmm so while u have a certain joker there is a chance for a specific song to play?
so im trying to learn to make mods. i have the rules set up, but how do i customize the cards you start with, and actually make it appear in game?
yeah you should be able to control the track timing with select_music_track
Yes
Ah ok thanks, ive never used select_music_track so ill look into it thanks
i'm doing my unlock checking incorrectly — i'm using 3 hooks to emulate what double_gold does, however check_for_unlock doesn't do what i want to do
what's the correct function?
how come my custom challenge doesnt show up in game?
does anybody know how to fix that?
well we'd need to see your code
can i see your JSON file?
ok im gonna need a little more handholding for this
please correct me if my understanding is incorrect
- you initialise an array called
full_UI_table.multi_box full_UI_table.mainis the first box, aka the main description- to add another box, you add an entry to
full_UI_table.multi_box, starting at index 2
what i dont see from the snipped you lniked is
- how do i set the text inside each box
- what the vars
nodeandname_nodecontains
sorry for all the asks i really need all the heps to understand this
i'm also having the same issue loading stuff from jokers_2.lua
try adding assert() around your load lines
that way, it'll crash if it fails
assert(SMODS.load_file(...))
no crash
^
could i see the new version?
i only did the assert thing with the challenges for now
-# Like a clock?
once i get that figured out it should be the same process to figure out why nothing else is working
(minus jokers.lua which works fine)
wait
i did a stupid
hold on
i forgot to do scripts/challenges.lua
ok that didnt fix anything
so now it looks like this
still doesnt crash, still doesnt show up
oh
move the parethesis inside the assert to outside the assert
eg. assert(SMODS.load_file("thing.lua"))()
oh, nope, still no showup
i'll try this
that didnt change anything either
oh it's happened a lot today
also hello ghos
hai :3
i love the fast reaction time for that lol
i'm out of ideas ;u;" sorry
once you're done i might ask you for help with... ui code....
amazing mods
*shudders*
oh ya kusane do you know anything about unlocks?
i wonder if moving the code to jokers.lua would change anything
ya give that a go ^^
unfortunately not i havent bothered locking any of my cards
didnt work, but it taught me something
is there a second thing i have to do? i think the issue isnt in loading the script, but actually creating the deck
oh like multiple abilities?
N has pointed me to some example but i am having a hard time wrapping my head
u can add multiple tables in the loc_vars
so the rules are there, but theres nothing to call the key for the challenge
yeah but i mean like dynamically adding a box during run time
u can use several keys for that i think
like adding an extra box each time you defeat a boss blind
😭
the text is obtained by localize from the localization file, in this case i have a special entry for a new description type but you can just use an Other entry
node is where those localize nodes are saved to then append them to multi_box
don't worry about name_node, this is basically for joker fusion so i also have the name of each joker before each box
oh ya hai N, question
hi
i've got some hooks i'd like to unlock a card from
code is currently this but check_for_unlock is not the right function
do i need to hook it too, or is there a better function for this?
wdym it's not the right function
your joker should have a check_for_unlock as well
and unlocked = false
or card
oh, can i not use unlock_condition?
no, that's only for the hardcoded ones
check the vanillaremade joker file
thanks!
ya i checked it out, and it told me it was equivalent ;u;"
i understand this now though
what it means is that they're equivalent but only for that condition so the reason I use check_for_unlock instead is as an example because mods will most likely use the function
:3
gaming!!!!!
how do i make it so during an event the player cant play any cards for a select time?
if hand_chips + context.other_card.chips + card.ability.extra.chips_penalty < 0 then
penalty = -(hand_chips + context.other_card.chips)
end
return {
chips = penalty,
colour = G.C.CHIPS
}```
i finally got the shines on the souls to work!! it required self.ARGS.send_to_shader
:3
Ghost seal? Who could kill such a cutie
hi is this the right way to check if a consum(e)able has been sold?
if context.selling_card and cardarea == G.consumeables and not context.other_card.ability.extra.refundjeapordy then
bump
Me killing GhostSalt to have a chance to have a negative joker (the cops are looking for me)
when does the game set challenge modifiers in G.GAME? i'm trying to change the scoring calculation for a challenge, but init_game_object and start_run hooks are too early
i tried following n's guidance and so far not successfull
whioch part did i do wrong
or have i fundamentally misunderstood this completely
ah nvm challenges have an (undocumented) apply parameter that can run custom code
if i wanted to make a DNA style joker, that instead creates a copy of the first destroyed card, what do i need to add or change from this or anything im perhaps missing that ill need to change from other stuff im stealing from DNA:
local copy_card = copy_card(context.full_hand[1], nil, nil, G.playing_card)
if context.remove_playing_cards and context.removed[1] then
local _card = copy_card(context.removed[1], nil, nil, G.playing_card)
_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
G.deck:emplace(_card)
table.insert(G.playing_cards, _card)
playing_card_joker_effects({_card})
end
thanks
oh but there seems to be a problem, not sure what the issue is
...per chance, did this go off multiple times?
yup
return { vars = { xiferp_seal_the_deal } }```
you said this would work, all it did was break the game with ') expected by ='
Was this copied by Blueprint?
yes, but i also had a second one
Move G.deck:emplace(_card) under table.insert(G.playing_cards, _card)?
Hey Ali
you miss the { and } in poll seal
SMODS.poll_seal("shuffletheseed" and guaranteed = true) more accurate?
ah. No (seed, table) issues, gotcha
still not applying any seals
show your code
SMODS.Consumable {
key = "magnesium",
set = "xiferp_Element",
atlas = "Golden_Brick_Road",
cost = 3,
pos = { x = 0, y = 0 },
unlocked = true,
discovered = true,
can_use = function(self, card)
return true
end,
loc_vars = function(self, info_queue, card)
local xiferp_seal_the_deal = SMODS.poll_seal({key = 'shuffletheseed', guaranteed = true})
return { vars = { xiferp_seal_the_deal } }
end,
loc_txt = {
name = 'Magnesium',
text = {
'Gives 2 random cards a random seal',
'and adds +10 chips to your next hand.',
},
},
use = function(self, card, area, copier)
G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 10
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(2, #options) do
local roll, i = pseudorandom(1, #options)
chosen[#chosen+1] = options[i]
table.remove(options, i)
end
for _, c in ipairs(chosen) do
local conv_card = c
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = function()
conv_card:set_seal(seal_the_deal, nil, true)
return true
end
}))
end
end
}```
your poll function is in a completely different place to your set function
put them both under the use?
now the code's mad because of the fact the use has to end right after setting seal_the_deal
and the entire code for Magnesium
nevermind, fixed it
as an idiot, i didn't know what you meant by this, but i did manage to get it working somehow, though an issue I'm encountering is that it only puts the cards in hand after scoring ends. though im guessing that's because the remove thing only triggers at the end of scoring:
calculate = function(self, card, context)
local extra = card.ability.extra
if context.first_hand_drawn and not context.blueprint then
local eval = function() return extra.card_destroyed_this_round == 0 and not G.RESET_JIGGLES end
juice_card_until(card, eval, true)
end
if context.remove_playing_cards and extra.card_destroyed_this_round == 0 and context.removed and #context.removed > 0 then
local copy_card = copy_card(context.removed[1], nil, nil, G.playing_card)
copy_card:add_to_deck()
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, copy_card)
G.hand:emplace(copy_card)
copy_card.states.visible = nil
if not context.blueprint then
extra.card_destroyed_this_round = extra.card_destroyed_this_round + 1
end
G.E_MANAGER:add_event(Event({
func = function()
copy_card:start_materialize()
return true
end
}))
return {
message = 'Memory Restored',
func = function()
G.E_MANAGER:add_event(Event({
func = function()
SMODS.calculate_context({ playing_card_added = true, cards = { copy_card } })
return true
end
}))
end
}
end
if (context.ending_shop) and not context.blueprint then
extra.card_destroyed_this_round = 0
end
end
If hand is played, context.destroy_card occurs after the scoring is done, yeah.
bummer, oh well
still did nothing
bump
No, it would be context.selling_card and context.card.ability.consumeable
oh
hello, I'm trying to make a legendary joker that takes ownership of blue seals so that they instead create negative planet cards. Looking at the page for taking ownership, it seems like I would be instead overwriting blue seals only as opposed to letting a joker do it.
How do I make it so that having the joker instead replaces the existing blue seals? Would i just put the SMODS.Seal:take_ownership under an if statement inside of the calculate section, along with the behavior I'm changing?
take ownership outside of the joker and check if you have the legendary in the blue seal
ah so change blue seals so that they have an if else or something that checks for the joker, that makes sense
current issue: the joker is meant to create a planet card when a playing card is destroyed, but it's not doing so
remove context.joker_main
may i ask how it's an issue?
No, you would have to patch.
context.joker_main and context.remove_playing_cards are never calculated at the same time
i see tysm
Taking ownership wouldn't work because Blue Seal is hard coded.
no clue what you mean by patch, you mean go into the games code and change the code there?
well darn, that's a lot of words
My files aren't updating in the game after I've restarted and saved. Any ideas?
wdym by that
Any changes in code after a certain point stopped being updated ingame
Nothing...
what were the changes
Mainly a new joker, and the loc_text for an old one
i think you’re not saving to the right place then
or you’re missing some important info that the game needs to register the joker
That might be it cuz I did move some files around
like the key
files aren’t loaded automatically except for your main file
Can you explain this to me
how can i check if a card scored, without using contexts?
wdym
smods doesn't load files automatically
except your mod's main file
I'll experiment a lil
each card tracks if its been scored this ante for the pillar
so you could check that ig
context.scoring_hand?
i suppose i could set a flag in the mod's calculate but there might be a pre-existing way
okie so
one of my Jokers has a lock condition: Play a Junk with a scoring Steel card
and i need to check if the steel cards passed in with hand_contents scored
you should also probably check if the player disabled junk (i do)
I got it we're good im stuupid
you can't play a Junk if you have it disabled so that's fine :3
Why cant you loop over context.scoring_hand
:/ then i cant unlcok it
read the question i asked please ;u;
Also theres SMODS.in_scoring
u won't be able to play with it anyway if u have it disabled :3
oh
aha, i'll check that out, thanks!
I did
Im just asking why you cant do that
unlock condition ig
because check_for_unlock doesn't have a context
Oh true
i think the played hand is considered a cardarea?
problem: SMODS.is_scoring requires the scoring hand
i don't have that
lemme try something else though
G.play.cards?
G.play.cards contains all played cards iirc, not all scored cards
okay i think i have a solution using my mod's calculate function
lemme test
sounds conplex
Guys, I just realized something, this may save a couple of people a headache. The #X# tags are in the order that you return the loc_vars. So, for example, I have value1 and value2, and I want to display both.
In the description of the joker, you need to put #1# then #2# to display value1 and value2 in the correct order
Use G.FUNCS.get_poker_hand_info(G.play.cards)
ywah
alright my method works :3 thanks
anybody know what function makes the descriptions for the blinds show up in the collection
like that
woah that's long
🎃 your long
That's what she said lol
yes, it is what i said :3
lol
On a more serious note, are the variables stored in the config field global or local? It seems to me they must be local, since I cant add to them. But I'm not sure
Yes
That is what I said lol
No, they are global because they are in the center which is global.
My code
It would be card.ability.extra.FreindyMult
Which line?
Every line where you use FreindyMult
Same for the other config variables.
what function makes blind popups like this appear when you hover over them in the collection?
wait is G.GAME.hands["handtype lol"].level not the way to have a hand's level as a var
i noticed its considered a table despite being one value as opposed to a Number and trying to index it and tonumber() it isnt working either it seems
It's to_number not tonumber
How do you access the card being scored when in the scoring cards context?
SMODS.Consumable {
key = "magnesium",
set = "xiferp_Element",
atlas = "Golden_Brick_Road",
cost = 3,
pos = { x = 0, y = 0 },
unlocked = true,
discovered = true,
can_use = function(self, card)
return true
end,
loc_txt = {
name = 'Magnesium',
text = {
'Gives 2 random cards a random seal',
'and adds +10 chips to your next hand.',
},
},
use = function(self, card, area, copier)
G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 10
local xiferp_seal_the_deal = SMODS.poll_seal({key = 'shuffletheseed', guaranteed = true})
return { vars = { xiferp_seal_the_deal } }
end,
calculate = function(self, card, context)
local options = {}
local chosen = {}
for _, c in ipairs(G.hand.cards) do
options[#options+1] = c
end
for _ = 1, math.min(2, #options) do
local roll, i = pseudorandom(1, #options)
chosen[#chosen+1] = options[i]
table.remove(options, i)
end
for _, c in ipairs(chosen) do
local conv_card = c
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = function()
conv_card:set_seal(xiferp_seal_the_deal, nil, true)
return true
end
}))
end
end
}```
This isn't working, what's wrong with it?
is there a way to make it so the planet card produced is always of the most played poker hand?
my friend made a jokerforge mod and this one specific joker crashes the game when it's loaded. any help with it would be appreciated <3
which context exactly?
check the vanillaremade wiki there's a faq for that
no idea where that is but thanks
ty
bump
(problem is: not giving out seals)
i see the code but i have no idea how im meant to implement it
Yes, you're putting everything in calculate instead of use
if I remove calculate it breaks
Log?
im just gonna change the function of the joker, i don't think doing that is possible for me
Remove the return
testing...
no seals again
I use it, it's supposed to give two random cards seals
no seals on anything
see above
Nevermind, I found a workaround that hopefully works
For what?
for what it's supposed to do, and what it's doing
(It gives the chips as it should, but not the random seals)
Code?
what i have atm
Scratch that, it didnt work. The context is context.main_scoring and context.cardarea == G.play
in that context the card scored is the card youre coding
so card
- dont do stuff outside a context check
- current_round.most_played_hand doesnt actually contain the most played hand at all times, because it checks per ante. the question just above the planet card one in the vr wiki answers that
- use the planet_for_handname as the key in add_card
all of these is explained in some way in that wiki btw, i recommend reading it fully if you ever have the time
i did ctrl+f on the wiki and none of that was explained but ok tysm
Hey, N!
hi i dont really want to read code
Alright. then how's your day going so far?
its been good i played a lot of ff8
good to hear
im assuming that i have to do a copy of 2 for every poker hand because i have no idea what any of that means
So, what got you into Balatro in the first place?
i would recommend watching a lua tutorial then lol
it looked fun so i played it
ik i suck at coding dude im trying to understand i promise but it feels like i should've known all of this when i was 9 😭
the idea of the wiki is that theyre literally code snippets you can copypaste
anything off with the code?
Yes, i wont exist so options[i] also wouldn't exist.
pseudorandom only returns one value.
any clean fixes?
Yes, change i to roll or use pseudorandom_element
local roll = pseudorandom(1, #options) Like this?
i tried to copypaste and it still didnt work right 💔
No, use pseudorandom_element
pseudorandom_element(options, 'seed')
I take it options is the table?
local roll = pseudorandom_element(G.hand.cards, 'xiferp_card_changer')?
No, local _, i = pseudorandom_element(options, 'seed')
like above?
man
I know the pain
No, options should be options
It should be key not set in SMODS.add_card
any other changes?
Because it's still not adding seals
Code?
it only adds high card now but it still adds anything so ty
I feel like I've sent it five different times with slight tweaks, but okay
Why did you put the calculate function back?
I ctrl-z'ed a bit too hard
here it is without that
anything off? Any reason the seals aren't being added?
does anyone know how i can change this from always giving pluto to giving the planet of the most played hand?
I'd say check vanilla remade voucher "telescope"
Have you tried printing options and chosen?
no
I just took someone's code that said those two were tables for however many cards
thank you twin
all that and i didn't even have to bother with the wiki to begin with 🥀
ok using blueprint on inflammation crashes the game
Hi friends! I'm having trouble coding a retriggering joker, and it's not retriggering any cards. Can someone help me figure out why this is happening?
does anyone know exactly how it's crashing?
it crashes when a planet card is being created
I see consumable_buffer in a contradition, between 0 and 1 (set to zero, set to +1, set to zero, etc.)
wdym
how does that make blueprint crash
idk, but it's stuff like this I llok out for now
apply = function(self, back)
G.STATE = G.STATES.SHOP
G.GAME.shop_free = nil
G.GAME.shop_d6ed = nil
end
seems a bit dangerous... but it works for starting a run in the shop.
may be whatever but im making inflammation blueprint imcompat
I've already created the profile.jkr, I just need to export from JSON to JKR and it'll be done.
thought this was a crypto scam for a second
Pardon me, I just never saw one before
te perdono bro
I based it on this repository https://github.com/TeddyHuang-00/BalatroSaveEditor.git
polite bump
currently getting an error for something??????
ik i probably wont get a response to this anytime soon so for now im gonna try to replicate my code from before
Your timing is off, _planet is not initialized by the time you call add_card
hey guys what does this mean 💔 (this is the best channel to ask this i think)
how would i go about fixing that
is that me
im you but slower
no speed in there
You have bad patch syntax somewhere
how do i fix ts
You have to reorganize your code a lot and I simply do not have the energy to walk you through that
Look through your patch files
may aswell scrap the joker tbh it's caused way too many issues anyways
i don't know anything about modding where do i find patch files
Is this caused by a mod you made? Or are you just a player?
player
Disable your mods one by one until it stops 
Which mod
its a mod for a separate game that i dont think has a discord server i just thought this was the best channel to ask because balatro modding uses lovely 💔💔💔
shit it does have a server
my bad
generating negative planet cards from modified blue seals only ever makes enough to fill the space you would normally have if they weren't negative, is there anyway to go around this?
show code
Yes, remove where you check if the number of consumables is less then the consumable limit.
yeah that would do it
another question, how do i detect the presence of a custom joker? i have the key for it but it doesn't seem to be detected. i am sure im missing something
if next(SMODS.find_card('j_modprefix_key'))
ah yes, of course i forgot one word
So, I have a problem, a proposed solution that I think is a bit of a hack, and my request is to know if there is a better way:
I would like to run code when a particular kind of card is created. This is intended to make the (consumable) card target a random joker, and reveal the target to the player.
This card (currently) only shows up in booster packs, and while I would like for it to also show up in the shop, that's going to be a playing it by ear sort of deal.
My current, bad and hacky, plan is to use the mod calculate to trigger on open_booster (and possibly reroll and shop start) to search for an already created card of the type I want to initialize, and then modify it. open_booster will require a delay, which can be affected by the game speed, because the cards aren't actually created until the booster explodes, and there's no guarantee that the player won't be faster than the difference between the card being created and the delay timing out.
My second idea is to create a lovely patch to optionally run initialization code when creating a card, but I'm hesitant to hook to code if I don't have to.
Is there a better idea?
hook create_card