#💻・modding-dev
1 messages · Page 582 of 1
what is it that you're trying to do anyways
Yes, SMODS.DrawStep
i wanna make Doug Dimmadome's hat gigantic
nope, it's the card's front right now
as are all of my Jokers' overlay sprites, except for the Legendaries and Possession
that works?
Yes, but that would break if the joker also happened to be a playing card.
apparently :3
das true
is this really a scenario worth supporting
part of the reason why i want this alternative
Yes.
if you care about cryptid compat then yes
lemme take a look at DrawStep
pretty outlandish
drawstep good yes
i've never used a DrawStep iirc so i'd like some help with the bits i don't understand yet
making the new drawstep should be relatively easy, you can probably just copy the front drawstep and change a few things
grand
(all the vanilla/smods drawsteps are in src/card_draw.lua in smods)
yupyup
thanks for your help :D
/gen
okay question
the func for the front drawstep mentions self.children.front a lot
i assume that was assigned earlier
what do i need to do to assign a new layer?
is that done automatically?
No, you just create a Sprite and you draw it on the card.
thanks, tho the stake description says "applies black stake" instead of "applies all previous stakes" now
but still amazing
i'll credit you instead of me since i really didnt do anything lol
how's this looking?
there's also #1412655729730650262
not my fault (i think)
literally the same thing
No, don't define a sprite every frame.
you just stole the idea smh
ah, do i only do that if it's nil?
create it in set_sprites probably
@umbral zodiac noway
No, you should hook Game:main_menu then define G.shared_thing = Sprite(...) and use that.
normal function on a center
okay i've got two answers now ;u;
oh ya one more question
what should self.T.y be if i'd like the extra sprite's bottom edge to be 1/4 of the card's height from its top?
like
about here
it was said that it's not related to pixel size so i'm wondering what it depends on
if it was pixel size, it'd be ((3/4 * card height) + extra height) / 2 i think (from the bottom)
virtual pixels or smth
there's an smods function converting between the two (it is a one liner)
yo, ive looked in the utils and documentations and im still not sure, how can i check if a card is destroyed?
A playing card or any other card?
playing card
okay i'm very lost 😭
context.remove_playing_cards
this should just make cards that are flipped still show their description right?
or did i forget smth
taking a break
should i avoid declaring local variables in calculate all together
it seems like all the variables are getting reset as soon as any calculate triggers
you should use local variables whenever you don't need them to persist past an individual instance of calculation, which is usually
Are you setting them outside of context checks?
yeah no, this returned question already confirmed what i have assumed
if i dont leave a global variable in g.game will i be affected by ramifications as well
global variables in G.GAME get reset when a new game starts
other global variables generally do not
if you make your own global variable it definitely won't, though it will get reset when the game is shut down
(unless you actively save it, which i don't know how to do)
-# As long as it is defined under G.GAME and is not a Card object(?) or a recursive table, it'll get saved.
DUDE I FORGOT EVERYTHING NOW
if you want something to be saved between games, you can save it in SMODS.current_mod.config["variable name"]
if you also want it to be profile-specific you can save it in G.PROFILES[G.SETTINGS.profile]["variable name"]
how to get the current tags owned
G.GAME.tags
k
(i imagine you can also combine these and use SMODS.current_mod.config[G.SETTINGS.profile]["variable name"] if you want to)
(though you would want to have a line somewhere before that that says SMODS.current_mod.config[G.SETTINGS.profile] = SMODS.current_mod.config[G.SETTINGS.profile] or {} so you don't go around indexing nil values)
(probably in the first few lines of your main file)
?
well, i didn't say "only do this before saving profiles"
G.SETTINGS.profile is a variable containing your profile number
it's always accessible
well yes
you can add things to it
the game doesn't save it once and then throw it away forever
is it possible to prevent a joker from repetition from context.repetition_check
That doesn't exist.
Hey guys, I'm having an issue where changing my seed for pseudorandom_element doesn't seem to change the result. Any ideas? I loop a number of times and do a pseudorandom_element with the loop index stapled to the end of the seed so that it would theoreitcally change the result every time, though idk if thats the best way at all
this might be super niche or just a thing ppl know abt pseudorandom_element, no worries if it's weird and you don't wanna troubleshoot for me lol
use this
this'll return a number right? I spose I could do that
that will return a boolean
table[psuedorandom("insertseedhere", 1, #table)]
got it, ill try that
there's actually a pseudorandom_element function
I was having issues with it that idk how to fix :/
hey
leaving this here if anyone has answers
does anybody here know a formula for converting a Joker's position in T into love2D coords?
pseudorandom_element(table, pseudoseed('insertseedhere')) should return a random element from the table
it does, and it changes between runs, but if I run it multiple times in my for loop, even with a different seed each time, it always picks the same item
oh wait
nvm gimme a second
i hadnt tried that pseudoseed thing but it didn't seem to fix it :/
Who's gonna tell him???
show your full code
I can give you all of it if you want theres just a bunch that I don't think is relevant
for i=1, (num_planets_destroyed) do
planet = pseudorandom_element(most_played_planets, pseudoseed('collapse!'))
G.E_MANAGER:add_event(Event({
func = function()
SMODS.add_card{key = planet, edition = 'e_negative'}
card:juice_up(0.5, 0.5)
return true
end
}))
end
most_played_planets is a table of keys of planets that correspond to your most played hand. So like if theres a tie there's multiple. I've been testing this with them all at 0 so all the hands should be in there
the events don't trigger until after the for loop is done
move the pseudorandom call inside the event
no worries, that's why we're here
i cant find a functions to create my own buttons im currently trying to add some stuff to the main menu and i cant find any functions for making buttons by default
check at UI_definitions.lua
UIBox_button
thanks
it doesn't seem like
context.hand_drawnactivates if no cards are drawn
So, I stumbled upon the same Problem - In my case it's for a Blind:
It works similar to Crimson Heart -> Debuff "Something" after a Hand is drawn.
I was thinking this was a Vanilla Bug, but Crimson Heart works perfectly fine!
Then I tested theVanilla RemadeCrimson Heart, and that doesn't work either (when you don't draw any cards)!
Now, it's not the worst thing for my current Blind to have this issue, but I wanted to ask:
Is this intended or should I put in a Bug report (for SMODS)?
-# The very rare direct Ping: @wintry solar
Is there a way to make generating a negative card skip the little animation and noise it makes?
Yes, set the 3rd input to true
Yes, use card:set_edition('e_modprefix_key', nil, true) instead of edition = 'e_modprefix_key'
hey what location should sounds be is it assets->sounds or something else and what file type should it be
assets/sounds, ogg
oh ok thx
try using context.drawing_cards
turns out it looks for resources/sounds
No, that means the key is wrong.
Yeah works but also triggers too early:
Works when trying to Debuff Jokers but when Debuffing Hand-Cards it triggers before the hand finishes drawing. Then again: I could check if the amount of cards exceeds the hand-limit and only then check for this context...
It just seems very... Convoluted?
At the end of the day it helps in my case (Thank you!) but, uh, yeah :D
I kinda liked using context.hand_drawn as "This is the Start of a new Turn" Context
can the key be any name?
No, it means you're using the wrong key when playing the sound.
perhaps do the debuffing in an event? idk
SMODS.Sound{
key = "error",
path = "error.ogg"
}
sound = { sound = "error", per = 1.2, vol = 0.4 }
pretty sure there is nothing wrong here
No, it's modprefix_key
I would expect hand_drawn to only trigger if a hand has been drawn, rather than whenever a hand should be drawn. You can also use the drawn_to_hand function on your blind itself
oh ok thx for clarifying
It's not even about Debuffing at this point, kinda applies to all things regarding that ^^'
What about Jokers then - Can they use that Context/Function too?
I get your point, but I'm kinda missing a "Start of Turn" context then ^^'
okay, getting back to this
this code is blatantly wrong, but what have i done wrong?
T is nil when the Sprite is being made
self is G in the hook.
👍
oh wait yeah i see what you mean
what do i replace the selfs with?
i assume i've put this code in the wrong place
0, 0, 71, 95
ah awesome ^u^ thanks
what would Y be if the sprite was 1 card height above where it would otherwise be?
would it be 95, or some magical mystery unit?
Also move the SMODS.DrawStep out of the hook.
it seems to be running before G.phanta_extra_sprites is initialised
G.CARD_H?
Yes, but the func wont run until then.
there isn't really a "start of turn" context
Also you should be running the old function first.
oh true :3
How is a card added to the main menu besides the existing one? I kinda forgot that's a thing that can be done and I recently got a cool idea for it
Hooking Game:main_menu and putting a card on G.title_top
Also: "drawn_to_hand" seems to work perfectly for my Blind, I didn't even know that was a Thing... Guess I should check the SMODS Code more often, kinda just reading the wiki for functions mostly ^^'
Yeah.. That's kinda my point ^^'
We love undocumented functionality 🔥
i'm struggling to paste my crash log as a file, but it's complaining about phanta_extra_sprites being nil
so it's trying to index into it before it's ready
i'll try nil-checking it
we also love documentation thats been there for 9 months
Still the same.
I've tried to write it a bunch of other ways but, I really don't know what i'm doing.
Just copying things from other jokers.
Browser Cache Moment 💀
Okay actually I got no Idea my Page's being Buggy-Moment
Welp, Ignore silly me then - Sorry to have bothered ya' 
when on earth is your cache from, this page has always had the function on
nless I am misreading things
eremel can u help ;u; i'm trying to get a second layer on top of my cards, similar to front, but it's not working
i've never used DrawStep before
realized i replied wrong, here.
this is how I do it
--in "enhancements.lua"
SMODS.Enhancement {
key = 'bone',
atlas = 'TBOJ_enhancements',
pos = {x = 1, y = 0},
config = {x_chips = 1.25, extra = { odds = 6} },
shatters = true,
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'tboj_bone')
return { vars = { card.ability.x_chips, numerator, denominator } }
end,
loc_txt = {
name = 'Bone Card',
text = {
[1] = '{X:chips,C:white}X#1#{} Chips',
[2] = '{C:green}#2# in #3#{} chance to',
[3] = 'destroy card',
}
},
calculate = function(self, card, context)
if context.destroy_card and context.cardarea == G.play and context.destroy_card == card and
SMODS.pseudorandom_probability(card, 'tboj_bone', 1, card.ability.extra.odds) then
return { remove = true }
end
end,
}
--in "reverse_tarots.lua"
SMODS.Consumable {
key = 'reverse_hierophant',
set = 'Tarot',
atlas = 'reverse_tarots',
unlocked = true,
discovered = true,
cost = 3,
pos = {x = 4, y = 2},
config = { max_highlighted = 1, mod_conv = 'm_tboj_bone'},
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS[card.ability.mod_conv]
return { vars = { card.ability.max_highlighted } }
end,
loc_txt = {
name = 'The Hierophant?',
text = {
[1] = 'Enhances {C:attention}#1#{} selected',
[2] = 'card into a',
[3] = '{C:attention}Bone Card',
}
},
can_use = function(self, card)
return G.hand and #G.hand.highlighted > 0 and #G.hand.highlighted <= card.ability.max_highlighted
end,
use = function(self, card, area, copier)
for i = 1, #G.hand.highlighted do
G.hand.highlighted[i]:set_ability(card.ability.mod_conv)
end
return true
end
}```
Hey all! I'm new to Balatro modding, so I apologize in advance if this is a really obvious mistake, but I'm not able to get my modded enhancement working. Whenever I try to use the reverse hierophant, I get an error that it "Could not find center 'm_tboj_bone'"
is your mod's prefix exactly "tboj" (including capitalization)?
Does the enhancement exist?
wym?
it should, it's at the top of the code that they posted
would it appear with the enhancements in the collection? or does smods not have that functionality yet
It should yes
You can remove the use and can_use functions because that's automatic.
Then your enhancements.lua is probably not loading properly
Thank you! I figured it out, there was a typo in main
u got it
pulling my hair out why won't this workkkkk
i wanna add to this that the hand has to contain two heart suits, how do i do that?
Try changing the order
What is context.other_card.sprint?
Nothing, because it doesn't exist.
it comes after centre though
So it's a self-made thing?
yea it's probably something that a mod added
Would you guys understand this code?
key = "foxy",
atlas = "fnaf1",
pos = {x = 5, y = 1},
rarity = 1,
cost = 4,
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = {extra = {chips = 0}},
loc_vars = function(self, info_queue, center)
return {vars = {card.ability.extra.chips}}
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if not context.other_card.sprint then
context.other_card.sprint = true
local c = context.other_card
G.E_MANAGER:add_event(Event({
func = function()
if c then
c.sprint = nil
end
return true
end,
}))
else
if context.individual and context.cardarea == G.play and not context.other_card.debuff then
carde = context.individual
card.ability.extra.chips = card.ability.extra.chips + carde.base.nominal
else
return 0
end
end
end
end,
})```
No, because you're returning a number.
That's the part that's confusing me too xD
What does context.other_card.base.nominal do?
would there be a way to add a 4th blind to the ante via patching?
assuming context.other_card is a playing card, it gets the amount of chips that the card's rank is worth (e.g. 2-10 for 2-10, 10 for jack/queen/king, and 11 for ace)
Got it, thank you :3
Weird question but is there a way to make the collection menu of Spectral cards to show 11 cards like Tarot? I made 4 more custom Spectral cards and I dislike how they spill to a new page
I changed create_UIBox_your_collection_spectrals to match the tarot one in UI_definitions.lua but it still displays 9 spectrals per page in game
Did you edit lovely/dump
😢
Oh dear, let me check
I'll make the patch then, was throwing edited file directly to the exe
lovely/dump is where lovely dumps all the vanilla files after they get patched
Ooops
Please check the integrity using steam
this is peak, you should have the mult decrease after the joker is scored tho
yeah :p
why does its neck do that
i somehow cannot figure this out
is this the wrong context?
Put that line below the return
Can the head look like a giraffe?
Wait what
Wouldn’t that have the code not execute cause it returns beforehand…..?
just try it
I can confirm, that was a nonsense suggestion.
Looks like you already do to me. Final Scoring Step occurs after Joker Main.
this does not work tho for some reason
nothing in the if statement triggers, like the message n stuff
you need a comma after that }
what happens when you get rid of the cardarea check
lemme try
The Xmult-decreasing line is not a field being set within {}. It is its own line of code. Adding a comma after that particular } would just be a syntax error.
how do i make it so that if i play a hand with a joker from my mod, this happens
G.jokers.cards is a table of all the jokers the player currently has
iterate over that and check if [joker].config.center.original_mod == SMODS.Mods["mod id goes here"] for any of the jokers
Does anyone know a mod that changes the background color on the main menu? I'd like to do that but have no idea how and so I'd like to check how it's done
mine
i fixed it!!
oh neat
@winter flower just to make sure you see
im trying to do
hi bestie
how are u doing
i dont know if im doing this completely wrong
what would be the best way to change the texture of a joker using based on a run variable using draw?
can i just change the card.config.center.pos?
like just changing it’s sprite?
yeah
you can use update=function(self,card,dt), then do “if (var) then card.children.center:set_sprite_pos { x = newx, y = newy }”
for soul_pos you can use children.floating_sprite
aha i see
that’s how i did it, and it works pretty well
ill just use draw though i think as its for that
no, overwriting the draw function means it stops doing the regular draw function stuff
i.e. things will probably go bad
oh, so like also rendering editions?>
no, the editions handle their own drawing. but every joker comes with a default draw function that draws its sprite, and defining your own draw function won't do that automatically anymore
well, i have this in the smods joker
and quick testing shows it works fine
so far
(this will delete literally everything BUT the image/obj you loaded)
so im trying to make it so that the small and big blinds are bosses, but they seem to be the same two bosses every ante. any help?
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.GAME.round_resets.blind_choices.Boss = get_new_boss()"
position = "before"
payload = '''
if G.GAME.modifiers.JCJ_bossrush then
self.GAME.round_resets.blind_choices.Small = get_new_boss()
self.GAME.round_resets.blind_choices.Big = get_new_boss()
end
'''
match_indent = true
Struggled to understand a bunch of stuff, but this is really cool
is there a SMODS.Enhancements, simillar to SMODS.Ranks and SMODS.Suits?
nvm i got this to work :)
heres what i need it for
basically, im trying to get the number of distinct enhancement types in your deck
you can find out by searching for it in the SMODS github repository, or by going into debugplus's console and running eval SMODS.Enhancements
(no, but i believe vanilla has a table of centers in general that'll include vanilla and modded enhancements? don't remember any more details off the top of my head)
Isnt there a get_enhancement function or smth
for your specific goal you can also just go reference paperback, the Grand Strategy joker checks for exactly this
And you use it on all cards in deck to retrieve their enhancement and then you can check all unique enhancement
SMODS.get_enhancements(card, extra_only)
function SMODS.get_enhancements(card, extra_only)
if not SMODS.optional_features.quantum_enhancements or not G.hand then
return not extra_only and card.ability.set == 'Enhanced' and { [card.config.center.key] = true } or {}
end
if not SMODS.enh_cache:read(card, extra_only) then
local enhancements = {}
if card.config.center.key ~= "c_base" then
enhancements[card.config.center.key] = true
end
local calc_return = {}
SMODS.calculate_context({other_card = card, check_enhancement = true, no_blueprint = true}, calc_return)
for _, eval in pairs(calc_return) do
for key, eval2 in pairs(eval) do
if type(eval2) == 'table' then
for key2, _ in pairs(eval2) do
if G.P_CENTERS[key2] then enhancements[key2] = true end
end
else
if G.P_CENTERS[key] then enhancements[key] = true end
end
end
end
SMODS.enh_cache:write(card, enhancements)
end
return SMODS.enh_cache:read(card, extra_only)
end
also yea, it would be a lot more efficient to just loop over playing cards and get their enhancements instead of looping over playing cards once per every enhancement in the game
^
...I also have a Joker that does check for unique enhancements too.
I wanted to make letter tarots then I changed my mind
oh hi F
hi
hey chaaat
I'm trying to inject cards into a pool again and it's not working and I don't know why
i feel like it's the fault of :inject()
but idk how to use that function properly
i am trying 1 other thing and if that doesnt magically fix it then im stumped
nevermind it didn't work
function Fusionpack()
SMODS.ObjectType({
key = "mjp_fused_pack",
default = "j_fuse_dynamic_duo",
cards = {
["j_fuse_dynamic_duo"] = true
}
})
for _, v in ipairs(FusionJokers.fusions) do
---Dynamic Duo is the default Joker for this pool and does not need to be injected into it again
if G.P_CENTERS[v.result_joker].rarity == "fusion" and v.result_joker ~= "j_fuse_dynamic_duo" then
SMODS.ObjectTypes["mjp_fused_pack"]:inject()
SMODS.ObjectTypes["mjp_fused_pack"]:inject_card(G.P_CENTERS[v.result_joker])
end
end
end
this code should be putting every fused joker into the pool but it's not putting any jokers into the pool, and packs using it only create dynamic duo
so I am very confused
if original_mod is nil and ocstobal mod is nil it'll be true
.rarity == "mod_prefix_fusion"
cuz every rarity needs mod prefix
it never needed that before
I guess that does explain why the code was working, until it stopped working randomly 🤔
probably
smods must've updated it to need one
oof
well that doesn't explain why the other one isn't working
i've got one here which is supposed to do it with fusion materials
function Materialpack()
for _, v in ipairs(FusionJokers.fusions) do
for _, vv in ipairs(v) do
local tempkey = vv.Jokers[1].name
local tempkey2 = vv.Jokers[2].name
---Splash is the default Joker for this pool and does not need to be injected into it again
SMODS.ObjectTypes["mjp_material_pack_pool"]:inject()
if G.P_CENTERS[tempkey].rarity ~= 4 and G.P_CENTERS[tempkey].rarity ~= "fusion" and tempkey ~= "j_splash" then
SMODS.ObjectTypes["mjp_material_pack_pool"]:inject_card(G.P_CENTERS[tempkey])
end
SMODS.ObjectTypes["mjp_material_pack_pool"]:inject()
if G.P_CENTERS[tempkey2].rarity ~= 4 and G.P_CENTERS[tempkey2].rarity ~= "fusion" and tempkey2 ~= "j_splash" then
SMODS.ObjectTypes["mjp_material_pack_pool"]:inject_card(G.P_CENTERS[tempkey2])
end
end
end
end
it has the same problem although all of its if checks are not equals
i fixed it
and i don't know how
so i'm gonna not touch it
and it's gonna keep working
Is it possible to blueprint the effect of a joker that the player doesnt have?
ive been waiting so long for this idea to be the only good solution
what if you created an invisible joker outside G.jokers and just put it offscreen somewhere
and it runs the effect
look at ortalab pinkprint
dark_edition
thank you
what's causing the issue?
wait i see why
i forgot to delete that when copying tooth
I'm attempting to get a variable i set on the creation of playing cards in function Card:set_sprites(_center, _front) or more specifically get_front_spriteinfo(_front) i got a way to pass self(the card) in set_sprites to get_front_spriteinfo though it seems to work different when running, the code is getting the correct atlas and pos that i would like when reviewing it through debug plus though it does not seem to be properly applying them.
fixed it 👍 for balancing should it be ante 2 or 3 when it shows up
does G.GAME.edition_rate also affect negative spawn rates?
Yes.
It affects all editions.
is there a way to target a specific edition when modifying the rate
Hook its get_weight
may i please be walked through this because i'm still very bad at hooking
local oldemodprefixkeygetweight = G.P_CENTERS.e_modprefix_key.get_weight
SMODS.Edition:take_ownership('e_modprefix_key', {
get_weight = function(self)
local weight = oldenegativegetweight(self)
-- change weight
return weight
end
}, true)
what does take_ownership do?
so then what do i call in the code for the card i want the modification effect to be for?
No, you do that in the hook.
well yeah. but i want a modification to the rates once a voucher is redeemed
how do you go about htat
if G.GAME.used_vouchers.v_modprefix_key
is it easy to retrigger specific effects? would retriggering only effects from seals be difficult?
No, just patch eval_card and run card:calculate_seal() twice then merge their effects.
And add {message = localize('k_again_ex'), message_card = card} in the middle.
should i merge with SMODS.merge_effects() or a different way? my shoddy current implementation isn't working
Yes.
here's the eval_card snippet i patched, seemingly disables red seals and doesn't do anything to others
No, you should only run it if the joker is found.
i had it like that before but had swapped to see if that would fix anything lol, my bad
ohhh wait i see what you mean
Also it would be SMODS.merge_effects({seals, seal2})
No, because Card:calculate_seal can return multiple values.
ah i see
this works perfectly on red seals, but no other seals have any effect (ignore the missing {message = localize('k_again_ex'), message_card = card}, will get that after)
Have you tried with purple seals?
yup, they only trigger once as well
Every seal except purple and red seals are hard coded.
is it possible to use calculate on seals (or otherwise) on cards still in the deck?
well that's inconvenient, had no clue
Yes, context.cardarea == G.deck also you have to enable it.
hmm, guess i'll have to target seals individually
what do you mean by enable it
i guess i could.. retrigger all cards with seals but that comes with the fact that full retriggers are definitely not intended
SMODS.current_mod.optional_features = function()
return {
cardareas = {deck = true}
}
end
Do purple seals still trigger if you remove every card:calculate_seal?
Also are you patching both times when card:calculate_seal is called in eval_card?
let me check
shoot, just one patch
thanks, whats the card area for after a card is been drawn and played/discarded
G.discard?
👍
is the ? because im ambiguous or youre unsure
It means that I'm unsure if you mean what I think.
patching twice still makes purple seals not retrigger, and purple seals do not trigger if the card:calculate_seal calls are removed
cards that arent "in deck" or in hand
You mean where cards go when they are discarded?
Yeah kinda but also after played
Then yes, it's G.discard
Ok thanks
how can i make color in a ui change dynamically without having to reload it
Are you sure? It works fine for me.
how to set main badge text of a seal
something akin to ref_table and ref_value in here, except for colours
the patching twice part?
yeah, i'm only getting one trigger on purple
What does your patch look like?
yup, both are present in the lovely dump
..huh. it was the if seals and part somehow??
works great now...
Yes, now you just need to run the other seals code manually.
yeah, that shouldn't be too difficult. theoretically this should account for most modded seals too, right?
Yes, unless they are hard coded.
also, where would i put that {message = localize('k_again_ex'), message_card = card} at?
perfect, thanks for the help
{seals, {message = localize('k_again_ex'), message_card = card}, seal2}
ah, didn't realize it took arguments like that
why does if context.end_of_round and context.main_eval and context.game_over == false then not work, when context.end_of_round does (just with the multiple triggers)
Is this a seal/enhancement/edition?
seal
context.main_eval isn't called on playing cards.
so how to prevent multiple retriggers on end_of_round
Look at blue seal in vanilla remade
https://github.com/nh6574/VanillaRemade/blob/24ee6098f692a58a34d573dec5a86a347c5fd13a/src/seals.lua#L20
context.playing_card_end_of_round
yep thanks, i looked at the wiki before, dunno why i dint think of that for this, sorry
wait how do i make a custom suit
SMODS.Suit
what's that
oh
thanks man
yuup ofc
How much sell value Negative gives to a consumable card?
doubles it I believe
It increases the cost of any card by 5 so the sell value increase is 2 but I could be wrong 
Wierd but thanks!
I'm gonna assume this is how take_ownership respects other mod's take_ownership
destroying asriel dreemurr creates a negative eternal astro joker, how do i do that?
Create it in remove_from_deck and check for not G.CONTROLLER.locks.selling_card
remove_from_deck = function(self, card)
if not G.CONTROLLER.locks.selling_card then
SMODS.add_card{ key = "j_busterb_astro" }
end
end
Yes, but you would also add edition = 'e_negative', stickers = {'eternal'}
like this?```lua
remove_from_deck = function(self, card)
if not G.CONTROLLER.locks.selling_card then
SMODS.add_card{ key = "j_busterb_astro", edition = 'e_negative', stickers = {'eternal'} }
end
end
(no eternal sticker)
force_stickers = true
in the same function?
Yes.
G.jokers.cards[i].edition == "e_foil" is this correct?
No, it's G.jokers.cards[i].edition and G.jokers.cards[i].edition.foil
ok so vscode is telling me there .holo and .holographic which one is the right one?
.holo
ok thx alot
Does creating a custom sticker require a hook on the function when the joker is created?
No.
How exactly would I go about reducing mult/chips/dollars given by all jokers?
You would change context.other_ret in context.post_trigger
alrighty, thank you
ease_dollars(card.ability.extra.dollars, true)
return{
message = '+' .. card.ability.extra.dollars .. "$",
colour = G.C.money
}
ok so this does not make money sound when retriggered, why?
return {dollars = card.ability.extra.dollars}
I tried this but for some reason it triggered twice
Yes, remove the ease_dollars
because you're also using ease_dollars alongside it
yeah no it triggers twice
no ease_dollars with it
if context.setting_blind and G.GAME.blind.boss then
return{
dollars = card.ability.extra.dollars,
message = '+' .. card.ability.extra.dollars .. "$",
colour = G.C.money
}
end
if context.end_of_round and context.game_over == false and G.GAME.blind.boss then
return{
dollars = card.ability.extra.dollars,
message = '+' .. card.ability.extra.dollars .. "$",
colour = G.C.money
}
end
No, it's just return {dollars = card.ability.extra.dollars}
No message and no colour
oh ok thx
how to make the joker give multiple messages with different colors?
message = '+' .. card.ability.extra.chips .. " Chips",
message = "+" .. card.ability.extra.mult .. " Mult",
return {mult = card.ability.extra.mult, chips = card.ability.extra.chips}
then what is the difference between mult_mod and mult etc
mult_mod, xmult_mod, chips_mod dont come with messages by default iirc
so does their non mod counterparts
no, mult, chips, etc have messages by default
oh wait my my iletrate brain didn't notice the don't in the first message my bad
sorry for bothering you but I'd like to ask if you know what I should be changing in other_ret?
Do you want all mult and chips and dollars or just ones that comes from jokers?
just the ones coming from jokers, so i'd assume i have to alter context.other_ret.jokers but again i'm not sure how to do that properly
if context.other_ret and context.other_ret.jokers then
for k, v in pairs(context.other_ret.jokers) do
if type(v) == 'number' then
context.other_ret.jokers[k] = reduce(v)
end
end
end
thank you !!!!
How do I check if a set is fully unlocked?
local unlocked = true
for k, v in pairs(G.P_CENTER_POOLS.Set) do
if not v.unlocked then
unlocked = false
break
end
end
if unlocked then
end
What specifically does this do? Just so I understand that
It loops through the set checking if they are not unlocked, if they aren't it will set unlocked to false
Do I need to clarify a specific set? I want to check for my consumable type
Yes, change Set to the key.
i have this currently and the joker functionally works great but i just have one issue,
the value up visual effect happens on the card instead of the joker
does anyone know why this is happening?
message_card = card
Firstly, use SMODS.add_card, Secondly, it takes a table.
whats a table in this context?
{ key1 = "value1", key2 = "value2" }
oh like that
where would i apply that here?
what i want it to do is a have a 50% chance to summon itself back into your deck
first of all, probability values are supposed to be config values and not hard coded
so things like oops all 6 can modify it
uh-huh
i was thinking of asking how to make it unaffected
bcs it could create an infinte money glitch
but then i realized i can just set its sell value to zero
lol
wait so are they key's the outcome or the jokers?
keys?
bcs if so wouldnt i just need key1 ="goochelaar"
well yeah but the keys stand for something dont they?
i give my goochelaar the key "goochelaar" to later identify it as such
the keys are kinda parameters to the add card call
No, that's the entire point of the function.
look at the smods docs
what
they can be hardcoded, the function modifies them
im hearing so many things at once
yea i mean it should be a config value instead of a hardcoded
yes and i mean that they dont need to
and also using a loc_var for the numerator and denominator
so what am i supposed to do to fix this...
you need to fix the create card bit like candycane said
so use a table?
yes
bcs im still kinda confused about what keys are
i thought they were just labels
so you can call it later
tables are usually reffered to as key/value pairs
idk if anyone here is familiar with java but is a table just a form of collection
like an array
or array list
it's more like a map or dictionary
hmm
that can also act as an array
it just seems so counterintuitive to create something like that for one value
and im not insulting you or candycane you guys are probably correct
it just seems so weird in my mind
it's so it's easier to get all the arguments
lua is weird (it doesnt really have classes either)
if not then this would lead to SMODS.create_card("Joker", nil, nil, nil, nil, nil, "e_negative", nil, ...)
Alright so I finally have a somewhat functioning mechanic which makes it so jokers are half as effective (mult, chips, etc. are reduced by 50%). How would I make their localization reflects this
it feels more refreshing to learn than java thats for sure
idk why my college says you dont need programming experience yet also expects you to get a fairy decent mastery over it and more in a year
fun
real
what is fun tho is balala modding
having a blast just coding random things
yeahh
all this because lua doesnt support named arguments lmao
You can't.
alright, i can think of something else
this is currently how it looks and i get this error
what line is the error on
this lol
also youre trying to access center but you defined calculate with "card"
wait whst
I've had that once before
or something similar
it was just a minor issue in the code that time
so I need to add center in my calculate?
so it needs a type?
you give a set argument to add_card
adding just set = "joker", still gives the same error
No, it only needs a key.
It's j_modprefix_key
OH UR SO RIGHT
? oh
i completely forgot my prefix
sorry
nah dw abt it
you helped plenty
one more quick question then ill fuck off (for now)
how do you set sell value
bcs i need this guy to be worth 0 to prevent infinite money lol
hang on ill check necromancer
Hook Card:set_cost
ok so use a local var to save the add_card return var
uh
i mean
both work tbh
im not picky XD
hooking it would set the sell value on the joker itself, not the one it created
i must admit i dont know how hooks work tho
ik ik im just saying it doesnt matter that much
???? whicj do you want to have 0 sell value
the joker itself
or the joker it creates
ig the one it creates
maybe ill change it later for balancing
but i do like ur idea more for now
right so save the return value to add_card in a local variable
and do var.sell_cost = 0
i must admit im a little confused
do i create a return on my if that has the variable?
local card = SMODS.add_card...
card.sell_cost = 0
yea u can see add_card returns the card it created (because the definition ends with -> Card) and cards are also just tables
i know i probably seem stupid its just so different from what im used to with java
fair, lua is a lot more fast and loose lol
getting back to Doug Dimmadome again
im used to everything being a alot more complicated so having things go so smoothly is a first
i've reverted it to what it was before, but commented out the new code
also where am i supposed to enter that
bcs my mind insctively went to the if statement
bcs thats where you define the SMODS.add_card
but that gives an error
so i was right
wdym what i originally had?
i did what mr seals on everything said
which was add the J_prefix_ before my joker
okay why does it dothat
send your current code
No, it would do any card.
nnno
No, hook Card:set_cost
capital C?
do local card = SMODS.add_card { key = "j_YA_Goochlear" }
Yes.
oh like that
but thats just a code convention no?
why would you do that tho
So it stays at 0
@vale grove does it matter if the jokers sell value can be increased after being created
yes
quite alot
bcs this guy is basically lucky cat
but for sell value
oh
and bcs he is a goochelaar (magician in dutch) i just thought it'd be cool to make him do a magic trick to make him reappear lol
and him not getting the abillity to increase his own sell value (after reappearing) makes it kinda pointless
then just decrease the copy's ability.extra_value by its current sell cost
can you define that in an if statement?
No, I mean it will go back to its original sell cost whenever card:set_cost is called.
okay i'm very lost with the DrawStep shenanigans i'm attempting
i'd like to add a DrawStep to render a sprite over center
the sprite will be referenced by the card via pos_extra and atlas_extra
wait now i keep getting an error when i just rolled back to a previos version that worked
tf
i'm not sure what the best thing to do is
i've checked Ortalab's curse code but i don't quite get it
if context.selling_self and SMODS.pseudorandom_probability(...) then
local new_card = copy_card(card)
new_card:add_to_deck()
G.jokers:emplace(new_card)
new_card.ability.extra_value = new_card.ability.extra_value - new_card.sell_cost
new_card:set_cost()
end
I'm thinking something like this. Copy the card being sold instead of making a new one so that it keeps any modifications, and the rest is as I said
hold on i gotta check why it isnt working
i had a previous working version except for sell value
and now it just goes back to an old error despite to my knowledge not touching any of it
I'll also note that SMODS.add_card returns the card being added, so if you want to do anything to the card afterwards, you should save the result of that function call and not the function itself
so, the Ortalab code creates the relevant sprites when it's injected
okay i'm very lost again ;u;
this just sets the sell value to 0, so no
yeah exactly
extra_value is reduced by the current sell cost of the copy
effectively setting the sell cost of the copy to 0
like am i not seeing something?
isnt this the except same version
besides
the prefix on SMODS.add_card
did you try what i sent?
im first trying to get my copying to work in general
i mean i could
i mean i suggested you copy the card in a different way..?
oh i didnt really look at it yet
i was too busy trying to figure this out
ill see if that works
im still so confused
bcs i was asking abt sell value bcs the copying worked
but now it doesnt anymore
oh yeah that works
so i was gonna put all of the extra sprites into a list, but i can't do that if i want them to be animatable
thank you mr smods
how do you know it doesn't work?
well i got an error when selling it with oops all sixes
lol
oh well lol
but
maybe you didn't save
this works
i did multiple times
but
it doesnt matter anymore
bcs this now works
thank you
im also kinda proud of the concept
i think a lucky cat for sell value is very fun
ohhh
that is a very fun idea
and a sound
yeah youve committed me to this
im looking up a magic smoke sound
-# and make the reappearing part also incompatible with blueprint unless you want it able to give duplicates?
what does this crash mean?
i already gave it non blue print compatible didnt i?
you need to specify and not context.blueprint, which you did for the first effect
yeah just checked it doesnt dupe the ability
OH LIKE THAT
LOL
well thats fixed
i hope
another thingy im realizing now
it still gets destroyed by cards like ceremoinal dagger and madness
now i did some digging and changed the context to "getting sliced"
but that still makes it get destroyed
you can use context.joker_type_destroyed and context.card == card to catch all instances of it being destroyed
what's the goal here again?
to make it copy itself when getting destroyed by madness or ceremoinal dagger
this works just fine
whoops, i gtg
why dont you do all this in remove_from_deck
that still makes it get removed
i think the issue lies in that its trying to copy the card that no longer exists
i dont understand what you mean by this
when i run that code
having it in my deck get destroyed by dagger
with an oops all sixes
doesnt make it reappear
might be that getting_sliced is set at that timing? idk
try adding new_card.getting_sliced = nil, but I'm not positive that's it
which should be 100% with oops all sixes (as it does with selling)
try what aure said but also show me the code you tried
this is what i tried last
im about to try this
it's not a context
where do i implement this
with joker_type_destroyed, just throw it at the end of the if block
ohhh
so with reference to this crash:
engine/sprite.lua:149: bad argument #3 to 'setColor' (number expected, got nil)
this is causing it
Things in card.children are drawn automatically.
remove_from_deck = function(self, card, from_debuff)
if not from_debuff and SMODS.pseudorandom_probability(...) then
local new_card = copy_card(card)
new_card:add_to_deck()
G.jokers:emplace(new_card)
new_card.ability.extra_value = new_card.ability.extra_value - new_card.sell_cost
new_card:set_cost()
end
end
you should also remove the selling self stuff for this
i should remove the selling stuff bcs this works the same is what ur saying right?
yes this works for all forms of removal
okay this can't be right 😭 (cards removed so i could see behind them)
i don't know why The Riddler's specifically is rendered twice and also massive
oh yeah that works, thanks twin
What is the goal?
quick question. is there a way to keep track of which jokers you've sold or destroyed during a run?
Why are you drawing the sprite twice and setting tilt_shadow to 0.6 the first time?
oh ;u;
Also you should be drawing it on card.children.center
i missed that, i didn't copy and paste it
ohhhh true
omg i'm so close 
i just need to fix the thing with the Jokers on the Doug Dimmadome page and i'm done
on this
im trying to make a silly sound effect play when it happens
is this not how to do it?
or does it require a message
indent your code
Yes.
thank you
Also remove_from_deck doesn't take returns.
anyway if you want to play a sound without a message, use the play_sound() function instead of returning a sound
thats what i was thinking
no idm that
but
how do i play it inside of this then?
play_sound('modprefix_key')
and message?
SMODS.calulate_effect({message = "message"}, card)
and if you're doing that then you can put a sound in that table in the calculate_effect call
is this just a rendering issue balatro has ;u;
and message colour to that?
What is the issue?
the table in a calculate_effect call is pretty much identical to a table that you can return in a calculate function
hold on lemme grab a screenshot
i see ty
for some reason this works
but when i add a colour
it breaks
does G.C.WHITE exist
it should
this tells me it does
calculate = function(self, back, context)
if context.post_trigger then
if context.other_ret and context.other_ret.jokers then
for k, v in pairs(context.other_ret.jokers) do
if type(v) == "number" then
context.other_ret.jokers[k] = reduce(v, k)
elseif type(v) == "string" then
context.other_ret.jokers[k] = reflect(v)
end
end
end
end
How would i check for a specific edition in my deck's calculate? I've tried a few things but yeah idk atp
what does it do with the color
wait nvm
i might be stupid
i was thinking abt sound
Edition on what?
i dont think the message works either lemme try
jokers
yeah message doesnt work either
if context.other_card and context.other_card.edition.modprefix_key
godsend, thank you
what doesn't work? it doesn't appear?
it crashes
then send the crash!!!
yeah i have no idea what's causing this ;u;
typo
calulate
dont trust anything i type because my keyboard is not working
then i will not do that anymore
thanks :D
np
idk what people are/aren't okay with so if you tell me ill make sure to respect ur boundaries
respectable! ✨
i reformatted things and now the extras aren't being rendered, do you see why?
(ignore the reference to v here, i forgot to fix that)
wait i'm actually such a klutz omg
i forgot to remove the big if statement 😭
okay wait the big sprite issue isn't a problem with Dimmadome
it happens with all of them
weird, removing the dissolve shader does nothing to that
so something else is rendering them
Have you tried not putting the sprite in card.children?
oh wait that renders them automatically right
lemme try that
wait that fixed it :D!!!!
tysm omg 
one more thing, why isn't the T being applied?
[note dimmadome's hat is not scaled, and not repositioned over his head]
do i have to do something other than setting the X, Y, W and H in Sprite()?
Yes, the first 2 inputs are where the sprite itself is located, the sprite on the card will be directly on the card, you need to offset it.
i thought i already set the first two inputs
0, Y
do you mean elsewhere?
OH wait i see what you mean
how do i set those?
what should I hook to modify the final score of each hand (without a joker/voucher/blind)
you can use the mod global calculate
gimme a sec that my keyboard isnt letting me copy the link lol
yeah
The ninth input offsets the y
ctrl + f calculation https://github.com/Steamodded/smods/discussions/919
do you mean in the diffuse shader line?
ah ye it seems to
lemme add that ^u^
No, in the draw_shader
ya das what i meant
so I suppose SMODS.current_mod.calculate = function(self, context)
like so, then?
No, the seventh input is rotation.
ah
is it the sixth then? do i pass that in as a table?
mm, no, it seems to be a number value
can i scale just the Y axis?
Yes.
how may i do that?
Change the T.h, VT.h and CT.h of the sprite?
👍 will try
little tiny sprite :3
also my jokers with animated extras have had their animated extras stop animating for some reason
code
how to do ^ mult?
Install Talisman and return {emult = number}
ok nvm I don't wanna add more dependencies
if you have cryptlib as a dependency (I think I remember that being something we helped you with before), I think it also implements emult in the same way
how can i forcefully draw specific cards into hand regardless of hand size
SMODS.draw_cards(x) should draw x cards to hand
nah I removed it
seals helped me implement the thing I wanted without cryptlib
how to change the weight of rarities when a joker is present?
change G.GAME.<rarity in lowercase>_mod
it is giving me an error
if context.card == card then
return{
card = card,
G.GAME.common_mod = 0.5
}
end
dont put it in the return
you dont need a return at all
context.card == card is also probably not correct
cryptlib has it too
exact same return
if context.cardarea == G.play and context.individual and #context.full_hand == 1 then
if G.GAME.current_round.hands_played == 0 or G.GAME.current_round.hands_left == 0 then
context.other_card:set_seal("comedy_smiley_seal", true, true)
return {
message = "Imbued with Chaos",
card = card,
}
end
end
getting the error "attempt to index a nil value"
send log?
as I said I removed it
could you just send the entire lovely log
hm
that doesnt even have a crash in it
wierd
though it had something about an smods patch failing, maybe somethings with your smods installation?
do you think i might need to reinstall Smod
no
