#💻・modding-dev

1 messages · Page 663 of 1

astral pine
#

Thank you!

sour garden
#

trying to make a blind that reduces the chips of the scored hand by 225 (min of 5) before the final score is calculated. this subtracts the chips visually, but then it immediately jumps back to what is was before?

calculate = function(self, blind, context)
        if not blind.disabled and context.final_scoring_step then
            G.E_MANAGER:add_event(Event({
                trigger = 'after',
                delay = 0.4,
                func = function()
                    G.GAME.current_round.current_hand.chips = math.min(G.GAME.current_round.current_hand.chips - 225, 5)
                    return true
                end
            }))
        end
    end
daring fern
tall void
#

hey guys someone have any guide or tips to start learning how to dev mod on balatro?

clear ocean
#

which kind of context is needed to make a matador like joker that gains xmult

#

context.before doesn't work either

wild patrol
#

I think matador just checks if it's a specific boss and if the debuff or discard triggers lol

#

Which is why it barely works right

faint yacht
#

context.debuffed_hand or G.GAME.blind.triggered and context.joker_main mimic the behavior pretty much.

red flower
#

why would you make another matador

primal robin
#

I need a help. I need a code which causes stack overflow but not closes the game instantly

kindred niche
#

Do you mean the optional features? I have retrigger enabled

frozen hamlet
#
SMODS.Sound({key = "song", path = "song.ogg",})
SMODS.Sound({
    key = "song", 
    path = "song.ogg",
    pitch = 0.7,
    volume = 0.6,
})

SMODS.Atlas{
    key = 'Jokers5',
    path = 'Jokers5.png',
    px = 71,
    py = 95,
}


SMODS.Joker{
    key = 'xico',
    loc_txt = {
        name = 'xico khaled',
        text = {
            "xico khaled on the {C:attention}BEAT",
            "{C:inactive}compralo para ver que es lo que hace"
            
        }
    },

    atlas = 'Jokers5',
    rarity = 2,
    cost = 5,

    unlocked = true,
    discovered = true,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = false,

    pos = { x = 0, y = 0 },

    config = {
        extra = { }
    },
    calculate = function(self, card, context)
        if context.setting_blind or context.joker_main then
            
            return {
                sound = "song",
                message = "XICO KHALED ON THE BEAT",

            }
        end
    end,
}
daring fern
red flower
wanton jolt
#

oh yeah that too

kindred niche
wanton jolt
#

it should be modname_song

#

on ur joker code

#

but i believe the crash itself was due to the wrong location of ur sound

daring fern
kindred niche
frozen hamlet
red flower
#

no

wanton jolt
#

no

frozen hamlet
#

damn

red flower
#

also you're defining the sound twice

wanton jolt
#

joker code,
sound = "cocosmod_song"

#

the crash is because since u didnt put modname it was looking for the audio in the vanilla assets folder

frozen hamlet
#

is there are another requirements for a .ogg file for modding ? because its now say "Could not read Ogg bitstream"

wanton jolt
#

are oggs supported? i've seen wav and mp3 working

#

also midi but i think that was converted to mp3

red flower
wanton jolt
#

lol

#

woops

#

is the ogg file fine

#

can u play it by itself

frozen hamlet
#

yeah

#

i open it from the files the song.ogg and its plays well

frozen hamlet
#

its work thank you both

faint yacht
#

-# I should probably include .xm songs some time.

thorn ingot
#

Guys.
Is it possible to add required score scaling by .5?

wild patrol
#

Yeah

thorn ingot
#

Thanks, I kind of missed it. 😅

granite raptor
#

for smods.has_any_suit, does that mean "counts as any suit" like a wild card or "has a suit, any suit" like any non-stone card?

daring fern
subtle hawk
#

I'm confused
It appears no matter what area you set in SMODS.create_card if the set is "Consumeables" it assigns created cards to G.consumeables???

#

Why...

primal robin
#

shortcut, kinda

subtle hawk
#

I realized that I don't even need that by now but it's still feels counter-intuitive idk

maiden phoenix
#

You can change the area

blazing helm
#

can you use SMODS.blueprint_effect with jokers you dont have? i want my joker that copys other joker abilitys based on the joker id (j_xxxx)

wintry solar
long sun
#

where does the game set what's in the shop? i'd like to replace the leftmost booster pack

crisp coral
#

game.lua

#

like update_shop or something

long sun
#

ah, cheers ^^

runic jay
#

What needs to be changed about the blueprint code to do so it does it to the left instead of to the right?

blazing helm
#

G.jokers.cards[i + 1] -> G.jokers.cards[i - 1]

#

it might crash if its all the way to the left tho not sure

blazing helm
long sun
#

<@&1133519078540185692>

hidden aspen
#

crush them

long sun
#

where does the game determine what booster packs appear each shop?

red flower
#

game:update_shop

long sun
# red flower game:update_shop

see that's the thing, it uses G.load_shop_booster which is only defined in that script, and is only ever initialised as nil

#

i have no idea where it's set

wooden belfry
#

the mods are dead... /j

red flower
long sun
#

ohhhhhhhh oh is that variable not used 😭

#

oh thunk!

red flower
#

no idea

long sun
#

it's probably that

#

cheers!

red flower
#

i think it is used

long sun
#

oh maybe it's on loading a run

#

mm

red flower
#

the areas get saved to "load_"... area_name iirc

long sun
#

ahhhhh ye i see then

wooden belfry
long sun
#

me too :3

#

okay that helps a lot ^^

long sun
#

this isn't working for some reason:

