#💻・modding-dev

1 messages · Page 641 of 1

red flower
#

thats why i said you need to patch before

short fulcrum
#

yeah I've been learning how patches work and how to make them since

hushed field
#

Yeah, you'd want to patch a check in, though you'd still use a regular set up for your localization file, haha

wintry solar
#

Oh I should make that auto format at a certain point actually

short fulcrum
#

yeah no I just didn't realise you could add a dictionary to your localization file

#

does this mean it's impossible or would it just be kind of difficult

hushed field
#

In this case, I'd choose to use v_dictionary and pass along a variable, instead of hardcoding the $20 in, btw, so you don't need to change it if you rebalance it

short fulcrum
#

that makes sense

red flower
#

idk how many places you need to patch tho

short fulcrum
hushed field
#

Definitely isn't impossible. Difficult if you're new to messing with code and uncomfortable, but if you're comfortable just tearing apart the source code to find where you insert a patch, it's pretty easy!

short fulcrum
#

yeah I do think I'm making progress, just kind of slowly

hushed field
#

Probably a lot less slowly than you'd reckon, haha

round lion
#

so theres no way in newer smods to register a item from a pre-existing table?

slim ferry
#

wdym by that

dense fulcrum
daring fern
red flower
#

<@&1133519078540185692>

round lion
#

ANOTHER ONE BITES THE DUST.

karmic creek
#

kaCHOW

short fulcrum
# short fulcrum yeah I do think I'm making progress, just kind of slowly

okay I've been working on this and I actually managed to get it working... in the collection. It displays $20 like I want it to, and everything else is normal. However, no matter how hard I try I can't get it to work for the actual blind in-game. I figure this is beyond my skill level so I turn to help

Here's the code that successfully makes the blind in the collection display a different reward:

{
  n = G.UIT.O,
  config = {
    object = DynaText({
      string = {
        blind.key == 'bl_mysingingjokers_crop'
          and localize('b_crop_custom_reward')
          or (_dollars and string.rep(localize('$'), _dollars) or '-')
      },

      colours = { G.C.MONEY },
      rotate  = true,
      bump    = true,
      silent  = true,
      scale   = 0.45
    })
  }
}

Here's the code for the in-game blind that I figured would work, as it uses some of the same logic, but it doesn't.

