#💻・modding-dev

1 messages · Page 636 of 1

dull bane
#

js redid it

#

so it wasnt even the two mods that were the issue?

primal robin
#

I see where issue happened

#

Go to mods folder

#

Find folder called lovely

#

Inside it dump/tag.lua

#

Send it here

dull bane
primal robin
#

%appdata%/Balatro/Mods/lovey/dump/tag.lua

dull bane
primal robin
#

I see

#

It's because of mod Arrow

#

@weak brook

#

FIx your patch please (replace 'at' to 'after')

dull bane
#

?

dapper sun
#

if you want an instant solution, disable arrow

dull bane
storm kraken
#

isnt the manager down or smth?

primal robin
#

idk

#

Not using it

dull bane
#

workin fine for me 🤷

#

i uh

#

dont know any other way to mod the game

#

so

primal robin
#

Okay, so, lets do advanced stuff

#

Go to %appdata%/Balatro/Mods

#

Find folder Arrow or smth like this

dull bane
#

still nothing abt arrow

#

sure it aint called sumthn else?

#

this all of em

#

no "arrow"

primal robin
#

okay, then archive "cardsauce" folder and send it here

#

I'll do a fix

dull bane
#

?

primal robin
dull bane
#

yes but

#

like

#

what am i doing with it?

primal robin
#

you dont know how to archive things?

dull bane
#

never even heard of doing that

primal robin
#

goddamnit

storm kraken
#

rigt click on the folder then compress to

dull bane
#

OHHH

#

DID

#

DI YOU MEAN COMPRESS??

#

I KNOW HOW TO COMPRESS

#

whyd u call it archive? 😭

dapper sun
#

bc zips are archives

dull bane
#

never heard it called archiving

#

everyone ive heard talk about it has js said compression

storm kraken
#

insane

#

7z calls it archives i think

primal robin
#

crazy

storm kraken
dull bane
#

i barely ever get 2 use 7z so

#

idk

dapper sun
#

i use winrar

#

it also says archives

dull bane
#

barely use THAT either

primal robin
#

I changed 5 letters btw

dull bane
#

oh damn fr

storm kraken
#

mad shit

dapper sun
#

reminds me how vanilla's Card:load() has a single capitalization typo that sets a card's height to nil

near bay
#

How to check if final score is a prime number?

primal robin
#

good luck

dapper sun
primal robin
#

It's very expensive task fyk

#

VERY expensive

dapper sun
#

tho that's for generating primes

#

not checking

dull bane
#

lmao

#

it worked

storm kraken
dapper sun
storm kraken
#

amazing fumble

#

nvm

dapper sun
#

pointing at bio

dull bane
#

ah.

dapper sun
#

don't point out our typos please

dull bane
#

erm

#

new problem

#

altho it MAY be an ezier fix i js wanna make sure

storm kraken
dapper sun
#

ty

primal robin
# near bay ?

checking is number a prive is VERY expensive operation for relatively big numbers

storm kraken
# near bay ?

id imagine checking for primes reaching the e numbers would be really slow

dapper sun
#

imagine trying to use that prime checker joker with numberslop mods like cryptid

primal robin
#

It will tage ages to check probably

#

If not thousands of years

dapper sun
#

3.5#6e2 or whatever numberslop notation looks like

storm kraken
#

ee

dapper sun
#

it uses # if you go big enough

#

i've done it in a cry run before

storm kraken
#

thats awesome

dapper sun
#

then ##

storm kraken
#

infinite prime

primal robin
#

I think that even for e100 check will take insane amount of time

hidden notch
#

Just prime-numer check the part after the e

primal robin
#

Actually, makes sense

#

In cryptid tho still will be insane values

dapper sun
#

maybe only check the rightmost exponent

near bay
#

Alright so I kinda get how all of this works but the code sounds very slow when comparing it to extremely high numbers

primal robin
#

Because it is

near bay
#

alright what do i do to check what the final score with be?

hallow slate
#

How do I localize rarity names?

near bay
#

actually no how do i check the current mult display?

idle oxide
#

is it possible to create a joker that upgrades the rank of cards into another rank (such as converting all 10s from deck into jacks) upon being sold after an amount of rounds (just like invis), dont really have a base to go off except invis code which for now is a bit too complex for me to understand

delicate pivot
#

I'm having a problem, probably a syntax one for using Malverk: I'm trying to use Malverk to replace the default card sprites in the game using this:

AltTexture({ -- Replace Cards
key = 'new_cards',
set = 'Default',
path = 'spritesheet.png',
keys = {
'c_base' = true
},
})

-- But I keep getting this error:
Oops! The game crashed:
[SMODS _ "src/loader.lua"]:571: [SMODS TestMod "main.lua"]:92: '}' expected (to close '{' at line 91) near '='

#

I can provide the actual main.lua if needed (I changed the mod name and key for temp reasons.)

wintry solar
#

Set should be Enhanced

#

iirc

delicate pivot
#

I'll try it.

#

I got the same error

wintry solar
#

Oh there’s a syntax error somewhere

#

Can you share the file

delicate pivot
#

yeah, one sec

loud citrus
delicate pivot
wintry solar
#

Oh

delicate pivot
#

wait, i see a small error in the temp thing i did. ignore the new_cards part, that wasn't supposed to be there

wintry solar
#

Remove = true

#

From the keys table

loud citrus
#

Just trying things lol
An inconsistency compared to your other lines of code

delicate pivot
#

I'll try that, the new_cards part should be retro_cards, I fixed that real quick. I'll test these fixes, thanks

wintry solar
#

It’s just the = true

#

Everything else looks fine

dapper sun
harsh belfry
#

you can’t key that table like that I think

#

for string keys you use [] those

#

along with the quotes

#

but you can also just remove the quotes

delicate pivot
#

It doesn't crash now, but it doesn't use the sprite I placed in the folder (2x) sprite called "spritesheet.png" which is a new blank card sprite

#

To correct myself, I placed a new sprite called (spritesheet.png) in the assets folder of my malverk pack. The image looks like this:

wintry solar
#

I’d have to check on my pc, hold on let me boot it up

idle oxide
delicate pivot
#

Currently, it just does this:

dapper sun
#

baltro

loud citrus
loud citrus
idle oxide
#

got it

quartz ravine
#

Happy Holidays everyone! In case someone missed it, the Youtuber 'Fir' did a really fun video where he enabled 40+ community mods in his Balatro and recorderd the outcome! It was really great to see the mods of so many folks I know from here on his video!

https://www.youtube.com/watch?v=SfejblgDZGo

@long sun , @tall wharf and many many others!

Today I installed way too many "Vanilla" Balatro Mods. Basically, if the mod self identified as a vanilla or vanilla+ style mod, I installed into my game. On their own a lot of these mods are pretty tame, but when combined together the game becomes an absolutely beatiful and fun mess. Enjoy the video!

Thanks to all the mod makers who created so...

â–¶ Play video
#

I felt so proud of my peers here to see their cool stuff shown off!

long sun
#

YAY yesyes!!

#

I snagged the end of the stream :3!

dapper sun
#

i remember seeing niko send this in hotpot discord

long sun
#

it was like

#

so cool pleading

primal robin
#
  • maximus
  • vanilla