[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''if not G.GAME.first_shop_buffoon and not G.GAME.banned_keys['p_buffoon_normal_1'] then'''
position = 'before'
payload = '''if _key == "shop_pack" and G.GAME.current_round.cardb_next_shop_spectral then print("pog") return G.P_CENTERS['p_spectral_normal_'..(math.random(1, 2))] end'''
match_indent = true```
#

ignore that i don't reset the next shop spectral variable

#

it should replace the first pack in the shop with a spectral pack

#

the result is the variable is set properly, but the patched code doesn't run (i've checked, and the patch is being applied)

#

FINALLY okay i had to do something completely different lol

blazing helm
wintry solar
#

with great difficulty

fading rivet
#

or you could have it create perishable jokers that debuff immeaditely

blazing helm
slim ferry
#

have a peek at pinkprint from ortalab

#

I guess

mystic river
#

and/or missing texture from more fluff

clear ocean
#

is it good practise when making new stakes, to have an above_stake paramater such as 'gold'

hidden aspen
#

anyone knows why SMODS has specifically these vanilla blinds in SMODS.Blinds? im curious lol

red flower
slim ferry
#

Question

#

Why the window

#

What would even be changed there

red flower
#

dunno i dont have it in mine so it must be a mod

past spade
#

what do I put in info queue to show the tooltip of a sticker?
info_queue[#info_queue + 1] = G.P_CENTERS.m_stone

past spade
#

thanks

hidden aspen
#

it was because i had HandyBalatro on fool

wooden belfry
long sun
broken rivet
#

is it possible to prevent func returns in calculate from juicing up the scored card

slim ferry
#

add no_juice = true to the return?

#

i think

broken rivet
#

ah

hardy vessel
#

How would I get the payout dollars from a defeated blind?

hardy vessel
daring fern
#

gaunt folio
#

What do I use to make a collection that isnt under the "Consumables" area? preferably something like the tags tab

red flower
wooden belfry
#

<@&1133519078540185692>

red flower
#

that just looks like a syntax error to me

primal robin
#

syntax error

gaunt folio
#

ah

#

i added this <eof> they mention and it just errors out im so lost tho ik its probably syntax related

slim ferry
#

<eof> is not an actual thing in code (afaik) its just short for end of file

frosty rampart
#

^ if you see "<eof> expected" then that usually means you have too many ends in your code

#

or closing brackets, or anything else of that nature

gaunt folio
#

a

#

i see im dumb

slim ferry
#

Or youre running code after a return

#

Iirc that also does that

gaunt folio
#

i think i got it

slim ferry
#

Since returning has to always be the last thing in a block of code

gaunt folio
#

maybe

gaunt folio
reef bobcat
#
    key = "batman_joker",
    pos = { x = 0, y = 0 },
    rarity = 1,
    cost = 5,
    blueprint_compat = true,
    eternal_compat = true,
    unlocked = true,
    discovered = true,
    atlas = 'batman_joker',
    soul_pos = nil,
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS.m_gold
    end,
    calculate = function(self, card, context)
        if context.before then
            for _, scored_card in ipairs(context.scoring_hand) do
                if playing_card:get_id() == 2 or playing_card:get_id() == 3 or playing_card:get_id() == 4 or playing_card:get_id() == 5 then
                    scored_card:set_ability('m_gold', nil, true)
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            scored_card:juice_up()
                            return true
                        end
                    }))
                end
            end
                return {
                    message = localize('k_gold'),
                    colour = G.C.MONEY
                }
            end
        end
}```
#

thought i had this down

#

but it crashes when i play cards

#

D:

idle plaza
#

What error do you get?

daring fern
reef bobcat
#

thank u!

#

it works now

gaunt folio
#

This is the current untouched code straight from the steamodded source. I probalby need to put this in a function of sorts but this just errors out

tulip pecan
#

is there a 1-line function to find the number of jokers you have from a certain set, or do I need to loop over all jokers individually and count them

tulip pecan
#

a specific pool that I made myself, yes

daring fern
red flower
gaunt folio
#

I see

sour garden
#

what function handles joker calculations? i want to hook into it for a blind where the required score increases if an xmult triggers

daring fern
slim ferry
sour garden
#

including

daring fern
sour garden
#

okie

slim ferry
#

you should hook SMODS.calculate_individual_effect instead since then the recursive looping over the effect table is done for you

spiral mural
clear ocean
#

lowkey out of ideas for any other stakes but wish there was a better transition between these two

daring fern
#

split creek
#

I don't know how recent this changed, but G.FUNCS.draw_from_deck_to_hand now checks hand size when drawing. Is there a way to get around this when calling the function?

gaunt folio
#

im trying to make a card convert two cards only if you have two specific ranks selected. yes ik the numbers but this just errors out with nil values

gaunt folio
#

full thing or just the statement it says

#

heres the short

sturdy compass
#

When exactly does it crash?

gaunt folio
#

when i highlight the tarot

#

ill show an example

red flower
#

you need to check if highlighted is more than 1

#

not more than 0

sturdy compass
#

Yep just noticed that too

#

Might honestly need to be == 2 since you're checking two cards

red flower
#

yeah

gaunt folio
#

yep

#

works

short fulcrum
#

I'm having a bit of a weird issue. I'm trying to make the reward text a custom string (it's supposed to say $20) for this blind. I've got the instance in the collection and the blind select screen working, but here it's just showing 3 exclamation marks? Why is it doing this

#

my best guess is that it has something to do with the cashout screen?

daring fern
short fulcrum
median veldt
#

Is there a way to make a dependency like
this mod Or this one

like
cryptlib or just cryptid

#

optionally, does it work if i just have both cryptlib and cryptid enabled in my game

harsh belfry
#

so like

#

depending on cryptlib would work if you had either cryptid or cryptlib

#

also don't use both

median veldt
#

well it doesnt lol

harsh belfry
#

thats a bad idea for internal state reasons

median veldt
harsh belfry
#

oh you're specifying version

#

i think thats completely borked with how cryptid does the provides

median veldt
#

mm so just

#

"Cryptlib"?

harsh belfry
#

yeah

median veldt
#

ok there it goes

#

thnx

frosty dock
median veldt
#

noted

frosty dock
#

also the default version of a provided mod is just the version of the mod that provides it

#

which you could also use to guard the version just based on cryptlib

#

though note it's not fully future proof if the versions end up overlapping at some points, so this is definitely bad of cryptid to not supply the proper version

granite jay
#

Anyone know how to make it so the display size of the card with the gloom enhancement differs between backside and front?

daring fern
#

round lion
#

is there a way to get on-screen cards

daring fern
granite jay
#

How do you make it so a joker is unlocked by discovering every booster pack?

blazing helm
#

how do you use generate_ui? i have a joker that has a string var that gets longer so i wanna use DynaText to make it scroll.

red flower
blazing helm
red flower
#

there is no info on how to use generate_ui because you basically have to understand how the description is made from the code

#

so it's hard to explain

thorny wigeon
#

how do I make a skin I'm working on put in a new Enhancements.png I've made?

red flower
thorny wigeon
#

That doesn't seem to tell me how to write it with my existing txt but I don't know

blazing helm
#

i thought i was staring to understand hwo ui works, i do not qwq

    loc_vars = function (self, info_queue, card)
        return {
           vars = {
            main_end = {
                n = G.UIT.R,
                config = {
                    align = "tm",
                    padding = 0.1,
                    scale = 0.75,
                    colour = G.C.CLEAR,
                },
                nodes = {
                    {n=G.UIT.O, config={object = DynaText({string = card.ability.extra.text or 'ERROR', colours = {G.C.BLACK},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1, scale = 0.33*1})}}
                }
            }
        }
    }

anyone know why nothing extra gets rendered?

fading rivet
#

your returning a table containing the information for a node

#

wrap everything inside main_end with a {}

blazing helm
#

like so?

    loc_vars = function (self, info_queue, card)
        return {
           vars = {
            main_end = {{
                n = G.UIT.R,
                config = {
                    align = "tm",
                    padding = 0.1,
                    scale = 0.75,
                    colour = G.C.CLEAR,
                },
                nodes = {
                    {n=G.UIT.O, config={object = DynaText({string = card.ability.extra.text or 'ERROR', colours = {G.C.BLACK},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1, scale = 0.33*1})}}
                }
            }}
        }
    }

cuase its still not rendering anything qwq

red flower
#

not inside vars

fading rivet
#

wait I might be stupid

#

yeah what N said

blazing helm
#

omg i mess read the docs lmao ya thats probably the prob XD

fading rivet
#

also don't do what I said earlier

blazing helm
#

its at least trying to render now lol still def got something wrong in my ui tho x.x

blazing helm
thorny wigeon
red flower
#

the playing card one or the other one

thorny wigeon
#

Enhancers

#

For steel, lucky etc

#

I have a PNG I made, I just want my .lua to recognise what it is

#

I only needed to change bonus, mult, wild, glass, gold and steel

fading rivet
thorny wigeon
#

I've downloaded like 6 mods that change the enhancers.png and all of them do it differently, and if I copy their work and rename it to fit in my .lua, it just doesn't work

#

Why is there no actual documentation on how to change it, like there's "The game reads enhancements as "centre" but then everyone refers to it as "back" but then "centre" in the same line of code

#

and it just doesn't work?

slim ferry
#

back is decks

#

which are on the same sheet

#

but a different set so malverk needs a seperate texture set for it

thorny wigeon
#

Sorry, I don't understand

slim ferry
#

Also are you actually looking at malverk texture packs

thorny wigeon
#

I'm gonna be so real, I have no idea how I'd figure that out

slim ferry
#

Because a malverk texture pack shouldnt be doing anything with base centers

slim ferry
thorny wigeon
#

One is

#

The rest aren't

slim ferry
#

AltTexture is for malverk so look at that

#

And you also need the TexturePack or whatever its called which youll find at the bottom of most malverk mods

thorny wigeon
#

The mod I've found thats using Malverk is Dark and Colorful

#

and it's just on Nexus

#

it has the normal
assets > 1x/2x
main.lua

#

I don't know what you mean by texture pack

slim ferry
#

Have you looked at the malverk example mods

thorny wigeon
#

Yeah and none of them use enhancers

slim ferry
#

I mean the code is the same

#

But with a different file name

thorny wigeon
#

I don't know because I tried using the same code wit ha different name, and balatro just ignored the file

slim ferry
#

And set will be Enhanced instead of whatever else

royal carbon
#

Is upgrade_poker_hands from SMODS fucky for anyone else? It's not displaying the hand name and it also leaves the chips/mult display at what the hand leveled up to, and when it levels multiple hands it says it's doing a bunch of random subtraction
I'm on 1323c for Polterworx reasons which is probably why, but it'd be handy to know if that ever got fixed

slim ferry
#

You also need to make sure your mod has a metadata file so it actually loads

#

Or steamodded header but that will likely be deprecated in the near future

thorny wigeon
#

So thing is, I only have a .lua file and my assets

#

it loads 100% fine

#

for the cards and all the mod info

slim ferry
#

Huh

#

Okay idk then

thorny wigeon
#

I literally just want to load Enhancers.png
I don't want to do anything fancy

slim ferry
thorny wigeon
#

no

#

I'll be honest I've been using a different template I got sent to me

slim ferry
#

im on mobile i cant view that

thorny wigeon
timid zinc
#

is there a reverse of G.hand.highlighted built in?

slim ferry
#

No

timid zinc
#

My specific thing is that I want to select cards that are not being discarded during context.pre_discard

slim ferry
#

Where the AltTexture and stuff is

thorny wigeon
slim ferry
#

Oh so it isnt even there

sturdy compass
thorny wigeon
#

I just found a template that worked so I don't know what I'm doing otherwise
I was told the DeckSkin stuff works fine and it's all everyone ever sent me
I had no idea Malverk had its own format

slim ferry
#

Oh yeah DeckSkin is only for the rank/suit sprites

#

I can only help so much on mobile though

thorny wigeon
#

Would you be ok if I sent you a DM and message you tomorrow as it's 1AM for me

slim ferry
#

Sure ig

#

Ill probably see it when im home

thorny wigeon
#

Thats ok, there's no rush

frosty rampart
slim ferry
#

Oh lmao

red flower
#

it's deprecated but i think they were talking about making it unsupported

slim ferry
#

Yeah thatp

median veldt
#

this is wrong and i dont know why am i stupid

slim ferry
#

e_negative

#

and set = "Edition"

median veldt
#

ah. thanks

slim ferry
#

But you should just do G.P_CENTERS.e_negative instead of that if you just need the default negative description for joker slots

median veldt
#

wait why

slim ferry
#

will automatically do the loc_vars and stuff for negative

#

Instead of needing to do vars manually

median veldt
#

ah.

which one is right then

slim ferry
#

The bottom

median veldt
#

kk

hard flume
#

Thinking about picking up Balatro modding again

timid zinc
#

is there a way to add cards to discard during context.pre_discard?

wanton jolt
#

the hook does that

G.E_MANAGER:add_event(Event({
                    func = function()
                        local any_selected = nil
                        local _cards = {}
                        for _, playing_card in ipairs(G.hand.cards) do
                            _cards[#_cards + 1] = playing_card
                        end
                        for i = 1, 2 do
                            if G.hand.cards[i] then
                                local selected_card, card_index = pseudorandom_element(_cards, 'vremade_hook')
                                G.hand:add_to_highlighted(selected_card, true)
                                table.remove(_cards, card_index)
                                any_selected = true
                                play_sound('card1', 1)
                            end
                        end
                        if any_selected then G.FUNCS.discard_cards_from_highlighted(nil, true) end
                        return true
                    end
                }))
timid zinc
#

Yeah but the problem with that is that it's during context.pre_discard so since you have cards selected they get discarded twice, duplicating them and creating ghost card stuff

wanton jolt
#

what are u trying to do

slim ferry
#

i feel like that should work?

wanton jolt
#

yeah

timid zinc
#

if i do that then the added cards don't get discarded and just remain highlighted

#

G.hand:add_to_highlighted, right?

slim ferry
#

Huh

#

Okay well idk then

timid zinc
#

maybe i just have to hook into the discard function for this one

red flower
#

the problem is that the discard code pre-computes the amount

#

does any mod use the discard card limit

short fulcrum
#

I've legit been trying to find a way to change the circled text for a specific boss blind for hours now, I don't think I'm able to do it on my own

#

I know where to patch but absolutely nothing I've tried has worked

#

the best I've done is make it display the default "!!!" but I can't even remember how I did that

daring fern
short fulcrum
#

into this line in UI definitions:

{n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.current_round, ref_value = 'dollars_to_be_earned'}}, colours = {G.C.MONEY},shadow = true, rotate = true, bump = true, silent = true, scale = 0.45}),id = 'dollars_to_be_earned'}},
#

I've managed to change similar text in the collection and the blind select screen, those were effortless in comparison to this

formal vessel
#

is there a way to make the plasma effect without the balance = true (i want to change it from balance to smth else)

daring fern
formal vessel
#

yea i mean without using the 'balance = true' thing

daring fern
formal vessel
#

lemme rephrase my question, how do i check how much mult and how many chips there currently are

frosty rampart
#

what is your goal here exactly

formal vessel
#

im wanting to make a challenge deck that makes it chips + mult

frosty rampart
#

so you want the final score of a hand to be chips + mult instead of chips x mult?

clear ocean
#

i have an idea for the stickers to put between the two stakes i made feel free to give me better ideas

#

lose $1 when hand discard and lose $1 when hand played

frosty rampart
formal vessel
clear ocean
#

like one dollar gone when you play or discard a hand respectivelly, admittedly they probably arent that good

formal vessel
formal vessel
clear ocean
#

yeah pretty much

formal vessel
clear ocean
#

i been on that vanillaremade game since the start 🔥

formal vessel
#

oh lol

clear ocean
#

it was more at a balancing standpoint if they are good stickers

formal vessel
#

ohh ok

daring fern
frosty rampart
#

^ thanks, my good laptop is in for repairs at the moment so i'm not doing so hot with my documentation references lol

formal vessel
thorn ingot
#

Hey everyone. Do you know how negative numbers in jokers work? I've been trying to make this one give it's chips and mult negatively and can't find a way to do it. It works, but gives positive numbers.

red flower
#

just return chips and mult without any message

red flower
thorn ingot
timid zinc
# red flower

the easiest way would be to just patch it to recalculate highlighted count after the context calc

#

hopefully wont break anything

dapper sun
tight notch
#

hey, so i'm updating my mod that i haven't touched since july, and when starting a new run with it enabled i get this every time. unsure what's causing it

#

on latest smods and everything

daring fern
tight notch
#

do you just want me to send it all?

#

it says "utils.lua" so i'm unsure

#

so whic file

daring fern
tight notch
#

ok

daring fern
# tight notch

You're setting cardareas to true in your optional features.

tight notch
#

ah ok

#

did they change it or something?

thorn ingot
#

Guys!!! It works. omg.

dapper sun
#

how do i add 2 soul layers to a joker?

#

preferably using soul_pos.draw

#

nvmd i think i got it

oblique lotus
#

Is there a way to include global variables in text?

dapper sun
#

in loc_vars?

#

just put the global var in the return

oblique lotus
#

Not in local vars.

dapper sun
#

?

#

loc_vars stands for localization vars not local vars

#

as in text

oblique lotus
#

Oh, my apologies, yes in localization

dapper sun
#

return { vars = { global_var_idk } }

#

nothing's saying you have to put a card's variable in there

#

you can have it show anything

oblique lotus
#

Wait, sorry, still not communicating right. I don't have a base Joker or object for this message.

dapper sun
#

oh

#

then what do you mean in text

oblique lotus
#

Like for example, if I had a message I wanted to write across the screen at a given point, and wanted it to include the profile name, how would I do that

dapper sun
#

you have to do UI Shit™ for that idk

oblique lotus
#

I see. Won't bother with it then. Thanks for your help.

mystic river
#

attention_text is a function that exists
you don't need to do UI Nonsense™ for that

#

but like. maybe step 1 of "put a profile name in a message on the screen" is "put a message on the screen", hm?

versed swan
#

How do you make a UI node not block elements behind it from being clicked

#

Or whatever UIBox{} creates

crisp coral
tulip pecan
#

How come when I switch this Joker Display code for misprint from a vanilla joker to this modded joker, I get an index error, despite the joker having the correct config items, and making sure the jokers file is loaded before the joker definitions file?

gilded blaze
#

show the full crash log

tulip pecan
gilded blaze
#

actually, don't use it that way

#

modded objects are yet to be injected into prototype pool (in this case G.P_CENTERS)

#

use SMODS.Jokers.j_uma_goldship instead, at least that's what I think shall work

tulip pecan
#

I’ll give it a test

tulip pecan
gilded blaze
#

oh, I see

#

it's a function inside dynatext.string

#

usually functions don't cause problems

#

until you invoke it directly at load

#

vanilla misprint display works because it's already there

#

at this point I recommend using the joker_display_def way

#

instead of defining each entry in a separate file, you define joker_display_def field in your joker code as a function that returns the exact same table you would define in JokerDisplay.definitions

#

since it's a function now, it won't cause problems unless you invoke it at the wrong time

#

the format shall be as follows:

SMODS.Joker{
    ..., --your code
    joker_display_def = function(JokerDisplay)
        return {
            text = {...},
            reminder_text = {...},
            calc_function = function(card)
                -- do stuff
            end,
        }
    end,
}
blazing helm
#

whats the name of the ui element used to make these selector things? wanna add on to my config :3

wild patrol
#

Pretty sure there is a standalone mod for more speed

#

Probably just look see how it manages it

#

@blazing helm

blazing helm
#

ah its create_option_cycle thx ^w^

granite raptor
#

does smods come with its own food joker object type i can add to for easier integration/unification with any other mods that might have food joker related effects?

wintry solar
#

Not yet

acoustic drum
#

How do I loop through the abilities table of a joker? I've tried this code but it keeps erroring:

for statName, statVal in pairs(joker.ability.extra) do
    if string.find(string.lower(statName), "chips") then
        if jokerChips == 0 then jokerChips = math.floor(100 * joker.config.center.rarity * joker.sell_cost / 4) / 100 end
    elseif string.find(string.lower(statName), "mult") then
        if jokerMult == 0 then jokerMult = math.floor(100 * joker.config.center.rarity * joker.sell_cost / 8) / 100 end
    end
end

(joker is a different joker from the one this code is in)

wintry solar
#

How are you setting this joker value?

acoustic drum
#

I look through G.jokers.cards and put all the non-eternal ones in a table (like how ceremonial dagger does it)
Then I loop through this table with a simple for _, joker in pairs(destructable_jokers) do loop

wintry solar
#

Not every joker will have an extra table

#

Many vanilla jokers dont for example

acoustic drum
#

Ohh alr, I'll change it so it skips if it doesn't find the extra table

#

Thanks a bunch

gilded blaze
#

this is what happens when I try to highlight a tag in tutorial
game just hard crashes lmao

vital wren
#

does anyone have the custom card skins from the base game? i want to make color edits to the shovel knight and potion craft skins for my own high contrast needs

red flower
#

you can unzip the exe to get them

vital wren
#

huh, i never knew you can unzip an exe. neat. thanks

slim ferry
#

Most programs dont let you unzip exes because the contents are usually pretty much completely obfuscated

#

Love2d games just happen to be just the source code and love2d library in a zip

formal vessel
#

so my mod isnt loading, saying theres an invalid metadata file or smth and idk how to solve this

red flower
formal vessel
#

oh ok, thx

#

ok its still saying its an invalid metadata file

#

well i did change the prefix but i only use the prefix in one place and i did update it there too

hasty kelp
#

i have one question of do i make my mod work with other mods like jens almenac i really want to have my own mod to be able to get the same things like the effects from cryptid mod on my mod like it can get the same editions

slim ferry
#

why would it not be able to get other mod editions

hasty kelp
#

idk i was asking that if i need to do something to make it happen like adding something in my code to make it work

slim ferry
#

you dont

verbal vigil
#

Does anyone know hit there is a way to run code after scoring a hand? I'm hookinh into Card:calculate_joker but I can't seem to get it to run code after the hand is fully done scoring.

wintry solar
#

what effect are you trying to do?

verbal vigil
wintry solar
#

but what is it trying to do

verbal vigil
#

I'm trying to run code after the hand finishes scoring so I can update my UI

wintry solar
#

what is the code intended to do then I can tell you the best place to put it

verbal vigil
red flower
verbal vigil
#

Yep

verbal vigil
red flower
#

we dont know what your ui is or what it's trying to do

#

so we cant know what after scoring means exactly either

red flower
# verbal vigil Yep

you can probably use an event in context.after in SMODS.current_mod.calculate

mossy anchor
verbal vigil
#

Why do you need what my UI does? Everything is working but the problem is that I can only figure out to call my UI function before the hand finishes even if I check context

mossy anchor
#

out of context funny gif

verbal vigil
verbal vigil
red flower
verbal vigil
#

when I'm referencing Card:calculate_joker and check for context.after code still runs at the start of the hand

red flower
verbal vigil
red flower
verbal vigil
tulip pecan
fervent rampart
#

I'm trying to run a code that only works on cards without an edition. "if not edition then" and "if not have_edition then" and many variants of it, but it always seems to be set to true for all cards or its a nil value. Trying to "edition and not edition.polychrome" did not differ the results on any card I tested. I started throwing code at the wall to see what sticks, "SMODS.edition(scored_card)" and such. I looked at wheel_of_fortune but "SMODS.Edition:get_edition_cards" only caused crashes. I can't find a single thing on the SMODS documentation that helps, yet the code for checking for enhancements is incredibly simple.
I'm just trying to make a card foil if it does not already have an edition.

slim ferry
#

not card.edition?

red flower
daring fern
#

I fixed this by using love.graphics.stencil

fading rivet
fervent rampart
# slim ferry not card.edition?

using that, all cards were turning foil. removing the "not" made no cards turn foil. So it's at least not crashing or giving a nil value, but it is still treating all cards as all not having an edition.

slim ferry
#

card.edition only exists for cards that have an edition so like

#

idk

#

you can use not card.edition and not card.will_be_editioned ig

fervent rampart
#

Oh I didnt realise that link to VanillaRemade was actually showing off more examples. I've got a few more things to try out it seems.

wintry solar
fervent rampart
#

What on earth?? I was just told I cant post my code here because I dont share a server with the recipient.

#
SMODS.Joker {
    key = "ivy",
    name = "Ivy",
    rarity = "fuse_fusion",
    cost = 19,
    unlocked = true,
    discovered = false,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    atlas = "fuseforce_jokers",
    pos = { x = 2, y = 5 },
    config = {
        extra = {
            x_mult = 1.5,
            joker1 = "j_flower_pot",
            joker2 = "j_marble"
        }
    },
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS.m_wild
        return {
        vars = {
            card.ability.extra.x_mult,
            localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, 
            localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}
        }
    }
    end,
    calculate = function(self, card, context)
          if context.setting_blind then
            local stone_card = SMODS.create_card { set = "Base", enhancement = "m_stone", area = G.discard }
            G.playing_card = (G.playing_card and G.playing_card + 1) or 1
            stone_card.playing_card = G.playing_card
            table.insert(G.playing_cards, stone_card)

            G.E_MANAGER:add_event(Event({
                func = function()
                    stone_card:start_materialize({ G.C.SECONDARY_SET.Enhanced })
                    G.play:emplace(stone_card)
                    return true
                end
            }))
            return {
                message = localize('k_plus_stone'),
                colour = G.C.SECONDARY_SET.Enhanced,
                func = function() -- This is for timing purposes, everything here runs after the message
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            G.deck.config.card_limit = G.deck.config.card_limit + 1
                            return true
                        end
                    }))
                    draw_card(G.play, G.deck, 90, 'up')
                    SMODS.calculate_context({ playing_card_added = true, cards = { stone_card } })
                end
            }
        end
        if context.before and not context.blueprint then
            local stones = 0
            local has_edition = card.edition
            for _, scored_card in ipairs(context.scoring_hand) do
                if next(SMODS.get_enhancements(scored_card)) then
                    if SMODS.has_enhancement(scored_card, 'm_stone') then
                        stones = stones + 1
                        scored_card:set_ability('m_wild', nil, true)
                        G.E_MANAGER:add_event(Event({
                            func = function()
                                scored_card:juice_up()
                                return true
                            end
                        }))
                        if not card.edition and not card.will_be_editioned then
                        --if not SMODS.has_enhancement(scored_card, 'e_polychrome') then
                            scored_card:set_edition('e_foil', nil, true)
                            G.E_MANAGER:add_event(Event({
                                func = function()
                                    scored_card:juice_up()
                                    return true
                                end
                            }))
                        end
                    end
                end
        end
                if stones > 0 then
                    return {
                        message = 'Wild'
                    }
                end
            end
        if context.individual and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_wild') then
            return {
                x_mult = card.ability.extra.x_mult
            }
        end    
    end
}```
#

I've exhausted all the options I was given and I just can't get it to actually differentiate between editioned and non-editioned cards. So here's the full code.
And wow Discord is struggling to function too, I guess my code must be really bad.

red flower
#

im assuming, i dont know what the effect is supposed to be

fervent rampart
red flower
formal vessel
formal vessel
#

im looking thru the wiki and i dont c anything

hard flume
#

Thats because its not on the wiki and you have to add the scoring calculation yourself, which also isn't on the wiki. Its on a specific update of smods

daring fern
hard flume
#

Also. How would I go about changing a single operator symbol in the calculation UI I have set up without modifying every instance of the * symbol

red flower
formal vessel
#

OHHH ok thx

hard flume
#

Oh

#

I never noticed the url

formal vessel
#

i literally cant see whats wrong with this code 😭 nor do i see where to put the second end

daring fern
formal vessel
#

OHHH omg im so dumb thank you

#

it works now, thx

median veldt
#

hey whats the atlas for vouchers

#

the size that is

wanton jolt
#

same as the cards

median veldt
#

am i doing this right i kind of took code from paperback

#

i dont think i am

#

the first one is Spell cards may appear in the shop and the second one is Spell Packs appear 2X more frequently in the shop

frosty rampart
#
  1. is your mod prefix shark?
  2. show the code where you create the SMODS.ConsumableType for spell cards
median veldt
#
  1. yes
  2. the key is Spell so maybe more like shark_Spell_rate?
frosty rampart
#

yea it should be shark_Spell_rate
but from there, the vanilla game/smods will automatically handle the rest!

median veldt
#

oh nice!

median veldt
#

so 2 should be more rare? and 4 should be double that?

frosty rampart
#

yea paperback soothsay has a comment that says it's 3 by default

median veldt
#

mhm

frosty rampart
#

but the way rates work in-game means that doubling the number doesn't actually double the odds
and quite frankly there's no easy way to handle that in a crossmod-friendly way

#

tarot merchant (ostensibly "double the odds") sets the rate value to 9.6

red flower
median veldt
#

oh

red flower
#

it doesn't add the prefix and it lowercases it

#

you should add the prefix to the consumabletype tho

median veldt
#

yeah you're probably right

#

i'll do that in a sec

frosty rampart
#

ahhh right

median veldt
#

would it be fine to leave it at 2 and 4?

frosty rampart
#

i think so yea
realistically players aren't gonna notice if it's not exactly doubled

red flower
#

you don't need to tell them the number, you can write it as 'increases the odds'

median veldt
#

huzzah it works

inner terrace
#

What causes atlas injection times to be super long? Is it in how long the atlas is? (It's for animated cards, so it's rather large)

frosty rampart
#

possibly, although the bigger issue is having a lot of different atlases
it can help organizationally to split stuff up, but if you go so far as to have a different atlas for every single joker then that's not good

inner terrace
#

Wait, really?

#

Because one of my atlases is...7668 by 3028 (1x)

#

And I figured that was causing the problem

frosty rampart
#

ok that's also an issue lmao

#

what are you even doing that requires a spritesheet like that

inner terrace
#

It's because we've got a lot of animated jokers

#

Some of which have ~100 frames

frosty rampart
#

ok a 100 frame animation should only be 710 by 95 at 1x resolution

#

unless you're drawing at a higher resolution than vanilla sprites

inner terrace
#

uhh

#

your math might be off?

#

71*100? 7100

frosty rampart
#

right lol

#

ok 7100 x 95 is a little closer to what you have

inner terrace
#

Longest animation is like, 120 frames

frosty rampart
#

honestly i don't think there's much you can do then

inner terrace
#

this, for example, is what it looks like zoomed alllll the way out

#

Would separating it to reduce empty space be helpful? e.g. categories by frame-count?

frosty rampart
#

i think so yea

fading rivet
#

How could I get the SMODS documentation in vs code?

#

like make this not show random stuff

grizzled tide
#

is there a way to set the font size of the text going into create_badge

red flower
#

keep in mind there are many things that are still not documented from vanilla so not everything will show good suggestions

red flower
grizzled tide
median veldt
frosty rampart
#

it's doing if (not #G.jokers.cards) + G.GAME.joker_buffer >= ...

median veldt
#

ohlol

frosty rampart
#

just take out the not and make it <

median veldt
#

either i'm adding it wrong or setting the variable wrong

red flower
#

i recommend adding prints to see where the code gets to

median veldt
#

you know

#

i genuinely forgot about that

#

Okay so it's not setting the variable

frosty rampart
#

ah edition is a table, you should be checking if G.jokers.highlighted[i].edition.key == "e_negative"
(check first to see if the card's edition table exists at all, so you don't try to index a nil value on non-editioned cards)

median veldt
#

Oh

#

cool it works now

#

ty

versed swan
#

What's the best way to directly set a blind's requirement, particularly an upcoming one?

oblique lotus
#

How do you make an object buyable?

#

To clarify, I don't mean to make it appear in the shop. I mean to give it the price and buy buttons like it would have in the shop

slim ferry
#

create_shop_card_ui(card, type, area) i think

oblique lotus
#

Thanks, will try it

daring scroll
#

I made wild cards immune to debuffs, and it works, but I'm also trying to update the description to reflect that. This is my duct tape and ramen-ass attempt but it doesn't work

SMODS.Enhancement:take_ownership(
    'wild',
    {
        loc_text = {
            text = {
                "Can be used",
                "as {C:attention}any suit{}",
                "{C:attention}Immune{} to {C:red}debuffs"
            }
        }
    }
)
slim ferry
#

its loc_txt, but localization files also take priority over loc_txt

#

so to change vanilla descriptions you need to use a localization file

daring scroll
#

wouldn't be Krus code if I didn't mistype something critical. Aight, I'll look into loc files

near coral
#

So you know how in the mod menu some mods have settings

#

How do you implement that

red flower
white hull
#

can i somehow display a line of text on the cashout screen without it giving any dollars?

#

i do wanna show a number, just without the money functionality

red flower
#

try copying what add_round_eval_row does

#

im pretty sure you can do it in context.round_eval and it works

wintry solar
#

yeah something like this
add_round_eval_row({dollars = 0, name='custom', number = card.effect.config.extra.amount, number_colour = G.C.RED, text = localize({set = 'Tag', type='name_text', key = card.effect.config.extra.tag}), text_colour = G.C.BLUE, pitch = 4, card = G.deck})

white hull
#

hm interesting

#

i'll try that, thanks

wintry solar
#

looks like this

grizzled tide
#

hey guys! is there a way to add images to badges

red flower
fading rivet
#

How could I make one suit be treated as another?
would it be best to hook into the card.is_suit function?

#

or is there another way

formal vessel
#

so theres G.GAME.modifiers.enable_rentals_in_shop to enable rentals, is there anything for pinned?

mystic river
#

probably not
the only vanilla usage of pinned is one challenge

formal vessel
#

oh

hard flume
#

percentage gaming

grizzled tide
#

i see SMODS.Gradient lets you use update(), what does update return (or modify) exactly to set the color

mystic river
hardy vessel
#

Trying to make a joker that wins small blinds for you if your chips are at least 50% of the requirement. That works fine and all, but the end of round screen has these extra blind chips appear

    calculate = function(self, card, context)
        if context.after and not context.blueprint then
            G.E_MANAGER:add_event(Event({
            blocking = false,
            func = function()
                if G.GAME.blind.small and G.GAME.chips >= G.GAME.blind.chips * card.ability.extra.chip_percent then
                    G.GAME.chips = G.GAME.blind.chips
                    G.STATE = G.STATES.HAND_PLAYED
                    G.STATE_COMPLETE = true
                    end_round()
                    return true
                end
            end
        }))
        end
    end
short mauve
#

What are these for

hard flume
#

Charge is the amount of "juice" you have left in a run. Once it reaches zero, if you have no way to quickly charge it, the run is (basically) over. Battery is the total amount of Charge you can have, and together they represent the percentage of your score that will actually be applied.

short mauve
#

That is very cool

oblique lotus
#

Its possible that it might already has it but it isn't showing. In that case, how can I get it to show?

oblique lotus
#

It is also important to note I am using the latest in-development version of SMODS, version BETA 1421c, as it is necessary for some features. It works on the latest full release but not in the in-dev. I don't know what would have changed that I need to account for.

grizzled tide
red flower
#

yes

fringe patrol
#

can someone help me with the ins and outs of SMODS.set_debuff ?

#

i'm updating some mods, and these lines seem to crash the game

#

the code used to use debuff_card

#

but set_debuff seems to work differently

red flower
#

SMODS.debuff_card

#

idk what set_debuff is

fringe patrol
#

leaving it as debuff_card hard crashed the game, it wouldn't even go to the crash log

red flower
#

probably because you were doing something else wrong

#

set_debuff is crashing because it doesnt exist

fringe patrol
#

this is what the set_debuff is according to the github

red flower
#

that's SMODS.current_mod.set_debuff and it's not a function you run, it's a function you define

#

what's your goal

fringe patrol
#

okay so, there's 2 custom blinds, one debuffs wild and polychrome cards, the other cycles through the suits to debuff every hand

#

there's also two functions defined in the main.lua that are for removing the debuffs afterwards

red flower
#

how are you debuffing them

fringe patrol
#

here's the wild/polychrome blind

red flower
#

instead of using SMODS.debuff_card in recalc_debuff I would just return true

#

for this blind that should just work im pretty sure

#

for the other one you might need to call SMODS.recalc_debuff on each card after each hand

daring scroll
#

Buffing greedy/lusty/wrathful/glutton jokers slightly. Thought this might do it, to my understanding, but it still does +3 mult. An I missing something and am I stupid lol?

SMODS.Joker:take_ownership(
    'greedy_joker',
    {
        config = {
            extra = {
                s_mult = '4'
            }
        }
    }
)
red flower
#

as far as i can see it should crash because the 4 is a string and you dont have the suit

daring scroll
#

you just reminded me to define the file path on my main file 💀. I'll do that and define the suit on each joker too

gilded narwhal
#

hey chat i'm trying to have a jimbo style tutorial thing pop up and just say 3 lines as a set piece for a trailer

#

where is a good reference

red flower
#

i dont have other references

gilded narwhal
#

Okay peam

daring scroll
dry marsh
#

am I in the right channel if I need help concerning the making of my mod ?

idle plaza
#

Yes

#

dev for making mods, support for playing mods

dry marsh
#

oh cool thank you

#

well, then cotext : I'm making a od for me and my gf to play with (light thing I only added 30 jokers for now) but there is two i particular that really messes with me

SMODS.Joker{
    key    = "x",
    atlas  = "x",
    pos    = { x = 0, y = 0 },
    config = { extra = { first_discard_done = false } },
    rarity = 1, cost = 4,
    blueprint_compat = true,
    eternal_compat   = true,
    unlocked = true, discovered = true,

    calculate = function(self, card, context)
        if context.before and not (context.individual or context.repetition) then
            card.ability.extra.first_discard_done = false
        end

        if context.discard and not card.ability.extra.first_discard_done then
            card.ability.extra.first_discard_done = true
            if #context.full_hand == 1 then
                G.E_MANAGER:add_event(Event({
                    func = function()
                        choose_random_highlight(G.hand.cards, 2)
                        G.FUNCS.discard_cards_from_highlighted(nil, true)
                        return true
                    end
                }))
                return { dollars = 10, card = card }
            end
        end
    end,

    loc_vars = function(self, info_queue, card) return {} end
}

and

#
SMODS.Joker{
    key    = "y",
    atlas  = "y",
    pos    = { x = 0, y = 0 },
    config = { extra = { current_rank = nil, pending_destroy = {} } },
    rarity = 1, cost = 4,
    blueprint_compat = false,
    eternal_compat   = true,
    unlocked = true, discovered = true,

    calculate = function(self, card, context)
        -- Lazy init
        if not card.ability.extra.current_rank then
            card.ability.extra.current_rank =
                pseudorandom_element({2,3,4,5,6,7,8,9,10,11,12,13,14},
                                     pseudoseed('mia_rank'))
        end

        -- Reset destroy queue at the start of each hand
        if context.before and not (context.individual or context.repetition) then
            card.ability.extra.pending_destroy = {}
        end

        -- Rotate rank at end of round
        if context.end_of_round and not (context.individual or context.repetition) then
            card.ability.extra.current_rank =
                pseudorandom_element({2,3,4,5,6,7,8,9,10,11,12,13,14},
                                     pseudoseed('mia_rank'))
        end

        if context.individual and context.cardarea == G.play then
            if context.other_card:get_id() == card.ability.extra.current_rank then
                local roll = pseudorandom('mia_effect')

                if roll < (1 / 15) then
                    local q = card.ability.extra.pending_destroy
                    q[#q + 1] = context.other_card
                    return { message = localize('j_destroyed'), card = card, colour = G.C.RED }

                elseif roll < (1 / 3) then
                    local target = context.other_card
                    G.E_MANAGER:add_event(Event({ func = function()
                        target:set_ability(G.P_CENTERS.m_wild)
                        target:juice_up(0.5, 0.3)
                        return true
                    end }))
                    return { message = localize('k_upgrade_ex'), card = card, colour = G.C.GREEN }

                else
                    return { message = localize('k_nope_ex'), card = card, colour = G.C.RED }
                end
            end
        end

        if context.after and not (context.individual or context.repetition) then
            if #card.ability.extra.pending_destroy > 0 then
                for _, target in ipairs(card.ability.extra.pending_destroy) do
                    local t = target
                    G.E_MANAGER:add_event(Event({ func = function()
                        t:start_dissolve()
                        return true
                    end }))
                end
                card.ability.extra.pending_destroy = {}
            end
        end
    end,

    loc_vars = function(self, info_queue, card)
        local names = {
            [2]="2",[3]="3",[4]="4",[5]="5",[6]="6",[7]="7",[8]="8",
            [9]="9",[10]="10",[11]="Jack",[12]="Queen",[13]="King",[14]="Ace"
        }
        return { vars = { names[card.ability.extra.current_rank or 2] or "?" }, key = self.key }
    end
}

both of them make in very particular case, sort of "ghost" cards, sometimes just leaving a blank space counted as card but there is nothing, sometimes as omniscient card not on screen always selected even after discard or play, and always hidden face, if the code seems messy it's because I tweak MANY things and ended up with this which is the less buggy version for each, if you need any helper functions used here ask me

idle plaza
#

You can do the format

```lua
text here
```

For proper code blocks with coloring.

dry marsh
#

oh thank you I was about to ask how to do it

#

X is "If first discard of round is only one card, discard 2 additional random cards and earn $10"
Y is "Scored [?] have a 1 in 3 chance to become wild cards, 1 in 15 to be destroyed instead (rank changes every round)"

red flower
dry marsh
#

what is the difference and when to use which ?

red flower
#

destroy_cards uses events to not create ghost cards in scoring, you pretty much never need to use start_dissolve over it

dry marsh
#

oh okay, does it have a destroyed message or anything like this or my custom j_destroyed is still valid ?

red flower
#

no thats fine

#

for the X joker try wrapping the event in another event

dry marsh
#

you mean another add_event inside the main event ?

red flower
#

yes

dry marsh
#

why should it help ?

#
                G.E_MANAGER:add_event(Event({ func = function()
                    G.E_MANAGER:add_event(Event({ func = function()
                            choose_random_highlight(G.hand.cards, 2)
                            G.FUNCS.discard_cards_from_highlighted(nil, true)
                            return true
                        end
                    }))
                    return true
                    end
                }))
#

like so ?

red flower
#

im guessing that the problem is that youre highlighting cards too early to discard causing you to discard the same cards twice, another event would make it run later

red flower
dry marsh
#

edited is this better ?

dry marsh
#

also how do you do the little jiggle like the DNA card when enabled before the first discard ?

#

tried somthing before but it only juiced up on playing a hand

red flower
dry marsh
red flower
#

yes

#

idk if it will fix it tho

dry marsh
#

I'll try next time I playtest

#

I did this when playtesting btw but I'm not sure that it's working

local allowed_jokers = {}
local joker_bag = {}

for key, center in pairs(G.P_CENTERS) do
    if center.set == 'Joker' then
        if string.find(key, 'mymod') then
            table.insert(allowed_jokers, center)
        else
            center.in_pool = function() return false end
        end
    end
end
-- [...]
G.pick_random_joker = function(seed)
    if #allowed_jokers == 0 then
        return nil
    end
    if #joker_bag == 0 then
        for i, joker in ipairs(allowed_jokers) do
            joker_bag[i] = joker
        end
        shuffle(joker_bag)
    end
    return table.remove(joker_bag)
end
#

the idea is making something that will one by one give only jokers from my mod and not twice until everyone has already been seen

rapid stag
#

is there a way to force unlock and discover a joker by key?

dry marsh
#
SMODS.Joker{
    key    = "yourmod_your_card",
    atlas  = "yourmod_your_card",
    pos    = { x = 0, y = 0 },
    rarity = 1, cost = 4,
    blueprint_compat = true,
    eternal_compat   = true,
    unlocked = true, discovered = true,

If I understand your question right then these lines are what you are looking for

unlocked = true, discovered = true
rapid stag
#

no

#

i'm experiencing a difficult to reproduce bug where i have a consumable that uses set_ability to turn a joker into another joker, which is the intended way to unlock & discover certain jokers in my mod, but for some reason it's being very temperamental and leaving the joker locked

and now that i've seen it happen live, i'm trying to figure out a fallback that will at least patch the issue until i figure out the root cause

dry marsh
#

I think you can make use of that

calculate = function(self, card, context)
    if context.hand then
        local center = card.config.center
        if not center.unlocked then
            center.unlocked = true
        end
        if not center.discovered then
            Card.discover_card(center)
        end
    end
end,
#

is it what you are looking for or still not ?

daring fern
rapid stag
#

thanks

fading rivet
#

where is the function that shuffles the deck at?

daring fern
fading rivet
#

thx

timid zinc
#

Wait, i messed it up

fringe patrol
red flower
# fringe patrol I'm not quite understanding. So the reason the crash is happening is that since ...

since recalc_debuff is being defined, but it's also called internally in debuff_card, it's doing an infinite loop?

yes

i'm not sure what you mean by just returning true either. then how do i apply the debuff with the proper tag then?

recalc_debuf debuffs the card when you return true
i dont see a reason why you need the debuff source? that would also make it harded for cards that prevent blind debuffs from working

#

you would return true without using SMODS.debuff_card

daring scroll
#

How would I edit the chips and mult gained from levelling up a poker hand? I'm trying to reference the base game and mods that tweaks level values, but the structure confuses me

#

I.E. use a consumable that increases Pluto from +10 chips and +1 mult, to +15 chips and +2 mult?

faint yacht
#

G.GAME.hands['High Card'].l_chips & G.GAME.hands['High Card'].l_mult

daring scroll
#

Gotcha, I'll give it a try

reef bobcat
#

assert(SMODS.modify_rank(G.hand.highlighted[i], 1)) what do I replace this with to make it turn a card into a specific rank?

red flower
#

assert(SMODS.change_base(G.hand.highlighted[i], nil, "Ace"))

#

for example

reef bobcat
#

ahhh ok thank u

reef bobcat
#

what if i want to be a queen and have a red seal?

granite jay
#

Is it possible to make it so when you play a hand, a joker adds a random card to your played hand?

I also want the joker to still apply if you play 5 cards, turning it into a 6 card hand >:3

frosty rampart
# reef bobcat what if i want to be a queen and have a red seal?

you can be whoever you think you are. i believe in you and i'm proud of you for realizing that about your identity /silly

replace "Ace" with "Queen", and change_base only handles rank and suit, so to add a red seal, you'll want to do G.hand.highlighted[i]:set_seal("Red")

reef bobcat
#

ohhhhhhh

#

and dw im already trans :3 u dont gotta reassure me

daring scroll
#

So, scratch what I said. I actually wanted to override the base mult and chips gained when a hand levels up. This is what I thought might work, but it doesn't, so I'm messing something up

SMODS.PokerHand:take_ownership(
    'High Card',
    {
        l_chips = 15,
        l_mult = 1
    }
)
#

I just imagine this is the equivalent to "if(crash) = don't fucking do that please"

dry marsh
#

I still have that issue where I get a ghost card out of my "If the first discard of round is exactly one card, discard 2 additional random cards and earn $10" joker and I don't know at all how to fix it after many attempts

SMODS.Joker{
    key    = "mycard",
    atlas  = "mycard",
    pos    = { x = 0, y = 0 },
    config = { extra = { first_discard_done = false } },
    rarity = 1, cost = 4,
    blueprint_compat = true,
    eternal_compat   = true,
    unlocked = true, discovered = true,

    calculate = function(self, card, context)
        if context.before and not (context.individual or context.repetition) and not context.blueprint then
            local eval = function() return G.GAME.current_round.first_discard_done end
            juice_card_until(card, eval, true)
            card.ability.extra.first_discard_done = false
        end

        if context.discard and not card.ability.extra.first_discard_done then
            card.ability.extra.first_discard_done = true
            if #context.full_hand == 1 then
                G.E_MANAGER:add_event(Event({ func = function()
                    choose_random_highlight(G.hand.cards, 2)
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            G.FUNCS.discard_cards_from_highlighted(nil, true)
                            return true
                        end
                    }))
                    return true
                    end
                }))
                return { dollars = 10, card = card }
            end
        end
    end,

    loc_vars = function(self, info_queue, card) return {} end
}

here's a clip of what it does in game
https://medal.tv/fr/games/balatro/clips/maSuj2DknMtxdcBjc?invite=cr-MSxmQ3IsNDkxNTIxOTg3&v=3

Regarde Balatro Mod siscard ghost card bug de 3cl1pse_ et des millions d'autres vidéos Balatro sur Medal. #balatro

▶ Play video
timid zinc
#

is there a built in way to shuffle a hand after it's been played?

formal vessel
reef bobcat
#
        if context.setting_blind and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                func = (function()
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            SMODS.add_card ({key = 'c_lassooftruth_token'})
                    G.GAME.consumeable_buffer = 0
                            return true
                        end
                    }))
                    SMODS.calculate_effect({ message = localize('k_plus_tarot'), colour = G.C.PURPLE },
                        context.blueprint_card or card)
                    return true
                end)
            }))
    end
    }```

this is supposed to create the card upon blind select, but when i select blind the game crashes D:
daring scroll
formal vessel
#

i thought it was either like
{(

)}
or the inverse

daring fern
#

I did this by patching eval_card and faking a retrigger.

daring scroll
#

I could give it a try, see if it'll help

timid zinc
#

Is there a way to tell if a debuffed card is a joker?

daring fern
daring scroll
timid zinc
mystic river
daring scroll
#

I might shelve the buffed level values for now

#

WAIT

#

I didn't have the path set up on my main.lua file

#

facepalm

formal vessel
#

oof, glad u were able to figure it out

daring scroll
#

still need to see if the code works

formal vessel
#

true

daring scroll
#

staying organized is awesome, I just keep fucking forgetting to write the paths down lol

#

It works 🎊

#

aight time to buff the other hands

dry marsh
clear ocean
harsh belfry
#

something about converting cards to steel when a full house happens

#

idk

clear ocean
#

One things for certain… the house always wins

tall void
#

theres a way i can get the pokerhand played level in a calculate?

daring fern
tall void
vocal helm
#

How would I make my mod name tag a gradient?

#

this part

harsh belfry
red flower
vocal helm
#

thank you :)

bright ivy
#

I am new to this but I have watched a couple of videos and tutorials, I have downloaded Lovley Injector, the STEAMMODS and all of that stuff and the mod button shows up in my game, but my mod itself does not show up, I was wondering why.

wanton jolt
#

how is ur mod built

#

did u have a manifest.json that points to a lua file

bright ivy
#

I just found this error message

#

INFO - [G] 2026-02-23 00:52:45 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\Users\cfcos\AppData\Roaming\Balatro\Mods/LightMods/mod.json, ignoring: [lovely json "libs/json/json.lua"]:185: unexpected character '' at line 1 col 1

wanton jolt
#

how is your mod.json looking like

bright ivy
#
{
  "name": "Light Mods",
  "display_name": "Light Mods",
  "id": "light_mods",
  "prefix": "lm",
  "author": ["CFC"],
  "description": "Adds to the game",
  "version": "1.0.0",
  "main_file": "main.lua",
  "priority": 0,
  "badge_color": "#FF0000",
  "badge_text_color": "#FFFFFF",
  "dependencies": ["Steamodded"]
}

#

@wanton jolt I fixed it

#

I just deleted the file and rewrote the code

wanton jolt
#

yeah

ocean remnant
#

I'm pretty new to modding so I hope that this isn't a stupid question, but how can I change the x/y position of a joker on the screen?

mystic river
#

it helps, when someone asks you a follow-up question, to answer it

#

as opposed to vanishing for a week and then asking the exact same question again as though trapped in a time loop

faint yacht
#

-# This is not a Minecraft ARG.

dry marsh
thorn ingot
#

Guys. Another super quick question.

Where can I find the info for what nil in this means? Or rather what do you put in those places.

(card_type, nil, nil, nil, nil, nil, nil)

Can't find it. 😭

slim ferry
#

nil is just no value so it doesnt mean anything

#

But also nobody can answer this without knowing what the function is

thorn ingot
#

wait, really. I usually see this when ppl create cards with a joker. so I thought maybe there would be a way to know what to type in each of those places.

bright ivy
#

i was wondering why everytime I try to play the challenge to attempt to use the modded joker it crashes, I can give the crash report if that is helpful
I do have the edition and enhancement part, but I cut them out of this


-- =========================
-- FIRE SPINNER JOKER
-- =========================

SMODS.Joker {
    key = "fire_spinner",
    loc_txt = {
        name = "Fire Spinner",
        text = {
            "If hand is {C:attention}Two Pair{},",
            "7s and Aces become",
            "{C:red}Burned{} when scored"
        }
    },
    rarity = 3, -- Rare
    cost = 8,
    blueprint_compat = true,
    atlas = "fire_spinner_atlas",
    pos = { x = 0, y = 0 },
    discovered = true,

    calculate = function(self, card, context)
        if context.before 
        and context.scoring_name == "Two Pair"
        and context.scoring_hand then

            for _, scored_card in ipairs(context.scoring_hand) do
                local id = scored_card:get_id()

                if id == 7 or id == 14 then
                    -- Apply the burned edition directly
                    scored_card:set_edition("e_burned", true)
                end
            end
        end
    end
}

SMODS.Challenge {
    key = "fire_spinner_challenge",
    loc_txt = { name = "Fire Spinner Challenge" }, -- literal name

    -- Start-of-run jokers
    jokers = {
        {
            id = "fire_spinner",
            eternal = false,
            pinned = true,
        }
    },
}
#

Clarifying: I cant even enter the challenge because when I click on the button to play it the game goes to the crash report screen

thorn ingot
#

And why are there so many nil? 🤨

white hull
#

there’s docs on smods wiki and vanilla remade wiki

white hull
bright ivy
thorn ingot
grizzled tide
#

how do i go about moving the mult score contianer

white hull
#

so j_modprefix_name

mystic river
# thorn ingot And why are there so many nil? 🤨

because when thunk defined function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append), it obligated him and us to type all those nils after the area parameter to reach key_append even if we don't care about the parameters in between
getting around this is what SMODS.create_card was invented for

thorn ingot
gilded blaze
#

create_card also has some limitations such as not being able to apply a seal directly upon card init
SMODS.create_card does that normally

mystic river
#

and SMODS.add_card goes one further by properly handling putting the card in its area and doing all the relevant calculations

thorn ingot
#

Interesting, will keep it in mind. I was seeing it a lot when reviewing mods.

umbral zodiac
#

does anyone here know how i would put a dynatext object (or any ui element) directly on top of a box rather than next to it
working on an alternative for sliders which is more like a progress bar but i want the text actually on top of it and centered

gilded blaze
umbral zodiac
#

other than the text it works fine and i love it

grizzled tide
#

why does SMODS.GUI.chips_container(scale) not use scale-

umbral zodiac
#

pure and utter brilliance one must assume

gilded blaze
umbral zodiac
#

that could work

wanton jolt
#

:)µ

daring scroll
#

Very quick question. If I surrounded a Joker with if next(SMODS.find_mod("id")) then and endthen would it only be added to the game if the defined mod is detected?

gilded blaze
#

yes, but it's easier to add a dependencies field (array of mod ids) to your joker code

mystic river
#

and/or if not next(SMODS.find_mod("some id")) then return nil end at the top of the joker file. if you're doing individual joker files anyway

daring scroll
#

gotcha

frozen hamlet
#
SMODS.Sound({
  key = "cocosmod_boostersong",
  path = "cocosmod_boostersong.ogg",
  pitch = 1,
  volume = 1,
  music = true,
  select_music_track = function(self)
     if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
        return 1337
    end
end
})
mystic river
#

key = "cocosmod_boostersong",
i don't see "music" anywhere in here

#

music = true,
what you've done here is create the field music and set it to true. that isn't what "Your track's sound code must contain the string music" means

frozen hamlet
#

oh so how do i do that?

wanton jolt
#

change key to

mystic river
#

type the letters "music" somewhere after key =

wanton jolt
#

cocosmod_music_boostersong

#

or something

mystic river
#

you have to have the word "music" somewhere in your key

wanton jolt
#

i get ur new wiki pr now minty

#

lol

mystic river
#

there's nothing in SMODS.Sound called a "sound code"! who typed that?!

frozen hamlet
#

i did it but now its says bad argument #1 to 'newDecoder' (filename, file, or fileData expected)

#

now instead of just instally crash its crash when the principal menu appears

#

it is the music file now problem?

mystic river
#

honestly i haven't the foggiest clue what that error message means

#

wild guess, your file is in assets/sounds/ and is named exactly cocosmod_boostersong.ogg, correct?

gilded blaze
#

path should not be modified unless file name is changed

frozen hamlet
#

and its /assets/resources/sounds should i change that too?

mystic river
frozen hamlet
#

yeah but i dont really understand the part of the API methods

mystic river
#

there's exactly one api method and none of your current questions relate to it

frozen hamlet
#

yeah the problem got fix and the music plays well the problem now is its crashes because of the background

#

like

gilded blaze
#

send crash log

frozen hamlet
gilded blaze
#

that's no longer the crash related to SMODS.Sound

frozen hamlet
#

yeah

gilded blaze
#

send the full crash log

#

we need the whole stack trace to start debugging

frozen hamlet
#

there it is

formal vessel
hardy vessel
#

If I want to update how much a blind's payout dollars are during a blind, is there a way to update the text shown (similarly to the required chips)?

slim ferry
#

can i make main_ends go into anything other than the first description box

#

<@&1133519078540185692>

slim ferry
#

dies

red flower
#

i will note it to pr it after next smods

bright ivy
bright ivy
formal vessel
# slim ferry <@&1133519078540185692>

dont ping the <@&1133519078540185692> they will get mad if u ping the <@&1133519078540185692> cuz pinging the <@&1133519078540185692> is very bad and it will make the <@&1133519078540185692> very angry if you ping the <@&1133519078540185692>

karmic creek
#

but why

formal vessel
fading rivet
#

How could I return played cards to hand?

dreamy thunder
#

it has this part

wintry solar
#

wait a couple of days and do it cleanly 👍

median veldt
#

alright what am I doing wrong this time 😭

#

granted i have no idea what that consumable usage thing is and if smods affects it

#

i just took fortune teller from vremade and turned tarot into shark_Spell

red flower
#

i dont think thats automatic

median veldt
#

gdi

red flower
#

ah it seems like it is

#

but lowercase

median veldt
#

ok but like

#

i Tried that

red flower
#

is it the same crash

median veldt
#

is this a new feature i lowkey havent updated smods in ages

red flower
#

no

#

you should tho

median veldt
#

i mean heres the version how bad's the damage

red flower
#

ok i think its because its not created until you use one

#

so (G.GAME.consumeable_usage_total.shark_spell or 0)

median veldt
#

🥹

#

wait so why does it work with tarot

red flower
#

because the vanilla oens are created at the start of the game

red flower
median veldt
#

noted

#

sooo this?

red flower
#

yes

median veldt
#

kk one sec

#

it iiiss not gaining anything

#

sob

fading rivet
median veldt
#

alwaus update your smods ok it works now? but the locvar isnt...

wintry solar
#

it's not in 1016

median veldt
#

ah

formal vessel
median veldt
bright ivy
#
extern number time;
extern number hovering;

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
    vec4 tex = Texel(texture, texture_coords);

    // Bottom-center origin
    vec2 origin = vec2(0.5, 1.0);
    float dist = distance(texture_coords, origin);

    float gradient = 1.0 - smoothstep(0.0, 1.2, dist);

    float pulse = sin(time * 4.0) * 0.5 + 0.5;

    vec3 orange = vec3(1.0, 0.4, 0.0);
    vec3 red = vec3(1.0, 0.0, 0.0);

    vec3 burn_color = mix(orange, red, pulse);

    float heat = sin(time * 2.0) * 0.25 + 0.75;
    burn_color.r *= heat;

    tex.rgb = mix(tex.rgb, burn_color, gradient * 0.6);

    return tex * color;
}

Error:

engine/sprite.lua:96: Shader uniform 'mouse_screen_pos' does not exist. A common error is to define but not use the variable.

frosty bone
red flower
#

is this jokerforge

formal vessel
red flower
#

im guessing the easiest way to tell is for them to tell me if they used joker forge, which is why im asking

median veldt
#

also "this wont work" is very unhelpful

#

what's your issue

bright ivy
normal crest
#

easiest way to tell if it's jokerforge is [1] = a string

frosty bone
#

when a polychrome joker triggers, it wont add mult

fading rivet
#

is context.modify_scoring_hand or context.before first?

red flower
fading rivet
#

perfect, thx

frosty bone
red flower
#

not many people are familiar with it here

median veldt
#

how does one check if a mod is cryptid compat

frosty bone
#

ah

fading rivet
median veldt
#

the former

fading rivet
#

boot them up and hope they dont crash

median veldt
#

ykw fair point

fading rivet
#

if its the latter I would check for demicolon compat on some of the cards

median veldt
#

i don't reckon ive ever heard of demicolon lol

#

i dont play cryptid too often

fading rivet
#

card.ability.cry_demicolon_compat

median veldt
#

mm

fading rivet
#

the card force triggers jokers

median veldt
#

i should add talisman compat to my mod

fading rivet
#

well uhhh

#

whoops

#

good news its half working

median veldt
#

what on earth

fading rivet
#

okay fixed it

median veldt
#

what even was the issue 😭

fading rivet
median veldt
#

lol

fading rivet
#

on to the next blind

primal robin
knotty compass
#

heya question how do you draw a specific card from deck? (in my case card with specific edition)

daring fern
knotty compass
crisp coral
#

this context.drawing_cards block, replace the enchanted stuff with your edition check

bright ivy
#

Wondering how to properly remove the card after it hits the 1/4:

SMODS.Edition {
    key = "burned",
    shader = "burned",

    loc_txt = { 
        name = "Burned",
        label = "Burned",
        text = {
            "1 in 2 chance to give +5 Mult",
            "1 in 4 chance to give X4 Mult",
            "then be destroyed"
        }
    },

    config = {},

    in_shop = false,
    pools = {},
    weight = 0,

    in_pool = function(self, args)
        return false
    end,

    calculate = function(self, card, context)
        if context.cardarea == G.play and context.main_scoring then

            local roll = pseudorandom(pseudoseed('burned_roll'))

            if roll < 0.5 then
                return { mult = 5 }

            elseif roll < 0.75 then
                return {
                    x_mult = 4,
                    remove = true
                }
            end
        end
    end
}
daring fern
# bright ivy Wondering how to properly remove the card after it hits the 1/4: ``` SMODS.Edi...
local effects = {}
if context.main_scoring and context.cardarea == G.play or context.pre_joker then
    if SMODS.pseudorandom_probability(card, 'burned_roll', 1, 2) then
        table.insert(effects, {mult = 5})
    end
end
if context.main_scoring and context.cardarea == G.play or context.post_joker then
    if SMODS.pseudorandom_probability(card, 'burned_roll', 1, 4) then
        if context.main_scoring then
            card.modprefix_destroy = true
        else
            SMODS.destroy_cards(card)
        end
        table.insert(effects, {xmult = 4})
    end
end
if context.destroy_card and context.destroy_card.modprefix_destroy then
    return {remove = true}
end
return SMODS.merge_effects(effects)
grizzled tide
#

do you guys know an example of how to add a new scoring window, ive been reading the documentation over and over again but i cant get it to work

wintry solar
grizzled tide
#

chips x mult x something else

wintry solar
fading rivet
#

How can I check if a card has a seal, or if it has an edition

daring fern
fading rivet
#

thx

fading rivet
daring fern
fading rivet
#

ight that works

#

would the lists of seals and editions be in G.P_CENTER_POOLS["Seals" or "Editions"]?

wintry solar
#

You can also do if card.seal

fading rivet
#

or not meaning the lua operator

red flower
#

G.P_SEALS iirc

fading rivet
#

thx

#

okay hopefully this works

#

wait minor stupid
tried to index G.P_SEALS lol

#

okay G.P_CENTER_POOLS["Editions"] is incorrect

#

thats working fine

#

its line 478 that's crashing

#

why that ?

#

the effect is to add a seal if it doesn't have one yet

#

oop

fading rivet
wintry solar
#

You should use the poll functions

fading rivet
#

ive seen them but they wont show up with info from the lsp

#

nvm I got it

wintry solar
#

You just need SMODS.poll_seal({seed = "X", guaranteed = true}) and similar for editions

fading rivet
#

yay thats all the blinds done (except acorn)

#

Where could I find resources to learn how to make a custom UI page?

grizzled tide
hardy vessel
#

trying to make a joker that gives mult when a debuffed card "scores", but i'm having issues. I have this, but no mult is being gained.

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play then
            if context.other_card.debuff then
                return {
                    mult = card.ability.extra.mult
                }
            end
        end
    end
daring fern
daring fern
grizzled tide
hardy vessel