#💻・modding-dev

1 messages · Page 667 of 1

granite jay
#

Yeah I wanna figure out how to change the card description

#

I’ve already got a base system working btw

#

This is what I mean btw

wanton jolt
#

i would apply a sticker ?

#

and remove that sticker on blind debuff/defeat

daring fern
wanton jolt
#

yeah do that

#

if you use a sticker

karmic creek
#

sweet

wanton jolt
#
local new_card = copy_card(G.playing_cards[pseudorandom(pseudoseed('felijo_ins_revo'), 1, #G.playing_cards or 1)])
                
                if card.ability.extra.count >= 5 then
                    new_card:set_ability(superior_enhancement)
                end
                
                G.E_MANAGER:add_event(Event({
                delay = 1,
                    func = function()
                        new_card:start_materialize()
                        new_card:add_to_deck()
                        G.deck:emplace(new_card)
                        return true
                    end
                }))

so it adds the card to an effective "deck" and i can't see it in the full deck view (53/52)

How can i add the card properly to the deck? (53/53)

umbral spire
# granite jay

if that's the final description, I think it's slightly unclear, I think mentioning X0 chips (if that's what it does?) makes more sense than "doesn't grant base chips" /lh /nf

long sun
#

i'm creating a card using Card(). how can i give it a button that appears when selecting it?

#

or does it not work like that?

wanton jolt
#

u have to hook function G.UIDEF.use_and_sell_buttons(card) i believe

long sun
#

ah grand

#

i have one of those already, so i'll modify that

#

thanks!

#

how do i make a created card selectable?

#

i'm creating my own collection, but the cards can't be selected

wanton jolt
#

wait i think i misunderstood

faint yacht
#

-# iirc Cryptid lets you "highlight" cards in the collections... so a Card:click() hook?

long sun
#

-# ah ye i'll take a look

#

aha, it's down to the cardarea

faint yacht
#

-# And/or Card:highlight(is_highlighted).

long sun
#

trues

daring fern
# wanton jolt bump
local function better_copy_card(card, new_card, area)
    if not card then return nil end
    local area = area or (new_card and new_card.area) or card.area or G.jokers
    local cardwasindeck = new_card and new_card.added_to_deck or nil
    local copy = copy_card(card, new_card)
    if new_card and cardwasindeck then copy:remove_from_deck() end
    if card.playing_card then
        G.playing_card = (G.playing_card and G.playing_card + 1) or 1
        copy.playing_card = G.playing_card
        G.deck.config.card_limit = G.deck.config.card_limit + 1
        table.insert(G.playing_cards, copy)
    end
    if (new_card and cardwasindeck) or not new_card then copy:add_to_deck() end
    if not new_card then area:emplace(copy) end
    return copy
end
better_copy_card(card)
wanton jolt
#

oh wow

#

thanks

fringe patrol
#

hey yall, so i'm trying to make a blind that (similar to The Wheel) has a 1-in-7 chance of debuffing each card in your hand

#
    loc_vars = function(self)
        local numerator, denominator = SMODS.get_probability_vars(self, 1, 7, 'v_rainbow')
        return { vars = { numerator, denominator } }
    end,
    collection_loc_vars = function(self)
        return { vars = { '1' } }
    end,
    calculate = function(self, blind, context)
        if not blind.disabled then
            if context.to_area == G.hand and
                SMODS.pseudorandom_probability(blind, 'v_rainbow', 1, 7) 
                then return { debuff = true }
                else return { debuff = false }
            end
        end
    end,
median veldt
#

check vremade for the wheel perhaps?

pastel kernel
#

i wanna use this for ease bg color but idk how

median veldt
#

looks like it should work, though i've never made a blind

fringe patrol
#

here's the vremade code for the wheel's calculate:

#
    calculate = function(self, blind, context)
        if not blind.disabled then
            if context.stay_flipped and context.to_area == G.hand and
                SMODS.pseudorandom_probability(blind, 'vremade_wheel', 1, 7) then
                return { stay_flipped = true }
            end
        end
    end,
#

not sure exactly what i'm missing in my case. either way, it's not doing anything on when testing, the cards all stay undebuffed

long sun
#

whoopsie

fallow breach
#

what is this btw

daring fern
# fringe patrol ```lua loc_vars = function(self) local numerator, denominator = SMOD...
calculate = function(self, blind, context)
    if not blind.disabled then
        if context.stay_flipped and context.to_area == G.hand and SMODS.pseudorandom_probability(blind, 'v_rainbow', 1, 7) then
            SMODS.debuff_card(context.other_card, true, 'v_rainbow')
        end
    end
end,
disable = function(self)
    for k, v in pairs(G.playing_cards) do
        SMODS.debuff_card(v, false, 'v_rainbow')
    end
end
fringe patrol
#

lemme try this

pastel kernel
#

idk whata i'm doing here```lua
BustB.easebg = function()
ease_background_colour { new_colour = G.C.WHITE, special_colour = HEX('b00b69'), tertiary_colour = G.C.BLACK, contrast = 2 }
return (
#Cryptid.advanced_find_joker(nil, "busterb_Grandiose", nil, nil, true) ~= 0
) and 100.000
end

#

if you get the joker and the joker has this rarity, the background changes, but i don't fucking know how to make that happen.

fringe patrol
#

or would i need to use recalc_debuff?

long sun
#

i need the ui used for the consumables page of the collection, but i can't find the definition for it — where is it?

red flower
red flower
clear ocean
#
AltTexture({
    key = 'joker',
    set = 'Joker',
    original_sheet = true,
    localization = false,
    path = 'joker.png',
})

TexturePack({
    key = 'watson',
    textures = { 'watson_joker' },
    loc_txt = {
        name = "Watson as Lucky Cat",
        text = { "My cat, Watson,", "as Lucky Cat" }
    }
})
#

any way to make it where its only lucky cat

#

keys?

#

it works!

long sun
#

ah no wait i think i found it

#

G.UIDEF.consumable_collection_page

#

thanks ^u^

worthy stirrup
#

How do I check each cards rank?

    calculate = function(self, card, context)
        if context.cardarea == G.play and context.main_scoring then
            
        end
    end,
frosty rampart
near coral
#

My coder told me he can't directly do ÷mult, can someone help with code to solve that

#

Is it impossible to do ÷1.2 mult, should I just have it do X0.833 mult instead

subtle hawk
near coral
#

Alr

subtle hawk
near coral
#

Ik

#

Instead of saying X0.8333 it'll say ÷1.2

near coral
#

Jumbo rekoj is too small when turning a wee joker into them

#

They're the size of a regular joker when jumbo rekoj is supposed to be 30% bigger

subtle hawk
#

Regardless my best bet is just setting Jumbo's T.h and T.w manually

near coral
subtle hawk
#

Interesting, might be something with how display_size is handled idk :/

subtle hawk
vital wren
#

what tools exist for mod testing? i want to be able to spawn in specific jokers or other cards to test that they're working as intended without needing to play until i find them

thin patrol
#

fast question:
how can I debuff a number card (like queen example) when you have a certain joker?

near coral
subtle hawk
median veldt
#

might be thinking of something else

near coral
#

That's all I got

daring fern
thin patrol
#

thanks 👍

rapid stag
tulip pecan
#

how would I change rates for each of my custom consumables individually, and not by simply modifying the shop_rate value in the SMODS.ConsumableType definition?

vital wren
#

oh, i would like to know how to do that too

frosty rampart
#

don't think there's a specific easy way
but you can have each consumable set its in_pool function to only return true if a random number is greater than some arbitrary value
e.g. a fairly common one would check if pseudorandom("seed") > 0.2 while a rarer one would check if pseudorandom("seed") > 0.7
you can also set up rarities for the consumabletype, if that serves your purposes better than controlling every single consumable's weight uniquely

umbral zodiac
#

G.GAME.consumabletypekeybutlowercase_rate

#

oh wait

#

sorry i thought you meant modifying the rate overall midrun

#

i need to learnhow to read

tulip pecan
frosty rampart
#

yea you can set custom rarities
i haven't toyed with this personally yet so i can't help much further than just this documentation

tulip pecan
#

oh fire

#

ill check into that

oblique lotus
#

How can you check what booster pack type you are currently in?

vital wren
#

i think there's a context for that but i dont remember off hand

oblique lotus
#

I think I found it, its SMODS.OPENED_BOOSTER.config.center.kind for future refrence

vital wren
#

oh nice. thanks for sharing

rapid stag
#

HELP cirSlain

#

that's the wrong video

granite jay
rapid stag
#

ok so i managed to fix the scale with the delay_sprite arg, but i can't get the undiscovered floating sprite to go away when the item is locked

vital wren
#

it would be nice if taking control of a joker's calculate wipes out the vanilla calculate entirely... needing to also use lovely to disable the vanilla effect is kinda weird

daring fern
vital wren
#

does setting it to the same string not still let it see it's vanilla code?

daring fern
vital wren
#

but i dont want to change its name

daring fern
umbral zodiac
#

name is a property that most vanilla calculations check for instead of the joker's key
setting it to an empty string will (in most cases) make the joker not activate as normal

#

note that it won't work on all jokers

vital wren
#

okay, does name go inside config or in the base take_ownership space? i dont see it in the documentation

umbral zodiac
#

inside the config
like SMODS.Joker:take_ownership("joker", {name = ""})

vital wren
#

i meant the config field. your code snippet suggests i should do it like this:

        config = {
            extra = {
                odds = 3,
                seal = 'Gold',
            },
        },
umbral zodiac
#

ohh i see

#

yes that would be correct

vital wren
#

okay, ill try this

umbral zodiac
#

it does not go in the config table, that's for values the joker uses like mult, etc

vital wren
#

hmm, im still getting a crash, so ill post some info and hopefully i can get help figuring out what's happening

#

my code for rough gem:

    { -- table of properties to change from the existing object
        name = '',
        config = {
            extra = {
                odds = 3,
                seal = 'Gold',
            },
        },
        loc_vars = function(self, info_queue, card)
            local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'vb_rough_gem')
            return { 
                vars = { 
                    numerator, 
                    denominator, 
                }
            }
        end,
        calculate = function(self, card, context)
            if context.before then
                local suits = 0
                for _, scored_card in ipairs(context.scoring_hand) do
                    if scored_card:is_suit('Diamonds') and not scored_card:get_seal(true) and 
                    SMODS.pseudorandom_probability(card, 'vb_rough_gem', 1, card.ability.extra.odds) then
                        suits = suits + 1
                        scored_card:set_seal(card.ability.extra.seal, nil, true)
                        G.E_MANAGER:add_event(Event({
                            func = function()
                                scored_card:juice_up()
                                return true
                            end
                        }))
                    end
                end
                if suits > 0 then
                    return {
                        message = localize('k_upgrade_ex'),
                        colour = G.C.MONEY
                    }
                end
            end
        end,
    },
    true    -- silent | suppress mod badge
)```
#

the crash log. it's still trying to use ability.extra as a single number that rough gem has in vanilla

#

currently no other jokers are affecting this. rough gem i have it's name set differently and i even commented out its original code in a lovely toml

#

im using almost identical code in context.pre_discard and it works fine

vital wren
#

since when?

frosty dock
#

since you introduced this changed rough gem

#

if you didn't, it will still have the original ability values

vital wren
#

it's the first time the joker has triggered in this run. does it not update the code of the joker calculate if i update the mod and load into the saved game?

frosty dock
#

the config values are default ability values

#

they don't get reapplied mid-run

#

that would ruin scaling jokers pretty bad

#

code does update, but those values don't

vital wren
#

it's ability values should be what my code says. the mod was there before the run started

frosty dock
#

try replacing it with a new copy of the joker anyways

vital wren
#

uh, okay. ill have to dig one up. do we have a debug tool for just giving specific jokers?

frosty dock
vital wren
#

this documentation is very sparse. how do i actually use this to spawn a joker?

umbral zodiac
#

holding tab reveals all debug commands also

vital wren
#

i see. okay. thanks. wish that was in the read me on the github. it doesn't even show up in the help text in console. okay. new rough gem in a new run functions as expected. ill keep that in mind going forward for testing

frosty dock
vital wren
#

oh i missed tab for menu when i read it before. i was pressing 3 on the blind select screen thinking i might get a pop up or something asking me what i wanted to spawn. lawl

frosty dock
#

fair nuff, it's indeed a bit imprecise

vital wren
#

now i know. thanks for y'alls help

frosty dock
#

np

tulip pecan
#

How come when I try to insert this consumable (and all others under it) into my set, it gives this crash, despite the others above being inserted just fine?

#

My only thought process is that all the others above were copies of tarot cards, while these are copies of planet cards. . . not sure if that makes a difference but it clearly did something

daring fern
tulip pecan
#

😭

#

yep that's probably it

vital wren
#

is there a way to disable the current fps and base event queue text in the top corner when using debug plus?

frosty dock
tulip pecan
#

How do I change a single consumable's text at the bottom to be unique to the whole set, like how base game does with Planet X or pluto?

mystic river
#

(and ik that's the joker page but it applies to consumables too. all centers iirc)

vital wren
#

when using SMODS.poll_enhancement is there a way to exclude m_stone from its pool?

#

maybe like, do get_current_pool("Enhanced") and remove m_stone from the pool and pass that as args.options? i just dont know how to do that

wild patrol
#

you think this is good as a protection joker

crisp coral
#

no not really

#

rare cards are rare

wild patrol
#

so uncommon?

sleek valley
#

uncommon is a better idea imo

#

cause you can get alot of commands

faint yacht
sweet nimbus
#

Is there any way to force redeem a voucher?

maiden phoenix
#

Card:redeem()

wintry solar
wild patrol
#

1 min by default

#

But can be changed

sleek valley
#

i'd still recommend uncommon anyway lol

wild patrol
#

I should be having an alpha ready soon

sleek valley
#

just cause rare cards basically dont show up at all in shops

wild patrol
#

Just putting on finishing touches

sleek valley
wild patrol
#

Before an alpha get better feedback

#

Other than yeah command works in chat

sleek valley
#

if only i had a twitch, i'd play it :3

wild patrol
#

Probably not gonna be ready for the alpha

primal robin
#

theres no way

wild patrol
#

Doom go brrrrr

#

Idea is a command to force you to play e1m1 to continue

sleek valley
#

that's demonically funny, i love it

granite raptor
sleek valley
#

also if i can make a suggestion, idk how doable it is
what about a blind that forces TwitchChat Plays? so it's the chat that has to help the streamer instead of just the streamer playing

#

why? because it's funny

wanton jolt
#

ooooooo

wild patrol
#

Maybe for a release build

wild patrol
#

But that sounds like a final boss thing

sleek valley
#

fair

wanton jolt
#

stocks finally has art

sleek valley
wanton jolt
#

lol!

wild patrol
#

Finally chat can show streamer how to properly play

#

sells all jokers

granite raptor
#

command that force selects a playing card a la cerulean smiley_face

sleek valley
#

that'd be fucking evil

do it

wild patrol
#

Have a command that destroys a random card in hand

sleek valley
#

even better lol

wild patrol
#

May or may not keep it depending on how the alpha run goes

#

once this last joker is implemented alpha probably be available on github

#

one of the jokers is just a straight up copy of bull

#

so def need to change that

#

might make it a rare and give it a xchip mult for certain amout of money

wild patrol
#

tried to make it a better bull

strong plume
#

Hello, does anyone know why this tag isnt doing anything? It just sits there doing nothing.

daring fern
strong plume
#

Ah; do you know a fix?

#

Wait, I think I know some workaround - thank you!

#

hm no this prob doesnt work

worthy stirrup
#

im getting a Unexpected <exp> error, is there something I forgot to close?


SMODS.Joker {
    key = 'CurtainCalls',
    atlas = 'Joker',
    loc_txt = {
        name = "Curtain Calls",
        text = {
            {
                "Random Joker is retriggered"
            },
            {
                '{C:inactive} Number Go Up{}',
                '{s:0.8,C:inactive} Infinite jesters still get curtain calls.{}',
            }
        }
    },
    pos = { x = 0, y = 0 }
}


# Lemon Joker
#

no wait, # isnt comment, isnt it

frosty dock
worthy stirrup
#

ive been using python a lot

sweet nimbus
maiden phoenix
#

Oops, must be Card:apply_to_run(center) then

#

That's where most of the voucher stuff is done it seems

worthy stirrup
#

I dont remember where i read it but I remember reading that I could mak my own one of these, how could I do that

red flower
worthy stirrup
#

thank you

thorn basin
#

question: which command should I use for rounding divisions?

faint yacht
#

math.floor to round down, math.ceil to round up.

thorn basin
#

aight, thanks!
also nice to see ya again Ali!

faint yacht
#

To round to nearest integer, math.floor(num+0.5).

thorn basin
#

I made an enhancement that gives Xchips of the half of the current total $ if played.
And that gives $ of the half of the total chips scored in the current played hand.
There are 2 problems that I'd like to solve.

#
  1. the $ counter in the label text box doesn't update whenever I get new money
  2. for some reason the Mime joker's ability doesn't work on this enhancement
#

How can I fix both problems?

strong plume
wild patrol
#

We put a special command in the twitch mod for devs, mods, a vips of twitch channels

#

It's the text command

#

To display text on screen

#

Was originally gonna be a whitelist but we felt that that would make whitelisting easier without have to manually put usernames in

thorn basin
gilded blaze
#

wait, hold on

thorn basin
gilded blaze
#

it's done in the card's update method

#

don't do that in calculate

slim ferry
#

You should probably just calculate the number each time in loc vars

#

Instead of repeatedly setting a value in the config

thorn basin
#

wait hold on

#

how should I do that then?

gilded blaze
#

wait nvm

#

it's context.main_scoring and context.cardarea == G.hand

slim ferry
gilded blaze
#

that's how you do held-in-hand effect for enhancements

slim ferry
#

Except dont set to the ability table

thorn basin
slim ferry
#

You dont need the config at all

long sun
slim ferry
#

Also

#

Displaying the dollars accurately will always be janky

wild patrol
slim ferry
#

Because the chips amount will be 0 usually

wild patrol
#

Just so the sticker doesn't cover it

long sun
vocal helm
#

How do I get a card ID from its base.value again? i.e. convert "King" into 13

slim ferry
#

SMODS.Ranks[key].id

vocal helm
#

thanks :>

thorn basin
slim ferry
#

just return math.ceil(hand_chips/2) directly in loc_vars and calculate for the dollars

#

Instead of setting it in card.ability

slim ferry
#

remove the card.ability.extra.Xchips in loc_vars since that doesnt exist anymore

thorn basin
slim ferry
#

Yea

long sun
#

how do i pass arguments into create_option_cycle?

#

and, what do those arguments look like when the opt_callback gets them?

thorn basin
long sun
#

i have:
create_option_cycle({ options = consumable_options, w = 4.5, cycle_shoulders = true, opt_callback = 'phanta_deathnote_your_collection_consumable_type_thing', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = { snap_to = true, nav = 'wide' } })

#

received by:
G.FUNCS.phanta_deathnote_your_collection_consumable_type_thing = function(args)

slim ferry
#

should be (hand_chips or 0)

red flower
#

usually the object gets passed

long sun
#

ah lemme check

red flower
#

this is what gets passed

long sun
#

ah i see

#

wait i don't get it ;u;

#

okay so args.cycle_config is passed in

#

ah ^^ okay i see

#

lemme try something then

thorn basin
rapid stag
wintry solar
#

Use that new function I made and can’t remember the name of

#

SMODS.clean_up_children or something

rapid stag
#

SMODS.theNewFunctionEremelMadeThatTheyCantRememberTheNameOf()
i think clean_up_children is the name, but i call set_ability which calls that. i guess i'll try adding more calls in my code to see if that changes anything

wintry solar
#

It is possible they undiscovered flags aren’t adjusted in set ability

acoustic drum
#

I can't understand why but my custom booster pack keeps placing multiple of the same joker inside when opened...
This is the pool for it:

SMODS.ObjectType({
    key = "lamodSpawnable",
    default = "j_lmd_multprint",
    cards = {},
    rarities = {
        {key = "Common", weight = 0.5},
        {key = "Uncommon", weight = 0.2},
        {key = "Rare", weight = 0.25},
        {key = "Legendary", weight = 0.05}
    },
    inject = function(self)
        SMODS.ObjectType.inject(self)
    end
})

And this is the booster code:

SMODS.Booster {
    key = 'booster_lamonmod',
    group_key = "k_lamonmod_booster_group",
    atlas = 'jokers_lmd', 
    pos = { x = 0, y = 0 },
    discovered = true,
    draw_hand = false,

    config = {
        extra = 3,
        choose = 1, 
    },

    loc_vars = function(self, info_queue, card)
        local cfg = (card and card.ability) or self.config
        return { vars = { cfg.choose, cfg.extra } }
    end,

    weight = 1,
    cost = 5,
    kind = "LamonmodPack",
    
    create_card = function(self, card, i)
        ease_background_colour(HEX("ffac00"))
        return SMODS.create_card({
            set = "lamodSpawnable",
            area = G.pack_cards,
            skip_materialize = true,
            soulable = true,
        })
    end,

    ease_background_colour = function(self)
        ease_background_colour_blind(G.STATES.BUFFOON_PACK)
    end,
    
    select_card = 'jokers',

    in_pool = function() return true end
}

It keeps spamming the default joker, even when I only have 1 or 2 of the ones in the pool (There are 9 inside the pool)

red flower
#

it rolls rarity first so if there's nothing from that rarity it will get the default too

acoustic drum
#

Ohh, is there any way to avoid that?

red flower
#

you would have to manually determine the rarity in the boosters create_card probably

acoustic drum
#

I'll try making my own polling then, I guess. Thanks!

rapid stag
#

is Game:main_menu() called when returning to the main menu after winning/losing a run?

daring fern
next grail
#

could someone please help me fix this lua

daring fern
next grail
#

how comes the crash log say about line 57 then?

red flower
#

it doesn't know exactly where the error is so sometimes it will say surrounding lines

#

also if you knew the error was in line 57 it could have helped if you said what that line was when asking help lol

daring fern
next grail
granite jay
#

I'm tryna apply a shader that tints these cards blue, anyone able to help?

glass scaffold
#

Is there a rank variation of context.debuff_card:is_suit like ...:is_rank?

red flower
#

card:get_id() gets the id of the rank

#

but there's no get_rank

#

you can also use card.base.value for the key

glass scaffold
red flower
#

i think get_id counts debuffed cards normally

glass scaffold
red flower
#

depends on what you mean when a hand is played, any scoring context including before is technically when a hand is played

glass scaffold
#

And finally:

What formats of video can Balatro play? I know .OGV is on the board, but can .MP4 work?

faint yacht
glass scaffold
#

Ah.

#

So how does one get a .OGV?

#

Nevermind, VLC can do it.

#

Ok, new issue:

It flickers. It doesn't even play the file.

granite jay
#

Do balatro profiles check how many consumable cards you sold?

I want this for a joker unlock condition where you have to sell a certain amount of consumables.

vocal helm
#

Is there a context for when a card's rank changes?

red flower
vocal helm
#

thanks!

glass scaffold
#

We didn't even ping the mods

sleek valley
#

my card is supposed to not trigger if the scored card has a seal, but still does anyway??
i dont know what to do, im pretty sure i did everything right

rough furnace
#

card is your joker

#

you want to check scored card

daring fern
sleek valley
#

...i am BEYOND stupid ;w;

daring fern
#

It should only be get_seal when you're not checking if it has a seal to apply a seal.

rapid stag
#

actually, why don't i just remove undiscovereds from that pool altogether

rapid stag
#

crash on startup cirLost
all i was doing was making manual edits to my mod config file via debugplus

red flower
#

you can just delete the saved config

rapid stag
red flower
#

well its probably not the same error

#

unless youre still saving something weird to config

rapid stag
#

oh it's because i'm copying a recursing table cirDerp

rapid stag
#

how do i distinguish between a keyed table and indexed table in code

#

oh i could just do #table > 0, right?

#

and if it is, it's indexed

red flower
#

well that won't detect tables that are both but probably good enough

frosty rampart
#

yea there's not much of a distinction between keyed and indexed tables in lua
indexed tables are just keyed tables where the keys are the natural numbers in order

fiery mirage
#

i did use jokerforge at first for the general mod structure, but moved to coding by hand cause jokerforge's pretty limited

red flower
#

hmm no idea, I'm guessing this is some problem with stone cards removing ranks that needs a more manual approach but i couldn't tell you rn

fiery mirage
#

no worries, honestly i'm happy that my very first joker is actually working exactly as intended, even if it's visually messesd up :D

gilded blaze
#

it's essentially vanilla behavior (Vampire reveals the card front before sucking Stone), smods tried to "fix" it but failed I assume

daring fern
# rapid stag therefore bump
local oldcenterdrawstepfunc = SMODS.DrawSteps['center'].func
SMODS.DrawSteps['center'].func = function(self, layer)
    local thunk
    if condition then
        thunk = self.config.center.discovered
        self.config.center.discovered = true
    end
    local g = oldcenterdrawstepfunc(self, layer)
    if condition then
        self.config.center.discovered = thunk
    end
    return g
end
vital wren
#

is there a context for a card in hand being triggered? i want a joker to react to that. whether its gold or steel cards or a parking joker or whatever

daring fern
rapid stag
#

and something here is causing CTDs when starting a new run or continuing one

daring fern
rapid stag
#

...oh, recursion cirDerp

#

derp

#

psa to not develop balatro mods while sleep deprived

glass scaffold
rapid stag
# rapid stag no dice

oh i never changed condition cirDerp

having discovered result in true won't actually discover the card itself, right? since it's supposed to be locked

daring fern
rapid stag
#

...what do i make condition, then?

not self.config.center.unlocked?

#

oh no, it'd need to be self.config.center.unlocked == false to account for nil

#

which would be everything that's locked

#

it's not specific to one item, it's all locked things

#

alright that seems like it works, thanks cirHappy

glass scaffold
rapid stag
#

anyone know what's going on with my scaling values here?

red flower
#

is this what you had before the new smods update?

rapid stag
#

me or them

red flower
#

you

rapid stag
#

this is what i'm writing because of the new smods update

red flower
#

then idk

near coral
#

Is there a way to make a joker detect the current ante level

rapid stag
#

G.GAME.round_resets.ante

near coral
#

Like I know it's possible to just make it update when defeating a boss blind or when a voucher is used but I also regularly do it with debug+ for testing purposes

near coral
#

Would that still work there

rapid stag
#

G.GAME.round_resets.ante * 3 would do that, yes

near coral
#

So something along the lines of + mult = G.GAME.round_resets.ante * 3 or something

rapid stag
#

yes

near coral
#

Ok

reef bobcat
#

ok so im making a joker that states that if the hand you play only contains cards of a certain suit then the hand is counted as a flush

#
        return { vars = {card.ability.poker_hand}}
    end,
    calculate = function(self, card, context)
        if context.evaluate_poker_hand and context.scoring_name == 'Three of a Kind' or context.scoring_name == "Five of a Kind" then
    return {replace_scoring_name = 'Flush'}
    end
end
}```

is this a good place to start?
red flower
#

thats how you change a hand, yes
have you tested that?

#

you would need to replace the check for 3oak and 5oak for one that checks suits

reef bobcat
near coral
#

My coder is having difficulty lowering the cost of rerolls by $2

#

As part of a rekoj

#

It also increases the price of everything else by $1 but that part works fine

#

It's just the lower reroll price

daring fern
near coral
#

Thank you

reef bobcat
#
    loc_vars = function(self, info_queue, card)
        return { vars = {card.ability.poker_hand}}
    end,
    calculate = function(self, card, context)
        if context.evaluate_poker_hand and playing_card:is_suit('Spades', nil, true) then
    return {replace_scoring_name = 'Flush'}
    end
end
}```

ok i tried this but oops all crashes
red flower
#

playing_card is not a thing there

#

you want to loop through context.scoring_hand and check each card in that table

vital wren
#

im in context.before and context.cardarea == G.hand and i need to check if specific other jokers exist. what's the function for checking if a joker is in hand?

daring fern
vital wren
#

yes, that one. thanks

reef bobcat
#
    loc_vars = function(self, info_queue, card)
        return { vars = {card.ability.poker_hand}}
    end,
    calculate = function(self, card, context)
        if context.scoring_hand and not context.other_card:is_suit(card.ability.extra.suit) then
    return {replace_scoring_name = 'Flush'}
    end
end
}```

tried a thing with this but no dice lol
daring fern
reef bobcat
#

it says unexpected symbol near if

#

like the top if

#

wait hold on

#

ok it works

#

i messed up a line

#

thank you!!

vital wren
daring fern
reef bobcat
#

i tried to do and not context.scoring_name == 'straight flush' next to evaluate poker hand

#

but that didn't seem to do the trick

daring fern
reef bobcat
#

ohhhhhhhhhhhhhh

red flower
tired flare
#

does anyone know how to add custom messages like the "extinct" message

#

I've been trying on my own for awhile and having no luck

#

sorry if this is like a stupid question

gilded blaze
#
return {
    message = "text",
}
tired flare
#

wait that's it

#

all the resources online said to use stuff like "localize"

#

Thank you though

gilded blaze
#

if you don't plan to localize your mod, returning plain text is fine

#

this is actually the choice of a lot of monolingual modders

tired flare
#

you're my goat

#

❤️

gilded blaze
#

making a mod is child's play
making a good mod requires real talent and knowledge

tired flare
#

bro hitting me with the wisdom

vital wren
#

in context.after can i check how many chips the hand just played is worth?

daring fern
vital wren
#

is that for just the one hand and not the entire round?

pearl whale
#

Is there a way to control what side of a card a tooltip appears in?

wild patrol
#

!text command got an upgrade

pearl whale
pastel kernel
#

candycane told me "you could just hook the function to change the swirls and have that loop through G.jokers"

#

i was asking about trying to ease bg color when a joker of a specific rarity is obtained

#

cause i don't know how to make a joker rarity affect the bg color when obtained

gilded blaze
#

hook Card.add_to_deck

pastel kernel
#

for the joker rarity checking?

gilded blaze
#
local add_to_deck = Card.add_to_deck
function Card:add_to_deck(from_debuff)
    add_to_deck(self, from_debuff)
    if self.ability.set == "Joker" then
        G.E_MANAGER:add_event(Event({func = function()
            ease_background_colour_blind(G.STATE)
        return true end }))
    end
end

for the general call

#

you then patch ease_background_colour_blind to include rarity checking

#

actually, this is a bit complicated

pastel kernel
#

payload = '''
if self.ability.set == "Joker" and self.config.center.rarity == 2 then
'''

#

...nah

daring fern
pastel kernel
#

then i replace G.STATE?

#

with new_colour = G.C.WHITE, special_colour = HEX('b00b69'), tertiary_colour = G.C.BLACK, contrast = 2?

gilded blaze
#

also how do you want to modify bg colour based on rarity

#

rarer ones override more common ones?

pastel kernel
#

Currently, this just works one rarity, but I plan to make it work when you obtain the higher rarities.

#

The whole thing just looks like this.

pastel kernel
#

Idk what I’m doing bruh

#
[[patches]]
[patches.pattern]
target = "otherfunctionalities.lua"
pattern = "ease_background_colour_blind(G.STATE)"
position = "at"
payload = '''
if self:is_rarity('busterb_Grandiose') then
ease_background_colour_blind({ new_colour = G.C.WHITE, special_colour = HEX('b00b69'), tertiary_colour = G.C.BLACK, contrast = 2 })
end
'''
match_indent = true```
#

i'm a brainlet

pastel kernel
#

I feel like I could use Cryptid.advanced_find_joker to check and then change background but idk how to implement it

vital wren
#

for what reason might my added cards not be displaying their text?

-- in localization
c_vb_inverted_fool = {
    name = 'The Inverted Fool',
    text = {
        "Reroll {C:attention}Rank{} of",
        "#1# selected cards",
    },
},

-- in main.lua
SMODS.Consumable
{
    key = 'inverted_fool',
    set = 'Tarot', 
    atlas = 'inverted-arcana-tarots',
    pos = {x=0, y=0},
    config = {
        max_highlighted = 3,
        mod_conv = 'rnd_rank',
    },
    loc_vars = function(self, info_queue, card) 
        return {
            vars = {
                card.ability.max_lightlighted,
            }
        }
    end,
}```
#

figured it out. was declaring the mod in two places and it wasn't seeing the tags correctly

long sun
#

how do you get a Joker to retrigger a consumable?

daring fern
long sun
#

mhm

gilded blaze
#

there's no general case for such thing

long sun
#

ah. damn

gilded blaze
#

joker retriggers only work on consumables that has calculate, not use

long sun
#

unfortunate

gilded blaze
#

however, for a specific set of consumables, you can do it within their use

long sun
#

ah ye i could do that

#

what would that look like?

daring fern
# long sun mhm
local olduseconsume = Card.use_consumeable
function Card:use_consumeable(area, copier)
    if condition then
        G.GAME.modprefix_retriggering_consumeable = true
    else
        G.GAME.modprefix_retriggering_consumeable = nil
    end
    local g = olduseconsume(self, area, copier)
    if not G.modprefix_consumeableretriggering then
        G.modprefix_consumeableretriggering = true
        if condition then
            SMODS.calculate_effect({message = localize('k_again_ex')}, self)
            G.E_MANAGER:add_event(Event({
                func = function()
                    G.GAME.modprefix_retriggering_consumeable = nil
                    return true
                end
            }))
            local ok, err = pcall(self.use_consumeable, self, area, copier)
            if not ok then sendErrorMessage(err, 'MODID') end
        end
        G.modprefix_consumeableretriggering = nil
    end
    return g
end
long sun
#

ah yay, thanks!

#

wait catastrophic blunder blunder these consumables use calculate for effects

#

USE makes them active

#

;u;

#

sorry

#

i'll save that code, it looks very useful

#

so joker retriggers would work for that right

daring fern
daring fern
thorn basin
#

Some days ago, N' helped me to make a consumable (that I made lots of time ago) have its "USE" button become active when you select 2 cards with a specific enhancement.
How can I make it that it activates if the 2 cards selected have different enhancements (while maintaining this condition?)

gilded blaze
#
can_use = function(self, card)
    if #G.hand.highlighted == 2 then
        local chemical_list = {}
        for _, playing_card in ipairs(G.hand.highlighted) do
            if SMODS.has_enhancement(playing_card, "m_SM_red_chemical_card")
            or SMODS.has_enhancement(playing_card, "m_SM_blue_chemical_card")
            or SMODS.has_enhancement(playing_card, "m_SM_green_chemical_card") then
                table.insert(chemical_list, playing_card.config.center_key)
            end
        end
        return #chemical_list == 2 and chemical_list[1] ~= chemical_list[2]
    end
end
thorn basin
#

so you're making a list of the highlighted cards and then in the return you make a condition that checks if the 1st one if different than the 2nd?
imma try this out rn

gilded blaze
#

uh

#

I changed the code a bit
next is too general

thorn basin
#

aight

thorn basin
vital wren
#

how do you get this lil info flyout to appear? i thought the info_queue would do it, but it's not working for me

#
config = {
    max_highlighted = 1,
    mod_conv = 'e_polychrome',
    extra = {
        odds = 3,
    },
},
loc_vars = function(self, info_queue, card) 
    info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome
    local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'inverted_wheel_of_fortune')
    return { 
        vars = { 
            numerator, 
            denominator, 
            card.ability.max_highlighted,
            localize{type = 'name_text', set = 'Edition', key = card.ability.mod_conv}
        }
    } 