stoic void
#

they should play my mod now

#

I have now got a release

#

everyone should play my mod

quartz ravine
#

It exposed me to the ModManager which I totally missed. Turns out you neeed to do work to publish your mod there

delicate pivot
primal robin
#

video thumbnail so cool tho, I like it

loud citrus
#

That helped massively! But now I'm trying to figure out how to only debuff clubs.
Removed the context.other_card so I know I'm on the right track, was trying to put :is_suit and still got a nil value

slim ferry
#

context.debuff_card:is_suit("Clubs")?

loud citrus
#

Yeah

wintry solar
slim ferry
#

you should check context.debuff_card on its own first, then the cardarea check, and then the suit check

white hull
#

also it should be context.cardarea

slim ferry
#

No, that doesnt exist in context.debuff_card

white hull
#

on its own instead of context.debuff_card.area

loud citrus
#

wait, this isn't right
i was just doing one step at a time because doing everything at once won't teach me as much, why is context.debuff_card nil in general???

slim ferry
#

its nil because it doesnt always exist when calculate is called

#

checking context.debuff_card first makes sure that it isnt nil

loud citrus
#

oh, that's wacky

slim ferry
#

and doing the cardarea check second makes sure that the card has a suit and that is_suit will therefore work on it

loud citrus
#

it's not crashing but nothing is getting debuffed, the first line works, it's the other two i can't seem to figure out.

slim ferry
#

it should be context.debuff_card.area, not context.cardarea

#

besides that it should work, so idk

loud citrus
#

WOW, i'm shocked that just splitting the checks worked!!!
now i have no tools for problem solving :)

#

thank you so much!

slim ferry
#

you can put all the checks into a single if statement btw, its just the order that matters

wintry solar
#

Update calc guide is live! 🥳

tranquil cypress
#

peak

#

woah this is great

hot remnant
#

Hi! Making my first mod, quick question: Is it possible to check the size of a played hand before the cards are scored?

#

I keep trying to compare the played hand size to a set value (3, like half joker) but it appears the value is null, and my game keeps crashing.

loud citrus
#

#context.full_hand

#

you can check for values like if it was square joker it would be
#context.full_hand == 4

#

i'm not sure how helpful that is

#

you could also do (as an example)
card.ability.extra.chips = card.ability.extra.chips*#context.full_hand
though i haven't tested

loud citrus
#

okay so this works, but i need it to count debuffed clubs instead of not debuffed clubs

loud citrus
toxic cave
#

where does the game undo the effects of a defeated boss blind? i see Blind:defeat() but it doesnt seem to do much

daring fern
toxic cave
daring fern
toxic cave
daring fern
toxic cave
daring fern
loud citrus
daring fern
toxic cave
loud citrus
cinder elk
#

rq where does balatro store its joker code

loud citrus
cinder elk
#

got it

#

how do i make it so a card is check to see if it's a wild card

#

just curious

daring fern
harsh belfry
cinder elk
#

like this right

harsh belfry
#

something can be all suits without being wild

#

so do you want to check for wild specifically

#

or all suits

cinder elk
#

just wild specifically

#

it's a jungle themed joker

#

so

#

wild

#

wild jungle

#

ehhhh

harsh belfry
cinder elk
wind steppe
harsh belfry
#

vaporize

wind steppe
#

also i dont think thats the right context for retriggering?

#

the check works

cinder elk
harsh belfry
#

context.repetition instead i think

wind steppe
#

(still keep the cardarea check)

harsh belfry
#

and its repetitions = 1

hot remnant
# loud citrus #context.full_hand

Thank you for the answer, I appreciate it.

That was the solution I was trying, but it kept giving an error message to the effect of "Cannot compare null to table"

I'll figure it out tho. At least now I know I'm on the right track lol

harsh belfry
#

instead of retrigger = true

daring fern
# cinder elk

No, it would be if SMODS.has_enhancement(context.other_card, 'm_wild')

wind steppe
#

why is my localize call not loading the description?

#

this is a lovely patch in generate_card_ui

#

this is the localization entry

cinder elk
#

so like this.

#

???

daring fern
# cinder elk
if context.repetition and context.cardarea == G.play then
    if SMODS.has_enhancement(context.other_card, 'm_wild') then
        return {repetitions = 1}
    end
end
cinder elk
#

ehhh?

wind steppe
#

that should do it

cinder elk
#

got it

#

lemme check

#

YEP

#

thanks much

#

i'll try and be more active here

#

i want to

#

learn.

hot remnant
#

Thats probably why it was giving me an error

loud citrus
#

lol

#

I forget often, so my favorite way to remember is

Are you checking? ==
Are you declaring? =

It's obtuse but having an easy question to help you stop and think goes a long way.

hot remnant
#

Its so silly cause I've been in computer science for so long, you'd think I'd remember those kinds of things, but I still forget commas and ending functions lolll

loud citrus
hot drift
round lion
#

cant have shit in balatro

#

i tried to modify the hands played thing to add a clause which refunds the hand immedietely if a eval returns true

#

it never worked

#

my mom then blamed the resulting panic attack over the video game

jolly shadow
quartz ravine
hot drift
#

lbp in the big 2025

vague crest
# cinder elk

Littleb.... ligglbigp... littglebuh... bigplsnet... buhhhh

#

🥺

#

This could change the game

#

Wait ninjabanana??

hot drift
#

heya

#

I've been here a while

#

mainly over in cryptid discord (and clams more recently)

unkempt thicket
loud citrus
#

how would one count debuffed cards like cloud 9?
i'm trying to count every debuffed club in a deck

loud citrus
#

i have this but playing_card.debuff doesn't work

spiral mural
#

someone REALLY should make a guide on custom context

quartz ravine
spiral mural
quartz ravine
#

hmmm that is interesting. I've never added a context. I would have to look at something like context.destroying_card or repetition to see how they handle their inputs to see whats going on. Also how you even register a context window and when that should happen

harsh belfry
#

theres a function you can call

#

that is passed as context

spiral mural
#

context wunkdow is NOT a myth...

harsh belfry
#

for every single thing

#

it don't even have to be a table

#

