#đ»ă»modding-dev
1 messages · Page 308 of 1
Show your current code.
local getidref = Card.get_id
function Card:get_id()
local id = getidref(self)
if id == nil then
id = 13
end
if next(SMODS.find_card('j_modprefix_dauphine')) then
if id <= 12 or id == 14 then
id = 13
end
end
return id
end
SMODS.Joker {
key = 'j_dauphine',
loc_txt = {
name = 'Dauphine',
text = { 'All cards with',
'{C:diamonds}Diamond{} suit are',
'considered {C:attention}Kings'
}
},
atlas = 'Jokers',
pos = {
x = 5,
y = 0
},
blueprint_compat = false,
perishable_compat = true,
eternal_compat = true,
rarity = 2,
cost = 6,
config = {
extra = {
}
},
}```
You need to add your mod prefix.
im not doing the diamonds part right now, first trying to get the pareidolia like stuff working
wdym?
ahhhhhh
Does your mod have a JSON?
In which file i add It?
no
The main one.
what does the smods header look like then
no
lol
Show your recent code.
local getidref = Card.get_id
function Card:get_id()
local id = getidref(self)
if id == nil then
id = 13
end
if next(SMODS.find_card('j_drx1_dauphine')) then
if id <= 12 or id == 14 then
id = 13
end
end
return id
end
SMODS.Joker {
key = 'j_dauphine',
loc_txt = {
name = 'Dauphine',
text = { 'All cards with',
'{C:diamonds}Diamond{} suit are',
'considered {C:attention}Kings'
}
},
atlas = 'Jokers',
pos = {
x = 5,
y = 0
},
blueprint_compat = false,
perishable_compat = true,
eternal_compat = true,
rarity = 2,
cost = 6,
config = {
extra = {
}
},
}```
Remove j_ when defining the joker.
wdym?
in the key?
okok, i added it bcs i saw it on the video w/o understanding it
works!!!!!
thank you very much!!
Ugh context.stay_flipped is so frustrating I understand why thunk coded the blinds that used it like that but fuck
Hard to use it on drawn cards
is the suit check different than usual outside the calculate? (or can i put it in calculate as in "if not context.etc.diamonds then return end"?)
so return 13 at the end instead of return id?
Error
game.lua:4032: attempt to index global 'SMODS' (a nil value)
Traceback
[love "callbacks.lua"]:228: in function 'handler'
game.lua:4032: in main chunk
[C]: in function 'require'
main.lua:16: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
It worked now but the animation is gone which showed the cards being burnt
calculate = function(self, card, context)
card.ability.mult_bonus = card.ability.mult_bonus or 0
if not card.ability.marked then
card.ability.marked = false
end
if context.setting_blind and context.blueprint then
card.ability.mult_bonus = 0
card.ability.marked = false
end
if context.destroying_card and
G.GAME.current_round.hands_played == 0 and
context.cardarea == G.play and
not card.ability.marked then
card.ability.marked = true
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
local burned = 0
for _, c in ipairs(G.play.cards or {}) do
if c and not c.removed then
c:remove_from_deck()
burned = burned + 1
end
end
card.ability.mult_bonus = card.ability.mult_bonus + burned
G.deck.config.card_limit = G.deck.config.card_limit - burned
if burned > 0 then
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = burned..' Burned!',
colour = G.C.FILTER
})
end
return true
end
}))
end
if context.joker_main then
return {
mult = card.ability.mult_bonus,
card_end = true
}
end
return {}
end
}
You check is_suit
just is_suit('Diamonds') ?
or do i have to do a separate hook?
@daring fern I had kept an animation where the cards get burnt after being scored instead of flying back to the deck animation
wdym
Can you record what you mean?
So it triggers and checks each time a card enters and leaves the hand, be it draws, discards, and played cards. So it triggers twice usually for every situation but the starting hand, and Iâm trying to get it to trigger every N cards which is possible, just annoying (as the first hand only triggers it once per card, effectively)
yeah that sounds terrible
ThatâŠ. looks like exactly what you want?
Itâs also undocumented to boot
So Iâve been looking through the code and puzzling it out
I've only used it to flip cards after each hand, but I haven't tested it too thoroughly
Yeah that it does pretty easily
@daring fern and @wintry solar see how the animation is after the first hand cards are chosen and burnt
Yes thatâs what you said it should do
do you know if SMODS' API allows me to apply a shader to a Joker directly
drawstep?
that's not directly
tried to check the suit like that but i dont know to do it outside of a smods joker, please dont hit me, (ofc it doesnt work)
local getidref = Card.get_id
local getsuitref = Card.is_suit
function Card:get_id()
local id = getidref(self)
local suit = getsuitref(self)
if id == nil then
id = 13
end
if suit == nil then
suit = 'Diamond'
end
if next(SMODS.find_card('j_drx1_dauphine')) and suit == 'Diamond' then
if id <= 12 or id == 14 then
id = 13
end
end
return 13
end```
Drawstep does that
multiple includes 1 đ
Drawstep is for any card drawing
because they seemed inefficient if you were doing individual stuff
see above
It just replaces the draw function with a system thatâs easily added to
My multilayer Jokers right now don't use DrawStep because they all have custom movement
How can I display a custom message when you press use on a consumable but it doesn't use it, for example the one I'm working on now will check if the hand size is above 5, if it isn't I want it to say "You're already small enough"
Is there an easy way to add custom movement to a DrawStep?
Whereâs your current code?
it's usually something like this
I think your just take the draw code and put it in the drawstep
But if this still works I donât see why youâd need to change it
but the movement so far is custom per card
well, this one specifically is shared with another one
how would I access the correct movement?
do i check the is suit within the function Card:get_id()? or do i have to make a Card:is_suit() separate?
I also need to individually list each key in a separate file to avoid drawing them twice
though now that I think about it, maybe I don't need to give each sprite an unique key?
You could probably save the movement values within each joker and use a generic drawstep
Or do separate ones
Doing separate ones seems inefficient
SMODS.DrawStep {
key = 'chameleon',
order = 1,
func = function(self, layer)
if self.config.center_key == 'j_ortalab_chameleon' then
if self.ability.extra.copied_joker then
if self.children.front then self.children.front:draw_shader('dissolve') end
self.children.center:draw_shader('ortalab_chameleon', nil, self.ARGS.send_to_shader)
else
self.children.center:draw_shader('dissolve')
end
end
end,
conditions = { vortex = false, facing = 'front' },
}```
This is my chameleon drawstep for example
Yes the @daring fern code fix is working but that animation isn't so is there a proper way to add the burning/destroying animation so the cards burn after being scored instead of flying back to the deck
how would i create custom badges?
That animation is for when a card is destroyed
What if you wanted a set of Jokers to share the same DrawStep?
Give them some sort of common property
but how
I believe thereâs also a check_conditions function you can define on the draw step
SMODS.Joker{ ⊠my_property = true, âŠ}?
How do you check hand size?
what's the difference between .front and .center here? Or did you define one of them for this Joker specifically?
Thatâs specifically for that joker
so you still need to set the sprite to give your Joker a child
what if the property is a function?
Can I use it to describe the movement?
I donât see why that wouldnât work
SMODS.DrawStep {
key = 'curse',
order = 35,
func = function(self)
if self.curse then
Ortalab.curse_sprites[self.curse].role.draw_major = self
Ortalab.curse_sprites[self.curse]:draw_shader('dissolve',0, nil, nil, self.children.center,nil,nil,nil, nil,nil, 0.6)
Ortalab.curse_sprites[self.curse]:draw_shader('dissolve', nil, nil, nil, self.children.center)
end
end,
conditions = { vortex = false, facing = 'front' },
}```
Hereâs another one that might be more useful
-# I donât remember how it works
There's a Joker I'm gonna want to make that will need 2 DrawSteps to work
and I have two Joker ideas that might need some complicated DrawStep calculations to work
Yah I want that animation, the destroying animation like the video was doing (the video I sent is my old code which has errors) now the new one works perfectly everything works no errors nothing just that the cards are going back to the deck (the animation) instead of the destroying animation
by trying to check the color i end up disabling the joker from working at all, what did i do wrong?
local getidref = Card.get_id
local getsuitref = Card.is_suit
function Card:get_id()
local id = getidref(self)
local suit = getsuitref(self)
if id == nil then
id = 13
end
if next(SMODS.find_card('j_drx1_dauphine')) and suit == 'Diamonds' then
if id <= 12 or id == 14 then
id = 13
end
end
return id
end```
@daring fern did u understand đ or am bad at explainations
Show the code
There must be something wrong with it if the animation isnât olaying
My original code or the one fixed?
The one that you have that doesnât work how you want
Here is the code @wintry solar
Can you screenshot pls reading code on mobile is a pain
đ true
calculate = function(self, card, context)
card.ability.mult_bonus = card.ability.mult_bonus or 0
if not card.ability.marked then
card.ability.marked = false
end
if context.setting_blind and context.blueprint then
card.ability.mult_bonus = 0
card.ability.marked = false
end
if context.destroying_card and
G.GAME.current_round.hands_played == 0 and
context.cardarea == G.play and
not card.ability.marked then
card.ability.marked = true
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
local burned = 0
for _, c in ipairs(G.play.cards or {}) do
if c and not c.removed then
c:remove_from_deck()
burned = burned + 1
end
end
card.ability.mult_bonus = card.ability.mult_bonus + burned
G.deck.config.card_limit = G.deck.config.card_limit - burned
if burned > 0 then
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = burned..' Burned!',
colour = G.C.FILTER
})
end
return true
end
}))
end
if context.joker_main then
return {
mult = card.ability.mult_bonus,
card_end = true
}
end
return {}
end```
@wintry solar
How's this?
not amazing
Thatâs even worse
@wintry solar âïž
Is that the right function to remove cards from the player's hand
Thanks sdm
It doesnât work because you donât return anything from the context
You need return { remove = true }
But also
This code is ridiculously complicated for what youâre trying to do
Yo @maiden phoenix thanks
how would i create a card with an edition?
As the function of the card is burn first hand gain mults per burnt card and the mult keeps on growing in the run per every total cards burnt
Yes it should be like 6 lines
@wintry solar question about DrawSteps: are all DrawSteps called for all cards?
I think so
isn't that inefficient?
that's why I didn't want to use them
Itâs just what Card:draw does
a DrawStep per Joker increases overhead by a lot
the Card itself could know how to draw itself
U mean I should put this in the last return { } ?
Not really.
Mostly because the "drawing" parts are not done if proper conditions aren't met.
And the function related to those are effecient enough that there really isn't a problem.
how would i make my mod talisman compatible
if talisman then talisman = nil end
The actual performance overhead for calling a function and indexing tables before trying to draw is miniscule.
DrawSteps also don't allow me to share variables between different DrawSteps
It just seems like a mostly worse system than what I already have đ€
You put to_big when comparing tables with numbers
k
I changed the name of my sprite and now it's rendering twice đ€
except seemingly for one of them
How do I check if a highlighted card is a face card
If you have two steps that need to communicate with each other, what's stopping you from just adding a value onto the card itself?
SMODS already does this with self.tilt_var
if G.hand.highlighted[1]:is_face() then
What is the one for?
because: 1) it could be a local variable instead; 2) I'm trying to use a vanilla variable
that is local
It means the first highlighted card in hand.
What if I want to check if all highlighted cards are face
Do they need to be 2 steps? Canât they be in the same one?
@daring fern (sorry for the ping)
The other one is vanilla's
a soul sprite (with custom movement) and a second sprite (with custom movement)
although to be fair, this particular version could've used a single sprite
Just donât use the standard soul stuff and use a drawstep for both
it doesn't seem right to not use the existing feature
Youâre overwriting the existing feature anyway
It's not overwriting if SMODS provides an API for it
and again
I can access the local variable this way
You would iterate over all of G.hand.highlighted
How?
do I do a "for" loop?
Do I start i = 0 or do I start at 1
@daring fern Like this?
1
should I turn that is_face check into an if statement and then return true
You would probably check if any are not face then return false elsewise return true
How would I word that
end return true```
Put return true outside the for loop.
Why not just return the function call?
like this?
This also doesnât need a loop
Well it didn't work anyway, so what is another way to do it
actually nvm it did work, forgot to save before I opened the game
does smods have a way to use context.destroy_card to store those cards somewhere
if i start with a joker's key, can i check if it's unlocked and discovered by looking for it in G.P_CENTERS?
.discovered and .unlocked could be checked for.
-# I can only vouch for .discovered, though.
that's what i'm thinking, G.P_CENTERS['j_joker'].config.center.unlocked
it seems to be in fact, just G.P_CENTERS['j_joker'].unlocked
How would I go about adding the same functionality of the "Strength" card but opposite
so instead it decreases in rank
Question for the SMODS heads, what is the purpose of the obj_buffer concept on some SMODS tables versus just iterating through the table itself?
This might be a Lua thing that I just haven't wrapped my head around yet
is it anything like the vanilla buffers
Afaik no? Because the buffers can be iterated through as tables, whereas the vanilla buffers like with joker and object count buffers are numbers
I got this crash with this code
I'm under the implication that you're supposed to use the vanilla buffers as you'd expect, to pre-empt a change made to one of the cardareas by a newly emplaced card. But instances where things like SMODS.Rank.obj_buffer are iterated through kinda confuse me. I forgot I didn't leave the SMODS server so I'll ask there
The first parameter has to be a card, not a table, just iterate over your highlighted cards trough a loop
yeah, G.hand.highlighted is a table of cards but the func wants the card itself
this better?
G.hand.highlighted[i]
what did you end up with
in code yes
What is your current code?

