#💻・modding-dev

1 messages · Page 598 of 1

wind steppe
#

and also create_card_for_shop

azure valley
#

that is significantly easier, I can't believe I didn't think of that.

#

(thanks a lot!)

rose hatch
#

Hello, very embarrassed to ask, but would some of you good folks modders like to use some of my card sprites for your balatro mods 😶

queen crescent
#

sorry i use different theming for my balatro mod

muted trout
#

Is it better to group your jokers in chunks or give each it's own separate file?

muted trout
#

I think it's a bit more organized to do your jokers in groups by the sprite sheet but that's just what I picked up personally

queen meadow
# wispy cove

i do the chaotic route and sort my jokers by rarity on the file names themselves

queen meadow
# gaunt tundra What does twister do?

if a seal triggers it triggers another seal effect
so if you get a tarot card off a purple seal there's the chance you get the effect of a gold seal from the joker (so $3)

rose hatch
queen meadow
shell timber
#

i too am in this modification

rose hatch
#

Nice

frigid cargo
#

is there a way to set a variable to a random poker hand?

frigid cargo
#

i found out how yay

wintry swallow
rose hatch
#

Which ones would you like to take

wintry swallow
queen meadow
#

how do you change the description of a joker with malverk

#

can you even do it in the first place

#

oh wait

#

i forgot to add a bracket hold on

wintry swallow
#

🍎 🍑

queen meadow
#

i find it weird that malverk doesn't revert back to a crossmod joker's original textures and instead uses the balatro joker spritesheet as a fallback

willow scroll
#

One big line of jokers

wintry swallow
#

can anyone help me figure out this hook? first time using them and I'm struggling to figure them out


Game.start_run = function (args)

    --"This print statement will happen BEFORE the original code runs!--

    local jokers = 
        jokers.config.highlighted_limit (args),
    end,

    --This print statement will happen AFTER the original code runs!--

    return 
        jokers.config.highlighted_limit = 2,
    end,

    return jokers,
    end
end```
wintry swallow
#

to increase the joker highlight limit to at least 2

#

<@&1133519078540185692>

daring fern
queen meadow
hidden mirage
#

How to place code at the final scoring step with a hook

daring fern
hidden mirage
hidden mirage
daring fern
jolly shadow
hidden mirage
wintry swallow
#

ok y'all im having a lot of trouble with a consumable i'm trying to make; i've checked in the Vanilla code and in other mods for examples to attempt to deconstruct, but I'm having a hard time. I'm trying to make a consumable that adds the sticker from the rightmost selected joker to the leftmost selected joker, then destroy the right joker. can anyone help me out?

daring fern
wintry swallow
# daring fern ```lua table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end) ...

so it take the two jokes highlighted, assigns them a and b functions, and prioritizes a over b. the local function takes the left and right selected cards (jokers, in this case) and equates them to the G.jokers.highlighted functions. k is the card ability (the sticker, in this case) and pairs is assigned to read the Stickers amongst the SMODS variables. It asks if the left most selected joker has an ability from a sticker, and if it does, it adds that sticker (k) applies it to the right, then destroys the left card.

did I get that right? I just want to clarify so i can learn instead of copying and pasting every time someons helps me

wintry swallow
#

ah.

daring fern
# wintry swallow ah.

It sorts the table so they are in order from left to right then it sets the left and right variables to the leftmost and rightmost jokers, then it iterates over SMODS.Stickers and checks if the leftmost joker has that sticker, and if it does, it applies it the rightmost joker, then it destroys the leftmost joker.

wintry swallow
#

ok, so what are function(a, b) and the k and v variables for?

#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2 },

    table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
    local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
    for k, v in pairs(SMODS.Stickers) do
    if left.ability[k] then
        right:add_sticker(k, true)
    end
end

SMODS.destroy_cards(left)```

Am I not implementing it correctly?
daring fern
wintry swallow
#

This is the error I keep getting, i don't understand what's wrong in the code; I'm closing the bracket at line 25, but apparently that's wrong?

bold gyro
#

hey y'all is there an alternative to SMODS.Suits that is instead an ordered list of suits?

pale holly
#
     calculate = function(self, card, context)
        local isBossBlind = G.GAME.blind.boss
        local isShowdown = G.GAME.blind.showdown  -- G.GAME.blind.config.blind.boss.showdown

        if context.joker_main  and isBossBlind then
                return {
                    xmult = card.ability.extra.xmult
                }
            end
            
        if context.setting_blind and isShowdown then
            G.GAME.blind.chips = G.GAME.blind.chips * 0.90
    G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
                card:start_dissolve({ G.C.RED })              
        end
    end
}```

the setting blind during a showdown boss won't work at all, and yes i tried blind config  shodown and wouldn't work either, i'm not sure what i'm doing wrong
bold gyro
pale holly
#

also yeah for the config blind boss, it gives me this

daring fern
daring fern
pale holly
#

i did changed the local as said so

daring fern
pale holly
#

Doesn't work either sadly, still stays in and work like if it was in a regular boss blind

rigid solar
#

I'd like to add some Multiplayer compatibility to my mod but I can't really find a channel for that on the Multiplayer server

Does anyone know how I'd go about checking when the nemesis (or any opponent in battle royal) plays a hand?

#

I was thinking about always looking at the current hand count, but it can get pretty hard to identify when an hand is played if an opponent gets more hands during the pvp, somehow

wintry swallow
#

dog im gonna crash out

pale holly
pale holly
rigid solar
#

I'm not really making a proper mod, I'm making an add-on for Pokermon, so I can't really create a thread for my mod and ask that there

wintry swallow
# pale holly What doesn't work exactly ?

I'm not sure? The "nil" value is supposed to be 2, and when I select the two jokers (moving the Sticker from the left joker to the right) it doesn't let me use the consumable

rigid solar
#

pinged the wrong person lol

pale holly
#

fuck

bold gyro
pale holly
wintry swallow
#

ive been so focused on the rest of the code i missed one of the simplest bits

pale holly
#

happens to me

#

also could you show your use function trough text ? i feel like it cutted some part of it in the image

wintry swallow
#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2, min_highlighted = 2 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.max_highlighted } }
    end,

    use = function (self, card, area, copier)
        table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
        local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
            for k, v in pairs(SMODS.Sticker) do
            if left.ability[k] then
            right:add_sticker(k, true)
        end
    end

    SMODS.destroy_cards(left)
end
}```
daring fern
wintry swallow
#

ok so the code works when I select two playing cards, but not when i select 2 Jokers

daring fern
wintry swallow
#

so how do i apply it to jokers then?

pale holly
#

try removing the min_highlighted just to see

#

like, not just 0, remove it entirely

wintry swallow
#

nope :(

pale holly
#

i think i remember crytpid had consumables working with more or less the same idea

#

try checking from there

pale holly
rigid solar
wintry swallow
#

dog idk i've been doing this for a combined number of days less than a week

rigid solar
#

can_use = function(self, card, context)
return card.ability.min_highlighted <= #G.jokers.highlighted <= card.ability.max_highlighted
end,

wintry swallow
# pale holly this, probably you can see how this work then use it for stickers instead
        local used_consumable = copier or card
        local combinedTable = Cryptid.get_highlighted_cards({ G.hand, G.jokers }, card, 2, 2)
        local highlighted_1 = combinedTable[1]
        local highlighted_2 = combinedTable[2]
        G.E_MANAGER:add_event(Event({
            trigger = "after",
            delay = 0.4,
            func = function()
                play_sound("tarot1")
                used_consumable:juice_up(0.3, 0.5)
                return true
            end,
        }))```

Something like this line from the Conduit?
rigid solar
#

though in base game you can't highlight 2 jokers

