#💻・modding-dev
1 messages · Page 105 of 1
bump
guys i have tried every variation of this i can think of please
i don't understand
Because I'm 100% sure that skipping_booster is a valid context
Other jokers use it
And it works perfectly fine with other contexts
isn't skipping_booster a joker context used only by red card?
Are deck contexts and joker contexts completely different
And it's used in other things as well
yes indeed
PR #324 actually adds this and other joker contexts as deck contexts
I just haven't reviewed it yet
I can do that tmr I guess and then what you've done will work
Okay I'll just work on the other parts then
What are the contexts that are going to be added tho?
I'm about to go to sleep but feel free to check yourself https://github.com/Steamopollys/Steamodded/pull/324
Whats the difference between this and running the game through Proton? I can already get achievements on linux.
wayland integration and faster launch times
Oh, does Proton just use Xwayland for the game currently?
yea
Proton uses Xwayland
Beautiful
its part of a bigger project im working on
porting indie games to native linux without relying on Proton
and using their respective underlying engines/frameworks to handle the game instead
which means you'll get easier access to saves and sometimes even linux-specific optimizations from the respective engines
i think love2d has some linux-specific optimizations
less cpu overhead too since no more proton and translating calls to windows calls
Hey- I'm new to Balatro modding. I'm trying to make a joker which has all cards base their face value off the first card held in hand. How can I access the currently selected/played hand in is_suit? It doesn't seem to have access to context so I'm guessing I need to access something in G.GAME
not answering your question, there's no default way to make a card have multiple ranks like it does suits
so coding it would probably only make it work for vanilla and your own mod
As update is called every frame... that depends on FPS, correct?
it should afaik
Okay, then what about suits? Still need to access the first card
Hey gang, I have some questions about the take_ownership function
Why does it undiscover the jokers that I modify
Is it possible to make those modifications only take place on a specific deck? I have this almost by just putting it in the back:apply, but the modifications stay even when switching to a different deck
Okay nvm I fixed the first one but how can I make that revert back after I switch decks
Is that just a steamodded thing?
I guess I'm coming here
how do I set up a framework mod
I want other mods to communicate to a mod I'm making
do I need to do take_ownership or is there a better method?
@ me on a response please
You can look at #1300851004186820690 as an example for how they do it I'm pretty sure, I think all you need is to store whatever in the global variable G so that other mods can access it, and then they can have your mod listed as a dependency.
There's not already a cashing_out context for calculate_joker, right? I created this hook, but if one already exists, I'll just use that
-- Hooks into cash_out function to call calculate_joker()
local cash_out_ref = G.FUNCS.cash_out
G.FUNCS.cash_out = function(e)
for i = 1, #G.jokers.cards do
G.jokers.cards[i]:calculate_joker({ cashing_out = true })
end
cash_out_ref(e)
end
ooo got it
thank you so much
I have tried several different contexts and it seems that I cant get this to trigger at the right time, either cards_destroyed equals nil and causes a crash or the Joker simply does nothing (in this case, it does nothing)
Can you not just do an end of round check, or am I misinterpreting what you're asking?
no, I need it specifically when the Cash Out button is pressed
It pays money in the cash out screen, and I don't want it to upgrade the payout before it gives it to the user
Yeah, think you had to make it yourself, the closest guarnteed check after end of round is leaving shop, I believe.
still need help with this
silly 🤭
Hey why does this not work in the way it's supposed to? Burglar just works like normal
Does burglar have your mod's badge on it when you hover over it?
Odd, what happens when you change "burglar" to "j_burglar"? Shouldn't change anything, but it's odd you're not getting mod badges, unless you have them toggled of in the steamodded settings,
Yeah that didn't do anything
Yeah, no idea, it just doesn't seem like it's getting called if that's working fine, I can't think of what to check. Maybe add an add to deck function with a debug message, see if it's specific to burglar's calculate function?
I don't think I'm gonna worry about that right now
ok so I figured out that this works, I just need to make it where its specifically a glass card that gets shattered specifically when played
looking at glass joker's code was no good
Is take_ownership also able to modify the text or do I have to use lovely for that
oh I would imagine you'd be able to, unfortunately I can't help with that
you can just use a loc file (localization/en-us.lua)
Nvm I figured out how to use take_ownership
how can i set a cards variable? like if i want its mult to be 0 from start
nvm i don't know anything because this doesn't work for some reason
current attempt
if its not obvious, I need help here
this does nothing
I hate how just directly copying glass joker's code just doesnt work
Guys how would I actually make this work
and using take_ownership with loc_txt doesn't work either
😭
make a folder called localization and a file called en-us.lua in it
then do
return {
descriptions = {
Joker = {
j_drunkard = {...}
}
}
}
I'm trying to make it so it only modifies the description on a specific deck
I just realized this is leveling up the hand for every card played, not for every card destroyed
awesome
I genuinely give up with this joker, its a pain to create and I'm just annoying people
I'm working on smth else
I know that feeling
I sure do love when your code doesn't work for no apparent reason
And there's no error or anything so you don't even have anything to point to
oh yeah thats what I've been doing, didn't change much
ah
i forgor how you do this with loc_txt
but yea usually debugging what certain things are at certain points helps
rather than doing print("im over here")
try context.cards_destroyed instead of context.after
this triggers whenever any card is destroyed, and gives access to context.glass_shattered (which is the list of all cards destroyed, not just glass)
and then copy the entire code and use context.removing_cards instead of context.cards_destroyed and context.removed instead of context.glass_shattered
i hope that makes sense
See what I'm so confused about is like I'm literally doing the exact thing that this mod is doing but it just like doesn't do anything
And I tried doing it in that format too
With the brackets
Nothing
And I know that the take_ownership thing is working properly because the config change works
never used take_ownership so sorry can't help :c
It's fiiiiine
Are there any mods that add extra save profiles? It seems like a pretty simple implementation so would be surprised if there isn't one
you mean like this right?
well unfortunately this doesnt work
I'm so annoyed rn
i'm not a programmer but I imagine this is how is feels
tbh I should be going to bed its midnight lol
oh shit you know hexie too
also hi yes i did just follow you on bluesky
I saw LOL
was thinking about making a mod where you upgrade jokers (using money & consumables) but now it just sounds like a copy of fusion jokers
wait what version of lua does love2d use
11.5 iirc
oh idk
Love framework uses LuaJIT which is 5.1
ok got it
heyyyy chat, i want a variable that stays the same throughout the entire run, the idea is the joker gains mult every time its destroyed and then comes back
how would i do that? make a global variable or whatever
check monster from cryptid
any idea why this doesn't work?
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "local hand_text_set = false"
position = "after"
payload = '''
for k, v in ipairs(G.play.cards) do
if v.ability.name == "Diseased Card" then
local changed = false
if k > 1 and G.play.cards[k - 1].ability.name ~= "Diseased Card" then
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
blocking = false,
blockable = false,
func = (function()
G.play.cards[k - 1]:set_ability(G.P_CENTERS["m_pencil_diseased"], nil, true)
return true
end)
}))
changed = true
end
if k < #G.play.cards and G.play.cards[k + 1].ability.name ~= "Diseased Card" then
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
blocking = false,
blockable = false,
func = (function()
G.play.cards[k + 1]:set_ability(G.P_CENTERS["m_pencil_diseased"], nil, true)
return true
end)
}))
changed = true
end
if changed then
card_eval_status_text(v, 'extra', nil, nil, nil,
{ message = localize({ type = 'extra', key = 'k_infected' }) })
end
end
end
'''
match_indent = true
it changes the cards eventually, but only after scoring has finished. also, card_eval_status_text doesn't work
You could store it ideally as a G.GAME variable.
that would make sense !! is there anything i need to do to set that up or can i like
G.GAME.variable_name = number
okay so i tried that and it crashed lol
im guessing theres a specific way to set up a g.game variable
G.GAME variables can only be made and accessed during a run, so you usually want to do G.GAME.variable or defaultvalue.
ohhh like uhm. probability i see
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_gain } }
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.boomerang = card.ability.extra.mult + card.ability.extra.mult_gain
card.ability.extra.mult = G.GAME.boomerang
card:add_to_deck()
G.jokers:emplace(boomerang)```
how does this look?
boomerang is the tag of the joker so
what are you doing in remove_from_deck
okay well it didnt cuz the game crashed lmao
increasing the value of the global variable, then setting the mult to that value (which i just realized i dont need to do)
then giving the joker back to the hand
i don't think you should give it back like that
cus the game tries to destroy it still
no yeah i wont but
ohhhh
well the idea is
as long as you have space
it'll give it back at the end of the blind
and if you dont it wont come back
(its a boomerang)
You can probably have it set mult to G.GAME.boomerang or 1 on add_to_deck.
you end up having a non-existent joker
no yeah i did that !
All duplicate copies would share boomerang values, though.
well its card.ability.extra.mult = G.GAME.boomerang
but i assume thats the same because game.boomerang or 1 is what it is in the config
im fine with that lmao
Do you have it in add_to_deck specifcally, not remove_from_deck?
card.ability.extra.mult = G.GAME.boomerang
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.boomerang = card.ability.extra.mult + card.ability.extra.mult_gain
card:add_to_deck()
G.jokers:emplace(boomerang)
end,```
Anyways, when does the crash happen? On boot, on hovering over the card, what?
Give the crash screen, it's not from_debuff.
ok !
i can kindaaa read this
like, i understand its an error with the game part
since its nothing
What's line 87 in your code?
config = {extra = { mult = 0, mult_gain = 7, (G.GAME.boomerang or 1) } },
makes sense
What about config = {extra = { mult = (G.GAME.boomerang or 1), mult_gain = 7 } },?
i can try that !
would i need to change anything with the card.ability.extra.mult
oop crashed again
ohhh my god.
i realized one of the problems (i think)
i didnt add the g.game to the return vars
Actually, wait, just set mult to 1, you don't need the game variable in the config.
Yeah.
kk!
IT LAUNCHED THIS TIME !!
crashed upon SELLING IT so that is a change
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_gain, (G.GAME.boomerang or 1) } }
end,
add_to_deck = function(self, card, from_debuff)
card.ability.extra.mult = G.GAME.boomerang
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.boomerang = card.ability.extra.mult + card.ability.extra.mult_gain
card:add_to_deck()
G.jokers:emplace(boomerang)```
i assume this is where its fuckin around
mainly
G.GAME.boomerang = card.ability.extra.mult + card.ability.extra.mult_gain
this
Yeah, it's trying to read the mult after already being destroyed, so there's nothig to read.
replace card.ability.extra.mult in this with G.GAME.boomerang
nah tried that
gave the same thing but instead of mult being nil, game was nil
Stupid idea, you could have G.GAME.boomerang = {mult = 0, mult_gain = 0} in the add_to_deck, and access it from a global value rather than trying to use the card's value.
So you'd use G.GAME.boomerang.mult instead of card.ability.extra.mult, yeah.
Not unless you did G.GAME.boomerang = {extra = {values}, the extra is there to prevent most cards from triggering unwanted effects - you could just have it as config = {mult = 5} actually, but the thing is that it'll automatically give you the 5 mult during the scoring phase, so unless you want a joker that's just +4 mult with no unique effects or conditions like base jimbo, you usually don't want this.
right right ok ! i knew that but in this case was kinda weird
alright i'll try
ohh wait
hm
if G.GAME.boomerang is the config
then i think the actual value i want to keep
would be something else
unless i have it wrong
i think i just need to change some code if thats the case
no yeah i think i know what to do
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_gain, (G.GAME.boomerang or 1) } }
end,
add_to_deck = function(self, card, from_debuff)
G.GAME.boomerang = {mult = 0, mult_gain = 0}
card.ability.extra.mult = card.ability.extra.mult
end,
remove_from_deck = function(self, card, from_debuff)
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
card:add_to_deck()
G.jokers:emplace(boomerang)```
looks gooooood ?
well i need to change the G.GAME.boomerang mult_gain into a 7
but other than that
Wait, that won't scale,
You'd be setting G.GAME.boomerang.mult to 0 every time it's added.
ohhh yes true
resetting the value
i mayy have an idea
G.GAME.boomerang = {mult = card.ability.extra.mult, mult_gain = card.ability.extra.mult_gain}
end,
remove_from_deck = function(self, card, from_debuff)
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
card:add_to_deck()
G.jokers:emplace(boomerang)```
this is so stupid

"mult = mult"
Actually, try G.GAME.boomerang = {mult = G.GAME.boomerang.mult or 0, mult_gain = 7}.
alright !
what i did crashed anyways lawl
upon giving me the joker
but no yeah it uh
oh wait
in return vars
boomerang is or 1
and its or 0 in here
probably not the full error but maybe important
Actually, it's as simple as:
add_to_deck = fucntion(self, card, from_debuff)
if G.GAME.boomerang then
card.ability.extra.mult = G.GAME.boomerang.mult
else
G.GAME.boomerang = {mult = 0, mult_gain = 7}
end
end
huh!
i see
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult, card.ability.extra.mult_gain, (G.GAME.boomerang or 0) } }
end,
add_to_deck = function(self, card, from_debuff)
if G.GAME.boomerang then
card.ability.extra.mult = G.GAME.boomerang.mult
else
G.GAME.boomerang = {mult = 0, mult_gain = 7}
end
end,
remove_from_deck = function(self, card, from_debuff)
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
card:add_to_deck()
G.jokers:emplace(boomerang)
end,```
You don't need the game variable in the return, but I don't think it'd crash anything, but the mult at the bottom needs to switch over to G.GAME.boomerang.mult = G.GAME.boomerang.mult + G.GAME.boomerang.mult_gain.
okay !!!!! thaaaaat makes sense actually
since extra no longer equals it
thats just for the config
interesting
on selling the joker
wait
it might be
the from_debuff
i just directly copied this from the uh
tutorial
What's line 35?
thats. so weird. because thats a different joker.
chip_mod = card.ability.extra.chips,
Wait, nevermind, tht's cardarea.
since it says the issue is card i assume its with adding the joker
and i was going to remove that anyways because like, that was just for testing purposes
card:add_to_deck() doesn't have a card to read from, by the way. Look at the steamodded wiki, utility near the bottom, I think - learn SMODS.create_card, do local card = SMODS.create_card(stuff here), and then emplace()card.
okay !!
except im gonna get rid of that because again, just testing lol
but i might need it later for uhm
when the blind is over
okay, didnt crash on sell
AND
IT SCALES
WHEN I GET IT BACK
THANKS A TON MAN WOOHOO !! will probably need more help later
lmao
Yeah, it was interesting to think about.
funny inside joke is
another joker from the same mod
is called the Crash joker
slowly increases in chance to disappear as you play it
and the temporary card art IS the crash joker
so it was really funny to have the game crash with that as the art
hello! is there a special thing i have to do in order to require another lua file in my mod? is it just as simple as doing a regular require?
SMODS.load_file, see https://github.com/Steamopollys/Steamodded/wiki/Utility
Would there be a way to check when a 1 in chance succeeds or not? Whether it’s from a joker or lucky card or whatever
I have an idea but I don’t know if such a thing is possible
not really
events is very broad lol
if there's a specific thing that has a chance to happen, you can patch into it to catch it
there's a bunch of chance based jokers too
No yeah !!
you can find all those individually too but you get no support for modded jokers/enhancements
I just mean
Ohh yeah I guess ?
I can detect it they activate their effect
But like you say nothing applicable for modded stuff
you'd have to patch into each calculation separately
and if you just fetch all then you're also taking in every playing card draw, every shop card, etc
so yea gotta ^^
which is wayyyy too much work even if I like the idea lmao
It was gonna be every failed 1 in chance the joker gains xmult or smth like that
Hey I seem to be having an issue where text values aren't being set correctly or something. I'm trying to create an Erosion-like joker but for mult mult and when I look in the collections it sets the text properly (first image), however it sets everything to nil in the joker list in a run (second image).
Code below (ignore the name and key I haven't slept):
SMODS.Joker {
key = "hi",
loc_txt = {
["default"] = {
name = "hi",
text = {
"{X:mult,C:white}X#1# {} Mult",
"per card under {C:attention}#2#{} in your",
"{C:attention}full deck",
"{C:inactive}(Currently {X:mult,C:white}X#3# {C:inactive} Mult)"
}
}
},
config = {
-- 300 is placeholder
extra = { Xmult = 300, deckSize = 52, mult_total = 1.0 }
},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult, G.GAME and G.GAME.starting_deck_size or 52, card.ability.extra.mult_total } }
end,
unlocked = true,
discovered = true,
no_collection = false,
rarity = 1,
cost = 0,
blueprint_compat = true,
calculate = function(self, card, context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.extra.mult_total } }
}
end
end
}
seems to work for me
though when playing a hand, it shows that the card gives x 1 mult, i think from the mult total not being updated
did you spawn the joker then re-enter the run after making changes? you need a new joker for it to fully update
also you can find total deck size from #G.playing_cards
Damn I figured it would be something as simple as this. I kept using the same run with the same joker.
Oh cool thanks, I was gonna try to find a way to do this but I went with a temporary solution while trying to monkey patch things together.
:P
Also how did you just, spawn the joker?
the debugplus mod
Tyty
if you hold tab it shows all the commands
anyone a kamen rider fan im thinking of making a full on KR Gotchard or Blade mod
101 chemies into jokers would be a nightmare tho lmao
ryuki cards can be consumable
decade can also be consumable? or playing cards
chemies and undeads are jokers
Photograph does something similar, in a roundabout way, maybe try looking at its definition
is there a way to make a joker randomly spawns in a run
if you start a blind then a joker would appear on the joker area something like that
Pretty sure you'd have to lovely patch that in
Hello, quick question: Is there a way to look and for example, change the suits of an entire deck?
... and the same thing but look for only a specific suit?
you mean joker evolution
yeah easily you just iterate through the deck
and you do that with for index, value in pairs(G.playing_cards) do
i think it can do ipairs too idk the difference honestly
value is the term you use to refer to the card here
so to check the suit you do value:is_suit("Suitname")
i don't know how to change the suit but it's probably not that difficult
-# to this day I still don't know what in pairs means
pairs takes the table that you give it and returns the key and value for each entry in it in turn
Surely surely someone has already made Xchips for me right right?
yep, exists in talisman
could someone give me that piece of code so i can yoink it real quick?
or like where I can find it, idk
fuck
how'd you lose on cryptid bro 😭
weak smh
also my first run lol
https://github.com/MathIsFun0/Talisman If you choose to have Talisman as a required dependency, you can use Xchip_mod in the return freely.
return {
message = localize({ type = "variable", key = "a_xchips", vars = { card.ability.extra.x_chips } }),
Xchip_mod = card.ability.extra.x_chips,
colour = G.C.CHIPS
}
Thanks. now I have to figure out how to do just that, lol.
Which type of header you using for the mod?
... what
how did you even do that
looks like he's tried to throw it in loc_vars return
I've figured that much, but why would there be a var in the loc_vars return...
🤷♂️
Because I need the text to change every played hand.
And not just a number.
I need to change the text color, background color, and the trailing text Chips <> Mult
I'd use different loc entries for that
you can return a key in loc_vars and it'll use that instead of the joker key to get the loc
So this?
Continue
add a localization entry in your loc file (assuming you have one) with a different key
then you'd give it a different key depending on whatever
me have no localization file
you should
I still don't, and I think one isn't really required here if you define it earlier in the script.
Though, I probably will eventually move stuff over to a localization file, still need to figure that out.
it isn't, you can use any process_loc_text function
but it's common practice because it's the only way to allow your mod to be localized
I don't know how to set a localization file
look at pretty much any larger mod for 1.0
^ only has his own mod, steamodded and talisman installed
pft excuses
simply download #1248287850512781452
🙄
To be fair, maybe a localization file example wouldn't be a bad idea.
if you add loc_txt to a joker you can get steamodded to dump localization and make the file for you
tis certainly a method
yeah that sets things up for you, but make sure you don't run any other mods that add localization strings while doing it
well if they have no other mods than talisman, steamodded and their own mod
it should be alright
i do not like this
how many times should the end of round context trigger, i think it's supposed to be once but it seems to trigger 17 times?
here we go again
this is a commonly known thing i'm sorry :(
if context.end_of_round and not context.repetition and not context.individual then
the end of round context is so annoying
oh thanks
fair
it takes playing the same flesh card
10 times for them to be as good as steel when held in hand
and steel can still be played and not give X0.5 mult
its just not worth it
i didnt want it to be X0.1 held Mult because it'd scale too fast possibly
dunno tho
i'll just have to test
or change effects
i think it conceptually just cant coexist with steel
its either going to make steel worthless or be worthless because of steel
hm
id change effect
yeah probably
maybe instead of giving X0.5 mult when played it could get debuffed when played, and then give +mult in hand instead of Xmult? would definitely have to be on a tarot instead of a spectral if you changed it this way
makes it synergise with steel cards instead of competing with steel cards
hm, i'll think about it
oh yeah I get this all the time
Fusion Enhancements. 🧠
one of my jokers activated its effect 8 times at end of round
me having to review the quantum enhancements PR
Jimbo going Nuclear.
Guess I'm doing localization file migration before I finish the animated one...
jimbo update
not sure if its balanced or not
you can always balance it after playtesting
hello, quick question: how do I make so a joker fires after a card gets retriggered but not after?
have someone made a mod where joker can randomly spawn in a blind
Nevermind, I maade the janckiest solution ever.
Hey does anyone that's online right now know how to do this again?
I've tried this ```
[[patches]]
[patches.pattern]
target = 'localization/en-us.lua'
pattern = '''text = {
"{C:red}+#1#{} discard",
"each round"
}'''
position = 'at'
match_indent = true
payload = '''
text = function()
local desc = {}
if G.GAME.selected_back.config.ttr_red then
desc = {
"{C:red}+#1#{} discards",
}
else
desc = {
"{C:red}+#1#{} discard",
"each round"
}
end
return localize(desc, self.config.d_size)
end
'''
And this ```
SMODS.Joker:take_ownership("drunkard", {
loc_txt = {
name = "Drunkard",
text = {
"{C:red}+$#1#{} discards",
},
},
config = {d_size = 5},
discovered = true,
})
Neither of them do anything
And drunkard is a bad example because it modifies literally one thing and that's it but I have other ones where they need to be entirely reworked and I need that to show in the description
You can’t lovely patch localisation files
Good to know
arent multiline pattern patches also like not a thing
What doesn’t work about the take ownership?
It just doesn't do anything
I’m sure someone was using one the other day
ah gotcha
Like this is the full thing, config and discovered work just not loc_txt
...can't you do a function for the text field instead? That way, you can do checks in the functions and return an appropriate table.
You could always just throw it in a loc file
I'm gonna try that
And if I make text a function with and ifelse statement that should work properly right?
Hmmm
I'm gonna try a few different things and see if they work
Because I'm pretty sure it's just that take_ownership doesn't work with strings
Or something like that
Actually, loc_txt can take functions.
They do execute during initialization only, though.
smods helper function for reloading a cards loc_txt when ...
So do you think that the initial goal of having it's description be modified with a specific deck is just not possible?
Wait
You can do that
Like this?
No
You’ll need to create a loc_vars in your take ownership call and have it return a different key depending on your back being selected
Then in your localisation file you have the two alternate descriptions (or probably just your new one if it should use vanilla without your deck)
they are but methrul forgot
Would I still need to use loc_txt?
Or can I just use loc_vars and localization
don't need loc_txt if you are providing localization
how might you make the badge color of a consummable type cycle through the rainbow?
SMODS.Gradient when
lol
you need to update the colour's values every frame
whats a funciton that triggers every frame?
Game.update is where the game does it iirc
also how do you make a color out of hsv
iirc theres a helper for that somewhere in the code
I haven't done much with colours
maybe that was in shader land
idrc
no there's a function, but idr what it was called
also, im trying to get objects to not spawn at all in its original sets
?
i found omit = true, but that doesnt change the set item counts in the menu
this joker for example
I did find https://love2d.org/wiki/HSL_color
it shows up when you go into the joker page of the collection
but the joker section still says 150/150
i want it to stay in the collection
i just want it to only appear in a custom pool
just set a custom in_pool function
wait waht are the args for that
uhh idk
cuz it doesnt say n the steaodded docs
based off the docs it seems like args is just a table
how do i see the possible table entries?
i need to check the actual pool its in
seems like it's whatever the games in pool passes
probably just print it out and see
how do i print a table lol
tprint or inspect
bump
or require('debugplus-util').stringifyTable if you're feeling fancy, have DebugPlus, and don't mind using unstable api's
did you actually print it?
print(inspect(args))
inspect just stringifies the table
args.source is whatever create_card has as an append key (RNG source)
My internet is sucking rn
inspect is part of smods, tprint is part of balatro
what even is the point of a whole args table if theres one arg
albeit that still works as a way to discern them
there can be other args
also future proofing
like initial_deck for suits/ranks
and we don't want to end up with 50 function params because we kept adding more
yay managed to get a system that works
am I getting closer
uh not quite
more like separate j_drunkard_red next to normal j_drunkard with own name and text
isn't name supposed to be a string and not a table?
yeah it's meant to be a string
Oops
else you'll probably hard crash
I mean I didn't hard crash
The name just didn't appear
And it still doesn't
I think I'm calling key wrong
yeah that's wrong
oh wait theres also a traling _ here
just put j_drunkard_red as the key
Is j_drunkard_red a global?
key = ‘j_drunkard_red’
I tried this but I'm still having issues
oh my god finally I'm so happy thank you
oh nice
Oh god indentation pls
Okay so now there's only one problem left that I need to solve before I just have to wait for SMODS to get updated so I can call on more contexts
My intention is that it only reworks the jokers while the deck is currently selected
oops yeah right
However, currently it makes it permanent after I select the deck, like unless I close the game then drunkard will give 5 discards, when I want it to do that only for the deck
if your just adjusting the config you should be able to store the original and reset it
You can also just give it a custom calculate that checks the deck first
you should change the config from set_ability
or this
i cant stop asking for help
is there a mod funciton?
like the mathematical modulus operation
So just mimic the calc function of the original joker but just add a check?
Yes this would work
why isnt dt gertting passed correctly through this hook?
Put (self, dt)
ok
something interesting I noticed is that nothing prints, with or without context.destroying_cards, even when glass cards do indeed get destroyed
what am I missing
still having a stroke
ok
That isn’t a valid context
Oh yeah you don’t have the : in the definition
ah, thats weird
You should use if context.remove_playing_cards then and then look through context.removed to identify the glass cards
and the base game in fact does not have an hsv function at all
I was told to use context.removing_cards for some reason, that mustve been the problem the whole time
Probably needs to be a table
Is it supposed to level up hands when glass cards break?
yup
ok
Okay you don’t need three different parts, just use the if statement I sent then loops over context.removed, do your glass check and then level up inside the loop
the error got worse!!!!!!
Might need an alpha channel too?
yeah when I saw glass joker's code when mine wasnt working I thought I had to do wacky junk whoops, tysm
im gonna inspect a hex value
yup alpha channel
yep it does that
...do I have to do things the Cryptid way if I want to influence values of a different card, be it a Joker, consumable or playing card?
its both not changing
and also bugged looking
if only i had the gradient system lol
that works!!!
finally oh my god
THE COLOR CHANGES!!!!!
but it still doesnt change after initially rendering things
so it stays at that color forever until it gets reloaded
how might i fix that?
So I have this but this gives me 6 discards, presumably because the original drunkard's function is still there, how would I fix that? (Ik I could just do ease_discard(4) but that wouldn't give the +5 on the UI)
How does it look on the card badge?
does someone know how i could add text here
You could always change the size of the text like
"+2.5 chips",
"{s:0.8} smol{}"
I think at least
also unchanging
trying to make this, can anyone provie some help
If you print the colour table you’re changing twice is it different?
That's a hand right?
yea
I don't know how to do that but here's the wiki page for poker hands https://github.com/Steamopollys/Steamodded/wiki/SMODS.PokerHand
imm thinking the problem is that i need to find a way to access the badges and the consumable types entrance that smods mmmakes directly and change the color there too
nothing really helps me there
Oh hang on
The colour will be where the secondary colours are saved
I don’t remember where it is off the top of my head
Try G.C.SECONDARY_SET.Place
Assuming place is your key
hey chat, im trying to figure out the SMODS.create_card(t) function but im a little loss on . where to put things i guess?
i really just need a solid format structure for it i guess
and im on the wiki i just would like a more specific explanation
any poker handers able to provide help :) im trying to code this
check moddedvanilla.lua's guide on walkie talkie !
helps with card id's
it will look like
SMODS.create_card({
set = "idk",
rarity = 485075,
)}
replace with actual args of the normal one
no yeah ofc
if i want to do the same thing twice would i just
copy paste the code lmao
my problem is that it does access secondary_set.place, but only when initially creating the buttons and badges
🤔 so it changes each time you hover over the card?
Even the badge?
thats how it feels
oh in play it changes every time i hover
speaking of doing things, how would i check the current edition of the joker via the joker?
iot does it too in the collecvtion
like check its own edition
the button for the type in the collection changes when reloading
please can someone tell me how to o this
all i want is a han that only works if you have a 3 1 an an ace in it
i finished localizing but there are some weird stuff i want to work out
i tried patching misprint word order but failed spectacularly
me when cards don't have multiple ranks at once
Also there's no context so no context.other_card in poker hands
how do dis with misprint
it uses a main_start or main_end I think
look its a work in progress im tryin my best i on know how to make a han type which only activates when your han has specific ranks
which is a fully custom UI element so you might need to override it completely using loc_vars/generate_ui
then iterate thru the cards in hand and check if each rank is present
This one part took like 3 hours to learn how to do
I'm so happy rn
BECAUSE NOW I CAN DO IT WITH ALL THE REST AND IT'LL BE E A S Y
what does that mean
This button placement is still cursed and I hate it 😡
do you have basic programming knowledge?
Where should it go
They should just be decks
Ehhh I like how it is rn, it's more faithful to TBOI's way of doing it
nah that's lowkey cursed
does this work without galdur?
Nah galdur is a requirement
maybe when I learn how to do UI stuff I'll fix that
yeah but not this because i haven't used this until now 😭 why did i get into thisss
btw in the bottom
of the deck desc
bbbut.... cool style points
I can't take you through every step and a time and assume no prior knowledge, I'd go insane
Counterpoint: it looks cool and the whole point is that it's based off of tainted characters
then can you at least apply it to every deck?
I'll get there when I finish the art for all of them trust
Unless you’re doing it for every single modded deck it doesn’t look cool
It’s just a redundant button on almost every deck select page
change the tattered button to have different colors when up and when pressed because it looks very weird
also i feel like the tattered button should send you to a wholly different page with tattered versions of all the decks
I think that's the end goal
Because like
This is how I want it to look
Would that be too hard to implement
oh dude this is insanely cool
im not the guy to help with that lol but i imagine not
new screens arent much of a challenge
where are the lists of registered enhancements and editions stored?
...huh
G.P_CENTERS my beloved....
i mean it makes sense lmao
G.P_CENTER_POOLS.Edition or Enhanced
i hate that its not G.P_CENTER_POOLS.Enhancement
was just confused on how those collective smods tables existed for some objects and not others
ty
enhancement, editions, jokers, consumables etc. all derive from SMODS.Center, so they don't have their own collective tables
they don't need to, the base game doesn't have them either. it just has pools
that sounds awful
centers don't stack
so no enhanced cards with seals no more
do you guys know exactly when the game overlays the seal sprite onto the normal card sprite?
somewhere in Card.draw 🙄
Editions and enhancements stack though
got this crash after deleting the card, aka removing it from deck
remove_from_deck = function(self, card, from_debuff)
SMODS.create_card({
set = 'Joker',
key = 'you_idiot',
skip_materialize = true
})
i dont exactly know what it means by center
i assume thats meant to be a variable
in the table
wait yeah editions are centers
I think you're supposed to use the full key, complete with the mod prefix.
ohh so like
I can't pretend now I don't think that's also cursed
j_prefix_you_idiot
ty !
where prefix is your mod prefix
Yes.
kk thanks !
Stickers are also bad
Assuming I access values of a given instance of the first Joker card held (specifically the config) via G.jokers.cards[1].children.center.config?
yeah stickers are even more cursed
Getting stickers to work with textures was a chore
Like the floating sprite on the soul
children.center is a Sprite
i just had a wonderful idea.
if you replace children with config that should work
any reason you can't use the card's ability though?
yeah you need to do some other things with the card it returns
specifically you should call add_to_deck on it and emplace it into G.jokers
...right, I actually meant that, whoops. Trying to modify values of the Joker.
yeye
local _card = SMODS.create_card(...)
_card:add_to_deck()
G.jokers:emplace(_card)
I think that's all?
actually i have an idea
yeah you definitely should use the card's ability table then. Else you're modifying the prototype which might persist into other runs and onto future jokers of the same type
can you apply stickers to playing cards?
you had it in remove_from_deck
mhm
yes
yesssss
though you should maybe rule out from_debuff, remove_from_deck also gets called when your joker gets debuffed
ohhh i see
yeah i just used a template lol
SMODS.create_card({
set = 'Joker',
key = 'j_melon_you_idiot',
skip_materialize = true
})
local _card = SMODS.create_card(...),
_card:add_to_deck(),
G.jokers:emplace(_card)
end```
just gonna double check that this is good
though i might be
compeltely wrong lmao
im like super good at following instructions as long as the instructions are very carefully planned out haha
fair point
uh not like that
no yeah i imagined not
I thought it was implied you actually put the args you already had in place of my ...
like that's clearly a placeholder, it just happens to be valid syntax too
how do i fix the big fat error
uh is that a mod badge
no
thats the red stud badge
also, how does the calculate function work on playing cards?
for stickers
assuming that's a sticker?
yes
I'm not positive it does
i need a version that works similarly to the enhanceent one
playing cards don't have a native calculate function for stickers, but Cryptid (and my mod) have added support for stickers on playing cards
alright completely rewrote it and it works !
@fallen tendon
-- Sticker compatability for playing cards (from Cryptid)
local ec = eval_card
function eval_card(card, context)
local ret = ec(card, context)
if card.area == G.hand or card.area == G.play or card.area == G.discard or card.area == G.deck then
for k, v in pairs(SMODS.Stickers) do
if card.ability[k] and v.calculate and type(v.calculate) == "function" then
context.from_playing_card = true
context.ret = ret
v:calculate(card, context)
end
end
end
return ret
end
in the SMODS.Sticker() register you can add a calculate function with args self, card, context
SMODS.Sticker calculate in base steamodded only works on jokers though
Hey gang, I have a few ideas for how to rework mystic summit to be balanced around Tattered Red deck (Hands/discards don't get replenished, but they can be gained through various actions). Which do y'all like the most?
which is why you have to hook eval_card to add playing cards with stickers
okay so, the problem with the card is that its supposed to add 2 of itself when you remove it, but it will add 2 despite the joker slots
what variable would be the amount of space in your joker area?
i assume g.game. something or other
okay, i understand #G.jokers.cards easily enough, its how many jokers you have
wasn't there a setting for the soul jokers that'd enable shared shaders for the soul? (for ex. if the base has foil, the soul also renders it)
but how exactly does G.jokers.config.card_limit work? like, how would a joker use that ?
probably easy to just make it if #g.jokers.cards is 4, only create 1 blah blah blah but i still would like to know
you can compare the two and stop creating cards if they're equal
Isnt x3 mult when 0 discard just sunset
dusk?
Yes
That's retriggering cards on last hand
Can I have an extra config (that's not accessible via card.ability) for a Joker that is separate?
Acrobat is x3 mult on last hand
There
So its a better accrobat
Basically
Well
When you have 32 discards and replenishing hands isn't a given then it's pretty much only relevant in end-game
I think I might do the first one because that's more in line with how I reworked dusk and acrobat
Unless people really want the third one
new util func
whats the context for using a consumable?
and is there like a list of contexts to make it so i dont have to ask questions so much lol
context.using_consumeable
thx!!
and yes
also no that is not a spelling mistake
it's actually consumeable
i mean i guess i should say it's not a spelling mistake on my part
RIGHT i remember this list i just. forgot about it lol
Hello, quick question: How can I make so a joker chooses between an interval of 2 numbers randomly?
is this just SMODS.Mods[arg] or does it do more?
checks if it can load and also checks provides
checking this previously had some non-obvious boilerplate so people weren't doing it correctly
ah makes sense
whats the behaviour if multiple mods provide the id
now that provides is fully functional, even that isn't fully correct anymore
or there is the mod and the provide
find_mod will give you each mod that provides the ID
potentially multiple times if you provide different versions
oh neat
provides got an extra table SMODS.provided_mods that store them per-id with reference to the providing mod
i.e. each SMODS.provided_mods[id] is an array of tables with a version and a mod
Hey guys how does the juice_card_until thing work?
check how misprint does it
pseudorandom(seed, min, max)
Thanks you.
Like I know this is definitely not correct
put card instead of self
Hmmm, that juices the card only after it activates for the first time hold on
And it also juices multiple times per hand
Weird, it only outputs the mininum and maxinum values.
what are your min/max values?
@frosty dock how is the multiplayer mod for balatro looking so far?
0.75 and 1.5
been a while that I played with it, i think it got updated tho
ah, pretty sure it's integers only
god dammit
pretty easy to get around depending on the precision you want
mhm
trying to put echo chamber from TBOI into the game, and im trying to make it so basically every card has a chance to be the fool
end,
calculate = function(self, card, context)
if context.using_consumeable then
if G.GAME.echo == nil then
G.GAME.echo = context.consumeable
else
if pseudorandom('echo_chamber') < G.GAME.probabilities.normal / card.ability.extra.odds then
local card = (G.GAME.echo)
card:add_to_deck()
G.consumeables:emplace(card)
end```
but it just doesnt give the card
actually i may have an idea
ok nvm the idea didnt work
G.GAME.echo = {card = context.consumeable}
else
if pseudorandom('echo_chamber') < G.GAME.probabilities.normal / card.ability.extra.odds then
G.GAME.echo.card:add_to_deck()
G.consumeables:emplace(G.GAME.echo.card)```
im using oops all 6s to make sure it activates
just merged it
wait did steammodded just update
you can just use SMODS.OPENED_BOOSTER for this, it's the card of the booster pack that was opened
yes
cool
individual and repetition are separate contexts and they don't overlap
Reworks!!!!
neato
c_base
Hey where are the G.STATES listed?
that is the list of them
i like the acrobat and dusk one the delayed gratification is also good but can give you less money technically
I mean if it worked like normal than if you got it early then you're getting $60+ every hand
So I just have it fixed at 8
anyone have a good guide on mod making?
there's a couple of videos but you're probably best just reading the documentation
depends how experienced you are
simple programming knowledge should be more than enough
https://github.com/Steamopollys/Steamodded/wiki
thats how to install it lol
ahh sorry mb lol
hi im simply looking to make it to where it plays a sound effect depending on what hand you play (like in Poker Night at the Inventory)
SMODS.Sound handles it
then just do an if statement based on the hand return true
alright
I'm confused, why does the crash say that ability is nil when I've defined them in set_ability
Help, how do I give color to the text and background badge thing?
Here's that crash report
Oops
Like it works fine when I do it here
And why does it still add mult when I've made calculate be xmult
How do I override it
look at the localization files of the base game and you may be able to understand how it works (unzip the exe file with smth like 7zip)
Alright.
OH wait the badge shit, its related to the json file to your mod
anyways, idk how to get this workin
yes I've done function Card:is_suit(suit, bypass_debuff, flush_calc) aswell but it did nothing
do I have to do card.base.suit instead actually?
Card:is_suit(suit, bypass_debuff, flush_calc) is the correct signature
alright good to know
if it still crashes, show the new crash pls
ill try this again
no crash, simply does nothing and does not allow me to play a flush with diamonds and spades
So, any ideas?
if you're talking about the badge that has a white bg and white text
set_ability = function(self, card)
if G.GAME.selected_back.effect.config.ttr_red then
card.ability.extra.mult = nil
card.ability.extra.Xmult = 4
card.ability.extra.d_remaining = 0
end
end,
calculate = function(card, context)
if G.GAME.selected_back.effect.config.ttr_red then
if context.joker_main and G.GAME.current_round.discards_left == card.ability.extra.d_remaining then
return{
message = localize{type='variable',key='a_xmult',vars={card.ability.extra.Xmult}},
Xmult_mod = card.ability.extra.Xmult
}
end
end
end,
loc_vars = function(self, card)
if G.GAME.selected_back.effect.config.ttr_red then
return {key = 'j_mystic_summit_red'}
end
end,
unlocked = true,
discovered = true,
})```
It is not tied to the mod badge thing.
I dont think thats even supposed to appear
I know because I have it set with other colors.
So for some reason this doesn't do anything and it doesn't overwrite the original one for some reason
Like it just gives +nil mult now which isn't helpful
doing that and changing self to card does this
no, still use self
alright
then check the logic i guess
nvm I figured it out
with this code, I realize that it does print, but does not consider the hand a flush
is there an event that triggers when hand downs happen?
i need the event that triggers G.GAME.current_round.hands_left to = G.GAME.current_round.hands_left-1
hook to ease_hands_played
no like i need it in a joker calculate
i need it to run like at the end of a hand played, assuming the blind isn't complete
rn i have if not context.end_of_round and context.after and not context.repetition then but this is triggering everything minus the return early
oh wait
context.final_scoring_step?
ahhh
that does nothing
😭
oh wait
hm
making this joker print woo and yeah is the funniest thing actually because it did this when it worked