#💻・modding-dev

1 messages · Page 113 of 1

quasi jewel
#

maybe i can just set renderscale to a fixed value

frosty dock
#

oops, I forgot to change something in there, should be G.TILESIZE instead of self.TILESIZE

quasi jewel
#

ohp

#

all good

frosty dock
#

upd

nocturne garnet
narrow pendant
#

I've got a hole in my code somewhere that's annoying me

#

anyone more experienced willing to take a look?

hearty mesa
#

i've tried to move the description of a joker or consumeable around and the values get updated but the UIBox stays in the same place.

Code:

SMODS.Keybind {
    key_pressed = "up",
    action = function(self)
        hover_popup, hovered_card = nil, nil
        for _, v in ipairs(G.jokers.cards) do
            if v.config.h_popup then
                hovered_card = v
                hover_popup = v.config.h_popup
                hovered_card.config.h_popup_config.offset.y = hovered_card.config.h_popup_config.offset.y + 1
            end
        end
        if not hovered_card then
            for _, v in ipairs(G.consumeables.cards) do
                if v.config.h_popup then
                    hovered_card = v
                    hover_popup = v.config.h_popup
                    hovered_card.config.h_popup_config.offset.y = hovered_card.config.h_popup_config.offset.y + 1
                end
            end
        end
        if hovered_card and hover_popup then sendInfoMessage(hovered_card.config.h_popup_config.offset.y) end
    end
}```
random sleet
#

its fun how simple that is

frosty dock
#

nice

#

deck skins are fun ngl

nocturne garnet
hearty mesa
crisp coral
#

where does Steamodded handle negative playing cards?

crisp coral
#

oh its fucking

#

commented

#

okay my implementation for enchanted cards is immensely flawed

surreal wolf
#

tried installing cryptid and talisman i keep getting this error

`Error

Syntax error: game.lua:4: '=' expected near 'Game'

Traceback

[love "callbacks.lua"]:228: in function 'handler'
[C]: at 0x7ffa8d2b2fa0
[C]: in function 'require'
main.lua:16: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'`

crisp coral
#

verify game files on steam

surreal wolf
#

it verified fine, it can run other mods, but not these two, and i tried the troubleshooting steps on the cryptid github, it didnt work

crisp coral
#

delete Balatro.exe and verify again

frosty dock
#

@wintry solar what do you think of this?

night pagoda
#

At which point steamodded's localization files are being copied to the global table?

#

I can't access them from process_loc_text for some reason, but really want to

wintry solar
frosty dock
#

not sure how that'd happen if levels have to be strictly decreasing

frosty dock
#

aka after language injection

night pagoda
frosty dock
#

oh sorry I thought you literally meant steamodded's own loc files

night pagoda
#

I have used other text entries from the same point in the dictionary, but after the game is loaded

#

and it worked fine

frosty dock
#

loc files from mods are used later

wintry solar
frosty dock
#

blinds support loc_vars, so you don't need this

night pagoda
#

I thought loc_vars was only for in-game?

#

as in: not collection?

frosty dock
#

collection_loc_vars exists

night pagoda
#

ohhh

#

awesome, thanks!

frosty dock
#

it would also allow having your retriggers be retriggered by standard retriggers, as in level -1

zealous glen
#

vscode are you drunk

frosty dock
#

it do that sometimes

wintry solar
frosty dock
#

inside a retrigger at level 2, further retriggers happen only if they're less than level 2, and retrigger checks don't retrigger

#

so one such joker might retrigger other effects of the other, but not the retriggering

#

same how retriggering a joker trying to retrigger at level 2, at level 1 wouldn't cause any additional retriggers

wintry solar
#

🤔

maiden river
#

how do you get the id from a joker (like the one used in an add_joker call)?
I've managed to get the name from a joker, which doesn't really help but is still useful

frosty dock
#
  • joker 1 retriggers all jokers once at level 2

  • joker 2 retriggers all jokers once at level 1

  • joker 3 retriggers all jokers once at level 0

  • joker 4 just exists

  • when joker 4 triggers, it gets one retrigger from all 3 other jokers at the respective level

  • joker 3's retrigger is level 0 and no retrigger checks have a lower level, so this causes no further retriggers

  • joker 2's retrigger is level 1, triggering joker 3's retrigger again because it's less in level, this is 2 more retriggers

  • joker 1's retrigger similarly retriggers both joker 2's and joker 3's retrigger, with joker 2 subsequently retriggering joker 3 once more. this is 4 more retriggers
    so joker 4 gets 7 retriggers in this case

maiden river
#

big

frosty dock
frosty dock
wintry solar
#

yeah that makes sense

#

I just need to unscuff what I currently have before thinking about implementing it 🤣

frosty dock
#

fair enough haha

#

i'd love to see what it's up to though, no updates to the branch in 2 days

nocturne garnet
maiden river
#

Jolly!

#

I've made three jokers now:
Flat Circle (left): gives a X2 mult if the hand played just after obtaining this card is played again
True Minima (middle): makes the card on the right of it negative and self destructs
Safeguard (right [art is a draft]): When blind is picked, stores the card on its right, destroys it, and at the end of the round (if it has room) returns it, but without any edition it had.

#

I'm probably gonna shoot for five of these total

primal robin
#

m

livid tapir
#

im coding the first joker of my mod, Joker Lottery
it destroys the joker to the left of it and creates a random joker of the same rarity

#

i would like to know how to destroy a joker
or if theres some documentation that shows things for destroying and creating stuff

nocturne garnet
#

Jolly time of the year

maiden river
#

whoops hit enter too early lmao

#

gimme a sec

maiden river
#

I have a bit of code I could share from one of my jokers

