#💻・modding-dev

1 messages · Page 660 of 1

stoic void
#

have a look at this maybe

#

it is all of balatro as a mod

cerulean aspen
#

anyone know why this dosent worK?

#

@daring fern if you know whats wrong with it

daring fern
cerulean aspen
past kelp
#

vanlla remade is slightly different than the version i am using

stoic void
past kelp
#

the way everything iis alligned when i put it into my code

#
    name = "Jokerless",
    id = 'c_jokerless_1',
    rules = {
        custom = {
            {id = 'no_shop_jokers'},
        },
        modifiers = {
        }
    },
    jokers = {
        {id = 'j_canio'},
        {id = 'j_triboulet'},
        {id = 'j_yorick'},
        {id = 'j_chicot'},
        {id = 'j_perkeo'},
    },
    consumeables = {
    },
    vouchers = {
    },
    deck = {
        type = 'Challenge Deck'
    },
    restrictions = {
        banned_cards = { 
        },
        },
        banned_tags = {
        },
        banned_other = {
        }
    } ```
#

the error wo't copy

stoic void
past kelp
#

oh ii thought i rechanged it

#

oh i copied the wrong code

#
        name = "Jokerless",
        id = 'c_jokerless_1',
        rules = {
            custom = {
                {id = 'no_shop_jokers'},
            },
            modifiers = {
            }
        },
        jokers = {
            {id = 'j_caino'},
            {id = 'j_triboulet'},
            {id = 'j_yorick'},
            {id = 'j_chicot'},
            {id = 'j_perkeo'},
        },
        consumeables = {
        },
        vouchers = {
        },
        deck = {
            type = 'Challenge Deck'
        },
        restrictions = {
            banned_cards = { 
            },
            },
            banned_tags = {
            },
            banned_other = {
            }
        }
    } 
}  ```
stoic void
#

before what is sent on the message

past kelp
#

yes the other challenges are berfore it

stoic void
#

can you screenshot the top off the code

#

for the jokerless

#

I just wanna be extra sure on something

past kelp
stoic void
# past kelp

so this is you trying to change a challenge to get all legendaries?

#

right?

past kelp
#

yes

stoic void
#

what code do you have to replace the code of the existing challenge?

past kelp
#

what do you mean

#

i replaced jokerless as a challenge

stoic void
#
SMODS.Challenge:take_ownership('jokerless', {
{
        name = "Jokerless",
        id = 'c_jokerless_1',
        rules = {
            custom = {
                {id = 'no_shop_jokers'},
            },
            modifiers = {
            }
        },
        jokers = {
            {id = 'j_caino'},
            {id = 'j_triboulet'},
            {id = 'j_yorick'},
            {id = 'j_chicot'},
            {id = 'j_perkeo'},
        },
        consumeables = {
        },
        vouchers = {
        },
        deck = {
            type = 'Challenge Deck'
        },
        restrictions = {
            banned_cards = { 
            },
            },
            banned_tags = {
            },
            banned_other = {
            }
        }
    } 
}, true)
#

I wanna like look at this

#

at the top it says it will replace the existing jokerless challenge

past kelp
#

Should i put this n and try it

stoic void
#

maybe?

#

-# I'm not sure if this WILL work, but I hope it does

past kelp
#

hold on let me just restart this mod because itcnat open no matter what i do

#

ok i have a normal balatro now

sleek valley
#

what would be the if statement to check if a card already has a seal(any kind) on it?

#

like if a joker wants to apply a seal, i dont want that seal replacing the one that's already there

past kelp
#

One last thing does anyone know how to add new pages to the challenge menu

wintry solar
#

they are automatically added when you add more challenges

past kelp
#

oh cool

#

I probaly added a challenge wrong last time

sleek valley
slim ferry
#

put the drawstep stuff into soul_pos.draw but replace G.shared_soul with card.children.floating_sprite

#

And remove the draw_major thing

#

And then remove the drawstep itself ofc

stoic void
#

"put the drawstep stuff into soul_pos.draw"

#

wha

#

sorry my brain isnt braining right now

dapper sun
#

soul_pos.draw

#

soul_pos = {x = 0, y = 0, draw = function(card, scale_mod, rotate_mod) end}

stoic void
#

ah

#

yay it works!

#

aw man

#

It dosent work when I make it trans

#

this is what I mean

#

when I use the malverk texture pack

past kelp
#

I swear I thought you were just using a modding term

stoic void
#

it dosent do the bouncy thing anymore

stoic void
sleek valley
stoic void
#

😭 It sounds kinda wrong without the message below

stoic void
#

WHAT DO YOU MEAN "SADLY" ? 😭

past kelp
#

I thought like a transitiion

#

or something

sleek valley
stoic void
#

ok 😭

past kelp
#

what part of the code would tarot card effects be in

wintry solar
#

malverk doesn't have custom draw functions for textures

stoic void
#

aw shucks

daring fern
viscid talon
#
SMODS.Joker({
    key = "sciencelab",
    config = { extra = { odds = 4, retriggers = 2 } },
    loc_txt = {
        ["name"] = "Science Lab",
        ["text"] = {
            {
            [1] = "Played hand has a {C:green}#1# in #2#{}",
            [2] = "chance to retrigger cards twice.",
            [3] = "If successful, {C:attention}destroy{} this Joker",
            }
        },
    },
    pos = { x = 9, y = 5 },
    cost = 5,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_hatch_sciencelab')
        return { vars = { numerator, denominator, card.ability.extra.repetitions } }
    end,

    calculate = function(self, card, context)
        if context.repetition and card.should_retrigger then
            return { repetitions = card.ability.extra.repetitions }
        end
        if context.main_scoring and context.cardarea == G.play then
                card.should_retrigger = false
            if SMODS.pseudorandom_probability(card, 'j_hatch_Sciencelab', 1, card.ability.extra.odds, 'j_hatch_sciencelab') then
                card.should_retrigger = true
            card.ability.extra.repetitions = 2
            end
            
            G.E_MANAGER:add_event(Event({
                func = function()
                    card:start_dissolve()
                    return true
                end
            }))
        end
    end
})
#

idk what im doing wrong

#

but its not doing anything

daring fern
viscid talon
#

gulp

#

what do i do instead

daring fern
viscid talon
#

ok i did that

#

it still doesnt do anything

#

it should be retriggering all played cards twice and then killing itself

#

nvm i think i figured it out

#

ok i fixed it

#

i decided to frankenstein some code together

sleek valley
#

well at least it works
if you ever want to, you can come back and make it cleaner later