wintry swallow
pale holly
wintry swallow
# pale holly oh, i guess not ? Honestly was expecting something else from it
        local combinedTable = {}
        dbl = false
        no_dbl = false

        for _, value in ipairs(G.hand.highlighted) do
            if value ~= card then
                if Card.no(value, "dbl") then
                    no_dbl = true
                elseif value.edition and value.edition.cry_double_sided then
                    dbl = true
                end
                table.insert(combinedTable, value)
            end
        end

        for _, value in ipairs(G.jokers.highlighted) do
            if value ~= card then
                if Card.no(value, "dbl") then
                    no_dbl = true
                elseif value.edition and value.edition.cry_double_sided then
                    dbl = true
                end
                table.insert(combinedTable, value)
            end
        end
        return (#combinedTable == 2 and not (dbl and no_dbl))
    end,```
#

there's this as well

pale holly
daring fern
pale holly
#

Also legit speaking, it's pretty weird it took that much to make a shodown detectable
and that G.GAME.blind.config.blind.boss.showdown or G.GAME.blind.showdow didn't worked out
huh

wintry swallow
daring fern
wintry swallow
#

ok so everything up until i actually use the consumable works and then

#

i want. to scream.

daring fern
wintry swallow
#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2, min_highlighted = 2 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.max_highlighted } }
    end,

    can_use = function(self, card, context)
    return G.jokers and #G.jokers.highlighted == 2
    end,

    use = function (self, card, area, copier)
        table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
        local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
            for k, v in pairs(SMODS.Sticker) do
            if left.ability[k] then
            right:add_sticker(k, true)
        end
    end

    SMODS.destroy_cards(left)
end
}```
#

this is the consumable code, i can also provide sticker code

#
    key = "trifuricated",
    badge_colour = HEX("a86232"),
    pos = { x = 6, y = 1 },
    config = { extra = { retriggers = 2 } },

    calculate = function(self, card, context)
        if (context.repetition or context.retrigger_joker_check) and context.other_card == card then
            return {
                repetitions = card.ability.inscrypt_trifuricated.extra.retriggers,
            }
        end
    end,

    loc_vars = function(self, info_queue, card)
        return { vars = { self.config.extra.retriggers } }
    end
}```
daring fern
#

Also it's SMODS.Stickers

wintry swallow
wintry swallow
#
    key = "trifuricated",
    badge_colour = HEX("a86232"),
    pos = { x = 6, y = 1 },
    config = { extra = { retriggers = 2 } },

    calculate = function(self, card, context)
        if (context.repetition or context.retrigger_joker_check) and context.other_card == card then
            return {
                repetitions = card.ability.inscrypt_trifuricated.extra.retriggers,
            }
        end
    end,

    loc_vars = function(self, info_queue, card)
        return { vars = { self.config.extra.retriggers } }
    end
}```
wintry swallow
#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2, min_highlighted = 2 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.max_highlighted } }
    end,

    can_use = function(self, card, context)
    return G.jokers and #G.jokers.highlighted == 2
    end,

    use = function (self, card, area, copier)
        table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
        local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
            for k, v in pairs(SMODS.Stickers) do
            if left.ability[k] then
            right:add_sticker(k, true)
                SMODS.destroy_cards(left)
        end
    end


end
}```
#

exact same thing, exact same error

daring fern
wintry swallow
daring fern
wintry swallow
#

Well now when I use the consumable, it's A) Not adding the sticker and B) not destroying the left Joker

#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2, min_highlighted = 2 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.max_highlighted } }
    end,

    can_use = function(self, card, context)
    return G.jokers and #G.jokers.highlighted == 2
    end,

    use = function (self, card, area, copier)
        table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
        local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
            for k, v in pairs(SMODS.Stickers) do
            if left.ability[k] then
            right:add_sticker(k, true)
            SMODS.destroy_cards(left)
        end
    end


end
}```
daring fern
wintry swallow
#

nope

#
    key = "stones",
    set = "Tarot",
    pos = { x = 2, y = 1 },
    config = { max_highlighted = 2, min_highlighted = 2 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.max_highlighted } }
    end,

    can_use = function(self, card, context)
    return G.jokers and #G.jokers.highlighted == 2
    end,

    use = function (self, card, area, copier)
        table.sort(G.jokers.highlighted, function(a,b) return a.T.x < b.T.x end)
        local left, right = G.jokers.highlighted[1], G.jokers.highlighted[#G.jokers.highlighted]
            for k, v in pairs(SMODS.Stickers) do
                if left.ability[k] then
                right:add_sticker(k, true)
                
            SMODS.destroy_cards(left)
        end
    end


end
}```
daring fern
hallow slate
#

How do you change the background colors like how the showdown blinds do?

wispy falcon
#

Is there a way to check if something is a playing card in SMODS.Sticker, specifically should_apply?

tepid crow
atomic edge
#

is there a md that adds a whole new type to cards like editions/seals etc.?

tepid crow
atomic edge
#

thanks

wispy falcon
final jewel
#
        if card.ability.extra.round_left <= 0 then
            return true
        end
        return false
    end,
    use = function (self,card,area,copier)
        G.E_MANAGER:add_event(Event({
            func = function()
                G.consumeables:change_size(card.ability.consumSlot)
                return true
            end
        }))
    end,```

I dont understand why it doesnt change the size of the consumeable slot
daring fern
final jewel
#

yeah

#
        round = 1,
        round_left = 1,
        consumSlot = 1,
        txt = 'Not ready yet'
    }},```
#

found out the bug

final jewel
#

is that good cause it make me crash

lavish elm
#
SMODS.ConsumableType{
    key = "would_you_rather",
    collection_rows = {4,5},
    primary_colour = G.C.JOKER_GREY,
    secondary_colour = G.C.GREY,
    loc_txt = {
        name = "Would You Rather"
    },
    shop_rate = 0
}

what am I missing?

daring fern
final jewel
#

oh ok thx

sinful crown
#

Is it possible to make a joker that changes all text in the game?

#

well its possible but how

red flower
sinful crown
#

yeah, I've been looking into it decided to go with the first option

#

thank you anyway

lyric wadi
#

is there a list of vanilla tag keys

wispy falcon
#

Why does this not work?

        --if in challenge, then apply to all jokers/consumables
        return G.GAME.challenge == "c_cstorm_death_challenge" and not card.playing_card
    end,```
red flower
lyric wadi
#

so would i do add_tag(Tag('tag_double')) or add_tag(Tag('double'))

burnt tide
#

how can i change all starting cards for a deck ?

final jewel
#

I dont understand that crash its soo weird

humble pawn
wind steppe
final jewel
wind steppe
#

for the sticker

wind steppe
final jewel
#

oh

burnt tide
final jewel
# wind steppe lovely patch
# PACKS MODIFICATION #
[[patches]]
[patches.pattern]
target = 'card.lua'
position = 'after'
pattern = '''
booster_obj = self.config.center
'''
payload = '''
if self.config.center.group_key == 'k_restaurant_pack' then
    self.ability.extra = self.ability.extra + (G.GAME.giga and G.GAME.giga.vouchers and G.GAME.giga.vouchers.newMenu or 0)
end
if self.config.center.group_key == 'k_restaurant_pack' then
    self.ability.choose = self.ability.choose + (G.GAME.giga and G.GAME.giga.vouchers and G.GAME.giga.vouchers._courseMeal or 0)
end
'''
overwrite = true
match_indent = true```

its probably in that but idk where cause I didnt change anything
wind steppe
#

functions/state_events.lua

final jewel
#

but I dont have that

wind steppe
wispy falcon
wind steppe
final jewel
#
[patches.pattern]
target = "functions/state_events.lua"
pattern = "for _, area in ipairs(SMODS.get_card_areas('jokers')) do for _, _card in ipairs(area.cards) do"
position = "at"
payload = "local places = Giga.areaprocess(SMODS.get_card_areas('jokers')); for _, place in ipairs(places) do local scoreCards = Giga.areaprocess(place.cards); for _, _card in ipairs(scoreCards) do"
overwrite = true
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "for _, v in ipairs(SMODS.get_card_areas('playing_cards')) do"
position = "at"
payload = "local playedCardsPlace = Giga.areaorderprocess(SMODS.get_card_areas('playing_cards')); for _, v in ipairs(playedCardsPlace) do"
overwrite = true
match_indent = true```
oh yeah that but I litteraly just use the patch from Toga just by changing the name
wind steppe
#

Giga doesn't exist yet

wind steppe
final jewel
wind steppe
#

go check for it

final jewel
#

ok

