#💻・modding-dev

1 messages · Page 664 of 1

oblique lotus
#

How can I look at all Jokers on start up to see if they have a specific atlas?

daring fern
oblique lotus
daring fern
#

Also it should be modprefix_atlaskey

oblique lotus
#

Gotcha

oblique lotus
mystic river
#

. should be :

fading rivet
#

Are there resources anywhere for making custom UI tabs

daring fern
oblique lotus
#

Okay, now I have something like:

function Game:main_menu(change_context)
    local atlas_check = main_menu_atlas_check(change_context)

    for k, v in pairs(G.P_CENTERS) do
        if v.atlas == 'modprefix_atlasname' then
            local name = localize { type = 'name_text', set = "Joker", key = v.key }
            print(name)
        end
    end

    return atlas_check
end```
And now it is giving this error.  Is this a function error or a problem with the Jokers I am looking at?
red flower
#

main_menu_atlas_check(self, change_context)

oblique lotus
#

That did the trick, thanks!!!

grizzled tide
#

does anyone happen to know the key needed for set_scoring_calculation to reset scoring to default

shrewd cobalt
#

does the apply function for a deck/back run when you hold R?
If not, how do I get something to randomize when restarting a run with R or starting a new run

daring fern
shrewd cobalt
#

Alright, thanks

bright ivy
#

How might I be able to make text pop up and say "Burned up!" when the card is destroyed?

frosty dock
#

also it has two identical conditions, so the second one would never run

#

fair, but it's a separate probability check

#

which means it's a 1 in 4 on top of the condition that the first check failed

#

which is actually a 1 in 8

#

my main point stands, don't ever destroy a card during its main eval

slim ferry
#

how can i prevent a card from juicing when triggered? i dont really want my card randomly jiggling while selecting cards because the hand would be debuffed

frosty dock
wintry solar
#

If people do need different timings

frosty dock
#

does it not fuck up the later contexts though

wintry solar
#

It shouldn’t do

frosty dock
#

hmkay

#

good to know

marsh horizon
#

i am so sorry if i put this in the wrong channel and/or if it's really off-topic, but, good morning/afternoon, i'd really like to improve my coding skills by trying to help people code balatro mods, i was thinking of a pizza tower mod, but all the posts about it are seemingly inactive, should i still try reaching out to the creators?

frosty dock
frosty dock
marsh horizon
real night
#

hey guys how do you destroy the lowest ranked card in the played hand

slim ferry
#

should i be using SMODS.ante_end or context.ante_end

frosty rampart
#

context.ante_end is a parameter passed alongside two different contexts

slim ferry
#

i know

frosty rampart
#

it's always just set to SMODS.ante_end

#

i don't think it matters too much

slim ferry
#

but SMODS.ante_end was created for the same thing because sometimes context.ante_end was broken

#

oh okay

soft pier
real night
#

okay wait i figured it out but How do i get the base nominal of a playing card

slim ferry
#

just do the raised fist thing

real night
#

god fucking damnit

slim ferry
#

vanillaremade

#

bro reinvented the wheel

bright ivy
past spade
#

is there some way to use localize() to convert a rank id number to its name? i.e 13 -> "King"

viscid talon
#

is there any way i can change wee joker's texture to this

daring fern
thorn ingot
#

Hey guys.

Is there any library for these effects?

backdrop_colour = G.C.SECONDARY_SET.Tarot

past spade
tidal hemlock
#

i think you mgiht need to take ownership

viscid talon
#

idk how to do that lol

slim ferry
#

backdrop_colour where

thorn ingot
#

in the sense of if there are more colors

slim ferry
#

what

#

wdym

#

Adding more colours or?

thorn ingot
#

Maybe? I thought there would be more colors in the base game. I got it from here.

slim ferry
#

Or do you mean what colours there are

thorn ingot
#

yeah that

slim ferry
#

G.C.SECONDARY_SET contains a colour table for every single card type

#

Including modded consumable types (the colour will be the defined secondary_colour on the object

#

And theres just a bunch of colours directly in G.C

#

And theres G.C.RARITY which contains the rarity colours

thorn ingot
#

uuu, okay. Will play around with it. But do you know if there is a list of them somewhere?

slim ferry
#

open balatro source code

red flower
#

search for C = { in the code

slim ferry
#

Ya

thorn ingot
#

aight guys. Thanks.

#

💕

tidal hemlock
clear ocean
hardy vessel
#

Is there a way to update the blind reward $$$ text like you can with the blind chip requirement?

viscid talon
#

i think so, yeah

#

lemme check the code i did for it

#

i managed to make it work with this joker

#
SMODS.Joker({
    key = "limepie",
    config = {
        extra = { dollars = 8, discard_sub = 1 },
    },
    loc_txt = {
        ["name"] = "Lime Pie",
        ["text"] = {
            "Earn {C:money}$8{} at end of round",
            "Payout {C:attention}reduced{} by {C:money}$1{}",
            "per discarded hand",
            "{C:inactive}(Payout is currently $#1#){}"
        },
    },
    pos = { x = 2, y = 5 },
    cost = 5,
    rarity = 1,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.dollars, card.ability.extra.discard_sub } }
    end,
    calculate = function(self, card, context)
        if
            context.discard
            and not context.blueprint
            and context.other_card == context.full_hand[#context.full_hand]
        then
            local prev_gold = card.ability.extra.dollars
            card.ability.extra.dollars = math.max(0, card.ability.extra.dollars - card.ability.extra.discard_sub)
            if card.ability.extra.dollars ~= prev_gold then
                return {
                    message = "-$1",
                    colour = G.C.YELLOW,
                }
            end
        end
        if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
            if card.ability.extra.dollars - card.ability.extra.discard_sub <= 0 then
                SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = localize("k_eaten_ex"),
                    colour = G.C.RED,
                }
            end
        end
    end,
    calc_dollar_bonus = function(self, card)
        return card.ability.extra.dollars
    end,
})```
#

no idea how you would make it work though

hardy vessel
#

For blinds, it definitely works different. I can update the dollar value just fine, just need to update the display text somehow

hardy vessel
torpid flicker
red flower
#

how do you want it to look

torpid flicker
red flower
#

then each thing needs to be in its own row
like

C = {
  R = { T= credits },
  R = { T= staff }, 
  R = { T= staff names },
  R = { T= contributors }
  R = { 
    C = { T = textwrapped1 }, -- although idk if the wrap will have the correct node formatting
     C = { T = textwrapped2 },
    C = { T = textwrapped3 },
   }
}
fading rivet
#

how get I get the current blinds image for use in a node object?

#

key is the blind key

#

also pretend I put hover and obejc tin config

torpid flicker
fervent rampart
#

I am making a joker that turns shop jokers negative if you have that joker already in your bought joker area (Yes this is only useful if you have Showman). I cannot find any examples of code that checks for joker IDs in your main joker area, neither for all of them, or individual ones (Individual as in making a shop joker Cavendish turn negative if you have a Gros Michel). I am hoping to make use of both types of checks, but right now I just want to know if either is even possible. The negative shop joker part is simple, I'm purely stuck on how to begin comparing joker IDs.

mystic river
#

local keys, for i,v in ipairs g jokers cards do keys[v.config.center.key] = true end

#

that might have to be global actually

#