{
  n = G.UIT.O,
  config = {
    object = DynaText({
      string = {
          blind.key == 'bl_mysingingjokers_crop'
          and localize('b_crop_custom_reward')
          or {
            {
              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'
  }
},
#

Oh and also with this code, when a blind is loaded, the game crashes and displays the error "attempt to index global 'blind' (a nil value)"

daring fern
short fulcrum
#

I'm patching it in so it replaces the code that generates the blind reward strings (usually a bunch of dollar signs). In theory, it should work like the first bit of code I sent, but it crashes instead

#

the code is mostly identical to the original, except I add the following logic to it:

          blind.key == 'bl_mysingingjokers_crop'
          and localize('b_crop_custom_reward')
          or {
#

it should detect if the loaded blind is The Crop and replace the reward string with a custom string, otherwise just work as normal. That's how the code for the blind in the collection book worked, I thought this would be the same

#

my assumption is that it's something about how blinds are loaded that makes it different, but I'm not sure how to mitigate that

daring fern
short fulcrum
inner terrace
#

Hi! I've been working on making a reskin, and managed to get some new K/Q/J skins in pretty easily
but I've been trying to add a toggle in the config menu, and for some reason its state never saves. The toggle exists, but will always return to off when the game restarts

short fulcrum
#

actually it's slightly different, it says "attempt to index field 'blind' (a nil value)" instead

inner terrace
#

Huh, normally that means the variable doesn't exist/hasn't been declared (in my Very limited experience)

red flower
inner terrace
#

` unbal_nodes[#unbal_nodes + 1] = create_toggle({
label = "Disable Reskinned Jokers",
active_colour = HEX("E01BDE"),
ref_table = UNBALATROABLE_config,
ref_value = "disabled",
SMODS.save_mod_config
})
This is the toggle code, with the config file set up as well

#

the toggle is to disable reskinning the jokers, but for now I'm just trying to get the toggle to save states between launches

red flower
#

what's UNBALATROABLE_config?

inner terrace
#

That's the variable where the config reference is stored

red flower
#

you could also make the reskins into a malverk mod inside your mod btw

inner terrace
#

UNBALATROABLE_config = SMODS.current_mod.config

#

Malverk?

red flower
inner terrace
#

I did just debate separating it out, have a separate mod for the joker skins that can be enabled or disabled separately yeah

red flower
inner terrace
#

Oh, sick!

short fulcrum
hushed field
#

Blinds in the collection get rendered differently, and have their own set of variables for the tooltip, iirc, so it wouldn't surprise me if there's a separate instance in the code that you also need to tackle

short fulcrum
#

the second code block is my attempt at trying to do that

#

I tried using the same logic but it doesn't work unfortunately

#

and since then I haven't had any epiphanies

hushed field
#

I sadly don't have time to help you out right now, much, but feel free to ping me another time this week if you're still struggling

hushed field
wintry solar
#

am I right in understanding that you just want to replace the 20 $ signs with a $20?

short fulcrum
short fulcrum
wintry solar
#

oh, why only a specific blind?

short fulcrum
#

The Crop (the blind) gives a $20 reward unlike any other blind, but as it is, a $20 reward looks really ugly in game as it makes the blind really wide

#

so I just want to replace the blind reward string (usually a bunch of dollar signs) with "$20"

wintry solar
#

yeah I was trying to judge whether it was just a "this display looks awful" or a specific reason

#

I will try and remember to fix this through smods so that blinds with a reward greater than whenever it starts to stretch get converted

short fulcrum
#

that would be such a useful (if niche) addition

wintry solar
#

I don't think it's too niche actually

#

modifying blind rewards seems reasonably likely to be done imo

short fulcrum
#

I'm surprised I haven't seen it in more mods, I've maybe seen one mod do something interesting with it (can't remember what one right now)

short fulcrum
smoky holly
#

so i made a joker that alters denominators of probabilities, and for some reason it applies internally to my custom jokers but not visually on the jokers in-game?

#

actually it's just not.

#

applying to my custom jokers at all

slim ferry
#

you need to use SMODS.get_probability_vars for loc_vars and SMODS.pseudorandom_probability for the probability roll for it to work

smoky holly
#

how do i use SMODS.get_probability_vars ?

#

nvm i found it in the wiki

wintry solar
short fulcrum
smoky holly
#

to loc_vars have a cap on how many you can have?

#

nvm im just dumb

next timber
#

should i be using extra_slots_used or card_limit to change how many slots a card with an edition uses?

next timber
#

cool

#

so whats the point of card_limit then

slim ferry
#

Adds extra slots

#

Ala negative

next timber
#

so its just based on if youd rather your counter say 0/4 or 2/5

#

or does setting card_limit to negative numbers mess things up

slim ferry
#

I honestly have no idea

frosty rampart
#

yea it's the semantic distinction between "this card modifies how many total slots the cardarea has" and "this card takes up x many slots in the cardarea"

#

at least in theory, i have no reason to believe setting a negative card_limit or extra_slots_used would have any unintended effects. it's just that it's more reasonable to use extra_slots_used for cards that actually use extra slots

smoky holly
#

so i have a joker that gives random tags, excluding orbitals or boss-reroll tags, and it was running just fine, until now it crashed

#

because it couldnt find tag "unknown"

next timber
#

hm, this card is meant to make all debuffed and/or unscored cards scored and undebuffed, but for some reason if an unscored card gets undebuffed it won't get scored as well

#

ohh does context.modify_scoring_hand ignore cards that were debuffed before context.before happened or smth

#

cause if so. that sucks a lot and i have no clue how to fix this

frosty rampart
#

yea that seems likely

#

a lot of calculation just gets skipped with debuffed cards

next timber
#

awesomeee

smoky holly
frosty rampart
#

send your current code for the joker

#

i'm not too familiar with tags but i know of some code i can reference for properly creating tags
that code can also help get orbital tags functional if you'd like to include them

smoky holly
#
SMODS.Joker
{
    key = "sunday_comic",
    atlas = "jokers",
    pos = {
        x = 8,
        y = 0
    },
    unlocked = true,
    discovered = false,
    rarity = 1, -- Common
    cost = 6,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,

    -------------------------

    config = {
        extra = {
            tag_amount = 2
          }
    },

    loc_vars = function(self, info_queue, card)
        local config = card.ability.extra

        return {
            vars = { config.tag_amount }
        }
    end,

    calculate = function(self, card, context)
        local config = card.ability.extra

        if context.setting_blind and G.GAME.blind:get_type() == "Small" then
                        for i = 1, config.tag_amount do
                repeat
                    local tag_key = get_next_tag_key()
                                until tag_key ~= "tag_boss" and tag_key ~= "tag_orbital"

        -- potential TODO: orbital tags can be added but it takes a fair bit to do
                                add_tag(Tag(tag_key))
                        end

            return {
                message = localize { type = "variable", key = "v_j_o_y_plus_tag", vars = { config.tag_amount } },
                colour = G.C.FILTER
            }
        end
    end
}
frosty rampart
#

interesting
do you happen to have any other mods installed?

#

and could you post a screenshot of the crash

smoky holly
#

the only other mods on are steamodded and debugplus

frosty rampart
#

very strange
everything you're doing looks fine, just something managed to mess up the tag creation process
do you have any other mods installed and turned off?

smoky holly
#

extracredit, all in jest, jokerdisplay, talisman, paperback

#

but i dont think those should be affecting...

#

WE GOT IT

frosty rampart
#

oh?

smoky holly
#

the local tag_key creation here is local within the repeat loop only

#

the add_tag can't reference it

frosty rampart
#

ohhhhh that's fucked up

#

very subtle issue lmao

#

yea you'll have to add just a local tag_key before the repeat loop

next timber
#

ive been trying

#

ive got nothin

red flower
#

use press_play instead of before probably

next timber
#

is that a new context

red flower
#

its a year old

#

in fact i think it was added alongside modify scoring hand

#

or before

next timber
#

huh

#

i never did hear of it

#

press_play doesnt have a context.full_hand so will i want to be looping over G.play.cards?

#

or have they not moved there yet

red flower
#

they havent, you can use G.hand.highlighted

next timber
#

awesome, thx

#

ok sick press_play works as intended

#

thx

vague crest
#

trying to set up something like drivers liscence and its just not working?

#

anyone know whats up here

#

got it im actually just rusty 💔

smoky holly
#

am i doing smth wrong here

frosty rampart
#

yes, you shouldn't include the assets folder in the path. it already starts in the assets folder

smoky holly
#

still crashes

#

its apparently adding the mod prefix to the atlas search??

frosty rampart
#

oh right you need the modicon to have the 1x and 2x versions like other assets do

smoky holly
#

ah

#

do i keep them in the 1x ad 2x folders too

frosty rampart
#

yes

#

the mod prefix isn't a problem and in fact is intended

smoky holly
#

it works! thank you

frosty rampart
#

no problem

warm solar
#

how do i make enhancements not show up in standard packs or shops?

quick scarab
#

Making a Joker that has 1 in 5 chance to create a random consumable for every $5 spent, but it keeps crashing, also I had Talisman installed in case this is relevant

SMODS.Joker {
    key = "king",
    blueprint_compat = true,
    rarity = 2,
    cost = 5,
    atlas = 'Joker',
    pos = { x = 7, y = 0},
    config = {extra = { money = 5, odds = 3} },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.money, G.GAME.probabilities.normal or 1, card.ability.extra.odds } }
    end,
    calculate = function(self, card, context)
        if context.money_altered >= card.ability.extra.money and (pseudorandom('fnaf_king') < G.GAME.probabilities.normal / card.ability.extra.odds) 
        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({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                    local sets = {'Tarot', 'Planet', 'fnaf_item'}
                    SMODS.add_card {
                        set = sets ,
                        key_append = 'fnaf_king'
                    }
                    G.GAME.consumeable_buffer = 0
                    return true
                end)
            }))
            return {
                message = "GAME WIN!",
                colour = G.C.Gold,
            }
        end
    end
}

frosty rampart
#

context.money_altered is just true or false

frosty rampart
#

if context.money_altered is true, then context.amount is the actual amount of money being used
also you wanna make sure it's less than -5, because it can be gaining or losing money

quick scarab
frosty rampart
#

well it'd be <= -5, but yea
you also don't need to explicitly have == true, just if context.money_altered is the same thing

loud citrus
#

if i use SMODS.current_mod.extra_tabs could it act as another config tab?

young leaf
#

chat is "All Consumables are Free" too good or too bad for a vanilla-type legendary

loud citrus
#

perkeo is the only monetary legendary joker so think on that :)

frosty rampart
frosty rampart
quick scarab
# quick scarab Making a Joker that has 1 in 5 chance to create a random consumable for every $5...
SMODS.Joker {
    key = "king",
    blueprint_compat = true,
    rarity = 2,
    cost = 5,
    atlas = 'Joker',
    pos = { x = 7, y = 0},
    config = {extra = { money = 5, odds = 3} },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.money, G.GAME.probabilities.normal or 1, card.ability.extra.odds } }
    end,
    calculate = function(self, card, context)
        if context.money_altered and context.amount <= -card.ability.extra.money and SMODS.pseudorandom_probability(card, 'fnaf_king', G.GAME.probabilities.normal, card.ability.extra.odds) 
        and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and G.STATES.SHOP then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                    local sets = {'Tarot', 'Planet', 'fnaf_item'}
                    SMODS.add_card {
                        set = sets ,
                        key_append = 'fnaf_king'
                    }
                    G.GAME.consumeable_buffer = 0
                    return true
                end)
            }))
            return {
                message = "GAME WIN!",
                colour = G.C.Gold,
            }
        end
    end
}
#

still not working

#

it crashes when I cash out

loud citrus
#

(also srounding context :)

frosty rampart
# quick scarab

for this one: i don't think you can have more than one set in an add_card call, you'll need to randomly pick the set before then

frosty rampart
#

also you still aren't using probability quite right, you shouldn't use G.GAME.probabilities.normal at all. the utility function handles that for you. you also need to use a second utility function, documented in what i already sent you, for the loc_vars stuff

quick scarab
frosty rampart
#

you have to convert -card.ability.extra.money to the big-number format that talisman automatically converts money into, and add a bit of extra code to the mod to account for if it's being played without talisman

quick scarab
loud citrus
# quick scarab

for line 927, it honestly looks right to me

the error says attempt to compare table with number so make sure one of your vales isn't coming out as a table, because that's the only way i think it could break, also typos can be a killer lol

frosty rampart
#

it's the talisman thing

loud citrus
#

OH

frosty rampart
#

talisman automatically converts money into its bignum format, which is a table

loud citrus
#

that's weird

frosty rampart
#

honestly you should be using amulet instead

quick scarab
frosty rampart
# loud citrus that's weird

lua physically cannot represent numbers larger than about 1e308 as a simple number format, so talisman implements a custom table that represents larger numbers
it automatically converts all money to that table format for. reasons. idk lol

frosty rampart
quick scarab
# frosty rampart ah that's good, so then it should just be throwing a to_big onto `-card.ability....

Yeah no it didn't work

SMODS.Joker {
    key = "king",
    blueprint_compat = true,
    rarity = 2,
    cost = 5,
    atlas = 'Joker',
    pos = { x = 7, y = 0},
    config = {extra = { money = 5, odds = 3} },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.money, G.GAME.probabilities.normal or 1, card.ability.extra.odds } }
    end,
    calculate = function(self, card, context)
        if context.money_altered and context.amount <= to_big(-5)
        and SMODS.pseudorandom_probability(card, 'fnaf_king', G.GAME.probabilities.normal, card.ability.extra.odds) 
        and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and G.STATES.SHOP then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                    local sets = {'Tarot', 'Planet', 'fnaf_item'}
                    local random_set = pseudorandom_element(sets, 'random_consumable_set')
                    SMODS.add_card {
                        set = random_set ,
                        key_append = 'fnaf_king'
                    }
                    G.GAME.consumeable_buffer = 0
                    return true
                end)
            }))
            return {
                message = "GAME WIN!",
                colour = G.C.Gold,
            }
        end
    end
}
frosty rampart
#

try using to_big on both sides of the <= then
given the error before, i'm fairly sure context.amount is a bignum sometimes but i guess not in this instance that caused this crash

loud citrus
#

i'm trying to get tooltip to work but i don't know how

foggy ginkgo
#

Is there a way to detect a card when changing suits

short fulcrum
stuck ore
#

How do you make a joker with the effect of retriggering other jokers?

daring fern
stuck ore
#

How is that implemented? I haven't seen that used before

daring fern
stuck ore
#

Oh

#

Wow it's really that easy

#

thanks a bunch spent way to much time trying stuff that didn't work