viscid talon
#
SMODS.Joker({
    key = "sciencelab",
    config = { extra = { odds = 4, hands_left = 1 } },
    loc_txt = {
        ["name"] = "Science Lab",
        ["text"] = {
            {
            [1] = "Played hand has a {C:green}#1# in #2#{}",
            [2] = "chance to retrigger cards twice.",
            [3] = "If successful, {C:attention}destroy{} this Joker",
            }
        },
    },
    pos = { x = 9, y = 5 },
    cost = 5,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, card.ability.extra.hands_left, 'j_hatch_sciencelab')
        return { vars = { numerator, denominator, card.ability.extra.repetitions } }
    end,

    calculate = function(self, card, context)
        if context.repetition and context.cardarea == G.play and SMODS.pseudorandom_probability(card, 'j_hatch_sciencelab', 1, card.ability.extra.odds) then
            return {
                repetitions = 2
            }
        end
        if context.after and SMODS.pseudorandom_probability(card, 'j_hatch_sciencelab', 1, card.ability.extra.odds) then
            SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = "Destroyed!"
                }
        end
    end
})```
#

the current code

#

not too shabby if i do say so myself c:

wintry solar
#

that doesn't do what you want it to do

#

this gives each scored card a separate 1 in 4 chance to be retriggered twice, and then the joker a separate 1 in 4 chance to be destroyed

sleek valley
#

question is, do they want it to go through the whole hand before self destruct, or self destruct the moment even a single card retriggers?

#

either way, you'd need to remove the second pseudorandom_probability

wild patrol
#

concepting another joker

#

what do you think

#

trying to make some jokers that can help defend from chat commands

primal robin
#

is your mod on github

wild patrol
#

private rn until it;s finish

#

not ready to be played at all lol

sleek valley
# wild patrol

is it going to destroy itself after it's out of protections?

wild patrol
#

probably not

sleek valley
#

i'd reccomend it does tbh, just for it to be clear to the player that they're vulnerable again lol
other than that, it's neat :3

granite raptor
#

how would i generate a random joker that is compatible with a certain sticker (perishable, in this case?) i don't need the joker to actually have said sticker, just not generate jokers like ride the bus, square, etc

wild patrol
sleek valley
#

understandable

primal robin
#

All I'm curious is how you connect to twitch via socket

viscid talon
#

im also currently trying to figure out how to have a joker create a random tag

wild patrol
#

from twitch

#

cause when u open balatro and click connect opens authorization page to link your twitch account

wintry solar
# viscid talon how do i fix it

context.before check your chance and set an internal flag
context.repetition check for flag and send repetitions
context.after check for flag and destroy

sleek valley
# viscid talon how do i fix it

simply remove the second pseudorandom_probability above the joker destruction

if context.after then
            SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = "Destroyed!"
                }
        end
    end
})
primal robin
wild patrol
#

Originally it was based off ur twitch blind mod

#

I dunno what they changed

#

since they are a lot smarter than me when it comes to this i'm just concepting jokers and making some commands lol

viscid talon
#

also how do i have a joker make a random tag

primal robin
#

I see, makes sense

viscid talon
#
local tag_pool = get_current_pool('Tag')
local selected_tag = pseudorandom_element(tag_pool, 'modprefix_seed')
local it = 1
while selected_tag == 'UNAVAILABLE' do
    it = it + 1
    selected_tag = pseudorandom_element(tag_pool, 'modprefix_seed_resample'..it)
end

?

#

ok idk why it did that

daring fern
viscid talon
#

oke

wintry solar
#

that function will break seeding fyi

daring fern
wintry solar
#

oh true I am blind nvm

sage crater
#

bump

slim ferry
#

In what sense?

#

Oh i see

#

Im pretty sure card.sort_id is what youre looking for

#

Since that is unique per card and increases per card created

sage crater
#

hell yeah

#

thank ya kindly

#

how do I add something to a table that is already constructed?

slim ferry
#

im assuming you mean appending to a number indexed table?

#

Which would be table[#table+1] = x

rough furnace
#

They should be able to hook SMODS.restart_game. I originally planned to make a system to aid in shutting down threads but I had to reduce scope due to time constraints. It likely will come later. Also sorry I haven't had time to look at handy, how's it going

slim ferry
#

or use table.insert

primal robin
#

About archives is low priority so no progress for now

tidal hemlock
sage crater
slim ferry
#

joker.soul_pos = ...

sage crater
#

suite

slim ferry
#

joker being whatever table neds that

sage crater
#

would that be like j_modID_jokerName or something

slim ferry
#

huh

sage crater
#

oh nvm, it looks like the key is all it needs

slim ferry
#

what are you actually doing

sage crater
#

I figured it out

slim ferry
#

You could also

red flower
#

why does your joker contructor use positional arguments..

slim ferry
#

let that function do soul_pos

wintry solar
#

wtf is this code

slim ferry
#

And also that looks like torture coding

sage crater
slim ferry
#

What do you mean

#

nil is the absence of a value

sage crater
#

no other joker would need a soul_pos

slim ferry
sage crater
#

yes

slim ferry
#

so

#

Whats the problem

#

It wont exist on jokers that dont use soul_pos

sage crater
#

I'd have to write nil 20 times, versus writing soul_pos once

primal robin
#

I do believe this guy is python dev

sage crater
#

oh boy

#

am I doing something very bad by lua standards

#

I'm used to Python, Java, and c#

slim ferry
#

Why are you using a wierd function to begin with

primal robin
#

ez

red flower
# sage crater wdym

why is it function(key, set, pos, rarity, config, info_queue, calculate) this looks like a nightmare

sage crater
wintry solar
#

but why

primal robin
#

that' actually crazy

sage crater
#

damn 😔

wintry solar
#

we stopped writing like this after 0.9.8 because it was silly

red flower
#

python has named arguments

sage crater
wintry solar
#

the order isn't the problem

sage crater
#

oh

wintry solar
#

why do you use a constructor function that requires you fill out arguments in a specific order (that doesn't even include all the options) to generate a table to feed into SMODS.Joker instead of writing the table yourself?

sage crater
#

what am I doing wrong? I'm not used to lua 😅

viscid talon
#
        return { vars = { card.ability.extra.mult, card.ability.extra.dollars, card.ability.extra.mult_gain } }
    end,

    calculate = function(self, card, context)
        if context.end_of_round and context.game_over == false and not context.blueprint then
            return {
                card.ability.extra.mult == card.ability.extra.mult + card.ability.extra.mult_gain,
                dollars = card.ability.extra.dollars * -1
            }
        end
        if context.joker_main then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
})```
viscid talon
#

why isnt my joker gaining mult

#

it loses money fine, but it isnt gaining mult

red flower
tranquil cypress
sage crater
# red flower

well- ok, I know that's an option, but making a constructor function saves me a decent amount of time having to rewrite all the variable names

viscid talon
#

oo

wintry solar
#

apart from it being hyper restrictive

primal robin
#

I mean, global replace

sage crater
#

alright fine, I'll go back to how it was before 😔

wintry solar
#

I mean you can do it however you like

#

it's just the way you have chosen makes it harder to do imo

red flower
#

also if you have lsp you can use autocomplete to save time or vscode snippets or copypasting

viscid talon
#

oke i made it work

cedar bronze
#

would like some help to know if im overcomplicating this
the pitch is an enhancement that, when held in hand, retriggers a random scoring card
i tried experimenting a bit but couldn't seem to make it work from within the smods section? i think because of when the held in hand cards are usually checked

is there an easier way to tell a card it needs to retrigger when the source is a card held in hand than messing with eval_card manually?

daring fern
cedar bronze
#

how do you mean? adding it into the enhancements calculate? it didnt seem to retrigger it when i tried that, im assuming because the held in hand cards arent usually checked then

#

will tinker with it again and come back if it doesnt work lmao

daring fern
cedar bronze
#

ooooh didnt know that existed, will try messing w that

cedar bronze
# daring fern No, `SMODS.current_mod.calculate`

got this working! but only for the first card causing the effect
i know i could just cause it to retrigger as many times as it should, but i'd really like to make each mirror card do the "again!" pop up individually, is there a good way to do that?

#

(note the first variable used to say sources before i was tinkering more so thats not the cause lol)

wintry solar
#

your for loop doesn't loop because of the return

cedar bronze
#

i imagined that was the case but not sure how to make it work

wintry solar
#

you need to use SMODS.merge_effects

cedar bronze
#

is there a good place to find out how to use that? not sure where i'd look on the wiki

#

oh wait maybe found it in utility

#

thank you! yippee

quick scarab
#

Quick question, I'm trying to make an unlock condition for my cards where you have to discover a certain amount of a custom consumable. I checked to see if it tracks automatically, and I can just call over, and it doesn't seem like it. Do I have to create a custom one on the code? and how would I do that?

wintry solar
#

check G.DISCOVER_TALLIES

past kelp
#

Does anyone know how to make every card in a deck debuffed as a challenge deck

sage crater
#

before, it wouldn't collapse correctly

fading rivet
#

How could I modify the amount of xmult an individual glass card gives?
I figured out how to change the display but it doesn't seem to change the amount given

fading rivet
#

no I did this

#
--- Lost Media
SMODS.Joker{
    key = "lostmedia",
    atlas = "jokers",
    pos = {x=6,y=0},
    rarity = 2,
    cost = 6,
    pools = {["Song"] = true, ["MonochroMenace"] = true},
    config = {
        extra = {
            inc = 1
        }
    },
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS.m_glass
        return {vars = {card.ability.extra.inc}}
    end,
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and context.other_card then
            if SMODS.has_enhancement(context.other_card, "m_glass") then
                SMODS.scale_card(context.other_card, {
                    ref_table = context.other_card.ability,
                    ref_value = "foobar_numerator",
                    scalar_table = card.ability.extra,
                    scalar_value = "inc",
                    no_message = true,
                    operation = function(ref_table, ref_value, initial, change)
                        ref_table[ref_value] = (initial or 1) + change
                    end
                })
                SMODS.scale_card(context.other_card, {
                    ref_table = context.other_card.ability,
                    ref_value = "Xmult",
                    scalar_table = card.ability.extra,
                    scalar_value = "inc",
                    scaling_message = {
                        message = "Tap the glass..."
                    }
                })
                SMODS.scale_card(context.other_card, {
                    ref_table = context.other_card.ability,
                    ref_value = "extra",
                    scalar_table = card.ability.extra,
                    scalar_value = "inc",
                    no_message = true
                })
            end
        end
    end
}
sage crater
#

oic, it's in a joker

daring fern
fading rivet
daring fern
fading rivet
#

ah

#

that still doens't explain why its not working for normal glass cards though

sage crater
fading rivet
#

its right above

fading rivet
#

it displays properly but is only giving x2

sage crater
#

did you edit this code since learning you need to use the context somethingcom pointed out?

fading rivet
#

since this is a regular glass card

#

the conditional is triggering to increase the stats

#

but the stats don't seem to be actually increasing

#

display visually showing as such

wintry solar
#

glass cards have two different xmult values

sage crater
#

oh, you're using scale_card. I see

#

that seems like not the best option

fading rivet
fading rivet
wintry solar
#

card.ability.x_mult and card.ability.Xmult

fading rivet
#

is x_mult the calculated and Xmult visual?

wintry solar
#

either that or the reverse, yes

fading rivet
#

ight thx

quick scarab
wintry solar
#

it's automatic

quick scarab
#

ok so I just make a var or something

fading rivet
#

yay that fixed it

#

thx

hidden aspen
#

i've read this page but i didnt get it at all

#

where should the UI code be written?

#

i can see that there are ways to make a table but i dont get where to send it

past kelp
#

I want to change strength's effect to lower rank of 2 cards how would I do that

wild patrol
#

probably just look how strength does it and just reverse it

past kelp
#

I cant find tarot card effects in the code

red flower
wild patrol
#

line 676

#

strength

past kelp
#

i can't find tarot.lua iin my actual balatro copy

dapper sun
#

?

#

bc there is no tarot.lua??

#

vanillaremade is vanilla content remade with smods functions

#

you're expected to reference the repo, not try and find the vanilla counterpart in the source code

past kelp
#

oh

#

I hoestly have been modding the source code all day

wild patrol
#

I mean

#

Technically you can

#

But smods provides more to work with

gusty pumice
#

Is there an action in a function to skip to the end of round payout after selecting a blind?

dapper sun
gusty pumice
dapper sun
#

you could just set your score to the blind requirements

gusty pumice
#