(don't call it just "keys" in that case obvs)

daring fern
fading rivet
#

okay this looks disgusting but it works

mystic river
#

The Hook

-# Retrigger 2 random cards
-# held in hand

fervent rampart
tidal hemlock
#

is there a blind template

#

for making blind art

wild patrol
torpid flicker
#

how do i underline ui text

fading rivet
#

progress

wintry solar
#

put {u:color} in your loc

torpid flicker
#

Im doing that but im just getting

fading rivet
fading rivet
torpid flicker
fading rivet
#

how are you getting it out of the file?

torpid flicker
#

{ n = G.UIT.T, config = { text = localize("spox_contributers_tab_name"), colour = G.C.UI.TEXT_LIGHT, scale = 0.6, align = "cm" } },

#

spox_helpers_tab_name = "{U:white}Project Staff{}",
spox_contributers_tab_name = "{U:white}Contributers{}",

fading rivet
#

thats the issue

#

you're basicly plugging those formats into the UI

#

instead of giving it nodes

wintry solar
#

lowercase u

torpid flicker
#

i tried lowercase first

wintry solar
#

but also what foo said

fading rivet
#
local N = {}
            localize{type = "other", key = "ba_" .. key, nodes = N}
            local B = G.P_BLINDS[key]
            local out = {n = G.UIT.C, config = {colour = G.C.WHITE, maxw = 4, padding = 0.1, r = 0.1}, nodes = {
                {n = G.UIT.R, config = {colour = get_blind_main_colour(key), r = 0.1, padding = 0.1}, nodes = {
                    {n = G.UIT.O, config = {over = true, object = SMODS.create_sprite(0,0, 1.4, 0.5, SMODS.get_atlas(B.atlas) or 'blind_chips', B.pos)}},
                    {n = G.UIT.T, config = {text = SMODS.Blind:get_obj(key).name or "ERROR", scale = 0.5, colour = G.C.WHITE}}
                }}
            }}
            for _, line in ipairs(N) do
                out.nodes[#out.nodes + 1] = {n = G.UIT.R, nodes = line, config = {align = "cm"}}
            end
#

this is what mine does

#
Other = {
            ba_bl_hook = {
                text = {
                    "Retrigger {C:attention}2{} random cards",
                    "held in hand"
                }
            }
        }
primal robin
#

what is over = true in G.UIT.O

fading rivet
#

that should be hover whoops

wintry solar
#

you need to give localize a table of nodes that it will populate for you

primal robin
#

this doesnt work for G.UIT.O since it dictated by object itself

#

So sprte should be hoverable instead

fading rivet
primal robin
#

You calling create_sprite function incorrectly tho, it's 4 number values and only after that atlas and pos

fading rivet
#

img is coming...

fading rivet
#

oh wait I see why its not scaled
i thought 0,0 was 0.0 lol

frozen hamlet
#
SMODS.Sound({
  key = "cocosmod_music_boostersong",
  path = "cocosmod_boostersong.ogg",
  pitch = 1,
  volume = 1,
  music = true,
  select_music_track = function()
        if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
                return 1337
            end
        end
})
fading rivet
wintry solar
#

Or if it was darker/lighter

fading rivet
#

okay better

frosty rampart
# frozen hamlet ```lua SMODS.Sound({ key = "cocosmod_music_boostersong", path = "cocosmod_bo...

yea G.STATES.SMODS_BOOSTER_OPENED is whenever any booster pack is open
here's what you'll want to do

if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
  local booster = G.pack_cards and G.pack_cards.cards and SMODS.OPENED_BOOSTER
  if booster and booster.config.center.key == "p_modprefix_boosterkey" then
    return 1337
  end
end

instead of literally checking for "p_modprefix_boosterkey", you'll want to put in your own mod's prefix and then the full key of the booster pack you've created

fading rivet
#

why are these horizontal 😭

#

they should be in a collumn

#

the data is in a collum

#

why is it sideways 😭

#

does anyone know how to fix this?

primal robin
#

wtf is this

primal robin
fading rivet
primal robin
#

Content in it, not column itself

#

columns placed horizontally next to each other and render content inside vertically

#

That's the logic

#

In excel spreadsheet rows placed vertically (0, 1, 2...), columns horizontally (a, b, c, d...)

#

Same here

fading rivet
#

oooh

#

thx

primal robin
#

Also I'm sorry but this code is really bad

#

specifically last 2 lines

wild patrol
#

trying make a Xmult version of misprint

#

is it possible to put the red box around the changing text?

fading rivet
#

okay good news I got them vertical
bad news I have 0 clue why they are indented

formal vessel
wild patrol
#

can't use 0 because anything x0 is 0

#

lol

#

anything x1 is itself

#

so basically no mult

frosty rampart
thorn ingot
#

Hey, is this good enough to signal I don't want a joker to appear randomly? Does it even work.

        only_shop_pool = true,
        only_booster_pool = true
    },```
formal vessel
#

cool idea

wild patrol
#

trying to but the xmult box around the number text

#

but way that it's done uses UIT

#

instead of loc_text

long sun
#

i'd like to make a new AltTexture using Malverk. the texture should replace one of Cryptid's textures. what do i do?

#

i can replace vanilla textures just fine, but am unsure what the procedure is for other mods

frosty rampart
#
if next(SMODS.find_mod("Cryptid")) then
  -- define the AltTexture
end
long sun
#

(also hai meta :3)

frosty rampart
#

hiii

long sun
#

ya that's the part i knew actually 😭

frosty rampart
#

oh my bad lol

long sun
#

so i have this so far

#

copied from the vanilla one, but with original_sheet = true removed

#

(oh and it's wrapped in the mod check)

frosty rampart
#

i think maybe you wanna add keys = { "j_cry_joker1", "j_cry_joker2", ... }? and then you might not even need display_pos at all

long sun
#

oh hmm, so like, add the jokers manually

frosty rampart
#

i think so yea
are you planning to replace all the cryptid jokers

long sun
#

yep ^^

frosty rampart
#

yea i'm not sure if there's a good way to do that then without manually specifying all the jokers, sorry

long sun
#

ah eek, no worries

#

i'll complain to eremel then

#

thanks!

frosty rampart
#

being able to specify a whole atlas to replace would be cool

long sun
#

yeahhhh it'd be awesome ^u^

#

judging by the way it shows texture packs, though, it can't do that right now

#

as a guess

#

it might be undocumented

frosty rampart
#

i don't wanna pester eremel about it tho bc I know he's busy finishing up the smods update lol

long sun
#

o tru

wild patrol
#

is there a simply way to make an aniamted jokers

#

like know how to make a sprite sheet for animations

#

but how would you changed the pos of the sprite in real time

daring fern
wild patrol
#

and this is for say I wanna make a joker look like it's moving left and right

#

nvm found the smod wiki page

#

yeah this is what I needed

wild patrol
#

nvm figured it out lol

#

:D

bright ivy
#

I was wondering how I get into the sorce code to see the Hiker Joker

wild patrol
formal vessel
wild patrol
#

It's just a straight copy of bull

#

Just picked a random joker to copypaste to try out animated sprites

formal vessel
#

ohhh ok

#

but bull is +5 chips for $1

wild patrol
#

it's copy paste from vanilla resource

#

so vanilla resource probably has it wrong

formal vessel
#

oh ok

frosty rampart
lucid owl
#

i know the answer is probably no but i figure i should ask, is there any reliable way to detect jokers that copy effects (blueprint-likes)

wild patrol
#

like if a joker can be copied by blueprint

#

or it copies a joker like blueprint

lucid owl
#

no, like if a joker copies like blueprint

wild patrol
#

would assume so

#

blue print exists so

#

lol

lucid owl
#

what 😭

#

i'm trying to ensure a stack overflow doesn't happen

wild patrol
#

u want joker to copy another joker like blueprint or

formal vessel
lucid owl
#

i already know how to do that

#

i'm asking if there's a way to detect whether a joker copies cards like blueprint

#

so i don't have to manually put in every single modded copier joker's key

wild patrol
#

probably make a check for SMODS.blueprint_effect and if it triggers do what u need it to do

frosty rampart
lucid owl
#

well i suppose adding a not context.blueprint should work

#

hmm

frosty rampart
#

yea I don't see any reason it won't work

lucid owl
#

idk why ihad it structured like that, im returning to half a year old code lol

#

seems like i had it the opposite before, it wouldn't match blueprint-likes but could be copied by them

#

now i'm not sure which to go with

frosty rampart
#

it's not like this card is itself doing a blueprint effect, it should just be fairly standard post trigger stuff

bright ivy
#
and context.other_card:get_id() >= card.ability.extra.value

Is there a way to see how many chips scored as I would like to use that rather than the cards base value.

bright ivy
#

thank you

bright ivy
# daring fern `card:get_chip_bonus()`
calculate = function(self, card, context)
        -- Only triggers on cards that actually score
        if context.individual and context.cardarea == G.play 
        and card:get_chip_bonus() >= card.ability.extra.value 
        then
            context.other_card.ability.perma_mult =
                (context.other_card.ability.perma_mult or 0)
                + card.ability.extra.mult_gain

            return {
                message = "+Mult",
                colour = G.C.MULT
            }
        end
    end

Now it doesn't give anything, am I using it right?

daring fern
bright ivy
#

thank you

bright ivy
#

Does this joker seem balenced?
It is similar to the hiker and has good synergy with it.

bright ivy
#
calculate = function(self, card, context)
        if context.before and not context.blueprint then
            for _, scored_card in ipairs(context.scoring_hand) do
                local enhancements = SMODS.get_enhancements(scored_card)

                if enhancements
                and enhancements.m_stone
                and not scored_card.debuff
                and not scored_card.jacked then

                    scored_card.jacked = true
                    -- Reset to base (removes Stone)
                    scored_card:set_ability('c_base', nil, true)
                    
                end
            end
        end
    end,

how can I make the card become a jack after it is hammered out?

fervent rampart
lucid owl
#

anyone know how one would "dynamically" add retriggers to a card? i have a joker with a 1 in 2 chance to retrigger a card with a red seal, that then increases to 1 in 3, and so on, but i can't figure out how to retrigger multiple times without knowing exactly how many retriggers will be needed

#

the idea is: 1 in 2 chance - > retrigger -> 1 in 3 chance -> retrigger -> 1 in 4 chance... and so on

#

i'm coming back to modding after like 2 months away lol so sorry if the solution is obvious

fervent rampart
bright ivy
fading rivet
#
local count = 0
while SMODS.pseudorandom_probability(card, "identifier", 1, count + 2) then count = count + 1 end --- i forget what the actually function is but ik the arguments are correct
return {repetitions=count}
mystic river
#

while do, not while then

fervent rampart
bright ivy
#

ok, thank you, I let yk if I find a way

fervent rampart
#

Thanks

bright ivy
# fervent rampart Thanks

It happens in vanilla Balatro too with the Vampire joker, because of that I am just going to let it be as Im working on a mod that is trying to stay close to vanilla

vocal helm
#

Do quantum enhancements apply to modded enhancements, and if an edition is polled, can a card count as said enhancement if it's stored as an extra config variable?

gilded blaze
#

that would be called quantum edition and it's non-existent

oblique lotus
#

Is there a way through smods that you can change how much space negative edition gives, or do you have to do it with a patch?

gilded blaze
oblique lotus
#

Thanks a thousand!

vocal helm
gilded blaze
#

I took a look at how quantum enhancement works

#

Sand cards reduces xmult gradually

#

except that might not be the case if applied as a quantum enh

#

it's always X2 Mult with no downside

dapper sun
#

quantum enhancements are handled in a context thing, so you should be able to do it in an edition

gilded blaze
#

I'm confused

#

did the original question mean to ask whether it's possible to apply quantum enhancement via an edition

vocal helm
#

my original question is if it's possible to apply quantum enhancements for modded enhancements

gilded blaze
#

why not bruh

#

Ortalab clearly did that

vocal helm
#

i ask since my current implementation is very bruteforce and only applies to vanilla enhancements

gilded blaze
#

the voucher that makes 5 random cards in deck act as Wild and Index cards

#

that's a usage of quantum enhancement

vocal helm
#

how can i do it ina way that's not this lol

gilded blaze
#

what exactly are you trying to do

vocal helm
#

my joker is "stone cards additionally act as [enhancement], [enhancement] changes every round"

gilded blaze
#
if context.check_enhancement and context.other_card.config.center_key == "m_stone" then
    return {
        [card.ability.extra.enhancement_type] = true,
    }
end
#

bruh

#

that's it

vocal helm
#

oh

#

huh

#

Wow, awesome, thank you

#

i didn't know that was a thing you could do

gilded blaze
#

any variable type can become a table index, not just strings

slim ferry
#

-# this is a string though?

gilded blaze
#

yea, I spoke it at the wrong context lmao

#

basically this is how Lua works

local a = {b = 1}
local c = a.b == a["b"] --true
local d = "b"
local e = a.b == a[d] --true
#

you can directly call a.b to grab the b index of table a
a["b"] also works
for more complex keys like strings that contain space, only a["contains space"] works

lusty marten
#

are there any way to make a joker probability like "Oops ! All 6"?

faint yacht
#
if context.mod_probability then
  return { numerator = context.numerator * 2 }
end
wild patrol
#

hmm something ain't right here

#

the highet is right

gilded blaze
#

1x file in 2x folder

wild patrol
#

yeah I see

#

Thanks

grizzled escarp
#

Yo chat

#

Suggest me a preview

#

For balatro

#

On mod manager

wild patrol
#

is there a loop funtion for play_sound

gilded blaze
#

you might wanna specify your sound as bg music, it does the looping automatically

wild patrol
#

using sync?

gilded blaze
#

sync just makes it transition seamlessly between it and the current track

#

it's mainly used for music tracks that are somewhat a modified version of Balatro's main track

wild patrol
#

what's the way to specify music

gilded blaze
#

define select_music_track field

#

it's a function that may return the number specifying its playing priority (higher is better)

#

here are some examples

#

key must contain music btw

faint yacht
#

path may not, though. fool

wild patrol
#

i'll figure this out more tomorrow it's late as is right now

gilded blaze
#

it's simply easier to copy key over if I set the file names like that

wild patrol
#

Is there a limit on how long a sprite sheet can be

#

In terms of width

#

Like say could I theoretically put 10000 jokers on the name line or would that be too much for balatro to handle

gilded blaze
#

the only limit I know of is your device's capability

long sun
#

i need to access all loaded centers, how can i do that?

#

G.P_CENTERS isn't working when my mod is being loaded

#

print(inspect(ghostcards_find_all_on_sheet("Cryptid", "cry_atlasone"))) works once the game is loaded, however it doesn't when the game isn't loaded

#
function ghostcards_find_all_on_sheet(mod, sheet)
    local atlas = {}
    for _, v in pairs(G.P_CENTERS) do
        if v.original_mod and v.original_mod.id == mod and v.atlas == sheet then
            atlas[#atlas + 1] = v.key
        end
    end
    return atlas
end```
long sun
#

ah, cheers ^u^

#

hmm. a new bug presents itself

#

i might've solved the issue, but Malverk's wiki was a little misleading

#

original_sheet needed to be true, because the positions matched those on the original sheet

#

there we go!

jolly rain
#

Could someone help me resolve an issue I'm having with understanding some game/lua logic? I'm trying to make what I believed to be a simple joker concept and it's instead hurting my brain and crashing my games.

long sun
#

do you have the crash log?

jolly rain
#

Wanted to make a card that functioned like obelisk, but reset if you DIDN'T play your most played hand.
Copy and pasted the reference for Smod code in their "VanillaRemade" library and tried to flip the true/false for reset.

#
SMODS.Joker{
    key = "monolith",
    config = { 
        extra = { 
            Xmult_gain = 0.2,
            Xmult = 1
        } 
    },
    loc_txt = {
        ['name'] = 'Monolith',
        ['text'] = {
            [1] = "This Joker gains {X:mult,C:white} X#1# {} Mult",
            [2] = "per {C:attention}consecutive{} hand played",
            [3] = "while playing your",
            [4] = "most played {C:attention}poker hand",
            [5] = "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)",
        }
    },
    pos = { x = 0, y = 0 },
    rarity = 3,
    cost = 8,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = false,
    unlocked = true,
    discovered = true,
    effect = nil,
    atlas = 'monolith',
    
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.Xmult_gain, card.ability.extra.Xmult } }
    end,
    calculate = function(self, card, context)
        if context.before and not context.blueprint then
            local reset = false
            local current_played = (G.GAME.hands[context.scoring_name].played or 0)
            for handname, values in pairs(G.GAME.hands) do
                if handname ~= context.scoring_name and values.played >= play_more_than and SMODS.is_poker_hand_visible(handname) then
                    reset = true
                    break
                end
            end
            if reset then
                if card.ability.extra.Xmult > 1 then
                    card.ability.extra.Xmult = 1
                    return {
                        message = localize('k_reset')
                    }
                end
            else
                card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
            end
        end
        if context.joker_main then
            return {
                xmult = card.ability.extra.Xmult
            }
        end
    end,
}
#