#
    if context.retrigger_joker_check then
        return {
            repetitions = 1
        }
    end```
#

I'm using this but it doesn't seem to be working the way it should

hushed field
stuck ore
#

Ah is there anything online that goes over that or is it just a line of code?

hushed field
#

It's a single line of code. The smods wiki does explain it somewhere, though I sadly don't remember exactly where

#

I'd check the wiki for mentions of optional features. Alternatively, you can check the code for other mods that use triggers and search all for 'optional'. My mod Kino does, and I know Cryptid does

gaunt phoenix
#

Does anyone knows how to make a changing-color text just like in the Perkeo description ? can't find it anywhere :c

hushed field
gaunt phoenix
#

Yes

hushed field
#

You'll want to make an SMODS.Gradient object with your colours. There's a bit more detail to it, but I'd start with looking into that!

gaunt phoenix
#

Okay thanks ! that should help me a lot

hushed field
#

I'd offer a better explanation but I don't remember by heart. I can check later if you're still stuck!

limber aspen
#

How do I apply edition shader to seals?

#

I think I got it

maiden phoenix
#

Check SMODS.Drawstep

slim ferry
#

just check vanillaremade gold seal

#

you can do the same code with any shader

sleek valley
#

Does anyone know what the code would be to check for the least played poker hand in a run?

slim ferry
sleek valley
#

Tyyy

rare torrent
#

is it possible to get the next joker in the joker order? (like the next one you're gonna get if you reroll or open a buffon pack), and then show that in a joker description?

hushed field
#

Yes, though it's not easy to set up

#

The misprint legendary or epic (I don't remember it's name) in Cryptid has this as a secret effect, showing you the joker order of the next joker that will spawn, so you could see how it works in that code. If you're lucky, it's been rewritten to be readable, but there's a chance it's still the old spaghetti, or that feature has been removed. But the idea is basically that you just check what the next randomization seed will be, so you can predict what the shop will roll

rare torrent
#

alright imma check it out then

hasty kelp
#

Hi how do i make a deck in balatro what starts with a specific joker and debuffs and buffs??

rare torrent
#

for some reason i can't send the code here tho

hushed field
#

I recommend not opting to mess with the randomness unless you're very comfortable with programming, yeah. Before Ruby rewrote the way Cryptid handles that code, I had to untangle the old code's implementation of spawning cards, and prediction was such a huge chunk of it that was littered throughout, and it made me scrap any similar ideas from my own mod, haha

rare torrent
#

godamm, i guess i'll think of another effect my joker would do

hasty kelp
#

I guess you can have an effect like polychrome but for x chips

wild patrol
#

thought it seems nice at first

#

but now realizing what's the point of the mult gain for Cavendish when u can just feed it Michel

wild berry
#

how can i get the jokers in the current shop when exiting it

wild patrol
#

also we made a C4 joker to possibly be a command for the twitch intergration but not sure how it should function

wintry solar
hushed field
#

I've not touched it at all. I made a note of it to mess with it, but after I saw what cryptid tried to do to make the same mechanic I wanted to work, I moved that to the lowest priority and have yet to give it a second chance, haha

wintry solar
#

I’ll try play with it later

#

I would assume it simulates the next seed call

hushed field
#

It would make sense to work like that, yeah

wild berry
#

what cardarea contains the shop jokers

slim ferry
#

G.shop_jokers

wild berry
#

k thanks

#

how can i change the sprite size of a card so its not 71x95px

wild patrol
#

Is there a way to check if a joker appears in the shop or do u just have to keep rerolling to check I have a joker I want to not appear in the shop at all

#

But not sure how to check

wild berry
#

theres in_pool

#

its a function to check whether to spawn the joker you want

#

returning true makes it elegible for spawning

#

otherwise it wont

#

something like this (from vanillaremade's cavendish)

#

look at just the bottom part

wild patrol
#

So just set in_pool to false

#

And it shouldn't appear in the shop

wild berry
#

yes

#

it wont appear at all

wild patrol
#

Cool thanks

wild berry
#

np

daring fern
wild patrol
#

Being using a mixture of joker forge and my own code so

#

It's be kinda of a pain

#

Thankfully been getting better at Lua

wild patrol
wild berry
#

my cardarea wont make cards show up inside it

#

it still counts cards inside it but they dont get moved there

red flower
#

in the type

wild berry
#

im using my own center type

slim ferry
#

that

#

isnt relevant to what the cardarea type should be

wild berry
#

oh

slim ferry
#

cardarea type just determines how the area behaves and not the actual contents

wild berry
red flower
#

sorry it's 'joker'

wild berry
#

ah

#

yeah it works now, thanks

keen hinge
#

can the low contrast and high contrast parts of a deckskin have different loc-txt variants?

red flower
#

what does that have to do with their question

wild berry
#

i thought thats what they meant

#

sorry

keen hinge
#

nw i could have explained it better

#

like for a deckskin it would have a loc-txt that shows in the customization menu right

#

but for the high contrast version it would have the same loc-txt

#

is there a way to make a different text show up

wild berry
#

you want to check when high contrast is enabled or do you want the color to stay the same regardless of contrast

keen hinge
#

i guess check when its enabled? the color isnt what im focusing on

red flower
#

im checking the wiki and it says you can have a loc txt per palette it seems

wild berry
wild berry
red flower
keen hinge
#

oh nice ok

#

but i use the lc_atlas and hc_atlas is that two separate palettes?

#

sorry im not super familiar with this stuff

red flower
#

ive never made a deckskin so i dont know the options too well, can i see your code

#

the example has this

#

in each palette you can add a loc_txt

keen hinge
keen hinge
#

thanks ill show you my code if i need any more help

wild berry
#

how can i directly change a center's size when its being created? the way i have it rn just doesnt seem good to me

red flower
#

generate_ui is for the hover description

wild berry
#

i noticed, i just dont know what other function i could put it in

red flower
wild berry
#

worked, ty

white hull
#

is there a function i can use to determine which poker hands a given poker hand contains? using name of hand, not a table of cards

#

it would be easy enough to just check for all hand types manually but that feels hacky

frosty rampart
#

yea no there's no function that does that afaik
and if there was it'd just offload the "check all hand types manually" work to the function

#

what are you planning to use it for tho?

white hull
#

To check if final played hand of round contains a full house

#

In the end of round context so there's no cards to look at

#

So I use G.GAME.last_hand_played

slim ferry
#

well G.GAME.last_hand_played is a string no?

#

you can really get the played cards at that point

white hull
#

Yeah so I can check if it's "full house" or "flush house"

#

I'm just wondering if there's a better way cuz if there are modded hands that contain a full house then it's borked

red flower
#

you would need to save the contained hands when the last hand is played

#

getting it from the string is impossible

frosty rampart
#

honestly what i'd do is just check for whether every hand contains a full house, save that status as a boolean variable in the card's ability table, and then just act on that variable in end_of_round

white hull
#

Yeah seems fine

#

Thanks y'all

#
if context.before and next(context.poker_hands['Full House']) and not context.blueprint then
    card.ability.extra.fullhouse = true
else
    card.ability.extra.fullhouse = false
end
#

This appears to not be doing the thing

frosty rampart
#

because of how the condition is set up, the else clause runs in every context that isn't context.before and the variable just gets forced back to false

white hull
#

ohh duh

#

thanks

#

I feel like I've gotten alright at coding these things but something like this trips me up once in a while lol

daring fern
#

white hull
#

How do I set the order of my Jokers in the collection? Is the only way to literally reorder them in the code?

red flower
#

yes

white hull
#

amazing

shrewd cobalt
#

I was wondering that too

#

Lowkey surprised that’s not an smods feature yet

slim ferry
#

changing the way smods loads objects for that would be a lot of work tbf

red flower
#

i think its a case of someone needing to sit down a work out some kinks the order problem has when the solution is already very easy and unless you have a million jokers it doesnt matter

white hull
#

Does the collection have to display things in load order tho? Maybe it could be patched to look for a variable in every object and order them according to that if the variable is present

round lion
#

how am i meant to use setability

white hull
#

Per mod maybe, so objects from different mods don’t get jumbled up

red flower
#

what im saying is that there are decisions you have to take for that that no one has taken yet because the problem is kinda niche

red flower
round lion
#

setting up initial values

red flower
#

i would appreciate a more detailed explanation of what you're trying to do

round lion
#

im trying to make an value in extra get randomized as soon as the card gets generated in the shop instead of after getting bought

red flower
#

you can just do card.ability.extra.whatever = random in set_ability

#

check to do list in vanillaremade

round lion
#

is therea a upper limit to how many things there can be in a table

normal crest
#

theoretically no

harsh belfry
#

run out of memory

#

there always is

#

and love2d has a very small hard limit

#

don't remember exactly what it is rn

#

i say "very small" but its fine

#

you wont hit it

#

you do not have to care unless you're doing crazy shit

red flower
#

the limit is 6

#

or 7

slim ferry
#

thanks N

rough furnace
#

DebugPlus

#

Anybody working on anything cool or interesting?

tidal hemlock
#

how broken are these

#

skelton is fixed chance btw

frosty rampart
#

neither of these are strong enough to be legendaries
stanczyk's essentially a sidegrade to dna, and skelton is not nearly likely enough to be worth holding onto

spiral mural
#

make them give 100x mult

slim ferry
#

make them _ _

spiral mural
#

make them...

tidal hemlock
#

buffed

slim ferry
#

Chance based revive kinda sucks in general

rough furnace
# tidal hemlock how broken are these

Skelton sounds really unfun. Most RNG in the game has some way to either improve consistanxt (making the trigger occur more often, getting more of the card, etc.). This is just if you lose there's a chance (worse than wheel of fortune) you don't. It can't be relied on or manipulated. I feel like some sort of activation would make more sense, (such as maybe a counter like loyalty card or invisible) or maybe a condition (like Mr. Bones)

slim ferry
#

Its really unreliable unless you have enough probability increases in which case you just win

rough furnace
#

The other one seems line just DNA

#

Oh you modified it let me read the new one

tidal hemlock
harsh belfry
slim ferry
#

Oh okay

harsh belfry
#

like game design wise

#

boring

slim ferry
#

Its still rng yeah

tidal hemlock
#

yeah i might redo skelton completely

slim ferry
#

Randomly not losing is just kind of an instant sell usually

rough furnace
#

Its RNG with no way to effect it

tidal hemlock
#

anyway thoughts on the new stanc?

harsh belfry
#

you just got a legendary lmao

rough furnace
#

What if it was just prevents death, and destroys all other jokers (or maybe just a random one)

harsh belfry
#

probably have a decent build or you got scammed

rough furnace
tidal hemlock
rough furnace
#

Probably something like that

#

Ant sort of renewable ibstant win is hard to balence and keep fun

faint yacht
#

@coral flume Best to discuss such here. Check for context.mod_probability and context.identifier being either 'lucky_mult' or 'lucky_money'.

viscid talon
#

im currently reworking "the whip" boss blind bc it doesnt work, so i went with a different approach

viscid talon
#
SMODS.Blind {
    key = "hatch_whip",
    dollars = 5,
    mult = 2,
    debuff = { h_size_ge = 3 },
    pos = { x = 0, y = 2 },
    boss = { min = 1 },
    boss_colour = HEX("cbb9a3"),
    atlas = 'CustomBlinds',

    loc_txt = {
        ['name'] = 'The Whip',
        ['text'] = {
            [1] = 'All consumables',
            [2] = 'are debuffed',
        },
    },

    calculate = function(self, blind, context)
        if not blind.disabled then
            if context.debuff_card and context.debuff_card.area ~= G.consumables then
                return {
                    debuff = true
                }
            end
        end
    end
}```
#

