#💻・modding-dev

1 messages · Page 680 of 1

daring fern
#

G.GAME.current_round.dollars?

median veldt
#

do booster packs need inverted weights?

vale grove
# daring fern `G.GAME.current_round.dollars`?

iam trying some stuff out but do you know how to modify it? iam trying to make a joker that takes half of your cashout value and turns it into rerolls at the shop but im having trouble actually modifying the cashout value

round lion
#

why do you have to put everything in extra anyways?

#

does config = {} discard all but certain variables?

dreamy thunder
#

u dont need to put everything in extra

#

config transfers everything to the base ability table afaik

daring fern
fading rivet
#

How do I make this not say error?

round lion
frosty dock
#

done, had to take care of some feature parity first

median veldt
# fading rivet How do I make this not say error?
misc = {
  dictionary = {
    your_pack_group_name = "bluh Pack" -- e.g. bstuck2_title (this key doesnt have a prefix, i added it to mine manually in the code)
  }
}

or group_name in loc_txt if you use that

fading rivet
median veldt
#

hm

frosty dock
#

np

vale grove
#

ive been trying to work with interest modification and i just cant wrap my head around this

SMODS.Joker {
    key = "to_the_moon",
    blueprint_compat = false,
    rarity = 2,
    cost = 5,
    pos = { x = 8, y = 13 },
    config = { extra = { interest = 1 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.interest } }
    end,
    add_to_deck = function(self, card, from_debuff)
        G.GAME.interest_amount = G.GAME.interest_amount + card.ability.extra.interest
    end,
    remove_from_deck = function(self, card, from_debuff)
        G.GAME.interest_amount = G.GAME.interest_amount - card.ability.extra.interest
    end
}

why does this line work
G.GAME.interest_amount = G.GAME.interest_amount + card.ability.extra.interest
assuming you have 25+ bucks isnt this just
5 = 5 + 1 ?
because of this
interest = 1
why does this accurately give 10

frosty dock
#

it's interest per $5 you have, not the interest limit or a flat bonus

#

this exists because of green deck

vale grove
#

okay so im trying to make a joker that removes your interest (that part was simple)
and converts the amount removed into bonus rerolls in the shop

#

and i just cant get it to work for the life of me

#

like the interest system is so confusing

#

like for example for testing i copied the to_the_moon code and added this line

        SMODS.change_free_rerolls(G.GAME.interest_amount)
#

but that always gives 2 no matter what

frosty dock
#

again interest_amount isn't the amount of interest gained this round

#

you have to get the value at cash out and potentially save it for later use

vale grove
#

i just cant really wrap my brain around the fact that modifying

        G.GAME.interest_amount = G.GAME.interest_amount + card.ability.extra.interest

interest like this accurately does anything

        SMODS.change_free_rerolls(G.GAME.interest_amount)

while this doesnt

frosty dock
#

it's just a static value used in calculating interest

vale grove
#

ohh like that

#

what would be the way to accurately get the value of interest then?

frosty dock
#

look where cashout happens, I can't tell you off the top of my head

vale grove
#

my original idea was a joker that took half your cashout value and transformed it into rerolls

#

realised that was too difficult for me, now this also seems way above my league

red flower
#

(or copy what that does)

vale grove
#

oh thats actually interesting

fading rivet
sturdy compass
#

Someone who would also use final cashout holy shit

#

I feel vindicated

vale grove
#

its not the first time ive been cucked out of a cool idea by that just being impossible bcs im a very bad lua programmer

#

also completely seperate question

#

is there a context check for adding/redeeming a tag?

frosty rampart
vale grove
limber aspen
#

How do vanilla jokers calculate their effect? Card:calculate_joker just scales it and G.P_CENTERS[key] table doesn't have calculate function

sturdy compass
#

calculate_joker is more than just scaling

frosty rampart
#

it should be in calculate_joker, some vanilla jokers are grouped by card.ability.effect (e.g. gluttonous, lusty, etc. all have "Suit Mult" in their effect so they aren't checked for by name in the function)

sturdy compass
#

in fact, that's also where modded jokers get called too

frosty rampart
limber aspen
#

Banner but preferably all of them, I want to hook calculate function to modify return value

frosty rampart
#

no need to hook, use context.post_trigger instead

sturdy compass
#

damn you beat me

limber aspen
#

Isn't it gonna trigger twice though? (First normal return, second modified)

#

I don't need just banner

frosty rampart
#

no, i'm pretty sure you can directly modify context.other_ret during context.post_trigger to modify the return value

limber aspen
#

I'll try

#

Nope!

#

Jokers have to be calculated somewhere, no?

vale grove
#

i have an info queue on a joker that creates investment tags (think diet cola)

#

why is the money nil lol

sturdy compass
#

Can you show where the info_queue is defined?

vale grove
#
    loc_vars = function(self, info_queue, center)
        info_queue[#info_queue + 1] = { key = 'tag_investment', set = 'Tag' }
        return { vars = { localize { type = 'name_text', set = 'Tag', key = 'tag_investment' } } }
    end,
#

i just looked at diet cola from vanillaremade bcs its my first time doing an info_queue for a tag

lyric wadi
#

yeah i had that mistake before, doing it this way only returns the loctext entry but not the vars for it

sturdy compass
#

For the info_queue part try info_queue[#info_queue + 1] = G.P_TAGS['tag_investment']

lyric wadi
#

you can return the vars separately as specific_vars or yeah do that and actually return the centre

sturdy compass
#

What's happening here is it's not getting the variables from investment tag in the info_queue and thus is showing nil

#

I think the method I gave handles that for you

#

the return is fine since you just want the name for it there

sturdy compass
#

hell yeah

viscid talon
#

ok so im making a variant of abstract joker that gives mult per negaitve joker held in hand

#

idk how to program it though

#
-- Negative Nancy
SMODS.Joker({
    key = "nancy",
    config = { extra = { mult = 3 } },
    loc_txt = {
        ["name"] = "Negative Nancy",
        ["text"] = {
            {
                "{C:mult}+#1#{} Mult for each",
                "{C:dark_edition}Negative{} {C:attention}Joker{}",
                '{C:inactive}(Currently{} {C:mult}+#1#{} {C:inactive}Mult){}',
            }
        },
    },
    pos = { x = 9, y = 7 },
    cost = 9,
    rarity = 3,
    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.mult, card.ability.extra.mult * (G.jokers and #G.jokers.cards or 0) } }
    end,
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                mult = card.ability.extra.mult * #G.jokers.cards
            }
        end
    end,
})
#

im currently looking over abstract's code

#

i also forgot what an info_queue was 😭

frosty rampart
#

abstract can get away with just using #G.jokers.cards to get the count of all the jokers because that's just the length of the table. you'll have to loop over G.jokers.cards and increment a counter every time you find a negative joker

viscid talon
#

ah, so just like steel joker

frosty rampart
#

ye
info_queue is used to add tooltips next to card descriptions (e.g. how steel joker displays the description for steel cards), in your case you'll probably want to use it to display negative's description

viscid talon
#

o i see

#

yeas

#
-- Negative Nancy
SMODS.Joker({
    key = "nancy",
    config = { extra = { mult = 0, mult_mod = 3 } },
    loc_txt = {
        ["name"] = "Negative Nancy",
        ["text"] = {
            {
                "{C:mult}+#2#{} Mult for each",
                "{C:dark_edition}Negative{} {C:attention}Joker{}",
                '{C:inactive}(Currently{} {C:mult}+#1#{} {C:inactive}Mult){}',
            }
        },
    },
    pos = { x = 9, y = 7 },
    cost = 9,
    rarity = 3,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

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

        local nega_tally = 0
        if G.jokers.cards then
            for _, joker in ipairs(G.jokers.cards) do
                if SMODS.has_enhancement(jokers, 'e_negative') then nega_tally = nega_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.mult, 1 + card.ability.extra.mult_mod * nega_tally } }
    end,
    calculate = function(self, card, context)
        if context.joker_main then
            local nega_tally = 0
            for _, joker in ipairs(G.jokers.cards) do
                if SMODS.has_enhancement(jokers, 'e_negative') then nega_tally = nega_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * nega_tally,
            }
        end
    end,
    in_pool = function(self, args)
        for _, joker in ipairs(G.jokers.cards or {}) do
            if SMODS.has_enhancement(jokers, 'e_negative') then
                return true
            end
        end
        return false
    end
})```
#

idk what im doing

#

nvm i think i ve figured it out

#

G.jokers and G.jokers.cards or {})

#

theorty

sturdy compass
#

yeah

#

that works

viscid talon
#

nvm

#

same error

#

updated code

#
-- Negative Nancy
SMODS.Joker({
    key = "nancy",
    config = { extra = { mult = 0, mult_mod = 3 } },
    loc_txt = {
        ["name"] = "Negative Nancy",
        ["text"] = {
            {
                "{C:mult}+#2#{} Mult for each",
                "{C:dark_edition}Negative{} {C:attention}Joker{}",
                '{C:inactive}(Currently{} {C:mult}+#1#{} {C:inactive}Mult){}',
            }
        },
    },
    pos = { x = 9, y = 7 },
    cost = 9,
    rarity = 3,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

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

        local nega_tally = 0
        if G.jokers.cards then
            for _, joker in ipairs(G.jokers and G.jokers.cards or {}) do
                if SMODS.has_enhancement(jokers, 'e_negative') then nega_tally = nega_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.mult, 1 + card.ability.extra.mult_mod * nega_tally } }
    end,
    calculate = function(self, card, context)
        if context.joker_main then
            local nega_tally = 0
            for _, joker in ipairs(G.jokers and G.jokers.cards or {}) do
                if SMODS.has_enhancement(jokers, 'e_negative') then nega_tally = nega_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * nega_tally,
            }
        end
    end,
    in_pool = function(self, args)
        for _, joker in ipairs(G.jokers and G.jokers.cards or {}) do
            if SMODS.has_enhancement(jokers, 'e_negative') then
                return true
            end
        end
        return false
    end
})```
sturdy compass
#

