#💻・modding-dev

1 messages · Page 95 of 1

civic pebble
#

So would it be possible to add this somehow into my mod?

strong plume
#

Easy quick question: What is the max handsize equivalent for what ease_hands_played does with + hands? I tried looking around but haven't gotten much luck finding documentation for the functions

EDIT: figured it out

sour aspen
#

Pardon me if this is already easily available, but I am making a test deck for my mod and want it to start me with the jokers I have modded in. I can't figure out how to do that. Can someone point me in the right direction?

strong plume
sour aspen
#

Ah, fantastic. In the case that I wanted to make a playable deck with a starting joker though, how would I go about doing that?

civic pebble
#

Nevermind, figured this out

languid mirage
#

if you want to search for definition of the function you have to search "function add_joker"

teal estuary
#

this might be a stupid question but if you do get_suit(“Suit”) and get_suit(“Suit2”) for all 4 suits, is that a way to check for wild cards?

faint yacht
#

card.ability.name == 'Wild Card'?

teal estuary
#

that’d also work

#

thank you

wooden nexus
#

Oh what the heck

#

I'm just using test colors for now and it looks like i spilled milk in a bucket of paint

teal estuary
#

it looks so weird, i kinda like it

tidal edge
teal estuary
#

literally

wooden nexus
#

They're honestly all green, all blue, and all White for the colors

#

This is how it actually looks rn

faint yacht
# wooden nexus Oh what the heck

Actually makes me think of cyanotyping for some reason.

The cyanotype (from Ancient Greek: κυάνεος, kyáneos 'dark blue' and τύπος, týpos 'mark, impression, type') is a slow-reacting, photographic printing formulation sensitive to a limited near ultraviolet and blue light spectrum, the range 300 nm to 400 nm known as UVA radiation. It produces a monochrome, blue coloured print on a range of supports,...

tidal edge
#

to match the bg of the tags

wintry swallow
#

Can I make a deck start with a joker? G.jokers doesn't exist yet so I'm not sure what the area would be

wooden nexus
#

lemme try the lighter color

tidal edge
#

like the white and gray on the tags

mellow sable
#

peak

tidal edge
#

wasnt this also in jen's?

wooden nexus
#

this has more plans than just "Gain a tag" in the future

tidal edge
#

this isnt a critisism just an observation

wooden nexus
#

The gain a tag part is for another deck w/ Ditpyrc

#

This is just being made for that

mellow sable
#

These will act more like CCD tags

wooden nexus
tidal edge
wooden nexus
tidal edge
#

👍

wooden nexus
#

It's a bunch of stuff that people can use if they wish as a dependency

#

want the link to the current version?

tidal edge
#

imo atleast

mellow sable
#

oh yeah I should probably do that

tidal edge
#

surprisedd only fudge is there

mellow sable
#

There’s one in the CSL that does Xmult too

#

but it is a nice unexplored area

tidal edge
#

btw is the CSL dormant or smth?

#

i dont know if its just me or

#

i havent seen any suggestions move statuses in ages, i thought a screening run was yesterday or last week.

mellow sable
#

progress has been slow but we are aware of the backlog and working on it

#

it’s been hard the last few days to get everyone for a screening run

tidal edge
#

by the way... no hard feelings?

mellow sable
wooden nexus
tidal edge
#

if im reading this right

wooden nexus
#

pretty much

#

Images atm are just Proof of concept art

tidal edge
#

seems way easier

wooden nexus
#

The problem is to implement it

tidal edge
#

i cant believe that at some point there was another balatro modding thing people ACTUALLY used over smods sometimes

#

considering how big smods is now

zealous glen
wooden nexus
teal estuary
#

very nice

tidal edge
wooden nexus
#

Wanted something different

wooden nexus
teal estuary
#

np

cerulean rose
#

still can't figure this out

wooden nexus
#

Crap

#

I forgot i need to make a tag for tag packs

#

and then a tag card for the tag for tag packs

faint yacht
#

That's a self recursion--

wooden nexus
karmic kelp
#

how do I create a specific consumable from code? I know the name and key of what I want to create, just not how

cerulean rose
#

SMODS.create_card({ key = "c_???" })

karmic kelp
#

will that toss it into the consumables area for me too?

cerulean rose
#

no, use emplace to do that

#

G.consumables:emplace(card)

karmic kelp
#

thank you

teal estuary
#

took this code from source and changed it a smidge to not be random, and its throwing an error?

    if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
      print("we got the cuzz (context huzz)")
        G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
        G.E_MANAGER:add_event(Event({
          trigger = 'before',
          delay = 0.0,
          func = (function()
            local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, 'hal')
            card:add_to_deck()
            G.consumeables:emplace(card)
            G.GAME.consumeable_buffer = 0
          return true
        end)}))
      card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE})
      end
    end
  end
end
}

i can show the first part of the error, but discord is deciding to be a pain in the ass and not allow me to send it as a file

#

nvm, can just make my own .txt file

cerulean rose
#

try changing the self in card_eval_status_text to card

teal estuary
#

that'd.. do it 😭

#

didnt even notice that self

#

HUZZAH!

#

ty

cerulean rose
tepid sky
#

I'd say, get the amount of 7 in hand and use that as retrigger amount?

cerulean rose
#

yes, i've got that done

#

but i want the 7 to animate when the 4 is retriggered

tepid sky
#

Animate how?

wintry solar
#

show your code

cerulean rose
#
calculate = function(self, card, context)
    if context.repetition and context.cardarea == G.play and context.other_card.base.id == 4 then
        local repetitions = 0
        for k, v in ipairs(G.hand.cards) do
            if v.base.id == 7 then
                card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_again_ex") })
                v:juice_up(0.3, 0.5)
                eval_card(context.other_card)
            end
        end
    end
end
wintry solar
#

and what isn't working?

cerulean rose
#

the four doesn't retrigger

wintry solar
#

you don't return anything

cerulean rose
#

i need to retrigger the 4 manually in order to animate the 7

wintry solar
#

you need to tell the game to retrigger the 4

#

the v:juice_up() will make the 7 jiggle

cerulean rose
#
calculate = function(self, card, context)
    if context.repetition and context.cardarea == G.play and context.other_card.base.id == 4 then
        local repetitions = 0
        for k, v in ipairs(G.hand.cards) do
            if v.base.id == 7 then
                G.E_MANAGER:add_event(Event({
                    trigger = 'after',
                    delay = 0.4,
                    func = function()
                        v:juice_up(0.3, 0.5)
                        repetitions = repetitions + 1
                        return true
                    end
                }))
            end
        end
        return { message = localize("k_again_ex"), repetitions = repetitions, card = card }
    end
end

this just doesn't work at all

#

for some reason the 4 doesn't retrigger

teal estuary
#

repetitions = card.ability.extra.repetitions

cerulean rose
#

no, repetitions is a local within calculate

teal estuary
#

hrm, didnt know you could do that

cerulean rose
#

actually, this almost works

calculate = function(self, card, context)
    if context.repetition and context.cardarea == G.play and context.other_card.base.id == 4 then
        local repetitions = 0
        for k, v in ipairs(G.hand.cards) do
            if v.base.id == 7 then
                repetitions = repetitions + 1
                G.E_MANAGER:add_event(Event({
                    trigger = 'after',
                    delay = 0.4,
                    func = function()
                        v:juice_up(0.3, 0.5)
                        return true
                    end
                }))
            end
        end
        return { message = localize("k_again_ex"), repetitions = repetitions, card = card }
    end
end

last time repetitions was being updated too late
but i still have the problem that the 7s animate at the wrong time

wintry solar
weak depot
#