Error code said I was comparing nil to a number, not sure where I did that

red flower
#

play_more_than is not defined

jolly rain
#

woopsies, accidentally changed play_more_than with current_played when I was fiddling around with stuff

#

Thank you N'

fading rivet
shrewd cobalt
#

anyone know why this isnt working? the files are in the right spot

frosty dock
#

oh mb it's more obvious, thanks Discord mobile for weirdly cropping images

#

you're files are in assets/shaders

shrewd cobalt
#

i keep getting the "file does not exist" error

frosty dock
#

you're telling the game that the files are directly in assets, which they aren't

#

in other words, it says the file doesn't exist because it doesn't

shrewd cobalt
#

still seem to get an error

shell timber
#

im assuming you have show file extensions on?

#

can you screenshot the folder in vs code?

shrewd cobalt
shell timber
#

uhh

#

maybe try using nfs? one second

frosty dock
#

what's to stop you from using an image atlas, anyway

shell timber
#

its for a shader?

ashen drift
#

how do i get the english localized name of a card

shell timber
#

though i guess you could grab the image out of it

#
local function get_image(path)
    local file_data = NFS.newFileData(path)
    local tempimagedata = love.image.newImageData(file_data)
    return love.graphics.newImage(tempimagedata)
end

local xyz = get_image(path .. "/assets/shaders/whatever2x.png")
``` ?
frosty dock
frosty dock
shell timber
#

right

red flower
ashen drift
#

alr

shrewd cobalt
long sun
#

AT LASTTTT

#

it took me so long to find out that Malverk doesn't set default_soul on modded Jokers 😭

shell timber
#

what if cryptid was good...

versed swan
shell timber
#

cryptid 2:

shrewd cobalt
shell timber
#

itd be G.ASSET_ATLAS["glaze"], though you may want to make one atlas for each glaze

shrewd cobalt
#

alright

versed swan
frosty dock
# shrewd cobalt alright

pretty sure you'd need to send the image and not the atlas itself though, so G.ASSET_ATLAS["glaze"].image

fading rivet
shrewd cobalt
#

ough ok there we go, thanks you two
my head hurts so much i hate code

frosty dock
thorny wigeon
#

Could anyone help me with this error I'm getting? I can't solve whats going on and I copied all of this from another mod and edited it to work for what I've made. All I did was change names and texts, not any of the code or any brackets.

thorny wigeon
#

Yeah but like, whats the error

fading rivet
frosty dock
#

you're missing a comma

#

maybe consider using an editor that has syntax highlighting

fading rivet
#

in texture_pack loc_txt

frosty dock
#

whatever you have is no good

thorny wigeon
#

thats dumb, it tells me I'm missing a }

fading rivet
#

so it thinks there should be a }, not some words

thorny wigeon
frosty dock
#

up to you, just my recommendation

#

you'll have a bad time using notepad, but if you so choose that's up to you

thorny wigeon
#

Yeah I understand there's significantly better options but my laptop has ghosts that eat my C drive

#

So, where does the comma go sorry?

frosty dock
#

name = '...',

thorny wigeon
frosty dock
#

yep

thorny wigeon
#

Because that does this

#

where tf is 's'

frosty dock
#

show the whole thing again

thorny wigeon
frosty dock
#

oh

#

quotes

#

the text in that same table is delimited with single quotes

#

yet it contains single quotes within it, which is bad syntax

#

you need to sub them for double quotes

thorny wigeon
#

As in " not '

frosty dock
#

yeah

thorny wigeon
#

for the "name"?

frosty dock
#

the delimiters in the text

#

text = {"..."}

#

-# Alternatively you can escape the inner single quotes with a \, just so you know

thorny wigeon
#

Interesting

#

Because this is working off a mod I downloaded to look at how it works, and that ones using '

frosty dock
#

yeah both are fine to use

#

you just can't have whatever delimiter you're using occur unescaped inside the string

thorny wigeon
#

Whats a delimiter?

frosty dock
#

by that I mean whatever you have at the start and end of the string

#

in 'text', the single quotes are delimiters

thorny wigeon
#

Darn, I assume I failed at doing what the other mod did

wintry solar
#

It should be 50BlessingsEnhancers_enhancement_tex

thorny wigeon
#

Yeah I just realised

#

lol

#

Wait where?

#

I thought I knew what I did

#

I do not

frosty dock
#

in textures

thorny wigeon
#

Oh the prefix at the top

frosty dock
#

yeah these need to match

wintry solar
#

Malverk is badly made in that regard 😭

frosty dock
#

take inspiration from applied_stakes I guess

thorny wigeon
#

Yippee I'm so good at this and did everything 100% on my own cuz I'm big brain

#

(I literally only did 1 thing on my own 2 weeks ago)

#

all this just to put a gradient over my cards to make them look like hotline miami stuff

frosty dock
thorny wigeon
#

Out of curiosity, can I put 2 .luas in one mod's folder?

#

currently it's 2 mods, one for the actual deck and one for the enhancers

frosty dock
#

if they both have headers, they can coexist but will be disabled together if you do disable them

#

you can however load more files from the main file

wintry solar
#

Are they both texture replacements?

thorny wigeon
#

Would I be able to put the malverk .lua stuff inside of the normal deckskin one and it all read okay?

wintry solar
#

Yeah that’s fine

thorny wigeon
final jewel
#

Smods headers is kinda anoying tbh

#

I put everythin' in mod.json

thorny wigeon
#

The second one has way more in it

frosty dock
#

that's a pretty old template oml

thorny wigeon
#

I am doing my best 😢

frosty dock
#

eh it's fine

final jewel
#

use this in a mod.json file

frosty dock
#

gtg anyway

thorny wigeon
#

Thanks for the help regardless

#

<3

#

Perfect

weary merlin
#

having some trouble hijacking the sell price for a joker.
when buying it in the shop, it'd cost the player $20, but upon being added to the inventory would have its sell price locked to 0

granite jay
#

Anyone know how to give Boss Blinds custom reward text?

#

Cos I have Blinds that grant Jokers when defeated

#

Also how do you make it so a Joker is unlocked when you unlock all spectral cards?

jolly rain
weary merlin
granite jay
granite jay
sour garden
#

doing a blind where xmult effects increase the required score by 30%, though this doesn't seem to be working. anyone know why?

SMODS.Blind {
    key = "Delta",
    atlas = "blinds",
    pos = {
        x = 0,
        y = 6
    },
    boss = {
        min = 6,
    },
    boss_colour = HEX("7db450"),
    
}

local eval_card_ref = eval_card
function eval_card(card, context)
    local eff, post = eval_card_ref(card, context)
    if G.GAME and G.GAME.blind and G.GAME.blind.name == 'bl_biasedBalance_Delta' and G.GAME.blind.ready and not G.GAME.blind.disabled then
        local x_mult = card:get_chip_x_mult(context)
        if x_mult > 0 then
            G.GAME.blind.chips = G.GAME.blind.chips + G.GAME.blind.chips * 0.3
            G.GAME.blind.triggered = true
        end
    end
    return eff, post
end
granite jay
#

Ok running into a very big problem here

Whenever I disable my mod, the patch that adds multirank support is still applied for some reason, causing the game to crash every time I do smth such as play a hand

Does anyone know how to fix this?

slim ferry
#

does the game crash if you dont have an atlas set for a blind? im just creating some temporary dummy blinds for testing and im wondering if i actually need an atlas

#

i know it doesnt crash for other objects but i know blind sprites are also a bit jank sometimes

daring fern
granite jay
red flower
granite jay
#

ye\

red flower
#

weird

#

well you can add nil checks to the patch i guess

slim ferry
#

for some reason bottom crashes in mix_colours despite nothing that matters for vanilla being different

red flower
#

what if you add boss_colour

slim ferry
#

trying that rn

#

ah

#

right because the first one doesnt have a description

past bear
#

i downloaded the deckskintemplate, it seems pretty simple and straightforward but

#

there are two files named icon_lc and icon_lq

#

what are their usages?

#

<- has no idea how modding works btw

slim ferry
#

its the atlas for the suit icons in the bottom left of the deck view, one for both low contrast (lc) and high contrast (hc)

red flower
#

the icon for the deck view iirc

slim ferry
#

you can omit them if you dont change them

past bear
slim ferry
#

leaving them out

past bear
#

uh huh

#

what if i remove them

#

ig that's what you meant?

#

anyways ty for explaining

slim ferry
#

i meant like you can just remove them to not change the suit icons

past bear
#

got it ty

sour garden
hardy vessel
#

Trying to make a blind that makes your lowest rank held in hand give decimal mult, and I want it to give xmult for each card of that rank. However, it only works once. I would like this effect to trigger on every card if possible (another question is if I can use context.individual on this?)

    calculate = function(self, blind, context)
        if context.final_scoring_step then
            local temp_ID = 15
            for i = 1, #G.hand.cards do
                if temp_ID >= G.hand.cards[i].base.id and not SMODS.has_no_rank(G.hand.cards[i]) then
                    temp_ID = G.hand.cards[i].base.id
                end
            end

            for i = 1, #G.hand.cards do
                if G.hand.cards[i]:get_id() == temp_ID then
                    return {
                        xmult = blind.config.blind.config.extra.xmult,
                        message_card = G.hand.cards[i]
                    }
                end
            end
        end
    end,
red flower
#

you can use individual
if you want to keep using final_scoring_step you would need to not return in the loop

hardy vessel
#

okay, i wasn't sure if i could. i'll have to try something else

sour garden
#

the first 2 prints of this trigger, but the one signifying that the event is running never happens. how can i make the event run?

idle plaza
sour garden
#

what's wrong with my intenting? FHDJFDS

hardy vessel
# red flower you can use individual if you want to keep using final_scoring_step you would ne...

Doesn't seem to be getting past the initial checks. I don't think individual and final_scoring_step are compatible

    calculate = function(self, blind, context)
        if context.individual and context.cardarea == G.hand then
            if context.final_scoring_step then
                local temp_ID = 15
                for i = 1, #G.hand.cards do
                    if temp_ID >= G.hand.cards[i].base.id and not SMODS.has_no_rank(G.hand.cards[i]) then
                        temp_ID = G.hand.cards[i].base.id
                    end
                end

                if context.other_card:get_id() == temp_ID then
                    return {
                        xmult = blind.config.blind.config.extra.xmult,
                        message_card = context.other_card
                    }
                end
            end
        end
    end,
idle plaza
red flower
#

also the logic would be different

#

because individual iterates on every card already

hardy vessel
#

Right now I do have it set up for working with individual, and it works just fine. I just would have liked the xmult to be applied after scoring just to make it a bit more effective

clear ocean
#

is xmult text like collapsed like no whitespace allowed

mystic river
#

yeah

#

iirc you can sneak around this by using B instead

clear ocean
#

okay would you prefer that or this (ill probably make the text smaller so it can fit one line)

clear ocean
near coral
mystic river
near coral
#

Also that's just worse idol

clear ocean
#

Is that a tiny dog in a big mattress joker

near coral
#

Rebate is infinitely more useful

clear ocean
#

i mean i can increase it to 6 dollars but there are retriggers

near coral
#

Yeah so does rebate

mystic river
fading rivet
near coral
thorny wigeon
tidal hemlock
#

angry luigi?!?!

clear ocean
tidal hemlock
#

ah

#

yeah i never played the fallout games

thorn ingot
#

Hey guys, do you know where I can find more about this.

SMODS.smart_level_up_hand

red flower
thorn ingot
red flower
#

hands is a string or table of strings for the keys of the hands

thorn ingot
#

oh I see. Let me look around. thanks.

sour garden
#

is there a better way to do this? hooking into eval_card is causing a lot of random crashes
intended to prevent card modifiers from triggering when scored

SMODS.Blind {
    key = "Gamma",
    atlas = "blinds",
    pos = {
        x = 0,
        y = 6
    },
    boss = {
        min = 4,
    },
    boss_colour = HEX("7db450"),
    
}
local eval_ret = eval_card
function eval_card(card, context)
    local ret = eval_ret(card, context)
    if (not G.GAME.blind.disabled and G.GAME.blind.name == 'bl_biasedBalance_Gamma') then
        ret.edition = nil
        ret.enhancement = nil
        ret.seals = nil
    end
    return ret
end
bright ivy
#

How would i set up a legendary joker, I have the background and the joker face, but I dont understand what soul_pos does

#

Ik thats what I need for it to float off the card background, I just dont know where to put things to make it work

frosty rampart
#

the background and the joker face need to be treated like two separate sprites on the same spritesheet. the joker will have its pos set to the background and its soul_pos set to the joker face

bright ivy
#
-- Icarus
SMODS.Atlas {
    key = "icarus_atlas",
    path = "jokers/icarus.png",
    px = 71,
    py = 95
}
#

Do I change something here?

frosty rampart
#

no, don't touch the atlas. just make icarus.png 142x95, and the right half of the image is the joker face sprite

bright ivy
#

ohhh I see

frosty rampart
#

really you should have all your jokers on one sheet, it's super not efficient to load a different atlas for each joker

bright ivy
#
atlas = "icarus_atlas",
    pos = { x = 0, y = 0 },
    soul_pos = { x = 1, y = 0},
frosty rampart
#

yep!

bright ivy
#

so something like this?

#

ok thanks

frosty rampart
#

no problem

near coral
#

If the first reroll is made less expensive does that mean all rerolls after would be less expensive than if the first was normal price

near coral
#

Ok

vital wren
#

i want to make a joker that lets straights wrap around. i need to find the code for determining what hand is being played but im not finding it anywhere. does another know where the game determines which hand is played?

reef bobcat
#
        return { vars = { card.ability.extra.mult } }
    end,
    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and context.other_card:get_id() == 12 then
            return {
                mult = card.ability.extra.mult,
            }
        end
    end
}```