final jewel
# wind steppe go check for it
[patches.pattern]
target = "functions/state_events.lua"
pattern = "check_for_unlock({type = 'run_card_replays'})"
position = "before"
payload = "if togabalatro then togabalatro.playextracards() end"
match_indent = true```
is it that
wind steppe
#

what did you replace with Giga

final jewel
#

just the name of var

#

for making it more clear for me

wind steppe
#

What was it

final jewel
#

its been like 2 month since i do that

#

and it crash just now

#

like I replace togabalatro for Giga

wind steppe
#

ctrl f togabalatro to find where it's defined and add that

#

also the functions in togabalatro

final jewel
#

I have all the function that was needed for it

final jewel
#

Idk but it just doesnt crash anymore

faint yacht
#

Just be mindful doing that will break my setup. 😅

#

-# We certainly need a hookable function in there, tbh.

daring quarry
#

Does anybody know an easy way to have a joker constantly shaking once a condition is met? (think invisble joker when it's ready to activate or dna on the first hand)
I've been using jokerforge as a base and then editing the code myself but their version of the effect is broken and I can't find a way to fix it

wispy falcon
daring fern
wind steppe
wispy falcon
#

Other question: How do I check if a card is flipped?

daring fern
stable kayak
#

how do I add a card to the title?

broken rivet
#

is it possible to call SMODS.calculate_effect with messages appearing on the consumables tray? i need to be able to call it without any card target

daring fern
willow scroll
#

is there a nicer way to modify ante scaling for a deck thats not modifying the get_blind_amount function

#

oh ante_scaling for config exists :clueless:

willow scroll
broken rivet
#

this is in a mod calculate

#

i might be able to try something with SMODS.merge_effects

humble pawn
daring fern
broken rivet
daring fern
# broken rivet

Have you tried having the card input be a card but set message_card = G.consumeables in the effect?

nocturne garnet
broken rivet
#

could try that?
i've swapped the effects to be a normal calculate return though

#

this works except the attention text is displayed over the deck

red flower
#

mod calculate uses the deck yes

broken rivet
#

yea

#

i'm trying to get it to use the consumables tray

#

but i don't quite know how i'd do that

red flower
#

message_card = G.consumeables? maybe

broken rivet
#

just realized i also used #ret > 0 instead of next(ret) boomeline

broken rivet
broken rivet
#

most people seem to think the tray being juiced looks very silly

red flower
broken rivet
#

ah

burnt tide
native bone
#

How do you return exponential mult using Talisman? I cant find any documentation. And I have more luck finding a needle in a haystack than actually reading the source code and then understanding it lol.

slim ferry
#

emult = <value>

native bone
#

I'll try that

fluid steppe
#

i thought it was e_mult

slim ferry
#

both works iirc

#

just like for you can do both xmult and x_mult

fluid steppe
#

wrow

slim ferry
#

missing collection = <collection page name>

#

in loc_txt

fluid steppe
#

oh uh

lavish elm
#

ok thx

fluid steppe
#

i noticed {C:G.C.SUITS.#1#}#1#{} isnt working

slim ferry
#

yeah

fluid steppe
#

any ideas or workarounds

slim ferry
#

you need to return a colour

#

in loc_vars

fluid steppe
#

ah oki

slim ferry
#

colours = {...} under vars

#

and then you can use them with V:1, V:2, V:3, etc in order

fluid steppe
#

return { vars = {drinksuit, colours = {G.C.SUITS[drinksuit]}} }

local drinktxt = {
    "When sold, randomly turns",
    "half of your deck into",
    "{V:1}#1#{}, and the other half into",
    "a random other suit"
}```
still not working??
slim ferry
#

are you not forgetting card.ability... part

#

also the suit colour keys are plural

#

but idk if thats an issue

fluid steppe
#
local suits = {"Spades","Hearts","Clubs","Diamonds"} -- todo: check for paperback/bunco suits
local drinks = {["Spades"]={2,3},["Hearts"]={3,3},["Clubs"]={4,3},["Diamonds"]={5,3}} 
for drinksuit, drinkatlas in pairs(drinks) do
    local drinkid = 'drink_'..string.lower(drinksuit)
    SMODS.Joker {
    key = drinkid,
    config = {},
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = { set = "Other", key = "hypr_devart" }
        return { vars = {drinksuit, colours = {G.C.SUITS[drinksuit]}} }
    end,
    …
slim ferry
#

yeah

#

because drinksuit is a local variable of the for loop

#

it wont exist anymore after the joker is created

fluid steppe
#

ahh

#

see now you're making sense

pale holly
#
      config = { extra = {mult = 20, chips=100, xmult = 3, dollar=25, min = 1, max = 3, set_value = 0 }},
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult,card.ability.extra.chips,card.ability.extra.xmult, card.ability.extra.dollar }  }
    end,
    calculate = function(self, card, context)
    
    if context.setting_blind then
    card.ability.extra.set_value = pseudorandom('cymbal_untextured', card.ability.extra.min, card.ability.extra.max)
    return {
    message = "?"
    }
    end
    
    
if context.joker_main then
    if card.ability.extra.set_value == 1 then
        return {
            mult = card.ability.extra.mult,
            key = "j_cymbal_untextured_alt" 
        }
    elseif card.ability.extra.set_value == 2 then
        return {
            chips = card.ability.extra.chips,
            key = "j_cymbal_untextured_alt2" 
        }
    elseif card.ability.extra.set_value == 3 then
        return {
            xmult = card.ability.extra.xmult,
            key = "j_cymbal_untextured_alt3" 
        }
    end
end
end
}

tried to make my joker change its text depending on the set value, at first i wanted to do when setting the blind, then tried to do with joker scoring but in both case it does nothing, not sure how to fix that, would appreciate the help !

#

Or should i use the loc_vars and key thing even in that case ?

faint yacht
#

In there, yeah.

#

You can `return { key = 'mod_key' } to use different locentry to show.

pale holly
#

oh i see, but can i use then something like

loc_vars = function(self, info_queue, card)
    return { key = card.ability.set_value == 1 and "j_cymbal_untextured_alt" or nil,card.ability.set_value == 2 and "j_cymbal_untextured_alt2" or nil }
end

or it needs to be different ?

faint yacht
#

key = condition1 and self.key.."_alt" or condition2 and self.key.."_alt2" or self.key

pale holly
#

okay i think see now so something like
key = card.ability.set_value == 1 and self.key"_alt" or card.ability.set_value == 1 and self.key"_alt2" or self.key

with conditions being the card.ability.set_value, am i understand it right ?

queen meadow
# queen meadow 💔

is there a proper way to implement modded joker skins on malverk that completely prevents this type of thing to happen? even as a separate mod/skin it can still happen if the skin isn't applied so it's either you have it on or remove it from the mod loader

faint yacht
pale holly
#
        return {key = card.ability.set_value == 1 and self.key.."_alt" or card.ability.set_value == 2 and self.key.."_alt2"or card.ability.set_value == 3 and self.key.."_alt3" or self.key}
    end```