do y'all know what i'm doing wrong here? it crashes on the set:edition() line. i'm a little confused ```lua
SMODS.Back {
name = "Chroma Deck",
key = "b_chr",
atlas = 'chrdeckatl',
pos = { x = 0, y = 0 },
loc_txt = {
name = "Chroma Deck",
text = {
"5 cards in deck have",
"a random {C:attention}edition{}",
},
},
config = {},
unlocked = true,
discovered = true,
apply = function(self)
local editions_added = 0
G.E_MANAGER:add_event(Event({

        func = function()
            while editions_added < 5 do
                local card_procced = pseudorandom_element(G.playing_cards, pseudoseed(self.key))
                if not card_procced.edition then
                    editions_added = editions_added + 1
                    local edition_chosen = pseudorandom_element({'polychrome', 'foil', 'holo'}, pseudoseed(self.key))
                    card_procced:set_edition(edition_chosen, true, true)
                end
            end
            return true
        end
    }))
end

}```

weak depot
#

OH

#

lemme try :>

wintry solar
#

you can also use poll_edition for your edition generation

#

it'll respect weights and allow for other modded editions

weak depot
#

oh, you can?? nice :>

#

out of curiosity, is there similar functions for tags or enhancements?

wintry solar
#

yes

#

enhancements uses SMODS.poll_enhancement

#

tags are a little different in that you'd have to do the random selection yourself but you can use get_current_pool('Tag') to get a table of valid tags

weak depot
#

okay! how would one use it?

#

the edition one, here

wintry solar
#

poll_edition(self.key, nil, true, true)

slow bloom
#

what function handles the visual effects/sounds when a card/joker is counted?

wintry solar
#

assuming you don't want negative

weak depot
wintry solar
#

the nil is a modifier if the 4th option is not true

weak depot
#

what would control the negative?

wintry solar
#

the third argument is for not negative, so setting it to true stops negative from being generated, as nil it would allow negatives

weak depot
#

okay, so if it was poll_edition(self.key, nil, false, true) negatives would be included then

#

got it :>

wintry solar
#

the 4th option is whetehr the edition is guaranteed or not, they ahve a base 4% chance of spawning, so setting this as true sets it to 100%, or altering the second argument to say 2, would increase it to 8%

weak depot
#

thank you so much for the help i very much appreciate it :>

wintry solar
#

the enhancement one works in a similar way but takes a table as the argument instead

weak depot
#

as in, you would put in a list of banned enhancements instead of true?

wintry solar
#

it'll just roll between all enhancements or a list you pass it

#

it doesn't support banning enhancements

#

perhaps it should

weak depot
#

yeah

#

i guess you could bandaid fix go "if [unwanted enhancement,] then reroll enhancement"

#

thank you for the help!!!!!!!!!

weak depot
#

my bad, oopsie

wintry solar
#

seal is like enhancement

weak depot
#

okay!

#

worked like a charm for my custom tarot too, thanks

weak depot
#

wait, so how would the prior code work if it was an enhancement instead of an edition? because currently it's throwing an error

    apply = function(self)
        local enhancements_added = 0
        G.E_MANAGER:add_event(Event({

            func = function()
                while enhancements_added < 10 do
                    local card_procced = pseudorandom_element(G.playing_cards, pseudoseed(self.key))
                    if not card_procced.abliity then
                        enhancements_added = enhancements_added + 1
                        local enhancement_chosen = SMODS.poll_enhancement(self.key, nil, nil, true)
                        card_procced:set_ability(enhancement_chosen, nil, true)
                    end
                end
                return true
            end
        }))
    end```
wintry solar
#

so an enhancement would be like this SMODS.poll_enhancement({key = self.key, guaranteed = true})

weak depot
#

OH it's just all a list in a sense

#

got it

weak depot
# wintry solar so an enhancement would be like this `SMODS.poll_enhancement({key = self.key, gu...