#
SMODS.Joker({
    key = "Safeguard",
    config = {
        extra = {
            Xmult = 2,
            card_name = "None"
        },
    },
    loc_txt = {
        name = "Safeguard",
        text = {
            "When Blind is picked,",
            "destroys the card on",
            "the right and", 
            "remakes it without its edition",
            "at the end of the round,",
            "or when it has space.",
            "(Currently stored: {C:attention}#1#{})"
            -- C:attention gives the text a yellow colour
            -- C:mult/C:chips colours the text to the colour of mult or chips
        },
    },
    rarity = 3,
    loc_vars = function(self, info_queue, center)
        return { vars = { center.ability.extra.card_name } }
    end,
    calculate = function(self, card, context)
        if context.setting_blind then
            local right_card = nil
            for i = 1, #G.jokers.cards do
                if G.jokers.cards[i] == card then
                    right_card = G.jokers.cards[i+1]
                    print(right_card)
                end
            end
            if right_card == nil then
                return false
            end
            if not G.GAME.SafeguardCard then
                G.GAME.SafeguardCard = right_card.config.center_key
                card.ability.extra.card_name = right_card.ability.name
                right_card:start_dissolve()
            end
        end
        if context.end_of_round then
            if #G.jokers.cards == 5 or not G.GAME.SafeguardCard then
                return false
            end
            add_joker(G.GAME.SafeguardCard)
            G.GAME.SafeguardCard = nil
            card:start_dissolve()
        end
    end,
    atlas = "Safeguard",
    pos = { x = 0, y = 0 },
})```
#

well hold on

livid tapir
#

oh thx, it also shows directional stuff, ill need that for my joker
thx for the help!

maiden river
#

no problem

#

I'm not too sure about the rarities though

livid tapir
#

ill figure it out

#

btw nice joker, cool concept and everything

maiden river
#

thanks

#

I actually don't really know when it would ever be useful tho lmao

livid tapir
#

honestly i could see smth
like if you have pareidolia and the boss blind is that one where it debuffs face cards

zealous glen
livid tapir
nocturne garnet
maiden river
maiden river
#

lemme test it

livid tapir
#

yea
based on when i lost a run bc i was using a pareidolia build and got that exact blind 💀

maiden river
#

ME TOO

#

man I was pissed lmao

livid tapir
#

me too

livid tapir
storm oar
#

how do i properly check if a card is unlocked/discovered?

livid tapir
maiden river
livid tapir
#

ah ok
so i dont need to worry about that for this joker

maiden river
#

technically, for the whole minima set it was supposed to be memory-based
so I'm going to take it out eventually
I just wanted the practice

#

I'm kinda stuck on thinking of two other mechanics, though

storm oar
#

what's the middle?

maiden river
#

it's a card that makes the joker on the right negative and then self-destructs

livid tapir
#

"you are negative now" explodes

maiden river
#

yeah pretty much

#

also that lock I drew is going to haunt me forever
this is why I don't do art 💀

livid tapir
#

meh i wouldnt be able to draw a good lock either

maiden river
#

but since all of the cards are supposed to be minimal i should probably change it anyway

zealous glen
#

maybe trace the base game's lock

maiden river
#

true

#

it looks like this now

tidal edge
maiden river
#

true

#

I'm just changing it to that temporarily

#

mainly so I can focus on other things

tidal edge
#

if you want i coul try braw one in the style you have

livid tapir
#

download icon fr

maiden river
livid tapir
#

ooh i can make my own poker hands too

#

thats fun

wintry solar
maiden river
#

I made a series of "wall" hands that were five enhanced cards
so stone -> stone wall
gold -> versailles gate
etc.

tidal edge
livid tapir
maiden river
#

goddammit

#

no

#

😭

livid tapir
#

LOL

tidal edge
#

just i wanna sese how it looks

maiden river
wintry solar
#

Hopefully it’s not scuffed 🤞

maiden river
#

ignore the green guy

livid tapir
#

i need to try and look at riff raffs code to figure out this rarity random thing

tidal edge
#

because the lock i provibeb was for 1x sprites

maiden river
#

ah

#

lemme redo it

tidal edge
#

gimmie a sec to ownsize it on the 1x

maiden river
#

well I put it on the 2x first

#

and then scaled the card down

#

yeah I made it better lmao

livid tapir
#

thats good

tidal edge
#

thx

maiden river
#

yup

hearty mesa
#

I might be going insane but I have no idea why this doesnt work

#

I tried replacing hover_popup:recalculate() with v.config.h_popup:recalculate() but it gave me the same error

livid tapir
#

i figured it out i think
basically its a different card creation function

maiden river
#

nice

#

coming from other languages to Lua
it's definitely
something

#

I don't think I'll ever get over ~=

livid tapir
# livid tapir
        if context.setting_blind then
            local left_card = nil
            for i = 1, #G.jokers.cards do
                left_card = G.jokers.cards[i-1]
            end
        end
        if left_card == nil then
            return false
        else
            left_card:start_dissolve()
            SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = left_card.rarity
            })
        end

    end```
i think this should work
#

now im wondering how i test it because like
how do i create that joker in game without having to go by luck

maiden river
#

so it actually looks for the joker on the left of this joker

livid tapir
#

thx

maiden river
#

in your loop it would always pick the next-to-last joker, I believe

maiden river
livid tapir
#

i should prob install it lol

maiden river
#

once you install it, you hover over a card in your joker collection and hit 3

livid tapir
#

thats cool

maiden river
#

yup

#

there are a bunch of useful tools

#

you can add/change enchancements, win blinds, up antes, etc.

livid tapir
maiden river
#

yeah

livid tapir
#

it exists

#

did nothing to greedy joker when i did my turn

#

sads

#

ok so i added some debugging and ig it just isnt recognising the greedy joker that is RIGHT THERE

shell condor
#

does anyone know where these functions are defined? cant find it anywhere in my decomp

#

i wanna do something similar to mail in rebate but i dont know how the game does it for that card and id rather retrofit that method while not relying on it outright than try and hack something shoddy together myself

livid tapir
# livid tapir did nothing to greedy joker when i did my turn

heres my joker code

SMODS.Joker {
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to left of this card,",
            "create a random joker of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 2,
    calculate = function(self, card, context)
        if context.setting_blind then
            local left_card = nil
            for i = 1, #G.jokers.cards do
                if G.jokers.cards[i] == card then
                    left_card = G.jokers.cards[i-1]
                end
            end
        end
        if left_card == nil then
            return false
        else
            left_card:start_dissolve()
            SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = left_card.rarity
            })
        end

    end
}
maiden river
livid tapir
maiden river
#

yeah

maiden river
#

change context.setting_blind to context.joker_main

livid tapir
#

ok

maiden river
#

it'll run after you play each hand

livid tapir
#

though it also didnt do anything when selecting a blind either

#

ok i changed it

#

and it still aint do anything 💀

#

i swear this is probably one of those painfully simple things that i never notice

spring lantern
#

sorry to interrupt but quick question, just started messing around with this - when calculating joker bonus after playing a hand, is there a way to get the amount of chips that the player has scored?

#

as in the blue number, no mult

faint yacht
#

hand_chips and mult are currently scored chips and mult respectively.

spring lantern
#

i was trying to do something along the lines of xmult but with chips

#

oh thanks

faint yacht
livid tapir
#

and why is left_card usually nil? ig thats whats happening

faint yacht
#

Each time you run the function, left_card doesn't exist until it is technically defined when you set it to the Joker.

wintry solar
#

You don’t actually do anything when you’ve identified a left card

livid tapir
livid tapir
#

so it needs to be in a context? its in joker_main context right? jeez this is confusing

faint yacht
#

Add config = { extra = { storedrarity = 0 } }, then store the card's rarity in card.ability.extra.storedrarity. When you recreate the card, call SMODS.create_card and pass the card.ability.extra.storedrarity to the rarity argument... then you can reset it to 0 or nil.

livid tapir
# faint yacht Add `config = { extra = { storedrarity = 0 } }`, then store the card's rarity in...
SMODS.Joker {
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to left of this card,",
            "create a random joker of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 2,
    config = { extra = { storedrarity = 0 } },
    calculate = function(self, card, context)
        local left_card = nil
        if context.joker_main then
            for i = 1, #G.jokers.cards do
                if G.jokers.cards[i] == card then
                    left_card = G.jokers.cards[i-1]
                    card.ability.extra.storedrarity = left_card.rarity
                end
            end
        end
        if left_card == nil then
            print("left card is nil")
            return false
        else
            left_card:start_dissolve()
            SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = card.ability.extra.storedrarity
            })
            card.ability.extra.storedrarity = 0
        end

    end
}```
soo.. is this what you mean?
faint yacht
#

Remove left_card entirely and replace checks of it against card.ability.extra.storedrarity.

merry raven
#
calculate = function(self, card, context, effect)
        if context.cardarea == G.hand then
            if card.facing == 'front' then
                card:flip()
            end
        end
 
        if context.cardarea == G.play and not context.repetition then
            effect.x_mult = 3
            if card.facing == 'back' then
                card:flip()
            end
            card_eval_status_text(card, 'extra', nil, nil, nil, {
                message = "Unblinded!",
                sound = "fm_blind",
                colour = G.C.MULT
            })
        end
    end

I'm trying to make my enhancement card drawn with face side down, but it still gets drawn face side up, anything I'm missing?

wintry solar
#

It should be in set ability iirc

merry raven
wintry solar
#

It’s a function you can define on an object

merry raven
#

I'll look into it, is there an example code or something on it?

wooden nexus
wintry solar
#

Should be in the wiki

wooden nexus
#

Been working on stuff

livid tapir
maiden river
#

does anyone know how to make a joker prevent death like our goat Mr. Bones?

wintry solar
#

There’s a context that you return true in

merry raven
wintry solar
#

It’s in Center

merry raven
#

Found it, cheers

livid tapir
# livid tapir imma wipe it clean and try to remake it to see if i make some breakthrough that ...
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to left of this card,",
            "create a random joker of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 2,
    config = { extra = { leftc = nil } },
    calculate = function(self, card, context)
        if context.joker_main then
            for i = 2, #G.joker.cards do
                if G.jokers.cards[i] == card then
                    card.ability.extra.leftc = G.jokers.cards[i-1]
                end
            end
        end
        if not card.ability.extra.leftc then
            return false
        else
            card.ability.extra.leftc:start_dissolve()
            SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = card.ability.extra.leftc.rarity
            })
        end
    end
}```
made this
basically just a worse version of the old code
crashes it when starting a run so lol
wooden nexus
#