it no worky

#

what do i do

#

ignore the min = 1, this is just for testing purposes

gaunt folio
#

how do i fix this? What im intending is for it to start like a timer and update every second?

slim ferry
#

Calculate does not run constantly

#

You use update iirc

viscid talon
#

who

slim ferry
#

The person above me

#

Nto you

viscid talon
#

oo

gaunt folio
#

aight

#

trying the funciton just causes the game to freeze up and crash

primal robin
#

Of course it is trash

gaunt folio
#

what else would work then?

#

actually kw ill see

slim ferry
#

For SMODS.Joker

#

Or any center for that matter

sage crater
gaunt folio
gaunt folio
#

i want it to update every second, how can i make that work if its even possible?

frosty rampart
#

the dt argument that gets passed to update is the time elapsed since the last call of update, in seconds iirc
you can add dt to a variable stored in the joker until the variable reaches 1, then reset that variable to 0 and do the thing you wanted to do

gaunt folio
#

ah

narrow plaza
#

whats the best way to get started in mod development:)

frosty rampart
smoky holly
#

ok i read up on installing and using vscode for modding but i dont quite think i understand this part

#

where exactly would i put that in the workspace settings or what exactly would i put in the .luarc.json file?

gaunt folio
#

okay i managed to get it to update

#

thing is, how can i make it update while viewing the description of the joker? will I have to mess around with dynatext like how misprint works?

sage crater
#

lol

smoky holly
normal crest
#

Both should work

smoky holly
#

i got it

#

for some reason i saves my .json to the steamodded folder and not my mod's folder

red flower
buoyant crag
#

whats the easiest way to make soul cards only spawn the vanilla legendaries? im thinking of just taking ownership of each and adding them to a pool to then edit soul to spawn from that pool, but im sure this is a common problem that might have easier fixes

daring fern
buoyant crag
daring fern
daring fern
#

twin hemlock
#

Hi, i'm a complete beginner and i'm using jokerforge
I tried to make a baron-like joker but i immediately crashed

#

When i tried to use it

#

Idk what to do right now

sturdy compass
vale zinc
frosty rampart
#

modding-support is for support installing and playing mods
this channel is for discussion of making and developing your own mods (including support in that aspect)

vale zinc
#

So, could any of you be a dear and tell me why this Blind's innermost function never gets called?

-- The Gale
SMODS.Blind {
    key = "gale",
    unlocked = true,
    dollars = 5,
    mult = 2,
    boss = {
        min = 1
    },
    boss_colour = HEX("B1DDBF"),
    calculate = function(self, blind, context)
        if not blind.disabled and context.before then
            print('A')
            if #context.scoring_hand > 1 then
                for i = 1, 3 do
                    print('B')
                    G.E_MANAGER:add_event(Event({
                        trigger = 'immediate',
                        func = function()
                            G.E_MANAGER:add_event(Event({
                                func = function()
                                    context.scoring_hand:shuffle('bl_lapsems_gale')
                                    play_sound('cardSlide1', 0.85)
                                    delay(0.15)
                                    print('Whoosh!')
                                    return true
                                end,
                            }))
                            return true
                        end
                    }))
                end
                delay(0.35)
            end
        end
    end,
}
limber aspen
# slim ferry just check vanillaremade gold seal

draw = function(self, card, layer) if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then card.children.center:draw_shader('funmode_monochrome', nil, card.ARGS.send_to_shader) if card.seal then G.shared_seals[card.seal]:draw_shader('funmode_monochrome', nil, card.ARGS.send_to_shader, nil, card.children.center) end end end,
(This is draw function from shader)
For some reason instead of shader being applied to seal and card, it does this and card just turns white :/

solemn aurora
#

because I may have a fix

limber aspen
daring fern
limber aspen
#

Thank you!!!! It looks really good

vale zinc
solemn aurora
# vale zinc What do you prescribe?

this
calculate = function(self, blind, context)
if blind.disabled or not context.before then return end
if #context.scoring_hand <= 1 then return end

for i = 1, 3 do
    G.E_MANAGER:add_event(Event({
        delay = 0.15 * i,
        func = function()
            for j = #context.scoring_hand, 2, -1 do
                local k = pseudorandom('bl_lapsems_gale', j)
                context.scoring_hand[j], context.scoring_hand[k] =
                    context.scoring_hand[k], context.scoring_hand[j]
            end
            play_sound('cardSlide1', 0.85)
            return true
        end
    }))
end

end

#
calculate = function(self, blind, context)
    if blind.disabled or not context.before then return end
    if #context.scoring_hand <= 1 then return end

    for i = 1, 3 do
        G.E_MANAGER:add_event(Event({
            delay = 0.15 * i,
            func = function()
                for j = #context.scoring_hand, 2, -1 do
                    local k = pseudorandom('bl_lapsems_gale', j)
                    context.scoring_hand[j], context.scoring_hand[k] =
                        context.scoring_hand[k], context.scoring_hand[j]
                end
                play_sound('cardSlide1', 0.85)
                return true
            end
        }))
    end
end

#

not sure if it works though

#

but you could I guess just manually shuffle the deck

solemn aurora
#

oof

vale zinc
#

Y'know, I might be able to pull this off with a patch instead.

#

I appreciate your care, though.

solemn aurora
#

you're welcome

daring fern
wild patrol
#

is it possible to make your own text with jimbo from the tutorial?

#

Trying to find find how tutorial jimbo text is done searching around using tutorial

red flower
#

that's what i used for hot potato anyway

wild patrol
#

I'm sorta what i've been trying lol

#

but I didn't know about say stuff gonna try that

red flower
#

chara is a card character object

wild patrol
#

right now just a simple text on screen

#
    if not whitelist[user:lower()] then return end
    if is_on_cooldown() then return end
    if not text_to_show or text_to_show == "" then text_to_show = "Hello!" end
    attention_text({
        text = text_to_show,
        scale = 0.8,
        hold = 4,
        align = 'cm',
        colour = G.C.WHITE,
        major = G.play
    })
    play_sound('voice1', 0.8, 0.5)
