#💻・modding-dev

1 messages · Page 647 of 1

daring fern
#

What is the full code?

gaunt folio
#

it almost works the way i intend, except that it multiplies wrong as it probably repeats the function

tidal hemlock
#

adn this is what happens when you combine freakshow, cryptid, and paperback

gaunt folio
#

to multiply the values of every joker in hand thats in a specific pool by 1.1X

daring fern
gaunt folio
#

omfg it was that simple of a fix thanks man

smoky bramble
#

does context refer to the state the game is in?

gaunt folio
#

think so

smoky bramble
#

hm alright

red flower
#

i need to change that now that the smods docs are better

naive agate
#

is there a way to have showman’s function affect a specific pool?

red flower
naive agate
#

I mean like do something like showman but for a specific pool, if that’s not what you already mean

red flower
#

yes

inner terrace
#

Alright I've been messing with this for about two hours now, and it feels like it should be working - I'm trying to reskin a base game joker, and have it animate
I'm declaring an SMODS.Atlas, declaring it as an atlas_table = 'ANIMATION_ATLAS', and using take_ownership with the atlas key, but it's just... not doing anything

red flower
#

have you tried using malverk

#

im guessing it accepts animated atlases now

inner terrace
#

I debated it, but since the newest beta for SMODS allows animation atlases to be declared so easily, it seems like it shouldn't be that nasty of a process anymore to animate it without?

red flower
#

no im not saying the animation is the problem

#

im saying taking ownership to replace the atlas is the problem

#

malverk solves that part

inner terrace
#

Oh
It's been working fine for the other jokers so far, the ones that aren't animated, I've got ~15 being overwritten

red flower
#

and im saying that idk if malverk accepts animations yet but probably it does

red flower
inner terrace
#

Balls, that's true
alright time to delve into the other possible option for getting this to work, in the style of the Aura mod (the other possible way without Malverk, that is. I'm... really not sure why I'm so adamant about this)

#

CORRECTION: IT'S WORKING

naive agate
#

how can I make it ignore duplicates of cards in a specific pool

red flower
#

(G.P_CENTERS[card_key].pools or {}).pool_key

naive agate
#

like this?

round lion
#

nostalgic pillar

reef belfry
#

ok apparently G.P_CENTER_POOLS.Joker still contains locked jokers, how would I go about checking which of them in that pool are unlocked or not, if I have to loop for it what would i need to check

wanton jolt
#

G.P_CENTER_POOLS.Joker and check if u can have "unlocked = true" or something

round lion
#

you MIGHT have to use the current pool

reef belfry
#

would looping through them like v.config.center.unlocked == true work

wanton jolt
#

uhhhhhh give it a spin idk

daring fern
reef belfry
#

oooh ok

wanton jolt
#

oh right because its a key in the joker itself, not the config

reef belfry
#
SMODS.Joker{
    key = 'reunlockall',
    atlas = 'crs_jokers',
    rarity = 4, 
    cost = 20, 
    unlocked = true, 
    discovered = true, 
    blueprint_compat = true, 
    eternal_compat = true,
    perishable_compat = true,
    pos = {x = 0, y = 0},
    config = {extra = {div = 50, retrig = 1}},
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.div, card.ability.extra.retrig} }
    end,
    update = function(self, card, dt)
        if G.P_CENTER_POOLS.Joker then
            local count = 0
            for i, v in ipairs(G.P_CENTER_POOLS.Joker) do
                if v.unlocked == true then
                    count = count + 1
                end
            end
            card.ability.extra.retrig = (math.floor(count/card.ability.extra.div))
        end
    end,
    calculate = function(self, card, context)
        if context.repetition and context.cardarea == G.play then
            return {
                repetitions = card.ability.extra.retrig
            }
        end
    end,
    crs_credits = {
        mod = "Re:Unlock All"
    }
}
subtle hawk
wanton jolt
#

wtf lol

subtle hawk
#

How many of them is actually unlocked??

reef belfry
#

i dont know why its not 1 nor 11 but 10

#

55

subtle hawk
reef belfry
#

OH

#

FUCK

subtle hawk
#

Lol

reef belfry
#

i forgot those are 2 different things

#

ok awesome it works as intended now

open aspen
#

how do i reference the balatro code for patches again 😅

daring fern
lament agate
#

is there a way to make every boss blind a specific one when a joker is held

wanton jolt
#

luasteam doesnt work as intended 😭

uncut cloud
#

hi chat, quick question
is there a way to do something like this but for the soul sprite?

#

oh

#

thanks a lot

wanton jolt
#

use card.children.floating_sprite

uncut cloud
#

oh

#

will try that then

#

thx !!

wanton jolt
#

not my code, my entire code is just for regular legendary stuff

#

center is the card sprite itself afaik

uncut cloud
#

im decently sure it is

#

didnt know about floating_sprite though

#

i dont usually work with legendaries

#

well that seemed to work

#

thanks a lot !!

wanton jolt
#

np

hard needle
#

how does the idol take a random card from the deck?

hard needle
#

ah i see

shell timber
#

<@&1133519078540185692>

daring fern
#

verbal vigil
#

Does anyone know if its possible to reference the in game joker atlas for a back? I've tried setting the atlas to 'Joker', 'Jokers', "Joker", "Jokers", "joker", "jokers", 'joker', and 'jokers" but the game crashed attempting to index field 'atlas' [a nil value]

daring fern
shrewd pulsar
#

question
when changing the score requirement of the blind by G.GAME.blind.chips, how does it return to its original score post-hand and how do i prevent this

red flower
#

i think you can use events to get around it

shrewd pulsar
#

how

red flower
red flower
#

i would need to test it

shrewd pulsar
#

alrighty

#

thanks

slim ferry
#

not the current score

red flower
#

ah i misread

#

then idk why it is resetting lol

red flower
vale zinc
#

This code does not as the tooltip describes. What must I do?