so how the heck does smods.sound work?

SMODS.Sound({
key = "Goku",
path = "Goku.ogg",
})

#

yet it's saying it doesn't exist

merry raven
wooden nexus
#

oh okay

#

Didn't think it included sounds before too

#

tbf, first time playing with sounds

merry raven
#

Here's my implementation of playing a custom sound for an Enhancement:

--- PREFIX: fm
----------------------------------------------
------------MOD CODE -------------------------
...(before defining all the SMODS objects)
SMODS.Sound({ vol = 0.6, key = "amplified", path = "amplified.wav" })
... (inside an SMODS.Enhancement implementation)
card_eval_status_text(card, 'extra', nil, nil, nil, {
                message = "Amplified!",
                sound = "fm_amplified",
                colour = G.C.MULT
            })
...
livid tapir
#

i almost just fell asleep

merry raven
# wintry solar It’s in Center

I still don't really have much of an idea on how to use set_ability, and inside card.lua there's nothing related to flips inside it

set_ability = function(self, card, initial)
        if initial then
            card.facing = 'back'
        end
    end,
    calculate = function(self, card, context, effect)
        if context.cardarea == G.play and not context.repetition then
            effect.x_mult = 3
            if card.facing == 'back' then
                card:flip()
            end
            card_eval_status_text(card, 'extra', nil, nil, nil, {
                message = "Unblinded!",
                sound = "fm_blind",
                colour = G.C.MULT
            })
        end
    end
wintry solar
#

I don’t remember right now but try taking a look at blinds that flip cards

merry raven
# wintry solar I don’t remember right now but try taking a look at blinds that flip cards

I did, it's how I managed to find card:flip() in the first place, the problem is making the card stay face down when drawn

function Blind:disable()
    self.disabled = true
    for k, v in ipairs(G.jokers.cards) do
        if v.facing == 'back' then v:flip() end
    end
    if self.name == 'The Water' then 
        ease_discard(self.discards_sub)
    end
    if self.name == 'The Wheel' or self.name == 'The House' or self.name == 'The Mark' or self.name == 'The Fish' then 
        for i = 1, #G.hand.cards do
            if G.hand.cards[i].facing == 'back' then
                G.hand.cards[i]:flip()
            end
        end
        for k, v in pairs(G.playing_cards) do
            v.ability.wheel_flipped = nil
        end
    end
function Blind:stay_flipped(area, card)
    if not self.disabled then
        if area == G.hand then
            if self.name == 'The Wheel' and pseudorandom(pseudoseed('wheel')) < G.GAME.probabilities.normal/7 then
                return true
            end

These are what I could find

wooden nexus
#

Is there a context for when the card is created? Like either by card effect or appears in the shop/pack/etc

wintry solar
#

No

wintry solar
#

I don’t remember if there’s a way to flip cards other than from a blind so it might need some patches

merry raven
#

There's card:flip(), like I said, it can actually flip cards without blinds, just apparently not correctly when drawn from the deck

wintry solar
#

Yeah I think they’ll just flip back though

merry raven
#

Yeah my first ever iteration is that the card came out face up, but when played it flipped face down

spring lantern
#

just created a mod but it doesn't appear on the modlist, did i maybe mess up the metadata?

{
"id": "L6_luckyjimbo",
"name": "Lucky Jimbo",
"author": ["LuckySix"],
"description": "My first mod, so it sucks a bit.",
"prefix": "L6jimbo",
"main_file": "luckyjimbo.lua",
"priority": -20, // [default: 0] ! Mods are loaded in order from lowest to highest priority value.
"badge_colour": "C958D1",
"display_name": "Lucky",
"version": "0.1.0~PREALPHA1",
"dependencies": [
"Steamodded (>=1.0.0~ALPHA-1225a)"
],
}

merry raven
tepid crow
#

(json doesn't support comments)

wooden nexus
spring lantern
#

so what would be the most efficient way to test a specific card in game?

wooden nexus
#

The effect is not implemented btw

spring lantern
#

this looks kinda trash LOL

maiden river
#

made another joker

#

(far right)

#

it saves from death, but destroys all other jokers and makes itself polychrome

thorny adder
maiden river
#

I'm not sure what you're referring to

thorny adder
maiden river
#

ah I see

#

haven't actually played it yet

thorny adder
#

Dont play it

#

You wont escape

#

The only reason why my mod is taking so much time to code is that game

maiden river
merry raven
nocturne garnet
wooden nexus
spring lantern
#

datamoshed jimbo

maiden river
#

does anyone know how to change the ante?

#

*with a joker, not with the debug menu lol

crisp coral
#

ease_ante

maiden river
#

big

merry raven
#

Ayo sorry to bother, been looking through chat histories to see if anyone figured out how to draw cards from the deck face down
Did you manage to do it? If so, how did you do it? Been trying to do something similar for a while now, ping me when you're able

zealous glen
#

What do you want to do exactly?

merry raven
#

I'm making a custom enhancement, the card is drawn face-down, but if you somehow score it, you get a nice xmult

rough furnace
merry raven
zealous glen
merry raven
#

Aw

zealous glen
#

I have a similar effect where it was a Blind that causes some Suits to be drawn flipped

#

So maybe a hook would be sufficient to replicate it

merry raven
#

I am currently fiddling with card:flip(), but the card just won't get drawn face down in non-Boss-Blind situations

merry raven
zealous glen
#

Maybe it would need to be a patch

merry raven
#

I also have zero experience making patches

zealous glen
merry raven
#

That's a Blind function so I never really considered it to use with my Enhancement, is this where a hook/patch comes in?

#

Oh wait I didn't see "hooking"

bold sleet
#

help, how do I iterate and compare through all the cards in the deck (+ held in hand if possible)?

merry raven
#

Yeah I'm gonna be struggling figuring out how to hook

zealous glen
#

Although

#

Now that I think about it I remember also having a method to force cards to look face-down

merry raven
#

Do you have it? Can I shamelessly copy it

zealous glen
#

Do you want them to be drawn face-down outside of Blinds?

merry raven
zealous glen
#

Yes

merry raven
#

Yeah sure why not, adds to the challenge

bold sleet
#

For each card, for example, compare and test if it is for example, a sevel of any given suit.

#

I would be looking for an enhancement, but that is just an example.

#

-# wait, let me check steel joker for a sec...

#

actually, this will do

#

The good news: I think I found the piece of code that makes it work. The bad news: No idea how it works, exactly.

#

So uh... help?

#

mainly the for loop because I stupid af and never got around to understanding it

maiden river
zealous glen
merry raven
#

Does it work anywhere and not just SMODS.Blind?

zealous glen
#

I think the best solution would be to patch after, and then do something like stay_flipped = stay_flipped or is_jitJets_enhancement(card)

merry raven
#

What field will the stay_flipped line be in? pattern or payload?

#

And I assume target would be the Lua file where Blind:stay_flipped be? I'm not at my computer rn so I forgot

zealous glen
#

The patch would look something like this, although you either define the function inside the patch or just check directly for the enhancement. something like card.center.ability == jitJets_enhancement; I don't remember where in the center the identity is stored

[manifest]
version = "1.0.0"
dump_lua = true
priority = 0

# Flipping Enhancement
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card)"
position = "after"
payload = '''
stay_flipped = stay_flipped or is_jitJets_enhancement(card)
'''
match_indent = true
#

Oops I think I forgot to change the target

zealous glen
#

Also @merry raven that shows how to check for an Enhancement, I suppose

merry raven
#

Yeah there's only one enhancement that does it, its key is blinded

So I could something like card.center.ability == "m_fm_blinded"? Wouldn't it, idk, break since im basically calling an enhancement inside its definition?

zealous glen
#

card.config.center == G.P_CENTERS.m_MODKEY_blinded

merry raven
#

Ah gotcha

#

I'll see what I can do tomorrow, it's getting late
Thanks for taking the time to help!

zealous glen
#