either or, I just dunno how to do either lol-

past kelp
dapper sun
gusty pumice
#

Thank you very much!

quick scarab
# wintry solar it's automatic

It didn't work

locked_loc_vars = function(self, info_queue, card)
        return { vars = { 4 } }
    end,
    check_for_unlock = function(self, args) -- equivalent to `unlock_condition = { type = 'discover_amount', tarot_count = 22 }`
        return args.type == 'discover_amount' and #G.P_CENTER_POOLS.fnaf_item <= G.DISCOVER_TALLIES.fnaf_item.tally
    end
gusty pumice
hidden aspen
dapper sun
red flower
red flower
# red flower you would call the function that creates the uibox at the appropriate moment

i dont have many good examples but i have this for when you press a button on a joker (the button is defined elsewhere but it has button = "joy_perform_summon")
https://github.com/nh6574/JoyousSpring/blob/16557e58b2db9315a2d767524877e380edf3c2a2/src/summon.lua#L1106

GitHub

Yu-Gi-Oh! Mod for Balatro. Contribute to nh6574/JoyousSpring development by creating an account on GitHub.

gusty pumice
# dapper sun try putting it in an event

so something like this?

calculate = function(self,card,context)
        if context.setting_blind and (G.GAME.blind:get_type() == 'Boss') then
            G.E_MANAGER:add_event(Event({
                func = function()
                    G.GAME.chips = G.GAME.blind.chips
                    G.STATE = G.STATES.HAND_PLAYED
                    G.STATE_COMPLETE = true
                    end_round()
                    SMODS.destroy_cards(card, nil, nil, true)
                    return true
                end
            }))
        end
    end
dapper sun
#

maybe put the destroy_cards before

wintry solar
quick scarab
# wintry solar probably timing issue, make sure the tables exist first

tried to make a function file to see if it works but it didn't

function fnaf_set_discover_tallies()
  G.DISCOVER_TALLIES = G.DISCOVER_TALLIES or {
      fnaf_item = {tally = 0, of = 0},
    }
  for _, v in pairs(G.DISCOVER_TALLIES) do
      v.tally = 0
      v.of = 0
  end
  
  for _, v in pairs(G.P_CENTERS) do
    if not v.omit then
      if v.set and v.set == 'fnaf_item' then
        G.DISCOVER_TALLIES.fnaf_item.of = G.DISCOVER_TALLIES.fnaf_item.of+1
        if v.discovered then 
            G.DISCOVER_TALLIES.fnaf_item.tally = G.DISCOVER_TALLIES.fnaf_item.tally+1
        end
      end
    end
  end

  if check_for_unlock then check_for_unlock({type = 'discover_amount',
        fnaf_item_count = G.DISCOVER_TALLIES.fnaf_item.tally})
  end
end
wintry solar
#

you don't need to set them yourself

gusty pumice
dapper sun
#

ah ok

#

still, i dunno

#

when are you calling it

#

wait i'm blind

#

i see

#

yea i dunno, sorry

gusty pumice
#

No worries!

wintry solar
#

change to context.hand_drawn

quick scarab
# wintry solar you don't need to set them yourself

Ok I tried another thing but it didn't work as well

check_for_unlock = function(self, args) -- equivalent to `unlock_condition = { type = 'discover_amount', tarot_count = 22 }`
    return args.type == 'discover_amount' and #G.P_CENTER_POOLS.fnaf_item <= 4
end```
gusty pumice
#

Is it possible to put a drawn hand back into the deck?

wild patrol
#

Probably

wintry solar
#
if context.hand_drawn and G.GAME.blind:get_type() == 'Boss' then
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.chips = G.GAME.blind.chips
                G.STATE = G.STATES.HAND_PLAYED
                G.STATE_COMPLETE = true
                end_round()
                return true
            end
        }))
    end

this 100% works

gusty pumice
#

huh, wonder what I was doing wrong then

#

worked for me too

#

Thank you!!

wild patrol
#

is there away to use a trigger to increase the spawn rate of a boosterpack

daring fern
quick scarab
# quick scarab Ok I tried another thing but it didn't work as well ```lua check_for_unlock = fu...

And it crashes, anyone knows how to tally discovered custom consumables?, I trying to make a unlock condition

SMODS.Joker {
    key = "cassie",
    atlas = 'Joker',
    pos = { x = 3, y = 2 },
    blueprint_compat = true,
    unlocked = false,
    rarity = 2,
    cost = 4,
    config = { extra = { odds = 4 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { G.GAME.probabilities.normal or 1, card.ability.extra.odds } }
    end,
    calculate = function(self, card, context)
        if context.using_consumeable and not context.blueprint and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit
        and context.consumeable.ability.set == 'fnaf_item' and (pseudorandom('fnaf_cassie') < G.GAME.probabilities.normal / card.ability.extra.odds) then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                    SMODS.add_card {
                        set = 'fnaf_item',
                        key_append = 'fnaf_cassie_item'
                    }
                    G.GAME.consumeable_buffer = 0
                    return true
                end)
            }))
            return {
                message = "+1 Item",
                colour = G.C.GREEN,
            }

        end
    end,
    locked_loc_vars = function(self, info_queue, card)
        return { vars = { 4 } }
    end,
    check_for_unlock = function(self, args) -- equivalent to `unlock_condition = { type = 'discover_amount', tarot_count = 22 }`
        return args.type == 'discover_amount' and #G.P_CENTER_POOLS.fnaf_item <= G.DISCOVER_TALLIES.fnaf_item.tally
    end
}```
fading rivet
#

is there an easyish way to apply a full screen shader?

daring fern
fading rivet
#

or is there another alternative

red flower
#

the alternative would be porting that system but I'll recommend waiting

#

it's probably in one or two weeks hopefully

fading rivet
red flower
#

you can use the dev version to work on it

fading rivet
#

do I just clone the current commit of smods instead of using releases?

mystic river
#

big green code button, yes

fading rivet
#

thx

wild patrol
fading rivet
#

okay downloaded it

#

is there documentation somewhere for SMODS.ScreenShader

umbral zodiac
#

hi i made screenshader

#

the docs are unmerged atm as far as im aware

fading rivet
#

oh rip

#

what would I need to do to apply a shader whenever you have a specific joker then?

umbral zodiac
#
should_apply = function(self)
  return next(SMODS.find_card(key))
end,
``` in your screenshader def
fading rivet
#

shader def would be

SMODS.ScreenShader{
  key = 'menaceshader',
  atlas = 'shaders',
  should_apply ...
}
#

or something else?

umbral zodiac
#

not atlas?

wild patrol
#
        return SMODS.Boosters.twitch_pack_1 * self.weight
    end,```
umbral zodiac
#

for screenshader there are two ways to specify what shader it pulls from

wild patrol
#

would this be right

umbral zodiac
#

either you define the shader earlier like:

SMODS.Shader {
  key = "a",
  path = "a.fs",
}

SMODS.ScreenShader {
  key = "a",
  shader = "modprefix_a",
}
#

or you give it the path to the shader like:

SMODS.ScreenShader {
  key = "a",
  path = "a.fs",
}
fading rivet
#

ah thx

daring fern
wild patrol
#

I see how to do overrall boosters

#

but not just specific booster pack

#

or is it just as simple as putting the key in there

random basin
#

is there a way to have ui transition into view instead of instantly spawn in an overlay?

umbral zodiac
#

this means there was an invalid file name for your shader

#

shaders aren't images

fading rivet
#

oh

#

what are they?

umbral zodiac
#

shaders are pieces of code which run on the GPU used for quickly modifying the visuals of something

fading rivet
#

fahlksdfoa8 whiekf ahuifesd

#

time to learn another lanaugae yay

#

whats the script type?

umbral zodiac
#

its GLSL* but the file extension is .fs for some reason
-# *not really, but it's very very similar

fading rivet
#

thx

umbral zodiac
#

there are plenty of guides to shaders you can find on the smods wiki

sleek valley
#

does anyone know a good way for a joker to check for multiple specific hands, including hidden ones?
the joker im tryna make rn is basically just a better Droll joker

wild patrol
#

I can't get the weight of the custom booster pack

#

in the get_weight function to work

#

is it not supported for doing a specific pack

fading rivet
frosty rampart
sleek valley
#

oohhhhh i did not notice that

frosty rampart
#

this is how droll joker works (card.ability.extra.type = "Flush" in the joker)

sleek valley
#

i kinda assumed that was looking for specifically just flush

#

but it does make my life easier

frosty rampart
#

yea no all the handtype jokers are "contains" stuff. so the pair jokers work with 5oaks and full houses and even a flush if that flush happens to also contain a pair

umbral zodiac
#

you must have the vertex function tho, otherwise itll crash

wild patrol
#

get_weight = function(self)
return mod.Booster.twitch_pack_1.weight * self.weight + 8
end,

#

probably doing this wrong but I just wanna see if i'm on the right track

fading rivet
#

wiat whats that

#

all I see is effect

#

this is what I got rn and its crashing

umbral zodiac
#

like this ```
#ifdef VERTEX
vec4 position(mat4 transform_projection,vec4 vertex_position)
{
return transform_projection*vertex_position;
}
#endif

#

make sure you have that function at the end

fading rivet
#

ah thx

#

still crashed ;-;

#

same as before

#

bad argument to apply patches

#

wait i

#

wait i'm stupid

#

the shaders folder is in the 1x fodler

umbral zodiac
#

seems problematic 😭

#

put them in assets/shaders/

fading rivet
#

buh it still crashed

wild patrol
#