(don't do that though)

spiral mural
#

how are context return tables even returned as

#

big table

#

a horrible tuple?

#

is it in cardarea area...

harsh belfry
umbral zodiac
spiral mural
umbral zodiac
#

Tables..

spiral mural
#

i hate tables

gaunt thistle
umbral zodiac
#

who is Mike Pall

spiral mural
#

who is mike pall

gaunt thistle
#

luajit's dad

#

he made the whole thing, still does

sturdy compass
#

Why is he being cloned

#

what

gaunt thistle
#

oh my god nevermind 😭

umbral zodiac
loud summit
#

hey is there any way to force localize() to use a specific language

daring fern
normal crest
#

so you'd have to load the localization file you want yourself

#

that's done in game.lua in the Game:set_language function

loud summit
#

dam

wind steppe
#

speaking of localize

loud summit
#

im pretty sure other indexes into the misc.dictionary section

faint yacht
#

mfw

function togabalatro.talismanjoke()
    local rtxt = G.localization.misc.ui_strings.toga_talismanjoke
teal grotto
#
        local other_joker = context.card
        if other_joker and other_joker.ability then
            local result = {}
            if other_joker.ability.extra and type(other_joker.ability.extra) == "table" then
                if other_joker.ability.extra.chips and other_joker.ability.extra.chips ~= 0 then
                    result.x_chips = other_joker.ability.extra.chips
                end
            end
            if next(result) then
                return result
            end
        end
    end,```
how do i make this trigger when other jokers trigger
wind steppe
#

ive tried type = "para_items" as well and no luck

loud summit
#

no like

#

where is your localization entry

loud summit
#

type can only be a few hardcoded ones

wind steppe
#

its an optional feature that you should look into

#

dont know too much about it unfortunately

teal grotto
wind steppe
daring fern
teal grotto
#

oh

loud summit
#

type = "descriptions", set = "para_items", key = "para_itemeternal"

teal grotto
#

tysm ive been trying for so long
and its that easy

loud summit
#

oh

#

try returning the same thing in vars and config

wind steppe
#

same crash

loud summit
#

type = "description"?

wind steppe
#

we're back to our original issue

#

hm actually let me try something

loud summit
#

try putting localize{ type = "description"... into the debugplus console

wind steppe
#

maybe it wont look for the loc_vars if i remove #1# and #2#

wind steppe
loud summit
#

hhhhh

#

localization is cursed

wind steppe
loud summit
#

big

reef belfry
#

ending the round as soom as entering a blind, how do i make it so the cards do not draw?

reef belfry
#

cant send the entire joker code for reasons

daring fern
reef belfry
#

it doesnt work still (actually wait)

#

yeah still doesnt work

loud citrus
#

i'm trying to make it so on discard debuffed clubs trigger adding mult, but nothing is happening
(i decided to pivot to what is better game design and what should be much simpler to code)

daring fern
loud citrus
#

tragic, is there any possible work around?

#

or any a mod has done?

daring fern
loud citrus
#

that's fine :)
it's the joker itself i truly care about

loud citrus
daring fern
stoic void
loud citrus
daring fern
gilded blaze
#

that wouldn't work

#

Card:is_suit(suit) already returns false if the card is debuffed

#

use Card:is_suit(suit, true) instead, it bypasses debuff state

loud citrus
#

i was doing this fo r so long i'm still in shock it now works, what would i do without the leader in our community balatroheart

storm kraken
#

😔
-# and yes, the card area DOES exist because trying to remove a card returns a nil error

golden field
#

question: how do i make a seal retrigger OTHER scored cards

golden field
#

please explain

daring fern
golden field
golden field
daring fern
golden field
# daring fern You would have to change most things in the `if v:get_seal() == 'modprefix_key'`...

is this correct

SMODS.Seal {
    key = 'club',
    atlas = 'wacleseals',
    pos = { x = 3, y = 0 },
    config = { extra = { repetitions = 1 } },
    badge_colour = HEX("5186a8"),
    
    calculate = function(self, card, context)
        if context.repetition then
            local retriggers, my_pos, full_hand = {}, 0, CardArea.is(context.cardarea, CardArea) and context.cardarea.cards or context.full_hand or G.play.cards
            for k, v in pairs(full_hand) do
                if v == context.other_card then
                    my_pos = k
                end
                if not v:is_suit('Clubs') then
                    retriggers[k] = {repetitions = 1, card = v}
                end
            end
            if retriggers[my_pos] then
                return {repetitions = retriggers[my_pos].repetitions, message_card = retriggers[my_pos].card}
            end
        end
    end
}
daring fern
golden field
daring fern
golden field
#

ah

#

thanks

golden field
# daring fern ```lua SMODS.current_mod.calculate = function(self, context) end ```

so smth like this

    SMODS.current_mod.calculate = function(self, context)
        if context.repetition then
            local retriggers, my_pos, full_hand = {}, 0, CardArea.is(context.cardarea, CardArea) and context.cardarea.cards or context.full_hand or G.play.cards
            for k, v in pairs(full_hand) do
                if v == context.other_card then
                    my_pos = k
                end
                if not v:is_suit('Clubs') then
                    retriggers[k] = {repetitions = 1, card = v}
                end
            end
            if retriggers[my_pos] then
                return {repetitions = retriggers[my_pos].repetitions, message_card = retriggers[my_pos].card}
            end
        end
    end
#

or do i have to put SMODS.calculate under calculate =

daring fern
golden field
daring fern
daring fern
# golden field all other scored cards
SMODS.current_mod.calculate = function(self, context)
    if context.repetition and context.cardarea == G.play then
        local retriggers, my_pos, full_hand = {}, 0, context.scoring_hand or context.full_hand or G.play.cards
        for k, v in pairs(full_hand) do
            if v == context.other_card then
                my_pos = k
            end
            if v:get_seal() == 'modprefix_key' then
                for kk, vv in pairs(full_hand) do
                    if not vv:is_suit('Clubs') and vv ~= v then
                        retriggers[kk] = {repetitions = (retriggers[kk] and retriggers[kk][1] or 0) + 1, card = v}
                    end
                end
            end
        end
        if retriggers[my_pos] then
            return {repetitions = retriggers[my_pos].repetitions, message_card = retriggers[my_pos].card}
        end
    end
end
daring fern
golden field
#

ah

#

omg it works tysm

golden field
#

why does this reflip the card when scored right after being unflipped

        if card.facing == 'front' and not context.main_scoring and context.cardarea ~= G.play then card:flip() end
        if card.facing == 'back' and context.main_scoring and context.cardarea == G.play then card:flip() end
bold sleet
storm kraken
#

h

bold sleet
# bold sleet help

The question is simply how do I clear these boxes as if there was no hand selected?

prisma loom
#

Folks, I have a function that doubles ante scaling by X2 for the rest of the run when you beat the Blind by scoring X2 the requirement. I want to tone down this effect to make it work on the next Blind only. How should I adjust the code to do that?

#

(ignore prints)

storm kraken
#

hm

#

have a variable that decreases or whatever at the end of the next blind

#

then you check if that variable has done its thing

bold sleet
harsh belfry
#

g

#

just empty string

#

you were like 99% of the way there lmao

bold sleet
#

ah

harsh belfry
#

oh and mult and chips should be 0 instead of empty string

bold sleet
#

amazing

faint yacht
#

...where in localization file do I define the text and labels for a custom ConsumableType?

bold sleet
#

descriptions[ConsumableType][c_prefix_key]

#

example

prisma loom
#

Otherwise itd be a bit confusing

faint yacht
#

...so, in my case,

SMODS.ConsumableType{
    key = "togaitem",
    ...
}

would be this?

bold sleet
#

I suppose it in misc.labels

faint yacht
bold sleet
#

No idea, sorry.

storm kraken
#

this is really funny to me for no reason lmao

bold sleet
storm kraken
#

new function:
ObjectType:kill(key)

#

can you guess what it does

bold sleet
#

clueless

olive path
#

any way to check if a card was face down before getting played?
tried to use card.facing == "down", but doesn't work bc the card gets flipped before getting scored

storm kraken
#

hey guys does anyone want another code dump from me being the clueless soul i am and asking for help on the simplest of stuff 🥺

primal robin
#

sure why not

bold sleet
#

Send it.

storm kraken
#

i assume its something to do with how i remove the cards from the cardarea on leave but i need help please 🥺

primal robin
#

When cardarea is removed it deletes cards for some reason

#

aka you're trying to do smth with removed card area

storm kraken
#

oh

primal robin
#
G.FUNCS.market_clean = function()
    for i = 1, 5 do
        G.fish_cards.cards[1]:remove()
        if i == 5 then
            G.FUNCS.exit_overlay_menu()
        end
    end
end

wtf is this

storm kraken
#

so i need to re add the card area?

storm kraken
primal robin
#

I do believe you doing something wrong if you need to do this on market closing

storm kraken
#

thats why im asking for help 🥺

primal robin
#

Decent amount of things here to cover

#

Starting from G.FUNCS.market be too generic name

#

Prefix all your stuff

storm kraken
#

uhh

#

sure!

primal robin
#

Then, you shouldnt store your stuff in just G

storm kraken
#

uhhhhh

#

sure!

primal robin
#

If you have own global object, use it instead

#

Because, game saves all card areas added to G object, which you probably don't want right

storm kraken
#

uhhhhhhh

#

idk

#

uhh i dont think i want that no

primal robin
#

When you have area added to UI via G.UIT.O, when UI is removed, it removes area and cards in it automatically, so you dont need cleanup them

#

But reference in G will contain removed card area

#

And attempt to add cards in it will crash because, well, it's removed

hushed briar
#

trying to fix bugs that have popped up with my mod since ive been away for a while, anyone know why trading card might not be active despite discards used being 0?

primal robin
#

holy, wtf

storm kraken
#

G slop

primal robin
#

that's not how localization should work ideally but okay, sure

storm kraken
#

the menu looks like this if that helps at all

primal robin
#

not the prettiest ui I seen I'll be fair

storm kraken
storm kraken
#

i agree it looks horrendous but it gets its job done

primal robin
#

Common practice for mods is have own global object where you store and manage your stuff

#

I guess you dont have one, that's okay

#

In theory you can make G.FishMarket = {} and store stuff here

storm kraken
#

hmmm k

#

i'll experiment more tomorrow

vocal cedar
#

Eyold Merry Christmas fellas

#

Im only active in this specific channel lol

steel quail
#

So
how does one create a mod for this game.
I am a bit intrigued

hardy vessel
#

Is there a way to re-enable a boss blind after it has been disabled?

elder rune
#

Yeah gimme a sec

elder rune
#

First joker at the top re-enables the boss blind

storm kraken
#

tho i learnt from a video guide

hardy vessel
elder rune
#

Np

daring fern
elder rune
#

Haven't encountered that problem so I didn't know picardia_shrug

hushed briar
#

like its random if trading card just doesnt work or not

steel quail
hushed briar
#

and looking at the code, G.GAME.current_round.discards_used is the only value trading card really checks so i have no idea what i couldve done to break it

elder rune
storm kraken
#

uhh

steel quail
storm kraken
elder rune
# steel quail Yes! I'd like to try and do that first.

Okay when I first got into modding I honestly checked how other mods did stuff and then made mine based off that. But the most important files are a "manifest" file that basically is the thing that loads in the mod essentially with some other info. And a "main" file that is usually for loading in other files and some function definitions

steel quail
#

would getting the cryptid mod be a good start?

elder rune
#

Vanilla remade is a good one to check

steel quail
#

Alr

elder rune
versed swan
elder rune
storm kraken
#

really you only need a main.lua, asset folder with images (1x and 2x sub folders), json with mod info

elder rune
storm kraken
elder rune
#

I just call it the manifest cause that's what I name it normally

versed swan
#

That's usually what those kinds of files are called

elder rune
#

Yeah exactly

storm kraken
#

oh well

#

learn something new every day

elder rune
#

Real

elder rune
steel quail
elder rune
#

Alr

storm kraken
#

balatro modding is like an in quint easing

#

it starts easy then you get 500 crashes of doom

steel quail
#

ok i think i got the lovely injector working!!

elder rune
#

The game crashes cause you forgot to add one end

storm kraken
#

forget a double =

#

from being so tired

#

maybe you miss a bracket

#

type o instead of i

elder rune
#

Legit my game crashed and I couldn't figure out why for 2 hours until I saw that I forgot 2 parentheses in the loading

storm kraken
#

💔

elder rune
#

Also play stocking stuffer now

storm kraken
#

dont you check the crashlog

elder rune
#

I read it

steel quail
#

I got a question about the downloading steps

#

Do i put the extracted steammodded folder in Balatro's mods folder?

storm kraken
steel quail
#

Ok i think did it!

noble violet
#

help?....

brazen kite
#

is there a way i could like. hook into lucky cards? (i'm trying to make a joker which replaces the +mult on lucky cards with xmult and it's currently working but it requires taking ownership of the entire enhancement which feels inelegant)

lilac trail
#

I need to localize my files, what is the format for localizing Jokers?

#

is it {prefix}_j_{name of joker}

daring fern
lilac trail
#

thx

#

What are the standard highlighting colors?

I know Mult is often highlighted with red. Chips are sometimes highlighted with blue as well

#

Is there any "standard" for Jokers?

slim ferry
#

usually the name of any given item is highlighted with {C:attention}, with the exception of consumables which are highlighted with the colour of their consumable type

hot drift
#

is there a context for determining if you are currently in a blind?

slim ferry
#

G.GAME.blind and G.GAME.blind.in_blind

hot drift
#

ty

idle oxide
#

coming back from last night with the idea i had about a joker similar to invis but that converts cards of a rank to another once sold, i implemented it but:

  1. it doesnt track progress
  2. im not sure if the actual transformation is correct
    would appreciate if someone tells me where it went wrong and if i did it correctly
loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.total_rounds, card.ability.extra.invis_rounds } }
    end,
    calculate = function(self, card, context)
        if context.end_of_round and not context.blueprint and not context.repetition then
            card.ability.extra.invis_rounds = card.ability.extra.invis_rounds + 1
        end
        if context.selling_self and card.ability.extra.invis_rounds >= card.ability.extra.total_rounds then
            for i = 1, #G.playing_cards do
                local deck_card = G.playing_cards[i]
        if deck_card:get_id() == 11 then
            G.E_MANAGER:add_event(Event({
                func = function()
                    local _card = G.deck[i]
                    assert(SMODS.change_base(deck_card, nil, "Queen"))
                    return true
                end
                }))
                    break
                end
            end
        end
        return {
            message = (card.ability.extra.invis_rounds < card.ability.extra.total_rounds) and
                (card.ability.extra.invis_rounds .. '/' .. card.ability.extra.total_rounds) or
                localize('k_active_ex'),
            colour = G.C.FILTER
        }
    end
}```
chrome widget
#

Is anyone here able to help with an accurate conversion of a node's coordinates to screenspace coordinates?

The base coordinate system conversion as the cursor implies is simply self.T.x/y * G.TILESIZE * G.TILESCALE, but it seems like for nodes they have some offset using self.shadow_parrallax and some other built-in offsets that I can't quite wrap my head around. The result is that the offset betweeen the base coord conversion and the real node's screen position looks something like this, but I haven't been able to wrap my head around what math gets me a consistent result to the real screenspace

slim ferry
#

is there anything wrong with this extension? the consumable type definitely exists and it does work when i have the set as the exact same thing in an SMODS.Consumable yet when i try to use the extension it crashes on launch

#

actually nevermind i might be stupid

feral tree
#

how can i check if the player has a specific achievement?

chrome widget
#

aaaand it was so simple

#

lmao

feral tree
#

wait do achievements even stay earned even after you disable and enable the mod?

upper quarry
#

yeah, i believe achievements are saved to player data which persists even after a mod is disabled

errant fulcrum
#

I'm trying to pull the enhancement key for the card that a seal is on, but I keeps saying center is a nil value. This is the line of code that mentions center:

local enh_key = card.config.center.key
Am I going about it wrong?

idle oxide
#

and other issues

delicate pivot
#

Still encountering an issue with something I tried to do. I tried to replace the white part of the card with a new default one and it shows up invisible now. I have an image called "retro_cards.png" in the (2x) folder and I have the code for the alt texture, but it doesn't work. Any ideas on what I did wrong? I've been stuck for a while trying to figure it out. (I'm using Malverk)

AltTexture({ -- Replace Cards
key = 'retro_cards',
set = 'Enhanced',
path = 'retro_cards.png',
keys = {
'c_base'
}
})

wintry solar
#

Can you send your main file again?

#

@delicate pivot

feral tree
#

is there a context to detect if you've won a run?

viscid talon
#

nvm i tried it again weeks lalter and its broken

#

SOBS

#

i hate this game

rocky plaza
#

with that

viscid talon
#

eremel helped me

rocky plaza
#

ah

rocky plaza
spiral mural
#

how do i get the currently selected joker

rocky plaza
spiral mural
#

how to get the rarity of a joker

rocky plaza
#

where card is a joker

#

if you're checking if a card is a certain rarity

#

you can just do
card:is_rarity(rarity)

spiral mural
rocky plaza
#

SMODS currently does not implement an ordering system for rarities

#

but for common - uncommon - rare - legendary they have number aliases

spiral mural
#

rarities are stored as numbers by default

#

yea

rocky plaza
#

i have to leave temporarily but ping me so i can get back to it easier

granite jay
#

Oooo what is this mod?

rocky plaza
spiral mural
#

just know that i know this will mostly work for my usecase

rocky plaza
#

If it works then it works

spiral mural
viscid talon
rocky plaza
#

Fair

tranquil cypress
golden field
#

question: how do i get the length of played hand as a number

daring fern
golden field
#

thanks

#

why does this keep returning +0 mult when i play a hand with less than 5 cards

    calculate = function(self, card, context)
        if context.before and context.cardarea == G.play then
            mult = mult + ( (5 - #context.full_hand) * 11 )
            return {
                message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.seal.extra.mult } },
                colour = HEX("575757")
            }            
        end
    end
#

mult = 0, manacle_mult = 11 btw

golden field
daring fern
golden field
#

ah

golden field
#

-# nvm it just rebalanced the effect lmao thanks

obsidian spear
granite jay
#

Interesting

loud citrus
#

You can find a joker or object that requires a run win to unlock

urban wasp
#

way way late response just realized but yeah just find blueprint

spiral mural
#

where is every playing card sstored

faint yacht
#

G.playing_cards

spiral mural
#

is there a context for when a card spawns in

faint yacht
#

context.setting_ability?

spiral mural
#

sounds like it?

#

how to check what type of card something is

storm kraken
#

which is like 'Tarot' 'Joker' etc

spiral mural
#

playing card?

#

does that have a set

storm kraken
#

i think its 'Base'

spiral mural
#

will try

storm kraken
#

tho i havent really needed to get the set of a playing card before

#

i just know its sometimes referred to as 'Base' in the code

spiral mural
#

is there any setting in set_edition, set_ability, or set_seal that allows you to mute the sound they would otherwise make?

spiral mural
faint yacht
#

¯_(ツ)_/¯

spiral mural
faint yacht
#

hec

spiral mural
#

i guess i couldl do that

#

but how do i stop it when the joker ceases to exist/gets debuffed

faint yacht
#

...wouldn't a return true kill said event?

spiral mural
#

i know that

#

but how do i check the joker ceasing to exist/debuffed

#

(and how to start it back up when the joker stops being debuffed)

#

@faint yacht

faint yacht
#

Stopping the event is return true if not next(SMODS.find_card('j_mod_key'))... but bringing it back up?

#

Or just do nothing if not next(SMODS.find_card('j_toga_notsosmileyface')) in the event.

spiral mural
faint yacht
#

SMODS.find_card(key, count_debuffed)

spiral mural
#

makes sense

storm kraken
weary merlin
#

how do i make a joker not appear nor count in the collection?

storm kraken
storm kraken
#

dancing gif

golden field
#

question: how do i use a loc file for seals

weary merlin
storm kraken
#

damn

weary merlin
#

is it possible to swap between two atlas pos indexes based on a joker's local variable?

daring fern
weary merlin
#

thanks

storm kraken
#

its so easy to lose track of balatro ui im crying

#

ive had to look for the node i was already editing again like 5 times

vale crow
#

Is the parts table of poker hand parts global name "parts"? I need to define a poker hand part in terms of another, like parts._all_pairs is define as the merged parts._2

golden field
#

i fucking swear to GOD this was working earlier why is it not now all of a sudden

SMODS.Seal {
    key = 'club',
    atlas = 'wacleseals',
    pos = { x = 3, y = 0 },
    badge_colour = HEX("b9cb92"),
}

SMODS.current_mod.calculate = function(self, context)
    if context.repetition and context.cardarea == G.play then
        local retriggers, my_pos, full_hand = {}, 0, context.scoring_hand or context.full_hand or G.play.cards
        for k, v in pairs(full_hand) do
            if v == context.other_card then
                my_pos = k
            end
            if v:get_seal() == 'tcg_club' then
                for kk, vv in pairs(full_hand) do
                    if not vv:is_suit('Clubs') and vv ~= v then
                        retriggers[kk] = {repetitions = (retriggers[kk] and retriggers[kk][1] or 0) + 1, card = v}
                    end
                end
            end
        end
        if retriggers[my_pos] then
            return {repetitions = retriggers[my_pos].repetitions, message_card = retriggers[my_pos].card}
        end
    end
end
#

-# for some reason when i delete the rest of my code it works 😭

vale crow
golden field
#

-# ...do i just send my entire fucking file or smth 😭

vale crow
# golden field what

local retriggers, my_pos, full_hand = {}, 0, context.scoring_hand or context.full_hand or G.play.cards
instead do this
local retriggers, my_pos = {}, 0
local full_hand = context.scoring_hand or context.full_hand or G.play.cards

golden field
#

ah noted

vale crow
#

local retriggers, my_pos = {}, 1
since it seems you use my_pose as the index of a table

vale crow
#

Does it even crash?

golden field
#

does not crash, it just straight up does not retrigger

vale crow
reef belfry
#

ive made a hook that "works" where cards arent being drawn

#

but the game state itself is just frozen

#

i dont wanna learn the ins and outs of how balatro operates the states so if anyone actually knows...

reef belfry
golden field
#

-# decided to revert it back since the minor changes didnt rlly work

daring fern
daring fern
golden field
#

oh my fucking god 😭

it's because you can't have more than one calculate

the lowest one overrides the ones on top 😭

#

welp tiem to learn how to add more code files

daring fern
golden field
#

oh my fucking god i'm stoopid

#

oker it works now :D

pastel kernel
#

how does Card.calculate_joker work?

primal terrace
#

I want to localise the name of G.GAME.last_tarot_planet, and so I need to find a way to make it reference two different sets, or check between them

daring fern
primal terrace
#

Sweet

loud citrus
#

i'm trying to identify the blind's name, how would i do so?

daring fern
loud citrus
#

i'm actually trying to create a joker that shares the same name as the current blind, should have been more specific
i know how to create a joker, just need the name

#

also i have made the jokers with the names

daring fern
daring fern
pastel kernel
daring fern
pastel kernel
#

Destroyed

#

Rubys gonna guide me since were using Entropy’s stuff

daring fern
pastel kernel
loud citrus
reef belfry
#

hey atleast it didnt draw the cards

storm kraken
#

😭

reef belfry
#

im just patching some stuff and seeing what sticks

#

if i actually pull this off by throwing random bullshit i should get an award

storm kraken
#

what are ya trying to do

reef belfry
#

make it so cards dont draw when starting a blind

storm kraken
#

uhhh

daring fern
# pastel kernel You might need to ask Ruby about that, Also this is a crossmod for Entropy so…
local oldcardremove = Card.remove
function Card:remove()
    if self.ability.consumeable and G.I.CARD[2] then
        local card = G.I.CARD[2]
        G.modprefix_savedconsumeables = G.modprefix_savedconsumeables or {}
        local old_ability = copy_table(card.ability)
        local old_center = card.config.center
        local old_center_key = card.config.center_key
        card:set_ability(key, nil, 'quantum')
        card:update(0.016)
        table.insert(G.modprefix_savedconsumeables, SMODS.shallow_copy(card))
        local fakecard = G.modprefix_savedconsumeables[#G.modprefix_savedconsumeables]
        fakecard.ability = copy_table(fakecard.ability)
        for k, v in pairs({'T', 'VT', 'CT'}) do
            fakecard[v] = copy_table(fakecard[v])
        end
        fakecard.config = SMODS.shallow_copy(fakecard.config)
        card.ability = old_ability
        card.config.center = old_center
        card.config.center_key = old_center_key
    end
    return oldcardremove(self)
end
if context.post_trigger then
    local other_joker
    for k, v in pairs(G.jokers.cards) do
        if v == card then
            other_joker = G.jokers.cards[k+1]
        end
    end
    if other_joker == context.other_card then
        for k, v in pairs(G.modprefix_savedconsumeables) do
            Cryptid.forcetrigger(v)
        end
    end
end
storm kraken
#

gl i guess

reef belfry
#

oh cool now the hand doesnt update to draw cards

#

i might actually use this for the future

junior tapir
#

So I want to implement a functionality that once a hand is played, at the end of the scoring it nullifies the score and returns the played cards to the hand. But whether I try it with a boolean that changes on context or contexts themselves, it doesn't work properly (I've listed what I've tried so far). Can anyone help out?

config = {
    used = false,
    last_score = 0,
    hand_incoming = false,
    hand_cards = {}
},

-- "Once per round at end of scoring process revert the played hand by selecting and dragging this joker"
-- no need to synchronize between several copies of the joker since you can't be dragging two jokers at once
calculate = function(self, card, context)
    if context.blind then
        card.ability.used = false
        card.ability.hand_incoming = false
    end

    -- intended if hand_incoming boolean used
    -- context. :  press_play, after 
    --  (for some reason context.before triggers it even not during hand playing, but everywhere else too, go figure)
    if context.press_play then
        card.ability.last_score = G.GAME.chips
        card.ability.hand_incoming = true
    end

    -- context. :  individual (triggers mr bones - beats blind after score nullified),
    --             main_eval (triggers it basically at all times),
    --             joker_main, post_joker, edition (don't work at all)
    if card.states.drag.is and not card.ability.used and context.edition then -- the third boolean I swap
        card.ability.used = true

        G.GAME.chips = card.ability.last_score
        G.GAME.current_round.hands_left = G.GAME.current_round.hands_left + 1

        -- TODO return played non-destroyed cards into hand
    end

    -- intended if hand_incoming boolean used
    -- context. :  hand_drawn, final_scoring_step
    if context.hand_drawn or context.end_of_round then
        card.ability.hand_incoming = false
    end
end
#

Currently I've made it so proccing the joker happens by selecting and dragging it, maybe I try a different approach, but I've made it somewhat work so far

#

I have to mention that with the card.ability.hand_incoming parameter things work only until the first played hand, after that it triggers non-chalantly at all times

storm kraken
loud citrus
#

fixed it!!!!

#

didn't need to make everything lower case lol
honestly the solution was much simpler than i thought

#

now i just need to figure out how to make a fail safe if it encounters an unsupported modded blind.

loud citrus
#

how can i identify if the current blind is a modded blind?

pastel kernel
#

how do i make it so that this makes exceptions for rare consumableslua if G.consumeables and #G.consumeables.cards > 0 then local itemcut = {} for i = 1, #G.consumeables.cards do if not G.consumeables.cards[i].ability.eternal and not G.consumeables.cards[i].getting_sliced and not consumable.config.center.hidden then itemcut[#itemcut+1] = G.consumeables.cards[i] end end

storm kraken
#

d

storm kraken
#

am i stupid??

pastel kernel
#

rare consumables are hidden by default

storm kraken
#

oh uh

#

just uhh check for those consumeable's keys then ig?

#

there shouldnt be too many

sharp anchor
#

mornin all, apologies for what is likely a very noob-y question, but i'm trying to make a deck modify the rate at which specific booster packs appear in the shop. is there a good pre-existing solution for this, and if not, how might i go about designing one?

edit, figured it out. weights are in G.P_CENTER indexed by the internal names of the booster packs. you can set an apply function which changes their weights when the deck comes into effect

candid acorn
#

Asking again

spiral mural
#

does find_card count jokers copying the target card

dapper sun
#

anyone know why this isn't working correctly?

local csc_hook = Card.can_sell_card
function Card:can_sell_card(context, ...)
    local csc = csc_hook(self, context, ...)
    
    if (SMODS.is_eternal(self, {from_sell = true}) and #SMODS.find_card("j_elle_diamond_pickaxe", false)>0) then
        return to_big(G.GAME.dollars) >= to_big(self.sell_cost)
    end
    
    return csc
end

local sc_ref = Card.set_cost
function Card:set_cost(...)
    sc_ref(self, ...)
    
    if (SMODS.is_eternal(self, {from_sell = true}) and #SMODS.find_card("j_elle_diamond_pickaxe", false)>0) then
        self.sell_cost = self.sell_cost * -2
    end
end```
#

the set_cost hook seems to be the one that isn't working

primal robin
dapper sun
#

ty i knew i was forgetting that but didn't remember the var name

#

also i found out it's just bc set_cost wasn't being run

primal robin
#

It's called from time to time when some events occur

#

You can call this manually

#
for k, v in pairs(G.I.CARD) do
    if v.set_cost then
        v:set_cost()
    end
end
#

I'm doin this when you getting jonkler or removing it

dapper sun
#

ty

primal robin
#

np

#

if you want you can ask questions in my dms in order to get faster responses

dapper sun
#

thanks

storm kraken
#

guhh does anyone know how to do good art how do i art,,,

pastel kernel
#

i cannot think straightlua if context.end_of_round and not card.getting_sliced and (context.individual or context.repetition) then if G.consumeables and #G.consumeables.cards > 0 then local itemcut = {} for i = 1, #G.consumeables.cards do if not G.consumeables.cards[i].ability.eternal and not G.consumeables.cards[i].getting_sliced then itemcut[#itemcut+1] = G.consumeables.cards[i].config.center_key end end if #itemcut > 0 then for _, c in ipairs(itemcut) do c.getting_sliced = true G.E_MANAGER:add_event(Event({func = function() card:juice_up(0.8, 0.8) c:start_dissolve({G.C.RED}, nil, 1.6) return true end })) return {message = "!!!"} end

#

for the love of god what the fuck am i doing wrong

primal robin
#

text

#

this thing stops after first item cutted because return inside of cycle

pastel kernel
#

i'm getting dumber and dumber

storm kraken
#

dude

#

you cant dissolve a key

#

you need to dissolve a CARD

pastel kernel
#

oh

faint yacht
#

itemcut[#itemcut+1] = G.consumeables.cards[i].config.center_key > itemcut[#itemcut+1] = G.consumeables.cards[i]

storm kraken
#

yeah

#

c looks in the table itemcut and that line returns the key which is a string

pastel kernel
storm kraken
#

What

pastel kernel
storm kraken
#

cool

pastel kernel
#

this was before ruby changed it to have .config.center_key

storm kraken
#

well uhhhh

#

have you tried c hecking what could be wrong there

pastel kernel
storm kraken
pastel kernel
#

only ruby can help, she made entropy

#

but i can't talk to her everyday

storm kraken
pastel kernel
#

what numbers

#

line 3693

storm kraken
#

o i see

#

it could be the fact that center has nothing in it

#

thats why its nil

pastel kernel
#

i don't wanna mess with entropy's library

storm kraken
#

okay

pastel kernel
#

i'm not gonna work on the joker today

#

it's being sent to the backburner

idle oxide
#

last night ive tried coding in a joker which acts similar to invis but as soon as being sold it converts all cards of 1 rank into another (in this case jacks into queens)
ive attached the code from it below as it doesnt actually keep count of the rounds played nor do i think the rank conversion works, if someones nice enough to look into my failure

loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.total_rounds, card.ability.extra.invis_rounds } }
    end,
    calculate = function(self, card, context)
        if context.end_of_round and not context.blueprint and not context.repetition then
            card.ability.extra.invis_rounds = card.ability.extra.invis_rounds + 1
        end
        if context.selling_self and card.ability.extra.invis_rounds >= card.ability.extra.total_rounds then
            for i = 1, #G.playing_cards do
                local deck_card = G.playing_cards[i]
        if deck_card:get_id() == 11 then
            G.E_MANAGER:add_event(Event({
                func = function()
                    local _card = G.deck[i]
                    assert(SMODS.change_base(deck_card, nil, "Queen"))
                    return true
                end
                }))
                    break
                end
            end
        end
        return {
            message = (card.ability.extra.invis_rounds < card.ability.extra.total_rounds) and
                (card.ability.extra.invis_rounds .. '/' .. card.ability.extra.total_rounds) or
                localize('k_active_ex'),
            colour = G.C.FILTER
        }
    end
}```
quick scarab
#

Does anyone know if it's possible to create a unlock requirement that involves the amount of blinds skipped?

#

do I have to do it manually or is it integrated on the code something that track blind skips?

#

Also I need some help to make this condition trigger, where the perso has to have -$20 on them to unlock a card

check_for_unlock = function(self, args)
  return args.type == 'money' and G.GAME.dollars == -20 
end
dapper sun
#

how do u add an info_queue for eternal

tranquil cypress
dapper sun
#

ty

tranquil cypress
#

youre welcome

cinder elk
#

right again. hello chat. i wanna figure out how exactly to make this so it triggers when there's a pair and not just any time before debuffing itself

#

`SMODS.Joker{
key = 'lbpfrida',

-- Display information for UI
loc_txt = {
    name = 'Frida the Bride',
    text = {
        'If played hand contains a {C:attention}Pair{},',
        'gain {C:mult}+15{} Mult',
        'Then this Joker is {C:attention}debuffed{}',
        'until end of round'
    }
},

atlas = 'Jokers',
rarity = 2,
cost = 5,
unlocked = true,
discovered = true,

-- Compatibility flags
blueprint_compat = true,
eternal_compat = false,
perishable_compat = false,

-- Position on board
pos = { x = 2, y = 0 },

-- Main calculation function
calculate = function(self, card, context)
    -- 1. Reset debuff at the end of the round
    if context.end_of_round then
        card.debuff = false  -- removes the debuff after the round ends
    end

    -- 2. Only trigger Joker effect if:
    --    a) The Joker is in the main slot
    --    b) The Joker is NOT already debuffed
    --    c) A 'Pair' is in the played hand
    if context.joker_main 
       and not card.debuff 
       and context.poker_hands 
       and context.poker_hands['Pair'] then

        -- 3. Apply the +15 Mult
        local result = { mult = 15 }

        -- 4. Debuff this Joker for the rest of the round
        card.debuff = true

        -- 5. Return the effect to the game engine
        return result
    end
end

}
`

#

i tried looking inc ard.lua

#

but

#

it is a

#

jumbled mess.

#

that i cant read!

loud citrus
#

so when something is debuffed, calculation stops
so i think the order is what matters here
if context.joker_main and context.poker_hands['Pair'] and not card.debuff and context.poker_hands then

#

i could be wrong on how to fix it lol

cinder elk
#

i did try and look at the uhh

#

jolly joker

#

but

#

wHAT DOES ANY OF THIS EVEN MEAN

loud citrus
#

oh! use the link i provided and use a search in the joker.lua

#

should be much cleaner

#

card.lua is pure spaghetti code

storm kraken
#

im just too use to balatro coding bs

cinder elk
#

ok so it looks like

#

config = { extra = { t_mult = 8, type = 'Pair' }, },

#

seems like the thing that calls the pair

loud citrus
#

you had the right thing, you don't need to call to a config

#

just need next

cinder elk
#

config..?

loud citrus
#

oh, the jolly joker config.extra

#

context.poker_hands['Pair'] is correct

#

next(context.poker_hands['Pair']) is needed

cinder elk
#

like

#

this?

loud citrus
#

if context.joker_main and next(context.poker_hands['Pair']) and not card.debuff and context.poker_hands then

#

just like how you where trying to use context.poker_hands['Pair'], the difference is you're checking for the next played hand instead of the current (which doesn't change soon enough for the joker_main if it's not next)

cinder elk
#

forgive me. i am. kind of slow with this. so i put

umbral spire
cinder elk
#

sort of, yeah

umbral spire
cinder elk
#

like this joker or

umbral spire
#

yeah

#

for the joker

cinder elk
#

pair gives +15 mult and then debuffs joker. that's it

loud citrus
#

Bingo!

cinder elk
#

so if context.joker_main is like. the starting point for every joker right

loud citrus
#

the main scoring timing of jokers
so when square joker would give you it's chips

#

take a gander through here, should help with learning the contexts

cinder elk
#

got it

#

so for this next joker; i dont think there's a good like

#

baseline joker to compare it to

#

i want it toooo

#

gain mult when a playing card is destroyed

#

but also have a chance to destroy a playing card

umbral spire
#

like gain-gain or +X mult?

cinder elk
#

the joker itself gains mult.

umbral spire
#

Ah ok.

#

Shoot! I forgot the context for "when a playing card gets destroyed" 😭

cinder elk
#

i cant find any like

#

vanilla jokers to look at for reference

umbral spire
cinder elk
#

i have

#

way too many mods

#

any mods you can think of that might do that

loud citrus
umbral spire
#

however, to gain mult, you can reference Flash Card:

SMODS.Joker {
    key = "flash",
    blueprint_compat = true,
    perishable_compat = false,
    rarity = 2,
    cost = 5,
    pos = { x = 0, y = 15 },
    config = { extra = { mult_gain = 2, mult = 0 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult_gain, card.ability.extra.mult } }
    end,
    calculate = function(self, card, context)
        if context.reroll_shop and not context.blueprint then
            -- See note about SMODS Scaling Manipulation on the wiki
            card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
            return {
                message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } },
                colour = G.C.MULT,
            }
        end
        if context.joker_main then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
}
umbral spire
loud citrus
umbral spire
# umbral spire however, to gain mult, you can reference Flash Card: ``` SMODS.Joker { key =...

specifically if you wanted a joker to gain mult you would doconfig = { extra = { mult_gain = 2, mult = 0 } }, and then to gain some mult you'd do:

            card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
            return {
                message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } },
                colour = G.C.MULT,
            }

the return { ... } is uneccessary if you dont want a lil' message to appear.

loud citrus
#

if context.remove_playing_cards then

if you want any playing card removed

umbral spire
#

and always the way to give mult after the hand, or more simply "when it's the jokers turn" is:

        if context.joker_main then
            return {
                mult = MULT_TO_GIVE -- <-- change this to what mult you want to give
            }
        end
#

and you could do it in 1 line like: if context.joker_main then return { mult = 5 } end

cinder elk
umbral spire
cinder elk
#

comparing

#

ok so we got

#

context.card_destroyed

umbral spire
cinder elk
#

ohhh

#

OH SHIT U RITE

#

this should work then

umbral spire
#

if you dont want it to be blueprint compatible

#

add and (not context.blueprint) to that first if condition

#

also checking and card.ability.extra.mult > 0 is unnecessary

#

returning mult = 0, will do nothing for you on its own

cinder elk
#

so legit this.

#

that's it

umbral spire
#

no add the other if back, that is necessary, what was not necessary was the and card.ability.extra.mult > 0

#

just add it back and remove the and card.ability.extra.mult > 0 part

cinder elk
umbral spire
#

yes

#

good

#

also,

#

if you want a lil message indicator

#

replace
if context.remove_playing_cards then ........ end
with:

                G.E_MANAGER:add_event(Event({
                    func = function()
                        G.E_MANAGER:add_event(Event({
                            func = function()
                                -- See note about SMODS Scaling Manipulation on the wiki
                                card.ability.extra.mult = card.ability.extra.mult + 3
                                return true
                            end
                        }))
                        SMODS.calculate_effect(
                            {
                                message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult + 3 } }
                            }, card)
                        return true
                    end
                }))
                return nil, true
