#💻・modding-dev

1 messages · Page 180 of 1

frosty dock
#

play_sound doesn't have context of being called from your mod

past forge
#

oh okay

#

now it just deciced it cant decode ogg

minor furnace
#

I still do not understand why these lines are crashing my game when I hover over the custom joker

loc_vars = function(self, info_queue, center)
    return {vars = {center.ability.extra.mult}}
end
dim lynx
#

whats the crash

minor furnace
#

^

#

it's that

past forge
#

"cofig"

#

instead of config

minor furnace
dreamy thunder
#

<@&1133519078540185692>

#

ae

minor furnace
#

the bane of my existence isn't my ability to code, it's my ability to spell

nova finch
#

anyway, is there any documentation on how calc_dollar_bonus works?

hushed field
#

the amount of times I've thought I fundamentally don't understand the way balatro works, only to realize I just did a capitalization error is humiliating, honestly

past forge
grim remnant
#

question! i want to scale a value by rounds elapsed just in general--not how many you've cleared since getting the joker, but the literal round value. in pseudocode, i want 1 + (0.05 * Rounds). so uh. How do I do that?
config = { extra = { Echips = 1 + (0.05 * idklol } },

limpid halo
#

oph my god jimbo on death row

sturdy compass
#

Just got up an tried this. It works, but I'm trying to get it in the normal spot (like a Joker's sell button), not coming out of the bottom

maiden phoenix
#

Wonder if its tied to the cardarea

sturdy compass
#

I do too

manic rune
#

quick question, where did you guys learn about how to add UIs?

sturdy compass
#

other mods lol

past forge
#

why are the message and the sounds not playing here?

manic rune
#

oof, i see

red flower
#

you need to hook into card:highlight i think

limpid halo
red flower
manic rune
#

fair

grim remnant
#

i'm yet to add the actual "progress a round" thing but this is tossing up an error. any idea why??

    key = 'hermey',
    loc_txt = {
        name = 'Hermey',
        text = {
            "{X:dark_edition,C:white}^#1#{} Chips for",
            "every round elapsed,",
            "C:inactive}(Currently {X:dark_edition,C:white}^#3#{C:inactive} Chips)"
        }
    },
    config = { extra = { scaler = 0.05 , roundsElapsed = 1 , Echips = 1 + (scaler * roundsElapsed) } },
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.Echips } }
    end,
    rarity = "stla_Stellated", --giving it special rarity
    atlas = 'StellationJokers',
    pos = { x = 8, y = 0 },
    soul_pos = { x = 9, y = 0 },
    cost = 34,
    mmmmblueprint_compat = true,
    calculate = function(self, card, context) --a lot of this shamelessly adapted from the waluigi joker from cryptid (tysm cryptid team <3)
        --actually do the effect thing
        if context.joker_main then
            return {
                Echip_mod = card.ability.extra.Echips
                --message = "STRIKE!",
            }
        end
    end
}```
red flower
#

the config can't check other config values

#

you need to change echips to not use scaler or roundeslapsed

sturdy compass
red flower
#

yay

orchid thunder
manic rune
#

i have a question actually

#

i have seen a lot of mods adding an additional card slot below the consumable slots

#

if you use multiple of those mods, how would that work?

limpid halo
#

probably poorly

#

try it, ig?

red flower
#

idk exactly but the ss from dimserenes pack are always funny

#

we should have a cardarea in every empty space

limpid halo
manic rune
#

why do you even have a clock in balatro, isnt that a bit overkill 😭

limpid halo
#

for the time based joker effects, duh

manic rune
#

oh

limpid halo
#

if its tuesday and 10pm set score to zero and set hands to zero

manic rune
#

nah i have an idea, make a joker which works best from 3 am to 6 am

#

forcing people to stay up late to grind balatro

#

🗣️

#

the gambling addiction doesnt stop

limpid halo
#

"Gains +Infinity mult after 10 hours"

manic rune
#

^^^^^ Infinity mult

manic rune
#

mmmmblueprint_compat = true,

#

mmmm?

frosty dock
#

the curse of restarting the game

nova finch
#

If i wanted to change the width and height of a joker like with photograph or wee, how do I do that?

manic rune
#

fair enough

manic rune
limpid halo
grim remnant
manic rune
#

M joker

grim remnant
#

fixing that still yields the same error tho

tepid crow
limpid halo
#

THERS A RESTART COMMAND?

#

😭

tepid crow
#

Yeah hold M

manic rune
#
SMODS.Joker {
    key = 'hermey',
    loc_txt = {
        name = 'Hermey',
        text = {
            "{X:dark_edition,C:white}^#1#{} Chips for",
            "every round elapsed,",
            "{C:inactive}(Currently {X:dark_edition,C:white}^#3#{C:inactive} Chips)"
        }
    },
    config = { extra = { scaler = 0.05 , roundsElapsed = 1 , Echips = 1} },
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.Echips } }
    end,
    rarity = "stla_Stellated", --giving it special rarity
    atlas = 'StellationJokers',
    pos = { x = 8, y = 0 },
    soul_pos = { x = 9, y = 0 },
    cost = 34,
    blueprint_compat = true,
    calculate = function(self, card, context) --a lot of this shamelessly adapted from the waluigi joker from cryptid (tysm cryptid team <3)
        --actually do the effect thing
        if context.joker_main then
            return {
                Echip_mod = card.ability.extra.Echips + (card.ability.extra.roundsElapsed * card.ability.extra.scaler)
                --message = "STRIKE!",
            }
        end
    end
}```
#

@grim remnant that should fix your issue, though you would have to add some other stuff to increase roundsElapsed after each round yourself

#

using context.end_of_round

#

...oh wait

#

the third line of text

manic rune
#

holding M is still too annoying for me

#

😭

#

since i have vsc in the background, it will start writing "mmmmmmmmmmmmmmmmmmmmmmmm" in my code

past forge
manic rune
#

something rpg

#

i have that mod

unkempt thicket
#

grim

red flower
manic rune
#

oof

grim remnant
#

i do have to ask, how do i make it not "nil" while in the collection menu?

stray warren
manic rune
#

yeah i just remembered, no wonder why i dont see any mod with "rpg" when i searched in my mods folder lol

stray warren
red flower
#

if it's what bepis sent earlier it's missing a variable in loc vars

manic rune
#

oh, it is?

limpid halo
#

im having a little silly but shouldn't this... work?
I want to override all music with custom track when joker is active
If i just return the big number, it plays always which is yes swag
am i brainfarting on how SMODS.find_card works??

Items/Loader.lua

-- Music override on Timeout joker
SMODS.Sound {
    key = "timeout_music",
    path = "timeout.wav",
    select_music_track = function()
        if next(SMODS.find_card("timeout")) then
            return 2e512
        end
        return false
    end,
}

Items/Jokers/Timeout.lua