end,
elder rune
vital wren
#

hmm, i pulled that from the VanillaRemade code...

frosty dock
#

should work fine

vital wren
#

the flyout just doesn't appear

vital wren
#

is there a way to just make a lil message appear like how it happens when scoring cards, but i can just do it whenever i want focused on any given card?

gilded blaze
#

SMODS.calculate_effect({message = "text"}, card)

long sun
#

i need to check something in context.repetition. my joker may return 0 here. how can i prevent a warning from being logged when 0 is returned?

#

(i realise this may be an XY problem)

frosty dock
#

don't return 0

#

i.e., check if the result is 0 and only return it if it isn't

long sun
#

ah icic ^u^ thank you

long sun
#

damn no preview

#

The XY problem is a communication problem encountered in help desk, technical support, software engineering, or customer service situations where the question is about an end user's attempted solution (X) rather than the root problem itself (Y).

frosty dock
#

I mean the root problem is returning 0, not the warning resulting from it

#

so yes it's an XY problem

long sun
#

👍

distant junco
#

hey guys idk if anyone else has noticed this but why does dt behave like the game is running at 15fps this is really stupid

primal robin
#

if youre game in 15fps then yes

distant junco
#

im not its running at 60

#

but doing 1/dt says 15

#

could it be vsync??

primal robin
#

