#💻・modding-dev

1 messages · Page 686 of 1

hushed stump
#

is SMODS.displaying_scoring the correct context to check anyway?

#

a better question, how do modders check current in-game values?

frosty dock
hushed stump
#

correct for checking when is the poker hand displayed

frosty rampart
#

debugplus has a console you can access at any time by pressing /
you can run eval any valid lua code in the console to run code

frosty dock
#

i'm not sure what exactly SMODS.displaying_scoring is used for, but i don't think it helps you if you're just evaling things?

hushed stump
frosty rampart
#

you can just eval it in the console on G.hand.highlighted instead

frosty dock
#

eval doesn't help you run code at any specific timing other than through hooks

#

checking for SMODS.displaying_scoring will check if it's true right now and doesn't care about what happens sometime else

hushed stump
#

okay...

frosty rampart
#

i feel like you're still missing the point that debugplus has a console where you can evaluate code at will

frosty dock
#

if you want to constantly display the info while hand is being selected, you want UI for this like I said

hushed stump
#
INFO - [G] > eval G.FUNCS.get_poker_hand_info(G.play.cards)
INFO - [G] < NULL, NULL, Table:
Flush House: Table:

Full House: Table:

top: Table:

Flush: Table:

Pair: Table:

Four of a Kind: Table:

Straight Flush: Table:

Straight: Table:

Three of a Kind: Table:

Flush Five: Table:

Two Pair: Table:

Five of a Kind: Table:

High Card: Table:

, Table:
, NULL
#

idk if i should evaluate it with G.play.cards as an argument

#

it returned all possible hands

#

but not just with my cards, with all cards

frosty dock
#

it returned no hands, actually

#

all of these are empty

hushed stump
#

oh

frosty dock
#

you want G.hand.highlighted

frosty rampart
#

G.play.cards only exists while a hand is being scored, if you run the code any time else it's empty
like i and aure said, you should do it with G.hand.highlighted instead, and that will get the poker hand info based on the hand you currently have selected

frosty dock
#

cards only move to G.play once you play them, otherwise it's empty

sleek valley
#

how do i display the description for a custom edition?

#

this isnt working, but idk why

frosty dock
sleek valley
#

ah, thx

frosty rampart
#

^ editions have an e_ prefix, like jokers have a j_ prefix

hushed stump
#

Alr that's more reasonable but what do these values even mean

#

i see that the available poker hands have a table, and the other ones have an empty table

frosty dock
#

printing cards is usually unhelpful

#

as for what these are, each entry is an array of arrays of cards, each representing a possible instance of the hand

hushed stump
mystic river
#

all you did was put its returns into local variables
you need to return the variable you want in the eval

frosty dock
#

assigning things to local variables does return nil

#

also you messed that codeblock up pretty bad

hushed stump
frosty dock
#

it's because you have unescaped _ making italics

#

discord likes to be extremely funky with those

hushed stump
#

crap

frosty dock
#

whatever

hushed stump
#

INFO - [G] > eval local pokerhand = G.FUNCS.get_poker_hand_info(G.hand.highlighted)
return pokerhand
INFO - [G] < Pair
yeeeey
at least i got the hand it should be played. it's the first argument of the table. no surprise

#

seems like it's a table containing a very big bunch of tables. that's not good

#

whatever
i'll focus on SMODS.PokerHandPart

teal grotto
#

does it not affect poker hand evaluation or am i just stupid

frosty rampart
#

...and it also doesn't fully support poker hand calculation as far as i'm aware
-# - me

daring fern
teal grotto
#

tysm

thorn ingot
#

Hey guys. Do you know if I can make a deck give a tag at the beginning using the config like with vouchers?

I tried to use config = { tag = { 'tag_coupon' },, but it doesn't work. 😑

faint yacht
#

Add an event in apply function that gives a tag.

apply = function(self, back)
    G.E_MANAGER:add_event(Event({
        func = function()
            if G.playing_cards then
                add_tag(Tag('tag_coupon'))
                play_sound('generic1', 0.9 + math.random()*0.1, 0.8)
                play_sound('holo1', 0.4, 1)
                return true
            end
        end,
    }))
end,

for adding a Coupon Tag at start of run, as example.

weak grove
#

yo can someone code a bossblind for me? The Curse: Each hand, (ante/1.25+1)X Blind size. Mult: (1/ante+1), Dollars: (ante * 5)

thorn ingot
sleek valley
#

can someone help me understand the booster pack background colour?
vremade uses G.STATES and i see cryptid using G.C but i dont know how to make either of those work for me
i have the custom colours i want to use, i just dont know how to write it properly

frosty rampart
# sleek valley can someone help me understand the booster pack background colour? vremade uses ...

the G.STATES stuff only works with vanilla stuff, it will be of no use here
for custom colors, here's what you do

ease_background_colour = function(self)
  ease_colour(G.C.DYN_UI.MAIN, CUSTOM_COLOR_HERE)
  ease_background_colour { new_colour = CUSTOM_COLOR_HERE, special_colour = G.C.BLACK, contrast = 2 }
end

replace CUSTOM_COLOR_HERE with whatever color you want. for the simplest way to go about it, you can literally just use HEX("FF00FF") with any hex color code; cryptid saves them in G.C but that's not strictly necessary, it's only a time save for if you use the color in a lot of places and you end up wanting to change it

sleek valley
#

Ah okay, so does that just mean G.C is just another form of G.ARGS.LOC_COLOURS?

daring fern
sleek valley
#

Well shit then

sleek valley
normal crest
#

you don't need to put them in G.C

#

if you're only going to use it for the booster you could define a local variable before the call to SMODS.Booster for example

faint yacht
#

Or just pass HEX('FFFFFF') directly.

#
ease_background_colour({ new_colour = HEX("515966"), special_colour = HEX("121417"), contrast = 1.25 })

also works.

rapid stag
#

...hm? i thought HEX() only took 8-digit hex codes

last time i did a 6-digit hex code, i got a crash

faint yacht
#

¯_(ツ)_/¯

#
function HEX(hex)
  if #hex <= 6 then hex = hex.."FF" end
  local _,_,r,g,b,a = hex:find('(%x%x)(%x%x)(%x%x)(%x%x)')
  local color = {tonumber(r,16)/255,tonumber(g,16)/255,tonumber(b,16)/255,tonumber(a,16)/255 or 255}
  return color
end
sleek valley
rapid stag
light tangle
#

heya folks, was wondering if anyone knew how to check if a played poker hand contains a certain enhancement? i'm doing it with custom one but even just knowing if it has a stone card for example will do lol

#

the final goal is to check for a pair with at least one card having whatever enhancement

#

i've seen mods with poker hands having stone cards and stuff before so i know it should be possible

#

just not sure where to look

daring fern
# light tangle just not sure where to look
if context.scoring_name == 'Pair' then
    local passed = false
    for k, v in pairs(context.scoring_hand) do
        if SMODS.has_enhancement(v, 'm_modprefix_key') then
            passed = true
        end
    end
    if passed then
    end
end
light tangle
#

i think i found it my own way lol

#

looked at how cryptid does stone card hands

#

but thx :)

#

he's real

daring fern
light tangle
#

ah i see

#

would this be in the evaluate for the poker hand?

#

this is what I have currently

#
evaluate = function(parts,hand) 
        if next(parts._2) then
            print("SB -- is pair")
            local settebello = false

            local _pair = parts._2

            for _,v in ipairs(_pair) do
                print(#_pair)
                for i = 1, #v do
                    print("SB -- ", v[i].base.value)
                    print("SB -- ", v[i].config.center_key)
                    settebello = settebello or v[i].config.center_key == 'm_sb_settebello'
                end
            end

            if settebello then
                return parts._2
            else return {} end
        end
    end
#

new to modding balatro so i'm figuring it out as i go really

daring fern
light tangle
#

ahhh

#

i think when i tried to do it like that before i forgot that there's another level down in the arrays

#

thanks very much :)

rapid stag
#

...how do i iterate through every card in the deck again? cirDerp

daring fern
rapid stag
daring fern
rapid stag
#

sanity check: localize{ type = 'name_text', key = 'e_foil', set = 'Edition' }?

woven flame
#

why do jokers i add show up in the shop even if i own them? I haven't added anything that would make that happen so is there something i need to add to make it so they can't show up multiple times?

idle plaza
woven flame
#

is that seriously the issue? dang well thanks

final jewel
final jewel
# daring fern Code?

for the overcharge if context.giga_pre_joker and context.cardarea == G.play then return { func = function() for _ = 1, self.config.extra.tarot + math.floor(Giga.discarded_overcharge() / 4) do if SMODS.pseudorandom_probability(card, pseudoseed('giga_orangeovercharge'), self.config.extra.odds, self.config.extra.chances) then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ func = function () SMODS.add_card({set = 'Tarot', edition = 'e_negative'}) G.GAME.consumeable_buffer = 0 return true end })) SMODS.calculate_effect({ message = localize("k_plus_tarot"), colour = G.C.PURPLE }, card) else if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ func = function () SMODS.add_card({set = 'Tarot'}) G.GAME.consumeable_buffer = 0 return true end })) SMODS.calculate_effect({ message = localize("k_plus_tarot"), colour = G.C.PURPLE }, card) end end end return true end } end

