#š»ć»modding-dev
1 messages Ā· Page 142 of 1
...do I need to add that too for the one Joker I have that retriggers other Jokers?
because when someone else enables the context for the deck and someone's code doesn't expect it (they never tested it with the deck context enabled after all, they might not even know it exists), it'll wrongly calculate there
Yes
Yes
Most contexts should be verified positively rather than negatively IMO
yes but people are stubborn
also i still think joker individual checks are clunky and weird
I think this is better because it incurs less overhead when not needed
nonono like the context.individual
cuz you still have to specify not context.repetition right
and also not context.end_of_round
Iterating for retriggers and the deck and discards
the crux of the issue is still the same, people will dev on slightly different versions of steamodded and things will break anyway when players actually put things together
I think thatās the developersā fault š¤
The problem itās trying to solve is overhead
TheAutumnCircus is your mod ID right?
So if a mod doesnāt use the feature it does have less overhead
I added that to my main with my id and it crashes, nice
i guess? but maybe there should be some more obvious "hey if you're developing you might want to know about this thing"
Thatās true about a lot of things Steamodded
sorry that's a global table i put my mod object into
SMODS.current_mod
but this is literally "if you're developing you should turn on all the options right now"
Maybe itās a function
How so?
so that you know if your code fundamentally breaks if those options are enabled?
@frosty dock so I wanna see if I can make a custom card if I do a SMODS.Suit does that mean I can use this to make a custom deck card?
and so that you can actually use the features that exist, like how nobody's joker retriggers work anymore all of a sudden
I mean, I think either the dev can fix it afterwards or make it incompatible
The problem of discovery already existed and will continue to exist
My retrigger joker is alive again, ty
is this worthy of legendary
Itās worth of being in Cryptid probably
š
sorry ill just go back to making my voucher
Yeah true, for example how did you get to know it became an optional feature
No need to apologize
Iām just unconvinced
But that doesnāt mean either of us is right or wrong
Either by paying attention to updates or by seeing something break
Steamodded isnāt released for a reason
If people want to dev for a stable version they can go back to 0.9.8 ;P
Was it mentioned in "Discussions"? If so do you have a link
It was mentioned in this channel and IIRC also the Steamodded thread
Itās probably also in a commit
If it stopped working for you itās because you updated :<
Yes I did update, but for something like this a Pin would've been appropriate
"""""stable"""""
What pin
pinning a message of the change in the thread
Steamodded devs canāt do that
Only mods can
And mods have better things to do usually
Sad
Iām not sure at what else to say for people who complain about breaking changes in an unreleased, alpha, in-development, crowdsourced API
If a mod is ready for others to play what's the best way to advertise it?
A forum thread I suppose
The main reason for toggling them off by default is they add a lot of overhead in calculation times if they arenāt being used
So, if I have a custom deck and/or I use discard-related contexts, I should "re-enable" them back?
If you need to run calculations on cards in your deck or cards you have already discarded
That'd affect context.remove_playing_cards too?
I still would like the option to be set by context :<
No
Right now I only need one context so I might stick to my homemade solution
I have only 1 joker that retriggers Jokers and no custom deck/discard related jokers
Do I keep it on all the time or is the optimal thing to do enable it when the joker is equipped or something
...as I have a Spectral card that destroys cards in the deck and a Joker that reads from any destroyed card on top of a retriggering Joker...
return {
cardareas.deck = true,
retrigger_joker = true
}
?
huh what is cardarea.deck optional too
G.deck and G.discard...
I imagine it works on load
Due to patching
But idk
cardareas = { deck = true }
idk why the tooltips are getting nil but
you can only set it on load through the mod field, but you could technically set or unset it later on SMODS.optional_features directly
Also Iām not sure you should manipulate it
If another mod also sets it to true, then what?
setting is fine but unsetting can break other mods
What if two mods are trying to be quirky and turn it on and off?
You can do it the quirky way if you store what it was previously
you could just toggle it on when it becomes relevant, then just leave it on after that; at least it's not on before it's needed, though after remains
What if two mods do that
or just like leave it on
But they change it in ABAB
so when A changes back B expects it to be in a different state?
Oh true
At best you could have a counter
As in, Steamodded could
Of how many mods want it
But thatās basically a listener system
Which I suspect is a more efficient form of handling calculation
Oh what I meant before was adding Negative to the wheel's edition pool
...wait, what's the full thing again? Is it just SMODS.optional_features or do I need to do it from SMODS.current_mod?
idk but here's cirno because i decided to try to make a pokermon addon
(unrelated to the wheel of wheel of fortune)
Cute art!
return {
retrigger_joker = true,
}
end```
thanks its not mine
(touhoumon art is by HemoglobinA1C (fan use permitted))
Clearly you stoled forked it
I've been using togabalatro = SMODS.current_mod for a while, so, I guess it becomes
togabalatro.optional_features = function()
return {
cardareas = { deck = true },
retrigger_joker = true
}
end
oh whoops advent cirno has the wrong text
Is that a Mega Man reference
should be "Played 9s become Steel Cards and give +9 Mult per ..." without the retrigger thing from Technical
Advent
no there's a touhou fan comic series thing called Advent Cirno or something to that effect where it's basically the plot of Final Fantasy VII retold with Touhou characters
Advent? is that a Library of Ruina reference??
touhoumon has the versions of the characters from that comic as special evolutions
Icy
yes i know way too much niche trivia about this thing hi
-# get it. āI see.ā Haha.
i dont could you please explain
That seems like a reasonable to low amount of trivia
hi autumn ur amazing
(before our yapping overrides this, yes this looks correct to me)
New to this, just want to replace a few sounds and have no idea how to go about it.š
SMODS.Sound({
key = 'ambientFire1',
path = 'ambientFire1.ogg'
})
SMODS.Sound({
key = 'ambientFire2',
path = 'ambientFire2.ogg'
})
SMODS.Sound({
key = 'ambientFire3',
path = 'ambientFire3.ogg'
})
local keys = {
'ambientFire1',
'ambientFire2',
'ambientFire3',
}```
I already added the metadata.š
āIcyā is homophonic to āI seeā; Cirno has ice powers
I guess not āhomophonicā
Just close
why is icy homophobic
Might depend on pronunciation
what no stop ew
Try seeing how L Corp does it
well I found out what happens when u combine tarot and jokers cards into a pack
u can't use the tarot card lol
unless i'm missing something
key = 'PotGreed', --joker key
set = 'Tarot',
loc_txt = { -- local text
name = 'Pot Of Greed',
text = {
'Draw 2 cards from your Deck.'
},
},
atlas = 'Jokers', --atlas' key
cost = 10, --cost
unlocked = true, --where it is unlocked or not: if true,
discovered = true, --whether or not it starts discovered
pools = { TCG_Yugioh = true },
pos = {x = 0, y = 0}, --position in atlas, starts at 0, scales by the atlas' card size (px and py): {x = 1, y = 0} would mean the sprite is 71 pixels to the right
config = {
extra = {
card_limit = 3 --configurable value
}
},
use = function(self, card, area, copier)
G.FUNCS.draw_from_deck_to_hand(2)
end,
})```
Tried this, but made the game crash.
SMODS.Sound({
key = 'ambientFire1',
path = 'ambientFire1.ogg'
replace = 'ambientFire1'
})
SMODS.Sound({
key = 'ambientFire2',
path = 'ambientFire2.ogg'
replace = 'ambientFire2'
})
SMODS.Sound({
key = 'ambientFire3',
path = 'ambientFire3.ogg'
replace = 'ambientFire3'
})
local keys = {
'ambientFire1',
'ambientFire2',
'ambientFire3',
}
Idk how "key" works, or if there might be a list.
key is basically a identifier I think?
can't use it or add it to the tarot slot
Fixed the crash (forgot to add commas), but it still plays the vanilla sound effects.
Also how do I stop the custom booster pack from making copies of multi 4 joker.cards
They can't even be selected
Thats a fallback Joker, it means your pack doesnt have a pool of jokers afaik
make more jokers
Well trying to make a combination pack
That has custom jokers and tarots
Not sure if it's even possible
You need to create a custom pool IIRC
Isn't that what SMOD.Booster is?
Not that Iām aware of
So how does one go about making a custom pool
Am I able to release this Joker or will I get banned

Oh shit man good luck
That one took me forever and I still don't know what I'm doing with it
is there a way to make it so a joker starts debuffed even in the shop and only works when you get a different joker in your jokers?
I have no idea where to start
I just need one that can combine jokers and tarots
so I can have yugioh cards that can focus as effects similar to jokers and tarots that are like a quick 1 time effect
I think a table of options should work
Now sure if anything else is required
{}
balanced
oh true i should have it say 
What's like the part of the wiki that explains that
I donāt think it exists
a whole lot of the wiki isn't filled out yet, yeah
Thereās not even anything to fill if itās not natively supported
Although it could be helpful
Lol, okay, it works (replaced "crumple1" as a test), but it treats "ambientFire" 1, 2, and 3 as a special case???
bruh
SMODS.Joker {
key = 'kubebows',
rarity = 1,
cost = 4,
atlas = "kubebow",
pos = { x = 0 , y = 0},
config = { extra = { mult_gain = 7, mult = 0, sevens = 0 } },
loc_vars = function(self, info_queue, card)
return { vars = {
card.ability.extra.mult, card.ability.extra.sevens, card.ability.extra.mult_gain
} }
end,
loc_txt = {
name = 'Kubebow',
text = {
'Gains {C:mult}+#3#{} mult',
'every {C:attention}seven{} scored.',
'{S:0.7}Currently {C:mult}+#1#{} mult.'
},
},
calculate = function (self, card, context)
if context.scoring_hand and context.cardarea == G.play and context.other_card:get_id() == 7 then
card.ability.extra.sevens = card.ability.extra.sevens + 1
card.ability.extra.mult = card.ability.extra.mult_gain * card.ability.extra.sevens
end
return {
mult_mod = card.ability.extra.mult,
message = "+#1#",
colour = G.C.MULT
}
end
}
why is the game screaming at me i did nothing wrong
i had a stroke
...set_ability code around here
I'm trying to make it so that after the scoring has ended, the current hand will gain Enhancements before the next cards are drawn, but rn the Enhancements only gets assigned if I have played a hand after
Any insights?
you probably want context.after right?
if card.ability.extra.state == "ready" and context.after and context.cardarea == G.hand then
I tried this instead, but still no dice, doesn't work even if I don't include context.cardarea
i got the game to stop screaming at me (witht he funny side effect of each seven giving mult)
i made it more complicated
The Wheel of Theseus
oh yeah and this is wheel of wheel
wheel of overcomplication: 1 in 5 chance to create a wheel with way too much explanation
the what
cant you just make a wheel of wheel that has a 1 in 2 chance to make a wheel
it is 1 in 4 i just have two oops all sixes
i know
the wheel spins for thee
they're wheely cool
Car of Fortune
true,,,
nil in nil? š„“
idk can I see your loc_vars
I don't judge
yes you do ive seen it
balatro pegi 18 card and grac 19 card?
okay okay I try not to judge
its been a while ok i forget how this stuff works
either you show me or I can't help, that's all 
nah its fine i realized what it was
the
gives x100 mult when the game rating isn't above ~17 years old
is it possible to spawn a joker debuffed and then a different joker rebuffs that original joker when its owned?
i was thinking of something like in the load = function set it to debuffed
what the fuck even is "Negative DONT"
Negatives don't need extra room to spawn because they create the extra room
yeah but its kinda weird to see (Must have a room: negatives dont)
because the case of needing room is conditional on the wheel being negative or not
it reflects the actual code implementation as best as possible with english words
also it's not supposed to go to black text after negatives there lol oops
"May need room"
lol
bumping this though i'm not at my pc right now, see my messages afterwards for what i tried š
better?
Hey Guys! I'm new to modding Balatro and have a question about an effect I'm trying to implement:
I want to add a joker that will have the game act as if cards with rank 4 are rank 9. I noticed that this would be similar to the smeared effect which I saw is pretty much hard coded in the game's source code. So would I have to basically do the same here and rewrite the game's functions that return a card's rank or is there a better way? Did anyone else implement a replacement effect like this?
Iāve implemented something similar and unfortunately hardcoding seems to be the way to go
Wheel of Wheel of Wheel of Fortune (Rare): 1 in 4 chance to redeem a Wheel of Wheel of Fortune when Blind is selected
Damn, I'll try to figure that out then. Thanks!
thats wheely good
Something along the lines of "quantum ranks" has been discussed several times before but we don't have a full implementation of it. Just overriding a card's effective rank has been done before (see Maximized from Cryptid) but the card won't count as its original rank anymore
it's possible to make multiple ranks on the same card work similarly to suits, but it requires modifying quite a bit of vanilla code and probably break a lot of mods as well. Even then we haven't come up with an efficient way to find straights in quantum-ranked hands
Ok, so I guess there is no easy way to go about this. Thank you for the reply.
Just to be sure, is this how its set up?
yeah looks about right. Though you're using a different atlas key in your joker than what you defined above?
yea, i just am using my code from yesterday, i havent gotten to that yet
thanks for reminding me tho
i have no clue what to do with these
how do i make joker change sell values like the egg joker?
@frosty dock i need some advice on this and the above video message
trying to get the message, sound, and chips/mult counters update at the same time and as of now i can only get two of those at once, despite the code seemingly being set up right according to digitaldetective
what if you move updating the hand text (and changing the mult/chip values I guess?) into the func (or the event, not sure)?
wait this is just a single sound now?
yeah
you can put single sounds that go with a message into the return table as sound
might add a little more but for now just this
mmm
before i go and do that im wondering if thered be a way to -
nah probably not the case
(combine sounds in the code without making a new sound file alltogether)
so sound = 'multhit2'?
^?
I was looking through the source of other mods to reverse engineer how they work, what is this G object I keep seeing?
was gonna post this in me mod post
but this works tbh to show that its working
something something 'Global' i think
or Game
Game
im guessing
is there anywhere I can see the properties of it?
not to be confused with _G, which is the global scope
most are defined in game.lua as Game.whatever
oh like in the balatro source itself?
anything defined on Game or on self within a function on Game will be present on G
yeah. You can extract the executable with 7-zip
there are also modified versions of those files present in Mods/lovely/dump for whichever files have been patched into
which should be most of them if you use steamodded
oh ok I'll look through that, thanks!
How can i make a jokers ablity activate once a hand is played but isnt related to the scoring
context:before iirc? checking
im not good at making jokers, so im trying to make more so i get better, lol
okay ya it's:
context.cardarea = G.jokers and context.before
thank you
np!
there is a state for SELECTING_HAND but there doesn't seem to be a similar one for jokers?
unless I'm misunderstanding what these states mean
just to be sure, im running
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.before then
return {
-- TO DO, Add chance to subtract and add from joker worth.
}
end
end
}
mhm
okay, sweet, time to find out how to add chances
still need help here
i mean just look at what egg does...?
if self.ability.name == 'Egg' then
self.ability.extra_value = self.ability.extra_value + self.ability.extra
self:set_cost()
return {
message = localize('k_val_up'),
colour = G.C.MONEY
}
i did
i couldnt get anything to work
card.ability.extra_value = card.ability.extra_value + whatever
card:set_cost()
is there any way to print to console?
im probably not, but am i doing this right?
if pseudorandom() < G.GAME.probabilities.normal/2 then
return {
-- TO DO, ADD VALUE
}
else
return {
-- TO DO, SUBTRACT VALUE
}
i want a 50/50 chance regardless if the player has the dice card
you can just use print but there's steamodded functions with specific log levels as well, see https://github.com/Steamodded/smods/wiki/Logging
I think it could be simplified a bit
thanks!
no
Crash log
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.before then
if pseudorandom() < 1/2 then
return {
sendInfoMessage("CashAdded", "Crypto")
}
else
return {
sendInfoMessage("CashSubtracted", "Crypto")
}
end
end
end
}
oh, will it be diffrent every game?
it will be the same if you use the same seed
no you just give it a string, the game makes it random for each seed by itself
ohhh, thank you
pseudorandom calls with the same seed identifier get the same queue of values for the same seed, so you should use different identifiers for unrelated randomness
what is the context for jokers that you own?
what
basically trying to iterate through my owned jokers to see if i have a certain joker in there
im praying this works lol
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.before then
if pseudorandom("crypto") < 1/2 then
card.ability.extra_value = card.ability.extra_value + 1
return {
card:set_cost()
}
else
card.ability.extra_value = card.ability.extra_value - 1
return {
card:set_cost()
}
end
end
end
}
why is the set_cost in your return table
also shouldn't you have a message?
im still learning
and how is that a context? you can check if you own a certain joker like if next(SMODS.find_card('j_modprefix_key')) then
sorry wrong wording from me
i mean, it works, somehow
thanks
i should probably add that message
Okay, I think this is better
if pseudorandom("crypto") < 1/2 then
card.ability.extra_value = card.ability.extra_value + 1
return {
message = "+1",
colour = G.C.MONEY
}
else
card.ability.extra_value = card.ability.extra_value - 1
return {
message = "-1",
colour = G.C.MONEY
}
end
end
card:set_cost()
end
}
Am I allowed to post this mod in the mod section for others to download or is it against the rules?
@mellow sable @frosty dock I'll include version handling for both of y'all's mods (Talisman & Steamodded), because apparently they are very necessary for a lot of mods
no way, it can make me pay to sell, thats cool
have a Conspiracy Theorist! (should i make the head a bit taller?)
is he a flat earther
Gains X1 Mult if 9/11 was an inside job (Currently 2X Mult)
It started at 1X
šØ
ooh parallel thinking!
how would i sort for highest ranking card in hand?
(not played hand, normal hand, if that matters)
okay this is much better :D
is it possible to then interact with that card ei debuff that card
What is the function call to sell a joker?
idea:
Creates a copy of Earth if played hand is a Full House
might be too strong, no idea
i didnt ask any questions but the questions previously asked and answered here helped me make my first modded joker work thank you all
thanks :D
might also be good for Cryptid, but I'll add Cryptid to the mod index when the developmental version gets more stable
Already added crypted to the index btw
thanks
for that one, what you need to know is:
Cryptid / Steamodded / Talisman
main / old calc / latest release
refactor / main / main
For short you can just do [#2] instead of [Currently #2#]
Like Yorick
that might be better, ty
Card:get_id()
i'm trying to make a card that discards a random card from your hand after every round, and upgrades by 0.01 * the rank of that card. however, whenever i try to perform math the multiplication on my saved variable for the card's rank (num), the game crashes saying it's a nil value and i'm unsure why. all of the discarding code was basically copied verbatim from the hook boss blind
is pos = { x = 1, y = 0 }, mesured by pixels or by px defined in Atlas
defined in atlas
basically locating which tile of the grid youve made in assets its calling for
okay, thanks
does anyone know how to get these guys to destroy different cards?
(feline is supposed to destroy the highest ranked card in hand)
preferably id also like for it to destroy after everything has visibly scored
god, what was that cards name when you sell it, it gives the double tag
double soda?
Make it work like Glass
or cola
Donāt destroy them directly
and how is that done?
okay, i couldnt remember it, thanks
Oh wait
In hand not in play
Then maybe put the loop inside an Event
That could be a bit buggy too
Hmm
what's the difference between mult and mult_mod?
I added a patch to avoid bugs when destroying cards
to be sure, this is how you check if the joker is sold?
calculate = function(self, card, context)
if context.selling_self() then
end
end
}
yes
i remember coding one that worked off of that
but yeah no ()
Actually does shatter and dissolve create events?
iunno
If not it might be easier
just if card and not card.removed
Where card is probably v
the inferior alternative to k,v
so add those to this if?
didnt work
still just erased one
a funny idea is trying to count how many felines there are
and set it to second/third etc depending on which feline it is
but that feels like a really bad way to do it
Then try the other suggestion
is this a 1/3 chance for each?
calculate = function(self, card, context)
if context.selling_self then
if pseudorandom("crypto") > 1/3 then
print("Sold 1")
elseif pseudorandom("crypto") < 2/3 then
print("Sold 3")
else
print("Sold 2")
end
end
end
}
shouldnt need the elseif, just else
or
wait nvm
misread
flip the first sign tho
Two thirds
Also missing the O!A6s scaling
Also it depends on what you mean by the chance of the second one
im wanting it to not be effected because id rather not have it always choose one tag
i think
just maybe
that was a few too many cards erased
As long as its probability isnāt listed
But also this
each one has a %33.3 chance of being chosen
should the middle one also be 1/3?
I think right now itās 1/3, 1/9, and 5/9
If you want even chances without doing math I suggest using the function that selects from a table
Just do the pseudorandom call once at the top
no as long as they fixed the sign being backwards that should be 1/3 1/3 1/3
oh wait
yeah thats an issue
Currently itās conditional
so something like this?
calculate = function(self, card, context)
if context.selling_self then
local random_value = pseudorandom("crypto") -- Generate the random value once
if random_value < 1/3 then
add_tag(Tag('tag_investment'))
elseif random_value < 2/3 then
add_tag(Tag('tag_economy'))
else
add_tag(Tag('tag_coupon'))
end
end
end
}
That works too but technically requires a bit of math
Just selecting one element from a table at first is equivalent and requires no further math
That looks like it works
i guess its time to make the next joker :3
Yeah thatāll be equal probabilities
so does anyone have any thoughts on this?
Wrong context
what am i missing then
Why arenāt you using the destroying context?
These are for the hand
Thereās a check for hand cards
Where do the destroying contexts work?
Deck? Discard?
One more reason to stick with my patch
so what context do i need to set up?
I think I did
Look the context list and see what to test for
after regular destroying_card
i know theres also a later section on it but like
couldnt this say the basics of it like the others in this list?
end of round, individual and repetition as well
Hmmm
So how Iād use it for the end of round
if context.end_of_round and context.destroying_card and context.other_card == card then?
Maybe throw in something to make it only execute once
what context do i need to destroy an in hand card per played hand?
destroying card isn't end of round though? it's after hand played
rephrase
what contexts would i need for this to trigger right?
I asked if you put it at the end of round and you said maybe
the Eye of Providence :D
no I said I think I added destroying card to deck and discard
I didn't introduce new timings for it
I wasn't responding to you
if context.destroy_card and context.cardarea == G.hand then I think
for the moment got rid of the add_event, and set up the contexts like john smods said, now its not deleting cards
needs to return { remove = true }
a random card is discarded every round (like the hook) and 0.01 * its rank is supposed to be added to the multiplier of the joker. however, it only adds 0.01 to the mult and nothing else, and i can't discern why
still not removing cards
wait
hm
might be fixed now
other than cryptid has any mod implemented double sided cards?
nope
Bunco has a double-sided tape
but playing cards
well still i can use the flipped mechanic
from what i can tell, card.ability.mult_gain isn't changing, but i'm unsure why unless selected_card.base.nominal isn't working correctly
cuz i want to implement something like this https://scryfall.com/card/lci/135/brasss-tunnel-grinder-tecutlan-the-searing-rift
{2}{R} ⢠Legendary Artifact // Legendary Land ā Cave ⢠When Brass's Tunnel-Grinder enters, discard any number of cards, then draw that many cards plus one. At the beginning of your end step, if you descended this turn, put a bore counter on Brass's Tunnel-Grinder. Then if there are three or more bore counters on it, remove those counters and tra...
wait does blueprint_compat default to false?
im not sure, i dont use that function, and blueprint works with it
is it possible to check the value of a variable while playing? i should probably actually effectively debug this lmao
have you tried seeing if there is a joker that does something similar, modded or vanilla
can an eternal joker self-destruct?
the raised fist is close to this and i essentially copied its formula, for some reason it just won't work in my case
yes
cool
what about any modded jokers?
i haven't checked, i'll search a bit tho
any self destructing jokers in vanilla are marked as incompatible with eternal
anyone know what this means/how to fix?
not cropping out useful parts of the crash screen would be a good start
cheersš
okay so voucher calculation
idk how much information about redeemed vouchers we need to store
maybe it just needs to be a cardarea
at least if i want to support any kind of mutable values, i don't think there's a way around it
animal well skins is so based
is there context for when a card is burnt/destroyed?
what kind of card
like when the knife deletes a joker, or when a bannana goes extinct
Not Jokers IIRC
I think Paperback had a non-jank solution
-# and betmma had a jank solution
wait, how do i even destroy a joker
Probably manually unless itās been added as a context
Which I donāt think it was
Can I use this function to change the sprite of my Joker during a run? Like it flips, changes sprite and flips back
Or is this the way to go for that
yeah use set_sprite_pos for that
Is that saved when you reload?
okay, im getting the Shcreenshotted to pop up but its not deleting
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.before then
if pseudorandom("crypto") < 1/4 then
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false,
func = function()
G.jokers:remove_card(self)
return true; end}))
return true
end
}))
return {
message = localize('screenshotted'),
colour = G.C.CHIPS
}
end
end
end
}
I dont know why its not leaving
never did i think, causing a joker to delete itself would cause so much trouble
Tried just now, it does not
I'll add it in set_sprites too
An easy solution might be set_ability
Or see what Bunco does for the tape
Is this too ugly?
its beautiful compared to the stuff im writing
-- This part plays the animation.
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
card.T.r = -0.2
card:juice_up(0.3, 0.4)
card.states.drag.is = true
card.children.center.pinch.x = true
-- This part destroys the card.
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.3,
blockable = false,
func = function()
G.jokers:remove_card(card)
card:remove()
card = nil
return true;
end
}))
return true
end
}))
-- Sets the pool flag to true, meaning Gros Michel 2 doesn't spawn, and Cavendish 2 does.
G.GAME.pool_flags.gros_michel_extinct2 = true
return {
message = 'Extinct!'
}
else
return {
message = 'Safe!'
}
end
end
end
}```
here. this is from the example mods of steammodded
omg, i had to switch to card
my game crashed from a memory alocation because it's out of memory. How do I reset that? I've done it before but forgot
how the fuck
I think that's emplace missing
i think its because i set card to nil outside the part it destroys it
What would constitute as using someone elses code?
name = 'Taped', custom_atlas = 'bunco_jokers_taped', position = 1,
rarity = 'Rare', cost = 6,
blueprint = false, eternal = true,
unlocked = true,
calculate = function(self, card, context)
if context.before
and context.full_hand
and not context.other_card
and G.GAME.current_round.hands_played == 0
and G.GAME.blind.boss
and not context.blueprint then
event({func = function()
local cards = {}
for i = 1, #context.full_hand do
if not context.full_hand[i].ability.group then
table.insert(cards, context.full_hand[i])
end
end
if #cards > 1 then
link_cards(cards, self.key)
big_juice(card)
for i = 1, #cards do
big_juice(cards[i])
end
end
return true end})
end
end,
set_ability = function(self, card, initial, delay_sprites)
if self.discovered or card.bypass_discovery_center then
card.T.w = G.CARD_W * 1.788732394366197
card.T.h = G.CARD_H * 1.189473684210526
end
end,
set_sprites = function(self, card, front)
if self.discovered or card.bypass_discovery_center then
card.children.center.scale = {x = 127, y = 113}
card.children.center:reset()
end
end,
load = function(self, card, card_table, other_card)
return self.set_ability(self, card)
end
})```
I've checked it, but I don't understand how it changes the sprite
or if its changing it at all
Is there a way to make custom challenges yet? If so, where can one find tutorials on it?
i dont know anything about coding, but i would love if there was a mod to add a different main song when getting to endless mode
found the messages when this happened last time. I uninstalled and reinstalled the full game
im so confused, its not taking in the blueprint photo, but instead is using Jimbo
SMODS.Joker {
-- How the code refers to the joker.
key = 'Scammer',
-- loc_text is the actual name and description that show in-game for the card.
loc_txt = {
name = 'Blueprint ',
text={
"Copies ability of",
"{C:attention}Joker{} to the right",
},
config = { extra = { worth = 2 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.extra_value } }
end,
rarity = 3,
atlas = 'JokerSheet',
pos = { x = 4, y = 0 },
-- Cost of card in shop.
cost = 10,
calculate = function(self, card, context)
return {
message = "Scammed!"
}
end
}
}
its so fucking good it just changes its face too
I suspect it's position
Must've been patched in
š¤
I remembered Cardsauce has a similar joker (Im so happy/Im so sad)
But its like
It uses update (first is cardsauce, second is mine updated)
How wrong is this from 0 to 10? lol
I tried it and it works but its probably a stretch (It also saves when resuming)
I don't think it should use update
Updae is called every frame
you don't need that
set_ability and set_sprite_pos should be sufficient
^
Yea, I was not convinced with this take as well
can anyone figure out why the code I've written doesn't actually produce a text window?
But idk how to use the two options you provided
did set_sprite_pos work for you
It did but it resets when you resume
use it, save the current position to extra.whatever, then have set_ability call set_sprite_pos with the saved position
I think that should work
loc_text should be loc_txt
thank you lol
it wasn't broken, it just wasn't doing anything. I assumed it had to be a stupid typo like that
trying to make a tarot card with unique functions depending on whether it's used inside or outside of a blind. any pointers?
I am not entirely certain of how the use method can be applied and of the contexts themselves
Sadly didn't work
set_ability might be too early then. load then?
has anyone put a cardarea inside a description of a card? is that too crazy of an idea?
trying to figure out how I might do that for this card that shows the top few cards in the deck
This is the winner, ty
another just listed them written down
High Card had one show the entire deck, but in a menu
I think you can try to do something similar to Blinds
And display an object inside the tooltip UI element
yeah thats what im trying to figure out rn
I think Blinds just show the Sprite
there was one person who put some joker cards inside a joker description
if card.config.center.discovered then
-- If statement makes it so that this function doesnt activate in the "Joker Unlocked" UI and cause 'Not Discovered' to be stuck in the corner
full_UI_table.name = localize{type = 'name', key = self.key, set = self.set, name_nodes = {}, vars = specific_vars or {}}
end
localize{type = 'descriptions', key = self.key, set = self.set, nodes = desc_nodes, vars = {}}
if G.deck and not card.area.config.collection then
local tohth = CardArea(
0,0,
5.5*G.CARD_W,
0.42*G.CARD_H,
{card_limit = card.ability.preview, type = 'title_2', highlight_limit = 0, card_w = G.CARD_W*0.5})
for i = 1, card.ability.preview do
if G.deck.cards[i] then
tohth:emplace(G.deck.cards[i])
end
end
main_end = {n=G.UIT.C, config={align = "bm", padding = 0.02}, nodes={
{n=G.UIT.O, config={object = tohth}}
}}
if main_end then
desc_nodes[#desc_nodes+1] = main_end
end
end
end```
I can send the code I have for Blinds in tooltips
see if it helps you
do you know what mod that was from?
There was a mod with dice inside Joker descriptions
@weak brook
Example output
Well, I also wrap it with the rest of the UI
so you need a little bit more code
I pass an auxiliary key to info_queue
not exactly what i'm looking for there cause i wanna keep any edition, enhancement, or seal the card has and display it properly in the preview
if its just the sprite its not accounting for that
It is though
You take the Enhancement as the Sprite
Then draw the face and seal on top
you also pass the correct edition as the shader
still that feels like a roundabout solution, feel like it would be much easier to just figure out how to put a cardarea in the ui and them emplace those cards in it
less extra work
That sounds like "it would be much easier to do [HARDER THING]"
it might not be harder? just trying to see if theres examples
seems like there is according to what rolo said
I've been trying to hook into a method for a deck I'm working on, but (despite a lack of warnings in the console) nothing seems to be happening ingame. I believe it's the hook itself messing up (because if I add another line that should trigger a noticeable effect, it still does nothing) but I really don't know how. Does anyone by chance know the reason?
Idk if there's an updated version
yeah i found it
Can anyone help me understand how ambientFire sounds work?
SMODS.Sound({
key = "ambientFire2",
path = "ambientFire2.ogg",
replace = "ambientFire2"
})
SMODS.Sound({
key = "ambientFire1",
path = "ambientFire1.ogg",
replace = "ambientFire1"
})
SMODS.Sound({
key = "ambientFire3",
path = "ambientFire3.ogg",
replace = "ambientFire3"
})
This does work, but not for these for some reason.
is this balanced for a legendary?
i dont think it is
but im not sure how to balance something like this
according to thunk, legendaries need not be balanced
fuck yeah
Perkeo definitely isn't
but this seems a bit weak
this earns 100$ a round if you play 5 luckies
i correct, it's niche
it's an interesting legendary for sure
it kills cavendish lol
and only +100 flat mult, kills cavendish, destroys glass cards
eh
the money is really what makes this joker
I think Balatrostuck has a similar Rare
but on the last hand
this is also a homestuck inspired joker
checks out
it might fit rare better tbh, it's useful if you have the right conditions for it
I think in general last hand is a nerf
but it can also hurt you or just do nothing
yea
first hand is definitely stronger than last though
My personal goal in designing Legendaries is changing how you play the game
this is a buff from its previous effect of "gives x4 mult every time a lucky card successfully triggers"
which was
really weak
making a legendary based on lucky cards is hard
ok to be fair
this + guaranteed probability on first hand joker
would go hard
so maybe the legendary has the x4 mult and the rare has guaranteed probabilities
joker with 3 effects then
4 effects
16 effects
small issue, you are almost never gonna find both
i had difficulty finding oops alll 6s in testing
neither seems appropriate for a Legendary for me
yea
but im not really sure how to make a legendary have something to do with luck
i'm trying to beat gold stake abandoned deck and i keep getting sock and smiley and photocard
RNG truly is a bitch
confirmation bias
fr
my other legendaries are very much more fun, this one is proving quite difficult
Is there a list or documentation anywhere of stuff that jokers can check for? I'm getting tired of checking a bunch of other code to find what I'm looking for lol
I think the guaranteed probability is a fun concept at least
even if in practice it's not very practical
oh yes in testing it is seeming quite useful, its just not practical
The other concept seems like Lucky Cat 2
more like a weaker triboulet for lucky cards
would making more lucky card based jokers help make this one more useful?
or more probability jokers
Yes
alright i'll get to work
lucky cards ain't a viable playstyle? The answer, use a joker, and if that don't work... Use more joker.
why does this crash?
how does it crash?
i'm trying to figure out how create_playing_card works and want to add jacks
this isn't a moment of "you're not using create_playing_card correctly"
it's a moment of "your code has problems"
i.e. you're using a variable _suit that doesn't exist
oh i thought thats how you specified the suit whoops
no it is, but you didn't define _suit
so how would i define it?
how am I supposed to know what you want your suit to be
ohh wait i think i figured it out
i was aiming to add a jack
but i think i figured it out
now assertion fail
but i think i have an idea why
i forgot to add e_
edit: yep that was the problem
is there a way to define the size of a joker's sprite? I have my atlas set to a smaller pixel size, but all that does is take the correct portion of the spritesheet and then stretch it to regular joker size. I want my jokers to be Wee Joker size
ok so it added the card but it wasnt a jack hmm
How would you make fool include spectral cards?
i cant actually figure out how to make create_playing_card give a specific suit
i managed to get the editions and seals part to work but the suit i'm stuck on
'H_J' would be a jack of hearts for example
wait
not suit
rank sorry
oh wait
DUH NO WONDER IT DIDNT WORK
hopefully changing it to rank fixes it
nope
huh
yeah i wanted it to be a jack of any suit
display_size = { w = 71 * 0.7, h = 95 * 0.7 } on the joker with normal pixel size on the atlas
Does āTarot_Planet_Spectralā (changed from āTarot_Planetā) work like I think it will?
No
Ah
Tarot_Planet is hardcoded
So how would I do what Iām trying to?
there's a fool specifically for spectrals in #1210728178201526373, you can go off that
i think i'm doing this wrong somehow but not sure how
-# don't ask me why that's in there
yeah no that first part is supposed to be a suit
Whatās it called?
The fool
The special fool
first part?
what you now changed to be _rank
oh so it should be _suit?
So how would I make it choose between tarot_planet and spectral?
Wait
Wrong wording
i want it to be a jack of any suit how would i do that
yes
local eligible_suits = {}
for _,k in ipairs(SMODS.Suit.obj_buffer) do
if not SMODS.Suits[k].in_pool or SMODS.Suits[k]:in_pool({ rank = 'Jack' }) then eligible_suits[#eligible_suits+1] = SMODS.Suits[k].card_key end
end
local _suit = pseudorandom_element(eligible_suits, pseudoseed('a_seed_of_your_choice'))
something like this should do
o i see
And why does fool say disable blind effect everywhere
Was that what it was supposed to do?
it did that in n old demo
if card.config.center_key and card.ability.consumeable and card.config.center.set == 'Spectral' then
see this line in my set_consumeable_usage hook?
you change this check to include tarots, planets and spectrals
i didn't use dissolve_color since months ago š„² currently is simply setting a value in card:sell , then check this value and do things in card:start_dissolve
IT WORKED
e.g.
if card.config.center_key and card.ability.consumeable and ({ Spectral = true, Tarot = true, Planet = true })[card.config.center.set] then
now i just have to make it add 3 of them and destroy itself lo
Pot of jacks?
I feel like jacks in the box would be a better pun
after it gets used up itll turn into a regular pot
as for the Tarot_Planet being the first argument of create_card, that actually doesn't matter at all
betmma ego searching 
But I heard Paperback has a solution which seemed good from what I heard (I did not read it)
Can i just ('Tarot_Planet', 'Spectral'...)
IIRC I also considered doing something with a variable set on the card but I think I didn't code it very well when I tried. I might've tried the other way around
this?
for what
if you're referring to the create_card argument, it doesn't matter at all. you could put anything you wanted there
No. I think it's this https://github.com/GitNether/paperback/blob/84063366cdccd76591bff395a6f19d06bfa9af6e/paperback-utils.lua#L77
tl;dr: it can discern whether the card is being sold or not via a Controller variable
I'm not sure how non-jank that is, but it seems non-jank
I had thought it wasn't real time dependent but I'm not sure
Where do I find that
60 or so lines down from this
hmm
if i try to simply add a } it doesnt like it, i dont know why it thinks the thing is just left open?
at the bottom
oh do i not need to indent calculate
your indentation suggests it be part of loc_vars
right that doesnt need to be there
yep, that was the issue
sorry for bothering you 
new lovely just dropped
im getting an error with my custom rarity stuff and idk why. Is this wrong?
SMODS.Rarity {
key = "secret",
loc_txt = {
name = "Secret"
},
badge_colour = HEX("0f1a1b"),
default_weight = 0.02
}
When testing a mod, how do I spawn in a Joker to test?
debugPlus, hover over it in the collection and press 3
yea
ok
hold tab to see all the things you can do with DebugPlus
oh and this is the error i suppose i should show it
In the original fool
no in what I sent
how would I code a Joker that gives 6 money at the end of round and then decreases the amount of money you get from it by 1?
Turtle bean and golden joker
when the conditions are met on this joker it does a random one of these and bunch of other random stuff not listed here is there a way i can make the sound play when the text is actually displayed rather than the moment the hand is played?
if outcome < 0.0667 then
-- x0 multiplier logic
card.ability.extra.mult = 0
G.GAME.pool_flags.crac_flag = true -- Set Crac's unique flag
play_sound("fn_fuck")
return {
message = "FUCK"
}
elseif outcome < 0.1334 then
-- x10 multiplier logic
card.ability.extra.mult = card.ability.extra.mult * 10
G.GAME.pool_flags.crac_flag = true -- Set Crac's unique flag
play_sound("fn_lesgo")
return {
message = "les goo!"
}
elseif outcome < 0.2001 then
-- -50 multiplier logic
card.ability.extra.mult = card.ability.extra.mult - 50
G.GAME.pool_flags.crac_flag = true -- Set Crac's unique flag
play_sound("fn_wtf")
return {
message = "Man wtf...."
}
What code does turtle bean have
if you're using latest steamodded, you can just put the sound into the return table like sound = 'fn_fuck',
+5 hand size, -1 each round
Where can I find its code
Card.Lua I believe
in case you don't know, balatro is source accessible, you can extract the executable with 7-zip
Card.lua is 5000 lines long, any tips on where to look?
if you're using any reasonable code editor, you have a search feature
is this the most recent version of steammodded?
Ctrl + f
no, this is exactly one month old
does anyone know what i have to do to force the play and discard ui to go away + make the hand drop down, like what happens when you use a consumable
I still do now know how to modify the foolās code to make it compatible with spectral cards
Thanks for the help but I still can't understand what its saying
so this card trys to destroy the highest ranked card every hand played, but currently does nothing, does anyone have any input?
Please Santa let somebody help me with this
Here's the current code for gaining money, what code should I add so that it reduces the money and disappears when 0
Set money to money - money decrease
yeah i got the new version with old calc and it just crashes
what i said is specific to new calc
well i didn't even make that change yet lol
I still have zero clue how do do what I need to do
Idk how to do that
I have made a couple other qol changes
I forgot the EXACT syntax but it should be x.y.money = x.y.money - x.y.money_decrease where x and y are various pathings that help find the variable
Let me find an example rq
hell nah i'm not debugging that mod list
figure out which mods are causing problems
you can remove half at a time
I think my code is a bit fucked up but still working
So donāt use me as an example
Also does fool reject any spectrals as answers or does it simply not check spectrals
If I know this I can probably fix my issue
my code is definitely fucked up on everything i've done but i've made a blind, decks, jokers, consumables, and boosters
Iāve made 1 joker and my codeās first words were timmeh
lol
alr, thanks though
is it a specific game state that makes the UI go down? or using the consumeable itself? anyone know
Iām modifying the source code for some simple qol stuff
is there a way to play the sound at the correct time without updating smods lol
If balatro were to update, would it overwrite any modifications in the source code?
yes, this is why you don't modify the source code directly and use lovely instead
I just say fuck it we ball to this
if you're using lovely patched, the gamee updating doesn't change anything unless your patch target got changed
Is it a bad idea? Yes. Do I care? No.
to that i say you'll regret that
And this is purely for modifying things in the base game
For new content then lovely is used
can you even release a mod thats just the base game with modified code like that
no lovely is literally used for modifying things in the base game
I would say no but someone has literally done that
unless its for yourself, i think releasing that would breach TOS
Iām sumply doing this for myself
since its just the games original source code
No releasing this
might as well carry on then, but lovely patches are really simple imo
I mean they're not allowed to
i strongly recommend you convert your changes to lovely patches still, you'll have a hard time recreating it when the game updates anyway
it is not posted on this discord
I reckon it's still not allowed
You goons are not getting your hands on observatory tarot deck without doing it yourself (goons as in non derogatory)
wait actually someone's tried that too
What's wrong with my code? The name and description are showing up blank
So this is worse for me because I donāt know how to simply modify the things
doesn't stop some people from doing it anyways
Instead of modifying the game code, hope the Ghosts of Christmas convince thunk to add automatically calculated card destruction to vanilla
I can add a new joker with some work
But modifying the foolās code to include spectral cards?
Or the other small things I did?
Nah
lovely patch, yeah
lovely patches are literally what you're doing, you type in the code you want to add and a target of where that code should be placed
its borderline no different
The thing is, I have no clue how to do that and I heavily doubt thereās a YouTube tutorial
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''
-- TARGET: card destroyed when played
'''
position = "after"
payload = '''
if SMODS.has_enhancement(scoring_hand[i], 'm_imaginary_werewolfCard') and not scoring_hand[i].debuff and scoring_hand[i].config.cardsToDestroy and #scoring_hand[i].config.cardsToDestroy > 0 then
for j=1, #scoring_hand[i].config.cardsToDestroy do
if SMODS.shatters(scoring_hand[i].config.cardsToDestroy[j]) then
scoring_hand[i].config.cardsToDestroy[j].shattered = true
else
scoring_hand[i].config.cardsToDestroy[j].destroyed = true
end
cards_destroyed[#cards_destroyed+1] = scoring_hand[i].config.cardsToDestroy[j]
end
end
'''
it doesnt get more complicated than this tbh, minus some quirks
I just remembered I can ask for help more directly than that
you just have to find a line to add code before, after, or at
i just say what file to target, what code is the spot to add my code & before/after/at, then my code
I lowkey forgot that a majority of people will help if theyāre able to, am I cooked?

as long as you can remember everything you added, converting to lovely patch wont take too long
^ (this is the big reason I avoided updating my Pokemon Essentials project for so long. Could not remember all my changes)
I increased temperance and hermit caps, added observatory voucher to tarot deck, and that was about it
The fool thing is something I havenāt done yet
Why not just make a new tarot card that creates the last used spectral
I just want to include it in the base fool
yeah but if that's not possible then try something else
I know for 100% sure itās possible, I just donāt know how
If I rebuilt balatro from the ground up, I could make that change
anyone know how to fix this?
all you really have to do is patch this line (1342) in misc_functions to include spectrals
Thank you
im not sure why it wouldnt be showing up, but i see the color tags are capitalized when they should be lower case
Is payload whatās printed or is print whatās printed?
text
instead of txt
there's no print
trying to get this to remove the highest ranked card in hand every hand played, now coming upon an interesting bug
there's pattern, which is the line in the file you're matching against, and payload is the code you're inserting
I copied the wrong thing
anyone have any thoughts?
so something like target = "back.lua" pattern = "({localize{type = 'name_text', key = 'v_tarot_merchant', set = 'Voucher'}, localize{type = 'name_text', key = 'v_planet_merchant', set = 'Voucher'}," position = 'at' payload = "{localize{type = 'name_text', key = 'v_tarot_merchant', set = 'Voucher'}, localize{type = 'name_text', key = 'v_planet_merchant', set = 'Voucher'}, localize{type = 'name_text', key = 'v_overstock_norm', set = 'Voucher'}}"
your code is wrapped in an event
which tries to re-run itself if you don't return true
you can't return that from the event out of the original function
because it gets run later
in this case you just shouldn't use an event
And would I need other code for that to run?
and now its just not doing anything at all
all i did was remove the event
oh i just saw, remove_playing_cards calculates when playing cards are removed
no, playing cards as in what those are called
oh ok nevermind
but it's not the context that calculates if you should remove a card
it gets called when cards are being removed
ooooh
ok so
preferably id like for this to happen after scoring, so replace it with context.after?
if context.cardarea == G.hand and context.destroy_card then
local highest = nil
for _,v in ipairs(G.hand.cards) do
if not highest or v:get_id() > highest:get_id() then highest = v end
end
if context.destroy_card == highest then return { remove = true } end
end
if I'm not crazy because it's 3am, this should work
that's just the index
which I'm calling _ because I'm not using it
could have just as well called it i or j or k or context
alr thanks