1/dt should say 0.016 for 60fps

distant junco
#

oh my gods its because of the game speed

#

game speed 1 makes it behave normally

distant junco
#

dt would be like 0.006 or whatever

#

ok then how can i check game speed...

primal robin
#

it's dt okay makes sense

long sun
#

how do i force a card to spawn with a certain edition?

#

(within the card itself, if possible)

distant junco
#

what kind of card

long sun
#

consumable

faint yacht
#

...wouldn't set_ability be also present for defining consumables?

red flower
distant junco
#

thats a thing?

red flower
#

yeah

distant junco
#

but also ive got a way of doing it with game speed accounted for

#

card.ability.extra.counter = card.ability.extra.counter + (dt/G.SETTINGS.GAMESPEED)

#

which works good

long sun
faint yacht
#
    set_ability = function(self, card, initial, delay_sprites)
        -- do stuff here
    end

This, I meant.

long sun
#

ah i see ^^

#

ya that would work

distant junco
#

welp, if anyone ever needs it... heres how you detect whether the date has been changed if your joker requires on the date... LOL

add_to_deck = function(self, card, from_debuff)
        card.ability.extra.month = tonumber(os.date("%m"))
        card.ability.extra.day = tonumber(os.date("%d"))
        card.ability.extra.t1 = os.time{year=tonumber(os.date("%Y")), month=tonumber(os.date("%m")), day=tonumber(os.date("%d")), hour=tonumber(os.date("%H")), min=tonumber(os.date("%M")), sec=tonumber(os.date("%S"))}
    end,
    update = function(self, card, dt)
        if next(SMODS.find_card('j_jammbo_jam_santa')) then
            card.ability.extra.counter = card.ability.extra.counter + (dt/G.SETTINGS.GAMESPEED)
            if card.ability.extra.counter >= 1 then
                card.ability.extra.seconds = card.ability.extra.seconds + 1
                card.ability.extra.counter = 0
            end
        end
        if card.ability.extra.seconds == 5 then
            card.ability.extra.seconds = 0
            card.ability.extra.t2 = os.time{year=tonumber(os.date("%Y")), month=tonumber(os.date("%m")), day=tonumber(os.date("%d")), hour=tonumber(os.date("%H")), min=tonumber(os.date("%M")), sec=tonumber(os.date("%S"))}
            local difftime = os.difftime(card.ability.extra.t2, card.ability.extra.t1)
            if difftime < 3 or difftime > 7 then
                SMODS.destroy_cards(G.jokers.cards)
                SMODS.calculate_effect({message = "Naughty!"}, card)
            end
            card.ability.extra.t1 = os.time{year=tonumber(os.date("%Y")), month=tonumber(os.date("%m")), day=tonumber(os.date("%d")), hour=tonumber(os.date("%H")), min=tonumber(os.date("%M")), sec=tonumber(os.date("%S"))}
        end
    end
