#💻・modding-dev

1 messages · Page 648 of 1

wanton jolt
#

uhhh ok it was my sigils all along and the bug persisted when i disabled them

#

thats fucking nuts

#

nevermind

young wigeon
#

Hi all, I am new to the scene, but am looking to try and make a bot as a ML project, has anyone made a mod to trigger actions programmatically, strip the visuals, a state recorder/replayer, a list of function triggers, or a mod that connects to web that I would be able to hook into, or reference?

#

or has anyone just made a bot already?

wanton jolt
#

the crash was toga all along

red flower
wanton jolt
#

what did i miss? stickers arent displaying descriptions and stuff

#

i'm fucking stupid

#

badge says error though

frosty rampart
#

badge is localized elsewhere

wanton jolt
#

labels?

frosty rampart
#

yep
misc -> labels -> modprefix_stickerkey = "something"

wanton jolt
#

thank u

#

whats the command to apply a sticker

viscid talon
#

okay uh

#

lemme fix it as best i can

frosty rampart
wanton jolt
#

oh fuck i meant on the console but

#

can i even launch a command

frosty rampart
#

yes, that is on the console
running eval [lua code] in debugplus will run the lua code
and in particular, eval dp.hovered:add_sticker("modprefix_stickerkey", true) will add the sticker to the card that you're currently hovering over with your mouse

wanton jolt
#

how do i open the dev console on debug plus again

viscid talon
#

i got a new error now

#

my sleep was really inconsistent today so theres probably something im missing

wanton jolt
#

switch ur probablility vars again

#

ur num and denom are still switched around

abstract turret
#

Ok i finnaly tested it, it actually fixes my problem. the problem was in incorrect key

viscid talon
#

IT WORKS

#

WOOOOOOOO

#

thankesi

wanton jolt
#

Ok so brittle didn't trigger on the joker

#

but it did on the card

cyan lagoon
#

everywhere where i used this now crashes the game with the newer steamodded version

slim ferry
#

message should not be a table

cyan lagoon
#

when did they change that?

umbral zodiac
#

recently

slim ferry
#

last smods broke messages being tables iirc

#

you can use dev smods too

cyan lagoon
#

i see

slim ferry
#

(also you should probably just use message = localize("k_plus_tarot"))

cyan lagoon
#

i dont bother with localization in my mod so i think it better to keep things consistent

slim ferry
#

🤷

#

alr then

wanton jolt
#

i want a joker to act like a glass card (1 to 1 chance of breaking when triggered) what context do i need to add

slim ferry
#

doesnt need to be any context in specific

wanton jolt
#

i'm using the sticker in both jokers and playing cards

#

so far it breaks playing cards fine

slim ferry
#

just do SMODS.destroy_cards(card) if its a joker

#

during probably context.after

wanton jolt
#

will it destroy the joker if it doesnt score or trigger?

slim ferry
#

it will

wanton jolt
#

that sucks

slim ferry
#

whats the actual effect meant to be

wanton jolt
#

if the joker triggers / card scores, break

slim ferry
#

so it should break on every trigger?

wanton jolt
#

it should break and die yes (so it should trigger once)

slim ferry
#

then do a little ```lua
if context.post_trigger and context.other_card == card then
card.getting_sliced = true
SMODS.destroy_cards(card)
end

#

shouldnt need a card type check since this context only runs on non-playing card triggers anyway but might be good to do for future proofing

wanton jolt
#

i mean if it detects a playing card first, its going to return (and exit the calculate function)

slim ferry
#

also true

knotty granite
#

forgot to upload thing to git hub pretty sure it is the same but an error appears

slim ferry
#

you misspelled odds as oddds

wanton jolt
#

yup

knotty granite
#

-_-

slim ferry
#

happens to everyone at least once

next timber
#

how would i go about having a consumable cause an effect at the start of the next X rounds? i have one that increases your hand size then slowly decreases it back down by -1 every round until its back to normal

frosty rampart
#

two options

  1. don't destroy the consumable until it's done, and just have it do things in its calculate function
  2. set some value in G.GAME when you use the consumable, and track it/do things in your mod's global calculate function
wintry solar
#

two options, either have the consumable hang around and give it a calculate function, or have it set a flag that is handled by your mod object calc function

next timber
#

lol

#

ill probably have it hang around since i imagine it would be easier to deal with having multiple active that way

#

now the question is if i let the player get the consumable slot back immediately or if they gotta wait for it to wear out

#

probably the former seeing as it can stick around for as much as 8 rounds at max level

wanton jolt
#

wait

#

it didnt save

slim ferry
#

do you have the post_trigger optional feature enabled

wanton jolt
#

where

slim ferry
#

in

#

your code

wanton jolt
#

it crashed

slim ferry
#

SMODS.current_mod.optional_features = { ... }

#

and then put post_trigger = true in there

wanton jolt
#

in main.lua?

slim ferry
#

probably

#

however you want to organize your mod

slim ferry
wanton jolt
#

i misspelled smth lol

slim ferry
#

oh ok

wanton jolt
#

it broke yay

slim ferry
#

epic

viscid talon
#
        return { vars = { card.ability.extra.chips } }
    end,

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and not context.blueprint then
        for _, scored_card in ipairs(context.scoring_hand) do
            if scored_card.vampired == nil then
                card.ability.extra.chips = card.ability.extra.chips + 20
                    return {
                    message = "Upgrade!",
                    colour = G.C.BLUE
                    }
                end
            end
        end
        if context.joker_main then
            return {
                chips = card.ability.extra.chips
            }
        end
    end
}```

MODIFIED CODE
#

im looking at the vampired documentation on vanillawiki rn

wanton jolt
#

uh now the sound plays when i play a card

lofty elm
#
-- See note about SMODS Scaling Manipulation on the wiki

Found this is green joker on vanilla remade, anyone know what its talking about? I just dont know what it could be referring to that would need further explanation

#

not important particularly just have no idea what its for

red flower
#

have you seen the note about SMODS Scaling Manipulation on the wiki

lofty elm
#

no lol idk where it is exactly

red flower
#

on the wiki

lofty elm
#

i didnt look very hard tbh but the wiki is kind of a mess imo

#

i can go look tho

viscid talon
#

is there like a hook

#

or some sort of function

red flower
viscid talon
#

that like, tells u "hey ur card's enhancement was removed!"

red flower
lofty elm
#

oh thats good my bad

viscid talon
#

smth like SMODS.vampire or whatever

#

oo whats that

red flower
#

it gets called when a card has its ability set

#

so for playing cards it would be getting or removing enhancements

viscid talon
#

how would i reproduce this effect then

lofty elm
#

ok i think at this point im dumb but idk what page im ctl-f ing

wanton jolt
#

the wiki

red flower
lofty elm
#

oh the faq

#

that makes sense, didnt know what page to be on

#

the faq page is awesome its just the rest of it that can be hard to search thorugh

viscid talon
#

would i do smth like context.setting_ability = SMODS.vampire = true or smth

lofty elm
#

ty, sorry for bothering you

pulsar hawk
#

Okay weird Pokermon skins toggle + Malverk texture crash fix time

#

this time it only happened when I enabled/disabled the texture

#

OH yeah i found why

#

so @wintry solar do alt textures register atlases also?

#

and if so - what are the odds that these two having the same key is the culprit

wintry solar
#

they won't have the same key

#

oh maybe they will

#

it wouldn't matter though

pulsar hawk
#

it would for atlas registry wouldn't it

wintry solar
#

I think this is a combination of both mods having broken code 🤣

pulsar hawk
#

can two altases register to the same key?

#

oh ig mod prefix?, hm...

wintry solar
#

they're the same image anyway

#

malverk prefixes it's atlases anyway iirc

next timber
#

how can i use juice_card_until to make a card juice up perpetually until it's destroyed?

#

not entirely sure how the function arguments work

#

thought juice_card_until(card,function() return false end, true) might work but apparently not