calculate = function(self, card, context)
    if context.remove_playing_cards and context.other_card == card and ((#G.consumeables.cards + G.GAME.consumeable_buffer) < G.consumeables.config.card_limit) then
        G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
        G.E_MANAGER:add_event(Event({
            trigger = 'before',
            delay = 0.0,
            func = function()
                SMODS.add_card({ set = 'Spectral' })
                G.GAME.consumeable_buffer = 0
                return true
            end
        }))
        return {
            message = localize('k_plus_spectral'),
            colour = G.C.SPECTRAL
        }
    end
end
daring fern
long sun
#

what's the context for a Joker being added?

#

(i don't mean context.buying_card)

red flower
#

card_added

long sun
#

rad, thanks!

#

is context.card:add_sticker("perishable", true) valid, or does Perishable use a different key?

red flower
#

should be

long sun
#

schweet

long sun
#

info_queue[#info_queue + 1] = SMODS.Stickers["perishable"]
why is this line crashing the game?

#

crashes at if not G.localization.descriptions[set][_c.key] then set = "Other" end in common_events

slim ferry
#

you cant do sticker tooltips like that

long sun
#

darn

#

it worked in Cold Beans with a modded sticker ^^; they must've patched that in

slim ferry
#

it has to be info_queue[#info_queue + 1] = { key = "perishable", set = "Other", vars = { G.GAME.perishable_rounds, G.GAME.perishable_rounds } }

long sun
#

ah, i see

slim ferry
#

idk about the vars since i think vanilla hardcodes a 5 for the total amount of rounds in the desc

feral flax
#

What-

lethal stratus
red flower
lethal stratus
#

well yeah ive been sent this about 6 times but i dont work well on this website

red flower
#

i think it would have been better to start there then
what's the part you dont understand?

wild patrol
#

is there an explanation on how the soul card is rendered with the small animation sprite overlayed on it

#

wanna learn how to do that

sturdy compass
#

setting a soul_pos attribute on an object will set that floating sprite

#

If you want custom animations for the floating sprite you will need a draw function

wild patrol
#

looking at the soul sprites is technically considered an enhancer

red flower
wild patrol
#

being in the same sprite sheet

mystic river
wild patrol
#

if u saw the mess i've made for this mod

#

it fits right in

#

just place holders for now

#

but the idea is it gives u super strong legendary twitch chat related jokers for doing stuff

#

one of the ideas is banning a user in chat for a 100x mult

round lion
wild patrol
#

I wonder if it's possible to use emotes as text

grizzled tide
#

hi! I need help having a joker remember a specific playing card in hand after reloading, does anyone have an idea of how to go about that

viscid talon
#

trying to make a joker that adds x0.5 mult per polychrome card in deck

#
        info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome

        local poly_tally = 0
        if G.playing_cards then
            for _, playing_card in ipairs(G.playing_cards) do
                if SMODS.has_edition(playing_card, 'e_polychrome') then poly_tally = poly_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.xmult, card.ability.extra.xmult * poly_tally, card.ability.extra.divine } }
    end,

    calculate = function(self, card, context)
        if context.joker_main then
            local poly_tally = 0
            for _, playing_card in ipairs(G.playing_cards) do
                if SMODS.has_edition(playing_card, 'e_polychrome') then poly_tally = poly_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * poly_tally,
            }
        end
        in_pool = function(self, args)
        for _, playing_card in ipairs(G.playing_cards or {}) do
            if SMODS.has_edition(playing_card, 'e_polychrome') then
                return true
            end
        end
        return false
    end```
#

it comes up with a weird "not defined" error

#

is SMODS.has_edition a thing?

slim ferry
#

it is not

#

it would be card.edition and card.edition.key == "e_polychrome" for the check

viscid talon
#

thankes

wild patrol
#

well the basics are there

#

just need to make it were the twitch soul doesn't appear so often

#

but with the lower joker pool already still has a high chance

#

is there away to fix the jimbo jokers that appear when the pool gets lower than what's available without having to stuff it with vanilla jokers

grizzled tide
#

guys, im trying to figure out which card in a played hand was force selected but i cant figure it out 😭

frosty rampart
grizzled tide
#

makes sense, thank you

#

does that save when reloading though? or should i run save_run()

frosty rampart
#

game autosaves every 10 seconds and whenever you do most things like adding a modification to a card (although if it's a type of modification you implemented yourself, you might need to still manually add it)

grizzled tide
#

kk

#

is that modification permanent or only for the hand? because id probably have to remember to remove it if its the former

frosty rampart
#

yea you have to remove it afterwards

grizzled tide
#

kk

long sun
#

i was today years old when i realised that all localisation texts ending with _ex end with exclamation marks too

#

k_upgrade_ex is short for k_upgrade_exclamation_mark

#

still not sure what the k means though :3

grizzled tide
#

is there a context for a played hand after all cards are scored btw? or would i just manually loop with joker_main

grizzled tide
grizzled tide
#

thanks :)

wild patrol
#

I guess soul_rate doesn't work if a consumable is in with joker cards

shrewd pulsar
#

ok so this is my situation
-# red = reality, blue = expected
-# x = time, y = blind score requirement
-# im deducting the blind score but it comes back

shell timber
#

send the code that does it

wild patrol
#

I tried assigning a weight didn't work either

#

I guess I should just keep it a spectral

shrewd pulsar
#
    calculate = function(self, card, context)
        if context.cardarea == G.jokers and context.joker_main then
            return {
                func = function()
                    if G.GAME.blind.in_blind then
                        local amount = pseudorandom('RANGE:50|100', 50, 100)

                        G.E_MANAGER:add_event(Event({
                            trigger = 'after',
                            delay = 0,
                            func = function()
                                card_eval_status_text(
                                    context.blueprint_card or card,
                                    'extra',
                                    nil, nil, nil,
                                    { message = "-"..tostring(amount).." Blind Size", colour = G.C.GREEN }
                                )

                                G.GAME.blind.chips = G.GAME.blind.chips - amount
                                return true
                            end
                        }))

                        return true
                    end
                end
            }
        end
    end
#

wait hang on maybe because i also have blindside installed

#

lol

wild patrol
#

soul_rate

#

doesn't work

#

soul_rate = 0.003, determines how likely this legendary is to replace each card in a pack

#

It appears at same odds as everything else

frosty rampart
#

soul_rate only works if hidden is true

wild patrol
#

damn maybe if I could read it would have saw it says that a few sentences up on the wiki

#

thx man

#

That should do it

lament agate
#

can i not change settings value inside of calculate func

#

it doesnt work

wild patrol
#

soul rate works now

#

Just shame doesn't work on jokers

#

wanted it to be in the booster with all twitch related stuff

slim ferry
#

cant you do soul_set = "Joker"

#

i thought that worked

wild patrol
#

not sure i can get it a shot

#

I just realized I put it in the wrong booster set

#

been testing for 15mins in the wrong boosters

wild patrol
#

or it's not working

slim ferry
#

The chance is only 0.3% per card

#

Just try setting the chance higher for testing

wild patrol
#

yeah about to

wild patrol
#

changed to 1

#

now one spawns every pack

slim ferry
#

Aweeome

wild patrol
#

I guess now just finding the sweat spot

#

for spawn rate

#
    key = "ttv_ttv_twitch_jokers",
    cards = {
        ["j_ttv_f"] = true,
        ["j_ttv_copycat"] = true,
        ["j_ttv_donation"] = true,
        ["c_ttv_kappsoul"] = true
    },
})```
#

also

#

should I have it in the pool

#

or is it not necessary

#

with the soul_set

slim ferry
#

With soul_set it isnt needed

next timber
#

incredibly basic question but how do you make tarot-like cards be the right size again

#

i forgor

median rose
#

I'm planning on making mod that requires states. Where a state is just information of what the user currently has. Like the number of hands, what jokers, how much money, etc. I also want one of the states to be a "sub state". Where it tells me where the user is in the game. Such as: selecting a blind, in the shop, playing a round etc. I wanted to know if anyone had a full lists of these "sub states" since I know certain jokers, like Perkeo, or Golden Joker trigger during specific states

teal grotto
#

bruh

#

thats literally

#

like a whole thing

#

contexts and game values

frosty rampart
#

also G.STATE tracks something like that too

median rose
teal grotto
#

long thing to ctrl-f in

red flower
# median rose I'm planning on making mod that requires states. Where a state is just informati...

To expand on the other two replies some things in the game are saved in G.STATE (in the shop, in a booster, selecting a hand, using a tarot) basically when there's some state machine kind of thing that the entire game needs to know it's under. Some others are given as a context to the calculate_joker function (or other calculate functions in smods), these are signals for actions such as skipping a booster, rerolling the shop, ending a blind, scoring steps, etc.

daring fern
#

torpid flicker
#

hey why wont my config menu show up

--Typ0.lua
local config = SMODS.current_mod.config

SMODS.Sound({
    key = "music_typ0_me",
    path = "music_me.wav",
    volume = 0.6,
    pitch = 1,

    select_music_track = function()

        if config.typ0_pack_music ~= true then
            return nil
        end


        if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
            local pack_cards = G.pack_cards and G.pack_cards.cards
            if pack_cards and #pack_cards > 0 then
                local first_card_mod = pack_cards[1].config.center.mod
                if first_card_mod and first_card_mod.id == "Typ0" then
                    return 1 
                end
            end
        end

        return nil 
    end,
})```

--config.lua

return {
typ0_pack_music = true,
}```

#

there both in my root folder

open aspen
#

getting this error

#

dump shows this

#

why would self.role ever be nil

daring fern
open aspen
#

one second

daring fern
open aspen
# open aspen

this is the newest code introduced which is when crashes started (just verified the game works fine without this code)

torpid flicker
daring fern
open aspen
#

that makes a lot of sense yea

#

i saved it as . and nort :

open aspen
#

that never takes self

daring fern
open aspen
#

i mean that like

#

with . you need self

daring fern
open aspen
#

ofc, if i saved a var as : it doesnt make sense

open aspen
#

new issue

#

notice i print hi..tagvar at the top

#

my console is showin tagvar as nil

#

in my sticker i have this code

#

(notice how i add true, true at the end there)

#

so it should make my two extra variables in my hook true

#

but i seem to be mistaken

lament agate
#

@rocky plaza

rocky plaza
lament agate
rocky plaza
wanton jolt
#

holy fucking shit

rocky plaza
# lament agate

In your game update hook add

if G.STEAM and not Tangents.user_steam_id then
  Tangents.user_steam_id = G.STEAM.user.getSteamID()
end

where Tangents can be replaced by the actual name of your global mod table

#

then to check, run
eval Tangents.user_steam_id
in debug+

lament agate
#

sure

rocky plaza
#

anyways i gotta go

lament agate
#

see ya thunder

open aspen
#

but i think i have some misunderstanding of how to utilize hooks

#

TLDR: i made a hook and am calling the function in my code with additional custom arguments but it seems to be nil every time

red flower
open aspen
#

ok

red flower
#

ok

open aspen
#

so i have a sticker sprite i made that is double the normal size of a sticker sprite

#

as a result it renders incorrectly

#

(i added a green border to visualize it better)

#

i made a bunch of hooks to try and make it so if the game draws my sticker it does it with an offset

open aspen
red flower
#

have you tried the values the function already has for scale and offset

#

im assuming so

open aspen
#

yea

#

tbh, im working with old code here

#

i solved this exact issue before but lost the changes and that was months ago and i picked up the project again

#

so im just like retracing my steps

#

based on images i sent here in the past

#

rn i think i have the exact or basically the same hooks and stuff i did earlier to fix it

#

but right now, it seems like this additional variable im adding is just always nil

red flower
#

have you tried instead of adding new arguments to pass them through a global

open aspen
#

no, i havent

#

is there a wiki page for how to use global?

red flower
#

no thats lua

#

let me write an example

open aspen
#

ty

#

that would be awesome

red flower
#
-- outside everything, because making random globals is not good practice
YourModTable = {}

draw = function(...)
  YourModTable.tagVar = value
  sprite:draw_sprite(...)
  YourModTable.tagVar = nil
end

then you would check YourModTable.tagVar in the hook

naive agate
red flower
open aspen
#

btw, defining yourModTable anywhere in my file lets me access it right?

red flower
#

as long as it loads before yes

#

most people name it their mod id

open aspen
#

which

#

well yea that makes sense ofc lol

#

this is the main.lua file i have

red flower
#

most functions will run after it loads so its fine

open aspen
#

i think i can repurpose UTM

red flower
#

yeah thats what that should be for

open aspen
#

great

#

ill try that

#

this also actually works far far better

#

because right now im patching 2 other functions

#

to get the variable where it actually needs to make a chane

red flower
#

while not as clean its usually better than adding new arguments because it will conflict with other hooks and patches

open aspen
#

this is what the function looks like now (the function i want to change)

open aspen
#

its not so spaghetti its hard to understand at least

#

close enough

#

lmfao

naive agate
final jewel
#

idk if I did it well but I want my card to not being able to be debuff and after when the card is played it remove debuff from card that are debuff in the played hand and if its held its the same thing its removing debuff from held in hand card

final jewel
#

no an enhancement

red flower
#

hmm yeah thats hard
return remove_debuff doesnt exist

final jewel
#

I tried this some month ago but wasnt able to do it with the skill I was having a this time

red flower
#

you want all cards to be undebuffed when you play it?

final jewel
#

kinda

#

imagine you play the card with the enhancement, every card that you played with it get their debuff remove

red flower
#

and if its held in hand all cards in hand?

final jewel
#

yeah exactly

#

I can do some patch and hook if I need but idk where to do it

red flower
#

for those two effects I would do a check in the global mod calculate to see if you have any in play or hand and then in context.debuff_card you wopuld return { prevent_debuff = true } for all cards in that area

#

for the card itself i would probably use SMODS.debuff_card(card, 'prevent_debuff', "source string") on it when the ability changes, i think theres a context for it you can use in global mod calculate too

#

but you would need to remove it once its unenhanced

#

or rather, you can probably do the prevent_debuff in set_ability and remove it in mod calculate

open aspen
#

why does debug plus console not work 😭

#

nvm

median rose
#

I want to make a function that gets triggered after every event. Do I need to override each function in order to inject my function, or is there a more simple way to do this?

final jewel
torpid flicker
#

why isnt it toggeling my music

red flower
final jewel
red flower
final jewel
#

oh shit

#

im dum

#

didnt think about that

red flower
#

no i mean

#

debuff_card works like individual

#

you shouldnt use individual here

final jewel
#

like so

unkempt bronze
#

How do I count the chip total of a hand and have a joker add it back to a later hand?

red flower
# final jewel like so

it doesnt have cardarea sadly, you need to check context.debuff_card.area

also e_w_held will not be kept between contexts

unkempt bronze
#

(hello?)

red flower
#

that will also not work for e_w_held

#

because you set it to false at the top

final jewel
#

oh

#

wait

red flower
#

nope

final jewel
#

cause its not doing the thing at the start like it will remove only when a card is played

red flower
#

ah yeah good point

#

my solution wouldnt work then

final jewel
#

nono I want it to not remove the debuff at start

red flower
#

yes my solution wouldnt work then

final jewel
#

oh shit

#

this effect is like really hard to make

red flower
#

yeah debuffs are wacky

#

i would need to test code but zzzzzzzzz

final jewel
#

yeah

#

but do you have an idea that could make this enhancement strong

#

like its the upgraded version of the wild card

teal grotto
#

so now its

local ante = G.GAME.round_resets.ante
local sign = 1
if ante % 2 == 0 then
    sign = -1
end
if (G.GAME.chips - G.GAME.blind.chips) * sign >= 0...
frosty rampart
#

i should have an answer for you no matter what but i do need clarification on that

torpid flicker
unkempt bronze
frosty rampart
#

in context.after, SMODS.calculate_round_score() should get you the final score of the current hand. (running it in an earlier context will get the score at the moment of that calculation, not accounting for jokers to the right/anything scored in later contexts). just save that as a value to the joker, and give it on the last hand
to make sure you only do it on the first hand, delete the value in the joker during the last hand (set it to nil), and then only save the value if it doesn't exist yet

unkempt bronze
#

Smods.calculate_round_score()

#

end

#

yes?

frosty rampart
#

not quite lol

#

like i said, you have to save it as a value in the joker's ability table

#

(i'm not gonna write all the code for you immediately, i'd like to encourage you to take a crack at it yourself first)

unkempt bronze
# frosty rampart (i'm not gonna write all the code for you immediately, i'd like to encourage you...
    key = "breadclip",
    atlas = "My_Way_and_The_Highway",
    rarity = 2,
    pos = { x = 3, y = 3 },
    cost = 6,
    blueprint_compat = false,
    config = { extra = { bag_of_chips = 0 } },
    loc_vars = function(self, info_queue, card)
        return { vars = card.ability.extra.chips }
    end,
    calculate = function(self, card, context)
        if G.GAME.current_round.hands_played == 0 and context.after then
            return {
                card.ability.extra.bag_of_chips == SMODS.calculate_round_score()
            }
        end
        if G.GAME.current_round.hands_left == 0 and context.final_scoring_step then
            return {
                chips = card.ability.extra.bag_of_chips
            }
    end
end
}```
#

This is probably off somewhere

frosty rampart
#

the first return in your calculate shouldn't be a return at all, just card.ability.extra.bag_of_chips = SMODS.calculate_round_score()
otherwise that should be good, yea

worth noting that if you're in a situation where the player only has one hand (e.g. needle), then it'll give the stored score from the previous round, but i'm not sure how to handle that cleanly

unkempt bronze
#

thank you

#

Anyway, now to code more cursed cards

#
SMODS.Joker {
    key = "sandwich",
    atlas = "My_Way_and_The_Highway",
    rarity = 1,
    pos = { x = 3, y = 3 },
    cost = 2,
    blueprint_compat = false,
    config = { extra = { mult = 4 } },
    loc_vars = function(self, info_queue, card)
        return { vars = card.ability.extra.mult }
    end,
    calculate = function(self, card, context)
        if context.joker_main then
             for i = 1, #G.jokers.cards do
                 if G.jokers.cards[i].key == 'lhc' then 
                     SMODS.add_card { key = 'c_xiferp_bolognium' }
                 end
             end
        end
        if context.individual and context.cardarea == G.play and context.other_card == context.scoring_hand[#context.scoring_hand] and context.other_card:get_id(full_hand[1]) == context.other_card:get_id(full_hand[#context.full_hand]) then
            return {
                mult = card.ability.extra.mult
            }
    end
end
}```
Like this beast, who's supposed to spit off +4 mult if hand is a sandwich
#

is it even close to rightly coded for that?

open aspen
#

how do i add a sticker to a playing card with debugplus

torpid flicker
# torpid flicker why isnt it toggeling my music

ive done some more trying and switched to this

SMODS.Sound({
    key = "music_typ0_me",
    path = "music_me.wav",
    pitch = 1,
    volume = 0.6,
    select_music_track = function()
        
        local mod = SMODS.current_mod
        local config = mod and mod.config

        
        if not config or not config.typ0_pack_music then
            return nil
        end

        
        if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
            local card = G.pack_cards and G.pack_cards.cards and G.pack_cards.cards[1]
            local card_mod_id = card
                and card.config
                and card.config.center
                and card.config.center.mod
                and card.config.center.mod.id

            if card_mod_id == "Typ0" then
                return 1  -- positive number = play this track
            end
        end

        return nil  
    end,
})```
its still not working

the goal is to make it only play  the music while the config is true
gaunt folio
#

Is there a way to make it so joker slots arent modified by the modify_joker_value function somethingcom made?

#

nvm fixed

unkempt bronze
#
SMODS.Joker {
    key = "chance_card",
    atlas = "My_Way_and_The_Highway",
    blueprint_compat = false,
    rarity = 2,
    cost = 7,
    pos = { x = 3, y = 3 },
    config = { extra = { mult = -4 }, },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult } }
    end,
    calculate = function(self, card, context)
        if context.before then
            if G.jokers.config.card_limit >= 5 then
                 G.jokers.config.card_limit = G.jokers.config.card_limit + 1
            end
            return {
                mult = card.ability.extra.mult
            }
        end
    end
}```
Got another issue: Uh... I'm pretty sure this will add an extra joker slot, bbut it will keep adding them
loud summit
#

what are u trying to do

unkempt bronze
#

subtract four mult and add one joker slot when the card is held

unkempt bronze
open aspen
#
if context.after and context.cardarea == G.play then
            -- Loop through the scoring hand.
            for index, otherCard in ipairs(context.scoring_hand) do
                -- If we found our card, continue.
                if card == otherCard then
                    -- If the next card exists, continue.
                    if (index + 1) >= #context.scoring_hand then
                        index = 0
                    end
                    -- Apparently, calculate functions process before animations finish.
                    -- So to make the change of the sticker line up with the message, we had to use an event
                    -- (The event is added at the end of an event queue, which means this will run after animations ig)
                    G.E_MANAGER:add_event(Event({
                        func = function() 
                            -- Apply the sticker to the next card.
                            SMODS.Stickers[self.key]:apply(context.scoring_hand[index + 1], true);
                            -- Remove the sticker from the current card.
                            SMODS.Stickers[self.key]:apply(card, false);
                            return true 
                        end
                    }))
                    -- Return the message to display when the sticker is applied.
                    return {
                        message = 'Tagged!',
                        message_card = context.scoring_hand[index + 1],
                        colour = G.C.RED,
                    }
                end
            end
        end
#

this is code for a sticker, it is meant to move itself to the card on the right after scoring

#

it works fine, but i noticed that if there are only 2 cards in the hand and the left card has the sticker, instead of displaying tagged on the right card and moving over, it displays tagged on the left card and removes itself

#

and im not going to lie, i dont see in the code where any kind of logic would lead to that happening

#

wait

#

im actually stupid

#

i figured it out

#

i think

#

if (index + 1) >= #context.scoring_hand then
index = 0
end

#

i assume its this

#

but also idk why its resetting to index = 0

median rose
#

I'm trying to set up hooks based off the vanilla wiki Am I only allowed to make hooks with vanilla functions? Did I mess anything up with the other files like the json or main one? Everything is in the root directory, no folders. I also had it before where hooks was not a file, and everything in there was in the main file

//a.json
{
  "id": "DeepLearning",
  "name": "Deep Learning",
  "display_name": "Deep Learning",
  "author": ["Hawker"],
  "description": "Debug Mod to help with Deep Learning",
  "prefix": "dp",
  "main_file": "main.lua",
  "version": "0.1.0",
  "dependencies": ["Steamodded (>=1.0.0~BETA-1221a)"]
}
--hooks.lua
local win_game_ref =  G.FUNCS.win_game
function win_game()
    -- Do something before the original code
    print("win game before")
    local ret = win_game_ref
    -- Do something after the original code
    print("win game after")
    return ret
end
--main.lua
--- STEAMODDED HEADER
--- MOD_NAME: Deep Learning
--- MOD_ID: DeepLearning
--- MOD_AUTHOR: [Hawker]
--- MOD_DESCRIPTION: Debug Mod to help with Deep Learning

----------------------------------------------
------------MOD CODE -------------------------

----------------------------------------------
------------MOD CODE END----------------------
open aspen
#

but i might be wrong

#

eg cryptid made a function called xyz_function(arg1, arg2, etc) and you loaded after cryptid

#

you can just hook it like you would normally

#

i think

median rose
#

so i should probably make it so my mod loads first

loud summit
#

your mod has to be a higher priority number tho (load after)

#

thats literally what youre doing for a lot of vanilla functions anyway since SMODS hooks a lot

open aspen
#

if i have a pair as my played hand with this sticker on the left card

#

it somehow triggers the loop around failsafe

median rose
open aspen
open aspen
#

cause hooking into a function that doesnt exist will cause problems

open aspen
loud summit
glass scaffold
unkempt bronze
#

I've yet to actually test it, I have a vibe it will just keep adding them

glass scaffold
#

You could be correct. ¯_(ツ)_/¯

median rose
# median rose I'm trying to set up hooks based off the [vanilla wiki](<https://github.com/nh65...

So I changed the following: made the priority a large number making sure my mod is loaded last. Used debug prints to verify the line would appear in the log (I am using debug plus, so it should work), but nothing changes :(. No logs when I win a run. Sucks bc I got this working a few months ago with a different function, but that was with vanilla

//a.json
{
  "id": "HawkerDeepLearning",
  "name": "Deep Learning",
  "display_name": "Deep Learning",
  "author": ["Hawker"],
  "description": "Debug Mod to help with Deep Learning",
  "prefix": "hdl",
  "priority": 100,
  "main_file": "main.lua",
  "version": "0.1.0",
  "dependencies": ["Steamodded (>=1.0.0~BETA-1221a)"]
}
--hooks.lua
local win_game_ref =  G.FUNCS.win_game
function win_game()
    -- Do something before the original code
    print("win game before")
    sendDebugMessage("win game before", "MyDebugLogger")
    local ret = win_game_ref
    -- Do something after the original code
    sendDebugMessage("win game after", "MyDebugLogger")
    return ret
end
golden lake
#

quick question, how would one implement a non-standard texture size blind? it looks fine outside of blinds (minus the weird transparency box, dont know whats up with that but in gameplay it looks entirely wrong - i'm looking for a dependencyless solution, so please don't direct me to API mods

round lion
#

might be smods goofing off.

crisp coral
#

use the smaller value of x and y for scale_mag

#

and in the SMODS.Blind:defeat function, reset it

G.GAME.blind.children.animatedSprite.scale = {x = 34, y = 34}
G.GAME.blind.children.animatedSprite.scale_mag = 34/1.5
G.GAME.blind.children.animatedSprite:reset()
daring fern
median rose
frosty rampart
#

not anything specific, just "is your mod actually loading the file hooks.lua"

median rose
#

Pressuambly not since the function debug lines are not being printed

#

my main file is main.lua if that's what you're asking

frosty rampart
median rose
#

got it thanks

median rose
crisp coral
#

np jane balatrostuck

golden lake
#

any idea what the semitransparent box might be caused by?

frosty rampart
reef belfry
#

how do you make something link to an info_queue for a non existent object

#

like just explaining what a term in the joker says

#

i mean i know it could just be referring to a localization entry but i dont know the exact table youre supposed to put it in

median rose
#

So how come this hook causes a softlock when all I said was print something before and after the original function? The lines do print which is a good thing, though at what cost

local end_round_ref = end_round
function end_round()
    -- Do something before the original code
    print("end round before")
    local ret = end_round_ref
    -- Do something after the original code
    print("end round after")
    return ret
end
daring fern
median rose
#

Also, invoking the function causes the function to trigger twice.

-- hooks.lua
local win_game_ref =  win_game
function win_game()
    -- Do something before the original code
    print("win game before")
    local ret = win_game_ref
    -- Do something after the original code
    print("win game after")
    return ret
end

local end_round_ref = end_round
function end_round()
    -- Do something before the original code
    print("end round before")
    local ret = end_round_ref()
    -- Do something after the original code
    print("end round after")
    return ret
end
crisp coral
median rose
# median rose Also, invoking the function causes the function to trigger twice. ```lua -- hook...

So looking back at this, it seems that there are two intances of my mod. Or at at least that is what I am assuming since when I load up the game , there are two of the same Deep Learning mod loaded log. Even though my main file only says it once

INFO - [G] Deep Learning mod loaded
INFO - [G] 2026-01-18 23:41:48 :: WARN  :: DeckSkin :: Old DeckSkin formatting detected on DeckSkin LPB_hearts_skin!
INFO - [G] 2026-01-18 23:41:48 :: WARN  :: DeckSkin :: Old DeckSkin formatting detected on DeckSkin LPB_spades_skin!
INFO - [G] 2026-01-18 23:41:48 :: WARN  :: DeckSkin :: Old DeckSkin formatting detected on DeckSkin LPB_clubs_skin!
INFO - [G] 2026-01-18 23:41:48 :: WARN  :: DeckSkin :: Old DeckSkin formatting detected on DeckSkin LPB_diamonds_skin!
INFO - [G] Deep Learning mod loaded
-- main.lua
--- STEAMODDED HEADER
--- MOD_NAME: Deep Learning
--- MOD_ID: DeepLearning
--- MOD_AUTHOR: [Hawker]
--- MOD_DESCRIPTION: Debug Mod to help with Deep Learning

----------------------------------------------
------------MOD CODE -------------------------
print("Deep Learning mod loaded")
assert(SMODS.load_file('hooks.lua'))()
----------------------------------------------
------------MOD CODE END----------------------
round lion
#

how do i reset cards affected with set ability

round lion
#

for i, v in G.P_CENTERS do

gave me a attempt to call table value in reset game globals

daring fern
round lion
#

i already realised but actual jumpscare

median rose
#

How did I mess up this function? I assume the logs I have should appear right when I start a blind considering I have a full deck

-- original function
G.FUNCS.draw_from_deck_to_hand = function(e)
    if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK) and
        G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then 
        G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false 
        return true
    end

    local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)
    if G.GAME.blind.name == 'The Serpent' and
        not G.GAME.blind.disabled and
        (G.GAME.current_round.hands_played > 0 or
        G.GAME.current_round.discards_used > 0) then
            hand_space = math.min(#G.deck.cards, 3)
    end
    delay(0.3)
    for i=1, hand_space do --draw cards from deckL
        if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then 
            draw_card(G.deck,G.hand, i*100/hand_space,'up', true)
        else
            draw_card(G.deck,G.hand, i*100/hand_space,'up', true)
        end
    end
end
--hook.lua
local draw_from_deck_to_hand_ref = G.FUNCS.draw_from_deck_to_hand
function draw_from_deck_to_hand(e)
    -- Do something before the original code
    print("draw_from_deck_to_hand before")
    local ret = draw_from_deck_to_hand_ref(e)
    -- Do something after the original code
    print("draw_from_deck_to_hand after")
    return ret
end 
daring fern
median rose
#

oh

open aspen
#

why doesnt this do my xmult 😭

#

this is copy pasted from an identical file where the only difference is the other one gives mult

#

wait im an idiot

#

disregard everything i said, i didnt capitalize xMult in my extra.xmult part

daring fern
torpid flicker
round lion
#

and now i cant even view the collection without crashing.

#
``` and a attempt to index field extra
round lion
#

this shit is gonna make me switch to vigil 😭

#

WHAT DOES IT WANT ME TO DO

#

I THINK I MIGHT BE LOSING MY HEAD

pulsar hawk
#

i mean all vscode wants is for you to make sure 'other' exists, but if you know it'll always be smth that has a [1] you're fine to ignore it

#

also other[1] == nil can probably be written as not next(other) and it'd do the same thing but without the warning maybe?

#

-# don't quote me on that

daring fern
round lion
#

this thi ng just ends up killing you immedietely as soon as you play a hand

#

bypassing everything ive set specifically to limit it

#

atr im pretty sure this obelisk got rabies.. that or i should just scrap this entirely

#

nvm it works

wild patrol
#

is there away to remove the sell option from a joker

#

Need to replace it with something

wild patrol
#

I could just resize the button to cover up the sell button

subtle hawk
# wild patrol

I might be brainfarting but wouldn't defining the defuse button as self.children.use_button in your Card:highlight hook remove the sell button?

wild patrol
#

I'll give it a shot

#

Right now in bed

#

Spent all night working on the mod

#

Can't wait to finish it for two ppl to play it and tell me it sucks

hasty kelp
#

are there a better way to make this triple clone joker

gritty stone
#

love to see the next "vanilla but its better because i made it bigger" joker

daring fern
warped ocean
#

yo can yall go over my code? its crashing and idk why lol

daring fern
warped ocean
#

ty o7

hasty kelp
warped ocean
#

i was confused cause it said it took string values

hasty kelp
#

is blinds mentioned like this blind.small, blind.big and blind.boss or is it something else cause i make a madness but only trigger at boss blind

hasty kelp
#

so i cant make a madness only trigger at boss blind only

red flower
#

yes check blind.boss

#

there's also no reason you can't just take madness and add a not to invert the condition

hasty kelp
#

huh

#

then its pointless making a mildness joker

#

i see

red flower
# torpid flicker bump

i think it would be better to put all information in one message rather than make people jump through a reply chain lol

torpid flicker
#

ok i will

#
SMODS.Sound({
    key = "music_typ0_me",
    path = "music_me.wav",
    pitch = 1,
    volume = 0.6,
    select_music_track = function()
        -- Get the latest config every time
        local mod = SMODS.current_mod
        local config = mod and mod.config

       
        if not config or not config.typ0_pack_music then
            return nil
        end

       
        if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
            local card = G.pack_cards and G.pack_cards.cards and G.pack_cards.cards[1]
            local card_mod_id = card
                and card.config
                and card.config.center
                and card.config.center.mod
                and card.config.center.mod.id

            if card_mod_id == "Typ0" then
                return 1  
            end
        end

        return nil  
    end,
})```
#
TYP0_CONFIG = SMODS.current_mod.config

if TYP0_CONFIG.typ0_pack_music == nil then
    TYP0_CONFIG.typ0_pack_music = true
end

SMODS.current_mod.config_tab = function()
    return {
        n = G.UIT.ROOT,
        config = { align = "cm", padding = 0.05, emboss = 0.05, r = 0.1, colour = G.C.BLACK },
        nodes = {
            {
                n = G.UIT.R,
                config = { align = "cm", minh = 1 },
                nodes = {
                    {
                        n = G.UIT.T,
                        config = { text = "Typ0'S Random Jokers", colour = G.C.RED, scale = 0.5 }
                    }
                }
            },
            {
                n = G.UIT.R,
                nodes = {
                    {
                        n = G.UIT.C,
                        nodes = {
                            create_toggle {
                                label = "Enable Pack Music",
                                ref_table = TYP0_CONFIG,
                                ref_value = "typ0_pack_music"
                            },
                        }
                    }
                }
            }
        }
    }
end```
my goal is to make it so that the music only plays inside my booster packs when the config is on.
#

and ive tried a fair few things to make it work

#

but i cant seem too

red flower
#

have you added prints to see if it enters any of the conditions

#

also have you tried returning a number bigger than 1

wintry solar
#

The select music track will always return nil if I’m not mistaken, you can’t access SMODS.current_mod after the game has loaded

torpid flicker
#

what should i use instead of current_mod?

wintry solar
#

You need to store the current mod outside of the objet

#

People normally do modname = SMODS.current_mod at the top of their main file

torpid flicker
#

👍

#

awesome that fixed it!

pulsar dawn
#

Hello I have a quick question, does anybody happen to know where the default joker's calculation function is stored? I'm trying to call a random base game joker within a mod I'm working on.

Thank you in advanced, and I hope you all have a great day!

wintry solar
#

Calling calculate functions from cards you don’t actually have is a lot more advanced than where the function is stored, they use a lot of internal values and functions that are stored within card objects themselves

long sun
#

i'd like my sticker label to fade between three colours. how can i do that?

pulsar dawn
wintry solar
pulsar dawn
#

I'm looking into card.lua rn.

round lion
verbal vigil
#

Hello! I have a quick question about modifying values for cards, I'm wanting to try and change some of the econ jokers' given cash but I can't seem to find a universal way to do it. Is there any? I'm changing scoring jokers' values in the Card.calculate_joker method. Thank you to anyone who can help!

wanton jolt
#

u think its possible to make a booster/consumable in the shop where if u open it you get a custom ui instead of having to pick a card

red flower
#

yes

#

for the consumable using the use function to open the ui is enough for boosters i think you would need to hook some things

red flower
verbal vigil
red flower
#

there's also a table in card.lua that has all the default joker values

verbal vigil
#

So I do have to hardcode it in for every joker?

red flower
#

what do you want to do exactly?

#

sadly most of the values are in different places with different names

verbal vigil
red flower
#

money given by jokers or any money obtained

verbal vigil
red flower
#

well some of them are in calculate_joker and others in calculate_dollar_bonus, you can change them there

#

the proper way would probably be to use context.post_trigger to change returned dollar values and hook calculate_dollar_bonus for the end of round ones

#

if you want to support all modded jokers

verbal vigil
#

O_o

slim ferry
#

you could also hook SMODS.calculate_individual_effect for returned dollars

verbal vigil
#

Alright, I'll try these. Thank you!

wild patrol
#

but this seems like the direction

unkempt bronze
#
            return {
                mult = card.ability.extra.mult
            }
    end```
Okay, I played a flush, and this activated on EVERY card
#

Flush didn't even have a pair

slim ferry
#

Card.get_id doesnt take any arguments outside of self, so youre essentially checking context.other_card:get_id() == context.other_card:get_id()
not sure what exactly the intended effect is here but i assume you want to check if context.other_card is the first or last card at least

unkempt bronze
#

if first card and last card are =

unkempt bronze
slim ferry
#

so if context.full_hand[1]:get_id() == context.full_hand[#context.full_hand]:get_id()

#

and also check if context.other_card is either of those cards

unkempt bronze
#

oh. I got them backwards, thanks!

#

Okay, it didn't activate at all

#

if context.individual and context.cardarea == G.play and context.full_hand[#context.full_hand] == true and context.full_hand[1]:get_id() == context.full_hand[#context.full_hand]:get_id() then

slim ferry
#

yeah because context.full_hand[#context.full_hand] isnt going to equal true

#

idk what the idea there is

unkempt bronze
#

Is context.other_card == #context.full_hand any better?

slim ferry
#

i assume you mean context.other_card == context.full_hand[#context.full_hand]

unkempt bronze
#

yes

slim ferry
#

yeah that works

unkempt bronze
#

Also, in the same card is

#
             for i = 1, #G.jokers.cards do
                 if G.jokers.cards[i].key == 'lhc' then 
                     SMODS.add_card { key = 'c_xiferp_bolognium' }
                 end
             end
        end```
slim ferry
#

G.jokers.cards[i].config.center.key

unkempt bronze
#

(adds a specific consumable if another joker is held)

slim ferry
#

also

#

no card will ever have the key lhc

unkempt bronze
#

Besides the one joker I'm checking for

slim ferry
#

no

unkempt bronze
#

why?

slim ferry
#

j prefix for jokers

#

and the mod prefix

unkempt bronze
#

gotcha

mellow thunder
#

just out of curiosity, how feasible would it be to make a deck that adds chips and mult together on the final scoring step instead of multiplying them together? I would be nerfing the blind scaling heavily so it would maybe be possible to beat

slim ferry
#

should be very simple

#

just SMODS.set_scoring_calculation("add") iirc

#

for the deck apply

mellow thunder
#

oh is it already just a default setting? oops

slim ferry
#

its pretty recent but yeah

mellow thunder
#

alright I'll check it out, thanks for pointing me in the right direction

wild patrol
#

coudln't remove the sell button

#

so I just covered it with a bigger button

unkempt bronze
#

Also, couldn't figure out how to code a card with xmult multing itself

#

like x2x2x2x2x2 and so on

#
        if context.before then
            return {
                xmult = card.ability.extra.mult
            },
            card.ability.extra.mult == card.ability.extra.mult * 1.1
        end
    end```
so the code looks like this
slim ferry
#

firstly

#

you cant run code after returning

#

second, you shouldnt have a comma after the return

#

third, it should be = and not ==

unkempt bronze
#

anything else?

slim ferry
#

no

#

actually

#

yes

#

you cant do scoring in context.before because it gets reset after, you should use context.initial_scoring_step

unkempt bronze
#

How do I display the running multiplier?

slim ferry
#

what

frosty rampart
#

this is basic localization usage

shell timber
frosty rampart
slim ferry
#

kid named loc_vars

mellow thunder
# slim ferry just `SMODS.set_scoring_calculation("add")` iirc

I'm getting a crash whenever I try to start a game with the deck, here's my code in case I did something stupid:

    key = "preschooldeck",
    atlas = "badlatroenhancements",
    pos = {x = 5, y = 0},
    config = { ante_scaling = 0.1 },
    loc_txt = {
        name = "Preschool Deck",
        text = {
            "{C:blue}Chips{} and {C:red}Mult{} are added",
            "together instead of multiplied",
            "{C:red}X#1#{} base Blind size"
        }
    },
    loc_vars = function(self, info_queue, back)
        return { vars = { self.config.ante_scaling } }
    end,
    apply = function(self)
        SMODS.set_scoring_calculation("add")
    end
}```
I also tried updating Steamodded and nothing changed
slim ferry
#

you might need to do it in an event

#

since apply runs pretty early afaik

wintry solar
#

it does need an event, yeah

mellow thunder
#

yeah that seems to have worked, thank you again

#

now to see if this is actually viable to play lmao

slim ferry
#

the apply function overrides the default i think

#

so youll need to do G.GAME.starting_params.ante_scaling = self.config.ante_scaling manually in the apply

mellow thunder
#

I tried changing the blind scaling with loc_vars and it seems to work fine?

wintry solar
#

that's not true

slim ferry
#

loc_vars will run a lot so that definitely isnt a good idea

unkempt bronze
#
                    'Currently {X:mult,C:white} X#4# {} Mult',```
Not working right...
(joker code for context)
```SMODS.Joker {
    key = "pex_card",
    atlas = "My_Way_and_The_Highway",
    blueprint_compat = true,
    rarity = 2,
    cost = 7,
    pos = { x = 3, y = 2 },
    config = { extra = { xmult = 1 }, },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult } }
    end,
    calculate = function(self, card, context)
        if context.joker_main then
                xmult = card.ability.extra.xmult
            card.ability.extra.xmult = card.ability.extra.xmult * 1.1
        end
    end
}```
slim ferry
#

you should actually return the xmult

#

or SMODS.calculate_effect the xmult

#

if you need the mult increase to go after

#

also youre using #4# in the description when the mult is variable 1 in loc_vars

unkempt bronze
#

I'm trying to show xmult

#

not mult

frosty rampart
#

fill in "xmult" wherever eris said just "mult"

slim ferry
#

the point is the position of the value

median rose
#

I am working on just getting familiarize with the code. I started yesterday in which all I did was make a hook script that logged the other scripts. It was working fine yesterday, but now, I cannot open the game. lovely opens for a bit, and then closes. What did I do wrong? Verifying integriy of files does not do anything

-- hooks.lua
local win_game_ref =  win_game
function win_game()
    -- Do something before the original code
    print("win game before")
    local ret = win_game_ref()
    -- Do something after the original code
    print("win game after")
    return ret
end
-- imagine fucntions like this for: end_round, new_round, draw_from_deck_to_hand, discard_cards_from_highlighted, play_cards_from_highlighted, and evaluate_play_ref
knotty granite
#

What did I do wrong I am pretty new to modding

slim ferry
frosty rampart
#

yea don't use any vanilla balatro code as reference, it's not an accurate reflection of how to mod the game
vanillaremade remakes all the vanilla content as if it was modded content

slim ferry
#

yeah balatro source code is quite different from mod code (and is pretty janky in some places because thunk)

knotty granite
#

At least its an error I have never seen before

red flower
#

also loc_vars is inside calculate for some reason

knotty granite
red flower
#

missing a comma

#

also you have two loc_vars 😭

knotty granite
#

Im new 😭

red flower
#

thats still the same infinite loop problem i said

dawn granite
#

i'm not exactly sure what's up here

red flower
#

classic talisman

#

swap Talisman for Amulet if you have it installed

dawn granite
#

i don't have amulet so should i just turn off talisman in general

#

i'd download amulet but it's 11pm and i just wanna make sure the joker works before i go to bed

red flower
#

yeah

knotty granite
#

what do I need to change

viscid talon
#

how do i make a deck that adds +1 booster slot

dawn granite
#

ok it works when talisman isn't losing it's shit cool

red flower
dawn granite
viscid talon
#

so id do smth like

#
        SMODS.change_voucher_limit(1)
    end,```
#

?

red flower
#

yeah

slim ferry
#

But booster

red flower
viscid talon
#

oke

#

danks

dawn granite
red flower
#

amulet is literally a talisman replacement

#

like it's the same mod but without the crash

knotty granite
#

How do I fix that infinite loop problem

frosty rampart
dawn granite
#

ah i see

frosty rampart
dawn granite
red flower
#

me when i don't follow the advice given to me and expect help

frosty rampart
#

ok well eris linked you it last time you asked, and i highly recommend reading it lol

knotty granite
#

srry

mellow thunder
#

does anyone happen to know why a blind debuffing hearts like this is toggles the debuffs whenever a card gets an enhancement/a non-playing card is added?

    return {debuff = true}
 end```
I also have some code that prevents you from scoring at all unless a queen is visible, so that might be doing something weird but I have no idea what:
```if context.debuff_hand and not G.GAME.blind.disabled then
            local _queenheld = false
            for i = 1, #G.hand.cards do
                if G.hand.cards[i]:get_id() == 12 then
                    _queenheld = true
                end
            end
            for i, queencheck in ipairs(context.full_hand) do
                if queencheck:get_id() == 12 then
                    _queenheld = true
                end
            end
            if _queenheld ~= true or string.find(context.scoring_name, "Flush") then
                blind.triggered = true
                return { debuff = true }
            end
        end```
#

oh and these are both in a calculate function, just in case this makes it look like I forgot that or something

smoky holly
#

im trying to figure out how exactly i would get the last used planet card

abstract turret
#

Hey, guys I'm new to modding Balatro(and lua in general)

How can i manipulate the odds of joker appearing in shop(Guaranteed on every roll or has increased chance compared to other jokers)

viscid talon
#
        info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome

        local poly_tally = 0
        if G.playing_cards then
            for _, playing_card in ipairs(G.playing_cards) do
                if card.edition and card.edition.key == "e_polychrome" then poly_tally = poly_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.xmult, card.ability.extra.xmult * poly_tally, card.ability.extra.divine } }
    end,

    calculate = function(self, card, context)
        if context.joker_main then
            local poly_tally = 0
            for _, playing_card in ipairs(G.playing_cards) do
                if card.edition and card.edition.key == "e_polychrome" then poly_tally = poly_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * poly_tally,
            }
        end
        in_pool = function(self, args)
        for _, playing_card in ipairs(G.playing_cards or {}) do
            if card.edition and card.edition.key == "e_polychrome" then
                return true
            end
        end
        return false
    end
``` it no worky
viscid talon
frosty rampart
viscid talon
#

oops

#

how

#

im so dumb

#

ok just applied

frosty rampart
#

happens to the best of us lol

smoky holly
knotty granite
#

at least it loaded

red flower
#

consumeable?

#

one of the two

knotty granite
#

had oops btw

smoky holly
#

whats global mod calculate...

red flower
red flower
knotty granite
#

also N' thanks for help

abstract turret
knotty granite
#

oops was not at fault

smoky holly
#

that changes things ok

#

do i do it like this, in the mod.lua?

red flower
#

yes
table should be context (i mean it could be table but its the context)

#

also assuming J_O_Y = SMODS.current_mod

smoky holly
#

ahh ok ok

#

how would i access a variable in here? would i just return that variable?

knotty granite
#

what do I do 😭

smoky holly
#

can i not store this in our custom table do i have to use SMODS.current_mod

#

thats probably what it is

frosty rampart
#

yea smods doesn't know shit about your mod's custom global table, SMODS.current_mod refers to the mod object that SMODS keeps track of

#

N said that was ok because he assumed you had local J_O_Y = SMODS.current_mod earlier in the file

smoky holly
#

yeah i misunderstood what he thought i meant, lmao

smoky holly
#

is it a basic lua thing or is it like,

frosty rampart
#

unclear what you're asking

smoky holly
#

so that another joker can reference that

frosty rampart
#

ahh right
so for global variables like that, you'll want to save it as a variable in the G.GAME table. so basically just

if context.using_consumeable then
  G.GAME.joy_last_planet = context.consumeable.config.center.key
end

and then your joker can check if G.GAME.joy_last_planet exists, and if it does, do something with that

smoky holly
#

hell yeah thank you

#

mm i still need to check if its a planet

frosty rampart
#

right
uhhh the center should store some info about its set but i dunno that off the top of my head, lemme check

smoky holly
#

wait i can just check constellation

frosty rampart
#

ah yep

red flower
frosty rampart
#

right i forgor

smoky holly
#

right here

smoky holly
frosty rampart
#

but also GAME is nil at certain times (it doesn't get generated until you start a game for the first time in the session, or at least after the jokers are all initialized)

smoky holly
#

ah. yeah

frosty rampart
#

you can just use G.GAME.j_o_y_last_planet directly in the calculate function and loc_vars and whatever

smoky holly
#

well heres the thing

#

is it doesnt. save if i exit the run and then re-open it

next timber
#

im trying to add compat with spectrum framework by making the decks with extra suits have the lower spectrum values, but nothing seems to be happening? the config has easy_spectra = true which isn't carrying over to G.GAME.starting_params, though G.GAME.starting_params.diverse_deck is set to true only on the 6 suit decks so i have to assume spectra is detecting it, so im not sure why the values arent decreasing

frosty rampart
#

yea i can confirm that it saves and loads anything stored in G.GAME just fine
maybe the game saves before calculating anything with using_consumeable, and you just quit too quickly for it to autosave

smoky holly
#

well it runs through the calculation just fine

#

i have a joker that updates its display to match the last sold joker, it updates fine

#

but then when i exit and relaunch it resets the display

#

so i think the variable is resetting

#

we had this issue with another joker some time ago too

frosty rampart
#

and you're directly using G.GAME.j_o_y_last_planet in the loc_vars function?

smoky holly
#
        local config = card.ability.extra
        local planet = G.GAME.j_o_y_last_planet
        local label

        if G.GAME.j_o_y_last_planet then
            table.insert(info_queue, planet.center)  
            label = localize { type = "name_text", set = planet.set, key = planet.key }
        else
            label = localize "k_none"
        end

        return {
            vars = { config.planet_count, label }
        }
end```
#

this is what the loc_vars code looks like

frosty rampart
#

ok yea, like i said, maybe you're just quitting too fast after the calculation runs for the game to save
try advancing the game state in any way (picking a blind, opening a pack, playing a hand, etc) in between using a planet and quitting the game, and see if the issue still remains

smoky holly
#

oh YEAH

carmine kindle
#

Technical questions :).

I'm working on a mod which adds unique modification which functionally and cosmetically change jokers effect (with each joker having a set of unique modifications). Currently I'm using custom hidden editions which I use to display infoqueques for each joker variant. The code for the mod is in the joker itself, not the edition. There's a way to make the edition display a variant used by the specific joker it is being used as an infoqueque from ?

Sorry for the long question but I wanted to be clear about it

tidal hemlock
#

it was generated via anomaly 74

subtle hawk
#

A74 code?

#

Although I'm not sure how the source of a seal could be a problem

#

But who knows

tidal hemlock
gaunt folio
#

If anyone uses a similar code somethingcom wrote or knows it, How would I reset a joker's values back to normal at the end of a round? Other methods I've tried give errors and this gives nothing

tidal hemlock
#

made via jokerforge so expect jank

subtle hawk
#

Okay I don't exactly see why it does that

#

Does it happen like with any seal

daring fern
tidal hemlock
#

nope, only purple is bugged

subtle hawk
tidal hemlock
#

i havent tested that yet

subtle hawk
#

Buh

tidal hemlock
#

ok so i've discovered 2 things:

  1. blue seal is also broken
  2. its bugged with cards that arent generated via triple rainbow
#

red seal and gold seal seem to work poperly though

subtle hawk
#

And since your mod is jokerforge, I would assume you wouldn't exactly make some new mechanics that break shit

#

Probably another mod's fault

tidal hemlock
#

yeah i'll try disabling some of the mods i have on

#

it's probably bunco, it started just after i downloaded bunco

#

tbf bunco breaks everything

loud citrus
#

how would i check to see each time the shop is re-rolled?

red flower
loud citrus
#

i completely forgot about that joker 😂
i've only been playing blindside sense it came out

round lion
#

add card is not adding the cards to deck at all, and is only creating ghosts

cerulean rose
#

how are you suppoed to change the joker limit? i've tried setting G.jokers.config.card_limit but that yields extremely glitchy results

sturdy compass
#

Probably G.jokers:change_size(number)

surreal quail
#

how does one change the music with a balatro mod?

round lion
#

how do i get unscoring cards anyway

daring fern
daring fern
#

rare phoenix
#

did they change jokerExists?

daring fern
rare phoenix
#

What???

#

It was def a thing at some point

frosty rampart
#

if it was, it was probably in like smods 0.9.8
use SMODS.find_card for what you're trying to do

daring fern
wild patrol
#

there's no defuse mechanic yet but it's a start

rare phoenix
#

I am NOT crazy

red flower
#

you are

#

sounds like a chatgpt invention

#

the fact that the first mention is 7 months ago when i was already modding makes me believe it's either just the same chatgpt hallucination or people copying code from a mod without copying the function too

#

they all mention it in regards to making a sound too

shell timber
#

jokerExists isn't real i think

red flower
#

the fact people did this when find_joker exists is astounding

#

ah it's also in yahimod

bold gyro
#

what part of my sticker should i target to allow it to work with the set_sprite_pos function? (eg. for jokers instead you use card.children.center:set_sprite_pos({ pos }))

abstract turret
#

Guys, i need small help, i create a function that replaces on reroll(almost) every joker with baron, it works through create_card, but when i try to chance the 'j_baron' with my modded joker key, it crashes and gives me an error about center is nil

i tried to replace it with ortalab 'j_biker' and it generates. What i did wrong?

abstract turret
# red flower code?

`local original_create_card = create_card

local force_next_joker = false

function create_card(card_type, area, legendary, rarity, skip_materialize, soulable, forced_key, ...)
if card_type == 'Joker' and force_next_joker and not forced_key then
force_next_joker = false
print('[ForceNextJoker] FORCING BARON')

    return create_card('Joker',area,legendary,rarity,skip_materialize,soulable,'j_baron')
end

local card = original_create_card(card_type,area,legendary,rarity,skip_materialize,soulable,forced_key,...)

if card_type == 'Joker' then
    force_next_joker = true

    local key = forced_key
    if not key and card and card.config and card.config.center then
        key = card.config.center.key
    end

    print('[ForceNextJoker] Joker created:', key)
end

return card

end`

This is the part of function.lua there another thing

red flower
knotty granite
red flower
abstract turret
knotty granite
red flower
abstract turret
red flower
#

it needs the full key

abstract turret
knotty granite
red flower
#

when do you want it to act

knotty granite
red flower
#

for each card played?

knotty granite
#

yes

red flower
#

then youre missing context.individual

knotty granite
#

yeah I realized that

#

just now

red flower
#

also you should indent your code properly

#

i think some of your conditions are at the wrong level

knotty granite
#

idk if its not working or im getting really unlucky

#

does oops automattically work with modded jokers?

red flower
#

yes

#

if you use pseudorandom_probability

knotty granite
#

the only conclusion then is that it is not crashing but not working

#

and I basically changed nothing

red flower
#

context.individual and context.cardarea == G.play

knotty granite
#

it can't be context.cardarea and context.individual?

red flower
#

it can but 1) it's better to have the proper context first before the other information in the context (cardarea is an attribute of individual) 2) you need to check what area context.cardarea is, not what context.individual is