I can get the rates for everything but booster

fading rivet
#
#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
    #define PRECISION highp
#else
    #define PRECISION mediump
#endif

extern PRECISION vec2 menace

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

    vec3 purple_tint = vec3(0.6 + (meance.y * 0.000001), 0.2, 0.8 + (meance.x * 0.000001));
        
    pixel_color.rgb = mix(pixel_color.rgb, purple_tint, 0.2);

    return pixel_color * color;
}

#ifdef VERTEX
vec4 position(mat4 transform_projection,vec4 vertex_position)
{
    return transform_projection*vertex_position;
}
#endif
#

oh wait ik why

#

more stupids

dapper sun
#

you say meance in the purple_tint vector

fading rivet
#

okay it actually read the file this time

fading rivet
dapper sun
#

yw

fading rivet
#

okay the game runs now

#

I was also missinga semicolon lol

dapper sun
#

that would do it lol

fading rivet
frosty rampart
#

ooo are you messing around with screenshader

fading rivet
#

si

umbral zodiac
#

screenshadre 🧡

#

the heart is orange like one of my ears

fading rivet
#

someone in the teto server suggested making menace tint your screen purple

#

so we did a bit of a sidequest

frosty rampart
#

i really wanna come up with a use for screenshader in one of my mods at some point

fading rivet
#

and now I know a little of GLSL

fading rivet
#

never touching this again 🔥 ( I hope)

frosty rampart
umbral zodiac
#

honestly

#

i had an idea for something that could go aloongside screenshader

#

which would distort your effective mouse position to the game

#

but that does not feel like an smods api thing

#

and its not like i need it for anyhting

peak void
#

is it possible to use a joker pool with :set_ability?

umbral zodiac
#

wow is that another lily

peak void
#

as in - i want to set a joker's ability to a random rare joker, for instance

#

hi yeah im lily

umbral zodiac
#

let me see

peak void
#

yeah thats true. i guess what im asking is like. how do i pull a random joker from the pool

#

ideally one that has been discovered

#

or. unlocked?

umbral zodiac
#

you may have to manually find a card within the pool

peak void
#

is there like. a way to get an array that is equivalent to the cards in the pool lol

#

its probably in the smods documentation

umbral zodiac
#

get_current_pool(set, rarity)

#

in this case get_current_pool("Joker", "Rare") would work

peak void
#

oh nice

umbral zodiac
#

note that this will not be a list of all available ones

#

but just all ones, with ones that arent available being "UNAVAILABLE" rather than their joker key

peak void
#

alright. good to know

frosty rampart
#

so from there you'll probably have a loop that uses pseudorandom_element to get a random element from that pool, and repeating until the result isn't "UNAVAILABLE"

umbral zodiac
#

i would say that

#

you dont necessarily need that

wild patrol
umbral zodiac
#

you usually do that in order for parity with vanilla but if youre just picking a random rare joker outside of the shop from another joker then its fine if you do a non loop approach

frosty rampart
#

true you could just go over that table and remove all the unavailables first

umbral zodiac
#

unless i need it to be identical to vanilla shop order style i usually would remove unavailables first because frankly

peak void
#

yeah that's my approach i'll just filter unavailable elements

umbral zodiac
#

i do not feel comfortable with while loops that have no consistent runtime

peak void
#
local _pool = get_current_pool("Joker", "Rare")
local _sanitized_pool = {}
for index, value in ipairs(_pool) do
    if(_pool[index] ~= 'UNAVAILABLE') then
        _sanitized_pool[#_sanitized_pool+1] = value
    end
end
local _new_joker = pseudorandom_element(_sanitized_pool, 'frozen')
card:set_ability(_new_joker)

like this

umbral zodiac
#

looks good

wintry crater
#

how would i make this have a 1/2 chance to fail like how wheel of fortune has the chance to fail? i looked at the code for wheel of fortune but i dont really understand it

wild patrol
#

I guess i'll make a skip for creating a twitch booster pack

#

because I can't get the get_weight to work

peak void
red flower
true jasper
#

when i take ownership of the planet consumable type it makes 2 planet tabs in the collection and I don't know how to fix that

gusty pumice
#

whats the thingy to look at the current hand type being played? G.GAME. something I'm guessing?

red flower
gusty pumice
# red flower where

not the if statement, trying to set a variable to the hand currently played

red flower
#

where

#

in what function? calculate?

gusty pumice
#

yes

red flower
#

context.scoring_name

gusty pumice
#

thank you thank you

true jasper
red flower
#

ah hmm

#

idk

#

smods would need to implement the vanilla consumable types for it to work i think

frosty rampart
gusty pumice
# gusty pumice thank you thank you

well, it's the other part that's getting weird now
How would I go about leveling up the final hand played if it wins a blind? I've gotten to about here

if context.press_play then
    card.ability.extra.hand_type = context.scoring_name
end
if context.after and G.GAME.chips >= G.GAME.blind.chips  then
frosty rampart
true jasper
frosty rampart
red flower
#

its probably that

true jasper
#

💔

frozen hamlet
#

i forg

gusty pumice
pale holly
#
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.0,
            func = function()
                SMODS.calculate_effect({message = 'Oh a cactus !', instant = true, colour = HEX('50ca96')}, card)
                delay(0.9375)
                card.children.center:set_sprite_pos({ x = 0, y = 1 })
                SMODS.destroy_cards({card}, nil, nil, true)
                anhilated = true
                play_sound("mii_vsauced")
                SMODS.calculate_effect({message = 'message', colour = HEX('50ca96')}, card)
                return true
            end
        }))
        delay(0.9375)
    end}

```l

hey so i'm trying to make to make the message have a delay before it does the rest (changing sprite, destroying, etc) but it stillchange the sprite almost near instantly, how do i fix it ?
frosty rampart
gusty pumice
#

och, gotcha

vale zinc
#

Is G.STATES.DRAW_TO_HAND used only for drawing new cards at the beginning of a Blind, or is it for whenever cards are drawn after Play/Discard?

#

Looked some more through game.lua; looks like it is for generic card-drawin'.

frosty rampart
#

even happens when cards are drawn in booster packs iirc

frozen hamlet
gusty pumice
vale zinc
#
print("Like this!")
frozen hamlet
#

    
    config = { 
        max_highlighted = 2,
        mod_conv = 'm_quemado'
    },
        loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
        return { 
            vars = { 
                card.ability.max_highlighted,
                localize { 
                    type = 'name_text', 
                    set = 'Enhanced', 
                    key = card.ability.mod_conv 
                } 
            } 
        }
    end,
vale zinc
#

Probably oughtta be m_<mod_prefix>_quemado instead of just m_quemado.

pale holly
#
             G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.0,
            func = function()
                anhilated = true
                SMODS.destroy_cards({card}, nil, nil, true)
                delay (0.3375)
            -- should be done at the same time the card start to disapear
                card.children.center:set_sprite_pos({ x = 0, y = 1 })
                SMODS.calculate_effect({message = 'message', colour = HEX('50ca96'), play_sound("mii_vsauced")}, card)
                return true
            end
        }))

Alright i'm not sure what i should do, i'm try to make so when the card disapear all the effects plays at the same time but the sound and the set sprite arrive too early how do i fix that ?

#

The message is the only one that is correctly timed tho

frozen hamlet
pale holly
#

"mod.json"

frozen hamlet
#

oooh

#

ok let me see

pale holly
frozen hamlet
vale zinc
pale holly
#

heh that's fine, but idk it's kinda infurating, normally following G.E_Manger logic, the sprite change and sound play should happen AFTER the destroy cards but it somehow does just before

#

i could try making another G.E_manager again

red flower
#

destroy cards has an event nested inside another event in its code

frozen hamlet
red flower
pale holly
red flower
#

i haven't read the entire thing but probably

pale holly
#

i guess the only work around is making separated event manager with delays 🤔

red flower
#

i think immediate is the 3rd argument

pale holly
#

i suppose you can't even do a play_sound instead the smods destroy cards ?

red flower
#

try setting that to true

pale holly
#

so SMODS.destroy_cards({card}, nil, immediate, true)?

red flower
#

no

#

put true instead

pale holly
#

so like this then

red flower
#

yesh

pale holly
#

i'll give it a try

red flower
#

yesh

#

yeah why cant i type that lol

pale holly
#

lmao

frozen hamlet
pale holly
#

tbh i don't think i've seen it explained before with the vanilla remade wiki, well the destroyed cards effect but not the things after "nil", etc

red flower
#

vanillaremade is not smods documentation

#

if it's explained anywhere it should be there

red flower
vale zinc
pale holly
# red flower yesh

well it's alright better, i do notice that when it's the end of the round, the destroying card effect will have a delay unlike when the shop is ending, but otherwise the rest works a bit better at least

vale zinc
frozen hamlet
# vale zinc Well, it looks like this only gives the `loc_vars` of the card. Could you, in th...
SMODS.Atlas{
    key = "atlas_consumeables",
    path = 'consumeables.png',
    px = 71,
    py = 96,
}

SMODS.Consumable({
    key = "consumeables",
    set = "Tarot",
    pos = {x=0, y= 0},
    order = 99,
    atlas = "atlas_consumeables",
    unlocked = true,
    cost = 4,
    hidden = false,
    object_type = "Consumeables",
    loc_txt = {
        name = "el piromano",
        text={
        "transforma {C:attention}2{} cartas ",
        "en {C:attention}cartas quemadas",
        
        },
    },
    
    config = { 
        max_highlighted = 2,
        mod_conv = 'm_cocosmod_quemado'
    },
        loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
        return { 
            vars = { 
                card.ability.max_highlighted,
                localize { 
                    type = 'name_text', 
                    set = 'Enhanced', 
                    key = card.ability.mod_conv 
                } 
            } 
        }
    end,

    use = function(self, card, area, copier)

        for i = 1, #G.hand.highlighted do
            G.hand.highlighted[i]:set_ability(card.ability.mod_conv)
        end

        G.hand:unhighlight_all()
    end,

    can_use = function(self, card)
        return G.hand 
        and #G.hand.highlighted > 0 
        and #G.hand.highlighted <= card.ability.max_highlighted
    end
})
vale zinc
# frozen hamlet ```lua SMODS.Atlas{ key = "atlas_consumeables", path = 'consumeables.png...

Replace the use() function with this and tell me what came of it.

use = function(self, card, area, copier)
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        delay = 0.4,
        func = function()
            play_sound('tarot1')
            card:juice_up(0.3, 0.5)
            return true
        end
    }))
    for i = 1, #G.hand.highlighted do
        local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.15,
            func = function()
                G.hand.highlighted[i]:flip()
                play_sound('card1', percent)
                G.hand.highlighted[i]:juice_up(0.3, 0.3)
                return true
            end
        }))
    end
    delay(0.2)
    for i = 1, #G.hand.highlighted do
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.1,
            func = function()
                G.hand.highlighted[i]:set_ability(card.ability.mod_conv)
                return true
            end
        }))
    end
    for i = 1, #G.hand.highlighted do
        local percent = 0.85 + (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.15,
            func = function()
                G.hand.highlighted[i]:flip()
                play_sound('tarot2', percent, 0.6)
                G.hand.highlighted[i]:juice_up(0.3, 0.3)
                return true
            end
        }))
    end
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        delay = 0.2,
        func = function()
            G.hand:unhighlight_all()
            return true
        end
    }))
    delay(0.5)