#

for the potteryif context.destroy_card and context.cardarea == G.play and context.destroy_card == card and SMODS.pseudorandom_probability(card, pseudoseed('giga_pottery'), card.ability.extra.odds, card.ability.extra.chances) then return { func = function() if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ func = function () SMODS.add_card({set = 'Giga_Artefact'}) G.GAME.consumeable_buffer = 0 return true end })) SMODS.calculate_effect({ message = localize("k_plus_artefact"), colour = HEX('444444FF') }, card) end return true end, remove = true } end

frosty rampart
#

that causes the pottery to think that there won't be any room, even though there will

final jewel
#

oh ok

#

thx

teal grotto
#

how to make the game update what poker hand you're making when you move cards instead of just selecting/deselecting

fading rivet
#

how can I tell if a card is generated in the collection

daring fern
fading rivet
#

thx

wary moth
#

Is there ways to manipulate the calculation process mid-calculation?
As two examples of what I mean:

  • A joker that changes the card scoring to happen upon the joker itself scoring instead (so that scoring starts at held-in-hand, then scores jokers until it reaches this joker, in which case it scores your cards, and then continues scoring the rest of the jokers to the right of this one)
  • A joker that skips scoring the joker to the right (different from a debuff since its only blocking the "context.cardarea == G.jokers and context.joker_main" context on the joker to the right)
daring fern
wary moth
# daring fern For the first one you would hook `SMODS.calculate_main_scoring` and end it early...

Oh wow, super cool that this is possible at all
What would hooking SMODS.calculate_main_scoring look like?
I know I can hook like this:

local old_main_scoring_func = SMODS.calculate_main_scoring
function SMODS.calulcate_main_scoring(context, scoring_hand)
   --Some Code here to do prior
   old_main_scoring_func(context, scoring_hand)
   --Some Code here to do after
end

But, it sounds like you're suggesting here to modify something mid-function, and I'm not sure where I would go about doing that

frosty dock
#

for mid-function modifications, you'd have to use a lovely patch

wary moth
#

ahh okay I'll have to look into that ty

daring fern
lyric wadi
#

man i wsih there's likje ways to pin these

#

i dont have a use for it right now but it would be so good to have it for later

fading rivet
#

or another server

wary moth
#

For the first example, could I just hook eval_card, skip and cache anything where context.cardarea == G.play and then call the cache when the card is that joker?

wary moth
lyric wadi
#

yeah thats what i wanted to do but with not as much effort as you

wary moth
#

I've not gotten very far and it might be ambitious, so..
I'm not sure how well itll turn out lol

lyric wadi
#

like i dont have any concepts or ideas for mechanics that'd use this function right now

fading rivet
slim ferry
#

is there still a proper way now to detect if a badge is your own mod's badge? i used to check DynaText.string but that doesnt seem to be working anymore as it creates a bunch of extra dynatext in the top left

lyric wadi
#

but like what if i need it later

#

maybe im a hoarder

fading rivet
#

vremade wiki

lyric wadi
#

eh

daring fern
fading rivet
#

if its not on there make a pr

wary moth
daring fern
wary moth
#

awesome tysm I'll write that down

daring fern
wary moth
#

Yeah but, figuring out WHAT the methods do I was wondering how one would do that?

#

tried looking at the SMODS github documentation but didnt see anything about SMODS.calculate_main_scoring

fading rivet
wary moth
#

putting "vremade" in quotes to specifically search for that term is just not showing anything

#

(is it a typo?)

lyric wadi
#

vanillaremade

fading rivet
lyric wadi
#

yeah doing shortform isnt gonna show up

wary moth
#

Ahhhh gotcha thank you

lyric wadi
#

to be fair we did not make that clear

wary moth
#

I feel so dumb most the time lol, I feel like I barely know what I'm doing or whats going on
New to modding, and modding balatro, and new to some of the enviornments (like navigating github wikis), so I think I'm missing a lot of common knowledge

lyric wadi
#

to be fair the common knowledge is very badly documented

#

like github wiki is terrible at being a wiki

wary moth
#

I got a whole lot of C# programming experience, so, I'm working off of mostly JUST that (which is vastly different from lua), and skimming through examples and discord history
I really appreciate the people here, yall been like, very very helpful

lyric wadi
#

and most of the answers you'd want are lost in the logs of this chat

wary moth
lyric wadi
#

so honestly your best bet to find any answer is first check vanillaremade, then Ctrl+F in this chat

#

most of the time it worked for me

#

but then if something isnt there i just ask here, so it exist in this channel

#

not ideal but it's the best we have for now

wary moth
#

thats pretty much what I've been doing so far lol, sometimes the searching is hard to hit a balance between specific enough to address my problem instead of 100s of others, and un-specific enough to be something that people actually had help with before in the discord

#

Looking at this on the vanilla remade wiki and Yeahhhh I think I just need to start using VSCode instead of just Visual Studio, because it looks like all the setup is for that, and aside from some of the plugins that help me with C# programming, its basically just a fancy colored notepad without any context menus or anything lol

lyric wadi
#

well no

#

this is showing you how to set up the Lua environment IF you're using vscode or any vscode-based editor

#

but like you can very well use your preferred editor, ive seen some use notepad++ or heck even normal notepad

#

the lua environment setup is just to aid you with syntax autofil and basic debugging

wary moth
lyric wadi
#

i mean if you're gonna start now then get vscodium maybe

#

surely a lua plugin is avaiable

#

im still using vscode just because i dont want to setup everything anew

#

but like for all i know use atom that's a perfectly good ide

slim ferry
#

vscodium is just a vscode fork i think

#

But debloated

#

so most things should be similar

lyric wadi
#

yea, and that debloat helps a lot from what i know

#

like im doing fine but there are some noticable chugs as it's trying to present its copilot bullshit on me

wary moth
#

Awesome ty for the suggestion I'll check it out

wary moth
#

Just a question
Do I need to worry about assigning anything to my mods global table mixing with other mods? Or are each mods given their own enviornment?

mystic river
#

mods are not given their own environment, no
but accidental overlap is rare. just give your table a reasonably unique name and not like, MyMod

gilded blaze
#

just set your mod object to a global table named with your mod id

#

example with mine: Sagatro = SMODS.current_mod
it's just that simple

ancient mango
#

Weakness

Decreases rank of up to 2 selected cards by 1

#

can someone help me with the art

#

please

#

i dont know how to draw

mystic river
ancient mango
#

sorry

wary moth
#

unless there is some issue I have not forseen here with doing something like that

mystic river
#

that should work fine, yeah

wary moth
#

cool cool ty

slim ferry
#

i usually just use my mod prefix in uppercase

#

since its shorter

gilded blaze
#

tables and functions in lua are always references

#

if you know pointers in C, it's pretty much similar

#

local D = DISHEVELED basically makes D refer to whatever DISHEVELED is referring to

vocal helm
#

If I wanted to make a Riff-Raff clone for modded Jokers, is there a parameter I could use for add_card to specify what mod it should pull from?

frosty rampart
#

if it's just for your own mod, you should just add an attribute to all your modded jokers and then use SMODS.poll_object to get the key of a random joker with that attribute

dapper sun
#

what if it's not

frosty rampart
vocal helm
#

woah

frosty rampart
#

something like this:

