#💻・modding-dev

1 messages · Page 682 of 1

rapid stag
#

what's the crash message

final jewel
#

like so

rapid stag
#

no

#

key = 'your_localization_key_here'

final jewel
#

I'll change the key

fickle gust
#

-# hotpot being my mod

#

-# also anegative is the name of the edition

red flower
#

where is your shader located because the path looks wrong

#

also i wouldnt recommend to name your mod hotpot haha

fading rivet
final jewel
#

like that, sorry Im not sure where I supposed to do things

fickle gust
#

rebrand time

rapid stag
fading rivet
red flower
fickle gust
red flower
rapid stag
#

probably collection shenanigans if i had to guess 🤷‍♀️

red flower
#

the one thats crashing is anegative

final jewel
red flower
red flower
rapid stag
final jewel
#

oh

#

but how do I remove from pool

fickle gust
final jewel
#

I didnt know I could do that

red flower
#

use the take_ownership to return false in in_pool and add no_collection = true

final jewel
#

so theirs no way that the normals joker coul spawn

red flower
#

the only problem is that vanilla is hardcoded to give j_joker as a fallback so you need to change that too

fickle gust
#

nvm my issue is solved.

red flower
#

if you just want to prevent vanilla jokers you can hook SMODS.add_to_pool

red flower
final jewel
#

this will prevent vanilla joker from spawning, nice

elder yoke
#

Hey, could someone please help me? I've been trying to get debugplus to work for help with mod testing, but for some reason the mod doesn't work, even though it is in the mod file, and the other mods in there work fine. Does anyone know what could cause this?

fickle gust
elder yoke
fickle gust
#

what happens when you press TAB in game?

elder yoke
#

nothing

gilded blaze
#

hold TAB

elder yoke
#

still nothing happens.

gilded blaze
#

is Brainstorm also installed

elder yoke
#

Do you need it to use debugplus? if so then that's the reason it doesn't work then.

gilded blaze
#

Brainstorm has its own debug toggle that may mess up with DebugPlus'

#

oh

#

does the console work

fickle gust
#

could we get your modpack?

elder yoke
#

heres my mod file, "Sargeant test" is my mod file that im trying to test if you are wondering.

fickle gust
#

but no because they said it didn't appear in mod menu

elder yoke
#

that is correct.

gilded blaze
#

lovely 0.9 should be able to handle nested folders iirc
why is debugplus not working 😭

#

wait

#

check debugplus folder, is it nested

elder yoke
#

what do you exactly mean with nested? im new with modding so i dont know all the terms and such.

fickle gust
#

like is there another folder inside of debugplus

#

that is also called debugplus

#

(or like debugplus-main)

elder yoke
#

Yes there is.

fickle gust
#

that's your issue

#

put the folder that was inside debugplus into your main mod folder

#

then it should work

elder yoke
#

Move the debugplus folder from the debugplus folder into the mod folder, okay

#

do i delete the other one then?

fickle gust
#

doesn't matter really but yeah

elder yoke
#

okay, i will see if it works right now.

#

Okay, it seems that doing that did not work unfortunately.

fickle gust
#

alr, just in case, check inside the new debugplus folder, maybe it's nested too X3
-# i don't really know what to try now..

elder yoke
#

this is the inside of the debugplus folder.

gilded blaze
#

ok, I believe it's installed incorrectly

elder yoke
#

What do i do to fix it?

gilded blaze
#

reinstall
this is how mine looks

fickle gust
#

mine looks like this

#

-# fresh install of 1.5.2

gilded blaze
#

looks shorter because I use git

elder yoke
sleek valley
#

The only other problem i could think off is a conflict problem with your test mod, unless something happened when you were installing smods

red flower
elder yoke
red flower
#

hmm idk my only guess is that the folder is still nested

fickle gust
elder yoke
sleek valley
elder yoke
#

but it doesn't because i tried that

sleek valley
#

Well shit man, idk

elder yoke
sleek valley
#

Which file

elder yoke
#

the mod file i was working on

sleek valley
#

Right okay

#

Then it has to be a problem with smods then??

elder yoke
#

this is how smods look

idle plaza
elder yoke
#

yet it works.

#

how do these kind of things keep happening to me-

fickle gust
#

hey, quick question, how does the negative edition add a joker slot? can't find anything that does that in it's code

