#💻・modding-dev
1 messages · Page 64 of 1
mood
well I guess I can patch somewhere here to make card visible if it's specified
honestly, that should've been there in the beginning, in hindsight
I dont think I ever noticed this method
¯_(ツ)_/¯
I only patched draw_card_from
can you pull latest
and confirm it works?
yup, one sec
how can you make the soul_pos not sway/move
I did this for the 3rd layer by… adding a new layer and writing the functions myself (in Cryptid)
i need to find a way to resize the extra layers because right now i can only resize the base card properly
I believe the scale of the layers is connected to their scale_mod
the funny thing is though; last time when i loaded into a saved run, i saw that waluigi's face sprite was resized properly
i might need to do some tomfoolery to get this to work
bingo!
Can someone explain what other_card is?
It usually means that it's just a single individual card, rather than being the whole hand like scoring_hand and such.
context.before and context.after I'm pretty sure never call other_card, but you'll see it during the main part while cards are being scored.
Gotcha, I am trying to make a raise-fist esque effect and I was reading old convos in this chat and thought that could help?
It only iterates through the playing cards that were scored, maybe look for G.hand instead.
Ah, that definitely helps
The example mods were really helpful, managed to get one Joker online, but now I need to properly learn the Steamodded API
I lied about the other_card only being for scored card, there does appear to be a other_card that looks through the hand.
Here's an immensely helpful cheatsheet, if you aren't already using it. #1247703015222149120 message
I was not! This looks like what I need
Does any mod have a raised fist kinda effect? I was looking at the balatro code but it doesn't have Steamodded API so I am getting very lost
Are you looking through Card:calculate_joker in card.lua?
I don't know what that does, so maybe!
It's basically just a large if tower that you'll need to follow, Raised Fist has elseif context.individual then and then if context.cardarea == G.hand then, which are the two contexts it checks for before activating. In that cheatsheet, it'd be under 7iii.
If you compare to the rest of the blocks, you can see that nothing else has individual = true and context.cardarea = G.hand at the same time, which means it won't be incorrectly triggering at the wrong time.
Gotcha, ok
I have stapled together the raised fist code and the example gold joker code, but it's just crashing the game, so I'll take a look at this
This code is probably really bad, but I am new to lua and cannot figure out the issue, game won't boot up, it says unexpected symbol on line 81 near "}"
calc_dollar_bonus should run at the end of the round, it finds the lowest rank card with the big for statement, runs the debuff animation if the selected card is debuffed, but otherwise it should return the money
whats line 81
ah
i think youre missing an end after the first if
in calc_dollar_bonus
it looks like you close the if inside the for, but not the for itself
also i think elseif is one word
not sure if that matters tho
Oh! ok sick
You are very right
for calc_dollar_bonus it did say that you need to check that the value isn't 0, but I'm worried bc in mod-space rank 0 cards exist
stone cards might return 0 or lower
that might be why
i dont think they work with raised fist for example
which im assuming you looked at the code for for this
There's a specific line in the huge for statement that ignores Stone Cards
It's like-- weirdly right in the middle
Ok, not crashing the game, time to test for functionality
fingers crossed
Ok! It tried to grab a nil value, so that means it didn't grab the money at all... OH no I understand now
Calc_dollar_bonus happens at payout, so I need to do all of this way before then
So need to cut out a significant bit of this
you can use make a calculate function that checks for context.end_of_round
then get the lowest card
store that in the card
and the use that in calc_dollar_bonus
Perfect yeah, that was the plan
when using multiple layers, how do you make a shader apply to only one of them?
sorry yeah you probably already knew what to do
Ideally I want these to look like gold cards proc-ing at the end of round, so I'm gonna check the code on gold cards next
You have been immensely helpful! I am very new to this
do you mean the soul layer?
glad to hear
Yeah, should work. Also, config values are stored in card.ability.extra, so you'd use card.ability.extra.temp_money for example, otherwise you're changing a global value.
might be worth checking out stuff like rebate
because you can just have it all in the calc function
easy as ease_dollars(temp_money) and and eval message on the card
pun kinda intended
yes and no, when I apply a shader to the soul layer its being applied to the 3rd soul extra layer. it doesn't happen when i apply one to the 3rd layer though.
i want to appily one to soul_pos, but not soul_pos.extra
if you just make sure the soul_pos.extra is drawn after the shader it should work?
i think
might be worth adding an apply to soul extra thing for editions
So I should just replace everywhere I put temp_money with "card.ability.extra.temp_money" and same with temp_ID?
Basically, yeah.
Besides the config values ofc
Ok, this is all good advice. I have basically just been trying to make 2 jokers all day, but it feels so good to make progress
i mean you should probably just make temp_id local
it doesnt need to be saved if you recalculate it every round
Oh, temp money also could be local, then I think
yeah youll want everything to be local
That too, though the temp_money I think should be kept in config because you pass it between the calculate and calc_dollar_bonus.
pretty much
^
Ok, great, and local variables I just put in whever, or does it want me to put them in loc_vars?
just define them at the top of the calculate function
bare in mind that any local variable is also local within if statements and for loops
Real quick, ease_dollars works, but I'm pretty sure it adjusts in real-time, rather than showing payout at the end, right?
yes
^
Alright, missed that, makes sense now. Think my internet might be lagging behind.
So if all variables are local, do I even need the config line?
Not really, no. It's just for values that persist between separate function calls.
its better practice to keep the extra money in there
that way it can be easily passed into loc vars
and for any values that are updated during the run youll need them in config too
because each jokers ability is a copy of the config
its own copy that is
That makes sense
If you had any variables, like it gave whatever amount +x, it's also good to store that x as a config even if it doesn't change so you can say x is now 2 instead of 1 for each instance of x in the code.
Yeah, I agree with most of these, it's just this design inherently doesn't keep any variables for next time/anything I can adjust
Yeah, no, this joker doesn't need any, nekojoe's suggestion is completely optional in this case I'd say, it's more just advice for future jokers.
Actually, I say that, because looking again, the loc_vars doesn't seem to be doing anything in this case.
I agree, I was wondering if I could cut it but scared to try
oops i didnt even realise that
It was in Golden Joker because it tells the loc_txt that #1# is the variable 4 grabbed from config.extra.money, so that golden joker shows as "$4" rather than "$#1#".
Exactly, but I didn't need that for my text
Ok great
Ok! It's working, just need to shake the card that's chosen a lil
:juice_up is probably what you're looking for.
Pretty sure the example mod has it on Cavendish/Gros Michel somewhere if you wanna look at that.
what does your code look like?
in your return if you have card = card then i thing it should shake up automatically
might be wrong tho
It doesn't have that, that usually shakes the joker itself, could I also do card = raised_card to proc the chosen one?
Yeah, you can.
I appreciate the help with my incredibly low stakes modding
i mean no one expects you to just know everything immediately
i struggled for way longer when i started lol
Storing x as a variable also gives it compat with things such as Misprint Deck from Cryptid that change Joker values
Perfect
whereas card is the card itself
even tho game uses self
which is a bit annoying at first
actually sorry youll wanna do card = context.other_card
if you want the money and shake to happen on the playing card
and card = card if you want the money and shake to happen on the joker
It says it can't field the "ability", getting a value of nil
But I have no idea what it's doing with the message line so idk how to fix it
thatll be because it needs to be card.ability.extra
Yeah, I adjusted it, still having issues
Yeah gimme a sec
nws
try starting a new run maybe
Is there a glossary or a page to see how to code in specific effects (for example how to proc X mult for every heart card played then destroyed played hearts card)
at least the code
you can look at the game source code to see what jokers do
like idol for x mult
sixth sense for destroying cards
There's not a great source beyond digging through the code yourself
Tried, and still got the same error
hm
I think the issue is I don't know what card.ability.extra is like-- trying to do?
could you send all the code?
card.ability.extra will be a copy of config.extra
ah
scrolled up and looks like your using a table
so youll wanna do card.ability.extra.temp_money
although youd have to make sure youre setting card.ability.extra.temp_money to the temp money value that round
so probably better to do localize('$')..temp_money
for the message
That makes total sense
I meant more of a Wiki page butI i guess that suffice
Yeah, I wish there was a wiki
well there is a wiki
its not quite finished
i assumed you knew that so i didnt bother mentioning it lol
mb
No you're good I know about that I meant maybe a discord post and stuff
It exists, but it's far from comprehensive rn
https://discord.com/channels/1116389027176787968/1247703015222149120 this is pretty useful
np
Ok! I got it appearing under the joker by implementing the faceless joker code, I kinda wanted it over the cards but I genuinely didn't remember that faceless has it by the joker
So I think it's probably a clarity thing
We take those
yeah all the jokers that give money display the text by the joker i think
That makes a lot of sense
Now the only issue is that the card is probably busted! But hey it's a good learning experience
Might try doing some art next as a pallete cleanser? But overall I'm really happy I got 2 jokers working
thats pretty good
i find that doing art is a nice wind down after a frustrating coding session lol
Mhm, probably need to sleep next, but I feel very accomplished
what does the other joker you made do?
we have joker retrigger api at home
this is art
what is that 9 of diamonds doing in the joker slots
Cursed
tbh i think the fact that the cards are drawn from the bottom of the deck rather than the top is more cursed
thank you square joker for cursing me with a more detailed visual of that
WHAT
yeah
i already knew this because of my deck-discard swapping joker (it draws the cards from deck for long enough to notice the cards are coming from the botton)
but having square joker's square back facing me while i tried to draw it was dreadful
I made one called Passing Grade which gives 6-10s +3 Mult when scored, I made Gambler which gives +1 hand per round but -$1 at end of round (UI is a lil broken there), and I just made Big Shoes, which gives -1 hand, but +$7 at end of round
I have a big document of ideas I have been steadily making for months, finally decided to implement some
if youre trying to drain money at the end of the round doing if context.end_of_round then ease_dollars(#) end would be better
although you'll need to return a message
they sound pretty cool, although big shoes sounds pretty strong
anyone done any messing around with the discard area before?
why is it up there
I do like it popping up on the payout screen, but yeah, it just ends up being red minuses
ive set its T to the same as the deck
Why is she there
i wish i could tell you
tbh why would u need to mess with the discard area
Gonna need to do a lot of balancing
wanna put it above the deck
if its for info then the deck info already shows u the discarded cards
true dat
i struggle w balancing a lot
a lot of my jokers ar eeither way too strong or way too weak
i don't balance
i thought you made cryptid tho, the balancing mod
The mod whose marketing is all about how it's balanced
I genuinely am really big on cards that are at an even keel with the rest of Balatro's designs, so the goal is not to go too crazy
balatro is just so charming
it appears i've hit a roadblocks in my mod
and that roadblock is that there's no real way for me to detect if a joker should retrigger or not
as in, if i have a red seal joker in a non-playing card calc
probably something i need to do through checking event queue
if i crack the case of silencing messageless retriggers, then i'll just need to go through the rest of the contexts to update them to use my system for this mod to be somewhat usable
what are they cooking
it was surprisingly easy
I forgot that I was making a mod, time to get back on track I guess
so i removed the /52 for the deck
and now its showing 0 / 500 under it instead
im a bit confused
it shouldnt be
500 is the default limit i think?
so maybe because ive removed it its drawing a default
but i wondered if anyone knew
could be discard pile
the discard pile is above it
oh yeah 500 is the limit for that not the deck
what am i saying
i think
i know one of the card areas has a limit of 500
this is odd
it looks like its drawing some kind of overlay
oh wait i know
maybe
its because i added my own card area
for burnt perk cards
and i just removed the discard type from invisible types
so its drawing that
beautiful
plan is to have the discard pile draw back to deck when you run out
its pretty easy to do
ik
probably lol
cant wait to try it
its probably gonna be a while before anything is out
although the blind health definitely needs to be nerfed cus like 😭
yeah im gonna have to figure out damage and stuff
currently round 1 isnt possible with this deck lol
maybe w erratic
still so much to do 😭
probably gonna have to rework most of the jokers and enhancements etc too
big project for sure
i can help with things
would you like to?
im currently in the middle of rewiring the entire state machine so i feel like i could help with that
i would appreciate any help i can get
okay if you're remaking dndg then surely i can remake ruina
balatro is so moddable you can do literally anything i think
for sure
300 dice rolls coming your way soon™️
yippee
currently on individual contexts, after that i'll just need to do a quick rundown over the context checks that happen outside of the hand play
and then the mod will technically be done with its first feature
i want to make a funny dangit grandpa card and it just so happens that the only logical translation of its effect (throw a guy into a different room 😭) is to make it throw jonklers into the consumable slots and i cant do that if i dont make a mod that makes consumables a valid calculation target
thats some serious determination for one card lol
fr tho the idea is super cool anyway
btw the mod (context api?) is going to be called magictrick because naming mods after balatro cards is cool and this mod does the same thing as magic trick (puts cards in places where they simply dont belong)
We embrace more mods naming themselves after cards (I already have one called Flower Pot and two on the backburner).
eris and ceres 🙏
exactly
calculate = function(self, card, context)
if G.GAME.cere_clock_card then
if context.repetition and context.cardarea == G.play or (context.cardarea == G.hand and (next(context.card_modifiers[1]) or #context.card_modifiers > 1)) then
if context.other_card:get_id() == G.GAME.cere_clock_card.id then
return {
message = localize('k_again_ex'),
repetitions = card.ability.extra,
card = card
}
end
end
end
end,```
code is same as what mime does so im not sure why is giving me an error
because its been changed to card effects apparently
it's kinda funny how much of magictrick is just "the joker retrigger api at home", especially considering the "-- MagicTrick does not support joker on joker retriggers outside of played/held hand because it's a smods feature in active development" I've left there seemingly just for myself
depending on how many contexts are calced outside of state_events, I might release the first version tonight
this joker is giving ^2 mult for consumables too?
howis that even possible
calculate = function(self, card, context)
if context.other_joker then
if context.other_joker.sell_cost < card.sell_cost then
G.E_MANAGER:add_event(Event({
func = function()
context.other_joker:juice_up(0.5, 0.5)
return true
end
}))
return {
message = '^' .. card.ability.extra .. ' Mult',
cere_Emult_mod = card.ability.extra
}
end
end
end,```
ye I talked about that yesterday
other_joker is a part of joker_main, meaning consumables also calc it
but
for _, v in ipairs(G.jokers.cards) do
local effect = v:calculate_joker{full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_joker = _card}
if effect then
local extras = {mult = false, hand_chips = false}
if effect.mult_mod then mult = mod_mult(mult + effect.mult_mod);extras.mult = true end
if effect.chip_mod then hand_chips = mod_chips(hand_chips + effect.chip_mod);extras.hand_chips = true end
if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end
if effect.cere_Emult_mod then mult = mod_mult(mult^effect.cere_Emult_mod);extras.mult = true end
if effect.cere_Xchip_mod then hand_chips = mod_chips(hand_chips*effect.cere_Xchip_mod);extras.hand_chips = true end
if effect.cere_x_chips then hand_chips = mod_chips(hand_chips*effect.cere_x_chips);extras.hand_chips = true end
if effect.cere_Echip_mod then hand_chips = mod_chips(hand_chips^effect.cere_Echip_mod);extras.hand_chips = true end
if extras.mult or extras.hand_chips then update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) end
if extras.mult or extras.hand_chips then card_eval_status_text(v, 'jokers', nil, percent, nil, effect) end
percent = percent+percent_delta
end
end```
this is the only place other joker is used
other_joker is called within joker_main
?
theres only one other_joker
yes, the loop you're showing me is from within joker_main
other_joker is iterated over G.jokers using the card from joker_main
jokers can see consumables through joker_main, but consumables cannot see other_joker
other_joker.config.center.set == 'Joker' (crazy magictrick forwardcompat)
oh i did if context.other_joker.ability and context.other_joker.ability.set == 'Joker' and context.other_joker.sell_cost < card.sell_cost then
I hope magictrick gets some attention from other modders purely because I want to see how unhinged code built around it is going to look like
i would def like to add some jokers that utilise it when its done
Magic Trick?
my only fear is that since most of it is lovely patching around events it might be a bit annoying for mods that patch around it too
basically all the cursed clips I've been posting of cards being in wrong cardareas
context api?
my goal is to change a bunch of systems (mostly context calling) to allow for almost any card to work in almost any context
Ye, the way im looking through all the cards is through a function that returns a list of valid areas (the intent being that custom areas are hooked into that function)
Ah so it’s not automatic
As in
There’s a CardArea creator that automatically does it
Although my idea was a bit different
It was to have a CardArea, a list of types, and an ordering, and then calculating every card of each of the listed types in the CardArea
The order I had in mind was either negative (before Jokers) and positive (after)
I might change that later, but for now it's a predetermined list (G.jokers and G.consumables) with a blacklist (functional artifact from older version) and an appending whitelist (when it's used it's mostly either G.hand or G.hand and G.play) depending on context
that sounds good so I'll look into it
the project is relatively small and flexible so I can do that
is there a way to return multiple messages in calculate_joker
should I make magictrick cardareas into smods objects?
@hushed cradle i don't think it worked?, the flush still showing up without the joker :I
whats your code
rn its like this ( couldn't really fit in the WHOLE joker, vscode won't let mezoom out
maybe remove the old code
which part?
the part in the calculate function
whole?
that was the bit that was causing it to always be a flush was it not?
idk honestly, rn it keeps the flush even after sold
yes because of the bit in the calculate function
the prefix is then "no_l" since the mod name is no_laughing_matter?
There probably needs to be a wiki page about SMODS functions that aren't just the injection stuff, I never knew that eval_this existed until a few days ago.
i didn't know about SMODS.find_joker before eremel just told me :>
mod prefix is based off your modid if you havent defined a prefix
it works, but after selling the card it keeps on working?? .-.
the code on the calculate function overwrites the suit function
calculate is intended to be used with contexts of events that are happening
the act of existing in the player's possession is not an event
I swear this code was working last night somehow, but it's now saying that effect doesn't exist, even though it should be getting called from
G.GAME.selected_back:trigger_effect(context = 'whatever_here')
so, self should be equal to G.GAME.selected_back, which, uses effect instead of ability, right?
Code and lovely patch for reference, might be a simple spelling mistake I can't find.
SMODS.Back{
key = 'hod',
loc_txt = {
name = 'Book of Hod',
text = {'All Jokers give +3 mult','They gain +1 mult','per round held'}
},
atlas = 'Decks',
pos = {x = 2, y = 0},
config = {mult_add = 1, mult_base = 3},
unlocked = true,
discovered = true,
trigger_effect = function(self, args)
local deck = self.effect.config
if args.context == 'hod_mult' then
sendDebugMessage('Tests')
if args.card.ability and not args.card.ability.hod_mult then
args.card.ability.hod_mult = deck.mult_base
sendDebugMessage(args.card.ability.hod_mult)
end
SMODS.eval_this(args.card, {mult_mod = args.card.ability.hod_mult, message = "Hod's "..localize{type = 'variable', key = 'a_mult', vars = {args.card.ability.hod_mult, colour = G.C.SO_2.Diamonds}}})
end
if args.context == 'eval' then
for i = 1, #G.jokers.cards do
local card = G.jokers.cards[i]
if not card.ability.hod_mult then
card.ability.hod_mult = deck.mult_base
else
card.ability.hod_mult = card.ability.hod_mult + deck.mult_add
end
end
end
end
}
Wait, changed local deck to G.GANE.selected_back.effect.config rather than self.effect.config and it works fine, maybe one of the trigger_effects I've injected sends something else as self?
Anyways, solved it for myself.
can I use lovely's vars in the pattern as well or only in the payload?
arguments to SMODS methods usually aren't the same as the base game functions, especially self. As a rule of thumb, self in smods methods is always the prototype table the function is defined on
Makes sense,
Also, double checking, is there a function for info_queues that's like SMODS.eval_this or just ease_mult or any of that?
what kind of util would you want out of that? most of the time you just pass it the set and key
- whatever vars
Mostly just to inject an info_queue item into an already existing info_queue.
There might be a simple way to do it I just don't remember, but my attempts usually end up overwriting rather than just adding.
I will say that my understanding on info_queues is still quite vague, so there's a pretty high chance it's completely on me.
anyone know a function that a Joker can use when a blind is selected?
A function or context?
It's in the context list, after the main evaluate explanation,
ty
#1247703015222149120 message Here's the exact one, I think.
:3
is this a thing that you can do or not
for i, v in ipairs(context.full_hand) do
So, just to check that I'm reading this right, can I just check that setting_blind == true and blind == G.GAME.round_resets.blind in a joker's calculate function to make an effect go off at start of round? Or is it more complicated than that?
context.setting_blind == true and context.blind == ... I believe
Put context. before those two.
Right. Got it ok
I am starting to understand how this list is helpful
I am literally at work and yet my mind yearns for the code mines
is there a wiki page or some simple example code for how to do steamodded configs? can't find any right now
Mostly just a few mods that have it, it's basically return a table in config.lua as the defaults, have a SMODS.current_mod.config_tab = function() in your code, and return some UI stuff there. Lobotomy Corp I know definitely uses the SMODS config tabs, there's a few other mods to look at as well, but I don't remember them off the top of my head.
ah cheers
Also, you acces config by usually having local config = SMODS.current_mod.config somewhere outside of any functions.
ah right, accessing it is probably helpful
is there a way to add the value of v to handval without causing a crash
depends on the type of the 2 I guess?
error code if this helps
Yeah, looks like you're trying to add a card to handval.
i think v refers to the card
OH right i need to get the value
thx
is there an easy way to get the base chip value of each card
kinda like get_id but it returns 10 on facecards as well
and 11 on aces
card.base.nominal iirc
managed to get a joker that can copy destroyed jokers and multiple jokers
problem: if 2 copied jokers have the same context the new one overrides the old one
so if i copy Joker and then i copy Sly Joker, it only does the effect of Sly Joker
Put the jokers into a list and have it go over the list each time?
thats what im doin
joker can only return one thing is the issue I assume
so youd need to combine the return values somehow
yeah thats ive been doing
it SHOULD work but i have no clue
btw what happens if it destroys itself (another copy)
it cant
totally original code i swear
totalret gets reset through the loop, is that intended?
ohhhh i see
it seems that im
just genuinely stupid lmfao

im the real joker
@languid mirage once again mentioned
im STEALING HIS NAME
i swear its original
its not obtainable lol
thunk was giving it to "cool people" (quoting him) on discord
but he can't be active on discord anymore
so it is very unlikely that anyone will ever get it again
Hm, okay
why not? 🤔
too many people 
it's not like he can keep track of who's cool or not
with 50k discord members
true
I think it's kinda nice that the joker role is more rare like this tbh
(helps me recognize people)
anyways, I find it kinda sad that official localization got freezed
but hey at least we got among us cards right
AMONG US!!!!!!!!!!!!!
amogus
a mod actually made my game do better? but when i removed almoast everything exept my own mod my joker broke?
its actually zasty 😭
how can you unrender/delete a soul_pos?
what do you mean?
like stop appearing, so the player can no longer see it
is there a certain condition for when it happens?
kind of, when it is used
card.children.floating_sprite.state.visible = false?
I don't remember if state table is in sprite prototype or in card
or just :remove()
those didn't seem to work but i found a work around by setting the position of the soul_pos to an empty location
how do i make an edition not spawn on jokers in shop?
id like it to be available on cards only
in_shop = false,
that'll remove it for cards too
you'll have to hook create_card_for_shop and remove the edition if it's there I think
this works if you only want it to be applied via jokers or tarots
damn
it'd be better to patch in to where it chooses the edition though
otherwise you'll get funky sound effects
is it better to store joker's variables inside SMODS.Joker{} or SMODS.Joker{config = {extra = {}}}?
SMODS.Joker {
key = 'Bulbasaur',
loc_txt = {
name = 'Bulbasaur',
text = {}
},
loc_vars = function(self, info_queue, card)
end,
config = {extra = {}},
atlas = 'Jokers',
pos = {x = 0, y = 0},
rarity = 2, -- 1 common, 2 uncommon, 3 rare, 4 legendary
cost = 6,
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
POKEMON = {
Types = {
[1] = 'Grass',
[2] = 'Poison'
},
Level = 5,
},
add_to_deck = function(self,card,from_debuff)
end,
remove_from_deck = function(self, card, from_debuff)
end,
calculate = function(self,card,context)
end
}
I got this POKEMON table outside config.extra, is there any downside to this?
It might not be copied properly by invisible joker?
is there a way i can make a suit not spawn by default?
like its never in the starting deck
You could do the same thing the checkered deck does, go through the deck after creation and instead of changing the suit, deleting the suit?
Or the idiotic 2nd way I thought of: you could pretend your deck is a challenge, then it's args.challenge.deck.no_suits in Game:start_run, but there's probably some issues there that I haven't thought of yet 🤔
ive got it doing the first atm
yeah that's... the better way
its just a bit unclean because you can see the cards get removed :(
thats cos its an event
and if it doesnt use an event then the cards dont exist yet
so it crashes
yeah, I believe aure has been wanting to move the deck creation to before the Back:apply() for a bit now for that reason
Hmm, that kinda sucks. Aren't there other mods that managed to do this?
not that i know of
i managed to make something that works
no way
local game_start_run_ref = Game.start_run
function Game:start_run(args)
if args.savetext then
if Ceres.CONFIG.suits.enabled then
for _, rank in pairs(SMODS.Ranks) do
SMODS.inject_p_card(nothings, rank)
end
end
end
game_start_run_ref(self, args)
if not args.savetext then
if Ceres.CONFIG.suits.enabled then
for _, rank in pairs(SMODS.Ranks) do
SMODS.inject_p_card(nothings, rank)
end
end
end
end
local game_delete_run_ref = Game.delete_run
function Game:delete_run()
game_delete_run_ref(self)
if Ceres.CONFIG.suits.enabled then
for _, rank in pairs(SMODS.Ranks) do
SMODS.remove_p_card(nothings, rank)
end
end
end```
feel so smart rn
do suits have in_pool?
what is this
no way 😭
literally solves all my problems
wouldn't that mean that they don't spawn in packs?
also I should look at more code from other ppl bcos it would be good to know how others do things
saying this bcos I usually handle optionality through custom inject functions
So the x2 resolution version of the ATLAS, is just-- go into the software and scale it up?
Yeah.
if your art programm blurs the scaled up image make sure to set the scaling mode to "closest neighbour"
yeah thats how i want it dw
ok so back to working on magic trick and i decided to look at joker retrigger api draft because i need to know what changes might be coming to the state machine so i can adapt quicker when it drops and
it will literally be the stake api moment again where i'll have to go back and remove a lot of code because update will render it redundant (and broken)
actually now that i think about it i should probably move onto the joker retrigger branch
where do I find a list of all the colors I can use in loc_txt.text and how can I add more?
loc_colour in functions/common_events.lua
the fact that i can't return {vars = {'{C:red}+1{}'}} inside loc_vars makes me cry everyday
you can put colors as variables using {V:1}, check how vanilla does it though
YOU CAN?!?
{V:1} in loc_txt and colours = {<colour>} in loc_vars
This still won’t work in loc vars though
anyone know what happend? it works WITH a mod, but not without?
@wintry solar was right
seems like you need to write a custom generate_ui for this
either that or make a custom loc_colour
I'm trying to make that Pokémon Info customizable, so that I can make it anytime without adding a new G.localization.descriptions.Other
i really don't want to do G.localization.descriptions.Other 151 times
You should be fine as long as you put your V:1 in the loc file itself
You can also define new colours
And you could just add the colored columns directly to the tooltip
Wrap the colours in specific_vars = {}
with this I'll get something like this (the boxes) or only colored text?
only coloured text
for the boxes you can build the entry for this before its rendered i think
because v:1 doesnt make fancy boxes 😔
oh can it not?
damn
you should be able to hook to the loc colour function
Ceres.C = {
epic = HEX('8E6DFF'),
devil = HEX('333333'),
dark_red = HEX('B60000'),
new_moon = HEX('2c485dcc'),
divine = G.C.DARK_EDITION,
the_bill = HEX('EDCE7B'),
the_fall = HEX('eb7a34'),
the_french = HEX('E5E5E5'),
}
local loc_colour_ref = loc_colour
function loc_colour(_c, _default)
return Ceres.C[_c] or loc_colour_ref(_c, _default)
end```
something like that
i think
the x_mult-like boxes
surely that works for them tho
so like {X:{V:1},C:white}?
no just {X:epic,C:white}
using this ^
yeah it does work
the issue is that they want the color of the box to change based on variables they pass
i just tried it
this?
they already did that, the issue is that they need to do it dynamically
colours = {
grass_type = HEX('whatever green is')
}```
then {X:grass_type,C:white}
using this hooked function
they already reached this point #💻・modding-dev message
the issue is not getting the box to show up but to have the content of the box change dynamically based on the card
the content here being the colour
surely its just like loc txt tho
oh i see now
yeah
i swear im so slow sometimes
could you not just do something like
Grass Poison
etc
for all the type combos
and chuck that in main start
thats probably the easiest way
to do by hand
why not just have the entry parsed dynamically
?
i can write the code for that rn
😍
the goat
@brisk pond this is a little bit overengineered but its futureproof for pokemon with more than 2 types
local entry = {}
local entry_parsed = {}
local pkmn_types = {'pkmn_grass', 'pkmn_poison'} -- example of expected table
for i = 1, #pkmn_types do -- go through each type
entry[math.ceil(i/2)] = (entry[math.ceil(i/2)] or "")..localize(pkmn_types[i])
if (i%2) == 1 and i ~= #pkmn_types then -- add a space
entry[math.ceil(i/2)] = entry[math.ceil(i/2)].." "
end
end
entry[#entry+1] = localize("pkmn_level") -- "Level #1#"
for i = 1, #entry do
entry_parsed[#entry_parsed+1] = loc_parse_string(entry[i])
end
G.localization.descriptions.Other.POKE_Info.text_parsed = entry_parsed```
you need to define each pokemon type in the fancy box and the level string at ``G.localization.misc.dictionary`` and ``pkmn_types`` should be a table that includes all of that pokemon's types (defined as the same strings as the entries in the dictionary)
this code goes into loc_vars function before it returns the level
pokemon should store its types in config.extra because thats a thing that can change i think
you should put this into a separate function from loc_vars so you can have all pokemon calling one function instead of having a unique copy of it in each pokemon definition
They can just create the objects and add them directly
update on magic trick: i've decided to rewrite it for the joker retrigger api branch and then backport it into current smods
- as a part of the rewrite im going to try making things cleaner and more usable (for example a proper api for adding custom cardareas into the calculation)
hmm
is there a way to change the default values of a card when it's added to your deck? i want to change the suits i'm adding to have unique effects instead of just being +(rank) chips
(and have them not added to decks by default)
is Card:add_to_deck not an option
i'm not entirely sure how that applies to SMODS.Suit
oh
by "card" i mean "playing card", i probably should have specidied
in_pool = function(self, args)
if args and args.initial_deck then
return false
else
return true
end
end```
you can use that to stop them from spawning in starting deck
not sure about the other thing sorry
maybe you can hook to create_card?
been reworking the hell outta this joker, i think this is the 3rd revision
forced is definitely a better word there
cus it forces the selection on next hand
i'm like 80% sure add_to_deck also gets called for playing cards
so you can check if a card has your suit
I disagree
Every effect is already forced
You can’t refuse Jimbo’s +4 Mult even if it want to scale Ride the Bus
okay so what im getting is the forced is ambiguious
cus what it means is that the cards are forcibly selected
when added to hand
If first hand played has
4 or less cards, add an
Enhanced card to hand and
force it to be selected.
-1 hand size each ante.
they are
Premise: i understand what this code does but not too much
Question: changing G.localization.descriptions.Other.POKE_Info.text_parsed for a Pokémon doesn't change it for every other one?
that doesn't create any problems?
also: what would
G.localization.descriptions.Other['POKE_Info'] = {
name = 'Pokémon Info',
text = {
'...'
}
}
look like?
it technically changes it for every pokemon but if it's called before the textbox is rendered (i.e. in loc_vars, where this code is intended to be) then it will always be correct
it doesn't even rlly need a text there because all of the contents of the box are created through the code, what you need is the pieces for the constructor at G.localization.misc.dictionary
G.localization.misc.disctionary.pkmn_level = "Level #1# + an entry for each type
It shows black text with no colored box, did i do something wrong?
change the entries in the dictionary to have the colorful box G.localization.misc.disctionary.pkmn_grass = "{X:PKMN_grass}Grass{}"
Also need to add a {C: attention} into the level string
you can do a similar code for statuses too (if that's going to be a thing?) although you'd probably want more than 2 per line so you'd need a better solution for the spaces (the code I wrote just adds a space after every odd numbered type except the last one)
Currently the function looks like this
function UTIL.buildPOKEInfoBox(card, info_queue)
-- CODE BY @spad_overolls ON DISCORD
G.localization.descriptions.Other.POKE_Info.text_parsed = {}
local entry = {}
local entry_parsed = {}
local pkmn_types = card.ability.extra.POKEMON.Types
for i = 1, #pkmn_types do
entry[math.ceil(i/2)] = (entry[math.ceil(i/2)] or "")..localize(pkmn_types[i])
if (i%2) == 1 and i ~= #pkmn_types then -- add a space
entry[math.ceil(i/2)] = entry[math.ceil(i/2)].." "
end
end
entry[#entry+1] = localize("POKE_Level") -- "Level #1#"
for i = 1, #entry do
entry_parsed[#entry_parsed+1] = loc_parse_string(entry[i])
end
G.localization.descriptions.Other.POKE_Info.text_parsed = entry_parsed
info_queue[#info_queue + 1] = {set = 'Other', key = 'POKE_Info', vars = {card.ability.extra.POKEMON.Level}}
end
i tweaked it a bit so I can do this inside the Jokers
loc_vars = function(self, info_queue, card)
if POKE.Debug then
print(UTIL.print(card.ability.extra.POKEMON))
end
UTIL.buildPOKEInfoBox(card, info_queue)
end,
I'm too showdown-pilled I forgot the various statuses don't actually show up near HP bar 💀
you can't go cleaner than this
ok my idea is that after winning a blind with a Pokemon Joker, it gains XP based on the required chip score and it loses HP based on if you used more than one hand to beat the blind
I'd like to show these info inside POKE_Info
btw if that util. function is for printing a table, balatro already has a tableprinter
print(tprint(<table goes here>))
tprint my beloved
oh, worm?
does find joker use the joker name?
base find_joker uses joker name yea
yes but use find_card instead
is that an smods thing?
if you don't use find_card i'm killing you anyway
yeah
in my defense i didnt know
SMODS.find_card(key, count_debuffed)
thanks
i know tprint but I made a cleaner version of that function and I prefer to use that
nice
it prints any type of variable, not just table
and gives a difference between true and "true"
tprint is great but sometimes it doesn't fit the purpose (source - it's been really unhelpful to me with contexts)
I need to read more smods
it really bugs me that you can just print bools in lua
yea this is the first time i've heard about tprint lol
tprint: {
EvolvesTo= table: 0x63c208e64860 {
[1] = table: 0x63c208e648a0 {
TradeRequired= "false",
ItemRequired= "false",
LevelRequired= 16,
Name= "Ivysaur",
},
},
Level= 5,
Types= table: 0x63c208e64760 {
[1] = "Grass",
[2] = "Poison",
},
HP= table: 0x63c208e647e0 {
Max= 15,
Current= 15,
},
}
UTIL.print: {
"EvolvesTo" = {
[1] = {
"TradeRequired" = false,
"ItemRequired" = false,
"LevelRequired" = 16,
"Name" = "Ivysaur",
},
},
"Level" = 5,
"Types" = {
[1] = "Grass",
[2] = "Poison",
},
"HP" = {
"Max" = 15,
"Current" = 15,
},
}
btw is there any reason the pokemon info is in the info box instead of the main info box
ah
@frosty dock I apologize for the ping but I just saw the Steamodded Index PR and I was curious on formatting for multiple DLs if it's implemented yet or not.
"name": "Familiar - The Alternate Expansion",
"description": "A Balatro Expansion pack that adds alternate versions of Jokers, suits, cards, and more.",
"github": "https://github.com/RattlingSnow353/Familiar",
"versions": [
{
"name": "Latest",
"branch": "main"
},
{
"name": "Playtest (NOT RECCOMENDED)",
"branch": "Playtesters"
}
]
}
I would assume that this could do it, if I'm wrong let me know but I should be able to make a PR for a mod in the index
scoring_name is the name of the type of the played poker hand right?
something like that will do, but it's currently unimplemented and details may change
yea
aight
like 'High Card'
should be there now 😊
cant figure out what the problem is
now it says this :v
the 2 space indentation is hurting my eyes
its the default im pretty sure
im not actually sure why its giving an error from that snippet of code tho
balatro uses 2 and 4 interchangeably LMAO
could you send a wider ss so we can see the line nums
god its awful
it has the line nums tho
the card.ability.extra.last_hand should be above the return
oh right
still not very familiar with the return thing
thx
sorry for bothering yall but i simply dont understand
try a space between the return and {
other than that ive got no clue
the colours look correct so i doubt that is the problem
i think i got it gimme a moment
could you send a ss of the entire calc function?
nvm
only thing off screen is 2 ends
also i removed the do and end around the return
oh my god
is there a way to change the description of a Joker
since it'd be a pain to use loc_vars
and i cant change the number of lines with loc_vars
if it's only ~2 descriptions to switch between, you can change return the key in loc_vars and have an alternate description
it's what I had to do for my sleeves
loc_vars(self, info_queue, card) -> { vars ?= table, main_start ?= table, main_end ?= table, key ?= string, replace_debuff ?= bool }
Pass variables (vars) to card descriptions. Add tooltips by appending to info_queue. **You can force the use of a different description entirely (`key`).** Add additional text to the start or end of a card description with main_start or main_end.
i
why did i NEVER reread this
i swear this couldnt have been in the steamodded guide forever
HAHAHAHA I had the exact same response
not sure who pointed it out to me last time
Ah, Eremel did. Of course
What would be better, one button to press and it gives a dropdown of all jokers, consumables, vouchers and packs or should I work out how to still use the same output and mapping per list somehow whilst having 4 buttons, one for jokers, one for consumables, one for vouchers and one for packs all side by side where Add Banned Card is now? Granted I am going to work on having it that you can search and get filtered/auto completed responses. So if you know what you're looking for you won't have to scroll the entire list.
I feel like this is knowledge I had forgotten 🤣
Cannot for the life of us figure out why this is happening
It's happening from the x.chips effect in Jens, from the powercards??? Only from multichip and powercard. So.
Have you checked to see if the Xmult_mod.ogg sound file does exist?
yes and it doesn't, but that file path is specifying the balatro resources folder which, shouldn't be being called in the first place
idk we're frustrated
What is the command line being used to call the file in the first place
Vid of the glitch
Sorry for the stupid question, but in what scenario are 1x textures used? I'm making textures for the jokers and I would like to give more importance to the 2x and lower their size to make them 1x, and not have to edit twice.
Oops! The game crashed:
Syntax error: functions/common_events.lua:1116: '}' expected (to close '{' at line 1098) near 'play_sound'
Additional Context:
Balatro Version: 1.0.1g-FULL
Modded Version: ???
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta6
Stack Traceback
(3) C function 'function: 0x3819bc40'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 828
(6) global C function 'require'
(7) Love2D function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x3819e1a0 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x3819e1c8 (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) Love2D function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) Love2D function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(Love2D Function)' (defined at line 355 of chunk [love "boot.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"])
how i fix
the game chooses between 1x and 2x if pixel smoothing is off/on respectively
Do most people have it active or not?
Which should I prioritize more, 1x or 2x?
you can just make the 1x version, then upscale it to 2x
generally you make the 1x and then just resize it
tried to make a blind that turns a random card in your hand to stone
accidentally made it remove your card off of the face of the earth
guys
how do i fix this
Oops! The game crashed:
Syntax error: functions/common_events.lua:1116: '}' expected (to close '{' at line 1098) near 'play_sound'
Additional Context:
Balatro Version: 1.0.1g-FULL
Modded Version: ???
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta6
Stack Traceback
(3) C function 'function: 0x1555bc40'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 828
(6) global C function 'require'
(7) Love2D function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x1555e1a0 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x1555e1c8 (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) Love2D function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) Love2D function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(Love2D Function)' (defined at line 355 of chunk [love "boot.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"])
i really want to play grim
looks like a bad installation
Pretty sure that is an outdated SMODS issue
i cannot figure out how to enhance a card
card:set_ability()
thank you
You can make 1x textures and resize them later. You could even make higher resolution textures to use as 1x and scale those up for 2x, although you’d need a mod to configure it properly (although a simple one IIRC)
(I think for the most part you just need to configure the Atlas so it knows the size is different from the native size)
its done
Not the low definition 1X texture
The image was super reduced, that's why it looks like this in 1x
this is how looks in 1x
Is that reshuffled 2
ok
Ayyy my generator now can do banned cards, filtering the dropdowns based on input, modifiers, customs with and without values to be input, including set seed which is the only string input for custom. All I've got left now is writing the pack, other and tag dictionaries then it pretty much covers every aspect of a challenge file.
Anyone know where I could find a list for other entries? I'm assuming it's mostly the boss blinds as what I can find in the challenge file is {id = 'bl_plant', type = 'blind'}, {id = 'bl_wall', type = 'blind'}, {id = 'bl_final_leaf', type = 'blind'}, {id = 'bl_final_acorn', type = 'blind'}, {id = 'bl_final_heart', type = 'blind'},
But not sure if there's anything else
Such a pretty deck
Turns out deck = { edition = 'foil', type = 'Challenge Deck' }, works so long as you don't have any specified card entries and the entire deck is given that edition
gold_seal = true, isn't the command, seal = 'Gold'," is. Now I just have to experiement with what other full deck modifications I can toss into my builder
no_suits = {S=true, }, and yes_suits = {S=true, }, are fine to use and don't affect edition, seal or enhancement for the overall deck. yes_ranks = {['3'] = true}, andno_ranks = {['3'] = true}, also don't affect it. So you can mass enhance, edition and seal a pregenerated deck, just not use the cards = {{ command
So I'm getting an error on line 76, it says unexpected symbol near "return", can I not have two return statements? Or am I missing a bracket somewhere?
you have a stray comma on l75
Commas confuse me immensely
I also don't understand when context.individual needs to be true still
I keep throwing it into my code but I don't know what it means
might wanna read through this #1247703015222149120
I have! It's just long and difficult to parse
Ok, directed question. I have something that upgrades after each hand, so it does a lil +10 Mult after you play every hand. At the end of round, it resets. But that means it will add then +10 at end of round and then immediately reset it, which looks a bit gaudy. Is there any way to check that the round is over before context.end_of_round is set to true?
Edit: I just needed a more specific if statement! All good now
ooh nice! :D
Just checking, is there an easy way to access the count of hearts/spades/whatever in player deck at any given time? I figure the deck tracker displays suits so maybe I can just grab that variable
card.ability.extra.suit_count = 0
for k, v in pairs(G.playing_cards) do
if v:is_suit("Spades") then card.ability.extra.suit_count = card.ability.extra.suit_count + 1 end
end
something like this should work
Can I somehow update probability value for blind description?
use loc_vars param
It works, thanks!
I can't figure out why this isn't showing proper numbers.
name = "Coach Physical Instrument", --name used by the joker
text = {
"Gains {C:mult}#4# mult{} per {C:attention}Stone Card{} scored", --description text.
"{C:inactive}(currently +#4# mult){}",
" ",
"{C:inactive}Eyes on the ball, dinky winky!{}"
},
config = { extra = { mult = 0, x_mult = 0, multadd = 4 } }, --variables used for abilities and effects.
pos = { x = 0, y = 0 }, --pos in spirtesheet 0,0 for single sprites or the first sprite in the spritesheet
rarity = 2, --rarity 1=common, 2=uncommen, 3=rare, 4=legendary
cost = 5, --cost to buy the joker in shops
blueprint_compat = true, --does joker work with blueprint
eternal_compat = true, --can joker be eternal
unlocked = true, --joker is unlocked by default
discovered = true, --joker is discovered by default
atlas = nil, --defines the atlas that you want to use for the sprite sheet. atlas=nil if you want to use single sprites
soul_pos = nil, --pos of a soul sprite.
calculate = function(self, context) --define calculate functions here
if context.individual and context.cardarea == G.play and not context.blueprint then
if context.other_card.ability.name == 'Stone Card' then
self.ability.extra.mult = self.ability.extra.mult + self.ability.extra.multadd
end
end
if SMODS.end_calculate_context(context) then
return {
mult_mod = self.ability.extra.mult,
card = self,
message = localize { type = 'variable', key = 'a_mult', vars = { self.ability.extra.mult } }
}
end
end,
loc_def = function(self) --defines variables to use in the UI. you can use #1# for example to show the mult variable, and #2# for x_mult
return { self.ability.extra.mult, self.ability.extra.x_mult, self.ability.extra.multadd }
end
},```
The code functions fine. The description does not.
is this smods 0.9.8?
No, unless it's compatible with 1.0.0, which as far as I know it's not.
if this is 1.0.0 why is it 0.9.8 code
Well, this is the template I found. It said it was updated to 1.0.0.
Is there a different 1.0.0 template?
Maybe I'm stupid but this looks like the exact same format of code.
SMODS.end_calculate_context(context) is literally in compat_0_9_8.lua
yeah
im on phone rn so i cannot read that at all, ill be at my pc in 5 mins ish tho
instead of loc_def use loc_vars
It's 6 am and I can't go to bed without fixing this or I'm going to die horribly.
also calculate is missing card as an argument
How would I fix that?
calculate = function(self, card, context) + replace any mentions of self for card (self = proto object; card = the instance of the card running the code)
Description is still not working.
Oh, now the joker itself doesn't work either.
Okay, I'm calling it a night.
you need to reformat it to be 1.0.0 instead of 0.9.8 but yeah
Tomorrow I'm forcing myself to learn Lua.
local empress_joker = Ceres.CONFIG.jokers.enabled and Ceres.CONFIG.jokers.rarities.rare.enabled and SMODS.Joker{
key = 'empress_joker',
rarity = 3,
unlocked = false or Ceres.CONFIG.misc.unlock_all.enabled,
discovered = false or Ceres.CONFIG.misc.discover_all.enabled,
pos = {
x = 0,
y = 0,
},
cost = 10,
atlas = 'rare_jokers',
eternal_compat = true,
perishable_compat = true,
blueprint_compat = false,
loc_vars = function (self, info_queue, card)
info_queue[#info_queue+1] = { set = 'Other', key = 'cere_temporary'}
info_queue[#info_queue+1] = G.P_CENTERS['m_steel']
info_queue[#info_queue+1] = {key = 'red_seal', set = 'Other'}
end,
calculate = function(self, card, context)
if context.setting_blind and not card.getting_sliced and not context.blueprint then
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local _card = Card(G.deck.T.x, G.deck.T.y, G.CARD_W, G.CARD_H, G.P_CARDS['H_A'], G.P_CENTERS['m_steel'], {playing_card = G.playing_card})
_card.states.visible = nil
_card:set_seal('Red', true, true)
_card:set_temporary(true)
table.insert(G.playing_cards, _card)
G.E_MANAGER:add_event(Event({
func = function()
G.hand:emplace(_card)
_card:start_materialize()
return true
end
}))
end
end,
}```
example of a joker
for passing variables into the description
use loc_vars
wait i just realised this joker doesnt even return
💀
1 sec
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra, card.ability.mult_mod}}
end,```
there you go
smth like this in your joker
return a table called vars
and each index of the table corresponds to the variable numbr
Oops lmao.
['j_cere_accountant'] = {
['name'] = 'Accountant',
['text'] = {
"Gains {C:mult}+#1#{} Mult and {C:money}$#1#{}",
"if hand contains",
'exactly {C:attention}3{} cards',
"{C:inactive}(Currently {C:mult}+#2#{C:inactive} Mult)"
}
},```
This is my second ever joker. I am very much still learning.
🙏
card.ability.extra goes into #1#
for example
Tomorrow I'll look into recoding all of it in the new format with your advice.
if you have your code id be more than happy to reformat what you have at the moment, and then that might help when you make more jokers, because you can use the reformatted ones as examples
If I let someone else do all the work, I won't learn
(I dont want my code to be made fun of.)
ill reformat this if you want then
just as 1 example
leave the rest to you
Fair. I'll work on it tomorrow. For now it's 6 am and I will vaporize.
Sure, I'd like that.
yeah maybe get some sleep lol
how would i draw a custom shader on a card?
with edition its just done automatically
glass:draw_shader('dissolve', nil, nil, nil, self.children.center)
can i change dissolve to the shader key?
Yes
damn why didnt i think of that
is it possible to make my mod flip peoples monitors?
function create_reverse_card_ui(card)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.43,
blocking = false,
blockable = false,
func = (function()
local t = {
n=G.UIT.ROOT, config = {ref_table = card, minw = 1.1, maxw = 1.3, padding = 0.1, align = 'bm', colour = G.C.GOLD, shadow = true, r = 0.08, minh = 0.94, func = 'can_reverse', button = 'reverse_card', hover = true}, nodes={
{n=G.UIT.T, config={text = localize('b_reverse'),colour = G.C.WHITE, scale = 0.5}}
}
}
card.children.reverse_button = UIBox{
definition = t,
config = {
align= "bm",
offset = {
x=0,
y=-0.3
},
major = card,
bond = 'Weak',
parent = card
}
}
return true
end)
}))
end```
anyone got any ideas?
if self.config and self.config.func and (((self.config.button_UIE or self.config.button) and self.config.func ~= 'set_button_pip') or self.config.insta_func) then G.FUNCS[self.config.func](self) end```
thats the line causing an error
yeah im stupid
i hadnt made my button func yet
but was expecting it to work up until the point i pressed the button
like other ui things do
does SMODS.find_card return the card ?
Oops! The game crashed:
Syntax error: functions/common_events.lua:1116: '}' expected (to close '{' at line 1098) near 'play_sound'
Additional Context:
Balatro Version: 1.0.1g-FULL
Modded Version: ???
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta6
Stack Traceback
(3) C function 'function: 0x2117bc20'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 828
(6) global C function 'require'
(7) Love2D function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x2117e1a0 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x2117e1c8 (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) Love2D function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) Love2D function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(Love2D Function)' (defined at line 355 of chunk [love "boot.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"])
help
you probably forgot to close an if statement or a loop
Average ai gen goku l
bruh
Imagine posting the same crash over and over after being told the problem 🙃
i updated the steamodded