knotty granite
#

ok

#

nvm I am dumb

past spade
#

I have an effect that reduces ante on blind skip, if I trigger it and then exit the run, the ante goes back up but the skip is still taken. However blinds still show the reduced chip score until entered. Other effects triggering on blind skip seems to work properly

red flower
past spade
#

I tried save_run() after changing ante but it didn't change anything

red flower
#

can i see the code

past spade
#

` calculate = function(self, card, context)
if context.skip_blind and not context.blueprint then
card.ability.extra.skip_counter = card.ability.extra.skip_counter + 1
if card.ability.extra.skip_counter >= card.ability.extra.skips then

            ease_ante(-card.ability.extra.anti_ante)
            G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante or G.GAME.round_resets.ante
            G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante - card.ability.extra.anti_ante
            
            card.ability.extra.skip_counter = 0
            card.ability.extra.skips = card.ability.extra.skips + 1

            save_run()`
red flower
past spade
#

what timing should it use? just immediate?

red flower
#

i just used the default

past spade
#

so this?
G.E_MANAGER:add_event(Event({ func = function() save_run() return true end }))

red flower
#

yeah

past spade
#

yup that works, thanks!

daring fern
#

long sun
#

my Joker isn't doing anything, why not?

if context.individual and context.cardarea == G.play and context.other_card:get_id() == card.ability.extra.chosen_rank then
      return { xmult = card.ability.extra.xmult }
    end```
#

i've checked, and it has both its chosen rank and xmult assigned

#

it's not giving any xmult when its chosen rank is played

#

ah have the full code

frosty rampart
#

You're setting the chosen rank to card.base.value, which is a string

long sun
#

oh ^^;

#

so get the base.value of other_card too?

frosty rampart
#

either that or do get_id() in the set_ability function

long sun
#

or the id of the chosen card?

#

ah ye

#

thanks! ^^

frosty rampart
#

no problem!

final jewel
#
                    blocking = true,
                    func = function()
                        if #G.consumeables.cards > 0 then
                            SMODS.destroy_cards(pseudorandom_element(G.consumeables.cards, pseudoseed('tRex_destroy')))
                            if not context.blueprint then
                                card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_add
                                card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chips_add
                            end
                        end
                        G.E_MANAGER:add_event(Event({
                            blocking = true,
                            func = function()
                                if #G.consumeables.cards < G.consumeables.config.card_limit then
                                    local set = next(SMODS.find_card("j_giga_velocyraptor" or "j_giga_velocyraptor_alt")) and 'Spectral' or 'Tarot'
                                    SMODS.add_card({set = set})
                                else
                                    SMODS.calculate_effect({ message = localize('k_no_room_ex') }, card)
                                end
                                return true
                            end
                        }))
                        return true
                    end
                }))``` why does the card is always destroy after