```lua
return {
    descriptions = {
        Joker = {
            j_cymbal_untextured = {
                name = "U.. extu  ..d J.k. r",
                text = { "{C:inactive} (Does something different each round.)"
                },
            },
            j_cymbal_untextured_alt = { 
                name = "U.. extu  ..d J.k. r",
                text = { "{C:chips}+100{} Chips"
                },
            },
            j_cymbal_untextured_alt2 = { 
                name = "U.. extu  ..d J.k. r",
                text = { "{C:mult}+20{} Mult"
                },
            },
            j_cymbal_untextured_alt3 = { 
                name = "U.. extu  ..d J.k. r",
                text = { "{X:mult,C:white}x3{} Mult"
                },
            },

getting unsure of what i'm doing wrong, the self key and the keys themselves are correct but it'll still stay to the default text

fluid steppe
#

i dont think you can evaluate inside tables

plucky berry
#

hello! i'm having problems with the localization of seals and booster packs, i've put them onther "Other" like other mods do, but it's the only things that show up blank, jokers and consumables are working fine

crystal perch
#

<@&1133519078540185692>

plucky berry
#

damn

crystal perch
#

that bot did NOT like your question

fluid steppe
#

lmaoo

plucky berry
crystal perch
#

thanks you mods

plucky berry
#

so does anyone know wtf is up with seals

#

and boosters

crystal perch
#

let me see

plucky berry
#

this should be fine it's identical to other mods but it doesn't show up

crystal perch
#

for boosters it should be p_mod-prefix_booster-key

plucky berry
#

j_ is for jokers,
other mods use p_ for packs

#

i hate italic

#

p_

crystal perch
#

my bad i accidentally read red card

#

didn't check!

plucky berry
#

yeah bt this still doesn't work

crystal perch
#

does your other localization work?

#

like ones that aren't packs/seals

plucky berry
#

yes

native bone
#

For some reason, the exponential mult isnt triggering, and I dont know why. The idea is that for every 5 cards with this seal scored, it gives ^1.25 Mult.

plucky berry
#

everything works except that

crystal perch
#

could i see the keys for the seals/packs you're localizing

#

just to make sure

native bone
#

if I used e_mult or emult

#

I'll try it though

crystal perch
#

hrm

plucky berry
#

cause i didn't solve it

crystal perch
#

imo exp mult is just too strong but that's a different conversation

lyric wadi
#

im reading and a lil confused

#

is SMODS.create_card{ set = 'Joker', rarity = 0.96 } a correct syntax to spawn a random rare joker?

plucky berry
#

rarity = 3 is rare

crystal perch
#

why's rarity = 0.96?

native bone
crystal perch
#

3 is rare yeah

plucky berry
#

it should work if you have just talisman in theory

true jasper
#

how would i make a deck have 2 voucher slots in shop

plucky berry
#

but it doesnt

crystal perch
crystal perch
#

and how is the text not working

#

like in-game

#

does the description show up but not the title?

lyric wadi
plucky berry
#

nothing

crystal perch
#

and double checking that your mod prefix is "napoli"?

plucky berry
#

yeah.. otherwise everything else wouldn't work

crystal perch
#

i'm just checking cuz i don't see anything else wrong

plucky berry
#

like jokers work fine

plucky berry
crystal perch
#

honestly i've had trouble with the Other tab for localization too

#

for now you could just set the loc_txt to whatever you want

plucky berry
#

yeah that works for everything except the seal badges

crystal perch
#

how so?

plucky berry
#

i mean idk how i would use loc_txt on those

crystal perch
#

for seals it's

loc_txt = {
  name = 'name'
  label = 'badge'
  text = {
    "text"
  }
}
plucky berry
#

oh okay

#

well that's a way to do it but it can't be translated then

crystal perch
#

yeah

#

if you don't intend on doing translations it's no big, but if you do then it's a big

frosty rampart
#

will lovely patches affect all relevant lines if multiple lines match the pattern, or only the first line?
(the patches.pattern, not the regex)

#

i suppose i can just find out lol

true jasper
frosty rampart
#

fuck
could i have a second copy of the patch to hit the second instance?

orchid nest
#

My friend wants to make a translation mod for toki pona, how do you add your own language to balatro? Thanks!

frosty rampart
faint yacht
frosty rampart
orchid nest
#

thank you!

pale holly
#

thanks a lot, it does work properly now

stone dagger
#

Hello, how do P_CENTERS work? I created a consumable but now Im not being able to summon it via a joker because it can't find the center. Do I define the centers? Is done automatically?

faint yacht
#

What's the key of it and what's your modprefix?

stone dagger
#

key is "erebos_favour" the modprefix idk how that works 😅

#

it's "mtgg" nvm

#

still dont know how to use it tho

#

do I need to pass the modprefix in the SMODS.add_card function?

lyric wadi
#

okay so how do you actually spawn a random rare joker

daring fern
wind steppe
#

but yeah what something said

red flower
lyric wadi
red flower
#

wtf

#

why

wind steppe
#

because that is exactly what something said

stone dagger
lyric wadi
wind steppe
#

also it's the same thing it just uses create_card

#

so it can go into the shop

fluid steppe
#

how does one get if high contrast is enabled? it's probably G.SETTINGS.<something> but idk what that something is

daring fern
fluid steppe
#

oh it's more granular now i forgot

#

what about per suit?

lyric wadi
#

is the per suit thing smod added

#

it wasnt like that before

fluid steppe
#

oh found it

slim ferry
fluid steppe
#

what aboud added suits

slim ferry
#

you shouldnt need this unless youre making smth else entirely

slim ferry
fluid steppe
#

does paperback set it automatically

#

..wait i can just check that cant i

slim ferry
#

idk paperback is just wierd ig

#

it shouldnt need to do that

frosty dock
#

there's no reason to do anything else

#

do make sure to include the mod prefix in the suit keys when you do use them

burnt tide
slim ferry
#

wrong atlas key

#

somewhere

wintry swallow
#

^^^

#

likely in relation to an asset you're using

burnt tide
#

oh yeah

#

i forgot i change one

#

thanks

#

how can i change ERROR ? it's not like this ?

wintry swallow
#

yeah i think the key in the SMODS.Rank should be extra_zero, not just zero

slim ferry
#

no

#

mod prefix

#

the mod prefix is extra

#

i presume

burnt tide
#

yes

#

it's the problem ?

slim ferry
#

shouldnt be

#

the key looks correct to me

normal crest
burnt tide
normal crest
#

put it at the same level, after line 110 in that screenshot

burnt tide
#

thanks!

#

i'm really bad at coding TwT

wintry swallow
#

mooooooods

chrome widget
#

we in it to win it gang

wintry swallow
#

oh good lord

tepid crow
chrome widget
#

so close to being done I just hate work and want to play wind waker

empty token
#

when my joker tries to Play a sound during scoring, the game crashes to this Any of yall know how to fix this?

round lion
#

4.jpg never works

empty token
#

Yea

#

Tried going from .ogg to .mp3 which didnt also work Idk what i was expecting honestly

tepid crow
#

I recall personally also having issues w/ ogg, and it working with mp3

empty token
#

I see

tepid crow
#

dunno though, I've never done much else w/ music in my mods

empty token
#

this error message didnt change when i was changing the file from ogg to mp3 and forgot to Change the path for the SMODS.Sound to say mp3 at the end

#

Which is kinda suspicious but Idk what it could mean

tepid crow
#

there's one thing I do remember, it loads things differently if the word "music" is somewhere in the key iirc?

empty token
#

Do you mean like if the word "music" is in the key it could mess up or Should i try having "music" in the key

tepid crow
#

I don't remember haha, try both I'd say

normal crest
#

if music is in the key it could mess it up, as that's intended for background music

empty token
#

na its not in the key fortunately

empty token
tepid crow
#

if that doesn't work either double check the file location (path and name)

#

it's failing while trying to find the filepath

short girder
#

this is supposed to override drawing cards which im sure is extremely wrong haha

faint yacht
#

draw_card merely executes the draw of a card...

#

function draw_card(from, to, percent, dir, sort, card, delay, mute, stay_flipped, vol, discarded_only)

cunning valley
#

Trying to make my enhancement increase in Xmult for every other card with that enhancement in full deck, but the code (which i totally didn't steal from the steel card from vanilla remade) causes a stack overflow when hovering over for some reason?

short girder
#

thank you ali

faint yacht
# cunning valley

This had been very much the same thing when I was also counting for specific enhancement on cards - you need to add a "is calculating" local variable to prevent looping into itself.

short girder
#

but for money im pretty usre

tepid crow
cunning valley
faint yacht
#

Or that.
-# Brain currently storming ideas about how feasable are replacements of my destructive patches... running on fumes.

cunning valley
#

In that case, what context check would be better?

tepid crow
#

if I'm understanding correctly, the calculates are looping somehow

#

weird thing is you already have a context check

faint yacht
tepid crow
#

that one's because your calculate didn't guard against contexts

    calculate = function(self, card, context)
        card.ability.extra.totalrepetitions = card.ability.extra.repetitions*toga_gettotalsteelcount() or 0
        ....
    end
#

wow nice indentation, thanks discord

cunning valley
#

ah, indentations! discord coder's worst nightmare!

#

(i would suppose, i'm not sure)

tepid crow
cunning valley
tepid crow
#

I'm wondering if your joker is the one infinitely looping or if your joker just triggers the infinite loop somewhere else

#

Where are you hovering over the joker?

#

(e.g. in a run, in the collection)

cunning valley
#

Same result as always

tepid crow
#

Ah my bad

cunning valley
#

(stack overflow crash)

cunning valley
short girder
burnt tide
tepid crow
#

that info_queue[#info_queue+1] = G.P_CENTERS.m_jsm_wet is not doing any favours for avoiding recursion

cunning valley
#

Well, from what i see it IS an info queue so it does look suspicious...

#

In any case, I never touched it, as i... actually have no idea what it does

tepid crow
#

You're telling balatro to generate the little tooltip on the side of the enhancement

tepid crow
#

and every time balatro adds a tooltip, you tell it to add "just 1 more"

#

ad infinitum

#

similar to how the Fool -> Magician -> Lucky card tooltip works

#

but then yours is Wet Enhancement -> Wet -> Wet -> Wet -> ...

solemn shuttle
#

infinite info queue erm

tepid crow
#

yea

cunning valley
#

Aha! Makes sense
Well, in that case it's useless since it's a enhanced card which already has the tooltip. Meaning if i delete the info queue... it'll be fine?

solemn shuttle
#

Yeah you should be

cunning valley
#

hi nix washing machine

tepid crow
cunning valley
#

⛓️‍💥

#

thank you lars!!! you're a life saver!!

burnt tide
#

my custom ranks are in every decks, how can i disable that ? (and only show in one deck)

solemn shuttle
tepid crow
ashen lynx
#

Hey I was wondering if anyone knows how to add a negative tooltip onto a card, is it somewhere in loc_txt?
I'm so lost I tried a few things but I'm not sure what to add 😅
My description works fine but I can't for the life of me seem to get the tooltip to show xD

loc_txt = {
  name = "Card",
  text = {
    "Has a {C:attention}10%{} chance to create {C:attention}20{}",
    " {X:dark_edition,C:dark_edition}Negative{} copies of random {C:consumable}consumables{}",
    " when leaving the {C:shop}shop{}."
    }
},
burnt tide
#

i'm trying but i really don't know how to do this

tepid crow
#

<@&1133519078540185692> pls

tepid crow
short girder
daring fern
burnt tide
#

-# i'm going to sleep anyway that's too hard for me

tepid crow
#

you'd have to check the deck used in the rank's in_pool method

short girder
daring fern
short girder
#

oh gotcha

cunning valley
#

Hello! Anyone know any contexts for when a card with an enhancement is played?

frosty rampart
#

there isn't a context for everything
there's a few contexts for "when a card is played" depending on what you mean by that, and then you can check if the relevant card has an enhancement with next(SMODS.get_enhancements(card))

cunning valley
#

Oh i mean, a context for when a playing card with an enhancement scores

unkempt bronze
#

Quick question:

#

I wanna code up 15 consumable cards similar to each other with slightly different effects (some buffing face cards, some odd, some even, some composite, and so on). However, I don't want to make a different variable for each one. Is there a way I can make those buff happen in the card itself?

frosty rampart
cunning valley
#

Can't forget about context.cardarea == G.play too right?

#

👀

frosty rampart
#

uhhh right yea, usually you don't have to worry about the cardarea but now that i think about it context.individual triggers on e.g. steel and gold cards held in hand too

#

so the cardarea check keeps it to played cards

cunning valley
#

YIPEE

#

wait couldn't i do SMODS.has_enhancement(playing_card, 'enhancement key') for enhancements instead?

frosty rampart
#

if you're looking for a specific enhancement, then yea that's better
the version i gave just checks if the card is enhanced with anything

cunning valley
frosty rampart
unkempt bronze
frosty rampart
#

i'm
more confused now

unkempt bronze
#

I want to define each consumable.
I want to define each one to buff certain cards.
I don't want to make individualized variables for each consumable.

frosty rampart
#

you should be able to just put local variable = value outside of any SMODS.Consumable definitions, and then for the rest of that file you can use variable

unkempt bronze
#

Now is the second part: how do I set up each consumable to activate on different ids?

#

Not on just one, but like on a good few

frosty rampart
#

i'd probably recommend having each consumable set a global variable to true when you use it, and then have the effects all trigger in your mod calculate function and reset the global variable to false

unkempt bronze
#

That's kinda what I was hoping against, but at least I can define one. Where should I define my variable anyway?

frosty rampart
#

i'm still unclear on what this variable is supposed to do

unkempt bronze
#

it's just a base addmult variable

frosty rampart
#

give an example of what one of these consumables would do, i think that'll help me understand

#

like one specific one

unkempt bronze
#

Upon use, one would add 20 mult per card of four letters for the next hand, as an example. Another would do three and a third would do five.

#

(Like fours, fives, nines, jacks, and kings)

frosty rampart
#

ah i see
yea you can literally just define this variable in a file outside of any tables or SMODS.Somethings, as long as it's in the same file as wherever you're using the variable it's fine
like put it on line 1

unkempt bronze
#

So, how do I have the card activate on the certain ids?

frosty rampart
#

you
check for the id

i'm sure there's a way to get a rank's name from the ID, and then there's a way to count how many characters are in a string

unkempt bronze
#

Can I do that in the consumable or no?

frosty rampart
#

is this supposed to just trigger when you're holding the consumable, or do you want to be able to use it to "activate" it?

unkempt bronze
#

after use

#

like you use it, then the buff

frosty rampart
#

ok, you'll need to put in a bit of work but yes you can set it up like this

  1. set the consumable's keep_on_use function to return true
  2. the consumable should have its own variable that tracks whether it's active, initially set to false
  3. set the consumable's use function to just set that active variable to true
  4. set the consumable's can_use function to only return true if the active variable is false
  5. set the consumable's calculate function to first check if the active variable is true. if it is, then do the calculation code and put SMODS.destroy_cards(card) right before the return function (don't worry, it'll still calculate fine even as it's being destroyed)
#

steps 1-4 are exactly the same for every consumable you have, which is why i suggested automating the definition a little bit

unkempt bronze
#
SMODS.Consumable {
    key = "asdf",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 12, y = 5 },
    unlocked = true,
    discovered = true,
    can_use = function(self, card)
      return true
    end,
    use = function(self, card, area, copier)
        G.GAME.xiferp_asdf_mult = (G.GAME.xiferp_asdf_mult or 0) + 5
    end,
    loc_txt = {
        name = 'asdf',
                text = {
                    'Adds +5 mult per Jack for',
                    'the hand after this is used',
                },
            },

        
}```
Here's one of the consumables I have, for ref
frosty rampart
#