end```
karmic nest
#

is there a way to remove a certain joker from the shop pool?

daring fern
wild patrol
#

hmmmm

#

I think my spawn joker command maybe a little broken

teal grotto
#

no shit

round lion
shrewd cobalt
#

What type of sandwich would you assosiate with the spades suit

slim ferry
#

grilled cheese

tepid eagle
#

ham and swiss

round lion
#

brisket

smoky holly
#

i was about to say a club sandwich and then i read what i was typing and realized im a dumbass

lyric wadi
#

grilled cheese

#

with sharp cheddar

smoky holly
#

we're probably not gonna tackle this yet but on a scale of 1 to 10 how difficult would it be to code a joker effect that copies a blind effect

#

the blind it's copying being effectively variable

shrewd cobalt
#

Many thanks everyone 🧡

short fulcrum
#

I have code here for a blind that makes 3 random ranks drawn face-down:

SMODS.Blind {
    key = "winds",
    dollars = 5,
    mult = 2,
    pos = { y = 10 },
    boss = { min = 1 },
    atlas = 'MySingingBlinds',
    boss_colour = HEX("e0b06c"),

    set_blind = function(self)
        self.selected_ranks = (function()
            local ranks = {}
            while #ranks < 3 do
                local rank = math.random(2, 14)
                local duplicate = false
                for _, v in ipairs(ranks) do
                    if v == rank then
                        duplicate = true
                        break
                    end
                end
                if not duplicate then
                    table.insert(ranks, rank)
                end
            end
            return ranks
        end)()
    end,

    stay_flipped = function(self, area, card)
        if self.disabled then return end

        if area == G.hand then
            local card_id = card:get_id()
            for _, rank in ipairs(self.selected_ranks) do
                if card_id == rank then
                    return true
                end
            end
        end
    end,

    disable = function(self)
        for i = 1, #G.hand.cards do
            if G.hand.cards[i].facing == 'back' then
                G.hand.cards[i]:flip()
            end
        end
        for _, playing_card in pairs(G.playing_cards) do
            playing_card.ability.wheel_flipped = nil
        end
    end
}

There isn't an issue with the blind itself, it works well, but I'm wondering if there's a way for it to include modded ranks, as right now it can only flip vanilla ranks

wild patrol
# wild patrol

You think a command where it just spawns something on screen that the streamer can't get rid off would be a fun command for twitch integration

red flower
#

you can get a random rank with pseudorandom_element, check the smods.rank docs

short fulcrum
#

ok, thanks, I'll have a look

wild berry
#

how can i make the sell ui box appear on my custom card

rough furnace
#

probably have to modify G.UIDEF.card_focus_ui

dapper sun
#

how do i make a card change a rarity's weights?

#

wait i think i found it

vale zinc
#

Could anyone say why the left statement returns a range of values but the right one doesn't?

dapper sun
wild berry
#

in this case you could try math.random(25, 125)/100

dapper sun
#

that's not weights???

stoic void
#

where it says

remove_from_deck = function(self, card, from_debuff)
  --stuff
end,
dapper sun
#

well duh

#

but what if i have a joker that affects rarity weights

stoic void
#

wouldnt you just do the reverse?

dapper sun
#

2 things affecting the rates

stoic void
#

O

dapper sun
#

no bc i'm not just adding to the weights

slim ferry
#

well

#

youre meant to multiply them afaik

dapper sun
#

which i'm not doing either

slim ferry
#

well

#

how are you doing it in the first place

dapper sun
#

i'm gonna normalize the weights between multiple rarities

slim ferry
#

well okay

#

but code wise

#

what are you doing

dapper sun
#

-# oops sent early

#

add the rarities' weights together and divide by the amount of rarities

slim ferry
#

and what are you doing to actually apply the weights

#

patch i assume?

dapper sun
#

no?

slim ferry
#

well

#

if youre doing the math on that that wont work

dapper sun
#

okay

slim ferry
#

because its a multiplier that always starts at 1

dapper sun
#

so should i patch instead?

slim ferry
#

i think so

#

probably look at SMODS.poll_rarity

dapper sun
#

okii

#

i'm looking at it and idk what i'd do to do what i said

#

😭

#

where i'd put it in the func and what vars i need to use

slim ferry
#

actually wait you could probably do a hook

dapper sun
#

oh cool yippee

slim ferry
#

check if the returned key is that of one of the affected rarities, and if so return a random one of the rarities

dapper sun
#

why random

#

what

slim ferry
#

well because its normalizing the weights right

dapper sun
#

yea?

wild berry
#

why doesnt this work

slim ferry
#

so when it wouldve normally rolled any of the rarities its effectively choosing an unweighted random rarity out of the affected ones

dapper sun
#

so would that have the same effect as all rarities being equally likely?

slim ferry
#

should be

dapper sun
#

ok

wild patrol
#

Is there a way to remove what mod a custom consumable is from

#

I made a fake soul troll card for the twitch mod

#

But the scrolling text of what mod it's from is a giveaway

vale zinc
dapper sun
#

ok i'm struggling on the hook

slim ferry
#

whatre the issues

dapper sun
#

idk what to put in the hook, or whether to do it before or after

#

i think before tho

slim ferry
#

you need to do it after because you need the return value

dapper sun
#

okii

#

i think i know what i'm doing now

wild berry
wild patrol
wild berry
#

also no_collection = true if you dont want to see it in the collection

wild patrol
#

I tried setting it to being locked

#

But started a new profile and it was still unlocked

#

But that works much better

#

Wish stuff like this was mentioned more on the smod wiki would help a ton

#

madness now if only I can figure out how to add the ability to put a jokers name in the create_card using twitch chat

#

I've almost got it working I just can't get the text to read from chat

weary merlin
#

i got a joker which draws the first hand face down, and gives xmult when a card played face down is scored
i got the context to flip them down, but i need some pointers as to the context to use for checking which cards in the played hand are face down prior to flipping them and revealing the hand

would this be context.before or context.press_play? something else? unsure if these contexts allow me to search the cardarea and the scoring hand.

dapper sun
jolly shadow
#

use Detained joker

dapper sun
#

_ _

#

you know what i meant

slim ferry
#

and add a chance roll to that

#

then set legendary to true if it passes

dapper sun
#

sho?

slim ferry
#

yeah

dapper sun
#

o right that's the shop thingy

slim ferry
#

thunk moment

dapper sun
#

i saw that when getting the poll_rarity hook working

slim ferry
#

i would set rarity to 4 instead

#

since legendary bypasses unlock state if true

dapper sun
#

yea

#

sounds good

daring fern
# dapper sun how would i make legendary jokers appear in shop
local oldgetcurrentpool = get_current_pool
function get_current_pool(_type, _rarity, _legendary, _append)
    if _type == 'Joker' and _append == 'sho' then
        local poll = pseudorandom('rarity'..G.GAME.round_resets.ante.._append)
        if poll < (1/odds) then
            _legendary = true
        end
    end
    return oldgetcurrentpool(_type, _rarity, _legendary, _append)
end
dapper sun
#

oh that seems much safer i think

#

what's with the 'rarity'..G.GAME.round_resets.ante.._append tho

slim ferry
#

like that it would be affected by context.mod_probability and context.fix_probability

#

fyi

dapper sun
#

true

#

would a normal pseudorandom() be better?

slim ferry
#

yeah definitely

#

well still with the seed ofc

dapper sun
slim ferry
#

not specifically, but adding _append and current ante makes it so the seed will actually be affected by the key_append used

dapper sun
#

ok

slim ferry
#

idk why current ante but vanilla does that often so its probably important

primal robin
#

Make pools separate between different antes

dapper sun
#

ah

slim ferry
#

oh right

#

i forget shops have different seeds for each ante

weary merlin
#

is there a proper way to check this? breaks because indexing self is nil context.scoring_hand[i].self.facing == 'back'

red flower
#

keep in mind unless some mod messes with it scoring cards are always going to be face up

weary merlin
smoky holly
#

ignore the reply i forgot i left that there

#

i meant to bump that question

red flower
#

yeah i would do that

#

in context.press_play

dapper sun
#

i got it working ty

red flower
#

also each blind function needs to be called at the appropriate time

slim ferry
#

SMODS.blindprint_effect when

modern kindle
#

SMODS.Blind when clueless

slim ferry
#

genius

weary merlin
#

what might be causing this to not give xmult when scoring face-down-played cards?

    config = { extra = { xmult = 2 } },
    loc_vars = function(self, info_queue, card)
        local targeted_cards = {}
        return { vars = { card.ability.extra.xmult } }
    end,
    
    calculate = function(self, card, context)
        if context.stay_flipped and context.to_area == G.hand and G.GAME.current_round.hands_played == 0 and G.GAME.current_round.discards_used == 0 and not context.blueprint then
            return {
                stay_flipped = true
            }
        end
        
        if context.press_play and context.cardarea == G.scoring_hand and not context.blueprint then
            for i = 1, #context.cardarea do
                if context.cardarea[i].facing == 'back' then
                    targeted_cards[#targeted_cards + 1] = 1
                else
                    targeted_cards[#targeted_cards + 1] = 0
                end
            end
        end
        
        if context.individual and context.cardarea == G.scoring_hand then
            for i = 1, #context.cardarea do
                if targeted_cards[i] == 1 then
                    return {
                        xmult = card.ability.extra.xmult
                    }
                end
            end
        end
    end,
slim ferry
#

G.scoring_hand isnt a thing

weary merlin
#

oh yeah haha it's just context.scoring_hand

slim ferry
#

also you should store if the card was flipped on the card itself probably

weary merlin
#

let me try that rq

weary merlin
red flower
#

theres no cardarea in press play btw

#

the cards are in G.hand.highlighted

slim ferry
vale zinc
#

@red flower, speaking of cards and how they're defined when "Play Hand" is pressed, could you tell me why this doesn't work? It shuffles the positions of the cards, but when it's time to score them, they revert to their previous positions.

[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'after'
pattern = '''
G.FUNCS.play_cards_from_highlighted = function(e)
'''
payload = '''
-- This is utilized by The Gale.
if (G.GAME.blind.config.blind.key == 'bl_lapsems_gale') and not G.GAME.blind.disabled and (#G.hand.highlighted > 1) then
    G.GAME.blind.triggered = true
    G.GAME.blind:wiggle()
    local LAPSEMS_selected_cards = {}
    for i = 1, #G.hand.cards do
        if G.hand.cards[i].highlighted then
            LAPSEMS_selected_cards[#LAPSEMS_selected_cards + 1] = i
        end
    end
    for i = 1, 3 do
        G.E_MANAGER:add_event(Event({
            func = function()
                delay(0.15)
                for j = #LAPSEMS_selected_cards, 2, -1 do
                    local k = pseudorandom_element(LAPSEMS_selected_cards, 'bl_lapsems_gale')
                    G.hand.cards[j], G.hand.cards[k] =
                        G.hand.cards[k], G.hand.cards[j]
                end
                play_sound('cardSlide1', 0.85)
                print('Whoosh!')
                return true
            end
        }))
    end
    --delay(0.35)
    delay(03.5)
end
'''
slim ferry
#

why are you patching for this

vale zinc
#

So I can be sure it happens before anything else in G.FUNCS.play_cards_from_highlighted().

slim ferry
#

context.press_play already does that

vale zinc
slim ferry
#

well

#

the point is

#

you literally dont need to patch

#

just use the old function but shallow copy the old scoring hand to a local variable

#

so it still exists in the event

vale zinc
#

What is the old function?

dapper sun
slim ferry
weary merlin
# red flower the cards are in G.hand.highlighted

@slim ferry works now except for one bug where the xmult is applied to the first scored card instead of the nth scored card, where n applies to each card that was played face down. current code looks like this:

    config = { extra = { xmult = 2 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult } }
    end,
    
    calculate = function(self, card, context)
        if context.stay_flipped and context.to_area == G.hand and G.GAME.current_round.hands_played == 0 and G.GAME.current_round.discards_used == 0 and not context.blueprint then
            return {
                stay_flipped = true
            }
        end
        
        if context.press_play and not context.blueprint then
            for i = 1, #G.hand.highlighted do
                if G.hand.highlighted[i].facing == 'back' then
                    G.hand.highlighted[i].ability.was_flipped = true
                else
                    G.hand.highlighted[i].ability.was_flipped = false
                end
            end
        end
        
        if context.individual and context.cardarea == G.play then
            for i = 1, #context.scoring_hand do
                if context.scoring_hand[i].ability.was_flipped == true then
                    context.scoring_hand[i].ability.was_flipped = false
                    return {
                        xmult = card.ability.extra.xmult
                    }
                end
            end
        end
    end,
#

does G.hand.highlighted refer to a subset of the played cards?

slim ferry
#

you should check context.other_card since the current code checks if any card in the hand was flipped

weary merlin
#

works fine if there's multiple

slim ferry
#

and only reset was_flipped for the whole hand in context.after

dapper sun
# dapper sun oh ok i started a new run and
SMODS.Voucher {
    key = "mixup",
    atlas = "vouchers",
    pos = {x=0,y=0},
    cost = 10
}
SMODS.Voucher {
    key = "breakthrough",
    atlas = "vouchers",
    pos = {x=1,y=0},
    cost = 10,
    requires = "v_elle_mixup"
}

local rarity1 = {[1]=true,[2]=true,[3]=true}    -- Rarities to check for, formatted for easier checking
local rarity2 = {1,2,3}                         -- Rarities to pick from

local pr_hook = SMODS.poll_rarity
function SMODS.poll_rarity(_pool_key, _rand_key, ...)
    local pr = pr_hook(_pool_key, _rand_key, ...)
    return (#SMODS.find_card("v_elle_mixup")>0 and rarity1[pr]) and pseudorandom_element(rarity2, "elle_rarity_mix") or pr
end

local gcp_hook = get_current_pool
function get_current_pool(_type, _rarity, _legendary, _append)
    if #SMODS.find_card("v_elle_breakthrough")>0 and _type == 'Joker' and _append == 'sho' and pseudorandom('ellerar'..G.GAME.round_resets.ante.._append, 1, 20)==1 then _legendary = true end
    return gcp_hook(_type, _rarity, _legendary, _append)
end```
#