how would I also have this effect affect cards with red seals?
vital wren
gilded blaze
vital wren
gilded blaze
#

wha

#

SMODS is Steamodded

vital wren
#

yeah, im just using lovely

gilded blaze
#

are you making a content mod

#

doing that with lovely alone is an extremely tedious work

vital wren
#

im just making some tweaks to things and like doing things my own way. if i can find the code for it i can just make it do exactly what i want

red flower
#

it should be get_straight in misc_functions

gilded blaze
#

you'll want to look at get_straight in misc_functions.lua
the way SMODS overrides it is quite complex

red flower
#

oh hey that's my new comment

gilded blaze
#

lmao

#

yea, I'm using dev smods rn

vital wren
#

thanks. ill poke around in there and if i cant figure it out i know i can rely on SMODS

gilded blaze
#

at this point just use smods

#

allowing straight to wrap around isn't an easy feat

#

I wouldn't say it's a small tweak

daring fern
vital wren
#

ive been using lovely because SMODS is just so much more complicated and it's easy to just change the game code that i can see. i just want to change Superposition from its current effect to making straights wrap and be worth extra if they contain an ace.

in lovely i can just replace the game code. but i agree that the wrap around code isn't simple. so how do i highjack a joker's effect in SMODS?

pastel kernel
#