i gave you a rather detailed answer

unkempt bronze
#

I know

#

So, add a calculate function to this that does the buff and destroys the card?

frosty rampart
#

as well as steps 1-4

unkempt bronze
#

How much of the other 4 steps have I covered?

frosty rampart
#

...none of them

muted trout
#

unsure of the error here but i may be missing something

frosty rampart
#

can't check context in loc_vars

#

what are you trying to do?

muted trout
unkempt bronze
muted trout
frosty rampart
frosty rampart
muted trout
unkempt bronze
frosty rampart
#

you can name it whatever you want. you are coding here, you have the power. as for the value:

  1. ...initially set to false
muted trout
#

the hands played wont be displayed, just the mult

frosty rampart
#

yea my bad
but the point is that the calculate function will do the work of calculating how many hands have been played, the loc_vars function shouldn't be doing that at all

muted trout
#

?

frosty rampart
#

no
it needs to be a new variable you add to the config -> extra table

unkempt bronze
frosty rampart
#

no it'd have to be if other_card.get_id() == 4 or other_card.get_id() == 5 or ...

#

which is why i recommended getting the rank's name and then counting how many characters there are in it (which would also support crossmod ranks)

unkempt bronze
#

The crossmod thing I'm not immediately caring for, just want to make a clean mod now. making it multi-mod compatible is a secondary thing at the moment

frosty rampart
#

nearly
loc_vars should be return { vars = { card.ability.mult * math.exp(card.ability.handsplayed) } } tho, going by your initial screenshot

muted trout
#

hand on i think i was doing the doubling wrong

frosty rampart
muted trout
#

it should've been added handsplayed to itself

frosty rampart
muted trout
#

i should probably make it start at 0 to return 1

frosty rampart
#

ok yea
it'll actually just be card.ability.mult * (2 ^ card.ability.handsplayed), lua has a ^ operator

unkempt bronze
# frosty rampart the crossmod thing is a bonus, the main benefit is not having to type out 5 sets...
SMODS.Consumable {
    key = "qwerty",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 12, y = 4 },
    unlocked = true,
    discovered = true,
    keep_on_use = function(self, card)
      return true
    end,
    can_use = function(self, card)
      return true
    end,
    config = { extra = { yes_is_no = false } },
    use = function(self, card, area)
        G.GAME.xiferp_text_mult = (G.GAME.xiferp_text_mult or 0) + 10
    end,
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and context.other_card.get_id() == (whatever) then
            if card.ability.extra.yes_is_no = true and (G.GAME.xiferp_text_mult or 0) > 0 then
              local give_mult = G.GAME.xiferp_text_mult or 0
                SMODS.destroy_cards(card, nil, nil, true)
                return { mult = give_mult }
              end  
        end
    end
end
}```
    Like this?
frosty rampart
#

getting there
still missing step 3 and 4
and you don't need the global variable anymore (unless you want it to stack where e.g. using a four-letter card and a five-letter card gives both bonuses on each played card that matches either 4 letters or 5 letters)

muted trout
#

new issue

unkempt bronze
# frosty rampart getting there still missing step 3 and 4 and you don't need the global variable ...
SMODS.Consumable {
    key = "qwerty",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 12, y = 4 },
    unlocked = true,
    discovered = true,
    config = { extra = { yes_is_no = false } },
    keep_on_use = function(self, card)
      if yes_is_no = false then
       return true
    end,
    can_use = function(self, card)
      return true
    end,
    use = function(self, card, area)
        set yes_is_no = true
    end,
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and context.other_card.get_id() == (whatever) then
            if card.ability.extra.yes_is_no = true and (G.GAME.xiferp_text_mult or 0) > 0 then             
              G.GAME.xiferp_text_mult = (G.GAME.xiferp_text_mult or 0) + 10
              local give_mult = G.GAME.xiferp_text_mult or 0
                SMODS.destroy_cards(card, nil, nil, true)
                return { mult = give_mult }
              end  
        end
    end
end
}```
Firstly, is this more like it?
and secondly, I just wanna be safe in case that comes up.
muted trout
unkempt bronze
#

(card.ability.handsplayed)

frosty rampart
# unkempt bronze ```-- (consumable base) SMODS.Consumable { key = "qwerty", set = "xiferp...

no to be clear
if you're using the global variable
it will add more mult per played card if you use two consumables than if you just use 1

anyway for step 3: set isn't a thing. this is basic lua. literally just fucking card.ability.extra.yes_is_no = true

and you put step 4 in the wrong function (it should be in can_use, not keep_on_use), and it needs to be card.ability.extra.yes_is_no

frosty rampart
muted trout
unkempt bronze
# frosty rampart no to be clear if you're using the global variable it will add more mult per pla...
SMODS.Consumable {
    key = "qwerty",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 12, y = 4 },
    unlocked = true,
    discovered = true,   
    config = { extra = { yes_is_no = false } },
    keep_on_use = function(self, card)
       return true
    end,
    can_use = function(self, card)   
      if card.ability.extra.yes_is_no = false then
        return true
    end,
    use = function(self, card, area)
       card.ability.extra.yes_is_no = true
    end,
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and context.other_card.get_id() == (whatever) then
            if card.ability.extra.yes_is_no = true and (G.GAME.xiferp_text_mult or 0) > 0 then
              G.GAME.xiferp_text_mult = (G.GAME.xiferp_text_mult or 0) + 10
                local give_mult = G.GAME.xiferp_text_mult or 0
                SMODS.destroy_cards(card, nil, nil, true)
                return { mult = give_mult }
              end  
        end
    end
