#💻・modding-dev
1 messages · Page 261 of 1
like tbh the only thing i can think of that can be moved out is the self.sprite = sprite() line
state machines are fun 🙃
but atm moving that to the sticker itself crashes because (i assume here) that it tries to get the custom atlas before it exists
typically stickers have a single shared sprite
would i add it like this?
card.ability.extra instead of self.ability.extra
where should i define my shared sprite though
And change G.hand.highlighted[1] to the thing you want to copy.
smods does this for you https://github.com/Steamodded/smods/blob/4240e45438e1967041f4262f4b0265b67aaf2557/src/game_object.lua#L567
why does it limit it to :sub(7) 💀
no problem
that one is stake stickers
which don't include the stake_ prefix
this is the right one
Hey I'm just getting started with modding this game and I was wondering if there are any resources that have the SMODS documentation as well as what needs to be defined to have a joker work and not crash
ur right but i forgot to change it to card
what's up with this function lmao
so i got it working and i would have thought it was card.sticker_sprite
because i thought i wrote that 💀
anyways it works
and that fixed all the lag
60 fps
this is a real line of code in the real game

does anyone know if you can #include other shaders in the shaders for balatro?
err... what?
you just put card.ability.extra, which is a table
oop
but
you gotta read the error 😭
that's still not correct (in this specific instance. you should be using card.ability.extra instead of self... in general)
what's your config table look like?
joker that clones scoring cards for the blind
I see
i'm surprised there's not an SMODS.copy_card (unless there is and it's undocumented, which would be unsurprising)
yeah
frankly I don't think it's ever been requested
well now is a good time to!
i would like SMODS.copy_card
that's also fair
figured this out (maybe)
gonna have to patch smods 
Need a SMODS.just_take_the_ideas_from_my_head_and_put_them_into_the_code
you just have to pay john smods $2000000 USD
am i crazy or do these look squashed
they do 😭
How about $2 and half of a milkshake
ok why are my cards squashed
what size is the atlas
Do the sprite size match the atlas?
sprites and atlas are both 63x93
well those aren't the standard card dimensions 😭
use jimbo for reference
ah
it's 71x95
am i going to have to redo like. 9 cards
probably
funsies
if i just make it 2 pixels taller and leave the width the same will that be fine?
or does width have to be specific too
it's specifically 71x95
well, it could also be 69x93
but that's without the extra transparent space
ok so 71x95, with one pixel of transparent space around the edge?
yeah
Not exactly
The size is 71x95, but the sprite inside is smaller than a joker card
huh 😭
one pixel transparency at the top and bottom, 4 on the left and right
i was gonna say, this feels wayy too wide for a consumable
no, everything fits within the 71x95 space
the actual size of the image in that space is different
ok so the only thing i actually have to resize is the canvas? resizing the canvas to 71x95 does leave the 1px vertical and 4px horizontal borders
ex. vouchers have a lot of whitespace on the sides
that should be fine
oh thank god
you can also look at the #1224362333208444989 templates as a reference
so for the px and py arguments in the atlas do i put 71x95 or do i put the size of the actual sprite within the 71x95 canvas
you put the 71x95
did you also make a 2x version
think so yea
you'll have to resize those too, if you haven't already (but I assume you did)
yep
big
much better
Hi everyone, I've gotten into challenge making, is it possible to make one behave like a regular stake (ex. Black Stake w/ faster scaling and eternal jokers)?
I'm not sure if that's in base smods
I know aiko did it
@tall wharf mentioning for whenever you show up
alr im pulling my hair out. how can i get this sticker draw function to draw at the same position on my card regardless of size
I solved the transition disabling the UI by simply setting the dummy blind in a different location
example of the behaviour when in hand vs when in deck view
Is there a provided way to visibly space lines of text in a joker description?
I'm having this issue where we have cards that have different "clauses", but I don't really like the way that it looks where the next clause starts with a capital but there's no grammatical separation otherwise
This one is less egregious because the top clause's justification inherently doesn't match the bottom one
This is the one I'm most mixed on
I've had issues with feeding empty lines into text boxes before, so let me try
even if not empty try putting a space or something
alright so i think if u imagine a grid where 0, 0 is the top left of the card, and 1,1 is the bottom right (in this case i know that 0,0 is actually the top left no matter what your looking at, im just using 1,1 as an example tho).
That works fine in the hand, but I think whats happening is that in the deck view the units of this imaginary grid dont scale down to match the smaller card size. So the tag is now displaying way lower than where it should be
so now uh idk how to fix that
Currently sitting here praying that G.GAME.discard currently holds the cards that have either been played or discarded over the course of a round
anybody know if that's what that cardarea does?
like i assume i can mathematically figure out what 1,1 should be in this new grid
but im a dumb idiot whos forgotten linear algebra
i do know that the scale_mag variable of the card changes between hand and deck view
but weirdly, it increases in deck view (e.g higher values make it render smaller i guess)
Its just G.discard
some joker ideas that came to me
It's an offscreen cardarea
awesome
because I want to shuffle them back into the deck
I think I know how to do this now
easier to see in negitive
ever glass card give +100 chips
Oh I did that too
i made this in like a minute lol
lol
I assume I can add them to the deck cardarea, pseudoshuffle, and empty the discard cards
Oh I misread deck as hand whoops
"draw from your graveyard"
That sounds fine tho
I do {s:0.3}
note the
otherwise the line gets automatically removed
That works!
the {s:0.3} makes the line smaller
oh thats sick i might write that a lot
also if you want I now have tech to extend the description upon pressing a key
How so?
It can be on the card itself of course
this example just uses an infobox
Why does this give me the error engine/sprite.lua:11: attempt to index 'atlas' (a nil value)?
wait my 2x spritesheet isnt resized
i thought i did that
I think animated sprites don't work with Cards in vanilla
Something is missing
No one bothered to figure out how in a scalable way
Autumn had made a working POC that crashed when "anything touched the card" IIRC
i mean this one just crashes because it doesn't know to look for an animation atlas
MathIsFun reimplemented animated sprites manually for Cryptid and later Aura
so if i want an animated consumable im going to suffer
On the bright side, if you make it work you can PR to SMODS for all of us
i hate patching i hate patching i hate patching i hate patching i hate patching i h
how would i give every played card the gold edition?
i should see if i can't make this kind of thing work in steamodded relatively painlessly
by that i mean I'll give up if it's much work

My suspicion is that the Animated Sprite class is missing some method or property that the Sprite class has
seriously though

yeah it was literally this simple
G.deck:emplace(v)
end
pseudoshuffle(G.deck.cards, pseudoseed('beast_shuffle'))
G.discard.cards = {}```
I have to figure out how to rephrase this to be one line shorter, and it might just involve making the description wider. I try not to make descriptions too wide unless they absolutely need to be, but unfortunately the collection is being annoying
Maybe I could just get away with putting her on the bottom row?
+69 chips if played hand contains multiple cards of the same rank?
oh but no fiveo f a kind
Not correct, because it's not an "includes" yeah, it's those specific hands
slight issue lmao the cards are permanently debuffed
Yes; also aure rewrote the positioning code IIRC
so you could try to tweak that
check out Spinagogue Champion from Cosmos but also Eremel mentioned porting a similar patch from Ortalab to SMODS to help do this
I'll try the simpler solutions first, I've got two spots on the bottom row and I think I can justify putting her in the leftmost one
Good
this seems workable
small blind card
seems i just have to make the API support it
On scored, immediately be sent to do a small blind. it will not affect your current ante
I replaced the card's children.front with an animated sprite
ooo
(and called set_role on it so it actually draws on the card)
i've made a tag that is supposed to create a card in shop under certain conditions but for some reason it's considered as triggered when the shop cards are created
local encore = {
type = 'Switch',
order = 24,
key = "encore",
pos = coordinate(28, 8),
config = { type = "store_joker_create" },
min_ante = 1,
apply = function(self, tag, context)
print(context.type)
if context.type == "store_joker_create" and G.GAME.encore_card then -- why is triggered on true????? it didn't even triggered????????
local card = SMODS.create_card({
set = G.GAME.encore_card.set,
area = context.area,
key = G.GAME.encore_card.key,
enhancement = G.GAME.encore_card.enhancement,
seal = G.GAME.encore_card.seal,
edition = G.GAME.encore_card.edition,
stickers = G.GAME.encore_card.stickers
})
create_shop_card_ui(card, G.GAME.encore_card.set, context.area)
card.states.visible = false
G.GAME.encore_card = nil
tag:yep('+', G.C.BLUE,function()
card:start_materialize()
return true
end)
tag.triggered = true
return card
end
end
}
does this mean we may be getting animated card api soon?
Try using a Tarot on it
Gains Chips if played hand is Pair, Three of a Kind, Four of a Kind or for each Joker of a certain type and move the amount mention to the tooltips on the side? Or Gains Chips depending on played hand or Jokers being of a certain type and mention the specific hands on the tooltips.
does it duplicate nicely
not yet, but that's because i haven't actually made any code changes yet
ah gotcha gotcha
would making a CLI/TUI for balatro be interesting? I want a project that I can do, I would probably try writing the CLI part in rust, but I think I would need a way to send the commands to the game (also never coded lua before so would need help with that)
well itd surely let me play balatro at work so id appreciate it
is there a way to run the game without rendering it in the window? it would probably be a fairly important part of making it work well (I think)
rust 
how exactly does idol logic exclude stone cards
no way its john lovely
im also interested in making a "remote" mod but for different reasons
what are you wanting to do?
when it's in playing cards deck - yes
keeping it a secret rn so my idea isnt sniped
just showing it transparent
is there any way i could make the idol logic not consider face cards? eg. it would only choose 2-10 and aces
hi headed branch
hello
i also have no clue where idol logic is calculated either and how it excludes stone cards :v
check vanilla code
.>
oh where is that?
common_events.lua
aaah ty
ctrl f across all files
oh how do you do that
i have a question. does anyone here know how to modify a baltro game save? i got the plant on a run i was just dicking around in and frankly i would rather just figure out how to add a luchador to my joker slots or like figure out a way to change the boss blind instead of playing it all over again. if not ill cut my losses lol
I can send some code
Gimme a sec
nonono its fine i have the reference i need i think
ctrl shift f
Oh alright
so i looked for idol, i saw that variable G.GAME.current_round.idol_card.rank
then i did ctrl shift f again and searched for G.GAME.current_round.idol_card.rank
its ctrl shift f in vscode at least
i just open the folder in vscode
dont tell me you just go open file explorer and check each file
not everything
uhhh
yeah i have no idea how to do this
debugplus mod?
let me try that
exciting
I'm not exactly sure how to handle front sprites with this tbh, the code with deck skins is a bit of a mess
carnaval
fr
So I'm trying to modify Campfire to ditch its reset function on boss blind. Any reason it keeps resetting despite the function not existing here? I've even tried adding context.end_of_round to do nothing and it will still reset. My novice coding skills are likely to blame. Any help is appreciated.
any objections to just not including this for now?
add if context.end_of_round and context.main_eval then return {} end
Yeah, just mark it as something to add later in the feature requests or an issue on the repo so it can be remembered.
you just need to return something in the context, else it will fall back into vanilla functionality
for some reason, this did not un-debuff my cards 🤔
self.disabled = true
for k, v in ipairs(G.playing_cards) do
v:set_debuff(false)
end
for k, v in ipairs(G.jokers.cards) do
v:set_debuff(false)
end
end,```
// -- the filter function, defined somewhere else in your code
// -- because it's not in lua by default
function filter(tbl, func)
local newtable = {}
for i = 1, #tbl do
if func(tbl[i]) then
newtable[#newtable+1] = tbl[i]
end
end
return newtable
end
// -- in your calculate function
if context.end_of_round and not context.game_over then
local deck_cards = filter(G.deck.cards, function (_card)
return not SMODS.has_no_rank(_card) // check for no-rank cards (i.e. stone)
end)
deck_cards = filter(deck_cards, function (_card)
return not _card:is_face() // check for non_face cards
end)
local card = pseudorandom_element(deck_cards, pseudoseed("idol"))
-- store the card somewhere here
end
my insane concept
I'm not too strong on lua 😭
That's what I figured and I had tried unsuccessfully, but that did the trick. Thank you!
works with backs too but it crashes galdur
https://github.com/Steamodded/smods/pull/583 made it into a pr for now
Fixing animated sprites!?
hihi, another question — is there a way of getting a Joker to send a message during context.destroy_card, while a bunch of cards are being destroyed?
aha wait lemme try something with config
yep, got it :D
ooh i joker idea
Bit crushed
all sounds releted to the joker are bit crushed
copys the one left to it left
and is animated so it looks like it changing bits every so often
is there a way to get a list of all active Planet cards?
Excluding the sound thing: Bitcrushed Joker (Uncommon) - Copies the ability of $RAND Joker, but with half the chip/mult. Joker copied changes each round
i'd like my Joker to only select Planet X if Five of a Kind has been played, for example
I think you can just collect the hands that have been played
Or rather iterate over all Planets, and if they have an associated hand see if it has been played
I’ve done something similar for Moody
in my mod
not what i mean
i mean like, the page in Run Info listing all the hand levels — i need my Joker to get a list of their corresponding planets
so that's Pluto - Neptune at the start of a run, and Eris / Planet X / Ceres if their hands have been unlocked
and the reason i'm not hardcoding them is to allow for modded planets to show up
(here's the ability)
Creates a copy of Pluto at the end of the round, Planet card changes every discard (Must have room)
sorry i've been using this channel so much, but i'm horrible at reading other people's code, and that goes for Balatro's source code 😭
G.P_CENTERS has a list of all the planet cards denoted by the object having set = "Planet". They each have a config with a hand_type and an optional softlock key
If the softlock is present the Planet card won't be available until that hand type has been played, and if it's not present it is available. To check if a hand type has been played you can check G.GAME.hands["HAND TYPE"].played > 0
ah that's very useful! thanks :D
oh one more thing, is the ability too weak, in your opinions?
just wondering
Unsure :P
Seems fine
goodgood ^^
And I’m saying to do it the other way around
Iterate over Planets and check if their hand has been played
ya i've done that already -w-
I’m just clarifying that’s what I had suggested when you said “not what I mean”
Random Planets are usually weak. I’m trying to encourage them in my own mod. It depends on yours
ah i see. ya i read that as you misunderstanding the ability ^^

ah, but you're encouraged to dig for the planets you want by using discards
mhmhm
i suppose everything in Balatro is sorta random though ^^ /nsrs
will give it a test run, anywho
is there a mod currently that has implementation of SMODS.DrawStep? Im trying to learn how to use that api
seeing code of it in use helps a lot
how do i make a consumable apply a given edition to a random joker?
Look up Hex/Ectoplasm's code
Is there a way to extract balatro's exe/macos equivalent using archiver software other than 7zip? Was hoping to create my own custom texture packs but ran into a roadblock because I'm using a mac, not windows. Apologies if someone's already asked how
What do people tend to use Steamodded for? Like, do most use its APIs for game logic, or is it merely used for its debugging/mod-handling capabilities, or other things? Sorry if the question doesn't make sense, still learning
its api stuff
yall is there any scenario where this will be an invalid index (other than 0 cards in hand which is accounted for)
the steammodded wiki should explain how to do it on mac iirc
i dont exactly remember how i did it, but u can do it on mac (im on mac) and i remember seeing it on the getting started page i think
this code crashes: attempted to index local 'card' [a nil value], can someone tell me what im doing wrong plz?
calculate = function(self, card, context) if context.cardarea == G.play and not context.repetition then for i = 1, #context.scoring_hand do if SMODS.has_enhancement(v, "m_stone") then return { remove = true } end end end end
I'll look there—thanks so much!
how would i check if a scoring hand contains a card with a certain enhancement? (and then change said enhancement)
sorry one more question — how do i get the name of a Planet in v.config?
and its planet id? (eg. c_pluto)
oh wow negative Power Cards look awesome
woah those are cool
v is an undefined value, you need to use
for _, v in ipairs(context.scoring_hand)
--code
end
come to the dark side. don't listen to the 'Balatro Black' truthers. use #000000. youll get cool negativessss
ohhh thanks :)
does anyone know how to check if a card is debuffed?
how come its indexing a nil value with this table?
if card.debuff
already with you lmao (i'll prob update it later tho)
thanks 🙂
oh damn this looks sick
ty!
(bumpbump?)
how are you guys so good at these background textures
looks like a 3d distorted voronoi tbh
says it goes wrong at this line which i KNOW works
goregous!
Hey doods, does SMODs have an easy way to add my own take on a stone card?
did you check how vanilla does stone cards
It's like a weird custom ability. Ohhhh, it is basically an enhancement
Can you make sure table exists and isn't nil? are you also sure that card_list has 7 items in it
whoa
is there not a set_sprites() option for Blinds?
Actually could you give me a hint, lol
just check vanilla code?
this is how card_list is created, it creates a list of every card that isn't k, q, j 10, or stone, then uses that list to create card_list (using 5 of hearts as a fallback if there are no valid cards remaining in the list)
i almost accidentally deleted my entire mod
Use GitHub at least
i deleted the folder through mod manager by hitting verify files. Thank god my IDE was open and held the changes
thats why we have github
ok, it is an enhancement
I was planning to get my first thing done properly then push to github
terrible idea
its in the enhancements tab of the collection. vampire can remove it. idk what you expected
It somehow seemed so special, and minerally to me. I guess I am not sure what I expected either lol
like the blood sweat and tears i put in to make my sticker work was saved by the IDE. So was atlas.lua, main.lua, and metadata.json. sprites and some util functions got wiped but I remade those fast (had backups of sprites)
this is a good reminder that I need to zip my mod and email it to myself again
tbf i only ever push to github when i've entirely completed a feature
so im not the smartest with it either
i definitely don't commit often enough
exactly
like my localization file is dead
gone
Yeah, what if someone looks at my old code, I don't know who has that much time but I don't want to share it until I am proud
thank god i only added one thing so far
i can just go look at the screenie and copy it again
Oh this is neat, I didn't know this existed
h_x_chips, -- Chips multiplier when held in hand during scoring, nil (not defined), 0 or 1 is treated as 1.
i couldn't possibly let someone stumblr upon the github and play an unfinished, possibly broken version of the mod
so instead i risk losing everything
clearly
i wrote that comment 🙂
hi everyone, i need some help for this piece of code:
if not context.blueprint then
local repeater = nil
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
repeater = i
break
end
end
if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then
if context.other_card == G.jokers.cards[repeater-1] then
return {
message = localize("k_again_ex"),
repetitions = card.ability.extra.repetition,
card = card,
}
else
return nil, true
end
end
end
end,```
i want the joker on the left and right of this one to retrigger, how can I make it work?
If i want to give double the sell value of a joker when its sold, would i have to store it as a seperate value?
currently i think its deleting the data before it can give the money
joker should still be inspectable when context.selling_card is triggered (context.card)
alright we are fully back in business all files have been recovered/remade
ayy
Never making that mistake again
Hey guys, I am looking for a context window I could use to see if a hand was played but my card was held in hand
i've currently got this in but its giving +$0 even despite the card having a sell value
working on the same joker as yesterday, i'm getting attept to index field 'card' (a nil value) error on this code
SMODS.Joker {
key = 'TOGO', --joker key
loc_txt = { -- local text
name = 'To Go menu',
text = {
"Food Jokes each give {C:mult}+5{} Mult",
"{C:inactive}(Ramen, Popcorn, Egg,",
"{C:inactive}Turtle Bean, Diet Cola, Seltzer,",
"{C:inactive}Gros Michel, Cavandish and Ice Cream",
"{C:inactive}are food jokers)",
}
},
config = { extra = {mult = 5}},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
rarity = 2, --rarity: 1 = Common, 2 = Uncommon, 3 = Rare, 4 = Legendary
atlas = 'MMM_Jokers', --atlas' key
pos = { x = 0, y = 0 },
cost = 5,
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
blueprint_compat = true, --can it be blueprinted/brainstormed/other
eternal_compat = true, --can it be eternal
perishable_compat = true, --can it be perishable
pos = {x = 0, y = 0}, --position in atlas, starts at 0, scales by the atlas' card size (px and py): {x = 1, y = 0} would mean the sprite is 71 pixels to the right
calculate = function(self, card, context)
if context.other_joker and context.card.ability.name == "Sly Joker" then
if card ~= context.other_joker then
G.E_MANAGER:add_event(Event({
func = function()
context.other_joker:juice_up(0.5, 0.5)
return true
end
}))
return {
message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult }}),
mult = card.ability.extra.mult
}
end
end
end
}```
is this a joker's calculate()? don't use self, use card. i'm surprised this isn't crashing.
I've tried looking at how the kidnap card from the cryptid mod works and even copied part of it but it doesn't work
seeing at it's under context.selling_self it probably is
ive used self for all of my jokers' calculates and it works 💀
calculate = function(self, card, context)
if context.selling_self then
return {
dollars = card.ability.extra_value
}
end
end
self is the center
not the card
the values in self are basically the template for all jokers that appear with that center for the entire runtime of the game, not even reset between runs
i also don't know if you can return dollars in selling_self 🤔
Wtf is a center anyway, whats the name supposed to mean
why does this crash? 745:'{' expected [to close '}' at line 744] near '='
if context.cardarea == G.play and not context.repetition then
for _, v in ipairs(context.scoring_hand) do
if SMODS.has_enhancement(v, "m_stone") then
return {
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
remove = true
}
end
end
end
if context.joker_main then
return {
chips = card.ability.extra.chips
}
end
end
end```
looks like effects on selling_self eval are triggered so it should be giving correct amounts of dollars
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain no comma at end of line
but wait
also
wtf
is that line in a table
put it outside the return i think?
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain why is this in your table
so its basically messing with a global value that all my jokers are tapping into?
i initially put it outside, but the code didn't work so i tried putting inside to test if it did somth LMAO
if SMODS.has_enhancement(v, "m_stone") then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
remove = true
}
end```
okay ty :)
something at some point went very wrong in all your code
self.ability is not supposed to exist
self.ability.extra_value is supposed to crash
i was messing around w it a lot yeah, i been coding this mod for about 5 hours and i think im starting to lose sanity
not yours
How would I unenhance a card?
im pretty sure literally the last thing left to do before i can release the first version of my mod is add booster packs
card:set_ability(G.P_CENTERS.c_base)
thanks ^^
(vampire joker code for reference)
printing #G.P_CENTERS is yielding 0, is there a reason why?
i looked at another mod to get an idea of how things worked, this is a whole joker
is it because it's a table?
it's a table with no numeric keys, so it has no length
is there a version of this that applies to the deck instead of just a card?
#x is just the highest consecutive numeric index starting to 1 that is available in the table
ah icicic
so i need to use ipairs then
gotcha
thanks :D
i'm starting to pick this whole Lua thing up ^^
for _, card in ipairs(G.playing_cards) do
card:set_ability(G.P_CENTERS.c_base)
end```
what is loc_def i don't think this is a thing? is this legacy? aure?
why does calculate(self, context) even work
what is your steamodded version 🤨
hey uhhh quick question how do you check the name of a diffrent joker?
So the docs page for SMODS.Sticker is not super obvious to me, is there anything that should actually be minded in terms of what stickers can and cannot overlap each other (assuming modded content from other creators). With vanilla, I absolutely know that Perishable and Eternal cannot coexist, but Rental can coexist with either, but does anything specify that in SMODS? The vanilla game seems to allow you to put both Perishable and Eternal on a joker via debug, but they visually squash each other and you're not supposed to do that
i wonder if we just happened upon a lua oddity
i'll just stick to what i know you should be doing
i've tried this context.card.ability.name == "Sly Joker" like how it was done in the cryptid mod but it crashes the game, then i tried this context.other_joker.config.center.ability == "Sly Joker" but it doesn't do anything
hmm, nothing was logged with this code, so i'm guessing G.P_CENTERS is nil or empty:
for k, v in ipairs(G.P_CENTERS) do
print(v)
end```
it's card.config.center.name btw
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card:get_id() == 3 then
if pseudorandom('stability') < G.GAME.probabilities.normal / card.ability.extra.odds then
return {
x_mult = card.ability.extra.x_mult,
card = card,
}
end
end
end,
loc_vars = function(self, info_queue, card)
return {vars = {
card.ability.extra.x_mult,
card.ability.extra.odds,
G.GAME and G.GAME.probabilities.normal or 1,
}}
end
ok, ill give it a shot
card being whatever your card reference is. Could be context.card or context.other_card depending on the situation
thanks
tysm! i'll try understand this and apply it to the rest of my stuff
well the joker is still not working but idk if that's the issue or something else
i'd assume whatever mod you looked at for examples is horribly outdated btw
Nothing built-in for now. There were some take about reworking how Sticker sprites render but nothing implemented
went to go test my joker out. tried cycling through editions on a playing card with debug plus and my game crashed?
stickers are implemented as a transparent overlay sprite, the position of the sticker badge is fixed (it's literally a 71x95 atlas as usual)
can someone explain to me how the pair() function works when looking through the deck (G.playing_cards)
idont understand the function at all
thunk placed eternal and perishable in the same position in the literal atlas assuming correctly that the two can't happen at the same time in vanilla
am i missing something? why is this empty / nil?
pairs() is an iterator function in lua that returns key/value pairs in a given table
again, ipairs() like # works with numeric indices
ipairs is a-- yeah
for context this is what the code looks like ```calculate = function(self, card, context)
if context.other_joker then
if card ~= context.other_joker and card.config.center.name == "Sly Joker" then
G.E_MANAGER:add_event(Event({
func = function()
context.other_joker:juice_up(0.5, 0.5)
return true
end
}))
return {
message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult }}),
mult = card.ability.extra.mult
}
end
end
end
}```
not sure what part is messing it up
if #table == 0 then ipairs() will not iterate any element
iterate with pairs() if you want to go through every key
awesome, thanks :D
It's used in a for loop
-- do something
-- k is the key
-- v is the value
end```
Similarly, `ipairs` is for integer indexed array tables, so you use it when you expect array tables
```for i, v in ipairs(table) do
-- i is the index (1, 2, 3, 4...)
-- v is the value
end```
integer indexed is incomplete
Keep in mind if the array table is missing an index your behaviour won’t be as intended
riiight
I SEE IT OK SO
i made an Ace negative, which caused the deck to draw a card because now i have room for an extra. which crashes my game. is that a game thing or a me thing?
is anything wrong with this then
it will only go from 1 through N where N is the last consecutive index in your array:
local _t = {[1] = 'one', [2] = 'two', [4] = 'four'}
for i, v in ipairs(_t) do
print(''.. i .. ' = ' .. v)
-- 1 = one
-- 2 = two
end
yo guys can someone tell me all the quality of life mods for making a mod and all the useful stuff like that? cuz i have debug plus and thats about it and idk how to do things like auto unlock cards and give myself certain cards and stuff
i need to check my logic, but woooooo!!
all you need is debugplus
good explaination, this is what I needed because I was missing my C# foreach (var x in collection) type loops
hold tab to see what DebugPlus can do for you
word
I truly wonder what compelled me into spending two hours to learn how cryptid does extra soul layers to make this.
ight thanks yall 👍
hi there, im relatively new to modding balatro and it's been fun so far!
im having an issue with trying to implement removing the stone card effect and giving the played card an edition. it looks funky.
update: it's a me thing. i THINK it may be due to THIS context setup?
I am trying to make a stone lke care that becomes more powerful if you hold it and play other cards.
It shoudl be increasing when not played, but I am not hitting the context window, anyone see the issue here?
calculate = function(self, card, context, ret)
if context.cardarea == G.hand and context.individual then
sendInfoMessage("I am being held")
card.ability.extra.h_x_chips = card.ability.extra.h_x_chips + card.ability.extra.chipsRate
return {
h_x_chips = card.ability.extra.h_x_chips
}
end
if context.cardarea == G.play and context.main_scoring then
sendInfoMessage("I am being played")
return {
chips = card.ability.extra.h_x_chips
}
end
-- Remove stone and apply edition
if context.cardarea == G.jokers then
if context.before then
if context.scoring_hand[1].ability.name == 'Stone Card' then
G.E_MANAGER:add_event(Event({
func = function()
local card = context.scoring_hand[1]
card:set_ability(G.P_CENTERS.c_base, nil, true)
card:juice_up()
delay(0.3)
return true
end
}))
G.E_MANAGER:add_event(Event({
func = function()
local card = context.scoring_hand[1]
local geode_transform = poll_edition('aura', nil, true, true)
card:set_edition(geode_transform, 0.5)
delay(0.3)
return true
end
}))
end
end
end
im trying to use events to make it play one at a time but i cant get it working
does anyone know how to delay removing the stone and applying an edition?
oh, you should just add a flip step first, first juice and flip, then enchant, then flip back around
huh, didnt know about flips. ill try that out, thank you!
It's what tarots and everything else do when changing a card
So I am definitely hitting my 'I am being played', but I am not hitting the 'I am being held' for my enhancement
i kind of wanted the effect to be like vampire where it shakes and just instantly removes the effect
maybe try evaluating the card or try to get the card context
theres a list of contexts that ive been using thats helpful
need a bit of patching lol
if context.hand_drawn then
for _, card in ipairs(G.playing_cards) do
card:set_ability(G.P_CENTERS.m_base)
end
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:flip()
return true
end,
}))
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:set_ability(G.P_CENTERS["j_hpfx_ijiraq"])
play_sound("card1")
card:juice_up(0.3, 0.3)
return true
end,
}))
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.15,
func = function()
card:flip()
return true
end,
}))
end```
how do i fix it crashing every time it tries to trigger?
crash log?
oh lmao
That guide on context was amazing
it’s so good
sorryyyyyy one more question
I wrote 30+ jokers and five editions without knowing that context page existed
context.discard triggers on every discarded card, but is there a context (which there probably is, there's loads) for just using a discard?
try context.pre_discard
can i debug a stone card into my deck before a blind
well, debug it in the small blind and then go into the big blind
oh true lmfao
(debugging from the view deck page doesn't work as those are actually just copies of cards in your deck, not the real thing)
(i know unfortunately)
These are displaying nil, not sure what i'm doing wrong here?
probably smth more i have to put in after fixing it to card.ability
looks like your config is inside your loc_txt?
and whatever comes after it too
do you have loc vars
theres probably so much i have wrong 💀
i did have it all working but was advised to change it bc it was outdated
wait wtf
its in my main lua
is there a guide anywhere on how i could add gui/text elements (specifically trying to add text below the blind req on boss blinds only, somewhere like shown in the ss)
Is there a way to change the requirement for a blind after it is selected?
G.GAME.blind.chips
Check out Bunco or my mod
and also G.GAME.blind.chip_text
man i sure love my stone deck
Oh, that's probably why. So I just set that to the new chip amount?
i think you'll need like a function to format it
if(context.setting_blind) then
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = function ()
G.GAME.blind.chips = G.GAME.blind.chips * card.ability.extra.xchips
return true
end
}))
end
This is what I currently have.
where did you call SMODS.Joker
what im hearing is i need to remake this from the ground up 💀
imma go look at some different mods for reference
how would i make a deck that gives you a joker/consumable when you start
wait nvm i have it already i just made a mistake
💀💀💀
wrong again! not the right mistake
anyway how would i do this
you can just put jokers and consumeables in the deck's config, each as a table of keys (including prefixes)
Just the key
okok ty
im kinda confused, how do you make booster packs give cards of a custom consumable type? anything i try to do gives me the error attempt to index local 'center' (a string value)??
what do you have so far
batro
well loc_txt shouldn't just be a string
but also to tell the booster pack what cards to spawn, you need to give it a create_card function
and what am i sposed to put in that function
have you read the docs on boosters?
The real question is aure can we see more of your kitty cat
im reading it and maybe its just bc its late but i dont really understand what exactly im meant to put in the function
do i need to create the card myself? then whats the card argument for
you can either return a card or something to be passed into SMODS.create_card
What would that entail?
so returning something like { set = 'YourType', key_append = 'some_random_seed' } is perfectly valid
where YourType is the key of your consumable type and key_append is just some randomness value used to make the queue of cards unique and not impact other RNG
i see i see
ok no error thats good
ok going to the collection and trying to debug unlock the booster gave an error
I had something like that I can show you an example when I'm home
alright
i think i didnt give enough loc_txt
for now you can check out functions/UI_definitions.lua and look for something about boss blinds and HUDs though
you can hook/patch that and add your UI nodes to it I forget the exact name of the function
wrong image
ayy
ayy
now to see if it actually works
????
the particles are going crazy
and also the error text
Hello
Can anyone teach me how to use drawstep to make extra soul pos layer
I tried all night
Looking at documentation and source code
But it doesn't tell me anything
card.ability is just the cards config value right?
skimming thru card.lua that seems true yeah
hoooow would i implement it so that when a rank that is one of the variables listed in this table of values, it removes the first variable sharing a rank within the table?
in context.individual, you'd just iterate over that table and remove it if the rank matches, no? Then break the loop?
OH true!!
oh wait, discared. Same thing, different context, haha
aaa i forgot about iterating over the table ty
how would i change the edition of a created tarot via joker calculate()? i tried just context.card.edition but that's not a thing apparently
Does anyone know the most effective way to reset a joker's scale/position values to its default?
edition of a tarot?
yeah, i just want to make it negative
oh
look at how perkeo does it for the planet cards, i suppose
theres an example for that in example mods
perkeo creates the planets itself though, i'm trying to modify a created one from a separate source
save the x pos and y pos to config, probably
I'm having a Spectral that replaces a joker with one of a similar rarity, so for example if a Wee Joker becomes a different joker, I'm having trouble making sure it resets from being small
Thus I have small boney
really? i thought it creates the card then turns it negative, hm
does anyone know whats up with the particles? also the error text lol but im very very confused by the unending swarm of particles
wait wait i think i might know this one
you have the floor
lol
does anyone know how you use dynatext i feel like this might be useful to me
i do not
and do you know how to fix the ERROR text by any chance?
this looks like stuff for localisation files which i. do not use because i cant be bothered
lol
i have a stamp that does the same, you need to store the rarity in a variable, destroy the joker, and then create a new one of the same rarity
are there any examples for recreating the wheels "nope!" effect?
if you're in a context just return {"message" = "Nope!"}
how would i get it to terminate after updating the table? [ignore the blackened out bit, wip condition for when all ranks removed]
break
oki
you have to add skip_materialize = true to create_card (or your return table, whichever you're using)
it's in the docs
i have a group_name though
what does your code look like
interesting
I use group_key instead (because I'm a localization file fiend) but it should be working
I think there is a specific localization entry you wanna do for that pop up text, but I don't know how to set that up when you define loc_txt in file, instead of using a localization file
(you should use localization files anyway they're better)
how would i write a trigger that activates when a card's id is equal to an id in a given table? currently trying if context.discard and not context.blueprint and context.other_card:get_id() == table.concat(card.ability.extra.ranks, ' or ', 1, #card.ability.extra.ranks) then but nothings happening
i cant be bothered to use a loc file, besides my mod is literally so small it doesnt have any jokers
if context.discard and not context.blueprint and context.other_card:get_id() == (card.ability.extra.ranks or 1)
I think the text that pops up when opening packs are misc.dictionary entries. No clue how you'd set that up this way though
is ranks a table?
Also, localization files are barely any effort, haha
kid named dump_loc
what is dump_loc
wouldn't that not work because a card's id can't be equal to a whole table?
i tried that same thing earlier in a pairs function and it did not properly work
something you can put in your mod metadata to automatically generate a localization file from your existing code
handy
that's why I was asking if ranks was a table
oh it is yeah
yeah I wish I knew that before I did it all by hand
on 21 jokers, 43 consumables, and an assload of decks and other misc text
in that case, you can just use if context.discard and not context.blueprint and inside of that, loop through each rank in the table and check the card's id against that
oh ofc right
ok i will figure out localisation files tomorrow after i have sleped
I do recommend using dump_loc, since it gets everything
:264: attempt to indec local 'v' [a number value]
is it crashing because v is used elsewhere in the calculate function under a different ipairs function?
because realistically, instead of storing anything complex you can just store a number
oh yeah im misunderstanding my own code hard lmao ranks is how many values are left in the table
that's all the ranks are (in the base game, anyway)
also it'd be table.remove(card.ability.extra.ranks, i), not v
for my multi-stage boss blind, do I bother trying to make Mr. Bones only carry you to the next wave instead of clearing the whole thing?
how would i give an edition to all scored cards?
I'm trying to get the floating sprite and the base sprite of a joker to line up for an effect, but they're offset slightly. Anyone know why?
shouldnt this apply negative to the first highlighted card?
G.hand.highlighted[1]:set_edition(e_negative, true, false)
yep it needed to be a string
question mark
cardsauce has several jokers that apply editions to scored cards, use that as a reference
ah
did you figure this out or do you still want the example
for some reason, the presence of a return function here is considered bad syntax
i would like the example i didnt get much progress
always works perfectly fine wo it
i was going to try dynatext but got sidetracked
r
?
local _create_UIBox_HUD_blind = create_UIBox_HUD_blind
function create_UIBox_HUD_blind()
local ret = _create_UIBox_HUD_blind()
local node = ret.nodes[2]
node.nodes[#node.nodes + 1] = {
n = G.UIT.R,
config = { align = "cm", minh = 0.7, r = 0.1, emboss = 0.05, colour = G.C.DYN_UI.MAIN },
nodes = {
{
n = G.UIT.C,
config = { align = "cm", minw = 3 },
nodes = {
{
n = G.UIT.O,
config = {
object = DynaText({
string = { { ref_table = G.GAME.blind, ref_value = "loc_debuff_text" } },
colours = { G.C.UI.TEXT_LIGHT },
shadow = true,
float = true,
scale = 1.2 * 0.7,
y_offset = -4,
}),
id = "blueatro_HUD_timer",
},
},
},
},
},
}
return ret
end
Here's an example that uses dynatext
oh im so silly in the brain
do you need the break in there?
i was looking for things that had blind and then hud not hud and then blind
this does this which obviously needs to be tweaked but you get the point
yeah, it ends the function that searches for and removes an item from the list
ty
Cards played previously this Ante are debuffed
i think you need to put it outside the if
put it under the break thats under it and see what/if error it gives
sorry i didn't hear that could you say that again please
i tried before i asked in here initially and a bunch of different placements have similar errors
im running into an issue where the stone layer seems to want to stay despite the fact that set_ability is making it a different enhancement. like it has the number / symbol sprite but the stone is above everything else
CARDS PREVIOUSLY PLAYED THIS ANTE ARE DEBUFFED
does it need a comma after the table.remove line?
that did not work no
i made a custom consumable type and im trying to get the descriptions working, i know the layout is
[CARD TYPE] = {
[LETTER]_[PREFIX]_[CARD KEY] = {}
}
}```
what is the card type actually supposed to be?
and what does the letter mean?
nvm i figured it out
what's with the nil, nil, nil, nil, nil, whenever a card is created
x_mult
oh neither got it
im trying to load my jokers into my main lua from a seperate file (using KCVanilla as a reference) but it keeps saying these are returning as nil values
thaaaaaaaaaaank you
assert(SMODS.load_file('file_name.lua'))()
is there any way i could solve this
my custom consumables are showing "ERROR" as their card type when in a run but show up just fine when in the collection. whats going on?
ta dah!!!
i really cant figure out the syntax error here for the life of me auuuugh
4 dollars for 6 mult is not very good
from a balance perspective
i like the idea of it
hey so i got a really cryptic error
im trying to make a joker
let me pull it up
here's the log
the error
bad argument #1 to 'ipairs' (table expected, got string)
oops
its mean to say the joker gains +6 mult
so it saves like +6, +12 etc
send ur joker
alright
one second
its gonna be a screenshot because my copy and paste is fucked rn
well hold up
yea but ur still paying 4 dollars for 6 mult
SMODS.Joker {
key = "crazy8",
loc_txt = {
name = "Crazy 8",
text = "For every {C: attention}8{} Played, grants {X: mult, C: white}#1#{} Mult."
},
config = { extra = {mult = 4}},
rarity = 4,
atlas = 'joker_atlas',
pos = {x= 0, y= 0},
cost = 8,
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.mult}}
end,
calculate = function(self, card, context)
if context.individual and context.card_area == G.play then
if context.other_card:get_id() == 8 then
return {
message = localize { type = 'variable', key = 'x_mult', vars = {card.ability.extra.mult}},
xmult = card.ability.extra.mult,
card = context.other_card
}
end
end
end
} ```
there
i need to adjust some text
but thats not the important art
part**
does anyone know why the chips, mult, and xmult don't work for editions, but card_limit does? i saw someone else had the same issue so it wasn't just me
its what i saw on the tutorial so i followed it
i thought it was neccessary?
or rather the example
im almost pretty sure u dont need it if ur returning xmult
also
i return my message like this
i dont know if localize is valid for message, it probably is tho so thats fine
like i assume it is
but like anyways one thing i notice is u dont need that
like just comment out the localize
dont put any text
alright
yeah
it will say x10 mult by default
just did that let me try the game out
if u return xMult
the load up animation or just loading mods and stuff
just the loading of mods
yeah that didnt fix anything
ah idk
alr
thought it might not
does it
ok im silly in the brain but i got it to show this, any idea how i can get the 600 as a normal value so i can square it?
crash when u open the game
it crashes while it's injecting i think
currently doing this
it gets 99% through with the loading bar then it burns
at the bottom
check ur main.lua name and what u have in metadata.json too just to be safe
in lovely?
or where
sorry for so many questions im just unfamiliar to the whole thing
you should have a json file and a main file for ur lua code
yeah
yeah
my main file isnt main.lua but the file name matches up
so its successfully loading the mod filkke
file**
ok then at least u know it isnt that
hmm
well its still saying main.lua not found
weird
yeah
could it be main.lua as in the game's file? would it be worth it to validate my game?
and just reinstall lovely?
im gonna try thast
just take shots ijn the dark
unless someone else has a better idea
so why does this crash my game? does steamodded do it different? do i change self to card maybe?
wait i should get the crash log
change self to card, probably
or a something else problem
never used juice_card_until before so idk :3
if its that easy
@open aspen there's for sure something fucked about that joker code
just commented it out and the game works
is there like a limit as to how much code can be under smods.joker or some shit
im so lost
shouldn't be
whats the crash log?
says it crashes at line 284 for an unexpected symbol near }
which is the last line
oh hey that's the exact error I've been fighting
oh no shit
but in lovely within the gamepass binary haha
blegh do u have a solve
my solution was to make sure I wasn't thrashing byte buffers when working with luajit state
alr so it does the juice up animation but it doesn’t proc the mult gain
gonna see if my transformation block is doing something iffy to it
ssorry what
solution is to "stop thrashing"....... you cant take away my metal liberals!!!!!!!!!!!! cool skeleton flipping off camera png
meow
so like. is the error that theres too much data in a function or
cats :3
I was just being disruptive tbh
I have no idea why you're having that problem
:/
Wanna see my cat?
never send that again.
BLAAUUAGAAH
FUCK!!! I HATE IT!!!!!
why did my game super crash on opening
i want to hug that carr
wet carr
He loves hugs
gotta figure out by trial and error ig
like the game closed
That’s strange
you don’t say 😭
Hi Toma
I point out the obvious
Car 👍
car
Two cars….
ugh im about to lose it
carrs
it’s giving the xmult AFTER SCORING 😭
would anyone be willing to help me out with an error im running into?
is this about me
its a different one this time lol
post it here and i will see what i can do :3
no it’s about me actually i’m an idiot
oh
makes sense
-- Geologist updating
local cardupdateref = Card.update
function Card.update(self, dt)
if G.STAGE == G.STAGE.RUN then
if self.config.center.key == "geologist" then
self.ability.stone_tally = 0
for k, v in pairs(G.playing_cards) do
if v.ability.name == 'Stone Card' then self.ability.stone_tally = self.ability.stone_tally+1 end
end
return true
end
end
cardupdateref(self, dt)
end
im trying to mimic cloud 9 but with stone cards. i was reading around here abt G.STAGE == G.STAGE.RUN but its throwing errors
felt
this too has been felt
hell yeah
how would i make a custom calculate trigger? i.e. use some consumable, that consumable has a chance to do something which triggers the calculate
im reading thru previous issues with this and i think i need to run this inside the joker file
for some reason there was a msg that said it shouldnt
let me test this
so yall how do i get the amount of money the player has
ok pal
oh it's
it's stuck like this i cant get in
(i fixed it and got the joker working thanks for the help)
what would i have to add to my smod code to enable me to have 2 seals on top of each other like this?
like how can i remove the 1 seal per card limit?
is a bad allocation crash concerning?
patching i believe ??
whats the exact error
prolly just out of memor y
if its been on awhile ur memory might just be super fragmented
teach me the tech wise one
which seems likely considering it was an error in the graphics library which (unless i fundamentally misunderstand dynamic libraries) has been reusing the same memory space for the dawn of whenever you turned on the pc
sorry
i just went digging and now realize i have no idea how calculate function is actually called, how would i just trigger a specific event
SMODS.calculate_context
mmm ok and would that accept a custom event
ya pretty sure you can do whatever context you want
you just provide the context table iirc
ok cool that's handy
any good mods with example tarot cards or spectral cards?
question
could you simulate seal behaviour with a sticker
shoot!
i think u can
omg that is right i never thought of that..
but how do you even code a sticker
it isnt too too different from something like an enhancement
severance balatro mod has some i think
my code is made significantly more complex because i went through the effort of doing custom draw function
hey guys, i just created my first joker and was wondering if i could start a run with that joker to see how it functions and test it, is there like a sandbox environment or something i could use?
My sticker used to be an enhancement and I just made some relatively minor changes to get it to work as a sticker. I wanted it as a sticker because stickers don't conflict with each other (as in you can have more than 1)
debugplus
(its a mod)
yeah i installed debugplus
what is patching
but their wiki doesnt have anything related to what im talking about (or maybe im just dumb and cant find it)
uhh idk all the commands keybinds but u can def use that to spawn it
theres a keybind to spawn card here