If you have a function that computes even a simple comparison like this, it's easier to make effects like Smeared

#

Something like Rank Smeared doesn't work in vanilla because it'd need to be hardcoded

#

so it wouldn't be compatible with mods

merry raven
#

I see

wintry solar
#

Then inside that you’ll want to use SMODS.has_enhancement

rough furnace
maiden river
#

oh

#

interesting

spiral vector
#

Oops! Something went wrong:

game.lua:993[string "147226"]:4273: function arguments expected near '}'

#

i was changing the localization file

#

can anyone tell me what i need to do to avoid this error or what causes this

elder vapor
#

code?

nocturne garnet
#

why must i be so trash at making ui codeeee

rough furnace
#

it attempted to call a nil value

nocturne garnet
rough furnace
#

look at the lovely dump then

nocturne garnet
#

im so fuckin stupid

#

i misspelled the function 😭

wintry solar
#

better calc 2 still giving different numbers than retrigger api 🤔

supple folio
#

Is there a way to remove a consumable from its respective pool?

#

Like make it so that you can’t get Strength from packs and shops, for instance

rough furnace
#

you can take_owenership on it and then override it's in_pool function

#

although irrc strength is the default tarot to it might still show up if it can't get another tarot

supple folio
#

Yeah, that was just an example

#

Thank you!

spiral vector
#

but i think i accidentally deleted something and i cant find it

hearty mesa
#

Anyone have any idea why this doesnt work? It's supposed to move the currently hovered joker or consumeable's description up by 1 unit but it gives this error

#

I know that the error is caused by v.config.h_popup:recalculate() but i have tried many values and it doesnt work

maiden river
#

is there a context for if a joker is being sold, and a way to tell if it is this joker?

#

nvm I found it

#

context.selling_self

supple folio
#

what is the copier argument in the consumable.use function?

maiden river
#

all five jokers done!

#

the last one swaps the editions of the jokers on the left and right once it's sold

#

also does anyone know how to get the name of modded jokers?

#

e.x. "Flat Circle" instead of "j_mini_FlatCircle"

stiff locust
#
for index, value in ipairs(G.jokers.cards) do
  if value.name == "whatever you're searching for" then
     ---do stuff
  end
end

that should do it

#

i think

#

i have yet to solve this problem in the cashout screen where

#

if a joker has its name color changed

#

the color changing tag shows up on the cashout message

#

i was told this is due to "not localizing it"? but i don't really know what that means in this context

#

anyone know how to fix that

stiff locust
#

SMODS.find_card has done nothing but betray me

#

I cannot get it to return a coherent result ever

#

the one time I got it to print the output, the table was empty

#

fuck smods find_card

rough furnace
#

Are you using the name instead of the key?

stiff locust
#

i was using the key yes

rough furnace
#

Were the cards you looking for debuffed?

stiff locust
#

nope

#

i had one joker, it was the one i was searching for, and smods.find_card simply did not run

rough furnace
#

I've never had issues with it

stiff locust
#

it has never worked for me

#

not once

rough furnace
#

What key did you use?

stiff locust
#

j_fuseforce_powerpop

#

and I tried using it for splash in my mod

rough furnace
#

And you sue that your prefix is right?

stiff locust
rough furnace
#

¯_(ツ)_/¯

stiff locust
#

it didn't work for holy water in my mod either

rough furnace
stiff locust
#

i'm going to update steamodded and hope all the problems magically go away

#

if they don't, i'm suing

rough furnace
stiff locust
rough furnace
#

Not sure but that seems like a bug

#

Or maybe just a missing feature

stiff locust
#

well that's annoying

rough furnace
#

@edgy reef the payout api is your domain right?

edgy reef
#

I wouldn't say "payout API" since that got nuked but yeah I know how the ceashout screen works.

rough furnace
#

Oh well that shows how much I know

edgy reef
#

It takes the raw text of an object and applies it's own color.

stiff locust
#

is there a way i can make it not show the color tag

#

on cashout

edgy reef
#

Make a patch on this line (in common_events.lua) before highlighted text that check for config.card and config.card.config.center.key == 'j_joker_key', with the same code in the if check except type = 'name_text' is switched to type = 'name'.

#

I think everything else should be fine?

stiff locust
#

uhhh

#

you lost me at the type = name_text part

#

ohhhhhh wait

#

i think i get it hold on

edgy reef
#

oh wait this wouldn't work cause then localize return a DynaText

stiff locust
#

oh

#

so what do we do doc

edgy reef
#

ok scratch this, new idea

#

Have your joker name without color text localized in G.localization.misc.dictionary

edgy reef
stiff locust
#

how do i make multiple patches in one lovely.toml file

#

do I need to redo the manifest section or just everything below patches.pattern or what

stiff locust
#

okay

tepid crow
#

Just look at what other mods (or steamodded) do

stiff locust
#

i don't expect this to work first try

#

it panicked

#

and died

#

yeah i don't know how to make multiple patches

#

figured it out

#

it crashed

shell condor
#

how would one go about making a playing card enhancement that makes the card copy all the attributes of the card to the right? have been trying to retrofit how blueprint works but im missing a key step somewhere

stiff locust
#

you're just assigning the card to the right to a variable that doesn't do anything

normal crest
#

By attributes do you mean enhancements and seals?

shell condor
stiff locust
#

