#💻・modding-dev

1 messages · Page 78 of 1

glossy stone
#

hmmm

#

actually maybe it's a different thing

#

Okay, I know the discard checking works - it only crashes when i dicard a 3oak or better

#

but WHAT IS GOING ON WITH LINE 411

#

it's probably something wrong with localize(text, 'poker_hands')...

primal robin
#

Bad hand checking logic btw.

Maybe this will be better

function get_poker_hands_better_than(target_hand, inclusive)
  local result = {}
  for _, poker_hand in ipairs(G.handlist) do
    if (inclusive or poker_hand ~= target_hand) then table.insert(result, poker_hand) end
    if poker_hand == target_hand then return result end
  end
end
glossy stone
#

wh

#

what

#

how do i

primal robin
#

Straight, Flush and Three of a Kind are not all hands better than Three of a Kind

#

Also you miss Full House

glossy stone
#

oh

#

yeah i know that

cursive ocean
#

This should be the right channel fool does anyone have insight into how to add a joker created with SMODS.Joker to a deck when the run starts? I'm able to load vanilla ones using e.g. 'j_blueprint' and passing that to create_card, but not with SMODS jokers.

glossy stone
#

i mean i just spawn it in with debugplus

languid mirage
#

you need to add mod prefix

#

so j_modprefix_jokerkey

#

mod prefix is like first 4 letters of your mod name? lowercase

#

unless you specified mod prefix separately

glossy stone
primal robin
#

"Two Pair"

glossy stone
#

yeah

#

and the level up code, where to put it

cursive ocean
glossy stone
primal robin
# glossy stone and the level up code, where to put it

Le'ts modify code a little bit:

function get_poker_hands_better_than(target_hand, inclusive)
    local result = {}
    for _, poker_hand in ipairs(G.handlist) do
        if (inclusive or poker_hand ~= target_hand) then result[poker_hand] = true end
        if poker_hand == target_hand then return result end
    end
    return result
end

calculate = function(self, card, context)
    if context.pre_discard and not context.hook then
        local poker_hands_to_upgrade = get_poker_hands_better_than("Three of a Kind", true)
        local poker_hand = G.FUNCS.get_poker_hand_info(G.hand.highlighted)
        if poker_hands_to_upgrade[poker_hand] then
            card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')})
            update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(poker_hand, 'poker_hands'),chips = G.GAME.hands[poker_hand].chips, mult = G.GAME.hands[poker_hand].mult, level=G.GAME.hands[poker_hand].level})
            level_up_hand(context.blueprint_card or self, poker_hand, nil, 1)
            update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''})
        end
    end
end
glossy stone
#

oh i see

cursive ocean
glossy stone
primal robin
#

Your result code shoul looks like this:

function get_poker_hands_better_than(target_hand, inclusive)
    local result = {}
    for _, poker_hand in ipairs(G.handlist) do
        if (inclusive or poker_hand ~= target_hand) then result[poker_hand] = true end
        if poker_hand == target_hand then return result end
    end
    return result
end

local trashtrash = SMODS.Joker({
    key = "trashtrash",
    loc_txt = {
        name = "Trash And Trash!",
        text = {
            "If discarded poker hand is",
            "{C:attention}Three of a Kind or better,",
            "{C:attenti}level up{} said poker hand",
        },
    },
    rarity = 3,
    cost = 8,
    atlas = "OSJokers",
    eternal_compat = true,
    perishable_compat = true,
    blueprint_compat = true,
    pos = { x = 3, y = 2 },
    calculate = function(self, card, context)
        if context.pre_discard and not context.hook then
            local poker_hands_to_upgrade = get_poker_hands_better_than("Three of a Kind", true)
            local poker_hand = G.FUNCS.get_poker_hand_info(G.hand.highlighted)
            if poker_hands_to_upgrade[poker_hand] then
                card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')})
                update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(poker_hand, 'poker_hands'),chips = G.GAME.hands[poker_hand].chips, mult = G.GAME.hands[poker_hand].mult, level=G.GAME.hands[poker_hand].level})
                level_up_hand(context.blueprint_card or self, poker_hand, nil, 1)
                update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''})
            end
        end
    end    
})
glossy stone
#

double oh

#

It works! but
local upgrade text goes off to the stratosphere???

teal estuary
#

didnt like your joker, tried to escape /s

primal robin
#

Good luck Lumaflute

wintry solar
#

card_eval_status_text needs card rather than self

glossy stone
#

OH

#

YEAH I WAS GONNA CHANGE THAT thankies

#

OKAY NOW IT WORKS WOO

#

https://youtu.be/dlmDDcRDByc
god i'm gonna get a rude awakening when i try to make the art...

和田たけあき(くらげP)と申します。
はい、さようなら。

■作詞・作曲・編曲 : 和田たけあき(くらげP) https://www.youtube.com/channel/UC7BYDRV-l741zjSUcyLT_cQ
■絵 : チェリ子 http://www.nicovideo.jp/mylist/36367946

公式サイト
http://www.wadatakeaki.net/
Twitter
https://twitter.com/WADATAKEAKI

インストはこちら
https://www.dropbox.com/sh/d01rjhfzcyxu4m8/AAAkeUsTspgkh7Fl0F_fYqNqa?dl=0
(±2,±5、キー変更用ドラムのみ/ドラム抜...

▶ Play video
teal estuary
#

thats a neat idea tbh

#

kinda like fire joker

glossy stone
#

yeah it's infinite burnt joker but antilobotomy
aka "get smeared/shortcut you fuck"

#

I'm up to 10 jokers implemented now... maybe I should make the art.

#

Maybe I'll try to implement this.
±0 (common)
If 0 cards left in hand, gain +1 hand size

#

...this is uncommon isn't it

teal estuary
#

hmmmmmm

#

i think you could get away with it being common, but its definitely a very good common

#

(there should be a mod that adds inbetween ranks, definitely /s)

glossy stone
#
local plusminus = SMODS.Joker {
 key = 'plusminus',
  loc_txt = {
    name = '±0',
    text = {
      "If {C:attention}0{} cards held",
      "in hand,",
      "{C:attention}+1{} hand size",
      "{C:inactive}(Currently +#1#)"
    }
  },
  config = { extra = {hand_size = 0} },
  cost = 5,
  rarity = 1,
  atlas = 'OSJokers',
  eternal_compat = true,
  perishable_compat = true,
  blueprint_compat = false,
  pos = { x = 4, y = 2 },
  loc_vars = function(self, info_queue, card)
    return { vars = {card.ability.extra.hand_size} }
  end,
  add_to_deck = function(self, card, from_debuff)
    G.hand:change_size(card.ability.extra.hand_size)
  end,
  remove_from_deck = function(self, card, from_debuff)
    G.hand:change_size(-card.ability.extra.hand_size)
  end,
  calculate = function(self, card, context)
    if #G.hand.cards == 0 and not context.blueprint and not context.individual then
              card.ability.extra.hand_size = card.ability.extra.hand_size + 1
      return {
        message = "UPGRADE!",
            }
    end
  end
    } 

okay literally nothing went right here XD, can you tell me what i should do

wintry solar
#

you need to chance the hand size in your calculate function

#

but also add a better context check

#

otherwise this will trigger lots

glossy stone
#

oh yeah of course hm

glossy stone
wintry solar
#

change*

glossy stone
#

oh

#

change by what tho

wintry solar
#

by 1

#

so after card.ability.extra.hand_size = card.ability.extra.hand_size + 1 put G.hand:change_size(1)

glossy stone
#

and do away with the add to deck right

#

eh it's fine

#

but

#

IT'S WORKING NOW! YATTA

wintry solar
#

yeah you don't need the add to deck

#

you need the remove from deck though

#

keeping add to deck would allow debuffing it to work properly mind

glossy stone
#

oh

#

yeah it's fine, it's working now WOOO

#

11 jokers are now implemented....

#

GEE MAYBE I SHOULD DO THE ART SO I CAN RELEASE THIS

#

(I'm so cooked...)

#

Okay so I have a OS Joker idea:
High Range Test (unc.)
Gains x.25 Mult if score is more than 2500, doubles on every upgrade

What would the Low Range Test be?

opal spade
#

idk but if u haven't done matryoshka yet it would be funny if it had something to do with creating smaller copies of itself like an actual matryoshka doll

crisp coral
#

you should do the vampire that's just the same as vampire

glossy stone
#

Anyways gn, I'll listen to Vocaloid before sleeping to find Joker ideas

opal spade
#

so there's like 0 original code

nocturne garnet
weak depot
#

i'm trying to make a deck in which you get no rewards from blinds (a la red chip but all of them.) do y'all know where i'm going wrong here?

tepid crow
weak depot
#

i... sorry...

tepid crow
#

it's fine, it's just... I can't copy-paste it to my machine to check it

#

and I definitely don't want to re-type the whole thing

#

if you use
```lua
[insert code here]
```

#

you get a nice discord codeblock, with formatting and colours

#

try it!

weak depot
#
SMODS.Back{
    name = "Discounted Deck",
    key = "discndeck",
    atlas = 'whitedeckatl',
    pos = {x = 0, y = 0},
    loc_txt = {
        name ="Discounted Deck",
        text={
            "Start game with {C:money,T:v_liquidation}Liquidation{}",
            "Blinds give {C:attention}no rewards{}",
        },
    },
    config = {vouchers = {'v_clearance_sale','v_liquidation'}},
    unlocked = true,
    discovered = true,
    apply = function(self)
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.modifiers.no_blind_reward = self.GAME.modifiers.no_blind_reward or {}
                G.GAME.modifiers.no_blind_reward.Small = true
                G.GAME.modifiers.no_blind_reward.Large = true
                G.GAME.modifiers.no_blind_reward.Boss = true
                G.GAME.selected_back:apply_to_run()
            end
        }))
    end
}
tepid crow
#