bright ivy
#
SMODS.Joker {
    key = "relay",

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

    blueprint_compat = false,
    rarity = 1,
    cost = 4,

    loc_txt = {
        name = "Relay",
        text = {
            "Each scored card gains Chips",
            "equal to the previous card's Chips",
            "if it has a higher rank",
        }
    },

    atlas = "test_atlas",
    pos = { x = 0, y = 0 },

    
    calculate = function(self, card, context)
        if context.joker_main and context.scoring_hand then
            print("---- RELAY DEBUG START ----")
            print("Scoring hand size: " .. #context.scoring_hand)

            local previous_card = nil

            for i, scored_card in ipairs(context.scoring_hand) do
                local rank = scored_card:get_id()
                local base_chips = (scored_card:get_chip_h_bonus() + rank) or "nil"

                print("Card " .. i)
                print("  Rank: " .. tostring(rank))
                print("  Base Chips: " .. tostring(base_chips))

                if previous_card then
                    local prev_rank = previous_card:get_id()
                    local prev_chips = (previous_card:get_chip_h_bonus() + prev_rank) or "nil"

                    print("  Previous Rank: " .. tostring(prev_rank))
                    print("  Previous Chips: " .. tostring(prev_chips))

                    if rank > prev_rank then
                        print("  CONDITION PASSED (higher rank)")

                        local chips_to_add = (previous_card:get_chip_h_bonus() + prev_rank) or 0
                        print("  Chips to add: " .. tostring(chips_to_add))
                    else
                        print("  CONDITION FAILED")
                    end
                else
                    print("  No previous card")
                end

                previous_card = scored_card
            end

            print("---- RELAY DEBUG END ----")
        end
    end,
}
#

I was wondering what context to use to make this work as the print is all correct

#

Also if you know of any other way to get the chips of the previous card that would be easier plz lmk

frosty dock
#

if it should properly work with retriggers, you'll have to consider that for the logic of changing the previous card (delay the change until all triggers are done), if not you should exclude retriggers

#

get_id() doesn't get you the card's scored chips either, and get_h_bonus() is for chips when held

final jewel
#

I really like how I am trying to update my mod with 1501 assets

#

heres the code

red flower
#

you're copying the card but never adding it anywhere

median veldt
#

Love it when that happened when I was devving sandcastle

red flower
#

just make sure to not insert them into G.playing_cards while you're looping

median veldt
#

Deb8ing if I want to develop this joker idea I've been thinking of

final jewel
#

okok

median veldt
#

It'd be a pain in the ass but

#

It might be good

final jewel
#

but I think just that is better

#

its just a reverse checkered

hidden aspen
#

why when i use get_current_pool("Tag") i get a bunch of UNAVAILABLEs? isnt get_current_pool supposed to return only working stuff?

red flower
mystic river
#

it does
UNAVAILABLE is how it excludes items that aren't in pool atm

red flower
hidden aspen
#

oh

dreamy thunder
#

i think latest release had a wrap function for getting the clean pool

frosty rampart
#

ye smods has a new SMODS.get_clean_pool function that should remove the unavailables

mystic river
#

SMODS.get_clean_pool() strips the unavailable entirely, if you want that for some reason

hidden aspen
#

pog

median veldt
# median veldt It'd be a pain in the ass but

Consider: Plural Joker

On spawn, does a bunch of numerical rolls to determine the odds for the joker for the rest of its existence

Then, every hand or so, it'll do a couple rolls.

  • Develop a new ability?
  • Which ability? Original or steal from an existing joker?
  • Switch to a different ability?
  • Which ability?
#

Idk if it's worth the effort

hidden aspen
median veldt
#

Hmm.

mystic river
#

first thought, define a whole buttload of random minor abilities, then when it spawns it picks like 12 of them to shuffle between at the end of each round

depending on how minor the abilities are, the joker could have multiple active at once

#

it would definitely be hilariously complicated

final jewel
#

should I required smods 1501a or 1503a since I need 1501a to work but 1503a is a bug fix ?

mystic river
#

i would require 1503 personally but i don't think it strongly matters

median veldt
median veldt
#

I'm deb8ing if its worth the effort

#

I have it all planned out

final jewel
wintry solar
#

It fixes quite a critical bug, and people will try and find 1501 is you specify that one because they are silly

open moth
#

How do I generate a joker image by using several other joker images dynamically?

#

For example, choose a hat, a costume and a background depending on the jocker's stats

shell timber
#

you can use drawsteps

open moth
median veldt
hidden aspen
#

add tag tag tag

elder rune
#

bro wants to add a tag 💀

hidden aspen
#

the taglerrrrrr

mystic river
#

event manager: add event (event)

hidden aspen
#

yesssss

frosty dock
hidden aspen
#

okay ill check

red flower
thorn basin
#

ok so I never did this before but, I made some booster packs of the same type (like the normal arcana packs) but I'm not sure how should I change the background when I buy one of them.
May someone please explain me how to do so?

frosty dock
#

but you can do add_tag { key = tag }

red flower
red flower
thorn basin
#

i think I'm gonna check out what does each one of them

red flower
#

this is what i do in my mod

junior tapir
#

Is there an easy way to tell that a patch hasn't influenced the code, other than just making it break the game? Also any tips and tricks to how yall approach when a patch doesn't work as intended? I normally check if the target file is the right one or nested in the correct directory, then primitively copy-paste check if SMODS has made any adjustments

weary merlin
#

noticed that the Game object seems to lack an attribute describing how many discards have been used in total in the current run. is there a way to alternatively get this value for the purposes of an unlock condition

wintry solar
junior tapir
#

ohh it is unused

weary merlin
#

yeah

#

which means i can check if the player has used every discard

junior tapir
#

trading card and burnt have something that check if it is the first discard, maybe it is a counter that helps

#

I know the hands have a counter because I've worked with them

red flower
#

in the mod's calculate

weary merlin
junior tapir
red flower
#

no, you would need to do that globally and then use that value in the condition

red flower
junior tapir
#

yeah, so end of round you could take the value of that variable

weary merlin
#

how would i set up a global calculate

red flower
junior tapir
#

does the dump always get updated to the latest run?

red flower
#

yes

#

you should also just check the dump in general to patch

junior tapir
#

wow, reverse engineering +100

junior tapir
red flower
#

i mean because if smods is patching it you will miss it, and sometimes smods just replaces stuff entirely

junior tapir
#

I guess if I do not know what causes the patched files to look what they look like there might be some dependencies, like I just found some function FNSJ.simulate_lucky_cat

#

I wanted to make it so both lucky procs update the cat

weary merlin
#

i doubt i implemented the variable and mod calculate properly

#

does anyone have a wireframe for this? api docs doesn't seem to help much here

red flower
#

can i see the code

weary merlin
red flower
#

SMODS.current_mod.calculate = function(self, context)

weary merlin
#

rawtext?

#

or do i reformat current_mod to the mod id

red flower
#

like i wrote it

#

it is described at the beginning of that page i linked

#

also it's not a good idea to make random globals, specially because it wont save bewtween reloads

weary merlin
#

fixed the G.Game casing too

red flower
#

G.GAME

weary merlin
#

wait i can just add variables to G.GAME

red flower
#

yes

weary merlin
#

?

faint yacht
#

G.GAME.farts, ye.

weary merlin
#

peak

red flower
#

add the prefix so it doesnt clash

weary merlin
#

this crashes the game on boot G.GAME.pemonlist_discards_used = 0

red flower
#

don't do it outside the function

weary merlin
#

should i not initialize it to 0?

#

ah ok

red flower
#

you don't need to
G.GAME.count = (G.GAME.count or 0) + 1

#

also i just realized your code will count more times than it should

#

you just check context pre_discard

#

idk how to type

weary merlin
slim ferry
#

but you also dont need to intialize numbers anyway because lua

weary merlin
#

it doesn't like this line

#

yes i know += operators

weary merlin
#

or 0 ah

slim ferry
red flower
#

sadly

slim ferry
#

i mean there is a good reason

weary merlin
#

hmm

slim ferry
#

wrong reply?

weary merlin
#

i suppose my only other experience with lua is p8

weary merlin
slim ferry
#

luaU does have += and such

#

so that might be where youre getting that from

red flower
#

i want to do something in p8

#

looks fun

slim ferry
#

oh p8

#

like

#

pico 8

#

?

red flower
#

im assuming

weary merlin
#

this does not activate

mystic river
#

iirc current round starts at 1, not 0

weary merlin
#

does round increment before or after setting blind

mystic river
#

also if you want to do things once at the beginning of a game, reset game globals is better

weary merlin
#

tbh that context could be replaced with a context.game_start if it exists

red flower
#

it doesn't

#

but you dont need to initialize the value

#

it will be deleted in a new run

mystic river
red flower
slim ferry
weary merlin
slim ferry
#

yeah

#

i mean usually you write print("message") but string calls do exist so the brackets are optional

red flower
#

that but i meant doing it in the console in-game which would be eval G.GAME.blahblah

weary merlin
#

got it working, thanks

hidden aspen
#

am i fetching a custom loc_txt property incorrectly? im getting nil back

#

is adding these custom loc_txt properties even allowed?

slim ferry
#

localize expects a key in a localization file

red flower
#

yeah thats not how localize works

slim ferry
#

loc_txt is only for text tied to the object and does not allow for arbitrary localization fields

hidden aspen
#

i see

red flower
#

you need to use a localization file, loc_txt in encounters are for the choices and descriptions

#

idk how it works in the library since i only used the hotpot one

hidden aspen
#

yeah i should use the localization file

#

are custom fields allowed in the descriptions? im getting nil anyway

slim ferry
#

custom categories are not loaded by default

hidden aspen
#

buh

#

i guess i'll just split up step into 3 different steps...

slim ferry
#

oh wait

#

i assume enc_Step is added by the encounters mod?

hidden aspen
#

yes

slim ferry
#

then the issue is probably just the fact that the text is within another table

hidden aspen
#

is it the wrong table? self.set returns enc_Step, or is game object set different from descriptions set

slim ferry
#

no i mean like

#

theyre within st_map_rps_play

#

and i dont think localize works with that unless the encounter mod changes that

thorn basin
hidden aspen
slim ferry
#

oh

#

hm

hidden aspen
#

text is a field of the mod, it might be because my fields are custom

slim ferry
#

<@&1133519078540185692>

hidden aspen
#

free money pog

red flower
slim ferry
#

mr beast one bililion dolar !!!!!

slim ferry
hidden aspen
#

one beastillion dollar

shy quest
#

discord is being slow

slim ferry
#

oh there it goes

stoic heron
#

bro why do people not want other people to get free money?!? society would be fixed if everyone got free money

hidden aspen
thorn basin
red flower
#

there are no docs

thorn basin
#

:[

#

darn

red flower
#

ease_color changes the rest of the ui like blind colours iirc

hidden aspen
red flower
#

special colour is the other colour for the background twirl iirc

thorn basin
#

....I think I may understood what you mean

red flower
#

honestly, the best way to understand is to try it and tweak it lol

#

not saying asking questions is bad but it's not like i made the game so any knowledge i have i got it that way

thorn basin
#

aight, thanks still for the help!

hidden aspen
#

i guess i could use this to have different descriptions for the some object

red flower
#

yes!

solemn shuttle
#

_

distant junco
#

ive updated to the newest smods and lovely and now this happens in my mod when cards are created

#

the cards function fine, and they even look fine in the deck

red flower
#

how are you creating the cards

distant junco
distant junco
#

ranks is a table with... all the ranks

red flower
#

let me try it

#

also why not SMODS.Ranks

distant junco
#

didnt know that was a thing

red flower
rapid stag
#

how can i change how much a joker costs to buy, during runtime? i want to make a joker with a semi-randomised cost

red flower
#

change card.ability.extra_value or whatever egg uses

#

if you want more precise control, hook Card:set_cost and change card.cost

distant junco
#

somethings broken somewhere!

red flower
hidden aspen
red flower
#

you could change future cost by modifying the prototype but that's bad practice

wintry solar
#

Huh

hidden aspen
#

ohhh i havent realised that SMODS.GameObject is a prototype pattern... really cool structure...

rapid stag
wintry solar
red flower
wintry solar
#

Interesting

shrewd cobalt
#

How do I replace the title screen logo?

rapid stag
shrewd cobalt
#

godsend 🙏

frosty rampart
rapid stag
#

ah

near coral
#

How do you fix this happening above a joker

sturdy compass
#

That’s sprite bleeding

fading rivet
#

oh

near coral
fading rivet
sturdy compass
#

Basically some cards on your spritesheet are too close together

fading rivet
near coral
near coral
#

It happens with a lot of the jokers actually

fading rivet
#

hmmm

near coral
#

I only just noticed

sturdy compass
#

Make sure the gap from the top of the file is also in check

near coral
#

?

fading rivet
#

there should be 1 pixel between the top of the file and the cards

#

same for all sides

near coral
#

Yes, everything is the same space apart as the vanilla atlas

sturdy compass
#

Is the atlas size too tall?

near coral
#

Let me just send the 1x atlas so you can see it for yourself

sturdy compass
#

I’m talking about the SMODS.Atlas

near coral
#

Oh

#

Idk about any of that

sturdy compass
#

bruh

near coral
#

I'm not the coding guy

fading rivet
near coral
#

Where is the atlas code found

fading rivet
#

uhh

#

atlas.lua?

sturdy compass
#

No

fading rivet
#

it depends on your mod

fading rivet
sturdy compass
#

Having an individual atlas file is very nonstandard I’m ngl

#

But if it works for you then cool

near coral
#

There is no atlas.lua anywhere in the mod

sturdy compass
#

Ask your coder where they are then

fading rivet
near coral
#

Yes but a very primitive build, I have yet to update the github zip

#

I can send the most recent one

fading rivet
#

could you send a link

near coral
#

It's untested however

fading rivet
#

not actually run anything

near coral
#

It's all zips rn

fading rivet
#

oh

near coral
#

Like I said I have yet to update the github upload

fading rivet
#

weird its fine

fading rivet
#

the inconsistent spacing is killing me but there isn't anything wrong

near coral
#

Wait aren't jokers normally 69x93

frosty rampart
#

69x93 with a buffer of 1px of transparency on all sides, hence 71x95

fading rivet
near coral
#

When did 93+1=95?

fading rivet
#

both sides

near coral
#

Oh

fading rivet
#

93+1+1

near coral
#

I'm rupid

#

I'm just gonna hope my coder can fix it

reef bobcat
#

trying to achieve an effect but dont even know where to start

#

want to make a joker that changes cards to clubs suit if they are adjacent to a clubs suit card while scoring

fading rivet
reef bobcat
#

after i would like

fading rivet
#

heres what I would do

during the after scoring context
iterate through each played card
check neighbors if clubs
make played card clubs if so

reef bobcat
#

how would i check neighbouring cards?

fading rivet
#
for i, card in ipairs(G.play.cards):
  if i ~= 1 then
    local left = G.play.cards[i - 1]
  end
  if i ~= #G.play.cards then
    local right = G.play.cards[i + 1]
  end
end
reef bobcat
#
        return { vars = { localize(card.ability.extra.suit, 'suits_singular') } }
    end,
    calculate = function(self, card, context)
        if context.after and not context.blueprint then
  if i ~= 1 then
    local left = G.play.cards[i - 1] == v:is_suit('Clubs', nil, true) then
        local scored_card = context.other_card
                G.E_MANAGER:add_event(Event({
                    func = function()
                        
                        assert(SMODS.change_suit(scored_card, nil, "Clubs"))
                            scored_card:juice_up()
                        return true
                    end
                }))
            end
  end
  if i ~= #G.play.cards then
        local right = G.play.cards[i - 1] == v:is_suit('Clubs', nil, true) then
        local scored_card = context.other_card
                G.E_MANAGER:add_event(Event({
                    func = function()
                        
                        assert(SMODS.change_suit(scored_card, nil, "Clubs"))
                            scored_card:juice_up()
                        return true
                    end
                }))
  end
end
}```
#

tried this but it did not work lol

fading rivet
reef bobcat
#

it said unexpected symbol near then

fading rivet
#

you did

#

local left = true then

#

line 5 of the calculate function

#

if you give me like 5 minutes I can fix it

#

im on my phone rn soo

reef bobcat
#

i'd feel bad if you did it for me D:

#

i'll try to make some changes

#

if it doesnt work

#

then u can fix it

fading rivet
#

this is wrong

daring fern
# reef bobcat then u can fix it
if context.after then
    for k, v in pairs(context.scoring_hand) do
        if (k > 1 and context.scoring_hand[k-1]:is_suit('Clubs')) or (k < #context.scoring_hand and context.scoring_hand[k+1]:is_suit('Clubs')) then
            G.E_MANAGER:add_event(Event({
                func = function()
                    SMODS.change_base(v, 'Clubs')
                    v:juice_up()
                    return true
                end
            }))
        end
    end
end
reef bobcat
#
    calculate = function(self, card, context)
   if context.after then
    for k, v in pairs(context.scoring_hand) do
        if (k > 1 and context.scoring_hand[k-1]:is_suit('Clubs')) or (k < #context.scoring_hand and context.scoring_hand[k+1]:is_suit('Clubs')) then
            G.E_MANAGER:add_event(Event({
                func = function()
                    SMODS.change_base(v, 'Clubs')
                    v:juice_up()
                    return true
                end
            }))
        end
    end
end
end
}```

i did this and it's no longer crashing, but the suit change still isn't happening D:
#

ok i changed

#

context after

#

to context individual

#

and card area == play

#

now it works

#

thank u

near coral
#

Can madness target itself

#

Wait wrong channel

daring fern
near coral
#

o

reef bobcat
#

i wanna do this from now so

#

how would i remove vanilla jokers?

#

just the jokers

#

i know pokermon does this

frosty rampart
#

i mean
referencing pokermon's code sounds like a pretty good idea

mystic river
#

i would guess it iterates over G.P_CENTERS and adds in_pool = function() return false end and no_collection = true to all the vanilla jokers

red flower
# reef bobcat how would i remove vanilla jokers?
local smods_add_to_pool_ref = SMODS.add_to_pool
function SMODS.add_to_pool(prototype_obj, args)
    if prototype_obj.set == "Joker" and
        (not prototype_obj.original_mod or prototype_obj.original_mod.id == "Balatro") then
        return false
    end
    return smods_add_to_pool_ref(prototype_obj, args)
end

you can add whatever other condition to the if there

mystic river
#

or that

reef bobcat
frosty rampart
red flower
mystic river
#

huh, i thought it removed them from the collection too

reef bobcat
#

it works!! thanks

#

plus they still appear in the collection

#

which is fine by me

near coral
red flower
#

code?

near coral
#

It's supposed to make cards and packs in the shop increase by $1 while lowering the price of rerolls by $2

near coral
daring fern
near coral
#

?

daring fern
# near coral ?
add_to_deck = function(self, card, from_debuff)
    G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost - 2
    G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost - 2)
