#💻・modding-dev
1 messages · Page 303 of 1
I'll change to the name of the modpack
i just do this
Also, you can only pass objects with a generate ui to info_queue that way, I think.
Lm grab how I pass along glossary items for Kino, which are objectless description
still won't show if your set isn't in game code
p sure
The box is there, just not the text. That's what's surprising to me
i just said what needed to be done 😭
question is why do you need the tooltip
https://github.com/icyethics/Kino/blob/main/items/Jokers/asteroid_city.lua
I mean, no reason to create a custom set honestly. I just bundle everything in other, like vanilla does
patch somewhere in common_events.lua inside function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)
"Patch the code" is not useful advice
patch the code
I was going to replace the list of Jokers with "Food Joker" so it's not as long of a description
Just use other as the set. Plenty of mods do it, for glossary reasons. Kino, JoyousSpring, Cryptid, etc.
Defining a custom set isn't necessary when there's a set explicitly for various additional items
yea no do what they are saying
Yes, using Other works. I don't know why it wouldn't work with a different set, but who cares. Thanks!
I think JoyousSpring does add its own set, but that's for separate reasons. The other thing you can do is just create a dummy object. I do that for Spells
because localthunk
-# (i just said why it doesn't work)
Sets are predetermined, they're not a simple key that gets indexed. Aiko's explanation for it is why, basically, haha
generate_card_ui function only accounts for sets that exists in the base game
so if you want to display custom sets
you'll have to patch that function
It has to do with the set type determining whether variable passing is possible or not
Or whether an item has a name or not
because localthunk also works
i mean i got this working
if you wanna steal the patching code it is https://github.com/Aikoyori/Balatro-Aikoyoris-Shenanigans/blob/main/lovely/localization.toml
here
I was looking for the path of least resistance. I have it by using "Other". We're good. Thanks!
i dont think i do
I should update the Kino prefix I'm using in the other set away from 'k_' and to something that isn't a letter in the alphabet
you can just use kino?
🔥_modprefix_key
Yeah, I should just see if a find and replace all covers all of it, haha
My "small qol mod" now 4000 lines in total 
source?
@red flower
nah they wouldnt know anything about that
that's true
omg
i dont even think N has read his own mod yet
those robot children i hate:
those robot children that i ate:
these are placeholder art 😭
you should keep that as the art its peak
make it its own rarity
programmer art
sketch jokers
just got the most time consuming idea from this message
your welcome
i redraw game art
i wish i had the capability to use programmer art but i just obsess over making it exactly perfect before the code is even there
put it in as joker
i just got a different idea for a joker that you can just customize yourself
like
draw
and set its ability
maybe not draw but def the second
draw your own joker
blank joker
you get to draw a joker
I was playing some Megaman Battle Network a few days back, and having a customizable joker that works like how the perks in that series work would be interesting, though way too much fucking effort
My Awesome Joker
so easy
i mean, gameplay wise it's doable for sure. I've got some jokers that work similar to that system
my awesome blinds
But actually making a joker with customizable elements that you can touch in the art, that's quite the challenge
🔥
from prepicked options
i bought both collections on release and still haven't played them..
wtf is this
*plays half joker*
I have intense nostalgia for them. the combat system is a favorite of mine, though I'd always play those games with a guide because the story's fucking whack and the level design's whacker
incredibly devious with negative antes
i would like to direct you to https://balatromods.miraheze.org/wiki/Aikoyori's_Shenanigans/Boss_Blinds
Aikoyori's Shenanigans adds 14 new Boss Blinds, 3 of them being Finisher Blinds and 4 of them being Forgotten Blinds. Forgotten Boss Blinds are Boss Blinds that...
Oh it’s in negative antes
oooooh
How does scaling work in negative?
neat
it doesnt
Yeah thought so
so this is devious :P
i think at one point i tried to make it the inverse of the positive ante
No way it's working, even without localization file..
I was gonna say, that blind would basically just be “lose the game” upon encountering it
A custom tooltip?
real
Kinda
UI pros at work
I'm a UI con
i hate this shit every time i see it
Why not use the built in version?
Which one?
ever again is devious
tooltip or detailed_tooltip
I don’t remember which one actually works or what the difference is
I think it’s detailed_tooltip
If i encountered this id sue you for hate crimes
And also it relies on localization file, which I don't have and not really planning to add
make one then
can mod config store a table?
anyways this joker is out now
so it won't explode if i try to store information i intend on staying persistent in a table in mod config 
but it's likely to get updated sometime
code wizards i once again ask for your help!
I've got a cardsauce card that has this concept for an ability but i'm stumped as to how to implement it. the idea isnt too complicated but figuring out how to implement it into the scoring logic is hard since this isnt something that can be done normally. i made this diagram to showcase the idea. any thoughts on how best to do this?
you'd have to patch evaluate_play
yeah i know that much but figuring out exactly how is tricky for me since im not used to coding in there
like all the contexts and stuff
I've tried to set up that exact effect for Tenet as a joker, and you'd have to set up evaluate play to basically trigger twice, but flipping the order of the table for the second round. I remember running into a whole lot of bugs with it, but that's also because I wasn't comfortable with SMODS yet, so I'm not sure if that's an actual warning to heed, haha
I think you can hook SMODS.get_card_areas to do that actually
oh yeah, I guess you could just make a card area that has the exact cards that play has in it, but in reverse order 🤔 That'd also solve the trigger order issues
Just a dummy table would be fine
hmmmm
oh that'd work probably
i keep forgetting that card areas in that function don't need to be actual card areas
how would I check if I am not inside the shop?
tetoris
oh the joker text in japanese is neat
this one is also in japanese
i think i get what you're laying out here, but i dunno if that fits exactly for the idea here. i wanna make sure that the additional triggers here are actually retriggers and not normal evaluations
4000 lines of pure Life Quality
that way certain jokers dont interact with it again
this one also is but you can barely tell
I think you'd be able to patch in a check to see if it's on the reverse path, and then make sure those count as retriggers
and also these two
guys, should adding cards to G.game.banned_keys make stuff like the soul not pick them?
normally?
is there a way to just force restart the game
hold m
me when I'm Texas
SMODS.restart_game()
im gonna do testing in completely vanilla balatro actually
thanks :D
Is this for Playsets, rocket?
btw i do also try to make the joker text fit the actual card itself
Yeah youd have to patch the repetition function to not work in your fake area then
I think that would achieve what you want
ok to start im trying this but i must have done something wrong cause now the game just crashes when trying to load a run
there's also alt+f5 now btw
I’d specify the type too btw
what the fuck real
And youd need to format your “area” correctly and add it to t
oh yeah
theres also alt f4
Sorry not type, context
I don’t remember if everything is passed the context though
there's also just the power button on your pc if you want 🙃
It might not be necesssary
you could also flip the breaker to your computer
there's a breaker
for your house
stolen joke
actually just cut the fucking wire to your house
👍
or just
work as a nuclear scientist and make a small mistake
I'm sure they won't mind
Local variables:
_type = string: "jokers"
_context = nil
t = table: 0x3e4d62a8 {1:table: 0x3e6a30b8, 2:table: 0x3de148b8, 3:table: 0x3e111f88}
(*temporary) = C function: next
(1698) Lua field 'find_card' at Steamodded file 'src/utils.lua:346'
Local variables:
key = string: "c_csau_diamond_killer_btd"
count_debuffed = nil
results = table: 0x3e4d6280 {}
(*temporary) = C function: ipairs
actually just
become eggman
literally 1984
not sure what the deal is there
😛
the automatic content block is weird on this server ngl
there's variants of fuck you can say, and variations you can't
CHICKEN JOCKEY!
try turning off too many jokers and see if that fixes the nil
what if SMODS.find_card uses SMODS.get_card_areas
oh
yeah that makes sense
though it seems like this is hard to filter seeing as most of the times get_card_areas is called it doesnt pass context
(a stacktrace with 1000+ entries should've hinted at that)
if you swap the order of the if you might not infinite loop?
ok i'll try that
since SMODS.find_card calls SMODS.get_card_areas with _type = "jokers"*
ok yeah there we go
no crashing but now i just need to figure out how to actually get the retriggers going even if they arent technically retriggers
why is my lovely script just not loading
Like I have no idea anymore why it's just not replacing that line
I have tested manually replacing that line does work as intended
check the dump?
is
the pattern correct
the formatting correct
the path correfct
so this doesn't work, why? I don't really understand how to work with hooks
my plain is to replace the numbers with some variables that are saved to the run and just make them 1, 0.95, and 0.7 respectively so effectly it will change nothing but other jokers/vouchers can edit them easier
did you save the file
do you just have a skill issue
have you considered shutting it off and on again
You know context.starting_shop exists?
it does? fuck me sideways
no thanks
last i checked that did not exist
yes
okay but I want to check if I'm in the shop without having it inside the joker code
G.STATE == G.STATES.shop i think
SHOP uppercase iirc
oh I included too many quotes I think
this just aint working man
alright, thank you
I feel your pain, haha. Is it giving crashes, or just not doing what you want it to do?
im kinda confused by these TARGET comments like are these meant to be used as targets for lovely patches? cuz i thought you couldnt lovely patch outside of vanilla balatros files
you can i thinj
You can! They're lovely patch targets, yeah
how the hell do you do that
It's a bit of an awkward formatting. I have it in Kino, but not at my pc right now, so I can't check until later
thanks
N to the rescue
i'm gonna try using that to add to the get_card_areas but something tells me its not gonna work well either
it's saying there's no match
you need to match the whole line
alright that does not work
or use regex
oh lol
capitalize shop
I did
thanks
can anyone tell why my code isnt working? id hoped for my joker to kill the joker next to it and gain half of its sell value as Xmult but it doesnt kill the joker or gain Xmult
is there a reliable way to detect when you game over and automatically restart 😭
the if is never going to be true youre comparing a string with a card
i tried G.STATES.GAME_OVER
did you G.STATE == G.STATES.GAME_OVER
right
You need to remove .config.center.key from the check.
having so many "at" patches worries me
evil ass code joker
crashing is completely gone but now this just does nothing
https://i.imgur.com/6tPgaAY.png
At which point is the code still Balatro code?
im going to end up remaking master duel in lua
how do i A make a blueprint joker and B apply a shader to a joker
Is this too situational or nah
let's say i want to add an SMODS.Achievement. how often is check_for_unlock called?
do i have to add more calls 
maybe just has an edition?
then like an extra +1 xmult if negative
very often
its the same thing used for unlocking decks and jokers and such
42 times.
the only way to get editions from jokers is wheel of fortune, that one spectral card and getting lucky in shop right
someone got hacked xD
k
they're even learning how to hyperlink too
slowest takedown ive seen yet
@glad osprey what about I make it X2 Mult and any edition
do you know off the top of your head if there's a check_for_unlock call either at the end of or directly following add_joker() (in functions/common_events.lua)
believe there is
maybe
...wait why am i patching this
i should just hook it
yea
@wintry solar i've got to this point, no more crashing but it just doesnt work for some reason. https://i.imgur.com/igb7aSJ.png
There is not.
B: using the draw function.
SMODS.blueprint_effect
wait, add_joker() doesn't do what i think it does. what handles creating new jokers in the shop?
create_card_for_shop
docs link pls
undocumented smods functionality
smods needs proper docs 😭
i only know about it because ive seen eremel mention it when he added it, ive never used it
@wintry solar stop teaching children and document this
Should be type = playing cards I think
It’s here
ty 🙏
That might be scuffed I don’t remember
It was hastily written in my notes to remind me to add it properly to the new docs
tbh im confused in doing this cause idk if this is actually what im looking for
like im not sure what differences this code will make in game cause im looking for the reverse scoring that i documented in the graphic i made and
thats just not happening
just normal hands being scored normally
bump
check if the card your bp'ing is blueprint and if so auto false it
also pls share the code i am making that exact joker rn lol
im new to modding, not sure how to do that
oh wait yea old bp i should check that
idk if it's discord but this formatting is very cursed
def discord
blueprint_compat is purely cosmetic.
blueprint calls calculate(). to prevent blueprint from copying your joker, include context.blueprint_card == nil as part of your checks for things that you don't want blueprint copying
I can take a look when I’m back home later, I definitely think this is the way to go about it though
you dont need == nil
that would be SUPER helpful, thanks
how would i force a card to have a sticker
...that would invert the condition
not context.blueprint
alternatively could do not context.blueprint yeah
yeah, use not
== nil is not necessary unless you explicitly want to make it distinct from false
fair 
so my game is crashing on 331...
I think you can force it on when a card is created, or you can do it by hooking the create_card func
self doesn't have an ability
you wanna use card
can i see your whole calculate function
sorry if this is a dumb question but how do i check what suit a card is during calculation? (i'm having a hard time understanding the documentation)
alternatively
how would i check if a card doesnt have a sticker
can i see your joker's calculate function 
knew it, it should be calculate = function(self, card, context)
i sent the txt file a bit earlier
.base.suit
here
omg im always switching around my params
if you don't have a reference to the card, it's usually context.other_card
would it be card.base.suit == "hearts"?
Stone cards still have this value.
oh right stone card
and some jokers
hm
yes! You'll wanna check for smods.has_no_suit and smods.has_any_suit as well, but honestly, depending on the case, you most likely wanna do it by checking the suit against every suit in the game, and seeing if it's true, rather than grabbing the suit from the item
wrap everything in your calculate()
in if not context.blueprint then [your code here] end
that feels a bit much. can't they just do :is_suit("Hearts") after the SMODS.has_no_suit() & SMODS.has_any_suit() and use the bool they get from that? why would they need to iterate through each suit
It depends on what they need
Fully depends on the goal
if you just wanna know if it's a Hearts, you can just grab that
as is_suit does the checks as part of its function
i'm just trying to check if a card of hearts is in hand
but if you wanna, for example, compare the suits of two cards, you'd have to iterate through all possible suits (which might include modded ones)
then, you'd use :is_suit("Hearts") and you're all set! No need for extra functions either!
is this correct?
if you want infinite money yes
this'd crash because the calc function would be called by the back, and the back doesn't have a rarity
It won’t crash
that seems to have worked, tysm!
It’ll just do nothing
doesnt number + nil crash tho
But yeah, you also don't wanna use calculate, there is a specific function for payouts
you also never really wanna use self in a calculate function
Replace card with back
What’s the actual intended effect? Give money based on each jokers rarity in the cash out screen?
yes
do you want your joker to be able to copy other copies of itself, though?
because that would require a different approach
yeah, that's what i'm trying to accomplish
in which case, you could, in your joker code where you create the blueprint context for the calculate call, do something like
context.blueprint.fromRight = true
and then in the if statement at the start, make it not context.blueprint or (context.blueprint and context.blueprint.fromRight)
that should allow it to copy itself
how would i make a shader that only applies to the red part
ive done this but the red keeps showing up from it bleeding into other colours
...what you could do, and this is a little bit hacky, but
make the middle part that you want to be different transparent - and make that entire graphic the soul graphic.
then do your funky stuff including shader as the base graphic instead
it'll probably be a bit weird, but that might be the effect you're after
only issue with that is that the soul does the funny move thingy
only in the opposite direction of the normal graphic and slightly out of sync.
fixed
I'm having trouble figuring out where to put the first one
after
context.blueprint_card = context.blueprint_card or card```
uhm
results in a crash
why are you decreasing context.blueprint
no, my bad, i gave them bad code
ok, instead of context.blueprint.fromRight just do context.fromRight
and then after
context.blueprint = nil
context.blueprint_card = nil
do context.fromRight = nil
you don't have to make it that complicated
as long as this question gets answered, at least
the premise of the question is flawed
they wanna make a version of blueprint that does to the left without crashing on a normal blueprint, but is able to copy instances of itself
alright, now it can copy itself, but crashes with normal blueprint again
context.blueprint is an internal counter that's supposed to stop infinite loops
why are you decreasing it
they're not decreasing context.blueprint. i told them to do something that attempts to interact with it as thought it were a table
wait
they are
oh, so they are
rookie mistake, my bad

what is the context for the rarity of your jokers
instead of just changing [i + 1] to [i - 1], i changed EVERY + into a -
does anyone know the config.center... for sell value?
card.sell_cost
same goes for the if statement btw if context.blueprint > #G.jokers.cards - 1 then, that should also be a +
What are you trying to do?
make a joker like dagger but for Xmult
and finally, you might be interested in SMODS.blueprint_effect
wdym
card.sell_cost is what dagger uses.
it's an SMODS function you can use for blueprint-like jokers like the one you're making
so i just referenced old blueprint in cryptid's code
i'm very new to coding as a whole, only started learning like a week ago
so i'm trying to have this card give x2 mult if your played hand has a card of hearts. for some reason it's not working and i don't get why
the calculate function is checked for each call to that function. This means your local gets reset every time it runs. There's never a moment where hasHearts will be set to true, and the context will be joker_main
oohh my bad. this is my first time modding this game. so i'm trying to figure this out
the way you'd wanna do this is iterate through context.scoring_hand in context.joker_main, and call is_suit("Hearts") on each of them, and just return if it's true. You're not actually doing something each individual card, so there's no reason to be in that context. It's more for when a joker makes specific cards do something, like make 3s give +10 chips, or something
no worries, I think the way variables are set and empied is something that starts to feel more natural once you've made mistakes like these a couple of times. Just reading about it can feel a bit unintuitive, if you're new to programming!
so something like
if context.scoring_hand and is_suit("hearts") then
return { stuff }
end
end
```?
context.scoring_hand is an array that contains each card that scores! You'll still need to check each card in there. It's also always passed along with context.joker_main, so you don't need to check if it exists!
I'd write it like this:
if context.joker_main then
for _index, _playing_card in ipairs(context.scoring_hand) do
if _playing_card:is_suit("Hearts") then
return {
xmult = card.ability.extra.xmult
}
end
end
end
I don't know if the function sets it to lower, but I think is_suit is capital dependent, so you'd use Hearts instead of hearts
alright that makes sense. i'll try it
anyone who's good at graphics knows how to make this kind of outer glow with particles or shaders or something
or do i have to learn myself
I could make that shader for you in unity, N, but I've still not been able to figure out Balatro's shader framework :/
sad
thank you so much for the help
I should start setting up the ui nodes for the codex jokers, so I can actually start making those jokers. I keep just going for the easy way out, and making new simple jokers instead of the ones that need my complicated fucking mechanics
I'm just trying to go through the joker pool and set the Rare and Uncommons to a modded rarity that's the same as the normal one but more common
Your icon is epic :3
icon?
Yeah your little discord thingy, I like the shape design of the character

Mhm!
is it cus take ownership needs the joker's name as a string and it's giving a table
how could I take a table's name as a string
wait, no I'm just dumb
I don't think so
aww man
context.final_scoring_step?
It might check for that but it doesn't seem to be working how I intend it tho. I'll have to come back to this another time, but thanks for the help. New context. unlocked
might be more fruitful to take ownership of the rarity instead
Take ownership works on most things.
well rarity is very weirdly implimented in the game
like modded rarites are actual like tables and shit but the vanilla rarities are just a value and any weighting and stuff is done by the functions
you can lovely patch those functions
especially because the rarities will still get used even with no jokers in them (j_joker everywhere)
How would I make a voucher work like Tarot Merchant/Tycoon where it increases the spawn rate of certain consumables, specifically a modded one? I found this in the source, but does SMODS.Consumable or SMODS.ConsumableType add a var like G.GAME.tarot_rate?
if center_table.name == 'Tarot Merchant' or center_table.name == 'Tarot Tycoon' then
G.E_MANAGER:add_event(Event({func = function()
G.GAME.tarot_rate = 4*center_table.extra
return true end }))
end
huh
the rarity is only really used for the spawning card calculation
but a lot of mods need that to function
and smod already edits it to impliment custom rarities
😭
am I stupid?
i think you can change the weight or smth idk
I can directly change the weight via a lovely patch but I want it to be triggered by a voucher
and I can do that also with a lovely patch and a if statement but that feels yucky
more hard coding in
😭
😭😭😭😭😭
how would i go about coding a joker that's like credit card, but with an infinite debt limit?
if possible of course
probably just set the bankrupt to -math.huge or something
you would just add this to your SMODS.Joker:
add_to_deck = function(self, card, from_debuff)
G.GAME.bankrupt_at = -math.huge
end,
If -math.huge doesn't work, just set it to a really big negative number.
thank you!
is that dlink
dragunity dragonmaid 🙂
hi chat!!! Is 30,000 on 8 ante ok for this deck?
Change card = self to card = card
What is the joker meant to do?
It should be card.ability.extra.toggle instead of toggle
im stupid
been a while i ve coded so i forgot how to do the most basic stuff
still nothin
Formula Deck(?)
Formulaic Deck
Hmm
It's based on the formula R12=R1*R2/(R1+R2), so it's probably more logical to call it that
i mean the name physics deck don't make sense to me
how do i add Tetris to Balatro
look it up
I'm not copying code
you should prob rewrite ur mod then
all code ever has already been written, thusly everything is a copy
yeah
what
i meant what I said
I mean it'd probably not be totally hard
i want it to be decent accurate
hardest part i can think of would be getting the game to render it without it fucking shitting itself
you could always just use base love2d drawing functions so that you don't have to use ui nodes
and that's just cuz I've never messed with rendering before
you would still most likely have to patch into the base draw code in order to allow for drawing custom stuff
maybe
because it probably is
idk how the engine works
How do I get the number of times a modded consumable has been bought at the shop in a profile?
G.PROFILES[G.SETTINGS.profile].consumeable_usage['c_modprefix_key'].count
Is key the SMODS.Consumable key or the SMODS.ConsumableType key? Is there a way to use the latter like how Tarot Tycoon keeps track of number of tarot cards bought?
It uses the consumable key.
I don't think tarot tycoon does that.
It only increases the tarot rate.
Sorry, I meant the unlock condition for it. It keeps track of number of tarot cards purchased in the shop through c_tarots_bought.
It checks in G.FUNCS.buy_from_shop
You could try hooking that.
wonder how many people will recognize this fella
so i'm having trouble with another thing. i'm trying to make to where if you play a three of a kind every card scored gets a retrigger
Show your code.
this is my current code
Do you want it to be if it contains 3 of a kind or if it is a 3 of a kind?
if it is a three of a kind
context.repetition
not context.individual
idk if rep has a reference to what hand is being played tho
Replace your current code with this: ```lua
if context.scoring_name == 'Three of a Kind' and context.repetition then
return {
repetitions = 1,
card = card,
}
end
well how about that
how tf do config pages work
is money earned calculated on joker after a hand is played?
like if you earn 20 from lucky and you have bootstrap, does it take the 20 into account into the same hand's scoring? or only then?
Bootstraps does change if a lucky card gives 20 dollars.
okkk its because i had the wrong game.dollar
bootstraps uses (G.GAME.dollars + (G.GAME.dollar_buffer or 0))
ok thank you!!
where is the code that prevents multiple of the same tarot from appearing without showman? I want to make two specific tarots not show up when the other is present without showman
You're putting mult instead of emult_mod
How do you make your own tooltips for text styling?
What do you mean?
For deck descriptions, like how Magic Deck has the tooltip for Crystal Ball voucher.
is there an actually good guide to ui? (not https://github.com/Steamodded/smods/wiki/UI-Guide because it is not helpful at all)
Put info_queue[#info_queue+1] = G.P_CENTERS.objectkey in loc_vars
Speaking of UI. How I can make this description looks better? Unfirtunately adding formatting like for xmult doesn't support spaces
Does this work with modded objects?
Yes you would just put modprefix_ in between the letter prefix and the key.
you can use XMult style background formatting via B:
Oh well..
I mean, if you're using smods then that means you can use this
this?
its still giving an error
The colour would be G.C.DARK_EDITION
What error?
need better specifics here
like does the game crash after this
or is it just something saying 'ERROR'?
no game crash
idk how to explain better when scoring hand calcs it literally goes "+100 in red, then ERROR in yellow)
its impossible to sc to show i dont have that quick of reaction
though i am wondering here why are you returning an invalid return table
the format should be
return {
message = "fuck",
mult = 5,
}
for example
got a pic
shit ur right that was an accident
was trying to trial and error
error usually means that there was a localization error
if it cannot find localization info for a specific key then it simply returns ERROR
im not sure why it pops up here since message uses a string directly here and not a result from localize
could be related to the odd invalid return table probably???
idk
yea idk thats why its stumping me
For adding a card from a Modded set using SMODS.create_card, would the set value be modPrefix_cardTypeKey?
It should.
i am localizing here
so i have the modded vanilla files, what's the process to publish it as a mod?
bit of a reach but try removing type = "variable"
sometimes thats how u get erros to work XD
could just be that a_powmult is not a valid localization string
in fact pow mults don't exist outside of talisman anyway
Is this in your localization?
with it removed the ERROR goes away but no square still only +100 mult
i havent made any localization
set up for mod rn i might need localization i think thats what the issue is
I'm making a tarot card, and was wondering if it's possible to when used it puts the cards in your hand back in your deck, shuffles, and deals the same amount the player had
making a localization lua file i think that should fix thats what ur sending here right?
is this correct?
Why does your deck have a rarity?
just put that in for testing
i dont know why
but thats besides the point
is it correct
@daring fern do i need a SMODS.localization? crashed game but idk if this is how u define
You dont and use the localization template here: https://github.com/Steamodded/smods/wiki/Localization
how can i get the active profile name? 
G.PROFILES[G.SETTINGS.profile].name
i got a randomized description working but it has a newline that says nil? how can i fix this?
does anyone know how to get the modify_rank to work?
i think you can use SMODS.set_base or something
Did you ever manage to get this to work? I've tested this without any other mods and get the issue.
nah, i was too lazy to see what mod was causing it
is it possible to easily create factorial mult?
why isn't it getting marked as a collection_card?
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''
G.your_collection[j]:emplace(card)
'''
position = "after"
payload = "card.collection_card = true"
match_indent = true
#
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''
if self.sticker or ((self.sticker_run and self.sticker_run~='NONE') and G.SETTINGS.run_stake_stickers) then loc_vars = loc_vars or {}; loc_vars.sticker=(self.sticker or self.sticker_run) end
'''
position = "after"
payload = """
print("called")
if self.collection_card == true then
main_end = VS.collection_ui()
end
"""
match_indent = true
like setting mult to the factorial of itself?
for SMODS.Achievement, when unlock_condition(self, args) is called, what exactly is args? 
is it the same args passed into check_for_unlock()?
something like multiplying mult by n!
currently getting this error as well
you will need talisman for this to work
util function
function UTIL_TABLE.factorial(n)
local res = to_big(1)
for i = 2, n do
res = res * i
end
return res
end
calculate function
function calculate(self,card,context)
if context.end_of_round then
card.ability.extra.n = card.ability.extra.n + 1
end
if context.joker_main then
return {mult_mod = mult*UTIL_TABLE.factorial(card.ability.extra.n), message = "X"..tostring(card.ability.extra.n).."!", colour = G.C.BLACK}
end
end
rename my placeholder variables too
you'll need to call SMODS.set_base
i don't remember the actual name or the argument
still getting the error
fixed
alright sorry to bother you
sorry here
where in the code do they create the jokers in the collection?
how can i make a joker unlock dependant on an achievement being unlocked?
do i just give it the same unlock condition or
Thunk gives some jokers the same condition as achievements yeah
why my smods.UndiscoveredSprite doesn't draw in 34*34 size
i remember it worked well before
feel like im super close on this still isnt working tho the +100 mult works but ERROR given on calculation for squaring
what would i need to do if i want to set the joker's Xmult to the factorial of its current Xmult at the end of each round
if that isn't too hard
function calculate(self,card,context)
if context.end_of_round then
card.ability.extra.n = UTIL_TABLE.factorial(card.ability.extra.n)
end
if context.joker_main then
return {Xmult_mod = card.ability.extra.n, message = "X"..tostring(card.ability.extra.n)}
end
end
config = {extra = {}}
if context.starting_shop == true then
--below gets a random joker that isnt eternal
local eligible = {}
for k, v in pairs(G.jokers.cards) do
if not v.ability.eternal then
eligible[#eligible+1] = v
end
end
--below destroys selected joker
local randomjoker = pseudorandom_element(eligible, pseudoseed('seed'))
if randomjoker then
randomjoker:start_dissolve()
end
--below gets a random joker that has no edition
for k, v in pairs(G.jokers.cards) do
if not v.edition then
eligible[#eligible+1] = v
end
end
--below adds eternal and negative to selected joker
local randomjoker = pseudorandom_element(eligible, pseudoseed('negative'))
if randomjoker then
randomjoker:set_edition({negative = true})
randomjoker:set_eternal(true)
end
end```
how do I make this not select the joker thats being destroyed
this is probably something really dumb but im new to lua and cant for the life of me figure out why this isnt working
Does anyone know how stay_flipped works? I saw that smods lets you use it in other contexts but I couldn’t quite figure it out
@rose dragon sorry for ping, i know this is probably egregiously incorrect, but i just cant wrap my head around this
areas
that was intended for a search bar but you've inspired me
areas
tryna figure out how to move a card to the middle of the screen. very new to this
syntax will be the death of me
Should have it say "Lamp Oil" when you get the lamp oil voucher
how do i determine whether or not the current run is seeded?
and if the SMODS unlocks override is active
Then "Rope, Bombs" for the upgraded voucher
The sounds are probably gonna get stripped out actually
i cant tell what its referring to
SMODS.Joker(
{
key = "factorialtest",
loc_txt = {
name = "Factorial Test",
text = {
"placeholder"
}
},
pos = {x = 0, y = 0},
cost = 10,
rarity = 3,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
atlas = "j_placeholder",
config = {
extra = {
n = 3
}
},
calculate = function(self, card, context)
if context.end_of_round then
card.ability.extra.n = UTIL_TABLE.factorial(card.ability.extra.n)
end
if context.joker_main then
return {Xmult_mod = card.ability.extra.n, message = "X" .. tostring(card.ability.extra.n)}
end
end
}
)
You can call SMODS.Joker without ()
ty for the help
also make sure you have util_table
show where you define it
do you have hte UTIL_TABLE.factorial function and did you set UTIL_TABLE to {} prior to defining it?
for i = 2, tonumber(n) do
should this be in the function?
replace for i = 2, n do with it
also, replace res = res * i with res = res * to_big(i)
still getting the crash
full code
bump
my card is like. not doing what it's supossed to do
also it doesn't act like a consumable should, it's always usable when it should only be usable when a card is selected
How do you reset sprites while bypassing discovery? Using copy_card seems to copy the card with the collection UI rather than the regular one if it was copied from the shop
has anyone experimented with adding extra textures to a shader?
I have. I use some passed in textures for a few shaders
what did you do
Clarify the question? I used passing in a texture to create a water shader, with the overlayed texture wavering
how did you pass in the texture
You declare an extern/uniform like
extern Image my_texture;
And then you pass it to the shader whenever you go to draw it using
G.SHADERS[shader_key]:send('my_texture', G.ASSET_ATLAS[texture_key])
You can also do the latter by assigning the key and texture to an array and then passing it into the draw_shader() function's third argument
i am already using draw_shader() so how do i do that
is it crashing because… cryptid?
what if i try ortalab
because the crashlog mentions crypid
Declare an array, or using self.ARGS.send_to_shader (which is already declared during the current draw steps), add a table like this as one of its entries
{ key = 'my_texture', value = G.ASSET_ATLAS[texture_key] }
final thing does that give the entire image or am i able to get a specific sprite from it
Actually determining what section of the sprite is used is up to the logic in the shader itself. It passes in the entire image, and the shader does what it needs with him
okay, cryptid is the issue
and um
it lets me select every card and give them a modded enhancement
it's also kinda scuffed rn
bump
why does it crash with cryptid and not ortalab
cryptid moment
i'm gonna try it with unstable installed
- G.GAME.seeded
- SMODS.config.achievements
i recommend looking up localization keys to find this stuff btw

help
it works with unstable too
probably smth cryptid patched messes with your mod
for now the mod is incompatable with cryptid
that's some stuff i want to fix
i want to fix the card selection limit issue and the scuffed animation
i want it to be like an enhancment giving tarot card
like this
how do i make a joker give birth to a child sprite
so how would i go about doing that
😭😭😭😭😭
do you have an answer
no but I'm adding Battleworm Insomniac to my mod
battleworm
battleworm
thank god
battle
with
worms
what's that game called again
game where you battle with worms
battleworn insomniac
worms iirc
Question: Why did the cards turn radioactive?
hello, ive come with a question my googling has failed to answer (so has searching the server). how on earth do i replace the shop sign asset with a smod or love mod? :>
and you didn't tell me????
how do i make it so my card does the "flipping into a new enhancment" animation to the cards it effects
i made this button
but the problem is since its stored in the same group as buy and use if i focus on a card that cant be used it doesnt show the new button
any other method of working around this is resulting in failure rn does anyone know how to help with this
im makin a joker that creates a card with a random enhancement, im wondering do i have to make a list of the enhancements that exist? or can i just use a variable to get all the possible enhancements
add a new child instead of grouping it with buy and use?
tried that but it resulted in it not being rendered behind the card and also rendered all the time even when a card is not focused
This is what incantation does ```lua
for k, v in pairs(G.P_CENTER_POOLS["Enhanced"]) do
if v.key ~= 'm_stone' then
cen_pool[#cen_pool+1] = v
end
end
how are you doing it
i hook card:highlight to do something similar to that
thank you!
Is there a way to only load a lovely file if a config option is set?
afaik no because smods can't access that part but you can make the patch itself conditional
like adding a condition to the patch code i mean
anyone know where the code is that pulls a card to the center of the screen when purchased
i wanna make this now actually
😭😭😭😭
i gave up on that
remind me how i get a joker's name from center 
I'll try
G.localization.descriptions.Joker[jokerkey] could probably also work.
this was my second thought, but i was just putting it out there 
do jokers added by SMODS.Joker get localization variables 
What do you mean?
like will G.localization.descriptions.Joker[jokerkey] work if the key is a modded joker key
There are usually localizations for modded jokers.
am i cooking
Very much so
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
local face_cards_played = 0
if context.other_card: is_face() then
G.E_MANAGER:add_event(Event({
func = function()
face_cards_played = face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
return true
end}))
end
if context.individual and context.cardarea == G.play then
return {
mult = (face_cards_played * card.ability.extra.Xmult) + 1
}
end
end
it is meant to give 0.5 Xmult per face card played but it crashes as soon as i open a blind
Am I cooking with this idea chat
Could possibly cut down on the wording but its cool
You're trying to run functions on context.other_card in contexts where it doesn't exist
could you expand on which ones?
You should add on a context.individual onto your check
creating a random spectral card may be too much but whatever
as another if or instead of context other card?
in the same if statement
if context.individual and context.other_card:is_face() then
this is truly seals on everything
Honestly it sounds like a pretty basic card so I think you'll be fine
this part is basic
Ah there's more to it lol
it'll also reset itself after a while or 1 in 1000 chance to destroy itself
Just take a look at Cavendish code for the 1 in 1000 destroy chance tbh
thatll be an easy part (i got most of my chance issues done)
Could also peep Campfire code for reset
true, forget about campfire
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
local face_cards_played = 0
if context.individual and context.other_card:is_face() then
G.E_MANAGER:add_event(Event({
func = function()
face_cards_played = face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
return true
end}))
end
if context.individual and context.cardarea == G.play then
return {
x_mult = 1+ (face_cards_played * card.ability.extra.Xmult)
}
end
end
``` back again tho cus it is detecting face cards but wont give the message until after the hand is played nor actually give xmult
you could honestly do without the event wrapper for what you're trying to do here
I think that's what's messing it up cuz your face_cards_played won't actually increment until the animations actually play out
wdym?
Internally, the game handles all of the math before animations/events are shown to the player
so face_cards_played doesn't get incremented during that math phase, but the animation phase instead, therefore no score
Also your scoring context should just be context.joker_main
so chuck face cards played after the animation?
Hold on
Hi! I'm trying to make a texture pack that replaces the planet cards with versions I've made. I've done texture packs for the deck, stickers, and jokers, and all of them work. My planet cards texture pack isn't working. It loads in, but the textures don't change. This is the contents of the .lua file:
--- MOD_NAME: Adanadhel Planets
--- MOD_ID: AdanadhelPlanets
--- MOD_AUTHOR: [BerryBerryDogberry]
--- MOD_DESCRIPTION: Replaces Planet cards with Selena
----------------------------------------------
------------MOD CODE -------------------------
function SMODS.INIT.AdanadhelPlanets()
sendDebugMessage("Launching Adanadhel Planets!")
local selena_planet = SMODS.findModByID("AdanadhelPlanets")
local sprite_trt = SMODS.Sprite:new("Tarot", selena_planet.path, "Tarots.png", 71, 95, "asset_atli")
sprite_trt:register()
end
----------------------------------------------
------------MOD CODE END----------------------
Can anyone help me figure out what's wrong?
ok so that's the 0.9.8 mod format
It should look something like this. Also, face_cards_played is being re-instantiated every calculate call. Store this within the card's extra table instead of locally
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
local face_cards_played = 0
if context.individual and context.other_card:is_face() then
face_cards_played = face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (face_cards_played * card.ability.extra.Xmult)
}
end
end
you should probably just use https://discord.com/channels/1116389027176787968/1300851004186820690 for this?
how do I access UI elements from this uibox definition in the game src?
all my other packs are working fine with this format and without Malverk, though, I just don't understand why this one isn't.
hi, is there a way to make vscode's autocomplete thing to recognise vars and stuff
rn when i hover over them it just says unknown and any
This is allegedly increasing x mult but it isnt giving xmult
Put SMODS in your workspace.
Did you see my suggestion about how to handle face_cards_played?
(it isnt updating xmult on the card but idk if i have the message done yet
in each calc cell?
I guess not. face_cards_played is being re-instantiated every calculate call. Store this within the card's extra table instead of locally
oh thanks
do you have an updated format? I've tried searching online and the one I'm using is the only one I could find
config = {extra = {Xmult = 0.5, face_cards_played = 0}},
rarity = 3,
--sprite location
atlas = 'Jokers',
pos = {x = 1, y = 0},
cost = 10,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult } }
end,
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() then
face_cards_played = face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (face_cards_played * card.ability.extra.Xmult)
}
end
end
}```
like this?
or in vars?
almost. gotta add card.ability.extra to all of your face_card_played usages in calculate
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult, card.ability.extra.face_cards_played} }
end,
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() then
card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
}
end
end
```??
yep. No need to return it in the vars table
The code is in python or lua?
lua
lua
lua
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult} }
end,
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() then
card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
}
end
end
}
config = {extra = {Xmult = 0.5, face_cards_played = 0}}, this one?
wait-, i forgot to chance it no?
*change
SMODS.Joker{
--identifier
key = 'cassetteTape',
--what it says
loc_txt = {
name = 'Cassette Tape',
text = {
"{X:mult,C:white} X#1# {} Mult",
"per face card played"
}
},
config = {extra = {Xmult = 0.5, face_cards_played = 0}},
rarity = 3,
--sprite location
atlas = 'Jokers',
pos = {x = 1, y = 0},
cost = 10,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult} }
end,
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() then
card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
}
end
end
}
``` whole thing in case
which line is line 327 in your code? is it the card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1?
} after that
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
} <--
the arrow is pointing to it
Huh that's a weird one
I wonder, did you remember to save? If not, did you start a new run to test the new code?
hey guys, quick question.
I don't want to be too annoying about this, but could someone help me out? or point me in the direction of a good tutorial?
blue archive :3
:3
What is the code to do 26 jokers?
new run lol. forgot that is a thing. Mult doesnt increase in description still sadly but it works
blue archive ,,,,
I know why that is. Your Xmult variable is never changing, just the face_cards_played
guys?
Also... these might fit
gotcha, to attach to my previous question, how would i do that?
What do you mean?
in the vars table of your loc_vars, return 1 + (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
I have to do 26 jokers
Yes it's the same algorithm as your scoring function lol
this makes no sense
does that fix both issues?
I have to make 26 kokers
No, but it might help diagnose it
what i would recommend for you is to learn basic lua
So just play a round and see what happens?
i don't get what you mean by "make 26 jokers" because i don't have any other advice than make 26 jokers
Yes actually lol
this feels like a don't ask to ask situation
yeah there's not gonna be a "make 26 jokers" button, you gotta code those yourself
I think if you want to mod 26 custom jokers into the game, the first step would be to learn how to mod 1 joker into the game, then do that 25 more times
what video?
STEAMODDED 1.0.0
A tutorial on how to make a modded Joker.
https://github.com/art-muncher/Example-Mod -- EXAMPLE MOD
https://github.com/Steamopollys/Steamodded -- STEAMODDED
https://github.com/WilsontheWolf/DebugPlus -- DEBUGPLUS
-----------------------------------------------------...
that video
I have never been more confused in this chat
Yes, you would do that for every one of the 26 jokers.
description is working but i only played two faces
average #💻・modding-dev experience, u either get blown away by how insane these people are or the same but complete opposite meaning
Nah this is a special case. It has never been to this degree lmfao
if you paste the template 26 times you will have 26 jokers, but in order for them to function at all you'll still need to code that behavior yourself
imma make the decription make more sense later
-# true...
I just came in here to ask for help with getting my planets texture pack working and now I'm just more confused than I was before
u should use Malverk for that one
ykw try tacking on a and not context.repetition in your if statement. I wonder if it's hitting on those for some reason
what should the key be?
can I not do it without using Malverk? I'm just confused because all three of the other texture packs I've made using the exact same format are working completely perfectly, it's literally JUST the tarot/planets one that isn't working, and I can't figure out what the difference is
loc_vars = function(self, info_queue, card)
return { vars = { 1 + (card.ability.extra.face_cards_played * card.ability.extra.Xmult)} }
end,
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() and not context.repetition then
card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * card.ability.extra.Xmult)
}
end
end
``` one face
huh.
i think i see the problem
The name of your joker all lowercase without spaces usually.
key can be anything, it's just the identifier for that joker, but yes it's best practice to make it the name of your joker all lowercase without spaces
SMODS.Altas{ key = 'a', path = 'LetterJoker.png', px = 71, py = 95
like this? I should add more.
so, if I have a joker named Red Joker, the key would probably be 'redjoker' or 'red_joker'
did not see the problem
calculate = function(self, card, context)
if context.individual and context.other_card:is_face() and not context.repetition then
card.ability.extra.face_cards_played = card.ability.extra.face_cards_played + 1
card_eval_status_text(card, 'extra', nil, nil, nil, {
message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.x_mult}},
colour = G.C.RED,
card = card
})
end
if context.joker_main then
return {
x_mult = 1+ (card.ability.extra.face_cards_played * 0.5)
}
end
end
oh wait
No thats the atlas the atlas key should be something like Jokers
Looks kinda hard but understandable
I'm starting to code games in assembly language
Oh my god I think I know what it is now. Add on and context.cardarea == G.play
My guess is it's getting the cards held in hand too
what's an Altas
aure jumpscare
oh.
I was thinking to mod some math abilities and add insane functions like Ackerman's function lmao
working now
Huge
does this work so far?
thats about it for the atlas, yes
Is LetterJoker.png in your mod/assets/1x and mod/assets/2x?
both.
isn't it suppose to be in both?
yes
https://github.com/Steamodded/examples/blob/master/Mods/ExampleJokersMod/ModdedVanilla.lua
this is a good page to look at for defining your jokers, and has a lot of comments explaining what every line does
though it might be a bit information dense
re: this, I guess, like, can someone help me out with finding a more updated texture pack format, or something, without needing Malverk? I have all these planet cards I'm really proud of and literally only this specific texture pack is having a problem, all three of the other packs I've made are functioning without a hitch
so this is where I put the key of my joker.
yes
No, its SMODS.Joker
how do i do two sets of odds for one joker? like, in loc_vars section
I'm sorry if I'm being annoying, I swear to God I don't want to be a pain, I'm just getting frustrated because I don't know how to troubleshoot this
ok. now I have to add the text.
Why dont you want to use Malverk?
You forgot an S on SMODS
What’s the problem with Malverk?
question. I have to type gains +1 mult for played aces (starts at +3 mult) for A where do I put the line breaks?
Probably between aces and (starts
You also need to mention what the current mult is.
yeah.
I'm onto that part.