so, what's going wrong with it? it doesn't apply?

weak depot
#

it was crashing but i noticed an error where i accidentally wrote self. instead of g. so we're trying again. i may be dumb

#

OKAY fixed it, i did some weird phrasing, my bad. thanks for the help anyhow and thanks for teaching me the code block thingamajig ❤️

#

corrected code:

    apply = function(self)
        G.E_MANAGER:add_event(Event({
            func = function()
                G.GAME.modifiers.no_blind_reward = G.GAME.modifiers.no_blind_reward or {}
                G.GAME.modifiers.no_blind_reward.Small = true
                G.GAME.modifiers.no_blind_reward.Big = true
                G.GAME.modifiers.no_blind_reward.Boss = true
                return true
            end
        }))
    end
}
tepid crow
#

ah, yeah, that'll break it

#

also nice fix on the event, that was gonna be an infinite loop

#

though I'm not sure you even need an event here

weak depot
#

maybe not, but i'm more putting guardrails to make sure i don't accidentally put something that needs an event where there isn't one. better safe than sorry

tepid crow
#

events are usually done when you need to time things

#

the reason the example decks all use events is because they directly modify the deck

#

and the deck isn't created yet when the Back:apply function is called

#

which is more of an issue with balatro itself... localthunk

weak depot
#

noted, thanks!

tepid sky
#

quick question: to let blueprint say it is compattable it was: "blueprint_compat = true," right?

teal estuary
#

mhm

#

i really wish it defaulted to true and not false, but its a meh thing

tepid sky
#

i could've swore it was in example jokers somewhere

tepid sky
#

it seems to be working

wooden nexus
#

Welp, I made some of my card art into a mod because I'm struggling to make my game

#

I'm gonna make a post for it

teal estuary
#

quick question, what mods have jokers that have Xmoney effects? need to do something similar, and looking at their code seems the best thing to do 😭

mental nacelle
#

like multiplying money full stop or money gain?

teal estuary
#

multiplying money

mental nacelle
#

i know there's a mod somewhere that has a NEO spamton joker that multiplies the player's money by two

teal estuary
#

i did see that, i just could not remeber the name 😭

mental nacelle
#

No Laughing Matter?

teal estuary
#

that was it, yuh

#

ty

tepid sky
primal robin
#

Question. Why G.GAME.blind.name for vanilla blinds is name The Psychic, but for modded it's key bl_twbl_nope?

tepid sky
#

🤷‍♂️

#

maybe they found funny

mental nacelle
#

question: do pattern patches only patch at one instance or every instance?

frosty dock
#

so it's not required that mods specify a name field, but it defaults to the key

primal robin
#

Understood

mental nacelle
teal estuary
#

is there something wrong this code? for some reason flushes arent working, but any other hands (3oak, pair, two pair, etc) is

#

they all have the same code, just a different == 'hand name'

wintry solar
#

that's not how context.poker_hands works

edgy reef
#

It's a table not a string

teal estuary
#

i mean it works, just not for flushes raisedcateyebrow

wintry solar
#

can you show one that works?

teal estuary
#

sure

#

i'll be damned, i realised what was going on

#

they were working before, no clue what happened 😭

wintry solar
#

try next(context.poker_hands["Three of a Kind"]

teal estuary
#

is that missing a ) at the end or

wintry solar
#

yes it is

teal estuary
#

😭 i realised you changed the captilisation, mb

#

yep, captilisation

#

thank you 😭

twilit oar
#

Okay I have joined, just to ask what is poker_hands a map to?
I have been trying to help Black, but what he is getting told to do makes very little sense to me.
I would like to say I'm experienced enough with Lua, I'm just most used to Factorio's api.

The only documentation I have seen is a link to #1247703015222149120, which is just attrocious and uninformative.

wintry solar
#

poker_hands contains all the possible poker hands from the cards you play

twilit oar
#

I kind of already understood that is the purpose, but how?
I understand it's a mapping of the name of the hand to a table of some sort. But what is that table

#

My first assumption was it was something like table<hand_names,true>, (hand_names being a union of strings) but the fact that you're supposed to use next() means that's clearly wrong

edgy reef
#

iirc it's something like table[<hand_name>] = <array of cards>

#

"Array of cards" being the cards from the hand that would form that specific hand.

twilit oar
#

Okay that's kind of what I thought
But if the hand is not valid, is it an empty array or something?

The idea that there would be an entry at all for an invalid hand sounds completely inane to me, but that's the only reason I can think of for using next()

tepid crow
#

did you try printing it?

twilit oar
#

Oh I don't even have the game. I'm a third party trying to understand enough to help my friend when they have issues

tepid crow
#

this is what I got when playing a two pair

{
  Flush House = table: 0x077a37d8  {
  },
  Full House = table: 0x077a3800  {
  },
  top = table: 0x07853940  {
  },
  Flush = table: 0x07264390  {
  },
  Pair = table: 0x07211880  {
    [1] = table: 0x07211858    {
      [1] = table: 0x07366760,
      [2] = table: 0x0726a0f8,
    },
    [2] = table: 0x07293028    {
      [1] = table: 0x0760f690,
      [2] = table: 0x0742c860,
    },
  },
  Four of a Kind = table: 0x0715ac30  {
  },
  Straight Flush = table: 0x07853918  {
  },
  Straight = table: 0x078a5988  {
  },
  Three of a Kind = table: 0x077ccec8  {
  },
  Flush Five = table: 0x07853940  {
  },
  Two Pair = table: 0x078a89b0  {
    [1] = table: 0x075b8eb8    {
      [1] = table: 0x07366760,
      [2] = table: 0x0726a0f8,
      [3] = table: 0x0760f690,
      [4] = table: 0x0742c860,
    },
  },
  Five of a Kind = table: 0x0728d988  {
  },
  High Card = table: 0x075f6430  {
    [1] = table: 0x076186f0    {
      [1] = table: 0x07366760,
    },
  },
}
edgy reef
#

The functions that check for valid hands to return an empty table.

tepid crow
#

I believe the innermost tables are the actual cards

twilit oar
#

One final question, is there luals type annotations that I should've forced Black to show me?

tepid crow
tepid crow
twilit oar
#

Alright. Coming from Factorio where we've got our api very thoroughly annotated
as well as my own personal choice of enabling the no-unknown warnings, that is plainly unacceptable to me.

I'll continue to help Black from afar, but I don't think I could ever touch it myself

#

Thanks for answering my questions and correcting my mis-inferences about the api

#

o/

tepid crow
#

I don't doubt Factorio has more structured documentation, kinda fits with the game haha

wintry solar
#

it's also a much more developed modding scene

tepid crow
#

about a difference of 7 years?

stiff locust
#

alright chat

#

how do i change the rank of a card

#

i can't make sense of how strength does it

brisk rose
#

SMODS.rank seems to exist

#

Idk how to use it though

brisk rose
stiff locust
#

i can't read it

brisk rose
#

They might do other stuff in other files for it

stiff locust
#

seems to be

#

assert(SMODS.change_base(_card, nil, new_rank))

#

where _card is the selected cards and new_rank is the new rank

brisk rose
#

Oh yeah it is change base you're right iirc

stiff locust
#

