#💻・modding-dev
1 messages · Page 658 of 1
i didn't save changes 😭
bruh
😭 real tho
in what sense
last page?
nah
try adding
unlocked = true,
discovered = true,
to the joker, might help idk
unlocked is true by default
ah well
do you like my sword sword sword my diamond sword sword
peak 🔥
time to figure out how to add the decal!
Uhm, so i recently got into Balatro and im enjoying it alot. I wanted to ask what some QoL mods are and any mods thaat improve overall enjoyment (No special decks just adds onto the standard game)
wrong channel? mb
this is for people who are developing their own mods
i have no idea how to add the decal
help
im stupid and don't get it
even though it should be very obvious
missing a comma
the }
OH
so it should be },
the curly bracket?
yes that's correct
},
atlas = 'Joker',
oh 😭
just get rid of pos it has a default
pos = { x = 0, y = 0 }
oh
and not pos{ x = 0, y = 0 }
yay!!
that took like 2 nearly 3 hours 😭
welcome to balatro moddding
figured
hey at least you have it down now
welcome to balatro moddding
also i would recommend using joker blocks with the live lua preview on as a way to kind of learn stuff like this, dont rely on it fully, not yet, atleast.
🫡
i have no idea what to make them do 😭
also im cooked for the sprites dude
i can't draw for the life of me
like
at ALL
what am i supposed to do
🤷♂️
that parts on you dawg
is it not possible to put any other if statements after if context.joker_main then? everytime i try it just says all ifs are unexpected
hold on im probably fucking this up somehow
IM DUMB OKAY 💔 do you know whats wrong
huh
you cannot put a block of code inside of a table
which is what you are doing right now
not all of the code should go in the return
those usually have too much shit going on for me to even process im not very good at that stuff
i am now beginning to realise that this may have been a bad idea
same here i may be going insane
define random outside the return table
think i got it
i have accidentally forced myself into making 48 jokers and two mods with zero experience and zero art skills
well good thing is you dont have a deadline
true
still im probably cooked
(i have no idea how im gonna make the sprites)
i don't even have ideas for what they're gonna do 😭
how do i get random jokers (i have a random value already for how many) and destroy them? (i assume SMODS.destroy_cards(G.jokers.cards) plays a part but i couldnt find a comprehensible example on the vanillaremade wiki)
i guess ill look again, maybe i missed something
Get a random element from G.jokers.cards, add it to a table
Then call SMODS.destroy_cards on the table
yeah i have like no idea how to do that 😭 ill study up a bit and try in a sec
good luck!
you don't need to add it to a table
SMODS.destroy_cards accepts individual card objects too
yeah true, it just sounds like they want several
yep yep
maybe not the best way to be doing this lmao
hey as long as it works
i think someone would explode if they looked at these if statements lmao
i'm about to find out lol
Couldnt you loop over G.P_CHALLENGES or whatever its called and check if each one with your mod as the original mod is completed
challenges don't have an original_mod field i'm p sure
I tried eval G.GAME.challenge.original_mod in the console
it's a nil
while in a challenge
G.GAME.challenge is a string no?
Does it give you an error or
yeah so try G.P_CHALLENGES[G.GAME.challenge].original_mod
G.CHALLENGES is a table
G.CHALLENGES[challenge_id] isn't doing the thing tho
How do I access......
a table of tables like this
Okay so it appears to be number indexed
But that should work for looping over to find challenges from your mod
yeah prob
if context.joker_main then
return {
random = pseudorandom("mod_somerandomseed", 1, 10),
message = tostring(random)}```
just has the joker say "nil", is this another table problem?
the return table takes only specific values
random is not a value it can do something with
damn
you'll want to specify local random = pseudorandom("mod_somerandomseed", 1, 10) before the return table
so it's an estabilished variable
ahh ok
then the table's message value - which it can work with - can take your local variable
What are you trying to achieve
Oh wait yeah
Nvm
the message thing is just a debug
Random outside the table ya
oh god damn it i have so many of these
okayyy so my randoms pick random jokers, but i cant use G.GAME outside of a return table, so I cant predefine the random functions.
do i need to make them local? if so, it just says its an undefined global
this is nicer lol
i'm not sure what you're having a problem with
can you show the code?
This is just the game not being in your vscode library so it doesnt know the functions exist
Also wdym you cant use G.GAME
thats what i thought
i cant use any of it outside of the jokers return function
i have this as softlock = true but when i use high priestess, it still shows up. i assume that the Planet set has something that my set does not but i dont know what it is, does anyone have any idea what i could do so it works as intended
softlock should go outside of config
trying to get a random joker
random_joker1 = pseudorandom_element(G.jokers.cards, "MOD_randomJoker1")
and i cant use random inside of a return table, but i cant use anything under G outside of a return table (when they were inside, the game actually opened, but didnt give any random values)
show the codep
because it appears that you are just putting the code outside of the joker as a whole
Which does not work
im putting them with the atlas and pool and stuff
jus show the code
SMODS.add_card({ set = 'uma_Planet' }) is still adding softlocked cards
I've also added my own planet card to the normal Planet pool, and softlock = true still works inside the config line
Huh
Okay i forget if its hardcoded to check if the softlock card is a planet
Check get_current_pool in vannilla
I'm not sure how I'm formatting this line wrong
i meant like look at the function in the code
ohhhhhhhh
get_current_pool gets a table of all available card keys for a set
CHAT I THINK MY FRIENDS GONNA MAKE THE SPRITES FOR ME!!!
Congratz
good jobth
:D
you mean you're defining a key in your joker table as G.GAME[something]?
for getting "every unique rank" in a hand, should i use get_id() or base.value
i dont really understand respects enchants so
get_id respects stone cards not having a rank
you can get the same with base.rank + SMODS.has_no_rank
o gotcha
hey so uh, wtf is happening? why isn't it doing it
???????????????
what wacky thunkism is this where it's reading a completely different value than what it's being told
is the unlock text just somewhere else?
...wait what? does process_loc_text just not work for the unlock table?
actually no, that's not even running because i'm changing it via malverk
...did eremel close the malverk thread?
i had to do malverk texture
Is it possible to make a Joker that detects copies of other Jokers
like e.g. it does something if you have two of the same Joker
#SMODS.find_card("j_modprefix_jokerkey") will be the total number of that joker you own
oh i didn't know it was that easy
I looked everywhere for a solution and found nothing so I just stated my problem here
Should've checked VanillaRemade omfg
i need to organize it better but idk how
is there a way to grab the list of all ranks cards could have
SMODS.Ranks
o sick, thanks
this is just for a specific Joker
My Joker's ability is +X1 Mult for each Joker you have an exact copy of
is THAT possible?
why does get_id() throw a random negative number with stone 😭
yeah just do that for every joker you own
if it's more than 1 then you have a copy
although it's probably better to do it manually to not increase the complexity lol
Quick question, how would I choose a random card from a consumable set with a key of uma_Planet, preferrably using the get_current_pool() function? otherwise it just ignores the fact that some cards are softlocked and still makes them while using SMODS.add_card({ set = 'uma_Planet' })
I was recommended to look at what get_current_pool() actually does but I don't fully understand it so I'm a bit lost
if context.individual and context.other_card:is_number() and context.cardarea == G.play then why that isn't working cause if I use not context.other_card:is_face() it does the thing on stone card
How do you write a compat check
Rejok is too complicated rn so I want it to have a compat check
And in a way that doesn't require you to edit every vanilla jokers' code just to add that check in
Do you just make it false for all by default unless specified otherwise?
is it in v_dictionary
get_current_pool returns a list of all keys available + "UNAVAILABLE" for the keys that aren't
is_number is not a thing
wtf why are there two dictionaries
one is for v and the other for

_ _
_ _
oh so how do I do that
I'm gonna bint my bogos
is it possible to make certain part of localization to appear if certain requirements are met
i.e "+4 Mult" shows up if you have this Joker
on their description
if you have a lot of combinations you can use main_end
if you have few then it's easier to change localization keys
what about the first one?
How do you maek compat checkds
look at how invisible joker does it
So for some reason, despite cards 10 - 12 being softlocked in the code, they still show up in the list. I used to have softlock = true inside of config = {}, but that didn't seem to help either.
lemme retry rq then, maybe i messed smth up
ah it only checks softlock if it's the set planet
do stone card keeps the id or it change
not (context.other_card:get_id() > 10 and context.other_card:get_id() < 14) I tried that but it doesnt work
you can add G.GAME.hands[v.config.hand_type].played > 0 to in_pool
wdym
stone cards have negative id
wait im dumb
(context.other_card:get_id() >= 2 and context.other_card:get_id() <= 10) it should work
is in_pool a value that goes in config? I haven't heard of that yes so im not sure how to set that up
how do i use animated atlas for jokers
oops lmao, i accidentally made 8 ball able to make tarots when the consumable area is filled, how fix 
i think there's an issue with my compare, but i'm not sure what to set it to
you dont need to check if the other card can calculate smods already does
i dont see how it's adding extras tho
yeah - like, i based this off of vanillaremade's 8ball
the only thing i can think of is that i'm not adding to the consumable buffer
OH
when you take ownership of a joker and add a calculate function, the original calculate still runs
it might have done the one i wrote, plus its original calculate
ah yeah
how do i make it not do that
How would I create the v value that in_pool now references since in_pool won't let me reference card for the hand type?
I'm trying to have a seal be applied to all cards played, but right now it only applies to one card.
calculate = function(self, card, context)
if context.joker_main then
if context.cardarea == G.play then
for i, card in ipairs(context.full_hand) do
card:set_seal("ModPrefix_Seal", true, true)
return {
message = "Sealed",
sound = "ModPrefix_SealSFX",
}
end
end
end
}```
What am I doing wrong?
nevermind I figured it out myself!
Where are these consumable textures used in-game? I don't know if I need to make versions for my new consumable sets or not
youre returning a message & sound - return means "end this function here, and return these results"
for the same effect without return, do SMODS.calculate_effect({message = "Sealed", sound = "ModPrefix_SealSFX"}, card)
also you probably don't need the context.cardarea check
i do actually, just tried and when i just clicked on the card, it started doing everything while not even being played 😭
im saying you dont need the cardarea check, you still very much need if context.joker_main then
if it was doing random stuff and you still checked for joker main then that's a Very Different problem
yeah i removed the cardarea check and thats what happened
ok tbh i might recommend you put this effect in either context.before or context.after
depending on if you want it before/after scoring, but if you put it in joker_main i think it might be a bit weirder
this just fixed all of the bugs thank you so much 😭
for sure
how would I make a joker check if a certain consumable was just used?
I have a custom joker with values that should go up when my custom consumable is sold. I know how to do everything other than relaying the information to the joker that the consumable was used
makes sense
how do I get the tooltips on the description of cards? (like if a card description references a seal, it will define that seal in another textbox to the left of it)
table.insert(info_queue, G.P_SEALS.modprefix_key) in loc_vars
thanks!
where do loc_vars go? i've never worked with them, and i guess they dont just go under SMODS.Joker
before i make a variable for this myself, is there a G.GAME variable that tracks the most recently sold joker?
you can check all the G's here https://github.com/Steamodded/smods/wiki/G
No.
Nvm, got it! Thanks!
I'm having trouble getting pools to work where I want to make a custom tarot that only spawns in the joker from a pool but I can't tell why it is spawning any joker still. I've got this but I think something is wrong, do I need to enable pools elsewhere? SMODS.add_card({ set = 'Joker', pools = "Hamburger" })
Inside the loc_vars = function() of a consumable card, would it be possible to reference the default config options for a joker? I basically have config = { extra = {stat1, stat2, stat3} } inside a joker and I want to be able to access those default values within a consumable card to use
iirc those are the undiscovered textures
there's a default undiscovered image so you don't need to, but you might prefer it
cool
I won't worry about it then
change its name field too
does this effect sound too strong? the seal initially only created the spectral card when destroyed but i realized that sounds kinda weak given that it's essentially "IOU a spectral card that actually does something". i'm wondering if the spread is too much though, even if card destruction isn't incredibly widespread
How come even after I disable certain consumables using in_pool = function(), the default card still continues to show up?
I too would like to know this
Btw I don't think it's terribly broken unless you are exclusively comparing it to base game, perhaps if you felt you wanted to balance it a bit more you could make it a chance that it will apply another seal (but still guaranteed to give a spectral), stopping it from going infinite while also giving more support for the GOAT Oops all sixes
Imma be honest even a 4/5 odds to spread would do wonders (in my opinion)
The default card of a pool will always spawn if no cards in the pool can currently spawn
So you should do something to make the set not spawn at all if the pool would be empty
so i need to modify the shop rate to fully turn them off?
is there an optimal place I can put my function to check whether a joker is present or not? that would be my trigger and I don't think I can just put the code in the joker, since once you sell the joker it probably wouldn't turn off since there's no code to run
im trying to make a seal that has the card its applied to only score half of its chips, whats the calculate function? i dont know how to get the card chip value
i suppose i mean strong in comparison to base game as well as in comparison to other mods around a similar strength. but i could add a chance to spread, yeah
you can use get_weight function on the consumable type to dynamically change the weight
honestly it seems pretty fine because it isn’t as readily accessible as purple tag with discards, you still gotta have something else to make it work and if anything I think it’s neat it improves the utility of card destruction and gives an additional effect to stuff like trading card and hanged man
self.config
can someone help explain how G.UIT.O works? i know im doing something wrong here but i have no clue how to fix it
@faint yacht yeyooo, just asking if love.timer.getFPS would work for Balatro?
Just check how vanilla checks fps
idk which lua does that, since theres so many
Global search exist
yes
why would it not
check what debugplus does then
Hmm
Is it possible to get the location of a joker in its atlas?
you need to keep calling it ...
when are you calling it
card.config.center.pos?
Oh! For some reason, I thought that referred to, like, position on the screen
also wdym by keep calling it
Hm... getting an error trying to index pos, which means I think I have my syntax wrong
Also, is there a resource that shows all of the card.ability and card.config syntax?
Code?
card.children.center:set_sprite_pos({x = card.config.center.pos +1, y = 0}) is the single line - I can send the whole function, it's basically trying to make it so that the popcorn card changes sprites when it activates. If I have it as an integer, it works fine
I managed a workaround, by making a config = {extra = {cardpos}} field, and accessing it with card.ability.extra.cardpos to increase continually
It should be card.children.center.sprite_pos.x+1
Ohh, okay
Is there a resource for learning all of the card.children, card.config, and card.ability contents?
I looked through modding-resources, and I think I've read effectively every page in the smods wiki, but I haven't found anything that discusses those past some basic card.ability stuff
please, im so confused
there's multiple issues
First, it's not how you create a card in a first place (check SMODS.create_card)
Second, c_fool used as a variable, not a string
And third, you cant put Card in G.UIT.O, you need make CardArea, put your card in this area, and put area in G.UIT.O
wait, so then it'd be { n = G.UIT.O, config = { object = CardArea("c_fool") } } right? am i still getting smth wrong?
Well no
local area = CardArea(0, 0, G.CARD_W, G.CARD_H, { type = "title", card_limit = 1, highlighted_limit = 0 })
local card = SMODS.create_card({ key = "c_fool", area = area })
area:emplace(card)
return { n = G.UIT.O, config = { object = area, id = "consumeable" } }
In Balatro we call it consumeable like LocalThunk intented
is there any context that triggers during scoring?
scoring is multi-staged thing yk
technically after pressing "play hand" everything it's scoring
riiiight
yeah after context.press_play is all scoring
you can just put the card in without the area
i've done it before
idk when I was trying it was crashing
well i was doing it with new Card(
maybe it's smtn in the smods function that makes it dislike putting them in ui
i do it here
Kinda makes sense since card is Moveable but, whatever
context.press_play exists?
nxkoo are you interacting with calculating for first time or smth
I thought you're improved in modding since stuff you're doing for bad director is looks cool
or all this done bu Ruby and not you
ruby just did the planet and thats it
just because i dont know 1 context doesnt mean i dont know anything,,,,,,,,
we're here to learn cause we dont know, it's not our fault that sometimes the questions sound a lil stupid
press_play is a newish context anyways
how do i stop a card from being draggable
card.states.drag.can = false
ty
i cant figure out what's wrong for the soul to not animate
the toggle doesnt even stay on, if i press it on that screen, switch to smth else and come back, it's just off again
x in set_sprite_pos should be a number.
how do i delay played cards from going away
im trying to have the played card do the usual flip and flip back animation revealing the change, then goes to discard
but currently they just fly off after the first flip
is there an smod function to control the tutorial jimbo?
or just to have this popup
i think mod.quip_filter(SMODS.JimboQuip, string) is what you're looking for?
tells me I can't assign a string to it my bad tells me it's a nil value being assigned
even with a string
Got a unique problem. I have a card that moves to different storage sections (i.e. joker slots, consumable slots, etc.) I want an effect to happen the moment it switches to a new slot type. How could I do that, and are there any examples of something similar?
put the code for the effect right next to the code for it moving?
Okay, thanks for the tip
well it's something just ripped the code from the vanilla game lol
just can't get the text box to appear
if not whitelist[user:lower()] then return end
if is_on_cooldown() then return end
if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
local Jimbo = nil
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 2.5,
blocking = false,
func = (function()
if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
Jimbo = Card_Character({x = 0, y = 5})
Jimbo.ui_object_updated = true
Jimbo:add_speech_bubble(text_to_show, nil, {quip = true})
Jimbo:say_stuff(1)
return true
end)
}))
end```
closes I can get
text doesn't seem to want to appear
even with default speech bubble from the vanilla game
ngl, i have no idea how to help beyond what i've already said
i never played around with it myself
good luck bro
I can get everything to work but the text
can't seem to pass the text from chat to the bubble like attention text does
do SMODS.Joker
like to a mod?
Again
you put another SMODS.Joker
yeah
Why didnt you just test it...
eris why are you hearts
i lack braincells that's why
nah it didn't add
what's your other jokers key
so like
name of the joker all lowercase
"swordy" for sword or "skate" for skateboard?
Just do whatever you want the actual key doesnt matter in the end
Did you put the correct atlas key
your description string is closed right
What
i assume this is incorrect
well
help me im scared
whats your atlas key
this is prolly wrong
it was cut off in the first screenshot
Well ueah but that would crash on load not on collection
sword.png (like the file name)
fair
oh
Not path
Have you made an SMODS.Atlas for your image?
i may have fixed it
ok
it's in the game
but the decal is gone
not like the default one
it's just
gone
show us your SMODS.Atlas
is the atlas on the joker also skate
yeah
your image is probably just white there then
you need to put art there for it to show up
no i have art in my folder for it
show image
pos should be 0, 0 not 1, 0
also why not reuse the same atlas for both
no
oh
theyre both 0, 0 because its the top left
what
if you combined the atlases one would be 0, 0 and one would be 1, 0
yeah
so smods.destroycard not work on Jimbo?
if not whitelist[user:lower()] then return end
if is_on_cooldown() then return end
local Jimbo = nil
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = (function(_,text_to_show)
if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
Jimbo = Card_Character({x = 0, y = 5})
Jimbo:add_speech_bubble(text_to_show, 'bm')
Jimbo:say_stuff(5)
SMODS.destroy_cards(Jimbo, nil, nil)
delay(0.30)
return true
end)
}))
end```
still trying figure out why text won't pass through to speech bubble
i assume SMODS.destroy_cards was meant for Cards and not Card_Characters
i'll figure something out later on destroying it after the text is read later
right now just trying figure out why the box is empty
the box is empty even with vanilla dialouge
this is how i did it in hot potato if it helps
https://github.com/Balatro-Potato-Patch/Hot-Potato/blob/9709c9045ab34514af643f5d9d13089d7babd428/Jtem/events_definitions.lua#L5471
I think it has something to do with the math.random
and how it randomly selects quips
game might be looking for a list of quips under ""
instead of just displaying the text written
🐘
is there a better explanation of the SMODS.JimboQuips
the smods wiki just seems so unifinshed
Game keeps crashing with string error
the pull request contains a decent explanation https://github.com/Steamodded/smods/pull/745
silly that we have to look there for that, though
We should put together a documentation strike team
this is true
please do
key = 'example_quip',
extra = { center = G.P_CENTERS.j_hanging_chad, particle_colours = { G.C.RED, G.C.WHITE, G.C.BLACK } },
filter = function()
if next(SMODS.find_card('j_hanging_chad')) then
return true, { rarity = 100 }
end
return false
end,
loc_txt = {
['en-us'] = {
"Hanging Chad is for Chads!",
}
}
}
chat_commands.text = function(_, user, text_to_show)
if not whitelist[user:lower()] then return end
if is_on_cooldown() then return end
if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
SMODS.JimboQuips('ttv_example_quip')
end```
haven't tried passing the chat text to it yet
I am not smods staff 😭
trying make sure this is the right setup
anyone can do a pull request to the wiki repo
... which is annoying as hell to find ...
https://github.com/Steamodded/wiki there. why isn't there a link to it on the main wiki page or something
I mean yeah this is true but I feel like I shouldn’t be the one to organize such a group
Ironically
... oh there is a link. it's at the bottom of the table of contents
how long has that been there. did my adhd brain turn it into background noise again
if i knew smods better and wasnt swamped id help with documentation
its really needed
Its SMODS.JimboQuip
JimboQuips just stores the created objects
Proper quip docs are here
They just haven’t been organised into a nicer place because I don’t care for doing it 🙃
gng how would i code this: "When this Joker is Triggered OR Retriggered, Activate one of 3 effects in rotation: +30 Chips, x3 Mult, Retrigger the Joker to the Left of this Joker. When this Joker is Triggered AND Retriggered 15 times, Activate all 3 effects at once."
friend said to make this the effect for Coil but i have no idea how to do that
help
im cooked aren't i
No you just need to count the times it triggers
im still trying to figure out how to code it
would this be right for the description?
'When this Joker is triggered OR retriggered, activate one of three effects in rotation: {C:Blue} +30 Chips, {C:Red} x3 Mult, {C:Green} Retrigger Joker to the left. When this Joker is Triggered AND Retriggered 15 times, activate all 3 effects at once.'
exactly like that
in the code
Triggered and retriggered are synonymous
Yeah
What are you trying to do
doesn't matter what I do the box is always blank
trying ot pass a twitch chat message into the box
works with attention_text
me as a joker
chat should i send my placeholder art so far
im chat and i say sure
ok
i still have Subspace, Vinestaff and Coil to make
(and the 7 Swords and Dom and Valk but WE DON'T TALK ABOUT THEM YET OK?)
better than i could've done tbh
i just have the advantage of transparency and some filters
yeah
otherwise im on even ground art skill wise
like im good at taking an existing thing and editing it
but drawing things from scratch i cant do that
i have the power of mspaint and a mouse
also still better sprite than yahislop
needs a lot of work but the vision is there
if not whitelist[user:lower()] then return end
if is_on_cooldown() then return end
local Jimbo = Card_Character({center = 'j_cavendish'})
-- local holdtime = text_to_show:len() / 10
if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
G.E_MANAGER:add_event(Event({
trigger = 'after',
func = (function()
Jimbo:set_alignment{major = G.play, type = 'cm'}
attention_text({ colour = G.C.WHITE, text = text_to_show, scale = 1, hold = 8, major = Jimbo, 'bm', backdrop_colour = G.C.PURPLE })
play_sound('voice'..math.random(1, 11), G.SPEEDFACTOR*(math.random()*0.2+1), 0.5)
return true
end)}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 8,
func = function()
Jimbo:remove()
return true
end
}))
end```
sloppy but get it better later
progress
basically duck taping together my own
with create card and attention text
Can you modify consumable slots in challenge decks?
yeah
idk if there's a built in config for it, but you can always put it in the apply function
@daring fern small question apologies for the ping again, is there any way to make a card immutable with your modification script you provided? If so would it be in here or extras, the code mentions "card.config.centers.immutable" or whatever
So, don't know if this might be related to something else that might have been messed up from my issue last night with accidentally refactoring G.jokers across way too many files (I've already redownloaded lovely and smods), but now I'm having an issue where the game crashes once I try to spawn a Photograph at the end of the round using another joker. This does not happen with another mod joker that I have that spawns mod jokers at the start of a round, and it's not happening with Judgement either. I have yet to do rigorous testing for this issue on other jokers that spawn jokers, but the traceback places the source of the error at engine/object.lua , so I'm not sure if this is an issue on my end or if something is corrupted in my game files. Has anyone else experienced a similar issue?
Yes, you would put immutable = true in the definition but outside the config.
so like where id put blueprint_compatible?
Yes.
is there a way to tell if a card is juicing up?
oh i can get if card.juice is a table or not
neat
Anyone know how to make it so jokers only do stuff when you buy things from the jokers/consumable row?
And not vouchers/bosster packs too?
helpe
is the range of x and y position for a joker (NOT its atlas) roughly consistent between screen sizes?
no lmfao
the apostrophe in can't is closing the string early
escape it or use double quotes
oh ok
ah
is. there a way to know how wide and tall the users screen is in Balatro Units
How do you get the high score for your current run?
The best scoring hand for the current run
like the high score from your you win screen
sorry for interrupting, but does anyone know how functions like pseudoseed, pseudoshuffle and pseudorandom_element in misc_functions.lua work (or any resources that document how they work)? their source code is above my understanding and i couldn't find anything about them (or the random number generation techniques balatro uses) on google
it basically just uses math.random from lua but saves the seeds so they stay consistent
what specifically do you want to know?
Anyone know how to add extra stuff to the vanilla challenges?
I would assume you'd have to hook or take ownership of those objects
what are you trying to add?
im trying to re-implement some of the pseudorandom code in a different programming language (rust) and was able to at least attempt to translate some of it, but specifically the calls that look like pseudorandom_element(..., pseudoseed(...)) give me trouble, as pseudoseed returns a float between zero and one, but the second parameter to the pseudorandom element chooser is passed to math.randomseed which usually only accepts integers and according to this reddit thread is a function that works different in LuaJIT. I've just been replacing the calls to math.randomseed with rand::StdRng in rust, but that only works with u64 (integers and not floats).
just truncating the float doesnt work as explained in the thread as that will always result in zero, leading to the same element always being picked
(Example output, trying to generate the erratic deck on some random seed 7LB2WFFF)
Seeding on `erratic` yields 0.48454444595106194
Seeding rng with 0
Picking card # 41
Card { rank: Rank4, suit: Diamond, enhancement: None, edition: Base, seal: None }
Seeding on `erratic` yields 0.6072349004158222
Seeding rng with 0
Picking card # 41
Card { rank: Rank4, suit: Diamond, enhancement: None, edition: Base, seal: None }
I'm pretty sure @azure valley was looking into this exact thing recently, maybe he can help?
Not At All
however you can convert between the two
let me find the github
this function gets the exact pixel pos of the center of a card
how do I give a card a modded sticker? this doesnt work
card:add_sticker('modprefix_key', true)
how do I make a seal only score half of a cards chips? (like a 4 card scores 2 chips, 10 scores for 5 etc.)
Hook Card:get_chip_bonus
what is hooking 😭
yeah im looking at it and i dont get ANYTHING i guess i can hold off until im more experienced
@loud crescent I can def help, but I'm afk. Can you ping me sometime later tonight? About 8 hours
Thank you in advance! Im going to go sleep now, so its probably going to be a bit longer than 8 hours
local oldcardgetchipbonus = Card.get_chip_bonus
function Card:get_chip_bonus()
local g = oldcardgetchipbonus(self)
if self:get_seal() == 'modprefix_key' then g = g/2 end
return g
end
@loud crescent sitting down for a second and reading up, it seems like you're running into the same problem I did. Essentially, luajit provides a random seeding function that doesn't conform to the same API as the C random seeding function that PUC Lua uses. Instead of taking an integer it takes a double. This explains the difference between PUC Lua (and the behavior you are expecting).
See https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lib_math.c#L114
hey guyseth how do you make a random shop item freeth
local shopcard = pseudorandom_element(G.shop_jokers.cards, 'seed')
shopcard.ability.couponed = true
shopcard:set_cost()
this Did Not work.
Code?
if context.starting_shop then
local shopcard = pseudorandom_element(G.shop_jokers.cards, 'seed')
shopcard.ability.couponed = true
return {
message = "Pirated!"
}
end
try adding shopcard:set_cost()
wait what were the things for that i have not modded in like 7 years
like the things inside the brackets
the parameters? set_cost doesn't have any iirc
i got pirate flag reacted I'm So Fucking Scared.
yarr
wait then like
add it after the couponed line
you're not setting the cost to anything, you're just updating what it should be based on being coupon'd
ohhhh
also i just realized this does only the cards in the top tap of the shop how would i do like. just All of the shop.
is there such a thing as double hooking a function..
Hook Card:set_cost, because card.ability.couponed only works for boosters and cards in G.shop_jokers
Can call the original function more than once like any other function. 🧠
local scref = SMODS.score_card
function SMODS.score_card(card, context)
scref(card, context)
scref(card, context)
end
would do the function twice. Or the hook of it that may have come before yours.
why is using card.children.center:set_sprite_pos({x=1,y=0}) on a joker putting a grey rectangle behind the joker?
no colon after set_sprite_pos, only before it
oh that was a typo in typing it out here not in the code
<@&1133519078540185692> kill
oh, hm. idk then
maybe i messed up on my joker atlas or smth
-# You mean shadow?
obviously i dont mean the shadow
lol
on second glance
i seem to have left my reference image partially visible
that would probably do it
trying to get the booster to fill with vanilla jokers after all are picked up
always seems to result in jimbo
trying the i
i == 1 only makes the first one a twitch joker anything else just results in this
tried <>~ and changing the number around
or just decrease the extra var when joker pool reaches a certain limit
Question: do I have to enable pools or set them up or can I just put pools = { hamburger } in the joker and then do a SMODS.add_card({ set = 'Joker', pools = "Hamburger" }) Or is there something I'm missing, because it's spawning anything as opposed to just from the pool
doesnt seem to work properly, but i cant seem to see what exactly went wrong (jokerforge)
set sets the pool.
do you have an smods.objecttype
oh so instead I need to have set = Hamburger?
set = "Tarot",
key = "hamburger",
loc_txt = {
name = "Hamburger",
text = {
"Create a random {C:attention}Hamburger Joker{}",
"{C:inactive}(Must have room){}",
},
},
pos = { x = 0, y = 0 },
atlas = 'hamburger_1',
use = function(self, card, area, copier)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
play_sound('timpani')
SMODS.add_card({ set = 'Joker', pools = "Hamburger" })
card:juice_up(0.3, 0.5)
return true
end
}))
delay(0.6)
end,
can_use = function(self, card)
return G.jokers and #G.jokers.cards < G.jokers.config.card_limit
end,
}```
This is what I have so far, I haven't worked with consumables before so this is a first
so you want to make that tarot?
yos
actually it might just because of degeneracy hold on
SMODS.add_card{ key = 'c_[your mod's prefix]_hamburger' }
oh
when I browsed through there I couldn't find that but now I know it's there I'll look through it again thanks
THANK YOU
local cubedjoker = {
object_type = "Joker",
name = "cubedjoker",
key = "cubedjoker",
atlas = "atlas_common",
pos = { x = 1, y = 0 },
config = {
extra = {
mult = 3
}
},
rarity = 2,
unlocked = true,
discovered = false,
in_pool = function(self, args)
return false
end,
blueprint_compat = true,
perishable_compat = true,
eternal_compat = true,
loc_vars = function(self, info_queue, card)
return { vars = { number_format(card.ability.extra.mult) } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if context.other_card.get_id() == 3 then
context.other_card.ability.perma_mult = to_big(context.other_card.ability.perma_mult) or to_big(0)
context.other_card.ability.perma_mult = context.other_card.ability.perma_mult + to_big(card.ability.extra.mult)
return {
extra = { message = localize("k_upgrade_ex"), colour = G.C.mult },
card = card
}
end
end
end,
add_to_deck = function(self, card, from_debuff)
card.sell_cost = 3
end,
}
Any time I play a hand the game crashes and says that I tried to "index into local 'card' (a nil value)"
Its probably something really simple that I am just missing
am open to changing the denominator or dollar amount but what do you think of the concept itself?
I just noticed
gold stake stickers for jokers like perifishable and stuff
don't seem to work on custom joker pools?
probably a super simple question but how would you give your joker description text
that tells you what it does
when you hover over it
DONT wanna like be bugging you or anything but the card returns a really long and unrelated number and doesnt add to chips 😭
does anyone know how to stop a function from looping? (for reference im using the code above, and it gets called like 10 times in a row, which is why it returns the "unrelated" number)
Thank u :3
Try return end
At the end of the function
Usually works for me when something does a disaster loop of infinity
any tips on how to come up with ideas for jokers and stuff
i think the main issue for me is that any idea i think of i feel like its either too derivative or been done before
There's nothing wrong with being a little derivative
As long as you're not carbon copying
Eventually every idea is gonna be done
There's like several different mods that have the same ideas
anyone know how to change the splash screen ace card to like a custom joker?
wait for the next smods update and there will be a system in place to help you do that
bet
It's already in the dev build
I'm using it rn
does anyone know i would reset g after each hand? it keep the initial divison value for some reason (like after a 10 is played and divided to 5, the chip_bonus will be 5 next hand on every card)
what is the code or way to add things to hypermult= { 1 , 4 } like how would i add 1 to the 1 when i play a card
instead of it being a 1, it'd be card.ability.extra.something (where "something" is whatever you want), and you want to define something = 1 in the joker's config table.
lol
anyway then yea reference the calculate functions documentation to see how to do something whenever a card is scored
ooo and card is scored?
the answers are in the documentation that has been so kindly provided to you :)
i recommend also looking into the vanilla jokers as examples if it's easier for you to copy their stuff
(specifically, look at VanillaRemade)
alr
return {
mult = card.ability.extra.hypermult,
level_up_hand
}
would this work for hypermult?
uh no
remember, you have to return hypermult = { something, something else }
return {
mult = card.ability.extra.hypermult,
hypermult = { 1, 4},
level_up_hand
}
so this?
no mult = at all, and hypermult = { card.ability.extra.hypermult, 4 },
now you can change the number at other timing during calculation
ooooo
how would i check for extra mult? or chips
like lets say that if i play a flush
no need
returning hypermult = { 1, 4 } will always apply ^4 to the current mult value at the time that the joker triggers
working on it and so far everything else is working fine but noticed that it resets and applies a new seal when you play a card that already has a seal so added a check, but i guess i did it wrong. any solutions?
if context.full_hand[1].card.seal == nil then is the check
context.full_hand[1].card.seal
remove the .card
^ it should just be context.full_hand[1].seal
wait so it will always add +1 hyperoperator?
that did the trick @red flower @frosty rampart thanks
scoring calculations always modify the current score, it's not directly setting it
tbh i'm not sure what you're asking here
last thing before working on jokerdisplay which shouldn't be hard is "Active!" in a blue colour good for this kind of joker
thats what dna does but something like sixth sense does k_spectral
basically if i score a card will it increase the card.ability.extra.hypermult?
not yet, you have to code that yourself
again, check the calculate functions documentation to see how to get code to run whenever a card is scored
consistency with dna is good i think. my first inclination would be G.C.ATTENTION because seals don't have a designated color like spectrals do, but if jokerdisplay uses blue for DNA then you should use blue too
alr got it, also how would i make it display what it is currently at?
that's documented here, specifically the loc_vars section
https://github.com/Steamodded/smods/wiki/Localization
for jd dna just does a green and inactive "active!" text
i agree and go ahead and which to attention as i think that would be more accurate
loc_vars = function(self,info_queue,card)
return {
vars = { card.ability.extra.whatever }
}
end
then in localization (whether using localization files or loc_txt)
do #n#
(n being dependent in what order you put the vars, so card.ability.extra.whatever would be #1#)
alr ty
yeah like that also... also new synergy
just have scout before dna so it can apply the seal first before copying
i was inspired to have it as scout similar to how scouts get their badges
i dont know how you do this this is hella confusing
not sure if "scout," "scout joker," or "scoutmaster" is the best theme but i think this does the trick. i really like how this came out
any time i try to run balatro this comes up
SMODS.Atlas {
key = "niko",
path = "heisgod.png",
px = 71,
py = 95
}
SMODS.Joker {
key = 'joker2',
loc_txt = {
name = 'Niko who is a god',
text = {
"gives {1}4 mult, +1 hyperoperator when flush is played"
end"
}
},
config = { extra = { mult = yes } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 2,
atlas = 'niko',
pos = { x = 0, y = 0 },
cost = 2,
calculate = function(self, card, context)
-- Check if we have played a Flush before we do any scoring and increment the mult
if context.before and next(context.poker_hands['Flush']) then
card.ability.extra.hypermult = card.ability.extra.hypermult + card.ability.extra.change
return {
message = 'Upgraded!',
colour = G.C.RED
}
end
-- Add the mult in main scoring context
if context.joker_main then
return {
hypermult = {card.ability.extra.hypermult, 4}
}
end
end
}
this is the joker
why is there an end there
^ remove the end" line in your localization
also the {1} will just vanish because formatting uses "{}"
hmm okay
and also the {1} has to be {#1#}
and the mult being "yes" will just lead to nil as the variable "yes" has no value
(or nil)
AND you don't have a config for hypermult and change
yea why did you get rid of hypermult in the config 😭
heh?
i used this from the tutorial thingy calculate = function(self, card, context)
-- Check if we have played a Flush before we do any scoring and increment the mult
if context.before and next(context.poker_hands['Flush']) then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.change
return {
message = 'Upgraded!',
colour = G.C.RED
}
end
-- Add the mult in main scoring context
if context.joker_main then
return {
mult = card.ability.extra.mult
}
end
end
no like here
you used to have hypermult = 1 in here, right?
ohh no
that use to be like 98135769839832475912759871253981725
i told you to assign hypermult to something all the way up here
thats here and here
and you want to define
something = 1in the joker's config table
whats that?
you should have this:
config = { extra = {
hypermult = 1,
change = 1
} }
to properly define what those variables start at. the computer doesn't magically know that you want them to equal 1
ok im just gonna
ohhhh
if you're still struggling badly i'm just gonna do it myself 😭
i try not to just write code for ppl because i think it's important that ppl learn how to do it themselves
i dont code well even though im in a coding class in my school 😭
otherwise they'll need you to write your code for them all the time
ok true
i put the config in and the game crases on loading
i replaced it for the config i had before
ok well now you also need to update the loc_vars function, because card.ability.extra.mult doesn't exist anymore
and also put a comma after the last closing brace of the config
should i change the card.ability.extra.mult to hypermult?
think about what variables you want localization to have access to and put those variables in the table
wait whats the table?
table = array = everything inside a set of {}
(technically table does not = array, more like arrays are a subset of tables)
so basically yes
would i do level_up_highcard to level up high card when i play a card?
no
in the return table, have level_up_hand = "High Card"
that makes way more sense then what i was thinking
also for the display how do i do it again?a to make it display the hyperoperator or wtv its at?
cause rn i have this but it kinda dosent work
read the localization docs again
you put stuff in the vars table in the loc_vars function, and then access that with #n# in the text itself (where #1# is the first thing in the vars table, #2# is the second thing, etc)
vars table is the return { .... } thing right?
specifically in the loc_vars function, yes
how do i call that function?
wait like this?
no that is not at all what i was saying
you don't need to, you've already defined it
the game will call it whenever it generates the text in-game
"gives [#1#]4 mult when card is played"
oh just that?
would i put n instead of 1?
where 1 is the first thing you put in the vars table in the loc_vars function you have in this screenshot, 2 is the second thing in that table, etc
so 1 is self, and 2 is info_queue?
#n# becomes vars[n]
no
when the game localizes text, it calls the loc_vars function that you define. 1, 2, etc. is indexed from the values that are returned from that function
it can be any number of values
vars being the vars table in the table you returned from loc_vars
^^^
wait so would i put vars[#1#]4 or what?
...
return {
vars = {
"this is vars[1]",
"this is vars[2]",
"lua is implicitly indexing these with numbers"
}
}
no
just #1# is all you need to access a var
i put the brackets there because then it'll appear as gives [1]4 mult when card is played in the actual text in-game when you read it
instead of just gives 14 mult
i don't understand what you mean by "repeats it" but i'm going to say yes it calls a var
ah okay
tbc that's not any lua function, this is something thunk coded into balatro specifically
which is why it doesn't follow normal lua syntax at all
hey guys i coded this in but the game crashed D: what did I do wrong?
how would i add something that makes it so that one card can apear in shop, only when another joker is in the joker slot
ah oaky
the effect is supposed to give 200 chips if played hand contains a 2
what's the crash exactly
the error message contains a hint
why is there just a
"effect = nil" there
anyway you're missing an end in your calculate
is there a specific place I should look?
the "one card" in question should have a custom in_pool function that checks if the player owns the "another joker"
documentation source https://github.com/Steamodded/smods/wiki/SMODS.Joker
you don't need to worry about any of the arguments, just have it return next(SMODS.find_card("j_modprefix_jokerkey")) where modprefix is your mod's prefix and jokerkey is the key of the "another joker". in_pool should return true when it's allowed to spawn and false when it's not, and SMODS.find_card will find all instances of the given card that is owned by the player
alr ty
usually the part right after "oopsie doopsie the game did a fucky wucky"
the rest is for complicated problems
was just part of the sample i used
if anything = nil like that you can just remove it entirely
how do you make a varible that persits between restarts of the game?
(example)
save it
easiest way is to put it in G.SETTINGS
ah ok, here then
ill just make it a config option ig
because then you can reset it if needed
well you already sent the joker file earlier so
you're missing an end
like this?
hoky fuck
not in the slightest
i may be a tad stupid
thanks so much
isnt that what i just have?
just without the bool
no...?
im confused 😭
look at where it is and how it is written in the link
this any better?
it's a step in the right direction
you fixed where it is but not how it's written
oh my god
wait i just realized
niko who is a god dosent spawn in the first place
he dosent spawn in the first place
oof, ok so the joker is in but it isn't giving the +200 chips
-> is straight up not lua syntax
if there's no in_pool function at all, it just defaults to normal joker spawning conditions
the docs just use that to tell you what your function should return
i don't want to make someone feel bad but this is going horribly 😭
oh no dont worry im ussually this stupid
ussually i do everything possible wrong before i get it right
This joker crashes the game when any hand it scored.
The error message is "attempt to index local 'card' (a nil value)"
Probably missing something really simple
well that's not mathematically possible
there are several permutations of complete gibberish that are wrong in addition to coherent misunderstanding
it should be context.other_card:get_id(), with a colon :
Oh my god
okay true but a LOT of wrong things to get one thing right
The amount of times I have done this when coding in lua is too high to count I stg
Thank you
it might help to look at the code of some existing mods that you know to work
first priority, how do i make niko who is a god spawn in the shop in the first place
it
should already
it's an uncommon
i went through like 40+ rerolls, saw blueprint and brainstorm and about mostly everything EXCEPT niko
rng can be terrible
bad luck lmao
ok i tried by myself but i couldn't figure it out. How do you make a card like Wily Joker that checks for a specific kind of card (like a king) instead of a specific kind of hand?
so back to the thing how would i make it so that it only apears when niko who can summon a god is in your joker slots?
https://medal.tv/games/balatro/clips/m7aLhzzwY_ehORxlH also i dont think this is just bad luck
Watch Untitled by Watsontheseal and millions of other Balatro videos on Medal. #balatro
he only showed up once
in_pool = function(self, args)
return next(SMODS.find_card("j_modprefix_otherjoker"))
end,
now it crashes when i load in
aGHFHHHGNGHGHHGDBH
im guessing im missing something
put the in_pool function into "niko who is a god"
again
and you're also missing a comma
where should i put it in the niko who is a god joker?
Now I'm getting the talisman "attempt to compare number to table" error
This ended up working 😄 first joker I've ever coded myself (even if 90% of this is copied from existing lol)
use amulet instead (solves the crashes)
Alright
wait should i put it in the loc_vars?
NO
the calculate = function(self, card, context) part?
oh wait noooo
it isnt working like i thought
it's giving each 2 +200 instead of just giving +200 if hand contains a 2
no