i couldn't get this to type in quotation marks ```toml
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '[' or args.key == ']' then return end'''
position = "at"
payload = ""
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = ''' local lower_ext = '1234567890-=;',./'
local upper_ext = '!@#$%^&()_+:"<>?'
if string.find(lower_ext, args.key) and args.caps then
args.key = string.sub(string.sub(upper_ext,string.find(lower_ext, args.key)), 0, 1)
end'''
position = "at"
payload = ''' local lower_ext = "1234567890-=;',./[]"
local upper_ext = '!@#$%^&
()_+:"<>?{}'
if string.find(lower_ext, args.key, nil, true) and args.caps then
args.key = string.sub(string.sub(upper_ext,string.find(lower_ext, args.key, nil, true)), 0, 1)
end'''
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '0' then args.key = 'o' end'''
position = "at"
payload = '''if args.key == '0' and G.CONTROLLER.text_input_hook.config.ref_table and G.CONTROLLER.text_input_hook.config.ref_table.ref_value == "setup_seed" then args.key = 'o' end'''
match_indent = true
overwrite = false

daring fern
pastel kernel
#

i need help

pastel kernel
#

pls

keen atlas
#

wheres your ui code

pastel kernel
#
version = "1.0.0"
dump_lua = true
priority = 0

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '[' or args.key == ']' then return end'''
position = "at"
payload = ""
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''    local lower_ext = '1234567890-=;\',./'
    local upper_ext = '!@#$%^&*()_+:"<>?'
    if string.find(lower_ext, args.key) and args.caps then 
      args.key = string.sub(string.sub(upper_ext,string.find(lower_ext, args.key)), 0, 1)
    end'''