in theory assert(SMODS.change_base(context.other_card, nil, "6") should change the rank to 6

brisk rose
#

The actual smods.ranks is kinda an internal thing, just a table of ranks it looks like

stiff locust
#

that was surprisingly easy

stiff locust
#

thanks chat

loud citrus
#

i'm making a custom challenge and i want to know if this is right?

#

wait nothing in the base game bans seals or enchantments

loud citrus
#

also new problem this breaks my mod and i don't know why

#

🐟

#

i think i know why

#

yay! i fixed it

glossy stone
#

I have to resist the urge to code in new jokers instead of making ART FOR ONCE

loud citrus
#

how do i make code that refers to a mod
i want a part of my code to only work with a certain mod mod

if {mod} then code stuffs end

brisk ember
#

Yooo, hey I've been trying to install the grim mod, but it seems like theres a bug in lovely where it autogenerates the card.lua file, it throws error here, and I assume its because its missing a comma... so is this the right channel to ask? 😓

regal wolf
nocturne garnet
#

test sprites

mental nacelle
#

the nefarious question mark card

brisk ember
brisk rose
#

np, you're good :3

brisk ember
nocturne garnet
#

i worked on sin for like 10 minutes

#

the background looks so boring 😭

brisk rose
#

I think they look god *good (though fitting typo)

#

and as for the plain bg, maybe add some stippling?

#

I don't think it really needs it though

#

plus remember these will have spectral shader in the game

teal estuary
#

im completely guessing here on how to do this (cant even access the source code rn 😭 ), but is this on the right track for having a joker have a chance to times its sell value?

nocturne garnet
#

<@&1133519078540185692> uh oh!

grand violet
#

🔫

nocturne garnet
#

fastest shot in the west

grand violet
#

wtf

#

it isn't deleting the message on my end

nocturne garnet
#

deleted for me

grand violet
#

Oh it just takes a while

#

thank you Disc and Cord

glossy stone
#

whuh...

tawny perch
# nocturne garnet

would help looking at the spectral cards for references
they mostly have cool effects in the bg relating to the card

cursive ocean
#

Is there a guide/definition/reference available for the context and card parameters used in the calculate function? I'm finding it hard knowing what's available to do with each of them fool

crisp coral
cursive ocean
#

im so bad at navigating discords -_-

#

thank u

brisk rose
crisp coral
royal ridge
crisp coral
#

i'm clinically insane

#

i hope nopeus can handle this

nocturne garnet
#

wuddaflip are camel cards....

crisp coral
#

they weren't lying

#

that unsafe can unsafe

nocturne garnet
brisk rose
glossy stone
#

all i did today was make 1 (one) joker art lmao

nocturne garnet
glossy stone
weak depot
#

how would one duplicate a selected card in hand? i have this so far but it's not working

SMODS.Back{
    name = "Reflective Deck",
    key = "rflctdeck",
    atlas = 'whitedeckatl',
    pos = {x = 0, y = 0},
    loc_txt = {
        name ="Reflective Deck",
        text={
            "On hand played,",
            "One card in hand is {C:attention}Duplicated{}",
            "One card in deck is {C:attention}Destroyed{}"
        },
    },
    config = {discards = -1},
    unlocked = true,
    discovered = true,
    apply = function(self)
        evaluate = function (parts, hand)
            local cardToDuplicate = parts[math.random(1,#parts)]
            local _card = copy_card(cardToDuplicate, nil, nil, G.playing_card)
            _card:add_to_deck()
            end
        }
glossy stone
#

here's how it looks like in game

weak depot
#

that looks awesome!!!

loud citrus
#

Where do I find the code for challenge rules?

glossy stone
crisp coral
weak depot
#

?

#

i'm a little confused

crisp coral
#

wait

#

nevermnind

zinc zenith
#

Is there a starting_param value for playable hand size?

crisp coral
#

yeah im a fucking dumbass

#

add this G.hand:emplace(_card)

weak depot
#

so this?

    apply = function(self)
        local cardToDuplicate = context.full_hand[math.random(1,#context.full_hand)]
        local _card = copy_card(cardToDuplicate, nil, nil, G.playing_card)
        _card:add_to_deck()
        G.hand:emplace(_card)
    end
mental nacelle
weak depot
zinc zenith
#

Nah sorry i'm tryign to create a new hand type but need the playable hand to be larger than 5. just trying to find where i can access this but so far it seems like it's a global value

loud citrus
weak depot
mental nacelle
#

oh, well you'll probably need to go digging in the files then

loud citrus
#

I thought it would be in card.lua but no 😭

zinc zenith
weak depot
#

this doesn't throw an error but it also doesn't... work (trying to duplicate one random card in hand when a hand is played and this deck is used)

SMODS.Back{
    name = "Reflective Deck",
    key = "rflctdeck",
    atlas = 'whitedeckatl',
    pos = {x = 0, y = 0},
    loc_txt = {
        name ="Reflective Deck",
        text={
            "On hand played,",
            "One card in hand is {C:attention}Duplicated{}",
            "One card in deck is {C:attention}Destroyed{}"
        },
    },
    config = {discards = -1},
    unlocked = true,
    discovered = true,
    apply = function(self)
            evaluate = function (parts, hand)
                local cardToDuplicate = parts[math.random(1,#parts)]
                local _card = copy_card(cardToDuplicate, nil, nil, G.playing_card)
                _card:add_to_deck()
                _card:emplace()
                G.deck.config.card_limit = G.deck.config.card_limit + 1
                table.insert(G.playing_cards, _card)
                _card.states.visible = nil
                G.E_MANAGER:add_event(Event({
                    func = function()
                        _card:start_materialize()
                        return {
                            message = localize('k_copied_ex'),
                            colour = G.C.CHIPS,
                            card = self,
                            playing_cards_created = {true}
                        }
                    end
                })) 
            end
    end

}
nocturne garnet
#

why is this happening

#

i didnt even do anything

weak depot
#

conflict between mods?

nocturne garnet
#

i didnt download any mods

#

i literally didnt do anything

zinc zenith
#

according to my search the file is related to the "Awesome Balatro" mod

nocturne garnet
#

jimb is jimbos pack

#

suddenly jimbo's pack's joker atlas doesnt load

zinc zenith
#

sounds like you know the problem then

nocturne garnet
#

i dont know what the problem is

#

okay wtf

#

my balatro is not well

nocturne garnet
brisk rose
#

also, what is the spades deck from?

nocturne garnet
nocturne garnet
brisk rose
#

lmfao

brisk rose
#

whenever I ask what something interesting is from, it's always cryptid

#

maybe one day they're make the 'balanced' version and i'll want to install it

#

though there's other mods with suit decks too to be fair

nocturne garnet
#

also

#

you can just disable things that are too overpowered in the config

#

and use the things that are fun

#

like the decks

brisk rose
#

I know the config exists, but the legendaries are also OP and can't be disabled sperately yet

#

says math himself

nocturne garnet
#

for a while now

brisk rose
#

@lusty epoch why no advertise?

nocturne garnet
#

its a legendary

nocturne garnet
hardy viper
#

nowhere near complete yet

nocturne garnet
#

in Misc Jokers

#

or are they just in the miscjokers fil for no reason

lusty epoch
brisk rose
#

well so is every mod, unless it's unfinished as in unplayable

hardy viper
#

its not balanced

#

thus it's not finished

lusty epoch
#

It unfinished as in i just started like a week ago and half the things are still op

brisk rose
#

lol fair. I just like... expect WIP threads I guess. They're fun for me

#

no worries regardless

lusty epoch
#

I mean it’s usuable rn if you want to give it a try

hardy viper
#

#balanced-cryptid in the cryptid discord

#

does that work for a wip thread gladeline

brisk rose
#

god I guess it makes sense to join the server, lol

#

can I get a link?

hardy viper
brisk rose
#

thank you :3

hardy viper
#

yw :3

cursive ocean
#

Just finished my first Jimbo, a ripoff of Midas Mask but for turning 7s lucky. Would love any feedback on it, improvements and especially on if I'm using the lifecycle/context correctly.

SMODS.Jokers.j_dogmod_lucky7.calculate = function(self, context)
        if context.before then
          local scoredCards = {} -- store the cards that should be upgraded
        
          for _, scoringCard in ipairs(context.scoring_hand) do
            if scoringCard:get_id() == 7 then -- if the card is a seven, save it for later
              table.insert(scoredCards, scoringCard)
            end
          end


          if tableLength(scoredCards) > 0 then -- do we have any scoring cards?
            G.E_MANAGER:add_event(Event({ -- delay the upgrade a bit?
              delay = 0.2, -- what's the unit?
              func = function()
                  for _, toBecomeLucky in ipairs(scoredCards) do
                    toBecomeLucky:juice_up(0.5, 0.5) -- jiggle. What's the unit?
                    toBecomeLucky:set_ability(G.P_CENTERS.m_lucky) -- make it lucky
                  end
                  return true
              end
            }))
            card_eval_status_text(self, "extra", nil, nil, nil, { -- pops after the hand is removed if in the above event
              message = localize("k_dogmod_lucky") -- "Lucky!"
            })
          end -- end length check    
        end -- end if context
    end -- end calculate  
#

Also anything Lua related as I've never used it before 😐

wintry solar
#

You’re using 0.9.8?

cursive ocean
#

Balatro Version: 1.0.1g-FULL
Modded Version: 1.0.0~ALPHA-1012b-STEAMODDED
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta7

#

But I did use a different mod as a way to get something going. Maybe that is/was using some older stuff? What is it that smells of 0.9.8?

#

Creating an appending to the table might be redundant. I thought I also had to delay the Joker message popping up in the same event, but apparently that triggers at a different time

wintry solar
#

Throwing the calculate in like that isn’t how 1.0 is usually coded

cursive ocean
#

Do you know of any good examples to see the 1.0 conventions?

brisk rose
#

Morefluff seems well made and striaghtforward

#

it splits its files up though which isn't really a convention, just the author's preference

maiden phoenix
#

Lots of big 1.0 mods do that now

brisk rose
#

yeah, it's not a bad thing at all

#

makes it a bit of a pain to navigate though

wintry solar
#

From a developing side, it makes it so much easier to navigate through 🤣

brisk rose
#

very fair, lol

wintry solar
#

I wish I’d broken galdur into smaller files, it’s such a pain to find anything in there

#

And that’s not even that big really

maiden phoenix
#

Time to make a mod that has the misc, utils and functions files balatrojoker

brisk rose
#

pfffft

cursive ocean
#

Thanks for the help. I'll try to make the Jimbos I want then do a whole refactor when I'm more comfortable working with this stuff

tepid sky
#

how do i , add juice to my joker?

#

like where do i put it

#

and does it needs something like self.juice_up or card.juice_up?

loud citrus
#

You don't need juice if you are returning a message though

#

Sorry I missed input, it's
juice_up
Not
juice

tepid sky
#

thanks!

#

is it supposed to be like this then?

wintry solar
#

that''ll juice twice

tepid sky
#

?

wintry solar
#

oh wait no

#

you can also add card = card in the return and it'll juice for you

tepid sky
#

ooh

#

like on the top of the mod?

#

on its own?

maiden phoenix
#

in the return

cursive ocean
#

Does anyone know how to get the ability of a card? The getter equivalent of set_ability..?

Like, foreach key, card in context.scoring_hand, if card.get_ability === "Glass"

#

As always as soon as you ask you figure it out

maiden phoenix
#

Rubber ducking

cursive ocean
#

Ok another one! Is this an OK way to temporarily nudge the probability of things triggering, like having an "Oops all sixes" for the one played hand?

local oddsBefore = G.GAME.probabilities.normal
        local newOdds = G.GAME.probabilities.normal * self.ability.extra.increaseOddsTimes -- 2

G.GAME.probabilities.normal = newOdds

G.GAME.probabilities.normal = oddsBefore
mental nacelle
#

how would i get the challenge id

mental nacelle
#

trying to patch this specifically gives a blank challenge (no rules)

rough furnace
#

random consumeable idea trigger a selected joker's on sell effect wihtout selling the joker

hardy viper
#

would be pretty funny

#

but also like kinda useless in 99% of situations

rough furnace
#

I mean invisible + it is a second free joker

#

(or unlimited with perkio)

umbral zodiac
#

anyone know why trying to get a random index for smods.ranks isnt working?

#

i just want a rnadom rank 😭

brisk rose
#

Why do the colors on the texr look just like my trance theme, lol.

#

Maybe they're just the normal colors fir debug and I didn't notice before

opal spade
#

they're normal for debugplus

brisk rose
#

Yeah I thought so

#

I just coincidentally picked similar colors on my theme

teal estuary
#

me and marie have been trying to make this work for a short while now - the original jokers function is to make it times its sell value but for now, just trying to even make it add to the sell value

#

but for some reason, it just does not work

edgy reef
#

set_cost would override any changes you make to it's sell value.

teal estuary
#

damn

edgy reef
#

You should be able to do the same thing Egg goes since this reads as just that but multiplied

teal estuary
#

but egg uses set_cost() raisedcateyebrow

#

like, the bottom half of that is just modified egg

edgy reef
#

ohhh

#

It's prob just an if check issue.

#

card.ability.extra is set to a number which means that card.ability.extra.odds won't work

#

Altho that would give you an error not just do nothing

teal estuary
#

i am getting an error but its for the extra_value = line, not the extra.odds line

#
Oops! The game crashed:
[SMODS MJOK "MoarJokers.lua"]:739: attempt to perform arithmetic on field 'extra' (a table value)

Additional Context:
Balatro Version: 1.0.1g-FULL
Modded Version: 1.0.0-ALPHA-0710a-STEAMODDED
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta7
Steamodded Mods:
    1: Debug Mode by MathIsFun_ [ID: DebugMode]
    2: MOAR Jokers by Mr.SmoothieHuman [ID: MJOK]

Stack Traceback
===============
(3) Lua method 'calculate' at file 'MoarJokers.lua:739' (from mod with id MJOK)
Local variables:
 self = table: 0x3abcfac0  {alerted:true, loc_vars:function: 0x3aa61908, _saved_d_u:true, original_key:awesome-egg (more...)}
 card = table: 0x3ae42228  {click_offset:table: 0x3af683f0, children:table: 0x3ae2a9b8, ambient_tilt:0.2 (more...)}
 context = table: 0x3b00e7d8  {end_of_round:true, game_over:false}
 (*temporary) = table: 0x3ab9a548  {bonus:0, h_mult:0, extra:table: 0x3ab9a570, hands_played_at_create:0, mult:0 (more...)}
 (*temporary) = number: 0
 (*temporary) = table: 0x3ab9a570  {Xmoney:3, odds:3}
 (*temporary) = string: "attempt to perform arithmetic on field 'extra' (a table value)"
(4) Lua method 'calculate_joker' at file 'card.lua:2396'
Local variables:
 self = table: 0x3ae42228  {click_offset:table: 0x3af683f0, children:table: 0x3ae2a9b8, ambient_tilt:0.2 (more...)}
 context = table: 0x3b00e7d8  {end_of_round:true, game_over:false}
 obj = table: 0x3abcfac0  {alerted:true, loc_vars:function: 0x3aa61908, _saved_d_u:true, original_key:awesome-egg (more...)}
(5) Lua field 'func' at file 'functions/state_events.lua:103'
Local variables:
 game_over = boolean: false
 game_won = boolean: false
 (for index) = number: 1
 (for limit) = number: 3
 (for step) = number: 1
 i = number: 1
 eval = nil
(6) Lua method 'handle' at file 'engine/event.lua:55'
Local variables:
 self = table: 0x3b094aa0  {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x3ae20dc8 (more...)}
 _results = table: 0x3b0e6058  {blocking:true, pause_skip:false, time_done:true, completed:false}
(7) Lua method 'update' at file 'engine/event.lua:182'
Local variables:
 self = table: 0x3af005e0  {queue_last_processed:16.183333333334, queues:table: 0x3af00608, queue_dt:0.016666666666667 (more...)}
 dt = number: 0.0291828
 forced = nil
 (for generator) = C function: next
 (for state) = table: 0x3af00608  {unlock:table: 0x3af00630, other:table: 0x3af00aa8, tutorial:table: 0x3af00680 (more...)}
 (for control) = number: nan
 k = string: "base"
 v = table: 0x3af00658  {1:table: 0x3aa2b518, 2:table: 0x3b094aa0, 3:table: 0x3aec2a40}
 blocked = boolean: false
 i = number: 2
 results = table: 0x3b0e6058  {blocking:true, pause_skip:false, time_done:true, completed:false}
(8) Lua upvalue 'gameUpdateRef' at file 'game.lua:2493'
Local variables:
 self = table: 0x3a9a2c40  {PALETTE:table: 0x3a9a3990, F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true (more...)}
 dt = number: 0.0291828
 http_resp = nil
(9) Lua method 'update' at file 'main.lua:480'
Local variables:
 self = table: 0x3a9a2c40  {PALETTE:table: 0x3a9a3990, F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true (more...)}
 dt = number: 0.0291828
(10) Lua field 'update' at file 'main.lua:133'
Local variables:
 dt = number: 0.0291828
(11) Lua function '?' at file 'main.lua:77' (best guess)
(12) global C function 'xpcall'
(13) Love2D function at file 'boot.lua:377' (best guess)
Local variables:
 func = Lua function '?' (defined at line 48 of chunk main.lua)
 inerror = boolean: true
 deferErrhand = Lua function '(Love2D Function)' (defined at line 348 of chunk [love "boot.lua"])
 earlyinit = Lua function '(Love2D Function)' (defined at line 355 of chunk [love "boot.lua"])
``` (wont let me send them at .txt, apologies)
brisk rose
#

How would you interrupt the draw routine for cards to add multiple shaders?

#

From what I understandyou have to switch between canvases to do it

stiff locust
teal estuary
#

oh i did

loud citrus
#

i'm trying to add a custom challenge rule where if you play your most played hand it doesn't score, i have no idea how i'm gonna make it becuase of how rules seem to work.

topaz sun
teal estuary
#

i changed it because, what i was told, extra = is only needed for things that would be changed? but sure, i will try it

opal spade
#

you can't math a table

teal estuary
#

that.. would make sense, yeah

#

question because its like 5am, and i can feel my brain melting, why the fuck is it a table?

stiff locust
#

because yeah balatro only saves joker values that are within extra which means they save when you close and reopen a run

opal spade
edgy reef
#

Table basically store values that you want to later access.

teal estuary
#

it finally clicked in my head what you guys mean, i think i understand now 😭

#

okay, so, i wanna be absolutely sure, do i need to define extra_value in the joker itself? if so, how? because i presume (from what spa said), you dont put it in config = {extra = {}} because you cant math a table raisedcateyebrow

brisk rose
#

You just need to get the number from the table to math it, which is just [].[] until you get down to the labeled numerical variable to do math on

loud citrus
#

could someone point me towards seeing a modded enchantment example? i don't know how to make them

brisk rose
#

Enhancement you mean?

#

Ortalab has quite a few

#

Make sure you're looking in the new demo repo

limpid flint
loud citrus
rough furnace
#

Someone remind to look into why this would be happening later

loud citrus
wintry solar
#

I think it’s just missing seals out of the ‘normal’ object types

#

Oh it misses blinds too, those are still on my local environment

brisk rose
#

it still says dev

cursive ocean
#

I'm trying to in a way replicate the interaction that Midas Mask and Golden Ticket (in that order) have when playing a face card, in that the card becomes gold and then is counted by the ticket. I have a Jimbo that turns certain cards lucky and another that checks if all played cards are lucky and temporarily increases the odds of them triggering.

I've tried to use the same context/lifecycle checks as Midas and Ticket, but when I'm checking the ability of the card in the probability up joker, the ability is reported as being "Default Base" despite a previous joker turning the card lucky. Any ideas as to why these don't interact in the intended way?

#
-- turn all 7s lucky
lucky7.calculate = function(self, context)
        if context.before and context.cardarea == G.jokers then -- TODO: must know more about lifecycle
          local scoredCards = {} -- store the cards that should be upgraded
        
          for _, scoringCard in ipairs(context.scoring_hand) do
            if scoringCard:get_id() == 7 then -- if the card is a seven, save it for later
              table.insert(scoredCards, scoringCard)
            end
          end

          if #scoredCards > 0 then -- do we have any scoring cards?
            G.E_MANAGER:add_event(Event({ -- delay the upgrade a bit?
              delay = 0.2, -- what's the unit?
              func = function()
                  for _, toBecomeLucky in ipairs(scoredCards) do
                    toBecomeLucky:juice_up(0.5, 0.5) -- jiggle. What's the unit?
                    toBecomeLucky:set_ability(G.P_CENTERS.m_lucky) -- make it lucky
                  end
                  scoredCards = {}
                  return true
              end
            }))
            card_eval_status_text(self, "extra", nil, nil, nil, { -- pops after the hand is removed if in the above event
              message = localize("k_mmc_lucky") -- "Lucky!"
            })
          end -- end length check    
        end -- end if context
    end -- end calculate  
#
-- temporarily increase odds of triggering if all cards are lucky
fixed_odds.calculate = function(self, context)
      if context.individual and context.cardarea == G.play then
        local allAreLucky = true

        for _, scoringCard in ipairs(context.scoring_hand) do
           print(scoringCard.ability.name)
           if scoringCard.ability.name ~= 'Lucky Card' then
              allAreLucky = false
           end
        end

        if allAreLucky then
          self.ability.extra.triggered = true
          card_eval_status_text(self, "extra", nil, nil, nil, {
            message = localize("k_mmc_odds_up")
          })

          for k, v in pairs(G.GAME.probabilities) do -- this is what oops all sixes does
            G.GAME.probabilities[k] = v*self.ability.extra.increaseOddsTimes
          end
          allAreLucky = false
        end -- end all are lucky
      elseif context.after and self.ability.extra.triggered then -- clean up after trigger to not inflate all probabilities forever
        for k, v in pairs(G.GAME.probabilities) do -- reset probabilities
          G.GAME.probabilities[k] = v / self.ability.extra.increaseOddsTimes
          print(G.GAME.probabilities[k])
        end
        self.ability.extra.triggered = false -- reset state
      end -- end if context 
  end -- end calculate
cursive ocean
#

I suppose my questions really are, how can we track the state of a card throughout a hand? Why is context.scoring_hand not reflecting the set_ability call that was done in an earlier calucate?

cursive ocean
#

Ooook I figured it out. It has to do with triggering the set_ability in a delayed event. Don't do it is what I've learned

hardy viper
#

so how would i make a steamodded mod config save

primal robin
#

Question. How G.E_MANAGER behave when game in mods loading state?

crisp coral
#

it doesn't i think

glossy stone
#

even with a reference this shit is so HARD

primal robin
#

I envy those who can draw, it's so cool

glossy stone
#

that's where you're wrong, i can't draw well

primal robin
#

OK drawing better than nothing

#

Drawing is 2nd most difficult part of any mod after "Idea"

primal robin
glossy stone
#

ok i'll make one on top one on botto-oh wait miku's gonna cover up the bottom text walc

#

but nevertheless yea

cursive ocean
#

At least I know I don't have to go digging in my own junk.

cursive ocean
# weak depot any help?

I'm not getting the evaluate function to trigger either. Where did that definition come from?

I'm able to get something to trigger on every hand with, trigger_effect, but don't know how to grab the played hand from it.

SMODS.Back{
  name = "Reflective Deck",
  key = "rflctdeck",
  --atlas = '',
  pos = {x = 0, y = 0},
  loc_txt = {
      name ="Reflective Deck",
      text={
          "On hand played,",
          "One card in hand is {C:attention}Duplicated{}",
          "One card in deck is {C:attention}Destroyed{}"
      },
  },
  config = {discards = -1},
  unlocked = true,
  discovered = true,
  apply = function(self)
    print("hello apply")
    return true
  end,
  trigger_effect = function(self, args)
    print("hello trigger")
    printObj(args)
    printObj(self)
  end,
}
#

Can't see anything about an evaluate function in the Steammodded or OG Backs definitions hmm

brisk rose
#

Evaluate is just the name they gave it

#

They defined it themselves it looks

cursive ocean
#

Hm, I though maybe the game somehow knew to look for an implicit return of an evaluate function idk. It's not doing anything as far as I can tell anyway.

cursive ocean
#

trigger_effect is at least what e.g. the plasma deck uses to balance chips and mult. Just gotta figure out how to grab the actual hand played. Maybe that's buried in G.GAME somewhere 😐 like G.GAME.last_hand_played

#

Returning or calling another function in apply doesn't seem to work. But I've been wrong before

weak depot
#

i'm glad i know about trigger_effect now LOL

#

still confused but we're getting somewhere

tepid crow
weak depot
#

yeah, i'm mostly having trouble finding the cards in a hand

wintry solar
#

You should be able to check G.play.cards in your trigger effect function

tepid crow
#

SMODS.Pokerhand is for creating an entirely new poker hand, not for finding cards in hand

weak depot
#

okay

cursive ocean
#

Here's a way to modify a random card at least

trigger_effect = function(self, args)
    print(args.context)
    if args.context == 'final_scoring_step' then
      ease_dollars(100)
      G.E_MANAGER:add_event(Event({
        trigger = "before",
        delay = 0.2,
        func = (function()
            local randomCardInDeck = G.playing_cards[math.random(1, #G.playing_cards)]
            randomCardInDeck:set_ability(G.P_CENTERS.m_lucky, nil, true)
            return true
        end)
    }))
    end
  end
#

Or get some dollars

weak depot
#

saving that for later use, thanks :>

cursive ocean
#

Might not need to wrap it in an event

weak depot
#

if nothing else i slightly modified it to do the second half of the deck's gimmick, in that it destroys a random card in deck

#
            func = (function()
                local randomCardInDeck = G.playing_cards[math.random(1, #G.playing_cards)]
                randomCardInDeck:remove()
                return true
            end)
hardy viper
cursive ocean
#

good shouts

weak depot
#

out of curiosity, how does one use the pseudorandom functions?

#

take ```lua
local randomCardInDeck = G.playing_cards[math.random(1, #G.playing_cards)]

opal spade
#

pseudorandom element

weak depot
#

?

opal spade
#

pseudorandom_element(_t, seed)
_t is the table
seed is pseudorandom seed

weak depot
#

do i just leave seed blank for the one by default...?

cursive ocean
#

You could do

local randomCardInDeck = pseudorandom_element(G.playing_cards, pseudoseed(self.key))

weak depot
#

okay, thanks!!!

cursive ocean
#

A good learning experience this

This turns a random card in the deck lucky and a random card in the played hand lucky. Plays a gong and shows a little blurb.

It does not take into account if the card was scored.

trigger_effect = function(self, args)
    if args.context == 'final_scoring_step' then

      local randomCardInHand = pseudorandom_element(G.play.cards, pseudoseed(self.key))
      local randomCardInDeck = pseudorandom_element(G.playing_cards, pseudoseed(self.key))

      randomCardInDeck:set_ability(G.P_CENTERS.m_lucky, nil, true)
      randomCardInHand:set_ability(G.P_CENTERS.m_lucky, nil, true)


      play_sound('gong', 0.94, 0.3)
      play_sound('gong', 0.94*1.5, 0.2)
      play_sound('tarot1', 1.5)  

      attention_text({
        scale = 0.8, text = 'Stuff happening!', hold = 2, align = 'cm', offset = {x = 0,y = -2.7},major = G.play
      })
    end
  end,
weak depot
#

think i got it!

#

would send the code but discord won't let me LMAO

cursive ocean
#

powerful

weak depot
#

is it too busted?

cursive ocean
#

oh no i meant like. muscle power. well done

weak depot
#

OH okay thank you :> couldn't have done it w/o y'all's help so

tepid sky
#

reflected? interesting

frigid flame
#

i'm trying to understand

weak depot
frigid flame
#

ah

#

i can see this being abused in many ways

weak depot
#

i'm worried it's too good

frigid flame
#

like i imagine it'd be insane at deckfixing

weak depot
#

yeah that was kinda my whole idea of it's use

#

flush five builds and whatnot

frigid flame
#

i'd say a decent trade-off would be something like

#

either hands leveling up slower

#

or blinds scaling faster

weak depot
#

i'll probably do blind scaling but damn that's the second scaling deck in this mod and there's only 5 decks LMAO

weak depot
opal spade
weak depot
#

it's a bit buggy, yeah

opal spade
#

it goes from 44 to 43 when it should stay at 44 or at least go back to 44

weak depot
#

i'm gonna try just turning a card in deck into the selected card

rough furnace
#

iirc creating cards in hand doesn't increment the deck count

#

double check with cryptid if that is the case

opal spade
#

wait it creates in hand

#

the delayed materialize is odd but what I was seeing is not an issue

rough furnace
#

oh wait is it in hand?

wintry solar
#

You have to add them to the tables yourself

weak depot
#

okay i went with a simpler approach, we just convert a card in deck to the one in hand

opal spade
weak depot
#

that was also very buggy, which is why i wanted to fix it

#

i'd occasionally end up with invisible cards

#

there!

rough furnace
#

use the webcam to make the deck have a reflective effect

frigid flame
#

ah yes

#

casual breach of privacy

nocturne garnet
#

most complicated cryptid exotic joker code

tepid sky
#

if i wanted to remove a random card from played hand how do i do that?

nocturne garnet
tepid sky
#

destroy

nocturne garnet
tepid sky
#

cuz i cannot figure it out for the life of me

nocturne garnet
#

is this before the hands are scored or nah

#

is this after or before cards are scored

tepid sky
#

eeh sure

#

that fits

#

also i've come up with this

#

but prob will be shi isn't it?

nocturne garnet
#

something like this would work right

tepid sky
#

thats- hella sort lol

nocturne garnet
tepid sky
#

.-.

nocturne garnet
#

wait

nocturne garnet
#

hopefully

#

i think

#

maybe

tepid sky
#

if i wanted it to trigger on the last hand i would have to add: and #context.full_hand == 1

nocturne garnet
#

if you wanted to make it trigger on the last hand you would do

if G.GAME.current_round.hands_left == 0 then
tepid sky
#

ooh okay

#

WHY IS IT BLUEEEEE

#

oh

#

nvm

#

fixed

weak depot
#

i'm adding a custom sfx into my mod. here's the code:

SMODS.Sound({
    vol = 1,
    pitch = 1,
    key = "reflect",
    path = "reflect.ogg"
})
``` however, when i call ```lua
play_sound('reflect', 1, 0.5)
``` it doesn't work. any help? is there something i'm doing wrong here?
tepid sky
nocturne garnet
#

it should be inside context.before

nocturne garnet
#

are you sure you have a card.ability.extra.chips

#

yk what im just gonna rewrite all of this

hardy viper
#

pleeeease

#

please

weak depot
nocturne garnet
#

what im assuming your code is:

before playing hand, destroy a random card and gain Xmult
after playing hand, return Xmult

nocturne garnet
frosty dock
tepid sky
#

also

#

rn when card is destroyed it is still gives chips

nocturne garnet
#

damn

#

i dont think thats a very important part so ehhh

tepid sky
#

lol

#

then i can change it to after right?

#

feels better now

#

its gud

tepid sky
nocturne garnet
#

and send the whole joker too

tepid sky
maiden phoenix
#

the X isn't capitalized

tepid sky
#

also gives error when giving mult o-o

maiden phoenix
#

it's case-sensitive

#

for the message key

tepid sky
#

where is the uncappalized "x" then?

maiden phoenix
#

The thing you're highliting in the pic?

tepid sky
#

but everything is uppercase? ;-;

#

i cannot find the one that isn't

maiden phoenix
tepid sky
#

ooh

maiden phoenix
#

should be a_xmult

tepid sky
#

that way around

#

thank you! <3

#

gn now ;-;

#

cyall

cursive ocean
#

im refactoring my jimbos but im having some trouble with localization. ive structured the project as follows, but can't seem to load the text from the localization file in my jimbo definitions. ive tried to follow the structure of the ortalab-demo project to the best of my ability, but the localization eludes me. the jimmies and their assets load fine, but the name and descriptions are empty. any suggestions?

.
├── assets
├── functions
├── localization
│   └── default.lua
├── main.lua
└── objects
├── jokers
│   ├── lucky_seven.lua
├── jokers_index.lua

-- main.lua
DogMod = SMODS.current_mod
SMODS.load_file('objects/jokers_index.lua')()
-- objects/jokers/lucky_seven.lua
SMODS.Joker({
    key = "lucky_seven",
    atlas = "jokers",
    pos = {x = 0, y = 0},
    rarity = 1,
    cost = 4,
    unlocked = true,
    discovered = true,
    blueprint_compat = false,
    eternal_compat = true,
    perishable_compat = true,
    config = {extra = {}},
    loc_vars = function(self, info_queue, card)
        return {vars = {'World!'}} -- localization??
    end,
    calculate = function(self, context)
       ...
            return {
                message = "Lucky!", -- needs localization (misc.labels.dogmod_lucky)
                card = self
            }
       ...
    end  
})

-- localization/default.lua
return {
    ["misc"] = {
        ['labels'] = {
            dogmod_lucky = 'Lucky!',
        }
    },
    ["descriptions"] = {
        ["Joker"] = {
            ['j_dogmod_lucky_seven'] = {
                ["name"] = "Cool Name",
                ["text"] = {
                    "Hello #1#",
                }
            },
        },
    }
}
maiden phoenix
#

SMODS.Joker needs to be between {}, not ({})

tepid crow
#

either way is fine

#

func{...} is just a Lua shortform version of func({...})

maiden phoenix
#

Oh

tepid crow
#

you can also do func"string" which is equivalent to func("string")

maiden phoenix
#

Not really the one who needs the most help rn

cursive ocean
#

Yees

--- STEAMODDED HEADER
--- MOD_NAME: DogMod
--- MOD_ID: dogmod
--- MOD_AUTHOR: [dog]
--- MOD_DESCRIPTION: Learn by stealing
--- DISPLAY_NAME: DogMod
--- MOD_PREFIX: dogmod  
----------------------------------------------
------------MOD CODE -------------------------
wintry solar
#

Huh 🤔

#

Oh

#

It’s just PREFIX

#

Not MOD_PREFIX

cursive ocean
#

oooo

#

hmm still blank

#

I can hardcode the labels in the joker constructor but it's just annoying that it doesnt work -_- whos ever gonna use my junk in german anyways

wintry solar
#

Do you have it available on git and I can take a poke around?

cursive ocean
#

suuure i can in a few minutes. if you dont mind the (temporarily) stolen assets

wintry solar
#

Nah I don’t mind

cursive ocean
#

sent you on dm

#

its in the middle of everything being reshuffled soo

nocturne garnet
#

how do you add config stuff to your mod

#

like disableable stuff

tepid crow
nocturne garnet
#

there should be tutorials for simple things like this

tranquil gull
#

reposting idea from #⚙・modding-general : vilatro (i.e. letting you play entirely with the keyboard)
rough sketch:

during a blind, you can press 1234567890 to select/deselect the 1st through 10th card in your hand, if you have >10 your hand goes off the screen and can be cycled through with arrow keys
deselect all with q and if you have only one selected you can move it by holding shift and inputting a position or using arrow keys
pressing enter plays, pressing backspace discards

pressing j shifts the focus to the jokers, where it's the same thing but you can only select one at once, and holding s for 1 second (configurable) sells it
same thing with k for consumables, except press enter to use
pressing / opens or closes deck view
in the shop, each buyable item is numbered (p sure you can't go over 10 in the shop in vanilla at least) and you can select one with number keys and buy with enter, buy and use with shift enter

there's more stuff i'd need to go over but yall get what i mean right
i might make this, might not tho bc college

hardy viper
#

well

#

it's not that hard at all

#

it's just like

#

nativefs stuff

#

2 lines worrh

tepid crow
#

steamodded handled all of the nativefs stuff for me in my config page

hardy viper
#

huh

#

how would it have done that

wintry solar
#

smods saves the configs when the window is closed

hardy viper
wintry solar
#

it creates the config file based off of your default.lua, the saving just updates that table

hardy viper
#

unless there's some random undocumented config place where you can set values that are consistently saved which wouldn't be surprising because nothing in smods is documented

#

you have to create a file called "default.lua" to utilize smods config files?

wintry solar
#

I assume creating the table manually in the code will also work

hardy viper
#

ya ive never seen a mod with a default.lua file so

#

regardless it seems kinda pointless considering just doing the nativefs stuff is really easy

#

definitely easier than figuring out random undocumented smods stuff

#

ill never stop complaining about smods

wintry solar
#

theres plenty of mods using config files

hardy viper
#

maybe there are but i have never seen a file named default.lua

rough furnace
#

yeah iirc just current_mod.config will be saved when the config window is closed

edgy reef
#

Plus I thought that config.lua in the main file directory was considered the "default config"

wintry solar
#

it accepts both maybe?

tepid crow
#

yeah it's config.lua

wintry solar
#

default.lua definitely works too

#

wait

#

no

#

I am in the wrong folder

#

nvm

edgy reef
#

default.lua is for localization defaults

wintry solar
#

it is config.lua

#

yeah

rough furnace
#

yeah config.lua is for config

#

(I use it for other stuff and it's annoying)

tepid crow
edgy reef
#

They need more than improvements they need to actually be written

tepid sky
tepid sky
#

seemed to have figured it out

#

nvm

#

it just isn't working

wintry solar
#

What are you trying to do?

tepid sky
#

the shake

brisk rose
#

At the very end ofc

#

Of the calculate function

tepid sky
#

like this?

nocturne garnet
#

not correct at all

#

first of all context.joker_main cant be inside context.individual

#

i believe you dont know how context.joker_main works?

#

context.joker_main is after every card scores, when most jokers like Joker trigger

#

its not what makes a joker trigger, its just an event that happens

tepid sky
#

hmm okay

nocturne garnet
#

returning ends the function, anything afterwards is cancelled

tepid sky
nocturne garnet
#

for example,

function iDontKnowWhatToNameThis(number)
      return number + 1
end

print(iDontKnowWhatToNameThis(3))
-- this will print the number 4, because the function returned the number + 1
tepid sky
#

so card = card doesn't need to be in the return?

nocturne garnet
tepid sky
#

litterally just letting all my jokers shake on activation

#

just like the base jokers ;-;

nocturne garnet
tepid sky
#

now before i do something stupid, what table, the return?

nocturne garnet
tepid sky
#

ok thanks

tepid sky
#

but i;ll try it with card:juice_up()

brisk rose
tepid sky
nocturne garnet
tepid sky
#

oh

brisk rose
#

Idk if card needs to stay context.other_card in this Cass though

brisk rose
brisk rose
brisk rose
#

It's true though

#

Also I meant dw

tepid sky
#

oh something worked

brisk rose
brisk rose
#

I've helped a lot with Pokermon, but only ideas and composing (not even drawing really) art

brisk rose
tepid sky
tepid sky
#

i am keeping it

#

its gud

tepid sky
tepid sky
tepid sky
#

y couldn;t i use self:juice_up()?

wintry solar
#

you can use card:juice_up() like we said at first

tepid sky
#

somehow it's all just not working

wintry solar
#

what isn't working

tepid sky
#

the card = card or card:juice_up()

wintry solar
#

can you send the entire calculate function?

tepid sky
#

:o

#

it worked

#

lol this one work when i discard smth

wintry solar
#

that'll work on every event

tepid sky
#

oh

#

it also crases my game when i use it,

#

idk what went wrong tho

stray orbit
#

i cant get function SMODS.current_mod.process_loc_text() to change text at all

#

is there more to it than this

tepid sky
tepid sky
#

Just wondering

stray orbit
#

its meant to set stuff in the localisation files

#

so in the screenshot i sent the default joker should be called test test test test rather than Joker

#

but idk how to make it work

tepid sky
#

Ooh cool

glossy stone
#

oh boy i can't wait to make joker a-
god deciding to strike me with "the sudden urge to play zenless zone zero":

crisp coral
#

-# hey pass me your id

glossy stone
#

I JUST STARTED PLAYINGGGGGG

nocturne garnet
#

do some of yall ever start modding and are no longer able to play balatro again

#

all i do now is make modded things 😭

#

i havent tried to win an actual run in so long

glossy stone
#

i mean i started modding immediately after c++ so yeah

glossy stone
#

well at least i know what my next project will be (retexturing burnt joker because yea)

tepid sky
crisp coral
#

-# i need to pull for her shit

glossy stone
#

MAY RNG BLESS US

stray orbit
tepid crow
stray orbit
#

i'd rather do it like this so it can be changed in game

primal robin
#

Use loc_vars then

hybrid iris
#

hi! im trying to make a planet card that upgrades the most played hand, but, im not entirely sure on how to achieve that 😭

#

i, remember seeing there was a mod that had that kind of functionality but i cant seem to find it anymore unfortunately

#

does anyone know of a way to do that?

#

the,, closest thing i can think of is manually having a use code for it but otherwise idk jsdhsdjh

tepid crow
#

Cryptid's white hole does stuff with the most played poker hand

hybrid iris
#

ooh interesting

#

okok ill take a look at that, tyy

shell timber
#

oh yeah that was the autumn circus iirc

#

which yeah

crisp elbow
#

Yeah I think there's also Station from Jen's

frosty dock
stray orbit
#

oh my goodness

#

im sure i couldnt get it to work in times before this tho

#

ill try it

#

oh my gosh thank you so much

#

lmao

frosty dock
#

completely my fault for using inconsistent naming

stray orbit
#

hahaha no worries

frosty dock
#

tbf that's been off my mind since the standard has become using localization files

stray orbit
#

this function works best for what im making

#

since im trying to make a mod that lets you rename jokers and collection items from in game and it would be nice to have them change immediately

frosty dock
#

it's interchangeable, the files are also just loaded and executed as a lua function. I guess it's slightly more convenient in that case

#

the main advantage of using files is easily being able to support multiple languages

#

which you might not care too much about

stray orbit
#

if i could get my mod to write to the default.lua file that would be perfect

#

is there a nice steamodded way to do that or should i try actual file io stuff

#

cuz i would love to have it support all languages

frosty dock
#

sounds like it'd require actual file io, though steamodded does come with a library for that, removing love2d's restrictions. there's also a util method to serialize tables into valid lua format and a json library, whichever one you'd want to use for your language file (both lua and json files are accepted)

stray orbit
#

ill look into it

#

where would i read up on the steamodded io library

frosty dock
#

it's not a steamodded library per say, it's called nativefs

stray orbit
#

ty ty

primal robin
#

I found easy reproducible silent game crash. Maybe it will help for someone to make try-catcher better, idk

SilentCrashClass = setmetatable(Object:extend(), {
    __call = function(table, ...)
        local __index_ref = table.__index or rawget
        table.__index = function(t, index)
            return __index_ref(table, index)
        end
        local obj = setmetatable({}, table)
        obj:init(...)
        return obj
    end,
})

local test = SilentCrashClass()
print(tostring(test.something))
hard mica
#

I'm actually curious on how I could start making mods for balatro Hlo

limpid wing
hybrid iris
#

hi! im having this weird problem with the SMODS.create_card function where for some reason, the cards generate in the right area but arent actually added as a consumeable

#

sdjfhsjdfh i, cant tell what the specific issue is for this one

#

nvm, fixed it!

#

forgot to use emplace on the card

surreal marsh
hybrid iris
#

tyyy

#

ksdfjhdskfjh okay uh

#

im trying to make a joker that turns all consumables being held into their "rotten" form

#

but i, cant seem to get this code to fully work-

#

because im trying to make an exception for when it's already the rotten form

#

but it doesnt, seem to work?

#

sdfkjhsdkfjh

#

like it replaces the card even if it's the same key

brisk rose
#

Does replacing it with itself change anything?

hybrid iris
#

wdym?

brisk rose
#

I mean... it sounds kinda cosmetic if it just replaced a rotten consumable with itself

#

Unless I'm missing smth

#

It being the bug

edgy reef
#

Couldn't you use set_ability to change the card without destroying it?

hybrid iris
#

oh huh

#

i did not think about that

hybrid iris
#

though i suppose that would be a very minor case

#

dsfjhsdfkjh

hybrid iris
#

if, i may ask

#

ksdfjhsdfkjh

edgy reef
#

You call set_ability passing the center of the rotten consumable on the card you want replaced

#

Something like ```lua
v:set_ability(G.P_CENTERS["c_tma_the_rot"])

hybrid iris
#

ahhh

#

sjdhsdjhsd

#

okok, cool!

#

thank you, so much

#

ill see if that works

#

,,sdkfjh

#

apparently not-

#

,,,hm

edgy reef
#

Maybe the key to the rotten consumable is wrong?

hybrid iris
#

well, it worked before

#

the key in the declaration is like

#

"tma_the_rot" so i assume it should be "c_tma_the_rot"??? sdjfhksdkjfh

crisp elbow
#

Isn't it your mod prefix?

hybrid iris
#

i,, dont believe i have one-

crisp elbow
#

your mod would automatically make one

hybrid iris
#

oh-

crisp elbow
#

I think it would be insc, it automatically makes one with the first 4 letters of your mod id

hybrid iris
#

,,,really?
it worked before at least-

#

or i mean, it didnt matter before

#

but anyways figured it out, it seems like there's a weird difference between "" and '' that i still dont quite get

#

jsdfkhsdfkjh

crisp elbow
#

idk if smods specifically has one

#

but usually I think ' ' is for variables and " " is for strings?

edgy reef
#

There's no difference

#

They're both handled as string

hybrid iris
#

,,,oh huh

#

well weirdly enough just changing that seemed to fix it fsr

#

Yeah wait what

#

this just, fixed, the whole replacing issue

#

i think

#

,,,okay!! yeah!! it worked!

tepid crow
hybrid iris
#

my only problem with this solution is that it,, doesnt have any animation to it 😭

tepid crow
#

you could have the card juice up?

hybrid iris
#

,,,ooh, maybe

tepid crow
#

is your dot key broken?

hybrid iris
#

oh no this is just how i type

#

i like the look of commas more

tepid crow
#

bet

hybrid iris
#

sorry to ask another question

#

is there a way to apply a sticker to a joker card?

#

and like, remove them?

edgy reef
#

SMODS.Stickers[<sticker key>]:apply(card, true) and SMODS.Stickers[<sticker key>]:apply(card) respectively

hybrid iris
#

oooh

#

gotcha, thank you!!

hybrid iris
#

i cant seem to understand this enhancement API

#

is it supposed to be treated like a standard joker?

hybrid iris
#

where are the calculations for enhancements done?

#

im trying to reference the base code but i cant find anything dsjfhksdfjh

brisk rose
hybrid iris
#

im looking and it doesnt really teach me anything 😭

#

also im so confused what's the difference between config and ability

#

because like
they seem, exactly the same in essence???

#

and other mods im looking at has abilities declared in config i think??

#

but like
the game doesnt seem to like it when i do that

brisk rose
#

Are you making sure ability is a table?

#

Idk of that'll make it work, but I think that's what the error means

hybrid iris
#

I have no clue

#

most mods im looking at dont create an ability table but use it all the same

brisk rose
hybrid iris
#

😭 yes i looked at the files already

#

sdfkjhsdfkjhd sorry

brisk rose
#

It's okay, obviously it isn't working right for you

hybrid iris
#

its,, just that like-
"ability" just seems to be lost on me for some reason

hybrid iris
#

earlier i was trying to do an enhancement similar to ortalab's sand

#

but like, i, dont see any of the code that reduces the card's xmult

brisk rose
#

First thing ifmd day that almost certainly went fix your problem, but will remove a variable is to downgrade to the lovely beta 6

hybrid iris
#

huh-

#

wdym?

#

did the new beta like,
break bunch of stuff?

brisk rose
#

Not all that much but enough where it isn't being used by pretty much anybody who plays with a lot of mods

hybrid iris
#

ahhh

#

,,,fair

brisk rose
#

I think the lovely patch might just be because of the fancy art effect

wintry solar
#

It was a choice for timing, you can absolutely change the values in a normal calculate function

edgy reef
#

Enhancement improvements were meant to be timed with calculation improved but then ejwu evaporated and nobody really knows how the better calc pr works now.

wintry solar
#

I am pretty sure though that enhancement calculation works to a perfectly acceptable level, and Math fixed edition calculations too

#

In terms of the config vs ability, when the centers are created, it copies the config table into the ability table, with some caveats in that it’ll only accept certain keywords for value names, hence the use of an extra table which is copied in it’s entirety

glossy stone
#

after OS comes out i want to make an inverse tsunami
a billion burnt jokers

teal estuary
#

quick question, what would be a good mod to learn how to make editions? deciding to dip my toes into something non-joker

glossy stone
wintry solar
teal estuary
#

ty ty

#

i just realised im an idiot, i meant enhancement (although, i presume those mods also have those)

wintry solar
#

ortalab has a load of those, yeah

teal estuary
#

yipee

frosty dock
languid mirage
#

nice

frosty dock
#

now for auto updating

#

there should probably be options for both git and no git, right?

teal estuary
#

do enhancements just not have loc_txt? or am i stupid?

wintry solar
#

all the ortalab loc_txt's are in the localization file

teal estuary
#

ooooh

#

makes sense, makes sense

teal estuary
#

is there a way to give cards enchancements using the debug tool, or do i gotta go find these through normal gameplay?

frosty dock
#

with DebugPlus, by pressing W

teal estuary
#

OOOOH

#

caps, but ty

frigid flame
#

you can also like

#

go to collection

#

find the tarot that makes the card that enhancement

#

press 3 with your mouse over it

wintry swallow
#

Imagine a mobile port of that

tepid sky
wintry swallow
#

But just imagine though

#

Imagine balatro had mod support for mobile

tepid sky
#

But we are only allowed to discuss modded for pc

#

Its the rules

wintry swallow
#

But im just saying dude, imagine there were mods for the mobile port, thats what i mean

regal wolf
#

Yeah, but like MiniRebel said don’t talk about mobile modding

frosty dock
#

i could save commit hashes somewhere ig, but how do i get them

regal wolf
#

What are you trying to do?

nocturne garnet
regal wolf
#

There’s a template in the game texture files for all the different card types. You could try using that to unify the art style

brisk rose
frosty dock
muted timber
#

guys why is chips nil here

#

i changed the plasma part to
if (self.name == 'Plasma Deck' or string.match(self.name, 'Test Deck') and args.context == 'final_scoring_step') then

#

that wouldnt break anything right

#

hmm only crashes in plasma deck

wintry solar
#

you need another bracket after your check for your deck

nocturne garnet
#

does anyone know where SMODS.Edition.super.register is defined?

#

i cant find it anywhere

wintry solar
#

that'll be the center register

nocturne garnet
#

trying to make certain things appear in the Spectrals collection instead

#

i see

muted timber
teal estuary
#

question, do enhancements use the same sort of structure as a joker for its calculate() function?

#

like “if context.X and not context.Y then”, “[something else]”, “[actual function]”

#

cuz im currently lost as fuck with the code i need to add to this to do what i want it do 😭

nocturne garnet
teal estuary
#

sick, cool

wintry solar
#

obviously they will only have the ones that are called on cards rather than jokers though

teal estuary
#

ofc ofc

#

wanna make sure because im still clueless as fuck, if i want to check the played cards, it'd be something like:

if context.indivdual and context.cardarea == G.play then 
return{
  --stuff here
}
end
#

?

wintry solar
#

if you spell individual correct, sure

teal estuary
#

😭

#

i have spelt it correctly in the code, yes

#

ty though

#

is this looking all good then?

wintry solar
#

oh right

#

there's a difference in how you have to return

teal estuary
#

oh?

#

code doesnt do anything anyway lmaooo

wintry solar
#

basically, it doesn't return to anywhere the way it's implemented, so you have to either use SMODS.eval_this or edit the effect table manually

#

you cna do effect.mult = card.ability.extra.repetitions

teal estuary
#

ohhh okay, gotcha

#

i just realised that it shouldnt be mult and it should be repetitions, whoops

#

but if i do effect.repetitions = , would that all just "work" or would i need to replace it with the .eval_this as well?

wintry solar
#

that would probably work, yeah

#

I'm not 100% on how repetitions interact with enhancements

teal estuary
#

thats fair enough

#

there we are, now its doing something

#

(the entire crash log, currently looking at ortalab code though)

wintry solar
#

can you send your enhancement code

teal estuary
#

sure

wintry solar
#

eval this doesn't handle repetitions