SMODS.poll_object {
  ...
  filter = function(pool)
    local new_pool = {}
    for i, v in ipairs(pool) do
      if G.P_CENTERS[v.key].original_mod.id == whatever then
        new_pool[#new_pool + 1] = v
      end
    end
    return new_pool
  end,
  ...
}
elder rune
ancient mango
#

its streangth but opposite(thats why its just streangth with inverted color and changed text)

sleek valley
#

is there a way to make consumeables in a booster pack not need to be instantly used?

#

cause i have alot of custom stuff that cant really be intantly used like that

daring fern
sleek valley
#

ah, thx

mystic river
rapid stag
sleek valley
#

you mean the commas? that's just built into the game

fading rivet
#

what version are yu playing

sleek valley
#

is it not???
i know damn well i didnt do anything on purpose to make it happen

sleek valley
#

at the time of that screenie, i gave myself a shit ton of money to make sure i could afford the booster packs for repeated testing

#

i did nothing to actually make the commas, it's just like that

rapid stag
#

...wut

idle plaza
#

Yeah my game gets commas for numbers like that too, just by default.

rapid stag
#

uhhhhhhh

median veldt
median veldt
sleek valley
median veldt
#

Oh neat

sleek valley
#

Ty
Took inspo from the combo cards in ColdBeans

median veldt
#

im sure this has been done already but i dont care

#

i mean like come on

silk latch
#
SMODS.Consumable {
    key = 'powerplay',
    set = 'Spectral',
    atlas = 'RTD',
    pos = { x = 0, y = 0 },
    soul_pos = { x = 1, y = 0 },
    hidden = true,
    soul_set = 'Mannpower',
    use = function(self, card, area, copier)
        for i = 1, #G.jokers do
            G.E_MANAGER:add_event(Event({
                trigger = 'after',
                delay = 0.4,
                func = function()
                    play_sound('timpani')
                    local editionless_jokers = SMODS.Edition:get_edition_cards(G.jokers, true)
                    for i2 = 1, #editionless_jokers do
                        local edition = 'e_negative'
                        editionless_jokers[i]:set_edition(edition, true)
                    end
                    check_for_unlock({ type = 'have_edition' })
                    card:juice_up(0.3, 0.5)
                    return true
                end
            }))
            delay(0.6)
        end
        for i, playing_card in ipairs(G.playing_cards) do
            local editionless_cards = SMODS.Edition:get_edition_cards(G.playing_cards, true)
            for i2 = 1, #editionless_cards do
                local edition = 'e_polychrome'
                editionless_cards[i]:set_edition(edition, true)
            end
        end
    end,
    can_use = function(self, card)
        return next(SMODS.Edition:get_edition_cards(G.jokers, true))
    end,

}
daring fern
silk latch
#

Okay now it's not crashing, but it doesn't do anything when used

rapid stag
#

sanity check: ```lua
SMODS.change_base(card, pseudorandom_element(SMODS.Suit), pseudorandom_element(SMODS.Rank))

#

i forget whether the smods suits/ranks classes are singular or plural

frosty rampart
#

plural, but you'll want to do pseudorandom_element(SMODS.Suits).key (and the same with ranks)

#

change_base takes just the key, while SMODS.Suits and SMODS.Ranks contain the whole suit and rank objects

coral flume
#

This is looping endlessly, is there an easy way to fix that?

if card.ability.extra.active == true then
    print("istrue")
      if context.money_altered and context.amount > 0 then
        print("money1")
        card.ability.extra.money = context.amount
        card.ability.extra.active = false
        print("money2")
      end
    end 
    if card.ability.extra.active == false then 
      ease_dollars(card.ability.extra.money) 
    end
frosty rampart
#

elaborate on "looping endlessly" and show more info about where this code is written

coral flume
#

Oh okay!

#

So that code is within calculate on a joker

SMODS.Joker {
  key = 'hyperdrive',
  loc_txt = {
    name = 'Hyper Space',
    text = { "Double $","Double Blind" }
  },
  atlas = "Jokers",
  rarity = 1,
  cost = 4,
  unlocked = true,
  discovered = true,
  blueprint_compat = true,
  eternal_compat = false,
  perishable_compat = true,
  pos = { x = 0, y = 3 },
  config = { extra = { money = 0, active = true } },

  loc_vars = function(self, info_queue, center)
    return { vars = { center.ability.extra.money, center.ability.extra.active } }
  end,

  calculate = function(self, card, context)
    if card.ability.extra.active == true then
      if context.money_altered and context.amount > 0 then
        card.ability.extra.money = context.amount
        card.ability.extra.active = false
      end
    end 
    if card.ability.extra.active == false then 
      ease_dollars(card.ability.extra.money) 
    end
  end
}
#

And Im assuming its and endless loop because this was me attempting to fix it seeing itself add money which was causing a endless loop of adding money and crashing the game. and this is crashing the game the same way

#

no crash report game just closes

#

Just trying to double any money a player would gain lol

frosty rampart
#
calculate = function(self, card, context)
  if context.money_altered and card.ability.extra.active then
    card.ability.extra.active = false
    ease_dollars(context.amount)
    card.ability.extra.active = true
  end
end

try this instead?

silk latch
naive agate
#

im lost

coral flume
#

Thanks heeps!

frosty rampart
#

no problem!

frosty rampart
naive agate
#

I'm trying to have this joker apply negative and a sticker as well as squaring its values if possible
doesn't seem to work properly from what I've seen

#

the sticker is fine but applying the edition and squaring values is the issue

#

Im not the best at wording this kinda stuff so

#

yeah

normal crest
# naive agate im lost

you haven't really explained which part isn't working, but never store card objects in ability tables like you did with card.ability.choice = chosen_joker

naive agate
#

ic

coral flume
#

How would i go about getting a random card in hand?

daring fern
coral flume
#

Thanks!

coral flume
#

I've gotten to here

calculate = function(self, card, context)
    if context.individual and context.cardarea == G.play and context.other_card:get_id() == 12 then 
      print("SEX")
      card.ability.extra.death_card = pseudorandom_element(G.hand.cards)
      if card.ability.extra.death_card then
        G.E_MANAGER:add_event(Event({
            func = function()
              SMODS.add_card{ set = "Base", rank = "Jack"}
              SMODS.destroy_cards(card.ability.extra.death_card, nil, true)
              return true
            end
          }))
      end
    end
  end

But if playing like 3 of a kind queens, they all destory the same card. Is there a way to make them each randomise what they destroy?

faint yacht
#

...you shouldn't destroy cards like such mid-scoring. Consider tagging the randomly selected card in your existing check.

local rndcard = pseudorandom_element(G.hand.cards)
rndcard.slayqueen = true

and then checking against context.destroy_card.

if context.destroy_card and context.destroy_card.slayqueen then return { remove = true } end
rapid stag
#

i'm planning out a showman-esque joker that also gives 1xmult for every duplicate held. what's the most efficient way to check how many duplicate jokers exist in G.jokers.cards? cirThink

e.g. if you have say, 2 blueprints and 2 brainstorms, that would be x3 mult (because 2 duplicates after x1 base)

#

off the top of my head, i think

#
local existing_joker_keys = {}
local dupeCount = 0
for _, jkr in ipairs(G.jokers.cards) do
  if existing_joker_keys[jkr.config.center.key] then
    dupeCount = dupeCount + 1
  else
    existing_joker_keys[jkr.config.center.key] = true
  end
end
#

and i can't help but wonder if that feels stupid or if that's the correct way to do that

#

or at least, there's no better way to do that

idle plaza
#

I won't say for sure that it's the best method (you never know with coding), but that is how I'd do it.

normal crest
#

mixing camelCase and snake_case for variable names should be against the modding rules

rapid stag
#

i blame steamodded, i used to only write camelCase but ever since i started doing PRs, snake_case has wormed its way into my cursed-ass coding """""philosophy"""""

#

camelCase is natural to me but 😭

#

although i have written worse

near coral
#

Is there a way to make playing a hand cost 2 hands instead of just doing -1 twice in quick succession

rapid stag
#

note to self: look into "misprint but hands"

near coral
#

Wghar

rapid stag
near coral
#

Ok

fading rivet
#

theres a project i'm working on that uses both js and python
i originally kept the cases seperate

rapid stag
#

i guarantee you there is no code worse than mine girldmPepe

fading rivet
#

but at one point I gave up

#

I have a camel cased python function being passed a snake_case function being assigned to PascalCase variable

#

several times

#

@rapid stag chud

rapid stag
#

still better than other things i've written

fading rivet
rapid stag
#

still better than other things i've written

near coral
#

If an event plays mid-hand does that halt everything that's going on until the event is done

fading rivet
#

with a straight face

#

under pressure

#

bad code is funny and all

#

until suddenly its not just your bad code

rapid stag
#

what exactly am i walking through if i do

for _, card in ipairs(SMODS.merge_lists{
  G.jokers.highlighted or {},
  G.consumeables.highlighted or {}
}) do
  -- what is card
end
#

so if i'm holding a fool, would card end up being the fool directly or would it be a table with the fool in it

normal crest
#

try it and see!!!!

rapid stag
#

what is causing this in the main menu top left

#

the only thing i can link this to is that all of the text that ends up here are name fields of entries i'm adding to info_queue

normal crest
#

how are you adding them

rapid stag
#

via code i patch into generate_card_ui just before the recursion loop at the end, that passes info_queue among other things into a mod function

normal crest
#

are you creating ui elements directly

#

or using one of the balatro functions like create_something

rapid stag
#

no, i'm just adding { key = 'key', set = 'Other' } to the info queue

normal crest
#

tbh idk, maybe you're adding stuff to info_queue too early

#

or it's not the info_queue stuff in the first place

analog geode
#

how can i grab the level of the currently played hand? this is my current attempt:

        if context.post_joker or (context.main_scoring and context.cardarea == G.play) then
            card.ability.extra.mult = G.GAME.hands[handname].level
            print (card.ability.extra.mult)
        end
    end```
normal crest
#

replace handname with context.scoring_name

analog geode
#

thanks 👍

rapid stag
lusty marten
#

i made a mod that can choosing level and multiply into Blind Chips , but when I test , all the decks convert into Red Deck , how can i fix it?

gilded blaze
#

||tiếng Anh hơi trôn, giải thích bằng tiếng Việt cũng đc, ko có gì hết||

gilded blaze
#

send an mp4 next time, I don't wanna download it just to watch once

#

||cái này hơi nâng cao rồi, rốt cuộc bro muốn thêm ascension vào game mà ko phải là stake à||

fallen timber
#

hello, whats the event for when consumable is bought?

daring fern
lusty marten
gilded blaze
#

||mới học code mà đã bay vào code thứ cao siêu hetcuu||

teal grotto
#

how would you make a custom rank give something like mult instead of chips?

fallen timber
#

is there a place where i could search up whatever event i want to use and not just ask here bothering you?

daring fern
daring fern
fallen timber
fallen timber
#

yea, so is there a place where all those context checks are put together?

lusty marten
stray karma
#

hey is joker forge even good

gilded blaze
teal grotto
gilded blaze
#

||ở đây cũng không vấn đề gì, người khác cũng có thể giúp nếu cần||

coral flume
#

Anyone know why this is crashing?

SMODS.Blind {
    key = "greatfilter",
    loc_txt = {name = "The Great Filter", text = {"Debuffs Most Played Hand"}},
    dollars = 8,
    mult = 2,
    pos = { x = 0, y = 7 },
    boss = { showdown = true },
    boss_colour = HEX("e34244"),
    debuff = {hand = { [G.GAME.current_round.most_played_poker_hand] = true }},
}
gilded blaze
# lusty marten

||sao lại nhảy về menu trực tiếp thế, code này là dở rồi|| 😭

#

setting G.STATE directly is bad practice

lusty marten
gilded blaze
#

||gọi thẳng UI chọn độ khó gì gì đó luôn, mắc gì hook vào Game.update bắt nó kiểm tra từng frame||

gilded blaze
#

||bỏ hook kia đi, rồi sửa lại G.FUNCS.reopen_fide_selector thành:||

G.FUNCS.reopen_fide_selector = function(e)
    local profile = G.PROFILES[G.SETTINGS.profile]
    if profile and G.STATE == G.STATES.MENU then 
        profile.fide_setup_complete = false 
        G.FUNCS.overlay_menu{definition = create_fide_selector_ui(), config = { align = "cm", type = "full" }}
    end
end
bold eagle
#

I'm getting this error and I don't know what it means

gilded blaze
#

it means it's not recommended to use global mult to access the mult parameter

bold eagle
#

I dont think im doing that

bold eagle
#
calculate = function(self,card, context)
        local has_whimsy = false
        for _, playing_card in ipairs(G.playing_cards or {}) do
                    if SMODS.has_enhancement(playing_card, 'm_zwp_whimsical') then
                        has_whimsy = true
                    end
        end
        if has_whimsy == false then
            if context.joker_main and 
            SMODS.pseudorandom_probability(card, 'zwp_coin', 1, card.ability.extra.odds) then
                return {
                    x_mult = card.ability.extra.xmult1
                }
            else
                return{
                    x_mult = card.ability.extra.xmult2
                }
            end
        end
    end
#

thats the calculate

#

if i give myself the joker then enter a blind it crashes with that

gilded blaze
#

you did not gatekeep your logic with a context

#

it fires at any context, which is not good

bold eagle
#

ah

#

ok

#

so I should only call anything in there when joker.main is the context

#

thank you

daring fern
# bold eagle in this case

It should be: ```lua
if context.joker_main then
if SMODS.pseudorandom_probability(card, 'zwp_coin', 1, card.ability.extra.odds) then
return {
x_mult = card.ability.extra.xmult1
}
else
return{
x_mult = card.ability.extra.xmult2
}
end
end

analog geode
bold eagle
#

cool thanks

lusty marten
gilded blaze
#

||vấn đề là không biết lỗi red deck ở đâu kìa 😭||

lusty marten
gilded blaze
#

||cấu hình máy liên quan gì hetcuu||

lusty marten
gilded blaze
#

||4gb ram trong năm 26 lớn hetcuu||

#

||vấn đề ở đây là đống code không có vẻ gì sẽ đụng chạm đến phần bộ bài, nói chung là vẫn đang bí đây DEAD||

gilded blaze
#

we all speak English here
this guy is an exception, he isn't very good at it so I asked him to talk in Vietnamese
at least that takes less efforts out of my comprehension skill

sleek valley
lusty marten
#

I am sorry if i disturbed anyone

sleek valley
#

dont worry, you're good

pastel kernel
#

how do you juice up the table operator

hushed stump
#

hi people

#

i'm trying to make some individual assets for my jokers

#

however, they look blurry, especially the 1x version (which you can see by disabling pixel art smoothing). I exported with GIMP, with compression set to 0

#

why does that happen?
even discord renders them blurry. in GIMP they look sharp, since they're just pixels

#

these are the 2x versions, which i scaled down to get the previous ones

#
SMODS.Atlas{
    key = 'SuspiciousJoker',
    path = 'SuspiciousJoker.png',
    px = 71, 
    py = 95
}
SMODS.Atlas{
    key = 'FunnyJoker',
    path = 'FunnyJoker.png',
    px = 71, 
    py = 95
}

These are my atlases

median veldt
hushed stump
#

if gimp had antialiasing...

median veldt
#

maybe try a different program

median veldt
median veldt
hushed stump
median veldt
#

set it to none

hushed stump
median veldt
#

hm

hushed stump
gilded blaze
#

developing a mod without DebugPlus is a bold choice

hushed stump
frosty dock
#

these don't look like they have any anti-aliasing problems

hushed stump
frosty dock
#

oh hm you're right

hushed stump
frosty dock
#

oh yeah no ts is blurry

#

discord likes to show 1x sprites blurry regardless

hushed stump
#

they're straight up pixels on a low res image

#

also, does the 2x one look right to you?

frosty dock
#

the 2x looks right I think, though a bit hard to tell on mobile

polar flint
#

Numbers = big

#

Ok mod done

hushed stump
#

bluratro

hushed stump
#

@median veldt @frosty dock apparently it's an issue with malverk???

frosty dock
#

oh huh

hushed stump
#

it only happens if i start the game with malverk and pixel art smoothing enabled, and then i disable pixel art smoothing

gilded blaze
hushed stump
#

if i start the game with pixel art smoothing disabled but with malverk enabled, they show fine anyways

#

it also blurs vanilla jokers a bit, but it's not that noticeable

lusty marten
gilded blaze
#

type eval G.GAME.viewed_back:change_to(G.P_CENTERS.b_blue)

wintry solar
#

I have no idea, it shouldn’t touch actual draw code

hushed stump
gilded blaze
#

if not, that's the main problem - the method is corrupted by an unknown cause

#

is main.lua your entire codebase?

#

if it is, check the code of the other mod you installed

gilded blaze
wintry solar
hushed stump
#

@frosty dock i'm on latest DEV smods. can this be affecting how malverk works?

frosty dock
hushed stump
#

this would explain why vanilla jokers aren't blurred much and mine is, since my atlas has a lower resolution

wintry solar
#

Malverk shouldn’t touch any atlas stuff that isn’t run through its system either

hushed stump
#

@frosty dock i downgraded smods to 1501a, and that """fixed""" it

#

so i think it's an smods issue?

frosty dock
hushed stump
#

with malverk enabled, but downgrading smods fixed it

frosty dock
#

then it might be caused by a smods change but is still a malverk issue

hushed stump
#

the issue only happens when i have latest smods an malverk at the same time

hushed stump
#

should i, for the moment, make an sprite of the same res as vanilla jokers so at least they look in line with the game?

frosty dock
#

I don't see how that affects things

frosty dock
#

the difference is probably that vanilla sprites aren't loaded through SMODS.Atlas

frosty dock
#

Just speculating though, I'd have to look closer into this to say more

hushed stump
wintry solar
#

1501a still works with Malverk enabled?

hushed stump
wintry solar
#

That it did what you expect with the sprites

hushed stump
#

oh no, actually i'm wrong

#

i did a bit more of testing

#

1501a doesn't change anything

#

i also notice that it doesn't even apply pixel art smoothing ON sometimes

#

you can tell it's still 1x, specially cause the atlases inject insanely fast

hushed stump
#

it's definitely a malverk issue, but idk why

wary moth
#

is there a way to add lines to loc_txt.text during the game?

hushed stump
#

it might imply reloading tho

#

jokers that scale do this, so you might want to look at something like hologram

wary moth
hushed stump
#

This depends on how SMODS handles it

wary moth
#

that does not appear to work

teal grotto
#

how would you make a custom rank show different text

lyric wadi
#

chat quick sanity check for an idea about interactions between two jokers

#

imagine two idols like jokers

#

one pick a card completely randomly, like idol does

#

the other goes through a predetermined sequence of card

#

would it be possible to make it so that if you have both of these jokers together, the random one stops being random and also starts going down the same sequence

#

and would you be able to make this effects the vanilla jokers, like idol, castle, etc

slate turtle
#

question

#

uh

#

how does one make blinds

lyric wadi
#

have you checked vanillaremade

slate turtle
#

..no?

#

i'll try

lyric wadi
#

👍

slate turtle
#

i'll probably add blinds based off ts

#

also i'll use my current jokerforge mod as the template

lyric wadi
#

oh

slate turtle
#

but the blinds i will add myself

lyric wadi
#

you're using jokerforge

#

uhhh then yea i have no answer for that

slate turtle
#

since jokerforge has no support for blinds

lyric wadi
#

you're just gotta start actually coding for those

slate turtle
#

i will

#

👍

lyric wadi
#

unfortunately or fortunately, whichever one applies

slate turtle
#

nvm found it

lyric wadi
#

oh ok

#

like if you need the basics of making something of a particular object type i would honestly just yoink one from here and modify it

slate turtle
#

do i make a new lua file for blinds

#

or do i just start from scratch

lyric wadi
#

technically everything in a mod can be in one file

#

but also it's going to be a pain to find things if your mod gets particularly big

slate turtle
#

ig i'm not using jokerforge anymore

lyric wadi
#

i would recommend start separating code files out earlier than later but it's not required

slate turtle
#

the main "mod" folder has separate folders for enhancements, seals n whatnot

#

do i just make a blind folder orrr

lyric wadi
#

anything you're comfortable with

#

because ideally it will be the structure you want to work with for the rest of the development

#

some people including me personally goes as far as making one file per one card so everything is fully modular but again there's upsides and downsides

slate turtle
#

what do you reccomend i use for editing .lua files

lyric wadi
#

i personally use vscode so i'd say vscodium

#

but generally any IDE would do

slate turtle
#

k

lyric wadi
#

really it is just a fancy text file that has a bit that tells your pc to read it as code

slate turtle
#

its going to be a bit weird working without jf

lyric wadi
#

so even notepad works (but also dont who in their right mind would do this)

slate turtle
slate turtle
slate turtle
#

ok

#

i have

#

if SMODS.pseudorandom_probability(self, "wheeloffortune_sailboat_blind",self.config.numer, self.config.denum) and not context.other_card:is_face() then return { .... }

#

how can i make the part in the return{} debuff the card

sly heron
slate turtle
#

SMODS.Blind{ key = "the_sailboat", dollars = 5, mult = 2, boss_colour = HEX("a7e8d6"), atlas = 'Blinds', boss = {min = 3}, pos = { x = 0, y = 1 }, config = { numer = 1, denum = 5, }, in_pool = function(self) return true end, loc_vars = function (self) local n, d = SMODS.get_probability_vars(self, self.config.numer, self.config.denum, "wheeloffortune_sailboat_blind") return { vars = { n, d } } end, collection_loc_vars = function (self) local n, d = SMODS.get_probability_vars(self, self.config.numer, self.config.denum, "wheeloffortune_sailboat_blind") return { vars = { n, d } } end, calculate = function (self, blind, context) if context.hand_drawn and not blind.disabled and context.other_card then if SMODS.pseudorandom_probability(self, "wheeloffortune_sailboat_blind",self.config.numer, self.config.denum) and not context.other_card:is_face() then context.other_card:set_debuff(true) end end end }
would this code work

teal grotto
#

how would you make a rank show a custom message when scored

frosty dock
#

for now: manually

#

but it's a planned smods feature

slim ferry
#

rank calculate? 👀

frosty dock
#

among other things, yeah

#

unfortunately it lives among the forsaken features that are best added after quantum ranks

slim ferry
#

wouldnt it be easier to build quantum ranks around that

#

instead of editing it to support it in the future

frosty dock
#

it's too massive as a single feature

rigid solar
#

Is there a simple way to un-redeem a voucher?

mystic river
#

that seems like something spectrallib would add (unconfirmed)

frosty rampart
#

confirmed

frosty rampart
rigid solar
#

ok so natively there's no way to do it

frosty rampart
rigid solar
#

thanks

rigid solar
#

so obv it crashes

slim ferry
#

oh my god bruh

rigid solar
#

😬

frosty rampart
#

bruhhh 😭

#

hang on

rigid solar
#

i also checked cryptlib just in case, no sign of update_used_vouchers either

frosty rampart
#

it's literally just like 6 lines from cryptid

rigid solar
#

lol

#

thx

slim ferry
#

amazing

#

meta are you fixing that or should i do it

frosty rampart
#

i'll take care of it
tbh i think i'll just put the code in directly, it's the only place that function is called and it's small enough

viscid talon
#
-- Prion
SMODS.Joker({
    key = "prion",
    config = { extra = { odds = 2 } },
    loc_txt = {
        ["name"] = "Prion",
        ["text"] = {
            {
                "Discards have a {C:green}#1# in #2#{} chance to {C:attention}destroy{} the card",
            }
        },
    },
    pos = { x = 4, y = 8 },
    cost = 9,
    rarity = 3,
    blueprint_compat = false,
    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_prion')
        return { vars = { numerator, denominator } }
    end,

    calculate = function(self, card, context)
        if context.discard then
            if SMODS.pseudorandom_probability(card, 'j_hatch_prion', 1, card.ability.extra.odds) then
                SMODS.destroy_cards(context.discard, nil, nil, true)
                return {
                    message = "Destroyed!",
                    colour = G.C.RED,
                }
            end
        end
    end
})```
#

how would i make this work? firstly i think the wording is slightly flawed

rigid solar
#

yeah i did just replace the function call by the function's code

viscid talon
#

secondly, when i discard a card, it gives an error of "cards not defined"

slim ferry
slim ferry
viscid talon
#

o whoops

slim ferry
#

second you can just add remove = true to the return

viscid talon
#

oke

frosty rampart
slim ferry
#

oh

viscid talon
#

hi meta i missed u

slim ferry
#

well then i might as well do it myself

#

probably faster

viscid talon
#

ok it works

#

thankes

#

this is such a broken joker

frosty rampart
frosty rampart
slim ferry
#

wait what file is this in cryptid codebase is so ass 😭

viscid talon
#

im ok i think i need to fix prion's odds

#

1 in 2 chance to destroy a discarded card is absurdly good

#

maybe ill have that be for divine prion instead

slim ferry
#

why tf is the file called modifiers.lua

frosty rampart
slim ferry
#

thanks cryptid

frosty rampart
#

but yea the function itself is lib/modifiers.lua in cryptid lol

viscid talon
#

this is just after a few rounds lol

frosty rampart
#

yea that seems very strong

#

especially with oops

rigid solar
#

erm
unredeem doesnt seem to work

frosty rampart
#

elaborate

rigid solar
#

gimem a sec

#

yeah it just doesnt remove the voucher

#

imma post a vid

frosty rampart
#

show code

rigid solar
#
for k, v in pairs(G.vouchers.cards) do
      if v.config.center_key == "v_telescope" then
        print("here")
        v:unredeem()
        return
      end
    end```
frosty rampart
#

hrm

rigid solar
teal grotto
#

when you return two things with default messages how do you only silence one of them

rigid solar
#

eh it's fine i can deal without removing the voucher

rapid stag
#

so if you have multiple jokers that have the same unlock condition, are they unlocked in the same order they're loaded?

i.e., you do ```lua
SMODS.Joker{ key = 'one', ... }
SMODS.Joker{ key = 'two', ... }

viscid talon
#

if i had to take a guess, i think the first joker that appears in a list is unlocked first

#

but i could be wrong

#
-- Green Card
SMODS.Joker({
    key = "greencard",
    loc_txt = {
        ["name"] = "Green Card",
        ["text"] = {
            {
                "Create a {C:green}Sephirot{} card",
                "when {C:attention}Blind{} is skipped"
            }
        },
    },
    pos = { x = 5, y = 8 },
    cost = 9,
    rarity = 3,
    blueprint_compat = true,
    eternal_compat = true,
    perishable_compat = true,
    unlocked = true,
    discovered = false,
    atlas = "CustomJokers",

    calculate = function(self, card, context)
        if context.skip_blind and not context.blueprint then
            return {
                G.E_MANAGER:add_event(Event({
                    func = function()
                        SMODS.add_card {
                            set = 'Sephirot',
                        }
                        G.GAME.consumeable_buffer = 0
                        return true
                    end
                }))}
        end
    end
})```
got an undefined ipairs error
#

nvm its a bad argument

#

i still dunno how to solve it

hushed stump
#

@frosty dock is unlock_condition undocumented? I see it commented on vanilla remade as being an equivalent for check_for_unlock function

teal grotto
#

it's what vanilla uses

#

that's all i know

hushed stump
#

okay, but how is it used? which arguments should be passed into it?
in my case, i only want the joker to be able to be purchased only if five of a kind is visible.
i'm already using SMODS.is_poker_hand_visible('Five of a Kind') but I can't do it for the entire SMODS.Joker function since the game hasn't been initialized yet

slim ferry
#

use in_pool

#

You should just be able to return that in there

hushed stump
#

what is in_pool, and how should it be used?

slim ferry
#

in_pool = function(self, args) in the joker

#

It returns true if the joker should be able to spawn

hushed stump
#

ah alr

hushed stump
slim ferry
#

It is

hushed stump
#

where?

slim ferry
#

Its just not listed specifically for jokers

#

Its listed with pos, atlas, unlocked with a link to the common parameters section in some other page

slate turtle
#

question

viscid talon
#

whats up

hushed stump
#

i expected it to be a parameter cause i'm stupid

slim ferry
#

oh wait right

teal grotto
#

quick question
how do all of you not be stupid
it took me HOURS to get something this simple to actually work

teal grotto
#

uh

#

it's not a joker

slate turtle
#

how can i make a blind destroy cards}

hushed stump
#

what is it anyway?

slate turtle
#

i assume you do it w/ context.destroy_card

teal grotto
hushed stump
teal grotto
#

yes i have seen tutorials?

#

it just takes me so long to actually figure out

#

how to do stuff

slate turtle
viscid talon
#

whats the intended effect here?

slim ferry
#

You can indeed do this

viscid talon
#

i have a boss blind that does smth similar

#
-- The Axe
SMODS.Blind {
    key = "hatch_axe",
    dollars = 5,
    mult = 2,
    pos = { x = 0, y = 0 },
    boss = { min = 2 },
    boss_colour = HEX("b6315e"),
    atlas = 'CustomBlinds',

    loc_txt = {
        ['name'] = 'The Axe',
        ['text'] = {
            [1] = 'Destroy first played card',
            [2] = 'after every played hand',
        },
    },

    calculate = function(self, blind, context)
    if not blind.disabled then
        if context.destroy_card and context.destroy_card.should_destroy  then
            return { remove = true }
        end
        if context.individual and context.cardarea == G.play  then
            context.other_card.should_destroy = false
            if context.other_card == context.scoring_hand[1] then
                context.other_card.should_destroy = true
                return {
                    message = "Destroyed!"
                }
            end
        end
    end
end
}```
#

this may help

slim ferry
#

Blinds have access to most contexts

#

This is lowkey kinda janky of a solution

#

Because you can just check if its the first in the destroy_card check

#

Rather than setting a flag

viscid talon
#

ig but it works

#

a nyways i still need help figuring out the error with green card

rigid solar
#

How would I got about adding a tooltip about a deck? I tried info_queue[#info_queue+1] = {type = "descriptions", set = "Back", key = "b_tboj_judas", vars = {"+1","-1"}} but it doesn't show the description, just the name

slim ferry
#

try G.P_CENTERS.b_tboj_judas instead maybe

#

Instead of that whole table

rigid solar
#

yeah but what about the variables

slim ferry
#

Doing it via the center will actually call the center's loc_vars for this

#

Thats like the whole point of using the center

rigid solar
#

oh ok

#

lol ok thanks

slate turtle
#

question

#

is there a context for a hand played

frosty rampart
#

that's a very broad description
you can use context.before, which is when space joker triggers
if you want to do any scoring, you should use context.initial_scoring_step, which is immediately after space joker triggers
or you can use context.press_play, which is the instant you click the play button

slate turtle
#

what i was referring to

#

is a context that has the cards played

frosty rampart
slate turtle
#

thx

silk latch
frosty rampart
#

your for loops should use G.jokers.cards and G.hand.cards, not just G.jokers and G.hand

#

both of the for loops are just entirely getting skipped over

viscid talon
#

need a fresh pair of eyes

#

in response to this code

#

im unsure what i did wrong here

#

all the others seem to be fine

#

nvm lmao

rapid stag
viscid talon
#

its fine i found out i didnt add the config to divine space joker

#

i fixed it either way

hushed stump
#

guys

#

any idea why non unlocked modded jokers can crash when you put the cursor above them?

#

[SMODS _ "src/utils.lua"]:2639: attempt to index field 'control' (a nil value)

#

hello

viscid talon
hushed stump
viscid talon
#

is control the name of a variable of yours

hushed stump
viscid talon
#

idk then

#

show me ur code

hushed stump
#

it happened with HilariousJoker

viscid talon
#

hmm, odd

#

someone else will be better for this

daring fern
hushed stump
daring fern
hushed stump
#

isn't there a way to lock a joker with debugplus?

#

i ended up doing it with a save editor. now i set the unlock text to ??? on purpose

slate turtle
#

in case you need lines 20-47

SMODS.Blind {
    key = "the_laceration",
    dollars = 6,
    mult = 1.8,
    pos = { x = 0, y = 0 },
    boss = { min = 5 },
    boss_colour = HEX("751a47"),
    atlas = 'Blinds',

    loc_txt = {
        ['name'] = 'The Laceration',
        ['text'] = {
            [1] = 'Destroy first played hand',
        },
    },

    calculate = function(self, blind, context)
        if G.GAME.hands_played == 0 then
            for _, card in ipairs(cards) do
                card:start_dissolve()
                return {
                    message = "Destroyed!"
                }
            end
        end
    end
end
}```
idle plaza
slate turtle
#
...
                return {
                    message = "Destroyed!"
                }
            end
        end
    end
}```
#

?

slate turtle
daring fern
slate turtle
#

going to test it. you will be credited when V2 comes out!

#

istg if this is another syntax error

hushed stump
idle plaza
hushed stump
#

don't you have the lua extension for visual studio?

#

it will tell you if you have syntax errors

slate turtle
#

WHERE DO I GET IT

#

/NF

frosty rampart
#

check the vanillaremade wiki :3

hushed stump
#

get the one from sumneko

slate turtle
#

i just did

slate turtle
# idle plaza It is. What's your code now?
-- The Laceration
SMODS.Blind {
    key = "the_laceration",
    dollars = 6,
    mult = 1.8,
    pos = { x = 0, y = 0 },
    boss = { min = 5 },
    boss_colour = HEX("751a47"),
    atlas = 'Blinds',

    loc_txt = {
        ['name'] = 'The Laceration',
        ['text'] = {
            [1] = 'Destroy first played hand',
        },
    },

    calculate = function(self, blind, context)
        if context.destroy_card and context.cardarea == G.play and G.GAME.current_round.hands_played == 1 then
            return {
        remove = true,
        message = 'Destroyed!'
    }
end
}
hushed stump
#
loc_txt = {
        ['name'] = 'The Laceration',
        ['text'] = {
            [1] = 'Destroy first played hand',
        },
    }
end,
idle plaza
daring fern
hushed stump
#

mb

#

where the hell does the game store the amount of hands you've played

idle plaza
#

G.GAME.current_round.hands_played

hushed stump
#

balatro save editors doesn't seem to find that neither on meta.jkr, profile.jkr nor settings.jkr

hushed stump
idle plaza
#

Oh ok

hushed stump
#

G.PROFILES[G.SETTINGS.profile].hand_usage.FiveofaKind.count codewise

#

i want to set my five of a kind hands to 0 so then i can test if my joker unlocks properly

slate turtle
#

omfg 💔

#
--The Sailboat
SMODS.Blind{
    key = "the_sailboat",
    dollars = 5,
    mult = 2,
    boss_colour = HEX("a7e8d6"),
    atlas = 'Blinds', 
    boss = {min = 3},
    pos = { x = 0, y = 1 },
    config = {
        numer = 1,
        denum = 5,
    },
    in_pool = function(self)
        return true
    end,
    loc_vars = function (self)
        local n, d = SMODS.get_probability_vars(self, self.config.numer, self.config.denum, "wheeloffortune_sailboat_blind")
        return {
            vars = {
                n, d
            }
        }
    end,
    collection_loc_vars = function (self)
        local n, d = SMODS.get_probability_vars(self, self.config.numer, self.config.denum, "wheeloffortune_sailboat_blind")
        return {
            vars = {
                n, d
            }
        }
    end,
    calculate = function (self, blind, context)
        if context.hand_drawn and not blind.disabled then
            for i, card in ipairs(context.hand_drawn) do
                if not card:is_face(true) and SMODS.pseudorandom_probability(self, "wheeloffortune_sailboat_blind",self.config.numer, self.config.denum) then
                    context.other_card:set_debuff(true)
                end
            end
        end
    end
end
}```
hushed stump
idle plaza
hushed stump
#

and it looks beautiful btw

hushed stump
#

can you show me your visual studio screen

#

?

slate turtle
#

im certainly making progress

#

i fixed it i think

rapid stag
#

so if i just do SMODS.poll_edition{options = { 'e_polychrome' }} will that do just a roll for poly at the default chance of getting poly when normally rolling editions?

slate turtle
#

the boss blind had no description

idle plaza
rapid stag
#

pretty sure guarantee rules out base

idle plaza
#

That's what I meant. As long as you don't include guaranteed = true it'll work how you want.

slate turtle
#

i think i'm starting to get the hang of this

rapid stag
#

in a custom back's calculate, is back:juice_up() possible? does that work to juice a back cirDerp

gilded blaze
#

why would you want to juice a back?

daring fern
rapid stag
#

oh yeah cirDerp

gilded blaze
#

but yea, the effect you may want is to juice the first card in deck or the deck area itself

#

the Back object is simply sprite on the back plus some calculations

rapid stag
#

alright, i got a new puzzle i need you to help me figure out

you know how you can go up/down ranks with SMODS.modify_rank() and it wraps to a 2 when you +1 amount to an ace, and to an ace when you -1 with a 2?

what's an easy way to do this, but for suits?

rapid stag
#

i just noticed, going through one of my files cirDerp
i also have instances where camelCase_and_snake_case are mixed in individual variable names

daring fern
# rapid stag alright, i got a new puzzle i need you to help me figure out you know how you c...
local function modify_suit(card, amount, manual_sprites)
    local other_suit
    for k, v in pairs(SMODS.Suit.obj_buffer) do
        if v == card.base.suit then
            if amount > 0 then
                for i=1, amount do
                    if k+1 > #SMODS.Suit.obj_buffer then
                        k = 1
                        other_suit = SMODS.Suit.obj_buffer[1]
                    else
                        k = k+1
                        other_suit = SMODS.Suit.obj_buffer[k+1]
                    end
                end
            else
                for i=1, -amount do
                    if k <= 1 then
                        k = #SMODS.Suit.obj_buffer
                        other_suit = SMODS.Suit.obj_buffer[#SMODS.Suit.obj_buffer]
                    else
                        k = k-1
                        other_suit = SMODS.Suit.obj_buffer[k-1]
                    end
                end
            end
        end
    end
    return SMODS.change_base(card, other_suit, nil, manual_sprites)
end
lyric wadi
#

if i want to make it so that a particular range of card do not get sorted by the hand sorting function, do i have to hook the sorting function or can it be done in simpler ways

naive coral
#

why does this error occur when i try to start a second game in multiplayer balatro? i would really like it to not crash on the second game, multiplayer compat would be ideal\

naive coral
#

normally i ask questions for a mod here, thought was valid to put it here

frosty dock
#

1.0.7-beta is from almost a year ago

naive coral
#

makes sense, my mod has to be on a higher verison where weights are easily modifyable (1531b)+ i think

#

even updated multiplayer still has similar errors tho. ah well its an annoyance, its only on the second round so you get 1 round then it crashes which is wierd

rigid solar
#

does anyone know why the message's displayed in blue

mystic river
#

is G.C.ORANGE actually a color that exists?

shell timber
#

its G.C.FILTER right(?)

rigid solar
#

it's a color yes

#

i still changed to filter just in case and it doesnt work any better

rapid stag
rigid solar
lyric wadi
#

why is it not coloured

#

??

rapid stag
lyric wadi
#

thats weird

#

why does that matter in colour syntax but not anywhere else

gilded blaze
thorn ingot
#

Hi everyone. Do you know if this is enough to ban a joker for a deck?

   G.GAME.banned_keys['j_mail'] = true
end```
rigid solar
#

it should

thorn ingot
#

omg, thanks for answering.

wintry solar
rigid solar
#

sure

#

it just felt weird to me because as far as i knew _mod keys were to replace the message with whatever you want your message to be, didn't think it'd ignore the colour

#

ig it took blue instead of red because mult happens before chips and chips override the mult's red?

#

the weird thing was when i added remove_default_message and it still didn't work with _mod lol

#

but eh whatev, i found the thing that works that's all i care about lul

wintry solar
#

Wait no nvm I am getting myself confused you are correct

#

I have no idea why it’s blue lol

rigid solar
#

time to fix it balatrojoker

wintry solar
#

Oh I know what it is

#

The function that actually displays messages adds colours and sounds based on certain keys being present

rigid solar
#

and completely ignores the "colour" key? 😭

wintry solar
#

Basically, don’t use the mod keys they are stupid

rigid solar
#

wait it's specifically with chip_mod? bruh

#

friendship ended with _mod keys (it never started)

fallen timber
#

anyone can explain why everything is nil apparently?

function newWeapon(key, badge, cost, config, loc_vars, update_values, use, pos, can_use, replicatable, has_soul)
    pos = pos or {x = 0, y = 0}
    badg = nil
    if badge ~= nil then
        badg = function(self, card, badges) badges[1] = create_badge(localize(badge), HEX("e62314"), nil, 1.2) end
    end
    can_use = can_use or function(self, card, area) return true end 
    use = use or function(self, card, area) apply_weapon(card.ability.extra) end
    if replicatable == nil then replicataable = true end
    if has_soul == nil then has_soul = false end

    SMODS.Consumable({
        object_type = "Consumable",
        atlas = "weapons",
        key = key,
        set = "Weapon",
        config = config,
        loc_vars = loc_vars,
        pos = pos,
        soul_pos = has_soul and {x = pos.x, y = pos.y + 1} or nil,
        cost = cost,
        unlocked = true,
        discovered = false,
        use = use,
        can_use = can_use,
        update_values = update_values,
        set_card_type_badge = badg
    })
    if replicatable then -- todo: add in BookOfLifeDrop pool
    end
end

newWeapon(
    "soulcard_purify",
    nil,
    10,
    {extra = {chips = 250, event = "on_joker", interations = 5}},
    function(self, info_queue, card)
        return {
            card.ability.extra.interations,
            card.ability.extra.chips
        }
    end,
    function(self, card, area)
        card.ability.extra.chips = card.ability.extra.chips * G.GAME.blind.ante
    end,
    nil,
    { x = 2, y = 2 },
    nil,
    true,
    true
)
wintry solar
#

Why are you making cards like this

normal crest
#

your loc vars return should be return { vars = { ... } }

#

rn you don't have the vars part

fallen timber
fallen timber
fading rivet
fallen timber
fading rivet
#

idk how i just know you can ;-;

fallen timber
#

noted

fading rivet
#

oh wait this is a custom consumable type

#

better solution then, use inject_card

queen crescent
wintry solar
#

Extend Consumable to give it all the defaults you need in your new type, I can find some code a little later for you

queen crescent
queen crescent
#

-# i already have the atlas on my end

wintry solar
#

Sorry that wasn’t to you

queen crescent
#

awww

slim ferry
# fallen timber like how
newWeapon = SMODS.Consumable:extend{
    atlas = "modprefix_weapons", --atlas default in extending must have prefix
    set = "Weapon",
}
#

this allows you to call newWeapon like you would SMODS.Consumable but with the set new default parameters

#

you can also add a cost and other stuff you want to be consistent across all the consumables

slate turtle
fading rivet
slate turtle
#

i just hovered over my joker i believe or smth

#

omfg i cant even send the code because of nitro

fading rivet
#

???

#

I dont need to entire file just the joker definition

#

honestly just the config and loc_vars

slate turtle
#
    loc_vars = function(self, info_queue, card)
        
        local new_numerator, new_denominator = SMODS.get_probability_vars(card, CellarGrowthSize, card.ability.extra.odds, 'j_wheeloffortune_cellargrowth') 
        return {vars = {card.ability.extra.CellarGrowthSize, new_numerator, new_denominator}}
    end,
    
    calculate = function(self, card, context)
        if context.after and context.cardarea == G.jokers  then
            if true then
                if SMODS.pseudorandom_probability(card, 'group_0_624dccf3', 1, card.ability.extra.odds, 'j_wheeloffortune_cellargrowth', false) then
                    SMODS.calculate_effect({func = function()
                        local target_joker = card
                        
                        if target_joker then
                            target_joker.getting_sliced = true
                            G.E_MANAGER:add_event(Event({
                                func = function()
                                    target_joker:start_dissolve({G.C.RED}, nil, 1.6)
                                    return true
                                end
                            }))
                            card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = "Destroyed!", colour = G.C.RED})
                        end
                        return true
                    end}, card)
                end
            end
        end
        if context.cardarea == G.jokers and context.joker_main  then
            return {
                x_chips = card.ability.extra.CellarGrowthSize
            }
        end
        if context.skip_blind  then
            return {
                func = function()
                    card.ability.extra.CellarGrowthSize = (card.ability.extra.CellarGrowthSize) + 1
                    return true
                end
            }
        end
    end
}```
#

sorry if the code sucks

#

i was originally making this shitty mod with joker forge

fading rivet
#

is CellarGrowthSize a global or a card attribute

#

if its an attribute you forgot card.ability.extra. in the SMODS.get_proability_vars

slate turtle
#

okay. it crashed again when i tried to view it in the collection mid-run

#

in case you need line 41

stiff locust
#

is there a way to have multiple soul_pos layers on one joker

slate turtle
#
  local new_numerator, new_denominator = SMODS.get_probability_vars(card, CellarGrowthSize, card.ability.extra.odds, card.ability.extra, 'j_wheeloffortune_cellargrowth') 
        return {vars = {card.ability.extra.CellarGrowthSize, new_numerator, new_denominator}}```