Eremel you're so right
i literally updated steamodded
i updated the mod i wanted to play
what else do i need to do
I mean all of your crash logs dont have a smods version, so I'd hazard a guess that you've installed it wrong
i downloaded it like i always did
And how did you do it?
try launching with just smods
Oops! The game crashed:
Syntax error: functions/common_events.lua:1107: '}' expected (to close '{' at line 1089) near 'play_sound'
Additional Context:
Balatro Version: 1.0.1g-FULL
Modded Version: ???
Love2D Version: 11.5.0
Lovely Version: 0.5.0-beta6
Stack Traceback
(3) C function 'function: 0x0486bc40'
(4) global C function 'require'
(5) main chunk of file 'main.lua' at line 828
(6) global C function 'require'
(7) Love2D function at file 'boot.lua:323' (best guess)
Local variables:
c = table: 0x0486e1a0 {identity:false, version:11.5, accelerometerjoystick:true, modules:table: 0x0486e1c8 (more...)}
openedconsole = boolean: false
confok = boolean: true
conferr = nil
(8) global C function 'xpcall'
(9) Love2D function at file 'boot.lua:362' (best guess)
Local variables:
result = boolean: true
(10) global C function 'xpcall'
(11) Love2D function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '(Love2D Function)' (defined at line 355 of chunk [love "boot.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"])
did you try deleting entire mods folder and then placing steamodded straight from zip
can you ss the top of core.lua in steamodded/core
ss?
screenshot
whats your full folder path?
show me core again
do you edit in notepad too?
no the folder
no
thank god lol
why would i?
still crashes?
well the default for lua files is notepad so do you manually open your mod files with another editor?
tbf my files all default to open in sublime text but I edit in vscode