end,
frozen hamlet
vale zinc
frozen hamlet
vale zinc
frozen hamlet
#

i know the line part but i see the code and i dont see something in the loc vars part that is a problem

#

ok nevermind i just fix it thanks btw

vale zinc
frozen hamlet
# vale zinc So, it's all running smoothly?

kinda, now the game don't crash if i open the game an but when i use the tarot card the cards now flip but its crashes saying attempt to index local 'center' (a nil value)

frozen hamlet
vale zinc
frozen hamlet
#

ooooh

#

no theres not its just. card.lua:280: attempt to index local 'center' (a nil value)

frozen hamlet
# vale zinc So what's on line 280?

its the code for another joker that is just "end," but i dont think that is related to the problem because its already a finished and working joker

vale zinc
#

And does this line 280 come before or after El Piromano's code?

normal crest
#

card.lua should be the vanilla file

frozen hamlet
vale zinc
frozen hamlet
normal crest
frozen hamlet
frozen hamlet
# normal crest Could you send the code for your enhancement
SMODS.Atlas{
    key = 'enchanters',
    path = 'quemado.png',
    px = 71,
    py = 96,
}

SMODS.Enhancement {
    key = 'quemado',
    atlas = 'enchanters',
    pos = { x = 0, y = 0 },

    loc_txt = {
        name = 'Carta quemada',
        text = {
            "se que hace pero me da lata poner la descripcion"
        }
    },

    config = { mult = 4 },

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.mult } }
    end,
}
#

i was just trying to just give +4 mult for then make the rest for the code

normal crest
#

hmm, when you hover over your consumable, does it properly show the description of the enhancement

frozen hamlet
peak void
#

is there a context for when a probability event occurs

#

i cant find one in the documentation

normal crest
vale zinc
normal crest
#

Isn't it context.pseudorandom_result then

vale zinc
#
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/utils.lua"]'
pattern = 'SMODS.post_prob[#SMODS.post_prob+1] = {pseudorandom_result = true, result = result, trigger_obj = trigger_obj, numerator = numerator, denominator = denominator, identifier = identifier or seed}'
position = 'after'
match_indent = true
payload = '''

if result then
    --
end

'''
frozen hamlet
vale zinc
frozen hamlet
#

should i put that also in the main.lua?

normal crest
peak void
normal crest
peak void
#

ah

#

alright

gloomy swallow
#

legendaries of the 2,3,4oak jokers

normal crest
frozen hamlet
frozen hamlet
normal crest
#

i can't tell what's wrong tbh
But m_cocosmod_quemado is somehow not the right key

frozen hamlet
#

oh

#

thanks btw

normal crest
#

If you have that remove it, otherwise try making sure you're looking at the right mod folder for the json

#

If it's there you should see the words "STEAMODDED HEADER" at the top of one of your lua files

normal crest
frozen hamlet
rapid stag
#

bump

normal crest
#

you'd have to load the other files yourself within the main file, but it's fine for now, you can experiment with that once we find out what the issue is

normal crest
#

And do you have the debugplus mod installed

frozen hamlet
#

i do both

#

its only crashes when i use the consumeable

normal crest
#

Okay can you go into collection for your enhancement, put your mouse over it, open debugplus console and type eval dp.hovered.config.center_key

#

And see what the output is

frozen hamlet
#

its say m_cocosmod_quemado

normal crest
#

oh wait I'm dumb

#

Can you just start a new run completely

#

not loading save file

frozen hamlet
#

its say the same thing with a new run

normal crest
#

Did you forget to save the main lua file

frozen hamlet
frozen hamlet
normal crest
#

Check that you're editing the right file too

frozen hamlet
#

yeah its still the same and im editing in the main.lua

normal crest
#

But like, 100% sure it's the main.lua in your Balatro mods folder

#

you're not editing a copy that's somewhere else or anything like that

frozen hamlet
#

oooooh

peak void
#

hey, question, is there a way to safely debuff and un-debuff a joker without worrying about un-debuffing perishables or during crimson heart?

frozen hamlet
#

should i make copy and paste my code into a folder with nothing in it? and start from zero with the folders?

normal crest
peak void
#

ah, thank you

normal crest
#

And not any other file

frozen hamlet
normal crest
#

Arghh okay

#

Go ingame and hover over your consumable and do eval dp.hovered.ability.mod_conv

frozen hamlet
#

its says m_cocosmod_quemado

normal crest
#

I am actually gonna go insane, everything points to it working but it doesn't

normal crest
#

For now if you have any other mods try either disabling them or moving them from the folder

#

To a different one

frozen hamlet
#

i have anothers mod and i disabled it i do the same thing with the debug?

normal crest
#

Keep debugplus enabled

#

Your only mods in the balatro mod menu should be your mod and debugplus enabled, if there is any other it should be disabled

gloomy swallow
normal crest
#

Check again that your enhancement appears in collection, that the center_key is correct and same with the consumable ingame with mod_conv

#

Using the debugplus console like before

frozen hamlet
#

now with the enhancement appears the messege "nil"

#

i will try now with the consumeable

#

the consumeables appears the m_cocosmod_quemado

normal crest
frozen hamlet
normal crest
#

no but that makes no sense, your enhancement is there in the collection right and you're running eval dp.hovered.config.center_key

#

While your mouse is on top of your enhancement

frozen hamlet
normal crest
#

That's not the right command

#

For the enhancement it's the other one I sent

frozen hamlet
#

oooooooh

#

my bad

frozen hamlet
normal crest
#

can you send the full current code for your consumable

#

last thing

#

either I figure out what's wrong here or I give up and I accept defeat

frozen hamlet
#

ok

#
SMODS.Consumable({
    key = "consumeables",
    set = "Tarot",
    pos = {x=0, y= 0},
    order = 99,
    atlas = "atlas_consumeables",
    unlocked = true,
    cost = 4,
    hidden = false,
    object_type = "Consumeables",
    loc_txt = {
        name = "el piromano",
        text={
        "transforma {C:attention}2{} cartas ",
        "en {C:attention}cartas quemadas",
        
        },
    },

    config = { 
        max_highlighted = 2,
        mod_conv = 'm_cocosmod_quemado'
    },
        loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
        return { 
            vars = { 
                card.ability.max_highlighted,
                localize { 
                    type = 'name_text', 
                    set = 'Enhanced', 
                    key = card.ability.mod_conv 
                } 
            } 
        }
    end,
})
    use = function(self, card, area, copier)
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        delay = 0.4,
        func = function()
            play_sound('tarot1')
            card:juice_up(0.3, 0.5)
            return true
        end
    }))
    for i = 1, #G.hand.highlighted do
        local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.15,
            func = function()
                G.hand.highlighted[i]:flip()
                play_sound('card1', percent)
                G.hand.highlighted[i]:juice_up(0.3, 0.3)
                return true
            end
        }))
    end
    delay(0.2)
    for i = 1, #G.hand.highlighted do
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.1,
            func = function()
                G.hand.highlighted[i]:set_ability(card.ability.mod_conv)
                return true
            end
        }))
    end
    
#

its not all the code

#

i dont have nitro

#

i will send the other part

#

"

delay(0.2)
    for i = 1, #G.hand.highlighted do
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.1,
            func = function()
                G.hand.highlighted[i]:set_ability(card.ability.mod_conv)
                return true
            end
        }))
    end
    for i = 1, #G.hand.highlighted do
        local percent = 0.85 + (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3
        G.E_MANAGER:add_event(Event({
            trigger = 'after',
            delay = 0.15,
            func = function()
                G.hand.highlighted[i]:flip()
                play_sound('tarot2', percent, 0.6)
                G.hand.highlighted[i]:juice_up(0.3, 0.3)
                return true
            end
        }))
    end
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        delay = 0.2,
        func = function()
            G.hand:unhighlight_all()
            return true
        end
    }))
    delay(0.5)