slim ferry
#

SMODS.destroy_cards already adds an event

#

iirc

final jewel
#

so I remove every event and it will work

slim ferry
#

you should keep the event for creating the card but remove the other

final jewel
#

okok

mellow thunder
#

does anyone happen to know why a blind debuffing hearts like this is toggles the debuffs whenever a card gets an enhancement/a non-playing card is added? I use context.debuff_hand elsewhere as well, so I can't just do debuff = {suit = 'hearts' }. I've also tried commenting out the other code and nothing has changed, so something about this specific code doesn't work:

  return {debuff = true}
end```
slim ferry
#

you should do context.debuff_card:is_suit('Hearts', true), with the true here making it bypass a debuff. otherwise the debuff will toggle every time its checked because debuffed cards normally dont count as their suit

mellow thunder
#

that was the problem, thank you

viscid talon
#

just checked over my code again and it still no worky

#
        info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome

        local poly_tally = 0
        if G.playing_cards then
            for _, playing_card in ipairs(G.playing_cards) do
                if card.edition and card.edition.key == "e_polychrome" then poly_tally = poly_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.xmult, card.ability.extra.xmult * poly_tally, card.ability.extra.divine } }
    end,

    calculate = function(self, card, context)
        if context.joker_main then
            local poly_tally = 0
            for _, playing_card in ipairs(G.playing_cards) do
                if card.edition and card.edition.key == "e_polychrome" then poly_tally = poly_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * poly_tally,
            }
        end

    in_pool = function(self, args)
        for _, playing_card in ipairs(G.playing_cards or {}) do
            if card.edition and card.edition.key == "e_polychrome" then
                return true
            end
        end
        return false
    end```
