#đŸ’»ăƒ»modding-dev

1 messages · Page 183 of 1

manic rune
#

am i doing this correctly?

#

...oh nevermind, the 'Hello World!' part is supposed to be localization stuff

#

i cant just directly put a string there it seems

#

i hate my life

violet void
#

restarting balatro be like

atomic edge
#

are there any mods that change the soul sprite dynamically which i can check?

manic rune
#

ok so genuinely, how do i call my own localization in this case?

gilded narwhal
#

Guys would you say "reveals the next 5 cards in your deck at all times" is a legendary

manic rune
#

thats all i remember, im sorry :(

manic rune
lavish lake
#
Oops! The game crashed:
[SMODS _ "src/utils.lua"]:1547: bad argument #1 to 'ipairs' (table expected, got nil)

Additional Context:
Balatro Version: 1.0.1n-FULL
Modded Version: 1.0.0~ALPHA-1415c-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.6.0
Platform: Windows
Steamodded Mods:
    1: Alphabet Jokers by Runtem [ID: alphabet_jokers, Version: 1.0.0]
    2: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.1, Uses Lovely]
Lovely Mods:

Stack Traceback
===============
(3) LÖVE function at file 'boot.lua:352' (best guess)
Local variables:
 errhand = Lua function '(LÖVE Function)' (defined at line 553 of chunk [lovely debugplus.console "console.lua"])
 handler = Lua function '(LÖVE Function)' (defined at line 553 of chunk [lovely debugplus.console "console.lua"])
(4) global C function 'ipairs'
(5) Lua field 'calculate_end_of_round_effects' at Steamodded file 'src/utils.lua:1547' 
Local variables:
 context = table: 0x38b4d1c0  {cardarea:unscored, end_of_round:true}
(6) Lua field 'func' at file 'functions/state_events.lua:168'
Local variables:
 game_over = boolean: false
 game_won = boolean: false
 (for generator) = C function: builtin#6
 (for state) = table: 0x38b4d198  {1:unscored, 2:table: 0x389b7878}
 (for control) = number: 1
 _ = number: 1
 v = string: "unscored"
(7) Lua method 'handle' at file 'engine/event.lua:55'
Local variables:
 self = table: 0x3890ea58  {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x38944380 (more...)}
 _results = table: 0x389a3a58  {blocking:true, pause_skip:false, time_done:true, completed:false}
(8) Lua method 'update' at file 'engine/event.lua:182'
Local variables:
 self = table: 0x386d59b0  {queue_last_processed:50.749999999998, queues:table: 0x386d59d8, queue_dt:0.016666666666667 (more...)}
 dt = number: 0.0133364
 forced = nil
 (for generator) = C function: next
 (for state) = table: 0x386d59d8  {unlock:table: 0x386d5c90, other:table: 0x386d6638, tutorial:table: 0x386d6148 (more...)}
 (for control) = number: nan
 k = string: "base"
 v = table: 0x386d5cb8  {1:table: 0x3886e558, 2:table: 0x3869b7e0, 3:table: 0x39016380, 4:table: 0x38f3efa8 (more...)}
 blocked = boolean: false
 i = number: 11
 results = table: 0x389a3a58  {blocking:true, pause_skip:false, time_done:true, completed:false}
(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2524'
Local variables:
 self = table: 0x38176750  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x387e3af8 (more...)}
 dt = number: 0.0133364
 http_resp = nil
(10) Lua method 'update' at Steamodded file 'src/ui.lua:84' 
Local variables:
 self = table: 0x38176750  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x387e3af8 (more...)}
 dt = number: 0.0133364
(11) Lua field 'update' at file 'main.lua:996'
Local variables:
 dt = number: 0.0133364
(12) Lua function '?' at file 'main.lua:935' (best guess)
(13) global C function 'xpcall'
(14) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
 func = Lua function '?' (defined at line 906 of chunk main.lua)
 inerror = boolean: true
 deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
 earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])

My game is crashing
Here's the new joker:

#
SMODS.Joker {
    key = "letter_j",
    loc_txt = {
        name = "J",
        text = {
            "This joker gains {C:mult}+#1#{} Mult per unscored {C:attention}Jack{}",
            "{C:inactive}(Currently {}{C:mult}+#2#{} {C:inactive}Mult){}"
        }
    },
    config = { extra = { gainMult = 6, mult = 0 } },
    rarity = 2,
    atlas = "alphabet_atlas",
    pos = { x = 1, y = 0 },
    loc_vars = function (self, info_queue, card)
        return { vars = { card.ability.extra.gainMult, card.ability.extra.mult } }
    end,
    calculate = function (self, card, context)
        if context.cardarea == 'unscored' and context.individual then
            if context.other_card:get_id() == 11 then
                card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.gainMult
            end
        end
        if context.joker_main then
            return {
                mult_mod = card.ability.extra.mult,
                message = localize { type = "variable", key = "a_mult", vars = { card.ability.extra.mult }}
            }
        end
    end
}
manic rune
#

uh wait, is localize supposed to look like that?

lavish lake
#

every other joker i have has this kind of localization message

manic rune
#

i see

lavish lake
#

and the game didnt crash

manic rune
#

well my best guess is probably at the if context.cardarea == 'unscored' and context.individual then part

lavish lake
#

we need to call our police officer mr. john smods

dreamy thunder
#

im returning localized messages like this

wintry solar
#

Update smods

lavish lake
wintry solar
#

Yes

lavish lake
#

i already have the latest version

wintry solar
#

No you don’t

manic rune
#

am i doing it right, never used localization in my life (probably a bad idea not learning this earlier)

atomic edge
manic rune
#

oh, no

atomic edge
#

shiet

manic rune
#

uhh lemme try finding it myself lol

atomic edge
#

no dont worry about it

lavish lake
manic rune
#

no no, im relatively certain i can find it

violet void
atomic edge
#

oh that would be great but dont make it take too much of your time

atomic edge
#

so basically once

#

i mean soul sprite

manic rune
#

oh

#

its a jen's almanac joker

atomic edge
#

thanks

atomic edge
manic rune
#

im booting up the mod to find, wait a bit

#

....oh im fucking dumb, its a legendary

#

not sure why i thought it was an exotic, sorry 😭

violet void
#

this worked for me but maybe its wrong

card.children.floating_sprite = Sprite(card.T.x, card.T.y, card.T.w, card.T.h, G.ASSET_ATLAS['prefix_atlas'], { x = 4, y = 5 })

minor furnace
#