end,
#

thats all

normal crest
#

does eval G.P_CENTERS.m_cocosmod_quemado say anything that's not nil

frozen hamlet
#

yeah its says a lot but no nil

#

you want me to screenshot it or something?

normal crest
#

no it's fine

#

Everything seems to be correct yet nothing seems to work

#

I'm just gonna assume you're cursed and wish you luck

#

🙏

frozen hamlet
#

goddamn

#

thanks btw

daring fern
#

red flower
normal crest
#

I love Spanish speaking people talking to each other in English

cloud thistle
#

I want to make a mod that does the following:
At the end of every blind, create a random negative eternal Cryptid joker (and you cant skip blinds) and i want the shop to just be the vanilla shop, so nothing from Cryptid.

blazing helm
#

is there any recorces on how to make a config for a mod? i dont see it anywhere on the smod wiki :/

blazing helm
subtle hawk
#

What do discover and bypass_discovery_center parameters for SMODS.create_card actually do?
Because whatever I do with them created card DOES get discovered

#

At this point it feels like I should just do the Card thing instead of trying to use these

hushed field
#

The config.lua file defines the parameters that are configurable. The config_menu.lua file turns that into a proper config page

blazing helm
hushed field
#

A guide would be nice, though, for sure! If I have time today, I might set up an example mod that just has some config options 🤔

#

Also, feel free to ping me if you still have questions. There's way more you can do for config pages than I could explain, but I'm sure I'd be able to explain the basics, if there's something unclear, haha

blazing helm
blazing helm
hushed field
#

UI isn't difficult, but it's annoying and finnicky, haha. I'm still not comfortable with it. Frustration while working on UI is normal 😛

hushed field
#

Have you messed around with DebugPlus? It has the ability to watch files, which allows you to reload UI immediately when you save a change. It makes it way easier to work on UI stuff!

blazing helm
cloud thistle
#

wait cant i autobanish every cryptid thing

#

because banishing is literally filtering it out from the shop

hushed field
#

Yeah, just cycle through centers and check for source mod

#

then just add to banned keys

wintry solar
subtle hawk
subtle hawk
wintry solar
#

I don’t have access to my dumps right now 😭

cloud thistle
hushed field
cloud thistle
#

i want to banish everything from Cryptid using the DELETE code card functionality and create a random negative eternal Cryptid joker at the end of every blind

#

(and keep the created joker banished from the shop)

#

maybe the DELETE code card functionality isnt enough since i also dont want you to be able to make them via Judgement for example although i think that doesnt matter that much

hushed field
#

Ah, that's slightly more complicated. The way deleting stuff works is adding them to the banned card lists, which bans them from being pulled from random pools. So you'd need to make a separate pool. My understanding is that DELETE works like that, removing a card from all random pools

cloud thistle
hushed field
#

But the way you'd do it is to go over all jokers in the joker pool, or the general centers pool, depending on what you'd want to be banned. If it's the jokers pool, all of 'm will count as jokers, but if it's G.P_CENTERS, check for [var].ability.set == "Joker" and [var].original_mod.id == "cryptid" (do double check cryptid's mod ID, I don't know it by heart

blazing helm
# hushed field Also, feel free to ping me if you still have questions. There's way more you can...

how do i make a button? i wanna make a button that likes out to the twitch auth page. the code is still basicly identical to yours lol rn i have this

local create_menu_button = function (parent, config_button, callback)
    parent.nodes[#parent.nodes + 1] = create_button_binding_pip({
        label = localize(config_button.label),
        callback = callback,
        ref_table = EngagementBait.config,
        ref_value = config_button.ref_value,

    })
    -- if config_button.tooltip then
    --     parent.nodes[#parent.nodes].config.detailed_tooltip = localize(config_button.tooltip)
    -- end
end

create_button_binding_pip was the only create button func my auto complete could see but it doesnt seem to be what i want (or im seting it up wrong)
config_button:

local config_buttons = {
    {ref_value = "link_account", label = "eb_config_link_account" }, --, tooltip = "eb_config_link_account_tooltip"},
}

also whenever i add the tooltips it crashes :/

blazing helm
hushed field
blazing helm
#

idk what a toggleable pip even is x.x but ya i want a button that can be liked that i can use to link out to a website.

hushed field
#

Oooh

hushed field
#

So, I'm not at my PC, so I can't link an example, but buttons are pretty simple. If you go to the Balatro Goes Kino repo, you can look for where I use 'Discord', as that should show you a button that does exactly that!

#

There are better examples, but it's the one I can give without checking an actual repo, haha

cloud thistle
#

i love when my mod crashes the game when starting a new run

blazing helm
#

so much worse is when it works for you then DJ uses it and it crashes 😭

hushed field
hushed field
blazing helm
#

the fact that it isnt consistent with the other functoins like create_slider or create_text_input or create_toggle is soooooo annoying

hushed field
#

Is there any difference between the two?

#

and what's the crash?

blazing helm
#

you have to put {} around the label in UIBox_button but not in the other ones

hushed field
#

Oooh, yeah, yeah

#

and yeah, UI specifically is hard to work with. It's made to do exactly what vanilla needs, so a lot of the other stuff is added by SMODS or needs to be made yourself. Makes working with it pretty awkward. For me, a lot of UI code is just copying pasting existing code I wrote, specifically to avoid running into issues where I use brackets where they weren't needed, etc.

#

Part of why there aren't really many resources on making modded UI. Most people working with it don't like doing it or are very comfortable working with it, haha

blazing helm
#

lol

#

is there a way to have the button not point to a global function?