position = "at"
payload = '''    local lower_ext = "1234567890-=;\',./[]"
    local upper_ext = '!@#$%^&*()_+:"<>?{}'
        if string.find(lower_ext, args.key, nil, true) and args.caps then 
          args.key = string.sub(string.sub(upper_ext,string.find(lower_ext, args.key, nil, true)), 0, 1)
        end'''
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '0' then args.key = 'o' end'''
position = "at"
payload = '''if args.key == '0' and G.CONTROLLER.text_input_hook.config.ref_table and G.CONTROLLER.text_input_hook.config.ref_table.ref_value == "setup_seed" then args.key = 'o' end'''
match_indent = true
overwrite = false```
keen atlas
#

no, your ui code

pastel kernel
#

like for the box?

keen atlas
#

the one with create_text_input

#

yeah

pastel kernel
#

can you read it

keen atlas
#

yeah

#

do you really need to override the whole text_input_key thing

pastel kernel
#

it was suggested to me by cg

#

to be honest i'm kinda low on brain power

keen atlas
#

ill have to go too, soon

#

i might try later

pastel kernel
#

k cya

keen atlas
#

look at

.. (hook.config.ref_table.extended_corpus and " 0!$&()<>?:{}+-=,.[]_" or "")

change it to

.. (hook.config.ref_table.extended_corpus and "\" 0!$&()<>?:{}+-=,.[]_" or "")
#

@pastel kernel

pastel kernel
#

nothing

keen atlas
#

wait i can put quotation marks with that text_input_key?

#

u sure the init is called?

#

try adding print in the init

pastel kernel
#

like the corpus thing?

keen atlas
#

no like

    init = function()
        --some code to make typing more characters better
        print("init called")
pastel kernel
#

it's not printing

keen atlas
#

the init is not called then

pastel kernel
#

oh

#

well idk what to do

keen atlas
#

atleast youve gotten somewhere

#

🤷‍♂️

#

how do you load the file?

#

or just, dont put it in the init i guess

#

i gtg

pastel kernel
#

i'm gonna stick with the toml file

keen atlas
#

...k

pastel kernel
#

it works without it

#

but i'm still troubled with the apostrophe

#

and the quotation marks

#

unless somethingcom comes to the rescue and types in a behemoth of code for me to use, i'm stuck and stumped

gilded blaze
#
local a = [[this is a string]]

use the illegal stringify method tf

oblique lotus
#

Here is an odd question. I have a Joker that has multiple forms depending on how it is gotten. It uses the key = self.key .. method of giving a unique description for each one. When I try to info queue the loc text for those forms using G.P_CENTERS, I get nothing in return. Is there a way that I can get those to appear?

gilded blaze
#
info_queue[#info_queue+1] = {set = "Joker", key = "j_modprefix_key_alt"}
oblique lotus
#

Thanks!

gilded blaze
#

I deal with that a lot lmao

#

also

info_queue[#info_queue+1] = {set = "Joker", key = "j_modprefix_key_alt", specific_vars = {--[[your variables go here]]}}
#

in case your alternative key has variable slots

oblique lotus
#

It did! Thanks for saving me the headaches!

oblique lotus
#

I'm kinda struggling a bit with the specific_vars. Imagine my default Joker has the key of "j_mymod_joker" and I want to get the description of one of its forms. So far my info queue looks like this:
info_queue[#info_queue+1] = {set = "Joker", key = "j_mymod_joker_key1", specific_vars = {5}}
What would I need to do to grab the variables of the base Joker to fill the variable slots in the description?

daring fern
oblique lotus
thorn ingot
#

Would you guys know why this crashes? When I try to use the consumable and there is no more possible jokers to apply the perishable it tells me that line 37 is nil.

#

The joker:add_sticker and I don 'know why

#

first time doing things with stickers.

gilded blaze
#

that is exactly what happens to joker when you pass an empty table to get a random element out of

#

it's nil

vital wren
#

i want to change Judgement from its normal create a random joker effect to instead immediately create and open a buffoon pack. how do i get the game to just make and open a booster?

gilded blaze
#

I have the exact card in my mod, except I have to do a lot of specal casing to make sure the opened buffoon pack doesn't corrupt another opened pack

#

are you sure you want that

vital wren
#

why would it corrupt other packs?

gilded blaze
#

when you try to execute the opening at an arbitrary time

#

e.g. inside Arcana Pack

vital wren
#

oh, do you just prevent it from letting you use the card if you're already inside the pack screen?

gilded blaze
#

that's impractical

#

and makes Judgement spawned by Arcana Pack completely useless

vital wren
#

oh right. lol

#

can i see your mod?

gilded blaze
#

the code that handles opening said buffoon pack scatters across the place, so I can't really point to an exact one

vital wren
#

i see

gilded blaze
#

this is the consumable code
it sets a variable to true

#

then hook Game:update

vital wren
#

question for a possibly easier solution for me. can i make a new tag that creates a normal buffoon pack and just grant one of those tags? that should just make it open the pack automatically once its safe, right?

gilded blaze
#

yea, that's the easier way

#

I chose the hard way and believe me, it's not beginner-friendly

vital wren
#

makes sense

thorn ingot
gilded blaze
#
local joker, pos = pseudorandom_element(available_jokers, pseudoseed('summon_perish'))
if joker then
    joker:add_sticker('perishable', true)
    -- your next stuff
end
thorn ingot
#

wow

#

didn't think about placing an if

#

thank you. let me try it.

vital wren
gilded blaze
vital wren
#

great, thanks

gilded blaze
#

wait wrong key

#

it's not the tag's key, my apologies

vital wren
#

it's "tag_buffoon"

slim ferry
#

It should be add_tag(Tag("tag_buffoon"), false, "Small")

#

iirc

gilded blaze
#

Ik what I'm doing, it's my PR to SMODS anyway

#

it's just not big enough to be mentioned in the release notes

#

if you're using 1224a that is

slim ferry
#

doesnt add_tag take additional arguments

thorn ingot
#

omg,omg.
It worked and I also learned that you need to put the end before the return.

#

thanks mr jonh

gilded blaze
#

no, add_tag only takes one argument, which is the Tag object
I expanded it to also take a table, letting it do the Tag init for you

vital wren
#

i'll just steal the code from Diet Cola's sell effect and change the key

                G.E_MANAGER:add_event(Event({
                    func = (function()
                        add_tag(Tag('tag_double'))
                        play_sound('generic1', 0.9 + math.random()*0.1, 0.8)
                        play_sound('holo1', 1.2 + math.random()*0.1, 0.4)
                        return true
                    end)
                }))
            end```
gilded blaze
#

that works too

vital wren
#

thanks for all your help so far

thorn ingot
#

Another question guys.

Do you know what's the info_queue for perishable? Can't find it.

gilded blaze
#

it's the same for every other sticker

thorn ingot
#

uuu, nice. Thanks.
It's not common to see it in mods.

#

umm, It makes the game crash. Do I have to enable something first?

#

Hold on. I think I found how to add it to the localization.

thorn ingot
#

Never mind guys.
It doesn't work if you put it in localization it needs the variable and #1# doesn't work. 😭
Life
Thanks anyway for all the help you guys give though. balatroheart

swift arrow
#

how do i remove the extra space on the left and right sides of the card area objects

swift arrow
#

if i set the width to be based exactly on the number of intended cards, 2 cards stack on each other

#

very awesome how config.lr_padding is unused

primal robin
#

Im even not know about existence of this one

swift arrow
#

i'll go with padding fuckery

bright spruce
#

I am considering making my own mod, how would I start?

wild patrol
#

start with a concept

#

what do you want the mod to do

bright spruce
wild patrol
#

do you know what u want them to do

bright spruce
wild patrol
#

first thing would be to look through the smod wiki

#

then probably the vanilla wiki

bright spruce
wild patrol
#

are pretty much your starting points

primal robin
#

Cutting-edge technology goes into next level: now it's a config property which can be applied to any element

gilded blaze
#

I'm not kidding, it's a valid string in lua

pastel kernel
#

On the toml?

gilded blaze
#

you prepend 2 dashes and the entire string becomes a multi-line comment

#

that's lua for you

pastel kernel
#

So just use [[]] on the ext?

gilded blaze
#

yep

pastel kernel
pastel kernel
#

i put it on the toml

gilded blaze
#

bruh

#

it's in lua

#

you're not doing that in a patch

pastel kernel
#

oh

#

well, i'll see if i can use the corpus thing again

long sun
#

why does this code create Gold cards with invisible fronts? (no rank or suit)

if context.first_hand_drawn then
            local _card = SMODS.create_card {
                set = "Base",
                enhancement = "m_gold",
                area = G.discard,
             }
            G.playing_card = (G.playing_card and G.playing_card + 1) or 1
            _card.playing_card = G.playing_card
            table.insert(G.playing_cards, _card)

            G.E_MANAGER:add_event(Event({
                func = function()
                    G.hand:emplace(_card)
                    _card:start_materialize()
                    G.GAME.blind:debuff_card(_card)
                    G.hand:sort()
                    if context.blueprint_card then
                        context.blueprint_card:juice_up()
                    else
                        card:juice_up()
                    end
                    SMODS.calculate_context({
                        playing_card_added = true,
                        cards = { _card },
                     })
                    save_run()
                    return true
                end,
            }))

            if G.GAME.dollars > card.ability.extra.money then
                card:start_dissolve()
                card_eval_status_text(card, "extra", nil, nil, nil, {
                    message = localize("k_eaten_ex"),
                    colour = G.C.FILTER,
                    card = card,
                })
            end

            return nil, true
        end```
pastel kernel
#

i thought he meant to delete it

#

what do i do from here?

long sun
#

damn, i looked for the Certificate wording on the wiki to see if any other mods did something similar, but uhm. both of these are mine 😭

pastel kernel
#

or just the lua?

long sun
pastel kernel
#

yes

#

but i'm just trying to make ROOT ACCESS write special characters in the text box

long sun
#

ah

#

wait i think i did that with Death Note

#

hold on

pastel kernel
#

phanta or catan

long sun
#

Phanta

#

here try this

#
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''if args.key == '[' or args.key == ']' then return end'''
position = 'at'
payload = '''if (args.key == '[' or args.key == ']') and not hook.config.ref_table.extended_corpus then return end'''
match_indent = true

# why does 0 crash the game why does 0 crash the game why does
# [[patches]]
# [patches.pattern]
# target = 'functions/button_callbacks.lua'
# pattern = '''if args.key == '0' then args.key = 'o' end'''
# position = 'at'
# payload = '''if args.key == '0' and not hook.config.ref_table.extended_corpus then args.key = 'o' end'''
# match_indent = true