(also you should probably have a check for if the card is the rightmost, or it might crash if you try to reference i + 1 when it's the last index)

shell condor
normal crest
shell condor
#

i know it doesnt have actual copy code yet, but thats because i dont know how to copy aspects of a playing card

#

the internal structure of a playing card is not somehting im yet familiar with

shell condor
#

ive tried retrofitting this once already but it crashes because playing cards dont have a calculate function, so i'm just like... yeah, trying to figure out how to get what i need by the time its time to score

stiff locust
#

if you want the card to act as the rank of the card to its right you'll have to do some stuff when the card is highlighted i think

#

there's a cursed tarot in dx-tarots that makes wildcards copy the rank of the card to their right, look at that

stiff locust
# stiff locust
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif string.find(config.name, 'joker') then"
position = "before"
payload = """
        elseif config.card and config.card.config.center.key == "j_tsun_secret" then
            table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = localize{"k_nocolor_secret"}, colours = {G.C.FILTER}, shadow = true, pop_in = 0, scale = 0.6*scale, silent = true})}})
"""
match_indent = true

i think i followed the instructions right?

#

but it's crashing

#

so /shrug

normal crest
shell condor
#

im gonna try as we speak

edgy reef
stiff locust
#

it was curly brackets when i copy pasted it

edgy reef
#

Second, the crash above is from failing a version check not from this

shell condor
normal crest
#

How'd you write it

shell condor
normal crest
#

try returning that

shell condor
#

maybe call it like other_card:eval_card?

#

ohhh

#

OH TRUE

normal crest
#

actually nvm, it's an enhancement

stiff locust
#

well I did just update steamodded

#

like an hour ago

#

do I roll back version or what

shell condor
normal crest
#

Wait

shell condor
#

?

normal crest
#

Store the return value of eval_card and manually set the values on the effect table

shell condor
#

..... eyesshaking

normal crest
#

that's my idea anyway, good luck

supple folio
#

Can anyone explain to me what copier is in the Consumable.use function?

normal crest
#

copier seems to never be used in the game

supple folio
#

It's in mod code for consumables, but I'm not sure why. things like this:

#

I guess I won't worry too much about it

normal crest
#

it's used like that in the game as well, but the function is never called with a 2nd parameter

#

looks like some kind of blueprint for consumables

cinder elk
supple folio
#

There's documentation, yeah

#

on the wiki

normal crest
supple folio
#

^^

normal crest
#

And these are on the SMODS.Center page

normal crest
supple folio
#

ye

#

that's what I'll probably do

wintry solar
#

I think copier is some remnants of old thunk code

edgy reef
#

It's never used

shell condor
#

so i've encountered a new problem... self, card, context, and effect in this function are all fed in as nil.
somehow.

#

so i literally cant get anything done in this function, and i dont know why its suddenly all nil

shell condor
#

i know printing things out can be a bit weird in lua, but as far as i can tell i cant get any info out anywhere in here

rough furnace
#

lovely is broken when printing tables rn

#

@gaunt thistle is that fixed in source rn

shell condor
#

ohh, thats why. lovely

rough furnace
#

DebugPlus shows it properly

#

or you can wrap the table in tprint or inspect for more info

shell condor
#

yeah... how do i print things to debugplus instead of the lovely console

gaunt thistle
rough furnace
#

it intercepts the console

shell condor
#

i havent actually figured that one out

gaunt thistle
#

debugplus is the way to do it

stiff locust
#

yeah i was just gonna say there's a tprint function for printing tables
print(tprint(table))

rough furnace
stiff locust
#

in balatro

rough furnace
#

instead of nil

gaunt thistle
#

I merged a PR which uses lua's tostring() function instead of lual_tolstring, so that should improve functionality

rough furnace
#

but for dev I just use print

gaunt thistle
#

that'll be in 0.7.0

shell condor
rough furnace
#

(thats what DebugPlus does)

#

check your config

rough furnace
#

you might have only show commands checked

stiff locust
#

ctrl + / should bring up the funny debugplus console

rough furnace
#

(just /)

stiff locust
#

oh right ctrl + / is what changes it showing up when there's a new entry

#

right

shell condor
rough furnace
#

oh change the log level to info

shell condor
#

OH

#

OH ITS A

#

THRESHOLD

#

NOT A LIMIT

#

i am stupid.

rough furnace
#

well its you get all the ones to the right of your option as well

#

maybe I should flip the level so Debug is the right one and error is the left

shell condor
#

my GOD this makes life so much easier

#

okay now i have tprint

#

awesome

#

ty

rough furnace
#

I will probably make an option to format tables in the future when just printed

#

but I need to adjust my table printer first

gaunt thistle
#

I could also theoretically implement it in lovely but I really want to avoid any bloat

#

it's the sorta thing that should be vendored out to an actually good library like debugplus

rough furnace
#

Yeah plus you doing it won't effect DebugPlus logs whereas me doing it will effect lovely logs

supple folio
#

Is it possible to make soul-type cards that can replace jokers?

#

Just had a random thought

nocturne garnet
#

like black hole and soul?

#

but for jokers?

supple folio
#

yes

#

Like, there's a chance for a specific spectral to replace a joker in a pack or something

nocturne garnet
supple folio
#

Cool

nocturne garnet
#

and has been done before

#

:3

supple folio
#

I'll have to play around with it

#

Thank you!

wintry solar
#

Results are in for this calculation!

#

Retrigger API 68 seconds

#

Better Calc 2 42 seconds

#

🎉 🎉 🎉

shell condor
#

i feel like im so close to getting this working, but whenever it tries to play this card this error happens

#

its not pointing back to anywhere in my code in the stack trace

#

not obviously, at least

rough furnace
livid tapir
#

i like lua sorta but the way it prints errors is so unreadable and stupid 😭

hardy viper
rough furnace
#

To be fair the error handler is part of smods

rough furnace
hardy viper
#

but yeah with GC overhead excluded it's probably a much bigger improvement than it seems

rough furnace
#

Like I believe joker display causes more delay with the clacuating screen

livid tapir
hardy viper
#

marginal

wintry solar
#

I think updating the chip display should be turned off too

rough furnace
rough furnace
#

And I'm the guy with the knowledge to fix it

livid tapir
#

wait really

hardy viper
#

overhead of calculation screen is ~40% of total iirc

gaunt thistle
#

fight fight fight fight

rough furnace
#

Well it's based off the love default handler

hardy viper
rough furnace
#

And stacktraceplus

wintry solar
#

40% seems like a significant amount, is there no way to reduce that down whilst still having some sort of visual progress?

livid tapir
# rough furnace And I'm the guy with the knowledge to fix it

then wtf is going on here please help 💀
the joker is supposed to destroy joker to the left of it, and then create a random joker of the same rarity
but it does absulotely nothing

SMODS.Joker {
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to left of this card,",
            "create a random joker of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 2,
    config = { extra = { leftc = nil } },
    calculate = function(self, card, context)
        if context.joker_main then
            for i = 2, #G.joker.cards do
                if G.jokers.cards[i] == card then
                    card.ability.extra.leftc = G.jokers.cards[i-1]
                end
            end
        end
        if not card.ability.extra.leftc then
            return false
        else
            card.ability.extra.leftc:start_dissolve()
            SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = card.ability.extra.leftc.rarity
            })
        end
    end
}
``` im guessing its something with the for statement (`for i = 2, #G.joker.cards do`)
WAIT
I KNOW EXACTLY WHAT IT IS
i swear
i swear if its just that i forgot the s in jokers in the for statement
hardy viper
#

go yell at Mike Pall if you want the luajit garbage collector to be better

wintry solar
#

fair enough in that case

#

I guess the alternative without it is you just run out of memory

hardy viper
#

ya

#

you know what

rough furnace
#

Yeah probably the best optimization at this point is to make less garbage and calculate less stuff

hardy viper
#

now that i think about it you could probably build a very efficient garbage collector targeted towards scoring

livid tapir
hardy viper
wintry solar
#

I've calculated less stuff!

rough furnace
#

Wonder if we can reuse memory somehow

wintry solar
#

I shaved nearly 40% off that calc

rough furnace
#

Nice

#

I was thinking if it would somehow be possible to load the game in a thread headless then save the game, send the dabe to the thread, load it and then calculate in the background

#

Would allow a stable fps and could be used for like divvys preview as a backend too

gaunt thistle
#

eg. a game process whose sole job is to do calculations?

thorny adder
#

Happy new year from france 🎊

#

:)

honest fulcrum
#

I'm pretty new, how can I use lovely to create a flag for a joker? (i.e. winning a boss blind with it). This is what I have now, but the variable doesn't seem to exist

gaunt thistle
#

you should look into achieving that with smods before you go for lovely

honest fulcrum
#

how so? I've looked through documentation and I'm not sure how I would keep track of that. I guess I should've specified that I want to keep track of this flag after the joker is gone (like Gros Michel)

#

nvm I found an example, thanks.

maiden river
#

finally finished my modpack

#

all five jokers now work as intended 👍🏿

proper relic
#

How can I modify the amount of chips needed to beat a blind? I was trying to take info from Mr. Bones but it doesn't seem to recognize G.GAME.blind as an actual value.