G.hand.highlighted[i] was meant to go in the function where you have i, in place of it:
for i=1, #G.hand.highlighted do
SMODS.modify_rank(G.hand.highlighted[i], -3)
end
Oh I'm sorry, I misunderstood, apologies
it makes sense, i wasn't clear enough 
Now how can I add chips at the same time
adding permanent chips to the card, like hiker?
No to the side thing (forget what it's called), and also how can I add the card flip
enhancement?
wait, do you mean add chips to the current score?
Yes! To the side where it's like Chips X Mult
sorry I suck at wording things, I can't even word the description right for this card
this is a consumable, right?
Yeah
unless it's either not possible or just not a good effect then I'll change what this consumable does besides decreasing a face card's rank
oh, it's definitely possible, just beyond my knowledge specifically
i do like the idea of a consumable being able to mess with the score, though
-# outside of observatory
I've just been trying to come up with ideas for Alice in Wonderland themed cards and I started with consumables and this was the "Drink Me" Potion so like in the movie it makes her small (hence the card rank decreasing) but I wanted it to benefit as well, rethinking about it I don't like the idea of adding chips
there's inherent benefits to decreasing card ranks
^hack
anyone know how you might show compatibility on jokers that have a copying effect? the same way that blueprint does in base game? possibly a silly question im just getting into modding for fun
but just face cards? Does that make sense?
is there inherent benefits to doing that
absolutely. ride the bus, hack as mentioned... there's a bunch of different builds that can benefit from being able to make the deck more consistent with decreased face cards
blueprint_compat = true/flase
in your joker^
like this
ah, my interpretation was that they were looking to copy how blueprint does that
not the other way around
bear in mind that blueprint_compat is purely cosmetic - blueprint and brainstorm call calculate with the special context of context.blueprint
What is a good rarity for a Joker that adds an enhanced Queen of Hearts when each blind is selected
balancing questions tend to go more in #âă»modding-general but i would say rare
Alright and right wrong place, I'll remember for next time
Yes, I wanted to see how blueprint itself shows "Compatible" or "Incompatible" ingame, if I were to make a second version of blueprint
How do I add the color and description for gold, steel, and holographic to my joker's description
it uses main_end in loc_vars
put the key in the info_queue
what about coloring the text?
{C:âŠ}
i have weird green particles around cards in my booster pack, how do i get rid of them?
Do I need to have a loc_vars function if my card doesn't have any variables
if your localization entry doesnt have any #number# in them then you dont need loc_vars
Alright, then where do I put the function for the info_queue
Alright thanks
E and I assume all the letter jokers that have have to do with playing cards gain mult when you have an eight and you don't play it.
also G upgrades on all the blind...
is there any way to make default (non-edition) cards to use a vanilla Balatro shader? I just can't wrap my head around it. nothing i try works
for example i want all planet cards to use the same shader that spectral cards use. but how?
Let me write it up for you, hold on
It's not creating the card, nothing happens when I select a blind
ok that old problem is fixed, now i cant find in the docs how to set background color for the pack
your function signature is wrong. calculate = function(self, card, context)
how is john smods doing
i'm well, ty for asking
Is that the only problem?
it is the problem that's preventing your code from running
the rest looks good to me but I'm too tired to guarantee for it
It worked
calculate = function(self, card, context)
if G.GAME.current_round.hands_played == 0 and context.destroying_card then
card.ability.mult_bonus = card.ability.mult_bonus + 1
return {
remove = true,
message = "Burned!"
}
end
if context.joker_main then
return {
mult = card.ability.mult_bonus
}
end
end```
-# no extra?
Is there a way to check if a flush contains all hearts
I just copied the values he already had
Someone else can fix his missing extras, Iâm going to bed đ
won't be me
Speaking of extra. Returning {extra={repetitions=X}} from calculate doesnt seem to actually want to calculate them.
hi
So what's the better way?
That message was unrelated to your problem, but as far as I can find, its setting extra.rep to nil, and adding it to rep
what smods version are you using?
this should be something that is fixed ahead of the latest release
Nothing recent lol, lemme check.
0315b, it was what cryptid staff was advertising week or 2 ago
I also couldve sworn I looked at the code for 0408 and the part where extra is eval'd didnt change
yeah that would do it, 0330a is the first version to have that fixed
I've seemingly made a shader that is immune to randomness
What do you think of this effect?
Cherry
After you use a Consumable, sell this card to create 2 copies of it
(Must have room)
compatible with spectrals too?
Yes
Sure
Cryptid's pointer: 
They aren't that good
Am I missing something here? testing with just one atlas.
SMODS.Atlas{key = "TOGARetroSkin", path = "togaretrodeckskin.png", px = 71, py = 95}
SMODS.DeckSkin {
key = "retro",
suit = "Hearts",
loc_txt = "test",
palettes = {
{
key = 'lc',
ranks = {'Jack', 'Queen', "King", "Ace",},
display_ranks = {'Jack', 'Queen', "King", "Ace",},
atlas = 'TOGARetroSkin',
pos_style = 'deck',
},
{
key = 'hc',
ranks = {'Jack', 'Queen', "King", "Ace",},
display_ranks = {'Jack', 'Queen', "King", "Ace",},
atlas = 'TOGARetroSkin',
pos_style = 'deck',
},
},
}
Did you guys remember what I said?
what rarity?
It was meant to be common
yeah that sounds about right
With this effect it might be uncommon
I'm not sure I want the Spectral interaction
instead of two copies just make one
That's just the Fool
well fool cant interact with spectrals
@frosty dock #đ»ă»modding-dev message đïžâ
i'm making an edit of the example jokers mod to see if i can make a version of walkie talkie for +5 chips and +10 mult for each 5 and 10 in hand but it seems to be triggering at the end of the blind too, how do i prevent this?
and not context.end_of_round
ok thanks
What extras were u talking about
also why are you returning context.other_card in your local vars
oh i added that thinking it might fix the issue i am really bad at understanding this stuff and all the documentation is a bit overwhelming so i'm kinda just throwing myself at it
i don't understand lua (or any coding language) very well at all i just wanna try make something
thats fair, local vars are returned for your localization stuff so in your case its for loc_txt, you see how you have a #1# and a #2# in there? those 1 and 2 values take the first and second variable that you are returning in your loc_vars
even if it's basic
makes sense?
i think so
so since you do not have a #3#, you have no reason to return a "third" variable, in your case your third variable would throw an error anyway since its not a valid return
gotcha
however, in your calculate function
you returning context.other_card matters
because the message of the localization (the +chips and +mult) MUST be on the playing cards
not the joker itself
ok right
for example, if you were to not return card = context.other_card then the +chips and +mult would appear on your joker
gotcha okay thanks
i could be wrong, someone feel free to correct me
im new to this myself lol
wait its not card = ..
you should use message_card = context.other_card the examples are a bit outdated. you never need to return card = something
sure thanks
What is the code to check for a certain poker hand being played
Specifically or if the hand contains said hand?
context.scoring_name
context.scoring_name == 'Flush'
oh wait i was doing an edited version of Runner in my edited examples and it uses context.poker_hands?
How do I fix this?
and how can I check if all of the cards are the same suit
also i was trying to change this so instead of adding to the chip count like runner it would just create an earth consumable but that went terribly
thats to check if it contains the poker hand rather if thats the poker hand actually being scored
ah ok
code time?
Scored cards or all cards played? Either way, you'd have to iterate over either hand.
in a flush?
Yes
Oh I am dumb
oops
but are a specific suit is what I meant to say like a Flush of Hearts
you can check the first card in context.scoring_hand
and check card.base.suit
or card:is_suit if you want a specific one
do I do if context.scoring_name == 'Flush' and context.scoring_hand == something
context.scoring_hand is a table
if you want to check for a specific one then context.scoring_hand[1]:is_suit("Hearts")
New plan: I rework Rebate Tag to have this effect, then I make Cherry create the Tag previously known as Rebate Tag
Thank you!
guys?
?
^
I got this crash after just selecting the five cards needed for a flush
I donât understand what youâre saying
when you hold like an 8. E triggers.
my letter joker.
if anyone feels like taking a look at this and seeing why it's causing an error on launch let me know i do not understand errors and it's probably a very simple mistake
I have A through K made. A, B, C, D, E, H, and I have logic errors.
i'm guessing blus1 is pluto but i'm honestly not sure i just kinda took that from balatro's code
Try to solve one at a time
the emplace is mispelled
but I doubt that is causing your issue
ok so A..
ok idk what that file is gg
i just copied on the crash screen so i guess that is the error
just screenshot it
try SMODS.create_card
with the key of 'c_earth'
brb
It is telling you there is an unexpected symbol on line 109
Worked đ
Is there any way to check for face down cards when you go to scoring? As far as I can tell they get flipped up before context.before sees them and can check, and Iâve not been able to figure out any trickery of checking highlighted cards first
crashed when i played a full house, lemme know what you think cuz i am still clueless and probably didnt even follow your instruction correctly
SMODS.add_card{key = "c_earth"}
Idk what could be causing this to happen, before I even play the hand
gotta ask again: is there any way to make planet cards use the same shader as spectral cards?
what's line 153
oh i see
should it be "H" instead of "Hearts" or is that the wrong quotation marks
sick that worked thanks
you need to define a specific context
now i just need to add a visual to the joker when it creates the earth card
Should I do context.main_scoring?
so context.joker_main on top of those other ones
yeah
like part of the and, or in it's own if statement
both work
--Function to store last destroyed card
G.destroyed_cards = {}
local function capture_destroyed_card(card)
if G.STAGE == G.STAGES.RUN then
local rank = card.base.id
local suit = card.base.suit
local enhancement = SMODS.get_enhancements(card, extra_only)
local edition = card.edition
local seal = card.seal
table.insert(G.destroyed_cards, card)
print("Rank destroyed: " .. rank)
print("Suit destroyed: " .. suit)
print("Enhancement: " .. (enhancement or "None"))
print("Edition: " .. (edition or "None"))
print("Seal: " .. (seal or "None"))
end
end
local original_shatter = Card.shatter
local original_start_dissolve = Card.start_dissolve
function Card:shatter(...)
capture_destroyed_card(self)
return original_shatter(self, ...)
end
function Card:start_dissolve(...)
capture_destroyed_card(self)
return original_start_dissolve(self, ...)
end
would this be the right way to record destroyed cards?
i feel bad that i'm constantly posting these but uh where did i go wrong this time...
currently the print enhancement is throwing an error since it is a table which cannot be printed with a string in the way i implemented it
i'm guessing the card?
also youre not creating your consumable in the calculate function which i suspect you would have to do
ah ok
to indent the code do i just copy and paste it from notepad++ and use the format with these guys ``
no i mean like for yourself lol
code is not easy to read and spot errors in when its written like that
ah ok
everything you have from message = onwards should be in a return
do you want to only do playing cards or any card
card = card is redundant, it will default to joker anyway, you can get rid of it
Is there any way to use pseudorandom_element with G.P_CENTERS, but limit to jokers only? I'm trying to make it so the joker that spawns on the splash screen is randomized, but replacing G.P_CENTERS['j_joker'] with pseudorandom_element(G.P_CENTERS) can also spawn spectrals and tarots
only playing cards
pseudorandom_element(G.P_CENTER_POOLS.Joker).key
then you can probably just hook SMODS.calculate_context and check for context.remove_playing_cards. your hooks will get any card without a check
thank you :), let me try this
so i would do if context.remove_playing_cards in my initial function yes?
where would i use the SMODS.calculate_context
if you only need it for one joker then just use that context directly
only hook calculate_context if you need it globally
Awesome, it works! Just had to remove the .key. Thanks a lot!
its not for a joker, its for a consumable that would create the last card you destroy
but i would need it for other uses later which is why im using a hook
yeah then hooking the smods thing makes sense for that
so i just need to add this then yeah?
anyone knows why my joker just gives me +mult and not the +chips also?
ohhh right got it working now thanks
yeah and do a loop through context.removed to get the cards
awesome okay let me try
iirc its chip_mod not chips_mod but lemme check
i was correct
Why not just chips = and mult =?
One of them is for playing cards and the other is from jokers from what I remember
so i modified my function to do this but im running into this error, i know context is supposed to be passed into calculate functions (?) but what calculate function would i use for something like this
if G.STAGE == G.STAGES.RUN and context.remove_playing_cards then
this is line 194
are you hooking calculate_context
ah thats what im missing
How are you running capture destroyed?
wdym
Or is it supposed to be something that just runs without any centers attached
is there a list of colours like
colour = G.C.CHIPS,
on the wiki somewhere?
thanks
There are some things that are out of date, but this is what I use
didn't breeze write that like a week ago
if the question is where im calling the function, its in these two hooks
but i think im supposed to replace these with
SMODS.calculate_context
yeah
Yes but it lists G.C.INACTIVE but that isnt a thing. I thought it was out of date, but I guess its just wrong....
it might be just wrong yeah
I mean. You can probably do it without contexts.
Not sure if it would be better or not.
i tried but couldnt get it working, since the game calls shatter and disolve without a card actually being destroyed when a run starts
You wouldnt need context for that I dont think.
i think it's easier and cleaner by using the context, you can do it without but requires more checks and stuff
Err yea i was thinking just removed cards, but their function is destroyed
Though honestly, checking the specific area of a card might be good.
--Function to store last destroyed card
G.destroyed_cards = {}
local function capture_destroyed_card(context)
if G.STAGE == G.STAGES.RUN and context.remove_playing_cards then
for k, v in context.removed do
local rank = v.base.id
local suit = v.base.suit
local enhancement = SMODS.get_enhancements(v)
local edition = v.edition
local seal = v.seal
table.insert(G.destroyed_cards, v)
print("Rank destroyed: " .. rank)
print("Suit destroyed: " .. suit)
print("Enhancement: ")
print(enhancement)
print("Edition: " .. (edition or "None"))
print("Seal: " .. (seal or "None"))
end
end
end
local base_calculate_context = SMODS.calculate_context
function SMODS:calculate_context(context, return_table)
capture_destroyed_card(context)
return base_calculate_context(context, return_table)
end
like this?
yeah
you could just do a nil check first
and context ?
since my function is only being called for calulate_context
let me look at the code again on my pc instead of mobile lol
i appreciate it
also i believe it shouldn't be SMODS:calculate_context
it should be SMODS.calculate_context
oh yeah that
: denotes it being a class function that takes in self automatically as the first argument, referring to the class instance
i dont understand the difference, someone told me it was the difference between adding a "self" and not in the ()
ah
okay i understand
also are you planning to save the destroyed cards in saves because they probably won't save properly here
atleast in my experience
next problem now đ
for k, v in context.removed do
ipairs
ipairs ,,,,
why wouldnt they, im saving it in a global variable yes?
lol yes ty
oh i didnt see that you were also saving the cards, those get nullified after destruction
cards aren't saved as is
ah
and when they get destroyed, any reference to them becomes nil
local suit = v.base.suit
local enhancement = SMODS.get_enhancements(v)
local edition = v.edition
local seal = v.seal```
i can use these values to recreate the card then yes?
i would just save these instead of v itself
yeah thats what i thought you were doing
yeah that was going to be my next step after fixing the initial problems
What exactly is the end goal of this? I joined a bit late
or create a copy of a card but you need to save those to a cardarea probably
i want to create a tarot card that creates two copies of the last destroyed card with random editions
ill be adding them into the players hand, like how immolate does
yeah you can just save the relevant information and use that as data for a card you create later
You could save copy_card()
Instead of fully recreating it, and probably missing mod specific data
so far so good
But then you would need another area for it
if you do just save the entire card then you will need to use a cardarea yeah
this might be a dumb question but
if only we had autumn's graveyard code..
what are card areas, like consumable slot joker slot player hand? etc
yeah
ah yeah, ill use that for when i implement the tarot card
rn im seeing if i can extract relevant information out of the destroyed card
how do i get the specific enhancement as a card.center from the SMODS.get_enhancement(card) thingy
whats this
wait
true
i can just see how copy_card() extracts data
genius
they had a mechanic in their mod where playing cards went to the graveyard
but they quit and deleted their mod
unfortunate
hi
i dont have thac
but i have graveyard (original)
how are you doing myst
I would probably recommend copying it, and making it put the info in a table instead of creating a new card
the horrors
understandable
thank you :) let me see how i can tweak it to my purposes
hmm i cant do this within the tarot however since i need to track destroyed card for each run since the start
You can clear the table at the start of each round
How could i change stone for a list of enhancements?
calculate = function(self, card, context)
if context.setting_blind and not card.getting_sliced then
G.E_MANAGER:add_event(Event({
func = function()
local front = pseudorandom_element(G.P_CARDS, pseudoseed('cave'))
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local card = Card(G.play.T.x + G.play.T.w/2, G.play.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.m_stone, {playing_card = G.playing_card})
card:start_materialize({G.C.SECONDARY_SET.Enhanced})
G.play:emplace(card)
table.insert(G.playing_cards, card)
return true
end}))
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_plus_stone'), colour = G.C.SECONDARY_SET.Enhanced})
G.E_MANAGER:add_event(Event({
func = function()
G.deck.config.card_limit = G.deck.config.card_limit + 1
return true
end}))
draw_card(G.play,G.deck, 90,'up', nil)
playing_card_joker_effects({true})
end
end}```
wait instead of returning a new card, i could just pop that new card into my destroyed cards table, but this is where the card area thing you said comes into play yes? since that new card needs to "go" somewhere
Is there a list or table that houses every joker key loaded?
G.P_CENTERS
You will need to filter for set == "Joker" though
yeah cards are not saved unless theyre in a cardarea in G
ahhh
i suppose the challenge is now in the fact i cant let the player access that card until the tarot is used
hmm
you can hide cardareas
oh sick
so basically create new area, keep it hidden
wait no
i cant create a card area can i
you can
my mod has like 20 new cardareas
:o
what warrants needing all those card areas
play it and find out đ
can you link, i would rather search through code than bug you with questions (unless you dont want me to)
i need to play joyousspring ,,,
this is probably the most similar to what you want but i dont do stuff with playing cards only jokershttps://github.com/nh6574/JoyousSpring/blob/main/src/banishment.lua
Now would be when I link the wiki, but I see no cardarea wiki page
yeah thats what i tried finding lol
thank you
lsp?
language server processesor or smth like that
when i change this the game crashes
The Language Server Protocol (LSP) is an open, JSON-RPC-based protocol for use between source code editors or integrated development environments (IDEs) and servers that provide "language intelligence tools": programming language-specific features like code completion, syntax highlighting and marking of warnings and errors, as well as refactorin...
Can you show the code around?
goddamn
calculate = function(self, card, context)
if context.setting_blind and not card.getting_sliced then
G.E_MANAGER:add_event(Event({
func = function()
local front = pseudorandom_element(G.P_CARDS, pseudoseed('cave'))
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local card = Card(G.play.T.x + G.play.T.w/2, G.play.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.ruby, {playing_card = G.playing_card})
card:start_materialize({G.C.SECONDARY_SET.Enhanced})
G.play:emplace(card)
table.insert(G.playing_cards, card)
return true
end}))
card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_plus_stone'), colour = G.C.SECONDARY_SET.Enhanced})
G.E_MANAGER:add_event(Event({
func = function()
G.deck.config.card_limit = G.deck.config.card_limit + 1
return true
end}))
draw_card(G.play,G.deck, 90,'up', nil)
playing_card_joker_effects({true})
end
end}```
i changed to "ruby", it is a custom enhancement from my mod
you need your mod prefix + the class prefix
unless you disabled them
fus_m_ruby then?
m_fus_ruby
tyty!
if i wanted to call an list i set before, how would i do that?
like, i want a joker that creates a card with one of the enhancements for the list everytime a bllind is selected
i only need to figure out the part where it chooses one random from the list
upon reading the lsp wiki
ive decided that instead of messing around with creating new card areas
pseudorandom_element({'S','H','D','C'}, pseudoseed('sigil')) smth like this. The suit initials would be your list, and sigil would be the seed
i will store an entire table of values instead
and use those values when needed by the tarot
lol
so
local card = pseudorandom_element({sapph, cob, ruby, cinna, red}, pseudoseed('cave'))
?
If you have your list, just put the list there.
Thanks to everyone who helped me out earlier, really appreciate it and I think I'm starting to understand it a bit better now!
okok! anything more?
crashed
That would be how you implemented it. Show code.
Those are editions. local card is being set to an edition
dont name ur vars "card", it overrides "card" from calculate btw đ„
^
shouldnt affect anything in ur code rn but its a bad practice
where is this set? i dont see it
in the "local card ="?
i did and got another crash
and i also changed the times it was mentioned to the new name
what are the arguments for juice_up again?
--Function to store destroyed cards
function card_information(other, playing_card)
local scale = 1
local card_snapshot = {}
card_snapshot.T = { x = other.T.x, y = other.T.y }
card_snapshot.width = G.CARD_W * scale
card_snapshot.height = G.CARD_H * scale
card_snapshot.playing_card = playing_card
card_snapshot.base = other.config.card
card_snapshot.center = other.config.center
card_snapshot.ability = {}
card_snapshot.ability.type = other.ability.type
for k, v in pairs(other.ability) do
if type(v) == 'table' then
card_snapshot.ability[k] = copy_table(v)
else
card_snapshot.ability[k] = v
end
end
card_snapshot.edition = other.edition or {}
check_for_unlock({type = 'have_edition'})
card_snapshot.seal = other.seal
if other.params then
card_snapshot.params = copy_table(other.params)
card_snapshot.params.playing_card = playing_card
end
card_snapshot.pinned = other.pinned
return card_snapshot
end
G.destroyed_cards = {}
local function capture_destroyed_card(context)
if G.STAGE == G.STAGES.RUN and context.remove_playing_cards then
for k, v in ipairs(context.removed) do
local info = card_information(v, nil, G.playing_card)
table.insert(G.destroyed_cards, info)
end
end
end
local base_calculate_context = SMODS.calculate_context
function SMODS.calculate_context(context, return_table)
capture_destroyed_card(context)
return base_calculate_context(context, return_table)
end
so this is the implementation i came up with
and when i use the tarot card, i would index the last card_snapshot within G.destroyed_cards
and use all the information within it
table within table (within table)
hey guys. what should I do to fix this?
wdm logic errors
So Iâve figured out how to track flipped cards on scoring by attaching an additional variable to them on flip thatâll be checked for on scoring, though it wouldnât work with the blinds
The problem is like, clearing that on unscored cards if you sell the joker
in SMODS.create_card(t) what set should i use for playing cards?
you dont
sick ty
np
and similarly for area
i would not either right
default would just be the playing hand?
local _rank = pseudorandom_element({'J', 'Q', 'K'}, pseudoseed('never_punished'))
local _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('never_punished'))
local _card = create_playing_card({
front = G.P_CARDS[_suit..'_'.._rank],
center = G.P_CENTERS.m_glass
}, G.hand, false,false,nil)
_card:add_to_deck()
table.insert(G.playing_cards, _card)
_card.states.visible = nil
G.E_MANAGER:add_event(Event({
func = function()
_card:start_materialize()
return true
end
code i use to create a random face card
create card can only make jonklers
oh nvm then
awesome i can use this
oh that code creates a random glass face card
fyi
yup gotcha, ill replace it with the edition i stored above
guys how would I make this work? I'm trying to balance the base mult and chips of poker hands but when a card scores it just goes back to normal values
It gains mult when you hold the card it says for those and I forgot F in there too.
you cant add seals or editions within create_playing_card eh
you have to do a thing
i forget what it is
check certificate code
okok
hiya! any common reasons why i might be getting this error?
i tried reupscaling the images in Phanta and BFDI, but no luck
okay aha what.
i removed one of my Spectral cards
and. huh.

???????????
How big are the files?
I think mine might be a tiny bit bigger HxW wise and is half the file size
oh is that your 1X?
That's my 2X
ah right
ya mine's 12x11
yours seems to be 9x12
oh i know why mine's so much larger
It is, but that doesn't seem like +200kb bigger??
to fix the dark edge bug, i ran a script to set the colour of all transparent pixels ^^
that's probably why
That sounds very hardware heavy lol
Also, dark edge bug?
do you have any decks?
a few
show me one of them :D
bingo. see those little grey lines, between the cards?
i'd boot up the game to show you, but i can't -w- but
most of the vanilla decks don't have that issue
iirc there are a couple for. some reason
Are you sure that's not just the CRT effect?
you can turn that off to confirm
Comparison for myself
ya there you go
look at the corners
Ah ok
it applies to all your cards, but it's more noticable on transparent Jokers, and Souls
i use this script to fix it, and it also upscales my assets for me
interesting, however doesn't seem worth the hassle lol
but, it requires Pillow, and you need to change the link in the code ^^
ya fair ^^"
okay anyway
gonna try lovelyignoring Phanta to see if it's causing the issue
oh nope.
What changes did you make immediately before it started causing issues?
i added a Spectral card, but removing it again caused the game to run out of memory
Very odd. Are you loading your cards' codes from external files or are they all in one big master file?
I wonder if your loop is running infinitely somehow
Take a look into how your cards are being loaded. I feel like that may have something to do with it
here's the Spectral working :D
You should make it draw cards after use
sounds difficult, but i'll give it a go :D
hmm, how would i go about doing that? i'd need to check if a card can even be drawn in the first place, as it can be used outside of a Blind
it should count Spectral packs too, though
Spectral makes more sense than how i have handsize in Shinku's Card Binder...
An Enhancement
Wdym by that?
I... might have made quite a big if check around that for my enhancement that could be repurposed?
like, say you open a Mega Spectral pack, and get a Norwell Wall, and choose it first
ooh i'll give that a go :D
does anyone know how the debug win run button works? I mayâŠneed it for somethingâŠ
Maybe what zombie said and then tack on an or G.STATE == G.STATES.SPECTRAL_PACK
Well, more of the conditions for it to be forced to draw... though, for you, I don't think it is necessary to lock it down behind if the cards are drawn if you are increasing the hand size.
Instead, after activation, check for
if ((context.other_drawn and (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or (G.STATE == G.STATES.SMODS_BOOSTER_OPENED and SMODS.OPENED_BOOSTER.config.center.draw_hand)))
or (context.first_hand_drawn or context.hand_drawn)) and G.deck and #G.deck.cards > 0 then
-- maybe call G.FUNCS.draw_from_deck_to_hand() here?
end
That's probably better since it takes every pack into account
I... sure had an experience getting the first enhancement I made to work as intended, let's put it lightly.
đ
The save_run() that made it work was just not used right.
Or even where I can look actually, cause then I can try to figure it out
if G.STATE ~= G.STATES.SELECTING_HAND then
return
end
G.GAME.chips = G.GAME.blind.chips
G.STATE = G.STATES.HAND_PLAYED
G.STATE_COMPLETE = true
end_round()
new consumables, that create cards and add them to your deck
How do u make a good looking deck
also on another note, how do i initialize a global variable thats not reset across the same run and also is not reset when you quit and restart the game into the same run
start with 2 and see if you think its too broken
I feel like its missing something though
Thanks đ
for example in the game, magician does 2 but chariot only does 1
because some are more strong than others
so see what balancing you want to keep with Dream cards
if you want them to be powerful you could also do 3 (but then nerf the spawn rate) if that makes sense
depends on what kind of balance you want for it really
bump
hmm, why is mph_full nil, here?
(assigning mph_full to mph here to make it easier to change later, in case i've done this wrong)
why are you making a car
mm?
why does your joker have a mileage
close enough
I believe it to be because index 1 doesnt exist.
or well 0
thanks :D
Was gonna ask if thatâs an index too
If that doesnt work, try ipairs. I dont know the full difference between them, but one of em works and thats all that matters
Hey this is super late, but I had the same question. Found out you can check "G.hand.config.card_limit" to get the hand size!
ah, i'm sure pairs works here, as i used this code in another Joker
b u m p
Possibly G.GAME. Im not too sure though. After im through with what im doing i could take a look
thank you :)
problem with G.GAME is that it is not initialized until a player starts a run, and so i cant define it when my mod is loaded in
My project was bust.
what did you want to do?
Game:init_game_object() is called every time a new run starts, and once other time, which I think is whenever loading into a new/old 'stage'
yeah so if i do
It returns a table, which is always immedietly setting the value of G.GAME
Yea
You would need to access it if G.GAME is equal to something
if G.GAME then X end
if G.GAME then
G.GAME['destroyed_cards'] = {}
end
basically
cool makes sense actually, seems obvious now that i think about it lol
wait no but if i did that
everytime a player closes the game
and restarts
it would reset the destroyed_cards to an empty table no?
guys i have an idea
bonus blinds
they replace small or big blinds and have much larger requirements
however you cannot lose on them and if you beat the requirement you get lotsa money
whats the downside?
No
might make a stupid modpack
Because .GAME is what is saved to the disk
oh sick
look at the vanilla code for init
okok tysm
it has everything like your money, to the marble joker's current suit
...castle?
was actually just wondering about the latter today lol
anyone understand this issue when using level_up_hand?
Show the code
local h_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted)
level_up_hand(context.blueprint or self, h_text, nil, 1)
end
end```
thanks, its working
so cool
:(
code
--Function to capture destroyed cards' information
local function capture_destroyed_card(context)
if G.STAGE == G.STAGES.RUN and context.remove_playing_cards then
for k, v in ipairs(context.removed) do
local info = card_information(v, nil, G.playing_card)
table.insert(G.destroyed_cards, info)
end
end
end
this is how im defining the table
2 problems. 1, G.GAME is not defined when your mod is loaded, so that bottom code will never run, and destroyed_cards will not exist
- i said G.GAME.destroyed_cards
how do i fix this part
whenever you are going to access destroyed_cards, make sure its defined, and if it isnt, define it
gotcha okay
let me try
--Function to capture destroyed cards' information
local function capture_destroyed_card(context)
if G.STAGE == G.STAGES.RUN and context.remove_playing_cards then
for k, v in ipairs(context.removed) do
local info = card_information(v, nil, G.playing_card)
if not G.GAME.destroyed_cards then
G.GAME.destroyed_cards = {}
end
table.insert(G.destroyed_cards, info)
end
end
end
if G.GAME and not G.....
did i not do that đ
G.GAME.destroyed_cards
am i being stupid
oh
my god
i am
being stupid
i changed the if but not the
part where im inserting
Hey quick question, how feasible would it be to implement a modded joker that only shows up after certain conditions are met? Like Cavendish only showing up after Gros Michel dies by its own effect
The condition I'm thinking would be another (vanilla) joker being sold previously during the run
I don't know how to fix the logic errors
pretty easy. SMODS even has an example for how to implement Cavendish
for hooking onto a vanilla joker being sold, you can simply take_ownership of it with a calculate function (which doesn't override* for vanilla jokers)
Ok so the basic idea is that there's a global flag that tells the game when the banana jokers are allowed to be generated, right?
How would I go about making a global flag of my own in my code?
anyone know a simple way to prevent a blind from being disabled
chicot is really gonna ruin it
Maybe don't frick over your players?
Fuck over rather, I'm used to a server that has profanity blocking
yeah sure, a boss blind that is only encountered by an intentional player interaction
I kinda hope there isn't a simple way to prevent it, not for your case but because I already hate a lot of custom blinds that come with otherwise good mods and I'd hate for them to make them even more annoying, lol
There prolly is though
then remove the part of the code that adds blinds to the mod for your own gaming pleasure
Which I have resorted to doing before, I just try to avoid it because I also host my personal mod setup as a modpack
I'm not trying to bitch, just rambling
dw, my blinds won't be the blind that debuffs red seal steel kings (tm)
they just kill your cards instead
It's little stuff like this that makes me always suggest that smods needs modularity built in to disable stuff Ala carte
Lmfao, not my playstyle
ok technically it's just mod perference, modders don't have to make more ways to disable the blind
and hell, blinds are cool actually
Which is why I am putting the onus on smods not the modders
ig there should be a little thing for easy disabling and enabling blinds
guess gotta dig into the code once more
Yeah that's all, really anything that mods add around be able to be modular on the smods side like that
Imo
Would also save work for those who do want to make their mod modulat, instead of having to do it with their own config
if they dont make the function then make it yourself
can't really make other people add what you want
thats what modding is for
It's not begging, just a suggestion. If I was competent with coding I'd do the pr myself
asking for better documentation though sigh.. i like to read not analyze code..
Afaik there actually is an external mod that does this, I just need to play around with it
yeah but it's not always reliable to wait and see if people are gonna add stuff you are hoping for
idk, an easy function to display images on screen would be real nice
end up making the function yourself by using another mod's code as scrap material for it
The funny thing is that love.grapgics is probably the one thing I have done experience with
From my very few modding attempts
Speaking of love.grqphics that's where you'll find documentation for graphics functions, on lovely's official site
for me it looks like putting magic numbers on a function and hoping it'll align correctly
should probably read that since id want to be adding multiple sprites and not limited to just adding one on screen for now
I haven't used it but I assume that it's similar to other frameworks that provide graphics rendering.
pretty new to this stuff so i barely know anything
local game_updateref = Game.update
function Game.update(self, dt)
...
-- i hate chicot
if true then G.GAME.blind.disabled = nil end
game_updateref(self, dt)
end
what the fuck
it worked
funny thing is that i already had this function in my code but the condition was never met
for some odd reason god i should be testing this more
why do you hate chicot đđđđ
i saw that code from another mod actually
Hey so this is kinda embarrassing lol, I've been busy with work recently and I could've sworn I tested this the day of, but it turns out that it actually doesn't work with Buffoon Packs đ
its almost as if i took that code from my mod
that's theft
i forgot you were the guy
is it theft if im stealing from myself
yes
wowww
unless you allowed yourself
which you have to do in paper
no pdfs no docx just printed paper signed with blue ink only
oh my god the problem was that it was supposed to be G.GAME.blind.config.blind.no_debuff rather than G.GAME.blind.config.no_debuff

cooked
whateverr.. finally finishing the asriel dremurr fight
I'm seeing why it doesn't work, hold on
chat
now im gonna take even more of your code to analyze how id be able to force small and big blinds to special blinds 
im gonna need more jokers
i was gonna do this
wow
my idea was to make a teto pack but i took all the time to work on one blind
you will be the third to make a tetoris joker
actually i wasn't planning on tetoris
igaku teto đ„
would it be a crime to make joker abilities play an animation cutscene every time they are triggered
Update to pass the proper flag into booster pack cards
Replace your current one with this
đđđđđ
no but Cryptid players already hate their calculation screens
the problem is they are playing mods that make too many calculations

(they have 25 rigged boredoms)
500 triggers