this is my whole voucher code why is it iterating through a string now

dapper sun
vale zinc
#

@red flower and/or @slim ferry: this produces a crash. What now?

calculate = function(self, blind, context)
    if not blind.disabled then
        if context.before and #context.scoring_hand > 1 then
            G.GAME.blind.triggered = true
            G.GAME.blind:wiggle()
            for i = 1, 3 do
                G.E_MANAGER:add_event(Event({
                    func = function()
                        delay(0.15)
                        for j = #context.scoring_hand, 2, -1 do
                            local k = pseudorandom_element(j, 'bl_lapsems_gale')
                            context.scoring_hand[j], context.scoring_hand[k] =
                                context.scoring_hand[k], context.scoring_hand[j]
                        end
                        play_sound('cardSlide1', 0.85)
                        print('Whoosh!')
                        return true
                    end
                }))
            end
            delay(0.35)
        end
    end
end,
dapper sun
slim ferry
#

that was

#

the thing i linked you

frosty rampart
vale zinc
frosty rampart
#

correct, you can't modify it directly
because it's in an event, context.scoring_hand ceases to exist by the time the event actually runs

vale zinc
#

Like this?

local list_of_scoring_cards = context.scoring_hand
slim ferry
#

it should be SMODS.shallow_copy(context.scoring_hand)

vale zinc
#

What does SMODS.shallow_copy() do?

red flower
#

im playing etrian odyssey im busy

slim ferry
#

then returns that new table

vale zinc
#
calculate = function(self, blind, context)
    if not blind.disabled then
        if context.before and #context.scoring_hand > 1 then
            local list_of_scoring_cards = SMODS.shallow_copy(context.scoring_hand)
            G.GAME.blind.triggered = true
            G.GAME.blind:wiggle()
            for i = 1, 3 do
                G.E_MANAGER:add_event(Event({
                    func = function()
                        delay(0.15)
                        for j = #list_of_scoring_cards, 2, -1 do
                            local k = pseudorandom_element(j, 'bl_lapsems_gale') -- Now this line produces a crash. What now?
                            list_of_scoring_cards[j], list_of_scoring_cards[k] =
                                list_of_scoring_cards[k], list_of_scoring_cards[j]
                        end
                        play_sound('cardSlide1', 0.85)
                        print('Whoosh!')
                        return true
                    end
                }))
            end
            delay(0.35)
        end
    end
end,
slim ferry
#

because j is a number

#

you cant pseudorandom_element a number

#

also btw is there even a reason you cant just do G.play:shuffle()

vale zinc
#

I remember that not working when I tried it.

#

But I never did try it with G.play.

red flower
#

if you shuffle them the play order doesn't change iirc

vale zinc
#

Just tried it with G.play:shuffle(), and the play order did not change. What am I to do?!

#

I've resorted to using a patch so the shuffled order gets set in stone before any other function acts on it, but it still crashes. Now what?

[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'after'
pattern = '''
G.FUNCS.play_cards_from_highlighted = function(e)
'''
payload = '''
-- This is utilized by The Gale.
if (G.GAME.blind.config.blind.key == 'bl_lapsems_gale') and not G.GAME.blind.disabled and (#G.hand.highlighted > 1) then
    G.GAME.blind.triggered = true
    G.GAME.blind:wiggle()
    for i = 1, 3 do
        G.E_MANAGER:add_event(Event({
            func = function()
                delay(0.15)
                G.hand.highlighted:shuffle() -- This is the offending line.
                play_sound('cardSlide1', 0.85)
                print('Whoosh!')
                return true
            end
        }))
    end
    --delay(0.35)
    delay(03.5)
end
'''
frosty rampart
#

did you know that the actual text of the crash is probably helpful for other people to identify the issue :)

vale zinc
#

It only says "attempt to call method 'shuffle' (a nil value)". But how can shuffle() be nil?!

frosty rampart
#

oh because you can't call shuffle on any table, it's specifically on a whole cardarea

#

you have to do it on G.hand, not G.hand.highlighted

wintry solar
#

press windows+shift+s, hold in the top corner of your screen and drag to the opposite bottom corner, press ctrl+v here

#

top tip advice for sharing your crash

vale zinc
rough furnace
frosty rampart
wintry solar
#

there are also some common crashes that experienced people will instantly recognise

vale zinc
#

Code adapted from Death, keeping track of each card's .T.x data, but the play order still doesn't change. What do I do?