SMODS.Edition {
    key = 'negative',
    shader = 'negative',
    prefix_config = {
        -- This allows using the vanilla shader
        -- Not needed when using your own
        shader = false
    },
    config = { card_limit = 1 },
    in_shop = true,
    weight = 3,
    extra_cost = 5,
    sound = { sound = "negative", per = 1.5, vol = 0.4 },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.edition.card_limit } }
    end,
    get_weight = function(self)
        return self.weight
    end,
    draw = function(self, card, layer)
        if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' and (card.config.center.discovered or card.bypass_discovery_center) then
            card.children.center:draw_shader('negative', nil, card.ARGS.send_to_shader)
            if card.children.front and card.ability.effect ~= 'Stone Card' then
                card.children.front:draw_shader('negative', nil, card.ARGS.send_to_shader)
            end
            card.children.center:draw_shader('negative_shine', nil, card.ARGS.send_to_shader)
        end
    end
}```
idle plaza
elder yoke
sleek valley
idle plaza
elder yoke
#

im going to try something myself

#

im going to restart my PC and see what happens

elder yoke
elder yoke
#

okay so restarting my PC did nothing

#

also quick question, is it normal for your mod to work with an empty file?

fickle gust
idle plaza
elder yoke
#

currently im going try and redownload debugplus and see if anything changes

#

Also did nothing.

idle plaza
#

What happens if you try to download some other mod?

elder yoke
#

uh let me see

red flower
elder yoke
#

well, the mod i downloaded also doesn't work

#

im starting to think it might be the mod file itself

sleek valley
red flower
#

in the wiki it says that it won't support betas

sleek valley
#

Oh yeah, missed that part

elder yoke
#

Okay this is getting ridiculous, i have removed the file from my mod folder and the mod still shows up in my mod folder.

#

like how

fading rivet
elder yoke
red flower
elder yoke
#

wait

#

wait wait wait wait

#

okay, i think i might've realised what the problem is

sleek valley
#

What was it then?

elder yoke
#

im testing smth rn

frosty dock
#

wrong mod folder probably

elder yoke
#

it might be stupider

#

I GOT IT!

#

okay let me explain what happened. So when i was setting things up, i made a sort of link to the mod file so i didn't have to look through all the files to find the mod. The thing is however that the link for some reason didn't update the actual files, meaning the mods i added/removed weren't in the real mod folder to begin with.

#

i feel stupid for not noticing that

sleek valley
#

🤦‍♀️

idle plaza
#

I wondered if it was somehow a "wrong mods folder" situation since nothing was changing, but had no clue what would possibly resulting in there being any other mod folder than just the one. That answers the 'how'.

elder yoke
#

welp, lesson learned. do not make links to mod folder because stuff like this would happen-

drifting garden
#

how would i make a joker's calculate retrigger all other retrigger effects an additional time?

#

or is calculate not the right place to do that?

red flower
tall sonnet
#

can anyone helpp me make my 1st ever mod

frosty rampart
tall sonnet
frosty rampart
#

it's unrelated
but i would recommend avoiding balatro mod manager, it tends to cause issues

tall sonnet
#

I dont know how to use other mod thing

frosty rampart
#

gee, step 1 of the link i posted would probably help you learn to install mods without balatro mod manager

#

you'll need to interact with those files anyway to be able to make a mod

tall sonnet
#

k ty

tall sonnet
#

I do this on main.lua right (im kinda new so idk)

tall sonnet
#

ok thank you for helping me out

tall sonnet
#

do it from the easy way

#

I mean whats this?

red flower
tall sonnet
#

really

#

omg then Im dum

red flower
#

the other tutorials are not easier they are outdated

tall sonnet
#

well

#

Im cooked then

#

I mean Im stuck here

dapper sun
#

that's old af

red flower
tall sonnet
#

no

#

i dont even know whats that

tall sonnet
#

are links allowed here?

red flower
#

yes

tall sonnet
#

this right?

plucky lantern
#

yea

red flower
#

yeah

tall sonnet
#

alr tysm

#

I made this and now trying to find the function thing

#

It should be like this right?

plucky lantern
#

ask in jokerforge disc

tall sonnet
#

ok

#

how do I download this
(I have normal steam modded)

frosty rampart
#

your smods is very old, you need to update it

frosty dock
#

you have old af steamodded

#

like 9 months

tall sonnet
#

so I download newest ver right

frosty dock
#

yea

tall sonnet
frosty dock
tall sonnet
#

dont tell me there is another smods there

frosty dock
#

if there is, that's wrong

tall sonnet
#

yeah there is

frosty dock
#

you'd want to move that out

tall sonnet
#

I moved that out to the mods folder

frosty dock
#

now most likely it's gonna crash and you're gonna have to update lovely

tall sonnet
#

YOURE SO GOATED

#

TYSM

#

it works now

frosty dock
#

awesomesauce

fringe oxide
#

trying to get this modded joker to work,
(burnt, stunned, and actionable are custom enhancements, and their names are their respective keys)

sleek valley
#

what exactly is the problem? is it just not showing up?

fringe oxide
#

heres its rules

sleek valley
#

alright well for starters, i could be wrong
but i dont think it's a good idea to have an entire function inside a return

fringe oxide
sleek valley
#

never used jokerforge personally, i've heard it's not great :/

fringe oxide
#

i mean i cant code so what other option do i have lol

#

im in too deep anyway

sleek valley
#

nah, that's fair, im not saying it's your fault!!
moreso the fault of whoever made jokerforge lol

fringe oxide
#

yeah

#

well i did modify the code a little bit, i changes the enhancements keys into my custom ones so itd (hopefully) work properly

#

apparently it dont work like that so idk how to fix it

sleek valley
#

just ctrl + f for "steel" and base it off that, i can help a bit more from there if need be

fringe oxide
#

ok gimme a quick sec

fringe oxide
sleek valley
#

aight, so you'd mostly wanna replace:
if SMODS.has_enhancement(playing_card, 'm_steel') then steel_tally = steel_tally + 1 end
with:

if SMODS.has_enhancement(playing_card, '[your_enhancement_key]') then 
  enhance_tally = enhance_tally + 1
end
#

and duplicate the SMODS.has_enhancement() part for each enhancement you want to check for

fringe oxide
sleek valley
#

it doesnt look like you changed anything

fringe oxide
#

wait what

#

oh ur right

#

yeah nvm

sleek valley
#

i can write it for you if you want and comment it to help you understand better

sleek valley
#

cool, gimme a sec :3

obtuse mortar
#

chatroom i need a little help i was like oh for sure i got this And then it crashed immediately upon playing a single card 😭🕊️🕊️

rapid stag
#

what was the error you got

obtuse mortar
sleek valley
#

lmk if there's another problem

rapid stag
# obtuse mortar well it did this

G.play.cards.base.nominal here's your problem. G.play.cards is the table of cards in your played hand. so it doesn't find base

you need to do G.play.cards[i].base.nominal

obtuse mortar
#

i see

#

i was looking at the raised fist code and mustve missed that bit

fringe oxide
sleek valley
#

okay well what does the description say?

sleek valley
#

okay, how did you paste the code i gave you exactly?

fringe oxide
sleek valley
#

copied the code into your fsness file right? and did you delete or comment out the code you had earlier?

fringe oxide
#

i got rid of the old code entirely and renamed your code to the old files name

#

and then i replaced it

sleek valley
#

alr in that case, that's weird then

#

are you using a saved game or debugplus savestate?

tranquil cypress
#

i think they just need to replace the enhancment keys with their own ones

fringe oxide
#

i do have debugplus installed but i didnt use savestates

fringe oxide
#

maybe i did it wrong

sleek valley
#

so if you arent seeing the "Chips" at the end of that line, it's a save issue

tranquil cypress
#

ah

fringe oxide
#

save file or save state

sleek valley
#

save state
im basically saying start a new run

fringe oxide
#

ok

fringe oxide
#

or is this my old one

#

oh its MINE 😭

#

bruh

fringe oxide
sleek valley
#

Hmmmm

fringe oxide
#

same as last time

sleek valley
#

Honestly i aint sure what i did wrong from here

#

And sadly, im having dinner, so i cant fix it

fringe oxide
#

i gotta go to gym class soon too so

#

oh well

#

thx for tryin

sleek valley
#

SHIIIIIT I KNOW WHAT I DID WROOOOONGGG

obtuse mortar
rapid stag
# obtuse mortar so this did fix the crashing. however. new issue encountered: it isn’t resetting...

these conditions are set up wrong:

if context.full_hand then
    for i = 1, #G.play.cards do
        BlackjackCount = BlackjackCount + G.play.cards.base.nominal
    end
    if BlackjackCount == 21 then
       card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
    end
else if BlackjackCount > 21 then
    local last_mult = card.ability.extra.Xmult
    card.ability.extra.Xmult = 1
    if last_mult > 1 then
       return {
         message = localize('k_reset')
       }
    end
end

you want it like this:

if context.full_hand then
    for i = 1, #G.play.cards do
      BlackjackCount = BlackjackCount + G.play.cards.base.nominal
    end
    if BlackjackCount == 21 then
      card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
    else if BlackjackCount > 21 then
      local last_mult = card.ability.extra.Xmult
      card.ability.extra.Xmult = 1
      if last_mult > 1 then
         return {
           message = localize('k_reset')
         }
      end
    end
end
sleek valley
#

@fringe oxide whenever you get back, i think i've figured it out this time

frosty dock
#

it's supposed to be elseif

obtuse mortar
#

much appreciated

vale grove
#
        local _poker_hands = {}

        for handname, _ in pairs(G.GAME.hands) do
            if SMODS.is_poker_hand_visible(handname) and handname ~= card.ability.extra.poker_hand then
                _poker_hands[#_poker_hands + 1] = handname
            end
        end

        local selected_hand = pseudorandom_element(_poker_hands, 'YA_to_do')
        card.ability.extra.poker_hand = selected_hand

        for i = 1, 3 do
            local hand = G.GAME.hands[selected_hand]
            hand.level = hand.level + 1
        end

i have this consumable that functionally levels up a random hand 3 times but it doesnt do it visually, how do i do it visually?

mystic river
#

don't increase the level variable directly

#

that would also fail to change the chips and mult

#

use the level up function. it's somewhere in the smods code

vale grove
#

i didnt even notice

frosty dock
frosty dock
#

np

#

as for my nick, it's opposite day

sleek valley
#

no, it's april fool's day
opposite day is January 25th

granite raptor
#

is there a booster_create_flags for context.create_booster_card?

sturdy compass
#

I believe so yes

bold eagle
#

ive made a custom rarity and put a joker into it, but it's still not appearing in the shop

frosty dock
bold eagle
#

yeah

scenic umbra
#

also if it's a seperate file do you have it set to load from the main

bold eagle
#

yeah its all set to load

scenic umbra
#

interesting

bold eagle
#

it all shows up in game but not in the shop

#

like

#

if i go to mod additions its there and right

scenic umbra
#

but the rarity isnt displaying?

bold eagle
#

rarity is displaying it's just not showing in the shop

#

like

scenic umbra
#

hmmm that's interesting

bold eagle
#

i have the rarity set very high weight, but its not showing up in the shop

scenic umbra
#

I went a seperate route with my rarity

#

So I never had to do that stuff

fringe oxide
#

i wont be online im in game club tho

bold eagle
#

i based mine off the ones in vanilla remade

sleek valley
fringe oxide
sleek valley
#

did you start a new run to be sure?

scenic umbra
#

do you have it set to spawn in the joker pool?

bold eagle
#

i misunderstood what it was saying to do on smods wiki, its working now

bold eagle
scenic umbra
#

ahhhh

#

i was looking at that code like something is missing here

bold eagle
#

yeahhhh

scenic umbra
#

lmfao time to make another unnecessary mod

obtuse mortar
#

ok so ive gotten everything to function properly but then i tried to set up the mod in the same way shown in the Beginner’s Guide to Making Balatro Mods video (rather than having everything on a single main.lua file) and the joker is Not showing up?? 🥀 the mod is being recognized as it shows up on the mod list but the joker itself isn’t actuall showing up 🕊️

inner terrace
#

Is there any way to make an entirely dummy card and change its text through the card.config or card.children subtables? I'm trying to have multiple variants of the same card appear in a popup context menu with different descriptions, which means they need to be distinct cards otherwise as far as I can tell changing either will change both

timid zinc
#

is there a way to give a message a longer lifetime?

daring fern
bold eagle
#

im wondering if there's any way to make a joker appear in the same pools as legendary jokers (soul, cryptid legendary deck, etc.) while having a custom rarity

obtuse mortar
#

what makes it so odd is that the other effects are working perfectly

#

the +chips and Xmult work fine on the first activation, it's just exclusively the all cards score that doesnt

#

almost forgot but here's the joker code. everything else is working so ive no idea what it is

#

im very confused (dont mind my placeholder texture balatrojoker)

frosty rampart
#

modify_scoring_hand might actually come before context.before, so it's actually using the blackjack status of the previous hand (and on the first hand, that's nil because the variable doesn't exist yet)

#

not related to the thing functioning, but you should probably store BlackjackCount as a variable in the joker's ability table instead of it just being a global like that

obtuse mortar
#

so then if i were to check for the chips value during modify_scoring_hand rather than before it should potentially work?

frosty rampart
#

i think so, yea

obtuse mortar
#

well it fixed the scoring issue but now the chips and mult dont activate Ever

vale grove
#
            if context.before then
                for _, scored_card in ipairs(context.scoring_hand) do
                    local seal_pool = {
                        "Red",
                        "Blue",
                        "Gold",
                        "Purple",
                        "seal_fent",
                        "seal_discord",
                        "seal_seal_seal",
                        "seal_scrumball"

                    }

                    local random_seal = pseudorandom_element(seal_pool, pseudoseed("rand_seal"))
                    scored_card:set_seal(random_seal, nil, true)

                    G.E_MANAGER:add_event(Event({
                        func = function()
                            scored_card:juice_up()
                            return true
                        end
                    }))
                end
            end

iam trying to make a joker that applies a random seal on a card.
currently i get the error card:618: attempt to index a nil value

rapid stag
obtuse mortar
#

your help was much appreciated balatrojoker

bold eagle
#

I'm trying to make a tarot card for my mod but it's not showing up in the additions section in game, or the tarot cards menu

#

never mind i accidentally put an = on line one

daring fern
vale grove
#

I was just calling the keys wrong

daring fern
frosty rampart
#

it'll let you respect the new weights system

#

instead of assuming that all seals have the same chance to be generated

scenic umbra
#

Should I put the message here as well?

bold eagle
#

is there a pool for the jokers that can spawn from a soul? I want to add a joker with a custom rarity that would act like a legendary

frosty rampart
#

no separate pool, it literally just searches through the set of legendary jokers

bold eagle
#

so theres no way to have one with a custom rarity be spawnable by the soul?

true jasper
rapid stag
#

you could make one girldmNodders

bold eagle
#

im very new to this and know like no lua

true jasper
bold eagle
#

woah

#

thank you

true jasper
#

@bold eagle in the SMODS.add_card in the soul use function make sure the set is the key for your pool you made

bold eagle
#

ok

#

so sould i just like, copy paste all the code from the vremade soul?

#

and make adjustments?

true jasper
bold eagle
#

ok

#

thank you

primal robin
#

is there easy way to make joker not crash when it's played in hand?

bold eagle
#

because i want to be able to use other modded legendaries with it

fringe oxide
#

what does >=1.* mean

frosty rampart
#

this is a malformed dependency string that wasn't ever supposed to work, but it used to
go into the mod's json file and delete whatever line says "Steamodded (>=1.*)", and you should be good to go

fringe oxide
#

it crashed lol

#

yeah i dont need that mod to work

rapid stag
#

is the april fools' update that balatro no longer restarts when you press R on the crash screen

bold eagle
#

how do i iterate through a pool of jokers/rarity

#

i cant find it anywhere

primal robin
true jasper
#

@bold eagle apologizes for the late response but this should work

SMODS.ObjectType({
    key = "placeholder",
    cards = {
        -- your stuff here
    },
})

for k, v in pairs(G.P_JOKER_RARITY_POOLS[4]) do
    SMODS.Joker:take_ownership(v.key, {
        pools = { ["placeholder"] = true },
    }, true)
end```
bold eagle
#