end,
remove_from_deck = function(self, card, from_debuff)
    G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost + 2
    G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost + 2)
end
local oldcardsetcost = Card.set_cost
function Card:set_cost()
    local g = oldcardsetcost(self)
    if self.ability.set == 'Booster' then self.cost = self.cost+1 end
    return g
end
near coral
#

Can you put it all together so I can send it to my coder whole please

daring fern
# near coral Can you put it all together so I can send it to my coder whole please
SMODS.Joker {
    key = 'magician',
    unlocked = false,
    discovered = false,
    rarity = 1,
    cost = 1,
    atlas = 'Jokers',
    blueprint_compat = false,
    pos = { x = 1, y = 11 },
    set_badges = function(self, card, badges)
         badges[#badges+1] = create_badge('Bizarro', G.C.SECONDARY_SET.Spectral, G.C.WHITE, 1)
         badges[#badges+1] = create_badge('Bonus', G.C.RARITY.Legendary, G.C.WHITE, 1)
    end,
    add_to_deck = function(self, card, from_debuff)
        G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost - 2
        G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost - 2)
        calculate_reroll_cost(true)
        G.E_MANAGER:add_event(Event({
            func = function()
                for k, v in pairs(G.I.CARD) do
                    if v.set_cost then
                        v:set_cost()
                    end
                end
                return true
            end
        }))
    end,
    remove_from_deck = function(self, card, from_debuff)
        G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost + 2
        G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost + 2)
        calculate_reroll_cost(true)
    end
}