end
}
        
}```
Like so?
frosty rampart
#

yes there you go

unkempt bronze
#

Also, what do I do for the variable itself?

#

Currectly it's just local variable = (exists) in my code

frosty rampart
#

fucking christ
you know what you want to use that variable for, right? then use it where you want to use it
it exists, so you can use it

#

you're acting like there's a right or wrong answer when there isn't really
this is coding. you are the maker. you decide what to do with the variable

red flower
#

meta crash out

unkempt bronze
frosty rampart
frosty rampart
unkempt bronze
unkempt bronze
queen meadow
#

yo is there a way to remove the booster pack shine

#

lemme try something

burnt tide
granite jay
#

Anyone figured this out yet? Here’s the code I have so far.

                if hand_chips + context.other_card.chips + card.ability.extra.chips_penalty < 0 then
                    penalty = -(hand_chips + context.other_card.chips)
                end
                return {
                    chips = penalty,
                    colour = G.C.CHIPS
                }```
#

Or a snippet

queen meadow
#

instead, can I make a booster pack unskippable?

burnt tide
bold gyro
#

oh also you'll need to chuck in a hook, it isn't vanilla nor smods built in

#
local can_skip_ref = G.FUNCS.can_skip_booster
G.FUNCS.can_skip_booster = function(e)
    if SMODS.OPENED_BOOSTER and SMODS.OPENED_BOOSTER.config.center.unskippable then
        e.config.colour = G.C.UI.BACKGROUND_INACTIVE
        e.config.button = nil
    else
        return can_skip_ref(e)
    end
end
queen meadow
#

I'll figure this out soon enough...

granite jay
#

How do I make it so if a joker is copied by blueprint or brainstorm, they can add xMult to the joker they're copying instead of themselves?

chrome widget
frosty rampart
#

clean

wary quail
#

Can someone help me with a joker that, each time a card is triggered:
adds 10 chips and plays a message,
adds 3 mult and plays a message,
multiplies mult by 1.1x and plays a message,
plays a final message with no modification

#

having the chips and mult apply hasn't been an issue for me but for some reason I can't get messages to play in sequence like this

frosty rampart
#

for the first three messages, do you want it to be different from the usual "+10"/"+3 Mult"/"X1.1 Mult" messages?

wary quail
#

Yeah, custom written ones

#

I plan to have sounds play with them as well but I figure once the messages are done that shouldn’t be too hard to figure out

frosty rampart
#

gotcha
when you return from a calculate function, you can return an extra table in the return table. this extra table itself behaves like a return table, so you can have another extra table inside that. the extra table is calculated after the main table is calculated
for your purpose, you'd do something like this:

return {
  chips = 10,
  message = "Something",
  extra = {
    mult = 3,
    message = "Something else",
    extra = {
      xmult = 1.1,
      message = "A third thing",
      extra = {
        message = "A fourth thing"
      }
    }
  }
}
#

and in each level, you can also have sound = "soundeffectkey" to play a custom sound

wary quail
#

Ohhhh okay that makes sense

#

Very helpful tysm

frosty rampart
#

no problem

daring fern
frosty rampart
#

ah dang it right

vocal helm
#

Is there a way to trigger a Joker's "on setting blind" context effect manually? With Modeling Clay (my Joker that changes effect each round) sometimes its effect can't trigger because it also changes its effect while setting the blind

#

-# it also acts weirdly with scaling jokers displaying nil values but that's a separate issue

daring fern
vocal helm
#

Ideally the one it just turned into

#

As in, setting blind -> change joker -> trigger setting blind effect of new joker

tall wharf
daring fern
vocal helm
#

Ooh, alright

#

I'll double check my code next time I'm working on it, just hopped off for the night

vocal helm
daring fern
tall wharf
#

yea

queen meadow
#

what if

#

negative booster packs

#

temporarily adds a +1 booster slot when it was present

#

probably not possible in smods

burnt tide
#

like remove all the aces

hybrid iris
real crown
#

How can I make another Joker other than Jimbo be the default for the Joker pool when it runs out?

real crown
#

Does that work for overriding the base Joker pool too? And not a custom one?

real crown
#

Alright, thank you!

hybrid iris
burnt tide
#

how did you do that ?

hybrid iris
#

thank you!!! they're essentially just playing card enhancements

#

I may or may not make this a whole thing

real crown
#

What's the context.type equivalent of context.setting_blind?

daring fern
real crown
#

Can I find the possible context.types somewhere?
Also, tags only work with context.types and wouldn't work with just simply doing context.setting_blind, right?

daring fern
dapper sun
#

how do i get a card's edition?

daring fern
dapper sun
#

ty

real crown
#

How can I wait for the previous tag to finish? Now all tags are triggering at the same time and it completely bugs the game out:

    key = "pool",
    min_ante = 2,
    pos = {
        x = 4,
        y = 2
    },
    loc_vars = function(self, info_queue, tag)
        info_queue[#info_queue + 1] = G.P_CENTERS.p_pool_1
    end,
    loc_txt = {
        name = "Pool Tag",
        text = {"Gives a free", "{C:attention}Mega Pool Pack"}
    },
    apply = function(self, tag, context)
        if context.type == 'immediate' then
            local lock = tag.ID
            G.CONTROLLER.locks[lock] = true
            tag:yep('+', G.C.SECONDARY_SET.Spectral, function()
                local booster = SMODS.create_card {
                    key = 'p_pool_1',
                    area = G.play
                }
                booster.T.x = G.play.T.x + G.play.T.w / 2 - G.CARD_W * 1.27 / 2
                booster.T.y = G.play.T.y + G.play.T.h / 2 - G.CARD_H * 1.27 / 2
                booster.T.w = G.CARD_W * 1.27
                booster.T.h = G.CARD_H * 1.27
                booster.cost = 0
                booster.from_tag = true
                G.FUNCS.use_card({
                    config = {
                        ref_table = booster
                    }
                })
                booster:start_materialize()
                G.CONTROLLER.locks[lock] = nil
                return true
            end)
            tag.triggered = true
            return true
        end
    end,

    in_pool = function(self, args)
        return false
    end
}```
daring fern
wicked leaf
#

my enhancement is not counting as a face card for jokers, how would I fix this?

wicked leaf
dapper sun
#

how do i do something to the hand at the end of round

wicked leaf
real crown
daring fern
wicked leaf
#

Why from_boss

daring fern
wicked leaf
#

Should I do the same with get_id?

daring fern
wicked leaf
#

I see I see

#

I do wanna get better at hooking stuff cuz I barely have any clue about it

dapper sun
#

nvmd i think i found it

winter flower
#

how would i use SMODS.add_card{} to give a random card from a specific mod

daring fern
dapper sun
hardy viper
#

ideally for that use original_mod instead of mod, the latter is influenced by take_ownership (so usually not what you want)

daring fern
dapper sun
#

okay

#

but i want to do smtn once to the hand, not per-card

#

or is context.individual the one for per-card

#

why did u add context.individual i said i DON'T want it to be per-card

daring fern
dapper sun
#

ty

#

okay i'm doing that now how do i get the held hand

daring fern
dapper sun
#

ok

#

ty

wispy falcon
#

How do I change the square color of the edition scoring message?

ashen drift
#

how can i get the mod that an enhancement is from just from the enhancement key?

daring fern
ashen drift
#

grand

dapper sun
#

add a colour entry to the return table

burnt tide
#

how do i make a rank that gives +1 mult instead of +1 chip ?

wispy falcon
red flower
#

what's the crash

wispy falcon
red flower
#

it's not calculate then

#

that looks like you have something wrong in info_queue

wispy falcon
#

I found the error, it was in the description

#

I accidentally typed V: instead of X:

#

colour doesn't work though, the square is still the default color

frosty dock
wispy falcon
wispy falcon
wicked leaf
#

can you somehow make a card be scored 5 times every time its scored?

wispy falcon
wicked leaf
#

I guess retriggering 5 times by itself could work

daring fern
wicked leaf
frosty dock
#

the loc_txt or localization entry

daring fern
wicked leaf
wispy falcon
daring fern
wicked leaf
#

i dont understand context.repetition from the wiki explanation

daring fern
wicked leaf
#

would it trigger when I score it

#

cuz thats my intention

#

if it scores, it retriggers 5 times

daring fern
wicked leaf
#

i will try it out I guess

atomic edge
#

what part of the game code handles planets leveling up hands?

#

is it the update_hand_text and level_up_hand?

slim ferry
#

yes

#

SMODS.smart_level_up_hand combines those two automatically though

#

well

atomic edge
#

okay great thanks

slim ferry
#

level_up_hand also uses update_hand_text normally

#

but SMODS.smart_level_up_hand doesnt do it when there isnt anything to update

atomic edge
#

okay thanks

wispy falcon
#

Back to my question: How do I change the color of that square behind the text?

atomic edge
#

what do i need to put into target to lovely patch smods?

slim ferry
#

target = "=[SMODS _ file path]"

#

iirc

atomic edge
#

thanks

frosty dock
frosty dock
#

target = '=[SMODS _ "file path"]'

slim ferry
#

ah

wispy falcon
atomic edge
#

is there a mod that adds new planet cards that add like 2x to chips or mult so i can check it out because i really dont understand how to use smart_level_up_hand

slim ferry
#

in base smods you can only just level up x times

stoic void
#

Universum cryptid

slim ferry
#

you need to create a function yourself for doing like anything else

stoic void
#

makes all planets double chips and mult

slim ferry
#

not a good example i would say

stoic void
#

ah ok

atomic edge
#

oh okay thanks

slim ferry
# atomic edge is there a mod that adds new planet cards that add like 2x to chips or mult so i...
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/game_object.lua"]'''
pattern = '''
hand[self.key] = math.max(hand['s_'..self.key] + hand['l_'..self.key]*(hand.level - 1), 0)
'''
position = "at"
payload = '''
hand[self.key] = math.max(hand[self.key] + hand['l_'..self.key]*amount, 0)
'''
match_indent = true
times = 1
``` use this patch to stop hand stats from recalculating from base level every time they level up
frosty rampart
#