like this? because it's still not really working, it doesn't throw an error but it freezes and crashes```lua
apply = function(self)
local enhancements_added = 0
G.E_MANAGER:add_event(Event({

        func = function()
            while enhancements_added < 10 do
                local card_procced = pseudorandom_element(G.playing_cards, pseudoseed(self.key))
                if not card_procced.ability then
                    enhancements_added = enhancements_added + 1
                    local enhancement_chosen = SMODS.poll_enhancement({key = self.key, guaranteed = true})
                    card_procced:set_ability(enhancement_chosen, nil, true)
                end
            end
            return true
        end
    }))
end

}

wintry solar
#

needs to be card_procced:set_ability(G.P_CENTERS[enhancement_chosen], nil, true)

weak depot
#

oopsie! thanks

#

still doesn't work, oddly

#

just freezes and crashes

wintry solar
#

huh

#

oh

#

card.procced.ability will always be true

#

its just stuck in an infinite loop of not doing anything

weak depot
#

oops, okay

#

how would i detect if a card is enhanced?

wintry solar
#

if card.ability.set ~= 'Enhanced' then

weak depot
#

ah! sorry, i'm a beginner, thanks again :>

clever abyss
#

where can i start learning how to make custom boss blinds? never made a mod so everything is new

mystic river
orchid thunder
#

Is it possible to allow a pach to pach inside a pach that has already been patched

hardy viper
#

3 chances to spell patch correctly

wintry swallow
#

Well 4

#

one worked

#

Like Wheel

hardy viper
orchid thunder
#

Oops

#

I missed the t 3/4 times

#

But still question still stands

sour aspen
#

This feels like a tremendously stupid question but I just can not get the hang of the data structures: where do I find the scoring cards during joker evaluation?

clever abyss
#

i'm still lost with that guide, i just dont know where to start

orchid thunder
clever abyss
orchid thunder
#

Minecraft

#

It's a huge WIP rc

clever abyss
#

any example boss blinds>

#

?

orchid thunder
#
SMODS.Blind{
    key = "creeper",
    loc_txt = {
         name = 'The Creeper',
         text = { "Ends run if not",
            "beaten in #1#"},
     },
    name = "The Creeper",
    dollars = 5,
    mult = 2,
    boss= {min = 3, max = 10},
    boss_colour = HEX("297711"),
    atlas = "mc_blinds",
    pos = { x = 0, y = 0},
    vars = {"0:20"},
    config = {},
    set_blind = function(self)
        G.GAME.blind.config.creepertiming = 20
    end,
    loc_vars = function(self, info_queue, card)
        if G.GAME.blind.config.creepertiming == nil then
            return {vars = {"0:20.00"}}
        end
        local m = math.floor(G.GAME.blind.config.creepertiming / 60)
        local s = (G.GAME.blind.config.creepertiming - (60 * m))
        local d = math.floor(100 * (s - math.floor(s)))
        s = tostring(math.floor(s))
        if string.len(s) == 1 then
            s = "0" .. s
        end
        d = tostring(d)
        if string.len(d) == 1 then
            d = "0" .. d
        end
        m = tostring(m)
        return {vars = {m .. ":" .. s .. "." .. d}}
    end,
}

SMODS.Blind{
    key = "wither",
    loc_txt = {
         name = 'Midnight Wither',
         text = { "All cards scored gain",
            "Wither sticker"},
     },
    dollars = 5,
    mult = 3,
    boss= {showdown = true, min = 10, max = 10}, 
    boss_colour = HEX("1a1a1a"),
    atlas = "mc_blinds",
    pos = { x = 0, y = 1},
    vars = {},
    config = {},
}

clever abyss
#

one example of a boss blind i wanted to do just to learn to do one was for example all spade cards are drawn face down

orchid thunder
hallow forge
#

cruel blinds

#

yeah

clever abyss
#

ah ok

orchid thunder
#

There entire thing is blinds

clever abyss
#

im just trying to find one to start a base off of to learn how to do

hallow forge
#

well it has stakes and deck too

clever abyss
#

boss blinds and challenge packs is what i really wanted to focus on

hallow forge
#

cruel blinds is literally that

clever abyss
#

word

#

gonna look at that rq

#

also noticing a lot of the blind mods are undiscovered i was trying to figure out how to change that

sour aspen
#

How might I save variables in between calculate calls? Like how many times a particular rank has scored in the blind?

clever abyss
hallow forge
#

(they copied code)

orchid thunder
#

In bonus blinds

clever abyss
#

i'm very impressed with mathguy's work trust me

#

been enjoying grim nonstop

orchid thunder
#

Now as a shameless plug you should go vote for Minecraft to be the next cross content mod

clever abyss
#

why not

#

is debuffing all odd numbered cards already a code

orchid thunder
#

Yes

sour aspen
orchid thunder
#

Cryptid does It I think

hallow forge
orchid thunder
#

Well kinds

#

Kinda

clever abyss
#

well for now i just wanna learn how to code that atleast

#

from a base

orchid thunder
#

Cryptid has a blind that debuffs every other rank and randomly picks between odd and even

hardy viper
#

for card in hand do if v:get_id()%2 ~= 0 then v:set_debuff(true) end end

#

etc etc

#

that wouldnt be hard to not make pseudocode but i cant be bothered

clever abyss
#

LOL i dont know what any of that means

hardy viper
sour aspen
sour aspen
#

I mean, there would also be the rest of the Blind definition

#

But that is how it would debuff all the odd cards

clever abyss
#

ts is so confusing but im willing to learn

sour aspen
#

Are you at all familiar with Lua in the first place?

clever abyss
#

nope

hardy viper
sour aspen
#

If not, I recommend doing a little bit of online learning about it

#

Go do a tutorial or smth. Really helps, trust me.

hardy viper
#
local place = G.hand --G.play for played cards, G.hand for cards in hand
for i, v in pairs(place.cards) do
 if v:get_id() % 2 ~= 0 and v:get_id() <= 10 and v:get_id() > 0 then
  v:set_debuff(true)
 end
end
clever abyss
#

not familiar with lua at all, just wanted to make custom mods

hardy viper
#

would that debuff stones

#

idr if their id becomes 0

sour aspen
#

I can go spin up my debug game if you want me to find out lol

orchid thunder
hardy viper
#

what the actual fuck???

sour aspen
clever abyss
#

but thats it

sour aspen
#

I

hardy viper
#

ohh i get it

hardy viper
#

it needs to be an actual number so the game can function but it cant be the same number because the stone cards would then be able to form 4oaks and whatnot

#

and other things

#

so its just some random negative number

#

😭

sour aspen
#

I came into this knowing Lua from my days screwing around with ComputerCraft

clever abyss
#

so its actually not that hard

sour aspen
sour aspen
clever abyss
#

that you recommend or anything

sour aspen
#

This was like 10 years ago. I think I used Codeacademy but iirc most of what used to be free there is locked behind paywalls now.

hardy viper
#

checking the code it seems possible

sour aspen
#

Yeah, that's why I would have reserved an id and just checked against it in hand eval

#

unless that behavior is intended. i dunno

clever abyss
#

okay, ill go look at a youtube guide or somehting

hardy viper
#

ah wait nevermind

#

theres a very roundabout way of ensuring that this only works on positive ids

#

missed it

sour aspen
#

Interesting

mellow sable
clever abyss
#

man, even starting lua is confusing to me. ill come back once i learned a bit tho, and thanks

sour aspen
mellow sable
#

cryptid 2 when

lament fjord
cerulean rose
nocturne garnet
sweet nimbus
#

One of my installed mods is causing the game to close if streamlabs tries to capture the window, any ideas as to why?

The mod replaces some texture files and has a edited en-us.lua for custom joker names etc

sweet nimbus
hybrid iris
#

wh a t

hybrid iris
#

oh that was

#

actually an easy fix

#

missed a single and

kindred saddle
#

Having a rough time debugging this code rn

#

Idk what causes the issue but here is the init code:

SMODS.Joker{
  key = "5_coren",
  loc_txt = {
    name = 'Corens Potluck',
    text = "Test"
  },
  config = {
    extra = {
      Xmult = 2,
      chips = 150,
      food_check = false
    }
  },
  loc_vars = function(self, info_queue, card)
    return { vars = { card.ability.extra.Xmult, card.ability.extra.chips } }
  end,
  rarity = 1,
  atlas = '5_coren',
  pos = { x = 0, y = 0 },
  cost = 4,
  calculate = function(self, context)
    if SMODS.end_calculate_context(context) then
        -- Check if food item is true
        if self.ability.extra.food_check then
          return {
            -- Return bonus message and apply bonus
            chip_mod = self.ability.extra.chips,
            Xmult_mod = self.ability.extra.Xmult,
            message =  "Food!",
            card = self
          }
        end
    end
  end
}
#

Any pointers in the right direction would be very appreciated

hardy viper
#

*log

crisp coral
#

end_calculate_context is a 0.9.8 thing

kindred saddle
#

Ah shoot

#

That's what I get for using example code

crisp coral
#

do context.joker_main

kindred saddle
#

if SMODS.context.joker_main(context) then

As such?

hardy viper
#
struct rightDirection {
 int *ptr = NULL
}```
forgot everything i know about C because i never made anything functional but this is functional code right ![egg](https://cdn.discordapp.com/emojis/1185774071150018580.webp?size=128 "egg")
kindred saddle
#

Thank you

#

Honestly, first time I've touched the code side of this game so this is prolly why I am totally lost lmfao

#

Especially since Steamodded's documentation is awfully confusing atm due to it being in an alpha limbo for the next version

kindred saddle
# crisp coral do context.joker_main

Apologies for the ping but could you please give some additional context? Which is to say, what exactly do I need to do here with the calculation context?

crisp coral
#

a

#

replace the entire thing with that

kindred saddle
#

if SMODS.context.joker_main then Like so?

crisp coral
#

if context.joker_main

kindred saddle
#

Ahhh

#

That makes more sense

hardy viper
crisp coral
#

also the parameters to calculate is missing card

#

yeah ^

kindred saddle
hardy viper
#

self refers to the center (used to generate that card), card refers to the actual card object

kindred saddle
#

Do I need to use the card parameter

hardy viper
#

yup

crisp coral
#

okay ill let cg help you because phone is ass

kindred saddle
#
    if context.joker_main then
        -- Check if food item is true
        if self.ability.extra.food_check then
          return {
            -- Return bonus message and apply bonus
            chip_mod = self.ability.extra.chips,
            Xmult_mod = self.ability.extra.Xmult,
            message =  "Food!",
            card = card
          }
        end
    end```
#

Like so then

hardy viper
crisp coral
#

god fucking damnit

hardy viper
kindred saddle
#

I appreciate all the help either way lolol

crisp coral
#

card.ability

#

not self.ability

hardy viper
#

ah yes

kindred saddle
#

Ahhh thanks

hardy viper
#

yeah not self

kindred saddle
#

Good catch

crisp coral
#

wuh

gaunt thistle
#

wuh

kindred saddle
#

Dying lol

#

Uhhh

crisp coral
#

oh

hardy viper
crisp coral
#

loc_txt

#

god i am. bad at typing

kindred saddle
#

Is it not a table?

hardy viper
#

it's not in that code

kindred saddle
#

Damn I thought the curly braces was how you'd define that--

hardy viper
#

it is

#

you did not type them

crisp coral
#

text = {"test"}

hardy viper
#

ya

kindred saddle
#

BRUH

#

LOL

#

I AM DUMB

hardy viper
#

it's okay dw 😭

kindred saddle
#

Programmer's dilemma

crisp coral
#

😭

#

so true

kindred saddle
#

Debug an entire system

#

Broke it due to a single period

#

OH MY GOD IT BOOTED

#

YAY

hardy viper
#

🔥

kindred saddle
#

Thank you both so much

hardy viper
#

np!

kindred saddle
#

Before I go to finish this out on my own

#

I have some logic for checking for certain cards

#

I have remove and add to deckref

#

Does it work any differently now on the newer version of steamodded?

crisp coral
#

no different

kindred saddle
#

Cool

#
  function Card:add_to_deck(from_debuff)
    if not self.added_to_deck then

      if self.ability.name == "Gros Michel" or self.ability.name == "Ice Cream"
      or self.ability.name == "Cavendish" or self.ability.name == "Turtle Bean"
      or self.ability.name == "Diet Cola" or self.ability.name == "Popcorn"
      or self.ability.name == "Ramen"  or self.ability.name == "Seltzer" then
        -- Check for Coren Joker
        for _, v in pairs(G.jokers.cards) do
            if v.ability.name == "5 Coren" then
                -- Update Coren Joker variables
                v.ability.extra.food_check = true;
                end
            end
          end

        if self.ability.name == "5 Coren" then
          -- Check for food jokers
          for _, v in pairs(G.jokers.cards) do
            if v.ability.name == "Gros Michel" or v.ability.name == "Ice Cream"
            or v.ability.name == "Cavendish" or v.ability.name == "Turtle Bean"
            or v.ability.name == "Diet Cola" or v.ability.name == "Popcorn"
            or v.ability.name == "Ramen"  or v.ability.name == "Seltzer" then
                  self.ability.extra.food_check = true
              end
            end
          end

    end
      add_to_deckref(self, from_debuff)
  end```
#

Awful code but

#

This is how I wrote it

crisp coral
#

. yeah that is Not Good

kindred saddle
#

Figures as much lmfao

crisp coral
#

ideally you would want to check for key instead of name

hardy viper
#

iirc cryptid has an implementation of this function that you can copy

kindred saddle
#

Ye I was gonna change this

hardy viper
#

slash study

kindred saddle
#

I'd love to read it

crisp coral
#

and for the coren check you can use SMODS.find_card(key) which returns a table of cards with that key

hardy viper
kindred saddle
#

Thank you!

hardy viper
#

so nvm

kindred saddle
#

Yeah I checked

#

In fact they do the same awfulness I'm doing

#
    if
        self.ability.name ~= "cry-happyhouse"
        and self.ability.name ~= "Acrobat"
        and self.ability.name ~= "cry-sapling"
        and self.ability.name ~= "cry-mstack"
        and self.ability.name ~= "cry-notebook"
        and self.ability.name ~= "Invisible Joker"
        and self.ability.name ~= "cry-Old Invisible Joker"```
hardy viper
#

in typical cryptid fashion

#

🔥

#

check how Cryptid.food is populated

#

i can't myself without poring through the code on mobile

kindred saddle
#

Ahh I see what I can do

#

Define a table of included names, check against table

hardy viper
#

ah it's just

local jokers = {
    "j_gros_michel",
    "j_egg",
    "j_ice_cream",
    "j_cavendish",
    "j_turtle_bean",
    "j_diet_cola",
    "j_popcorn",
    "j_ramen",
    "j_selzer",
}
if Cryptid.enabled["Misc. Jokers"] then
    jokers[#jokers + 1] = "j_cry_pickle"
    jokers[#jokers + 1] = "j_cry_chili_pepper"
end
if Cryptid.enabled["Epic Jokers"] then
    jokers[#jokers + 1] = "j_cry_oldcandy"
    jokers[#jokers + 1] = "j_cry_caramel"
end
if Cryptid.enabled["M Jokers"] then
    jokers[#jokers + 1] = "j_cry_foodm"
end
if Cryptid.enabled["Spooky"] then
    jokers[#jokers + 1] = "j_cry_cotton_candy"
    jokers[#jokers + 1] = "j_cry_wrapped"
    jokers[#jokers + 1] = "j_cry_candy_cane"
    jokers[#jokers + 1] = "j_cry_candy_buttons"
    jokers[#jokers + 1] = "j_cry_jawbreaker"
    jokers[#jokers + 1] = "j_cry_mellowcreme"
    jokers[#jokers + 1] = "j_cry_brittle"
end
for i = 1, #jokers do
    Cryptid.food[#Cryptid.food+1] = jokers[i]
end
#

minor text wall mb

#

true

crisp coral
#

guh

kindred saddle
#

So I can prolly do sm like

local jokers = {
  "j_gros_michel",
  "j_egg",
  "j_ice_cream",
  "j_cavendish",
  "j_turtle_bean",
  "j_diet_cola",
  "j_popcorn",
  "j_ramen",
  "j_selzer",
}
local add_to_deckref = Card.add_to_deck
  function Card:add_to_deck(from_debuff)
    if not self.added_to_deck then

      if self.key == jokers[self.key] then


#

I didn't know Lua could do this so easily since this is my first direct exposure to it. I'm used to every other language

hardy viper
#

so trying to index with the key will always be nil

kindred saddle
#

Ahh

#

I need a dict

hardy viper
#

yeah instead do something like ```lua
local jokers = {
j_gros_michel = true,
--...
}

#

i love lua for this

#

table ....

#

tables...

kindred saddle
#

I knew Gmod used LUA but I was too young to understand code lmfao

#

So again, first time exposure for me

hardy viper
#

my lua experience came from roblox exploiting mostly

kindred saddle
#

Oh that's hilarious

hardy viper
#

i was so into that shit when i was 13

#

my ass was on every shitty simulator game trying to break em

#

but it was fun

#

side note nobody on roblox knows what they're doing ive seen some absolutely abysmal practices

kindred saddle
#

Oh you're younger than me by quite a bit... I was into Roblox more back when they still had things like Tickets

#

So...

hardy viper
#

haha yeah

#

i wasn't around before FE

kindred saddle
#

I loved logging on everyday to get more free tickets and I have some stuff from back in the day that you can't even get anymore as a result

#

Apparently there's demand for the 2009 summer hat on the market so that's funny

hardy viper
#

i was still learning to walk

gaunt thistle
#

the little lua I knew was from configuring neovim

#

I know lua pretty well now but I also know little, if nothing at all

kindred saddle
#
local jokers = {
  j_gros_michel = true,
  j_egg = true,
  j_ice_cream = true,
  j_cavendish = true,
  j_turtle_bean = true,
  j_diet_cola = true,
  j_popcorn = true,
  j_ramen = true,
  j_selzer = true,
}

local add_to_deckref = Card.add_to_deck
  function Card:add_to_deck(from_debuff)
    if not self.added_to_deck then
      if jokers[self.key] then
        -- Check for Coren Joker
        for _, v in pairs(G.jokers.cards) do
            if v.key == "5_coren" then
                -- Update Coren Joker variables
                v.extra.food_check = true;
                end
            end
          end

        if self.key == "5_coren" then
          -- Check for food jokers
          for _, v in pairs(G.jokers.cards) do
            if jokers[v.key] then
                  self.ability.extra.food_check = true
              end
            end
          end

    end
      add_to_deckref(self, from_debuff)
  end
-- Function for when Jokers are removed
local remove_from_deckref = Card.remove_from_deck
  function Card:remove_from_deck(from_debuff)
    if self.added_to_deck then
      if self.key == "5_coren" then
        -- Reset Coren value
        if self.ability.extra.food_check then
          self.ability.extra.food_check = false
        end
    end
    if jokers[self.key] then
        -- Check for Coren
        for _, v in pairs(G.jokers.cards) do
          if v.key == "5_coren" then
            -- Check if any food is still present
            for _, b in pairs(G.jokers.cards) do
              if jokers[self.key] then
                b.ability.extra.food_check = true;
              else
                b.ability.extra.food_check = false;
              end
          end
        end
      end
    end

  end

remove_from_deckref(self, from_debuff)
end```
#

Sorry for wall

#

But I rewrote it

#

Whoops noticed a mistake

#

Fixed it tho

vivid glade
#

when using steamodded, how do i replace a default sound with my new one?

#

like music1

frosty dock
kindred saddle
#

Hmmm

#

So now I have reached the phase of debugging

#

Seems like the joker card check doesn't return true

#

if jokers[self.key] then

#

With a dict of local jokers = { j_gros_michel = true, j_egg = true, j_ice_cream = true, j_cavendish = true, j_turtle_bean = true, j_diet_cola = true, j_popcorn = true, j_ramen = true, j_selzer = true, }

#
  function Card:add_to_deck(from_debuff)
    if not self.added_to_deck then
      sendDebugMessage("Joker Added", "MyDebugLogger")
      if jokers[self.key] then
        sendDebugMessage("Found food", "MyDebugLogger")
        -- Check for Coren Joker
        for _, v in pairs(G.jokers.cards) do
            if v.key == "5_coren" then
              sendDebugMessage("Found Coren", "MyDebugLogger")
                -- Update Coren Joker variables
                v.extra.food_check = true;
                end
            end
          end```
#

For fuller context

vivid glade
#

here's the code

frosty dock
#

as in, it longer plays the track at all? or does it just keep playing music1

vivid glade
#

no longer plays the track at all

#

no music1, no neut1

#

here's the file structure, but i just did as steamodded said to do

frosty dock
#

hm

#

i don't think i ever really tested support for wav files, i just assumed it would be supported. Not so sure now, nothing else seems to be wrong

vivid glade
#

then ill try converting them to ogg using ffmpeg in a bit and update

#

will update if it works or not since steamodded 1.0 is still beta iirc

crisp coral
vivid glade
#

will try in a second!

vivid glade
#

without converting files

#

to be fair, steamodded does not document what "key" does 😭

#

i dont know WHY it worked but it worked

crisp coral
#

because bgm needs to have "music" in the key

languid mirage
#

it's something thunk did iirc

vivid glade
#

is there anything for custom sounds?

#

like anything i need to add like music_?

crisp coral
#

nope

frosty dock
#

oh lmao i forgot about that, sorry

#

it's even in the docs i sent but i didn't spot it 😭

languid mirage
#

only music and ambient need that

vivid glade
frosty dock
#

and that's with those being my docs 💀

teal estuary
#

if you wanted to make a joker only activate when another joker is there, can you do something like card.ability.name = "Jimbo" to check if its there?

frosty dock
vivid glade
frosty dock
#
if next(SMODS.find_card('j_joker')) then ... end
frosty dock
vivid glade
#

dude 😭

teal estuary
vivid glade
#

please add examples to the functions, itll make them so much better

teal estuary
#

oh thank god 😭

frosty dock
vivid glade
frosty dock
#

oh lmao sorry i didn't realize that's what you were doing

crisp coral
#

lmao??????

teal estuary
frosty dock
#

there's really no need for that

#

just use or/and

teal estuary
frosty dock
#

do you know how lua works 😭

#
if next(SMODS.find_card('j_joker1')) or next(SMODS.find_card('j_joker2')) or next(SMODS.find_card('j_joker3')) then ... end
#

something like 'j_joker1' or 'j_joker2' or 'j_joker3' as the argument would just evaluate to the first string

teal estuary
#

im not good with instructions 😭 but that is exactly what i was asking, thank you

vivid glade
#

is there a way to make my blind always trigger (for testing it)?

#

im trying to make a boss blind

frosty dock
#

iirc with debugplus you can press (ctrl+)3 on the blind in the collection while on the select screen

vivid glade
#

thanks!!!

#

also thanks for telling me debugplus was a thing lol

tepid sky
#

same, its usefull to know, ty!

vivid glade
#

btw how do i add a debuff?
the docs show this but it is not clear at all

tepid sky
#

they'll may be of help

#

or look at other mods

vivid glade
#

i cant really find any other boss blind mods that use this

#

not in steamodded example mods, not on awesome-balatro...

kindred saddle
#

I ask merely to make sure that I don’t need to perform a loop

shell timber
#

next is a function that takes a table and (ignoring unnecessary detail) returns a truthy value if the table has a value, else returns nil

#

SMODS.find_card just searches through your entire joker lineup

kindred saddle
shell timber
#

basically it returns the next value and index given an index into a table

kindred saddle
#

Like I thought it would be used for that

molten ice
#

iirc its technically supposed to be an iterator that gets the next index, it's just lua treats any value as true, and nil as false so it can be used for a check like this
SMODS.find_card returns a table of all joker with the specified ID, it can have more than one if you have more than a single copy of the joker (eg. from showman, invisible etc)

kindred saddle
molten ice
#

oop i'm too slow

shell timber
#

yeah just the next(SMODS.find_card("whatever"))

kindred saddle
#

Sweet

#

Thanks

#

I know you weren’t helping me but this was actually related to what I was doing

#

I did it the old terrible way (attributes)

#

That being said, how would I retrieve the key from the self argument for when a joker card is added or removed

#

In other words, a function like
local add_to_deckref

frosty dock
#

it's actually also not needed or recommended to use function hooks for things like add_to_deck or remove_from_deck. you just put a function in the joker object when registering

kindred saddle
#

Ahh I did it that way since the only way I saw people do it online was with the function hook

frosty dock
#

the arguments are slightly different, self in the original function is the second argument and usually called card, while the first argument self is just the prototype. the key is then just self.key (or card.config.center_key)

kindred saddle
#

self.key specifically

frosty dock
#

self.key works only for the steamodded function

#

which i take you're not using??

kindred saddle
#

I guess now that I can decouple the logic from the argument hook, I can probably just run a simple Joker search to see if I should trigger the Joker or not

#

Instead of needing a Boolean value

#

And this junk

frosty dock
#

oh you're not doing add effects of a specific joker? what i said doesn't make too much sense in context

#

it's basically the second option of what i said above then

#

self.config.center_key

#

or self.config.center.key, funnily enough both of these work

kindred saddle
#

I got it to work but only in the old attribute and argument hook way, so at least now I can move it to key

frosty dock
#

yeah function hooking is actually the most straightforward option in that case because it's not bound to one specific joker

kindred saddle
frosty dock
#

now that i come to think of it, this probably isn't the best way to implement what you're doing anyways

#

you should just check for food jokers in your calculate function

kindred saddle
#

But I thought “oh but it’s more efficient to do it this way”

#

When I could honestly just cut down on almost all of the logic I had to write

frosty dock
#

that's what we call premature optimization

kindred saddle
#

Lmfao yeah

frosty dock
#

also it's not strictly more efficient

kindred saddle
#

Yeah I just thought it would be better to use a Boolean flag and call it a day

#

Rather than check every time

#

When I’m still checking every time lol

#

In retrospect, not the brightest idea

frosty dock
#

fair 'nuff

kindred saddle
#

I’ll take a crack at it again later

#

Now that I have a better idea of what I can do

#

Thanks

autumn coral
#

thinking about making some pulls on cryptid for bugfixes

#

there should be some way to have a speed above 4 for trains like what i have rn

#

this shit gonna take FOREVER

#

dude i'm still on the third card

mellow sable
mellow sable
vivid glade
autumn coral
#

god.

#

there are 3 of those btw

autumn coral
#

i'm on mac tho

#

wait how do i change the speed for talisman what

mellow sable
#

Not speed, but it can disable the scoring animations

#

Mods > Talisman > Disable Scoring Animations

autumn coral
#

ohhh

#

oh wow that's so much better wth

#

wait i think i lowk crashed the game with that hand

#

with a new hand i mean

#

i think i crashed the game @mellow sable

#

guess not

#

good god

tepid crow
#

it is very normal to crash the game with cryptid btw

autumn coral
#

i see that

#

god save us all

#

3 jawbreakers

#

i got rid of them though lmfao

hot drift
autumn coral
#

huge

sour aspen
#

Is there a way to intercept a function call debuffing a card to prevent it from doing so?

#

context: I am trying to make a seal that prevents a card from being debuffed

languid mirage
#

Yes, by creating a hook. You store previous function into a local variable and then override the function, if debuff needs to be cancelled, you return from the function, otherwise you call the function with the same parameters

sour aspen
#

So uh
Dumb question
How do I make a hook

hardy viper
#
local oldFunc = G.this.function
function G.this.function(arg1, arg2)
 if condition then
  return
 end
 return oldFunc(arg1, arg2)
end
sour aspen
#

Would that not just recurse infinitely

hardy viper
#

naw

#

you're saving the old function before you overwrote it

sour aspen
#

Ok

hardy viper
#

also note that this can have side effects of an argument isn't passed and you're hooking a, say, C function that insists on a certain type for it's values

languid mirage
#

also keep in mind that declaration like function Controller:do_something(arg1) is short for function Controller.do_something(self, arg1)

hardy viper
#

^

languid mirage
#

so you'd need to pass self into the old function manually

sour aspen
#

Lua's patterns of reference saving versus value saving hurt my Java/Python brain

hardy viper
languid mirage
#

yeah, it's weird

hardy viper
#

shoutout copy_table

wintry swallow
#

LUA looks like someone ran over Python with a monster truck and scooped the remains into a sack.

hardy viper
#

running over garbage just leaves you with more garbage

wintry swallow
#

I didn't say ran over Java

languid mirage
#

🗿

hardy viper
sour aspen
#

egg

mystic river
languid mirage
#

lovely patching like that would just cause incompatibility if another mod tries to patch the exact same thing

#

but mostly because that's a bit unoptimal to do full function replacement, you can just add one check after this line

#

I mean logic wise it'd behave differently, now that I think of it

#

in this case it'd probably make more sense to override instead of patching

wintry solar
#

A hook would still be better here

#

You could also just target the if line

languid mirage
mystic river
#

I'll probably redo the thing after work today
if i can take it out of lovely patching entirely I'd prefer that. but if i can't do that then at least i can make it less awkward

tepid crow
mystic river
#

on a technical level, it's still lovely patching, it just sucks :v

#

but now that i know function hooking exists I'm gonna try that instead
this should also be useful for another thing i was trying to figure out. probably

gaunt thistle
#

lovely is a last resort, other options are usually better ones

mystic river
#

true, but i couldn't find the better options back then

#

I'd love it if my next update let me delete lovely.toml out of my mod entirely :v

gaunt thistle
#

that's the spirit golden_joker

tepid crow
mystic river
#

i think all three would be relatively simple, based on how it looks like function hooks work
but I'll have to test it and find out. after work

rough furnace
sour aspen
#

Currently trying to adapt Inscryption Sigils into Seals

#

They obviously won't work 1-1

#

But

#

I am trying

frosty dock
rough furnace
#

fair enough

#

the tab menu, collection number keys, save states and the console don't need ctrl

frosty dock
#

good to know

humble gale
#

Alright, im trying to make a joker reduce the cost of all jokers and buffoon packs in the shop.
Ive does the injection in the lovely.toml below and the discount will not apply

#Add discount for Limp Bizkit
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if (self.ability.set == 'Planet' or (self.ability.set == 'Booster' and self.ability.name:find('Celestial'))) and #find_joker('Astronomer') > 0 then self.cost = 0 end"
position = "after"
payload = """
    if (self.ability.set == 'Joker' or (self.ability.set == 'Booster' and self.ability.name:find('Buffoon'))) and #find_joker("LimpBizkitSec") > 0 then
        self.cost = self.cost * 0.5
    end
"""
match_indent = true

Anyone know why the discount would not be applying?

#

I just put it after the code for Astronomer since they pretty much do the same thing

rough furnace
#

with after won't it be in the if statment for astronomer

#

also you should probably use SMODS.find_card with your joker's id

tepid crow
humble gale
autumn coral
#

btw where is this supposed new version of cryptid

#

i have lts i'm pretty sure...

hardy viper
#

lts isnt really a thing unfortunately

autumn coral
#

lol

hardy viper
#

nothing is retroactively updated

#

latest cryptid build

autumn coral
#

i have that

#

😭

#

ppl were saying placeholders n shit were replaced but like

hardy viper
#

then youre on latest

autumn coral
#

i literally have lts

spare elk
#

how do i make a deck that starts with no cards and with tags? my attempt just didnt remove any cards and made 13 tags every frame

rough furnace
#

your event needs to return true or else it's re called

spare elk
#

ah thanks the packs work fine now
what about the 0 card deck?

slow bloom
#

does balatro/steamodded have a console/log so I can test events and see if they are activating properly?

#

whoops i cant read apparently, its literally all in the wiki

hardy viper
orchid thunder
#

OH SHIT

hardy viper
#

G.P_CENTER_POOLS.somePool = {
1 = <center>{..., order = 1},
...
67 = <center>{..., order=67}
}

orchid thunder
#

I JUST GO TIT TO WORK

hardy viper
#

gg

orchid thunder
#

wait a sec i might have not

hardy viper
#

not gg

crisp coral
orchid thunder
rough furnace
wintry yoke
#

Does DebugPlus let me spawn jokers for testing?

rough furnace
#

yes

#

can press 3 in the collection to spawn the joker

mystic river
#

or c

keen sleet
#

How do I set a card enhancement's name in steamodded 1.0? Setting it in loc_txt adds the name above the description, but doesn't change the badge. Custom rarity didn't seem to work either

languid mirage
maiden phoenix
#

Did something change with how mod icon are loaded?

#

Nvm didn't see the metadata changes

lofty socket
#

Hey friends, I'm new around here. I'm a programmer by trade but never touched Lua.
I have a run I started yesterday that exceeded naneinf, so I installed my first mod yesterday - talisman - to keep playing the run and see my hand scores.
Unfortunately Talisman won't play nice with vanilla saves and my e308+ hand scores "Infinity" instead of vanilla "naneinf", and an "Infinity" does not beat a blind, so I am stuck at ante 39.
I am super attached to this run and hyperfixated on keeping it going, so I want to either patch talisman to work with my save, or patch my save to work with talisman.
Guess my questions are - how do you get started on this? I read up on https://learnxinyminutes.com/lua/ enough to know what I'm reading.
What now? I tried looking through the mod code to find either the save format or the scoring function but if I understand correctly, these functions are part of Balatro source code, and the mod just patches them?
Should I be looking through the source code? Running with a runtime memory editor? How do I get started working on this?
Thanks in advance from a hyperfixated noob

hardy viper
#

pretty sure math is working on patching talisman to be compatible (one-way at least) with vanilla saves

#

until then there's not much you can do, there's the option of simply starting a new run with the same seed and using debug to get back to where you were

mellow sable
#

@lofty socket I made a small change, try seeing if it makes your save work when loading with this version
Please do make a backup though in case I screwed something up

tepid sky
#

how does voucher lvl 2 only appear in shop after lvl 1 has been bought?

hardy viper
#

very likely the same thing

tepid sky
#

pools r complicated lol

hardy viper
#

?

#

requires = {
"v_key"
}

mellow sable
tepid sky
#

hmm

#

lol

#

ty

spare elk
#

anyone got the code to abandoned deck? still trying to make a 0 card deck and i just realized abandoned deck's code could be useful since it removes cards

weary jungle
# spare elk anyone got the code to abandoned deck? still trying to make a 0 card deck and i ...
for k, v in pairs(self.P_CARDS) do
                local _ = nil
                if self.GAME.starting_params.erratic_suits_and_ranks then _, k = pseudorandom_element(G.P_CARDS, pseudoseed('erratic')) end
                local _r, _s = string.sub(k, 3, 3), string.sub(k, 1, 1)
                local keep, _e, _d, _g = true, nil, nil, nil
                if _de then
                    if _de.yes_ranks and not _de.yes_ranks[_r] then keep = false end
                    if _de.no_ranks and _de.no_ranks[_r] then keep = false end
                    if _de.yes_suits and not _de.yes_suits[_s] then keep = false end
                    if _de.no_suits and _de.no_suits[_s] then keep = false end
                    if _de.enhancement then _e = _de.enhancement end
                    if _de.edition then _d = _de.edition end
                    if _de.gold_seal then _g = _de.gold_seal end
                end

                if self.GAME.starting_params.no_faces and (_r == 'K' or _r == 'Q' or _r == 'J') then keep = false end
                
                if keep then card_protos[#card_protos+1] = {s=_s,r=_r,e=_e,d=_d,g=_g} end
            end```
i think this is it, but there might be some patches or smth (game.lua)
#

the self.GAME.starting_params.no_faces line

spare elk
#

... oh

tepid crow
#

yeah it's the starting_params.no_faces

spare elk
#

so like i'd add to the "_r == 'K' or _r == 'Q' or _r == 'J' " part with all the other types of cards and it'd start with no cards?

tepid crow
#

you could lovely patch in there I suppose

#

might also be able to pretend your deck is actually a challenge (the _de parts)? that might have some unintended side effects though lol

#

or just manually remove cards on apply similarish to what checkered deck does (see back.lua:240)

spare elk
#

from my low understanding all i can see checkered deck doing is changing 2 suits into 2 others, nothing about adding or removing cards

weary jungle
#

you could probably destroy all cards instead of change suits

wintry solar
#

won't you just instantly lose if you have 0 cards in the deck?

weary jungle
#

i think its supposed to be jou get a bunch of standard packs

spare elk
#

yeah thats what i want it to do

#

you start with no cards but you make your own deck with 13 mega standard packs

tepid crow
weary jungle
tepid crow
#

here's a deck I coincidentally have for testing

SMODS.Back {
    key = "test",
    loc_txt = {
        name = "testing",
        text = { "removes all but 12 cards" }
    },
    apply = function(self)
        G.E_MANAGER:add_event(Event({
            func = function()
                local i = 1
                while i <= #G.playing_cards do
                    local v = G.playing_cards[i]
                    if i > 12 then
                        v:remove()
                    else
                        i = i + 1
                    end
                end
                return true
            end
        }))
    end
}
spare elk
tepid crow
#

theoretically

weary jungle
#

or without the suit check

tepid crow
#

you'll run into a fun programming issue where you're modifying the size of the list (table) you're iterating which can cause all sorts of whackiness

weary jungle
#

if you remove all cards

spare elk
#

ah

tepid crow
#

which is why I manually keep track of the index i in my code instead of the for k, v in pairs()

hardy viper
#

it's very easy to simply

local i = 1
repeat
 if <condition> then
  cards[i]:remove()
 else
  i = i + 1
  end
until not cards[i]

preferred solution for me
doesn't need a break

#

you could also do the same exact thing with a while loop and it'd function the same but regardless

#

assuming there's always at least one card in the list (if there isn't repeat would be prone to breaking here)

spare elk
spare elk
#

which i do not understand at all

zenith sage
#

both of the jokers in context.end_of_round proc wayyy more often than they should and i feel like theres an obvious solution to this i dont know

hardy viper
zenith sage
#
elseif context.end_of_round then
            if not context.blueprint then
                if self.ability.name == 'Perpetual Stew' then
                    if G.GAME.blind.boss then
                        self.ability.extra.h_size = self.ability.extra.h_size + self.ability.extra.bonus
                        G.hand:change_size(self.ability.extra.bonus)
                        card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex'), colour = G.C.MONEY})
                    elseif self.ability.extra.h_size - self.ability.extra.h_mod >= 0 then
                        self.ability.extra.h_size = self.ability.extra.h_size - self.ability.extra.h_mod
                        G.hand:change_size(-self.ability.extra.h_mod)
                        return {
                            message = localize{type='variable',key='a_handsize_minus',vars={self.ability.extra.h_mod}},
                            colour = G.C.FILTER,
                            card = self
                        }
                    else
                        return {
                            message = localize('k_eaten_ex'),
                            colour = G.C.FILTER,
                            card = self
                        }
                    end
hardy viper
#

you need to check against context.individual

zenith sage
#

thank you

zealous glen
#

I'm guessing the game automatically deletes the cards that are marked to not be kept

#

Not quite—it seems that if keep is false it doesn't add the card to the list of card prototypes

#

so you probably want something like

if self.GAME.starting_params.MY_MOD and self.GAME.starting_params.MY_MOD.MY_PARAM then keep = false end
#

probably as a patch

zenith sage
#
        elseif context.end_of_round then
            if context.individual and not context.blueprint then
                if self.ability.name == 'Perpetual Stew' then
                    if G.GAME.blind.boss then
                        self.ability.extra.h_size = self.ability.extra.h_size + self.ability.extra.bonus
                        G.hand:change_size(self.ability.extra.bonus)
                        card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex'), colour =  G.C.MONEY})
                    elseif self.ability.extra.h_size - self.ability.extra.h_mod >= 0 then
                        self.ability.extra.h_size = self.ability.extra.h_size - self.ability.extra.h_mod
                        G.hand:change_size(-self.ability.extra.h_mod)
                        return {
                            message = localize{type='variable',key='a_handsize_minus',vars={self.ability.extra.h_mod}},
                            colour = G.C.FILTER,
                            card = self
                        }
                    else
                        return {
                            message = localize('k_eaten_ex'),
                            colour = G.C.FILTER,
                            card = self
                        }
                    end
                elseif self.ability.name == 'Experienced Joker' then
                    self.ability.mult = self.ability.mult + self.ability.extra.mod
                end
            end
#

that procs less often but still too often

#

i tried checking for individual first, putting end of round in the existing individual check, and that seemed like it would never check for end of round after beginning the individual check so that didnt work

#

not sure how im supposed to be checking it

tepid crow
spare elk
#

changing the < to <= worked, thanks so much!!!
the deck is now fully functional lets gooooo

mystic river
#

always important to know whether you're working with less-than or less-than-or-equal nodnod

tepid crow
spare elk
#

im still not that good at coding so i cant really tell whats wrong with my code most of the time 😅

teal estuary
#

how do you make some joker code triggerif the number its going to become is a number you want it to do something on? currently working on a joker of mine and it doesnt trigger on the hand where it reaches the desired number, it triggers after which is irritating 😭

  calculate = function(self, card, context)
    if context.after and not context.repetition and not context.blueprint then
        card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chips_gain
        card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
        return{
          message = "Cooking!",
          colour = G.C.CHIPS,
          card = card,
        }
    end
    if context.joker_main then
      if card.ability.extra.chips >= 20 then
      SMODS.eval_this(card, {
             message = localize{type = "variable", key = "a_chips", vars = {card.ability.extra.chips}},
             chip_mod = card.ability.extra.chips,
             colour = G.C.CHIPS,
       })
       if card.ability.extra.chips >= 20 then
        card.ability.extra.chips = 0
       end
    end
  if card.ability.extra.mult >= 20 then
      SMODS.eval_this(card, {
             message = localize{type = "variable", key = "a_mult", vars = {card.ability.extra.mult}},
             mult_mod = card.ability.extra.mult,
             colour = G.C.MULT,
       }) 
       if card.ability.extra.mult >= 20 then
        card.ability.extra.mult = 0
       end
    end
  end
  end
#

(image for reference)

hybrid iris
teal estuary
tepid crow
#

I'm confused, isn't the current behavior in-line with your joker's description? or will you change that too?

teal estuary
hybrid iris
#

but yeah right this is also just what your joker behavior, is-

tepid crow
#

ah so you'll be changing the description to match, I see

hybrid iris
#

yeaaaa

teal estuary
#

but also, so

weary jungle
#

how do you let a card stay on screen, like that one glitch where cards persist on screen and you can move them around

hybrid iris
#

you can either move the 'cooking' code to inside the joker_main thing

#

or make it context.before

teal estuary
#

isnt after used for after a hand is played? so if its not in a after context, wouldnt it not work how its supposed to work? /genq

tepid crow
#

could make it context.before like Luna said yeah

teal estuary
#

-# or wait, the checking goes in context.before?

#

-# not the counting?

hybrid iris
#

skdfjhsdfjh uh--

#

okay, after is used for effects that happen after everything is scoring, like how ice cream and seltzer lose stuff after it happens

tepid crow
hybrid iris
tepid crow
weary jungle
teal estuary
hybrid iris
tepid crow
#

LMAO

hybrid iris
#

"bye"

tepid crow
weary jungle
#

how do i fix this

faint yacht
teal estuary
tepid crow
#

if context.after -> if context.before

teal estuary
#

oooh, neat

#

ty

weary jungle
#

i think my joker is emplaced in joker and G.play???

tepid crow
#

is it the superposition joker

weary jungle
#

what?

#

yes

#

i cant sell it

tepid crow
#

(cuz superposition means it's in 2 places at once)

weary jungle
#

i spawned regular jimbo and i cant sell any of them

#

i think that the central one is a jimbo, and the one near the jokers is my joker

#
        if G.play then
            G.play:emplace(card)
        end
    end,```
#

why cant i sell my jokers

stiff locust
#

set_ability is run when the joker appears in the shop or collection???

weary jungle
#

yea i think sp

stiff locust
#

no i know that's what it is

#

card is a variable that you declared in set_ability so

#

the card is spawning itself?

#

if you wanted to create jimbo here

#

you'd do it with G.jokers not G.play

#

here's the code that would actually create a jimbo

local card2= create_card("Joker", G.jokers, nil, nil, nil, nil, "j_joker")
                card2:add_to_deck()
                card2:set_edition({negative = true})
                G.jokers:emplace(card2)
#

i included the set edition line as an example if you wanted to do that

#

that's how you set editions when you do this

tepid crow
#

he doesn't want to create a jimbo in the joker slots

stiff locust
#

what should be made then

#

more copies of the same card?

stiff locust
#

ahhh

#

i think bettma's mobile joker does that if it's placed in the hand?

#

also i don't think you can sell them because they're not being made as jokers?

stiff locust
calm sand
#

I'm working on a fully featured, robust save editor for Balatro. Is there a list of all joker, planet, tarot, etc cards by their names in the code? e.g. j_perkeo j_hanging_chad etc

tepid crow
calm sand
#

Perfect, this is even better than I hoped for

calm sand
tepid crow
#

sounds good 👍

ember moat
#

How can someone start modding Balatro?

frosty dock
bronze thunder
#

all planet cards, all seals, and most spectral cards refuse to change textures and i don't know why

#

i changed every texture to pure red for demonstration

#

i don't get how it can happen when they're on the same atlas

hybrid iris
#

do you have any other mods installed?

bronze thunder
#

nope

hybrid iris
#

huh

#

weird

bronze thunder
#

i had one but i deleted it

#

and i sent it to a friend who never had any mods so it can't be that

kindred saddle
#

@frosty dock @hardy viper Thanks for the advice and help, it works now, and I cut down the logic from 130 lines of code to about 70 lines of code from cutting out the function hook, and doing everything solely within the calculate function

#

(Oh and it uses keys now, and not ability name)

orchid thunder
#

I wonder how hard it would be to make a little "mini ante" with custom blinds

rough furnace
#

Iirc I have some incomplete card manipulation for my save editor

#

Not sure if it was ever pushed or what

lofty socket
#

Saved my run!!!

#

I do still have a backup in case something goes wrong, I'll let you know. Thanks so much!!

mellow sable
#

yw :)

lofty socket
#

On another subject, is this an appropriate place to ask if I run into lovely errors?

#

My game consistently crashes when I try to rearrange my planet cards, I believe this was happening before I started using Talisman as well

hardy viper
#

ya share those errors here

tepid crow
lofty socket
tepid crow
#

why did it Failed to get additional context :/ 🤔

#

on that same note...

hardy viper
hardy viper
tepid crow
#

I'm more interested in what functions/common_events.lua:2957 looks like

hardy viper
lofty socket
hardy viper
#

they're timestamped so

lofty socket
#

Oh oh the thing after the dash is a timestamp

#

I believe this should be it. I have several mods in my Mods directory as indicated by the logs but only Talisman is loaded.

hardy viper
lofty socket
tepid crow
#

cheers

#

2957: localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} 🤔