pulsar hawk
#

okay so Malverk is crashing for me regardless of the stake sprite toggle

#

and the texture

wintry solar
#

I have pushed a fix

#

I think

pulsar hawk
#

yup looks good!

#

no crash on my end

#

I'll PR the prefix config thing for the atlas anyway

wintry solar
#

yeah, I think that will crash without Malverk if you toggle it

#

and I think Malverk would actually prevent that crash because of when it initialises the default values

modest sedge
#

Why do my debuffed cards still score?
(Example code)

    calculate = function(self, blind, context)
        if not blind.disabled then
            if context.after and context.main_eval then
                if #context.scoring_hand == 1 then
                    context.card:set_debuff(true)
                    G.GAME.blind:wiggle()
pulsar hawk
#

context.after is after main scoring, isn't it?

#

wouldn't you want context.before if you didn't want it to score?

abstract turret
#

I need another help. I tried to change my function that was changing every joker in the shop on baron. I tried to firstly create a card, check if thats a common then change it onto baron.

local original_create_card = create_card

function create_card(card_type, area, legendary, rarity, skip_materialize, soulable, forced_key, ...)
local card=original_create_card(card_type,area,legendary,rarity,skip_materialize,soulable,forced_key,...)
rar=card.config.center.rarity
if rar==1 then
print("Change every common with baron")
return original_create_card(card_type,area,legendary,rarity,skip_materialize,soulable,'j_baron',...)
end
return card
end

But because i created the common joker first, after i create a baron, the common one becomes just a dragable copy. How can i fix this?

next timber
#

how do i prevent a card from being sold if a condition is met?

slim ferry
modest sedge
wintry solar
#

there are also the shop contexts that mean you odn't need to do this hook at all

slim ferry
#

right

pulsar hawk
#

ye context.create_shop_card is your best friend

#

whoever is doing that

#

(I don't know how I of all people managed to forget about that one considering I built a whole ass reroll simulator and had to account for it)

abstract turret
#

Ok, thanks everyone for help il try to figure something out

frosty rampart
#

either hook SMODS.is_eternal or use context.check_eternal, whichever makes more sense
in the context check, you can check context.trigger.from_sell to only catch the sell button; in the function, the trigger argument behaves the same and you can check trigger.from_sell. returning true in the hook, or { no_destroy = true }, should make the sell button greyed out like an eternal card's is

next timber
#

odd, i tried that and it didnt work

if context.check_eternal and card == context.other_card then
  if card.ability.extra.activated then
    return {no_destroy = true}
  end
end
frosty rampart
#

hmm

#

not sure tbh

next timber
#

splendid

frosty rampart
#

maybe the hook will have better luck? idk

knotty granite
#

Are there any special requirements for the atlas of a back?

slim ferry
#

No

knotty granite
#

Ok thanks

sweet pelican
#

If anyone would mind taking a look at this, been a minute since I've made a joker, just trying to figure out why I'm not getting any of the extra retriggers to activate despite my deck being 100% KoHs. Any help would be greatly appreciated!

red flower
#

you need to copy the loc_vars stuff again in calculate

sweet pelican
#

ah

#

thank you 😭

#

I'm getting two retriggers after moving it to the calculate, but it should be four now, maybe I made some logic error and I forgot how math works?

wanton jolt
#

i wanna make an enhancement that bloats the hand, basically u can't select it, play it, discard it or sell it, unless u r in a custom blind

sweet pelican
#

does G.playing_cards count the full deck or just remaining cards *in the deck?

red flower
#

full deck

sweet pelican
#

okay odd

frosty rampart
#

remaining deck is G.deck.cards

red flower
#

you need to do == 1 first then .66 then .33

sweet pelican
#

🤦 I gotta brush up on my *logic thank you king

wanton jolt
#

can u even sell a playing card

red flower
#

not normally no

#

but it woldnt be hard to add if you know what youre doing

daring fern
wanton jolt
#

would it make u able to show the sell button

daring fern
dawn linden
#

I'm having trouble figuring out how to replace the main theme with a variation in a different soundfont; I'm looking at the Steamodded wiki but I'm not sure how to get create_replace_sound(self,replace) to work in practice

gaunt folio
#

how do i make the blind size mod or just the text update happen upon trigger, it does it immediately

daring fern
gaunt folio
#

do you mean i put it in the return function or not idfk man i feel so dumb 😭

loud summit
#

hi

#

how do i make a joker retrigger a card multiple times and change the message each time

daring fern
loud summit
#

ok so uh

#

is there any way to make an arbritrary number through a for loop

daring fern
loud summit
#

oh wait what does merge effects do

daring fern
loud summit
#

oh ok

#

thx

loud summit
#

heyo so i need a bit of help

#

^ this is the joker im trying to fix

#

basically when oops6 is used, the DISPLAYED number is above the denominator

#

but inside the loop the INTERNAL odds eventually hits 0 which terminates the loop since zeroed odds do nothing

#
        if context.repetition then
            -- this SHOULDNT be null but just incase
            card.ability.extra.chain = card.ability.extra.chain or card.ability.extra.initial_down
            local odds = card.ability.extra.initial - card.ability.extra.chain

-- [...]

            while SMODS.pseudorandom_probability(card, "nflame_dicechain", odds, card.ability.extra.initial) do
                if activations > 100 then break end

                odds = odds - 1
                card.ability.extra.chain = card.ability.extra.chain + 1```
#

is there any ways to prevent the early termination at 0? obviously if i just start the odds at the get_probability_vars then it would effectively double the odds from the displayed numbers

#

actually nvm im going to keep it

vernal path
#

in context.remove_playing_cards, if I checked context.removed would those cards also still be in G.playing_cards?
And in context.playing_card_added is context.cards in G.playing_cards already?

daring fern
vernal path
#

Okay, cool

#

man we really should have valkriya's cookies here
that would be really fun

#

(get a cookie for getting someone to thank you, pointless but fun leaderboards for being helpful)

#

Does context.setting_ability trigger when using stuff like Death?

daring fern
vernal path
#

gotcha
thanks!!

tight pumice
#

Is there already a table I can access that has all the consumeable names in it or do I gotta make one

tight pumice
#

Thanks

#

I was trying to use get_current_pool and was tripping up

vernal path
#

Does there exist an update boolean like card.added_to_deck and card.removed for setting_ability or otherwise changing enhancement to a card?

normal crest
#

Iirc it's called inside Card:set_ability

vernal path
#

oh, yeah modify_deck

#

How would I make use of that inside an update function though? Is there some boolean flag set in check_for_unlock that I can check for or something?

#

I mean I suppose I could patch something, but I feel like it's bad practice to just make a new global variable

vernal path
#

@normal crest I suppose I will just put a patch in card.lua at the point where it makes that check. Although, since this is something that could be updated more than once, what would be the best way to mark it as false so it can be checked again?

naive agate
daring fern
#

It seems all I had to do was hook SMODS.calculate_retriggers and add 1+#retriggers retriggers.

slim ferry
# naive agate uhhh

you use card.ability.extra.Xmult in the code when you put xmult in the config

naive agate
#

ahhhh

slim ferry
#

you also dont have a Xmult_gain1 in the config

naive agate
#

i am stupid and i apologize,

glass scaffold
#

So does anyone know why this isn't giving money? I copied the code from Rocket and modified it a little.

slim ferry
#

the code for Rocket's money uses calc_dollar_bonus, not calculate

#

so you should either return { dollars = amount } or move the code that gives the money to calc_dollar_bonus

glass scaffold
#

So like this?

slim ferry
#

remove the return true

#

besides that yes

glass scaffold
slim ferry
#

?

#

only events work like that

glass scaffold
#

got it

slim ferry
#

also idk if G.GAME.blind.chips gets adjusted before calc_dollar_bonus runs, so that might be something youll need to work around

glass scaffold
slim ferry
#

awesome

long sun
#

this code in card.lua doesn't seem to be running, when opening a Standard pack:

elseif self.ability.name:find('Standard') then
                        card = create_card((pseudorandom(pseudoseed('stdset'..G.GAME.round_resets.ante)) > 0.6) and "Enhanced" or "Base", G.pack_cards, nil, nil, nil, true, nil, 'sta')
                        local edition_rate = 2
                        local edition = poll_edition('standard_edition'..G.GAME.round_resets.ante, edition_rate, true)
                        card:set_edition(edition)
                        card:set_seal(SMODS.poll_seal({mod = 10, guaranteed = next(SMODS.find_card("j_phanta_stampedjoker")) and true or nil}), true, true) print("kjdfngdf")```
#

is the code for this elsewhere?

primal robin
#

isnt SMODS override all booster packs?

long sun
#

probably ^^;

#

ah yes

#

found it, thanks!

wild patrol
#

is it possible to change a joker without destroying it?

#

Like replace it

primal robin
#

:set_ability(center)

wild patrol
#

G.jokers:set_ability(center)?

#

working on a command that'll pick a joker at random and swap it with a michel or Cavendish

primal robin
#

G.jokers.cards[1]:set_ability(G.P_CENTERS.j_rocket)

wild patrol
#

replace j_rocket with j_(jokername)

wild patrol
#

that's the slot number

#

?

primal robin
#

card position

#

but basically yes

wild patrol
#

hmmm

#

I guess I could make it select a random number between 1 - 6 unless there's a real way to randomly select

#

oh

#

I didn't realize the defuse button i made is on every joker lol

wild patrol
#

right now I need to figure out why the defuse button is on every joker

#

I thought I put it only on the bomb joker

daring fern
wild patrol
#
  key = 'defuse_button',
  order = -30, -- before the Card is drawn
  func = function(card, layer)
    if card.children.ttv_bomb_button then
      card.children.ttv_bomb_button:draw()
    end
  end
}

}