Check for G.jokers and not G.jokers.cards in your loc_vars

viscid talon
#

oke

sturdy compass
#

also you're using SMODS.has_enhancement to look for an edition which will not work

viscid talon
#

oops 😭 meant to do has_edition

sturdy compass
#

I don't think that exists

viscid talon
#

WHAT

#

jokers.edition?

#

mebbe

sturdy compass
#

You'd check for if joker.edition and joker.edition.negative

viscid talon
#

this is the code for divine love letter which has a slightly similar effect

#

hmm

mystic river
viscid talon
#

yeas

sturdy compass
#

Here's a loop I've used for checking negative before but you can pretty easily change it

#

-# in reality it's checking for negative, non-eternal, and not getting destroyed but I digress

viscid talon
#

i see :o

#

so i could rewrite it as smth like

#

acc wait

#

nvm i think ive slowly begun figuring it out

sturdy compass
#

w

viscid talon
#
-- Negative Nancy
SMODS.Joker({
    key = "nancy",
    config = { extra = { mult = 0, mult_mod = 3 } },
    loc_txt = {
        ["name"] = "Negative Nancy",
        ["text"] = {
            {
                "{C:mult}+#2#{} Mult for each",
                "{C:dark_edition}Negative{} {C:attention}Joker{}",
                '{C:inactive}(Currently{} {C:mult}+#1#{} {C:inactive}Mult){}',
            }
        },
    },
    pos = { x = 9, y = 7 },
    cost = 9,
    rarity = 3,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS.e_negative

        local nega_tally = 0
        if G.jokers then
            for _, joker in ipairs(G.jokers and G.jokers.cards or {}) do
                if joker.edition and joker.edition.key == "e_negative" then nega_tally = nega_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.mult, card.ability.extra.mult_mod * nega_tally } }
    end,

    calculate = function(self, card, context)
        if context.joker_main then
            local nega_tally = 0
            for _, joker in ipairs(G.jokers) do
                if joker.edition and joker.edition.key == "e_negative" then nega_tally = nega_tally + 1 end
            end
            return {
                Xmult = 1 + card.ability.extra.xmult * nega_tally,
            }
        end

        in_pool = function(self, args)
            for _, joker in ipairs(G.jokers or {}) do
                if joker.edition and joker.edition.key == "e_negative" then
                    return true
                end
            end
            return false
        end
    end
})```
#

this might be it

#

im so fucking scared

#

ok uh nvm it just gives +1 mult no matter what, for some reason

#
-- Negative Nancy
SMODS.Joker({
    key = "nancy",
    config = { extra = { mult = 0, mult_mod = 4 } },
    loc_txt = {
        ["name"] = "Negative Nancy",
        ["text"] = {
            {
                "{C:mult}+#2#{} Mult for each",
                "{C:dark_edition}Negative{} {C:attention}Joker{}",
                '{C:inactive}(Currently{} {C:mult}+#1#{} {C:inactive}Mult){}',
            }
        },
    },
    pos = { x = 9, y = 7 },
    cost = 9,
    rarity = 3,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",
    loc_vars = function(self, info_queue, card)
        info_queue[#info_queue + 1] = G.P_CENTERS.e_negative

        local nega_tally = 0
        if G.jokers then
            for _, joker in ipairs(G.jokers and G.jokers.cards or {}) do
                if joker.edition and joker.edition.key == "e_negative" then nega_tally = nega_tally + 1 end
            end
        end
        return { vars = { card.ability.extra.mult, card.ability.extra.mult_mod, card.ability.extra.mult_mod * nega_tally } }
    end,

    calculate = function(self, card, context)
        if context.joker_main then
            local nega_tally = 0
            for _, joker in ipairs(G.jokers) do
                if joker.edition and joker.edition.key == "e_negative" then nega_tally = nega_tally + 1 end
            end
            return {
                mult = 1 + card.ability.extra.mult * nega_tally,
            }
        end

        in_pool = function(self, args)
            for _, joker in ipairs(G.jokers or {}) do
                if joker.edition and joker.edition.key == "e_negative" then
                    return true
                end
            end
            return false
        end
    end
})

i have no idea what im doing wrong

frosty rampart
#

ipairs(G.jokers.cards), not G.jokers

sturdy compass
#

your return math is using card.ability.extra.mult which does not exist

#

or I mean it's zero

viscid talon
#

oop

viscid talon
sturdy compass
#

you do not need the 1 + either since this is +mult and not Xmult

viscid talon
#

mmmm,

#
            return {
                mult = card.ability.extra.mult + (card.ability.extra.mult_mod * nega_tally),
            }
        end
frosty rampart
viscid talon
#

o i see

#

wait whats the difference between G.jokers and G.jokers.cards anyways

frosty rampart
sturdy compass
#

In all honestly you don't even need that mult value here lmao

viscid talon
#

i dont? :o

sturdy compass
#

lmfao brainwave

viscid talon
#

interessant

frosty rampart
viscid talon
#

:o i see

frosty rampart
#

and that applies for all cardareas

viscid talon
#

i might have figured it out MAYBE

frosty rampart
#

yayyy

viscid talon
#

defo gonna buff it to +8 mult tho

#

bc its a rare

sturdy compass
#

mhm

dapper sun
#

kinda seems like a worse abstract joker rn tbh

viscid talon
#

yeas but i cant rly think of any other changes atm

#

it will probably remain pretty crappy but thats fine

wanton jolt
#

+12

viscid talon
#

ok

tidal hemlock
frosty rampart
#

yea looping through G.jokers.cards includes the card currently being calculated

viscid talon
#

this + paper plane is fucking broken

#

im curious to see how this setup would go

#

+11 mult is no joke

#

what the fuck is this glitch

#

wait wrong channel

royal carbon
#

Ok how the fuck do probabilities work post-0711a? My prob is getting affected twice as much by Oops and presumably similar stuff (ie it's going from 1 in 2 without to 4 in 2 with)
Code is:

local new_num, new_denom = SMODS.get_probability_vars(center, G.GAME.probabilities.normal, center.ability.extra.odds, "acornling")
return {vars = {new_num, new_denom}}```
sturdy compass
#

Don't use G.GAME.probabilities.normal

#

Just use 1

royal carbon
#

Even for the actual check later, or just in the loc vars?

frosty rampart
#

yes even for the actual check

sturdy compass
#

even for the check

royal carbon
#

👍

frosty rampart
#

all the probability functions that smods provides already take G.GAME.probabilities.normal into account

sturdy compass
#

What's happening is oops will still double that value, and when you pass it into the probability func, it doubles it again

frosty rampart
#

and oops all 6s is the only thing that should be touching that variable directly

#

we are really on the same wavelength today lmao

sturdy compass
#

fr lmao

royal carbon
#

It's still doubling it twice kabbuTHONK

sturdy compass
#

Did you save the change/start a new run?

frosty dock
#

new run shouldn't matter

sturdy compass
#

I meant new copy of the joker

royal carbon
#

I didn't save the file.

sturdy compass
#

lol

frosty dock
sturdy compass
#

Why not? Wouldn't an already created joker still hold the old functions?

frosty rampart
#

