#💻・modding-dev
1 messages · Page 689 of 1
I don't know the key but something like this would work;
set_ability = function(self, card, initial, delay_sprites)
if card.config.center.discovered and initial then
G.E_MANAGER:add_event(Event({
func = function()
card:set_edition('KEY_HERE') --> NEGATIVE EDITION KEY
return true
end
}))
end
end,
sweet, thank you
e_negative I think is negative edition
ok
Sounds right 
I know cuz I always get editions wrong by not putting e_ prefix lol
im not good with adding prefixes
what would be the command for eternal?
still 50-50 on whether I want kerry to be eternal
Honorable mention of Flowire 
tbh you can get eternal egg and it does follow that sorta counter
I think you could be really cheaty and add it like this;
-# Or also in 'set_ability' and apply it with the sticker command adding thingy lol
Yeah 
dang ok im doing that thats easy
you can do card:add_sticker("eternal", true) in set_ability
which is probably better practice
That is much better 
ok
I made gold bot fuck it we ball
and i highly doubt it work properly all the time
this one gave me no trouble making lol
the rest of em I needed some amount of help for
It's a collaberative effort
yapping petyr I dont think required that much help
spent more time making lines for his yaps then actually implementing his ability
(if hes not talking a lot, hes not using his ability)
how would I filter for cards in hand that are also not highlighted?
card.highlighted is set to true for any card that's highlighted
so just go through the cards in hand and check for if it's false
i'm throwing the towel on this one
Fair enough, don't be too hard to yourself over it 
decided to keep eternal but allow perishable. Get a low roll sticker and a high roll one
is there a list of G.STATES ?
I’m trying to make something not happen when you’re in a shop
nevermind forgot the vanilla remade faq exists
vanilla remade faq the goat
fr
Then it crashes with
[SMODS mannpower "src/blinds/hasteblind copy.lua"]:19: attempt to index global 'card' (a nil value)
it should just be if playing_card.highlighted == false then
i use card as a generic stand in for any card object, like playing_card in your for loop
thanks
how do i give a joker -$20 sell value
-- Swindler
SMODS.Joker {
key = "swindler",
config = { extra = { mult = 20, dollars = 20 } },
pos = { x = 9, y = 0 },
cost = 5,
rarity = 1,
blueprint_compat = false,
eternal_compat = false,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HLJokers',
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.joker_main then
return {
mult = card.ability.extra.mult
}
end
if context.selling_self then
return {
dollars = -card.ability.extra.dollars
}
end
end
}
this mostly works, but it gives a sell value of $2 after taking away the $20
set_cost() hmmmm
-- Swindler
SMODS.Joker {
key = "swindler",
config = { extra = { mult = 20, price = 20 } },
pos = { x = 9, y = 0 },
cost = 5,
rarity = 1,
blueprint_compat = false,
eternal_compat = false,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HLJokers',
calculate = function(self, card, context)
if context.cardarea == G.jokers and context.joker_main then
return {
mult = card.ability.extra.mult
}
end
if context.selling_self then
card.ability.extra_value = card.ability.price
card:set_cost()
end
end
}
this did NOT work lol
this just makes it sell for $20 more
you should hook Card:set_cost to force sell value to -20 for this joker specifically
how do i hook it
is there a reason why the consumeable (totem head of the printer) tooltip is not showing up?
this is what i used to set copied card sell costs as 0
local cardSetCostHook = Card.set_cost
function Card:set_cost()
local ret = cardSetCostHook(self)
if self.ability.felijo_copied then
self.cost = 1
self.sell_cost = 0
end
return ret
end
Can't seem to find a way around this crash
try if not playing_card.edition
thanks
try changing L28 to if not playing_card.edition then
yeah remove the [i]
so im guessing id write it as
-- Swindler Localisations (Code by LasagnaFelidae)
local cardSetCostHook = Card.set_cost
function Card:set_cost()
local ret = cardSetCostHook(self)
if (SMODS.find_card("j_hatchl_swindler")) then
self.cost = 1
self.sell_cost = 20
end
return ret
end```
you're trying to something you already have
i think that would set every card's cost to 20 if you own swindler
i need to make it so that swindler specifically has a sell value of -20
local oldcardsetsellvalue = Card.set_sell_value
function Card:set_sell_value()
local g = oldcardsetsellvalue(self)
if self.config.center.key == 'j_modprefix_key' then
self.sell_cost = -20
end
return g
end
yeah so
do what somethingcom did because i stopped typing when i saw the message
this would be better because you're hooking something i didnt know existed (set_sell_value())
as i understand it would show the tool tip if its in G.P_CENTERS but Jokers are in there right
o i see i see
thank
s
truth be told i dont really know how hooks work so this is useful info
ive looked at the vanillaremade guide
still makes little sense to me 😭
basically what you're doing is wrapping the function you are hooking with your code
shouldnt g be local
Think of a function like a set of actions. Function is called, and the set of actions is performed
A hook is basically a spy, that sees the function being called and is going "wait now hold up, do THESE actions instead"
the real hooks was the imposters we made along the way
so if i had a function that told the program "print hello world" the hook would come in and say "actually print goodbye world instead"
Yeah, basically
i mean it would print both
I'm pretty sure it doesn't if you dont return the original function
Yes, but that would be an override, not a hook.
this
yeah, my b, im confusing terminology
a hook says both an override says ur new thing
spy going "also do this" instead of "do this instead" in my analogy
its still a good analogy I think
😭
override is the evil spy
(usually you don't wanna override functions)
the real hooks were the red spy's we made along the way
ok so its because im stupid and left a space before the T: modifier
we love being stupid
It still doesn't actually do anything as far as I can tell
How do I change the mult of the current hand? Like the Mult from Chips x Mult
Thank you :3
Where do I use that? This doesn't work
if context.main_scoring then
mult = mod_mult(0)
end
end,```
yeah vanillaremade is the goat
it shouldnt be returned
wait
nvm
im blind
It should be return {mult_mod = -mult}
Code?
if Cryptid then
SMODS.Voucher {
key = 'developer_console',
atlas = 'vouchers',
order = 32657,
dependencies = {
items = {
"set_cry_tier3",
},
},
pools = { ["Tier3"] = true },
pos = { x = 2, y = 0 },
requires = { 'v_mannpower_squad_surplus' },
calculate = function(self, card, context)
if context.create_booster_card and context.booster.config.center.group_key == "k_cry_program_pack" and pseudorandom("developer_console") > 0.8 then
return { set = "Mannpower", key_append = "ar2" }
end
end
}
end
It should be return {booster_create_flags = {set = 'Mannpower', key_append = 'ar2'}}
Still not working
if context.main_scoring then
return {mult_mod = -mult}
end
end,```
What type of object is this?
It's the calculate of an edition
It should be (context.main_scoring and context.cardarea == G.play) or context.pre_joker
It works now, thank you!
Wait, am I missing a context or why does it trigger so many times?
SMODS.pseudorandom_probability(card, 'cstorm_glitch', 1, card.edition.odds) then
card.glass_trigger = true
return { remove = true }
end```
Also, what does card.glass_trigger do? I didn't find out
card.glass_trigger is so things can see that a card was shattered from being glass.
What is the goal?
is there a way to make it so a tag can only appear on skip blinds selection and not from any other thing that generates tags, like how legendaries and hidden spectrals are excluded from pools
The edition has a 1 in 4 to destroy a random amount of cards currently in hand
if context.after and SMODS.pseudorandom_probability(card, 'cstorm_glitch', 1, card.edition.odds) then
return {func = function()
local destroyed_cards = {}
local temp_hand = SMODS.shallow_copy(G.hand.cards)
table.sort(temp_hand, function(a, b) return not a.playing_card or not b.playing_card or a.playing_card < b.playing_card end)
pseudoshuffle(temp_hand, 'seed')
for i=1, pseudorandom('seed', 1, #G.hand.cards) do table.insert(destroyed_cards, temp_hand[i]) end
SMODS.destroy_cards(destroyed_cards)
end}
end
Thank you again
for some reason my sephirot cards arent showing up
lemme update my repository and show you all the code i have written so far
why does this code make ghost cards? i can't figure it out
it doesn't even destroy cards
https://github.com/cosmeggo/Hatchet-Lite/tree/main <- here is the tree rn
https://github.com/cosmeggo/Hatchet-Lite/blob/main/src/sephirot.lua this is sephirot.lua specifically
sephirot cards seemingly dont exist
im aware that some jokers lack localisations, which is okay becasue ill add those later
the sephirot card set itself shows up
but no cards ;-;
ur welcome :)
What is the goal?
have the cards be discarded after any hand is played
guys can yall hepl
how can i activate on-sell effects???? context.selling_self doesn't work
show code, because context.selling_self is literally the context designed for on-sell effects
calculate = function(self, card, context)
local extra = card.ability.extra
if not extra then return end
if context.individual and context.other_card then
local c = context.other_card
if c.ability and c.ability.set == "Enhanced" then
extra.counter = (extra.counter or 0) + 1
if extra.counter >= 15 then
local gain = math.floor(extra.counter / 15)
extra.counter = extra.counter % 15
extra.X = (extra.X or 0) + gain
return {
message = "+1 X",
colour = G.C.CHIPS,
card = card
}
end
end
end
if context.selling_self then
print("sell")
extra.sold = true
end
end,
idk how to format
weird
maybe uhhh
print(inspect(context)) at the top of the calculate function and check what it prints in debugplus when you sell the card
OOOOOOOOH IT PRINTS IN DEBUGPLUS?? ok
ok it says selling_self
alr so i just have to fix the code
Are shader colors like in polychrome decided by hexes or hues
rgba format by default, with each value going from 0 to 1
there are lots of shaders out there with functions to convert between rgb and hsl tho, you can just steal that if that makes more sense to you
am i doing this correctly? because i'm not getting dupes in testing
why did i not show the whole hook
@red flower i'm following the vremade example but idk what's happening
looks correct to me
did you not open a mega arcana pack
it's a lot easier to get dupes there than mindlessly rerolling the shop
you should have just given yourself every tarot
Does anybody know how to specifically change the background of the game? just started modding textures and I'm not sure how to do it.
like the colors or something else?
the background is a shader iirc
so making it into an image would take a bit of work
https://github.com/Steamodded/smods/pull/1340 we have a WIP PR for that
thank crodie
i'm making stakes for my mod and it appears in the menu and all but it's unselectable ? (its above gold stake, and gold stake was beaten)
how do i make a joker randomly disable other jokers
i cant find anything about disabling jokers/cards
debuff i mean
ok thank you
yeah i dont really know how to apply all that
is truthy/falsy value just like true or false
falsy = false or nil
truthy = true or any value
How could i create a random joker of a certain rarity?
SMODS.add_card({set = 'Joker', rarity = 'modprefix_key'})
Just common for common jokers? It seems to be giving rares and uncommon too
Wait nvm
Im dumb
How easy would it be to make Balatro's UI change transparency when something happens?
Would probably need to patch that