true
(i have a PR open in SMODS that, among other things, stops hand stats recalculating from base level. need to make some requested changes and write some utility functions but it should hopefully be merged eventually)

stoic void
#

text chess moment

#

its so stupid but the vids are good

true jasper
stoic void
#

agreed

#

book move or smth

stoic void
#

No way I win

#

damn

thick wren
#

the timing's a little wonky here
it runs the add_card event and creates the new joker before cards are scored even though it's in context.after, but then runs destroy_cards at the right time
any thoughts?

dapper sun
#

how do i get what rank a card is?

dapper sun
#

ty

daring quarry
#

how would I access the number of vouchers in the shop as a variable?

true jasper
daring quarry
vale zinc
daring quarry
true jasper
#

SMODS.change_voucher_limit(number) you can use this do increase/remove a voucher slot in shop

atomic edge
#

in a cards code is what is self and what is card?

#

or are they the same?

#

for example in a consumables use function

#

it is function(self, card)

daring fern
atomic edge
#

ohh

#

thanks

vale zinc
slim ferry
thick wren
#

yeah i got it, thanks though

cunning valley
#

Yo! Does anyone know any easy ways of messing around with shaders without having to reopen the game every 5 seconds?

cunning valley
winter flower
normal crest
#

in the console type watch shader Mods/your mod/assets/shaders/name.fs

winter flower
#

OH

#

I

#

OH M YGOD I CANT READ

normal crest
#

it will automatically update whenever you modify the .fs file

cunning valley
#

oh that's SICK

faint yacht
#

Used watch lua when developing the mod config tabs.

atomic edge
#

what language are balatro shaders?

faint yacht
#

GLSL.

charred widget
#

Hello friends! It's finally time for me to put together something I've been putting off for a while: The god of Time, Dialga

#

I tried to make it so it retriggers all played cards twice, but it's not working. Could someone help me fix this?

charred widget
#

IM SORRY 😭 it was originally made with Jokerforge and I tried reformatting it but it evidently still looks like shite

willow scroll
atomic edge
#

is there a tutorial on making shaders for balatro?

charred widget
#

i'd also like to know that

unkempt bronze
#
    key = "qwefeqrgaergar",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 0, y = 0 },
    unlocked = true,
    discovered = true,
    can_use = function(self, card)
      return true
    end,    
    loc_txt = {
        name = 'qergwetgwqetgt',
                text = {
                    'Gives 1 random card a random suit',
                    'and adds +5 chips to your next hand.',
                },
            },
    use = function(self, card, area, copier)
        G.GAME.xiferp_text_chips = (G.GAME.xiferp_text_chips or 0) + 5        
    calculate = function(self, card, context)
            local suit = pseudorandom_element(G.GAME.suit, 'aniceoutfit')
            local card_to_change = pseudorandom_element(G.hand.cards, 'shufflethedeck')
                      G.E_MANAGER:add_event(Event({
                           func = function()
                           SMODS.change_base(card_to_change, suit)
                           return true
                     end
             }))  
        end   
   end 
}```

Why isn't this applying a new suit?
frosty rampart
#

G.GAME.suit isn't a thing

unkempt bronze
#

Well, what should I replace it with?

daring fern
unkempt bronze
#

thank you, the both of you

frosty rampart
#

and then you'll have to use suit.key in the change_base call

#

at least i don't think change_base can handle taking a whole suit object

unkempt bronze
#

so, just SMODS.suits?

atomic edge
#

what is the simplest shader in balatro

unkempt bronze
daring fern
unkempt bronze
# daring fern Code?
    key = "qwefeqrgaergar",
    set = "xiferp_Keyboard",
    atlas = "Golden_Typewriter",
    cost = 3,
    pos = { x = 0, y = 0 },
    unlocked = true,
    discovered = true,
    can_use = function(self, card)
      return true
    end,    
    loc_txt = {
        name = 'qergwetgwqetgt',
                text = {
                    'Gives 1 random card a random suit',
                    'and adds +5 chips to your next hand.',
                },
            },
    use = function(self, card, area, copier)
        G.GAME.xiferp_text_chips = (G.GAME.xiferp_text_chips or 0) + 5        
    calculate = function(self, card, context)
            local suit = pseudorandom_element(SMODS.Suit.obj_buffer, 'aniceoutfit')
            local card_to_change = pseudorandom_element(G.hand.cards, 'shufflethedeck')
                      G.E_MANAGER:add_event(Event({
                           func = function()
                           SMODS.change_base(card_to_change, suit)
                           return true
                     end
             }))  
        end   
   end 
}```
daring fern
unkempt bronze
#

Sure that'll work?

daring fern
unkempt bronze
winter flower
#

im a bit confused on why this keeps crashing

daring fern
daring fern
winter flower
#

well that's something i haven't realized yet, strict ordering

dapper sun
#

does anyone know how to make a custom info_queue message type

unkempt bronze
# daring fern Code?
SMODS.Consumable {
    key = "magnesium",
    set = "xiferp_Element",
    atlas = "Golden_Brick_Road",
    cost = 3,
    pos = { x = 0, y = 0 },
    unlocked = true,
    discovered = true,
    can_use = function(self, card)
      return true
    end,    
    loc_txt = {
        name = 'Magnesium',
                text = {
                    'Gives 1 random card a random suit',
                    'and adds +5 chips to your next hand.',
                },
            },
    use = function(self, card, area, copier)
        G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 5        
            local suit = pseudorandom_element(SMODS.Suit.obj_buffer,'aniceoutfit')
            local card_to_change = pseudorandom_element(G.hand.cards, 'shufflethedeck')
                      G.E_MANAGER:add_event(Event({
                           func = function()
                           SMODS.change_base(card_to_change, suit)
                           return true
                     end
             }))  
        end   

}```
Here is the actual code
#

Well? Why isn;t it working?

dapper sun
#

i have a joker that changes the rank of cards before scoring, is it possible to make it re-evaluate the hand type?

daring fern
unkempt bronze
#

More accurately, how do I pick a random suit and apply it?

daring fern
unkempt bronze
dapper sun
faint yacht
#

iirc you could also pass SMODS.Suits to pseudorandom_element, though?

unkempt bronze
#

lemme check

faint yacht
#
Even though SMODS.Suits and SMODS.Ranks are unordered tables, it is possible to feed them directly into pseudorandom_element to get a random suit or rank while respecting in_pool. Example: local rank = pseudorandom_element(SMODS.Ranks, pseudoseed('myrank'))
unkempt bronze
#

Didn't seem to work...

#

local suit = pseudorandom_element(SMODS.Suits,'aniceoutfit')
stuck it in like this

frosty rampart
#

add a debug print(suit) after that line to see if it's actually getting a suit

unkempt bronze
#

now it just breaks, as it's expecting a table that isn't there

frosty rampart
#

ok so it's not an issue with the pseudorandom call
revert back to how you had it when it printed spades

when are you using the consumable? during a blind?

vernal plank
#

anyone knows how to make a deck that starts with a specific joker?

daring fern
vernal plank
snow needle
#

can anyone help me?

#

how do i matchmake in multiplayer balatro

#

all i can do is join directly to lobbys

gusty compass
gusty compass
#

idk

#

also what could i do here to make this more discreet, since cards that flip via the effect have a short period of time where they can be seen by the player:

#
SMODS.Back{
    key = "GG_eclipsedeck",
    atlas = "atlasholders",
    pos = {
        x = 4,
        y = 2
    },

    loc_txt = {
        name = "Eclipse Deck",
        text = {
            "Cards may be drawn face down",
            "according to the amount of",
            "hands left, {C:blue}+1{} hand",
            "every round"
        }
    },

    apply = function(self)
        G.E_MANAGER:add_event(Event({trigger = "after",
            func = function()
                G.GAME.round_resets.hands = G.GAME.round_resets.hands + 1

                return true
            end,
        }))
    end,

    calculate = function(self, deck, context)
        if context.hand_drawn then
           for k, v in pairs(context.hand_drawn) do
                if v.facing ~= "back" and pseudorandom("eclipsedeck") < G.GAME.current_round.hands_left * 0.03 then
                    v:flip()
                end
            end 
        end
    end
} ```
flat cypress
#