#

@frosty rampart what do

#

it doesnt do anything

red flower
#

what part doesn't work, the scoring?

#

you're checking card instead of playing_card

viscid talon
#

yeah the scoring

#

hmm

frosty rampart
#

ah yea that would do it
also you still aren't ending the calculate function properly, so the in_pool function isn't going to do anything. you need to add another end, right before the in_pool function

viscid talon
#

oke

#

if i dont add the extra end, its fine

frosty rampart
#

you need a comma too

#

like you have a comma at the end of the loc_vars function

viscid talon
#

o

slim ferry
#

you still have calculate code at the bottom that isnt inside calculate

#

you should put that in calculate

viscid talon
#

moved it

#

i have a new issue now: how do i make a booster pack pick up a card instead of applying it

primal robin
#

Whats hex vale of G.C.CHIPS

stoic void
viscid talon
#

its fine i fixed it

slim ferry
#

is there a way to allow any version of a mod in dependencies? do i just not include a version?

frosty rampart
#

yea that should work

slim ferry
#

wait actually i just realized that having smods dependency with no version restriction is pointless because you literally need smods to see missing dependencies anyway

red flower
#

add a balatro dependency

frosty rampart
#

oh that does remind me tho
is there a way to make a mod conflict with talisman without also conflicting with amulet (which provides talisman)