local create_menu_button = function (parent, config_button, callback)
    parent.nodes[#parent.nodes + 1] = UIBox_button({
        label = {localize(config_button.label)},
        -- button = callback,
        button = "LinkAccount",
        ref_table = EngagementBait.config,
        ref_value = config_button.ref_value,

    })
    -- if config_button.tooltip then
    --     parent.nodes[#parent.nodes].config.detailed_tooltip = localize(config_button.tooltip)
    -- end
end

"linkAccount" works but callback doesnt :/

hushed field
blazing helm
#

jsut general neatness. "EngagementBait.LinkTwitch" is more clear that is from my mod then "G.FUNCS.LinkTwitch"

red flower
#

no, you should just add the prefix to that

hushed field
#

For clarity there, you can still add your mod's key in your functions name

blazing helm
#

ya ik. if ya cant ill just use globals, just wanted to ask if you can use non globals

dapper sun
#

anyone know how to fix this?

daring fern
dapper sun
#

weird

#

bc it's a blueprint-style joker not a retrigger one

daring fern
dapper sun
#

no

#
calculate = function(self, card, context)
    -- Start Retriggering
    if context.before then
        local hasAce = false
        local has4 = false
        for _, v in pairs(context.full_hand) do
            has4 = has4 or v:get_id() == 4
            hasAce = hasAce or v:get_id() == 14
        end
        
        if has4 and hasAce then
            card.ability.extra.trigger = true
            card.ability.extra.upgrade.count = card.ability.extra.upgrade.count + 1
            G.E_MANAGER:add_event(Event({func = function() card.ability.extra.spr = true return true end }))
            return { message = localize("elle_41_activate"), colour = G.C.BLUE }
        end
    end
    -- Retrigger
    if card.ability.extra.trigger then
        -- Stop Retriggering
        if context.after then
            card.ability.extra.trigger = false
            G.E_MANAGER:add_event(Event({func = function() card.ability.extra.spr = false return true end }))
            return
        end
        
        local card_pos = 0
        for i = 1, #G.jokers.cards do
            if G.jokers.cards[i] == card then card_pos = i break end
        end
        
        ret = {}
        local retl = SMODS.blueprint_effect(card, G.jokers.cards[card_pos-1], context)
        local retr = SMODS.blueprint_effect(card, G.jokers.cards[card_pos+1], context)
        if retl then
            retl.colour = G.C.BLUE
            ret = SMODS.merge_effects(retl, ret)
        end
        if retr then
            retr.colour = G.C.BLUE
            ret = SMODS.merge_effects(retr, ret)
        end
        return ret
    end
end```
dapper sun
#

oh 😭

red flower
#

yeah i was gonna say merge effects adds .extra

#

so it will always count as returning something

dapper sun
#

a

red flower
#

you should check if the joker returns anything before merging

dapper sun
#

oh i also noticed smtn

#

ret isn't being made as a local var

daring fern
dapper sun
#

oh

#

wait i think i see my mistake

shell timber
#

yeah do like if not retl and not retr then return nil end

dapper sun
#

it only happens if it does retrigger tho

#

wait

#

i get it yea

#

ty

#

it works now

#

nope

#

now it's not retriggering

dapper sun
hidden aspen
#

i am trying to assign a tooltip to a button

dapper sun
#

...i just replaced my whole retrigger code with this

local ret = {}
ret[#ret+1] = SMODS.blueprint_effect(card, G.jokers.cards[card_pos-1], context)
ret[#ret+1] = SMODS.blueprint_effect(card, G.jokers.cards[card_pos+1], context)
return SMODS.merge_effects(ret)```
red flower
#

if the first card doesn't return then it won't do anything

#

wait no

#

hmm

cloud thistle
# hushed field But the way you'd do it is to go over all jokers in the joker pool, or the gener...

why doesnt this code work (with help from chatgpt because i dont want to learn lua):

local cryptid_mod_id = "Cryptid"

local function is_from_cryptid(center)
    return center 
       and center.mod 
       and center.mod.id == cryptid_mod_id
end

local original_get_current_pool = get_current_pool
function get_current_pool(_type, rarity, legendary, key_append)

    local pool = original_get_current_pool(_type, rarity, legendary, key_append)
    local filtered = {}

    for _, center in ipairs(pool) do
        if is_from_cryptid(center) then
            table.insert(filtered, center)
        end
    end

    return filtered
end

local function get_random_cryptid_joker()
    Cryptid_jokers = {}

    for k, center in pairs(G.P_CENTERS) do
        if center.set == 'Joker' and center.mod and center.mod.id == cryptid_mod_id then
            table.insert(Cryptid_jokers, k)
        end
    end

    if #Cryptid_jokers == 0 then return nil end
    return pseudorandom_element(Cryptid_jokers)
end

function create_negative_eternal_cryptid()
    local key = get_random_cryptid_joker()
    if not key then return end

    local card = create_card('Joker', G.jokers, nil, nil, nil, nil, nil, key)

    if card then
        card:set_edition('negative', true)
        card:set_eternal(true)
        G.jokers:emplace(card)
    end
end

local original_defeat = end_round
function end_round()
    original_defeat()

    create_negative_eternal_cryptid()
end
hushed field
vale zinc
cloud thistle
#

i think its more that i dont know how the create_card function works exactly (i do have the balatro source code but its very unreadable code)

blazing helm
red flower
blazing helm
#

thx

vale zinc
cloud thistle
vale zinc
cloud thistle
#

i am aware

red flower
#

then why do you think that's strange

cloud thistle
#

But the code makes a list of keys for Cryptid jokers but i dont think the code chooses from that pool

red flower
#

keys are strings

#

the cryptid function works on centers

cloud thistle
#

Wait so how do i create a random card from the list of centers (one of the previous versions of my code did use centers)

red flower
#

what's the goal here

mystic river
split creek
#

There's something about this joker that is causing the following crash, and I'm not sure what it is

--Ajani
SMODS.Joker { 
    object_type = "Joker",
    name = "mtg-ajani",
    key = "ajani",
    pos = { x = 0, y = 7 },
    config = { 
    extra = {
      planeswalker = {
        has_activated_loyalty = true,
        loyalty = 3,
        loyalty_abilities = {
          {
            cost=1,
            use=function(self, card)
              print("activate!!!")
            end
          },{
            cost=-3,
            use=function(self, card)
              print("activate!!!!!")
            end
          }
        },
      },
    },
    
  },
  order = 5,
    rarity = 2,
    cost = 8,
    atlas = "mtg_atlas",
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.planeswalker.loyalty } }
    end,
    calculate = function(self, card, context)
    if context.setting_blind and not (context.blueprint_card or card).getting_sliced then
      card.ability.extra.planeswalker.has_activated_loyalty = false
    end
  end
}```
#

In the middle of the blind this crash will occur, even if the player isn't doing anything

red flower
#

loyalty abilities has a function in it

#

balatro doesn't like functions in cards

split creek
#

Is there a way that I can have a function associated with a card?

#

I'm calling the function externally

G.FUNCS.use_loyalty = function(e)
    local card = e.config.ref_table
    local loyalty_ability = card:get_loyalty_ability(e.config.index)
    card.ability.extra.planeswalker.loyalty = card.ability.extra.planeswalker.loyalty + loyalty_ability["cost"]
    card.ability.extra.planeswalker.has_activated_loyalty = true
    G.E_MANAGER:add_event(Event({
        trigger = "after",
        delay = 0.1,
        func = function()
            loyalty_ability["use"](card)
            return true
        end,
    }))
    G.jokers:unhighlight_all()
    if card.ability.extra.planeswalker.loyalty <= 0 then
        card:start_dissolve(nil, true)
    end
end```
red flower
#

if it's exclusive to that card save it to the center (with a unique name including your mod prefix) and then do card.config.center.modpefix_function()

if it can be shared save it to a global table like MTJ.function and then save the name to the card

#

save it to the center means have it at the same level as calculate

split creek
#

got it

#

How is it accessed from the card if it is saved to the center?

red flower
#

card.config.center.function_name()

#

or self.function_name() in the card's functions

red flower
#

ah idk how delete works but you can just add stuff to G.GAME.banned_keys

cloud thistle
#

That makes sense

granite raptor
#

if i call SMODS.create_card and use the stickers field, will it only generate cards compatible with said stickers? i.e. if i do SMODS.create_card({set = "Joker", key_append = "modid_append", stickers = ["eternal"]}), would it automatically filter out cards like gros michel, etc?

wintry solar
#

iirc it will just not apply eternal to cards that aren’t compatible

normal crest
#

i went to check and it's not adding eternal regardless to any joker, probably cus should_apply is false always

split creek
#

Is there a way to change color in description text from loc_vars?

red flower
#