[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''local corpus = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'..(hook.config.ref_table.extended_corpus and " 0!$&()<>?:{}+-=,.[]_" or '')'''
position = 'at'
payload = '''local corpus = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'..(hook.config.ref_table.extended_corpus and " 0!$&()<>?:{}+-=,.[]_'" or '')'''
match_indent = true```
#

typing 0 crashes the game so sadly you can't do that

pastel kernel
#

you can write quotation marks?

#

and apostrophes

long sun
#

ah no i didn't put those in

#

apostrophes yes

#

you can add \" to the corpus if you wanna type quotes

pastel kernel
#

i used this for the 0```lua
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '0' then args.key = 'o' end'''
position = "at"
payload = '''if args.key == '0' and G.CONTROLLER.text_input_hook.config.ref_table and G.CONTROLLER.text_input_hook.config.ref_table.ref_value == "setup_seed" then args.key = 'o' end'''
match_indent = true
overwrite = false

long sun
#

okie doke

pastel kernel
long sun
#

mhm

pastel kernel
#

i can't believe i didn't consider asking you yet

long sun
#

^u^

#

is it working?

pastel kernel
#

let me check

#

maybe it's the position?

long sun
#

hmm weird, my patch doesn't replace the brackets

#

did you paste it right?

pastel kernel
#
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '[' or args.key == ']' then return end'''
position = "at"
payload = ""
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == "'" then return end'''
position = "at"
payload = ""
match_indent = true
overwrite = false

[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''local corpus = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'..(hook.config.ref_table.extended_corpus and " 0!$&()<>?:{}+-=,.[]_" or '')'''
position = 'at'
payload = '''local corpus = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'..(hook.config.ref_table.extended_corpus and "\" 0!$&()<>?:{}+-=,.[]_'" or '')'''
match_indent = true

[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if args.key == '0' then args.key = 'o' end'''
position = "at"
payload = '''if args.key == '0' and G.CONTROLLER.text_input_hook.config.ref_table and G.CONTROLLER.text_input_hook.config.ref_table.ref_value == "setup_seed" then args.key = 'o' end'''
match_indent = true
overwrite = false```
#

i believe so?

long sun
#

it's important it only works on extended corpus mode

pastel kernel
#

where exactly do i put the quotation marks

long sun
#

where?

pastel kernel
#

also wdym by first patten

long sun
#
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''if args.key == '[' or args.key == ']' then return end'''
position = 'at'
payload = '''if (args.key == '[' or args.key == ']') and not hook.config.ref_table.extended_corpus then return end'''
match_indent = true```
pastel kernel
#

oh

#

i only used the extended corpus one

#

what

#

@long sun dawg

long sun
#

no clue 😭

#

okay i seriously don't get this. this code also creates rankless gold cards

if context.first_hand_drawn then
            local _card = SMODS.add_card {
                set = "Enhanced",
                enhancement = "m_gold"
            }
            G.GAME.blind:debuff_card(_card)
            G.hand:sort()
            SMODS.calculate_context({
                playing_card_added = true,
                cards = { _card },
             })

            if G.GAME.dollars > card.ability.extra.money then
                card:start_dissolve()
                card_eval_status_text(card, "extra", nil, nil, nil, {
                    message = localize("k_eaten_ex"),
                    colour = G.C.FILTER,
                    card = card,
                })
            end

            return nil, true
        end```
pastel kernel
#

HOLY SHIT WAIT

#

I JUST REMOVED THE FUNCTION FROM THE RETURN

#

IT FUCKING WORKS

#

THE LUA WORKS

#

not the toml

#

BUT THE LUA WORKS

dreamy thunder
#

tho idk why it makes them rankless in the first place

long sun
#

ah icic

#

lemme try that

pastel kernel
#

Looks like I can finally add this card to the Bootleg consumables, and call it something like loadstring.

long sun
#

thanks!

dreamy thunder
#

np

pastel kernel
#

how do you check for if a mod is enabled?

#

for an entire file specifically

frosty rampart
#

if next(SMODS.find_mod("mod ID")) then

noble ore
frosty rampart
#

what's your goal

noble ore
#

i just want to detect if there are other mods enabled

#

i still dont know what i want with it but atleast i know earlier than later lol

frosty rampart
#

if you want to check for if any mods other than your own are active, loop over pairs(SMODS.Mods) and check if there are any other than Steamodded, Lovely, Balatro, and your own mod

#

if you want to have any specific crossmod interactions, just go check that other mod's source code to find its mod ID lol

noble ore
#

thank you ^^

bright ivy
#

-- =========================
-- BURNED EDITION
-- =========================

SMODS.Edition {
    key = "burned",
    shader = "burned",

    loc_txt = { 
        name = "Burned",
        label = "Burned",
        text = {
            "Gives between {X:mult,C:white}X2-5{} Mult", 
            "if {X:mult,C:white}X5{} Mult then destroyed.",
        }
    },

    config = {},

    in_shop = false,
    pools = {},
    weight = 0,

    sound = { sound = "foil1", per = 1.2, vol = 0.5 },

    in_pool = function(self, args)
        return false
    end,

    calculate = function(self, card, context)

        -- SCORING PHASE
        if context.main_scoring and context.cardarea == G.play then

            -- Reset destroy flag safely at start of scoring (So retriggers work as intended)
            if context.scoring_hand and not context.retrigger_joker then
                card._burned_destroy = nil
            end
            
            local roll = math.floor(pseudorandom('burned_roll') * 4) + 2 -- 2-5

            if roll == 5 then
                card._burned_destroy = true
                card:juice_up()
                return {
                    xmult = 5,
                    message = "Burned Up!",
                    colour = G.C.RED
                }
            else
                card:juice_up()
                return {
                    xmult = roll
                }
            end
        end

        -- DESTRUCTION PHASE
        if context.destroy_card 
        and context.destroy_card == card 
        and card._burned_destroy then
            return { remove = true }
        end
    end
}

I was wondering why when this gets retriggered and one of its trigers is the x5 and it says burned up it does not get removed at the end of the hand?

frosty rampart
#

context.destroy_card is only for playing cards

#

also you shouldn't need to reset the destroy flag if it's intended to be immediately destroyed anyway

red flower
#

thats what makes retriggers not work

bright ivy
#

I think I figured it out:

if context.before and context.cardarea == G.play then
                card._burned_destroy = nil
            end

Is the new code

bright ivy
frosty rampart
#

why are you resetting the flag at all
either it doesn't roll x5 and it's still nil, or it did roll x5 and it's destroyed before you get around to resetting it

frosty rampart
bright ivy
#

fair enough, Ima remove it and see if it works as intended

#

Thank yall

#

it works

oblique lotus
#

Still confused about this if someone can help give clarification

rare torrent
#

how do i made it so you can actually draw this card in your hand? right now it adds a card to my deck but i can't draw it in that specific round

            G.E_MANAGER:add_event(Event({
                    func = function() 
                        local _card = create_playing_card({
                            front = pseudorandom_element(G.P_CARDS, pseudoseed('cert_fr')), 
                            center = G.P_CENTERS.c_base}, G.deck, nil, nil, {G.C.SECONDARY_SET.Enhanced})
                        _card:set_ability(G.P_CENTERS.m_omega_sigil)
                        return true
                    end}))

                playing_card_joker_effects({true})
            end```
daring fern
oblique lotus
oblique lotus
rare torrent
daring fern
oblique lotus
daring fern
rare torrent
daring fern
rare torrent
#

ok either im getting astronomically unlucky, or you can't draw cards added to the deck at the start of the round🙏

#

what context should i use instead of context.first_hand_drawn?

slim ferry
#

first_hand_drawn happens after the hand is drawn so that would be the issue

#

you should use context.setting_blind for the same timing as marble joker

rare torrent
#

also another quick question, how do i make an enchancement remove itself (the card) at the end of round?

        if context.end_of_round then
            remove = true
        end
    end``` this didn't work
mystic river
#

that's not how that works
what you've done there is set the global variable remove to true

slim ferry
#

also returning remove = true in an arbitrary context doesnt work

#

plus its playing_card_end_of_round for playing cards, which also only triggers when it is held in hand

rare torrent
#

yeah i figured, i also tried card:remove() and self:remove() but those also didn't work since the calculate function of an enhancer only activated when a card is in the hand

#

not in the deck

#

so idk

slim ferry
#

use SMODS.current_mod.calculate

#

And loop over G.playing_cards to remove all cards with the enhancement

#

In context.end_of_round there

rare torrent
#

wait wha- where?

#

inside the calculate function of the enchancer? or forget that?

slim ferry
#

outside of the enhancement calculate

#

SMODS.current_mod.calculate just allows you to run calculate code globally and not tied to an object if needed

rare torrent
slim ferry
#

Yeah

#

You might want to add all of them into a table and then call SMODS.destroy_cards on that though

#

So you get the destruction animation

rare torrent
slim ferry
#

Oh

#

Try also checking for context.main_eval

#

Ig

#

Oh wait

#

You didnt make it a function...

#

java ahh

#

Or whatever language does code blocks like that idk

oblique lotus
rare torrent
slim ferry
#

No

#

SMODS.current_mod.calculate = function(self, context)

rare torrent
#

ah

#

ok now it works thank you!

daring fern
oblique lotus
daring fern
oblique lotus
#

Thank you so so so much!

vocal helm
#

How do I reroll a boss blind without using up Director's Cut

daring fern
vocal helm
#

Thanks!

oblique lotus
mystic river
thorn ingot
#

What does G.GAME.spectral_ratemodify?
The pack weight?

frosty rampart
#

no, i think it's the weight for spectral cards to appear in the shop

#

(so 0 most of the time)

thorn ingot
#

Makes sense. Do you know if there is any way to modify spectral pack rate?

frosty rampart
#

don't think there's anything as easy as doing it for the cards themselves in shop
you'll probably have to patch into the code where the shop creates the packs and add a rate value you can change

thorn ingot
#
    get_weight = function(self)
        if G.GAME.stake >= 5 then
            return self.weight * 2
        end
        return self.weight
    end
}, true)```

I had been using this and it works, but the problem I have with it is that I can't get it inside of a stake.
So I assume that if the player has other mods that modify the stake it won't be able to override it.
Actually, do you know if I can make it so the player can "turn off" the lua with a config change.
#

Does it make sense.

vocal helm
#
calculate = function(self, card, context)
        local end_of_ante = context.end_of_round and context.game_over == false and context.main_eval and
            context.beat_boss
        if end_of_ante and not context.blueprint then
            card.ability.extra.rerolls = card.ability.extra.rerolls_max
            return {
                message = localize('k_reset'),
                colour = G.C.GREEN
            }
        end
        if context.before then
            if card.ability.extra.rerolls > 0 and next(context.poker_hands["Flush"]) and G.GAME.blind:get_type() ~= "Boss" then
                return {
                    message = localize("j8mod_flushed_ex"),
                    colour = G.C.GREEN,
                    func = function()
                        card.ability.extra.rerolls = card.ability.extra.rerolls - 1
                        G.from_boss_tag = true
                        local thunk = G.GAME.round_resets.boss_rerolled
                        G.FUNCS.reroll_boss()
                        G.GAME.round_resets.boss_rerolled = thunk
                    end
                }
            end
        end
    end

code for context

#

additionally, I'm curious if the boss blind can be rerolled during a boss blind

red flower
#

rerolling outside the select screen is kinda jank

#

if you reroll in the middle of the blind it would do nothing afaik

split mantle
red flower
#

if you put it in calc_scaling it will create an infinite loop since thats the function scale_card calls

#

you are meant to put that in calculate

split mantle
#

okay i see

#

ty!

frosty dock
#

check if the stake is active based on a flag you set when the stake is applied instead of using stake_level, too

#

it's unreliable because stakes can branch

primal robin
#

SMODS doesnt used hook for Game:draw yet, that's so crazy

#

I'll be first

red flower
#

smods overrides game draw, no?

#

or just card draw?

primal robin
#

probably only card draw

#

I'm inserting all my stuff in ui.lua and call it a day

frosty rampart
#

you should also search for Game.draw just in case

primal robin
#

good point, no results

#

I guess we'll figure out where to put all this code inside PR, I'll create it as draft first

#

Biggest concern I have is this specific patch

#

it works but it feels somewhat wrong

grizzled tide
#

how do i make a clone a joker

granite jay
#

I set it to -1 and it works well

daring fern
# grizzled tide how do i make a clone a joker
local function better_copy_card(card, new_card, area)
    if not card then return nil end
    local area = area or (new_card and new_card.area) or card.area or G.jokers
    local cardwasindeck = new_card and new_card.added_to_deck or nil
    local copy = copy_card(card, new_card)
    if new_card and cardwasindeck then copy:remove_from_deck() end
    if card.playing_card then
        G.playing_card = (G.playing_card and G.playing_card + 1) or 1
        copy.playing_card = G.playing_card
        G.deck.config.card_limit = G.deck.config.card_limit + 1
        table.insert(G.playing_cards, copy)
    end
    if (new_card and cardwasindeck) or not new_card then copy:add_to_deck() end
    if not new_card then area:emplace(copy) end
    return copy
end
better_copy_card(card)
vocal helm
slim ferry
#

oh

#

wait nvm

#

im stupid

#

okay why is this extremely janky

#

it starts drawing cards extremely slowly

#

and theres a ghost card in there

#

for some reason

#

and it doesnt even draw a full hand

#

okay it appears to only do that after a discard

#

which is good because i only want it to trigger after hands

#

still wonder why it did that though

frosty dock
#

it somewhat makes sense that that's janky

#

i wonder what's to be improved there 🤔

slim ferry
#

i just find it wierd that its only on discard

frosty dock
#

janky hack mate

slim ferry
#

what

heavy terrace
#

Really weird issue: my calculate function works fine if I spawn in my consumable card via DebugPlus, but spawning it in using add_card within another consumable just doesn't trigger calculate at all.

The other card spawning this one puts it in a separate custom CardArea. Dunno if that has anything to do with it potentially?

#

The one in the default consumable area reaches both calculate and before prints, but the one in my custom CardArea reaches neither

tranquil cypress
wintry solar
slim ferry
#

Draw an extra card after hand for each held 8

#

It works fine after a hand but not after a discard

#

Discard isnt relevant for my purpose but it happened while i was testing because i forgot a check

wintry solar
#

Hmm I wonder if discarding uses a different draw function

heavy terrace
#

All I know about them is that they're related to .toml files, I think

tranquil cypress
daring fern
slim ferry
#

If you want to actually organize the patches

tranquil cypress
#

true

heavy terrace
heavy terrace
#

Anyhow, thanks people FrostApproved

clear ocean
#

going ahead and planning out my mod before working on it, what do you think about this?

frozen hamlet
#
select_music_track = function(self)
        if joker_main  ==  G.GAME.blind then
            return 1337
        end
    end
})
vocal helm
#

just since it's been a fairly common issue with some of my Jokers here and there, is there any way to update a card's edition/enhancement/etc. mid-scoring without it counting as the previous edition
i.e. turning a stone card into a glass card, and a retrigger has it count as glass instead of stone

daring fern
vocal helm
#

that tracks, yeah

clear ocean
#

progress on blind ideas (for the must play a X card, i might have to see if i can make where it will only appear in pool if you have it in your deck to prevent decks like abandoned and checkered from being screwed)

vocal helm
#

is there any way i could make the front invisible before it upgrades?

daring fern
vocal helm
#

gotcha

frosty rampart
#

fwiw, this does happen in vanilla too iirc- if you play stone cards while you have vampire, the front appears before the enhancement visually disappears

vocal helm
#

-# really? damn

#

okay good to know

frosty rampart
#

it's less relevant with vampire tho because the enhancement is removed before cards score

clear ocean
#

formatted it better, im going to get something to eat

astral pine
#

Does anyone have an example of drawing a sprite ontop of a joker? I want to draw depending on a joker card's ability but I can't seem to wrap my head around it

daring fern
# astral pine Does anyone have an example of drawing a sprite ontop of a joker? I want to draw...
local oldmainmenu = Game.main_menu
function Game:main_menu(change_context)
    local g = oldmainmenu(self, change_context)
    G.shared_sprite = SMODS.create_sprite(0, 0, G.CARD_W, G.CARD_H, 'modprefix_atlaskey', {x = x, y = y})
    return g
end

SMODS.DrawStep{
    key = 'key',
    order = -9,
    func = function(self)
        if self.ability.condition then
            G.shared_sprite.role.draw_major = self
            G.shared_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center)
        end
    end,
    conditions = {vortex = false, facing = 'front'},
}
astral pine
#

Thank you! It seems my hook to the main menu fails though (attempt to index nil field shared_sprite), is the jokers lua file the wrong place to do all this?

sturdy compass
#

You can call G.shared_sprite whatever you want, specifically the "shared_sprite" part (and honestly should be renamed), and this hook should be done in whatever your main file is as defined by your metadata .json

random thorn
#

Hello im looking for help bugfixxing my mod

#

this is the error

sturdy compass
#

This bit here looks to be the problem, code cannot run after a return statement

#

However you did it with the pre_discard thing is how you should be doing it here