how do you make the unlock requirement of a card be “win a run with this specific joker (for example Blueprint)”? I can’t remember for the life of me

unkempt bronze
#

Look up similar cards on VanillaRemade

flat cypress
#

are there any Vanilla cards where the unlock requirement is based on winning a run with a different joker? Am I tripping? I could have sworn there weren’t

daring fern
flat cypress
slim ferry
#

return stay_flipped = true to draw a given card face down

flat cypress
#

basically, what I’m doing is making temporary upgrades of Vanilla jokers. If you happen to win a run with one in the upgraded state, you unlock the corresponding legendary version (usually the same effect but doesn’t downgrade back to the vanilla joker).

Is there a way to block all legendaries in a certain pool from spawning via The Soul until after they’ve been properly unlocked? I think I could do it with flags but if there’s another way to do it that doesn’t require hundreds of flags that would be nice

unkempt bronze
frosty rampart
#

wait to be clear
is the issue that it's not changing the suit for a random card, or that it's not buffing the next hand?
because you literally have zero code to do the "buffing the next hand" part

gusty compass
# slim ferry use context.stay_flipped

Does this abide with individual cards or the entire hand? since I'm planning to make it where the deck uses pseudorandom + hands left to determine the chance of a card getting flipped

slim ferry
#

individual cards

unkempt bronze
frosty rampart
#

ok i dunno then

unkempt bronze
#

neither do I, that's why I'm asking around

gusty compass
slim ferry
#

flipping back forward would have to be done during a seperate context

#

stay_flipped is only called once when a card is drawn

gusty compass
#

Could you demonstrate it perhaps?

slim ferry
#

well

#

idk what youre trying to do

#

i thought you only had to flip newly drawn cards for your thing

gusty compass
#

Yea, the deck would flip it similar to blinds like the wheel

#

But I am a bit puzzled why it unflipped the second hand and not the first

slim ferry
#

it should not unflip anything with context.stay_flipped

gusty compass
#

It seems to be unflipping rn since I'm testing it

slim ferry
#

did you remove the context.hand_drawn part

gusty compass
#

Yea?

#

Well it's kinda a good thing that the cards unflip in all seriousness

slim ferry
#

is there anything else that could mess with flipping cards or smth

#

<@&1133519078540185692>

gusty compass
#

Third time wtf

#

How long has this happened?

ivory citrus
#

Hello, does anyone know if I can make my flags affect vanilla cards?
For example: Wheel of fortune
1 in 4 to Foil, Holo or Poly -> 1 in 4 to Poly

unkempt bronze
# frosty rampart ok i dunno then
SMODS.Consumable {
    key = "magnesium",
    set = "xiferp_Element",
    atlas = "Golden_Brick_Road",
    cost = 3,
    pos = { x = 0, y = 0 },
    unlocked = true,
    discovered = true,
    can_use = function(self, card)
      return true
    end,    
    loc_txt = {
        name = 'Magnesium',
                text = {
                    'Gives 1 random card a random suit',
                    'and adds +5 chips to your next hand.',
                },
            },
    use = function(self, card, area, copier)
        G.GAME.xiferp_alkemetal_chips = (G.GAME.xiferp_alkemetal_chips or 0) + 5        
            local suit = pseudorandom_element(SMODS.Suits, 'aniceoutfit')
            print(suit)
            local card_to_change = pseudorandom_element(G.hand.cards, 'shufflethedeck')
                        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()
                card_to_change:flip()
                return true
             end
             }))
             end
             G.E_MANAGER:add_event(Event({
                trigger = 'after',
                func = function()
                    SMODS.change_base(card_to_change, suit)
                    return true
                end
               }))
             G.E_MANAGER:add_event(Event({
             trigger = 'after',
             delay = 0.15,
             func = function()
                  card_to_change:flip()
                  return true
             end
            }))
     end

}```
testing this version (with flips)
gusty compass
#

Yea ok, the cards seem to unflip improperly, I played a high card and the second concealed card was unflipped while the first one wasnt...

vernal plank
#

i'm trying to make a custom deck, but the deck's art always looks like checkered deck

#

any fix for this?

slim ferry
#

did you put in the correct atlas

#

or rather

#

remember to define an atlas at all

vernal plank
slim ferry
#

on the deck i mean

#

deck code?

vernal plank
slim ferry
#

no

#

the code

#

all of it

vernal plank
#

imma share it rq

gusty compass
#

I could try initial_scoring_step to ensure the played cards are unflipped?

#

Or is that the wrong context in this equation

slim ferry
#

cards are always unflipped when they are played

gusty compass
#

Some cards seem to not follow this rule, especially when some don't score

unkempt bronze
#

One last issue, how do I apply a suit to a card?
because SMODS.change_base(card_to_change, suit) isn't working, even though both variables are defined

slim ferry
#

whats the code look like

gusty compass
#

It is very generic 🙏

slim ferry
#

?

gusty compass
#

Like basic

slim ferry
#

i just want to see the code vro

gusty compass
#

Ok sorry 😔

#
SMODS.Back{
    key = "GG_eclipsedeck",
    atlas = "atlasholders",
    pos = {
        x = 4,
        y = 2
    },

    loc_txt = {
        name = "Eclipse Deck",
        text = {
            "Cards may be drawn face down",
            "according to the amount of",
            "hands left, {C:blue}+1{} hand",
            "every round"
        }
    },

    apply = function(self)
        G.E_MANAGER:add_event(Event({trigger = "after",
            func = function()
                G.GAME.round_resets.hands = G.GAME.round_resets.hands + 1

                return true
            end,
        }))
    end,

    calculate = function(self, deck, context)
        if context.stay_flipped then
            if pseudorandom("eclipsedeck") < G.GAME.current_round.hands_left * 0.05 then
                return {
                    stay_flipped = true
                }
            end
        end
    end
}```
slim ferry
#

hmmmmmmmmmmm

#

okay im just going to guess

#

do you have wierd face-down cards that are also like darker than normal

gusty compass
#

Uh, I don't think so

#

They all appear normal as far as I can tell

slim ferry
#

because im pretty sure those are like the wierd inbetween state of ghost cards and real cards where they can be selected/played but dont score or do anything

gusty compass
#

well it could be since it doesnt do it when every card scores, but if its like a few cards that score, few dont, there are inconsistencies

slim ferry
#

i mean theres definitely something wierd going on with your cards

#

idrk what though

gusty compass
#

i dunno if context.initial_scoring_step allows me to get the full hand so if thats the case, i could just run a for loop to skim through the cards for this

#

its context.full_hand i reckon so i could just use that if its available

vernal plank
slim ferry
#

yeah

#

the atlas is not on your deck

#

your deck needs an atlas field

vernal plank
gusty compass
#

Well it seems like it's working, small delay but it does seem remotely functional

vernal plank
#

I already put hapodeck.png in both 1x and 2x

slim ferry
#

did you get the position right

vernal plank
#

hold on

vernal plank
slim ferry
#

jokers should be a table of keys

vernal plank
#

as in, i can see it, but it's like way smaller

slim ferry
#

and you dont need the apply to add the joker

slim ferry
vernal plank
slim ferry
#

did you not accidentally mix up the 1x and 2x

vernal plank
slim ferry
#

no

#

2x is supposed to be bigger

#

than the 1x

vernal plank
#

yet it's still small

slim ferry
#

what is the size of the actual image file

vernal plank
#

I finally found a fix and the deck FINALLY works

wary quail
#

disregard the previous message, I totally fixed it and didn't realize

ivory citrus
broken rivet
#

does anyone know how to investigate a framerate drop like this? i have a feeling it might be a result of trying to use a for loop to allow multiple mod calculates but i'm not sure how to even begin looking into this sort of thing

#

the framerate goes from 75 to 66 at one point