local oldcardsetcost = Card.set_cost
function Card:set_cost()
    local g = oldcardsetcost(self)
    if next(SMODS.find_card('j_modprefix_key')) and self.ability.set == 'Booster' then
        self.cost = self.cost+1
    end
    return g
end
near coral
#

Thank you

urban wasp
#

i want this joker to make spades and clubs held in hand at end of round give $1, but it doesn't work (likely because i have a slightly wrong context)
the only thing in vanilla that does something like this are gold cards... and their code in vremade uses a base config of h_dollars, so i don't have any reference here

calculate = function(self, card, context)
    if
        context.cardarea == G.hand and
        context.end_of_round and
        context.game_over == false and
        (context.other_card:is_suit("Spades") or context.other_card:is_suit("Clubs"))
    then
        G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + card.ability.extra.dollars
        return {
            dollars = card.ability.extra.dollars,
            func = function()
                G.E_MANAGER:add_event(Event({
                    func = function()
                        G.GAME.dollar_buffer = 0
                        return true
                    end
                }))
            end
        }
    end
end
vital wren
#

throw a context.individual in there

urban wasp
#

ah okay thank you

urban wasp
vital wren
#

i dont think you need so many contexts either. context.individual and context.end_of_round and your suit check

ignore this i was wrong

vital wren
urban wasp
#