daring fern
stiff locust
fading rivet
#

look into the floating sprite drawstep

slim ferry
#

steal from spectrallib floating_sprite2 drawstep

primal robin
rigid solar
slate turtle
median veldt
#

how possible is it to like. give a certain rarity of cards a shader
i know nothing about shaders so i might not go this route but

wintry solar
#

very possible

median veldt
#

how Easy

wintry solar
#

you just need a custom drawstep that checks for the rarity of the card and then draws the shader

#

you could copy the edition drawstep and change a few things around very simply

median veldt
#

i see

#

i might not do that purely because i have zero idea how to create a shader

median veldt
#

ok genuinely what am i doing wrong here

#

my only guess is k_EX but that seems odd considering the pool is bex_EX

median veldt
#

kk give me a few minutes i left home

median veldt
#

worked

slate turtle
#

wait

#

does the code not work if there's a space before it

#
 pretend theres a space here
--like this```
true jasper
#

Just send the code

slate turtle
#

fuck

#

its too big

true jasper
slate turtle
#

nvm that excludes some parts

#

this is the complete code of the tarot card i used that caused the game to crash

silk latch
#

Currently, this applies Polychrome to the cards in your hand and then crashes the game.

rapid stag
# daring fern ```lua local function modify_suit(card, amount, manual_sprites) local other_...

