#💻・modding-dev
1 messages · Page 575 of 1
add next(SMODS.find_card("j_modprefix_jokerkey")) to the if statement
that'll make it only trigger if you have that joker
And what would I need to add into the if statement to make it be both suits?
nothing
the card is still its original suit, and will pass is_suit checks for its original suit
all we are doing is, when the card is checked to be Spades, making it set to true regardless of the card's original suit
this won't get in the way of any other suit checks on the card
just don't do return false if your check fails
if you did that, it would override the original suit check
Would I just use suit == "Spades" in my joker then to make that work?
nope
your joker doesn't have to do anything
the suit argument is what is passed into the is_suit function for which suit to check
is_suit("Spades") returns true if the card is spades
your joker could have zero calculate code and this would still work, it just has to exist to trigger the effect
Kinda funny
yeah it works out that way sometimes
Would other jokers trigger on the cards too? Like the one's that give mult if the card is spades, for example?
yep
it affects ALL suit checks
which includes scoring
it could score in a spades flush
unless the effect is coded to check card.base.suit specifically
(in this case they'd be actively trying to avoid things like smeared joker anyway, so it's fine)
but pretty much every modded effect should use is_suit
Okay and if I wanted to make it be noticable on the card with like an effect/shader/info_queue I would do that in the joker or where?
And how?
Just say it in the description?
yeah the joker's description is good enough for vanilla standard
That should be enough to convey the information usually
smeared joker doesn't have any additional visuals
so your card doesn't need them either
alright
@wispy falcon i forgot something
you should add and not SMODS.has_no_suit(self) to the if check
so it doesn't trigger on cards with no suit i.e stone cards
unless you want it to do that?
up to you
Gonna think about that but thank you for telling me
Okay, so with the following code it should make Wrathful Joker give mult even on a club, diamond or heart when I have my joker, right?
function Card:is_suit(suit, bypass_debuff, flush_calc)
-- Code before
print("Before :O")
local ret = card_is_suit_ref(self, suit, bypass_debuff, flush_calc)
-- Code after
if self.base.suit and suit == "Spades" and next(SMODS.find_card("j_cstorm_joker_the_riveter")) and not SMODS.has_no_suit(self) then
print("Check worked >W<")
end
return ret
end
SMODS.Joker {
key = "joker_the_riveter",
pos = { x = 0, y = 0 },
rarity = "cstorm_chatter",
cost = 15,
blueprint_compat = false,
eternal_compat = true,
unlocked = true,
discovered = false,
--atlas = "chatters",
}```
yep
wait
you need to return true if the check passes
that's what makes it actually work
Damn, that's why it didn't do anything
👍
Now I know how hooking works but I still don't get what suit == "Spades" does. In my eyes it would check if the suit is spades, which it isn't so it is wrong
Like, in my eyes I would need to make it suit ~= "Spades" to make it work
suit is the argument put into the function is_suit when checking for a suit
card:is_suit("Spades") should be true if the card is spades suit
the "Spades" is a function argument
which is referred to as suit inside the function
suit == "Spades" makes it so you only override suit checks for Spades specfically
otherwise, it would override the suit checks for any suit
Ohh, I think I understand it now
Damn, hooking and patching is so useful when modding this game
it really is
you can hook any context for anything apparently by the way
on top of these other functions
ive always found lovely patching to be more annoying to deal with anyway
Guys It's not hooking
I'm saying this the 932903290130193th time 🤓
It's called making a upvalue of a lua function
I don't know how I would use that for something but that seems nice to have
it might come up one day
lovely patching is a lot of overhead, but it's still preferable when you just want to insert a line of code in the middle of a function or something. i do try to use hooks over patches whenever possible tho
If you want to do hooking you need to do debug.sethook according to the 23.2 page of the official lua documentary https://www.lua.org/pil/23.2.html 🤓
I hate searching through the code to find the exact place of a function that I need to patch
language prescriptivist 🫵
yes
how can I check if a pool exists
an smods.objecttype or whatever it's supposed to be called
if <key of objecttype> is returning nil
Did you try SMODS.ObjectTypes[...]?
what
will that return true if it exists
alright i'm really close to the thing i wanna do
but something is going wrong
It's a table of all the object types
cards["j_gros_michel"] = true would be the same as cards = { j_gros_michel = true }, right?
The former would error if cards wasn't already previously declared as a table
The latter is declaring a new table with the single key mapping in it
well yeah
assuming cards exists as an empty table
these would both result in the same outcome
sure
okay
yeah i'm lost then
i've got a table with a bunch of joker keys in it and I'm trying to convert that into an SMODS.ObjectType pool which contains all of those jokers
and I'm not sure if it is working or not
but when I try to have a booster pack use this pool, it crashes on opening the pack
which doesn't happen if I give the code an SMODS.ObjectType pool which is already set up with ["j_gros_michel"] = true inside its cards argument
so I assumed something was wrong with the pool? and if it's not that diifference then idk what it is
Hello, a friend and I are making a mod for Balatro, but we don't understand the SMODS API very well, so we don't know how to make a certain Joker in our mod create a consumable when selecting Blind, could someone help?
look at vanilla remade, cartomancer is your friend here
^
That’s literally cartomancer
and then make sure you are using a code editor with an LSP so you can see exactly what the function does and what arguments it takes
but it will create spectral card
Someone can test my mod?
GUARANA?!
please look at the vanilla remade code, it will make sense.
ok
Oh are you from the Click no Paulo?
Please dm to portuguese lol
sim
What function is used to score a playing card? I'd like to see if I can make a Joker that scores cards left in your hand even if they weren't played
Try looking at nichola from paperback 👍
ty :>
solution: It's just called SMODS:score_card()
how do I use ObjectType.inject_card(self, center)
smods wiki tells me what it does but not how to use it (as in what values to put in self and center)
if that doesn't work then I'm out of options idk what to do
i have code in my mod that dynamically inserts all my cards into an objecttype
does that help
assuming it's not done by putting pools = {poolkey = true} inside the jokers' code
this seems like it would do it
SMODS.ObjectTypes["joy_monster"]:inject_card(v)
and v is the center of the card?
yeah
gotcha
if that doesn't do it then it has to be an issue with my booster pack
yeah it didn't work
@chrome widget im going to bed because it's 1am and i feel quite sleepy, dont feelthe need to rush it at all I appreciate wnaht you are doing either way
It's okay I just got on a plane anyway 😭
do you have boosters that use those pools
Had to put my laptop away. It's nearly done, just trying to solve a crash with a delayed event in Blinds, cause I'm recreating the entire UI and there are some stale references it needs to account for
Airplane
i used to, but not anymore
hi dilly
Hi N
damn
How are you

i am hungry
Get some food
besides the UI still being there, some minor jank and the whacky boss armor scaling this is almost complete
Basically, the required score boxes just slim down and only show the blind reward, and the total round score will just be either a blank color or completely invisible
I hope your flight goes awesome winter
Whichever works to keep the original spacing
It's going fine except the babey is upset
^
Kibby
CUTE KITTY
I've tried doing it by just removing the nodes but that went terribly for obvious reasons
I have a setup from one of my own mods that sets all score fields to say ????? instead, with an effect of a randomized blind score within a range
So I'm just modifying that with what you need. Main issue is just cleaning up some nodes that other places in the code access by ID and maintaining the general tree structure so nothing breaks
I actually had all score fields say ??? at one point but the main problem was that from a design standpoint it just looked pretty bad to have it around alongside the health bar
Quick question
Is there a way to make a booster pack not have obligate you to immediately use your card, since I have some of them that can only used in certain conditions, like during an blind or something. But they are practically uselessness on booster packs and only take up space
put select_card = 'consumeables' in your booster definition
on the smods boosters wiki
is this supposed to say newCard?
regardless it's still not working I just jumped through like
3 hoops just to end up at the same crash 😭
Just that simple??
Seems like a typo
yeah i'm pretty sure it is
is there a way to make it so that the cards don't briefly slide out of existence when you grab the first one of several in a mega pack
(see videos in linked message for context)
#💻・modding-dev message
atp i'm pretty sure something is wrong with my pool
i don't really know how to debug this
I can take a look at this at some point, if there’s not an issue in GitHub, creating one would make it more likely that I remember to look at it 🤣
how would I print out the pool from its key
will do lol (later tonight)
i just wasn't totally sure if it was an issue on smods side
Hey could someone give me beginner code on how to make a rank I'm trying to make the BACE
read the documentation
https://github.com/Steamodded/smods/wiki/SMODS.Rank-and-SMODS.Suit
if you want reference code, the "unstable" mod is probably helpful
if you specificallly want bace to be able to go below a low ace or above a high ace in straights, you'll need to put in a bit of work and the "apostle" rank + auxiliary code from paperback will be very helpful
Someone help me
With lovely
toml is supposed to do what is in the image but it doesn't work
SMODS.set_scoring_calculation('add')
yea you don't need to do that through a lovely patch anymore
latest smods adds an API for custom scoring formulas
Yes.
But does this only work on the latest smods?
Yes.
trying to add a custom animated texture to be used as the back of a custom deck, but i get this error whenever i try to select the deck. i am very confused
You have to animate it manually.
oh damn ok
Didn't work, didn't even detect it
--- STEAMODDED HEADER
--- MOD_NAME: Funny ranks
--- MOD_ID: FR
--- MOD_AUTHOR: [the bunnuny]
--- MOD_DESCRIPTION: yes'.
--- PREFIX: xmpl
------------MOD CODE------------
--Atlas for extra ranks
SMODS.Atlas {
key = "rank_b_hc",
path = "rankhc.png",
px = 71,
py = 95
}
SMODS.Atlas {
key = "rank_b_ex",
path = "ranklc.png",
px = 71,
py = 95
}
SMODS.Rank {
hc_atlas = 'rank_b_hc',
lc_atlas = 'rank_b_ex',
hidden = false,
key = 'b',
card_key = 'b',
pos = { x = 0 },
nominal = 20,
next = {},
prev = { 'Ace' },
shorthand = 'Bace',
in_pool = function(self, args)
return true
end
}
Bro uses header
How do I make it so a joker makes consumables give mult? Like observatory but a joker
checking the vanillaremade code for observatory sounds like a good idea
here's how observatory does it
this makes tarots give xmult https://github.com/nh6574/JoyousSpring/blob/fefb0aa1195ee596fb978629929e40c7023ba4a9/src/jokers/09PSYFrame.lua#L363
how would i get more specific with the card i want to give mult for?
so if i wanted to only make The Sun per se give mult, how would i go about specifying that?
context.other_consumeable.config.center_key == "c_sun"
For blueprint_compat jokers, how do i have the blueprint juice during retriggers instead of the joker itself?
Fascinating that I have a consumable and I just modify the score instead of just doing something simple like that
I was going backwards this whole time
you have an extra end in your calculate function
ok thank you 🙂
What's the error message now?
no error message, just not doing anything
Your calculate function checks that card.ability.extra.active exists, but this is never defined anywhere.
You can probably just not check for that at all.
wait i think i just had to change something
you're right, card.ability.extra.active DOESN'T exist
it's supposed to be looking for card.ability.extra.xmult instead
no way jokerforge
God forbid you use jokerforge
It isn't that bad
It would be a crime not to
does anyone know why this sticker is breaking when it tries to render? i know it has something to do with it's apply/remove functions because when i comment those out it renders just fine, the issue is i don't know how to remedy that.
Code?
here's my code for the apply func:
apply = function(self, card, val)
CHAK_UTIL.mod_card_values(card.ability,{
multiply = 2,
x_protect = true,
unkeywords = {
odds = true,
Xmult_mod = true,
mult_mod = true,
chips_mod = true,
hand_add = true,
discard_sub = true,
h_mod = true,
size = true,
chip_mod = true,
h_size = true,
increase = true,
ranks = true,
targets = true,
destroyed = true
}
})
end,
how is it not crashing at launch
this is the mod card values func as well
---@param table_in table|Card
---@param config table
function CHAK_UTIL.mod_card_values(table_in, config)
if not config then config = {} end
local add = config.add or 0
local multiply = config.multiply or 1
local keywords = config.keywords or {}
local unkeyword = config.unkeywords or {}
local x_protect = config.x_protect or true -- If true and a key starts with x_ and the value is 1, it won't multiply
local reference = config.reference or table_in
local function modify_values(table_in, ref)
for k,v in pairs(table_in) do -- For key, value in the table
if type(v) == "number" then -- If it's a number
if (keywords[k] or (CHAK_UTIL.REND.table_true_size(keywords) < 1)) and not unkeyword[k] then -- If it's in the keywords, OR there's no keywords and it isn't in the unkeywords
if ref and ref[k] then -- If it exists in the reference
if not (x_protect and (CHAK_UTIL.REND.starts_with(k,"x_") or CHAK_UTIL.REND.starts_with(k,"h_x_")) and ref[k] == 1) then
table_in[k] = (ref[k] + add) * multiply -- Set it to (reference's value + add) * multiply
end
end
end
elseif type(v) == "table" then -- If it's a table
modify_values(v, ref[k]) -- Recurse for values in the table
end
end
end
if table_in == nil then
return
end
modify_values(table_in, reference)
end
with its other needed funcs
-- couple util funcs nabbed from https://github.com/RenSnek/Balatro-Rendoms :33 (nested into CHAK_UTIL to avoid compatibility issues)
CHAK_UTIL.REND = {}
--- Credit to RenSnek. Given a string `str` and a shorter string `start`, checks if the string's first `#start` characters are the same as `start`.
---@param str string
---@param start string
---@return boolean
CHAK_UTIL.REND.starts_with = function(str,start)
return str:sub(1, #start) == start
end
--- Credit to RenSnek. Given a `table` and a `value`, returns true if `value` is found in `table`.
---@param table table
---@param value any
---@return boolean
CHAK_UTIL.REND.table_contains = function(table,value)
for i = 1,#table do
if (table[i] == value) then
return true
end
end
return false
end
--- Credit to RenSnek. Given a table, returns a more accurate estimate of its size than the `#` operator.
---@param table table
---@return number
CHAK_UTIL.REND.table_true_size = function(table)
local n = 0
for k,v in pairs(table) do
n = n+1
end
return n
end
it is crash, but because returns nill
had to send it in a bunch of diff messages to avoid the character limit
yes i saw this error
but i think it should crash before even executing anything
Then....
How make mult and chips sequentially
??
return {mult = number, chips = number}
....
not numbers, messenges
Firstly, you are doubling the values every time the sticker is applied or removed.
yeah i'm aware
the sticker is meant to double the scoring ability values of the joker it's attached to
Yes, but when the sticker is removed, it would double again.
no it's multiplied by 0.5
instead of 2
No, it's not.
apply is called for application and removal.
i just did this quick and dirty for now and i'll fix that later, the main thing i'm concerned with is the rendering
Does this happen in game?
yes
awakened on the left (+8 instead of +4) and normal on the right
no visual difference at all, not even rendering the info
Have you tried printing card.ability after multiplying?
i haven't, no
the effect does work though i know for certain
returns this when you open up the sticker collection
and this is when it's applied to just a normal Joker
if you have a custom apply function for your sticker, you need to manually apply the sticker to the ability table. it only automatically does it if you don't override the apply function
after the whole mod_card_values function call, do card.ability[self.key] = val
that should fix the rendering
thank you that fixed it 
also, while i'm here, i've been having a problem where if i reference a different joker in a joker's info queue and then try to return my joker's card ability vars, i get this crash
i've been getting around this by using self.config instead of card.ability but now that i have awakened the player needs to be able to see the modified values
here's the loc_vars
loc_vars = function(self, info_queue, center)
info_queue[#info_queue+1] = {key = 'chak_ethereal', set = 'Other'}
info_queue[#info_queue + 1] = G.P_CENTERS.j_chak_joe_joker
return { vars = { card.ability.extra.Xmult_gain, card.ability.extra.Xmult_gain * (G.jokers and #G.jokers.cards or 0) + 1 } }
end,
card doesn't exist, it would be center here.
i'll change that then
How do I check if an Arcana pack has been opened?
Not on Pc so I cant properly tell but check SMODS code for context.open_booster, see what value is used to reference said opened booster
(Iirc the context name properly)
Then you can check if its an Arcana by checking its [booster_variable].config.center.kind value
if context.open_booster and context.card.config.center.kind == 'Arcana'
Thanks.
G.P_CENTERS.c_stone doesn't exist.
It would be if SMODS.has_enhancement(v, 'm_stone')
Hey thanks, but I changed the code and still nothing happened
Hey it works now, thanks! However, my original code only let it update when blind is selected. Do you know how to check for card changing updates?
What is the goal?
So I've been counting stone cards when blind is selected. I want make sure the count is updated when other events like buying a stone card or using tower also updates the count
But that doesn't sound like the calculate function
You would put it in loc_vars as well.
Is there an example I can follow/ check out?
Thank you for the resource!
Dang this chat is so helpful
I remember asking once for help with modding Minecraft in the official curse forge discord server and someone told me “if you use fabric you’re a [racial slur]” they got banned tho
Lol
what's the simplest way to add hands?
Permanent or temporary?
Temporary
ease_hands_played(number)
Thanks
context.modify_ante is a lil' Jank;
Using this: if context.modify_ante and context.ante_end and context.cardarea == G.jokers then return { modify = 1 } endWorks fine, it will Up the Ante by an Additional 1 - So; Ante goes up by 2!
... Now, if I duplicate the Joker; It'll still just add 1.
No, the Ante doesn't go up by 3, it will still be 2. :(
Is there a command in debugplus to set a poker hand level?
eval G.GAME.hands["hand"].level = number
modify = #SMODS.find_card(self.key)
First of all: Thank you
But second of all: That should not be necessary!
it also doesn't work, if yet another joker modifies the Ante-Change
You could just hook ease_ante
I'm just gonna put in a Bug report, why get a cool new Context if multiple jokers using it won't work
I used ease_ante before but wanted to use the new context x3
chat i need to debug a joker pool and I don't know what to do
something is wrong with it and it crashes when I try to create a joker using the pool (specifically in a booster pack)
but I don't know how to figure out what's wrong with it
What's the crash
something is wrong with the pool or the cards defined in said pool, it crashes like this every time I try to create a joker using one of the pools
Is the pool key matching in both places
I don't know how to print out or check the pool to make sure it's being defined properly
but the pool key is matching
Are you sure
You could print out SMODS.ObjectTypes["pool_key"]
i've got code here that sorts every joker into lists based on which mod they come from (sorting by mod prefix) and then it should be putting those jokers into pools organised by mod
i'll see what comes up when I do that
https://github.com/Steamodded/smods/issues/976 😭 how did this even get in
So the pool key you gave it is probably invalid
the pool key is valid
Or the pool wasn't initialized
I'm guessing the pool wasn't properly initialized
i put some print statements in to check where it breaks
ah
the second for loop just isn't running at all
I think I've solved it?
moved an end
nope it's still not running
hmmm
I think I figured it out for real this time
I was using ipairs instead of pairs
progress
got a different crash
it's because of
SMODS.ObjectTypes["cura_curated_pack_pool_" .. value.DisplayName]:inject_card(G.P_CENTERS[value2])
this line
DisplayName exists and value2 is the key of a joker
so I'm not really sure what's going wrong here
oh wait no I know what it is
That usually means a key joker key is invalid
it's because I changed the application method
but I didn't fully change it
new crash with information in it
i'm lost now
feels like i got closer but it's still not working
the pool isn't empty I'm defining it with splash as a default joker so it doesn't break anything
so I don't know why it's complaining about empty pool
i think the default is not actually inserted into the pool
well it is
for _, value in pairs(Curator.joker_table) do
if value.Jokers then
SMODS.ObjectType({
key = "cura_curated_pack_pool_" .. value.DisplayName,
default = "j_splash", ---I like splash way more than jimbo
cards = {
["j_splash"] = true
}
})
for index, value2 in pairs(value.Jokers) do
print("c")
SMODS.ObjectTypes["cura_curated_pack_pool_" .. value.DisplayName]:inject_card(G.P_CENTERS[value2])
end
end
end
current code block
OH RIGHT
it has to be = true
my mistake
yeah
i dont think that was the problem tho
yeah it did the same crash
a pool can be empty when you inject cards, that crash is usually because it cant find it
how would it not be able to find it
the concatenated keys should be the same for both instances here
🙃
i tried something similar and it just seems like it doesnt like creating and inserting into an objecttype at runtime
or at least not immediately
this code is being run when a run begins
in game:start_run hook
cause I thought it might miss some jokers if I did it during initialization unless my mod loads last
if you do it in a hook the load order doesnt matter
yeah thats the idea
and it doesn't miss any jokers that way but is that what's making it crash
no i mean in a hook on initialization, i think creating objecttypes at the start of the run is probably not good lol
oh
so how do I make it not crash
oh i found it i think
try doing SMODS.ObjectTypes["cura_curated_pack_pool_" .. value.DisplayName]:inject() before the last loop
mk
it seems to have worked
no crash starting a run
holy shit it works
this is amazing
thank you n the balatro game
I now have a pack that only contains jokers from a randomly selected mod
that is 2/3rds of the content
letsgo
now I need to make a text input
so I can make a pack where you can select a mod for it to pull from
ui code 😭
it shouldnt be too bad yeah
i also want it to recreate the text input if you put in an invalid mod ID
or one which is on the blacklist
but that's the easy part
alright
where can I find a UI popup text input
that isn't from cryptid's POINTER://
that's the only one I know
I want it to be like pointer but cryptid's code confuses and overwhelms me
i think you just do the
create_uibox_generic_definition() or whatever that function is called and call G.overlay_menu with that
or some Shit
oh
i got my config UI from somewhere and copy pasted it into all my mods that use config
i'll still look at the pointer code just in case it's somehow readable
i think it was fine
it doesn't look tooooooooo bad
how do I display a deck when you do an achievement? Similarly to how the vanilla game does it by displaying the deck you unlocked on the side. IIRC it replaces the trophy icon. Not sure if it was just a static image or a full on deck tho so i could be making shit up
how do I change a specific blind's size other than using G.GAME.blind.chips = G.GAME.blind.chips / 2?
yeah no i can't figure out UIbox
What's the thing you don't understand
yes
-# all of it
What do you want to use it for
I want it to allow you to input a mod ID when you click on my booster pack
the booster pack will then create jokers from the mod whose ID you put in
Oh so you want a general UI thing
I have all of the other code working I just need a UI box where you can type in a value
I can hook card:click() for a trigger to make the UI box appear so it's
just the UI box code
I'm not sure if a text input or just a few buttons would work better
the ideal solution would be to open a list of every mod that has jokers
and let the player click on a mod
Oh damn
but I don't know how to do that in a concise and readable way
and UI code confuses me in general
I don't know how to do that too
Why are you looking for a different way to do it?
G.GAME.blind.chips = math.floor(G.GAME.blind.chips - G.GAME.blind.chips * 0.5)
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
idk what your problem is with that code but this is the code I use to change blind size mid-blind
math.floor +0.5 rounds it cause decimals are ugly
The best thing you can do when figuring out UI is to figure out each step of the process separately. It's not complicated, but the way UI works is very obscured due to it being such a giant chain of functions
I use recalculate alongside this as well but I don't think it's necessary? Been a while since I worked on something like this so idk anymore
*and tables
is there any good documentation on it
I was prolly missing the number format
thanks
Not really, there is definitely info out there, but it's not that great at helping with more complex UI
more complex no
The issue with it, in my experience, is that most people that have made complicated UI things still don't feel comfortable enough with writing documentation, because there's so many asterixes to keep in mind.
Making UI pop up is a doable step, though
Making UI have you type in an entry is also doable
I don't need anything too complicated yeah
its fairly similar to html from what ive seen, theres a ton of very far nested things but thats about it. you just need to know how to read it to get started
I can do normalising and verifying the input later but I just
don't know where to start on the UI box
I really recommend trying to find the minimal functionality that you can test, and just try and get that working first. That's how I've started with more complex UI stuff. What's the specific stuff with UIBox you're running into?
cryptid's pointer didn't really help, when I tried to use code in its format it gave me cryptid crashes as if it was running cryptid code
As UIbox is basically just a container that gets drawn on the screen that you can stuff with UI nodes
I haven't gotten very far at all
making a popup is as simple as
G.FUNCS.overlay_menu({
definition = ...
})
attempted to repurpose pointer code and got startup crashes that were located inside cryptid's code.lua file
I don't even use cryptid in my mods
where the definition is the table crap
Cryptid's generally a bad mod to base things off of. The newer code that's more conventional still really relies on older code that does stuff you don't need to do that's just there to make things more complicated, haha
I do quite a bit
Have you been able to make a pop up menu without the text entry box?
not quite yet
attempting now with this
https://github.com/icyethics/Kino/blob/main/src/spell_UI_popup.lua
It's a lengthy chunk of code, so it might not be the best example, but this is for a menu I display in Kino when you press 's'
I put this in main.lua and it didn't work
Oops! The game crashed:
[SMODS _ "src/game_object.lua"]:3720: attempt to index field 'GAME' (a nil value)
https://github.com/icyethics/Kino/blob/main/src/spellslinger_deck_UI.lua
This is just drawing UI straight onto the screen, without it being a menu of any sort, to help with UI for a specific deck
okay I think I broke something
and I know what broke and why it broke
I think I accidentally copied the cryptid folder into the folder of another mod
Does anyone know how to use SMODS.set_scoring_calculation('add') correctly?
Yes, you need to do it while in a game.
How?
I just put it on main.lua alone, from what I understood it would work :/
yeah.. you should call the function when you want it to happen generally
not just. somewhere random
I want it to always be plus, how can I do that? I don't know much about it, sorry
you need to hook one of the functions that run at the start of the game
can anyone provide a link to that one moddedvanilla repository with some faq as the wiki? can't find it
or that
https://github.com/nh6574/VanillaRemade/blob/main/VanillaRemade.lua i assume youre talking about this one
yeah thats it thanks! (for future reference for me, im gonna put moddedvanilla modding faq vanillaremade here)
no
it feels like it's trying to make one appear, and the screen shakes as though one should appear
but nothing shows up
here's what i do, replace "expo_ecalc" with "add"
I assume that's because I haven't actually put a UI box into the definition yet
function Curator.create_uibox_selector(card)
G.FUNCS.overlay_menu({
definition = {}
})
end
definition is supposed to have stuff in it
but it's not crashing so I think that's progress
That is progress
I'd make the simplest UI at first, as in just display a white square
Haha, yeah good question
for that part I think this explains it well https://github.com/Steamodded/smods/wiki/UI-Guide
you can copy the examples and put it in the definition
Hi N and Ice
hewwo
I don't have time to rn to go into detail, so I'd check out the two files I linked above, and the smods documentation! If no one else manages to help you figure it out, and you're still having problems in a few hours, or tomorrow, feel free to ping me!
👍
nothing is happening still
I put the example node into the definition
function Curator.create_uibox_selector(card)
G.FUNCS.overlay_menu({
definition = {
{
n = G.UIT.C,
config = { align = "cm", padding = 0.1 },
nodes = {
{ n = G.UIT.T, config = { text = "Hello, world!", colour = G.C.UI.TEXT_LIGHT, scale = 0.5 } }
}
}
}
})
end
the screen shakes again but it doesn't come up with anything
i assume it's either closing instantly or not opening at all but it's trying to do something
most of the time i use create_UIBox_generic_options to deal with popup-related stuff. it might not fit what you need, but it works. here's an example
G.FUNCS.overlay_menu({
definition = create_UIBox_generic_options({
contents = {
{ n = G.UIT.R, config = { minw = 1, minh = 1, colour = G.C.WHITE } } --- Creates a white box
}
})
})
from this i can conclude I was using definition wrong
i just realized you had a nested table
new crash
i might've found the cause
there is a white box
OK
I don't want there to be a back button though
progress 🎉
will there be a center button though 🔥
no_back=true
add an option no_back = true on create_UIBox_generic_options
gotcha
im not sure what im doing wrong here, im trying to make a deck which has a 1 in 2 chance for each card to turn into a stone card at the start of the game, right now im doing this by destroying cards and then adding a new stone card in their place (I'm assuming you can just change the enhancement but i couldnt find anything about that in the documentation), the issue is that it just freezes on this screen now whenever i start the game with the deck
what am i doing wrong here
so that's what no_back does
your event needs to return true
use set_ability instead of destroying and creating, also events loop until returning true
ok so like should i just put return true at the end of the loop or
so I need three nodes in a vertical column
and then the bottom node needs to be a row that contains two nodes
just return true at the end of the event
I can probably do that now
idk how to turn the nodes into buttons yet
ok that worked thx
Formatting is for cowards
formatting is for people who like to be able to read their own code imo
you can set a button attribute in the node's config that points to one of the G.FUNCS. the UIBox_button helps with formatting the UI
what did you mean by set ability, like SMODS.set_ability("m_stone")?
no, card:set_ability(G.P_CENTERS["m_stone"])
card:set_ability('m_stone') should do, no?
idk
worked thx
vanillaremade does G.P_CENTERS["m_stone"] so i just do that
it does?
well this isn't what I wanted
i will change it
share your ui code
hmm
it does for the tarots iirc
function Curator.create_uibox_selector(card)
G.FUNCS.overlay_menu({
definition = create_UIBox_generic_options({
no_back = true,
contents = {
{
n = G.UIT.C,
config = { minw = 1, minh = 1, colour = G.C.BLUE, padding = 0.15 },
nodes = {
{ n = G.UIT.R, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } },
{ n = G.UIT.R, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } },
{
n = G.UIT.R,
config = { minw = 1, minh = 1, colour = G.C.BLUE, padding = 0.15 },
nodes = {
{ n = G.UIT.R, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } },
{ n = G.UIT.R, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } }
}
}
}
}
}
})
})
end
yeah
I want it to have three rows in a column
the bottom row should have 2 squares next to each other
and the top two should have 1 square only
everything just showed up in one column
you'll need to alternate between column, row, column
n = G.UIT.C,
config = { minw = 1, minh = 1, colour = G.C.BLUE, padding = 0.15 },
nodes = {
--- ...
{
n = G.UIT.R,
config = { minw = 1, minh = 1, colour = G.C.BLUE, padding = 0.15 },
nodes = {
--- change these to column
{ n = G.UIT.C, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } },
{ n = G.UIT.C, config = { minw = 1, minh = 1, colour = G.C.WHITE, padding = 0.15 } }
}
}
}
nice
yeah, remove the colour = G.C.BLUE
do vouchers in packs work as is or do they require extra code to work there?
alright
check reverie's anything packs, MultiPack's Blank Packs or betmma's voucher packs mod
all of those have vouchers in them and they seem to work
betmma probably did something insane and unnecessary to it though
alright multipack literally has one instance of the word voucher in the entirety of its only code file so i assume its fine then
now I want the top box to display text
h
h
add a text node. set the config to atleast have a text and scale attribute. example:
{ n = G.UIT.T, config = { text = 'Hello', colour = G.C.BLACK, scale = 0.4 } }
oh this isn't so bad
there is text on the screen
the documentation has an example for buttons they don't seem so bad
question is how do I detect when a button is pressed
<@&1133519078540185692>
make a G.FUNCS.my_function function. in your ui node / UIBox_button, add button = 'my_function'
ahh
so that function runs when you press the button named that
UI code really wasn't as bad as I thought lol
it just looks daunting but it's not too bad to make simple things with
yes
mk
the hard part is making it look like an actual balatro menu
new thing
i want those boxes to be centered
try adding an align = 'cm' in your dark node
you should also add r = 0.1, emboss = true to them if they're buttons iirc
what do those values do
you can see what the values does in the documentation https://github.com/Steamodded/smods/wiki/UI-Guide#node-configuration
yep
well
what does contrast do in ease_background_colour?
is this balanced enough
what's missing?
the buttons don't look like buttons (that can wait) and I want them to close the UI when pressed
also there's no text appearing on them but I did put text nodes there
to close the overlay, call G.FUNCS.exit_overlay_menu()
can you show part of the ui code?
{
n = G.UIT.R,
config = { minw = 1, minh = 1, colour = HEX("1e2b2d"), padding = 0.15, align = 'cm' },
nodes = {
{
n = G.UIT.C,
config = { minw = 1, minh = 1, colour = HEX("3a5055"), padding = 0.15 },
nodes = {
{
n = G.UIT.C,
config = { button = "cura_confirm", r = 0.1, emboss = 0.05 },
nodes = {
{ n = G.UIT.T, config = { text = localize("k_cura_confirm"), color = HEX("FFFFFF") } }
}
}
}
},
{
n = G.UIT.C,
config = { minw = 1, minh = 1, colour = HEX("3a5055"), padding = 0.15 },
nodes = {
{
n = G.UIT.C,
config = { button = "cura_confirm_previous", r = 0.1, emboss = 0.05 },
nodes = {
{ n = G.UIT.T, config = { text = localize("k_cura_last_confirm"), color = HEX("FFFFFF") } }
}
}
}
}
}
}
these are the button nodes right now
text nodes need a scale attribute
oh right
the text is now appearing
and I want the text to be centered
it's too high up right now
add align = 'cm' again. in this case try adding it in the node with colour = HEX("3a5055")
cm means center middle, it does both
gotcha
as per the smods ui guide:
this is getting somewhere
the buttons work and close the UI as they should, issue is you can press esc to close the menu without putting anything in
I'm not exactly against that but I'd want it to unhighlight everything if you do
because this is a UI box that will activate when you click on a pack, and said pack requires this input or it'll crash when obtained
I know how to unhighlight, but how do I figure out if they closed the UI box with esc?
if it unhighlights on exit, then you can't buy the pack (or pick it from a MultiPack or such) without putting anything in
which solves the crash
but I can't have it unhighlight on exit for everything, because then it'll do that on the buttons and you can never buy the pack
does esc just call G.FUNCS.exit_overlay_menu()
yeah
G.shop_booster
why does this keep saying "attempt to compare number with table" on the line with "if discriminant >= 0 then" ```calculate = function(self, card, context)
if context.joker_main then
local a = G.GAME.current_round.hands_left or 0
local b = G.GAME.current_round.discards_left or 0
local c = G.GAME.dollars or 0
local sol1, sol2 = 1, 1
if a ~= 0 then
local discriminant = b*b - 4*a*c
print(string.format("[Quadratic Joker] a=%d, b=%d, c=%d, discriminant=%d", a, b, c, discriminant))
if discriminant >= 0 then``` and it's because of G.GAME.dollars, when doing eval G.GAME.dollars in the console it prints the number just fine but when trying to use it to calculate it breaks everything, and if i do tonumber(G.GAME.dollars) it returns 0 for some reason
do you have talisman
yes
thats why
damm but why?
talisman replaces most numbers with table
all 6s
can you not unhighlight shop or booster like this
uhh that looks right for me
it crashed on the G.shop:unhighlight_all()
ok yeah just putting the to_big() solved it thankssss
G.shop is an UIBox
oh
yeah no I need the card areas
but you don't have to do G.hand.cards when you do it for G.hand:unhighlight_all()
G.shop_jokers -- Main shop area for Jokers, Consumables, Playing Cards, etc.
G.shop_booster -- Shop area for Booster packs
G.shop_vouchers -- Shop area for Vouchers
ah
okay it works now
wonderful
the buttons need one more functionality thing
okay well
the text misaligned itself I can align it I know how to do that
but now clicking the buttons works anywhere in the box instead of just on the text
is everything working?
not quite
there is 1 functionality thing I have left to do
which is to turn the white box in the center into a text input
(i also need to center the text on the buttons and the title)
(putting align = "cm" in the text nodes didn't work, but I needed to resize the buttons to fill the boxes to make them easier to click, and that broke the alignment)
i'm guessing I have to put an additional empty node
which is centered inside the button
and then put the text inside that?
use a create_text_input function. provide a ref_table and ref_value where the value will go to.
you can see more options for that function here https://github.com/frostice482/balatro-lsp/blob/master/functions/UI_definitions.lua#L244
replace the white input box node with the create_text_input one
yes, its a function, you call it
where in the node do I call it
{ ..., nodes = { create_text_input(...) } }
gotcha
Text input is weird thing
how would you randomize the enhancement given by this
also how would you set the edition/seals using this too?
Particulary buggy for some reason
poll_enhancement, poll_seal and poll_edition
thx
so what is ref_table supposed to be
ref_value is the place where the value goes after it has been entered I can get that much
because of the way lua works the functions need to get a value from a table by doing ref_table[ref_value]
its a table where the value will go to. ref_value is the attribute name.
example:
local data = {}
create_text_input({ ref_table = data, ref_value = 'input' })
you then access it later with data.input
and what's hooked_colour for
the rest I can get the idea of
its the background color to set when typing
mk
you might not need it, its not required
i'll put one in and see if I like the way it looks
new crash
current UI code
I put both buttons inside an extra node to try to center their text but also added the text input
i got that crash too when trying.
so you'll need to provide initial string value for your ref_table, an empty string will work
okay
in this case, local data = { input = '' }
well the text didn't center on the two buttons but the input works now
and I want the enter mod ID text to also be centered but it's not doing that either
functionally speaking this is all working now
and this is amazing
Set the align of the button
I did
it has align = "cm"
wait no it doesn't
you're so right
that aligned the text
i'd recommend making your button uis a function so you can maintain it easier
now I gotta make the buttons looks like balatro buttons
how do I go about that
Just put a colour on that column node that is your button
oh also the Enter Mod ID text doesn't appear until you click into the text input box?
i would take out these button structure and put it in a function, since mostly it is a repeated structure. the only difference is the button and the button text. you can make it as a function parameter
its up to you
I should really do that in case I want to use buttons in the future again (I do)
do I just copy that code block into a function and swap out the button key and text for function inputs?
I hate expanded UI code so much lol
is it that easy
i wanted to condense it, but vscode keeps expanding it every time I click format document
so I just kinda let it be
smh using auto formatting instead of just formatting correctly yourself
im not sure about that one
auto formatting saves me so much time
but, it would look something like:
I see
this is just advice from someone who doesn't like nesting while also maintained big ui code 😅
it's really nice to have them in functions
this mod probably won't use any other buttons but I will use my satanic user interface manifesting abilities for other shenanigans later
yeah that made the code I have to look at way smaller
What are you cooking Marie?
a mod that has packs which contain jokers from specific mods
Ooh neat
it has some packs which choose random mods and I'm making a UI where you can input a chosen mod for a more expensive pack
How do you know which mod the booster has?
gotta do a bit more polish and then actually make pack art
it says so on its info_queue
Neat
it's selected during set_ability if it's random
otherwise it is selected in the UI box when you click on the selector pack
the hardest part about this mod is going to be the pack art
Making every pack SDM_0's Stuff one 💪 🔥
tbch
I still need to normalise the entered value and check it against the blacklist
but that's not so bad
I also need to exclude legendaries
-# putting that in a config
right now I gotta figure out why the top text node won't show up until you click into the text entry field
the enter mod id one?
yeah
oh thats weird
i just made the buttons look a million times better
the space for the text is still there
but the text doesn't appear until I click the text box
Mystery mod
you can remove minw and minh
nevermind, i thought you meant the spacing was too large
the spacing is fine
it's just that the Enter Mod ID text does not appear until you click the text entry field
i have no clue currently
🤔
try adding G.OVERLAY_MENU:recalculate() after G.FUNCS.overlay_menu(...)
here?
no, at the bottom
G.FUNCS.overlay_menu({
-- stuff
})
G.OVERLAY_MENU:recalculate()
trust
mk
that worked
I think that's everything then
I might change the button colors or give them an outline I'll mess with the styling
functiionality wise it's all good
I appreciate all the help on the UI
it really wasn't as bad as I thought it would be though
it looked bad in code
yeah
this just makes ankh not delete any joker's instead of any other joker type can someone tell me why for k, v in pairs(deletable_jokers) do if v ~= chosen_joker and v.config.center.id ~= chosen_joker.config.center.id then v:start_dissolve(nil, _first_dissolve) _first_dissolve = true end end
it's v.config.center.key
thanks
now it's just vanilla ankh
what's the code
the entire ankh code or this snippet?
this snippet with what you changed
it's ``` for k, v in pairs(deletable_jokers) do
if v ~= chosen_joker and v.config.center.key ~= chosen_joker.config.center.id then
v:start_dissolve(nil, _first_dissolve)
_first_dissolve = true
end
end
did you also change chosen_joker.config.center.id to chosen_joker.config.center.key
the other id should be key too
ok
yuup
why if I may ask?
id doesnt exist
because thats just what the variable is called
to make a deck how do i remove a certain rank (aces)
get normalised
with the british spelling specifically
I feel like line 140 is incorrect somehow, but I don't know exactly.
context doesnt exist in redeem because its the voucher equivalent of use
use calculate instead
anyone know how to attach localisation to a malverk pack
This work?
yes
is it not context.other_card
i would be annoyed if it was context.card because that's inconsistent
other_card is usually for scoring related effects
but yeah i agree on it being inconsistent though i assume its also thunk code
how can i flip cards like when theyre enhanced by certain tarots
:flip()
code?
i dunno whats causing it tbh, is it this joker?
its the most recent ive written
it happens after i enter the shop
wtf???!!!
splash shows up in every pack because I needed a default joker across all packs as a fallback and I like splash way better than jimbo
bearing that in mind check this shit out
this is the coolest thing i've done all week
Video doesn't load for me 😔
amazing
aww
Is there a way to dynamically change a card’s rarity with cross-mod content? Like, normally it’s a legendary but if Cryptid is installed, it’s an Exotic?
hmm can i make a joker break like a glass card
Can't forget splash from SDM_0's Stuff ⛈️
i had to include a default joker okay
You can use play_sound to play the glass sound during it's destruction ig
it was easiest to just make it splash for every pool
what's the sound if you may know, i wanted to do that but couldnt figure the name out
shatter iirc
ty
alright chat
I need to get the rarity of a joker from its key
I know I start with G.P_CENTERS["key"] but where in there is the rarity
anyone know a malverk mod where i can check if i got these right
that.config.center.rarity?
Wait I dont think config.center is needed whenr referencing from G.P_CENTERS? Idr
Should be G.P_CENTERS["key"].rarity which should give the rarity as a number value.
That's what I thought oops
oops all 6s
Can i remove system folders ? Like mods ?
You can remove mods from your mod folder if that's your question
os.remove ?
define a local variable outside SMODS.Joker that contains the correct rarity depending on if the other mod is active, then inside the joker definition set rarity to that variable
minty check out my cool pack
My question is can you make a joker that deletes folders if possible
yeah, but why tho
Hatred and despair
I thought you can’t tho
thank you
you can
Got it, thanks!

cool pack, you say? 
^
another locust done, only 20 more to go
oh that is neat
Pushing 20 already
i have to make one for every spectral and tarot
sadge
Make death alternative good please
i already made death
Can i see
Also i will accept condolences
I just lost my 50 50
the sprite is unfortunately a placeholder but that's the general effect
crashed after using high priestiess
yeah and it's trash what do you want from me
What’s the theme you’re going with
Ik i’m just saying
something close to t. apollyon but i'm really bad with art so these will be placeholders for a while
it tried to create a planet card based on the hand Royal Flush?
though it seems to have been set up as an example hand
I see
yeah i figured, i forgot to delete an example planet
that'll do it
i can show you the rest of the locusts if you wanna see which direction im taking the deck in
Okay send me in dms
i think i can draw something
does psuedorandom accept the current run's seed?
anyone know why the malverk pack wont apply the localisation file?
default.lua is the localisation and the other one is the main file
card:shatter()
thank you
how should i make my psuedorandom seeds work
because i want the jokers' effects to remain consistent along one seed
but still be able to spit out a "random" value on new seeds
that's... usually how things work
pseudorandom is made to respect seeds yeah
no like
you don't need to do anything fancy with the seed
the seed entered into pseudorandom is for the pseudorandom function to use
it shouldn't be doing that
What does your code look like right now? Or at least the part where you use pseudorandom.
you should use a string as seed
oh
it gets converted to a number but also accepts numbers directly
how would I make a card:click() hook activate only when you select something and not when you deselect it
i already have it activating when you click on a specific thing
but the conversion to a number is where the seed gets factored in
check if it's highlighted?
what's the table for highlighted cards
<CardArea>.highlighted
mkay
i don't recall if there's an easier way
card.highlighted is a thing
yea i was about to mention that
i thought it was, i'm just slow and had to check
Is there a context for individually triggering an effect per Joker? Like context.individual but for Jokers.
what do you mean by that
if you want it like baseball card, context.other_joker is what you want I think
Like say i want a Joker to have each other Joker give chips but only when they would normally trigger.
yeah context.other_joker then
thats
not that
post_trigger is for when another joker triggers
but you gotta enable that first in optional features
help i am small brained and require help loll
if anyone has good knowledge of malverk
the files
me when i see something i implemented word for word in a private repo i can't access anymore so i can't help
hi im not great with coding at all but working on a project, how do i modify a deck to be able to start with jokers? (for example starting with square joker and splash on red deck)
b_red= {name = "Red Deck", stake = 1, unlocked = true,order = 1, pos = {x=0,y=0}, set = "Back", config = {discards = 1, discovered = true},
Use Takeownership or lovely patches
And insert SMODS.Add_card into the code
script lets you just run lua code on run start which should probably be good enough for what you need https://github.com/lord-ruby/Script
decks can have config.jokers set as an array of joker keys
How would I make a consumable that does +50% on a selected joker's chips?
i feel like we've explained something similar to this to you before
joker value manipulation is not an easy task, especially if you want to edit a specific config variable. you can make assumptions about where the joker's +Chips is stored, but someone could come along and have a joker where they store the chips in card.ability.extra.obnoxious and you can't do shit about that
Right, I remember
But couldn't I patch/hook something to get what return chips? Like what is used in the Joker for chips =
Smods.calculate_effect?
What is that for?
I want to throw myself into an industrial incinerator
You wanna know what took the longest out of this description?
THE COLOUR
IT TOOK 1 HOUR TO PICK IT CORRECTLY
BECAUSE IT WAS A mix_colours()
(for the recursive description boxes)
But couldn't I patch/hook something
What the...
Non Euclidean spaces in balatro
Got it. That's in the smods files though, right?
what?
Why did i say Minecraft