How do I hide the stickers on a card, when a specific edition is on it?
dude why isn't this set's soul card working man
why dont you set the soul rat to 1 for testng
idk how to do that
soul_rate = 1
on the card itself or the set definition?
the card
card
okay cool it does work I guess OFFBYONE is just a fraud
yeah but I opened like a dozen packs with dozens of slots each
you underestimated 0.3%
I'm contemplating splitting this effect between two soul cards
PowerPlay for the Polychrome, and Godmode for the Negatives
which mod is the best for stacking cards jokers consumables etc
so I can get to insane amounts like 1 trillion jokers 1 trillion consumables
you are not going to get to 1 trillion jokers
yeah this is balatro, we call it 1e12 jokers
this is talisman, we call it e1.2e1 jokers
wouldnt it be ee1.079 or something
Guys. How do I increase the weight of all spectral packs using the object poll thing?
The code I used to use doesn't work anymore, sadly.
if context.modify_weights and context.pool_types.Booster then
for _, pack in pairs(context.pool) do
if pack.key == "p_spectral_normal_1" or
pack.key == "p_spectral_normal_2" or
pack.key == "p_spectral_jumbo_1" or
pack.key == "p_spectral_mega_1" then
pack.weight = pack.weight * whatever
end
end
end
Also, does the option to introduce weights mess up the seeds too bad?
uuu, thanks man.
what was your old code actually
typically seeds arent used for modded content
because mods that add any amount of content screw up seeds
Yeah, I guess that's true. thanks.
get_weight = function(self)
if G.GAME.stake >= 6 then
return self.weight * 1.8
end
return self.weight
end
}, true)```
Scuffed, I know.
I think it was like that, I deleted this morning, haha. nvm, it is correct.
I think it got messed up in the last update or two.
kid named kind:
oops
all sixes

why is pairs purple now
wtf
bump
Probably hook the Stickers drawstep?
Guys, guys. How do I hide my mod's label on my new stake?
Doing },true) at the bottom doesn't work.
you can't silently create an object
oh. okay
delay = 0.1,
func = function()
G.hand.highlighted[i].ability.perma_x_chips = G.hand.highlighted[i].ability.perma_h_x_mult or 0
G.hand.highlighted[i].ability.perma_x_chips = G.hand.highlighted[i].ability.perma_h_x_mult + 0.1
return true```
GRAAAHHHHH WHY IS IT GIVING XCHIPS INSTEAD OF HELD XMULT
because you put perma_x_chips????
it's literally right there
oh
uhh
wtf
i think i forgot to save
feel free to throw tomatoes at me
or sum
🍅
lua really needs an increment/decrement operator 😭
give me my 1 trillion jokers
this reeks of cryptposting
what the fucking kind of mod is this
thanks
does add_to_deck work for setting a cards enhancements?
as in if an enhacement has add_to_deck in its abilities, will that trigger when a card is set to the enhancement?#
bizarre
when i try to decrease the card rank it just
crashes
idk why
it used to work but it no worky
why are you omori now
how do i get the least played hand
do i just do most played hand code but
local hand_name, play_count = 'High Card', math.huge -- how max integer get?
for hand_key, hand in pairs(G.GAME.hands) do
if hand.played < _played then
play_count = hand.played
hand_name = hand_key
end
end
local most_played = hand_name
I'm experiencing a bug with one of my jokers:
if (context.joker_type_destroyed and context.card == card) and not context.blueprint_card then
local editionType = nil
if self.edition ~= nil then
editionType = "e_" .. card.edition.type
end
SMODS.destroy_cards(card)
if editionType ~= nil then
SMODS.add_card { key = "j_goob_Kerry_rage", edition = editionType }
else
SMODS.add_card { key = "j_goob_Kerry_rage", no_edition = true }
end
end
if ceremonial dagger destroys the joker, I get 2 copies of "j goob kerry rage" and not 1
gonna troubleshoot other destroying methods
nah it just seems to be dagger
wait no madness does it too
but not the spectral card
oh
its because the card is already being destroyed
duh doi
smods.destroy card is redundent
nevermind
I am not sure why that wasnt an infinite loop
riddle me that one batman
Yes, but you would also want to check if SMODS.is_poker_hand_visible(hand_key)
Like, as the card is being destroyed I had code to destroy it..which would retrigger the context destroying it
why would it only repeat one additional time
hello people, i wanna start modding balatro, where do i start?
https://github.com/nh6574/VanillaRemade/wiki good place to start I think
Get used to reading the SMODS doc as well - don't let it scare you, take your time reading it
awesome, thanks, but where do i actually code? like in the game's direct source code or do i make a new file from scratch?
how increase discards? ok it is just 
ease_discard
Yes, but if you want to add permanent discards you would also modify G.GAME.round_resets.discards
that's fine, it's just for the blind 👍
am i correct in thinking that this would get me the name of both the hand played - and the hand that was discarded?
SMODS.Joker {
key = "susjoker"
atlas = "placeholders",
pos = {
x = 0,
y = 0
},
config = {
extra = {
chips = 6152018
}
},
rarity = 1,
cost = 0,
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.chips
}
}
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips
}
end
}
my joker wont appear
is there something wrong with this code or is it somewhere else
There are multiple syntax errors here. If your game loads despite that, then that implies this code is never even seen by the game. Where did you put this? If it's in a file separate from your main lua file, you need to load that separate file manually using assert(SMODS.load_file("your_filename_here.lua"))()
As for syntax errors:
- Missing comma after
key = "susjoker" - There should be two
ends before the final}of your code here, not just oneend
oh damn, i suck at coding, thanks for your help!
It's fine, everyone has to start somewhere.
how does SMODS.recalc_debuff(card) work, recalculates debuff doesnt tell me much
local jcard = pseudorandom_element(jokers,"zwp_random")
how would I get the key of the joker output by this
jcard.config.center.key
Yes.
its checks every card to see if it should be debuffed
use it if you make a change to what cards should be debuffed outside of the debuff context
bump?
try it
set_ability function does get called when enhancement is applied.
thanks!!
whats the infoqueue for editions?
info_queue[#1116390750314307698_queue + 1] = G.P_CENTRES["e_baggutro_faded"]
cause this isnt working
G.P_CENTERS.
foiled by englishh difference once again
i assume that's how they do it in canadia
How would I check for the amount of times a seal has triggered this run?
i don't think that function is built in anywhere, but you can add it to the mod calculate (if you mean any seal, or any seal of type X) or the seal calculate (if you mean a specific seal object)
Yall know if the game has an internal timer that counts how much time have you spent in a run or do I have to built that from the ground up
Is there a way for a challenge deck to ban all of a specific card type except for a specific whitelist or do I have to ban everything outside of the whitelist by hand?
need own one
Damn
how would I do the mod calculate thing (this is for a specific seal)?
(i.e. where would I put it)
doesn't matter where you put it as long as it gets loaded
yea uhhh one question, how is the square joker set up in like height and width wise, i wanna make a card of its size..
like so. it specifies the height in the pixel_size
you can do this width too
ohhhhhhh thx
i was also asking cuz liike to get templ8s i take the joker.png from the files copy it into my mod and crop, so should it be 71 X 71
sorry i dont understand could you explain that again lol
like you take the joker.png file from the game (this image) and crop said item, square joker, whats its width naturally?
every joker image in that file is 71x95 px
then how do I make a variable like G.GAME.consumeable_usage_total.tarot?
do you know how variables in lua work
i understand partially what context.joker_main and G.GAME.hands[context.scoring_name] and G.GAME.hands[context.scoring_name].played_this_round > 1 means but how can i change context.scoring_name to refer to a rank
Not really on a global scale
i cant find any similar things on the vanillaremade wiki D:
why do you want context.scoring_name to refer to a rank
that's the name of the poker hand
you want context[something that refers to a rank]?
i don't know what would be "similar to this but for ranks"
try explaining it directly
yea pretty much but more like context[something that refers to a rank].played_this_round > 1
like essentially how can i get if said rank was already played
broader stats like cards played in a round are not tracked in context
that's what G.GAME is for
context is the immediate context of what's currently being calculated
ohh.. yea makes sense
it's temporary and will be lost when calculation completes
oh yea.. but i wanna know if the rank was played THIS ROUND
so wouldnt it be context?
ohhh
ok i get that and all but what would be the syntax to write, would it be like G.GAME.rank.already_played = True?
G.GAME.rank isn't a variable that exists
also true is the boolean value, not True
oh.. i get confused with how its used because i do python
and have some knowledge with lua
but how can i write it
to assign a boolean to a variable you do variable = true
the same way you assign any other value
no more like get if rank was played but that helps too
w8 dont variables start like local variable = "string" or soemthing like that or am i confusing it with robloxs terrible lua
you don't have to declare global variables in advance, only locals
i don't believe there's anything in vanilla or smods that tracks whether a given rank has been played this round; you'd need to build that yourself
oh dang..
i could do a list/dictionary
rite?
im used to roblox lua and not as much as balatro engine lua, would i write lists/dictionarys/whatever its called like local list = {thing,thing2}
and i forgor how to addd
thunk didn't change any of the basic lua syntax
ohhhh okie
SMODS.current_mod.calculate = function(self, context)
if context.individual and context.cardarea == G.hand and not SMODS.has_no_rank(context.other_card) then
G.GAME.ranks_played_this_round = G.GAME.ranks_played_this_round or {}
G.GAME.ranks_played_this_round[context.other_card:get_id()] = (G.GAME.ranks_played_this_round[context.other_card:get_id()] or 0) + 1
end
if context.end_of_round and context.main_eval then
G.GAME.ranks_played_this_round = {}
end
end
(though i'd double check the end of round part, i'm not sure mods do main_eval)
that is way to complex for me, could you add like comments to it or explain..
please
(i'd recommend naming the variable something like G.GAME.modprefix_ranks_played_this_round but with your actual mod prefix, so that it doesn't collide with any other mods that might do the same thing)
if a card jsut got scored
create the table if it doesn't exist
at the index of the just-scored-card's id, add +1 to the count
if the round is over
empty the table
alright.. and i would write luas form of saying "if the rank of this card is contained in G.GAME.modprefix_ranks_played_this_round then do thing" right
if we're in whatever context that cares about cards scored this round
if table[rank id] then that rank has been scored this round, do whatever we care about this for
did you try it?
do you have debugplus? you can just use the in-game console to test something that simple
oh..
ok so i have my code right? and essentially where can i insert the thing it does
for this example my item will give 4 dollars in game if the rank was played, i dont think i need help with the giving money but i will need help with the like where i put it
have you looked at the smods wiki at all?
when someone asks "where do i put my code" there are several values of "where" they could be referring to depending on how much they understand about basic code ideas
i like looking at vanillaremade instead because it has everything laid out but i could check
vanillaremade is great for examples, but if you want explanations of basic structure, you should look at the actual documentation
alright im more asking like i have the thing right? but now how am i going to add the like
if this is contained in this list
give four dolla
do you mean: a calculate function?
kinda yea
i know vanillaremade has many examples of calculate functions
but like now im askign whats the difference between calculate = function(self,card,context) and SMODS.current_mod_calculate = function(self, context)
well. you see. your mod isn't a card.
yea...
so it doesn't take a card parameter.
(also it's current_mod.calculate, not current_mod_calculate, that was a typo)
the mod calculate??? yeah you declare a mod calculate outside a joker
so where can i put it now, at the top?
thats rhetorical
yea i can
or atleast i think
ok.. now i add it all
it mostly doesn't matter what order you do it in, as long as you don't try to call any functions or reference any variables that don't exist yet (but declaring a function now that calls something which doesn't exist yet is fine, if you know it won't be called until the thing exists)
i have it like this? do i have to declare the variable somewhere
you don't have to declare that you're adding to a table that already exists, which SMODS.current_mod is
w8 is current_mod a placeholder where i put my prefix
no
oh ok
when smods loads your mod, it sets SMODS.current_mod to your mod's table
ok..
now how do i get if the rank was already played with this list and newfound knowledge
well, based on what you've typed so far, what will be true if a rank has been played at least once this round?
you can also get SMODS.Mods.your_mod_id
which is a permanent and stable reference to your mod's table
ok lemme enable debugplus
alright but did we add a calculate = function(self,card,context)?
you appear to have created the beginning of a global calculate function
now what would i put in debugplus
eval 2+2
yeah
now you know what that command does
G is a table full of globals
you can look at them
how
well you see. variables have names. try typing the name of a variable
that's the name of the table yes
you know that's the name of the table because that's what you named the table
it cant find it because i use prefix "epicerMod" do i remove it?
what exactly is it saying
oh i see
you misunderstood what meta meant by "prefix"
she was suggesting that you change the name of the variable
what you did was not that
nvm i think i got it lemme see
no i dont it says nil when i write it as a command XD
prefix_name is the variable named prefix_name
table.name is the variable named name inside the table named table. but you can't declare variables in a table that doesn't exist yet
so i type like G.GAME.table.ranks_played_this_round
what
would i type in eval G.GAME.table.ranks_played_this_round wheres tables significance in the text to find it
i'd recommend naming the variable something like G.GAME.modprefix_ranks_played_this_round
please note that meta did not sayG.GAME.modprefix.ranks
ohhhhhh ok
you will have to change it in the mod calculate too
wdym
your mod calculate is currently going to crash when you play any card
what do you mean you haven't put code in
like the calculate in the card that does the function.. havent done that yet
you can't check whether your code works if you don't. use. your code.
your code to do a thing will not do a thing if you don't do the code
these are not magic passwords that extract desired behavior from the aether, these are instructions to a computer
ok sorry
nothing, because you are looking for the results of a behavior you have not yet implemented
im starting to understand it now
we can say that G.GAME.epicerMod.ranks_played_this_round wont exist because it cant collectively read the mod prefix.. and without it its nothing
but i can still find variables!
G.GAME.epicermod doesn't exist because you never declared it. this is the default state of all variables
because it doesn't exist, you can't declare G.GAME.epicermod[some subvalue], because this would require first indexing G.GAME.epicermod, which is nil
ohhhhhh so its G.GAME.epicermod[ranks_played_this_round] and not exactly G.GAME.epicerMod.ranks_played_this_round
not remotely
ok.. am i getting there though?
table.value is shorthand for table["value"], that is, the value inside table indexed at the string "value"
I don't get how this applies to me trying to format a global variable and give it a way to automatically update when a specific seal is played during that specific run
table[value] would be indexing at the contents of the variable named value
which leads to my favorite cursed fact about lua
local table = {}
table[table] = table
this table consists of a single index, itself, which contains a single value, also itself
OH W8 I THINK I GET IT
if ranks_played_this_round is a table then i can say like ranks_played_this_round[1]
you can, yes
that would get the value indexed at the number 1
(not to be confused with the string "1", which would be a different value)
And for this one (which is not related to the achievement thing), the reason I'm asking is because I'd rather not have to blacklist every Joker except the ones that follow the criteria.
alright alright
idk if im being just an idiot but im essentially saying eval G.GAME.epicerMod.ranks_played_this_round[1] or it has to be said differently
probably useful context: Card:get_id() returns a number, the id of the card's rank (or a random massively negative number if the card has no rank, e.g. Stone)
what rank has the id 1?
hmmmmmmmmm
wehere am i finding it in eval
im slowly getting confused i think i might need a break at some point.....
well, dp.hovered contains whatever you're hovering over, if you want to look at the numbers in a card object
(if you're running debugplus)
alright..
so you could do eval dp.hovered:get_id() on any card you can hover over
also. i've tried saying this a few ways but i don't think you've even noticed?
you don't want epicerMod.ranks_played_this_round. you want epicerMod_ranks_played_this_round
OHHHH
the first one tries to find a variable named ranks_played_this_round inside a table named epicerMod (which is a problem, since you've never declared such a table)
the second one just tries to find a variable named epicerMod_ranks_played_this_round
i get nil but its probably because im not specifying. if i write it like eval epicerMod_ranks_played_this_round its gonna come as nil but if i specify like eval epicerMod_ranks_played_this_round[1] ill get something right?
no
if you eval an empty table you should get something like
Table:
if you eval a variable that doesn't exist you'll just get nil
alright makes sense
the difference is important, because empty_table.index is just nil (which is generally fine in if checks, it's basically just false), but nonexistent_table.index gets you an error
ok.. so that means our table does exist because it doesnt give us an error
which table?
the table were trying to get answers from when trying to eval
name
epicerMod_ranks_played_this_round
if you fixed and implemented your mod calculate i would expect that table to exist
though i would not expect that if you did not do so
i did insert it
it hasnt tho.. its probably because i havent fully set the thing up..
what do i fix however
oh w8
i was thinking that too
lemme test it
ok so i might be trying to type it in wrong but im not so sure
well get back to it l8r
okay wait so would something like this work?
SMODS.current_mod.calculate = function(self, context)
if context.individual and context.cardarea == G.hand and context.other_card.seal == "mannpower_strange" then
G.GAME.mannpower_strange_counter = G.GAME.mannpower_strange_counter or 0
G.GAME.mannpower_strange_counter = (G.GAME.mannpower_strange_counter or 0) + 1
end
if G.GAME.mannpower_strange_counter >= 10 then
check_for_unlock({ type = 'strange_threshold1' })
end
end
SMODS.Achievement {
key = "strange1",
bypass_all_unlocked = true,
unlock_condition = function(self, args)
if args.type == "strange_threshold1" then
return true
end
end,
}
by default, check_for_unlock isn't called during a seeded run, right? or do i have to account for that in a hook
question, SMODS.Enhancement can into add_to_deck? 
nope
hmm. what calculate context(s) should i use to substitute for that, then
i'm trying to implement a deck effect that changes the amount of held xmult steel cards have
in that case, i'd actually recommend just taking ownership of the steel enhancement to give different xmult if the deck is active
but if you do want to just go the route of modifying steel cards as they appear, context.setting_ability is used when a card changes its ability, which usually includes applying an enhancement. and you can check context.new to see which enhancement it is
pair that with context.playing_card_added to account for cards that are created as steel already (e.g. cards found in standard packs or from familiar), and you should be good
This is certainly code
am i layering patches correctly
ok i figured that out, but now i need to plug my atlas on there
all of the packs appear to be lacking a create_card function
someone that understands shader
vec4 tex = Texel(texture, texture_coords);
float gray = (tex.r + tex.g + tex.b) / 3.0;
vec3 gold = vec3(0.85,0.8,0.43);
float factor = smoothstep(0.0,3000.0,time);
tex.rgb = mix(tex.rgb,vec3(gray)*gold,factor);
why does this is always same color
instead of being animated
both have same edition
time is a fixed value
check_for_unlock = function(self, args)
return args.type == 'strange_threshold1' and (G.P_CENTER_POOLS.Stake[G.GAME.stake].key == "red" or
G.P_CENTER_POOLS.Stake[G.GAME.stake].key == "blue") and true
end
Why isn't this working for unlocking my deck?
thanks
what's your shader name?
which value should I use for color animations?
golden_shader
that's the name of the vec2 inside your shader, right>?
yes
yeah I don't know why thunk named that value time when it isn't a time value
what does that actually equal
well, it is the time in the CRT shader
(This is supposed to check for when the strange_threshold1 check_for_unlock thing occurs on either Red or Blue Stake)
but otherwise its this G.SHADERS[_shader or 'dissolve']:send("time",123.33412*(_draw_major.ID/1.14212 or 12.5123152)%3000)
genius!
this crash is unrelated to the folder loop
the atlas with the key "sussy" is attempting to load an image file that doesn't exist
oh no
could someone check over a part of my localisation? the sephirot cards arent having their localisation show up
here is the en-us.lua file
all of the other localisations work fine
but the localisation wont show up
here's sephirot.lua if it helps
SMODS.ConsumableTypes don't get their mod prefix added automatically.
You would remove it from the key in localization, or you would add it to the key manually.
which means...?
sorry, i suck at understanding context clues and such
i need visual explanations for this sorta stuff
oh i found this in main.lua
key = 'sephirot',
primary_colour = HEX('0ebab2'),
secondary_colour = HEX('0ebab2'),
collection_rows = { 4, 5 },
shop_rate = 0,
loc_txt = {
name = "Sephirot",
collection = "Sephirot Cards",
}
}
hmmm
needs adjusting i think
anyways looks like i fixed it
I don't get why this isn't working
bump
oh hell yeah
everything past Mags hasn't been implemented yet
are they jokers or blinds
Okay I've changed it to
check_for_unlock = function(self, args)
if args.type == "strange_threshold1" then
if G.P_CENTER_POOLS.Stake[G.GAME.stake].key == "red" or
G.P_CENTER_POOLS.Stake[G.GAME.stake].key == "blue" then
return true
end
end
end
and it works without the part where I check the stake, but doesn't if I include the stake check.
it's called, it just returns immediately
i did a thing in bibliography to allow specific unlocks in seeded runs, mainly because the unlock method i picked was "type a specific seed", terraria style
specifically i did this thing https://github.com/wingedcatgirl/Bibliography/blob/main/lib/hooks.lua#L146
nvm i'm dumb
Also uh this doesn't work at all
SMODS.Voucher {
key = 'developer_console',
atlas = 'vouchers',
dependencies = {
items = {
"set_cry_tier3",
},
},
pools = { ["Tier3"] = true },
pos = { x = 2, y = 0 },
-- unlocked = false,
requires = { 'v_mannpower_squad_surplus' },
calculate = function(self, card, context)
if context.create_booster_card and context.booster.config.center.group_key == "k_cry_program_pack" and pseudorandom("developer_console") > 0.8 then
return { booster_create_flags = { set = 'Mannpower', key_append = 'ar2' } }
end
end
}
ok, i have string A which is a hand name and string B which is also a hand name
just from those strings, how can i tell if the hand that A describes, contains B?
like i know that say, if A is a three of a kind and B is a high card, A would absolutely contain B
You would have to create every card in A's example, put those in a table, then you would check if next(select(3, G.FUNCS.get_poker_hand_info(hand))[B])
jokers!
maybe i'm overthinking what i'm trying to do here, then
basically - i want to know if the hand that was played or discarded here contains the most played hand and if it contains the least played hand
yea you don't need to do what somethingcom gave you
just do G.FUNCS.get_poker_hand_info(context.full_hand)["High Card"] (to see if it contains high card)
i think just wrapping that in next(...) should be enough to properly check
this will work both in the case of context.before and context.pre_discard?
yes, both of those contexts have context.full_hand
oh, it does have context.full_hand
ok
doesn't get_poker_hand_info return like 5 things though
well yea
that's why you index it with the ["High Card"] at the end to get just the hand you're looking for, and then wrap it in next(...) to check if any of that specific hand actually exists in the original hand
oh, i was substituting high card with my variable
bad argument to next 
yea sorry i dunno how exactly get_poker_hand_info works off the top of my head
use debugplus to interact with the function and see how it's all laid out
next(select(3, G.FUNCS.get_poker_hand_info(context.full_hand))[hand])
help
could you elaborate on it not working? like it doesn't show up in G.P_CENTERS?
The mannpower cards don't show up in the code packs
well based on the pseudorandom("developer_console") > 0.8, it's a 20% chance, right? if you're making sure it works, have you tried without that check
might just be bad luck
although i'm not entirely sure that's how that works 
nope
What version of SMODS do you have?
does updating to current release work
Kinda???
good or not?
You need to add skip_materialize = true to the table.
Kerry has weird interactions with cryptid mod but idc 🔥
Rework card destroys a joker but doesnt trigger kerry destruction
maybe for the best
I have elected to change the global color values of the High Contrast mode hex codes
works great, though I'm sure it's not a very versatile solution
Is there a way to increase the odds that your modded jokers appear in the shop?
thinking about making a joker along that line, so I dont want it to be like 100% lol
enable object weights
yall 😭
anyone know why this doesn't work?
if context.joker_main then return { xmult = card.ability.extra.Xmult } end
thank you
is there a way to check if a skipped blind was a small blind, specifically?
G.GAME.blind:get_type() im assuming?
Interesting character.
No, it would be G.GAME.blind_on_deck
how do i do animatied jokers?
ik i put the sprites on the sheet but how do i code it
atlas_table = 'ANIMATION_ATLAS', -- set atlas to be animated
frames = 10, -- how many frames
fps = 4 -- optional, how fast it animates
when using SMODS.Atlas to define an atlas.
In theory, you can point to same file, but keep in mind that animated atlases will ignore the x value of pos.
pos = { x = 0, y = 0 },
atlas_table = 'draugratlas',
frames = 10,
fps = 2,
wait
i think i forgot teh .png
nope nvm it just isnt working
you put your key as atlas_table

SMODS.Atlas({
key = "draugratlas",
path = "draugratlas.png",
px = 71,
py = 95,
atlas_table = "ANIMATION_ATLAS"
})
frames is in the top one
pos = { x = 0, y = 0 },
atlas_table = 'draugratlas',
frames = 10,
fps = 2,
im definately doing something wrong but i cant figure out what
SMODS.Atlas({key = "TOGAJokersUpdate", path = "togajokerupdate.png", px = 71, py = 95, atlas_table = 'ANIMATION_ATLAS', frames = 10, fps = 4})
Something like such.
SMODS.Atlas({
key = "draugratlas",
path = "draugratlas.png",
px = 71,
py = 95,
atlas_table = "ANIMATION_ATLAS",
frames = 10,
fps = 2,
})
pos = { x = 0, y = 0 },
atlas_table = 'draugratlas',
It's just atlas for use in SMODS.Joker.
is the last played hand type stored somewhere or do I have to track it
SMODS.last_hand.scoring_name?
not sure that exists when you need it to
that should work, thx
is there a way i can make an enhancement cause a card to never score? like the opposite of stone?
never_scores = true iirc
does anyone here have any idea of what's going on here (there should be 8 sprites arranged in a 4x2 grid)
the sprites are all handled by an extension of Moveable
are the sprites missing or just empty?
missing
too little info then
what other info would i need
show the code
hold on
vs code gave the ui function wonky indentation when i copypasted it 😭
honestly i'm not even sure how to go about finding where the error even is
can't look at all of this on mobile, but one thing that seems problematic is self.children.sprite.states = self.states
it makes both states tables the same table
i will note the sprite that does appear also flies in from the top of the screen
ah
so i might want to do copy_table(self.states)?
mhm
didn't fix the collection issue but good to know anyway
yeah I wasn't confident that's the issue. just the first thing I noticed
kinda wondering if it might be something here
idk if the moveable being local is fucking things up
i noticed the blind moveable gets added to G.I.CARD
but doing that doesn't seem to help
i had previously used SMODS.create_sprite for this which worked fine
that's because it's a card and not a custom Moveable extension
Blind is not an instance of Card???
oh I thought you meant the collection blinds
which are made cards by smods
where is this code
oh it's in src/overrides 😭
Yo guys!!! I need help!! Yall know how can I change normal binds (small, medium) to random boss binds? I wanna do a joker inverse to the luchador kinda thing where when you sell the joker the next ante is just boss binds for x2 money. Help will be super appreciated! Thxs!!
With a lot of patching
In this episode, I teach you how to create Lovely patches and hook functions
Repo: https://github.com/the-Astra/ExampleMod/tree/Episode-3
Tools:
- toomanyjokers: https://github.com/cg-223/toomanyjokers
Resources:
- SMODS wiki: https://github.com/Steamodded/smods/wiki
- VanillaRemade: https://github.com/nh6574/VanillaRemade
painfully
balatros blind code is incredibly hard coded
the most important file to mess with is gonna be functions/state_events.lua
That dictates every 3 rounds a random boss blind?
that file handles changing game states, which includes generating the boss blinds, and switching the current blind
Alright so is just messing with that for the current ante?
theres also some jank with ante changes
since the game is hardcoded somewhere to always reset blinds and increase ante after a boss
There’s also a load of save stuff you need to account for
do deck backs have draw functions like jokers, or some equivalent? trying to apply a shader to one
how do i get started in modding
not really, the deck "sprite" is actually literally just a playing card from the deck that's face down
you'd probably want to use a custom SMODS.DrawStep to draw the shader if it's a playing card that's currently face down
i know Joker Forge isn't exactly actual mod dev but im still very happy with the results
How would I make a joker shrink hand size?
https://github.com/nh6574/VanillaRemade
by checking this and knowing what vanilla content uses a similar system, you can do most simple stuff very easily
thanks
thank you
can you ban things from existing challenges or do mods and challenges just not really work well together?
you can probably take ownership of vanilla challenges
how do you make a boss blind debuff multiple ranks?
because
debuff = { value = '2', '3', '4', '5', '6', '8', '7', '9', '10' },
isn't working
you can't use that debuff shortcut, you'll have to use the blind's calculate function
calculate = function(self, blind, context)
if not blind.disabled then
if context.debuff_card then
local rank = context.debuff_card:get_id() -- context.debuff_card is itself a card object being checked to see if it should be debuffed
if rank == 2 or rank == 3 or ... then -- i'm sure there's a more efficient way to do this but i don't feel like figuring it out lol
return { debuff = true }
end
end
end
end
Do score, xscore, blind_size, and xblind_size returns just not work when called by blinds???
how would i remove a joker from the judgement pool?
like
using the in_pool in the SMODS.Joker
And also this
And here's the calculate function for each, which just don't do anything for some fucking reason help
wait I used my reflect card on a 4 and it didn't apply the xblindsize
I think it might just not work at all for some reason????
in the latest version of smods
You can't return effects in events.
that doesn't explain regen not working
I think they may have just broken the effects too? My Reflect consumable was working perfectly fine before I updated and now it just does nothing
Even after pulling it out it doesn't work
nevermind
Code?
It's still in an event.
that doesn't explain why regen doesn't work though
Tried to fix it and now it softlocks
Events softlock when they don't return true. That's happening in the event that used to hold the return score value. When it was there, it was close enough to return true as far as Balatro's event code was concerned.
I put the normal return true back where I had moved the return score from and IT STILL DOESN'T FUCKING WORK
I think you should use context.before instead of context.press_play here. The issue with your current method is that you only increase your numberofthings in an event, which is ran after your return. If you use context.before instead, you can loop through context.full_hand outside of an event to juice the cards. You can also just use #context.full_hand in your return, instead of manually re-counting the cards in numberofthings.
so then something like this?
calculate = function(self, blind, context)
if not blind.disabled then
if context.before then
for i = 1, #G.play.cards do
G.E_MANAGER:add_event(Event({
func = function()
G.play.cards[i]:juice_up()
return true
end,
}))
numberofthings = numberofthings + 1
delay(0.23)
end
return {
blindsize = math.floor((get_blind_amount(G.GAME.round_resets.ante) * 0.1)) * numberofthings
}
end
end
end
Kinda. It's better to use context.full_hand in place of G.play.cards. In addition, #context.full_hand/#G.play.cards is already the number of all played cards, so you don't need your own count of numberofthings at all.
As-is, you'll crash just because you don't set any starting amount for numberofthings before increasing it, it's easier and more efficient to just do without entirely.
oh i forgot to finish getting rid of that lol
so just
calculate = function(self, blind, context)
if not blind.disabled then
if context.before then
for i = 1, #G.play.cards do
G.E_MANAGER:add_event(Event({
func = function()
G.play.cards[i]:juice_up()
return true
end,
}))
delay(0.23)
end
return {
blindsize = math.floor((get_blind_amount(G.GAME.round_resets.ante) * 0.1)) * #G.play.cards
}
end
end
end
okay cool it does
now just to figure out why Regeneration isn't working
SMODS.Blind {
key = "regen",
atlas = 'mannpowerblind',
pos = {
y = 5
},
boss = { min = 4 },
config = {
blind_mod = 0.25,
},
loc_vars = function(self, info_queue, card)
return {
vars = {
number_format(lenient_bignum((get_blind_amount(G.GAME.round_resets.ante) * 0.25))),
},
}
end,
collection_loc_vars = function(self)
return {
vars = {
"(" .. number_format(0.25) .. "X base)",
},
}
end,
boss_colour = HEX("ED712B"),
calculate = function(self, blind, context)
if not blind.disabled then
if context.after then
return {
score = get_blind_amount(G.GAME.round_resets.ante) * -0.25,
}
end
if G.GAME.chips < 0 then
return {
score = G.GAME.chips * -1,
}
end
end
end
}
because by all means it should work
It sends the message but doesn't actually lower the score
When happens if you remove the if G.GAME.chips < 0 then half of the calculate function?
Because it's outside of a specific context, it'll be repeatedly and sporadically checked, and may immediately override the initial score decrease. I don't know for sure if it's the issue (as it sounds like the score just isn't decreasing at all from the context.after part), but it's likely an issue.
SMODS.ObjectType({
object_type = "ObjectType",
key = "goob",
weight = 10,
default = "j_goob_Petyr",
get_weight = function(self)
if next(SMODS.find_card("j_goob_Boblin")) then
return self.weight * 1.25
elseif not next(SMODS.find_card("j_goob_Boblin")) then
return self.weight
end
end,
cards = {}
})
this would be painstaking to debug, but I did correctly make it so if I have joker "j_goob_Boblin", "goob" type objects are 25% more likely to show up right?
the object type works correctly I already know that from another joker I just added weight and get_weight
G.GAME.banned_keys.item_key_here = true
I did that but it's still not working properly???
I guess to debug it I could just make the number 9000% lol
tho I'd probably wanna put the increased weight clause in calculate
tho, guess theres no point really
aside from that one cryptid card maybe? im not sure how that interacts with debuffed cards
hmm
I mean it would be funny if I dont know this is working
Boblin IS supposed to be a meme, after all
someone please help ive tried abunch of stuff and im trying to make a deck that only lets legendary jokers spawn like in rarrans video i cant figure it out SMODS.Back{ key = 'LG', atlas = 'LG', pos = {x = 0, y = 0}, config = { }, apply = function(self) end } https://youtu.be/R_uCfxzwSK0?si=XjU2X-E1uPz1-gfM
Subscribe and Like the video :)
Checkout: @BeanBalatro
You should watch me live on Twitch:
https://twitch.tv/rarran
▶Discord: https://discord.gg/AYThPma
▶Twitter: https://twitter.com/RarranHS
▶TikTok: https://www.tiktok.com/@ytnarrar
Edited By: Wolti
Thumbnail By: Rarran
#Hearthstone #Rarran #balatro
local oldgetcurrentpool = get_current_pool
function get_current_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and G.GAME.selected_back and G.GAME.selected_back.effect.center.key == 'b_modprefix_key' then
_legendary = true
end
return oldgetcurrentpool(_type, _rarity, _legendary, _append)
end
something did I do my implementation right or no
ill try it out
do i just put that in the apply
?
SMODS.ObjectTypes don't have get_weight
ah
No, you would put it outside of the SMODS.Back definition.
Yes.
that didnt work
but it does have a weight value?
hmm
@daring fern i tried that could and nothing happened
Code?
yeah it didnt work\
The easy implementation would just be make every joker have a weight and have a get_weight for boblin checking
eh fuck it im lazy
and also, its boblin
Stupid implementations make sense
hmm, dont know if that worked
:/
gonna implement this a little differently then just affecting weight
Yes, I need to see the code to see what the problem is.
Like this is just weird because sometimes it lowers the score a bit but not always and it doesn't do the right amount.
So I'm trying to make it so every 2 gives +14 mult, but it wont work. doesn't crash, just wont work.
context.repetition is for calculating retriggers
Not the main issue, but this will help: Use G.GAME.blind.chips to get the actual score requirement of the blind. The function get_blind_amount(ante) only gets the base requirement, AKA the small blind requirement.
Oh, wait, the actual issue is this: context.after is after all scoring is completed, and disallows any further scoring. You want context.final_scoring_step instead.
thanks
y'know this is way too annoying so im just gonna give boblin one of the other effects I was thinking about
chat any ideas why pseudoshuffle is failing?
card.ability.extra.unrevealedindex is just a list of the number 1 to 45
Cool.
Now the only thing left to fix is the Reflect consumable that broke when I updated SMODS for some reason (it gives a playing card X0.95 Blind Size)
And, moreover, worked completely fine before updating
1606b makes it so card.ability.perma_x_blind_size starts at 0 instead of 1
Oh.
So then I just update it to
for i = 1, #G.hand.highlighted do
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
func = function()
local _card = G.hand.cards[i]
if G.hand.highlighted[i].ability.perma_x_blind_size == 0 then
G.hand.highlighted[i].ability.perma_x_blind_size = card.ability.extra
else
G.hand.highlighted[i].ability.perma_x_blind_size = (G.hand.highlighted[i].ability.perma_x_blind_size or 1) *
card.ability.extra
end
return true
end
}))
end
?
No, it would be G.hand.highlighted[i].ability.perma_x_blind_size = ((G.hand.highlighted[i].ability.perma_x_blind_size+1)*card.ability.extra)-1
Wouldn't that cause a starting value of 0 to become -0.05x Blind size, thus instantly making the blind size negative when played?
(0 + 1)*0.95 - 1
after implementing that joker I have a better lengthier idea that shouldnt be undoable 🔥
however, im coded out for today
No, because it adds 1
It then subtracts 1
(blind_size + 1)*0.95 - 1
(0 + 1)*0.95 - 1
1*0.95 - 1
0.95 - 1
-0.05
No, I mean Card:get_bonus_x_blind_size adds 1 to card.ability.perma_x_blind_size
Oh
That's fucking weird
I assume it's just to keep shit like Cryptid's Glitched edition from affecting it
No, it's to keep it consistent with the other perma-bonuses.
bump?
It's because pseudoshuffle doesn't check if list[1] is a table before checking if list[1].sort_id exists.
ok then i dont understand how its implemented
like is list in this case not just the input list? if so why would it check that the first element is a table
it worked perfectly fine shuffling a list of strings, so why does it fail when it's a list of numbers?
Because strings can be indexed, but numbers can't.
how to i check for skipping the small blind specifically? like i want it to trigger when skipping small blind but not big blind
i know theres a context for skipping blind and there's a global var for skips that throwback uses
where should my localization entry be for providing a key to the saved return in game_over
if G.GAME.blind_on_deck == 'Big'
so like if i put that in the skip check it'd mean you skipped from small to big?
and if you skipped big G.GAME.blind_on_deck would return boss instead?
is that how it works?
is it possible to set the scalar_value of an SMODS.scale_card call to a local variable, instead of pulling it from a table?
just set scalar_table to a local variable
like
scalar_table = {val},
scalar_value = 1
scalar_table = {points},
scalar_value = 1
so would this tell it to use the first value from that table?
yeah
alright
Yes, but you should set operation as a function instead.
why?
i just need to use a value thats not in a table as the scalar_value
what does .getting_sliced mean?
i was looking at something in vanillaRemade and it says that you should set it to true for cards that are being destroyed
thats specifically for Ceremonial Dagger i think
basically you're just giving the card a flag that you can check for later
It makes it so the card cannot calculate in almost every context.
i'm sure context.joker_type_destroyed bypasses that
I assume it's used for the dagger/madness?
it's for all joker destruction effects im pretty sure
that'd include ankh and hex for example, but yeah dagger and madness
bump
G.localization.misc.dictionary
Is there a way to modify the bonus an enhanced card gives? For instance i want to make a joker that makes bonus cards score x1.5 chips instead of +30 chips
take ownership of Bonus
SMODS.Enhancement:take_ownership("bonus", {
config = {bonus = 30, xchips = 1.5},
update = function(self, card, dt)
if next(SMODS.find_card("j_modprefix_key")) then
if not card.ability.old_bonus then
card.ability.old_bonus = card.ability.bonus
end
card.ability.bonus = 0
elseif card.ability.old_bonus then
card.ability.bonus = card.ability.old_bonus
card.ability.old_bonus = nil
end
end,
calculate = function(self, card, context)
if context.main_scoring and context.cardarea == G.play then
if next(SMODS.find_card("j_modprefix_key")) then
return {
xchips = card.ability.xchips,
}
end
end
end,
})
do you need explanations for the snippet
the only question i have for the moment is if put the snippet inside SMODS.Joker{} or elsewhere
put it anywhere but inside another SMODS.GameObject
it's fully complete, there's no need to modify it in any way
right, tysm
it's Cryptid-proof
meaning any value manipulation to card.ability.bonus is temporarily stored as card.ability.old_bonus
Won't old bonus immediately be set to 0 after 2 frames of having the joker
i was just testing that lol
alr, fixed
previously scored bonus dont score the old one
man, that slipped under the radar because I didn't test it myself
wait

man, this sucks
I should be more careful when updating something every frame
now it should work
thx
wdym
like in general
or do you have a specific target in mind
Setting them all to the number 3
for key, value in pairs(card.ability.extra) do
if type(value) == "number" then
card.ability.extra[key] = 3
end
end
note this will only affected modded cards iirc
vanilla stores their stuff in card.ability
I also used to do that.
I could iterate through both?
also the number check isn't explicitly needed but will stop crashes caused by setting stuff like suits to 3
better to hardcode vanilla
iirc all vanilla jokers are defined in game.lua
question. Does anyone know how to take a high quality picture and resize to fit the tarot cards? I'm asking for a personal mod I'm making for myself
got an image size of 800X1582
set the atlas your file dimensions
71x95 is recommended for stylistic consistency, along with being at the correct aspect ratio, but anything works
I have a card that's 142x190 in mine
so theortically could half the size of my current file work?
or something like 200px wide?
anything positive will work
OK, thank you I've been struggling with this for a while
the way the game works (from what I've observed I havent actually looked into this)
is that it draws the entire atlas on the screen, scales it down based on the size you told it the cards where, and the crops out the excess
good to know, thought i had to resize those large images into tiny proportions
how do I make a variable for G.Game, im trying to make a michel/cavendish relationship where it is saved whether or not a joker got destroyed



for inconsistencies