actually, follow up to this -

with modify_rank, if i want something to move one rank at a time towards a specific rank, i can lay out the ids 2 to 14 - and check both the id's value and half-2 if the amount should go down rather than up

but how do i quantify that with suits, while potentially accounting for modded suits? how do i find the shortest direction from suit A to suit B?

silk latch
rapid stag
#

which line is 19

silk latch
#
                        editionless_jokers[i]:set_edition(edition, true)
rapid stag
#

well i is your first loop's iterating value and i2 is your second loop's. is that intentional for your effect or

silk latch
#

Yeah, because I'm specifically looking for Jokers without an Edition

gilded blaze
#

you're using i instead of i2 for the second loop

silk latch
#

Ah,

rapid stag
# silk latch new crash just dropped

if i'm reading this correctly,
(5) Lua field 'func' at file 'src/mannpower/PowerPlay.lua:33' (from mod with id mannpower)
which if i'm reading your code right, should be local editionless_cards = SMODS.Edition:get_edition_cards(G.hand, true)
...which doesn't make sense to me as i don't get why card_area would be nil in that case

gilded blaze
#

wait

#

huh

#

why are you using 2 loops in the first place

silk latch
#

To find the (jokers/cards in hand) first and then go through specifically those without an Edition

rapid stag
#

that's not what that's doing, though
you're just looking for all editionless jokers and cards in hand as many times as there are total jokers and total cards in hand respectively