the functions actually get copied from the center when a save is loaded apparently
(because they can't be saved i assume)

sturdy compass
#

mm I see

frosty dock
#

yeah functions are unserializable

wanton jolt
#

how do i make a new starting_param? i want my card sleeve to change the card limit in my custom area

#

directly changing the card limit in the apply function crashes the gam

frosty dock
#

just set the param in apply?

#

or an event in apply should do

wanton jolt
#

thank you

red flower
#

<@&1133519078540185692>

rapid stag
#

are they starting to avoid the honeypot channel?

#

activity data seems to imply it posted in it girldmHuh

frosty dock
rapid stag
#

oh true

livid scroll
rapid stag
#

ahhh, the bot can't delete all their messages

frosty dock
#

that's a classic discord moment

livid scroll
frosty dock
#

Sure is

upbeat oracle
#

a bit ago someone gave me a github guide for making balatro mods, I forgot to bookmark it and lost it does anyone know what im talking about, if so can you find it???

cursive sentinel
#

Tried to make it so player cant draw anymore after first draw, but it just seems to not draw at all (which is a soft lock as well), what did i do wrong?

if context.setting_blind and not context.getting_sliced then
            G.hand:change_size(card.ability.extra.draw)
            G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + card.ability.extra.draw
        end

        if not context.first_hand_drawn then
            if context.stay_flipped and context.from_area == G.deck and context.to_area == G.hand then
                return {modify = {to_area = G.deck}}
            end
        end
upbeat oracle
#

thanks

frosty dock
daring fern
frosty rampart
#

it says if not context.first_hand_drawn

daring fern
frosty rampart
#

ok well that doesn't help the issue

cursive sentinel
#

shall i make a flag?

#

that goes true at first hand drawn, and is itself a condition to stay flipped stuff?

frosty rampart
#

oh wait no yea i see the issue now
yea do that with the flag, but instead of doing stuff with context.stay_flipped, just check context.drawing_cards and return { cards_to_draw = 0 }
unless you really really want to block all other things that draw additional cards, that's a cleaner way to do it

cursive sentinel
#

will try this, thanks a lot !

frosty rampart
#

i think it's intuitive that stuff that draws extra cards overrides this effect anyway

cursive sentinel
#

will have to word it nicer then, for now it's RED saying "You can't draw anymore" with a dramatic tone

frosty rampart
#

lol fair enough

cursive sentinel
#

tried like this, but doesnt prevent drawing it seemeth, i did it wrong it seemeth

if context.setting_blind and not context.getting_sliced then
    G.hand:change_size(card.ability.extra.draw)
    G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + card.ability.extra.draw
end

if context.first_hand_drawn then
    card.ability.extra.flag = 1
end

if context.drawing_cards and context.from_area == G.deck and context.to_area == G.hand and card.ability.extra.flag == 1 then
    return {cards_to_draw = 0}
end

if context.end_of_round then
    card.ability.extra.flag = 0
end
frosty rampart
#

oh drawing_cards doesn't really have any extra stuff, remove the from_area and to_area checks

#

everything else looks good i think

upbeat oracle
frosty dock
upbeat oracle
#

lmoa

#

i use imm and downloaded smods from inside imm

#

im geussing that uses the up to date one

cursive sentinel
frosty dock
#

what smods version do you have?

upbeat oracle
#

lemme check

frosty rampart
upbeat oracle
#

actually just checked and enabled 1503a

frosty dock
#

yeah no issues there

upbeat oracle
#

ok but how would i access the smods folder since i need to do that in vs code

frosty dock
#

that's covered on the smods wiki I sent..

sturdy compass
#

You can click the installed mods button in the mods list

frosty dock
#

that too

upbeat oracle
#

???

#

but how would that help access the file in vs code

frosty dock
#

you can drag the folder into vscode

frosty rampart
#

where is the confusion coming from
you can locate the file, and then open it in vs code

frosty dock
#

or just find it in the open dialog

upbeat oracle
#

i cant find the folder

frosty rampart
#

there is literally a button in-game that takes you straight to the folder

upbeat oracle
#

oh ummmm

#

where?

frosty rampart
#

You can click the installed mods button in the mods list
-# -Astra, 3 minutes ago

cursive sentinel
#

is there a line to make you lose the blind actually?

frosty dock
upbeat oracle
#

ohh ok thank you so much

daring fern
cursive sentinel
#
calculate = function(self, card, context)
  if #G.hand.cards == 0 then
    G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false
  end
end
frosty rampart
#

make the condition if context.hand_drawn and #G.hand.cards == 0, that way it doesn't check for an empty hand before it actually draws any cards or if you beat the blind with an empty hand

formal vessel
#

how do i put an image into the mod (the 1x and 2x thing)

frosty rampart
formal vessel
#

thx!

cursive sentinel
versed swan
#

How do you add a shadow to a G.UIT.T node?

frosty dock
versed swan
#

Doesn't work

frosty dock
#

what if you add hover = true

versed swan
#

nope

frosty dock
fading rivet
fading rivet
#

why is there a shadow lmao

versed swan
#

Hmm

versed swan
frosty dock
versed swan
#

...huh

#

I'll have to double check my code

#

Because like I do set shadow on the text node but it doesnt show shadow

frosty dock
#

oh huh

#

appears the ui engine doesn't actually care about config.shadow on text nodes

primal robin
#

it is but not always

rapid stag
#

when a glass card procs and is gonna be destroyed, that's detectable in context.remove_playing_cards right? like the cards will be in context.removed

red flower
#

smods also adds .glass_trigger

rapid stag
#

as part of context?

red flower
#

as part of the card

rapid stag
#

ahhhhh

#

i assume that if i want to copy_card the destroyed card, i need to set .getting_sliced to nil?

red flower
#

i dont think copy_card copies getting_sliced

rapid stag
#

oh, nice

#

if i want to mess with the ability table of a copied card, i can do smth like

local copy = copy_card(cardHere ... )

copy.ability ... = whatever
``` ?
red flower
#

yeah

rapid stag
#

or am i overcomplicating that

rich pollen
#

Whats wrong with my localization, my description nor name show up for my joker in game?

rapid stag
frosty rampart
#

^

rich pollen
#

Uhhhh

#

Let me see if I have one of those

frosty rampart
#

you defined it in your mod's json file

rich pollen
#

Thats right

#

Thank you

#

Ok it works, thank you all

rapid stag
#

sanity check, scale_card adds the scalar value to the ref value, right?

mystic river
#

by default
you can define an operation to make it do a different thing

coral flume
#

Could I get a hand with something? I'm trying to make lucky cards of a specific rank have a 5x probability mod, I've been told a while ago that I should be looking for lucky_mult & lucky_money in context.mod_probability but I'm unsure what that means I have to do, and how I do it within the card scoring.

Here is my code so far which is detecting when a 'lucky number' is being played

  calculate = function(self, card, context)
    if context.individual and context.cardarea == G.play then
      if context.other_card.ability.name == "Lucky Card" and context.other_card:get_id() == G.GAME.current_round.idol_card.id then
        print("Lucky Number Found")
        
      end
    end
  end
red flower
coral flume
#

Cheers N' I'm pretty sure you're the person who gave me the context advice like 7 months ago lmao

rapid stag
#

what was glass's identifier? just its key?

red flower
#

glass

rapid stag
#

just glass, alright

frosty rampart
#

you can find out any identifier by putting in if context.mod_probability then print(context.identifier) end and then making sure you have debugplus installed or digging through the lovely console

rich pollen
#

Would anyone mind to explain to me what exactly a github repository does, and how to use it corectly?

Because there was some documentation that recommended I use it, but I just tried to commit a change and it spammed my code with a bunch of bullshit, talking bout some unmerged changes

rapid stag
#

source control is black magic and i refuse to attempt to comprehend it girldmDizzy

fading rivet
#

version control

#

good for collaborating with other coders

rich pollen
#

Yeah i figured that much

fading rivet
#

what exactly did it spam your code with

#

typically that doesnt happen

rich pollen
#

maybe it was >>>>>>>>>>>

#

I dont remember

fading rivet
#

or are you talking about this

rich pollen
#

Looks like the map to a metro station

fading rivet
frosty rampart
fading rivet
#

i did some janky stuff I shouldn't have done with messed up my commit tree lmao

rich pollen
frosty rampart
#

the unmerged changes stuff only pops up if the repository online has some changes that you didn't have on your local copy when you were trying to commit

frosty rampart
rich pollen
frosty rampart
#

ah fair enough

rich pollen
#

If I make it public however

#

Its not downloadable is it

fading rivet
rich pollen
#

I know literally nothing about github

frosty rampart
#

it will be downloadable yes
that's the nature of open source

rich pollen
#

I dont want it downloadable until I have a release version of the mod

fading rivet
#

iirc you can keep your code private but won't be allowed to post it in modding

fading rivet
rich pollen
#

I mean i dont really care that much

#

Idk im on the fence about it

#

This is the first time the whole unmerged changes thing has happened so

fading rivet
#

but yeah it will be downloadable to anyone with repo access

red flower
red flower
#

yes, but not because they want to post it

#

but because meta asked for them to share it now

rich pollen
#

Iet me look into it

#

Again idk how github works at all

#

Im toying with my github account

#

When committing changes, should i be doing it pretty much any time I change a single thing

#

Or can i do it like a patch notes kinda thing, cuz thats what I've been doing

red flower
#

you should do it probably everytime you do a fix or add a feature

#

how are you using git?

#

from the console or some app?

rich pollen
#

App

red flower
#

which? the github one, vscode, another one?

rich pollen
#

vscode

#

Im using that to make the mod cause im familiar with it

#

Used it in high school

red flower
#

weird, it doesnt add that for me

#

you probably committed the merge conflict file or something

rich pollen
#

I might have just done my Mekai magic and caused a problem that noone knows how to

#

Anyways imma get back to making jokers. Im at like 5 out of 140 rn

#

Idr the exact joker count but im speeding through them

red flower
#

do you do it from here?

rich pollen
#

I think so

rich pollen
#

what does that do

red flower
#

this is the git extension, it commits to the repository

rich pollen
#

And listen, idk what im doing here. I write the funny words that put the little thing in my roguelike deck builder

red flower
#

it comes by default

rich pollen
#

This is the thing I think

red flower
#

yesd

rich pollen
#

Ok fire

#

We're getting somewhere

red flower
#

just write a message and click commit and then push and it should work fine

rich pollen
#

Wait omg the little <<<<<<<< thingies are in my public repository

#

ew

red flower
#

yes

rich pollen
#

wait push

#

hit the little traingle and hit commit and push?

#

Cuz Ive been hitting commit, and then a sync button pops up

red flower
#

yeah thats fine

#

thats how i do it

rich pollen
#

Ok cool

#

so what does >>>>>>> 81e525f72380836bd917995fc626bdf591919f7e mean then

red flower
#

idk probably a merge conflict file

rich pollen
#

w h a t

red flower
#

dont worry about it

#

just delete that

rich pollen
#

I did, but its still in the repository

#

and its doing things to my vscode

red flower
#

even after you push?

rich pollen
#

Little red triangled

rich pollen
#

I can make a change and try again

frosty rampart
#

when a merge conflict happens, git will create a copy of the file that contains both versions of the code, from your local side and from the repo side. the string of numbers and letters is the commit ID, and it's basically like this

<<<<<<<<< commit1
-- the version of the code from commit1
=======
-- the version of the code from commit2
>>>>>>>>> commit2
rich pollen
#

Interesting

#

So whats a merge conflict 😭

frosty rampart
#

when the changes you have locally can't be automatically merged into the code on the repository, probably because you made too many changes in a single commit

red flower
#

when a merge conflict happens vscode should alert you and you should be able to open the merge conflict solver thingy

rich pollen
#

I went like 3 hours without committing :3

red flower
#

you probably commited that file instead of solving the conflict

frosty rampart
#

yea that's most likely what happened lol

rich pollen
#

Ok got it

#

Ive got be more smarter written in my notes app

#

that should remind me

#

My risk of rain mod is coming to fruition...

rich pollen
#

Ok then thats not what happened

#

Anywho, Ill figure it out eventually

#

This is my first programming project ever, that wasnt a school assignment

coral flume
#

Does anyone know why this code would be crashing the game when I hover overtop of Lucky Cat??

  calculate = function(self, card, context)
    if context.mod_probability and (context.identifier == 'lucky_mult' or context.identifier == 'lucky_money') and context.trigger_obj:get_id() == G.GAME.current_round.idol_card.id then
      return { numerator = context.numerator * 5 }
    end
  end
red flower
#

what is the crash

coral flume
daring fern
# coral flume

Because context.mod_probability is being called where context.trigger_obj is a fake card.

#

So you need Card.is(context.trigger_obj, Card)

coral flume
#

Thanks :)

coral flume
frosty rampart
#

no, just use it as a check before the get_id check you have

#

you need to make sure the trigger object is a real card before you do real card things to it

coral flume
#

Ohhhh Okay I think I get it

#

thanks for explaining :)

vital wren
#

does SMODS.Back have an easy config setting for blacklisting jokers, vouchers, etc.?

sturdy compass
#

You can add keys of items you wanna blacklist to G.GAME.banned_cards iirc

vital wren
#

im guessing i can add those in the back's apply method?

sturdy compass
#

yep

rapid stag
rapid stag
#

and you do G.GAME.banned_keys[itemKey] = true

naive coral
#

how do i exclude a joker from appearing in shop and how do i stop a joker appearing from a soul card

naive coral
#

ty

vital wren
#

can the eventmanager handle an event that just runs a loop until something is true and allows the rest of the game to continue on?

#

maybe using blocking = false, blockable = false ?

daring fern
vital wren
#

so i need it to run a loop to check if specific tags exist and then only perform its effect once none exist

#

oh! the functions automatically run each frame until they return true!

#

i totally misunderstood how these work

#

if i can get a confirmation, i will be at ease. will this event play each frame until there are no longer any tags with type == 'new_blind_choice'?

G.E_MANAGER:add_event(Event({ func = function()
    local _stop = true
    for k, v in ipairs(G.GAME.tags) do
        if v.config.type == 'new_blind_choice' then _stop = false end
    end
    if _stop then
        booster_tag = nil
        busy_with_tag = nil
    end
    return _stop
return true end }))
rapid stag
#

you don't need the return true after return _stop

vital wren
#

oh, oops, thanks

rapid stag
#

that might cause an error, actually

vital wren
#

im also adding a break if it finds a tag, cuz no reason to keep searching. but this should be working now right?

rapid stag
#

i was about to mention that

#

but that should do that, yes - although that's probably going to cause the game to hang all the time there's a tag with the new_blind_choice type

vital wren
#

trying to get booster pack tags to open automatically in the shop, but it was opening multiple at a time because closing a pack already tells the next one to open so it would open two at once and softlock the game x.x

rapid stag
#

not really...? have you ever used a double tag to get two tags that open packs? they get queued, and the first tag pops with it opening the pack, but the second tag sits there until you're done with the pack

vital wren
#

if i make it trigger = 'after', delay = 1 will it only check once per second?

vital wren
rapid stag
vital wren
#

if it runs each frame without lag, it's fine. but i can try to space them out to reduce lag if needed

rapid stag
#

...you could try adding blocking = false to your event table in that case?

vital wren
#

yeah i need to. now i just have a booster pack sitting on my screen lol

#

with blocking = false it works perfectly and no lag. so also no need to use a delay

#

thanks for your help

limber aspen
#

How do vanilla jokers get calculated?

rapid stag
#

in Card:calculate_joker, it's literally a giant bunch of if else statements that parse the effect based on context and joker name

limber aspen
#

It just scales the joker though

rapid stag
#

what?

limber aspen
#

For example it doesn't have j_joker

vital wren
#

all of the different contexts are in the function. so jokers will get scaled in one context, but scored in another

limber aspen
#

Oh okay sorry, thanks

vital wren
#

basic joker's scoring is on line 3980 of card.lua

daring fern
vital wren
#

where do consumeable loc_vars get set in the vanilla code?

daring fern
vital wren
#

oh weird. there's a whole thing for this for the jokers in card.lua lol

idle plaza
#

Yeah the code is not really all that organized.

vital wren
#

it feels very organized coming from hollow knight modding i will say

vital wren
#

me: why is my code not affecting the hierophant
balatro: *has misspelled hierophant's key*

idle plaza
#

Caino and Selzer can relate.

elder rune
#

Is there a function that's always called when changing the amount of money you have

vital wren
#

ease_dollars()?

elder rune
#

oh yeah

#

thought about it but I wasn't sure

vital wren
#

im pretty sure it's always used

fallen topaz
#

does anyone need art for a mod if so id be happy to help

vital wren
#

do custom jokers get added to the pool automatically or do i need to do that myself?

scenic umbra
#

You gotta do it yourself

#

Check out the vanilla remade mod on GitHub it helped me a lot with that

vital wren
#

looking at other mods that add jokers, they aren't including in_pool unless there's some special condition. that suggests to me that the default is return true

daring fern
vital wren
#

is there something randomly broken with c_lovers? im using some code to make the tarot cards update dynamically when they have editions. it's working perfectly for all the other tarot cards including the new ones ive added. but the exact same code, copy and pasted from a working tarot card, just isn't affecting lovers

pastel kernel
#
loc_vars = function(self, info_queue, card)
        if card.edition and card.edition.negative then
            return { key = "j_busterb_roffle_heavy", vars = {card.ability.extra.xmultmod, card.ability.extra.xmult}}
        else
            return { vars = {card.ability.extra.xmultmod, card.ability.extra.xmult}}
        end
    end,
``` dawg i couldn't figure out how to get it to display roffle heavy when roffle is negative
vital wren
# daring fern Code?
SMODS.Consumable:take_ownership('c_lovers',  -- object key (class prefix not required)
    { -- table of properties to change from the existing object
        config = {mod_conv = 'm_wild', max_highlighted = 2},
        loc_vars = function(self, info_queue, card)
            info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
            info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
            card.ability.consumeable.max_highlighted = card.ability.max_highlighted + valueof(card.edition)
            return { 
                vars = {
                    card.ability.consumeable.max_highlighted,
                    localize { type = 'name_text', set = 'Enhanced', key = card.ability.mod_conv },
                }
            }
        end,
        add_to_deck = function(self, card, from_debuff)
            card.ability.consumeable = copy_table(card.ability.consumeable)
            card.ability.consumeable.max_highlighted = card.ability.max_highlighted + valueof(card.edition)
        end,
    },
    true    -- silent | suppress mod badge
)
daring fern
vital wren
#

valueof(edition) just returns 1 for foil and holo, and 2 for polychrome

pastel kernel
#

i put it in joker

#

also yes that is the entry key

#

manlua return { key = card.edition and card.edition.negative and "j_busterb_roffle_heavy" or nil , vars = {card.ability.extra.xmultmod, card.ability.extra.xmult}}

#

still not working

#

it crash

#

i just found out the loc entry has no comma which is why it kept crashing

hardy vessel
#

Working on an enhancement that gives +mult to playing cards if they score in the winning hand of a round, but I can't seem to have the effect be triggered by retrigger effects such as Red Seals. I'd just use end_of_round, but I couldn't get the played hand if I did

    calculate = function(self, card, context)
        if context.after and context.cardarea == G.hand and G.GAME.chips + SMODS.calculate_round_score() >= G.GAME.blind.chips then
        local triggered = false

        for _, v in ipairs(context.scoring_hand) do
            if not v.debuff then
                v.ability.perma_mult = (v.ability.perma_mult or 0) + card.ability.extra.mult
                G.E_MANAGER:add_event(Event {
                func = function()
                    v:juice_up()
                    return true
                end
                })
                triggered = true
            end
        end

        return triggered and {
            message = localize('k_upgrade_ex'),
            colour = G.C.MULT
        }
        end
    end
vital wren
#

can context.after also accept context.individual? that might get you there

daring fern
vital wren
#

context.end_of_round and context.individual and context.cardarea == G.hand should be enough, no? it'll see the scored cards i think and will get repeated?

#

won't need a loop that way, can just apply the effect to context.other_card

hardy vessel
#

from what i'm reading, context.end_of_round doesn't support G.play/unscored so that wouldn't offer much

daring fern
drifting garden
#

how do you check if the player has a specific joker in their slots?

vital wren
#

next(SMODS.find_card('jokerkey'))

drifting garden
#

this is what I'm trying to add it to, as a condition for this to activate if and only if you have a specific Joker

local create_card_ref = create_card

function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
    local card = create_card_ref(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)

    if G.pack_cards and area == G.pack_cards then
        if _type == "Base" then
            local six_count = 0
            for _, c in ipairs(G.pack_cards.cards) do
                if c.base and c.base.id == 6 then
                    six_count = six_count + 1
                end
            end
            
            if six_count < 3 then
                card:set_base(G.P_CARDS["C_6"])
            end
        end
    end

    return card
end
vital wren
drifting garden
vital wren
#

using the full key with the mod prefix?

daring fern
drifting garden
#

!

#

what is the formatting for adding the prefix?

#

is it like prefix_key?

vital wren
#

j_modprefix_key

drifting garden
# vital wren `j_modprefix_key`

the issue im running into is that this works on its own to modify standard packs to force them to contain 3 sixes:

local create_card_ref = create_card

function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
    local card = create_card_ref(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
        if G.pack_cards and area == G.pack_cards then
            if _type == "Base" then
                local six_count = 0
                for _, c in ipairs(G.pack_cards.cards) do
                    if c.base and c.base.id == 6 then
                        six_count = six_count + 1
                    end
                end
            
                if six_count < 3 then
                    card:set_base(G.P_CARDS["C_6"])
                end
            end
        end
    return card
end

but when I add some kind of condition, it stops working, is this the correct place to put the if then check?
also i'm new to this so apologies if im doing something obviously wrong.

local create_card_ref = create_card

function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
    local card = create_card_ref(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
    if next(SMODS.find_card('j_nmb_triple_six')) then
        if G.pack_cards and area == G.pack_cards then
            if _type == "Base" then
                local six_count = 0
                for _, c in ipairs(G.pack_cards.cards) do
                    if c.base and c.base.id == 6 then
                        six_count = six_count + 1
                    end
                end
            
                if six_count < 3 then
                    card:set_base(G.P_CARDS["C_6"])
                end
            end
        end
    end
    return card
end
vital wren
#

try this

local emplace_ref = CardArea.emplace
function CardArea:emplace(card, location, stay_flipped)
    emplace_ref(self, card, location, stay_flipped)
    if self == G.pack_cards and G.STATE == G.STATES.STANDARD_PACK and next(SMODS.find_card('j_nmb_triple_six')) then
        local six_count = 0
        for _, c in ipairs(self.cards) do
            if c.base and c.base.id == 6 then
                six_count = six_count + 1
            end
        end
    
        if six_count < 3 then
            card:set_base(G.P_CARDS["C_6"])
        end
    end
end```
#

major differences being checking G.pack_cards after the card is already added and checking all the cards (both Base and Enhanced)

#

forgot to add the self to the ref call. fixed

drifting garden
#

its crashing saying length of field 'cards' is a nil value

daring fern
#

It should be c:get_id() instead of c.base.id

hidden notch
#

info_queue is being mean again :(

daring fern
vital wren
#

oh oops

#

Card:open() seems to disagree?

            G.STATE = G.STATES.STANDARD_PACK
daring fern
vital wren
#

yeah

#

does smods change that?

daring fern
vital wren
#

oh, my bad. i just comb the vanilla code when im trying to figure stuff out. i have a hard time finding things in SMODS

daring fern
vital wren
#

sorry, what's the lovely dump then?

daring fern
vital wren
#

huh. thanks

drifting garden
#

so do i need to replace c.base.id == 6 with c.get_id() == 6?

daring fern
drifting garden
#

oh mb

#

mistyped

#

and before i was doing if G.pack_cards and area == G.pack_cards. this is doing G.STATE = G.STATES.STANDARD_PACK, which is not correct?

hidden notch
drifting garden
#

i assume the self == G.pack_cards is the same sort of thing?

vital wren
#

listen to them. they have more experience than me :)

drifting garden
#

am i safe to just remove that condition?

drifting garden
#

now i just wait until it breaks something :D

daring fern
# drifting garden now i just wait until it breaks something :D
local oldcardareaemplace = CardArea.emplace
function CardArea:emplace(card, location, stay_flipped)
    local g = oldcardareaemplace(self, card, location, stay_flipped)
    if self == G.pack_cards and SMODS.OPENED_BOOSTER.config.center.kind == 'Standard' and next(SMODS.find_card('j_modprefix_key')) then
        local sixes = {}
        for k, v in pairs(self.cards) do
            if v:get_id() == 6 then
                table.insert(sixes, v)
            end
        end
        if #sixes < 3 then
            SMODS.change_base(card, nil, '6')
        end
    end
    return g
end
drifting garden
#

what would happen if i didnt check if a standard pack was being opened?

daring fern
drifting garden
#

that is cursed

vital wren
#

6 of tarot

drifting garden
# daring fern ```lua local oldcardareaemplace = CardArea.emplace function CardArea:emplace(car...

this didn't end up working, but I took what you said to make the other code work and this version seems to be working:

local emplace_ref = CardArea.emplace
function CardArea:emplace(card, location, stay_flipped)
    emplace_ref(self, card, location, stay_flipped)
    if self == G.pack_cards and SMODS.OPENED_BOOSTER.config.center.kind == 'Standard' and next(SMODS.find_card('j_nmb_triplesix')) then
        local six_count = 0
        for _, c in ipairs(self.cards) do
            if c.base and c:get_id() == 6 then
                six_count = six_count + 1
            end
        end
    
        if six_count < 3 then
            card:set_base(G.P_CARDS["C_6"])
        end
    end
end
#

probably bc i didnt read it now that i look at it

#

forgot to replace the key

#

thank you everyone

hidden notch
vital wren
#

uhhhh???? my stakes are in reverse order???? how on earth did that happen. it persists through restarts

vale grove
#

when you select them on the bottom do they also go in reverse order?

#

also im just reading up on the hone voucher (making editions more common)

SMODS.Voucher {
    key = 'hone',
    pos = { x = 4, y = 0 },
    config = { extra = { rate = 2 } },
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.rate } }
    end,
    redeem = function(self, card)
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.edition_rate = card.ability.extra.rate
                return true
            end
        }))
    end
}

is there a variable like this one but for rarities instead?
G.GAME.edition_rate

daring fern
vale grove
vale grove
#

PLEASE keep it and call it smth like the hallucination deck

vital wren
vale grove
#

aww

daring fern
vital wren
#

i didn't do anything to make it happen as far as i can tell. it just suddenly happened after i finished a run

vale grove
#

one of the few things i havent added to my mod is a new stake so i cant really help with that sadly

vale grove
frosty dock
vital wren
next timber
#

how do i create a random joker from a specific group of jokers, while still considering rarity?

red flower
next timber
#

ohh wait nvm i get it

next timber
red flower
#

SMODS.add_card { set = "objecttypekey" }

next timber
#

awesome thx

fading rivet
#

i dunno how but cryptid and UT/DR do it

vale grove
#

I'll go and have a peak overthere

fading rivet
#

does joker display have support for consumables or just jokers?

wild patrol
#

I accidentally messed up my Linux distro nearly lost everything I was working on lol

#

Thank God I pushed a couple commits to a repo for the mod

next timber
#

ok am i stupid why this isnt working

red flower
next timber
#

i do believe i did

#

thank you

red flower
fading rivet
#

waht page?

red flower
#

home

fading rivet
#

I am in fact very blind it is not only covered but directly showcased

#

thx

next timber
#

oh what the fuck

fading rivet
next timber
#

is there like

#

a way to fix it

fading rivet
#

idk

next timber
#

fuuck

fading rivet
# red flower home

should I add a check to make sure consumables isnt in there already or do you handle that later

red flower
fading rivet
#

sick

next timber
red flower
#

tell them to use dev smods?

gilded blaze
red flower
#

or do i have to do that myself

gilded blaze
#

well, no 😭

red flower
#

pls do if you have the time

gilded blaze
#

I mean, the logic isn't that hard to understand
I should probably mention now in the issue that the fix works

wintry swallow
#

is there a way to have custom text in the rules section of a challenge

red flower
fading rivet
#

How should I display values for a card that copies multiple cards for JokerDisplay?

fading rivet
#

ight

remote shell
formal vessel
#

do yall know whats wrong with this localization that this is crashing

    descriptions = {
        Back = {
            b_bstuff_none = {
                name = "None Deck",
                text = {
                    "Applies most {C:red}negative{}",
                    "{C:red}effects{} of each {C:blue}vanilla{} deck",
                    "most {C:green}positive effects{}",
                    "become {C:red}negative effects{}",
                },
            },
        },
        Sleeve = {
            sleeve_bstuffs_snone = {
                name = "None Sleeve",
                text = {
                    "Applies most {C:red}negative{}",
                    "{C:red}effects{} of each {C:blue}vanilla{} deck",
                    "most {C:green}positive effects{}",
                    "become {C:red}negative effects{}",
                }
            }
        }
    }
}```
rapid stag
remote shell
#

FINALLY

#

Optic cards transmuting enhancements and rendering them blank was a longstanding bug from Oblivion's pre-alpha that still plagues the demo so this is huge

fading rivet
#

is there a way to put these lines below or no?

wintry solar
remote shell
#

it was confirmed to be an smods bug after a lot of testing

fading rivet
#

rip

remote shell
#

it displayed the front properly before

red flower
#

only one line below for screen space reasons

fading rivet
#

ah

red flower
#

also jokerdisplay is not for explaining the effect of the card, just for reminders

#

you don't need to say that it copies the card

#

for that you read the description

fading rivet
#

this should work then

red flower
#

i would still put them in two lines, what if they have long names

fading rivet
frosty dock
fading rivet
red flower
#

3/5

frosty dock
#

I'd give it a solid 3.1/5.1

cursive sentinel
#

hi question, i have a joker that increases handsize but prevents drawing (after first hand drawn). Although, when cards are played, the space between the remaining cards isn't equalized (as in, cards stay compressed as if they were 20+ when there are only 4 remaining), anyone would happen to know? I can provide the code too
On the left what i have, on the right what i should have (with two stuntman for the example, but works also when deleting cards)

fading rivet
#

halfway fixed

frosty dock
#

otherwise things would look quite weird while drawing cards

cursive sentinel
fading rivet
frosty dock
#

if this weren't the case, cards would shrink together while drawing them

cursive sentinel
red flower
frosty dock
#

wait it does? I might be misremembering then 🤔

cursive sentinel
#

wait a sec, providing proof

cursive sentinel
#

oh fuck

#

you're right

#

it doesnt work above a certain size

rapid stag
red flower
#

where

#

i want a rework

frosty dock
#

you've been told you're working on a rework

red flower
#

i see

rapid stag
frosty dock
#

lmao

#

will you tell me I'm working on some wicked smods feature no one asked for next?

zealous path
#

does any1 know how to actually debuff the cards real time. it just appears as debuffed but the cards still works like normal

rapid stag
wintry solar
#

it might do

foggy bison
#

hi
we're simply trying to make simple face card skins (+ and ace) but it crashes the game. anyone has any idea what might be the problem? thank you

idle plaza
red flower
# foggy bison

Your key starts with " but ends with ', it's an unclosed string as a result.

:3

foggy bison
#

aight lemme try, thanks guys

#

well it doesnt crash the game but I can't select the skins in the settings lol

rigid solar
#

During context.modify_scoring_hand, is there a way to tell if the card is currently scoring or unscoring?

#

Ah I just noticed there's context.scoring_hand so I guess I can just check if it's in it

#

yeah that works ok

dry osprey
#

im extremely new to to this and have been following a specific guide

#

but why wont this

#

like

#

work

#

in the guide the "main_file"

#

turned blue

#

i dont know if it has any semblance or whatever

#

i must do

frosty dock
dry osprey
#

oooh

#

you are right

#

its so weird that its a normal comma

#

and not ;

#

like on cpp

#

thank yo

frosty dock
#

I mean a semicolon usually ends a statement, which this isn't

#

it's just object notation

#

javascript object notation for that matter, which doesn't make it better

#

but object notation

sharp jasper
#

I added a mod icon to my texture pack (bottom right) and around half of the mods without an icon switched to mine. How do I fix this

slim ferry
#

whats the modicon atlas definition

sharp jasper
#

--- STEAMODDED HEADER
--- MOD_NAME: Qwerry's Playing Cards
--- MOD_ID: qwerrycards
--- MOD_AUTHOR: [Qwerry]
--- MOD_DESCRIPTION: Playing cards if they were good


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

function SMODS.INIT.qwerrycards()
sendDebugMessage("Launching Qwerry's Playing Cards!")

local tpt_mod = SMODS.findModByID("qwerrycards")
local sprite_deck1 = SMODS.Sprite:new("cards_1", tpt_mod.path, "cards_1.png", 71, 95, "asset_atli")
local sprite_enhancers = SMODS.Sprite:new("centers", tpt_mod.path, "centers.png", 71, 95, "asset_atli")
local sprite_jkr = SMODS.Sprite:new("Joker", tpt_mod.path, "Joker.png", 71, 95, "asset_atli")

sprite_deck1:register()
sprite_enhancers:register()
sprite_jkr:register()

end

SMODS.Atlas({
key = "modicon",
path = "icon.png",
px = 32,
py = 32,
raw_key = true
})

------------MOD CODE END----------------------

slim ferry
#

remove raw_key = true

wet light
slim ferry
#

also

#

holy shit

#

fucking ancient code

sharp jasper
#

it works

slim ferry
#

0.9.8 code in the wild this is like finding a live dinosaur on the street

red flower
sharp jasper
#

nothing changed when i removed raw_key

sharp jasper
slim ferry
#

this code will break eventually

red flower
#

that code is deprecated and it's not guaranteed it will work forever and it might also be part of the issue

sharp jasper
#

ill fix it when that happens

slim ferry
#

because this is extremely old functionality that is no longer updated

red flower
# wet light

it doesn't show up at all?
did you save the files because it looks like you didn't in the screenshots

#

also the lovely.toml and the version.dll don't work like that they are not necessary

wet light
#

oh ok

wet light
#

why is my 2 jokers not showing up though????? its meowl.lua and dorito.lua

frosty dock
wet light
#

its copied over from my main.lua in my other mod

frosty dock
#

how did you come up with that

wet light
#

my other mod was made from the visual studio code, ai

frosty dock
#

oh that makes more sense

#

every part of that code is hallucinated garbage

frosty dock
# sharp jasper its just the icon, the rest works fine

the icons issue is because you're using the old format, youre changing sprite data that doesn't belong to your mod because the old version didn't even have mod icons. do what you want but no one will support you with this if you insist on using this approach

foggy bison
#

hi, I've been tinkering more with the skin mod and now it displays, but as the default cards

#

this is my code after some fixing around
for the record, there's no hc version

red flower
# foggy bison

you are removing the prfix from the atlas but then using it in the deckskin

#

prefix

foggy bison
#

so delte the prefix_config line?

red flower
#

yeah

foggy bison
#

aight lemme try

#

nope still nothing

red flower
#

hmm no idea

hoary spear
#

How should i format this effect for my flowerpot rework?

'Each scoring {C:attention}Wild Card{}',
'gives {C:chips}+#1#{} Chips per',
'{C:attention}Wild Card{} in played hand',

hoary spear
tidal hemlock
hoary spear
hoary spear
red flower
#

that's how i would word it

#

each x gives y for every z is a staple in my mod

hoary spear
#

Huh, guess i did an alr job then

tidal hemlock
hoary spear
#

I mean, yesn't, you shouldn't have to check the description just to look at the number imo

rapid stag
# foggy bison

spelling
when you removed prefix_config = {key = false}
the atlas key became kremboyz_kremboyz
but your deckskin looks for the key kremboyz_kremboys

foggy bison
#

played around with the code and the sprites appear, but the ace appeares as the jack for some reason

rapid stag
#

what's the sprite sheet look like

foggy bison
#

I tried moving the ace to the far left but then my king dissapeared

rapid stag
#

seems to be the pos style,
try setting it to

posStyle = 'suit'
foggy bison
#

cards became blank

rapid stag
#

'ranks'? girldmDizzy

foggy bison
#

yes it worked, thank you so much!
the ace is a bit jank but it's probably due to the location on the sprite itself

rapid stag
#

most likely

foggy bison
#

once again thank you very much

rapid stag
#

np

sleek valley
#

i've got a boss blind that randomises the rank of your played cards before scoring, but the chips they score that hand doesnt change with the new ranks

#

any way i could fix that?

red flower
#

dont do it in events

rapid stag
#

...it's possible to change the base amount of chips a card scores?

red flower
# red flower dont do it in events

if you need the events for the animation you need to use a flag on the card for delaying the change_base animation but i dont recall what i was rn let me see if i can find it

red flower
sleek valley
rapid stag
#

...wait a minute, i could have called :get_chip_bonus() the entire time to get the amount of chips the card will score? girldmDead

red flower
sleek valley
#

like this then?

#

wait no, i forgot to remove the assert in the event-

long sun
#

what usually causes this crash?

rapid stag
#

last time i got it, it was because i was trying to serialise something that can't be serialized, which was a function in a G.GAME var girldmDead

slim ferry
#

Trying to save a function

slim ferry
long sun
#

ah

#

so i have this code

#
local main_menu_ref = Game.main_menu
Game.main_menu = function(change_context)
    local ret = main_menu_ref(change_context)

    for k, v in pairs(G.P_CENTERS) do
        if v.set == "Joker" then
            v.in_pool = v.in_pool or function()
                return true
            end

            v.set_ability = v.set_ability or function(self, card, initial, delay_sprites) end
            local my_key = v.key

            local in_pool_ref = v.in_pool
            v.in_pool = function()
                local ret2 = in_pool_ref()
                if not ret then return ret2 end
                local blacklisted = false
                if next(SMODS.find_card("j_mxfj_blacklisted")) then
                    for _, card in ipairs(SMODS.find_card("j_mxfj_blacklisted")) do
                        for _, vv in ipairs(card.ability.extra.blacklist or {}) do
                            if vv == my_key then return false end
                        end
                    end
                end
                return ret2
            end

            local set_ability_ref = v.set_ability
            v.set_ability = function(self, card, initial, delay_sprites)
                if v.rarity == 1 and next(SMODS.find_card("j_mxfj_blacklisted")) then
                    for _, card in ipairs(SMODS.find_card("j_mxfj_blacklisted")) do
                        if card.ability.extra.blacklist then card.ability.extra.blacklist[#card.ability.extra.blacklist + 1] = v end
                    end
                end
                return set_ability_ref(self, card, initial, delay_sprites)
            end
        end
    end

    return ret
end```
#

