#💻・modding-dev
1 messages · Page 588 of 1
and the default one should be the default joker, right?
by default cards that are in play anywhere get excluded from the pool
excluding enhancements and editions
alrighty
i dont think playing cards are excluded
wdym
they definitely are
otherwise you would get defaults as soon as you have one of each enhancement
no like the base cards
if i have a ten of clubs i can still get another ten of clubs
from standard packs
yeah
correct
you can
because ranks and suits arent even centers so duplicates can appear by default
me when i cardboard
about this code mr seals,how do i update the local word to be split into 5 (i want to check each individual later to see if every letter is arranged properly for wordle)
or alternatively how do i check the first letter of the local
local letters = {}
for i=1, #word do
table.insert(letters, word:sub(i, i))
end
do i make 5 of those for each individual one?
No, it makes a table called letters and puts each letter in it.
so how do i call each individual letter?
or well not call
but check
letters[3] would be the third letter.
local my_pos
for i=1, #G.jokers.cards do
if G.jokers.cards[i] == card then
my_pos = i
break
end
end
G.jokers.cards[2] is the second joker if thats what you mean
then what is the point of my_post if you mind me asking
my_pos is the position of the joker itself
so if i want to check the first letter of the joker in the second position do i need my_pos[2} or G.jokers.card[2]
weird how in local letters the letters is the table but here it is
im learning something new everyday
is this how i would do debuffing cards of a certain rank
No, it's debuff = {value = '2'}
how to add joker slots?
look at blackdeck in vanilla remade
ok thx
black deck does it via built-in deck functionality
for anything else its G.jokers:change_size(mod)
for multiple values do i do
debuff = {
value = '2', '3'
}
would both of these work?
local passed = true
for i=1, #word do
local joker = G.jokers.cards[i]
if word:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
-- code
end
local letters = {}
local firstletter = {}
for i = 1, #word do
table.insert(letters, word:sub(i, i))
end
for i = 1, #word do
table.insert(firstletter, getJokerName:sub(i, i))
end
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
my_pos = i
break
end
end
if context.joker_main and G.jokers.cards[1] then
if first_letter{1} == Letters[1] then
return {
message = "test",
}
end
end
i currently have this
any reason this would /wouldnt work?
besides the second table doing #word twice
Yes, it wouldn't.
how come?
besides the 2 fixed typos
first_letter and #word on
What is the goal?
play wordle with the first letter of the name of the joker
(for example runner would be r)
Okay, can someone help me with making blackjack as a boss blind?
You mean for the joker to trigger the first jokers first letter of its name needs to be the same as the first letter of the wordle word?
no currently im making a deck and if you spell out todays wordle all your jokers trigger again
So the first five jokers first letters of their names would need to be the same as the wordle word for all jokers to retrigger?
yes
if context.retrigger_joker_check then
local passed = true
for i=1, #word do
local joker = G.jokers.cards[i]
if word:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
end
so lets say the word was READY
you'd need
R unner
E ven steven
A bstract
D elayed gratification
Y orick
in that order
so i repeat this 5 times for each individual letter?
No, that does everything.
Assuming word exists.
im changing word to G.YA_wordleword
function Game:main_menu(change_context)
local g = oldmainmenu(self, change_context)
local date = os.date("*t")
local newdate = string.format("%04d-%02d-%02d", date.year, date.month, date.day)
local _, json = require"SMODS.https".request("https://www.nytimes.com/svc/wordle/v2/"..newdate..".json")
G.YA_wordleword = JSON.decode(json).solution
return g
end
bcs this is how i define the wordle word
or do you advice creating a local word = G.YA_wordleword?
how to get the variables from vars and use it in calculate?
wdym vars
you should save variables in the card's config and use that in both loc_vars and calculate
bump2
here is the thing I have a joker that changes all values and I don't want to change those specific values
this is why value manipulation should have never been invented /j
wdym
more seriously, set up your joker that modifies values so that it can ignore certain marked variables (e.g. put values you don't want to change into a subtable called "immutable" or something, and then the joker can ignore the immutable table)
ok thx
Hey can you help me, been trying this and it has been almost 9 months now yet I still can't get this working all I want is that the card does what mime joker does but x2 instead of once and it's second function is to give me x10 xmults when I have all my other 4 custom joker card I made j_rwby_....
Now the second function doesn't work it gives me 10x mults even tho if those cards are not there.
youre using the wrong context
also you dont have to delete it and resend it
with a message this big, it's so annoying to keep reposting it that people are probably less likely to help you
bump3
No no I just made a mistake so instead of re-eding over and over i sent it again
Can u explain I kinda still learning this part
Mime? Joker
calculate = function(self, back, context)
local letters = {}
local firstletter = {}
for i = 1, #G.YA_wordleword do
table.insert(letters, G.YA_wordleword:sub(i, i))
end
for i = 1, #firstletter do
table.insert(firstletter, getJokerName:sub(i, i))
end
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
my_pos = i
break
end
end
if context.retrigger_joker_check then
local passed = true
for i=1, G.YA_wordleword do
local joker = G.jokers.cards[i]
if G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
end
end
when i run this i get an error saying itsays YA_wordleword is a nil value
despite G.YA_wordleword = JSON.decode(json).solution me defining it here
My main issue is that I want the joker to only give me x10 mults when my other 4 custom jokers are there but it doesn't do that,
Firstly, remove the old code, Secondly, you didn't change modprefix in the hook.
what old code and where do you see mod prefix?
Like how exactly becz I did type that and yet it did work or have I done a mistake?
wdym how theres not much to do different
Everything other than the code I gave you, it still says G.modprefix_wordleword in the Game:main_menu hook.
This is what I did
local oldmainmenu = Game.main_menu
function Game:main_menu(change_context)
local g = oldmainmenu(self, change_context)
local date = os.date("*t")
local newdate = string.format("%04d-%02d-%02d", date.year, date.month, date.day)
local _, json = require"SMODS.https".request("https://www.nytimes.com/svc/wordle/v2/"..newdate..".json")
G.YA_wordleword = JSON.decode(json).solution
return g
end
im probably just really stupid but i genuinely dont see it?
This is so ai generated 😭
Sorry but “Team Bonus !” Is too funny
bump4
No, in the code you sent previously it was still G.modprefix_wordleword
oh yeah but i said i updated that didn't i?
No.
The card is about Team RWBY, and the card has a second function where the other character joker cards are active it give a team bonus 10xmults but yah I can't figure out how to make this joker to detect the other 4 joker and give me 10x mults it's either it doesn't give me or it give me even if the other joker are not there
I wish I could just use Ai it just never works 😭 it actually messed my whole code instead of helping me
then i mustve imagined it, anyway why does it not recognize my G.YA_wordleword = JSON.decode(json).solution
In my deck.lua?
And call the other function
for i = 1, #G.YA_wordleword do
table.insert(letters, G.YA_wordleword:sub(i, i))
end
here in specific
Am new I use Smods wiki and learnt Lua a bit to get till here and asked so many people for their option on how to get those function am sorry if am being annoying but I really am confused when u tell me it's next (SMODS.find_card(...))
Can u explain how I could exactly do it what should I remove or add in the pre existing code
If context.joker_main and next(SMODS.Find_card()) and next(SMODS.Find_card()) and … then
— code
End```
capitalization moment
So btn the ( ) I should add the joker key?
Yes ofc
which is
what i was trying to say
I was lost when u said like that am sorry 😭
💀😭🤣
Thanks both of u let me try and I will come back (am sure I will mess it up)
Btw ai doesn’t know how to make balatro mods
Unless you feed one the entire smods framework
And lovely
and the entirety of balatro
Honestly you can make an ai that does that if you have the source code
and also it has to even understand lua to begin with when most ai's knowledge ends at python lmao
I learnt the hard way after it messed my whole code it literally changed the good part of the code and ahhh that's why u guys are very helpful thanks a lot 🙏
Lmaoooo
but don't do that (check pins)
Yah.... Lol someone should make one ngl, just type ur thoughts and it makes u the mod
Yes I’m legally disallowed i know
don't do that (check pins)
i mean thats like literally the only thing python is good at besides that its bad at fucking everything
I don’t like being sued
Check pins?
check the pinned messages in this channel
config = {extra = {extra_Xmult = 2, required_mult = 10, extra_Joker_slot = 1, current_Xmult = 1, current_Joker_slots = 0}}
modify_joker_values(G.jokers.cards[i], {["*"] = mult_rand}, {x_mult = 1, x_chips = 1, card_limit = true, extra_slots_used = true,
current_Joker_slots = true})
why is it still tampering with the value
Interpretive language when the immortal “public class main” walks in
Owhh I get it, is it really bad to use Ai tho?
what part of "Discussions regarding the use of AI and AI tools is now strictly prohibited in these channels." encourages you to continue talking about using AI
if context.cardarea == G.play and context.repetition then
return {
repetitions = card.ability.extra
}
end
if context.joker_main then
if next(SMODS.find_card('j_rwby_ruby')) and
next(SMODS.find_card('j_rwby_weiss')) and
next(SMODS.find_card('j_rwby_blake')) and
next(SMODS.find_card('j_rwby_yang')) then
return {
xmult = self.config.team_mult,
message = "Team Bonus!",
colour = G.C.RED
}
end
end
end
}```
Now? Better?
yeah that works
you should be using card.ability instead of self.config
and the find_card function call needs a lowercase f
otherwise yes that looks good
There is two more jokers that I have an issue my ruby joker stopped working for some reason now after updating Smods (ya I got bck to this mod after a 3months gap) and keeps on crashing 😭
--The Magician? - Discards 3 random cards in hand without spending a Discard
SMODS.Consumable {
key = 'reverse_magician',
set = 'Tarot',
atlas = 'reverse_tarots',
unlocked = true,
discovered = true,
cost = 3,
pos = {x = 8, y = 2},
config = { extra = { discards = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.discards } }
end,
loc_txt = {
name = 'The Magician?',
text = {
[1] = 'Discards {C:attention}#1#{} random cards in hand',
[2] = 'without spending a {C:attention}Discard',
}
},
can_use = function(self, card)
if G.hand.cards then
return (#G.hand.cards > 0)
end
end,
use = function(self, card, area, copier)
local not_selected = {}
local numb_discarded = 0
for _, playing_card in ipairs(G.hand.cards) do
not_selected[#not_selected + 1] = playing_card
end
for i = 1, 3 do
if G.hand.cards[i] then
local selected_card, card_index = pseudorandom_element(not_selected, 'tboj_reverse_magician')
G.hand:add_to_highlighted(selected_card, true)
table.remove(not_selected, card_index)
numb_discarded = numb_discarded + 1
play_sound('card1', 1)
end
end
G.FUNCS.discard_cards_from_highlighted(nil, true)
SMODS.draw_cards(numb_discarded)
return true
end,
}```
Reverse Magician almost works, but I have a problem that it's not returning discarded cards when it's used in a pack
Like the cards are still discarded when you enter a new blind
ive been updating it and just dont get it, no matter what i do
G.YA_wordleword = JSON.decode(json).solution
this i define in the Game:main_menu
just does not transfer into
for i = 1, #G.YA_wordleword do
table.insert(letters, G.YA_wordleword:sub(i, i))
end
with everything ive been trying
Can u check now I edited the same message
you still left a self.config in the second return, but yea that's better
pls help
No, you need to put everything you don't want to be changed in a table called immutable in the config.
What are you doing 😭
I am a terrible coder
I don't make clean code
I make functional code basically bare minimum
still tampers with the value
Thanks a lot!
Code?
config = {extra = {extra_Xmult = 2, required_mult = 10, extra_Joker_slot = 1, current_Xmult = 1}, immutable = {current_Joker_slots = 0}}
what was the comment in the other channel about?
No, immutable would go in extra
oh ok thx
if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
G.FUNCS.draw_from_discard_to_deck()
end
how would i make a blind change your cards when you play them?
You would do it in context.press_play
how tho
Thanks! I tried doing something similar to this but had the wrong condition lol
Do you mean changing their rank and suit?
i want to change their suit, and get rid of their enhancements and seals
if context.before then
for k, v in pairs(context.full_hand) do
v:set_seal(nil, true, true)
v:set_ability('c_base', nil, true)
SMODS.change_base(v, 'Suit')
end
end
and i replace "suit" with the suit, right
for some reason when changing the values the joker slots go back to 5
if context.individual and context.cardarea == G.play and
(context.other_card:is_suit("Clubs") or context.other_card:is_suit("Spades")) then
card.ability.extra.current_Xmult = card.ability.extra.current_Xmult + card.ability.extra.extra_Xmult
if card.ability.extra.current_Xmult >= card.ability.extra.required_mult then
card.ability.extra.immutable.current_Joker_slots = card.ability.extra.immutable.current_Joker_slots + card.ability.extra.extra_Joker_slot
G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.extra_Joker_slot
card.ability.extra.current_Xmult = 1
return{
message = "Upgrade",
colour = G.C.IMPORTANT
}
end
return{
message = "Upgrade",
colour = G.C.IMPORTANT
}
end
Yes.
local oldmainmenu = Game.main_menu
function Game:main_menu(change_context)
local g = oldmainmenu(self, change_context)
local date = os.date("*t")
local newdate = string.format("%04d-%02d-%02d", date.year, date.month, date.day)
local _, json = require"SMODS.https".request("https://www.nytimes.com/svc/wordle/v2/"..newdate..".json")
G.YA_wordleword = JSON.decode(json).solution
return g
end
no matter what i seem to do this G.YA_wordleword just is not found in here
SMODS.Back({
key = "Wordle",
loc_txt = {
name = "Monkey with a typewriter",
text = { "Play the daily wordle",
"with the first letter",
"of your jokers",
"All your jokers retrigger"
},
},
config = {},
pos = { x = 1, y = 1 },
atlas = "Jokers",
unlocked = true,
calculate = function(self, back, context, word)
local letters = {}
local firstletter = {}
local word = G.YA_wordleword
for i = 1, #word do
table.insert(letters, G.YA_wordleword:sub(i, i))
end
for i = 1, #firstletter do
table.insert(firstletter, getJokerName:sub(i, i))
end
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
my_pos = i
break
end
end
if context.retrigger_joker_check then
local passed = true
for i=1, #G.word do
local joker = G.jokers.cards[i]
if #G.word:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
end
end
})
i just cannot figure it out
maybe for additional context the first lua file is main.lua and the second is decks.lua
G.word doesn't exist and you need to remove the old code.
thats not the issue (yet)
it doesnt recognize g.YA_wordleword
in this
for i = 1, #word do
table.insert(letters, G.YA_wordleword:sub(i, i))
end
even if i remove local word and just put G.YA_wordleword it also doesnt work
i keep gettings this (with uipdated G.word)
How would one change the weight of a modded enhancement depending on a variable
use get_weight for things that need a weight that changes dynamically
I know that, but how would I set the weight? Like do I use self.weight? How would I access the weight variable to set it
yeah use self.weight
Huh, okay
and then whatever other variable that you set to change the weight
you return the weight
I’ll try
yeah
also im confused on the "old code"
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
my_pos = i
break
end
end
```you mean this?
ohh do i not need that anymore?
Yes.
okay so now it doesnt crash my game anymore but still does not work
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
what does name_text need to be? (i want it to check the first letter of the joker name)
It needs to be name_text
well it currently doesnt work and im trying to rule out thingies
today is kinda a bad wordle for testing CIVIL
how do i affect the odds that a joker shows up in shop? i want to make a joker with a very small chance of appearing, way smaller than if i were to just make it a rare
You would make a new rarity.
currently im trying Clever Icecream Vagabond Ice cream again and Loyalty card
CIVIL
and it doesnt do the retrigger
alright, got it
Hello, everyone. Mister "Trouble_with_mods" is back again, and I have a trouble with mods. Specifically, in one I'm making. See, I have a joker that should randomly add or subtract a rank and randomly change the suit of a duplicated card, but I don't know how to code such a thing. Ideally, the original card isn't altered at all, just the copy.
im trying calculate = function(self, back, context, word)
if context.retrigger_joker_check then
local passed = true
for i=1, #G.YA_wordleword do
local joker = G.jokers.cards[i]
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
end
end
is there eanything else i need for this besides the definition of G.YA_wordleword
Do you have retrigger_joker enabled?
where am i supposed to enable that?
SMODS.current_mod.optional_features = function()
return {
retrigger_joker = true,
}
end
in SMODS.Back? or in my main.lua
No, outside of everything.
wdym outside of everything?
optional features also dont need to be a function
im so confused
another thingy
before i read that
calculate = function(self, back, context, word)
SMODS.current_mod.optional_features = function()
return {
retrigger_joker = true,
}
end
if context.retrigger_joker_check then
local passed = true
for i=1, #G.YA_wordleword do
local joker = G.jokers.cards[i]
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
end
end
how do i make each joker message their own first letter at the end of a round
if context.end_of_round and context.main_eval then
local effects = {}
for i, v in ipairs(G.jokers.cards) do
table.insert(effects, {message = localize({type = 'name_text', set = v.ability.set, key = v.config.center.key}):sub(1, 1), message_card = v})
end
return SMODS.merge_effects(effects)
end
bump
you should do G.jokers:change_size(card.ability.extra.extra_Joker_slot) instead
I have been getting the message 'attempt to index field 'extra' [a nil value] when running if SMODS.pseudorandom_probability(card, 'callosum', 1, card.ability.extra.odds) then in context.before. my config looks like config = { extra = { effects = 1, {}, odds = 2} },. Is there a reason I am card.ability.extra is returning nil?
i can post more of the jokers code if it may be relevant
Did you start a new run?
?
?
❓
I had an idea to make Fortunato from The Cask of Amontillado a legendary joker but it turns out he isn't actually a jester, he just wears a jester's clothes for symbolism
do it anyway
?
So what I thought of for his effect was "stone cards give x3 mult when scored or held in hand, which is kinda bad
I mean that's pretty strong, stone cards aren't too hard to make/find and that makes them both outclass steel cards and kings/queens with triboulet
Doesn anyone know how to enable the high contrast option for custom cards?
where am i supposed to put this?
SMODS.Back({
key = "Wordle",
loc_txt = {
name = "Monkey with a typewriter",
text = { "Play the daily wordle",
"with the first letter",
"of your jokers",
"All your jokers retrigger"
},
},
config = {},
pos = { x = 1, y = 1 },
atlas = "Jokers",
unlocked = true,
calculate = function(self, back, context, word)
if context.retrigger_joker_check then
local passed = true
for i=1, #G.YA_wordleword do
local joker = G.jokers.cards[i]
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
if context.end_of_round and context.main_eval then
local effects = {}
for i, v in ipairs(G.jokers.cards) do
table.insert(effects, {message = localize({type = 'name_text', set = v.ability.set, key = v.config.center.key}):sub(1, 1), message_card = v})
end
return SMODS.merge_effects(effects)
end
end
end
})
bcs i currently have it like this
SMODS.Joker{
cost = 7,
key = 'snakeJoker',
loc_txt = {
name = "Snake",
text = {
'A fragile {C:attention}Snek.{}',
'Everytime you free this snek...',
'It comes back {C:red}STRONGER.{}',
'Gains {X:mult,C:white}X1{} mult',
'each time you find and buy it again',
'{X:mult,C:white}X#1#{}'
}
},
atlas = 'Jokers',
pos = {x = 0,y = 0},
config = { extra = {Xmult = 1}},
loc_vars = function(self,info_queue,center)
return {vars = {
SnekLevel
}
}
end,
Im trying to get it to show a custom number, and when i sell the card the mult increases by 1 the next time i find the card, but the number isnt showing at the bottom of the description of the joker.
the joker effect of selling and buying works fine, just the description is stuck saying "X1" at the bottom
how would i get my script to edit an existing balatro function? wanting to export card information when selected
or override an existing function* i guess
use a hook or a lovely patch
https://github.com/nh6574/VanillaRemade/wiki#whats-a-patch
(next section is hooks)
thanks so much
can a patch call functions contained in the same script or does the patch execute inside of balatro.exe and therefore couldn't find the reference?
yeah it can
this is great news
when iterating through card.ability, how can I tell when I've reached card.ability.extra, if it's even there?
for key, value in pairs(card.ability) do
if key == "extra" then
-- code
end
end
?
thx
SMODS.Back({
key = "Wordle",
loc_txt = {
name = "Monkey with a typewriter",
text = { "Play the daily wordle",
"with the first letter",
"of your jokers",
"All your jokers retrigger"
},
},
config = {},
pos = { x = 1, y = 1 },
atlas = "Jokers",
unlocked = true,
calculate = function(self, back, context, word)
if context.retrigger_joker_check then
local passed = true
for i=1, #G.modprefix_wordleword do
local joker = G.jokers.cards[i]
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
if context.end_of_round and context.main_eval then
local effects = {}
for i, v in ipairs(G.jokers.cards) do
table.insert(effects, {message = localize({type = 'name_text', set = v.ability.set, key = v.config.center.key}):sub(1, 1), message_card = v})
end
return SMODS.merge_effects(effects)
end
end
end
})
for today im leaving it at this, the displaying at the end of round works (although not in the wordle colour format but thats an issue for later) the retriggering doesnt work yet
SMODS.Atlas {
key = "Blazing",
path = "Blazing.png",
px = 71,
py = 95
}
SMODS.Joker {
key = 'findyouroneway'
loc_txt = {
name = 'Find Your One Way'
text = {
"Hands of your most played"
" {C:attention}poker hand{} gain {X:mult,C:white}X5{} Mult."
"Other hands do not score."
}
}
config = { extra = { Xmult = 5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult } }
end
rarity = 3
atlas = 'Blazing'
pos = { x = 0, y = 0 },
cost = 6,
calculate = function(self, card, context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = locaize { type = 'variable', jey = 'x_mult', vars = { card.ability.extra.xmult } }
}
end
end
}
I've never done any sort of coding before (outside of scratch) so forgive me if this is an easy question, but i can't figure out what this crash explanation means
from what i understand it has the correct closing bracket where it wants them
could someone help me understand?
you're missing commas in the text
between each string
also after the name
also after a bunch of other stuff
oh alright
so like this then?
SMODS.Atlas {
key = "Blazing",
path = "Blazing.png",
px = 71,
py = 95
}
SMODS.Joker {
key = 'findyouroneway',
loc_txt = {
name = 'Find Your One Way',
text = {
"Hands of your most played",
" {C:attention}poker hand{} gain {X:mult,C:white}X5{} Mult.",
"Other hands do not score."
}
}
config = { extra = { Xmult = 5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult } }
end,
rarity = 3,
atlas = 'Blazing',
pos = { x = 0, y = 0 },
cost = 6,
calculate = function(self, card, context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = locaize { type = 'variable', key = 'x_mult', vars = { card.ability.extra.xmult } }
}
end
end
}
Just wondering, are you using notepad to code? I'd recommend using VSC with a lua extension
It will highlight errors like missing commas
i'm just using base vs code
Ah, without any lua extension?
i didnt know there were extensions
you're missing one before config
are they 3rd party or can i get one inside the app?
You can click on this button in VSC and get this extension
thank you both so much
does anyone have an example of how to make a joker that targets the probability only on specific random groups? like if i wanted to make an oops but specifically for lucky cards
ok the Xmult part works but it says error instead of X5 when it activates
return { xmult = ... }
i don't have an example but i can explain how to
as per the documentation in the smods 0711 release notes, every probability roll has an identifier, which you can get as context.identifier
to figure out which one(s) you want, do if context.mod_probability then print(context.identifier) end in your joker's calculate code and then have the relevant probability run so you can see what prints. make sure you have debugplus so you can see the console in-game
once you know what identifier you're looking for, check if the probability roll is for that identifier in your context checks
any chance the identifier is the same as the probability key? im using joker forge to try and make the bulk of my mods, and im so lazy i dont want to consider making a joker outside of it to then adding everything back in to the main mod and editing the atlas or whatever. ill probably end up doing it anyway if i have no other option though
how do i instantly destroy a joker with no animation, i want to make it so that 2 j_otm_magnetictile jokers coagulate into a j_otm_magnetictower joker, i have this so far:
calculate = function(self, card, context)
if context.card_added and context.cardarea == G.jokers then
local new_card = context.card
end
end
guys what's the command for ^mult
I'm trying Emult but it's not working
looked in the cryptid files and it's using both Emult and emult I don't understand
or you might be able to do Xmult with the current amount of mult or exponetilized further (X * X = X^2, X * X^2 = X^3, etc.)
i have talisman
key = "sodalite",
unlocked = true,
discovered = true,
atlas = "jokers",
blueprint_compat = true,
rarity = 3,
cost = 8,
pos = { x = 1, y = 1 },
config = { extra = { odds = 3, Emult = 1.1 } },
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'napoli_sodalite')
return { vars = { numerator, denominator, card.ability.extra.Emult } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card and context.other_card.base
and context.other_card.base.suit == "napoli_spade"
and SMODS.pseudorandom_probability(card, 'napoli_sodalite', 1, card.ability.extra.odds) then
return {
Emult = lenient_bignum(card.ability.extra.Emult)
}
end
end
}```
this is my code it's to make a joker like bloodstone with ^mult
napoli_spade is my custom suit
made the same code for another jocer with xchips and it works
is anybody gonna help me with mine
i'd help you if i knew how to
How would i use this section of code from VanillaRemade's wiki
-- Similar to The Ox
local _handname, _played = 'High Card', -1
for hand_key, hand in pairs(G.GAME.hands) do
if hand.played > _played then
_played = hand.played
_handname = hand_key
end
end
local most_played = _handname
to activate this card
SMODS.Joker {
key = 'findyouroneway',
loc_txt = {
name = 'Find Your One Way',
text = {
"Hands of your most played",
" {C:attention}poker hand{} gain {X:mult,C:white}X5{} Mult.",
"Other hands do not score."
}
},
config = { extra = { Xmult = 5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult } }
end,
rarity = 3,
atlas = 'Blazing',
pos = { x = 0, y = 0 },
cost = 6,
calculate = function(self, card, context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.Xmult,
message = "Step it, Buddy!"
}
end
end
}
only when the most played hand is played
how do i instantly destroy a joker with no animation, i want to make it so that 2 j_otm_magnetictile jokers coagulate into a j_otm_magnetictower joker, i have this so far:
calculate = function(self, card, context)
if context.card_added and context.cardarea == G.jokers then
local new_card = context.card
end
end
if context.joker_main then
-- that code here
if most_played == context.scoring_name then
return { ... }
end
end
Thank you
if nobody replies is because 1) there's nobody here, 2) they don't know, 3) they don't want to help rn
spamming the channel won't make people help faster (ive seen you do this multiple times now)
i think it's
SMODS.Back { stuff here }
not
SMODS.Back( { stuff here} )
but i may be wrong
i don't think that is the issue but i can try just to cross it out
here's an example i have
same error it isn't that. i didn't think it was that, but it didn't hurt to try
maybe try with only one voucher
yeah it is because its a table. but is there a way to make it where it starts with two vouchers?
how do i make it so that if there's a specific blind present
something like let's say the music changes to something else
i could just do one
looking at cardsleeves it might just be where vouchers only do one maybe thats because thats how balatro was coded or balancing which i guess is fair since you do start off with a voucher
have you checked this
i actually tried that with adding the apply before reading the top comment and doing +2
might be showing how it wouldve been implentanted if it wasnt config done
which one do you prefer when you dual play with the sleeve and deck all star? hone or out the park
killing myself
Working on my own design for cards
Faces placeholders
Interesting. If you have an enhanced card it just uses the shadow of that
So guess that means even regular ones are only using the card back for the shadow
i think there's a variable or function to disable the shadow if needed
Yeah since my design covers a good chunk of the card I figure I'd have to make custom enhancers so they'll actually show up xD
Oh no the shadow is fine it's just something interesting to notice
does anyone know how I could set the level of a specific hand to lvl 4 from the start of the game? (I have a deck that I want to have high card start at level 4)
besides giving myself 4 plutos
i think there are either two ways: some config that i don't know of that does that or an apply function that levels up
you could look at space joker
nvm
https://github.com/nh6574/VanillaRemade/blob/24ee6098f692a58a34d573dec5a86a347c5fd13a/src/spectrals.lua#L953 @fickle vale
SMODS.smart_level_up_hand(card, "High Card", true) and there is either another argument or you can just do a for loop four times
okay the sleeve combo might be cracked 😭
rerolling its was just a lucky pull of rares and editions but uncommon/rares and editions appear which is the point of the vouchers which does work
not too worried of the sleeve combo since you will need to play with the sleeves mod idk
you decide on that
yeah after rerolling its i think balanced enough and more of a fun deck to play around with
yeah its a fair deck tested with sleeve and red deck
thanks for your help!
since i made an edition, its only natural to make a tag
what's wrong with this? trying to make it so planet cards dont take up any consumable slots in a joker
what is rares default_weight?
How would I apply a shader effect to a Joker that shifts its pixels (i.e. a wave shader) without it going past its card size in the canvas? Right now the shader I've got draws itself normally and then applies a copy of itself with the shader that kinda bypasses into other parts of the atlas
hey so when youre directly calling level_up_hand to level a custom hand
do you use the key of the hand instead
it can take either the key or the poker hand object itself i think
local ref_levelup = level_up_hand
function level_up_hand(card, hand, instant, amount, ...)
if next(SMODS.find_card("j_nflame_genplanet")) and hand ~= "nflame_generic" then
level_up_hand(card, "nflame_generic", instant, 1)
end
return ref_levelup(card, hand. instant, amount, ...)
end
``` ok am i doing this right
not quite
you've got the right idea but the hook is a bit wrong
you are doing a bit of recursion
yes
local ref_levelup = level_up_hand
function level_up_hand(card, hand, instant, amount, ...)
if next(SMODS.find_card("j_nflame_genplanet")) and hand ~= "nflame_generic" then
ref_levelup(card, "nflame_generic", instant, amount, ...)
end
return ref_levelup(card, hand, instant, amount, ...)
end
also pass amount instead of 1, unless that was intentional
hmm... trying to thinnk if that would be balanced lol
what's the mechanic here exactly
also if you want it to absorb the level up (ie not level up the original hand) then you would return in that if statement
oh right forgot the return
basically im making a joker that makes every hand score as this generic hand, and all levelups also level this generic hand
local ref_levelup = level_up_hand
function level_up_hand(card, hand, instant, amount, ...)
if next(SMODS.find_card("j_nflame_genplanet")) and hand ~= "nflame_generic" then
ref_levelup(card, "nflame_generic", instant, amount, ...)
return ref_levelup(card, hand, true, amount, ...)
end
return ref_levelup(card, hand, instant, amount, ...)
end
heres what you would do if you wanted it to level both but not show the original level up (if instant is what i think it is)
ah ok
intuitively i'd say let the amount pass through, especially since i don't think there's any vanilla content that does more than 1 level up at a time. balance wise i'd only cap it if there's an easy way to level up a hand by multiple levels at once in your mod
i havent made something like that
yet
ok its still erroring
indexing nil with key level
figured out a neat effect but would still appreciate help on this given I'd want to be applying this shader to the card itself rather than re-drawing it with a shader on top (breaks with editions b/c it's checking for pure white)
the effect I'd like to do in quesiton: https://www.shadertoy.com/view/msySzK
Justymakeit wigly
last time i tried this happened
is this a case of adding a DrawStep
if editions can disable_base_shader, can Jokers do that too
help
so i managed to get the mod to not crash, but the jokers and tarots i made dont appear in collections. is there perhaps a common reason why?
how to juice up the deck
G.deck.cards[1]:juice_up()
yeah okay thanks
how do you set your mod icon?
SMODS.Atlas{key = "modicon", path = "modicon.png", px = 32, py = 32}
What does this mean
tnx!
im also having trouble implementing emult even if i have talisman on
tried making a bloodstone like joker and it works if i put x_chips but it doesn't trigger with Emult
I'm tryin' to check before scoring a hand if the played cards are hearts. I'm trying it on a for k, v in ipairs(context.scoring_hand) block. Does anyone know how can I access to the suit property, and compare it to the Hearts value? quq
if context.before then
local passed = true
for k, v in pairs(context.full_hand) do
if not v:is_suit("Hearts") then
passed = false
break
end
end
if passed then
-- code
end
end
Thanks!
oh this is neat. so it shows how the lovely patches apply?
yeah, that's the goal
egui makes it crossplatform right
iterate over the table with a for loop? ez
oops didnt realize that was old
i was behind on a ton of messages
but fr tho thats a rlly simple programming concept, if u cant use a table, only single instance, then do a for loop that iterates through every single instance of that table and adds it one by one
are failed patches gonna be in there or no
is there a way to specify that a draw step shouldn't be overridden by Holographic / Polychrome / Negative?
my Jokers with extras lose their extras if they're any of those
does it just not run at all if there's an edition?
is it possible to make cards transparent
regular
SMODS.Back({
key = "Wordle",
loc_txt = {
name = "Monkey with a typewriter",
text = { "Play the daily wordle",
"with the first letter",
"of your jokers",
"All your jokers retrigger"
},
},
config = {},
pos = { x = 1, y = 1 },
atlas = "Jokers",
unlocked = true,
calculate = function(self, back, context, word)
if context.retrigger_joker_check then
local passed = true
for i=1, #G.modprefix_wordleword do
local joker = G.jokers.cards[i]
if #G.YA_wordleword:sub(i, i) ~= localize({type = 'name_text', set = joker.ability.set, key = joker.config.center.key}):sub(1, 1) then passed = false end
end
if passed then
return {repetitions = 1}
end
if context.end_of_round and context.main_eval then
local effects = {}
for i, v in ipairs(G.jokers.cards) do
table.insert(effects, {message = localize({type = 'name_text', set = v.ability.set, key = v.config.center.key}):sub(1, 1), message_card = v})
end
return SMODS.merge_effects(effects)
end
end
end
})
hey yall, im trying to make a deck where you have to play wordle with the first letter of your jokers, now theres alot of things wrong with this but currently im trying to get the right colour sceme down
(for those who dont know,if a letter isnt in the wordle its gray
if the letter is in the wordle but not in the right space its orange
and if the letter is in the wordle and on the right space its green
busted
now currently im just trying to change the colour in general which is also giving me a hard time
Code?
:3 how do i do it then
doesnt joker stencil do that?
wuh
what do you need the transparency for?
not really, the joker's sprite has a gap in the middle
i want to have the joker fade away
do you want it to be like an animation?
it has to be for all jokers, too
so like, this is what im doing rn
i want to make this ui fade away after about 2 seconds or so
right, deffo a shader then
dang it
3:
yeah thanks, im gonna opt for my alternative which is to pull the ui back to the right then lmao
i mean, you could prolly get away with making it move back to t- yeah :}
it would be hard to sync the shader with the transparency of the ui box otherwise
-# not me making up excuses since i dont know SHIT about shaders :3
-# so true
...yeah
wait, so how are the editions rendered then?
does the edition affect the extra if it's rendered before it?
Yes, because the edition is being drawn on the center.
Yes, and you have to draw it after the edition.
grand, thanks ^^
yes
can i see the sheet?
havent decided or really thought about them
your sheets are not transparent
ah mb
i wonder how @/thewintercomet does it, would mention her but idk if that'd be unwarranted
mods get its ass
<@&1133519078540185692>
thank you :>
how can I make by boss blind trigger the effect after all the cards and jokers triggered?
(like crimson heart does)
((cuz rn my boss blin's effect triggers after you chose the playing cards))
You mean when you play the hand?
yeah
Put it in an event.
both functions or one of them?
The one that is not returning.
okay so, I'm not sure but should the trigger have a different condition than "after"?
Yes, remove it.
aight
okay, it works now, thanks!
Which of these is for what things?
button.nodes[1].nodes[1].config.ref_table = G.GAME
button.config.button = nil
button.config.func = nil```
that just seems to clear out some values for a button, for the specifics you would need to provide more context
where can i check if a run is seeded or not
for what each value means heres a guide https://github.com/Steamodded/smods/wiki/UI-Guide
G.GAME.seeded i think
alr
Here's the whole hook:
function create_UIBox_buttons()
local t = old_buttons()
if G and G.GAME and G.GAME.blind.config.blind.key == 'bl_cstorm_the_riddler' then
local index = 3
if G.SETTINGS.play_button_pos ~= 1 then
index = 1
end
local button = t.nodes[index]
button.nodes[1].nodes[1].config.text = "Test"
button.nodes[1].nodes[1].config.ref_value = nil
button.nodes[1].nodes[1].config.ref_table = G.GAME
button.config.button = nil
end
if G and G.GAME and G.GAME.blind.config.blind.key == 'bl_cstorm_the_riddler' then
local index = 1
if G.SETTINGS.play_button_pos ~= 1 then
index = 3
end
local button = t.nodes[index]
button.nodes[1].nodes[1].config.text = "Test2"
button.nodes[1].nodes[1].config.ref_value = nil
button.nodes[1].nodes[1].config.ref_table = G.GAME
button.config.button = nil
button.config.func = nil
end
return t
end```
is there an evaluation for when a card is discarded in JokerDisplay?
no, what are you trying to do
jokerdisplay is not meant to run calculations like that
save it in the joker and then display that value
i.e. the one in loc_vars
i don't understand what other than displaying the xmult is there
What do I change in the hook to make it draw a card when it is clicked?
How would I grab a specific element from the hand in relation to a scored card?
I’m trying to just make a list of all the scored cards and go one down the list
But I’m struggling to access my card itself to check
actually i guess this could also work
How would I change the SMODS src/ui lua file?
so like, patching right
gimme a sec
'=[SMODS _ "src/ui.lua"]'
put this in the target
Excellent, thanks!
bump
why my joker doesn't seem to activate for unscored cards?
not context.scoring_hand isn't how you check if a card is unscored
what is the context for checking if a card is scored?
there isn't a dedicated context
you just have to check if context.other_card is contained in context.scoring_hand or not
I'm kinda confused...
context.scoring_hand is a table of cards
context.individual doesnt get called for unscoring cards anyway, you should be using context.destroy_cards for this
oh right
bump2
like this?
yeah
and then you just need to do a for loop over context.scoring_hand to check if the card was scoring or not
i think destroy_cards actually has a special "unscored" cardarea
might be an optional feature
so like for i, k in ipairs(not context.scoring_hand)
...no
no wait
thats not how not works
without the "not"
yeah
it still doesn't work, am I missing something?
but how can I check if the card isn't scoring?
local unscoring = true
for _, v in ipairs(context.scoring_hand) do
if v == context.other_card then
unscoring = false
break
end
end
so you use a local variable to determine if the card is unscored
its not optional
huh
it was for like a version a year ago
wtf
okay nvm
you can just do context.cardarea == "unscored" apparently
i think thats the correct thing
oh so
also SMODS.in_scoring exists
although it is literally just that same loop
ah so like this then
does context.individual work if added to the if condition?
Okay hear me out
Joker that says it will give x10000 mult
But
When the next hand is played it turns into a ditto that does nothing
((i don't think this is the best channel to ask that))
And hear me out
Joker that changes the background music
How do I code such a thing?
alongside destroy_card? no
aight
Do i just slot my music in the .ogg spot?
Its N my goat
Why do the buttons only work once?
local index = math.random(1, #G.hand.cards)
SMODS.destroy_cards(G.hand.cards[index])
end
function G.FUNCS.draw_a_card(e)
SMODS.draw_cards(1)
e.config.button = 'draw_a_card'
end
local old_buttons = create_UIBox_buttons
function create_UIBox_buttons()
local t = old_buttons()
if G and G.GAME and G.GAME.blind.config.blind.key == 'bl_cstorm_the_riddler' then
local index = 3
if G.SETTINGS.play_button_pos ~= 1 then
index = 1
end
local button = t.nodes[index]
button.nodes[1].nodes[1].config.text = "Test"
button.nodes[1].nodes[1].config.ref_value = nil
button.nodes[1].nodes[1].config.ref_table = G.GAME
button.config.button = 'draw_a_card'
button.config.func = nil
end
if G and G.GAME and G.GAME.blind.config.blind.key == 'bl_cstorm_the_riddler' then
local index = 1
if G.SETTINGS.play_button_pos ~= 1 then
index = 3
end
local button = t.nodes[index]
button.nodes[1].nodes[1].config.text = "Test2"
button.nodes[1].nodes[1].config.ref_value = nil
button.nodes[1].nodes[1].config.ref_table = G.GAME
button.config.button = 'destroy_a_card'
button.config.func = nil
end
return t
end```
Sorry for that wall OwO
how can i unfuck this
the 2nd text input window uses create text input and supposedly "there can just be only one idless input"
how do i assign an id to the thing returned by create text input
is there a place i can view the parameters of an object?
currently making a hook and i want that hook to return the name of the card and also whether that card is negative. assuming it will be something like card.joker.edition but i want to know exactly what the reference is
theres no much documentation on all the info but the stuff you want is listed here https://github.com/nh6574/VanillaRemade/wiki#variables
you can also print a cards info with debugplus
open the console, hover over the card and type eval dp.hovered
awesome
i am stupid i can just put it in the args
bump
finally implemented JokerDisplay on all of my jokers that need it
(took me a whole day to figure it out)
is there just like a massive list of all the base game keys to refer to somewhere
much obliged 💜
oh i see
ok i thought different types of consumables had their own prefixes i was doing "t_wheel_of_fortune"
okay working :)
is there a way to get rid of the extra edition ones
i have no guthib page btw
i should remove this probably
the table is a tad outdated
bump2
i think both buttons have a one_press attribute, or so-named
How do I change that?
you could set it to nil
though i'd inspect the table first to find what that attribute is actually called
How do I do that?
add print(inspect(button))
yay!! np :D i hope it works!
how do i sell a card?
there should be a wee button that does that <3
/silly /i can check
okay try:
G.FUNCS.sell_card({ config = { ref_table = card_you_want_to_sell } })
unless smods has a handier way
if there is i can't find it
Okay, now the scary thing... How do I make a UI pop-up when the button is pressed?
OMGOMGOMG guess who finally got my card extra drawstep working!!!!! >:3
i'm actually the best
my fellows are back 
love the art!
just ignore whatever the fuck's happening down here and you'll be fine :333
(i know what caused this)
YAY THANKS ^U^
Tbh, the thingy down there looks magical xD
bump
oh and arguably the best polychrome is back >:3
I've thought about a joker like this for ages! would be amazing to have
right is this going to do what I want it to?
bump2
I'm wanting to make a joker that does something if the current number of scored chips is equal to a number. Is there a way to check for the current number of scored chips in context.after?
SMODS.calculate_round_score()
thank you
Is there a way to get the mult and chips HUD to show negative numbers?
it should be currentCard:use_consumeable()
also SMODS.find_card is always truthy
this returns the whole score, is it possible to see just the current total chips?
you want next(SMODS.find_card(...))
and it will crash if it has no edition because newJoker.edition will be nil
thank you, i'll add in some checks
and G.jokers is not a list
G.jokers.cards is, and i don't think ipairs works like that
SMODS.get_scoring_parameter("chips") i think
or just the variable hand_chips, but i like the get_scoring_parameter call more
Thank you
i used ipairs because of this soo idk. first time making a mod ever https://github.com/nh6574/VanillaRemade/wiki#how-do-i-get-if-the-player-has-a-certain-card
bump3
guys can someone help me fix my modded joker? it's supposed to be like bloodstone but with ^mult, (i have talisman on and i edited the code from bloodstone in vanilla remade) but the ^mult never triggers, even if i make it full odds
i can send the code if needed
yeah definitely send the code people cant help you without code
key = "sodalite",
unlocked = true,
discovered = true,
atlas = "jokers",
blueprint_compat = true,
rarity = 3,
cost = 8,
pos = { x = 1, y = 1 },
config = { extra = { odds = 3, Emult = 1.1 } },
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'napoli_sodalite')
return { vars = { numerator, denominator, card.ability.extra.Emult } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card.base and context.other_card.base.suit == "napoli_spade" and
SMODS.pseudorandom_probability(card, 'napoli_sodalite', 1, card.ability.extra.odds) then
return {
Emult = card.ability.extra.Emult
}
end
end
}```
napoli_spade is my custom suit
if I use any other talisman scoring effect like x_chips it works
i tried using emult instaed of Emult too
bump4
i will try but i think using is_suit crashed me already
if is_suit is crashing you then youre definitely doing something else wrong
it has no reason not to work
Is there any way to add a feature for showing negative mult?
are you actually using the correct suit key?
ok it's not crashing but still no triggers
suit key is right
key = "sodalite",
unlocked = true,
discovered = true,
atlas = "jokers",
blueprint_compat = true,
rarity = 3,
cost = 8,
pos = { x = 1, y = 1 },
config = { extra = { odds = 3, emult = 1.1 } },
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'napoli_sodalite')
return { vars = { numerator, denominator, card.ability.extra.emult } }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card.base and context.other_card:is_suit("napoli_spade") and
SMODS.pseudorandom_probability(card, 'napoli_sodalite', 1, card.ability.extra.odds) then
return {
emult = card.ability.extra.emult
}
end
end
}```
bump5
does your mod prefix also have the exact same capitalization as in here
yes, otherwise everything else wouldn't work
yeah true
i could implement my own exponential mult i guess but i wouldn't know how to
could it maybe be an issue of mod priority?
well idk how to troubleshoot this
try removing the check for context.other_card.base i guess? i doubt thats the issue but not like its needed anyway
still nothing
does anyone know how i can cause a joker to disable scoring for a hand?
similarly to a boss blind
bump6
does anyone have an example or can help with how to make a custom enhancement increment mult each time the same enhancement is scored? but reseting after the hand plays
context.debuff_hand
check vanillaremade blinds
(you can use it on jokers)
oh awesome
i was looking at blinds but i assumed all that stuff was exclusive to them
bump7 TwT
all the calculate stuff you can use anywhere
in the uhh UI guide page on the SMODS wiki
how can I make consumable destroy a specific joker when the consumable is used? what do i put in the "use" section of the code?
I have a joker that applies enhancements but the problem is that
the enhancements don't take effect after being applied
current condition:
if context.cardarea == G.play and context.individual and not context.blueprint_card then
bump8...
apply the enhancement using context.before
tried it but it just completely stops working
check midas mask vanillaremade
context.individual is run for each scored card individually, whereas context.before just runs once
and context.main_eval
and not context.blueprint
then```
how can i destroy a specific joker by using a consumable?
ok thx
main_eval changes literally nothing
specific as in a specific position (i.e. "destroy the leftmost joker"), or a specific card (i.e. "destroy green joker"?)
specific card
SMODS.destroy_cards(SMODS.find_card("j_modprefix_jokerkey")) will destroy all copies of the joker, if the player has any (replace modprefix with the relevant mod's prefix (you don't need one if it's a vanilla joker), and replace jokerkey with the key of the relevant joker)
and if you only want the consumable to be usable if the joker in question exists, do this for the can_use function: return next(SMODS.find_card("j_modprefix_jokerkey"))
thank you! it worked
this checks to see if the hand activates the boss blind, right? does it also allow a joker to act as a boss blind itself?
in the way that it could set debuff_hand to true
no that's a different context with a similar name
this one is for disallowing a hand
oh ok
so then i would set the hand to be debuffed with
debuff_hand = not 'ph_most_played'
``` ?
or wait actually would it be G.GAME.current_round.most_played_poker_hand
whats the best way to register a keybind? I want a specific function to start and stop on a key press
SMODS.KeyBind
it's not really documented, but this example built into smods binds "Alt + F5" to restarting the game
no
did you read the code for how the blinds do it
bump9 #💻・modding-dev message
can someone help me with this? dont mind the mods though i was trying to make something
thats only updated at the start of each ante since its used for the ox, use this instead https://github.com/nh6574/VanillaRemade/wiki#how-do-i-get-the-most-played-hand
i did, but i dont think i understand enough to implement it into the joker's code
calculate = function(self, card, context)
if context.joker_main then
local _handname, _played = 'High Card', -1
for hand_key, hand in pairs(G.GAME.hands) do
if hand.played > _played then
_played = hand.played
_handname = hand_key
end
end
local most_played = _handname
if most_played == context.scoring_name then
return {
message = "Step it, Buddy!",
Xmult_mod = card.ability.extra.Xmult}
end
if most_played ~= context.scoring_name then
if context.debuff_card then
return {debuff = true,
message = "Tch, pathetic."}
end
end
end
I took code from the pillar and removed the part that checked if a card was already played this ante, i cant seem to get it to trigger at all
well first i said debuff_hand not debuff_card
but joker_main and debuff_card cant be combined
(or debuff_hand)
you need to use them in separate if conditions
Oh, alright
my bad
Thank you for your help, it finally works!
The only issue i'm having is it says the message any time you select cards that are the wrong hand instead of when you submit the hand, but I think i can figure out how to fix it
yeah that worked 👍
'''SMODS.Keybind {
key_pressed = 'f5',
event = 'pressed',
action = function(self)
start_or_end_loop()
end
}'''
any idea why this is causing me issues?
also mb formatting problems
nil value error
but idk why because my settings.json is fine
what's the crash log
this is just in the debugger
"attempted to index a nil value (global 'SMODS')"
using vscode
oh the vscode debugger?
yes
it can't run balatro code
but i have the lua debug extension installed
you run all the code in game
assuming there isn't a debugger mod for balatro?
no
nvm the error log is pretty comprehensive
there are mods that help debug like debugplus and balatest
calculate = function(self, card, context)
if (context.post_trigger and context.other_card == card)
or (context.main_scoring and context.cardarea == G.play)
then
card.edition.extra.money = card.edition.extra.money + card.edition.extra.money_gain
return {
message = "+" .. card.edition.extra.money_gain,
colour = G.C.MONEY
}
end
if context.end_of_round and card.edition.extra.money >= 1 then
return {
p_dollars = card.edition.extra.money,
message = "reset",
colour = G.C.FILTER,
func = function()
card.edition.extra.money = 0
end
}
end
end
this works when a card with the edition scores, but not when a joker is triggered. how do I fix this problem?
anyway still getting a nil value error in game, this function isn't working: function use_card(currentCard) currentCard:use_consumeable() end
here's how i'm getting currentCard: use_card(SMODS.find_card("c_judgement"))
what's the effect of the card
that's a list, you need to get the element
it will gain $1 every time the card is triggered, and then give it all out at the end of the round
(obviously the amount of money stored resets afterward)
other_card == card means when itself is triggered
is that why it's not doing anything for jokers?
what is this? a joker? an enhancement?
most likely
an enhancement
yeah that's always false then
after removing that part it still does nothing
the what
can confirm it's only for jokers, i've been working on something similar that needs post_trigger for enhancements
maybe i'll PR it if i'm happy with how it comes out
I'm talking about things that receive post_trigger. I'm pretty sure decks do
ohh
so I guess I replace "current_mod" with my mod's id?
SMODS.Joker:take_ownership( v ,
{ -- table of properties to change from the existing object
discovered = false
},
true -- silent | suppresses mod badge
)
end```
This was working last time I played Balatro, but now it's broken
for i,v in pairs(G.P_CENTERS) do
if v.set == "Joker" then
end
end
So I have a ton of joker images. Do I put them together in like... Illustrator or whatever and link to that png for the joker images or link to each separately
like this?
if v.set == "Joker" then
SMODS.Joker:take_ownership( v ,
{
discovered = false
},
true
)
end
end```
yes I think
nah, that gives me a different crash
am i misunderstanding what G.jokers.cards does? when i do this: newJoker = G.jokers.cards[-1] i get an "attempted to index a nil value" error, surely it should just give the rightmost joker?
also looks like G.P_CENTERS only pulls the vanilla jokers
last() also did not help me
hi coming back to balatro modding after a hiatus is there documentation yet for global operator stuff
holy moley you're alive
yep
operator stuff can be found on this page. Look for SMODS.Scoring_Parameter https://github.com/Steamodded/smods/discussions/919
does SMODS.find_card() work for non-jokers? it looks like it shouldn't looking at the source code and i'm annoyed by the amount of find_joker() calls in cryptid
I think your assumption is correct
god
gotcha ty
time to make Cryptid.find_consumable() to replace these then
😭
i am honestly considering fully rewriting my mod

the voices...

you missed 3 new releases of smods
i cant look at this code without getting physically sick
and also everything is broken as fuck
Sounds like a rewrite is worth
how i feel looking at my old figura avatar code
but that thing has like multiple months of effort put into it and a full rewrite is scary
yeah
astronomica rewrite will take weeks probably
but this whole mod is held together with tape and string so
its probably necessary
yea
does the print() function print into the console as in the log itself
🙏
im trying 😭
or where does it print
wish i had like a team or something
Both console and game log
ahhh kk
i dont have the passion i used to
Assuming you have DebugPlus obv
yea
:(
whats the button for debugplus again?
Should be / to open game console
you could find some
calculate = function(self, card, context)
if context.after and context.cardarea == G.play then
print("Hello")
my_cards = {}
cus im doing this as the start of my calculate function
and its not printing anyhting into the console
which is confusing me
need help, this is turning cards that have an enhancement into gold even though i dont want it to
that checks out
so how would i fix it?
not sure why that'd interfere with just printing to console though
wrap This is wrong, has_enhancement checks for a specific, specified one as a second argument. What you wanna check for is SMODS.has_enhancement(context.other_card) in a next()if not next(SMODS.get_enhancements(context.other_card)) then
My guess is context.after also never runs through G.play to begin with
calculate functions wiki page does seem to indicate context.after gets G.play as a cardarea
yea
how do i go about getting a function to use a specific consumable held? like using c_emperor as an example
like, as in trigger the consumable? or just check if you have it?
if it's the 2nd one, just use SMODS.find_card(key)
trigger the consumable, checking i can do but i'm struggling to actually assign the specific consumable to a variable so i can call G.FUNCS.use_card()
G.FUNCS.use_card({ config = { ref_table = selectedCard } })``` this doesn't seem to work
Is there a way to hide this?
am i missing smth with uh
checking the flame fx/score req
cuz i check G.ARGS.score_intensity.flames and am just getting 0 ,,
unless im not checking the right thing
-# to be precise im using it for effects involving beating a blind with one hand or Not doing so
you don't need to check that, they added a variable in 0827
if you specifically want to check if the player beat the blind in one hand, check for this + if it's currently the first played hand
np :3
Hey guys, where do I find all of the tags in the context?
I'm trying to find context.jokers_destroyed
Or make the card trigger when you destroy any joker.
(The card itself cannot destroy jokers, but it triggers when jokers are destroyed via means such as ceremonial dagger)
You want context.joker_type_destroyed
And context.card to check the destroyed card still.
Sorry for asking so many questions, but i'm trying to make a joker that turns played kings and jacks into queens, i took some of midas mask and ouija's code but it's activating all face cards, not just ones that scored
calculate = function(self, card, context)
if context.before and not context.blueprint then
local faces = 0
for _, scored_card in ipairs(context.scoring_hand) do
if scored_card:is_face() then
faces = faces + 1
local _rank = 'Q'
for i=1, #context.scoring.hand do
G.E_MANAGER:add_event(Event({func = function()
local card = context.scoring.hand[i]
local suit_prefix = string.sub(card.base.suit, 1, 1)..'_'
local rank_suffix = _rank
card:set_base(G.P_CARDS[suit_prefix..rank_suffix])
return true end }))
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
return true
end
}))
end
end
this is probably really bad code but here's what i have
what's the actual difference between nesting two layers of G.E_MANAGER:add_event and just using one?
🤷♂️
Is this an estrogen card?
so use and context.card.joker?
context.card.ability.set == 'Joker'
gotcha, imma try that
ok i was wrong it's actually changing ALL played cards instead of just scored face cards
For some reason it's not triggering when any cards are destroyed
whether that be hanged man or ceremonial dagger
(context.remove_playing_cards and context.cards[1]) or (context.joker_type_destroyed and context.card)?
Latter worked tysm
local xiferp_spade_change = psuedorandom_element(G.hand.cards, xiferp_astro_card)
set xiferp_spade_change to suit_conv //priorly set to spade
end```
How make this actual code?
to be clear, you want to pick a random card held in hand and change its suit to spade?
yeah, and the end of each round
look at any of the suit-changing tarot cards in vanillaremade
there's some event coding involved to get the nice visuals where the card flips around
(when I asked Astro what they wanted their card wanted to do in my mod, they said just that)
SMODS.Joker {
key = "astro_card",
blueprint_compat = false,
rarity = 2,
cost = 7,
pos = { x = ?, y = ? },
config = { extra = { suit_conv = Spades } },
loc_vars = function(self, info_queue, card)
calculate = function(self, card, context)
if context.end_of_round then
local xiferp_spade_change = pseudorandom_element(G.hand.cards, xiferp_astro_card)
return { vars = { card.ability.xiferp_spade_change, localize(card.ability.suit_conv, 'suits_plural'), colours = { G.C.SUITS[card.ability.suit_conv] } } }
end,
end
}```
How's this?
(most of the crucial code is cribbed from The World)
Alright, fine. Lemme set-up my other jokers first...
I am saving this
if context.scoring_hand[1] not context.blueprint then
if local eval = function() not G.RESET_JIGGLES then
juice_card_until(card, eval, true)
end```
This part of Corrupted Dna is itself corrupted, "then expected near not"
i hate shaders they just dont make sense to me how is it a re-occurring issue where i'll have a shader that works perfectly fine for ME but crashes for anyone else
hey whats the common way to spawn in jokers/cards/etc.
im trying debugplus's keybindings but its not working
in DebugPlus or Balatro?
Balatro.exe
debug plus should work what exactly are you pressing?
ah thanks
3
also ctrl+3
nothing works
also: is there a way to mass-spawn like all 150 vanilla jokers (its kind of important for what im testing)
what about ctrl+c
SMODS.Joker {
key = "astro_card",
blueprint_compat = false,
rarity = 2,
cost = 7,
pos = { x = 0, y = 2 },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra }}
end
calculate = function(self, card, context)
if context.end_of_round then
local xiferp_spade_change = pseudorandom_element(G.hand.cards, xiferp_astro_card)
SMODS.change_base(xiferp_spade_change, 'S')
end,
end
end```
eval for k, v in pairs(G.P_CENTERS) if v.set == "Joker" and not v.mod then SMODS.add_card({key = v.key}) end end in the console.
You're , is on the wrong end
like this shader runs and looks great for ME why does it instantly crash for anyone else?????
It should be on the loc_vars end.
Log?
oh and i can just do that with anything huh
okay awesome this makes stuff so much easier to test
still breaks in the same way
Code?
No, the code.
runs fine for me but when they crash from trying to view it its always like
Oops! The game crashed:
engine/sprite.lua:117: Shader uniform 'shockwaved' does not exist.
A common error is to define but not use the variable.
You have an extra end
where?
On line 87
Seems to break before then, but okay
this same issue was also present with overshielded before it got reworked into an entirely different shader
fixed it, same issue
my only solution i've found to this shit is literally just entirely different (usually much worse shaders)
Did you save the file?
yes. always do!
but shockwaved honestly looks sick i dont want to use the entirely different much worse looking shader (left) when a cool shader (right) exists :/
think i got it now
nope.
Everything is ready, except the literal last piece.
does anyone here understand shaders at all to tell me wtf is wrong with this?
code. Where problem?
Okay, the game's just angry.
It wants } at line 88, I give it } at line 88, it still wants } at line 88
top is message, bottom is code
why is that your mod's id
anyway you have one too many ends at the very end of the astro_card joker
SMODS.Joker {
key = "top_to_bottom",
blueprint_compat = false,
rarity = 2,
cost = 7,
pos = { x = 0, y = 1 },
local xiferp_top_to_bottom = SMODS.wrap_around_straight
function SMODS.wrap_around_straight()
if next(SMODS.find_card("j_xiferp_top_to_bottom")) then
return true
end
return xiferp_top_to_bottom()
end```
Where is the "unexpected symbol near local"?
what
no don't put the hook in the joker definition, you had it right before (albeit with weird indenting)
i literally gave you the answer to the original problem
can seals not return stuff like chips and mult in their calculate function? I keep getting this crash
No, they can.
how can I do that? even something as simple as this is causing the crash
No, you need a context check.
I tried context.individual, context.individual and context.cardarea == G.play, context.individual and context.cardarea == G.play and context.other_card:get_seal("customseal") but none worked. what's a context check that works for when a card with a seal is scored?
context.main_scoring and context.cardarea == G.play
that worked, thanks!
if context.individual and context.cardarea == G.play then
local reps = math.random(card.ability.extra.min_rep, card.ability.extra.max_rep)
print(reps)
return{
repetitions = reps,
message = "Again!"
}
end
why does it only retrigger once?
It's context.repetition not context.individual
nvm figured it out
slap negative on it or make it give 1 additional slot
does anyone know how much smaller specifically wee joker is?