does p_joker_rarity_pools get replaced by anything?

#

also thank you

bold eagle
true jasper
bold eagle
#

it didnt work but thank you for all the help

rapid stag
#

i have a joker effect that, when glass cards break, they're immediately recreated with +1 chance denominator (1 in 4 -> 1 in 5, etc.), an additional X2 mult, but are debuffed until the next ante.

they don't appear to be being added to the deck correctly? what am i doing wrong here that the deck limit is doing this

vale zinc
near coral
#

The shader for tanzanite seal is the same as gold seal's yet looks too bright for some reason

daring fern
# near coral This is the code for tanzanite seal
draw = function(self, card, layer)
    if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
        G.shared_seals[self.key].role.draw_major = card
        G.shared_seals[self.key]:draw_shader('dissolve', nil, nil, nil, card.children.center)
        G.shared_seals[self.key]:draw_shader('voucher', nil, card.ARGS.send_to_shader, nil, card.children.center)
    end
end
near coral
#

Is that supposed to replace everything from line 15 onwards?

daring fern
near coral
#

So only line 15?

daring fern
near coral
#

It didn't work

#

It's still super bright

#

Unless I did something wrong

SMODS.Seal({
    key = "tanzanite",
    atlas = "BZR_Seals",
    pos = { x = 2, y = 0 },
    badge_colour = HEX '2E76FD',
    shiny = true,
    gold = true,
    config = { shiny = true, gold = true },
    calculate = function(self, card, context)
        if context.discard and context.other_card == card then
            ease_dollars(-3)
            card.ability.perma_bonus = (card.ability.perma_bonus or 0) + 10
        end
    end,
        draw = function(self, card, layer)
    if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
        G.shared_seals[card.seal].role.draw_major = card
        G.shared_seals[card.seal]:draw_shader('dissolve', nil, nil, nil, card.children.center)
        G.shared_seals[card.seal]:draw_shader('voucher', nil, card.ARGS.send_to_shader, nil, card.children.center)
    end
end
})
true jasper
#

how would i apply a custom dynatext to a badge text

gilded blaze
obtuse mortar
#

pardon me if this is a silly question but. is it necessary to set jokers to be available in shops? ive been rerolling shops with debug for like 20-30 minutes and ive not been able to get it appear :(

sturdy compass
#

Do you have DebugPlus

obtuse mortar
#

yeag

#

ive already tested everything else properly i just want to make sure it can actually appear in shop

sturdy compass
#

You don't need to reroll for it

#

you can go to collections and press '3' while hovering over it to spawn it in

obtuse mortar
#

well yea i did that for testing the effects, again i just wanted to make sure that it is able to appear in shop and is purchasable nd stuff balatrojoker

sturdy compass
#

Oh I see

#

You don't have an in_pool function attached to your joker do you?

#

If you do not then that's fine

#

You're very likely just getting really terrible luck lol

obtuse mortar
#

i don’t think so no

#

i see

round lion
#

do objecttypes actually check if the rarities in the rarities table exist before using them?

coral flume
#

Anyone know why I can't use this spectral card? Heres the can_use code

    can_use = function(self, card)
      if G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] then return true end
    end,