local function defuse_button(card)
  return UIBox {
    definition = {
      n = G.UIT.ROOT,
      config = {
        colour = G.C.CLEAR
      },
      nodes = {
        {
          n = G.UIT.C,
          config = {
            align = 'cm',
            padding = 0.15,
            r = 0.08,
            hover = true,
            shadow = true,
            colour = G.C.MULT, -- color of the button background
            button = 'ttv_defuse_button_click', -- function in G.FUNCS that will run when this button is clicked
            func = 'ttv_defuse_button_func', -- function in G.FUNCS that will run every frame this button exists (optional)
            ref_table = card,
          },
          nodes = {
            {
              n = G.UIT.R,
              nodes = {
                {
                  n = G.UIT.T,
                  config = {
                    text = "Defuse",
                    colour = G.C.UI.TEXT_LIGHT, -- color of the button text
                    scale = 0.4,
                  }
                },
                {
                  n = G.UIT.B,
                  config = {
                    w = 0.1,
                    h = 0.8
                  }
                }
              }
            }
          }
        }
      }
    },
    config = {
      align = 'cr', -- position relative to the card, meaning "center left". Follow the SMODS UI guide for more alignment options
      major = card,
      parent = card,
      offset = { x = -0.2, y = 0 } -- depends on the alignment you want, without an offset the button will look as if floating next to the card, instead of behind it
    }
  }
end

-- Will be called whenever the button is clicked
G.FUNCS.ttv_defuse_button_click = function(e)
  local card = e.config.ref_table -- access the card this button was on
  play_sound("ttv_bomb_explosion", 1.0, 0.7)
  G.E_MANAGER:add_event(Event({
      trigger = 'after',
      delay = 0.5,
      func = function()
          if G.STAGE == G.STAGES.RUN then 
              G.STATE = G.STATES.GAME_OVER
              G.STATE_COMPLETE = false
          end
      end
  }))
  -- Show a message on the card, as an example
  SMODS.calculate_effect({ message = "Hi!" }, card)
end

-- Will run every frame while the button exists
G.FUNCS.ttv_defuse_button_func = function(e)
  local card = e.config.ref_table -- access the card this button was on (unused here, but you can access it)

  -- In vanilla, this is generally used to define when the button can be used, for example:
  local can_use = true -- can be any condition you want

  -- Removes the button when the card can't be used, otherwise makes it use the previously defined button click
  e.config.button = can_use and 'ttv_defuse_button_click' or nil
  -- Changes the color of the button depending on whether it can be used or not
  e.config.colour = can_use and G.C.MULT or G.C.UI.BACKGROUND_INACTIVE
end


SMODS.draw_ignore_keys.ttv_bomb_button = true

local highlight_ref = Card.highlight
function Card.highlight(self, is_highlighted)
  if is_highlighted and self.ability.set == "Joker" and self.area == G.jokers then
    self.children.ttv_bomb_button = defuse_button(self)
  elseif self.children.ttv_bomb_button then
    self.children.ttv_bomb_button:remove()
    self.children.ttv_bomb_button = nil
  end

  return highlight_ref(self, is_highlighted)
end```
#

just slightly modified from the vanillia wiki

#

doesn't really do anything other than end the game

daring fern
wild patrol
#
function Card.highlight(self, is_highlighted)
  if is_highlighted and self.config.center.key == 'j_ttv_bomb' and self.area == G.jokers then
    self.children.ttv_bomb_button = defuse_button(self)
  elseif self.children.ttv_bomb_button then
    self.children.ttv_bomb_button:remove()
    self.children.ttv_bomb_button = nil
  end```
#

unless i'm doing this wrong

#

nvm

#

I forgot to remove the --- on the file that loads custom buttons

#

now it works

ripe thicket
#

I keep getting this crash error but I higkey have no clue why its doing that since it's almost complete copy+pasted code from another joker I have which works normally

wild patrol
#

I don't think DARK_EDITION is an actual colur could be wrong

#

try setting it to G.C.WHITE see if that works

ripe thicket
ripe thicket
ripe thicket
red flower
#

it is a color

#

the problem is that the message is a table

#

it should be a string and the color should be a different attribute

ripe thicket
#

ohhhhhh

#

hm now it shows as a red message though

red flower
#

idk works for me

#

mult_mod is not really recommended, try mult and use mult_message = { message = "text", colour = G.C.DARK_EDITION }

ripe thicket
#

yep that did the trick.

#

thanks!

final jewel
#

What is the global for the hand size

#

like is there a G.GAME.hand_size or something like this

daring fern
final jewel
#

oh ok nice

#

G.hand:change_size(G.hand.config.card_limit) that will double the hand size right

open moth
#

this doesnt create a perishable joker, why

final jewel
#
            card.ability.extra.original_size = G.hand.config.card_limit
            G.hand:change_size(G.hand.config.card_limit)
        end
        if not context.blueprint and card.ability.extra.original_size <= G.hand.config.card_limit and context.ending_booster then
            G.hand:change_size(-G.hand.config.card_limit)
        end````
Why does the end size always become 0 when returning to the blind
stiff locust
#

need a ui wizard to help with creating an option cycle

open moth
stiff locust
#