oh
i guess i dont even know what mine open in actually
hmm, i think it means nil?
if G.GAME.current_round.hands_left > 0 and not G.GAME.modifiers.no_extra_hand_money then
omg thunk building in support for things that mods can use but he doesnt
yeah
is there better way to make dynamic colors 🤔 different color for different text
{V:1}
what's this
then pass {vars = {}, colours = {HEX('ffffff')}} iirc
the colours might be inside the vars table I dont remember
yeah its inside the vars table
oo thanks
loc_vars = function(self, info_queue, card)
local vars = {G.GAME.hands[card.ability.hand.hand_type].level, G.GAME.hands[card.ability.hand.hand_type].l_mult * card.ability.extra, G.GAME.hands[card.ability.hand.hand_type].l_chips * card.ability.extra, card.ability.extra}
local level = G.GAME.hands[card.ability.hand.hand_type].level or 1
local col = G.C.HAND_LEVELS[math.min(level, 7)]
if level == 1 then
col = G.C.UI.TEXT_DARK
end
vars.colours = {col}
return {vars = vars}
end,```
thats for planets
Thank you!
out of curiosity, why do Cryptid and Talisman folders need to be named exactly that?
I think it's to make sure the folders are loaded properly + whatever lovely shenanigans go on
hardcoded
Also hardcoded yes
ah
😠 damn you math
when its reading the files it needs to look in the folder Cryptid/whatever
if nativefs.getInfo(lovely.mod_dir .. '/Ceres/') then
Ceres.MOD_PATH = lovely.mod_dir .. '/Ceres/'
elseif nativefs.getInfo(lovely.mod_dir .. '/Ceres-main/') then
Ceres.MOD_PATH = lovely.mod_dir .. '/Ceres-main/'
end```
i did this
so you dont have to rename it if you download the main branch
might be a way to get current folder name but idk how lol
basically having a similar harcoding moment rn and was like "is that why cryptid"