[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'after'
pattern = '''
G.FUNCS.play_cards_from_highlighted = function(e)
'''
payload = '''
-- This is utilized by The Gale.
if (G.GAME.blind.config.blind.key == 'bl_lapsems_gale') and not G.GAME.blind.disabled and (#G.hand.highlighted > 1) then
    G.GAME.blind.triggered = true
    G.GAME.blind:wiggle()
    local LAPSEMS_selected_cards = {}
    for i = 1, #G.hand.cards do
        if G.hand.cards[i].highlighted then
            LAPSEMS_selected_cards[#LAPSEMS_selected_cards + 1] = i
        end
    end
    for i = 1, 3 do
        G.E_MANAGER:add_event(Event({
            func = function()
                delay(0.15)
                for j = #LAPSEMS_selected_cards, 2, -1 do
                    copied_LAPSEMS_selected_cards = copy_table(LAPSEMS_selected_cards)
                    local k = table.remove(copied_LAPSEMS_selected_cards, j)
                    local l = pseudorandom_element(copied_LAPSEMS_selected_cards, 'bl_lapsems_gale')
                    G.hand.cards[k], G.hand.cards[l],
                    G.hand.cards[k].T.x, G.hand.cards[l].T.x
                    =
                    G.hand.cards[l], G.hand.cards[k],
                    G.hand.cards[l].T.x, G.hand.cards[k].T.x
                end
                play_sound('cardSlide1', 0.85)
                print('Whoosh!')
                return true
            end
        }))
    end
    delay(0.35)
end
'''
#

It's adapted from what the Death Tarot card uses to determine which selected card is the leftmost in hand, if that's any clarification.

twilit tundra
#

what makes certain consumables show up rarer? is it just having a soul_set or having hidden be true?

red flower
twilit tundra
#

but having both automatically makes it rarer, right?

red flower
vale zinc
hardy vessel
#

How would I set G.GAME variables when a game starts? I don't want it to be reset like Mail and Castle. I might just be overlooking something

frosty rampart
# twilit tundra but having both automatically makes it rarer, right?

the way it's implemented means just thinking about it as making the card rarer is technically wrong
if you set soul_rate to 1, then every card of that consumable type becomes the "hidden" card you're setting up

if you don't want it to be treated like soul/black hole/etc, and just be a regular consumable, consider just making in_pool only return true like 50% of the time or whatever (depending on how rare you want to make it)

red flower
hardy vessel
red flower
hardy vessel
#

Ok, I wasn't understanding how it works exactly, but I think I got it now

Thank you!

round lion
#

would it be considered malware if i opened a site

smoky holly
#

am i required to do math to change the pixel size of a joker?? i cant just like, set it to a different number??

red flower
smoky holly
#

no i mean why is it like

#

why not use the actual printed pixel size of the joker

#

why make it a division

#

is it that hard to say like. 50 or smth

red flower
#

it is a lot more clear when it's the base size modified by another number

#

it would be better if they weren't magic numbers but i didnt feel like changing that

#

if it is like that it's easier to change the size by just modifying the second number

smoky holly
#

this kinda feels less clear because i was under the impression i needed to do this

#

what about the actual pixel size and then a comment appended to it like "base is 95"

red flower
smoky holly
#

i know it returns a number, this makes me think it's gonna read wrong if i DONT do it EXACTLY like this

#

whatever

red flower
#

im sorry this is very basic programming

smoky holly
#

so h is height and w is width

red flower
#

yes

smoky holly
#

im just dumb

red flower
#

then dont get mad at me 😭

smoky holly
#

youre making fun of me!

red flower
#

idk i dont like when people talk about what i did with dismissiveness when they don't know what they're talking about

smoky holly
#

look im aware how division and basic programming works, my brain is so melted in all these different weird ways that smods and balatro work and referencing everything that it didnt cross my mind i didnt need to do it. im sorry

#

like given everything it fully would have made sense in my head to have had to manually calculate the pixel size of a joker from base size because of some bullshit with, card back scaling or whatever. im not thinking clearly and im just generally pissed off

round lion
#

how do i hook into a function in card, do i just dont?

vale zinc
#

Is there anything like update_blind_amounts() that can instead update any changes to a Blind's appearance and boss_colour?

white hull
#

So when making art for the jokers and stuff, are you supposed to draw the 1X version and then scale it up, or draw the 2X version and then scale it down?

#

I see the Aseprite balatro extension has a tool for 1X -> 2X scaling, so it makes me think you need to draw 1X first

#

Haha thanks

red flower
smoky holly
#

is there any efficient way to get a blueprint_effect to return twice?

#

this is what we have but, as you can see from the comment it doesnt exactly work

red flower
#

return SMODS.merge_effects{ ret, ret2 }

#

you want to call blueprint_effect twice even if it is a single card because there might be other effects aside from the return

smoky holly
#

epic, thank you

#

im assuming i cant return ret, ret this way? has to be two separate locals?

loud citrus
#

your past answer helped someone in the future.
absolute hero
(no reply ping, so you might not even see this lol)

daring fern
wind steppe
smoky holly
#

ahh

#

that makes sense

dapper sun
white hull
#

Seems useful

dapper sun
#

ty

vale zinc
#

Is there any function that can be run to update a Boss Blind's appearance and boss_colour? This thing's functionality is already completed, but I want it to turn verdigris-colored if it picks Chips and orange if it picks Mult.

vale zinc
#

Any takers?

#

By my own testing, I ran eval G.GAME.blind.config.blind.boss_colour = HEX('FFAA00'), but the color wouldn't update to bright orange until I headed to the main menu then back into the game.

white hull
#

Speaking out of my ass here lol

vale zinc
#

Draw function? How do I access that?

white hull
#

just Blind:draw() maybe? dunno

vale zinc
white hull
#

Well I have no idea what I'm talking about so fair enough lol

red flower
#

just found this

vale zinc
#

Gee, where?

red flower
#

blind.lua

vale zinc
#

[I] > eval Blind:change_colour(HEX('A00AA'))

white hull
#

ourple...

vale zinc
#

Since it's a Showdown Blind I'm working with, changing the background color isn't so necessary, but I'd still like to know how to do it. Any ideas?

red flower
#

uhh i think the booster packs in vanilla remade use the function to change it

vale zinc
#

[I] > eval ease_background_colour_blind(HEX('FF0000'))

white hull
#

very nice

vale zinc
#

And after this gets sorted out there's still the question of: how do I change the Blind button's appearance, too?

white hull
#

Try ease_background_color{new_colour = G.C.RED}

white hull
#

Nice!

#

Lol I'm impressed with myself for somewhat being able to read Balatro's code now

shell timber
vale zinc
#

And now, I can use this as much as I darn well please! ⭐

LAPSEMS.change_blind_color = function(new_color)
    Blind:change_colour(new_color) -- Blind box
    ease_background_color{new_colour = new_color} -- Background
end
white hull
#

Awesome :)

tidal hemlock
round lion
harsh belfry
vale zinc
harsh belfry
#

talismans "big numbers" cannot be directly compared with normal numbers

tidal hemlock
harsh belfry
tidal hemlock
harsh belfry
#

for every single comparison

#

of two numbers

#

or it explodes when it compares a bignum and a normal num

vale zinc
#

Might this do the trick?

--[[
Cribbed from Minty's Silly Little Mod, apparently for compatibility with Talisman.
--]]
to_big = to_big or function(x)
    return x
end

to_number = to_number or function(x)
    return x
end
white hull
#

Alternatively use Amulet instead of Talisman, which fixes this

white hull
#

So you don't need to use to_big() on every single number in your code

harsh belfry
#

to_big needs to be added in the comparison to begin with

#

and amulet yeah

shell timber
tidal hemlock
#

ok this joker looked worse than i thought

shell timber
#

it just makes the required checks not crash if you dont have talisman

tidal hemlock
#

surprisingly, the balatro font has support for a wide range of symbols/letters

harsh belfry
#

most of them have support

kindred zephyr
#

ooo

kindred zephyr
vale zinc
tidal hemlock
#

ACCIDENTALLY MADE IT SO THAT IT WAS +X1.5 EACH, WOOPS

white hull
#

Lol nice

round lion
#

moved to working on the mod fulltime because roblox went up in flames.

vale zinc
#

And more still that're cross-mod Blinds; there're three for Minty's Slly Little Mod.

tidal hemlock
#

X23.5 on each

#

im playing a run through my own unfinished mod to find all of the early bugs

white hull
#

Alright here's a funny one

#

I have a joker that says a variety of funny phrases during various points of your run

#

And they're all stored in a table in config extra

#

How do I move this into the localization file without it being completely incomprehensible

#

Currently I just return like message = card.ability.extra[math.random(1, 10)] to get a random message from a subset of these

frosty rampart
#

put a bunch of entries in misc -> dictionary in your loc file like so:

misc = {
  dictionary = {
    something_quote_1 = "I'm helping!",
    something_quote_2 = "Yum!",
    ...
  }
}

and then return like message = localize("something_quote_" .. math.random(1, 10))

white hull
#

That should work

#

Could I store a table in misc dictionary though? Then I could do kinda the same thing with just getting a numbered entry from the table

#

Or does it have to be one string per entry

red flower
#

it has to be one per (of course you can save anything to a table in lua but it won't work with vanilla functions)

white hull
#

Yeah I figured

#

Welp I have my work cut out for me lol

frosty rampart
#

yea the localize function won't be able to handle the table properly, which is what you use to get the strings from the localization file

vale zinc
#

I've looked all throughout blind.lua, but nothing I found looks useful for changing a Blind's appearance from one sprite to another. Anyone have any tips for me?

white hull
#

Yeah this works lol

vale zinc
# white hull Yeah this works lol

Here's an unsolicited suggestion: how 'bout you split 'em up into nancy_usefuljoker_scoring_1, nancy_usefuljoker_obtained_1, and so on?

white hull
#

Then I'd have to rewrite the code more and I'm lazy

#

It already has math.random with the correct numbers, so I won't touch it

vale zinc
#

But this way, it'd be easy-peasy to add more quips in the future. Minor rewrite now saves you from a bigger headache later on, was my rationale.

white hull
#

That's a fair suggestion

#

I don't think I'll be adding more to this guy though

#

He's chatty enough :)

tidal hemlock
#

was rerolling a deck for a specific starting legendary joker
there are 2 extra legendaries in this mod (7 total)
i got stanc 3 times in a row

#

1 in 343 chance

#

WHAT

#

WHAT

#

stanc 4 times in a row and counting

white hull
#

I think he likes you~

tidal hemlock
vale zinc
#

Running eval G.GAME.blind.config.blind.pos.y = 1 doesn't change the Blind's appearance until I head to the main menu and then continue the game. What must I do to have it instantly change appearance?

next pivot
#

what's the best way to create a stack of a card in a cardarea vertically?

obsidian spear
#

@lament agate could i ~~steal ~~ borrow your config menu code

obsidian spear
#

tyyy nxkoo ur the best

frosty rampart
harsh belfry
#

mayhaps

frosty rampart
#

true but that's vaguely evil in nature

harsh belfry
#

indeed

#

alternatively hook where blind token sprite is made

#

and assign it to a global

#

that can be accessed by an update function

#

with a nil check ofc

#

if the creation is done inline with the ui it will be annoying though

#

i'd have to check

lament agate
vale zinc
next pivot
#

is it possible to have a ui node inside of a cardarea?

frosty rampart
#

and it involves working with code deeper in the UI and visuals systems of the game than most modders should deal with on a regular basis

twilit tundra
#

how would i make a poker hand intrinsically do things

where playing the hand does something (not attached to a joker or voucher or whatever, its the hand itself that does a thing)

like some of the highest priestess shit (i tried looking but they seem to have a whole hand library system that uh. i dont really want to just rip that out wholesale that seems like way too much compared to what i actually need)

harsh belfry
twilit tundra
#

calculate? no i mean do things when it is played

#

not in terms of what counts as the hand

harsh belfry
#

it was metaphorical referring to the joker calculate

harsh belfry
#

global mod calculate

#

it can just check for the hand and do whatever

#

-# now if this is about cold beans

#

-# please for the love of god

#

-# use the function

random basin
#

everything rn cycles back to this round eval adding tags based on checking the hand

#
              "bm_TwicePureDoubleChi", "bm_OutsideHand", "bm_PureStraight", "bm_HalfFlush", "bm_FullFlush",
              "bm_ThirteenOrphans", "bm_Tsuiisou", "bm_LittleFourWinds", "bm_BigFourWinds", "bm_Junchan"}