I did this which does both, and seems to be working as I intended, so far at least

            G.E_MANAGER:add_event(Event({
                trigger = 'after',
                delay = 0.1,
                func = function()
                    card:shatter()
                    return {remove = true}
                end
            }))
        end```
manic rune
#

alright so can anyone explain to me how 'b_unlock_all' doesn't work, but 'ml_demo_thanks_message' does? they are both inside balatro's localization file

#

is it simply because b_unlock_all value isnt a table?

runic pecan
#

So I just defined a sticker.
How do I apply it to a playing card?

manic rune
#

thanks :D

#

FINALLY saw some progress, and its not even something impressive 😭

neat plover
#

how would i check if played card is a certain suit or rank

manic rune
neat plover
#

ok

ionic timber
#

is there any way to check if a certain sound is playing or not ?

autumn coral
#

q: would this work the way i'm thinking it would in my head

#

i need it to check if the probabilities after buying an oops all 6es is bigger than the saved probabilities

#

i know most of this is right i'm just thinking the context.after might not work the way i was thinking it would

#

i need it to pull the probability after tbh

wintry solar
#

And remove the event

#

Literally just need the return

wintry solar
#

card:set_sticker(“key”) iirc

#

Maybe add sticker?

#

Let me check

iron socket
#

Hey, me again. I've tried looking into the Steamodded documentation, as well as the example jokers mod and the source code, but I'm still pretty stumped on how to add a new Tarot card (specifically one that does the reverse of the strength card, reducing the rank of two cards by 1). Does anyone have an example mod that just adds a couple Tarot cards that I could investigate and learn from?

wintry solar
maiden phoenix
autumn coral
runic pecan
autumn coral
#

i haven't worked on my mod in like well over a month

wintry solar
autumn coral
#

the way it works is basically it supplies a minimum that it needs to surpass based on the highest value in order to change itself

wintry solar
#

I don’t remember if the buying context is before or after the add to deck call

autumn coral
#

gotcha

hardy viper
#

add an event maybe

autumn coral
#

hmm

hardy viper
#

and do the logic in there

autumn coral
#

yeah

#

wait should i just do context.added_to_deck?

#

is that even a thing

#

lmao

#

it should b e

#

honestly it should be

hardy viper
#

considering that doesn't exist

#

no

autumn coral
#

ok so how WOULD i get an event after oops all 6es is added,,, i'm sowwy my ass has forgotten this workflow

#

also did the context.other_card work in this context with buying_card

#

that's the only thing i need an answer to actually

hardy viper
#

it's context.card

#

for some reason

autumn coral
#

gotcha

#

so this would be right then?

hardy viper
#

probably better to do the check for oops outside of the event so you don't create a bunch of useless events even when your joker won't do anything

#

also, you need to return true at the end of your event so it doesn't loop forever

autumn coral
#

right right

wintry solar
#

Change name to key

autumn coral
#

gotcha

#

tbf both work

wintry solar
#

But also I don’t think this event will work

autumn coral
#

why

#

oh i forgot the return true again

#

lmao

wintry solar
#

It won’t be at the right point of the stack

autumn coral
#

any ideas on how to make this work realistically?

hardy viper
#

looks like it'd work to me? what would be wrong about it

wintry solar
#

Well first you need to check the order of the things, whether it’s calculate or add to deck first

autumn coral
#

i mean i can test it rn

atomic edge
#

does anyone know if there is a mod that dynamically changes the soul sprite of a card that i could look at (jen's jokers do something similar but not what im looking for)

autumn coral
atomic edge
#

oh

#

i didnt even see you guys responded to me

#

im sorry

manic rune
#

how do i make it so those text can be colored?

atomic edge
#

thanks so much ill try it

long sun
#

hi, this code is triggering on the last two cards, and not only the last card:
if context.cardarea == G.play and context.other_card == context.scoring_hand[#context.scoring_hand] and context.other_card.edition == nil then

#

what'd i do wrong? 😭

atomic edge
#

oh my god i can just do this card.children.floating_sprite:set_sprite_pos({x = 1, y = k - 1})

#

its from the hunter

#

thanks both of you so much

violet void
#

oh thanks for the info

autumn coral
#

it works

#

well, the first half works

#

let's see if it gets that the probabilities are higher

#

because yeah i forgot to write a print statement to check for that oops

#

cool

manic rune
#

idk

autumn coral
#

yep it works

manic rune
autumn coral
#

{C:(variable)}text here{}

manic rune
#

i tried doing that, doesnt seem to work

autumn coral
#

check steammodded wiki for the variables you can replace it with

#

weird

#

no clue

manic rune
long sun
spark tinsel
#

Hey, is there any fast reload game (with mods/mod) ingame (like keyboard shortcut or smth) - smods?

violet void
#

holding M

spark tinsel
#

Thank you <3

atomic edge
#

how does juice_card_until work?

#

nvm got it

tepid crow
limpid flint
#

M

minor furnace
neat plover
#

why is my lua always crashing and attempting to call a nil value

minor furnace
#

it should tell you which line is throwing the error

neat plover
#

nah it just says its attempting to call a nil value

limpid halo
#

further down

spring lantern
#

i guess i could specifically have it not copy any instances of brainstorm but iunno

iron socket
limpid halo
#

i think blueprint stops if it triggers more than the amount of jokers or smth

spring lantern
#

guess that could be one way to do it but it still seems a bit scuffed LOL

long sun
#

hi again, my sound effect isn't playing when my status text appears, how do i fix that?

play_sound("bfdi_david", 1, 0.5)
        card_eval_status_text(context.blueprint_card or card, "extra", nil, nil, nil, {
          message = "Nope!",
          colour = G.C.FILTER
        })```
manic rune
long sun
#

if i have five of them, they all play their sounds before the first message

violet void
#

have you tried adding it in an event

long sun
#

mhm

#

i don't think i did it correctly though

violet void
#

card_eval_status_text should already be an event

#

play_sound isnt

long sun
#

rightright

#

so, what should i do?

manic rune
#

yeah so im researching joyous spring (yugioh mod)

red flower
#

joyousspring mentioned

violet void
manic rune
red flower
#

ty let me know if u need any help

manic rune
#

i cant replicate how you colored the text 😭

long sun
#

cheers, will try that :D

manic rune
#

im reading this part rn

red flower
#

if you have your text in a description table and call localize it will make an ui object with the color

long sun
#

okay, cheers, it worked! thanks!!

manic rune
#

i basically copied your code over, except maybe the return part, to see if it works, but they just turned out to be two empty white boxes

#

...oh, now that i think about it, maybe the big difference here is that mine has more than 1 line in the localization stuff

#

lemme try smt

red flower
#

misc dictionary doesn't work with color

manic rune
#

oh

#

wait so that affects things too?

#

i thought its just for organizing stuffs, damn

red flower
#

basically the game parses the descriptions beforehand and makes text objects with the colors, scale, etc

#

it doesn't do that with the dictionary

#

or at least not that one

manic rune
#

oh damn, i never knew about that, thanks a lot 😭

#

gotta make sure im more careful with putting stuff in localization then, jeez

neat plover
autumn coral
#

now that i'm thinking about it, how does swashbuckler dynamically get the sell values of all cards in the joker slots?

#

there has to be a way to actually get if cards are added in real time other than the buying_card

red flower
#

card.sell_cost?

autumn coral
#

no sorry that was for what i'm doing

autumn coral
#

like right now my joker is wrapping buying_card to get when a joker is added to the library, but that's REALLY annoying for debug reasons and also would NOT work with an ankh so

#

like this only works with buying it

#

surely there's no way that swashbuckler checks every tick for the values LMAO

maiden phoenix
violet void
autumn coral
#

CRYING

neat plover
autumn coral
#

ok i'm gonna create my own event then i'm not scared of this shit

#

this shit's so inefficient

iron socket
# maiden phoenix Putting them in an event might help

I actually just figured out how to set the animation and sound up :) Now I'm trying to figure out a few bugs. I can select more than two cards at once and decrease the rank of all of them, and if I try to do it on a 2 some very weird things happen 😂

hardy viper
#

i don't think you need to use update? you should just be able to only do it right before it's relevant (loc_vars and calculate)

red flower
neat plover
maiden phoenix
# iron socket I actually just figured out how to set the animation and sound up :) Now I'm try...

You can use a can_use function on your consumable and check if the highlighted hand has 2 cards like this

can_use = function(self, card, area, copier)
        if G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK then
            return card.ability.extra.max_highlighted >= #G.hand.highlighted and #G.hand.highlighted >= 1
        end
        return false
    end,
red flower
#

missing a comma

maiden phoenix
#

card.ability.extra.max_highlighted is a config value

iron socket
#

Oh sweet, thanks!

maiden phoenix
#

(I should update the code since there's a SMODS booster thing iirc)

neat plover
autumn coral
#

mfw created my own context event because i'm not going to lag my game like that

#

lmao

red flower
#

you also have an extra comma

neat plover
#

after mod?

red flower
#

yes

ivory igloo
#

Really stupid github question
How do you just link to "latest release" directly, or is it just "link to the main zip download"

iron socket
minor furnace
#

If this is what you meant, then the card doesn't get removed from the deck, and does't get destroyed

            return {remove = true}
        end```
tepid crow
wintry solar
minor furnace
#

ah I see

ivory igloo
tepid crow
#

BMM might have some mods that directly link to the latest release download, idk what the link looks like by memory

ivory igloo
#

Ah I see, looking here I can always link to the correct page, but making sure it's always the latest file is down to the dev using the same zip file name it seems.

minor furnace
wintry solar
#

Add shatter = true to the enhancement definition iirc

minor furnace
#

oh that's just a built-in thing?

wintry solar
#

As of the other week yeah

minor furnace
#

it's crazy how many things are just not on the documentation page

#

because xchip also exists despite not being on the smods.enhancements page

wintry solar
#

Writing docs is boring I have better things to do 😂

minor furnace
#

fair enough lmao

#

I assume this goes inside of the config? it did not

wintry swallow
#

is there some introduction to making a mod, im wanting to make some card editions ideas i had

wintry solar
minor furnace
#

that was going to be the next thing I tried

tepid crow
#

(it'll be the source code instead of the provided zip, but that shouldn't matter for balatro mods afaik)

minor furnace
#

it did not work 💀

    key = "crystal",
    atlas = "New_Enhance",
    pos = {x = 1, y = 6},
    loc_txt={
        name="Crystal Card",
        text = {
            "{X:chips,C:white} X#1# {} Chips",
            "{C:green}#2# in #3#{} chance to",
            "destroy card",
        }
    },
    shatter = true,
    config = {
        extra = {
            x_chips = 2,
            shatter_prob = 4
        }
    }```
wintry solar
#

Let me check what it should be hold on

#

shatters

minor furnace
#

ahhhh

ivory igloo
minor furnace
wintry solar
#

Show code pls

minor furnace
#
    key = "crystal",
    atlas = "New_Enhance",
    pos = {x = 1, y = 6},
    loc_txt={
        name="Crystal Card",
        text = {
            "{X:chips,C:white} X#1# {} Chips",
            "{C:green}#2# in #3#{} chance to",
            "destroy card",
        }
    },
    shatters = true,
    config = {
        extra = {
            x_chips = 2,
            shatter_prob = 4
        }
    },```
wintry solar
#

That should work

#

What smods version are you on?

minor furnace
#

excellent question, let me check

#

I downloaded it like 3 days ago

wintry solar
#

Oh that will be fine

minor furnace
#

0.9.8 by the looks of it? in manifest.json

wintry solar
#

Check in your main menu

#

Top right

minor furnace
#

1.0.0 ALPHA 1415c

wintry solar
#

Yeah that’s fine

minor furnace
#

hmmm

#

well this is the full enhancement if it makes any difference

    key = "crystal",
    atlas = "New_Enhance",
    pos = {x = 1, y = 6},
    loc_txt={
        name="Crystal Card",
        text = {
            "{X:chips,C:white} X#1# {} Chips",
            "{C:green}#2# in #3#{} chance to",
            "destroy card",
        }
    },
    shatters = true,
    config = {
        extra = {
            x_chips = 2,
            shatter_prob = 4
        }
    },
    loc_vars = function(self, info_queue, center)
        return {
            vars = {
                center.ability.extra.x_chips,
                G.GAME.probabilities.normal,
                center.ability.extra.shatter_prob
            }
        }
    end,
    calculate = function(self,card,context)
        if context.main_scoring and context.cardarea == G.play then
            return { x_chips = card.ability.extra.x_chips}
        end
        if context.destroy_card and context.cardarea == G.play and pseudorandom('crystal') < G.GAME.probabilities.normal/4 then
            return {remove = true}
        end
    end
}```
wintry solar
#

And it doesn’t shatter?

minor furnace
#

nope, just the normal dissolve

past forge
past forge
# past forge any help on this?
SMODS.Enhancement { 
    key = "burnt",
    atlas = "enhancements",
    pos = {x=0, y = 0},
    
    replace_base_card = false,
    no_suit = false,
    no_rank = false,
    always_scores = false,
    
    config = {extra = { mult_mod = 1 }},
    
    loc_vars = function(self, info_queue, card)
        return {
            vars = { card.ability.extra.mult_mod}
        }
    end,
    calculate = function(self, card, context, ret)
        if context.cardarea == G.play and context.main_scoring then
            local text = G.FUNCS.get_poker_hand_info(G.play.cards)
            card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')})
            

            if not instant then 
                G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
                    play_sound('tarot1')
                    if card then card:juice_up(0.8, 0.5) end
                    G.TAROT_INTERRUPT_PULSE = true
                    return true end }))
                G.GAME.hands[text].mult = G.GAME.hands[text].mult + card.ability.extra.mult_mod
                update_hand_text({delay = 0}, {mult = G.GAME.hands[text].mult, StatusText = true})
                delay(0.6)
            end
        end
    end
}
#

this is the code btw

wintry solar
wintry solar
past forge
wintry solar
past forge
#

it works (the ui doenst update properly) but the problem is that when you use a planet card the mult will go to the mult of the level

wintry solar
#

I’ll check mine later and update smods if necessary

minor furnace
#

could I just write a lovely patch for this

                    G.hand.highlighted[i]:shatter()
                else```
wintry solar
autumn coral
#

IT WORKS LETS GOOOO

past forge
minor furnace
#

yeah that was my plan

past forge
wintry solar
#

I’ll fix it this evening on the smods side @minor furnace

minor furnace
#

thanks!

#

I'll see if I can get a patch working in the meantime, and then take it out once the update comes

past forge
#
if SMODS.has_enhancement(G.hand.highlighted[i], 'm_glass') or SMODS.has_enhancement(G.hand.highlighted[i], 'm_[your_mod_prefix]_crystal')  then
                    G.hand.highlighted[i]:shatter()
                else
#

maybe something like this should work

minor furnace
#

yeah that was what I was planning to try

past forge
#

nice

wintry solar
#

Literally just wait it’s just wasting your time otherwise

#

It’s like a thirty second job for me to change when I’m not on mobile

minor furnace
#

although I think it's "m_reverse_crystal" because of the prefix

wintry solar
#

And you won’t have to change any of your code

minor furnace
#

it gives me practice patching

#

it's a fun exercise at least

#

oh well the pattern didn't match I'll just move on then

marsh basalt
#

Hello, can I ask - how could I get the playing card negative info blurb on the joker?

#

I'm currently using G.P_CENTERS.e_negative info queue with the Joker but I cannot find what the playing cards use

autumn coral
#

how do i get the current mult and chip values of the current played hand? i already have the post-scoring stuff set up, i just forgot, it's blind something i don't remember

#

i need to store it in a variable :p

#

wait isn't it just mult and hand_chips

#

am i stupid

marsh basalt
red flower
#

its an smods thing

marsh basalt
#

Ah

#

My bad

#

Oh, right, SMODS is itself a mod

#

I should be checking that too

marsh basalt
autumn coral
#

how can you get the final mult and chips from a hand after all other jokers have scored actually

#

can't figure out the context event for some reason

#

💀

#

bc uh

#

if context.final_scoring_step and context.cardarea == G.play then unfortunately this doesn't work

#

pretty sure this one's locked to plasma iirc

faint yacht
#

hand_chips and mult are globals you can access, which are the currently scored chips and mult as shown in the boxes respectively.

autumn coral
#

why are they tables lmao

high stag
#

any idea why this is giving nil?

primal robin
autumn coral
#

OHHH

autumn coral
#

thanks actually i wouldn't have caught that lmao

primal robin
#

You should use all values in your calculations as to_big(number) instead

#

Do not try reverse it

autumn coral
#

no i need to like retrieve the value

#

my card takes the max value of chips and mult played this run and sets all hands to use that instead of anything lower, or use whatever is higher

primal robin
#

This not how it works

#

If you're interacting with big numbers, you must do all stuff in big numbers

autumn coral
#

ok well how can i compare one to another

#

because that's the only thing i need to do here

primal robin
#

if to_big(hand.chips) > to_big(my_stored_chips) then end

autumn coral
#

cool

#

thaanks

#

thanks*

#

that's all i neede

manic rune
primal robin
#

And to prevent mod from crashing, you must include on start of file

to_big = to_big or function(n) return n end
high stag
autumn coral
#

how can i represent it at

#

mk

#

oops didn't mean to press enter

#

how can i represent it as a string lmao

#

or does it do that automatically

#

nevermind

#

i see it

manic rune
primal robin
#

No clue

left lance
high stag
#

yeah that solved it, thanks y'all
now to make the card actually work TashaLOL

left lance
high stag
#

it's Caino-based and I've been tweaking the code from that one, idk why its not proccing yet, currently working through that

grim remnant
#

silly question, how do i make a food joker that like, decays over time a-la ice cream/popcorn?

#

(namely, how could i like, designate it as a food joker, for the sake of other mods.)

autumn coral
left lance
grim remnant
#

like, we just don't wanna be caught off-guard if there is some unspoken agreement of "oh you mark a food joker as isFoodJoker = yea, in the code for other mods". totally understand if this is just me overthinking it tho, fdsgjhk

left lance
#

Oh if other mods have other ones they're handling that separately from how the base game does it. From what I can tell the basegame just treats them like any other joker, but with a destroy event after a certain number of rounds (though admittedly I am trying to make my own but am running into an issue with it never updating the value, so take what I say with a grain of salt)

hardy viper
high stag
#

you could snag the extra values from every joker in play every hand, then snag them again and compare to see if they go down, but that would probably grab a few jokers you dont intend

maiden river
#

does anyone have any sort of template/reference for making art for seals
it's not in the community assets

grim remnant
autumn coral
minor furnace
#

Ain't no way I got this code to work first try

autumn coral
#

ok so how do i make my joker trigger directly at the end of all other calculations

#

like i want it to be after all x mults and all other effects

#

bc that's the last step here

maiden river
#

there's context.after, right?

minor furnace
autumn coral
#

yeah but i couldn't get that one to work

left lance
autumn coral
#

LOL

maiden river
autumn coral
#

mattman scream

autumn coral
#

context.final_scoring_step doesn't work either

#

i can try again though!

maiden river
#

this is what it says in the wiki

autumn coral
#

yeah i tried that too

#

didn't do anything

#

but also i don't want it to be after scoring, i want it to be after all effects

#

i want it to be the final effect that occurs, like plasma or smf like that (well, actually i want to do it after plasma)

#

actually i could just look at cryptid there's a card that does something similar

#

the answer is always cryptid sigh

stray wing
#

Posted about an issue before , but I've narrowed down the cause and am looking for some advice. I'm writing a joker that replaces Gift card, and the code for that is here

    "j_gift",
    {
        loc_txt = {
            name = "Skips",
            text = {
                "Current xmult #1#",
                "Gain xmult is #2#"
            }
        },
        atlas = "Wada",
        config = {extra = {xmult = 2, xmult_gain = 1}},
        pos = {x = 0, y = 0},
        loc_vars = function(self, info_queue, card)
            return {
                vars = {
                    card.ability.extra.xmult,
                    card.ability.extra.xmult_gain
                }
            }
        end,
        calculate = function(self, card, context)
            if context.joker_main then
                return {
                    xmult = card.ability.extra.xmult
                }
            end
            if context.after then
                card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain
                return {
                    message = "Charged up!",
                    colour = G.C.CHIPS,
                    card = card
                }
            end
        end
    }
)

I'm getting a crash for trying to perform arithmetic on a table extra, and I finally figured it out.

Gift card's base config has this:

j_gift= {order = 79, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Gift Card",set = "Joker", config = {extra = 1}, pos = {x=3,y=13}},

where the sole variable is stored under the name extra. I tried changing the name of the inner table on my joker to extran, so like this:
config = {extran = {xmult = 2, xmult_gain = 1}},
but that didn't solve the issue. Is there an easy way to fix this?

tepid crow
maiden river
autumn coral
#

ok i found it

#
if context.cardarea == G.jokers and not context.before and not context.after and not context.debuffed_hand and hand_chips and mult then
#

this is what cryptid has for sync catalyst which essentially does this exact thing

wintry solar
#

context.final_scoring_step is the plasma step

autumn coral
#

yeah

#

figured

wintry solar
#

if it "doesn't work" then you're likely using it incorrectly

autumn coral
#

no i got it

minor furnace
hardy viper
#

explodes your computer

#

99.999%

wintry solar
#

don't use that

#

its old jank that will break with other stuff

autumn coral
#

me or

#

uh

hardy viper
#

not context.before and not context.after is probably what eremel is referring to

left lance
autumn coral
#

i'll check it out in a sec

minor furnace
# minor furnace well uhh, it sure does say Nope *somewhere* on the screen

literally just copied this from the regular wheel of fortune, not sure why the offset is wonky

                attention_text({
                    text = localize('k_nope_ex'),
                    scale = 1.3, 
                    hold = 1.4,
                    major = used_tarot,
                    backdrop_colour = G.C.SECONDARY_SET.Tarot,
                    align = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK) and 'tm' or 'cm',
                    offset = {x = 0, y = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK) and -0.2 or 0},
                    silent = true
                    })
                    G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function()
                        play_sound('tarot2', 0.76, 0.4);return true end}))
                    play_sound('tarot2', 1, 0.4)
            return true end }))```
stray wing
#

As a general question, is there a reason modded jokers usually have their variables as extra inside config?

tepid crow
#

Other stuff doesnt get stored by default iirc

stray wing
tepid crow
#

To the save file. When exiting the game

stray wing
#

okay, so if I were keeping variables like config = { cost = 2 }, I'd have issues loading a save?

wintry solar
#

it just wouldnt be there when you loaded

tepid crow
#

It might just not be provided instead of being false

wintry solar
#

@minor furnace fixed in 1418a

autumn coral
#

removing the stuff you asked for broke it lol

#

actually wait

wintry solar
#

what code do you have

autumn coral
#

i might've broken it myself

#

hold on

#

lmao

#

no yeah it broke lmao

#

ok whateevr

#

i'll just bring it back

#

clearly it works bc cryptid has it and honestly idrc if it's bad practice bc if it works it works

minor furnace
wintry solar
#

it works in old calc but new calc it either wont work or will likely break with other mods

#

just do it properly

grim remnant
#
        if context.joker_main then --score Xchips
            xchips = card.ability.extra.Xchip
            return {message = "TEST" }
        end```
for whatever reason this isn't scoring xchips? everything else works just fine...
wintry solar
#

smods version?

minor furnace
#

oh yeah, wer're shattering cards now

tepid crow
left lance
grim remnant
#

OH. i forgor the return 😔

autumn coral
#

i got it to work

stark moss
#

how hard is balatro modding? i kinda wanna look at it and get into it but im curious. it doesnt sound too difficult but idk

autumn coral
#

i'll make sure to add that they need the cryptid version of smods though in the release notes

tepid crow
#

I love actively developing for old-calc

wintry solar
#

its the best right?

#

only 6 weeks out of date đŸ€·â€â™‚ïž

autumn coral
#

i'm a college student i really don't give enough of a shit lmao

#

when it's convenient i'll fix it

tepid crow
autumn coral
#

it is not convenient right now

midnight heath
#

is there a way to make a soundtrack mod where it can be toggleable like the cardsauce mod? I never used lua

left lance
tepid crow
#

To the lovely console yes

left lance
#

... man this one is really thowing me for a loop, but I'll try again to see if I can get the print statements working

wintry solar
#

try changing it to not context.game_over

tepid crow
#

If the print is the first thing in your calculate and its not printing, sounds like your calculate isnt being called

wintry solar
#

OH

#

it's calculate = function(self, card, context)

#

you have them the wrong way round

#

but also change the game_over thing, nil doesn't equal false

left lance
tepid crow
#

Ugh good catch

wintry solar
#

lars do you remember any of the shop util stuff people wanteD?

tepid crow
#

Shop util stuff?

#

Wdym

wintry solar
#

like people wanted an easy way to icnrease the number of boosters

#

I've done booster count, voucher count and free reroll count, but I don't remember what else there was, if anything

tepid crow
#

Ah

#

I dont think I was ever part of those conversations tbh

#

Though it might be nice if steamodded automatically supported big shops?

#

iirc the shop starts going off-screen at like 8 items in the main shop

wintry solar
#

hmmm I'll take a look

grim remnant
#

wuh oh, what are we doing wrong here

wintry solar
#

hmmmm it seems I have already patched this somewhere

tepid crow
#

I'm assuming cryptid isnt in your mod list?

wintry solar
#

it is not

tepid crow
#

Alright, already fixed it is then

#

Perfect

grim remnant
wintry solar
#

I remember doing it sometime ago but I don't know if its in smods or something locally I have

wintry solar
tepid crow
#

I don't recall this being in a recent smods version

wintry solar
#

lemme see if I can track down what's handling it

grim remnant
#

wait i think i spoted PART of the issue

wintry solar
#

it's in ortalab for some reason đŸ€Ł

grim remnant
#

okay no, that made the error happen earlier and i feel like i was not meant to remove that return.

tepid crow
#

Your lua is right to complain

#

Why is there a { on line 332

wintry solar
#

you can also just call card:start_dissolve() to remove it iirc

tepid crow
grim remnant
#

okay, it works now, but i can't figure out how to display the "Eaten!" text. what do?

midnight heath
wintry solar
#

I'm 99% sure you can just change your code to be

if card.ability.extra.Xchip <= 1 then
  card:start_dissolve()
  return { message = localize('k_eaten_ex') }
end
tepid crow
orchid thunder
#

how can i do something to a joker when it is triggerd

neat plover
red flower
neat plover
#

where is that

grim remnant
red flower
#

extensions

wintry solar
old bane
#

Would this code make it so that each card in the scoring hand be one random rank?

local rank = pseudorandom('washing', 2, 14)
for k, c in ipairs(context.scoring_hand) do
  assert(SMODS.change_base(c, nil, rank))
end 
orchid thunder
#

what is the table telling me

#

so if i do other_card it will use the said triggerd card?

grim remnant
#

that works! though uh. in testing all this i accidentally stumbled upon a bug for an entirely unrelated thing

#

for whatever reason, this doesn't detect cards self-destructing; like food cards being eaten, or gros michel going extinct. uh. How would we do that?

local card_remove_ref = Card.remove
function Card:remove()
    if self.area and (self.area == G.jokers) and not G.CONTROLLER.locks.selling_card then
        SMODS.calculate_context({joker_destroyed = true , card_destroyed = self})
    end
    card_remove_ref(self)
end```
normal crest
#

Instead of checking self.area check self.added_to_deck

#

If you do thar you'll have to add another check for if the card is actually a joker

grim remnant
#

how would we go about that? we mean, outside of just appending another "and" check--that much is obvious--we mean like, what variable ;P

normal crest
#

if self.ability.set == "Joker" and self.added_to_deck and not G.CONTROLLER.locks.selling_card then

#

Food jokers get removed from the jokers card area before Card.remove is called, which is why checking for the area doesn't work

#

but added_to_deck gets set to nil in Card.remove, so you can use that if you hook at the start

wintry solar
#

is this a custom context?

normal crest
#

Yes

grim remnant
#

that worked, thank you very much!

wintry solar
#

put it in remove from deck

grim remnant
#

Danton will now re-imburse you for your Gros Michel.

#

(sentence that makes a LOT of sense, we're sure.)

normal crest
#

Why would that be better

wintry solar
primal robin
wintry solar
minor furnace
#

do custom enhancements automatically get added to the G.P_CENTER_POOLS["Enhanced"] enhancement pool?

normal crest
orchid thunder
normal crest
#

e_polychrome

orchid thunder
#

oh ok

wintry solar
#

context.other_card

orchid thunder
#

oh ok

wintry solar
old bane
#

am i able to make it so that a steel card permanently gives more mult when it's held in hand?

orchid thunder
#

how can i "upgrade" an edition

hardy viper
#

iterate through the pool of editions, find the index of the edition you currently have, increment it by 1, and index the pool of editions with that to figure out the next one (and if that doesn't exist you wrap around to 1)

#

alternatively do center.order

#

i think they should be the same

grim remnant
#

wuh oh. when hovering over spring mushroom in the collection menu when you haven't started or loaded a run yet, the game. Dislikes that.

ionic timber
#
calculate = function(self, card, context)
        if context.discard and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
            G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
            G.E_MANAGER:add_event(Event({
                trigger = 'before',
                delay = 0.0,
                func = (function()
                        local _card = create_card('Uncannycard',G.consumeables, nil, nil, nil, nil, nil, nil)
                        _card:add_to_deck()
                        G.consumeables:emplace(_card)
                        G.GAME.consumeable_buffer = 0
                    return true
                end)}))
            card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Feur", colour = G.C.PURPLE})
        end
    end

I kinda need help, I'm trying to have an effect on my custom seal similar to the purple seal, but for some reason it creates two cards instead of one, I might just be missing something but this code is mostly similar to the purple seal so I'm confused

orchid thunder
red flower
#

in loc vars

grim remnant
#

uhhhh, how do i do that

red flower
#

if G.playing_cards then

orchid thunder
wintry solar
#

you're on old calc jank mode

orchid thunder
#

oh shit

grim remnant
red flower
#

the syntax is

if your_condition then
-- your code
end
grim remnant
#

THERE we go

midnight heath
# tepid crow So what's your question

i'm not sure. i'm so new to this whole thing and im afraid if any question is gonna be very dumb to the smartest masters of lua coding, even though i'm new.

tepid crow
#

If you're completely new, I suggest checking out some "how to code in lua" tutorials

midnight heath
tepid crow
#

Regardless your 2 options are either to ask someone to do it for you, or learn how to do it yourself

midnight heath
long sun
#

hiya, this ability triggers at the right time, but doesn't destroy the cards it triggers on — how would i do that?

if context.destroying_card and context.destroying_card.ability.name == 'Glass Card' then
      card_eval_status_text(card, "extra", nil, nil, nil, { message = "Pranked!", colour = G.C.FILTER })
      return nil, true
    end```
tepid crow
midnight heath
#

ok

orchid thunder
minor magnet
#

can someone tell me why this doesn't display correctly?

#

the green bar which should show you what's your last used tarot doesn't show up

#

at all

wintry solar
#

I believe you need to return the main_end

minor magnet
wintry solar
#

outside, like main_end = main_end

#

also probably need a local on where you create it

limpid halo
#

im having a bit of a brainfart but is it possible to get card variables in Card:draw ?
self.config.center.config seems to just get the default values and not anything that's been modified since the card was spawned

olive moth
#

trying to create a simple deck mod, what am i missing here? what could cause this?

#

it seems like it's not an error in my code necessarily, but the way it interacts with the game i think?

#

this is literally the whole code rn
do i need to add actual functionality before i can see the deck ingame or..?

minor magnet
wintry solar
#

what does the crash say?

olive moth
#

yall asking advanced questions, i feel like a neanderthal among you lowkey 😭

tepid crow
sturdy compass
#

Just put some brackets around the string and all should be good

tepid crow
#

Well

#

I'd use the proper keys too

sturdy compass
#

oh yeah u right about that too

olive moth
#

thank youuu

tepid crow
#

Return remove = true

#

Not literally, in a table

sturdy compass
#

Oh yeah random question I've been wondering but haven't tried yet: Is it possible to pass a sound variable in the extra table of a card_eval_status_text call?

wintry solar
#

do you need to use card_eval_status_text?

long sun
#

ah that worked! cheers ^^

wintry solar
#

-# the answer is yes but you shouldn't need to use that jank ass function

limpid halo
#

wait why not what's the correct func to use

wintry solar
#

just use the return table

limpid halo
#

but what if you want to do multiple / outside of calculate?

sturdy compass
wintry solar
#

then you can use SMODS.calculate_effect({table here}, card_to_act_on) if outside of calculate

#

if you need to chain messages you can add extra = {new table here} to your return table

sturdy compass
#

Here's the code I've currently got that's causing this ask

#

It's probably bad but to be fair it worked

wintry solar
#

I mean card_eval... works it's just jank to use

#

like you could replace it with SMODS.calculate_effect({message = "success!", colour = G.C.GREEN}, card) there and avoid all the nils

sturdy compass
#

And judging from the answer, I would be able to add a sound field?

wintry solar
#

yes

sturdy compass
#

sick, thank ya

wintry solar
#

it'll also work if you just add sound to cest

left lance
#

Okay y'all, a final quesiton I have before I stop bothering y'all for a bit; I'm trying to make a version of abstract joker with money instead of mult; if I test it in a game it works fine, but it crashes my game if I view it in the collection not in a game. I know I have to do something where I tell it because it can't access #G.jokers outside a game it displays 0, but I'm unsure how to actually enforce it

sturdy compass
minor furnace
#

working as intended 🙂

left lance
tepid crow
#

That would work yes

orchid thunder
#

how can i make post trigger happen well On trigger

#

it happens beforee they trigger

tepid crow
#

I don't think you can? That's why it's called post trigger?

orchid thunder
#

post is after 💀

tepid crow
#

Wait you're saying "post triggers are happening before the actual trigger"?

orchid thunder
tepid crow
#

How can you tell that's happening?

orchid thunder
#

il get a video

#

i cant explain

tepid crow
#

Sure

wintry solar
#

post triggers definitely happen after

orchid thunder
wintry solar
#

show your code

#

you're using instant messages

tepid crow
#

Yeah that's my guess too

orchid thunder
#

Oh

normal crest
left lance
normal crest
#

Yeah if G.jokers exists it'll return the length of cards * 2, otherwise 0

left lance
#

huh yeah, thats def me thinking things work like they would in python, or close to it

orchid thunder
wintry solar
#

add the delay argument to the edition

orchid thunder
wintry solar
#

immediate to false

orchid thunder
#

is it set on to default?\

wintry solar
#

I don't remember

#

but worth a try

#

otherwise throw them in events

orchid thunder
limpid halo
#

im having an immense skill issue trying to get a soul_pos to not be centered on the base card.
Anyone know what to change to get a Sprite() to draw at a offset? i was trying with it's X and Y but that doesn't seem to do anything
also modifying stuff with the draw_shader call i don't really get any usable results :v

left lance
wintry solar
#

put {count}

left lance
#

ah it is literally that easy

#

Lua... truly one of the programming languages of all time

normal crest
#

dont blame it on lua

#

vars is just meant to be a table

left lance
hardy viper
#

i love ambiguous typing!

#

does zig do that

#

i don't think zig does that

#

oh it does

#

sick

edgy reef
#

It is extremely strange but I do value Lua since imo it's less painful to learn as a first language compared to the presumed hell of immediately jumping into C or C-ish languages.

#

(technically I learned Python first but that language is fake)

#

I do wish the Lua LSP was less... atrocious to work with.

normal crest
#

I also found myself really enjoying Lua

orchid thunder
normal crest
#

But it comes with all the problems of dynamically typed languages that's annoying

wintry solar
#

I think dynamically typed languages are only annoying if you already know how to use a typed language

normal crest
#

Yeah, then you know what you're missing out on

edgy reef
#

"Fuck it we ball" typing is fun sometimes

wintry solar
#

I don't mind it now I'm used to it again though, it's actually remarkably useful in some situations

normal crest
#

It is but making large projects with it becomes more difficult imo

edgy reef
#

Hobby language moment

#

I just wished the LSP got the memo because it genuinely think Lua is statically typed (or at least tried to force it).

hardy viper
#

lua doesn't have too much bullshit with iterators and it doesn't force an abysmal amount of OOP onto you which i love

violet void
#

is self.deck_preview the thing I need to check if I want these custom card areas to move down too when hovering the deck?

high stag
#

I'm not insane for thinking that nothing should be able to hit the else to print "after" right? like, I have a yes or no question as the other 2 if options, is the score nil? If yes, return "score is nil" if it isnt return that it isnt and do the rest of the code

and yet, somehow, "after" returned

#

the errors are about booting up the shop

normal crest
#

Maybe nil * nil is nan, but idk

orchid thunder
wintry solar
#

I think it's this

#

try wrapping the math.floor(... in brackets

gaunt thistle
#

lua doesn't need types. Mike Hall didn't sacrifice all he loved so you could sully luajit with types.

normal crest
#

I don't think anyone said lua needs types tbh

wintry idol
#

i learnt it and liked it for a bit but

#

man

high stag
wintry idol
#

it’s like inconsistent with other languages and inconsistent with itself

#

and then also slower than other languages

gaunt thistle
#

python is fun

#

but it's a pain

high stag
#

it came back saying i was comparing the value of the hand with nil

chrome widget
#

Ideally for really big projects, it can be beneficial to use both weakly and strongly typed languages tbh. My last job had us use this big C#/C++ engine, but had a whole big typescript scripting engine hooked into it

wintry solar
chrome widget
#

That said I'm kinda shit at backend programming and have hated what little of it I've done, so I'm glad to not have to work with that

wintry idol
#

neat**

#

the more nested your code is the harder it gets to manage

#

but it does come down to preference

chrome widget
#

Can concur, early returns are neat

high stag
#

for me its a preference thing, the more nested it is the easier it is for me to chunk it apart

#

I can go "okay we are still within that function/loop/if/etc's bounds" just by seeing the tier

normal crest
#

But if your entire function is inside a condition then you might as well early return

high stag
#

the messy part comes from when I just flat shove chunks of the base game code in the middle of that

left lance
#

okay as ACTUALLY a final question... this currently changes money not once per round but continuously... is there a way to fix that without making some weird local variable and doing tracking that way? also is context.start_of_round not the opposite of context.end_of_round?

normal crest
#

add and context.main_eval

#

There's no start_of_round, there's setting_blind tho

#

Or first_hand_drawn if that's what you want

left lance
#

oh yeah first hand drawn is best

gloomy rain
#

need help with making kinda unique joker code

I want to make a joker that gives you a 1 dollar at the end of a roudn for every face card that gets destroyed

Like Canio but for money instead of mult

wintry solar
neat plover
violet void
maiden phoenix
wintry solar
#

some of the types of area don't have them

neat plover
gloomy rain
#

like the 7/8 that shows you cards in hand at the bttom right

#

I think

neat plover
#

oohh

neat plover
#

LIKE IT'S BEEN TRYING TO FOR THE PAST HOUR

wintry solar
#

your context check isn't specific enough

neat plover
#

what is that?

hallow slate
violet void
minor furnace
#

For some reason, it's triggering the effect to lose money twice at the end of the round

    key = "pyrite",
    atlas = "New_Enhance",
    pos = {x = 2, y = 6},
    loc_txt={
        name="Pyrite Card",
        text = {
            "{C:mult}+#1#{} Mult",
            "when {C:attention}played",
            "{C:money}-$#2#{} if this",
            "card is held in hand",
            "at end of round",
        }
    },
    config = {
        extra = {
            mult = 6,
            p_dollars = 2
        }
    },
    loc_vars = function(self, info_queue, center)
        return {vars = {center.ability.extra.mult, center.ability.extra.p_dollars}}
    end,
    calculate = function(self,card,context)
        if context.main_scoring and context.cardarea == G.play then
            return { mult = card.ability.extra.mult}
        elseif context.end_of_round and context.cardarea == G.hand then
            return { p_dollars = -card.ability.extra.p_dollars}
        end
    end
}```
grim remnant
#

Silly question; how can we make it so that a specific calculation doesn't happen when Blueprint'd, but others will? Some scaling jokers are acting rather strangely with blueprint, and while it's funny, it's also causing some cards to become... A little counter-intuitive.. ;P

neat plover
minor furnace
minor furnace
#

oh for consistency I shoul probably call the extra h_dollars I suppose

neat plover
#

i really don't see the problem with my code

spark tinsel
#

any ideas are helpful <3

wintry solar
neat plover
#

how do i make this work then

wintry solar
#

look at the calculate guide and find the timing you want and copy the check

neat plover
#

well its the one im using if i want to upgrade the joker when a certain card with suit played

zealous glen
#

Cool

placid ember
#

I'm making a version of balatro called IRLtro that uses ARUco tags on cards to read them automatically with a webcam, and since I need to recreate the entire game in python for it to work it's currently playable in the command line

am I allowed to publically share the repo? it doesn't use any source code from the game, I've just taken all of the information on the wiki and recreated it

wintry solar
neat plover
#

ok thnks!!

violet void
wintry solar
#

not off the top of my head

neat plover
#

ok

#

before it triggered between 3 and 6 times now its only 2 but still the same problem

normal crest
wintry solar
#

what does your code look like now?

unkempt thicket
#

where can I iterate though each joker, right after they are initiated?

neat plover
vestal ore
#

is there a way to set a playing card in the deck to be a steel card in debug mode while in a run?

#

(or just, any enhancement?)

violet void
vestal ore
wintry solar
wintry solar
neat plover
wintry solar
#

yes, for every card you play you loop over the entire hand right now

unkempt thicket
#

How can I check if each in-game joker contains a specific var?

minor furnace
#

What is it about this context that loses the money twice at the end of the round?

        if context.main_scoring and context.cardarea == G.play then
            return { mult = 6}
        elseif context.end_of_round and context.cardarea == G.hand then
            return { dollars = -2}
        end
end```
#

Or I guess, I should dig through and see what Gold cards do

graceful magnet
#

is there an easy way to check when the player's money decreases?

junior pine
#

bumping this, I've been digging through the G.blind_select_opts table, but can't find the things I'm looking for

unkempt thicket
rain latch
#

anyone know how to fix this with the images

minor furnace
#

Thousand Year Door 👀

neat plover
wintry solar
#

use context.other_card

neat plover
#

ok i feel really dumb now

high stag
#

what's the context for checking something about each individual card in a played hand before score starts getting counted?

neat plover
#

broad question, in lua, to put an if after another one, do you need particular syntax or not?

novel dagger
#

I got this error saying [SMODS _ "src/game_object.lua"]:363: Failed to collect file data for Atlas Garty_Jokers and I have no idea what that means

minor furnace
#

or do you mean the if statement is nested?

neat plover
#

no no that was what i meant thanks

#

YESSSS

#

FINNNAALLLY

coral grotto
#

i'm trying to make a joker that scales when a specific modded tarot card is used, what i've got now doesn't seem to be working
i tried using context.consumeable.ability.name as well (which worked when i switched it to a vanilla tarot), is there some specific SMODS thing i need to use to make this work

        if context.using_consumeable then
            if context.consumeable.key == "tarot_grungler" then
                card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.extra
                card_eval_status_text(card, "extra", nil, nil, nil, {message = localize({type = "variable", key = "a_xmult", vars = {card.ability.extra.xmult}})})
                return nil, true
            end
        end
neat plover
novel dagger
rapid heart
#

Does anyone know how to change the speed of the music in game?

ionic timber
junior pine
# junior pine bumping this, I've been digging through the `G.blind_select_opts` table, but can...

if anyone is wondering, you can get the tag if skipped can be found in G.GAME.round_resets.blind_tags, win chips is get_blind_amount(G.GAME.round_resets.ante)*G.UIDEF.current_blinds().nodes[i].nodes[1].nodes[1].nodes[1].nodes[1].config.ref_table.mult*G.GAME.starting_params.ante_scaling, reward is G.UIDEF.current_blinds().nodes[i].nodes[1].nodes[1].nodes[1].nodes[1].config.ref_table.dollars and the name of the blind is G.UIDEF.current_blinds().nodes[i].nodes[1].nodes[1].nodes[1].nodes[1].config.ref_table.name

zealous glen
ionic timber
#

that's the thing, I don't know why

#

I'm only discarding one card, and most of the code is like purple seal , and this one works well

sturdy compass
#

Alright time to get a bit technical (maybe). I have two jokers that act as blueprints, but they both copy the ability of cards whose positions can change. My current solution is to store the card table in a variable, and that works fine unless the player closes the game and continues the run later, causing a crash. I believe I have been told that variables that hold tables are cleared on restart so I'm sure that's what's causing it, but I'm unsure of how I should go about fixing this. I had an idea that involved just storing the card's key instead, but I'm not sure how I should calculate the card's ability from that key. Any ideas? Here's the code of one of the two jokers to give an idea of what I'm working with

unkempt thicket
#

how do you get a cards cardarea from the card itself? (in this context SMODS.current_mod.set_debuff(card))

red flower
#

card.area

grim remnant
#

how do we add a new deck exactly?

rapid heart
#

Is there any way to stop just the music's pitch from changing? There's a custom song I want to import and it always changes the pitch and stuff
There was a line of code that I changed that fixed the issue but then the pitches for other sounds were messed up and Idk if there is another way around it

sturdy compass
limber blaze
grim remnant
#

we also went to the well of Big Penny for joker design inspo

limber blaze
#

looks awesome

grim remnant
#

please do not change yours. we think it is objectively hilarious if there are two distinct pennies that double in size that function differently based on mod. of all the concepts to run into the "50 minecraft mods that all add copper ore" conundrum

limber blaze
#

oh yeah this one increases size every time too like physically it gets bigger but its not doubling its not even multiplicative

#

it just gains 0.1 scale

grim remnant
#

AWESOOOME

limber blaze
#

i keep adding rare jokers that are annoying to implement and by keep i mean its happened only 1 other time so far

normal crest
limber blaze
limber blaze
# normal crest surely the scale is limited

i mean to get high enough for it to matter youd have to go past ante 38 cause the max scale getting it on ante 1 would put the scale at 4.9 which is honestly not too outrageous

minor furnace
#

Making a Mult equivalent of a Stone card, but it didn't score when I played it with a pair

    key = "marble",
    atlas = "New_Enhance",
    pos = {x = 3, y = 6},
    loc_txt={
        name="Marble Card",
        text = {
            "{C:mult}+#1#{} Mult",
            "no rank or suit",
        }
    },
    config = {
        extra = {
            mult = 10
        }
    },
    replace_base_card = true,
    no_rank = true,
    no_suit = true,
    alaways_scores = true,
    loc_vars = function(self, info_queue, center)
        return {vars = {center.ability.extra.mult}}
    end,
    calculate = function(self,card,context)
        if context.main_scoring and context.cardarea == G.play then
            return { mult = card.ability.extra.mult}
        end
    end
}```
coral grotto
#

misspelled always

minor furnace
#

thank you

#

I swear it's always the dumbest things

#

yeah that did it

coral grotto
# coral grotto i'm trying to make a joker that scales when a specific modded tarot card is used...

i've tried the following:

        if context.using_consumeable then
            if context.consumeable.config.center_key == "The Grungler" then
                card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.extra
                card_eval_status_text(card, "extra", nil, nil, nil, {message = localize({type = "variable", key = "a_xmult", vars = {card.ability.extra.xmult}})})
                return nil, true
            end
        end

and have added this to my consumable:

config = {
        center_key = 'The Grungler'
    },

still doesn't appear to be working, is there anything i'm doing wrong

sturdy compass
minor furnace
# limber blaze

so you can disable Oops All 6's while playing glass then? 👀

limber blaze
#

you can do many things

high stag
#

So I am still working on that joker that changes card suits
With this layout of Jokers, a played Heart card currently follows this order of events:
displays as heart
changes to spade
triggers Lusty Joker
triggers Reverse Card
triggers Wrathful Joker

I am looking to make it follow this order instead:
displays as heart
triggers Lusty Joker
triggers Reverse Card
changes to spade
triggers Wrathful Joker

any idea what needs to change about this code to cause the "changes to spade" element to not trigger until the reverse card is triggered? (and yes I know that the return currently triggers an Upgrade! message, I'm gonna fix that once the card functions correctly otherwise

foggy carbon
marble flint
grim remnant
#

does anyone know if it's possible to give a deck a soul layer? i had a really cool effect in mind, but uh, just trying to insert pos = { x = 1, y = 0 }, soul_pos = { x = 2, y = 0 } did nothing

sturdy compass
#

You'd probably have to make some injects into Back rendering code to get that to work

grim remnant
#

whoof, guess i'm not doing that unless steamodded updates to vastly streamline that particular process ;P

high stag
old bane
#

how do i update the info center to match a dynamic tarot card? I want to make it so that a Joker gives you the tarot card matching the suit you have the most of (if you have more Spades, it'll give you the World), and I want the info_center bubble to update to the appropriate tarot card (like if it'll give you a Moon card, the info_center will show you the description of the Moon)

grim remnant
#

more on the actual functionality side, how can i make it so the player starts with a random joker of a given (custom) rarity? i mean i could also start them with the card that SPAWNS that given rarity but that is vulnerable to a Perkeo Moment

high stag
#

let em perkeo

neat plover
#

for common, give em a riff raff

grim remnant
#

i mean, i need it to be for a custom rarity. the closest thing i can think of to compare it to is Wormhole Deck in Cryptid.

sturdy compass
#

I think you should just do a normal create_card() process the deck's apply function

#

For the rarity parameter, here's what the vanilla rarities act as

#

Not entirely sure how a custom rarity would factor into that tho

rain latch
#

making this mod pack is def guna push me to the edge lmao

grim remnant
#

how do we run the apply(self, back) function and put create_card() in it, exactly? (this is the first time we've made a deck so we have NO idea what the syntax is here)

#

(also would it be like, bad to use SMODS.add_card over create_card() for this)

normal crest
#

the apply function is not run by you

#

and do use SMODS.add_card

old bane
#

how would i use localize to get the name of a tarot card by key? would it be like
localize{type = "Tarot", key = 'c_world'}?

grim remnant
#

okay, yeah, the syntax here is all wrong. how do we apply?

sturdy compass
#

you forgot an end

unkempt thicket
#

How can I check if each in-game joker contains a specific var?

sturdy compass
#

Are you checking for a returned value or just one that's being stored?

unkempt thicket
#

A vaule thats being stored, one each joker would have.

sturdy compass
#

What exactly are you looking for?

unkempt thicket
#

if joker has a stored var then i want to add it to a list, the key. if it doesn't have the var it doesn't add the joker key to the list.

#

my problem is doing this for every joker before the game begins (a run)

grim remnant
#

tried with both it in and out of the add_card but nothing. still not sure if we even set up the apply correctly... ^^;

high stag
#

i think all jokers fall into a set you can for loop through, then you can be like "if i in joker_set has var == X, add to list"

sturdy compass
grim remnant
#

game boots, but on trying to start a game with the deck, this happens.

unkempt thicket
sturdy compass
#

You don't need to do the loop or all the other fancy stuff, just the SMODS.create_card

chrome widget
#

What's the cheapest way to find every joker the player has that is part of a valid list of jokers? Literally just nested for loops?

#

I don't know off the top of my head if there's some fun lua shenanigans I can pull here

sturdy compass
#

Yeah probably

normal crest
#

that'd avoid using nested loops

chrome widget
#

Oh true! Lua shenanigans

sturdy compass
#

Does SMODS.create_card return the card it created?

#

nvm it does

normal crest
#

if you don't emplace it it just floats around tho

#

which is pretty silly

sturdy compass
#

I thought it emplaced by default?

#

huh, guess not lol

#

@real temple You

normal crest
sturdy compass
#

Ahhhhh ok

unkempt thicket
#

How can I check if each in-game joker contains a specific stored var, before the game begins (a run)?

sonic cedar
#

I have the descriptions for my jokers stored in a localization file, but how do i get the file to find them? The jokers just keep showing up with blank description boxes.

old bane
sonic cedar
#

i

forgot the j_

old bane
#

oop

sonic cedar
#

does it need to be like in the actual joker too?

old bane
sonic cedar
#

like

#

localization key= j_prefix_joker

does the SMODS.Joker also now have to use j_prefix_joker, or can it still use joker

old bane
#

it can just be joker

sonic cedar
#

ok thanks

old bane
#

cause if you do j_prefix_joker for the joker key the localization key has to be j_prefix_j_prefix_joker and that's a bit ridiculous

#

how do i have a shader be just a transparent image overlaid on top of the card? I wanna have like a "watermark" effect with one of the jokers

unkempt thicket
sturdy compass
#

The key isn't a card object tho and would error

unkempt thicket
#

i know that why its geting the cards.config.center_key

#

which gets the jokers key that equals the set key

#

in the players jokers

sturdy compass
#

Ah I see what you're trying to do now, but that would require the copied joker to be in the card area. Ideally they retain the effect even if the copied joker isn't in the jokers area

unkempt thicket
next pivot
#

how do i make a hand that is more than 5 cards playable?

sturdy compass
next pivot
sturdy compass
unkempt thicket
#

this should also prove useful to me

next pivot
# sturdy compass This is just the hand type?

Yeah, here's the joker if it's needed.

SMODS.Joker{
    key="draw_full",
    loc_txt={
        name="Draw Full",
        text = {
            "Draw {C:attention}literally your entire deck{}",
            "into your hand",
            "Also, lets you select your entire #1# card deck."
        }
    },
    rarity = 1,
    atlas="spark",
    pos = { x = 0, y = 0 },
    config = {extra = 52},
    center = {config = {extra = 52},},
    cost = 2,
    loc_vars = function(self, info_queue)
        return { vars = { math.max(1, math.floor(self.config.extra)) } }
    end,
    calculate = function(self, card, context)
        if not context.blueprint and not context.retrigger_joker then
            if context.first_hand_drawn then
                G.FUNCS.draw_from_deck_to_hand(#G.deck.cards)
                return nil, true
            elseif G.hand.config.card_limit < 1 then
                G.hand.config.card_limit = 1
            end
        end
        G.hand.config.highlighted_limit = G.hand.config.highlighted_limit
        + math.max(1, math.floor(self.config.extra))
    end
}
sturdy compass
#

Why are you changing the highlighted_limit to highlighted_limit? There's no change there

next pivot
#

There's a plus added below it

#

It's just indented to the bottom

sturdy compass
#

Ah

#

Ok instead of doing that in calculate() you should do this in add_to_deck()

next pivot
#

So just change calculate() to add_to_deck()?

sturdy compass
#

Just the part where you change the highlighted_limit

#

You should also add a remove_from_deck function to reset it when you get rid of the card

next pivot
#

The Play Hand button is still grayed out.

sturdy compass
#

did you set up the function correctly?

next pivot
#

this is what i changed it to:

#
    calculate = function(self, card, context)
        if not context.blueprint and not context.retrigger_joker then
            if context.first_hand_drawn then
                G.FUNCS.draw_from_deck_to_hand(#G.deck.cards)
                return nil, true
            elseif G.hand.config.card_limit < 1 then
                G.hand.config.card_limit = 1
            end
        end

    end,
    add_to_deck = function(self,card,context)
        G.hand.config.highlighted_limit = G.hand.config.highlighted_limit
        + math.max(1, math.floor(self.config.extra))
    end,
    remove_from_deck = function(self,card,context)
        G.hand.config.highlighted_limit = G.hand.config.highlighted_limit
        - math.max(1, math.floor(self.config.extra))
    end
sturdy compass
#

It looks like you declared the functions incorrectly

sturdy compass
unkempt thicket
#

I thought it was kind of what you were trying to do, well not randomized but very similar

next pivot
#

declared the functions the correct way, same thing.

    add_to_deck = function(self,card,from_debuff)
        print("added")
        G.hand.config.highlighted_limit = G.hand.config.highlighted_limit
        + math.max(1, math.floor(self.config.extra))
    end,
    remove_from_deck = function(self,card,from_debuff)
        print("removed")
        G.hand.config.highlighted_limit = G.hand.config.highlighted_limit
        - math.max(1, math.floor(self.config.extra))
    end

-# quickly added some debug prints, yeah it's working

sturdy compass
old bane
#

okay so i really want to draw a sprite over a card like the soul or legendary cards (but instead of it floating it'll be on the card like an enhancement) and i'm struggling with trying to comprehend how the draw functions work, does anyone have any idea how one might accomplish this?

#

I would like to avoid having it be a sticker but if I have to have it be a sticker because editions aren't flexible enough I can

sturdy compass
# next pivot declared the functions the correct way, same thing. ``` add_to_deck = functi...

Ah I forgot you need to make a lovely patch to allow playing more than five cards. You can use mine

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > 5 then "
position = "at"
payload = "if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > G.hand.config.highlighted_limit then "
match_indent = true
times = 1
next pivot
#

Gotcha, makes sense, thanks!

sturdy compass
#

np

rain latch
#

would anyone know why the Jokers.png is making the jokers appear like this instead of the individual jokers

old bane
sturdy compass
#

Can you show the code for the cards?

rain latch
#

its very bare bones so if i dont have what i need it would not shock me 😓

#

im still learning LUA

#

so any tips is appreciated

sturdy compass
#

Also it looks like the cards are misaligned on the sprite sheet due to other cards bleeding through on the bottom

rain latch
#

this is truew

#

i wasnt sure how the legendarys would work

#

with the layered cards

sturdy compass
#

Yeah for legendaries you just need to add a soul_pos that has the coordinates to the floating head on the spritesheet

rain latch
#

ooooh okay

#

doe sthe sprite sheet seem to be made incorrect?

#

i didnt do the art im just the coder guy lol

sturdy compass
#

Here's an example of a correct soul_pos addition

rain latch
#

ooooh

sturdy compass
rain latch
#

okay thankyou

sturdy compass
#

The general rule of thumb is the art should have a 2px border on each side

rain latch
#

2px okay these are only 1

#

i shall let the art guy know

sturdy compass
#

It should total to 4px between cards

rain latch
#

i think that may be 4

#

bad pciture lemme send a better one sorry

sturdy compass
#

Sorry not border

#

Like 2px of blank space surrounding it

rain latch
#

okay so the white should be 2 and then grey 2 aswell

#

cuz i know the joker should be 71x95

#

and i think these are like 2-3 less

sturdy compass
#

gimme a sec

rain latch
#

okie dokie

sturdy compass
#

This should show it a bit better

#

and if that 4px gap doesn't work then try 2px. My sprites might be a little oversized

rain latch
#

okay thankyou

#

this is guna be hard but its very fun!

#

if i have any other questisons am i good to ask you

sturdy compass
#

Sure. Just ask here cuz I'm one of many lol

rain latch
#

no issue lol

nova finch
#

how do i add these little description things?

#

nvm i just remembered

small moon
#
print("Adding Achievement !!!!!!")

SMODS.Achievement {
    key = "true_clown",
    loc_txt = {
        name = "A True Clown",
        text = {
            "Complete a Gold Stake run without using any Jokers"
        },
        unlock = {
            '???'
        }
    },
    atlas = "BoingularMisc",
    pos = {x = 0, y = 0},
    bypass_all_unlocked = true,
    hidden_text = true,
    unlock_condition = function(self, args)
        --  and (args.stake or self.GAME.stake or 1) == 8
        if args.type == "add_card" and args.args.ability.set == "Joker" then
            print("Mel: Adding Joker!")
            G.GAME.current_round.mel_true_clown_status = false
        end
        print("Checking: "..args.type)
        print(G.GAME.current_round.mel_true_clown_status)
        return args.type == "win" and G.GAME.current_round.mel_true_clown_status
    end
}

I have the above code for a custom achievement, but in the Achievements menu it shows "ERROR" as the description, and unlock_condition is never run, even with Achievements enabled in the menu (or else I'd be seeing a lot of debug messages when the game first starts)

umbral zodiac
#

is context.after for when a played hand is done scoring

nova finch
#

how do i make a info_queue for a tag?

stray warren
#

info_queue[#info_queue + 1] = G.P_TAGS.tag_rare for example

nova finch
#

ohhh

#

that's why

#

i was uing P_CENTERS

stray warren
#

yeah, a Tag isn't a Center

timid lynx
#

I’m trying to make a simple skin pack, and I just imported the few jokers I’ve made so far into the game. But for some reason only one of them is actually changed in game? I’m wondering how that’s possible since all jokers are on the same PNG file

wintry swallow
#

I have a minor annoyance due to insufficient information about it on the web. I have successfully merged a ton of skin mods to change the appearance of the card but I cannot find any documentation on what the key for the actual 52 card deck is. Everything else has a name such as Joker for Jokers and Planet for the planet cards.

timid lynx
#

I only changed 2 jokers (and only one of them actually updated in game) and I changed all of the planet cards but none of those updated either

paper zealot
#

I believe it's G.playing_cards that you're interested in

wintry swallow
#

Which joker did you change? The Lua looks good

timid lynx
#

I changed Scholar and Madness, only Madness actually changed

wintry swallow
timid lynx
#

ooooooooooh gotcha

wintry swallow
#

Planet, spectral, Tarot. Even though they are all the same image

#

The one you change on the bottom right appears to be too large on the right side

wintry swallow
nova finch
#

is there a way to make one rank count as another? (e.g. make a 8 count as a 9)

old bane
#

how do i add a sticker and have it be like the perishable sticker? I have it set up to where there's calculate and set functions for the sticker but i'm stuck on how and where to declare

self.ability.drained = true

as a part of the Card object.

wintry swallow
#

The second image is too far to the right

timid lynx
#

Which image?

wintry swallow
#

The one you added. Not the one from baldis basics

timid lynx
#

Madness? Thats the only one that’s showing up in game though, so if it’s too far to the right why is that the one that’s working?

wintry swallow
#

Interesting. It loaded differently for me. Let me check