#

the loop reads as "first joker. let's look for all editionless jokers and give them the edition. done. second joker. let's look for all editionless jokers and give them the edition. done. third joker..."

#

i don't know the exact effect you want for this consumable, but based on the code you've shown, don't you want something more like

use = function(self, card, area, copier)
        for i = 1, #G.jokers.cards do
            if not G.jokers.cards[i].edition then
              G.E_MANAGER:add_event(Event({
                  trigger = 'after',
                  delay = 0.4,
                  func = function()
                    play_sound('timpani')
                    G.jokers.cards[i]:set_edition('e_negative', true)
                    check_for_unlock({ type = 'have_edition' })
                    card:juice_up(0.3, 0.5)
                    return true
                 end
            }))
            delay(0.6)
            end
        end
        for i, playing_card in ipairs(G.hand.cards) do
            if not playing_card.edition then
              G.E_MANAGER:add_event(Event({
                  trigger = 'after',
                  delay = 0.4,
                  func = function()
                    playing_card:set_edition('e_polychrome', true)
                    check_for_unlock({ type = 'have_edition' })
                    card:juice_up(0.3, 0.5)
                    return true
                  end,
              }))
            end
        end
    end
fringe oxide
#

is there a way to make some spectrals illegal to spawn normally (like the soul)