cinder elk
#

legit just like this

umbral spire
#

oh remove the tabs

#

here:

G.E_MANAGER:add_event(Event({
    func = function()
        G.E_MANAGER:add_event(Event({
            func = function()
                card.ability.extra.mult = card.ability.extra.mult + 3
                return true
            end
        }))
        SMODS.calculate_effect(
            {
                message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult + 3 } }
            }, card)
        return true
    end
}))
return nil, true -- This is for Joker retrigger purposes
umbral spire
#

make it look good atleast

umbral spire
cinder elk
#

easy enough

umbral spire
#

Anyways gtg, gl with your dev journey!

cinder elk
#

thanks much

#

i dont think it's supposed to do that

gilded blaze
#

put your event and SMODS.calculate_effect inside the context check

cinder elk
#

this part?

#

w

#

which part

loud citrus
#

Currently whenever anything happens, the game will run the code, you'll need context to prevent that, so put the part of your code under the context you want it to trigger

hallow slate
#

How do I get the localized name of a rarity?

daring fern
storm kraken
#

holy shit

#

where did you get all of this calculate code from

cinder elk
#

hell.

loud citrus
#

Honestly if you're just adding mult during scoring, rework all but the context.remove_playing_card

Put it under
context.joker_main

The code here isn't how we currently make jokers