sturdy compass
#

I don’t think you need the third argument tbh

coral flume
#

Fixed it :D

reef bobcat
#
     loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult, localize(card.ability.extra.suit, 'suits_singular') } }
    end,
    calculate = function(self, card, context)
         if context.individual and context.cardarea == G.play and
            context.other_card:is_suit(card.ability.extra.suit) then
            return {
                mult = card.ability.extra.mult
            }
        end
         if context.joker_main then
              for _, playing_card in ipairs(context.scoring_hand) do
            if playing_card:get_id() == 12 then
                for k, v in pairs(context.full_hand) do
        if v.base.suit == 'Clubs' or v.base.suit == 'Hearts' or v.base.suit == 'Spades' then
            SMODS.change_base(v, 'Diamonds')
        end
    end,
}```

something about this is crashing the game, the ends it seems, i've tried adding more and less but nothing is working
vale zinc
#

I have these context events that keep track of every card destroyed in a run. Whenever I destroy some cards, the game suffers a thread error a few seconds after I discard any cards. What do I do?

LAPSEMS.shallow_copy = function(t)
    local t2 = {}
    for k,v in pairs(t) do
        t2[k] = v
    end
    return t2
end

--[[
Code adapted from Extra Credit's Ship of Theseus.
--]]
if context.cards_destroyed then
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        blockable = true,
        blocking = false,
        func = function()
            G.GAME.LAPSEMS_cards_destroyed_this_run = G.GAME.LAPSEMS_cards_destroyed_this_run or {}
            for k, val in ipairs(context.glass_shattered) do
                G.GAME.LAPSEMS_cards_destroyed_this_run[#G.GAME.LAPSEMS_cards_destroyed_this_run + 1] = LAPSEMS.shallow_copy(val)
            end
            return true
        end
    }))
elseif context.remove_playing_cards then
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        blockable = true,
        blocking = false,
        func = function()
            G.GAME.LAPSEMS_cards_destroyed_this_run = G.GAME.LAPSEMS_cards_destroyed_this_run or {}
            for k, val in ipairs(context.removed) do
                G.GAME.LAPSEMS_cards_destroyed_this_run[#G.GAME.LAPSEMS_cards_destroyed_this_run + 1] = LAPSEMS.shallow_copy(val)
            end
            return true
        end
    }))
end
vale zinc
#

The error message is not informative.

Oops! The game crashed:
Thread error (Thread: 0x01e30c8e3c70)

engine/string_packer.lua:43: attempt to concatenate local 'v' (a userdata value)
stack traceback:
engine/string_packer.lua:43: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:37: in function 'STR_PACK'
engine/string_packer.lua:69: in function 'compress_and_save'
engine/save_manager.lua:82: in main chunk
normal crest
vale zinc
normal crest
#

what you were doing was the equivalent of trying to save the card object directly, just without the metatables

zealous path
#

is there something to check if a repetition has occured. i need for something im making rn, i want it so that it does something every time a repetition occurs

drifting garden
#

how do you track the last sold joker?

fringe oxide
fringe oxide
#

its affecting the base game too even when the mod folder is removed

daring fern
drifting garden
#

i have looked at how pinkprint does it, but ortalab has some of its own definitions and i have no idea how to actually do something similar

tepid heron
#

hey does anyone know how to fix this

daring fern
red flower
tepid heron
#

oops.

drifting garden
daring fern
drifting garden
daring fern
tepid heron
#

hey does anyone know how to change like the round/blind number

daring fern
drifting garden
# daring fern You would do this: https://discord.com/channels/1116389027176787968/120950636098...

what do i actually wrap this in?

if G.GAME.nmb_last_sold_joker then
    local key = G.GAME.nmb_last_sold_joker
    G.nmb_savedjokercards = G.nmb_savedjokercards or {}
    G.nmb_savedjokercards[card.sort_id] = G.nmb_savedjokercards[card.sort_id] or {}
    if not G.nmb_savedjokercards[card.sort_id][key] then
        local old_ability = copy_table(card.ability)
        local old_center = card.config.center
        local old_center_key = card.config.center_key
        card:set_ability(key, nil, 'quantum')
        card:update(0.016)
        G.nmb_savedjokercards[card.sort_id][key] = SMODS.shallow_copy(card)
        G.nmb_savedjokercards[card.sort_id][key].ability = copy_table(G.nmb_savedjokercards[card.sort_id][key].ability)
        for k, v in pairs({'T', 'VT', 'CT'}) do
            G.nmb_savedjokercards[card.sort_id][key][v] = copy_table(G.nmb_savedjokercards[card.sort_id][key][v])
        end
        G.nmb_savedjokercards[card.sort_id][key].config = SMODS.shallow_copy(G.nmb_savedjokercards[card.sort_id][key].config)
        card.ability = old_ability
        card.config.center = old_center
        card.config.center_key = old_center_key
        for k, v in pairs({'juice_up', 'start_dissolve', 'remove', 'flip'}) do
            G.nmb_savedjokercards[card.sort_id][key][v] = function(_, ...)
                return card[v](card, ...)
            end
        end
    end
    return G.nmb_savedjokercards[card.sort_id][key]:calculate_joker(context)
end```
#

do i make it an external function and then call it in the joker, or do i put this in the joker itself

#

originally i was making it update when a joker was sold and then also when my joker was added to deck, because i needed it to update both while you have the joker and while you dont

daring fern
tall sonnet
#

Hello. Can anyone help me about JokerForge because nobody is helping thru the forum?

tall sonnet
#

I have another problem

#

actually its about the Joker Forge

frosty dock
#

in that case this.

long sun
#

how do i change the x / y positions of a sprite?

#

i'd like to move a sprite by a distance less than one pixel

tall sonnet
long sun
#

gonna try editing VT

fringe oxide
glad osprey
long sun
bold eagle
#

Currently trying to implement a joker that will only trigger on scored cards with my custom enhancement

SMODS.Joker{
    key = "propeller",
    atlas = "placeholders",
    pos = {
        x = 4,
        y = 0},
    config = {
        extra = {
            xmult = 1.5
        }
    },
    rarity = 4,
    cost = 10,
    
    
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and
            SMODS.has_enhancement(card, 'm_zwp_whimsical') then
            return {
                xmult = card.ability.extra.xmult
            }
        end
    end,
    
}
#

it will trigger on any card if I remove the SMODS.has_enhancement(card, 'm_zwp_whimsical') line, and thats the only way I know how to check for enhancements

red flower
#

card is the joker

#

you want context.other_card

bold eagle
#

That’s it?

#

Just change card to context.other_card?

#

Sweet it worked thank you

#

how would I make a joker both retrigger cards and give xmult, do I just use two calculates?

red flower
bold eagle
#

gotchu, thank you

bold eagle
#

currently trying to make an enhancement that will remove the enhancement and add a random edition, but the visual for the edition being added happens immediately upon playing the hand, and I want it to happen after the enhancement gets taken away, the effects of the edition don't go into effect immediately, only the visual

#
SMODS.Enhancement{
    key = "whimsical",
    atlas = "enhancements",
    pos = {
        x = 0,
        y = 0
    },
    config = {
        mult = 0,
        extra = {odds = 10},
    },
    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'vremade_glass')
        return { vars = { card.ability.mult, numerator, denominator,  } }
    end,
    calculate = function(self, card, context)
            if context.cardarea == G.play and context.destroy_card and context.destroy_card == card and 
            SMODS.pseudorandom_probability(card, 'zwp_whimsical', 1, card.ability.extra.odds) then
                    card:set_ability('c_base', nil, true)
                    local random_edition = SMODS.poll_edition { key = "modprefix_seed", guaranteed = true, no_negative = true } 
                    card:set_edition(random_edition)
                    return {
                        message = "Evolved",
                        
                    }
            end
            
    end
}
#

woah it formatted weird

#

oh nvm wraparound

frosty rampart
#

move the set_edition call into something like this