rapid stag
#

you could add them to G.GAME.banned_keys

#

so for the soul, you'd do G.GAME.banned_keys.c_soul = true

fringe oxide
rapid stag
#

no

#

you would have to have this happen at the start of a run

#

although it didn't occur to me that you might want it as a general blanket ban all the time

fringe oxide
#

trying to have it appear in certain booster packs and never appear anywhere else, like the soul

rapid stag
#

hmmmmmm

near coral
#

Is it possible to detect if a played card will score and make something happen before scoring starts if it will

median veldt
#

paired with context.individual maybe?

#

i have my own question. how do i check if a given joker key exists at all

daring fern
umbral zodiac
#

solve the halting problem for my joker

urban wasp
#

this effect is part of a deck where the effect is simply +4 mult after all scoring. why is it that it just doesn't give any if another +mult effect triggers before the deck's?

...
    trigger_effect = function(self, args)
        if args.context == "final_scoring_step" then
            args.mult = args.mult + self.config.mult
            update_hand_text({delay = 0}, {mult = args.mult})
            G.E_MANAGER:add_event(Event({
                func = (function()
                    play_sound("multhit1", 1, 1)
                    play_sound("tarot1", 1.5)
                    attention_text({
                        scale = 1.4, text = "+"..self.config.mult.." Mult", hold = 2, align = "cm", offset = { x = 0,y = -2.7 }, major = G.play
                    })
                    return true
                end)
            }))
        end
    end
...
#

most code is copied straight from plasma if it wasn't obvious

daring fern
urban wasp
#

speed face

#

you cannot be serious 😭

#

thanks mr. somethingcom

#

actually i take that back nvm

#

not the thank you a deleted message 💔

urban wasp
#

i saw it used on some other deck and thought "it must be common!"

#

guess i was wrong

#

anyway good night

near coral
#

To add an enhancement to the game do you just put the design on an empty card?

near coral
#

Oh ok

#

I guess this means the ranks and suits are layered on top of the cards rather than being the cards themselves

slim ferry
#

that is correct

near coral
#

Me rn

open moth
#

I have a deck idea but no idea of how it could be implemented:

  • consumables may appear with editions
  • editions don't increase buy value
hearty lagoon
#

Im trying to make a joker that when you sell it, the joker to its right scores a +30 chip bonus every hand kinda like the foil edition, I think there is something wrong with the hook because i cannot get it to score the bonus but i can see that the chip bonus variable gets stored in the target joker

gilded blaze
#

calculate_joker is a method of the Card class, SMODS has nothing to do with it

#

also the hook is far from being correct in the first place

hearty lagoon
#

how should i do it or what resources should i take a look at, first time doing hooks

median veldt
#

is it possible to return loc colours inside of loc vars (e.g. "{C:mult}" if something is false and "{C:green}" if true )

#

if so how cuz its not working

daring fern
gilded blaze
# hearty lagoon how should i do it or what resources should i take a look at, first time doing h...
SMODS.Joker{
    ...,
    calculate = function(self, card, context)
        if context.selling_self then
            -- get target joker
            local other_joker = nil
            for i = 1, #G.jokers.cards do
                if G.jokers.cards[i] == card then
                    other_joker = G.jokers.cards[i + 1]
                    break
                end
            end
            -- nil check in case this joker is sold while at rightmost
            if other_joker then
                -- use a unique key here, extra is not recommended as for some vanilla jokers this is a number, not a table
                other_joker.ability.soy_chips = (other_joker.ability.soy_chips or 0) + card.ability.extra.chips_add
            end
        end
    end,
}

local calculate_joker_ref = Card.calculate_joker
function Card:calculate_joker(context)
    local o, t = calculate_joker_ref(self, context)
    if context.joker_main and self.ability.soy_chips then
        o = SMODS.merge_effects{o or {}, {chips = self.ability.soy_chips}}
    end
    return o, t
end
#

when doing hooks, be careful about the return values as you may discard all values starting from the second one onwards
e.g. Card.calculate_joker returns 2 values

hearty lagoon
#

omg, thank you so much

gilded blaze
#

this is just the backend tho

#

it's recommended that you add a tooltip to the joker that gained chips

hearty lagoon
#

yeah, ill try to figure that out

frosty rampart
#

i'm mainly just confused because like
there's no defined "order" for suits

primal robin
rigid solar
#

when you sort your hand by suit it's always the same order

frosty dock
#

suit order in vanilla code actually is inconsistent

rigid solar
#

😭

frosty dock
#

it's reverse order in RNG or whatever

rapid stag
#

when using debugplus with vanilla suits, when you go "right" one rank through the full lot, it's always hearts -> diamonds -> spades -> clubs

#

or is it "left"

#

either way, the principle's still the same

primal robin
#

In hand diamonds always last

median veldt
#

is there like. something i can crossreference to make a drawstep that draws a shader over every joker of a specific rarity

frosty dock
#

"cycling" suits inherently doesn't make much sense

frosty rampart
#

agreed

rapid stag
#

well the deck also displays an order for suits. from top to bottom, it always seems to be hearts, clubs, diamonds, spades

primal robin
frosty rampart
#

especially when you add modded suits to the mix (what if the modded suit isn't in the pool? what if it's supposed to be a rare suit, like optics in oblivion? what about that one mod that adds mixed suits?)

primal robin
#

Suit have nominal which used for sorting

rapid stag
#

hmmm

frosty rampart
#

and even if there was a consistent ordering internally, i'd still be against "cycling" suits in-game
that's just not how it works in vanilla, whenever you change a card's suit you're just directly assigning it

#

it's not intuitive to players or to coders imo

primal robin
#

assuming mod have seals on jokers, well, does it matter that much?

frosty rampart
#

huh

frosty dock
#

it's still not something I'd want to encourage

primal robin
#

hm, maybe

#

btw did you seen my recent development towards ui thing?

#

I managed to make it work with Object:extend() and it extends properly

#

Not in cleanest way but whatever

frosty dock
#

haven't looked at it but that sounds cool

primal robin
#

It behaves like SMODS.GameObject, I copy-pasted extend function from it

#

xd

stiff locust
#

what's the standard text styling for exponent mult

slim ferry
#

Spectrallib emult gradient :chud :

daring fern
median veldt
#

oh wow thank you

does this just. work

daring fern
rapid stag
#

when i call SMODS.destroy_cards, how can i make it play the slice sound instead?

do i have to use skip_anim?
i just did what vremade's ceremonial dagger does

median veldt
#

destroying cards only makes the "woosh" sound iirc, so you could get away with just playing the slice sound on top of that

#

is there a way to like. override what poker hand the game thinks you're playing

#

i'm imagining i'd need to hook a function

#

but yk

fading rivet
#

theres a context for it ik

faint yacht
#

context.evaluate_poker_hand

median veldt
timid zinc
#

is there a way to get the config values of another mod while being a lower priority (so it loads after)

median veldt
#

depends on when you're getting the values

#

should be fine usually, SMODS.Mods["mod_key"].config