red flower
#

looking at the code for conflicts i dont think so

frosty rampart
#

dang, ok

cyan lagoon
#

heya, why this doesn't get retriggered?

#

i had a fix in a form of 'return nil, true' but now it's here by default and the joker still doesn't get retriggered

sonic musk
#

Hey guys, does someone have a joker sample? I wanna trace over one but the one I found isn't the right size

#

nvm i found it

viscid talon
#

am i missing something?

#

[REDACTED]

#

WAIT

#

WHERE DID THE SIZE THING COME FROM

#

istg i do NOT remember that

#

i still get the same error :(

#

here's the corrected code that i still get the error on

#
SMODS.Joker{
    key = "foolsgold",
    loc_txt = {
        ['name'] = 'Fools Gold',
        ['text'] = {
            [1] = 'Played {C:attention}Gold{} cards',
            [2] = 'have a {C:green}#1# in #2#{} chance to',
            [3] = 'create a {C:tarot}Fool{} card',
            [4] = '{c:inactive}(Must have room){}'
        },
    },
    pos = { x = 9, y = 8 },
    cost = 5,
    rarity = 1,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = false,
    unlocked = true,
    discovered = false,
    atlas = 'CustomJokers',
    config = { extra = { odds = 4 } },

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

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_gold', 'j_hatch_foolsgold') and
            SMODS.pseudorandom_probability(card, 1, card.ability.extra.odds) then
            return {
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            SMODS.add_card {
                                key = 'c_fool',
                            }
                            G.GAME.consumeable_buffer = 0
                            return true
                        end
                    }))}
        end
    end
}
frosty rampart
#