return {
  message = "Evolved",
  func = function()
    card:set_edition(random_edition)
  end
}

that should adjust the timing i think

bold eagle
#

cool imma try that

#

it shows error lines under the function stuff

#

this was all the error stuff

frosty rampart
#

odd
what's the error saying? it should be fine, unless i'm being stupid

bold eagle
#

there was a funky symbol somewhere the error is gone now

#

idk how it got there

frosty rampart
#

ah good lol

bold eagle
#

okay so it still displays the edition before scoring

#

wait i have a really stupid idea

#

i moved the card set edition outside of and after the if statement, that way if it doesnt go through the if the variable random_edition never passes so it wont display until after

#

maybe

#

im trying it and if it works im gonna be shocked

#

it did not work

#

hm

#

i could maybe change some draw order? idk how any of that stuff works

red flower
#

wait i think im missing an argument

#

there

bold eagle
#

thats it?

#

cool

bold eagle
#

nvm I was being stupid

#

oh my god it's working

#

thank you both so much

fading rivet
#

How could I change a cards sprite while its upside down?
right now this is causing infinite recursion

real night
#
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''
        if card.ability.repetitions and card.ability.repetitions > 0 then
            ret.seals = ret.seals or { card = card, message = localize('k_again_ex') }
            ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.repetitions) or card.ability.repetitions
        end
        if card.ability.perma_repetitions and card.ability.perma_repetitions > 0 then
            ret.seals = ret.seals or { card = card, message = localize('k_again_ex') }
            ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.perma_repetitions) or card.ability.perma_repetitions
        end