G.GAME.blind.chips = math.floor(G.GAME.blind.chips * percent)
G.GAME.blind.blind.chip_text = number_format(G.GAME.blind.chips)```
hardy viper
honest fulcrum
proper relic
teal estuary
#

could that also be used to find out id you overshoot the blind score?

maiden river
proper relic
#

I would assume so, G.GAME.blind.chips is the amount you have to achieve and i think G.GAME.chips holds how many chips you currently have

teal estuary
#

ty ty

sturdy compass
#

Now this is just silly

#

Part of an effect of a Joker I made called "Refrigerator" that makes food jokers degade half as fast

radiant halo
sturdy compass
#

...maybe

radiant halo
#

nice

#

im in the same boat lmao

sturdy compass
#

A necessary evil

radiant halo
#

how did you prevent your mod name from showing up on the modified jokers tho?

sturdy compass
#

I didn't take ownership of the jokers, I injected my changes with Lovely patches

stiff locust
#

couldn't you just

#

search for the joker

and change its values manually if it's in the joker slots...

#

you don't need a lovely patch or anything

radiant halo
stiff locust
#

refrigerator could do it self contained

sturdy compass
#

If I do that then the description wouldn't show up properly in shops or collections or etc.

stiff locust
#

why would it show up halved in the collection that doesn't make sense

#

you can check the jokers that are in the shops and they have values set you can change

stiff locust
#

just check it again when you reroll

sturdy compass
#

Descriptions in collections do change during runs and I wanted to keep that consistent

#

Thus here we are

sturdy compass
radiant halo
#

i mean i literally started yesterday, im sure i can get there eventually

#

im also learning lua at the same time

stiff locust
#

example mod with joker stuffs in it

#

very useful tool

radiant halo
#

i am dw

stiff locust
#

good

#

they also have an edition example mod

sturdy compass
stiff locust
#

and one for seals

radiant halo
#

it doesnt have any examples for take_ownship though which im struggling with a bit

stiff locust
#

take_ownership is really simple

#

it has two arguments

#

the first one being the key of the thing you wanna take

#

like j_splash for splash as an example

#

the second one being a table

#

this table should contain everything you want to replace

#

this is pretty simple when changing things like the name which are just variables but

#

if you wanna change the calculate function for example, which is usually why you're using the function in the first place

#

you need to replace the entire calculate function

#

so first just copy paste the calculate function from the other joker, and then change what you want to change

radiant halo
#

yeah thats the main part thats tricky

stiff locust
#

i'm gonna take ownership on splash solely to put my mod badge on it

radiant halo
#

rn im trying to take_ownership of obelisk to make it trigger on most played hand instead, but for whatever reason it still executes the original code on top of my code

stiff locust
#

okay well first of all

#

jimball from cryptid already does that

#

second I do not support overwriting obelisk to make it "good" it's a joker for pivoting i think it should be changed to uncommon but not have its function changed

#

i'm not really sure why you'd do this with take_ownership when you can make a new joker?

radiant halo
#

ok specifically it keeps its normal functionality but changes to upgrade on most played hand if another joker is in the inventory

sturdy compass
#

I second this ngl

radiant halo
stiff locust
#

yeah the problem with obelisk is just that it's too rare

radiant halo
#

im not just changing it outright

stiff locust
#

do anything.

#

also

radiant halo
#

wym it doesnt do anything

#

i mean rn its breaking obelisk but its doing stuff

stiff locust
#

what does it do now

radiant halo
#

if monolith isnt in hand it works as normal but scales twice as fast, if monolith is in hand then it works the same but always says "reset" when most played hand is player, even is mult is at X1

stiff locust
#

wouldn't it be like

#

way easier to just

radiant halo
#

heres the vanilla code for reference

stiff locust
#

put one if statement that checks if monolith is there

#

and then write the full code the way it should act if monolith is there

and then put the vanilla code in the else

#

that sounds like it'd be much easier and would probably indirectly solve your problem

radiant halo
#

probably tbh, lemme try

#

trying this, still scales twice as fast

#

and monolith does nothing

#

im really stumped

#

i think it might be cause like, when it gets upgraded it doesn't actually return anything

#

unlike something like runner which gives an "upgraded" message

#

ok yeah when i put a retrun {} after the mult upgrade it scales correctly, but the joker does a little juice up with no msg and looks awkward

lyric urchin
#

Hi, how can I get a card to count as any suit?

radiant halo
#

under what contexts? like any card at any time?

hardy viper
wintry solar
#

oh man I can't wait for the death of card = card

hardy viper
#

so true

radiant halo
#

but it works

hardy viper
#

it just won't give a message

radiant halo
#

yeah but it still does the like, little juice up effect, just with no text

hardy viper
#

if you return nothing it won't do that

radiant halo
#

uhh

hardy viper
#

if you return a blank table (which is something) yeah it might juice itself

radiant halo
#

i mean it did with return {}

#

oh like nil?

hardy viper
#

{} is not a falsy value

proper relic
hardy viper
#
 return
end```
is valid code
radiant halo
#

i assumed that would bug out tbh

hardy viper
#

naw

#

it's treated the same as returning nil

#

even though nothing doesn't exist in lua

lyric urchin
#

But thank you anyway

radiant halo
hardy viper
#

essentially obelisk behavior is defined explicitly in the vanilla calculate_joker code, so taking over calculate doesn't erase the vanilla behavior

#

you can use a lovely patch to remove that behavior

radiant halo
#

i was fearing that was the answer..

hardy viper
#

i mean

#

it's not too scary

radiant halo
#

i believe it

hardy viper
#

i don't remember toml syntax for patches anyways

#

i rarely need them and i just copy other people's code and edit the necessary fields

proper relic
# lyric urchin More like the smeared joker

You'd have to edit the code for the Card:is_suit() function I'm pretty sure, since you're basically just making smeared again and that's where smeared works. I'm not entirely sure how to use lovely patches but if you can figure it out, adding this right above both smeared joker parts should work.

if next(find_joker('YourJokerName')) then
  return true
end
radiant halo
#

i know its like as easy as subtraction, but im still learning addition lmao

shell condor
#

potentially dumb question, how do i add a custom enhancement to an existing card via a consumable? for the life of me i cant find how tarot cards like empress and tower do it

rough furnace
hardy viper
#

that's for sure on the table as well

#

and yeah probably higher on our priorities

radiant halo
rough furnace
#

I imagine it will insanely speed up calculations too

hardy viper
#

there's a file path, a pattern (what you want to change), a place (whether you want to to be before, at, or after), and a payload

radiant halo
#

does cryptid use patches?

hardy viper
#

and all the other stuff is just filler basically

hardy viper
wintry solar
#

better calc only calulates repititons that actually do something now

radiant halo
#

i dont know existing mods well tbh

rough furnace
wintry solar
#

but you're going to have to do calculations to calculate retriggers anyway

radiant halo
#

ah it's its literally like, regex?

wintry solar
#

but I suppose you can just do the repetition contexts first and pass back the number

rough furnace
radiant halo
#

awesome ty

teal estuary
#

oh shit is the calc 2.0 almost done?

merry raven
#

Thank you so much for your help!!

#

Although people can peek in the deck, but it'll get harder when they get more Blinded cards

zealous glen
#

So I thought about an effect that makes the next card drawn face-down

#

Since you know which ones have the effect but you don't know what's next

merry raven
normal crest
#

Love the 2nd from the first image

zealous glen
#

Those are awesome

zealous glen
merry raven
#

Nah they're just plain cards

zealous glen
merry raven
#

Sure thing

merry raven
frosty dock
#

chat i just got done porting the currently most relevant balamod mod to steamodded (i saw 2 people use it in just one day)

cold grotto
#

when i was testing the steel joker code, for another joker i'm making, the smods version always seems to be one update behind, compared to the steel joker, am I potentially missing something to constantly update it?

restive magnet
#

question: i want my mod to do different things depending on what the ante is (music changes every 2 antes). i think i could make it work by shoving a bunch of G.GAME.round_resets.ante comparisons in the select_music_track return, but would it be possible to use if statements for each case?
right now im trying if (1 <= (G.GAME.round_resets.ante % 8)) and ((G.GAME.round_resets.ante % 8) <= 2) and its never true. it's also nested under a if (G.GAME) but i dont really know what G.GAME is

frosty dock
restive magnet
#

there are 7 of these smods.sound blocks per case

#

surely the problem isnt that i didnt save lol let me check

#

yeah its saved, doesnt work

crisp coral
#

it doesn't work because you're only creating the sound when you're ingame

#

and all those conds are false when the game launches

rough furnace
restive magnet
frosty dock
restive magnet
#

alright i figured that would work, its just messy

frosty dock
#

it's the way

#

else you're statically creating or not creating the data for the music when the game loads

restive magnet
frosty dock
#

line breaks:

rough furnace
#

tbh I would do (G.GAME.round_resets.ante * 2) % 2 == 0

#

(the first 2 is the number of antes it takes to change and the second is the number of songs to choose from)

#

then the other song has the == 1

restive magnet
#

thats smarter thanks

#

upon further thought wouldnt that always be = 0

frosty dock
#

yes

rough furnace
#

I may be stupid

radiant halo
#

did...did localthunk accidentally leave in the "chip" part for each of these function names?

rough furnace
#

no your score is your chips so your mult would be your chip multiplier

radiant halo
#

oh ok thank god

sturdy compass
rough furnace
#

People be like "I'm not really good at art" and then don't see my art

merry raven
#

Lmaooo alright yeah I can draw abstract patterns and shapes but not faces and tangible objects

rough furnace
teal estuary
#

peak

merry raven
#

Absolutely peam

random sleet
merry raven
#

One more but I don't know how to shade ice