#

wait your error line moved around???

lofty socket
#

wdym?

tepid crow
#

first time it was 2957, now it's line 2960

lofty socket
#

This might not be the exact correct log then

tepid crow
#

2960: G.GAME.hands[cfg.hand_type].level,localize(cfg.hand_type, 'poker_hands'), G.GAME.hands[cfg.hand_type].l_mult, G.GAME.hands[cfg.hand_type].l_chips, this one seems more likely for it to crash on

lofty socket
#

This time they should match I hope

tepid crow
#

yeah now they both point at 2960 which makes more sense anyway

tepid crow
tepid crow
lofty socket
#

Spoken like a true programmer

tepid crow
lofty socket
#

filename?

#

oh lovely.toml

tepid crow
#

as given

lofty socket
#

Can I append it to an existing lovely.toml in one of the mods?

tepid crow
#

if you prefer, sure

hardy viper
#

(minus the header)

lofty socket
#

Yup no crash now!!

hardy viper
#

lol

#

nice

lofty socket
#

Thank you!!

#

I may now rearrange my celestials in peace

tepid crow
#

(normally this is shown in the crash log but since that also crashed...)

lofty socket
#

Now I'm curious, why is that weird? Could you not replicate the crash on your setup?

tepid crow
#

No, I could

lofty socket
#