'''
position = 'after'
payload = '''
SMODS.calculate_context({card_retriggered = true})
'''
match_indent = true

first time making a patch why does it specifically trigger when a card triggers outside of retriggers

rapid stag
real night
dapper sun
#

how do i put Sprites on the screen?

frosty rampart
#

i assume this is mod jam related so i won't ask for further details
your best bet is probably a custom UIBox; somewhere in that UIBox should contain a G.UIT.O node with its object set to your sprite

dapper sun
#

okay

zenith quarry
#

im trying to make a joker that destroys unscored cards, is there a way to detects cards played but not scored

slim ferry
#

context.cardarea == "unscored"

vale grove
#

is there a guide anywhere on how to add your own mod to the balatro mod manager?

vale grove
#

idk tho

frosty rampart
# vale grove is there a guide anywhere on how to add your own mod to the balatro mod manager?

https://github.com/skyline69/balatro-mod-index
note the "CLAUDE.md" file in this and the balatro mod manager itself tho, i hope you think twice about supporting a vibe-coded tool like this

GitHub

A comprehensive collection of mods for Balatro, the roguelike poker deckbuilder. This repository serves as a central hub for the Balatro modding community. - skyline69/balatro-mod-index

zenith quarry
vale grove
frosty rampart
vale grove
#

ill look into it ig

daring fern
frosty dock
#

but it definitely makes use of vibe coding now

vale grove
#

ill look into it

#

its not a high priority for now

zenith quarry
vale grove
#

someone suggested it so i thought id look into how to do it

zenith quarry
silent sail
#

very confused rn

#

apparently a sound file doesnt exsist but like

#

it does

frosty rampart
#

post your definition of the SMODS.Sound, as well as the place where you're calling the sound

silent sail
wintry solar
#

no

#

don't do that

#

yo uneed to add your mod prefix to the sound key in the edition defintions

idle plaza
silent sail
#

ok thaks

#

ok i think i did something wrong

#

its modprefix_soundname right?

#

cause it still isnt working

idle plaza
silent sail
#

im so lost

rapid stag
#

sanity check:

if context.mod_probability ... then
  return { denominator = context.denominator + [modifier value here] }
end

or

if context.mod_probability ... then
  return { denominator = [modifier value here] }
end
frosty rampart
#

first one iirc

tranquil echo
#

what does local ret = {} mean in lucky cards

#

im confused

umbral zodiac
#

lucky cards roll both of their chances at the same time and apply them both in the same context

#

so it makes a table, rolls the mult effect, adds that to the table if it succeeds, then repeats that with the money effect

#

and then it returns that table

tranquil echo
#

ohhhh

#

so i dont need that table if im doing single probability enhancements?

umbral zodiac
#

probably not

tranquil echo
#

peak

umbral zodiac
#

you can just return inside of the probability success

rapid stag
vale zinc
# normal crest It's what the game uses to save cards, selectively picking what stuff to save, y...

Now, a crash is produced for the one thing I implemented that list for.

set_blind = function(self)
    local cloned_cards = {}
    for _, card_to_resurrect in pairs(G.GAME.LAPSEMS_cards_destroyed_this_run) do
        for i = 1, self.config.extra.copies do
            G.playing_card = (G.playing_card and G.playing_card + 1) or 1
            local cloned_card = copy_card(card_to_resurrect, nil, nil, G.playing_card) -- This is the line that produces a crash.
            SMODS.debuff_card(cloned_card, true, 'bl_lapsems_final_ossuary')
            cloned_card.ability.LAPSEMS_final_ossuary = true
            cloned_cards[#cloned_cards + 1] = cloned_card
        end
    end
    
    for i = 1, #cloned_cards do
        G.E_MANAGER:add_event(Event({
            trigger = 'after', delay = 0.05,
            func = function()
                G.deck:emplace(cloned_cards[i])
                return true
            end
        }))
    end
    
    self.original_deck_size = G.GAME.starting_deck_size
    G.GAME.starting_deck_size = #G.playing_cards
    G.deck:shuffle('bl_lapsems_final_ossuary')
end,
normal crest
normal crest
#

try this

local cloned_card = Card(0, 0, G.CARD_W, G.CARD_H, G.P_CENTERS.j_joker, G.P_CENTERS.c_base)
cloned_card:load(card_to_resurrect)
vale zinc
#

Got it working, and adjusted the first two values -- presumably coordinates -- so they don't pop out of thin air from on the screen. Changed 'em to 50, 0 'cause I hought that's roughly where Rouge Rose's cards come from.

vale zinc
#

How come context.other_card returns nil here?

calculate = function(self, blind, context)
    if not G.GAME.blind.disabled then
        if context.individual and context.cardarea == G.play then
            G.E_MANAGER:add_event(Event({
                trigger = 'after',
                blockable = true,
                blocking = false,
                func = function()
                    -- ...
                    return true
                end
            }))
        end
    end
end,
daring fern
vale zinc
wary moth
#

is it possible to have a tag do an effect when you click it?

open aspen
#

how would one have a joker destroy itself

#

aka perish

inner terrace
#

SMODS.destroy_cards

inner terrace
open aspen
#

i heard of something called start_dissolve as well

#

ill try what u mentioned first

daring fern
wary moth
daring fern
wary moth
true jasper
#

I'm unsure why this is crashing

whole lava
#

how can i make a joker pinned to the rightmost slot?

daring fern
whole lava
#

why my joker only score +1 mult when i didn't have any +mult and it didn't score ^mult?

vocal helm
#

Is there a list of all unqiue owned jokers in a run?

slim ferry
#

Also, ^mult is not a builtin return value, you need to implement it yourself or use a library that adds it

daring fern
vocal helm
#

Alright

#

thanks anyway!

coral flume
#

Is there a way to return cards to hand, like force draw them?

wary moth
# daring fern Yes, try hooking `Tag:click` or `Sprite:click`

So this so far DOES print when you click the tag

local old_sprite_click = Sprite.click
function Sprite:click(...)
    print("Sprite Clicked!");
    return old_sprite_click(self, ...)
end

But I'm struggling to figure out how to get any info about the tag you're clicking

wary moth
wary moth
#

Trying to figure out what is inside the "tag" table
And also I need to know what is in the "G" table because I want to check if this is a tag you actually own, and not a tag thats like, in the collection screen
But, yeah, I'm struggling to find documentation about what is in these tables and I don't know how to figure it out

#

I'm a bit new to lua and modding, so, apologies, struggling with this a bit

gilded blaze
#

tags are a bit different compared to other game objects

wary moth
gilded blaze
#

tags are stored in G.GAME.tags as an array
the visible tags you can see on the screen are their sprites instead
they don't have an area like cards do, they instead behave like a linked list, where given the first tag sprite's position, all subsequent tag sprites anchor at an offset

#
for i = 1, #G.GAME.tags do
    local tag = G.GAME.tags[i] -- the tag object
end
wary moth
# gilded blaze tags are stored in `G.GAME.tags` as an array the visible tags you can see on the...

ahh alright ty that is helpful to know
I was trying to see if I could add a function to tags to call whenever I click them, I think I'm almost there but its not quite working
can I just add my own function to the table for tags? Like putting this inside of my custom tag:

click_action = function(self)
  print("Did an action! Yippie!")
end

then doing something like

if tag.click_action then
  tag.click_action(tag)
end

but, it doesnt seem to work, I might be misunderstanding something here

gilded blaze
#

unlike card objects (what you see is what you can interact with), tags only show their sprites to you

wary moth
# gilded blaze this

Are you saying that, self.data on the Sprite.click function is not the actual tag itself?
Like, I need to search through all the existing tags for the tag that matches the key of the one I clicked or somethin?

gilded blaze
#

that would be the case

wary moth
#

okay cool, that sounds doable
is there anyway to get the sprite instance from the G.GAME.tags that it draws and compare it with the one from Sprite.click?

#

just to make it so that the tag that gets used is the actual one I clicked (not a big deal if I cant)

gilded blaze
#

Card class is inherited from Moveable
while Tag class is inherited from Object
I have absolutely no idea what thunk was thinking about it

frosty dock
#

the sprite is in the tag's children (I don't remember what key)

gilded blaze
#

it's actually the tag_sprite field

#

tag.tag_sprite:is(Sprite) == true

frosty dock
#

oh because it's not a Moveable?

wary moth
frosty dock
#

that's dumb

gilded blaze
#

like I said

#

no idea what thunk was thinking

#

apparently he does this

frosty dock
gilded blaze
#
  • set up a sprite field
  • add/override several methods to it
  • assign it to Tag object's tag_sprite
frosty dock
wary moth
#

how do I get the sprite I clicked on in the Sprite.click function?
is it just "self"?

gilded blaze
#

the tag "area" being a hardcoded linked list instead of an actual area is another dumb thing

gilded blaze
#

Sprite itself is inherited from Moveable, but due to the way the game handles Tag objects, it's better to just override click of that specific Sprite field instead of the whole class

wary moth
#
    click_action = function(self)
        print("Did an action! Yippie!")
    end

to the custom Tag object and am trying to reference it

#

I can find another way around this, I just thought it'd be convenient to put the functions on the tags themselves

#

(This might be just a me not understanding lua very well sort of issue)

frosty dock
wary moth
gilded blaze
#

if you're asking for a convenient way to add click action to a tag object via SMODS.Tag, you can just modify the same hook to:

local tag_ui = Tag.generate_UI
function Tag:generate_UI(_size)
    local tag_sprite_tab, tag_sprite = tag_ui(self, _size)
    local obj = SMODS.Tags[self.key]
    if obj and obj.click and type(obj.click) == "function" then
        tag_sprite.click = function(tag_sprite_self)
            obj:click(self)
        end
    end
    return tag_sprite_tab, tag_sprite
end

and in your Tag object, simply add a click field:

SMODS.Tag{
    key = "my_tag",
    click = function(self, tag)
        -- do stuff
    end,
}

this has to be a convenient PR to SMODS ngl

frosty dock
#

note: there's no practical difference between SMODS.Tags and G.P_TAGS other than G.P_TAGS containing unmodified vanilla tags

wary moth
#

I apprecaite yalls help a ton, I think I understand a little more

silent sail
#

can someone helpl me sort thehse sounds out

frosty dock
silent sail
frosty dock
#

yuh that seems all correct. what happens when applying the edition and how are you testing it?

whole lava
#

is there anyway you can make a joker pin to the rightmost?

silent sail
frosty dock
frosty dock
silent sail
#

where would that be?

#

wait i got it

wintry solar
#

Does your sound file work?

silent sail
#

yeah they all play in file viewer

#

do i need to atlas it?

#

because its not a sprite so

wintry solar
#

What did you change to get this new error?

frosty dock
#

where is your sound file?

silent sail
#

local function load_sounds_file()
local mod_path = SMODS.current_mod.path
assert(SMODS.load_file("sounds.lua"))()
end
load_sounds_file()
added this code to the main.lua

sand tree
#

so i made a custom deck with the custom deck mod and i tried to make a glass cannon deck that bans jokers with enhancement related conditions to them and now anytime i get to the shop it crashes

silent sail
frosty dock
silent sail
#

assets/sounds

open moth
#

any idea of how I could implement that?

frosty dock
open moth
vital wren
#

hook Card:use_consumeable, check if the card is a planet card, apply additional mult. you can check level_up_hand to see how it's affecting the mult and chips of the hand

frosty dock
#

if this should affect level ups in general, you can also modify the level_up_hand method on the mult scoring parameter. otherwise the above

open moth
#

i still dont know precisely what a hook is, is it context.using_consumable for example?

gilded blaze
#

look at vanillaremade wiki

open moth
#

to hook I need to write a toml file right

frosty dock
#

that is a lovely patch

frosty dock
open moth
#

ok so its a bit like a wrapper in python

#

and I just... throw a hook into the joker code?

#

ok I searched it up

open moth
#
local level_up_hand_base = G.FUNCS.level_up_hand
G.FUNCS.level_up_hand = function(card, hand, instant, amount)
    local ret = level_up_hand_base(card, hand, instant, amount)
    local privet = SMODS.find_card("j_florr_privet")
    print("Test to see if it runs")
    if #privet then
        for i = 1, #privet do
            privet[i]:juice_up(0.3, 0.4)
            play_sound("tarot1", 1.0, 0.7)
            G.GAME.hands[hand].mult = G.GAME.hands[hand].mult + math.floor(math.sqrt(G.GAME.hands[hand].level))
        end
    end
end

this doesnt print anything in the chat or do anything

wintry solar
#

That function you are trying to hook isn’t a thing

open moth
frosty dock
#

wait yeah it isn't

open moth
#

this one

frosty dock
#

what made you think that was in G.FUNCS

wintry solar
#

Yeah but hooking that might get a little bit funky

open moth
open moth
#

is there an easier way then?

faint yacht
#

You'd want to explore SMODS.upgrade_poker_hands for sure. 🖐️

hardy vessel
#

Is there a way to use the sprite atlas from one mod in another?

red flower
wintry solar
#

I don’t think load order would matter

hardy vessel
open moth
frosty dock
red flower
faint yacht
vital wren
#

is there an easy function call that just forces the hand to sort itself by current sort order?

#

CardArea:sort() passing no method?

red flower
#

i dont think the game stores sort order

#

actually it should nvm

#

its too early

red flower
vital wren
#

looks like card areas have self.config.sort

red flower
#

yeah, sort uses whatever the one stored there is

vital wren
#

works. thanks for the help

whole lava
#

how can i make a new type of consumable that can have duplicate without showman?

silent sail
#

why is my c:edition text turning yerllow

fading rivet
silent sail
#

how odd

#

how do i get it to be like the othher ones

#

liek the text in the tags

frosty rampart
#

c:dark_edition

silent sail
#

ah

silk latch
#

scale_card is a something that you call from within the calculate function
So, like this?

frosty rampart
#

no, it would replace what you currently have as line 29

silk latch
#

And then, what would the context be for triggering it when the joker to the right is triggered?

frosty rampart
#

use context.post_trigger, along with some additional work to make sure that the joker trigger that caught it was the joker to the right
note that post_trigger is an optional feature you have to enable

silk latch
#

How do I enable it?

#

like where do I put the thing

frosty rampart
#

it's just a function that goes directly in your mod's main file

silk latch
#

cool

frosty rampart
#

and you only need to return post_trigger = true, not any of the other stuff (unless you want those features too)

silk latch
#

I'll just leave them to be safe

frosty rampart
#

(in particular, quantum_enhancements will probably cause a dip in performance)

slim ferry
#

also object_weights messes with vanilla seeding

#

and retrigger_joker and the cardareas also add additional calculations which slow stuff down

near coral
#

This is only supposed to have 2 uses but it had 3, I turned the config = {extra = {keep = 1}} into keep 1 though so now it's 2 uses
But the description is still 1 lower than the amount of uses left, on the last use it always says 0 left

rapid stag
frosty dock
#

keep on use n times <==> n+1 uses left

near coral
#

Uhhhh

#

I don't know where to put that I didn't code this

#

I only changed one value

dapper sun
#

anyone know why this is giving me this error despite the shader having both functions?
local shader = love.graphics.newShader(SMODS.current_mod.path .. "assets/shaders/shader.fs" ) -- Gives me more control than SMODS.Shader
bad argument #1 to 'newShader' (missing 'position' or 'effect' function?)

#

oh it seems there's a compile error

#

idk why tho

#

i was missing an opening brace

near coral
#

What if the shader is EVIL

fading rivet
#

how do I make a booster change the music?

daring fern
# fading rivet how do I make a booster change the music?

You would put this in the SMODS.Sound definition: ```lua
select_music_track = function()
return G.booster_pack and not G.booster_pack.REMOVED and SMODS.OPENED_BOOSTER and SMODS.OPENED_BOOSTER.config.center.kind == 'kind' and 100 or nil
end

fading rivet
#

ah thx

silk latch
#

It keeps crashing when I look at my jokers or boss blinds even though the atlases should be correct?

fading rivet
#

neonmod.json or something

silk latch
fading rivet
#

uhh

#

hmm

#

try starting the game again

silk latch
#

I have, like 20 times

#

every time I look at my mod's jokers or blinds, it crashes

fading rivet
#

and the type in the console

eval for key, _ in pairs(SMODS.Atlases) do print(key) end
rapid stag
silk latch
fading rivet
#

run it in the console

fading rivet
silk latch
fading rivet
#

get debugplus

#

then run that code in the console

silk latch
#

they're not there for some reason

frosty rampart
#

the first one creates a new atlas, the second one overwrites the whole definition of what an atlas is

silk latch
#

Ah.

zenith quarry
#

ive made jokers but ive never made a deck does anyone know how i would do it

frosty rampart
#

decks can have calculate functions just like jokers can, but also have an apply function that's called at the start of a run if that deck is selected

silk latch
#

It doesn't crash when I look at or hover over the jokers anymore, but when I entered the shop it crashed for some reason.

#

(Hovering over the blind still crashes for some reason, but at least I can look at the icon)

silk latch
#

okay the contect was a typo apparently

crude swallow
#

Every time i play a hand it says on the logs " DefaultLogger :: Found effect table with no assigned repetitions during repetition check", the joker effect works but idk why it says that

daring fern
silk latch
#

Trying to make this scale whenever the joker to the right triggers, but it's not working.

slim ferry
#

context.cardarea is not the joker that triggered

#

why

#

why are you even checking cardarea

silk latch
#

idfk man

slim ferry
#

context.other_card

#

its in the documentation

frosty dock
#

(insert "read the fucking docs" hamster here)

silk latch
#

okay but now it's activating on literally every Joker?

slim ferry
#

you are actually checking if context.other_card is equal to other_joker right

near coral
#

How can stake stickers from multiple series' of stakes be shown simultaneously

silent sail
#

can someone explain why this doesnt work for jokers?

slim ferry
#

i dont think editions can use joker_main

#

it should be pre_joker or post_joker

#

also holy shit why is joker forge like this just use the dollars return value 😭

wintry solar
#

this is possibly the dumbest way I have ever seen to add 1 dollar

frosty dock
#

oh wow

slim ferry
#

saving a global in a local for no reason
then the exact same global +1
then set added amount to x - y which is just dollars - (dollars - 1) which is literally just dollars - dollars + 1

#

insane levels of genius

#

and the manual message too

slim ferry
#

not even return message but card_eval_status_text with no localized message just manual concat of a +

#

not even a dollar sign

frosty dock
#

"+"..tostring(1)

#

concat with a constant even

silk latch
#

Speaking of which...

#

How much of this is fucked up?

slim ferry
#

post_joker is only for editions calculating after the joker it's on has calculated

#

and i think you meant to do context.individual instead of main_scoring

frosty dock
#

isn't blind.ability not a thing

silk latch
#

idfk

slim ferry
#

also

#

yeah

frosty dock
#

or did we add that

slim ferry
#

its like

#

blind.effect

#

iirc

#

i think N added that he can probably confirm

#

if that doesnt exist just use self.config.extra

#

wait

frosty dock
slim ferry
#

bruh

#

everything is in config

frosty dock
#

geez

silk latch
frosty dock
#

blind.effect.extra.xmult

normal crest
#

will make everyone's life easier

frosty dock
#

I was just about to say

#

this would be easier to spot in properly formatted code

silk latch
normal crest
#

or you can enable format on save in vscode settings

silk latch
#

ohhhhhh

#

okay now I'm back to the unfathomable

normal crest
silk latch
#

ah, okay

near coral
# near coral Visual examples

If this is impossible then is it possible to make it a config option to prioritize either the vanilla stickers or the ones from my stake series

maiden phoenix
silk latch
#

current version and current crash when I hit play hand

rapid stag
#

is there a way to apply xscore after the played hand has been calculated and added to the score girldmDizzy

#

context.after?

wintry solar
#

I imagine so yeah

rapid stag
#

hmmm, no. after is ever so slightly too early

bold eagle
#
    calculate = function(self,card, context)
        if context.before and context.cardarea == G.play and context.individual and SMODS.has_enhancement(context.other_card, nil)
         and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
            return {
                context.other_card:set_enhancement("zwp_whimsical")
            }
        end
    end
fading rivet
#

where is the draw function for center objects at?

faint yacht
bold eagle
fading rivet
faint yacht
bold eagle
#

ok

#

do i even need the return then?

#

actually wait im gonna want text nvm

fringe oxide
#

yall know how to change the balatro bg

faint yacht
#

...are you checking if card has any enhancements?

#

SMODS.has_enhancement(context.other_card, nil) wouldn't be the way to do it... next(SMODS.get_enhancements(context.other_card)) would be that.

bold eagle
#

ah

#

i thought it would have to have nil

#

ok thank you

#

it still didnt do anything

#
calculate = function(self,card, context)
        if context.before and context.cardarea == G.play and context.individual and SMODS.has_enhancement(context.other_card)
         and SMODS.pseudorandom_probability(self, 'zwp_pencil', 1, self.ability.extra.odds) then
            
            
            return{
                message = "silly",
                func = function()
                    context.other_card:set_enhancement("zwp_whimsical")
                end
            }
        end
    end
#

wait nvm i misread your message

bold eagle
faint yacht
#

If you don't want the card to be enhanced, not next(SMODS.get_enhancements(context.other_card)) then.

bold eagle
#

okay

#

it's still not working

faint yacht
#
  1. card instead of self for SMODS.pseudorandom_probability.
  2. There is no context.individual for context.before - you'd want to iterate over the cards and roll the chance for each card separately.
faint yacht
#

Do you want to count the full hand or scoring hand?

bold eagle
#

only scoring

faint yacht
#
for _, pcard in ipairs(context.scoring_hand) do
  if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
    pcard:set_enhancement("zwp_whimsical")
  end
end
bold eagle
#

would that all be inside of calculate?

#

nvm dumb question

silk latch
faint yacht
#

For yours, you can have it self.config.extra.xmult, but for calculate, blind.effect.extra.xmult.

bold eagle
faint yacht
#

Again, log.

bold eagle
faint yacht
#

Where are the odds stored?

bold eagle
#
SMODS.Joker{
    key = "pencil",
    atlas = "woker",
    pos = {
        x = 2,
        y = 0},
    config = {
        extra = {
            extra = {odds = 2}
        },
        
    },
    
    rarity = 2,
    cost = 5,
    
    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'zwp_pencil')
        return { vars = { numerator, denominator } }
    end,
    
    calculate = function(self,card, context)
        for _, pcard in ipairs(context.scoring_hand) do
            if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
                pcard:set_enhancement("zwp_whimsical")
            end
        end
    end
    
}
#

damn it

#

i just realized

faint yacht
#

extra.extra

bold eagle
#

yep

faint yacht
#

Remember to spawn a fresh copy before re-testing.

silk latch
bold eagle
#

it crashed again

faint yacht
faint yacht
# bold eagle

...you removed the if context.before and context.cardarea == G.play conditions...

silk latch
faint yacht
bold eagle
faint yacht
# silk latch Got this when I rerolled onto it
config = { extra = { xmult = 0.9 } },
loc_vars = function(self)
  return { vars = { self.config.extra.xmult } }
end,
calculate = function(self, blind, context)
  if condition then return { xmult = blind.effect.extra.xmult } end
end

should work fine.

faint yacht
bold eagle
#

i set the odds to 1/1

#
SMODS.Joker{
    key = "pencil",
    atlas = "woker",
    pos = {
        x = 2,
        y = 0},
    config = {
        extra = {odds = 1}
        
    },
    
    rarity = 2,
    cost = 5,
    
    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'zwp_pencil')
        return { vars = { numerator, denominator } }
    end,
    
    calculate = function(self,card, context)
        if context.before and context.cardarea == G.play then
            for _, pcard in ipairs(context.scoring_hand) do
                if not next(SMODS.get_enhancements(pcard)) and SMODS.pseudorandom_probability(card, 'zwp_pencil', 1, card.ability.extra.odds) then
                    pcard:set_enhancement("zwp_whimsical")
                end
            end
        end
    end
    
}
faint yacht
#

Try just if context.before then?

bold eagle
#

crashed

#

crashed upon playing a hand

#

i should say

faint yacht
#

:set_ability("m_zwp_whimsical"), that's on me-

valid sable
#

hi, started modding yesterday, is there a tool that can help me make my sprite atlas without using online editors to align to a grid? lmao

bold eagle
#

still crashed

faint yacht
#

:set_enhancement doesn't exist.

#

:set_ability does.

bold eagle
#

oh ability

#

i just dont read sometimes

faint yacht
bold eagle
#

it finally worked thank you so much

valid sable
#

just had the grand idea of sprite sheets lmao

silk latch
faint yacht
#

...curious, try adding card = context.blueprint_card or context.other_card or blind to return?

silk latch
#

For reference, my Joker setup was Left Joycon, Portal Radio, and RIght Joycon, in that order

silk latch
faint yacht
#

After message = '...', ye.

timid zinc
#

Can cards be face down and debuffed at the same time?

fading rivet
#

yes

bold eagle
#

how would I cause the summary for an enhancement to appear next to a joker?

#

like with midas mask and gold cards

fading rivet
#
loc_vars = function(self, info_queue, card)
  info_queue[#info_queue+1] = G.P_CENTERS.enhancement_key
end
bold eagle
#

cool thank you\

fading rivet
#

np

#

any idea why this won't draw the circle properly?

silk latch
#

IT'S ALIVE! (I'll probably just scrap the playing card half of it and make the scaling harsher to compensate)

bold eagle
#

is there a way to add a line gap in localization text?

#

like

this

near heart
#

erm

#

hm

fading rivet
near heart
#

I don't know, is there Zarcheus?

fading rivet
#

you could probably do something with custom colors though

#

make it the same as the background

near heart
#

that is surprising to here actually

rapid stag
fading rivet
#

I didn't try a space

rapid stag
#

yeah, i have several localization text blocks that do this and this is most likely what @bold eagle is looking for. try that

bold eagle
#

cool, thanks

near heart
#

Zarcheus your mod is going to explode.

#

Not if I do first.

silk latch
#

Trying to do this but it just isn't working with this (or the even earlier attempt at making it just force the packs to become Spectral)
Probably because I have zero clue what's actually occurring with the payload bs and what it would actually need to be doing to accomplish that

valid sable
#

how would I go about making a custom message appear over a playing card when the joker condition is fulfilled? I can't think of any jokers that do something like this off the top of my head

frosty rampart
#

return { message = "Something", message_card = whatever the playing card object is }

valid sable
#

ty!

frosty rampart
#

if you're in context.individual, i think the message will just be on the relevant playing card by default even

valid sable
#

I guessed as much when the walkie talkie 2 example joker had to specify the message appears on the joker

#

do I need to set up a message variable to get this to work? or is there a message variable just in general that can get used

frosty rampart
#

no, you can just return what i gave you
when you have { message = x } in a table, "message" is a key into the table, so you're essentially setting up the message variable right there

valid sable
#

gotcha

#

is there a way to control what color the message background appears as?

bold eagle
#

how would I check through the owned jokers for a custom rarity?

frosty rampart
frosty rampart
bold eagle
#

how would I move through multiple jokers

#

this is for checking things to add jokers to pools

frosty rampart
#
for i, v in ipairs(G.jokers.cards) do
  -- do something with v, which is an individual joker from the table
end

this is basic lua

bold eagle
#

ok thank you

#

I don't really know much lua

valid sable
#

ok I got the joker to work as intended, but is there a way that I can make the custom message entirely take the place of the message that is supposed to show that something gave x mult?

frosty rampart
valid sable
#

ah tysm

#

does using loc_vars start at 1 rather than 0?

frosty rampart
#

yep
everything in lua starts at 1 actually

valid sable
#

thats so dark and twisted

frosty rampart
#

if you're familiar with coding already it's definitely something to get used to lol

rapid stag
#

well atlas co-ords start at 0

valid sable
#

I'm new to balatro modding and lua but am quite familiar with coding lol

rapid stag
#

but yeah, going between 0-based and 1-based is weird

valid sable
#

ok so currently I've absorbed some parts of jokers I've seen, does this look right? I didn't understand the setting up custom colors lol

#

I'm pretty sure I've done something wrong with the loc_vars setup

frosty rampart
#

you're close
colours = { ... } goes inside the vars table right next to card.ability.extra.Xmult, and then it'd be {B:1} in the localization itself

valid sable
#

ohh gotcha

rapid stag
#

if i'm reacting to another joker via context.post_trigger, how can i get any chips or mult returned by other jokers? girldmDizzy

#

oh, remind me how i make a use of scale_card not trigger calc_scaling? girldmDead

frosty rampart
#

as per the documentation, during context.post_trigger, you'll get context.other_ret as the return table from the joker trigger
iirc it'll be a bit nested in some other tables, but it's in there somewhere i promise

and from the same page, you can block scaling manipulation by adding some part of this table to the scale_card call, but it'll always trigger the calc_scaling function for stuff that just wants to react to something scaling

fading rivet
#

you could probably make a patch to disable it

#

actually I might PR that, seems moderately useful and lightweight enough

frosty rampart
#

yea if you don't want any calc_scaling to trigger at all, just skip the scale_card call entirely lol

rapid stag
#

my problem being that i have a calc_scaling function that calls scale_card and i just realised that this causes an infinite loop if i have two of that object

rapid stag
#

admittedly, my first thought is to ignore objects with the same key, but

fading rivet
#

yeah i'd do it manually or make a patch for an option to disable it

frosty rampart
vast bough
#

yes i search for messages containing joker forge occasionally

fringe oxide
#

do yall know how to change the bg swirl colors on balatros main menu?

rapid stag
fringe oxide
#

also,,, do the colors need a hex code?

frosty rampart
#

y'all need to get more comfortable with trial and error smh my head /lh