{V:

#

check smods text formatting wiki

rapid stag
#

bump

normal crest
#

the game calls check_for_unlock within set_ability if the card is in the jokers or consumables area

#

oh wait I get what you mean

rapid stag
#

but it's actively not unlocking despite that

normal crest
#

still, the game calls discover_card in Card:added_to_deck

rapid stag
#

well i have a consumable that runs set_ability on a joker and the result doesn't get unlocked in collections, so something's wrong

normal crest
#

just tested it and it seems to work for me

#

could you send the code you're testing with?

split creek
#

This is causing strange behavior when I have multiples of the same joker (spawned with debugplus), any idea what might be causing it?

local updateref = Card.update
function Card:update(dt)
      updateref(self, dt)

      if G.STAGE == G.STAGES.RUN then
        if not self:is_planeswalker() then return end
        local can_activate  = self:can_activate_any_loyalty_ability()

        if can_activate and not self.config.center.planeswalker.jiggle then
            local eval = function(card) return card:can_activate_any_loyalty_ability() end
            juice_card_until(self, eval, true)

            self.config.center.planeswalker.jiggle = true
        end

        if (not can_activate) and self.config.center.planeswalker.jiggle then
            self.config.center.planeswalker.jiggle = false
        end
    end
end
faint yacht
#

You're applying it to the "prototype" object.

#

Did you mean something akin to self.ability.planeswalker.jiggle?

wild patrol
#

what's the G.P_CENTERS. equivalent of custom stuff like G.P_CENTERS.p_standard_mega_1 how would I point it to a custom booster

wintry crater
#

how can i make it so youre unable to sell something until you have ten dollars?

wild patrol
#
discovered = true,```
#

does't seem to work in tags

#

custom tag is still locked

#

nvm I found the issue I had a tag with same key from testing stuff lol

tulip pecan
wild patrol
#

I figured out everything on tags but how their text is displayed

#

I tried the local_text but doesn't seem to work

near coral
#

For context some jokers of mine are to only trigger when the poker hand is a combination of other poker hands (two pair, full house, straight flush, etc.) however my coder made it to where if it contains those hands it triggers, making them triggerable in flushes with 2 pairs and is having a hard time setting it to what's intended

#

Is there some lines of code I can send them that can help with that

wild patrol
#

yea it works

red flower
#

so you want to replace "contains" for "is"?

quick scarab
#

anyone knows how to tally discovered custom consumables?, I trying to make a unlock condition but it seems to keep crashing

SMODS.Joker {
    key = "cassie",
    atlas = 'Joker',
    pos = { x = 3, y = 2 },
    blueprint_compat = true,
    unlocked = false,
    rarity = 2,
    cost = 4,
    config = { extra = { odds = 4 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { G.GAME.probabilities.normal or 1, card.ability.extra.odds } }
    end,
    calculate = function(self, card, context)
        if context.using_consumeable and not context.blueprint and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit
        and context.consumeable.ability.set == 'fnaf_item' and (pseudorandom('fnaf_cassie') < G.GAME.probabilities.normal / card.ability.extra.odds) then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                    SMODS.add_card {
                        set = 'fnaf_item',
                        key_append = 'fnaf_cassie_item'
                    }
                    G.GAME.consumeable_buffer = 0
                    return true
                end)
            }))
            return {
                message = "+1 Item",
                colour = G.C.GREEN,
            }

        end
    end,
    locked_loc_vars = function(self, info_queue, card)
        return { vars = { 4 } }
    end,
    check_for_unlock = function(self, args) -- equivalent to `unlock_condition = { type = 'discover_amount', tarot_count = 22 }`
        return args.type == 'discover_amount' and #G.P_CENTER_POOLS.fnaf_item <= G.DISCOVER_TALLIES.fnaf_item.tally
    end
}```
daring fern
near coral
primal robin
#

Cutting-edge technology I'm working on

near coral
#

Ben starr blueprint

lyric wadi
#

how do you modify a playing card's base chips

#

like not adding or subtracting permanent bonus chips like hiker

#

but like actually modifying their base chips

daring fern
lyric wadi
#

or like is it so tied to its rank that modifying it isnt worth

#

oh ok

errant arrow
#

i genuinely can't tell if im stupid or not.
can someone explain how the ipairs stuff works in crayon eating terms? i'm still so lost on how to detect certain variables (in this case, joker(s))

slim ferry
#

What is "the ipairs stuff"

#

just like

#

ipairs loops?

errant arrow
#

the joker im trying to create wants to detect certain jokers in order to scale and do a hidden effect once both jokers are obtained
i keep being told to do ipairs and if statements, but i'm so lost.

slim ferry
#

find_card

#

Not joker

#

next(SMODS.find_card("joker key"))

fading rivet
#
calculate = function(self, carry, context)
  if context.main_joker and not context.blueprint then
    if next(SMODS.find_card("j_modid_jokerkey")) then
      --- scale
    end
  end
end
hidden aspen
errant arrow
#

would SMODS.find_card work in the loc_vars section?

#

i see.
-# i think...

vale zinc
#

How may I pass an SMODS.calculate_context() call as a boolean value? Outside of The Tuba, the Discard button is grayed out after each Hand played, and while playing The Tuba, the Discard button remains enabled no matter what.

[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
match_indent = true
position = 'after'
pattern = '''
e.config.button = 'discard_cards_from_highlighted'
'''
payload = '''
if SMODS.calculate_context({
    LAPSEMS_should_the_discard_button_be_blocked = true,
    full_hand = G.hand.highlighted
}) then
    if (G.GAME.current_round.hands_left > G.GAME.current_round.discards_left) then
        e.config.colour = G.C.UI.BACKGROUND_INACTIVE
        e.config.button = nil
    end
end
'''
calculate = function(self, blind, context)
    if not blind.disabled then
        if context.LAPSEMS_should_the_discard_button_be_blocked then
            for _, card in pairs(context.full_hand) do
                if card:is_suit(self.config.extra.suit) then
                    return true
                end
            end
            return false
        end
    end
end,
fading rivet
errant arrow
#

so, for confirmation (and to see if im being stupid or not...)

        loc_vars = function(self,local_queue,card)
            return {vars = card.ability.extra.mult,card.ability.extra.scaling}
            if SMODS.find_card("TBC_jokerhere) or SMODS.find_card then
            (insert rest of code)
        end,
fading rivet
#

return will cut the function short

errant arrow
#

so return would have to be later in the code? or do i have to cut it out?

#

-# also, how are you guys getting color in your text?

fading rivet
#

and pass the result of SMODS.find_card into next()

fading rivet
fading rivet
errant arrow
#

ah, for confirmation:

  loc_vars = function(self,local_queue,card)
    if SMODS.find_card("TBC_jokerhere") or SMODS.find_card("TBC_jokerhere2") then
      (insert code)
  next()
  (return code)

?

vale zinc
# vale zinc How may I pass an `SMODS.calculate_context()` call as a boolean value? Outside o...

I've done something similar for another Blind and it's worked with no fuss.

[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
match_indent = true
position = 'after'
pattern = '''
e.config.button = 'discard_cards_from_highlighted'
'''
payload = '''
-- This is utilized by The Horn.
if (G.GAME.blind.config.blind.key == 'bl_lapsems_horn') and not G.GAME.blind.disabled then
    for i = 1, #G.hand.highlighted do
        if LAPSEMS.is_one_of_these_ranks(G.hand.highlighted[i], G.GAME.blind.config.blind.config.extra.ranks_to_anti_discard) then
            e.config.colour = G.C.UI.BACKGROUND_INACTIVE
            e.config.button = nil
            break
        end
    end
end
'''
fading rivet
#
  loc_vars = function(self,local_queue,card)
    if next(SMODS.find_card("j_TBC_jokerhere")) or next(SMODS.find_card("j_TBC_jokerhere2")) then
      (insert code)
   end
  (return code)
end
#

ignore my horrible tabbing im on phone

#

@errant arrow

red flower
red flower
vale zinc
#

Or may I simply add a LAPSEMS.block_discard_button() function call instead of a return true?

red flower
#

i dont bother with any of that and just make my jokers set a global variable

#

its not like i care about other mods using my contexts

vale zinc
#

I think I'm just gon' go with a LAPSEMS.block_discard_button() call.

slim ferry
#

smods does this itself

vale zinc
slim ferry
#

useful if you only need boolean flags

slim ferry
#

Not what i mean

#

Nor does that sentence make sense

red flower
slim ferry
#

Huh

#

Wdym

red flower
slim ferry
#

Uh not sure

normal crest
vale zinc
#

I'm afraid I don't follow either.

#

I thought I could just patch in an SMODS.calculate_context() statement and assign the result to a boolean value.

vale zinc
tulip pecan
# daring fern Yes.

Is this the correct way to hook this function? We're trying to make it so that selling consumables with negative sell value don't let you go under the minimum amount of money but it’s not working

frosty rampart
#

N recommending bad practices 🥀 never thought i'd see the day /silly

slim ferry
#

Or just dont calculate a context

#

And do the checks in a hook

vale zinc
slim ferry
#

Im on mobile

slim ferry
#

But like just check if the given boss is active

#

And loop over G.hand.highlighted to check the cards

#

And see if its valid to discard

#

And if not then you e.config.colour = G.C.UI.INACTIVE; e.config.button = nil

#

Or whatever i forgot what the colour is called

#

Just look at the original function

frosty rampart
# red flower :3

in all seriousness it's a fair enough implementation if you don't expect others to interact with the context, especially since you put the globals in a table for the mod. just feels a little bit evil lol

vale zinc
#

Surely, if I've already implemented SMODS.calculate_context({LAPSEMS_before_jokers_score = true}), then this should be a piece of cake.

red flower
#

calculate context is not designed to return a boolean

#

and you probably shouldnt mess with it to do so

#

true as a return is basically reserved for destruction so for example merge_effects will fail

vale zinc
red flower
#

it is designed to return things in a table

vale zinc
red flower
#

no but you can probably do next(table)

#

but anyway i dont know if the returns will actually be passed

#

because smods looks for specific keys

#

i think return_table does get all the returns

#

but i might be wrong i cant test rn

faint yacht
normal crest
#

that's with j_joker only in joker_main

red flower
#

lol

hardy vessel
#

Trying to make a blind that needs to be one-shot in order to beat. I believe the effect is working, just the text isn't being updated. Am I missing something to make the score show 0?

calculate = function(self, blind, context)
    if not blind.disabled then
        if context.after then
            if not SMODS.last_hand_oneshot then
                G.GAME.chips = 0
            end
        end
    end
end,
faint yacht
#

I believe I had something like that as a Joker before.

red flower
#

ah G.GAME.chips updates after the context is ran

#

so you would need to use events i think

faint yacht
#

-# If that helps any.

hardy vessel
#

I'll take a look, thank you!

vale zinc
quick scarab
vale zinc
cloud thistle
#

but always negative

#

i did:

card:set_edition({negative = true}, true)
card:set_eternal(true)
card:add_to_deck()
G.jokers:emplace(card)```
wintry solar
vale zinc
wintry solar
#

Oh I misinterpreted your message

past ridge
#

yall im new to modding do you delete the zip file after extracting

slim ferry
#

The delete button in file explorer

#

The trash can looking one

#

While you have the zip selected

past ridge
#

no do you or do you not

slim ferry
#

Oh

#

I

past ridge
#

so yes

slim ferry
#

I cant read

#

But yeah delete it

past ridge
#

oh lol ur fine

dapper sun
#

how do i get a card's position?

slim ferry
#

like in the cardarea?

dapper sun
#

no

#

on screen

slim ferry
#

card.T.x and card.T.y iirc

#

But its in balatro units which are insanely janky so if youre doing math with them be prepared

dapper sun
#

the problem is that's not in pixels

#

yea

slim ferry
#

Okay

viscid talon
#
SMODS.Joker({
    key = "abacus",
    config = { extra = { mult = 0, plusmult = 1, minusmult = 1 } },
    loc_txt = {
        ["name"] = "Abacus",
        ["text"] = {
            {
            [1] = "{C:mult}+#2#{} Mult for each played {C:attention}2{}, {C:attention}4{}, {C:attention}6{} and {C:attention}8{}",
            [2] = "{C:mult}-#3#{} Mult for each played {C:attention}3{}, {C:attention}5{}, {C:attention}7{} and {C:attention}9{}",
            [3] = "{C:inactive}(Currently {C:mult}+#1#{}{C:inactive} Mult){}"
            }
        },
    },
    pos = { x = 4, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult, card.ability.extra.plusmult, card.ability.extra.minusmult } }
    end,
    
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play then
            if context.other_card:get_id() == 3 or
                context.other_card:get_id() == 5 or
                context.other_card:get_id() == 7 or
                context.other_card:get_id() == 9 then
                card.ability.extra.mult = card.ability.extra.mult - card.ability.extra.minusmult
                return {
                    message = localize { type = 'variable', key = 'a_mult_minus', vars = { card.ability.extra.minusmult } },
                    colour = G.C.RED
                }
            end
        if context.individual and context.cardarea == G.play then
            if context.other_card:get_id() == 2 or
                context.other_card:get_id() == 4 or
                context.other_card:get_id() == 6 or
                context.other_card:get_id() == 8 then
                card.ability.extra.mult = math.max(0, card.ability.extra.mult - card.ability.extra.minusmult)
                return {
                    message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.plusmult } },
                    colour = G.C.RED
                }
            end
        end
        if context.joker_main and context.cardarea == G.jokers then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
end
})```
#

my code is being super janky

#

the joker doesn't gain mult or lose mult when i play these cards

slim ferry
viscid talon
#

i think im messing up some contexts but idk what

#

im not very smart

slim ferry
#

Probably ask her

dapper sun
#

i'm trying to make a soul sprite with different dimensions to the card it's on, but i'm having trouble with fixing its rotation pivot

#

that's why

slim ferry
#

Ruby did something like that with a janky solution for entropy i think

dapper sun
#

yea

viscid talon
#

oo icic

dapper sun
#

i know