cinder elk
#

yknow maybe i should just. redo the whole thing.

#

just t

#

just to be safe

storm kraken
#
if context.remove_playing_cards then
card.ability.extra.mult = card.ability.extra.mult + 3
end
if context.joker_main then
return {
mult_mod = card.ability.extra.mult,
message = [what you have there is fine but the mult has to have the 3 removed]
}
end
#

i typed this on mobile please dont kill me

#

also the 3 in + 3 should be a new card.ability entry

#

localisation or smtg

cinder elk
#

so like. this.

storm kraken
#

sobbing....

storm kraken
#

but remove the 3

cinder elk
storm kraken
#

you can also
message = '+'..card.ability.extra.mult, colour = G.C.RED

storm kraken
cinder elk
daring fern
storm kraken
cinder elk
#

😭

#

IT CANT BE THIS DIFFICULT

#

AM I JUST

#

DAFT

storm kraken
#

read up smods on github

#

you can find it by searching for repositoroes on github

cinder elk
#

read?

#

i dont think even reading would fix this

storm kraken
#

yes

storm kraken
cinder elk
#

HOW????????

#

WHERE

storm kraken
#

REMOVE THE RETURN IN REMOVE_PLAYING_CARDS

cinder elk
storm kraken
#

YES

#

I THINK

#

I THINK

cinder elk
#

lesseee

#

i think i fixed it

#

YEP

#

misplaced bracket.

#

what

storm kraken
cinder elk
#

i mean

storm kraken
#

youre blocking the message

cinder elk
#

the joker works. kind of.

#

it just pops up a uh

#

+3 mult

#

and then another message that says +3 mult

#

even after destroying the cards the mult didnt change

mystic river
#

yeah you don't need the message in your return table

storm kraken
#

wait uh

storm kraken
#

there

mystic river
#

smods handles basic scoring messages automatically now

storm kraken
#

by the returb

#

mult_mod =

cinder elk
#

mult_mod here correct

storm kraken
#

yuh

mystic river
#

(or you can do what fish is saying, sure. i don't recommend it unless you want the message to be something other than the basic "+X mult")

cinder elk
#

how would i make the message say something else. like text

storm kraken
storm kraken
mystic river
storm kraken
#

yuh this

mystic river
storm kraken
cinder elk
#

:agony: