#💻・modding-dev

1 messages · Page 668 of 1

long sun
#

oh also i shouldn't be putting that in an event

jagged sun
#

can someone please tell me why this doesn't actually ease the blind's score? it changes the value of G.GAME.blind.chips but there's no visual display

G.E_MANAGER:add_event(Event({
  trigger = 'ease',
  ref_table = G.GAME.blind,
  ref_value = 'chips',
  ease_to = 1000, --dummy value
  delay = 0.5,
  func = (function(t)
    return math.floor(t)
  end)
}))
umbral zodiac
#

its a little dumb but that is how it works

jagged sun
#

roger that, is lua gonna throw a fit if i throw in the desired value wholesale into chip_text or do i need to perform some kind of string conversion?

umbral zodiac
#

i thiiink its safe to put chip text as a number but just try it and see

jagged sun
#

(i don't program in lua often 😭)

umbral zodiac
#

note that chip text won't overwrite the value in chips and you still have to change that

jagged sun
#

yeah yeah

gilded blaze
#

when you want to update it as a whole, do this:

G.GAME.blind.chips = new_value
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
#

G.GAME.blind.chips hold the actual value you need to reach to beat the round
it can be as precise as 52.454751647856478
G.GAME.blind.chip_text is the text version of G.GAME.blind.chips with proper format so that it's short enough to be displayed, in this case it's 52.5

jagged sun
#

thank you so much

dense adder
#

Im trying to get a loop going of checking 3's in a Three of a Kind, not triggering.

 if context.before and (next(context.poker_hands['Three of a Kind'])) and not context.blueprint then
          for i = 1, #context.scoring_hand do
            if context.scoring_hand[i]:get_id() == 3 then
              card.ability.extra.ThreeCount = card.ability.extra.ThreeCount + 1
            end
          end
        
         if context.joker_main and not context.blueprint then
            if card.ability.extra.ThreeCount >= 3 then
              card.ability.extra.ThreeCount = 0
               return{ xmult = card.ability.extra.xmult}
            else
              card.ability.extra.ThreeCount = 0
            end
        end
      end
gilded blaze
#

your context.joker_main check is inside context.before

daring fern
gilded blaze
#

well, you may want tighter checks for it

dense adder
tulip pecan
#

Is there a way to make multi-line challenge rules work? do I just have to add a separate rule that does nothing for each extra line that I want to add?

gilded blaze
dense adder
#

also it won't work as i forgot te context of needing 3 threes in the played hand

#

but its working now

tulip pecan
hidden aspen
#

is there a way to render a tag so that you could read its description?
since jokers are centers i just made CardArea and put them there, no idea how to do the same for tags

hidden notch
hidden aspen
#

how come my custom context within a tag never triggers, but

#

but inside a joker it does trigger

analog spoke
#

non-code related question for y'all here, but how would you refer to "hands per round" in a description when it comes to a card that ISN'T giving them to you? My specific use I'm using this for is for a joker which gives xmult based on how many hands you have, but any way of writing it I can think of gives off the impression I'm talking about the "remaining hands" rather than the full per round amount, lol

hidden aspen
red flower
hidden aspen
#

insane, but sure

frosty dock
#

Tag calculate when balatrojoker

red flower
frosty dock
#

🥶

long sun
#

struggling with implementing an ability that doubles the values of consumables

#

i have code but it's not working

#

is there a standard way of value-manipulating things?

#

i currently have:

function smsn_multiply_all_berry_values(mult)
    for i = 1, #G.consumeables.cards do smsn_multiply_berry_values(G.consumeables.cards[i].ability.extra, mult) end
    for _, v in pairs(G.P_CENTERS) do if v.set == "Berry" then smsn_multiply_berry_values(v.config.extra, mult) end end
end

function smsn_multiply_berry_values(berry, mult) -- We shouldn't recurse down nested tables, in case a Berry wants to keep track of playing cards, or such.
    for k, v in pairs(berry) do if type(v) == "number" then v = v * mult end end
    return berry
end```
rigid solar
#

I saw that in the last smods version, context.end_of_round now also has the winning hand. How do I get it? Is context.end_of_round itself the winning hand?

#

oh it's context.scoring_hand / context.full_hand, neat

red flower
long sun
#

mm. not touching that then

shell timber
#

which is compatible with cryptlib

long sun
#

i've managed ^u^ it works now

#

i was modifying values that weren't references

hushed field
#

Consumable value manip works strangely, yeah

#

I haven't had to deal with the in-and-outs in a few months but I seem to remember there also being differences in how vanilla vs modded consumables are handled, as well as consumables like the suit or enhancement tarots vs those with their own dedicated use function

long sun
#

right, ya

analog spoke
#

okay so, forgive me if this question is simple, but I haven't modded in a while so I'm not really able to recall exactly how I'd've done this before, but how do I check for the amount of cards of a certain enhancement in my deck and use that as a variable? I want to make something sorta like cloud nice here, but with enhancements rather than rank! :3

hushed field
#

But for just doing it with a custom type, your solution seems entirely sufficient

long sun
#

i'm lucky, i'm not messing with those ^u^

hushed field
#

I wouldn't use an API for that, no. Though if you ever want to, I'd gladly help with setting up a compatibility standard for Blockbuster up for ya

analog spoke
analog spoke
#

oh thank you!
much appreciated <3

red flower
#

dont believe his lies

analog spoke
rigid solar
#

vanillaremade is a collective hallucination

#

when we open the github we have a 1 in 2 chance to create a tarot card

analog spoke
#

lmao

#

strodinger's cat situation lol

hushed field
#

n our lord made an apple and yet refuses to let us eat from it

#

🐍

agile narwhal
rigid solar
#

who doesnt

shell timber
#

i wish vanillaremade existed when i started

analog spoke
hidden aspen
#

balatro lsp is really underrated

#

its like mini docs for og sourcecode

wild patrol
#

thoughts on effect

#

thought about something dumb like +1 mult

analog spoke
wild patrol
#

actually that's pretty good lol

#

our jimbo

agile narwhal
#

peepee poopoo

urban olive
#

is there a non-cursed way of running a function when a card with a custom edition is clicked on? i'm trying to play a sound on top of the usual card select sound effect if the card has said edition

#

i could hypothetically add an update that checks if the card is highlighted, but i strongly prefer not running things per frame if an alternative exists

wild patrol
urban olive
#

sure, that works

spark sedge
#

Like today, woke up to this 😭

wild patrol
#

peepee poopoo

#

actually kinda works lol

agile narwhal
#

is this a kappa deck n oway

wild patrol
#

it's nothing special just starts a run with a twitch related joker that's it

#

also

#

May or may not release the alpha today

long sun
#

trying to code an effect that converts +mult effects into 2.5X value +chips, however it's not working

-- Thanks, TOGA's Stuff!
local calcindiveffectref = SMODS.calculate_individual_effect
SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, from_edition)
    local astros = SMODS.find_card("j_smsn_astro")
    if scored_card.config.center.set == "Joker" and next(astros) and key then
        if string.lower(key) == "mult" or string.lower(key) == "mult_mod" then
            key = "chips"
            amount = amount * astros[#astros].ability.extra.chips_times
        end
    end

    return calcindiveffectref(effect, scored_card, key, amount, from_edition)
end```
#

the effects happen normally, but also give +chips

#

why?

#

oh also Onyx Agate is unaffected

wild patrol
#

sre u want +chips or xchips

long sun
long sun
#

how do i modify the card selection limit? i remember seeing it on the smods wiki but i can't find where exactly i found it

#

ah found it

#

nevermind

wintry solar
long sun
#

so for example, Joker gives +10 Chips and +4 Mult

#

when it should only give +10 Chips

wintry solar
#

is it actually giving the mult or is it just the message?

long sun
#

mult and message

#

iirc

#

lemme check

#

aha. just the message

#

i see why then

#

it's not removing the mult message

wintry solar
#

it's because mult_mod effects have the message seperate, they don't use the built in smods auto-message functionality

pastel kernel
#

how to check for rightmost again

#

or if "the joker itself" is rightmost

red flower
#

G.jokers.cards[#G.jokers.cards]

pastel kernel
red flower
#

no, that gets the rightmost

wintry solar
#

@willow plinth how are you getting this self detected dupe?

long sun
#

what do i do then ^^;;?

wintry solar
#

you can remove the message from those effects, but the message might not always be specifically the mult one for some modded stuff

long sun
#

i see

#

i think that's okay ^^

#

if i'm changing the scoring then i can change the message too

#

how would i remove the message, though?

wintry solar
#

effect.message = nil

long sun
#

ah grand ^^ thank you!

weary merlin
#

got quips working
there's a specific easter egg quip i have where it switches the card used to a reskin of itself with a ifferent soul texture.
this, however, doesn't keep the stake sticker as on the real joker card and thus creates an inconsistency.

is there a way to force two cards to share the same stickers?
-# i have another regular joker pair i'd like to do this for too

faint yacht
#

...do you explicitly need it to be a different Joker? You could just change what textures are used for base and soul.

weary merlin
#

as for the other one, it's partially inspired by the Jekyll/Hyde gimmick of Brainless Kitty from Qualatro and follows the same gimmick. I'd want to merge those too since i did that before but it was a little buggy with tooltip displays not being updated or showing the other state

weary merlin
#

on another note i can't quite figure out how to replace the vanilla quip pool upon use of the custom quip (since it's joker-conditionahle), so i just have its weight set to 999999999
would want to proof this though so i don't have to rely on workarounds

wintry solar
#

you can put a quip_filter on your mod object to remove all the others

rapid stag
#

wait, it has to be a hook? even for a custom joker or

slim ferry
#

if you want more precise control

#

so anything that isnt adding/subtracting value

red flower
rapid stag
#

i see. does the original set_cost return anything?

or do i have to get the initially determined cost by calling the original set_cost first and then adjusting it afterwards?

#

oh, it doesn't

rapid stag
#

anyone got set_edition documentation? cirDerp

#

i'm rifling through the smods wiki and for some reason can't find anything

red flower
rapid stag
#

why does it not show up in search cirLost

red flower
#

search is not good for the wiki sadly

#

thats why i made the vremade one be all in one page

long sun
#

how do you create a random card from a pool?

#

i'm changing my Hanafudas to use pools instead of booleans in their configs

daring fern
long sun
#

thanks ^U^

wintry swallow
#

hey guys is it posibel to make a joker look iff there are ohter cards it need, Fx lets say i have to cards that can combin and i wanna look if boths cards are there befor it is abale????

long sun
#

next(SMODS.find_card("your joker key here"))

wintry swallow
#

thx man

long sun
#

ya npnp ^^

tulip pecan
#

how would I go about setting a variable inside a challenge rule description? I would assume it's some sort of #1# like others use but I'm not sure where the variable would be set.

slim ferry
#

custom challenge rules will use whatever is set as the value for it in #1#

#

im fairly certain at least

red flower
#

yes

willow plinth
#

why does my aero color card have a suit and rank??? 😭

red flower
#

lmao

wintry solar
#

I have also noticed this today

willow plinth
#

i also got the same "effect" briefly on a death card from revo's vault

wintry solar
#

it's when you copy a card

willow plinth
#

i see

willow plinth
wintry solar
#

guess it is an os issue

#

weird

willow plinth
#

maybe my launch script is also complicating things

#

i have it like this (which works but i don't think it's the "vanilla" lovely file):

#!/bin/bash
gamename="Balatro"
exename="$gamename"
defaultpath="/Users/$USER/Library/Application Support/Steam/steamapps/common/$gamename"

export DYLD_INSERT_LIBRARIES=liblovely.dylib

cd "$defaultpath"
lovefile="$defaultpath/$gamename.app/Contents/Resources/$gamename.love"
if [ ! -e "$lovefile" ]; then
    ln -s "$gamename.loves" "$lovefile"
fi
./$exename.app/Contents/MacOS/love "$lovefile" "$@"
long sun
#

how do you poll a pool?

willow plinth
#

so i guess if defaultpath was a relative path i would be fine

long sun
#

i see how create_card does it, but i'm assuming there's an SMODS function for that

long sun
#

aw

#

okie i'll write my own then

wintry solar
#

coming soonTM

long sun
#

wahoo :D!

tulip pecan
slim ferry
#

i

#

dont know if its possible to do multiple variables in a challenge description?

#

it might be but its at least not easy

long sun
#

oopsie poopsie! (this is good news because it means the pool worked properly)

#

how would i set the default of this pool, though?

slim ferry
#

default = "card key"

long sun
#

thanks ^U^

vocal helm
#

How do face card skins/playing card skins/friends of Jimbo cards work, and would there be a way to mix and match the appearances of individual ranks' appearances based on sets of deck skins

long sun
#

weird, it's still doing it

#
local pools = {
  phanta_chaff  = { default = "c_pine_chaff_a" },
  phanta_ribbon = { default = "c_pine_ribbon" },
  phanta_animal = { default = "c_plum_blossom_ribbon" },
  phanta_bright = { default = "c_pine_crane" },
}

for rkey, pool in pairs(pools) do
  if not G.P_CENTER_POOLS[rkey] then
    local reg = pool
    reg.key = rkey
    reg.cards = {}
    SMODS.ObjectType(pool)
  end
end```
timid zinc
#

Is there a way to make a message appear without returning?

mystic river
daring fern
timid zinc
#

i knew it existed but it wasnt on the wiki so i didnt know what it was called

#

Thank you

red flower
timid zinc
#

Oh

rapid stag
red flower
faint yacht
#

Or use the source code version instead of release if absolutely needed.

rapid stag
#

yeah that seems to be the solve

#

i guess that's what 'the fix' everyone has been referring to since it explodes when trying to parse a multibox description

sturdy compass
#

Did STJ finally implement multibox support???

red flower
#

i knew it did but i thought it was in an update

#

a release i mean

sturdy compass
#

Regardless, that’s a big common issue solved

#

Def weird for it to not be in a release like instantly tho

viscid talon
#

now that the new update is out, is there any way i can change the card in the title screen to a custom card

#

i think theres smth called context:title_card but idk what that is LOL

rapid stag
viscid talon
#
return {
  { key = 'j_hatch_hatchet' },
  remove_original = true
} end```
rapid stag
viscid talon
#

oh right

#

oke

#

we did it reddit

#

thank you

agile narwhal
#

my sticker's localisation values and sprite arent showing up 😭

viscid talon
#
SMODS.Joker({
    key = "burrito",
    config = { extra = { discards = 7, discard_sub = 1 } },
    loc_txt = {
        ["name"] = "Burrito",
        ["text"] = {
            {
                "{C:red}+#1#{} discards",
                "{C:attention}-#2#{} discard per round"
            }
        },
    },
    pos = { x = 6, y = 6 },
    cost = 7,
    rarity = 2,
    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.discards, card.ability.extra.discard_sub } }
    end,

    calculate = function(self, card, context)
        if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
            if card.ability.extra.discards - card.ability.extra.discard_sub <= 0 then
                SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = localize('k_eaten_ex'),
                    colour = G.C.FILTER
                }
            else
                card.ability.extra.discards = card.ability.extra.discards - card.ability.extra.discard_sub
                return {
                    message = "-1 Discard",
                    colour = G.C.FILTER
                }
            end
        end
    end,
    add_to_deck = function(self, card, from_debuff)
        G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discards
        ease_discard(card.ability.extra.d_size)
    end,
    remove_from_deck = function(self, card, from_debuff)
        G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discards
        ease_discard(-card.ability.extra.d_size)
    end
})```

fucked up but im unsure where
#

lemme send over the exact error

#
functions/common_events.lua:113: bad argument #2 to 'max' (number expected, got nil)

Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-1501a-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.9.0
Platform: Windows
Steamodded Mods:
    1: Hatchet by Plasma [ID: hatchet, Version: 1.6.0]
    2: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.5.1, Uses Lovely]
    3: Deltarune Deck by nolo33lp [ID: DeltaruneDeck]
Lovely Mods:

Stack Traceback
===============
(3) LÖVE function at file 'boot.lua:352' (best guess)
Local variables:
 errhand = Lua function '(LÖVE Function)' (defined at line 605 of chunk [lovely debugplus.console "debugplus/console.lua"])
 handler = Lua function '(LÖVE Function)' (defined at line 605 of chunk [lovely debugplus.console "debugplus/console.lua"])
(4) field C function 'max'
(5) Lua upvalue '_mod' at file 'functions/common_events.lua:113'
Local variables:
 mod = nil
 (*temporary) = C function: builtin#37
(6) Lua field 'func' at file 'functions/common_events.lua:145'
(7) Lua method 'handle' at file 'engine/event.lua:96'
Local variables:
 self = table: 0x35de4f58  {start_timer:true, timer:REAL, blockable:true, trigger:immediate, func:function: 0x35de4f30, delay:0, complete:false, time:20.51750065384, blocking:true (more...)}
 _results = table: 0x35ab6628  {blocking:true, pause_skip:false, time_done:false, completed:false}
(8) Lua method 'update' at file 'engine/event.lua:184'
Local variables:
 self = table: 0x358b58c0  {queues:table: 0x358b58e8, queue_last_processed:9.2166666666667, append_count:0, append_queue:base, queue_dt:0.016666666666667, queue_timer:9.3191175663527 (more...)}
 dt = number: 0.0178875
 forced = nil
 (for generator) = C function: next
 (for state) = table: 0x358b58e8  {unlock:table: 0x358b59d8, other:table: 0x358b5a78, tutorial:table: 0x358b5a28, base:table: 0x358b5a00, achievement:table: 0x358b5a50}
 (for control) = number: nan
 k = string: "base"
 v = table: 0x358b5a00  {1:table: 0x35783f58, 2:table: 0x35de4f58}
 blocked = boolean: false
 i = number: 2
 results = table: 0x35ab6628  {blocking:true, pause_skip:false, time_done:false, completed:false}
(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2617'
Local variables:
 self = table: 0x35188900  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x35dcb3a0, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x35d52da8 (more...)}
 dt = number: 0
 http_resp = nil
(10) Lua method 'update' at Steamodded file 'src/ui.lua:190' 
Local variables:
 self = table: 0x35188900  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x35dcb3a0, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x35d52da8 (more...)}
 dt = number: 0.0178875
(11) Lua field 'update' at file 'main.lua:1022'
Local variables:
 dt = number: 0.0178875
(12) Lua function '?' at file 'main.lua:961' (best guess)
(13) global C function 'xpcall'
(14) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
 func = Lua function '?' (defined at line 932 of chunk main.lua)
 inerror = boolean: true
 deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
 earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
red flower
viscid talon
#

OH

#

LMAO 😭

red flower
#

or discard_sub idk which one

viscid talon
#

I KNEW IT WAS A SIGHT ERROR

#

😭

agile narwhal
#

im doing this exactly the same as everyon eelse

#

whyyyyy

red flower
#

code?

agile narwhal
#

its all in the right places

long sun
#

i have a Joker that retriggers unscored cards, however a few effects aren't being retriggered

#

only scoring or money effects are being retriggered

#

is there something i can add to their return tables to say they can be retriggered?

agile narwhal
#

shrug emoji 😭

#

bro smods hates me

red flower
#

yeah i dont see anything wrong

agile narwhal
#

i wonder

#

if i wipe the profile

agile narwhal
#

nop

long sun
#

okay this code is trash 😭 i didn't return anything

#

i used card_eval_status_text

#

it'll probably work when i return something

#

that has indeed solved the problem

agile narwhal
# agile narwhal i

finally figured it out, when you override apply you have to set card.ability.[sticker key] to true

reef bobcat
#

ok so im making a joker that's like madness but it levels up every poker hand instead of giving itself xmult

#

i tried to copy black hole

#

in place of where normally it would gain mult

#

but the game's not responding to that at all

#

ok i figured it out

#

nvm

random basin
#

any explanation as to why using m_lucky as a quantum enhancement seems to affect all of my played cards instead of just the ones with a seal adding it?

        if context.final_scoring_step and context.cardarea == G.play then
            return {
                xchips = card.ability.seal.extra.xchips,
            }
        end
        if context.check_enhancement then
            return {
                m_lucky = true
            }
        end
    end```
red flower
random basin
#

ah I see it now, I need to check if the seal is on the current card during scoring right

red flower
#

depends on the effect

#

if you just want the card to always be considered lucky just check context.other_card

random basin
#

and context.other_card doesn't work

red flower
random basin
#

nor context.other_card.seal == [seal]

red flower
random basin
#

i'll try nesting it instead of and

red flower
#

i dont see what the difference would be

#

is the key correct?

random basin
#

should be

#

both with and without mod prefix it fails

#
        if context.final_scoring_step and context.cardarea == G.play then
            return {
                xchips = card.ability.seal.extra.xchips,
            }
        end
        if context.check_enhancement then
            if context.other_card.seal == "modern" then
                return {
                    m_lucky = true
                }
            end
        end
    end```
red flower
#

can you print context.other_card.seal in that context

random basin
#

sure

#

still doesn't work with the correct name

#

must be context.other_card in some way then

red flower
#

what does it print

random basin
#

nil for cards with none and [modprefix]_modern for the ones that do have it

#
        if context.final_scoring_step and context.cardarea == G.play then
            return {
                xchips = card.ability.seal.extra.xchips,
            }
        end
        if context.check_enhancement and context.other_card.seal == "fgc_modern" then
            return {
                m_lucky = true
            }
        end
    end
}```
#

this fails

red flower
#

how does it fail, does it still do all of them

#

or none

random basin
#

never applies lucky properties

red flower
#

weird..

#

i think quantum enhancements are evil

random basin
#

true

#

I should just manually write out my own lucky card odds table here

#

probably more fun that way anyway

#

cool this works

        if context.main_scoring and context.cardarea == G.play then
            local ret = {}
            if SMODS.pseudorandom_probability(card, 'lucky_mult', 1, card.ability.seal.extra.mult_odds) then
                card.lucky_trigger = true
                ret.mult = card.ability.seal.extra.mult
            end
            if SMODS.pseudorandom_probability(card, 'lucky_money', 1, card.ability.seal.extra.dollars_odds) then
                card.lucky_trigger = true
                ret.dollars = card.ability.seal.extra.dollars
            end
            G.E_MANAGER:add_event(Event {
               func = function()
                   card.lucky_trigger = nil
                   return true
               end
            })
            return ret
        end
    end
}```
red flower
#

that is very funny

wicked sonnet
#

Ok, so, im having a bit of a problem, im trying to make it so that the Joker counts how many light and dark suits are in a played hand, and if they are equal, it adds 0.2 for every pair, and tho its currently somewhat working, it can only detect if its equal, and Im not sure what causes it, idk if someone can help me out

red flower
wicked sonnet
red flower
#

you dont even need the context.individual part, you can just do the counting in joker_main directly by iterating on context.scoring_hand

wicked sonnet
red flower
tulip pecan
#

What's the best way to read this 20 value? I've found that SMODS.Challenge.obj_table.c_uma_unstable_income.rules.custom[1].value works, but was wondering if there was an easier way

tulip pecan
#

yeah that tracks

tulip pecan
# daring fern `G.GAME.modifiers.uma_tax`

Do you know if its possible to have multiple values stored in the challenge rule? or is it limited to 1? I tried a bunch of things earlier but nothing ever worked with the description (#1#, #2#, etc.)

wicked sonnet
rapid stag
#

is no_juice not working for anyone else?

urban wasp
#

a function for ordering jokers inside the collection still doesn't exist, right?

rapid stag
#

honestly, how would that even work? i wonder how that could be done in a way that doesn't have mods arguing with other mods about how the collection should be ordered. would one mod take precedent, or

umbral zodiac
rapid stag
#

or other weird niche cases like "i want everything all crazy style but legendaries go at the back"

umbral zodiac
#

for the latter higher mod priority
for the former they should probably not want that , messing with vanilla collection order is just annoying unless its fully wanted by the player, in which case they should download a mod that specifically does that

urban wasp
urban wasp
#

wait lmao i didn't even recognize you

#

well in any case hi lily

#

er

#

ophelia, now

umbral zodiac
rapid stag
#

i mean, i guess

umbral zodiac
urban wasp
#

any reason for the name change or just because you felt like it?

#

(which isn't like unreasonable btw)

umbral zodiac
#

felt my first major bout of dysphoria tonight and i needed to do something

urban wasp
#

ah

#

well hope you're alright

umbral zodiac
#

im fine enough

urban wasp
#

doesn't sound particularly fun

umbral zodiac
#

yum blinds

urban wasp
#

well i sincerely hope you feel even better soon

urban wasp
umbral zodiac
urban wasp
#

"will continue to be" is really what matters here

umbral zodiac
urban wasp
# umbral zodiac yum blinds

so like super hard blind but it doesn't actually like end your run or anything and gets you an exquisite joker if won?

umbral zodiac
#

yes

#

no stakes but high reward

#

its only spawned by the valkredux equivalent of gateway

urban wasp
#

yea so like a little reward if you can beat this challenge

umbral zodiac
#

ugh i have to convert it to blindexpander if i want it to be good though

urban wasp
#

what's that?

umbral zodiac
#

api mod which primarily adds 'passives' for blinds
which are basically just mini blinds that you can apply to any boss blind easily

urban wasp
#

"mini blinds"? what does that mean?

umbral zodiac
#

theyre just blinds except no sprite or anything and they dont spawn

#

like you could have a passive for -1 discard and then apply that to any other boss blind in your mod and itd have that effect as well

urban wasp
#

in all honesty, i'm not exactly following... but, it seems pretty ambitious and fun

umbral zodiac
#

its bsaically just a way to modularly split blind effects into easier to read chunks

urban wasp
#

oh i see

#

like multiboxes but for blinds?

umbral zodiac
#

basically but the multiboxes are actually the effects rather than just extra text for fun

urban wasp
#

are multiboxes usually used for fun? most of the time i see them it's just to split up long effect descriptions on jokers/(rarely) consumables

umbral zodiac
#

by 'for fun' i mean being able to be split arbitrarily

#

with blindexpander you would define each passive and its loc seperately and then just define all the passives that the blind uses

urban wasp
#

oh i see (again)

umbral zodiac
#

so the split for multiboxes is not arbitrary

urban wasp
#

okay now i understand

#

that's cool

#

pretty useful for really long stuff like the blind you posted

#

wh

#

what

gilded blaze
#

Unrestrained curiosity can lead to forbidden knowledge you can't unsee.

urban wasp
#

is shakespeare really dead?

gilded blaze
#

I didn't mean it to rhyme

tulip pecan
distant junco
red flower
#

i can probably pr a way to add more vars later today doesn't seem very hard

past spade
#

trying to fix a joker that discards your hand. The problem is discard_cards_from_highlighted is constrained by the 5 card highlight limit and draw_from_hand_to_discard has weird delay and doesnt trigger discard effects. Is there some better way to implement this? just looping over a few cards at a time with discard_from_highlighted?

red flower
fading rivet
#

how can I add a custom UI into info_queue?

past spade
#

alright next issue, there does not seem to be any safeguards against discarding the same card twice, so if I have two copies of the joker all discarded cards get duplicated. probably will just need to patch discard_cards_from_highlighted to fix this

red flower
fading rivet
red flower
#

so just normal text?

fading rivet
#

yeah

#

I only know how to do it with P_CENTER's or similar though

red flower
fading rivet
#

thx

#

ah thats easier than I thought

#

no UI jank yay

granite raptor
#

any advice for wording this better? the idea is basically that aces give more xmult the more you have in the scoring hand (e.g. if you play a high card ace then the ace is worth 1.2x mult, if you play a pair of aces each ace is 1.4x mult, so on) but i feel like this makes it look like a high card ace would give 0.2x mult when scored, as in reducing your mult by 80% - but if i rewrite it to 1.2x mult, then it would look like a pair of aces would give 2.4x mult for each ace, which isn't how it works. i'd rather not write "1x mult + 0.2x mult for each ace in scored hand", because while accurate that's rather wordy. there's gotta be a better middle ground here

wild patrol
# urban wasp

Reminds me of that old conspiracy theory from note pad people thought Bush hid the files turning into [][][] when you saved it was Microsoft hiding something lol

#

When in reality it was just a bug

wild patrol
#

And any sentence with same structure would result in same thing

granite raptor
fading rivet
#

time to see if I understood the wiki enough to add my own context

granite raptor
#

can one add calc_dollar_bonus to something other than jokers? or just a custom means for variable end-of-round money? (for reference, i'm attempting to make a custom seal, you earn $1 at end of round for every card in your full deck with that seal)

wanton jolt
#

perma_p_dollars, -- money on scoring
perma_h_dollars, -- money on held at end of round (like gold cards)

granite raptor
#

neither of those would work though, no? i'm trying to make it so it's money at end of round in full deck, like cloud 9 does for 9s

wanton jolt
#

ohhhhhh

#

in full deck?

#

ohhhh

#

i get it

fading rivet
#

any idea why the bottom 2 methods are nil on instances of the card?

wanton jolt
red flower
red flower
wanton jolt
#

oh okay

fading rivet
red flower
fading rivet
#

thx

#

can I access it with self:func in the code or do I need to do that too

red flower
#

yes

granite raptor
wanton jolt
#

yeah i understood after n' clarified

red flower
#

you can use mod calculate and context.round_eval to add it

#

but i dont have an example for that

wanton jolt
#

i can't find any

#

on github

#

wait you can use it on vouchers too right

#

nvm

fading rivet
#

okay its halfway working (maybe)

#

yay it works

hidden aspen
#

is it theoretically possible to change the deck during a game zeflynHmm

#

G.GAME.selected_back and G.GAME.selected_back_key seem related to this, im gonna check what happens if you change it

rigid solar
#

You can apply a new deck, but to remove the previous one you'd have to hardcode something for some of them (like hardcode -1 discard if you lose red deck)

#

I havent tested it yet but I was told this works to apply a new deck

red flower
#

that sounds really janky

rigid solar
#

As I said I havent tried it

#

Pokermon recently released a challenge that applies a random Pokermon deck to the challenge and I believe that's more or less how it was done

#

Im not yet in a stage of my mod where I can really use these kind of effets so I havent looked much into it

red flower
#

i mean it should work it just wouldn't support any modded decks and you would likely need to take decisions as to what 'unapplying' some decks means and even then it might behave badly if you apply magic deck when you have full consumable slots or something

#

this would be better as a separate api first probably

rigid solar
#

Definitely

fallen timber
#

Hey, im codding a mod and stumbled upon an issue, i cant access mult for some reason.
The joker supposed to get current mult and do operations based on it (odd/even mult events, maybe other stuff later on)
While ive seen some mods using G.GAME.chips, for me G.GAME.mult is just nil
I even tried to get mult from context.mult, its a nil too

fallen timber
frosty dock
#

W vremade wiki

fading rivet
#

can I make a seal on a playing card trigger during context.individual or no

red flower
#

why

fading rivet
#

I wanna make a seal that makes cards in-between it an another sealed card give x1.2 mult

#

like

seal card card seal card

card 2 and 3 would give x1.2 mult

red flower
#

you can probably use mod calculate for that

fading rivet
#

ight, thx

#

its just self, context right

granite raptor
#

how does one get the card representing the deck, i.e. the one in the bottom right you can click to view deck & drag around and stuff?

frosty dock
#

G.deck.cards[1]

granite raptor
#

and to be safe is that nil if you've already drawn every card from the deck?

frosty dock
#

yes

fading rivet
#

do playing cards not store an instance of their seal on them, just the key?

red flower
#

afaik, yeah

frosty dock
#

what's an instance of a seal?

#

you have card.ability.seal, which mirrors the config values

fading rivet
frosty dock
#

they also only store config values

#

oh wait you have config.center

fading rivet
#

for getting the config of a seal would it be
G.P_SEALS.my_seal.config

frosty dock
#

for the config you have it in card.ability.seal

#

which has the advantage of not being static

fading rivet
#

thx

frosty dock
#

if you need other properties of the prototype that you'd access with config.center on enhancements, what you said is right

wintry solar
#

You shouldn’t often need those though

frosty dock
#

yep

tulip pecan
#

Less risk of my user error

red flower
#

i guess

agile narwhal
#

how do i check if a card has been repeated

wanton jolt
agile narwhal
#

im trying to make a joker detect if a card has been retriggered

wanton jolt
#

found this

tranquil cypress
#

You can use this lovely patch to create a context for it (https://github.com/nh6574/VanillaRemade/wiki#whats-a-patch)

# Add context when a card retriggers
# Credit: Somethingcom515
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/utils.lua"]'
pattern = '''effect.message = effect.message or (not effect.remove_default_message and localize('k_again_ex'))'''
position = "after"
payload = '''
effect.extra = {func = function() SMODS.calculate_context({modprefix_card_retriggered = true}) end}
'''
match_indent = true

then you can use context.modprefix_card_retriggered

wanton jolt
#

does this add a flag

#

retriggered = true

tranquil cypress
#

it adds a new context you can use in calculate (modprefix_card_retriggered is true)

wanton jolt
#

oooooh

#

it would be useful to have this in smods

tranquil cypress
#

yeah

wintry solar
#

It would be better to just set a flag when a card is retriggered

tranquil cypress
#

ah i see

primal robin
#

What if I'll make PR where I'll use forbidden knowledge to recreate badge & mod authors line line with initially intented marqueen?

primal robin
#

Like this

red flower
viscid talon
#

trying to figure out how to make this joker work. here are the errors so far

  • it does lose $1 but it doesnt seem to update it with the standard "-$1" text that you would see in, say, a rental sticker - so i had to program my own one and i dont really like it
  • it does NOT spoil at -$20 or below even tho i really want it to
#
-- Spoiled Milk
SMODS.Joker({
    key = "spoiledmilk",
    config = { extra = { dollar = 1, limit = 20 } },
    loc_txt = {
        ["name"] = "Spoiled Milk",
        ["text"] = {
            {
                "Lose {C:money}$#1#{} per round",
                "If balance is below {C:money}-$#2#{}",
                "this {C:attention}Joker{} spoils"
            }
        },
    },
    pos = { x = 8, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.dollar, card.ability.extra.limit } }
    end,

    calculate = function(self, card, context)
        if context.end_of_round and context.game_over == false then
            if G.GAME.dollars <= -20 then
                SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = "Spoiled!",
                    colour = G.C.FILTER
                }
            else
                G.GAME.dollars = G.GAME.dollars - card.ability.extra.dollar
                return {
                    message = "-$1",
                    colour = G.C.YELLOW
                }
            end
        end
    end
})
red flower
#

you can add ```lua to the code block so it has nicer colors

viscid talon
#

:O OMG I HAD NO IDEA

#

it no worky

#

nvm

#

figured it out

#

thats so cool omfg

viscid talon
#

imma try that rn

red flower
#

does it destroy itself a round after you get to -20? or does it never do it

viscid talon
#

it doesnt, no

#

it should be doing that but it doesnt

#
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.dollar, card.ability.extra.limit } }
    end,

    calculate = function(self, card, context)
        if context.end_of_round and context.game_over == false then
            if G.GAME.dollars <= -20 then
                SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = "Spoiled!",
                    colour = G.C.FILTER
                }
            else
                return {
                    dollars = -card.ability.extra.dollar
                }
            end
        end
    end
})```

the code rn (guidance from eris and bakerdozenbagels)
#

the next joker i need to program i genuinely have no idea how to make

#

its pretty simple in concept: gain x0.1 mult per dollar below 0

#

but like

#

idek how to do that

red flower
#

btw does this not remove like a million dollars per round?

viscid talon
#

im guessing some sort of hook?

viscid talon
red flower
viscid talon
#

ohhhh

#

also it works!!! yippeeee

frosty dock
primal robin
#

Now problem

wintry solar
#

Can you control overflow direction?

frosty dock
#

ouch

viscid talon
#

i have one last issue but its a pretty small one

primal robin
#

option 1: I'm PRing this with partial overflow support (i.e. only truncate vertical or only horizontal)
options 2: I'm adding padding for this line specifically

viscid talon
#

ill bring it up after i test milkman

red flower
#

uhhhh is context.individual in end_of_round broken

slim ferry
#

is context.individual calculated with context.game_over present normally

red flower
#

no?

slim ferry
#

i mean like at the end of round

red flower
#

i dont think so

frosty dock
slim ferry
#

because if you do context.game_over == false that wouldnt trigger in individual

#

since game over would be nil

#

i think

viscid talon
#

oke milkman works but the text isnt updating. lemme see if i can fix that ymself

frosty dock
#

context.individual isn't present in end_of_round

red flower
#

?

#

am i crazy

frosty dock
#

you just do context.end_of_round and context.cardarea == area

red flower
#

no?

frosty dock
#

don't you?

red flower
#

it has repetition too

wintry solar
#

I’m pretty sure individual exists

primal robin
#

Okay.
option 1: no_overflow = vh stands for vertical/horizontal
option 2: no_overflow = wh stands for width/height

wintry solar
#

It was the main reason for adding main eval, no?

viscid talon
#

nvm i have no idea

red flower
#

now only main_eval seems to run

frosty dock
#

wait I'm confused

red flower
#

let me try without the game over

primal robin
#

okay got it

wanton jolt
#

mhhh chezburger

frosty dock
#

yeah context.individual should work fine

red flower
#

oh ok without the game over it works i either didnt know that or it changed at some point

viscid talon
#
-- Milkman
SMODS.Joker({
    key = "milkman",
    config = { extra = { xmult = 1, xmult_gain = 0.1 } },
    loc_txt = {
        ["name"] = "Milkman",
        ["text"] = {
            {
                "Gain {C:white,X:mult}X#2#{} Mult",
                "per {C:attention}dollar{} below zero",
                "{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive} Mult)"
            }
        },
    },
    pos = { x = 9, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult, card.ability.extra.xmult_gain } }
    end,

    -- Credit to N' for code
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                xmult = 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0)
            }
        end
    end
})

i know why it isn't updating (the "currently" text is calling back to card.ability.extra.mult) whereas this joker is referring to an overall xmult variable. so im guessing i have to add some sort of way to equate card.ability.extra.mult's value to xmult, all the time. but idk how

frosty dock
viscid talon
#

doing smth like card.ability.extra.mult == xmult wasnt working

frosty dock
#

it's only present in the main eval

#

which is also responsible for Mr bones type effects, which is why the game over is there

primal robin
#

option 1: no_overflow = "vh"
option 2: no_overflow = { v = true, h = true }

red flower
#

i dont think this was always the case but i might be wrong

primal robin
#

makes sense

wintry solar
primal robin
#

then how optimize this

#

I dont really want drop no_overflow = true

#

or am I forced

frosty dock
#

convert true to "vh"

#

on init

primal robin
#

okay

red flower
frosty dock
# primal robin okay

you can also invalidate other truthy non-string values and assume it's either falsy or a string after that

primal robin
#

it's not necessary imo

frosty dock
#

yeah it isn't

primal robin
#

game doesn't check align so why should I

viscid talon
#
-- Milkman
SMODS.Joker({
    key = "milkman",
    config = { extra = { xmult = 1, xmult_gain = 0.1 } },
    loc_txt = {
        ["name"] = "Milkman",
        ["text"] = {
            {
                "Gain {C:white,X:mult}X#2#{} Mult",
                "per {C:attention}dollar{} below zero",
                "{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive} Mult)"
            }
        },
    },
    pos = { x = 9, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0) } }
    end,

    -- Credit to N' for code
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                xmult = card.ability.extra.mult
            }
        end
    end
})```
?
red flower
#

the first one should still be card.ability.extra.xmult_gain

viscid talon
#

o oke

frosty dock
#

align does too

viscid talon
#

uh oh 😭 i fucked up somewhere

#
-- Milkman
SMODS.Joker({
    key = "milkman",
    config = { extra = { xmult = 1, xmult_gain = 0.1 } },
    loc_txt = {
        ["name"] = "Milkman",
        ["text"] = {
            {
                "Gain {C:white,X:mult}X#1#{} Mult",
                "per {C:attention}dollar{} below zero",
                "{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive} Mult)"
            }
        },
    },
    pos = { x = 9, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult_gain, 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0) } }
    end,

    -- Credit to N' for code
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                xmult = card.ability.extra.mult
            }
        end
    end
})
wanton jolt
#

i am the milk man

viscid talon
#

milkman and spoiled milk my beloveds

#

i feel like i should know how to diagnose this but i rly dont

red flower
#

both are #1#

viscid talon
#

o should they both be #2#

#

also it doesnt return the xmult

red flower
viscid talon
#

o oke

primal robin
#

okay probably second to lasu question: vh or hv (for like docs purposes, I will do check like align anyway)

red flower
viscid talon
#

yeah i think so

#
-- Milkman
SMODS.Joker({
    key = "milkman",
    config = { extra = { xmult = 1, xmult_gain = 0.1 } },
    loc_txt = {
        ["name"] = "Milkman",
        ["text"] = {
            {
                "Gain {C:white,X:mult}X#1#{} Mult",
                "per {C:attention}dollar{} below zero",
                "{C:inactive}(Currently {X:red,C:white}X#2#{C:inactive} Mult)"
            }
        },
    },
    pos = { x = 9, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult, 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0) } }
    end,

    -- Credit to N' for code
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                xmult = card.ability.extra.xmult
            }
        end
    end
})``` im gonna test this out
red flower
#

the calculate code is still wrong

primal robin
viscid talon
#

oe

#

im so confused 😭

wintry solar
#

Vh

red flower
wintry solar
#

Thanks autocorrect 😭

frosty dock
#

vh imo

viscid talon
#

the code that was done earlier worked well, the only issue was the localisation not updating correclty

primal robin
#

okay

viscid talon
#

o

red flower
wanton jolt
#

ok

viscid talon
#

oh i thought i was supposd to move that to loc_Vars

#

not copy it over

frosty dock
#

why would you change it if it was working...

viscid talon
#

idk i was misinterpreting what was being explained to me

#
-- Milkman
SMODS.Joker({
    key = "milkman",
    config = { extra = { xmult = 1, xmult_gain = 0.1 } },
    loc_txt = {
        ["name"] = "Milkman",
        ["text"] = {
            {
                "Gain {C:white,X:mult}X#1#{} Mult",
                "per {C:attention}dollar{} below zero",
                "{C:inactive}(Currently {X:red,C:white}X#2#{C:inactive} Mult)"
            }
        },
    },
    pos = { x = 9, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.xmult, 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0) } }
    end,

    -- Credit to N'
    calculate = function(self, card, context)
        if context.joker_main then
            return {
                xmult = 1 + (G.GAME.dollars < 0 and card.ability.extra.xmult_gain * -G.GAME.dollars or 0)
            }
        end
    end
})``` this should be fine
primal robin
#

you know getting responses to a small questions immediately feels very nice

frosty dock
viscid talon
#

it should

#

im so confused GUHHH cus like

#

the code is fine, what wasnt updating was the localisation

#

so n is like "ok add this to locvars" so im thinking "ok so i have to move this" then

#

i need like super specific instructions bc im autistic as shitr

#

and something like this is kinda outside of my wheelhouse

frosty dock
#

it's fine haha, we got there in the end

viscid talon
#

when i say im autistic as shit, im not exaggerating

#

i literally have autism

#

diagnosed

#

either way this should work

frosty dock
#

looks good

viscid talon
#

ok thats kinda weird, for some reason it adds an extra +1 mult for no reason

frosty dock
#

that looks correct though?

viscid talon
#

[ignore my dumbassery]

red flower
#

gains X0.1 implies it starts at one imo

frosty dock
#

X1 base, 18 times X0.1 added

viscid talon
#

o wait

#

yeah

#

ur right

#

god

#

im so b ad at math

#

how did i get a 6

#

(grade b)

frosty dock
#

that 6 could have meant anything without clarifying

#

where I'm at it's the worst grade you can get

viscid talon
#

gcse and its consequences

frosty dock
#

in Switzerland it's the highest grade you can get

primal robin
viscid talon
#

in gcses, grades go from 1 to 9

#

6 is like a B

#

i didnt do math for alevels or uni so

frosty dock
#

(0-15)

frosty dock
wintry solar
#

I would be lazy and not account for people being dumb and using it wrong

frosty dock
#

wait yeah we established that's unnecessary

#

I just meant you can assume it's falsy or a string after accounting for the case where it's true

primal robin
#

Game does not check what alignment is, it assumes it's string anyway

#

bad screenshot but you can barely see

#

I want follow same logic despite it's lazy one

rapid stag
frosty dock
#

I mean it's not :find

#

I'm not sure what string.find does if not passed a string

wanton jolt
#

smart lovers card

primal robin
#

it returns nil, goddamn

#

this makes so much sense

#

At least for number

frosty dock
#

it probably converts the number to string?

#

try string.find(1, "1")

primal robin
#

yes, and looks like only number

#

it match 1 for 1

viscid talon
#

is there any documentation on manipulating booster packs in the steammodded wiki

#

like adding extra choices, taking away choices, etc

primal robin
#

boolean, nil, table throws error

#

so it makes sense do string.find just to throw more clear error to log

#

I'll do that

red flower
viscid talon
#

oh thanks

primal robin
#

another variant, any truthy value considered as true i.e. vh; string passed as-is; nil and false, well, falsy

wintry solar
#

honestly, if people want to be dumb, let them be dumb and have it not work

primal robin
#

true

viscid talon
#

ok now im a little lost

#

ik i have to use G.GAME.modifiers.booster_size_mod in some way

primal robin
#

I'm stopping and this then, I still need adjust collision check and drawing to partial things

viscid talon
#

is there like a context i need to call or

twilit hearth
#

might be a silly question but is there a mod/a way that I can spawn cards to do testing on?

viscid talon
viscid talon
twilit hearth
#

Ahh thank you so much!!

viscid talon
#

Download this mod, and follow the instructions. I use Ctrl+3 to spawn in jokers and Ctrl+C to spawn in cards, but idk if thats right

#
-- Ballad of Jimbo
SMODS.Joker({
    key = "ballad",
    config = { extra = { slot = 1 } },
    loc_txt = {
        ["name"] = "Ballad of Jimbo",
        ["text"] = {
            {
                "{C:attention}Buffoon Packs{} may",
                "contain an extra {C:attention}Joker{}",
            }
        },
    },
    pos = { x = 0, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.slots } }
    end,

    apply = function(self, card, context)
        G.GAME.modifiers.booster_size_mod(1)
    end,
})```
#

would this work

red flower
#

no SMODS

viscid talon
#

o

red flower
#

also = 1 instead of (1)

viscid talon
#

oke

#

heres hoping it works

red flower
#

or G.GAME.modifiers.booster_size_mod = G.GAME.modifiers.booster_size_mod + 1 would be better

#

also there's no apply on jokers

viscid talon
#

o is it just the standard calculate function

red flower
#

you want add_to_deck

viscid talon
#

okei

#
-- Ballad of Jimbo
SMODS.Joker({
    key = "ballad",
    config = { extra = { } },
    loc_txt = {
        ["name"] = "Ballad of Jimbo",
        ["text"] = {
            {
                "{C:attention}Buffoon Packs{} may",
                "contain an extra {C:attention}Joker{}",
            }
        },
    },
    pos = { x = 0, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = { } }
    end,

    -- Credit to N'
    add_to_deck = function(self, card, context)
        G.GAME.modifiers.booster_size_mod  = G.GAME.modifiers.booster_size_mod + 1
    end,

})
red flower
#

ah yeah

#

G.GAME.modifiers.booster_size_mod = (G.GAME.modifiers.booster_size_mod or 0) + 1

#

because it doesnt exists at the start of the run

viscid talon
#

oke

twilit hearth
#

@viscid talon i must be missing something. i cannot find the spawn command for the life of me

viscid talon
#

ok hold on

red flower
viscid talon
#

heres how you spawn a joker

twilit hearth
#

wait

viscid talon
#

first click options

twilit hearth
#

I found it

viscid talon
#

then collection

#

then jokers

twilit hearth
#

im just a little slow sometimes

#

thank you guys

red flower
#

you can also hold tab during a run for the commands

viscid talon
#

then ctrl+3

#

yippee it work

daring fern
wanton jolt
#

i hate explosion gif i hate explosion gif

twilit hearth
#

if i wanna use a joker to take money away from the person, is it not just dollars = -{amount}?

slim ferry
#

it is just dollars = -amount

primal robin
#

Okay, easy part is done. Now, collision Trolge

wanton jolt
#

oh it is drawing the explosion

#

its just not animating it

twilit hearth
#

oh im stupid

twilit hearth
slim ferry
#

lmao

twilit hearth
#

I apologize if this is an obvious question but I want to add joker art to my jokers. I know I could probably figure out how to, but im sure you guys might know more than me.

wanton jolt
#

you need atlas

#

declare atlas

#

assign atlas to joker

#

assign where the sprite is in atlas to joker

twilit hearth
#

<3 thank you

rapid stag
wanton jolt
#

i think you overwrote something

viscid talon
#
-- Hearts and Minds
SMODS.Joker({
    key = "heartminds",
    config = { extra = { mult = 0, mult_mod = 4 } },
    loc_txt = {
        ["name"] = "Hearts and Minds",
        ["text"] = {
            {
                "Gain {C:mult}+#2#{} Mult if played hand",
                "contains a {C:attention}Flush{}",
                "then {C:attention}destroy{} cards",
                "{C:inactive}(Currently{} {C:red}+#1#{} {C:inactive}Mult{})"
            }
        },
    },
    pos = { x = 1, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    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_mod } }
    end,

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play then
            context.other_card.should_destroy = false
        if context.before and next(context.poker_hands['Flush']) and not context.blueprint then
            context.other_card.should_destroy = true
            card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
            return {
                message = localize('k_upgrade_ex'),
                colour = G.C.RED,
            }
        end
        if context.destroy_card and context.destroy_card.should_destroy then
            return {
                remove = true
            }
        end
        if context.joker_main then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
end
})

it no worky

#

to clarify, it doesnt seem to recognise flushes, gain mult then destroy the cards

wanton jolt
#

use smods.destroy_cards instead

viscid talon
#

yeah prolly a better idea

rapid stag
# wanton jolt i think you overwrote something

but like, what? all i have are enhancement and seal changes and a custom sticker. there is this? but i don't know if that's the culprit?

nothing should be removing the card name from the card

viscid talon
#
-- Hearts and Minds
SMODS.Joker({
    key = "heartminds",
    config = { extra = { mult = 0, mult_mod = 4 } },
    loc_txt = {
        ["name"] = "Hearts and Minds",
        ["text"] = {
            {
                "Gain {C:mult}+#2#{} Mult if played hand",
                "contains a {C:attention}Flush{}",
                "then {C:attention}destroy{} played cards",
                "{C:inactive}(Currently{} {C:red}+#1#{} {C:inactive}Mult{})"
            }
        },
    },
    pos = { x = 1, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    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_mod } }
    end,

    calculate = function(self, card, context)
        if context.before and not context.blueprint and next(context.poker_hands['Flush']) then
            card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
            SMODS.destroy_cards(card, nil, nil, true)
            return {
                message = localize('k_upgrade_ex'),
                colour = G.C.RED,
            }
        end
        if context.joker_main then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
})

nvm it seems to destroy itself and not the scored cards

wanton jolt
#

thats because you gave it card

#

you need to

#

list out the cards to destroy

rapid stag
viscid talon
#

oe

viscid talon
red flower
viscid talon
#

o yay

wanton jolt
#

ooooh yeah

#

i mean wouldnt it be better to do context.scoring_hand?

red flower
#

the description says played cards so i assumed

#

either works depending on what the effect is

vocal berry
#

trying to make a joker that makes steel cards and gold cards have the same effects and be considered as the same, tried has.enhancement and center, nothing seems to work, anyone knows how to do it?

frosty dock
rapid stag
#

aren't quantum enhancements really laggy atm though

frosty dock
#

they may impact performance, there's not much to be done about that though

viscid talon
#
-- Spoiled Ballot
SMODS.Joker({
    key = "spoiledballot",
    config = { extra = {} },
    loc_txt = {
        ["name"] = "Spoiled Ballot",
        ["text"] = {
            {
                "On the {C:attention}first hand{} of round",
                "the {C:attention}first{} played card is",
                "enhanced into a {C:attention}Salt Card{}",
            }
        },
    },
    pos = { x = 2, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        return { vars = {} }
    end,

    calculate = function(self, card, context)
        if G.GAME.current_round.hands_played == 0 then
            if context.cardarea == G.play and context.other_card == context.scoring_hand[1] then
                scored_card:set_ability('m_hatch_salt', nil, true)
                G.E_MANAGER:add_event(Event({
                    func = function()
                        scored_card:juice_up()
                        return true
                    end
                }))
                return {
                    message = "Spoiled!",
                    colour = G.C.GREEN
                }
            end
        end
    end
})```
this returns with an "attempt to globalise scored_card, null value" error
frosty dock
#

well you didn't define scored_card

viscid talon
#

oo how do i define it

frosty dock
#

that depends on what card you want to change the enhancement of

#

to start with, that context check is bogus

#

what should this actually do?

viscid talon
#

first played card becomes a salt card ;-;

#

on the first played hand only

frosty dock
#

in that case add a check for context.individual

#

and replace any scored_card with what the scored card actually is, i.e., context.other_card

viscid talon
#
-- Spoiled Ballot
SMODS.Joker({
    key = "spoiledballot",
    config = { extra = {} },
    loc_txt = {
        ["name"] = "Spoiled Ballot",
        ["text"] = {
            {
                "On the {C:attention}first hand{} of round",
                "the {C:attention}first{} played card is",
                "enhanced into a {C:attention}Salt Card{}",
            }
        },
    },
    pos = { x = 2, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    calculate = function(self, card, context)
        if G.GAME.current_round.hands_played == 0 then
            if context.individual and context.cardarea == G.play and context.other_card == context.scoring_hand[1] then
                other_card:set_ability('m_hatch_salt', nil, true)
                G.E_MANAGER:add_event(Event({
                    func = function()
                        scored_card:juice_up()
                        return true
                    end
                }))
                return {
                    message = "Spoiled!",
                    colour = G.C.GREEN
                }
            end
        end
    end
})```
like this?
frosty dock
#

here, you dropped this

#

context

viscid talon
#

oh, where does that go

frosty dock
#

also there's another instance of scored_card you forgot to change

viscid talon
#

oke

frosty dock
#

I said context.other_card

#

which you somehow turned into just other_card?

viscid talon
#

i apologise

frosty dock
#

all good

viscid talon
#

i have amended the error

#
    calculate = function(self, card, context)
        if G.GAME.current_round.hands_played == 0 then
            if context.individual and context.cardarea == G.play and context.other_card == context.scoring_hand[1] then
                context.other_card:set_ability('m_hatch_salt', nil, true)
                G.E_MANAGER:add_event(Event({
                    func = function()
                        context.other_card:juice_up()
                        return true
                    end
                }))
                return {
                    message = "Spoiled!",
                    colour = G.C.GREEN
                }
            end
        end
    end
})```
still returns with an error
#
[SMODS hatchet "src/jokers.lua"]:3920: attempt to index field 'other_card' (a nil value)

Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-1501a-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.9.0
Platform: Windows
Steamodded Mods:
    1: Hatchet by Plasma [ID: hatchet, Version: 1.6.0]
    2: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.5.1, Uses Lovely]
    3: Deltarune Deck by nolo33lp [ID: DeltaruneDeck]
Lovely Mods:

Stack Traceback
===============
(3) LÖVE metamethod at file 'boot.lua:352'
Local variables:
 errhand = Lua function '(LÖVE Function)' (defined at line 605 of chunk [lovely debugplus.console "debugplus/console.lua"])
 handler = Lua function '(LÖVE Function)' (defined at line 605 of chunk [lovely debugplus.console "debugplus/console.lua"])
(4) Lua field 'func' at file 'src/jokers.lua:3920' (from mod with id hatchet)
Local variables:
 (*temporary) = nil
 (*temporary) = nil
 (*temporary) = string: "attempt to index field 'other_card' (a nil value)"
(5) Lua method 'handle' at file 'engine/event.lua:96'
Local variables:
 self = table: 0x379fce20  {start_timer:true, timer:TOTAL, blockable:true, trigger:immediate, func:function: 0x36f3fe20, delay:0, complete:false, time:32.101023284119, blocking:true (more...)}
 _results = table: 0x37276c28  {blocking:true, pause_skip:false, time_done:false, completed:false}
(6) Lua method 'update' at file 'engine/event.lua:184'
Local variables:
 self = table: 0x370801d0  {queues:table: 0x370801f8, queue_last_processed:14.316666666667, append_count:0, append_queue:base, queue_dt:0.016666666666667, queue_timer:14.444634293842 (more...)}
 dt = number: 0.0168431
 forced = nil
 (for generator) = C function: next
 (for state) = table: 0x370801f8  {unlock:table: 0x370802e8, other:table: 0x37080388, tutorial:table: 0x37080338, base:table: 0x37080310, achievement:table: 0x37080360}
 (for control) = number: nan
 k = string: "base"
 v = table: 0x37080310  {1:table: 0x36af17e0, 2:table: 0x379fce20, 3:table: 0x379fd7d0, 4:table: 0x379fd970, 5:table: 0x379fdd58, 6:table: 0x379fedb0, 7:table: 0x379fee38 (more...)}
 blocked = boolean: false
 i = number: 2
 results = table: 0x37276c28  {blocking:true, pause_skip:false, time_done:false, completed:false}
(7) Lua upvalue 'gameUpdateRef' at file 'game.lua:2617'
Local variables:
 self = table: 0x36934ca0  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x373e0220, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x3737e3d8 (more...)}
 dt = number: 0.0168431
 http_resp = nil
(8) Lua method 'update' at Steamodded file 'src/ui.lua:190' 
Local variables:
 self = table: 0x36934ca0  {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x373e0220, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x3737e3d8 (more...)}
 dt = number: 0.0168431
(9) Lua field 'update' at file 'main.lua:1022'
Local variables:
 dt = number: 0.0168431
(10) Lua function '?' at file 'main.lua:961' (best guess)
(11) global C function 'xpcall'
(12) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
 func = Lua function '?' (defined at line 932 of chunk main.lua)
 inerror = boolean: true
 deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
 earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])
frosty dock
viscid talon
#

h

#

;-;

frosty dock
#

you need to save context.other_card to a local variable outside and reference that

viscid talon
#

local other_card = ??

frosty dock
#

context tables are reused between cards being scored, so context.other_card is expired by the time the event gets to run

viscid talon
#

im getting rid of the event

frosty dock
#

don't

#

that will mistime the juice

viscid talon
#

i got rid of the juice too

#

it works now

frosty dock
#

fair

viscid talon
pale rampart
#

how do i make a custom consumable rate bigger, like the thing on the spectral deck but with my own type of consumable 🤔

urban wasp
slim ferry
torpid flicker
frosty dock
#

what's the code that's causing this

slim ferry
#

and adding a default atlas

pale rampart
#

i'm kinda dumb

torpid flicker
#

ur all good

urban wasp
slim ferry
#

and

urban wasp
#

and jokers use atlas = "joker"

slim ferry
#

are you actually loading the file with the atlas

urban wasp
#

it's worked for like forever

urban wasp
#

oh wait

#

i'm loading them after lol

#

oopsie

slim ferry
#

that

#

shouldnt matter

urban wasp
#

oh you're right

#

in that case i'm not actually sure what's going on

#

this is how i load the jokers

local files = {
    appetizers = {
        list = {
            "dragonfruit",
            "blueberry",
            "grapes",
            "shrimp",
            "durian",
            "wonderous_bread",
            "jelly_beans",
            "apple",
            "apple_core",
            "tomato"
        }, directory = "items/appetizers/"
    },
    jesters = {
        list = {
            "hal",
            "henry",
            "tom",
            "barber",
            "ballbo",
            "rogue",
            "eddrick",
            "super",
            "eureka",
            "timmy",
            "gary",
            "golden_sun",
            "jack_frost",
            "jim",
            "gumphrey",
            "soothsayer",
            "polymath",
            "luminary",
            "furious",
            "larry",
            "phony",
            "frank",
            "crafted",
            "schlitzohr",
            "hotboxer"
        }, directory = "items/jesters/"
    },
    normalities = {
        list = {
            
        }, directory = "items/normalities/"
    },
    fables = {
        list = {
            -- "narr",
            "manqian",
            "turold",
            "taillefer",
            -- "dagonet"
        }, directory = "items/fables/"
    }
}

for _, set in pairs(files) do
    for _, name in ipairs(set.list) do
        assert(SMODS.load_file(set.directory .. name .. ".lua"))()
    end
end
#

it should be pretty simple

viscid talon
#

is there an enhancement equivalent of SMODS.has_any_suit

torpid flicker
urban wasp
#

that is nowhere near the point of that

torpid flicker
#

yeah ik

#

just pointing it out

urban wasp
#

it's essentially a rudimentary way of ordering jokers

urban wasp
#

i've tried many, many times to implement the way that other mods do it to no avail

#

so this is just how it is lol

torpid flicker
#

the way joker order is deterimined is by what is defined first

#

so you could have them all in one lua file and they would be in order from top to bottom

urban wasp
#

i am not putting all of my jokers in one lua file

torpid flicker
#

you dont have to

urban wasp
#

just flat-out i'm not doing that

torpid flicker
#

that was an example

urban wasp
#

there's just some other ways that mods like cryptid/all in jest do it that i can't seem to replicate

torpid flicker
#

cryptid has its jokers in one joker file?

urban wasp
#

no, it separates them

#

but it uses a function to order jokers in the collection

#

same with all in jest

torpid flicker
#

im looking at the github right now?

#

i mean they are seperated by rarity

#

so im half wrong

urban wasp
#

inspect every joker and peep the order function

#

additionally, multiple files define jokers

#

e.g. m.lua, exotic.lua, misc_joker.lua, epic.lua

torpid flicker
#

intresting

urban wasp
#

in any case, my one issue right now is just this crash lol

torpid flicker
#

yeah

torpid flicker
urban wasp
#

sure

daring fern
viscid talon
#

noe

urban wasp
# torpid flicker can you send your atlas code and where you reference the key? this atlas you pas...

these are all of my atlases, inside of lib/smods.lua, loaded by my main.lua file:

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

SMODS.Atlas({
    key = "joker", 
    path = "joker.png", 
    px = 71,
    py = 95, 
})

SMODS.Atlas({
    key = "placeholder", 
    path = "placeholder.png", 
    px = 71,
    py = 95, 
})

i use the joker one, for example, simply like this:

...
    blueprint_compat = true,
    atlas = "joker",
    calculate = function(self, card, context)
...
viscid talon
#

im trying to make a flower pot clone that creates a divine card if there are sulfur, mercury and salt cards played

#
    calculate = function(self, card, context)
        if context.joker_main then
            local elements = {
                ['Sulfur'] = 0,
                ['Mercury'] = 0,
                ['Salt'] = 0,
            }
            for i = 1, #context.scoring_hand do -- IF NOT
                    if context.scoring_hand[i]:has_enhancement('Sulfur', true) and elements["Sulfur"] == 0 then
                        elements["Sulfur"] = elements["Sulfur"] + 1
                    elseif context.scoring_hand[i]:has_enhancement('Mercury', true) and elements["Mercury"] == 0 then
                        elements["Mercury"] = elements["Mercury"] + 1
                    elseif context.scoring_hand[i]:has_enhancement('Salt', true) and elements["Salt"] == 0 then
                        elements["Salt"] = elements["Salt"] + 1
                end
            end
            for i = 1, #context.scoring_hand do -- IF YES
                    if context.scoring_hand[i]:has_enhancement('Sulfur') and elements["Sulfur"] == 0 then
                        elements["Sulfur"] = elements["Sulfur"] + 1
                    elseif context.scoring_hand[i]:has_enhancement('Mercury') and elements["Mercury"] == 0 then
                        elements["Mercury"] = elements["Mercury"] + 1
                    elseif context.scoring_hand[i]:has_enhancement('Salt') and elements["Salt"] == 0 then
                        elements["Salt"] = elements["Salt"] + 1
                end
            end
            if elements["Sulfur"] > 0 and
                elements["Mercury"] > 0 and
                elements["Salt"] > 0 then
                return {
                    xmult = card.ability.extra.Xmult
                }
            end
        end
end
})``` im wondering if this will be enough
daring fern
viscid talon
#

SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_sulfur') ?

viscid talon
#

where do i put that

#

-- Philosopher's Stone
SMODS.Joker({
    key = "philosopher",
    config = { extra = { } },
    loc_txt = {
        ["name"] = "Philosopher's Stone",
        ["text"] = {
            {
                "If played hand contains",
                "a {C:attention}Sulfur Card{}",
                "a {C:attention}Mercury Card{}",
                "and a {C:attention}Salt Card{}",
                "create a {C:tarot}Divine Card{}",
            }
        },
    },
    pos = { x = 3, y = 7 },
    cost = 7,
    rarity = 2,
    blueprint_compat = false,
    eternal_compat = false,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    calculate = function(self, card, context)
        if context.joker_main then
            local elements = {
                ['Sulfur'] = 0,
                ['Mercury'] = 0,
                ['Salt'] = 0,
            }
            for i = 1, #context.scoring_hand do -- IF NOT
                    if SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_sulfur') then
                        elements["Sulfur"] = elements["Sulfur"] + 1
                    elseif SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_mercury') then
                        elements["Mercury"] = elements["Mercury"] + 1
                    elseif SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_salt') then
                        elements["Salt"] = elements["Salt"] + 1
                end
            end
            for i = 1, #context.scoring_hand do -- IF YES
                    if SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_sulfur') then
                        elements["Sulfur"] = elements["Sulfur"] + 1
                    elseif SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_mercury') then
                        elements["Mercury"] = elements["Mercury"] + 1
                    elseif SMODS.has_enhancement(context.scoring_hand[i], 'm_hatch_salt') then
                        elements["Salt"] = elements["Salt"] + 1
                end
            end
            if elements["Sulfur"] > 0 and
                elements["Mercury"] > 0 and
                elements["Salt"] > 0 then
                return {
                    xmult = card.ability.extra.Xmult
                }
            end
        end
end
})``` my code rn
#

good news is that it doesnt break

#

bad news is that it doesnt really do anything

#

oh wait

#

LOL

#

HOLD ON

#

nvm i figured it out LOL

viscid talon
#

bizarre issue

#
-- Medicine Cabinet
SMODS.Joker({
    key = "medicine",
    config = { extra = { xmult = 3, odds = 4 } },
    loc_txt = {
        ["name"] = "Medicine Cabinet",
        ["text"] = {
            {
                "{C:white,X:mult}X#3#{} Mult in a {C:attention}Boss Blind{}",
                "{C:green}#1# in #2#{} chance to expire",
                "during a {C:attention}Boss Blind{}"
            }
        },
    },
    pos = { x = 5, y = 6 },
    cost = 7,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    loc_vars = function(self, info_queue, card)
        local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_hatch_cakeslice')
        return { vars = { numerator, denominator, card.ability.extra.xmult } }
    end,

    calculate = function(self, card, context)
        if G.GAME.blind.boss then
            if SMODS.pseudorandom_probability(card, 'j_hatch_cakeslice', 1, card.ability.extra.odds) then
                SMODS.destroy_cards(card, nil, nil, true)
                return {
                    message = localize('k_extinct_ex')
                }
            else
                return {
                    message = localize('k_safe_ex')
                }
            end
        end
        if context.joker_main and G.GAME.blind.boss then
            return {
                xmult = card.ability.extra.xmult
            }
        end
    end
})

whenever i go into a boss blind and try this, the game just... dies. no crash message, nothing. it just closes 😭 im guessing its stack overflow

red flower
#

the first if condition doesn't have any context checks

#

when do you want it to be destroyed?

viscid talon
#

during a boss blind

red flower
#

at the start?

viscid talon
#

at the end

#

like banana

urban wasp
red flower
#

then add context.end_of_round

#

and context.main_eval

#

to the G.GAME.blind.boss condition

viscid talon
#

oke

analog spoke
#

question here, which tbh is mostly out of curiousity rather than any idea I currently have for any jokers or anything, but how would you make a math function for dice? What I mean is, like "3d6", "5d6", etc
I know how I'd do it, like, on it's own, it being random(1,6) + random(1,6) or whatever lua's random function is (I forgor lol), but like, how would I make that into a repeatable var u know? Simple example joker idea would be a joker which gives +1d6 Mult and rolls an additional die for each boss blind you defeat while holding it

daring fern
urban wasp
#

i have a joker that upgrades based on the number of cards with a random suit in the total deck of the player, but the logic for upgrading is a bit odd at the moment
i'd still like it to use SMODS.scale_card for compatibility, but i'm unsure on how i'd set this up such that "upgrade" isn't shown suit_count() times

if suit_count() ~= 0 and context.end_of_round and context.main_eval and not context.blueprint then
    for i = 1, suit_count() do
        SMODS.scale_card(card, {
            ref_table = card.ability.extra,
            ref_value = "xmult",
            scalar_value = "xmult_mod",
            message_colour = G.C.MULT
        })
    end
end
daring fern
urban wasp
#

i had thought of that, but on the molecular-level chance that somebody somehow uses this joker and tracks when it scales, it would be off
i know it doesn't really matter all that much, but if there's a better way to do it accurately, i'd want to use it

#

especially considering it would be easily possible by just setting the value to the correct one instead of using SMODS.scale_card

daring fern
urban wasp
#

so it becomes this?

SMODS.scale_card(card, {
    ref_table = card.ability.extra,
    ref_value = "xmult",
    scalar_value = "xmult_mod",
    message_colour = G.C.MULT,
    operation = function(ref_table, ref_value, initial, change)
        ref_table[ref_value] = ref_table[ref_value] + suit_count() * change
    end
})
urban wasp
#

thanks so much!

hidden aspen
urban wasp
#

how do i make the upgrade message appear after a stone card is scored, as, currently, this joker upgrades before

if context.individual and context.cardarea == G.play and not context.other_card.debuff and SMODS.has_enhancement(context.other_card, "m_stone") then
    SMODS.scale_card(card, {
        ref_table = card.ability.extra,
        ref_value = "mult",
        scalar_value = "mult_mod",
        message_colour = G.C.MULT
    })
end

bonus question: do i need not context.other_card.debuff or would it work correctly without?

wanton jolt
#

you need to return a message

#

oh wait

#

do you upgrade every time a stone card has been scored

#

or do you just upgrade once, even if two stone cards or more have been scored

faint yacht
#

...set no_message = true in the table, then manually SMODS.calculate_effect the message on the card?

urban wasp
urban wasp
urban wasp
#

er ok wait no i get it

#

i’ve never used SMODS.calculate_effect though so i don’t really know what i would do there

faint yacht
#

SMODS.calculate_effect({message = localize('k_upgrade_ex'), colour = G.C.MULT}, target_card_here)

wanton jolt
#

aqre you upgrading the joker or the card itself

urban wasp
wanton jolt
#

yeah then i would put card and not the stone card

urban wasp
#

i never did put the stone card though

wanton jolt
#

as the target

#

i was talking to toga

urban wasp
#

oh

#

but nor did they?

wanton jolt
#

he edited tho

urban wasp
#

i see

wanton jolt
#

target was other_card

reef bobcat
#

how do i make a joker transform into another joker?

wanton jolt
#

ooo ooo its my turn

#

^ ^ ^

daring fern
keen blaze
#

im trying to get into making mods for the game for the first time and im searching through steammodded's api to see how things work and im starting to get an idea of how different systems n stuff in the game work but i cant seem to find how i get my mod to actually do anything, like how to get it to initialize itself and act as a mod instead of just being some files with code that dont activate

i know its probably pretty simple and im probably just looking in the wrong places but i really cant find how to do it properly

reef bobcat
#

also

#

how do i make it say a message

#

when it transforms

#

i tried a few stuff

#

but nothing's been working

daring fern
reef bobcat
#

ok i figured it out

keen blaze
#

oh yeah i looked through the metadata and i have metadata set on my test mod the mod still doesnt really do anything

#

currently im just trying to add a single extra joker

red flower
keen blaze
#

ooh this looks nice

#

thanks ! ill take a look through that

reef bobcat
daring fern
# reef bobcat nevermind

If it's in a calculate you would do return {message = 'message'}, elsewise, you would do SMODS.calculate_effect({message = 'message'}, card)

reef bobcat
#
    loc_vars = function(self, info_queue, card)
        return { vars = { card.ability.extra.mult } }
    end,
    calculate = function(self, card, context)
        if context.setting_blind and not context.blueprint then
            card:set_ability("j_sj_captainmarvel_joker")
            return {
                message = 'SHAZAM!',
                colour = G.C.RED
            }
        end
        calculate = function(self, card, context)
        if context.joker_main then
            return {
                mult = card.ability.extra.mult
            }
        end
    end
    end,
}```

this plays the message but now the other effect (+4 mult) doesn't work
daring fern
reef bobcat
#

when i do that then the game crashes :((

#

wait let me try something

#

ok phew

#

there was an extra end

#

now both the message and effects happen

#

thank u

#

btw how do i make it so one of the jokers can't show up in the shop? Do I just give it like a 0 rarity?

faint yacht
#

return false in in_pool.

keen blaze
reef bobcat
# faint yacht `return false` in `in_pool`.
    cost = 7,
    blueprint_compat = true,
    eternal_compat = true,
    unlocked = true,
    discovered = true,
    soul_pos = nil,
    in_pool = false,```

i did this but i get the feel it's not what you meant
faint yacht
#
    in_pool = function()
        return false
    end,
reef bobcat
#

ohhhh im dumb ok

#

it worked thanks

near coral
#

The aim is for example:
Imagine a reroll costs $5, this would bring it down to $3 but the base price would still be $5, and if the base price goes any lower it would take 2 off that instead

#

Someone please look into their code and clean it up according to their description, I still want it to raise the other prices in the shop by $1

near coral
#

I sent it to my coder and unless they just didn't do it the code didn't work

daring fern
near coral
#

Did you test it yourself or something

daring fern
near coral
#

Maybe they forgot to put it in or something

#

Does your test version include the price increase for other shop items

#

If yes can you slide it for me to put into the build I'm testing

urban wasp
# daring fern Put `no_message = true` in `SMODS.scale_card` then return a message.

why is the upgrade text triggering on the played card(s)?

calculate = function(self, card, context)
    if
        (context.individual and
        context.cardarea == G.play and
        not context.other_card.debuff and
        SMODS.has_enhancement(context.other_card, "m_stone")) or
        (context.discard and
        not context.other_card.debuff and
        SMODS.has_enhancement(context.other_card, "m_stone")) and
        not context.blueprint
    then
        SMODS.scale_card(card, {
            ref_table = card.ability.extra,
            ref_value = "mult",
            scalar_value = "mult_mod",
            no_message = true
        })
        return {
            message = localize("k_upgrade_ex"),
            colour = G.C.MULT,
            card = card
        }
    end
near coral
#

Ok so my coder legit just forgot to do it

daring fern
urban wasp
daring fern
urban wasp
#

thank you again king somethingcom

near coral
#

A card does indeed equal a card last I checked

urban wasp
near coral
#

Damn I wonder if I'll get +3 mult if I set the mult to give |-3| mult

#

So uh I'm testing big leagues which does this

#

And it created a brainstorm

#

Which then created another joker

#

And I'm wondering if that's like a bug or something cuz brainstorms aren't supposed to copy the effect that created it I assume

daring fern
near coral
#

I know that but the caveat is that big leagues created it, and it copied the rekoj post-trigger

#

Of course brainstorm will copy it but I'm wondering if it makes sense for it to copy it in this context

urban wasp
#

okay i have a very specific issue with my joker. this is its code at the moment:

calculate = function(self, card, context)
    if
        (context.individual and
        context.cardarea == G.play and
        not context.other_card.debuff and
        SMODS.has_enhancement(context.other_card, "m_stone")) or
        (context.discard and
        not context.other_card.debuff and
        SMODS.has_enhancement(context.other_card, "m_stone")) and
        not context.blueprint
    then
        SMODS.scale_card(card, {
            ref_table = card.ability.extra,
            ref_value = "mult",
            scalar_value = "mult_mod",
            no_message = true
        })
        SMODS.calculate_effect({message = localize("k_upgrade_ex"), colour = G.C.MULT}, card)
    end
    if context.individual and not context.other_card.debuff and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, "m_stone") then
        return {
            mult = card.ability.extra.mult,
            card = context.other_card
        }
    end
end

right now, the upgrade message appears before the card has been scored, and the effect is obviously applied after the joker has upgraded
what i would like to occur is for the joker to upgrade after a stone card has been scored, INCLUDING the actual effect itself
so, for example, if i haven't played any stone cards in the run and i play one stone card, i wouldn't like it to give any mult whatsoever; then, the next one would give +5
how would i go about this timing?

daring fern
urban wasp
daring fern
urban wasp
#

which is why i used an SMODS.calculate_effect here

#

am i missing something?

daring fern
urban wasp
#

is there any documentation for SMODS.merge_effects?

#

i've never seen it used before

daring fern
urban wasp
#

thanks you once again king somethingcom

final jewel
#

is it possible to do the same thing but for seals

daring fern
final jewel
#

okok

wintry solar
gilded blaze
#

atrocious hook I think

#

with quantum enhancements enabled that's gonna drag performance

fallen timber
#

When i play a card, the joker should burn it with 50% chance, but instead it crashes the game, am i doing something wrong?

Oops! The game crashed:
main.lua:2438: functions/common_events.lua:919: attempt to index local 'card' (a nil value)
This crash may be caused by continuing a run that was started on a previous version of Steamodded. Try creating a new run.

Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-1016c-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.9.0

Note: it was a new run

fallen timber
fallen timber
fallen timber
#

-# im sorry for pinging you so much lol