restive magnet
# restive magnet question: i want my mod to do different things depending on what the ante is (mu...

I got this working and now the next thing i want to do is make it so music stops playing when you beat the boss blind where the music is going to change. i think i can use SMODS.Sound:create_stop_sound for this (or if not i can use a silent sound file) but i dont know what game condition to check for (the same one where the payout screen pops up). is there a list of game conditions somewhere? or a way to poll for them with debugplus?

restive magnet
#

new question: is there a way to do intro + loop music like how binding of isaac does it (intro plays once and then a separate sound file plays afterwards on loop)

#

brute forcing it with a long audio file is lame and makes for a large download

hardy viper
#

what's stopping you from playing the intro once and then playing the rest on loop

sturdy compass
#

Here's a fun one i just finished

hardy viper
#

fun fact you can do this naturally, within a very very small window

hardy viper
restive magnet
#

theres no flag for when an audio file finishes or anything

#

i could play an intro as a sound effect instead of music but then theres no way to make the looping part come after it, they would play at the same time

hardy viper
#

okay so let's say the intro music lasts 10 seconds
you wait 10 seconds after playing it
then play the other thing

restive magnet
#

all the music is handled within smods.sound, so i dont think thats possible

#

the issue is how do i play two audio files sequentually using smods.sound

hardy viper
#

i mean if you confine yourself to only what you can put inside an SMODS.Sound call then you can't do it yeah

#

but of course there's other things you can do

#

everything is entirely open to tinkering

restive magnet
#

im relying on it because it checks what to play every frame and i otherwise dont know how to really do anything that doesnt just run once when the game starts lol

hardy viper
#

well i wouldn't be able to help with this specific thing (especially because i can't get to my computer)

weak depot
#

do y'all know why this isn't working? it's just straight up not activating

#
deck.trigger_effect = function(self, args)
    if args.context == 'using_consumeable' and args.context.consumeable.ability.set == 'Planet' then
        G.E_MANAGER:add_event(Event({
            trigger = "before",
            delay = 0.2,
            func = (function()
                --this is all jenlib stuff
                local low_hand = jl.lowhand()

                jl.th(low_hand)
                level_up_hand(self, low_hand, nil)
                jl.ch()
                sendInfoMessage("Upgraded lowest level hand", "Shellular's Deck of Cards")
                return true
            end)
        }))
    end
end
#

for reference, the deck is trying to level up your lowest level hand when you use a planet card

livid tapir
#

im switching between versions of the joker and tweaking things, rn im tweaking my first attempt at making it

hardy viper
livid tapir
hardy viper
#

use the first one

livid tapir
#

ok

#

ok i made an update
lets see if it works

#

ok it worked in some way
but now uh
theres a lot of jokers
they arent taking up a slot

#

ig its just infinitely creating jokers now

#

heres the code

local left_card = nil

SMODS.Joker {
  key = 'jolot',
  loc_txt = {
    name = 'Joker Lottery',
    text = {
      "Destroy joker to",
      "left of this card,",
      "create a random joker",
      "of the same rarity"
    }
  },
  rarity = 3,
  atlas = 'atlas',
  pos = {x = 0, y = 0},
  cost = 2,
  calculate = function(self, card, context)
    if context.setting_blind then
      for i = #G.jokers.cards, 1, -1 do
        if G.jokers.cards[i] == card then
          local left_index = i - 1
          if left_index > 0 and G.jokers.cards[left_index] then
            left_card = G.jokers.cards[left_index]
            break
          end
        end
      end
    end

    if left_card ~= nil then
      left_card:start_dissolve()
      SMODS.create_card({
        set = 'Joker',
        area = G.jokers,
        rarity = left_card.rarity
      })
      left_card = nil
    end

    return true
  end
}
hardy viper
livid tapir
#

isnt that what area does?

hardy viper
#

so G.jokers:emplace(card)

hardy viper
livid tapir
#

hm

#

weird

#

but how do i identify the SMODS.create_card thing that i did in emplace

hardy viper
#

it returns the card it created

livid tapir
#

so i cut that function (SMODS.create_card) into the emplace function?

hardy viper
#

you can do that or you can assign the card you create to a variable

#

they are functionally equivalent

#

outside of technical things

livid tapir
#

so this would work

hardy viper
#

yes

#

most people wouldn't do it like that though

#

mostly because you also need to call card:add_to_deck()

livid tapir
hardy viper
#

potentially

livid tapir
#

'for' limit must be a number
lemme check

hardy viper
#

improper return in your calculation function

livid tapir
#

thats confusing

#

oh return true

#

thats bads

hardy viper
#

show full code

#

ideally

livid tapir
#

ok

--- STEAMODDED HEADER
--- MOD_NAME: H1DRO Mod
--- MOD_ID: H1DROmod
--- MOD_AUTHOR: [H1DRO]
--- MOD_DESCRIPTION: Interesting, or extremely dumb stuff..

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

SMODS.Atlas {
    key = "atlas",
    path = "atlas.png",
    px = 71,
    py = 95
}
local left_card = nil

SMODS.Joker {
  key = 'jolot',
  loc_txt = {
    name = 'Joker Lottery',
    text = {
      "Destroy joker to",
      "left of this card,",
      "create a random joker",
      "of the same rarity"
    }
  },
  rarity = 3,
  atlas = 'atlas',
  pos = {x = 0, y = 0},
  cost = 2,
  calculate = function(self, card, context)
    if context.setting_blind then
      for i = #G.jokers.cards, 1, -1 do
        if G.jokers.cards[i] == card then
          local left_index = i - 1
          if left_index > 0 and G.jokers.cards[left_index] then
            left_card = G.jokers.cards[left_index]
            break
          end
        end
      end
    end

    if left_card ~= nil then
      left_card:start_dissolve()
      left_card = nil
      G.jokers:emplace(SMODS.create_card({
        set = 'Joker',
        area = G.jokers,
        rarity = left_card.rarity
      }))
    end

    return true
  end
}