i'm assuming it's doing that somewhere

#

but i don't see where

slim ferry
#

oh youre saving cards in the ability table

#

It seems

#

Which you cant be doing

long sun
#

oh whoops 😭

#

i meant to save the key

#

thanks!

sleek valley
red flower
sleek valley
#

wym? you only said to move the change_base outside an event, no?

red flower
sleek valley
#

weird...

final jewel
#

how do I edit the name and the desc of a joker in a take ownership

red flower
#

use a loc file

slim ferry
#

You need to override the localization entry in a locilation file

#

since localization file always takes priority over loc_txt

#

as far as i know

final jewel
#

oh so by a patch

red flower
#

no

#

if you add the vanilla key to the file it works

final jewel
#

ok

red flower
#

it's the card

#

so it would be center.config.center.taw_data

final jewel
#

oh mb

#

forgor

mystic river
rapid stag
#

if you implement a custom deck
and then beat it in an unseeded run for the first time, does the game store the fact that you beat a run with that deck anywhere? girldmDizzy

it doesn't seem to be stored anywhere; i was curious about how vanilla things worked where they had winning with a specific deck as an unlock condition, for example magic deck which needs a red deck win on any stake - which has the unlock condition that looks for type = 'win_deck', deck ='b_red'

frosty rampart
#