your probability calls are wrong
you need a string as the seed between card and the numerator

wanton jolt
#

i love hovering cards and have balatro crash

viscid talon
#

vremade_bloodstone?

frosty rampart
#

SMODS.pseudorandom_probability(card, "something", 1, card.ability.extra.odds). the string can be anything you want
and do the same for the get_probability_vars function too

viscid talon
#

oek

frosty rampart
#

vanillaremade usually uses the key of the joker as the seed

viscid talon
#

huh i see

#

thats strange, ill do it rn

wanton jolt
#

yeah for pseudo random probability u need to have ur seed

viscid talon
#

seed,,,

wanton jolt
#

,,,,

viscid talon
#

i also decided to simplify no dice (a joker of mine) bc its code was way too janky

frosty rampart
#

if two different probability calls share the same seed, then you could (theoretically) predict the outcome of one based on the outcome of the other

viscid talon
#

uh what the Fuck

frosty rampart
#

because it's not actually random

#

uhhh hold on

viscid talon
#
SMODS.Joker{
    key = "foolsgold",
    loc_txt = {
        ['name'] = 'Fools Gold',
        ['text'] = {
            [1] = 'Played {C:attention}Gold{} cards',
            [2] = 'have a {C:green}#1# in #2#{} chance to',
            [3] = 'create a {C:tarot}Fool{} card',
            [4] = '{c:inactive}(Must have room){}'
        },
    },
    pos = { x = 9, y = 8 },
    cost = 5,
    rarity = 1,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = false,
    unlocked = true,
    discovered = false,
    atlas = 'CustomJokers',
    config = { extra = { odds = 4 } },

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

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_gold') and
            SMODS.pseudorandom_probability(card, 1, 'j_hatch_foolsgold', card.ability.extra.odds) then
            return {
                    G.E_MANAGER:add_event(Event({
                        func = function()
                            SMODS.add_card {
                                key = 'c_fool',
                            }
                            G.GAME.consumeable_buffer = 0
                            return true
                        end
                    }))}
        end
    end
}
#