SMODS.current_mod.calculate = function(self, context)
    if context.before then
        for i = 1, #yaku do
            if next(context.poker_hands[yaku[i]]) then
                G.E_MANAGER:add_event(Event({
                    func = function()
                        add_tag(Tag(("tag_" .. yaku[i])))
                        play_sound('generic1', 0.9 + math.random() * 0.1, 0.8)
                        play_sound('holo1', 1.2 + math.random() * 0.1, 0.4)
                        return true
                    end
                }))
            end
        end
    end
end```
vale zinc
#

Setting aside the desire for changing Copper Colossus' image, @frosty rampart, might you instead know how to put tooltips onto Boss Blinds as seen in the collection screen, like with card-enhancing Tarot cards? Going with the classic info_queue method in collection_loc_vars() didn't do it for me.

frosty rampart
#

as far as i'm aware it takes custom ui coding. aikoyori's shenanigans does it but it involves basically just manually recreating how the infoqueue system works so that it can be applied to blinds

vale zinc
#

Sounds like it'd be more trouble than it'd be worth for me. But it'd be cool if Steamodded did that by default.

daring fern
#

wild patrol
#

You think a booster pack called temu full of bootleg versions of rare jokers would be a fun idea

torpid flicker
wild patrol
#

Had an idea for blueprint where it fails half the time

#

And likely hood of perishing

#

But they are dirt cheap

obsidian spear
torpid flicker
wild patrol
#

Is it?

obsidian spear
torpid flicker
#

yeah i was playing with a few mods and i saw a similar idea

wild patrol
#

I know the cryptid mod has like a blueprint that has 1/2 chance of working

#

Is it just blueprint or all rare jokers

obsidian spear
#

@wild patrol check yahimod joker.lua 2993 Half-Blueprint

#

it uses repetitions

wild patrol
#

I know spaceman isn't a rare but was gonna make it where had a 1/4 chance to upgrade a random hand instead of the played one

torpid flicker
#

ive also seen something like that somewhere

#

its kinda hard to come up with unique joker ideas

wild patrol
#

Still but u get the idea

#

Temu

#

Cheap booster

torpid flicker
#

yeah

wild patrol
#

Broken jokers

torpid flicker
#

youd have to keep them all common rarity. but make them spoofs of rare and legendary jokers

wild patrol
#

The spaghetti code I made to get this to work tho

#

Still not sure if this is a good concept for a joker

torpid flicker
#

nah its fun

wild patrol
#

Because feeding it Michel seems better than hunting for cavidish for extra

torpid flicker
#

eh its intresting and unique

wild patrol
#

I might look into the temu idea tho

loud citrus
#

how would i detect if the anti contains a showdown blind? (and possibly see what blind that is, i know how to check the blind config and it's key)

wild patrol
#

Is there a good way to make or learn shaders for a beginner

dapper sun
#

use the vanilla shaders as reference

wild patrol
#

wel I kinda wanna makea shader effect for a custom joker edition

#

for temu jokers I wanna give off that holo stank from bootleg tcg cards u get off temu and other chinese seller websites

#

what's the area for spectrals/tarots

dapper sun
#

how do i get if a card's in the collection area

wild patrol
#

G.TAROT?

dapper sun
#

trying to send a link for u but

#

my pc's clipboard has been acting up recently

#

here

#

G.consumeables

wild patrol
#

yeah I see it

#

Appricate it

limber aspen
#

How would I get consumable sell cost

dapper sun
limber aspen
dapper sun
#

Card.sell_cost

limber aspen
#

Doesn't work

dapper sun
#

weird

limber aspen
#

Oh nvm its working

#

Thanks

dapper sun
#

yw

wild patrol
#

local card = create_card('consumables', G.consumeables, nil, nil, nil, nil, 'ttv_thefakesoul')

#

is this correct or am I missing something

#

I get a center nil value error

daring fern
dapper sun
#

ty

daring fern
wild patrol
#

still getting local center nil value

daring fern
wild patrol
#
        if is_on_cooldown() then return end
    if G.STAGE == G.STAGES.RUN and G.consumeables then
        local card = SMODS.add_card({key = 'ttv_thefakesoul'})
        card:add_to_deck()
    end
end```
daring fern
wild patrol
#

yup that was it

#

now if I can figure out how to remove the twitch intergration

#

it would be perfect

#

I added no_mod_badge = true,

#

but didn't seem to work

wild patrol
daring fern
dapper sun
#
local cu_hook = Card.update
function Card:update(dt, ...)
    if self.area and self.area.config.collection and G.GAME.banned_keys[self.config.center_key] then
        print("hook!")
        self.children.center:draw_shader('debuff', nil, self.ARGS.send_to_shader)
    end
    cu_hook(self, dt, ...)
end```
#

why isn't it adding the shader

daring fern
dapper sun
#

ah ty

winter flower
#

how do i debuff a pool of jokers
-# more specifically on a stake too

wild patrol
#

I made a test shader to replace the background menu with I see hwo to add the shader but how woudl I got about replacing the background it with

#

looking for references in the main game but can'e seem to find it

#

nvm I believe I found it

#
        shader = 'background',
        send = {
            {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL_SHADER'},
            {name = 'spin_time', ref_table = G.TIMERS, ref_value = 'BACKGROUND'},
            {name = 'colour_1', ref_table = G.C.BACKGROUND, ref_value = 'C'},
            {name = 'colour_2', ref_table = G.C.BACKGROUND, ref_value = 'L'},
            {name = 'colour_3', ref_table = G.C.BACKGROUND, ref_value = 'D'},
            {name = 'contrast', ref_table = G.C.BACKGROUND, ref_value = 'contrast'},
            {name = 'spin_amount', ref_table = G.ARGS.spin, ref_value = 'amount'}
        }}})```
wild patrol
#

trying to use a lovely patch to change the colour values

#

but I can't seem to get it to work

slim ferry
#

this is supposed to check if the total amount of hand levels above 1 is greater than the number of highlighted cards, yet it always seems to be off by one and requiring 1 extra level on top. what could cause this?

#

wait

#

im stupid

#

nvm

wild patrol
#

I tried swaping the colour values around to doesn't seem to change anything either

#

I know the patch sorta works because if I cahnge the background sharder to the custom one I made it crashes the game

elder rune
#

how do you create a tag

dapper sun
#

add_tag(Tag('key'))

elder rune
#

thx

dapper sun
#

that took me 20 seconds to find through vanillaremade

elder rune
#

I entirely forgot about vanillaremade okay

lyric wadi
#

im trying to make a joker unlock condition and from my testing it's not unlocking

#

here's the bit i wrote last night, using_customable is a custom unlock arg type that i've just got being called anytime a consumable is used in a different file

red flower
#

did you try returning true instead of unlock_card

lyric wadi
#

i tried both

red flower
#

does it enter either if condition

lyric wadi
#

it should but i havent run a full debug

red flower
#

i think you should do that before asking imo

#

always good to have a couple prints

lyric wadi
#

progression is a mistake

#

i should just resign and be another yahimod

slim ferry
#

is there a way to tell how many times a given card has been played? i recall hearing that that was still left over from when the magnet vouchers were a thing

#

nvm im just making my own variable

primal robin
tight pumice
#

Anyone know how mods add those little credits for people’s ideas/art on a joker?

slim ferry
#

they steal from cryptid

#

usually

red flower
#

you can also just add them as an info queue

granite raptor
#

i'm reading the SMODS api documentation but i can't seem to find info on method parameters and what they do, nor can i find information on global functions like ease_ante(), are they on that github wiki or do i have to just keep referencing vanillaremade and reverse engineer?

wintry solar
#

Most of the global functions you are thinking of are vanilla functions that are rarely documented on the smods wiki, most smods functions themselves are either buried somewhere on the wiki/in update posts, or have reasonably informative lsp definitions

dapper sun
#

anyone know why this is triggering twice

calculate = function(self,card,context)
    if context.joker_main then
        return {
            mult = card.ability.extra.mult
        }
    end
    if context.joker_type_destroyed and not context.blueprint then
        print(inspect(context))
        card.ability.extra.mult = card.ability.extra.mult - card.ability.extra.smult
        local dest = card.ability.extra.mult <= 0
        
        return {
            message = dest and "Consumed!" or "Defended!",
            func = dest and function() SMODS.destroy_cards(card) end,
            no_destroy = dest
        }
    end
end```
frosty rampart
#

i figure it might still be calculating when it destroys itself? (assuming you mean the joker destruction effect is triggering twice)

dapper sun
#

the print is running twice