it applies the stake sticker to the deck

rapid stag
#

in a check_for_unlock func, how can i capture a type == 'win_deck' check? is it in args? args.type == 'win_deck'?

faint yacht
#

ye.

rapid stag
#

this balance = true gets undone during scoring. is doing balance not intended during context.before? should i try during context.initial_scoring_step instead?

faint yacht
#

Changes to score during context.before is discarded pretty much.

#

context.initial_scoring_step is where scoring actually can be affected and onwards.

rapid stag
#

ahhh

coral flume
#

Trying to make this seal only trigger on itself being destroyed


  calculate = function(self,card,context)
    if context.remove_playing_cards then
      return {
        card == self,
        dollars = self.config.money
      }
    end
  end
#

I've tried a few different ways but they either change nothing or stop it from working

#

If someone could give me some tips it would be much appreciated :)

red flower
#

have you tried

if context.remove_playing_cards then
  for _, pcard in ipairs(context.removed) do
    if pcard == card then
      return {
        dollars = self.config.money
      }
    end
  end
end
#

idk if it will work because by this point the card might not be able to calculate

coral flume
#

I didnt consider a for, I'll try that :)

#

Yo thats perfect !

#

Thanks N'

rapid stag
#

...is it possible to retrigger a probability check?
like if i do

if
  context.pseudorandom_result
  and not context.result
  and context.trigger_obj.config.center.key == 'c_wheel_of_fortune'
  -- insert other conditions here, like a probability check for example
then
  return { repetitions = 1 }
end

could i retrigger a failed wheel of fortune?

#

or does the i am have stupid

#

which is more likely

faint yacht
#

You'd need to "re-use" the consumable.

final jewel
#

how do I get the current edition of the card and its stickers too

red flower
#

of card or the card added?

rapid stag
#

the card's edition is stored in card.edition, but you'll need to nil check it because base is nil

stickers are weird.

to my understanding, card.ability['sticker key'] if the sticker is present

final jewel
red flower
#

that then

#

are you trying to transform the card?

final jewel
#

yeah

red flower
#

do card:set_ability(key) then, it will keep everything else

final jewel
#

oh ok

rapid stag
#

if i hook check_for_unlock and check for args.type == 'win_deck', how do i get the deck key?

#

i'm thinking that in those circumstances, G.GAME will always be a thing and therefore G.GAME.selected_back_key

near coral
#

How do you replace small and big blind with other custom blinds on certain stakes

#

Also, a sticker I have is meant to keep a joker debuffed until the end of the ante but it keeps removing the debuff when starting the next round

flint spindle
#

I'm trying to redo the skip tag so that it multiplies the next blind size by X0.5, and the game isn't recognizing chips. This worked for other effects within the blind but I guess it doesn't work for blind_on_deck. What do I do instead?

coral flume
#

Are seals given by their names or keys?

daring fern
coral flume
#

Right I thought so

#

Damn I have no idea why this is crashing. Could I get a hand?
This is the code and crash error.

idle plaza
coral flume
#

When using the spectral card

daring fern
coral flume
#

Legend!

#

Thats totally it 🤞

#

Yup :)

daring fern
near coral
#

Like an example blind replacement

#

On an example stake

daring fern
# near coral On an example stake
local oldresetblinds = reset_blinds
function reset_blinds()
    local g = oldresetblinds()
    G.GAME.round_resets.blind_choices.Small = 'bl_modprefix_key'
    G.GAME.round_resets.blind_choices.Big = 'bl_modprefix_key2'
    return g
end
near coral
#

So bl_modprefix_key is the blind you want to replace it with?

near coral
#

Alright

true jasper
#

how would i go through the whole deck and get all the cards of a certain rank and apply a bonus to them when a consumable is used

daring fern
true jasper
flint spindle
#

I'm trying to redo the skip tag so that it multiplies the upcoming blind's size by X0.5, and the game isn't recognizing chips. This worked for other effects within the blind but I guess it doesn't work for blind_on_deck. What do I do instead?

daring fern
flint spindle
#

ok so instead of changing the current blind choice I should just change the chips when I enter the blind

#

that makes sense

#

ty

sullen igloo
#

whats the code for the display text on a joker?

#

my slow brain isnt finding it

daring fern
sullen igloo
true jasper
#

How would I make a consumable be able to show up multiple times without showman

daring fern
true jasper
#

thank you

reef belfry
#

1.) this object inherents the same value across all other instances of it, how do I NOT make it do that

2.) How do i make it so it removes itself