the code rn

wanton jolt
#

whats ur description

frosty rampart
#

fuck my bad, you don't need the seed for get_probability_vars

#

my mistake

viscid talon
#

i used to use jokerforge to make probability jokers

wanton jolt
#

oh no

viscid talon
#

yeah and now ive switched to standard coding i keep finding random bugs

#

whats weird is that other probability jokers (e.g. staircase) work

#

wot

wanton jolt
#

dont mind the weird structure, i'm ommiting the uninteresting

#

invert ur seed and ur odds when u do local numerator, denominator

#

also ur french

#

@viscid talon

wintry solar
#

yeah those arguments are in the wrong order

wanton jolt
#

eremel

#

ur here

wintry solar
#

I am here

viscid talon
#

oak

wanton jolt
#

i have an icon for malverk, i still have the project file if u wanna tweak

wintry solar
#

I'm okay, thanks, I'll make my own at some point

wanton jolt
#

oh okay

wintry solar
#

you should definitely use this for something though!

wanton jolt
#

uhhh idk lol

viscid talon
#

FGRHRHSHFSHEFHESDFHSGH I STILL GET THE SAME ERRORRRR

wintry solar
#

your SMODS.pseudorandom_probability call is missing the seed

frosty rampart
#

the thing feli was saying was only for get_probability_vars, the seed needs to go before the numerator in the pseudorandom_probability call

#

there's actually no seed at all in get_probability_vars, which again, is my mistake for saying so initially. that string is just the identifier for the probability call

wanton jolt
#

yeah and u switched the seed in line 31 too

frosty rampart
#

that's what i just said 😭

wanton jolt
#

no

slim ferry
#

yes?

#

fym no

wanton jolt
#

i cant even test the code anyways because my game keeps crashing when i hover cards 😭😭

slim ferry
#

that seems more like your own issue

#

tbh

wanton jolt
#

i know