SMODS.Joker {
    key = 'timeout',
    loc_txt = {
        name = 'Timeout',
-- ...etc joker node
grim remnant
manic rune
#

i didnt notice since im just fixing his error

manic rune
#

like, j_(prefix)_timeout or something

red flower
stray warren
manic rune
#

ah i see

orchid thunder
#

i ned help BAD

limpid halo
#

doesn't seem to work

manic rune
grim remnant
orchid thunder
#

i can get this Frickign Ui to go up for the love of god

manic rune
limpid halo
manic rune
#

i see

limpid halo
#

j_com_beepsterr_genmod_timeout worked :^)

red flower
manic rune
orchid thunder
orchid thunder
manic rune
grim remnant
manic rune
#

mhm

#

if a variable in loc_vars gets changed

limpid halo
manic rune
#

your joker's description will change too

orchid thunder
#

whateber i do Nothing changes

wintry solar
orchid thunder
#

ig

manic rune
limpid halo
#

btw is that how cryptid's glitched cards work? do they just randomize those values?

manic rune
#

probably? i havent read too much cryptid's code yet

atomic edge
#

how could i change the card:set_base function from the card.lua to check if the new card is of the same suit as the card its changing it into

grim remnant
#

so uh, how do i increment roundsElapsed at the end of round? just?

            return {
                cardarea = G.jokers, -- G.hand, (G.deck and G.discard optionally enabled)
                end_of_round = true,
                game_over = game_over, -- true or false
                roundsElapsed = roundsElapsed + scaler
        }
        end```
atomic edge
#

i just dont understand it at all

manic rune
#

i dont think you need to return anything here

stray warren
grim remnant
#

i mean, it's incremented by the value in scaler, not 1

manic rune
#

oh actually?

#

i thought your Echips work by: 1 + (scaling * roundsElapsed)

grim remnant
#

OH

#

i'm a fool

nova finch
grim remnant
#

forgot that this is for roundsElapsed and not Echips ^^;

manic rune
#

oof

red flower
#

you don't need roundselapsed at all in that case, just increment scaler

manic rune
#

but also, remember to call card.ability.extra.roundsElapsed instead of just roundsElapsed like what OppositeWolf corrected

#

ngl, yeah

grim remnant
#

end of round crashes--oh, that'd be why

manic rune
#

ability isnt exactly config but you get my point ❤️

grim remnant
stray warren
#

No curly brace for if statements lol

manic rune
#

at the end_of_round part

#

theres {}

#

oh also

#

you dont need "," here, since this is not a table

grim remnant
#

ohhhh

manic rune
#

but if you want to get your joker to send a message, you would need to do

return{
  message = "smt",
}

or a function which i forgot its name, try asking other people for this one, sorry 💀

stray warren
#

localize(localization_key)

atomic edge
#

guys how do i check if two cards have the same rank please

orchid thunder
stray warren
orchid thunder
#

ok good news and bad news

#

its closer

manic rune
#

im a bit curious, what are you doing here?

red flower
#

the problem is that the cage has a hole in it

manic rune
#

i actually thought this was your take on the loading/starting screen

#

😭

#

until i saw that 1/1

orchid thunder
wintry solar
barren basin
#

is there a way to change the priority of an existing vanilla rank in a way that affects the order the card is drawn in in the hand and how much it scores

grim remnant
#

well, that's annoying

quasi thicket
#

uh hello, im sorry if this is a bit of a silly question, i'm looking to make my own personal mod which would be a simple swap of how the cards look, my boyfriend is a big fan of the "moomins" franchise and i figured it'd be fairly easy to make the face cards into something moomins related for his birthday, problem is i do not know how i would go about that, i dont need an entire tutorial, i'd just really appreciate being pointed in the direction of where i could learn to do smth like this since im fairly new, thank you for your time and sorry if its a weird thing to ask.

red flower
orchid thunder
manic rune
#

every feature is cool for everyone but programmers

grim remnant
red flower
#

tostring()

grim remnant
manic rune
#

thats because it is almost guaranteed your ideas have been considered by other programmers, but the work to implement them are so tedious they straight up gave up before even trying

orchid thunder
#

i dont understand how to move it

grim remnant
red flower
#

"^".. tostring(your number)

although you don't need tostring there

frosty dock
#

it includes the default message

atomic edge
frosty dock
#

Card:get_rank() is not a function that exists

#

it's Card:get_id()

manic rune
#

get_id()

stray warren
#

oops

#

was on my phone, sorry

manic rune
#

it fine

atomic edge
#

oh thanks

#

and what is the function for the suit?

manic rune
#

get_suit()

atomic edge
#

thanks

grim remnant
#

mostly functioning now, tho for some reason it's applying scaling twice and i can't help but feel like at some point i got my wires crossed in coding this

manic rune
#

can return Diamonds, Hearts, Clubs, or Spades

#

what is that debug info stuff

grim remnant
red flower
manic rune
grim remnant
#

alright, that's definitely not the intended scale.

manic rune
#

oh i see the problem here

grim remnant
manic rune
#

it actually expoentially increases here lol

grim remnant
#

wuh oh

manic rune
#

this line

#

it should be card.ability.extra.Echips = 1 + (blah blah) instead

grim remnant
#

ohhhh!

orchid thunder
#

how od i move ui objects closer together

manic rune
#

💔 would love to help but i understand shit about ui rn

red flower
#

i understand some but i can't really help without a pc to test rn

atomic edge
#

how could i check if i have a certain joker

#

like

#

if <has jimbo> then etc..

red flower
#

SMODS.find_card(card_key)

orchid thunder
#

thats intresting

atomic edge
#

and that returns true/false?

red flower
#

next(SMODS.find_card(card_key)) tells you if you have any

orchid thunder
#

but i want the 2 clamp things closer xd

red flower
atomic edge
#

okay thanks

dreamy thunder
#

i really dont know what i did there

orchid thunder
stray warren
dreamy thunder
#

i forgot context.before was a thing 😭

unkempt thicket
#

How do i change the max playable cards to 6?

stray warren
stray wing
#

Is there an easy way to see what cards are upcoming in the deck?

grim remnant
#

almost entirely functional, but the end-of-round message doesn't appear for whatever reason. any idea why?

stray warren
dreamy thunder
stray warren
#

but haven't looked into it myself

stray wing
#

wait what does misprint do

red flower
atomic edge
#

im sorry for being annoying but i just dont understand how to patch this set_base function to check if the card before and after has the same suit

grim remnant
#

how would i do that? just, replace that line with return { message = "Buffed!" }?

red flower
#

yes

barren basin
#

how do you change the order of which vanilla ranks are drawn into the hand

#

in steammodded

stray warren
dreamy thunder
red flower
limpid halo
#

anyone wanna hear the worst version of the combined balatro themes ever?

stray warren
# dreamy thunder ^?

Try setting the trigger to 'after' in the event? But it should work, not sure why it isn't

dreamy thunder
#

trigger is already after though

stray warren
#

sorry, meant 'before'

dreamy thunder
#

ah

#

trying it rn

#

nope

wintry solar
paper zealot
# atomic edge im sorry for being annoying but i just dont understand how to patch this set_bas...

If i understand right, it might be easier to hook the function instead of patching it.
https://forums.kleientertainment.com/forums/topic/129557-tutorial-function-hooking-and-you/

Klei Entertainment Forums

In LUA, it is a very important concept to understand that everything is a variable and all variables may be edited in runtime. This includes functions. With modding other peoples' LUA files, like Klei's basegame code, you may find yourself wanting to run your code before or after the original fun...

dreamy thunder
atomic edge
#

hahah thanks either way ill surely watch the video because i know nothing about that

stray warren
dreamy thunder
#

i tried putting it next to context.cardarea as well

stray warren
#

G.play isn't a valid context for context.before

#

just remove that part

dreamy thunder
#

ah

#

aight

stray warren
#

wait, it seems like it is

dreamy thunder
#

it works now

stray warren
dreamy thunder
#

though

dreamy thunder
# stray warren

i mean i went on lookin at this too but it worked after removing G.play

#

thanks

past forge
#

is there a smods function to open a shop?

stray warren
#

I think just specifying context.before by itself will make it trigger more times in other situations, so just be aware of that

dreamy thunder
#

ik its fine if its triggered by any other thing but itself

orchid thunder
chrome widget
#

Is there a reasonably vanilla way to easily know the chips result of the hand? I'm trying to do a joker that scales if the first hand doesn't immediately win the blind, but he only point I can find (without adding a new context in SMODS ofc) is by adding another event to the queue that will eventually follow when the game eases the player's total chips to the correct number. But I'm not seeing if there's any context that just straight up passes in the hand_chips*mult number that it eventually eases to

wintry solar
#

just calculate it manually

orchid thunder
#

padding*

wintry solar
#

yes

#

iirc it's a bit wonky but it does work

atomic edge
orchid thunder
#

direction*

wintry solar
#

I don't believe so

orchid thunder
#

damn

#

its shifting up

wintry solar
#

you can add a spacer above it to shift it back down if needed

orchid thunder
#

fair

bleak bone
#

is there a way to affect cards not in hand?

#

if so i wanna see a spectral card that deletes your entire deck except for one random card and makes 51 copies of it

unkempt thicket
#

How can I add/remove an amount from the total payout? (at blinds end)

past forge
#

shouldnt this open a shop when s blind is skipped? it doesnt work and I cant find any work around

wintry solar
#

no

red flower
wintry solar
#

opening a shop is a lot more involved than that

nova finch
#

how would I do Xchips? I heard there was support for it in steammodded

past forge
wintry solar
#

a patch 100%

wintry solar
nova finch
#

ok

#

thanks

atomic edge
red flower
#

that might be wrong then, I just copied what a comment earlier said but i can't look up what the correct method is rn

atomic edge
#

oh okay thanks either way for your time

manic rune
wintry solar
#

'x_chips', 'xchips', 'Xchip_mod',
these are the valid keys

manic rune
#

got it

past forge
#

where is the code when a round is ended and you go to the shop? cant find it

#

the closest thing that i found is update_shop in game.lua

normal crest
#

in game.lua

#

look for the line G.CONTROLLER:snap_to({node = G.shop:get_UIE_by_ID('next_round_button')})

atomic edge
#

does anyone else please know how i could change the set_base function so i can check if the suit of the card is the same after the change?

past forge
#

okay thanks

stray wing
#

How is the order of cards in the deck randomised? Or more specifically, what does it depend on other than the seed? Is it determined by the number of cards played and/or discarded previously during the run?

past forge
#

when you press "cash out" how does it open the shop?

atomic edge
#

sendDebugMessage("This is a debug message", "MyDebugLogger") what can i change here to make is display a variable value?

chrome widget
faint plank
#

i cant seem to figure out why this isnt working, even when i take out the name check it still does nothing

                context.other_card.config.center.key ~= self.key and 
                string.sub(context.other_card.ability.name, -2) == "er" then
            return {
                message = localize("k_again_ex"),
                repetitions = card.ability.extra.repetitions,
                message_card = card,
            }
        end
end,
left sonnet
#

Hey folks, looked around and couldn't figure out a solution based on existing problems.

#

The line in question - callback(context.blueprint_card or self, ret, context.retrigger_joker)

past forge
#

im going to take a different approach, anyone knows a mod that opens a shop when its not usually open?

grim remnant
#

is there a way to make it so a line of loc_txt only appears if a config setting is enabled?

prisma loom
#

So I want my consumable card to enhance a card into a custom enhancement, is this correct?

left sonnet
#

Try it out man

prisma loom
#

crash

left sonnet
#

Rip

chrome widget
#

Average day of programming tbh

violet void
left sonnet
#

By base Balatro legendary standards, yes I'd say

#

Well

chrome widget
#

It seems like a cool idea, and probably not too strong since it's only a single hand per boss blind. Personally though, I probably would've just had it select from a randomly drawn hand of regular hand size, consistent with how most of the other "select x cards from hand" things in the game work (like opening Tarot/Spectral packs)

#

That'd inevitably make it weaker though

graceful magnet
#

does context.other_card have something for checking if the card has a seal?

#

or just like is there a way I can check if a card has any seal

red flower
#

this

past forge
#

card:get_seal()

weak gate
#

what are the names of the card areas, or where do I find that in the vanilla code? (or does smods change that?)

past forge
red flower
#

i remembered it

chrome widget
#

it's the same in vanilla code, you check for card area by doing context.cardarea == [area]

#

G.jokers, G.play, G.consumables, and G.hand are the primary ones

#

there are others for contextual actions (G.pack_cards, G.shop_jokers, etc)

weak gate
#

right, I'm looking at the shop ones, yes

chrome widget
#

What are you looking to do?

weak gate
#

a thief joker that makes some of the cards free, but preferably not the voucher, and... not the packs, maybe

violet void
chrome prawn
#

trying to make a spectral card that has a 50% chance to either destroy a card or turn it into an edition but the destroying part of the code isn't working for some reason

chrome widget
#

So bad news is that you may need to add a custom context for that via a lovely patch, but I've actually made a very similar joker if that would help

#

It discounts cards in the shop

atomic edge
#

is there a function that gets a cards suit because get_suit() seems like it doesnt exist

chrome widget
#

you do card:is_suit('Suit')

#

So doing is_suit('Diamonds') on a diamond card will return true

atomic edge
#

oh my god

#

thank you so much

graceful magnet
#

is there something like that for seals too? now I need a specific check for purple seals

violet void
#

card.seal == "Purple" afaik

graceful magnet
#

k, should be good

atomic edge
#

how do i write the debug message to show the value of a local variable for example?

chrome widget
#

@weak gate You'e using SMODS, correct?

weak gate
#

I did do a lovely patch already and it's successfully doing discounts in some cases; actually was stuck on deciding when the joker should say "Yoink!"

chrome widget
#

I basically just have my joker activate its effect right after tags are applied to the shop (Rare, Uncommon, Foil, Holographic, Polychrome, and Coupon tags)

#

I.E. basically do "Yoink!" at about the time that this joker says "Discounted!", roughly 48 secs in?

weak gate
#

Yes; it shouldn't say it if the 1 in X roll failed for all cards and the joker didn't manage to set any card's price to 0

chrome widget
#

mhm mhm

weak gate
#

although I'm interested in how you detected that you entered the shop; or is it that you're detecting when a card's price was set?
there's a context for shop rerolls (context.reroll_shop), so my card works in rerolls, but not on the first shop screen

chrome widget
#

I basially just have a "start_shop" context (constrasting the "ending_shop" context perkeo uses in vanilla) right here in game.lua after the shop sets all its cards, and then the card just evaluates here when it sets the cost of every card in the game to some amount, which it resets on leave

#

That said this one literally just reuses the inflation mechanic from the challenge, because that's built into the set_cost() function

#

You can do it far more directly though

weak gate
#

Hmm, where's the code in the first screenshot? Inside a function that gets called inside a lovely patch?

vague pendant
#

is there a way to retrigger Joker effects?

chrome widget
#

It's inside Game:update_shop(dt), in the vanilla game's game.lua file

#

I inserted the SMODS context function at around line 3228

wooden nexus
sturdy compass
#

Erm actualy it’s a Horoscope card 🤓☝️

#

Jokes aside we called them that cuz there’s already so many zodiac card mods

weak gate
past forge
chrome widget
#

No, due the way lua works, it's literally just appending a new property to the context table, so this isn't in comparison to any vanilla code or anything

prisma loom
#

Did I miss something? This enhancement is supposed to make it so the scored card would gain +0.5xMult when scored but it doesnt for some reason

past forge
chrome widget
pulsar flower
#

is there a way to append extra information to the description of a card with a custom enhancement? i've managed to do it to base and the vanilla enhancements, but my custom ones don't display it

atomic edge
#

how do i write the debug message to show the value of a local variable for example?

chrome widget
pulsar flower
#

yes, specifically something like hiker extra chips, where the info may not be present

chrome widget
weak gate
unkempt thicket
#

How can I add/remove an amount from the total payout? (at blinds end)

chrome widget
#

I.E. this is the equivalent space in the vanilla code, obviously sans the context check

grim remnant
#

how can i specify a custom hex color for text in descriptions? :o

vague pendant
#

Is there an easy way to retrigger a joker's effect? something like returning "repetitions = 1"

chrome widget
grim remnant
#

for context, i'm just trying to make "Stellated" here be a solid #CE001F

    key = 'chuTeng',
    set = 'Spectral',
    loc_txt = {
        name = 'Chu-Teng',
        text = {
            "Summons one {C:CE001F}Stellated{} joker",
            "{C:inactive}(must have room)"
        }
    }
}```
#

(obviously this isn't done yet, i haven't even added functionality, but shhhh)

chrome widget
minor furnace
#

why are none of the Enhancement Tarot card use effects like Magician and Chariot in the Card:use_consumable function of card.lua, and where are they?

grim remnant
#

also, does anyone know how to add a legendary card-esque layer to a consumable?

vague pendant
#
SMODS.Consumable {
    key = 'chuTeng',
    set = 'Spectral',
    loc_txt = {
        name = 'Chu-Teng',
        text = {
            "Summons one {V:1}Stellated{} joker",
            "{C:inactive}(must have room)"
        }
    }
loc_vars = function(self, info_queue, card)
        return {
            vars = {
                colours = {
                    HEX('CE001F')
                }
            }
        }
    }
end
#

Im definitely off on braces and tabbing

grim remnant
#

it's a coder's favorite game show: WHERE'S! THAT! BRACKET!

#

oh. wait, it was comma

#

wait no it's mad still?

atomic edge
#

where do playing cards keep their suit stored? i mean in which variable

unkempt thicket
#

card.base.suit

atomic edge
#

because when i use is_suit() to check wether it is a certain suit it says attempting to access field base a nil value

#

yea makes sense

#

but why does it say its nil

#

i mean you cant answer without code i know

marble flint
#

one after loc_txt, one after loc_vars, one after pos

atomic edge
#

this is the code its in the set_base method in card.lua and the print(is_suit) is throwing the error

#

it says base is a nil value

#

it happens during initialization of the game if that is any help

#

should i maybe put an if so it doesnt do that line if it is nil?

#

nvm got it

left lance
#

what's the game setting for joker slots? essentially, I know it should be G.GAME.fillinhere but unsure what the variable is

wintry solar
hushed briar
#

would it be possible to get the calculate function of a vanilla joker? so that i can essentially hook it when taking ownership

left lance
hushed briar
#

well i would like to do it this way so it can account for any other mods that mightve like lovely patched it or something like that

#

i mean like, can i access a vanilla joker's calculate function from within the code itself, like you would when hooking a function

spring lantern
#

is there anywhere i can check for the available ui colors?

spring lantern
#

oh fire

past forge
#

just check for "colours"

atomic edge
#

someone already answered but it doesnt seem to work, how can i check whether i have a certain joker/consumable

#

so if i have the joker do something

past forge
atomic edge
#

and that returns true or false?

past forge
#

that is going to be either true if you have the joker or false if you dont

atomic edge
#

oh okay thanks

#

and if its a consumeable its c_?

#

right

past forge
#

i guess so

atomic edge
#

okay thanks

past forge
#

ive never worked with consumables, but thats the prefix for them

atomic edge
#

works like a charm thank you so much

vague pendant
red flower
#

you need to do next(SMODS.find_card("j_[mod_id]_[joker_id]")

atomic edge
#

oh so basically the other one will always be true pretty much

red flower
#

yes

atomic edge
#

ohh okay thanks

spring lantern
#

okay so i'm working on my first attempt at a booster pack and i'm a bit overwhelmed. if i want the pack to give specifically rare and legendary jokers, how do i declare the pool that the booster pulls from? or like how do boosters work in general LOL

#

i'm a bit lost

past forge
spring lantern
#

haven't really done anything other than fill in some variables

unkempt thicket
#

How do I change the max playable cards to 6 with better calc?

red flower
# past forge whats the difference?

find_card returns a table of all the cards or {} if none

in lua {} is truthy so it doesn't work to check if there's any. next() gives you the next value or nil if none

past forge
#

oh okay

#

so next is kust better

violet void
spring lantern
#

oh alright

#

found it in the wiki, seems much more manageable than i thought

violet void
#

If you need a chance-based card creation, you can do something like this

```create_card = function(self, card, i)
    return cs_utils.random_alignment(true, false)
end,```
    local card_type = pseudorandom(pseudoseed('alignment'))

    if card_type > .98 and architectable then
        return SMODS.create_card({
            set = 'Alignment',
            key = 'ali_cs_architect',
            no_edition = true
        })
    elseif card_type > .95 and chameleonable then
        return SMODS.create_card({
            set = 'Alignment',
            key = 'ali_cs_chameleon',
            no_edition = true
        })
    else
        return SMODS.create_card({
            set = 'Alignment',
            no_edition = true
        })
    end
end```
fossil grotto
#

does the wiki have a modding guide?
I'm trying to mess around with the drop rates of vouchers, tags, jokers etc and i have no idea what im doing

past forge
#

so the answer is yes

fossil grotto
#

may i have a link?

past forge
#

of course

fossil grotto
#

thank you

past forge
#

np, any doubt just ask it

fossil grotto
#

oh im sure theyl be plenty xd

left lance
#

speaking of the wiki, I can't find examples of adjustable joker slots... I'm trying to make a card that makes it -1 joker slot when held in hand. The Balatro source code has a joker_slot option but it looks only used in starting configurations, never mid-round from what I see

fossil grotto
# past forge np, any doubt just ask it

what im trying to do is manually lowering the chances of all the content from a particular mod from apearing ( cryptid ). like do you have any idea where should start?

past forge
#

honestly no idea

past forge
#

im also kind of new

left lance
fossil grotto
#

thank you! and what about other content?

#

oh im looking at the documentation it works for any object (I think?)

#

thanks

atomic edge
#

is there a way to find the key of a card for example c_[modid]_[jokername] because i cant seem to write the right one and im not even sure where i put what it should be

spring lantern
#

is there a way i could guarantee a booster pack spawning for testing purposes?

past forge
#

lmao

atomic edge
#

you can spawn it using the debug console i think

spring lantern
#

i'm trying that and it's not working

#

guess i'll set the weight to like 300

atomic edge
#

are you using debug plus

spring lantern
#

wait i forgot i have like a super barebones debug

atomic edge
#

use that mod it makes life a 1000 times easier

#

but im not sure if it can spawn boosters i never tried it but it does everything so safe to assume it can

spring lantern
#

oh hey it workjed

#

thankls

atomic edge
#

np

spring lantern
#

it works but the group name is not

past forge
#

Im trying to do this patch but it doesnt seem to work, the dump file for game.lua doesnt change

spring lantern
#

is this how to do the thing

past forge
red flower
atomic edge
#

thank you

#

so much

red flower
#

edited

spring lantern
past forge
#

no clue how to get the one inside the pack tho

#

is that the group_name?

spring lantern
#

i thought that was it

#

the wiki says so

past forge
#

im just freestyling, never worked with packs

#

the link sends you to the line

#

dont scroll when you enter, wait for it to load

left lance
#

ah, im just illiterate thanks

past forge
#

or go to the line 1803

atomic edge
#

and its not working

#

can it find cards that are in a seperate area than the regular ones

#

because my mod has it in a new area

dreamy thunder
spring lantern
#

i set the group key to this just to have something lol

graceful magnet
#

I assume SMODS.add_card{set = card.ability.extra.usedConsumes, key_append = 'spellbook'} is incorrect, what do I want to do to call a card saved in that list?

atomic edge
#

oh im looking at the code and it doesnt

#

nvm ill change it

#

thanks

dreamy thunder
spring lantern
#

iunno i've never done localization so idk how it goes

dreamy thunder
#

it aint that hard

#

jst takes some time

red flower
graceful magnet
#

Perkeo2 uses pseudoseed instead of pseudokey so that might work

red flower
#

yes that

graceful magnet
#

nnnnope, I get the same error

red flower
#

are you checking if card.ability.extra.usedConsumes has anything first?

spring lantern
#

so where's boosters

graceful magnet
red flower
#

oh it should be config.center.key instead of just key when you add

graceful magnet
#

really? A previous card I made that creates specifically Cryptid used just key

red flower
hushed field
#

boosters go in other, yeah

graceful magnet
grim remnant
#

how do i make a card that gives a random joker card of a given rarity, a-la soul? unsurprisingly my first try, uh, didn't go well. (i'm yet to add the check for if you have room but i want the actual "give a random card" part working first)

red flower
graceful magnet
#

ohh

grim remnant
#

where do i put that in, do i replace the event manager thingamabob?

red flower
#

replace create_card or you can use SMODS.add_card (same parameters) and replace the next 2 lines after create_card too

grim remnant
#

the whole line, or do i keep "local"?

red flower
red flower
#

if using add_card

unkempt thicket
#

How can I add/remove an amount from the total payout? (at blinds end)

dreamy thunder
grim remnant
#

for add_card, how do i force it to be of a custom rarity? i want it to generate only jokers with stla_Stellated

spring lantern
#

aghh it still shows up as error

dreamy thunder
#

how did you do it?

spring lantern
#

im assuming i need to add the prefix

#

it was giving me an error without the p_

dreamy thunder
spring lantern
#

huh

dreamy thunder
spring lantern
#

okay it works thx!!

dreamy thunder
#

no worries

red flower
dreamy thunder
atomic edge
#

what command can i use to create a specific card from its id

grim remnant
#

still a crash here

dreamy thunder
#

"Joker" for set

red flower
#

you forgot a comma before use

grim remnant
dreamy thunder
#

you're still missing ""

#

i think

frosty dock
#

also wrong brackets, you need {} not ()

#

and missing SMODS.

dreamy thunder
#

oh yeah

#

i didnt even pay attention to that 😭

spring lantern
#

anyone know what the weight value of spectral packs is?

frosty dock
grim remnant
#

okay, game boots, but i uh. i apparently need to actually give a use condition. ;P

dreamy thunder
#
     if #G.jokers.cards < G.jokers.config.card_limit or self.area == G.jokers then
         return true
            end
       end,```
#

ae

#

nvm i give up editing

chrome widget
#

Okay, what does context.poker_hands actually contain? I was under the impression each hand table inside it contained the respective cards for each hand it represents

grim remnant
#

works now!

dreamy thunder
#

nice

sturdy compass
#

Hey I'm running into this error when clicking on a card in my custom Booster pack. I think it has to do with my method of forcing the button types via this patch, but not exactly sure what needs to change

fluid pecan
#

sorry to go over you astra

#

why does it work like this

sturdy compass
fluid pecan
#

but not when i change it to xmult =

#

even tho the docs list it as a valid return

fluid pecan
atomic edge
#

is there a way i can change the colors of the text on a card based on conditions

limpid halo
#

Heya, Anyone here who would be willing to look trough my code to see if i'm doing weird/incompatible shit?

dreamy thunder
minor furnace
#

So, I have a custom tarot card that successfully creates two base game enhancements, but the moment I change it to my custom enhancement, the game crashes. I assume the issue is somewhere in my SMODS.Enhancement?

SMODS.Enhancement{
    key = "m_loaded",
    name="Loaded Card",
    atlas = "New_Enhance",
    pos = {x = 0, y = 5},
    loc_txt={
        "{C:green}#1# in #3#{} chance",
        "to win {C:money}$#2#{}",
        "{C:green}#1# in #5#{} chance",
        "for {C:mult}+#4# Mult",
    },
    config = {
        extra = {
            base_prob = "1",
            p_dollars = "6",
            money_prob = "5",
            mult = "60",
            mult_prob = "15"
        }
    },
    loc_vars = function(self, info_queue, center)
        return {vars = {
                center.ability.extra.base_prob,
                center.ability.extra.p_dollars,
                center.ability.extra.money_prob,
                center.ability.extra.mult,
                center.ability.extra.mult_prob
            }
        }
    end
}

This is the line in question that gives the enhancement:
G.hand.highlighted[i]:set_ability("m_loaded");

dreamy thunder
#

Whats the crazh

#

Crash

minor furnace
#

let me bring the log up real quick

dreamy thunder
#

You should include your mod's prefix btw

minor furnace
#

where should the mod prefix be included?

maiden phoenix
stray warren
sturdy compass
#

Yes

dreamy thunder
#

I think

minor furnace
maiden phoenix
past forge
#

context.hand_drawn is the moment when you draw cards or the cards that you draw?

sturdy compass
#

Oh I see

#

lmao

maiden phoenix
#
--Code from Betmma's Vouchers
G.FUNCS.can_pick_card = function(e)
    if #G.consumeables.cards < G.consumeables.config.card_limit then
        e.config.colour = G.C.GREEN
        e.config.button = 'pick_card'
    else
      e.config.colour = G.C.UI.BACKGROUND_INACTIVE
      e.config.button = nil
    end
end
G.FUNCS.pick_card = function(e)
    local c1 = e.config.ref_table
    G.E_MANAGER:add_event(Event({
        trigger = 'after',
        delay = 0.1,
        func = function()
          c1.area:remove_card(c1)
          c1:add_to_deck()
          if c1.children.price then c1.children.price:remove() end
          c1.children.price = nil
          if c1.children.buy_button then c1.children.buy_button:remove() end
          c1.children.buy_button = nil
          remove_nils(c1.children)
          G.consumeables:emplace(c1)
          G.GAME.pack_choices = G.GAME.pack_choices - 1
          if G.GAME.pack_choices <= 0 then
            G.FUNCS.end_consumeable(nil, delay_fac)
          end
          return true
        end
    }))
end
#

Here you go

sturdy compass
#

thank ya kindly

dreamy thunder
fluid pecan
#

why the docs incorrect

dreamy thunder
#

No worries

fluid pecan
#

cuz its the new version?

past forge
maiden phoenix
minor furnace
maiden phoenix
#

Which SMODS are you dev'ing on?

past forge
#
    calculate = function(self, card, context)
        if context.hand_drawn then
            for k, v in ipairs(context.hand_drawn) do
                if pseudorandom(pseudoseed('braille')) < G.GAME.probabilities.normal / card.ability.extra.odds then
                    v:flip()
                    return {
                        message = ('FLIPPED!'),
                        colour = G.C.RED,
                        card = v
                    }
                end
            end
        end
    end

I want 1 in 2 cards to be drawn face down

limpid halo
#

main branch

dreamy thunder
#

Im on mobile so i cant really help tht much

past forge
minor furnace
# dreamy thunder Whats the code like rn

The enhancement looks like this now

    key = "m_reverse_tarot_loaded",
    name="Loaded Card",
    atlas = "New_Enhance",
    pos = {x = 0, y = 5},
    loc_txt={
        "{C:green}#1# in #3#{} chance",
        "to win {C:money}$#2#{}",
        "{C:green}#1# in #5#{} chance",
        "for {C:mult}+#4# Mult",
    },
    config = {
        extra = {
            base_prob = "1",
            p_dollars = "6",
            money_prob = "5",
            mult = "60",
            mult_prob = "15"
        }
    },
    loc_vars = function(self, info_queue, center)
        return {vars = {
                center.ability.extra.base_prob,
                center.ability.extra.p_dollars,
                center.ability.extra.money_prob,
                center.ability.extra.mult,
                center.ability.extra.mult_prob
            }
        }
    end
}

and the line applying the enhancement is
G.hand.highlighted[i]:set_ability("m_reverse_tarot_loaded");

maiden phoenix
#

for the loop

stray warren
#

The key on line 2 should just be the enhancement name, not the m_ or the prefix

minor furnace
#

I'm silly

#

I forgot I made the prefix different from the name of the mod pack in the config

#

it's just "reverse"

stray warren
#

well still, the key for the enhancement should just be loaded on that line

unkempt thicket
#

How can I add/remove an amount from the total payout? (at blinds end)

minor furnace
#

OH

#

well then

past forge
fluid pecan
#

something that doesn't seem to be covered in the docs is how to get the joker activation wiggle when you apply the message to another card 😅 is there any way to do that

minor furnace
maiden phoenix
#

Oh yea because you're returning something the first iteration

atomic edge
#

how does the {V:1} color modifier work ?

maiden phoenix
past forge
maiden phoenix
#

Oooooh

#

I thought this was a first hand draw thing

fluid pecan
# atomic edge how does the {V:1} color modifier work ?

not fully sure so someone correct me if i'm wrong

at the end of ur vars as your last variable: add "colours =" and then what the color V:1 should be. i haven't diven far into it but this is a surface guess that might get you furhter

atomic edge
#

thanks

#

and follow up question

#

is there a lua command that can let me do an if function when declaring a variable i know other programming languages use ?

#

the question mark

maiden phoenix
#

oops typo

fluid pecan
maiden phoenix
past forge
maiden phoenix
#

No replace G.hand.cards by SMODS.drawn_cards

#

Should have replied off this one sorry

atomic edge
maiden phoenix
atomic edge
#

thanks!

past forge
#

yeah that was it

#

thanks :D

#

one doubt

#

whats the difference between context.joker_main and joker.individual?

wintry solar
#

context.hand_drawn and SMODS.drawn_cards are exaxtly the same

fluid pecan
# manic rune :juice_up()

could you give a little more info on how this should be implemented. do i just add this in the return statement? and if so, which variable?

past forge
#

or self instead of card, it depends on the context

maiden phoenix
manic rune
#

you don't use it in return, since it's actually a function used in balatro

a:juice_up(b,c)

a being the card you want to shake, b and c being stuff to modify the shake

fluid pecan
#

oh so just put it inside the if statement and thats it

manic rune
#

mhm

fluid pecan
#

oh now that i know the name i did find it

#

but its quite hidden

#

thank you!

fluid pecan
#

I DONT THINK

#

uhm

#

that was right

#

it made a full 360

#

oh

#

wait

#

mbmb

#

i used a comma instead of a point

#

:D

#

dutch troubles

limpid halo
#

soms heb je dat

hushed field
#

klassieke fout

limpid halo
#

doesn't the base game use 0.3 btw?

#

(i dont have source available on this device sooo can't double check)

fluid pecan
atomic edge
#

why does it say that this is a number value? shouldnt it be a colour

limpid halo
#

hmm do i sprite up (badly) 2 jokers or work on coding the 8th joker

fluid pecan
past forge
novel drum
#

i'm making a joker that converts scored cards to enhanced cards, but after running the code in context.before, the seals and enhancements don't get counted in scoring. anyone know how to recalculate enhancements after context.before?

manic rune
stray warren
past forge
#
    calculate = function(self, card, context)
        if context.hand_drawn then

            for i = 1, #SMODS.drawn_cards do
                if pseudorandom(pseudoseed('braille')) < G.GAME.probabilities.normal / card.ability.extra.odds then
                    if SMODS.drawn_cards[i].facing ~= 'back' then
                        SMODS.drawn_cards[i]:flip()
                    end
                end
            end
            return {
                    message = ('FLIPPED!'),
                    colour = G.C.RED,
                    card = SMODS.drawn_cards[i]
            }
        end

        if context.individual and context.cardarea == G.play then
            for i = 1, #context.scoring_hand do
                if context.scoring_hand[i].facing == 'back' then
                    xmult = card.ability.extra.xmult
                end
            end
        end
    end
fluid pecan
manic rune
#

i see

limpid halo
manic rune
#

probably need G.EVENTS and and add event stuff in this case

past forge
fluid pecan
limpid halo
#

card in this case is probably your joker...

fluid pecan
#

yeah u use the G.E_manager to activate it for every card, i think that might be related to it

limpid halo
# fluid pecan

yeah you gotta call it for context.other_card like context.other_card:juice_up() and put it in a G.E_MANAGER:add_event so they dont all play at the same time

fluid pecan
#

nah i want to shake the joker, not the other card

limpid halo
#

oh sorry, mb

fluid pecan
#

but

#

it does make sense

#

what ur saying

#

ill give it a shot

limpid halo
fluid pecan
#

hmm i see

#

nice

#

this shit too advanced for me alr bro i have no clue what i'm doing anymore 💀

#

nah what am i saying

#

i got this

limpid halo
#

dont ever give up just yell at code till code do good

hushed briar
#

where does the game handle the visual effect where cards appear to move in 3d space, like how if your mouse is on the top of the card the bottom of it will appear closer to you

fluid pecan
#

every joker has this effect

#

i thought it was implemented in base game

#

automatically

#

i must be missing something

limpid halo
#

Look trough the source for similar cards

fluid pecan
#

lol i'll see

limpid halo
#

The events are honestly a pretty easy way to make it all run in order and pretty

past forge
#

the print comes up, but the card doesnt give the xmult

fluid pecan
#

i had the same issue

past forge
#

lol

#

thanks

fluid pecan
limpid halo
fluid pecan
#

it just

#

doesn't do the activation thingy

#

the little

#

wobble

past forge
limpid halo
fluid pecan
limpid halo
fluid pecan
#

i have a lead tho

#

the baseball card does have it added

#

maybe

#

if i look at that code

#

OMG

#

IT WORKED

#

just addd

#

``

#
G.E_MANAGER:add_event(Event({
                    func = function()
                        card:juice_up(0.5, 0.5)
                        return true
                    end
                })) 
#

and then it does work

limpid halo
#

yup

fluid pecan
#

so weird

#

but hey

#

im not complainig

past forge
#

still not working

limpid halo
past forge
#

strange, since the print does work

past forge
limpid halo
#

If so you need to do x_mult = {whatever var u used} in the return statement

past forge
#

wouldnt the return break the loop?

#

wait

#

do i need the loop since im using context.individual?

limpid halo
#

Oh yeah correct you need to apply it differently

#

If ur using individual then no you shouldn’t need a loop

#

I haven’t used individual thought so idk

#

Look at baron or smth I guess

fluid pecan
#

still it activates when the card is being played instead of when the effect is applied 😭 but its better than nothing i guess

graceful magnet
#

I am an arbiter of fair and balanced gameplay

foggy carbon
#

oh god lol

wintry solar
#

individual doesn't need a loop

unkempt thicket
#

How can I add/remove an amount from the total payout? (at blinds end)

gilded narwhal
#

hey guys does context.setting_blind happen before or after the boss blind like the water or the needle activate its effect

wintry solar
#

I believe it's after

gilded narwhal
#

damn

#

that's inconvenient

fluid pecan
#

Which is what is coming from the joker

wintry solar
#

hmmm?

obtuse silo
#

redid my code after a brainwave to simplify things
doesn't even work fool

fluid pecan
# wintry solar hmmm?

So instead of it acting like bloodstone (just to paint an example) it does the wiggle when the chips are bing scored instead of when it activates the mult after the chips

obtuse silo
#

NO WAIT
I FORGOT TO USE INSERT >_<

wintry solar
#

@fluid pecan I don't know anything about your card

obtuse silo
#

i'mma gon work on it myself

minor furnace
#

is there a keyboard shortcut in the debug mod to reboot the game?
found it, it's hold M

hushed briar
#

out of curiosity does anyone know how to make a child node of a card have a different size than its parent (for example card.children.front)

fresh dune
#

I've been trying to make my first custom joker, and ive been looking at tutorials/ reading guides, as well as fiddling with the joker's code, for a couple hours now and im quite stumped.

I have the card art and the modded joker showing up in game just fine, it's just actually giving it an effect/ coding it properly.

Could i ask someone for a bit of help/ guidance? especially because i dont think that the joker im trying to make is that complex. figured i should ask for help instead of struggling alone for 2 more hours lol.

obtuse silo
normal crest
minor furnace
#

UI Error when attempting to add custom Enhancement description to the info_queue, and when applied to card 🙃
in the SMODS.Consumable before the return:

loc_vars = function(self, info_queue, center)
        info_queue[#info_queue+1] = G.P_CENTERS.m_reverse_loaded

And the Enhancement

SMODS.Enhancement{
    key = "loaded",
    name="Loaded Card",
    atlas = "New_Enhance",
    pos = {x = 0, y = 5},
    loc_txt={
        "{C:green}#1# in #3#{} chance",
        "to win {C:money}$#2#{}",
        "{C:green}#1# in #5#{} chance",
        "for {C:mult}+#4#{} Mult",
    },
    config = {
        extra = {
            base_prob = "1",
            p_dollars = "6",
            money_prob = "5",
            mult = "60",
            mult_prob = "15"
        }
    },
    loc_vars = function(self, info_queue, center)
        return {vars = {
                center.ability.extra.base_prob,
                center.ability.extra.p_dollars,
                center.ability.extra.money_prob,
                center.ability.extra.mult,
                center.ability.extra.mult_prob
            }
        }
    end
}
fresh dune
#

this is what i have currently

#

which is not much lol

normal crest
minor furnace
#

hmmm

normal crest
normal crest
minor furnace
#

we are so back

fresh dune
desert ore
#

I'm trying to make a joker that gives -1 joker slot, which means I need to have functionality that makes it so a joker can't be purchased or duplicated when at situations like 4/5 cards, any mods that have an example of a joker with -joker slot or a function where it can't be purchased in certain scenarios?

normal crest
desert ore
#

I really don't want to have to compromise for removing it from the pool

fresh dune
normal crest
desert ore
#

that's true

modern kindle
desert ore
#

he's saying if there's 3 purchasable jokers from the shop

modern kindle
#

ah ic

desert ore
#

or even 2

spark remnant
#

is there a function that gets a cards suit, similar to get_id()

red flower
#

card.base.suit

normal crest
# desert ore that's true

As for how to make it unable to buy, I presume you'll have to find the function responsible for making the use button ui and see if you can make a patch to disable the button

normal crest
desert ore
random sleet
#

no wait that doesnt work cuz nil is stupid lol

#

yea just make sure to check SMODS.has_no_suit(card) (when checking suit) and SMODS.has_no_rank(card) (when checking rank)
hell i oughta go through all the ortalab boss blinds and report like 70% of them for not using the latter my stone card builds keep getting killed by shit that shouldnt affect them

wintry solar
#

hehe

#

it's on my list to fix

graceful magnet
#

this looks awful but it's probably not the worst looking piece of code I've written for my mod

#

cool got the mistakes I made fixed

grim remnant
#

how can i make an effect proc only if a joker is destroyed?

    key = 'searc',
    loc_txt = {
        name = 'Serac',
        text = {
            "{X:dark_edition,C:white}^#2#{} Mult for every",
            "joker destroyed",
            "{C:inactive}(Currently {X:dark_edition,C:white}^#1#{C:inactive} Mult)",
            "{C:inactive}Art by: rixithechao"
        }
    },
    config = { extra = { Emult = 1 , scaler = 1 } },
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.Emult , center.ability.extra.scaler } }
    end,
    rarity = "stla_Stellated", --giving it special rarity
    atlas = 'StellationJokers',
    pos = { x = 8, y = 1 },
    soul_pos = { x = 9, y = 1 },
    cost = 34,
    blueprint_compat = true,
    calculate = function(self, card, context)
        --actually do the effect thing
        if context.joker_main then
            return {
                Emult_mod = card.ability.extra.Emult,
                colour = G.C.DARK_EDITION,
                message = "^" .. tostring(card.ability.extra.Echips) .. " Mult"
            }
        end
    end,
}```
minor furnace
#

Implementing a custom probability-based enhancement is harder than I anticipated

graceful magnet
minor furnace
left lance
red flower
pulsar flower
#

how would i give multiple enhancements to a card? i'm doing this but it doesn't seem like that context runs at all, despite the documentation?

graceful magnet
desert ore
grim remnant
#

is it possible to check for if a joker has been destroyed, and then run a calculation accordingly? i want to make a joker that scales whenever a joker gets destroyed

graceful magnet
red flower
left lance
desert ore
normal crest
desert ore
#

ok so looks like I'm not too far off

red flower
#

that check should be first

small moon
#

How do I check if a modded joker exists in the jokers? I saw the next(SMODS.find_card("j_stencil")) already mentioned, but it doesn't seem to work for modded jokers

graceful magnet
small moon
#

Friend has a modded joker with key "wah_knife" and it's not picking it up. I saw somewhere that you have to add the prefix as well but we couldn't get that to work exactly either

red flower
vale lake
#

does anyone know how to add a linebreak in main_end or main_start?

desert ore
red flower
#

yes

desert ore
#

ok ok, tysm

pulsar flower
small moon
minor furnace
#

anybody know what file the pseudorandom() function is stored in off the top of their head?

vale lake
#

misc_functions

minor furnace
#

thanks 🙏

grim remnant
#

sorry to nag about this, does anyone know if there's a way to check if a joker has been destroyed?

left lance
# red flower yes

could you clarify what 'outside' the joker means? Do you mean outside the SMODS.Joker {} object?

red flower
vale lake
red flower
vale lake
#

I just made a lovely patch for it

red flower
#

i do this for my mod

grim remnant
#

where would i put this in my code, out of curiosity? for reference, i want to make it so that, when a joker is destroyed, it resolves card.ability.extra.Emult = card.ability.extra.Emult + card.ability.extra.scaler.

    key = 'searc',
    loc_txt = {
        name = 'Serac',
        text = {
            "{X:dark_edition,C:white}^#2#{} Mult for every",
            "joker destroyed",
            "{C:inactive}(Currently {X:dark_edition,C:white}^#1#{C:inactive} Mult)",
            "{C:inactive}Art by: rixithechao"
        }
    },
    config = { extra = { Emult = 1 , scaler = 1 } },
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.Emult , center.ability.extra.scaler } }
    end,
    rarity = "stla_Stellated", --giving it special rarity
    atlas = 'StellationJokers',
    pos = { x = 8, y = 1 },
    soul_pos = { x = 9, y = 1 },
    cost = 34,
    blueprint_compat = true,
    calculate = function(self, card, context)
        --i think a check for joker deletion goes here???
        
        --the primary joker effect of actually giving Emult
        if context.joker_main then
            return {
                Emult_mod = card.ability.extra.Emult,
                colour = G.C.DARK_EDITION,
                message = "^" .. tostring(card.ability.extra.Echips) .. " Mult"
            }
        end
    end,
}```
red flower
#