(For context, the object is an extension of stickers that I based on pb's paperclips)

#
tjestuff.wp_stickers{
  key = 'digitized_wpsticker',
  atlas = 'wp_stickers_atlas',
  pos = { x = 0, y = 0 },
  badge_colour = G.C.BLUE,
  config = {extra = {percentage = 200, increment = 50, tally = 0, tally_meet = 5}},
  loc_vars = function(self, info_queue, card)
    return {vars = {self.config.extra.percentage, self.config.extra.increment, self.config.extra.tally_meet, self.config.extra.tally_meet-self.config.extra.tally}}
  end,
  calculate = function(self, card, context)
    if context.main_scoring and context.cardarea == G.play then
      self.config.extra.tally = self.config.extra.tally+1
      G.E_MANAGER:add_event(Event({  
        trigger = 'after',
        delay = 0.5,
        func = function()
          play_sound('tje_digitized_pixel')
          return true
        end    
      }))
      card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Increased!", colour = G.C.BLUE})
      self.config.extra.percentage = self.config.extra.percentage+self.config.extra.increment
      local chipval = card:get_chip_bonus()
      return { mult = -1*(math.abs(self.config.extra.percentage*(chipval/100)))}
    end
    if context.after and self.config.extra.tally == self.config.extra.tally_meet then
      self = nil
      G.E_MANAGER:add_event(Event({  
        trigger = 'after',
        delay = 1,
        func = function()
            play_sound('tje_digitized_death')
            return true
        end    
      }))
    end
  end
}
daring fern
#

Also you would do card:remove_sticker(self.key, true)

pastel kernel
#

what happens if i wrote both the set and the soul set as the same consumable set?

slim ferry
#

well then it can only spawn from that single set

true jasper
#

how did I create a card from a local table

slim ferry
#

What

left sonnet
#

Yo gang, is anyone familiar with how sets work? When you make a ConsumableType, does that stuff get added to Centers? Do you need to add anything to make create_card work?

pastel kernel
#

am i doing this right?lua G.C.EPILEPTIC = SMODS.Gradients["busterb_epileptic"]

frosty dock
#

you can use it in localization as-is with {C:busterb_epileptic}

pastel kernel
#

calculating messages

wintry solar
#

just use the gradients reference

frosty dock
#

G.C isn't special in any way, it just holds colour references. wherever you need the reference you can use the gradient directly

mystic river
#

if that function returns true (which, by default, happens iff showman is owned) then duplicate cards can appear

silent sail
#

does anyone know how to do tags? i tried editing off of vanilla remade but it doesnt show up ingame

red flower
#

the ones in vanillaremade are correct

silent sail
red flower
#

are you loading this file?

silent sail
#

oh wait how do i do thaty

#

im doing it wrong thats for sure

slim ferry
#

that means the file doesnt exist

silent sail
#

I think i messed up the patching

#

local function load_tags_file()
local mod_path = SMODS.current_mod.path
assert(SMODS.load_file("lunartag.lua"))()
end

is this right?

silent sail
#

i think i got it we all good

tall wharf
fading rivet
#

500

#

oh that's life

#

mtg

tidal hemlock
subtle hawk
formal vessel
#

so ive got no_faces and randomize_rank_suit with no_faces coming after, but its not even doing no_faces, how do i fix this
return { vars = { self.config.discards, self.config.extra_hand_bonus, self.config.extra_discard_bonus, self.config.no_interest, self.config.vouchers, self.config.consumables, self.config.consumable_slot, self.config.spectral_rate, self.config.hand_size, self.config.ante_scaling, self.config.randomize_rank_suit, self.config.no_faces , { localize { type = 'name_text', key = 'tag_double', set = 'Tag' } } } }

dapper sun
#

that's 52 cards, yea

#

no_faces isn't running at all

#

i thought maybe it was removing the face cards before randomizing the ranks but ig not

formal vessel
#

hmm

#

i do notice when looking thru vanilla remades code that it doesnt even return { vars = { self.config.no_faces } }

fading rivet
sharp jasper
#

how do i replace textures in different mods?

hardy vessel
#

Trying to make a joker that changes its card image based on the season. I have that taken care of, but the sprite is not setting when the joker is loaded. I had a method working before, but I want the current season to be permanent for whatever run that joker is currently in. Right now it always appears as summer

    set_ability = function(self, card, initial, delay_sprites)
        if initial then
            local season = "summer"
            if tonumber(os.date("%m")) <= 5 or tonumber(os.date("%m")) == 12 then
                season = "winter"
            else
                season = "summer"
            end
            card.ability.extra.form = season
            self:set_sprites(card)
        end
    end,
    set_sprites = function(self, card, front)
        if card.ability and card.ability.extra and card.ability.extra.form then
            if card.ability.extra.season == "winter" then
                card.children.center:set_sprite_pos({ x = 2, y = 11 })
            else
                card.children.center:set_sprite_pos({ x = 2, y = 8 })
            end
        end
    end
#

variable issue oops. everything works as intended lol

daring fern
formal vessel
#

oh ok, thx

#

i tried remove_faces and "remove_faces" and neither worked

formal vessel
#

lemme try to get enough of the code where it can still be understood but also where i dont need nitro to send the message

#
    key = "all",
    -- atlas = 'decks',
    pos = { x = 1, y = 0 },
    config = {
        discards = 1, -- red deck
        dollars = 10, -- yellow deck
        extra_hand_bonus = 2, -- green deck
        extra_discard_bonus = 1, -- green deck
        no_interest = true, -- green deck
        vouchers = { 'v_crystal_ball', 'v_telescope', 'v_tarot_merchant', 'v_planet_merchant', 'v_overstock_norm' }, -- magic, nebula, zodiac deck
        consumables = { 'c_fool', 'c_fool', 'c_hex' }, -- magic, ghost deck
        consumable_slot = -1, -- nebula deck
        spectral_rate = 2, -- ghost deck
        randomize_rank_suit = true, -- erratic deck
        no_faces = true, -- abandoned deck
        hand_size = 2, -- painted deck
        ante_scaling = 2, -- plasma deck
    },
    loc_vars = function(self, info_queue, back)
        return { vars = { self.config.discards, self.config.dollars, self.config.extra_hand_bonus, self.config.extra_discard_bonus, self.config.no_interest, self.config.vouchers, self.config.consumables, self.config.consumable_slot, self.config.spectral_rate, self.config.hand_size, self.config.ante_scaling, self.config.randomize_rank_suit, self.config.no_faces, { localize { type = 'name_text', key = 'tag_double', set = 'Tag' } } } }
    end,```
#

@daring fern

daring fern
formal vessel
#

yea thats what im trying to do

daring fern
# formal vessel yea thats what im trying to do
apply = function(self, back)
    for k, v in pairs(G.P_CENTERS) do
        if v.set == 'Back' and not v.original_mod then
            SMODS.merge_defaults(self.config, v.config)
            if v.name == 'Checkered Deck' then
                Back.apply_to_run({effect = {config = {}, center = v}, name = v.name})
            end
        end
    end
end
vale grove
#
    calculate = function(self, card, context)
        local rerolls = card.ability.extra.rerolls
        if context.end_of_round then
            rerolls = rerolls + 2
        end
    end,

im probably missing something stupid but why doesnt this make the number go up(dont worry about the actual functionallity its more about the actual number bcs display still has it as its base value 0 at the end of the round)

gilded blaze
#

rerolls is a number, not a reference

#

you're modifying the local variable, not the actual value

#

also do if context.end_of_round and context.main_eval then, otherwise it'll fling your rerolls to the sky

vale grove
vale grove
#
    calculate = function(self, card, context)
        local rerolls = card.ability.extra.rerolls
        if context.end_of_round and context.main_eval then
            card.ability.extra.rerolls = rerolls + 2
        end
        if context.reroll_shop and not context.blueprint then
            card.ability.extra.rerolls = card.ability.extra.rerolls - 1
        end
    end,
    add_to_deck = function(self, card, from_debuff)
        SMODS.change_free_rerolls(card.ability.extra.rerolls)
        G.GAME.interest_amount = 0
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.rare_mod = card.ability.extra.rate
                return true
            end
        }))
    end,
    update = function(self, card, dt)
        SMODS.change_free_rerolls(card.ability.extra.rerolls)
    end

iam trying to make a joker that removes interest and gives you rerolls (and make rare jokers more common) however that rerolls dont really work accurately, upon testing the rerolls continued onto -5 on the joker. how do i make this more accurate?

#

from my understanding ive done everything correctly

gilded blaze
#

*incorrectly

#

you're calling SMODS.change_free_rerolls every frame, which is wrong

vale grove
#

but why would that approach be wrong?

gilded blaze
#

what's the full ability

vale grove
gilded blaze
#

your changes seem to be permanent

#

have you considered remove_from_deck?

vale grove
#

that was the next step

#

but first it has to work while you actually have the joker

gilded blaze
#

the amount of free rerolls every shop persists throughout the run
look at how Chaos The Clown works

sharp jasper
#

how would i replace textures on other mods with my own?

#

and then put that function into a mod

vale grove
sharp jasper
#

right now i have this:

#
    if SMODS.Mods["Bunco"] then
        print("Debug Bunco")
        SMODS.Atlas({
        key = "bunc_bunco_cards",
        path = "ExoticCards.png",
        px = 71,
        py = 95,
        raw_key = true
        })
        SMODS.Atlas({
        key = "bunc_bunco_cards_hc",
        path = "ExoticCardsHC.png",
        px = 71,
        py = 95,
        raw_key = true
        })
    end

    if SMODS.Mods["Cryptid"] then
        SMODS.Atlas({
        key = "Cryptid_cry_misc",
        path = "cry_misc.png",
        px = 71,
        py = 95,
        raw_key = true
        })
    end
end```
#

but it doesnt work.

gilded blaze
#

let me rephrase the effect, is it:

2 free rerolls per shop
Earn no interest
Rare jokers appear more often
or:
At end of round, gain 2 free rerolls
Earn no interest
Rare jokers appear more often

#

note that these two are different

vale grove
#

oh i know

#

i was torn between that when making

#

but its the first one

#

but i think stacking is more fun

#
    calculate = function(self, card, context)
        local rerolls = card.ability.extra.rerolls
        if context.end_of_round and context.main_eval then
            card.ability.extra.rerolls = rerolls + 2
        end
        if context.reroll_shop and not context.blueprint then
            card.ability.extra.rerolls = card.ability.extra.rerolls - 1
            SMODS.change_free_rerolls(card.ability.extra.rerolls)
        end
    end,
    add_to_deck = function(self, card, from_debuff)
        SMODS.change_free_rerolls(card.ability.extra.rerolls)
        G.GAME.interest_amount = 0
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.rare_mod = card.ability.extra.rate
                return true
            end
        }))
    end,

currently the only bug is that you can sometimes go -1 reroll in debt which i find strange

gilded blaze
#
add_to_deck = function(self, card, from_debuff)
    SMODS.change_free_rerolls(card.ability.extra.rerolls)
    G.GAME.rare_mod = G.GAME.rare_mod * card.ability.extra.rate
end,
remove_from_deck = function(self, card, from_debuff)
    SMODS.change_free_rerolls(-card.ability.extra.rerolls)
    G.GAME.rare_mod = G.GAME.rare_mod / card.ability.extra.rate
end,

the "earn no interest" part is a bit tricky so it's not yet included here

vale grove
#

earn no interest is really easly

#

that works functionally

vale grove
#

i think the issue with is that add_to_deck runs once when obtained

gilded blaze
#

it's meant for fixed 2 free rerolls, not scaling

#

but you wanted the latter