Honestly it might just be due to my fucky save, I started it on vanilla and installed talisman midway through

tepid crow
#

but it seemed like an error that should've popped up constantly by anyone playing balatro

#

so I'm guessing it's because you continued a save with talisman midway yeah

lofty socket
#

Thank you anyway :))) I'm really attached to this run lol this discord is helping me keep it alive on a breathing machine and IV

tepid crow
#

🤣

#

good luck haha

nocturne garnet
weary jungle
#
local Jok1 = pseudorandom_element(jokers, pseudoseed('BerkanoChooseDup'))
            local Jok2 = pseudorandom_element(jokers, pseudoseed('BerkanoChooseDbf'))
            if #G.jokers.cards ~= 1 then
                repeat
                    Jok2 = pseudorandom_element(jokers, pseudoseed('BerkanoChoose'))
                until (Jok1 ~= Jok2)
            end``` is there any edge cases i havent considered?
#

let me test this first

crisp coral
#

it might fuck up when having no jokers

karmic kelp
#

the case where there are 0 jokers? since 0 is not 1, the repeat would go on forever comparing nil to nil
(or just crashing on Jok1)

weary jungle
#

it can only use when 1

#
    can_use = function(self, card)
        return (G.STATE == G.STATES.SELECTING_HAND) and (G.jokers.cards) and (#G.jokers.cards > 0)
    end,
#

(yes its a consumable)

karmic kelp
#

is there a list of states somewhere, by the way? I've cut a few corners in my foree into modding and haven't actually put state checks into my consumables yet

hardy viper
#

steamodded defines a few more

#

examples being the one for custom booster packs

#

(it is one state, not one per consumeable type)

weary jungle
#

Oops! The game crashed:
functions/misc_functions.lua:267: bad argument #1 to 'pairs' (table expected, got nil)

#

uh oh

#

how do i get a list of all jokers

#

oh im just an idiot

#

ok i think this is good

#

noqw

#

dbf and dupe

bronze thunder
weary jungle
#

dont tell me.....

vivid glade
#

do i really have to put all lovely patches in one big lovely.toml?

#

also, how do i log stuff to the lovely console?

gaunt thistle
#

you can split them up into separate .toml files if you put them all into a lovely/ directory

vivid glade
#

how can i know if my patch has applied btw?

#

it dosent show anything in the logs

frosty dock
#

you can check the dump

#

iirc for regex patches it will let you know if it failed

languid mirage
vivid glade
languid mirage
#

Mods/lovely/dump

languid mirage
vivid glade
#

i am not modding balatro, i just dont know of another place to talk about lovely lol

#
[manifest]
version = "0.0.1"
dump_lua = true
priority = 0

[[patches]]
[patches.pattern]
target = 'src/menu/mainmenu/mainmenu.lua'
pattern = "Programming art and sound effects - Noba"
position = 'after'
payload = '''
SwitchMod by teesh3rt
'''
match_indent = true

this is my patch, it dosent show it as a regex mismatch but nothing is happening! is there something wrong?

#

this is the way i saw steamodded doing things so im just doing it like that

languid mirage
#

ah, lovely does have own discord / thread

languid mirage
#

I think lovely doesn't give any warning if path is incorrect

#

so if file doesn't exist

elder vapor
#

i don't think you can do patches like that

languid mirage
#

read message above the one you replied to

vivid glade
elder vapor
#

ah

#

the lovely dump should have everything post-patches so you can check if it was applied there

vivid glade
#

the strange part about it is that lovely dosent even produce a dump

#

even though i tell it to dump_lua

languid mirage
#

pretty sure dump_lua doesnt do shit

crisp coral
languid mirage
#

it's always true

vivid glade
#

my file structure is:

Mods/
  switchmod/
    lovely/
      core.toml
  lovely/
    log/
crisp coral
#

game file

#

not your file

#

in other words you can't do anything until it gets fixed for lovely

vivid glade
#

oh god darn it

crisp coral
#

yup

#

found that out while modding beatblock

languid mirage
crisp coral
#

balatro never has this issue

languid mirage
#

meth knows about it, right?

crisp coral
#

ask em

vivid glade
languid mirage
#

well there isn't an issue for it on github so uh will do

crisp coral
#

how'd you not know that

tepid crow
languid mirage
#

I left a message on discord

#

but feel free to create an issue, will probably work better as a reminder

gaunt thistle
#

an issue would be best

crisp coral
#

is there a lovely discord i don't know about?

tepid crow
#

lmao

crisp coral
#

hi meth

languid mirage
gaunt thistle
tepid crow
gaunt thistle
#

I had Discord open in the background

#

lucky timing

gaunt thistle
#

I think it's time to merge that feature since I haven't made much progress on the manifest feature

languid mirage
#

woo

tepid crow
#

wait I thought this issue

iirc files deeper than 2 folders aren't considered by lovely
was talking about the target being more than 2 folders deep

languid mirage
#

^

#

yeah

tepid crow
gaunt thistle
#

ah alright

tepid crow
#

so are these 2 seperate (confusingly similar) issues or did I misunderstand?

languid mirage
#

yes

#

I used "target files" specifically to distinguish from that one, but I guess it still caused confusion

crisp coral
#

latter, there's never any need for double nested lovely patches i don't think