i mean i guess that makes sense lol

vital wren
#

so in this case, you're looking at each card in hand (context.other_card) to see if its spade or club

urban wasp
vital wren
#

shrug, it seems superfluous to me but it shouldn't hurt anything

urban wasp
#

that's fair

frosty rampart
#

it doesn't matter too much, since events pause when the game over window pops up

urban wasp
#

ah okay

#

one more question: the joker seems to juice twice per eligible card held in hand

#

i assume this is due to the event shenanigans, but i'm unsure since i believe i've used this exact setup before due to it being used for the code in vremade's reserved parking

vital wren
#

i dont think you need the dollar buffer code. i think just returning the dollar value will be enough. check if you're getting double the money. or just try commenting it out and see if it still works

urban wasp
#

i know it'd theoretically work; i'm just wondering if there's some kind of easy/common solution for this since the event manager block is used for timing with other possible things out of my control

#

i think it's fine though

vital wren
#

with joker calculates basically all of the timing and messages get taken care of automatically from just the returns. but im not entirely sure what you're trying to do

#

anyone know how i can grab the entire contents of the full deck. i want to check each card in it for stuff

red flower
vital wren
#

til

red flower
urban wasp
#

i.e. for checking enhanced cards for a joker in my mod:

if G.playing_cards ~= nil then
    local enhanced_count = 0
    for k, v in pairs(G.playing_cards) do
        if v.config.center ~= G.P_CENTERS.c_base then
            enhanced_count = enhanced_count + 1
        end
    end
    card.ability.extra.mult = enhanced_count * card.ability.extra.mult_mod