you should be reducing it by the difference between the original handsize and the current handsize (also, won't this logic not work properly if you use ectoplasm or other handsize reductions mid booster?)

stiff locust
#

then make changes to _card (add the sticker manually)

daring fern
stiff locust
#

add card can probably do it on its own but idk i dont use it

final jewel
open moth
pure nebula
#

does anyone knows how to change the base suit rate in in the shop?

like making it so that you only have heart suit but unlock others through vouchers?

daring fern
daring fern
modest sedge
#

Why is "round_resets" always nil? I tried everything, unless if I'm missing something obvious...

SMODS.Blind {
    name = "b_metro",
    key = "b_metro",
    loc_txt = {
        name = "The Metro",
        text = {
            "Debuff #1# random",
            "cards for every Blind",
            "skipped this run"
        }
    },
    unlocked = true,
    discovered = true,
    pos = {y = 20},
    atlas = "Blinds",
    dollars = 5,
    mult = 2,
    boss = {min = 1},
    boss_colour = HEX("000000"),

    loc_vars = function(self, info_queue, card)
        return {vars = (G.GAME.current_round.round_resets.blind_ante or 0)} -- Here
    end,

    set_blind = function(self)
        G.E_MANAGER:add_event(Event{func = function()
            local targets = {}
            for k, v in ipairs(G.deck.cards) do
                table.insert(targets, v)
            end
            for i = 1, (G.GAME.round_resets.blind_ante * (G.GAME.skips or 0)) do
                local target, key = pseudorandom_element(targets, pseudoseed("metro"))
                target:set_debuff(true)
                table.remove(targets, key)
            end
            return true
        end})
    end,
}
modest sedge
#

oh
thank you :3

#

I "fixed" it, but #1# still just says "nil" ingame


SMODS.Blind {
    name = "b_metro",
    key = "b_metro",
    loc_txt = {
        name = "The Metro",
        text = {
            "Debuff #1# random",
            "cards for every Blind",
            "skipped this run"
        }
    },

...

loc_vars = function(self, info_queue, card)
        return {vars = tostring(G.GAME.round_resets.blind_ante or "0")}
    end,
modest sedge
#

oh i thought i put the curly brackets in
thank you

daring fern
#

‎

stiff locust
#

is there a vanilla pool for food jokers

red flower
#

no

stiff locust
#

alright

red flower
#

consensus is just to make a food pool with the same key as the cryptid one

stiff locust
#

is there a commonly de- okay

#

how can I check for jokers from a specific pool then

red flower
stiff locust
#

mm, bus

red flower
#

theyre in G.P_CENTER_POOLS.Food too

stiff locust
#

thats quite simple

#

so what's the key for the cryptid one

red flower
#

Food

#

without the prefix

stiff locust
#

oh thats simple

#

i should check if the pool exists before i make it and not make it if cryptid is there right

red flower
#

no it will just fail without errors

stiff locust
#

?

red flower
#

like, you can make it and even if it exists it will just throw a warning before the game loads but it wont do anything bad

stiff locust
#

oh i see

#

i think i'll still not make it if cryptid is present

#

that sounds like not a good idea

cyan lagoon
#

how can i make this not count debuffed aces?

red flower
cyan lagoon
#

thanks

tight pumice
#

Is there a way to conditionally take_ownership of an enhancement? Context is I’m trying to make a voucher that when redeemed modifies the behavior of an enhancement

#

My initial approach was to take ownership of the enhancement and then check for voucher redemption to modify the calculate function, but that doesn’t help with changing the text descriptions on the enhancement and such

daring fern
lament agate
#

can i directly patch an audio file?

#

because using SMODS.Sound for certain stuff does not work

kindred zephyr
#

how do i add a separate text box for a card?

tight pumice
daring fern
daring fern
lament agate
#

and the organ for the high scoring hand

#

using SMODS.Sound does not seem to work

daring fern
kindred zephyr
plain apex
#

does anyone know what the multiplayer nemesis blind uses instead of G.GAME.blind.chips to see the chips your opponent has?

red flower
frosty rampart
#

the "tooltips" this part refers to

kindred zephyr
#

ohhh

#

ty

lament agate
round lion
#

how do you get the current cost of a card

daring fern
knotty granite
#

How do you make it do that you get a joker when you select a certain deck?

daring fern
knotty granite
#

thanks

viscid talon
#
SMODS.Joker{
    key = "windmill",
    config = {
        extra = { chips = 0 }},
    loc_txt = {
        ['name'] = 'Windmill',
        ['text'] = {
            [1] = 'This Joker gains {C:blue}+20{} Chips when a',
            [2] = '{c:attention}card Enhancement{} is removed',
            [3] = '{C:inactive}(Currently {C:blue}+#1#{C:inactive} Chips)',
            [4] = 'CURRENTLY BROKEN!'
        },
    },
    pos = { x = 0, y = 5 },
    cost = 5,
    rarity = 1,
    blueprint_compat = true, 
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = 'CustomJokers',

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

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and not context.blueprint then
        for _, scored_card in ipairs(context.scoring_hand) do
            if context.setting_ability == true then
                card.ability.extra.chips = card.ability.extra.chips + 20
                    return {
                    message = "Upgrade!",
                    colour = G.C.BLUE
                    }
                end
            end
        end
        if context.joker_main then
            return {
                chips = card.ability.extra.chips
            }
        end
    end
}```
#

how do i fix this joker?

#

im aware i havent defined the ability but like

#

idk what smods function is used to declare a card enhancement removal

daring fern
primal robin
#

You know, while developing API or QoL-only mods has own benefits (like no need to draw or come up with new content ideas), it has own drawbacks.
And the biggest 2 of them are: balatro players can't read, and balatro players are lazy.
This makes my life so so much more difficult. Starting from people have no idea how to install mod properly, ending basically too lazy to update mod to get new and better features.

If you will work with smth similar, take this into account. Its much bigger problem that you think

viscid talon
#

ill give this a try

#

hrmb

#

its not gaining chips

daring fern
viscid talon
#
SMODS.Joker{
    key = "windmill",
    config = {
        extra = { chips = 0 }},
    loc_txt = {
        ['name'] = 'Windmill',
        ['text'] = {
            [1] = 'This Joker gains {C:blue}+20{} Chips when',
            [2] = '{C:attention}card Enhancement{} is removed',
            [3] = '{C:inactive}(Currently {C:blue}+#1#{C:inactive} Chips)',
        },
    },
    pos = { x = 0, y = 5 },
    cost = 5,
    rarity = 1,
    blueprint_compat = true, 
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = 'CustomJokers',

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

    calculate = function(self, card, context)
        if context.individual and context.cardarea == G.play and not context.blueprint then
        for _, scored_card in ipairs(context.scoring_hand) do
            if context.setting_ability and G.P_CENTERS[context.old].set == 'Enhanced' and G.P_CENTERS[context.new].set ~= 'Enhanced' then
                card.ability.extra.chips = card.ability.extra.chips + 20
                return {message = localize('k_upgrade_ex'), colour = G.C.BLUE}
            end
            end -- credit to Somethingcom515 for the enhanced ability thing
        end
        if context.joker_main then
            return {
                chips = card.ability.extra.chips
            }
        end
    end
}```
daring fern
viscid talon
#

whenever im here nowadays its either

  • tries coding something with zero equivalent in the vanillaremade wiki
  • a simple mistake

and i love it /positive

#

oke

knotty granite
#

does not crash but does not replace rank

viscid talon
#

it works! thank you

daring fern
knotty granite
#

thanks

#

does the same thing

#

nvm

#

why does this happen?

frosty rampart
#

b is the prefix for backs, not j
so it shouldbe b_sj_2_deck

stoic void
#

j is for jokers

frosty rampart
#

thank you flash card /lh

stoic void
#

LOL

knotty granite
#

thank you thought I put b

#

hmmmmm

stone pecan
#

where do I find the code for Merry Andy's effect?

frosty rampart
#

for editing or reference purposes?

stone pecan
#

I wanted to see how Merry Andy's code works to see how I could go about making my own

frosty rampart
stone pecan
#

thank u

plain apex
# red flower never played mp so i might be wrong but this?

yeah that works heres the code if anyone else uses G.GAME.blind.chips for anything

function Game:update(dt)
    upd(self, dt)

    -- Only run during a game run
    if G.STAGE ~= G.STAGES.RUN then return end

    if G.GAME and G.GAME.blind
        and G.GAME.blind.config.blind.key == 'bl_mp_nemesis' then

        G.GAME.blind.chips = to_big(
            MP.INSANE_INT.to_string(MP.GAME.enemy.score)
        )
    end
end
viscid talon
#

i think im dumb 😭

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

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

it returns with "ERROR" likely because of an undefined key

#

which liek

#

i dont know how to define it so like

#

also it doesnt gimme the monies

knotty granite
viscid talon
#

lemme check my code

#

is this in a localisation file (en-us.lua)

#

i believe you'd need to add a descriptions bit, maybe?

#
    descriptions = {
        Back = {
            b_vremade_abandoned = {
                name = "Abandoned Deck",
                text = {
                    "Start run with",
                    "no {C:attention}Face Cards",
                    "in your deck",
                },

taken from en-us.lua

knotty granite
viscid talon
#

hm

knotty granite
viscid talon
#

idk then :sob

#

im sorry

#

im newer to this than you

knotty granite
#

all good

knotty granite
viscid talon
#

i only started coding proper like, december

#

before that i used to use jokerforge for everything

knotty granite
#

lol I started like 2- 3 weeks ago

viscid talon
#

:o

#

this is so good for 3 weeks ago 🥺

knotty granite
#

I feel like I am doing horribly

sweet pelican
#

Anyone know if theres a way to change the pitch of a sounds if its played within a calculate function? Would I need to make an event?

daring fern
sweet pelican
#

oh, that works in a calculate funtion? for some reason I thought it didnt

#

my fault lol

kindred zephyr
#

i'm not quite sure how SMODS.mod.process_loc_text works, can someone please explain?

wintry solar
#

what are you trying to achieve

kindred zephyr
#

i want to add a localization string

wintry solar
#

you should use a localization file to do that

kindred zephyr
#

i mean specifically i have this line
info_queue[#info_queue+1] = G.P_CENTERS.m_coin
how do i define a p_center

frosty rampart
#

the game should automatically define it

gaunt thistle
frosty rampart
gaunt thistle
#

have you looked at the release notes willy 😭

rough furnace
#

yes

gaunt thistle
#

phew

rough furnace
kindred zephyr
frosty rampart
#

what is it then

kindred zephyr
#

i'm just trying to add a tooltip

frosty rampart
#

to be clear, this is a completely custom tooltip that isn't supposed to be the description for any card modifier/joker/etc in the game?

kindred zephyr
#

yes

frosty rampart
#

put it in descriptions -> Other -> m_coin in your localization file, format it the same (containing a name string and a table of text), and then do this:
info_queue[#info_queue + 1] = { set = "Other", key = "m_coin" }

stone pecan
#

what did I do wrong
[SMODS FOXALATRO "FOXALATRO.lua"]:92: attempt to index field "consumables" (a nil value)

if #G.consumables.cards + G.GAME.consumable_buffer < G.consumables.config.card_limit then

red flower
#

consumeables notice the e

stone pecan
#

augh

#

my bad

stone pecan
#

wait

#

am I stupid

#

I misunderstood sorry

red flower
#

no it's a vanilla typo

#

you need to write it with the typo

stone pecan
#

sobbing

frosty rampart
#

thunk moment

#

did you know that canio's internal ID is j_caino

dreamy thunder
#

did you also know that hierophant's internal ID is c_heirophant

stone pecan
#

what is the fools key for it to be called in add_card ?

#

is it just the_fool or something else

frosty rampart
#

c_fool

stone pecan
#

thanks

frosty rampart
#

all consumables start with c_

kindred zephyr
#

my localization isn't localizationing

quaint lotus
#

hey guys

#

what would your reccomendation for a modding tutorial be

#

or should I just learn Love 2d in general

stone pecan
#

is there an equivalent for for i, removed_card in ipairs(context.removed) do but for joker cards instead of playing cards?

sweet pelican
#

Looking for some help with a joker, trying to destroy a random card for every G.GAME.probablities.normal if you play 5 scoring cards, but I can't wrap my head around how to make the random selection not have a chance of selecting the same card twice, let alone function. I've tried looking at the code for immolate but I can't piece it together, any help would be very appriciated!
(here is what I have so far, I'm aware it wouldnt be functional lol)

red flower
stone pecan
red flower
#

context.joker_type_destroyed but it doesn't work the same way, it's called once per card

stone pecan
#

so if multiple jokers get destroyed at once (ex. Ankh) it would trigger once for each destroyed joker?

#

with context.joker_type_destroyed

red flower
stone pecan
#

great thanks

#

that's what I wanted

sweet pelican
#

Okay, think I'm getting closer, getting an error on line 159, but I think its starting to make a bit more sense, still not sure if this would even function as intended though 😭

#

oops I didnt put the line numbers

red flower
#

you shouldn't have that second if there

#

the syntax is if [condition] then

sweet pelican
#

oh sweet, that makes more sense ty

#

okay I can boot in now but it doesnt seem to be destroying cards, am I using "SMODS.destroy_cards" correctly?

#

actually it's not triggering anything at all, probably something is wrong in the conditions to make it return

#

okay yeah that was it, its crashing now but atleast something is happening lmfao

sour garden
#

had a thought, and was wondering if this would be possible or not with Balatro's engine
would it be possible to make a deck where the top card of the deck is face up? as in, it'll show you the next card you'll draw in your deck?

#

I'm sure it's possible through lovely patches but am curious if SMODS has anything built in for cases like that

red flower
#

i dont think it would be hard to do tho

gaunt thistle
#

iirc you would need to render the other layers of the card

#

I think there's a check for it being in the deck but I cant remember where that is

#

there should be a helper in the game for it

icy nymph
#

New to modding but using the mod manager and grabbing this regirock (Makes all cards act as stone cards) turns all cards white. Who do I need to reach out to? wanna make sure this is on someones radar if they arent aware.

sour garden
#

I know misprint has functionality for getting the rank and suit of the next card in your deck, so I'm sure I can piggyback off something in the base game

red flower
#

the top card is in G.deck.cards[#G.deck.cards]

next pivot
red flower
#

I'm not sure if the alignment in the deck area is from top to bottom or not

umbral zodiac
#

or at least organize them really well in the file

next pivot
#

the toml file's 480 lines long

#

well, total

red flower
icy nymph
#

thanks

umbral zodiac
#

maybe split it just for organization

knotty granite
#

What do I do?

umbral zodiac
#

your localization is not the issue im pretty sure

#

oh wait

#

you opened two tables in the text and only closed one

knotty granite
#

same thing happened

knotty granite
#

the code for the back if you are wondering

umbral zodiac
# knotty granite

it should be text = {"string1", "string2", etc...} not text = {{"string", "string", ...}}

#

that may not fix it but it is an issue

knotty granite
#

ok

vernal path
#

I forgor
am I allowed to put an arbitrary function in my joker (to avoid code duplication)?
Or should I put it somewhere else

vernal path
#

fuck yeah

umbral zodiac
#

the entire thing is copied over so you can just , do that

sweet pelican
#

I think I'm grossly misunderstanding how to use SMODS.destroy_cards 😭

knotty granite
#

worked

stone pecan
#

is it possible to have a function on a joker that detects when playing cards are triggered by any means

#

*retriggered

sweet pelican
umbral zodiac
#

what did you do 😭😭

#

are you on like 7 month old smods or what

sweet pelican
#

uhhhh I don't think so lmfao

umbral zodiac
#

oh one issue with your code

sweet pelican
#

1.0.0~BETA-0506a-STEAMODDED

umbral zodiac
#

Oh my god

#

you actually are on 8 month old smods

sweet pelican
#

LMFAO

umbral zodiac
#

i was JOKING

sweet pelican
#

BAHAHA

knotty granite
#

It doesn't display the deck correctly...

umbral zodiac
stone pecan
sweet pelican
#

Okay I'll update that thank you

stone pecan
#

😭

umbral zodiac
#

add atlas = "2_deck", somewhere

knotty granite
#

ok

stone pecan
#

I found context.repetition in the wiki but I'm not sure it works perfectly for this since it seems to randomly add values when nothing happens

umbral zodiac
sweet pelican
umbral zodiac
#

context.repetition is for adding retriggers, not for checking them btw

knotty granite
#

I never thought making a back would be this hard 😭

umbral zodiac
#

do you have a 2x version of your png

knotty granite
#

yes

umbral zodiac
#

hm

#

can i see your whole deck definition again

knotty granite
umbral zodiac
#

ah

#

you set pos to x=1,y=3
but your atlas is only one sprite

#

anything past that is just treated as empty space - it doesn't loop over

knotty granite
#

so put it to 0,0?

umbral zodiac
#

yes

glass scaffold
#

yep

spiral mural
vernal path
#

in loc vars return put a localize { name = "whatever", etc }

#

also hiii heloo haiii :3

umbral zodiac
#

meow

umbral zodiac
sweet pelican
#

OKAY SO ITS KINDA WORKING, only issue is its destroying cards left in my hand, not the scoring ones, I'm assuming I need to change "G.hand.cards" to something to refer to specifially the scoring cards?

umbral zodiac
#

oh yes

sweet pelican
umbral zodiac
#

g.hand is your hand, G.play is the cardarea youre looking for

sweet pelican
#

OK

#

wonderful

umbral zodiac
#

also

#

you should probably movew the smods.destroy cards outside of the return but still inside of the if-statement

sweet pelican
#

okay I'll try that too, thank you!

umbral zodiac
#

its not technically an issue but basically youre returning xmult = [number], message = [string], 1 = nil, remove = [boolean]

#

which is a little strange

vernal path
# umbral zodiac the entire thing is copied over so you can just , do that

Would this be how you call it?

  update_hands = function(card)
    if G.playing_cards then
      local steel_tally = 0
      for _, playing_card in ipairs(G.playing_cards) do
        if SMODS.has_enhancement(playing_card, 'm_steel') then steel_tally = steel_tally + 1 end
      end
      local new_handsize = math.min(math.floor(steel_tally / card.ability.extra.divisor))

      local change = new_handsize - card.ability.extra.hand_size
      if change ~= 0 then
        G.consumeables:change_size(change)
        card.ability.extra.hand_size = new_handsize
      end
    end
  end,

  calculate = function(self, card, context)
    if context.remove_playing_cards or context.playing_card_added or context.setting_ability then
      card.ability.update_hands(card)
    end
  end,```?
umbral zodiac
#

nah itd be umm

#

i believe self:functionname(card)

vernal path
#

well, it'd be . since i'm not asking for self

umbral zodiac
#

right

#

probably should just because its standard with every other function but thats up to you

vernal path
#

:P

umbral zodiac
#

either way it would be self rather than card.ability in which you find the function

vernal path
#

yaha! it works!

tidal hemlock
#

how does one make a subcategory of hand type (like how royal flush is a subcategory of straight flush, though its still a straight flush)

knotty granite
#

how would I make a joker that makes all cards considered the first played card?

#

I might know how

next pivot
# next pivot
poll_question_text

for my patches (my mod is basically just patches), do I:

victor_answer_votes

3

total_votes

4

victor_answer_id

2

victor_answer_text

split it

frosty rampart
# knotty granite how would I make a joker that makes all cards considered the first played card?

i don't think that's feasible
the way content generally checks for "first played card" is just to check if the card is the first element in G.play.cards, which is like. a regular array. you could probably do some shenanigans with moving cards into the first slot when it's their time to score, but that might have visual effects + it won't work with anything that affects the first played card outside of context.individual

knotty granite
#

dang

#

so this won't work?

subtle hawk
#

Literally does nothing

frosty rampart
#

even if it was feasible to do what you set out to do, that would not be remotely close to it

knotty granite
#

ok

#

I don't know what to make

subtle hawk
winter flower
knotty granite
#

how would you check if you played a hand with context

stone pecan
#

I saw something about accessing the discard pile in the smod wiki but I'm not sure how to make use of it, how would i for example access the last card in the discard pile?

#

something to do with context.cardarea == G.discard

main pebble
#

when adding rarities to the atlas how do i actually add them to the rarity pool

#

i thought adding new ones would make it default to 5 since 4 is legendary

#

doing rarity = "whatever" doesn't work

knotty granite
#

how do I debuff a random joker?

main pebble
#

something like

red flower
#

it should be modprefix_key

red flower
random basin
#

how do I make variables in joker text update in menus? more specifically where do I put the condition to update those variables to be updated in the menu?

main pebble
main pebble
glass scaffold
random basin
#

left is in use, right is in collection/shop

#

like how people spy the top of the deck with misprint

glass scaffold
random basin
#
SMODS.Joker {
    key = "Dusty Cabinet",
    loc_txt = {
        ['name'] = 'Dusty Cabinet',
        ['text'] = {
            [1] = '{X:chips,C:white} +1 {} Chip for every person playing',
            [2] = '{X:default,C:edition}#1#{} on {C:dark_edition}Steam',
            [3] = '{C:inactive}(resets every blind)',
            [4] = '{C:inactive}Currently {C:blue}+#2#{C:inactive} Chips'
        },
        ['unlock'] = {
            [1] = 'Unlocked by default.'
        }
    },
    cost = 4,
    rarity = 2,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = true,
    config = {
        extra = {
            name = "",
            activegame_players
        }
    },
    loc_vars = function(self, info_queue, center)
        return {
            vars = {center.ability.extra.name, center.ability.extra.activegame_players}
        }
    end,

    calculate = function(self, card, context)
        recheckSteam()
        card.ability.extra.activegame_players = activegame_players
        card.ability.extra.name = activegame_name
        if context.joker_main then
            return {
                color = G.C.BLUE,
                message = "+" .. card.ability.extra.activegame_players,
                chip_mod = card.ability.extra.activegame_players
            }
        end
        if context.end_of_round and context.game_over == false and context.main_eval and not context.blueprint then
            recheckSteam("please")
            return {
                message = localize('k_reset')
            }
        end
    end
}```
#

recheckSteam() calls steam api code for a random game name/active player count, similar to the yahimod twitch logic

red flower
glass scaffold
main pebble
random basin
#

that helps but I think I need to call recheckSteam at an earlier time

#

values are just the default of my local variable bc it doesn't run that until calculate()

#

let me check how vanillaremake misprint works

glass scaffold
red flower
red flower
glass scaffold
#

Then it'd be MODPREFIX_RARITYKEY?

red flower
#

yeah

hallow moat
#

is it possible to make a mod that allows me to run tarot loops as fast as possible? I already have the script for loop automation, but even with animation skip I still have to wait a half second after emperor to use the next tarot

main pebble
#

works but the badge color and the rarity name don't show up

#

vanilla remade doesn't have much info on adding new rarities

red flower
#

where is that

main pebble
#

localization

#

no clue how to localize rarities

red flower
#

did you read the documentation

loud summit
#

hi!

#

so im having an issue with a custom context not working

#
SMODS.current_mod.calculate = function(self, context)
    -- [...]
    if context.nflame_post_shuffle then print("otherside") end
end

local cas = CardArea.shuffle
function CardArea:shuffle(_seed)
    local retr = cas(self, _seed)
    print("from hook")

    local sortab_raw = {}
    local sortab = {}
    SMODS.calculate_context({ nflame_post_shuffle = true, cardarea = self, seed = _seed }, sortab_raw)``` these two prints work just fine and fire properly
#

so its not an issue with setting up the context

#

but in my boss calculate function lua calculate = function(self, context) if context.seed then print(context.seed) end if context.nflame_post_shuffle then print(context.seed)

#

it doesnt hit either trigger

red flower
#

does it work if you print without any context check

loud summit
#

hm ill try that

red flower
#

oh it wont

#

its missing an argument

#

self, blind, context

loud summit
#

oh

#

docs are just wrong moment

#

yea that fixed it

red flower
unkempt bronze
#

(fyi, it's supposed to buff the second most common suit ignoring ties)

glass scaffold
#

Why is it showing x1 for both Chips and Mult in the game, but xnil for Money?

crisp coral
#

card.ability.extra

glass scaffold
glass scaffold
daring fern
#

‎

knotty granite
#

how do you debuff a joker>

#

?

granite raptor
#

if i'm using a localization file, when creating a joker/deck/etc should there be something else in place of the loc_txt field?

red flower
ashen parrot
#

how would I set a specific card's repetitions?

#

trying to do a "mime" effect for specific cards in hand

#

I have the card object from its index in the hand if that helps

#

I'd assume just returning a repetitions value would affect all cards

open moth
#

Some guy asked me to make a joker that restores the last destroyed glass card at the start of a blind, any way I could do this?

ashen parrot
#

wouldn't that affect it permanently?

#

I just want it while it's in hand

daring fern
daring fern
open moth
#

Ok

#

I'll try it out

#

Thanks

ashen parrot
daring fern
open moth
ashen parrot
#

trying to retrigger cards adjacent to a specific card in hand

#

not sure how I'd do that

open moth
wooden orbit
#

i wonder why this is erroring

#

trying to check whether a file is a directory/folder

#

well

#

i know why it is erroring but im clueless as to how i would be able to check a file's info

#

oh

#

oops

#

i forgot to add an slash

white hull
#

can i change the sound of a message return without changing the message? returning sound doesn't work

loud summit
#

i believe the scoring sounds are hardcoded?

white hull
#

ouch

daring fern
# white hull ouch

mult_message = {message = 'message', sound = 'modprefix_key', colour = G.C.colour}

loud summit
#

you can use localize to create the mult message and set that tho

#

i dont remember the key for it :(

white hull
#

bummer

granite raptor
#

if i wanted to run a function each time jokers are rearranged (via dragging or jokers being added/destroyed), how would i go about this? is there a function i should hook into, is there a relevant context for this, or?

stone pecan
#

can i use context.other_card to check a card against copy_card?

#

as in if i used copy_card earlier to copy a playing card and then used context.other_card to try and see if its the same card as before

#

does that work or do i need to use a different function/context

daring fern
stone pecan
#

i think i meant to use get_id()

#

my bad

daring fern
stone pecan
#

oh, okay

red flower
red flower
#

copied_card.modprefix_flagname = true if you only need it for a calculation cycle or copied_card.ability.modprefix_flagname = true if you need it to be saved

(you need to set it to nil after using it)

stone pecan
#

thank you

#

`calculate = function(self, card, context)

    if context.individual and context.cardarea == G.play then
        local check_copy = copy_card(context.other_card, nil, nil, G.playing_card)
        check_copy.states.visible = nil
        
        if check_copy.FOXA_flagname == true then
            return {
                xmult = card.ability.extra.x_mult
            }
        end
        check_copy.FOXA_flagname = true
    end
end`

not sure what i've done wrong here, my intention was to have an effect where if a card is retriggered it grants x mult (check if the card that just scored is flagged, meaning it was scored before, as its supposed to flag a card after scoriing it the first time)

wind steppe
#

yeah you're setting the flag on the copy

#

theres no reason to copy the card at all

#

also you need to reset the flag after a hand is played

slim ferry
#

what

slim ferry
wispy falcon
#

Hello, it's been a bit. I'm still struggling to get this to work.

I want the edition to have a fixed 1 in 4 to not trigger. The problem right now is that it is triggering non-stop and I don't know how to change that.

tight pumice
#

I’m still having a bit of an issue trying to make an enhancement work differently (and have different text) once a voucher is redeemed. The main thing is the text, I was told to return a key to a localization entry in loc_cars but I’m a little lost

#

Trying to take ownership of an enhancement and then check for voucher redemption to then alter its behavior

#

That itself seems to be fine, but swapping out the text of the card seems tricky

daring fern
tidal hemlock
#

trying to make a joker that makes numbered cards also be treated as double their number. what did i do for this to happen

daring fern
tight pumice
#

This looks better

daring fern
# tidal hemlock

You're returning 14 every time but also that is not how you do quantum ranks.

tight pumice
#

Not even trying to do the voucher logic rn, just trying to test if I can get the localization entry to pop up for the card's text at all since until now I've just done loc_txt for stuff

daring fern
tight pumice
#

Tried this and self.key instead of key, first one didn't work and the second one crashed

#

hm wait

#

I see my problem

#

Okay fixed that, is there a way for me to implement the voucher logic specific part? I want the key to stay the same unless the voucher is redeemed I suppose?

#

Or maybe I can conditionally take ownership of the enhancement once the voucher is redeemed. Not sure what would work as the best method

daring fern
tight pumice
#

Good to know

#

My initial thought is some method of checking for voucher redemption and then setting the key as a result of that, but I don't think that would work since that kind of logic might need to happen after the text stuff is already finished

white hull
#

aren't vouchers also evaluated during scoring

#

just have the voucher itself give xchips for stones held in hand

tight pumice
#

So within the voucher itself do calculate and context stuff

white hull
#

i think so

#

like observatory

daring fern
hard needle
#

how do you get the level of the played poker hand?

daring fern
hard needle
#

was more so confused on how to get the played poker hand i forgot context.scoring_name is a thing

viscid talon
#

idk what i am doing

tight pumice
viscid talon
#

to elaborate, it crashes when i try and do "scored_card"

white hull
#

How can I make a consumable stick around until a function that it called is finished running? It disappears immediately and when the booster pack closes the game freezes

viscid talon
#

im trying to have it so it converts all played cards into hearts

white hull
#

me too bestie

daring fern
viscid talon
wispy falcon
daring fern
daring fern
wispy falcon
daring fern
viscid talon
#

ok good news, it flips

#

bad news, it doesnt convert all played cards into hearts

slim ferry
#

how can i get all held cards with a specific edition (just like SMODS.find_card)

viscid talon
daring fern
daring fern
unkempt bronze
wispy falcon
final jewel
#

What is the condition that make a consumable usable in a pack

#

like G.GAME.pack.in_pack idk

white hull
#

i don't want the player to keep it, i just need it not to disappear for a bit of time

#

i.e. so the booster pack doesn't immediately close

slim ferry
daring fern
lament agate
#

is this cryptlib thing

#

because it doesnt show the localization text

scarlet spire
#

has anyone else experienced context.post_trigger issues like this?
basically, I have a joker that gains chips when another joker triggers. but for some reason, if I have Oops all 6s, this joker gains chips basically any time I hover over an item in the shop
I could technically just exclude any joker named Oops all 6s, but it'd be nice to know the actual source of the problem so I could fix that instead

wispy falcon
#

Real quick, what is the name of the variable that is all the mult in the scoring?

scarlet spire
#

1317a

viscid talon
#

i have a joker that makes it so when you play a flush, it converts all played cards into random suits

#

although it worked, it was a little janky

#

so i decided to add a flip animation

#

now it isnt working

#

this was originally generated using jokerforge

viscid talon
#

but i went back and added the extra flip code myself

#

now idk what to do

daring fern
viscid talon
#

im gonna go to the bathroom rn, but ill need some clarification as to what it is i may need to do

red flower
lament agate
red flower
#

the description you want to add, check if your code removes it

red flower
#

it should be there by default

lament agate
#

hold

lament agate
# red flower it should be there by default
BadDirector.description_loc_vars = function()
    return {
        text_colour = G.C.WHITE,
        background_colour = G.C.CLEAR,
        scale = 1
    }
end

SMODS.current_mod.custom_ui = function(nodes)
    local logo = {

        n = G.UIT.R,
        config = {
            align = 'cm',
            colour = { 0, 0, 0, 0 },
            r = 0.3,
            padding = 0.25
        },
        nodes = {
            {
                n = G.UIT.R,
                config = { align = 'cm' },
                nodes = {
                    {
                        n = G.UIT.O,
                        config = {
                            object = SMODS.create_sprite(
                                5, 0,
                                8, 4,
                                'bd_modlogo',
                                { x = 0, y = 0 }
                            )
                        }
                    }
                }
            }
        }
    }
    table.insert(nodes, 2, logo)
    return nodes
end
#

the text thing is there

red flower
#

hmm

#

if you comment the table.insert(nodes, 2, logo) does it appear

lament agate
#

do i remove the loc vars thing?

red flower
#

try it

#

maybe one of the configs is wrong

red flower
lament agate
#

EXACTLY WHAT IM THINKING

#

😭

#

it happens after i added Mod

#

it shows but no text?

red flower
#

ok can i see the loc

lament agate
red flower
#

i think thats the problem

lament agate
red flower
#

that part is fine because it wouldnt break it otherwise

viscid talon
#

oke am back

#

what do i doooo 🥺

lament agate
#
return {
    descriptions = {
        Mod = {
            baddirector = {
                    "{s:1.2}Test{}"
                }
        },
red flower
#

ah yeah thats the problem

lament agate
#

oh?

#

which

white hull
# daring fern Yes, you would make it disappear after the function runs.

I'm not following
By "function" I mean the consumable calls a function outside of itself when it's used, and then immediately dips
This causes issues because the function operates on cards in hand, and if the consumable is in a booster pack, the pack closes before the function is done and it softlocks the game
So I need the consumable not to dip before the function is done doing the thing

red flower
lament agate
#

oh it needs name and text

#

thats odd

#

hold on

red flower
#

thats why it breaks the button too

lament agate
#

fair

wraith jolt
#

Hi, I trying to figure out if I got this code correctly placed

#
                text = {
                    'Every played odd card {C:attention}odd{}",
                    "{C:inactive,s:0.8}(Excludes face cards){}"         'permanently gains',
                    '{C:red}+2{} Mult when scored'
                }```
red flower
#

where is it placed..?

primal robin
#

It's just incorrectly formatted

#

and missing a comma

daring fern
wraith jolt
#

It place in Localization

primal robin
#

what is even this util function goddamn

#

SMODs is goddest class ever, thats crazy

wraith jolt
primal robin
#

between 2 string in middle line place comma and it should work

#

Also adding "+2" in localization is working but not correct way to do it, use loc_vars

scarlet spire
lament agate
#

i just gotta position the logo correctly

#

no matter what i do, it always stretches

primal robin
#

wrap it in container then

lament agate
#

what container

primal robin
#

in other element, row in this case

#

Set sizes for this row

lament agate
primal robin
#

You actually already did this I see

lament agate
#

yeah

primal robin
#

Then just adjust sizes for sprite you create

#

w = 8 and h = 4 is probably not correct ratio for your sprite

lament agate
#

whats the first and second parameter

primal robin
#

x, y

lament agate
#

ohhh

primal robin
#

when its placed inside G.UIT.O has no effect

lament agate
#

noted

viscid talon
#

hi

tidal hemlock
tidal hemlock
#

ok why and what is 14

#

and why is it being returned

hallow saddle
#

If I have a .jokerforge file, can I convert it to lua somehow so I can code in effects that joker forge doesn't support?

#

Im not great at lua yet so I was tryna get as much mileage out of jokerforge as I could

daring fern
tidal hemlock
#

ah

#

that's not supposed to happen at all

#

what are ids of the numbered ranks, if not just the numbers themselves

daring fern
smoky holly
#

when making effects that destroy cards is it supposed to play the destroy sound automatically or do we need to add it in?

red flower
#

it does play a sound im pretty sure

white hull
hallow saddle
white hull
#

i mean export it like a finished mod

smoky holly
white hull
#

then inside the .zip with the mod there will be .lua files and other stuff

daring fern
white hull
#

that you could look at

hallow saddle
#

Yea, I got it exported and such, my issue is that I wanted to add joker effects -- like a midas mask that adds mult cards under certain circumstances -- but I don't know how to code said file, like if I can write in it

#

would I break the whole thing

white hull
#

.lua files are just text, you can write in them

smoky holly
#

so why is this not playing the sound then?

        local config = card.ability.extra

        if context.after and G.GAME.current_round.hands_played == 0 and #context.full_hand == 1 then
            local played_card = context.full_hand[1]

            if played_card.base.value == config.triggering_rank then
                SMODS.destroy_cards(context.full_hand)

                J_O_Y.create_tag {
                    predicate = function(tag_key)
                        return tag_key == "tag_" .. config.tag
                    end
                }

                return { message = localize "j_o_y_fart" }
            end
        end
    end```
white hull
#

but again, jokerforge code is convoluted and you'll be better off starting from scratch yourself

hallow saddle
#

aight so I can write in it as if its a lua file?

#

cool

#

Ill try and redo things, thanks!

tidal hemlock
# tidal hemlock

ok so i fixed the return issue, but i want them to also be treated as their original rank, without having the opposite relationship. any help?

unkempt bronze
daring fern
# unkempt bronze bump again
local suits, suits2 = {}, {}
for k, v in pairs(G.playing_cards) do
    suits[v.base.suit] = (suits[v.base.suit] or 0) + 1
end
for k, v in pairs(suits) do
    table.insert(suits2, {suit = k, count = v})
end
table.sort(suits2, function(a,b) return a.count < b.count end)
card.ability.extra.target_suit = suits2[#suits2-1]
hallow saddle
#

Are their resources for balatro keywords? Like is_face i see in the midas mask remake, is there like is_enchanted or is_multcard

daring fern
hallow saddle
#

Thanks!

#

Is there anywhere I can look for these keys rather than ask about them all here

red flower
#

theres a page on the left with all the keys

hallow saddle
#

thats hilarious, thank you

smoky holly
#

oh wait really

#

oh my god

#

lmao

red flower
#

yeah its nice, ive never used jf but i use that page

red flower
hallow saddle
#

yea I got a remake of midas mask up atm

#

its a weird joker effect but having this as a semi reference helps a lot

#

wait you made this midas mask, lmao, thanks for the framework

red flower
#

:3

hallow saddle
#

loc_vars = function(self, info_queue, card)
info_queue[#1116390750314307698_queue + 1] = G.P_CENTERS.m_gold
can I ask what this does? It runs on midas before the function does

frosty rampart
#

the loc_vars function handles passing variables to localization (e.g. a scaling joker displaying its current value) and adding tooltips next to descriptions (e.g. the description for Gold Cards appearing next to the description for Midas Mask)

hallow saddle
#

cool, thanks!

daring fern
smoky holly
#

how is that used to destroy a card? wouldnt that only check if a card is destroyed?

frosty rampart
hallow saddle
#

how do I check the position of the card

#

I wanted to enchant a random card in the hand if that helps the answer

mystic river
#
local pos
for i,v in ipairs(G.hand.cards) do
 if v == card then pos = i break end
end
white hull
mystic river
#

and if pos is nil after that it means the card isn't in G.hand

slim ferry
smoky holly
#

so, hold on

slim ferry
#

or at least theres no reason to do the loop

frosty rampart
#

what exactly is the intended behavior here
you want to destroy a card after a hand is played, right?

daring fern
mystic river
smoky holly
#
        local config = card.ability.extra

        if context.after and context.destroy_card and context.cardarea == G.play and G.GAME.current_round.hands_played == 0 and #context.full_hand == 1 then

            if context.destroying_card.base.value == config.triggering_rank then

                J_O_Y.create_tag {
                    predicate = function(tag_key)
                        return tag_key == "tag_" .. config.tag
                    end
                }

                return {
                    message = localize "j_o_y_fart",
                    remove = true
                }
            end
        end
    end```
#

i want it to work like how sixth sense does

slim ferry
frosty rampart
smoky holly
#

when does destroy card happen?

slim ferry
#

on its own

frosty rampart
#

it's its own thing

smoky holly
#

ah ok

#

thank you

mystic river
ashen parrot
#

why does this for loop keep resulting in slot being 2 (slots_to_retrigger is populated with several values)

smoky holly
#

it works!

ashen parrot
#

like its exclusively just 2

mystic river
#

... i don't know why it's 2, but it's returning early

ashen parrot
#

ah