----------------------------------------------
------------MOD CODE END----------------------
``` its not much else
hardy viper
#

ya

#

you're right do not return true

livid tapir
#

ok ty

#

lemme try it now

#

ok now it does nothing

#

pluh

#

prob me using the stupidest way of emplacing

livid tapir
#

for the emplacing

#

wait

#

has to have local

hardy viper
#

yea

livid tapir
#

now is that good

hardy viper
#

call new_card:add_to_deck() after emplacing

#

other than that yeah it's good

livid tapir
#

ok

hardy viper
#

contrary to what the name says it has nothing to do with putting a card in your deck

livid tapir
#

ok cool

#

so this

hardy viper
#

yup

livid tapir
#

ok imma test it

#

does nothing
lemme show the full updated code

--- STEAMODDED HEADER
--- MOD_NAME: H1DRO Mod
--- MOD_ID: H1DROmod
--- MOD_AUTHOR: [H1DRO]
--- MOD_DESCRIPTION: Interesting, or extremely dumb stuff..

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

SMODS.Atlas {
    key = "atlas",
    path = "atlas.png",
    px = 71,
    py = 95
}
local left_card = nil

SMODS.Joker {
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to",
            "left of this card,",
            "create a random joker",
            "of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 2,
    calculate = function(self, card, context)
        if context.setting_blind then
            for i = #G.jokers.cards, 1, -1 do
                if G.jokers.cards[i] == card then
                    local left_index = i - 1
                    if left_index > 0 and G.jokers.cards[left_index] then
                        left_card = G.jokers.cards[left_index]
                    end
                end
            end
        end

        if left_card ~= nil then
            left_card:start_dissolve()
            left_card = nil
            local new_card = SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = left_card.rarity
            })
            G.jokers:emplace(new_card)
            new_card:add_to_deck()
        end
    end
}

----------------------------------------------
------------MOD CODE END----------------------
hardy viper
#

it's just not doing anything?

livid tapir
#

yea it aint crashing, just isnt doing anything (seemingly, dont have any debug things)
i have a mad joker to the left of the joker lottery and when i play a hand, mad joker just does its thing and nothing else happens

hardy viper
#

you're checking for context.setting_blind

#

so yeah it won't do anything when you play a hand

livid tapir
#

OH WAIT
I FROGOT TO CHANGE THAT AFTER GOING BACK TO OLD CODE

hardy viper
#

and when you set a blind it'll crash saying "attempt to index a nil value" because you undefine left_card and immediately try to index it

livid tapir
#

so it needs to be joker_main right

livid tapir
#

i gotta fix that lemme uh

#

there we go, moved left_card = nil to right after the create_card

#

now lemme test

#

IT WORKED
but it did a weird thing (im not very sure what)
this is the result

hardy viper
#

it'll get garbage collected

livid tapir
#

oh yea
i could ngl

hardy viper
#

oh wait nvm why are you defining that as a global

#

define it as a local that's in scope during the whole function

livid tapir
#

though i could just do local right there

hardy viper
#

oh i see

livid tapir
#

in the function

hardy viper
#

yeah that's traditionally better

livid tapir
#

like this

hardy viper
#

naw that's not in scope

livid tapir
#

oh yea it aint

hardy viper
#

also you can do local varname as a shorthand for local varname = nil

livid tapir
#

so should i do local left_card as first line for the calculate function or just put it outside like i did before

hardy viper
#

first one

livid tapir
#

ok

#

IT WORKED IT WORKED IT WORKED LETS GOOO

#

that normal joker got me a Cloud 9

#

tysm for the help

hardy viper
#

nice

livid tapir
#

i couldnt have done it without you

merry raven
#

Is there a way I can overlay a sprite on top of a card (including the swiveling movement when you move your cursor on top of a card)? This is entirely separate from an Edition, Seal or Enhancement

livid tapir
#

though it was uncommon instead of common but im sure i can figure out that little issue

obsidian fjord
#

Is there a way I can disable all vanilla jokers from showing up in the shop and only load my mod's jokers?

random sleet
merry raven
livid tapir
#

ok nope

#

did an uncommon and got common

wintry solar
wintry solar
#

That’s the one but you’ll want to look at the lovely dumps instead

random sleet
#

i noticed theres a spectrum mod now so i made my mod support it

merry raven
wintry solar
#

Huh, I was sure there were changes

random sleet
#

if a file is dumped then there is a change

#

it doesnt dump unchanged files

merry raven
#

Ah I see

random sleet
merry raven
#

It seems like they are used to add existing seals, editions and stickers
But I do want to add a layer without clashing with them, if my layer is considered a seal in the backend then the card with the layer can't take in any other seals

wintry solar
#

What exactly are you trying to achieve?

crisp coral
#

sounds like a new card modifier type

merry raven
#

It's a custom Boss Blind mechanic, a new modifier type that only appears in them

merry raven
wintry solar
#

Then yeah, you don’t want to use seals

merry raven
#

What should I go for, somehow create a brand new card modifier type, or use some other modifier as a foundation besides seals?

crisp coral
#

former

merry raven
#

I see

#

Oh boy where do I start, closest thing I can find rn is SMODS.ObjectType

wintry solar
#

You could always use stickers

#

The calc is a bit jank right now though
-# better calc 2 pls

merry raven
#

I haven't played Balatro that religiously yet, do hand cards support stickers
I know Jokers do

spring lantern
livid tapir
#

yall know how to get a card's rarity?

spiral stirrup
#

I would assume Baseball Card's code would have that in there somewhere

wintry solar
spiral stirrup
livid tapir
spring lantern
#

quick question where can i find all the values that context provides

merry raven
# wintry solar They do but like I said, the calc is a little jank

I actually don't plan to do calculations on it, it sort of acts like a flag on the card and that's it
For my idea of a Boss Blind, it will mark random cards for destruction, and this sticker will be the mark, the card will be destroyed after 2 played hands unless there's a mechanic you have to do

livid tapir
# livid tapir hm

lemme share code

--- STEAMODDED HEADER
--- MOD_NAME: H1DRO Mod
--- MOD_ID: H1DROmod
--- MOD_AUTHOR: [H1DRO]
--- MOD_DESCRIPTION: Interesting, or extremely dumb stuff..

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

SMODS.Atlas {
    key = "atlas",
    path = "atlas.png",
    px = 71,
    py = 95
}

SMODS.Joker {
    key = 'jolot',
    loc_txt = {
        name = 'Joker Lottery',
        text = {
            "Destroy joker to",
            "left of this card,",
            "create a random joker",
            "of the same rarity"
        }
    },
    rarity = 3,
    atlas = 'atlas',
    pos = {x = 0, y = 0},
    cost = 4,
    calculate = function(self, card, context)
        local left_card
        if context.joker_main then
            for i = #G.jokers.cards, 1, -1 do
                if G.jokers.cards[i] == card then
                    local left_index = i - 1
                    if left_index > 0 and G.jokers.cards[left_index] then
                       left_card = G.jokers.cards[left_index]
                    end
                end
            end
        end

        if left_card ~= nil then
            left_card:start_dissolve()
            local card_data = {}
            local new_card = SMODS.create_card({
                set = 'Joker',
                area = G.jokers,
                rarity = context.left_card.config.center.rarity
            })
            G.jokers:emplace(new_card)
            new_card:add_to_deck()
        end
    end
}

----------------------------------------------
------------MOD CODE END----------------------
obsidian fjord
obsidian fjord
random sleet
#

and keep in mind that any jokers you currently possess are removed from the pool

spring lantern
#

i'm trying to get the chip count for the current hand so a joker can apply a multiplier to it but i don't know how to access it

obsidian fjord
#

Oh this is a deck modifier so hopefully none of the vanilla jokers should even be possessed

livid tapir
random sleet
#

if it tries to show you a rare joker but you have none, you get jimbo. same with uncommon and common as separate things.

wintry solar
#

You have to modify the pool function too

#

It’s certainly possible though

random sleet
#

theoretically you can just take_ownership every vanilla joker and add a yes_pool_flag that you never set

random sleet
spring lantern
#

oh thanks lmao

#

didn't know it was a global var i thought it came packaged with context

random sleet
#

yep lol

spring lantern
#

makes sense now that i think of it

storm oar
#

how can I make a joker that would make 6s specifically always score? id assume maybe i could look at splash but just modify the code to only work with 6s right?

livid tapir
#

so i think joker lottery is FINALLY done

#

im so proud seeing my idea come to life in balatro (peak game)
even if its a quite simple one

merry raven
#

Ayyyy that's sick

obsidian fjord
#

Oh my issue was I was also accidentally disabling my own jokers without realising it. Awesome. Lmfao

livid tapir
#

ill send the current mod (only one joker so far, will add more) tomorrow, for now i gtg to bed
happy new years yall!

spring lantern
#

happy new year!

merry raven
#

Happy new year!

#
calculate = function(self, card, context, effect)
        if context.cardarea == G.play and not context.repetition then
            local has_adjacent_slow = false
            for i, playedCard in ipairs(context.scoring_hand) do
                if playedCard == card then
                    if (i > 1 and context.scoring_hand[i-1].config.center == G.P_CENTERS.m_fm_slow) or
                       (i < #context.scoring_hand and context.scoring_hand[i+1].config.center == G.P_CENTERS.m_fm_slow) then
                        has_adjacent_slow = true
                        break
                    end
                end
            end
 
            if has_adjacent_slow then
                card.ability.extra.frozen = true
                card_eval_status_text(card, 'extra', nil, nil, nil, {
                    message = "Frozen!",
                    sound = "fm_freeze",
                    colour = G.C.BLUE
                })
            else
                if math.random() < 1 then
                    G.hand:emplace(card)
                    card_eval_status_text(card, 'extra', nil, nil, nil, {
                        message = "Slowed!",
                        sound = "fm_slow",
                        colour = G.C.BLUE
                    })
                end
            end
        end
    end

I'm making an Enhancement that has a chance of returning to your hand when played (chance set to 1 just for debugging), it actually does return, but it comes back into the hand flipped, and unselectable, any insights?

storm oar
#

i think its just like card.facing or something like that

#

but its cause it flips