you probably want something like anywhere outside of the SMODS.Joker and then in the calculate function you check for context.joker_destroyed

#

(i dont know if this covers all the cases)

normal crest
#

that will happen when a joker is sold too

red flower
#

oh yeah

grim remnant
#

that... would be a problem ;P

normal crest
#

you can add a and not G.CONTROLLER.locks.selling_card check

#

that's what I do anyway

grim remnant
desert ore
# red flower smth like this

I'm going to have to hook for edge cases with duplication with like invisible joker and stuff like ankh with eternals as well huh. Can someone also like define hook as well I don't really know what it means

#

is it taking something from the base game and changing it?

normal crest
#

hook is simply adding your own code to an existing function

desert ore
#

ok

red flower
normal crest
#

the limitations are that you can't add stuff in between lines

desert ore
#

ok thank you guys so much

grim remnant
# red flower ye

if i wanted to curb selling counting, would i add and not G.CONTROLLER.locks.selling_card like so?

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
#

even if the original function doesn't return anything, you should return card_remove_ref(self) just in case

#

and that looks good

grim remnant
#

well, that's annoying

normal crest
#

move the modifying of Emult before the return

hollow marsh
#

is there any reason why with malverk it isn't retexturing card backs? everything else works from the enhancers texture

grim remnant
#

silly question, how do i add a custom sound effect?

normal crest
small moon
#

Is there any way to get the mod folder from within the mod? Like if I make a mod with code to get the mod folder in the folder "foo" I'd get (in my case) C:\Users\USER\AppData\Balatro\Mods\foo

#

I saw "mod.path" in the smods code but mod isn't a global variable

normal crest
#

SMODS.current_mod.path

#

Or if you're doing it in a function that's not in the loading stage

#

SMODS.Mods[your mod id].path I think

small moon
#

Tysm!

grim remnant
normal crest
#

play_sound('prefix_key') would be my assumption

#

where prefix is your mod prefix and key is the key you have to the sound

faint yacht
#

Define the key and then you can call the sound by specifying modprefix_keyname as string.
SMODS.Sound({key = "win95start", path = "win95start.ogg"}) + toga (my prefix) = toga_win95start

grim remnant
#

when i specify the path do i need to include the /assets/sounds/ part or is that automatic?

faint yacht
#

Automatic.

grim remnant
#

for whatever reason it's still not playing? no idea why?

  &   SOUNDS   &
  &&&&&&&&&&&&]]
SMODS.Sound { --serac buff sound
    key = "seracBuff",
    path = "serac_buff.ogg"
}

        --check if a joker died
        if context.joker_destroyed then
            card.ability.extra.Emult = card.ability.extra.Emult + card.ability.extra.scaler
            play_sound(stla_seracBuff)
            return { message = "Demo!" }
        end```
normal crest
#

play_sound takes a string

faint yacht
#

You can do this too.

return { message = "Demo!", sound = "seracBuff" }
grim remnant
normal crest
#

yes it does

#

so it needs the mod prefix too

minor furnace
#

Discrete math actually coming in handy, using the inclusion/exclusion principle to get the probabilities right (I think)

    calculate = function(self,card,context)
        if context.main_scoring and context.cardarea == G.play then
            loaded_val = pseudorandom('loaded_both')
            if loaded_val < G.GAME.probabilities.normal * G.GAME.probabilities.normal/75 then
                return{
                    mult = 60,
                    dollars = 6
                }
            elseif loaded_val < G.GAME.probabilities.normal/15 then
                return{
                    mult = 60
                }
            elseif loaded_val < (G.GAME.probabilities.normal/5 + G.GAME.probabilities.normal/15 - G.GAME.probabilities.normal * G.GAME.probabilities.normal/75) then
                return{
                    dollars = 6
                }
            end
        end
    end
chrome prawn
#

I'm trying to make a joker similar to raised fist when the game selects the lowest ranked in your hand and destroys it but for some reason this code either doesn't work or it targets every single card instead of the lowest ranked one
can someone please help me?

gusty sequoia
#

Hey guys, my joker doesn't show as compatible with Brainstorm & Blueprint, despite the fact it is, why is that?

normal crest
#

set blueprint_compat = true on your joker

gusty sequoia
#

Ah, thanks!

faint yacht
small moon
#

Putting this here for anyone who might be looking for it in the future:

To find/search for files in a directory, Smods uses a filesystem library called "nativefs," (not lfs) so if you want to split your additions into separate files like I do, you can implement it like this:

local nativefs = require("nativefs")

function string:endswith(suffix)
    return self:sub(-#suffix) == suffix
end

-- Written by Melody (https://meluhdy.dev)
function load_files_in_dir(relative_path)
    local absolute_path = SMODS.current_mod.path..relative_path
    local files = nativefs.getDirectoryItemsInfo(absolute_path)
    for i = 1, #files do
        local file = files[i]
        local file_info = nativefs.getInfo(absolute_path.."/"..file.name)
        if file_info.type == "directory" then
            load_files_in_dir(relative_path.."/"..file.name)
        elseif file.name:endswith(".lua") then
            assert(SMODS.load_file(relative_path.."/"..file.name))()
        end
    end
end

Then you just need to call it with the name of the folder you store your stuff in (yes it is recursive). For example:

load_files_in_dir("jokers")

I think I got all the keywords in but just in case:
load, file system, fs, filesystem, lfs, nfs, nativefs, mod path, split files, directories, separate

gaunt thistle
#

nativefs is distributed alongside smods :-)

small moon
#

Fixed, thank you

gaunt thistle
#

pre-smods filesystem access was a monumental pain in the butt

#

nativefs is such a useful library

small moon
#

I can imagine, seeing as the only way I could see base lua doing it is through command line and obviously that's not inherently cross-platform compatible

gaunt thistle
#

yeah, either that or ffi. I've contemplated implementing something like nativefs entirely in lovely but it's a lot of work haha

small moon
#

If you do try to go ahead and do that, then I wish you the absolute best of luck

gaunt thistle
#

it's a really weird design choice by the love2d team. like, I get it, but it makes really common fs operations so much more diifficult and convoluted

#

I would if nativefs didn't already work great :-)

small moon
wicked spire
#

In the following code, why is the line mult_mod = card.ability.extra.mult necessary? When I take it out, it seems to change the color of the message sent, but I don't understand why and can't seem to find any explanation on the Steamodded wiki documentation.```lua
-- When Joker is triggered and Mult is >0, add Mult
if (context.joker_main) and (card.ability.extra.mult > 0) then
return {
message = localize {
type = "variable",
key = "a_mult",
vars = {
card.ability.extra.mult,
},
},
mult_mod = card.ability.extra.mult,
}
end

normal crest
#

mult_mod actually modifies the the mult value in scoring

#

the message is purely visual

#

if you're not in an old version of steamodded you can replace your entire return table with { mult = card.ability.extra.mult }

wicked spire
faint yacht
grim remnant
#

what'd i bork here?

twilit cargo
#

dont trust me tho im tweaking

grim remnant
#

uhhhh how so?

#

(like, what about the brackets)

marble flint
#

lua uses then and end, not brackets

twilit cargo
#

youve written it more like js (dw me too)

grim remnant
twilit cargo
#

make sure to end the if

grim remnant
#

ohhh

#

on hovering over the joker, this happened. huh?

twilit cargo
#

ok i been at this for exactly an hour now and still don't have a single line of working code 😭😭😭 does anyone know how to change the config of a booster pack from the same mod? im tryna make a voucher that gives an extra option and extra select but can't figure out how to change the extra and choose config

minor furnace
#

I'm attempting to implement a Reverse Fool Tarot, which creates an inverted version of the most recently used tarot, Fool and Reverse Fool excluded. However, I'm running into an issue where if I hover over the normal Fool card after using the Reverse Fool, it creates a stack overflow error. I think it might be because the info_queue is infinitely adding the description for the Reverse Fool, but I'm not entirely sure. This is the loc_vars function where I'm adding the info of the previously used card to the queue

  loc_vars = function(self, info_queue, center)
        local fool_c = G.GAME.last_tarot_planet and G.P_CENTERS[G.GAME.last_tarot_planet] or nil
        local last_tarot_planet = fool_c and localize{type = 'name_text', key = fool_c.key, set = fool_c.set} or localize('k_none')
        local colour = (not fool_c or fool_c.name == 'The Fool') and G.C.RED or G.C.GREEN
        main_end = {
            {n=G.UIT.C, config={align = "bm", padding = 0.02}, nodes={
                {n=G.UIT.C, config={align = "m", colour = colour, r = 0.05, padding = 0.05}, nodes={
                    {n=G.UIT.T, config={text = ' '..last_tarot_planet..' ', colour = G.C.UI.TEXT_LIGHT, scale = 0.3, shadow = true}},
                }}
            }}
        }
        if not (not fool_c or fool_c.name == 'The Fool' or fool_c.name == 'The Fool?') then
            info_queue[#info_queue+1] = fool_c
        end
    end
#

or maybe it's an issue where it just keeps calling this even if nothing is added to the info_queue?

#

I essentially just copied the function from common_events.lua

normal crest
normal crest
#

But I assume it's just a hook/patch on the part of the code that creates booster packs + a global variable in G.GAME

minor furnace
twilit cargo
#

sounds scary for a 5am 5min coding adventure but will have a look later 🙏

normal crest
#

good luck soldier

minor furnace
normal crest
#

wouldn't it be fool_c.ability.name?

minor furnace
#

that just crashes when I hover over the card

normal crest
#

oh yeah it's a center, nevermind

minor furnace
#

the line does correctly give the effect of the previously used card

normal crest
#

print(inspect(fool_c))

minor furnace
#

yeah I'll check what that does

#

I'm not entirely sure where it prints to, but it's late so it might be better if I just sleep on it

minor furnace
desert ore
#

do I need to do lovely patches to edit base game cards? I need to cover edge cases with invisible joker and ankh where they duplicate like in the situation with me not being able to purchase

sturdy compass
#

Yes you do

desert ore
#

ugh, needing to learn how to do that sooner than I thought

#

well, here goes nothing

sturdy compass
#

It’s honestly not as intimidating as it looks. It’s basically just telling it “here’s a line of code, this is how I want you to edit it”

limpid halo
#

please put code in code thnak you lovely

desert ore
#

yeah it's just I just learned hooking, and all of this is still very very new to me, it's just a little overwhelming at times

sturdy compass
#

Welcome to learning lol

nova finch
#

can you use context.other_card with context.before?

limpid halo
#

doesn't look like it in the docs but you can always try

nova finch
#

nope

#

doesnt work

limpid halo
#

then it's not there but you probably want context.scoring_hand or context.full_hand anyways

wicked spire
#

If you don't specify them not to, do Jokers' calculate effect still trigger when the Joker is debuffed?

grim remnant
#

i'm trying to make a joker that gives Xmult = 1 + (high cards played this run * scaler variable). uh. how do i grab how many high cards have been played this run a-la supernova?

wicked spire