end
daring fern
urban wasp
#

instead of the if v.config.center ~= G.P_CENTERS.c_base?

urban wasp
#

alright; thank you

#

is context.cardarea == "unscored" even a thing?

urban wasp
#

how would i get this condition to search for cards of the given suit in the unscoring portion of the hand? at the moment the game just crashes upon playing a hand

if context.cardarea == "unscored" and (context.other_card:is_suit("Hearts") or context.other_card:is_suit("Diamonds")) then
#

i'm pretty sure that i have to replace other_card with something, i'm just not sure what exactly

urban wasp
#

ah, okay

#

funny given that my last issue was solved through the context as well 😭

#

does context.round_eval exist?

daring fern
urban wasp
#

okay; what could be the reason on why this doesn't reset its dollar amount then? by the way, i assume that context.round_eval is occurs after the payout; though, i may be incorrect

local triggered = 0
if context.cardarea == "unscored" and context.individual and (context.other_card:is_suit("Hearts") or context.other_card:is_suit("Diamonds")) then
    SMODS.scale_card(card, {
        ref_table = card.ability.extra,
        ref_value = "dollars",
        scalar_value = "dollars_mod",
        message_colour = G.C.MONEY
    })
    triggered = triggered + 1
end
if context.round_eval then
    card.ability.extra.dollars = math.max(1, card.ability.extra.dollars - (triggered * card.ability.extra.dollars_mod)) -- this is for compatibility with value manipulation
    triggered = 0
end
daring fern
urban wasp
#

ah

urban wasp
#

obviously context.starting_shop could work, but i kinda want it to have perfect timing such that the reset occurs directly after all dollar "calculations" on the payout screen have finished

warm solar
#

does anyone know how to properly check what booster pack is being opened?

daring fern
warm solar
#

Thank you

smoky talon
#

hey so im trying to make this consumable that wins the blind instantly when used. it gives the chips, but the blind doesnt end and you still need to play abother hand. im also try ing to get it to display text, but while i can make a joker do that, it doesnt work for a consumable in the same way from what i can tell.

SMODS.Consumable {
key = "shutdown",
set = "CMD",
cost = 4,
atlas = 'CMD',
pos = {x = 4, y = 0},
loc_txt = {
name = "C:\_shutdown",
text = {
'Immediately wins the blind',
}
},
can_use = function(self, card)
return G.GAME and G.GAME.blind and G.GAME.blind.chips
end,
use = function(self, card, area, copier)
local half = math.floor(G.GAME.blind.chips)

G.E_MANAGER:add_event(Event({
    func = function()
        play_sound('tarot2', 0.76, 0.4)
        card:juice_up(0.3, 0.5)
        G.GAME.chips = (G.GAME.chips or 0) + half
        if G.hand_text_area and G.hand_text_area.game_chips then
            G.hand_text_area.game_chips:update_text()
        end
        -- Trigger win check
        if G.GAME.chips >= G.GAME.blind.chips then
            G.FUNCS.win_round()
        end
        return true
    end
}))

end,
}

vital wren
#

if a card has zero or one enhancement, will SMODS.get_enhancements() still return a table or just the single value?

vital wren
#

can i do SMODS.get_enhancements()[1] to just grab the first one without needing to store the table?

daring fern
vital wren
#

that's so annoying. how do i just get a card's enhancement?

daring fern
vital wren
#

okay, just confirming. will this work? trying to just copy an enhancement from _source to _target

local _enhance = G.P_CENTERS[_source.config.center.key]
_target:set_ability(_enhance, nil, false)
vital wren
#

okay thanks

#

blarg... still not working...

#

kay, but you confirming it should work let me find the issue. checking against the wrong extra value 🤦🏼

wintry solar
#

_enhance.key

tulip pecan
#

I'm trying to figure out how to add custom challenge rules to my mod, and found myself looking at this snippet of code in game.lua for starting a game.

Would I hook into this area of the function, add a check for my custom rule to change a self.GAME.modifiers variable to then use in other hooks to do what I want?

Or am i thinking about this all wrong?

daring fern
tulip pecan
daring fern
tulip pecan
#

or however I want to store it?

hallow moat
#

Is anyone experienced with modding willing to take a look at some disgusting chatgpt modified yorick code I've been messing around with that's been crashing?

daring fern
tulip pecan
#

i see

#

thank you for clearing up the confusion 👍

long sun
#

i need to destroy cards in context.end_of_round, however this function isn't doing it:
SMODS.destroy_cards({context.other_card})
why not?

#

ah wait i'm. a little dense, hold on

#

i put that in an event which won't recognise the context