#đ»ă»modding-dev
1 messages · Page 626 of 1
in the second if condition you should add and context.individual if your goal is to repeat EVERY card by card.ability.extra.repetitions
then what are you using to repeat?
it generates the same stone cards with internal ranks and suits on every seed
a joker i created
should i put the key in the joker label
yes.
that certainly wasn't the case for me
Oh I know why
CardSleeves moves the seeding stuff to happen earlier
I missed that last night
can we just make that an smods pr
and save the sanity of like, literally every developer here
it's alr lol
nvm
lol
What does this code do
if you're referring to that screenshot, it sets up the run seeding before Back:apply_to_run is called
# stupid implementation because steamodded didn't accept my PR (could possibly rewrite using events instead)
# Move seed generation to be before Back:apply and Stake.modifiers() so that both methods can use the seed and true pseudorandom numbers
# Needs to have later priority than Cryptid
# Game:start_run (both patches)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''
if not saveTable then
if args.seed then self.GAME.seeded = true end
self.GAME.pseudorandom.seed = args.seed or (not (G.SETTINGS.tutorial_complete or G.SETTINGS.tutorial_progress.completed_parts['big_blind']) and "TUTORIAL") or generate_starting_seed()
end
for k, v in pairs(self.GAME.pseudorandom) do if v == 0 then self.GAME.pseudorandom[k] = pseudohash(k..self.GAME.pseudorandom.seed) end end
self.GAME.pseudorandom.hashed_seed = pseudohash(self.GAME.pseudorandom.seed)
'''
match_indent = true
position = "at"
payload = '''
-- moved this code to earlier in the function (by CardSleeves)
--[[
if not saveTable then
if args.seed then self.GAME.seeded = true end
self.GAME.pseudorandom.seed = args.seed or (not (G.SETTINGS.tutorial_complete or G.SETTINGS.tutorial_progress.completed_parts['big_blind']) and "TUTORIAL") or generate_starting_seed()
end
for k, v in pairs(self.GAME.pseudorandom) do if v == 0 then self.GAME.pseudorandom[k] = pseudohash(k..self.GAME.pseudorandom.seed) end end
self.GAME.pseudorandom.hashed_seed = pseudohash(self.GAME.pseudorandom.seed)
--]]
'''
I donât see why that would have been rejected
Iâll have to find the original PR and see
still doesnt
I donât see why we canât move the seeding before these functions are called, but the playing card issue remains the case
Balatro has a way of adding extra cards to the deck already if that's what you meant
it's just that apply_to_run currently can't use seeding before it happens
No I mean aures comment about when they are created
forgot the second part of this (have to make separate post since char limit)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''self.GAME.selected_back_key = selected_back'''
match_indent = true
position = "after"
payload = '''
if not saveTable then
if args.seed then self.GAME.seeded = true end
self.GAME.pseudorandom.seed = args.seed or (not (G.SETTINGS.tutorial_complete or G.SETTINGS.tutorial_progress.completed_parts["big_blind"]) and "TUTORIAL") or generate_starting_seed()
end
for k, v in pairs(self.GAME.pseudorandom) do if v == 0 then self.GAME.pseudorandom[k] = pseudohash(k..self.GAME.pseudorandom.seed) end end
self.GAME.pseudorandom.hashed_seed = pseudohash(self.GAME.pseudorandom.seed)
'''
@wooden nexus sorry for these constant pings, just another quick question, are you intending for your mod to be Steamodded-dependent or not?
aight, lemme try it
oh
this question tho
it will have smods compat yes
I mean it would be relatively easy to allow for decks to directly modify/filter the card_protos, it'd just be annoying to work with those card control tables
gotcha
local blind_are_seeing = Game.update_blind_select
function Game:update_blind_select()
local ret = blind_are_seeing(self)
for _, fusion in pairs(Giga.POOLS.fusion_jokers) do
local mats = G.P_CENTERS[fusion].giga_data.merge_materials
local required = {}
for _, mat in ipairs(mats) do
required[mat] = (required[mat] or 0) + 1
end
local has_all = true
for mat, count_needed in pairs(required) do
local count_have = count_jokers_in_inventory(mat)
if count_have < count_needed then
has_all = false
break
end
end
if has_all then
SMODS.add_card({ key = G.P_CENTERS[fusion].center_key, edition = 'e_negative' })
for mat, need in pairs(required) do
local to_destroy = need
for _, c in ipairs(G.jokers.cards) do
if to_destroy <= 0 then break end
if c.config.center_key == mat then
G.E_MANAGER:add_event(Event({
blocking = true,
func = function()
SMODS.destroy_cards(c)
return true
end
}))
to_destroy = to_destroy - 1
end
end
end
end
end
return ret
end
I am getting this crash
line 55 is :
local mats = G.P_CENTERS[fusion].giga_data.merge_materials
either you have a wrong key in that pool, or not every center in the pool has giga_data
Giga.POOLS = {
r_food = {
_calculate = function()
Giga.POOLS.r_food = {_calculate = Giga.POOLS.r_food._calculate}
for _, c in pairs(G.P_CENTERS) do
if string.sub(c.key, 1, 2) == 'c_' and c.giga_data and c.giga_data.r_food then
table.insert(Giga.POOLS.r_food, c.key)
end
end
end
},
fusion_jokers = {
_calculate = function()
Giga.POOLS.fusion_jokers = {_calculate = Giga.POOLS.fusion_jokers._calculate}
for _, c in pairs(G.P_CENTERS) do
if string.sub(c.key, 1, 2) == 'j_' and c.giga_data and c.giga_data.merge_materials and #c.giga_data.merge_materials >= 2 then
table.insert(Giga.POOLS.fusion_jokers, c.key)
end
end
end
}
}
-- INITIALISATION --
function init_pools()
for _, pool in pairs(Giga.POOLS) do
pool._calculate()
end
end
I add my joker in my pool like that
SMODS.Joker{ --MOC
key = 'moc',
atlas = 'secret3',
giga_data = {
merge_materials = {
'j_giga_blackLusterSoldier',
'j_giga_darkMagician'
}
},
pos = {x = 1, y = 0},
soul_pos = {x = 0, y = 0},
cost = 35,
...
and my joker are like that
@wooden nexus
# function Game:start_run
# Config property "stone_total"
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = """
if self.GAME.starting_params.extra_cards then
for k, v in pairs(self.GAME.starting_params.extra_cards) do
card_protos[#card_protos+1] = v
end
end
"""
position = "before"
payload = """
if self.GAME.selected_back.effect.config.stone_total then
for i = 1, self.GAME.selected_back.effect.config.stone_total do
local suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('stone_total_suit'))
local rank = pseudorandom_element({
'2', '3', '4', '5', '6', '7',
'8', '9', 'T', 'J', 'Q', 'K', 'A'
}, pseudoseed('stone_total_rank'))
card_protos[#card_protos+1] = {
s = suit,
r = rank,
e = 'm_stone',
}
end
end
"""
match_indent = true
and then the Back object just needs config = {stone_total = 13}
aight I'll try it, thanks
this time the cards are random per seed
I assume the key that is causing issues is _calculate
Yeah that's what this crash issue
but now if I have the materials it crash
when doing add_card use G.P_CENTERS[fusion].key instead of center_key
oh shoot Im dumb
not all but one and maybe some others if they're uneven enough.
hell yeah I forgot a return true
oh no its not that
Its generating infinitely
I think its because of the function I have hook
which function should I use
try doing all that only if not G.STATE_COMPLETE then
and before calling the original function
That said, why couldn't you have used the global mod calculate
it sounded like a better option to me
https://github.com/Steamodded/smods/wiki/The-Mod-Object#modcalculateself-table---table-boolean this is all there is about it
Ok I'll try that
Welp 3 hours into the planning phase of my first mod and I have 34 Joker concepts and 18 consumable concepts. Now I just need to dive into coding and figure out how to make my vision a reality lol
hell yeah dude
Oh you know what, I have a big question. So I copied and unzipped the balatro source code into a seperate folder. Any changes I make to this code won't affect my main game, right??
Before I start typing stuff in đ€Ł
@normal crest don't know if you got my response but just in case.
I know I can always reinstall from Steam should my game get corrupted or I break something, but I have several mods installed and it'd be a pain in the ass to get them back if I had to reinstall
but are they stickers you made yourself
or just any sticker in general
no, modifying that won't change anything
Awesome thanks!
any sticker in general like mostly the chip stickers enternal stickers and more
cause right now I cleared a deck with the jokers I made. but right now once cleared the sticker display is out of bounds.
can you show what it looks like
right now it looks like this:
also seems off since the sprite of this card is like smaller and well yeah.
@normal crest Not sure if there is a way to fix this.
does the game save crashlogs anywhere? getting a stack overflow crash thats definitely an infinite loop of some kind, but the crash also freezes up the crash handler so i cant ctrl+c to copy it
calculate = function(self, card, context)
local enemyroundup = {}
if G.GAME.current_round.hands_played == 0 and context.before then
for k, v in pairs(context.full_hand) do
if not SMODS.in_scoring(v, context.scoring_hand) then
table.insert(enemyroundup, v)
print("added card")
end
end
end
if #enemyroundup > 0 and not card.ability.extra.target then
card.ability.extra.target = pseudorandom_element(enemyroundup, "nflame_susie")
print("new target")
end
if context.destroy_card and context.destroy_card == card.ability.extra.target then
card.ability.extra.target = nil
return { remove = true }
end
end``` anyone know why this code is causing a stack overflow?
Mods/lovely/log
the error log points to the copy_table function in misc_functions
You can't put cards in other cards.
OH LMAO
TWO MODSâS HOOKS ARE CALLING EACH OTHER OVER AND OVER IN AN INFINITE LOOP
thats uh
bad
is there any way to get the total number of chips a card would give (ie chip value + bonus chips)
card:get_chip_bonus()
would that give the total number?
Yes.
ok good
SMODS.Font {
key = <string>,
path = <file name>,
render_scale = G.TILESIZE*10 --[[number]],
TEXT_HEIGHT_SCALE = 0.83 --[[number]],
TEXT_OFFSET = { x = 10 --[[number]], y = -20 --[[number]] },
FONTSCALE = 0.1 --[[number]],
squish = 1 --[[number]],
DESCSCALE = 1 --[[number]]
}
You'll have to experiment with the numbers because idk what they do xd; afterwards you can use these fonts in localization via {f:<mod prefix>_<font key>}
Guys I mentioned earlier that I was looking to see if there was any kind of visual modding option for Balatro and I think I found one by accident, called Joker Forge? It's super helpful and has worked for me so far while making a couple Jokers. It's not perfect, and doesn't have all effects in it, but maybe it could help someone else out who is more visually stimulated like myself. Has anyone used this tool before?
while i donât recommend using JF for more advanced stuff,
there is a thread made for this tool
https://discord.com/channels/1116389027176787968/1386843228330004611
i have used jf in the past and itâs great for starting off modding
Hell yes, thank you! Still super new to this stuff, figuring things out.
though traditional coding will surpass jf by a longshot, so take a shot at that if you need to
let me get the smods wiki
how would i move a card from one area to another smoothly
like moving a card from the play back into your hand without it going back into the deck and being redrawn
Thx you were right it's working like knife in butter (its from a french expression)
trying to create a joker that does a death type effect at end of round, I think I'm misunderstanding how copy_card works, been looking at vrm death to no success
if self.ability.name == 'Photograph' then
local first_face = nil
for i = 1, #context.scoring_hand do
if context.scoring_hand[i]:is_face() then first_face = context.scoring_hand[i]; break end
end
if context.other_card == first_face then
return {
x_mult = self.ability.extra,
colour = G.C.RED,
card = self
}
end
end
if self.ability.name == 'test' then
local first_face = nil
for i = 1, #context.scoring_hand do
if context.scoring_hand[i]:is_face() then first_face = context.scoring_hand[i]; break end
end
if context.other_card == first_face then
return {
x_mult = self.ability.extra,
colour = G.C.RED,
card = self
}
end
end```
is this right? im copying photographs code just to test.
(unless youre making a mod with only lovely then you kinda have to i guess)
I can't find it anywhere, what's the name for High Card in the code?
the same
the keys for all the vanilla hands are the same as the english localized name
like 'High Card'?
yes
thx
they're trying to mod in the gamepass version
by just editing the source code directly
(and with no lua knowledge)
oh
does that even work
or does the source code just get restored when starting the game
i know steam loves reverting tampered files in some games
it seemed to work for them yeah
Is there a specific context in which the ante increases?
if context.ante_change and context.ante_change > 0
Thanks!
bump
this is suposed to increase the rank of the card when you play a High Card, but it isn't working, does anybody know why?
there's no context.other_card in context.before
use context.scoring_hand[1] to get the first and only card in the played hand
scoring hand
not full hand
my bad
Does anyone know how to level up all poker hands containing a pair? or how check if poker hands (not current) contain a pair
currently performing UI witchcraft
all UI work is witchcraft if you ask me
guys im new to modding does anyone know a documentation? (not the installation or the examples mod)
consult the smods wiki
ok
i was already looking at this
what are you looking for thats not here
does anyone know of a way to change the default scoring operator? i wanna make a joker that levels it up from an times mult operator to an exponational one
Also check out https://github.com/nh6574/VanillaRemade/wiki
how does loc_vars work
does this also work for like exponential?
Yes, but it would be exponent instead of add
you are a life saver!
interesting that Scoring_Calculations don't seem to be documented anywhere
yeah that is why i came here
how do i add variables
cus i straight up couldnt find it
sry i thought that had to do smt with variables i just wanna know how to add variables
It does say how to add variables; but here's the syntax for that:
loc_vars = function(self, info_queue, card)
return {
vars = {
value1,
value2,
-- etc.
}
}
end
On the loc_txt or localization file, your description should have #1#, #2#, etc., which the values in the vars table will replace correspondingly
what localization file
Theyâre âdocumentedâ in the discussion post that came out with the update it was shipped with
i only use one file
Itâs not ideal tho
does context.remove_playing_cards trigger on joker destruction?
You should probably read this page https://github.com/Steamodded/smods/wiki/Localization
Oh, so they are
they could probably be pasted directly from that discussion post into the actual docs
how do i get a list of the chosen cards when using a tarot card
how do you create a duplicate of a card
local copy = copy_card(card)
card.area:emplace(copy)
copy:add_to_deck()
thx
do you have a link to it
i wanna see if there are more of them
thank you!
hey what args type and variables would i use to check the amount of discovered spectral cards
its not working, the deck view doesnt contain the new cards
local function better_copy_card(card, new_card, area)
if not card then return nil end
local area = area or (new_card and new_card.area) or card.area or G.jokers
local cardwasindeck = new_card and new_card.added_to_deck or nil
local copy = copy_card(card, new_card)
if new_card and cardwasindeck then copy:remove_from_deck() end
if card.playing_card then
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
copy.playing_card = G.playing_card
G.deck.config.card_limit = G.deck.config.card_limit + 1
table.insert(G.playing_cards, copy)
end
if (new_card and cardwasindeck) or not new_card then copy:add_to_deck() end
if not new_card then area:emplace(copy) end
return copy
end
local copy = better_copy_card(card)
when updated correctly it should be the number of cards ever added to the deck iirc
I am having trouble defining new poker hands. Looking at vanilla remade helps when combining parts of other hands, but it isn't the clearest on creating new ones. Is there a good guide out there that explains the process?
no sadly
i would recommend looking at other mods
but its basically just making lists of cards
joyous spring's got a couple unique ones for example
Guys I need help with my coding, I don't know what I did wrong but the game crashes on launch and tells me there is an error on line 24 of my custom consumable. Can anyone figure out why it doesn't work?
dont look at highest priestess though its got its own hand type registry system it wont be helpful, thoug
theres also cardsauce which has a few...
@oblique lotus
so yeah just look at what other mods do, it really depends on how you want your hand to be structured
It says that line 24 should have an "end" but like, it does?? On line 54, doesn't that close the loop??
isnt that closing the for loop? you need an end for the function too
Lmao I think youre right, I think my eyes are tired
you cant have code after a return and returning in use doesnt do anything
yes
Ohhhh is it the return that's making it not work then??
Omg it was the "return"!
It's fixed now, thank you!!
badge_colour = SMODS.Gradients.modprefix_key
draw_card
â
Anyway time to casually drop a banger feature: full palette customization
hey, that's pretty cool
Definitely going in Arrow 1.1
is there any easy way to reset the player's deck (of cards) to the default one, or should i just manually destroy each card and add the normal ones back
is it possible to use the retrigger_joker optional feature on editions and make editions retrigger jokers?
this is probably wrong but i want this edition to retrigger cards with the edition or jokers with it
if ((context.repetition and context.cardarea == G.play) or context.retrigger_joker_check) and context.other_card == card
ill try that
it repeats cards that dont have the effect but kw ill keep it as a bonus buff
can config store anything
im not storing cards
im storing the ranks of cards
can config store anything excluding cylic tables
and functions
oh my fucking god you are such a smartass
when the replies get deleted and you look schizophrenic
crazy
Is there a way to color poker hand names in run info? Tried to do it through the localization file with no luck.
Yes, you would patch create_UIBox_current_hand_row
Bump
thanks
You mean you want to level up all existing poker hands that if they were played they would contain a pair?
Yes
Like level up pair, two pair three of kind, full house, , four of a kind, five of kind, flush house, flush five and every balatro modded poker hand with pair
Im messing around with the sorce code and was wondering why this isnt working.
j_test= {order = 151, unlocked = true, discovered = true, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Test", pos = {x=0,y=9}, set = "Joker",effect = 'Hand Size Mult', cost_mult = 1.0, config = {extra = {mult = 20, size = 3}}},
&
elseif self.ability.name == 'Test' then loc_vars = {self.ability.extra.mult, self.ability.extra.size}
if self.ability.name == 'Test' and #context.full_hand <= self.ability.extra.size then
return {
message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult}},
mult_mod = self.ability.extra.mult
}
end
im just trying to get somthing to work so im copying the half jokers code
local pokerhands = {}
for k, v in pairs(G.GAME.hands) do
local hand = {}
for kk, vv in pairs(v.example) do
local fakecard = {get_id = function() return SMODS.Ranks[G.P_CARDS[vv[1]].value].id end}
table.insert(hand, fakecard)
end
if next(get_X_same(2, hand, true)) then table.insert(pokerhands, k) end
end
for k, v in pairs(pokerhands) do
SMODS.smart_level_up_hand(card, v)
end
I'll check later, since I don't have access to Balatro right now, but huge thanks!!
Apologies for the ping. I found the line in the source code. While it would be easy enough to change the color of all the hands, I want to color a specific hand. Do you have any advice on how I could do that?
Yes, handname is the key.
bump
Sorry, last question for tonight. Is there a way to tell if you are highlighting a specific Joker?
@daring fern can you help me with something
You mean highlighting a specific card or highlighting a joker with a specific key?
for some reason my joker isn't triggering, can you see how (pasting code in soon)
-- setup
if not G.GAME.current_round.MDJ_construction_jokers_ranks and not G.GAME.current_round.MDJ_construction_jokers_temp_ranks and not G.GAME.current_round.MDJ_construction_jokers_displayed_ranks and not G.GAME.current_round.MDJ_construction_jokers_first_hand then
G.GAME.current_round.MDJ_construction_jokers_ranks = {}
G.GAME.current_round.MDJ_construction_jokers_temp_ranks = {}
G.GAME.current_round.MDJ_construction_jokers_displayed_ranks = "None"
G.GAME.current_round.MDJ_construction_jokers_first_hand = true
end
local ranks = G.GAME.current_round.MDJ_construction_jokers_ranks
local ranks2 = G.GAME.current_round.MDJ_construction_jokers_temp_ranks
local rank_shorthands = MyDreamJournal.rank_shorthands
if context.before and not next(ranks) and G.GAME.current_round.MDJ_construction_jokers_displayed_ranks == "None" and next(SMODS.find_card("j_MDJ_constructionjoker")) then
for i = 1, #context.scoring_hand do
local v = context.scoring_hand[i]
local rank = v:get_id()
local rankless_check = SMODS.has_no_rank(v)
if rankless_check then
rank = 1
end
if not ranks[rank] then
ranks[rank] = 0
end
ranks[rank] = ranks[rank]+1
table.insert(ranks2, rank_shorthands[rank])
end
G.GAME.current_round.MDJ_construction_jokers_displayed_ranks = table.concat(ranks2, ", ")
elseif context.before then
G.GAME.current_round.MDJ_construction_jokers_first_hand = false
end
if context.ante_change then
G.GAME.current_round.MDJ_construction_jokers_ranks = {}
G.GAME.current_round.MDJ_construction_jokers_temp_ranks = {}
G.GAME.current_round.MDJ_construction_jokers_displayed_ranks = "None"
G.GAME.current_round.MDJ_construction_jokers_first_hand = true
end
end```
if context.before then
card.ability.extra.hand_matches = true
local hand_ranks = {}
local stored_ranks = G.GAME.current_round.MDJ_construction_jokers_ranks
local first_hand_check = G.GAME.current_round.MDJ_construction_jokers_first_hand
for i = 1, #context.scoring_hand do
local v = context.scoring_hand[i]
local rank = v:get_id()
local rankless_check = SMODS.has_no_rank(v)
if rankless_check then
rank = 1
end
if not hand_ranks[rank] then
hand_ranks[rank] = 0
end
hand_ranks[rank] = hand_ranks[rank]+1
end
for i = 1, 14 do
if hand_ranks[i] ~= stored_ranks[i] then
card.ability.extra.hand_matches = false
end
end
if card.ability.extra.hand_matches and not G.GAME.current_round.MDJ_construction_jokers_first_hand then
card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Increased!", colour = G.C.mult, delay = 0.2})
card.ability.extra.mult = card.ability.extra.mult+card.ability.extra.gain
end
end
if context.joker_main then
return {
xmult = card.ability.extra.mult
}
end
end```
The later
if G.jokers.highlighted[1].config.center.key == 'j_modprefix_key'?
I think that will work. Thanks!
What is the goal?
the trigger should happen when the stored_ranks (a table with holes in it) matches withh hand_ranks(another table with holes within it)
the ranks are stored as their ids (or 1 if its rankless)
Apologies, one more thing, how can I get it where it won't crash if I don't have something selected at that moment?
if G.jokers.highlighted[1]
Thanks
Yes, but what does it do from the players perspective?
im starting to get a feeling that you aren't quite real, but
if card.ability.extra.hand_matches and not G.GAME.current_round.MDJ_construction_jokers_first_hand then
card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Increased!", colour = G.C.mult, delay = 0.2})
card.ability.extra.mult = card.ability.extra.mult+card.ability.extra.gain
end```
No, I mean what does the description say?
?
The description of the joker that shows up when you hover over it.
what would i need to hook (if anything) to check if the final score of played hand does not exceed blind requirements
like
after all other things have calculated when playing a hand
something that would check after context.final_scoring_step ideally
wwhen the video doesn't load
not SMODS.last_hand_oneshot?
that does the check, but i specifically need this check to be ran after context.final_scoring_step happens
so like a context that fires after context.final_scoring_step
...context.after? or do you need this to apply score too
Yes, it doesn't get changed to anything else until the next hand has finished scoring.
im probably overthinking this
I want to increase a certain stat im tracking if played hand does not one shot the blind
and I wanted to ensure that when i check for a one shot that nothing else that happens after can affect the score but that in hindsight it probably is impossible to make such a check
aight imma use context.after and not SMODS.last_hand_oneshot
how do you change the weight of a consumable set? is it just G.P_CENTERS and the key just the key to the respective consumable type?
Does anyone know how to get the price of a booster pack you're currently are in ?
bump
SMODS.OPENED_BOOSTER.cost
thanks
â
why no sprites :(
--| updaing ui
-- Update ui
if G.btr_guard.node then
G.btr_guard.node:remove()
end
G.btr_guard.node = UIBox({
definition = Bitterstuff.guardUpdate(),
config = {type = "br", major = G.ROOM_ATTACH, offset = {x=1,y=0.9}, bond = "Weak", instance_type = "POPUP"}
})
local Uinode = {n=G.UIT.O, config={object = G.btr_guard.node, type = "br"}}
im gonna die
is there any way for a boss to look if the player has any specific joker?
I want a boss that has a ridiculous size unless you have an specific joker, then it would just be a blind without efects
if next(SMODS.find_card('j_modprefix_key'))
okay im gonna need some real good help here, my plan for a joker is to have it so you can pick it up and place it anywhere, what ever is underneath it will be added to a variable.
Ill make it a blueprint type joker btw
Plan: Clone the joker, and put it in no area (does mean position needs to be saved) and somehow make it update the variables of the main joker hide the original joker somehow
tl;dr: joker needs to duplicate and move anywhere, record jokers under it to be blueprinted
PLEASEE someone help
thx!!
Sprite(-500, -500, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0})
why does it not appear
why are you putting -500
that would make the Sprite appear off-screen I believe
question: does the repetition variable also work on jokers
in which file do i add this
any
Check for yourself, majority game engines need minus since to go down on a screen you need to go dow numbers, you start 0,0 / top left
I also tried reversing it anyway
actually you're dead wrong
sure, the origin is at top left, but the y axis points downwards
ok so i may be stupid (and it's probably in the wiki) but how do i change the color of the background (so it's not white)
box_colours in loc_vars
this is also usable with multi-boxes, right?
yes
Hello, i was wandering on how does it work to use files in different folders, like a lib folder, a joker folder etc....... cause i've tried but i keep having crashes
fantasy usually destroys jokers, i plan to make a dreamy joker named saitama that prevents fantasy from destroying jokers, how do i do that?
Good luck modding guys
check if you dont have that joker in the consumable code for the destroying part
TheShowMustContinue = {}
assert(SMODS.load_file("globals.lua"))()
-- Load Jokers
local joker_src = NFS.getDirectoryItems(SMODS.current_mod.path .. "jokers")
for _, file in ipairs(joker_src) do
assert(SMODS.load_file("jokers/" .. file))()
end
--Load Library Files
local files = NFS.getDirectoryItems(SMODS.current_mod.path .. "lib")
for _, file in ipairs(joker_src) do
assert(SMODS.load_file("lib/" .. file))()
end
you are loading everything from joker_src twice
ok so just write "if not SMODS.find_card" on top of the existing code?
ctrl v moment
you need
if not next(SMODS.find_card(...))
since SMODS.find_card at minimum returns an empty table which is not nil
thanks
My best config UI so far 
i've tried to create a new rarity
SMODS.Rarity {
key = "Fantastic",
default_weight = 0.01,
badge_colour = HEX('850058'),
loc_txt = {
name = "Fantastic",
},
get_weight = function(self, weight, object_type)
return weight
end,
}
but i have that error, i don't understand where is the problem, do i have to manually define a pool?
i'm sorry for asking so many questions
send the joker definition?
-- you can have shared helper functions-- exemple from SampleJimbos
function shakecard(self) --visually shake a card
G.E_MANAGER:add_event(Event({
func = function()
self:juice_up(0.5, 0.5)
return true
end
}))
end
SMODS.Atlas({
key = "theshow",
path = "theshow.png",
px = 71,
py = 95,
})
SMODS.Joker{
key = "theshow",
name = "The Show",
config = { extra = { x_mult = 2, x_mult_mod = 1 } },
pos = { x = 0, y = 0 },
rarity = "Fantastic",
cost = 20,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
atlas = 'theshow',
calculate = function(self, card, context)
if context.selling_card and context.card.config.center.key == 'j_ring_master' then
if not context.blueprint then
-- Incrémente correctement
card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.x_mult_mod
return {
card = card,
message = localize('k_upgrade_ex'),
colour = G.C.RED
}
end
end
if not (context.individual or context.repetition) and context.other_joker and context.other_joker.ability.name == "Showman" and self ~= context.other_joker then
shakecard(context.other_joker)
return {
message = localize{type='variable',key='a_xmult',vars={card.ability.extra.x_mult}},
colour = G.C.RED,
x_mult = card.ability.extra.x_mult
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.x_mult }, key = self.key}
end
}
It was working just fine until i change the rarity
yepp, now it work perfectly, thanks a lot!
Hello, I'm new and looking for the Packer tool to create a .pak file. Can anyone help me find it?
what the hell are pak files
Its some zip-adjacent thing
Often used for game files apparently
From a quick google search
I don't know if I got an answer yet but ho exactly does sticker positions work?
yeah but in the context of balatro?
Its just wherever you put them on the sprite
packer tool
Stickers are still 71x95 sprites
what is your goal here
balatro modding doesn't use pak files anywhere
I mean
Making a zip and just renaming it to be a .pak just works apparently
So unless you need a pak file with a specific data structure just do that
editions do not have add_to_deck or remove_from_deck
ope
on_apply and on_remove are probably what you're looking for
goddamn it lsp
will those be called when checking the edition outside a run
eg in collection
not sure, but i assume so
you can always check G.STATE if you want it to not do something in the collection
ok now im having a different problem
if the joker with the edition shows up in shop then it does its effect
basically the idea is to increase some passive stats while you own a joker with that edition
ah shoot
hmm
i could check and see if the card is in G.jokers and if so, apply the effects
but then id need to check for every instance of adding a joker
and so forth
how to not comedy
how would i identify the type of card that an edition is on, aka if the card is a joker or consumeable, it will do something, if its a playing card, do something else?
you can do if card.ability.set == "Joker" or if card.playing_card
cheers
I changed the code a little so that it doesn't give an error, but it just doesn't work now :(
for k, v in pairs(G.GAME.hands) do
if not v.example then return nil end
local hand = {}
for kk, vv in pairs(v.example) do
local fakecard = {get_id = function() return SMODS.Ranks[G.P_CARDS[vv[1]].value].card_key end}
table.insert(hand, fakecard)
print(fakecard)
end
print(hand)
if next(get_X_same(2, hand, true)) then table.insert(pokerhands, k) end
end
for k, v in pairs(pokerhands) do
SMODS.smart_level_up_hand(card, k)
end```
No, it's SMODS.Ranks[G.P_CARDS[vv[1]].value].id not SMODS.Ranks[G.P_CARDS[vv[1]].value].card_key
just crash
What is line 1228 in Mods/lovely/dump/SMODS/_/src/utils.lua?
update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(hand, 'poker_hands'),chips = G.GAME.hands[hand].chips, mult = G.GAME.hands[hand].mult, level=G.GAME.hands[hand].level})
iirc table.insert inserts the element into the table as an array
wait maybe something wrong with for k, v in pairs(pokerhands) do
SMODS.smart_level_up_hand(card, k)
end because if i use print(v) its work
yep
pokerhands should be something like {'Pair', 'Three Of A Kind', âŠ} and not like {Pair = value1, ['Three Of A Kind'] = value2, âŠ}
Change k to v in SMODS.smart_level_up_hand
yes it work huge thanks 
still needing assistance
my plan is eventually to just make it a greyish brown dot, but it doesnt actually appear?
You need to draw it.
how so
sprite:draw_shader('dissolve')
iight
so what would be to happen if i have thousands possibly ten thousand of these dots
how could I save the players pc
Question: Does anyone know where the Planet card's softlock check (as in if a Planet card should appear if you played it's hand or not) is located? I want to hook into it, but can't find it.
Any help would be greatly apperciated
Hey, how do you make a consumable enhance a card to an enhancement?
functions/common_events.lua in the get_current_pool function
Thanks!
Check out vanilla remads's version of the tarot cards. Should give a good idea based on what you are trying to do.
https://github.com/nh6574/VanillaRemade/blob/fb7939cca1b907bad4ee5ba6ad62c608176454a2/src/tarots.lua
I'm too bad at balatro modding, why doesn't it work with flush :(
ok, thanks
why does this happen to my blind
SMODS.Blind {
key = "wordblind",
loc_txt = {
name = "nameblind wip",
text = {"Each hand play a word game", "Losing adds +1X base mult"}
},
mult = 2,
}```
the wiki diesnt say I have to add anything but kye and loc_txt
how do i add steammodded's lsp to vscode (i have the lua extention installed)
vanillaremade wiki explains it
is there a way to hide these extra suits from the deck viewer
(i have made a copy of all 4 suits)
(and i want to hide the originals)
probably, i think theres a lot of mods that add suits which have them hidden from the deck view at first
so the vanilla ones could probably also be hidden in a similar way
Hmmm
paperback or bunco are probably worth looking at at least
in_pool = function(self, args) return not args.initial_deck end
oh cool
hey so uhh my Check_for_unlocks belonging to achievemnts arent working, any help with that
I don't know how to make for flush, but it seems to be working
yeah the wiki is missing that the boss colour is required
great
Trying to change the planet softlock check to use visibility rather than hands played. I don't know why this isn't working as a patch. I get a nil value error. Any advice would be greatly appreciated.
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''if (not v.config.softlock or G.GAME.hands[v.config.hand_type].played > 0) then'''
position = "at"
payload = '''if (not v.config.softlock or G.GAME.hands[v.config.hand_type].visible) then'''
match_indent = true
overide = true```
Log?
can i see the code for 0chill_house_rules_planet
I can do that. Is it fine if I DM it to you?
how would i grab player's interests
force them to play
thanks soulware
yuri
G.GAME.interest_amount i think
ill try
is there somewhere I can find some usefull thing for making animation
like the wiki of steamodded doesnt really help me
wait no wrong one
how would i get the total of the cashout
dunno, its not a variable i dont think
what animation
I mean my event when vard are upgraded are feeling weird since its a new mechanic
i dont know what any of that means
function SMODS.calculate_individual_effect(effect, scored_card, key, amount, from_edition)
if G.jokers and next(SMODS.find_card("j_bd_damocles")) and (key == "mult" or key == "mult_mod" or key == "h_mult") then
if key == "mult_mod" then effect.message = nil end
return ref(effect, scored_card, "xmult", amount, from_edition)
else
return ref(effect, scored_card, key, amount, from_edition)
end
end
is there a reason why this doesnt work anymore
nevermind
Ill try to explain it the right way, and understandable. So in my mod enhancement can be upgraded with a certain consumable so rn its a juice up flip event and its feels weird to have a vanilla animation for this mechanic. So im trying to make a new animation can replace that but everything I find in the wiki of smod isnt what I want to have as the animation . So Im trying to find documentation about advance event, animation or something like that
oh there isn't
there's no much you can document, animations are just moving cards around with different timings
Ask them whatâs their interests
Oh thats sad
hey guys
how do i make a card give no score when played
(asking for enhancement purposes)
thanks heaven
How can I prevent a card from being sold at a given moment? I tried card:set_eternal, but I think that only works for Jokers.
hook Card:can_sell_card
Gotcha
bump 2
the latter
ok
I am trying to define a global table. How would I do that? I know I need G.GAME.[variable_name], but I don't know if it needs to be through a hook or something. Any guidance or good examples would be greatly apperciated.
it has to be during the run, where depends on what you want to do
but you can basically do it anywhere
Gotcha. So, just hook into the function that is the best fit for it and place it there?
that's too vague for me to give a definitive yes but basically
how do i get a joker to the left of another joker + how do i debuff/rebuff a joker
local left_joker
for k, v in pairs(G.jokers.cards) do
if k > 1 and v == card then left_joker = G.jokers.cards[k-1] end
end
``` And `SMODS.debuff_card`
are these both correct or is one wrong?
local enhancement_pool = {}
for _, enhancement in pairs(G.P_CENTER_POOLS.Enhanced) do
if not enhancement.overrides_base_rank then
enhancement_pool[#enhancement_pool + 1] = enhancement
end
end
local cen_pool = {}
for _, enhancement_center in pairs(G.P_CENTER_POOLS["Enhanced"]) do
if not enhancement_center.overrides_base_rank then
cen_pool[#cen_pool + 1] = enhancement_center
end
end
Yes, they do the same thing.
okie thank you
cen_pool == enhancement_pool and enhancement == enhancement_center
No, cen_pool and enhancement_pool are different tables.
I mean like functionally/on paper
Can something advise me I'm doing the right thing or not?? (Is_suit as I remember, it return self.base.suit == suit)
???
also code
SMODS.Joker {
key = "eyesjoker",
atlas = 'awesomejokers',
pos = { x = 4, y = 0 },
discovered = true,
rarity = 2,
loc_txt = {
name = "Let's take a look",
text = {
"Debuff the Joker to the left of this joker.",
}
},
pronouns = 'he_him',
blueprint_compat = true,
perishable_compat = true,
eternal_compat = true,
cost = 8,
config = {},
loc_vars = function(self, info_queue, card)
return { vars = {} }
end,
calculate = function(self, card, context)
if card.area and card.area == G.jokers then
card.set_debuff(true)
local left_joker
for k, v in pairs(G.jokers.cards) do
if k > 1 and v == card then left_joker = G.jokers.cards[k-1] end
if left_joker then
SMODS.debuff_card(left_joker)
end
end
end
end
}```
You need to add self as the first input of is_suit
is there a context for when you're selecting cards?
No, hook Card:highlight
not when you've selected a card specifically, i meant before you've played a hand
context.press_play?
I am trying to set up a table as a global variable. I tried to put it in Card.add_to_deck with a hook as I thought that would likely be called, but my card couldn't find it. What am I missing?
function Card:add_to_deck(from_debuff)
G.GAME.the_table = {}
end```
is it possible to put an G.E_MANAGER:add_event in a G.E_MANAGER:add_event?
yes very much so
You are overriding Card:add_to_deck not hooking it.
Ok
what's going wrong here
calculate = function(self, card, context)
if card.area and card.area == G.jokers and context.cardarea then
local left_joker
for k, v in pairs(G.jokers.cards) do
if k > 1 and v == card then left_joker = G.jokers.cards[k-1] end
end
if left_joker then
SMODS:debuff_card(left_joker)
end
end```
how do i make a custom deck i cant find code for them in vremade
It's SMODS.debuff_card not SMODS:debuff_card
SMODS.debuff_card(left_joker, true, self.key)
also how do i buff the card it it was debuffed by the joker specifically
Apologies, but is there a clean example of how to save a variable to G.GAME?
G.GAME.modprefix_variable = value
And you can place this anywhere, or does it need to be in a hook or something similar to get it somewhere specific? Does it also change anything if we are trying to store a table?
Thanks btw
No, G.GAME has to exist, also you can't store cards or functions.
Do you have any good example mods you can point me too? Would be beyond appreciative if you could. It is still not fully clicking for me.
i'm using the draw_card function to move a card from play back to your hand after scoring finishes, but the card always returns face down, any idea how to fix this?
i'm pretty sure this is because draw_card automatically flips the card as part of its function, and setting stay_flipped to true/false doesn't change anything. i also tried adding card:flip() after the draw_card function but that occurs too early to change anything
You mean you want a card to move back to your hand instead of the deck?
how do i check if a card is debuffed
if card.debuff
the code works (pasted below) it just returns to hand fliped which i don't want
if context.after and context.cardarea == G.play then
draw_card(G.play, G.hand, 90, 'up', nil, nil, nil, nil, true)
end
changing stay_flipped from true to false doesn't change anything
No, I was asking if you want the played cards to return to the hand instead of the deck.
yes, which they do
No, they don't, they return to the hand and the deck.
i can literally show you a clip of it working how i want if you need
basically i have a seal which i apply to playing cards which makes them return to hand after being played
You mean like old gold seal?
old blue yeah
No, it's old gold seal and old blue seal.
regardless, here's a clip showing what's happening
[[patches]]
[patches.pattern]
target = '''functions/state_events.lua'''
pattern = '''
for k, v in pairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
end
'''
position = "at"
payload = '''
local handcards = {}
for k, v in pairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) and not v:get_seal() ~= 'modprefix_key' then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
if (not v.shattered) and (not v.destroyed) and v:get_seal() == 'modprefix_key' then
table.insert(handcards, v)
it = it + 1
end
end
if #handcards > 0 then
G.FUNCS.draw_from_play_to_hand(handcards)
end
'''
overwrite = true
match_indent = true
this works to keep the card face up, but introduces a strange bug where there's a gap in the hand, almost like an invisible card
evil unselectable invisiible card that can only be seen if you pour flour on it
i think the current code for the black seal is maybe compounding with the lovely patch
i'll just remove it and see what happens
yeah
works perfectly now
uh oh
playing a winning hand with black sealed cards leaves the unsealed cards behind
i'll see if just adding a not end of round condition will fix it
I think a returning-to-hand API (akin to old gold seal) for smods would be nice to have
there's a g.func for it in the game so đ€·ââïž
by that I mean integrating it into calculation pipeline where you can simply return {return_to_hand = true}
true
if (not v.shattered) and (not v.destroyed) and not v:get_seal() == 'modprefix_key' then should be if (not v.shattered) and (not v.destroyed) and v:get_seal() ~= 'modprefix_key' then instead, that fixed the problem
for this final code
[[patches]] # CHAK - Black Seal -- Thank you somethingcom515!
[patches.pattern]
target = '''functions/state_events.lua'''
pattern = '''
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
end
'''
position = "at"
payload = '''
local blackcards = {}
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) and v:get_seal() ~= 'chak_black_seal' then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
if (not v.shattered) and (not v.destroyed) and v:get_seal() == 'chak_black_seal' then
table.insert(blackcards, v)
it = it + 1
end
end
if #blackcards > 0 then
G.FUNCS.draw_from_play_to_hand(blackcards)
end
'''
overwrite = true
match_indent = true
I suggest shortening the code like this
[[patches]] # CHAK - Black Seal -- Thank you somethingcom515!
[patches.pattern]
target = '''functions/state_events.lua'''
pattern = '''
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
end
end
'''
position = "at"
payload = '''
local blackcards = {}
for k, v in ipairs(G.play.cards) do
if (not v.shattered) and (not v.destroyed) then
if v:get_seal() ~= 'chak_black_seal' then
draw_card(G.play,G.discard, it*100/play_count,'down', false, v)
it = it + 1
else
table.insert(blackcards, v)
it = it + 1
end
end
end
if #blackcards > 0 then
G.FUNCS.draw_from_play_to_hand(blackcards)
end
'''
overwrite = true
match_indent = true
SMODS.add_card {
set = 'Joker',
}
how do i make it pick from a certain pool? (food jokers)
do you have food joker pool defined?
if so set = "Food"
if not go like. steal definition code from somewhere else
and then set = "Food"
where do i steal from?
personally i stole from cardsauce
lol
YA.vanilla_food = {
j_gros_michel = true,
j_ice_cream = true,
j_cavendish = true,
j_turtle_bean = true,
j_diet_cola = true,
j_popcorn = true,
j_ramen = true,
j_selzer = true,
j_egg = true,
j_YA_mango = true
}
if not SMODS.ObjectTypes.Food then
SMODS.ObjectType {
key = 'Food',
default = 'j_joker',
cards = {},
inject = function(self)
SMODS.ObjectType.inject(self)
for k, _ in pairs(YA.vanilla_food) do
self:inject_card(G.P_CENTERS[k])
end
end
}
end
so like this?
card.config.center.key
No, just do cards = YA.vanilla_food
cards = YA.vanilla_food {
j_gros_michel = true,
j_ice_cream = true,
j_cavendish = true,
j_turtle_bean = true,
j_diet_cola = true,
j_popcorn = true,
j_ramen = true,
j_selzer = true,
j_egg = true,
j_YA_mango = true
}
if not SMODS.ObjectTypes.Food then
SMODS.ObjectType {
key = 'Food',
default = 'j_joker',
cards = {},
inject = function(self)
SMODS.ObjectType.inject(self)
for k, _ in pairs(YA.vanilla_food) do
self:inject_card(G.P_CENTERS[k])
end
end
}
end
``` like this?
if not SMODS.ObjectTypes['Food'] then
SMODS.ObjectType({
key = 'Food',
default = 'j_joker',
cards = {
j_gros_michel = true,
j_ice_cream = true,
j_cavendish = true,
j_turtle_bean = true,
j_diet_cola = true,
j_popcorn = true,
j_ramen = true,
j_selzer = true,
j_egg = true,
j_YA_mango = true
}
})
end
local spr = Sprite(0, 0, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0})
spr:draw_shader('dissolve', nil, nil, nil, G, 0, 0, -500, -500)
Why does it still not appear, and instead give error with VT
Yes, you need to draw it every frame.
You should not be creating a sprite every frame.
ah
so save it to a table since Ill want multiple, then draw it?
why does ti crash tho
with VT?
Why are you inputting G as other_obj?
i want it to be global?
i dunno much about sprite and ui
would it be G.ROOM_ATTACH ??
No, change it to nil
ight
tyy
its still not appearing...
c = card, yes I do want a new one every update
table.insert(c.ability.extra.tbl,Sprite(0, 0, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0}))
for _, spr in pairs(c.ability.extra.tbl) do
spr:draw_shader('dissolve', nil, nil, nil, nil, 0, 0, -500, -500)
end
No, you can't put sprites in cards where it would be saved.
where do i put it
, is there anything else I could get wrong?
also still not happening, just lagging like it should ig
if not G.GAME.DIRT then G.GAME.DIRT = {tbl = {}} end
table.insert(G.GAME.DIRT.tbl,Sprite(0, 0, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0}))
for _, spr in pairs(G.GAME.DIRT.tbl) do
spr:draw_shader('dissolve', nil, nil, nil, nil, 0, 0, -500, -500)
end
No, you can't put sprites in G.GAME either.
in G.GAME.DIRT.tbl
do I just set a local variable then?
i dont even need to ask
If you want it to be global you would put it in G
still not appearing
if not G.btr_dust then G.btr_dust = {} end
table.insert(G.btr_dust, Sprite(0, 0, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0}))
for _, spr in pairs(G.btr_dust) do
spr:draw_shader('dissolve', nil, nil, nil, nil, 0, 0, -500, -500)
end
deleting the joker also removes it so
Remove everything after 'dissolve'
whaterervsatr iog
there isnt anything?
you mean calculate?
OH
okay
but I need to offset it?
aaaaaaaaaaaaaaaaaaaaaa is it just offscreen or doesnt appear
update = function(_,c)
if not G.btr_dust then G.btr_dust = {} end
table.insert(G.btr_dust, Sprite(0, 0, 71, 95, G.ASSET_ATLAS["Bitters_JokeJokersAtlas"], {x=0,y=0}))
for _, spr in pairs(G.btr_dust) do
spr:draw_shader('dissolve')
end
end,
No, you put that in the Sprite call.
but still would appear on screen, would reach to 71,95
since its drawing topleft to bottomright
anyone wanna explain how to show a sprite to me?
@daring fern sorry for bothering you but do you know which function thats responsible for the cash-out?
How can I create a mod that modifies Vanilla values and where/in what app should I start?
can you be a bit more specific in what you wanna do?
I want to modify the chance based jokers/taro cards to be a better chance
like a 1in4 to a 1in2, a 1in2 to 2in3 etc
So there's different ways to do that, depending on what you're hoping to do. Do you just want to permanently change the odds for those cards? In that case, you can use take ownership to change them
Permanently, yes
In that case, you'll want to use take ownership! I'll grab the documentation for how that functionality works!
loc_vars = function(self, info_queue, card)
return {
vars = { card.ability.extra.creates, card.ability.extra.rounds },
key = card.ability.extra.from_brammeke == true and self.key .. "_alt" or self.key
}
end
i have a card.ability.extra.from)brammeke set to true but the_alt text doesnt appear how do i make it appear?
you don't want to edit the key in the return!
i have tried it with other checks and the text does appear it just for some reason doesnt with this loc_vars
oops, no wait, ignore me, I'm speaking with too much confidence
you do want to do that
loc_vars = function(self, info_queue, card)
return {
vars = {
card.ability.extra.chips, card.ability.extra.chip_mod, card.ability.extra.mult, card.ability.extra
.mult_mod, card.ability.extra.Xmult, card.ability.extra.Xmult_mod
},
key = next(SMODS.find_card("j_YA_matthsilly")) and self.key .. "_alt" or self.key
}
end
but this one works
Yeah, entirely my bad, haha
nwnw
So it never uses the alt key there, right? I'd just add some print statements and test before returning it to see if it's actually getting the right value from card.ability.extra.from_brammeke == true
well in the joker itself i use that key
in short its a joker that summons a food joker at the end of an ante and i have a check that destroys itself if its from brammeke after a period of time
and all of it works functionally i just cant get the text to display the rounds left
The documentation for Taking ownership
This should get you started. It just allows you to treat existing objects like they're smods objects, and change any of their fields. In this case, you'll wanna check how the odds are stored for each card, and just change them through taking ownership of the config
Oh, I assume so yeah, but if it's not displaying the alt text, while you're using syntax that worked in another instance, the error's probably in the step before that. But you're using and alt description to display rounds left? Is that because you're changing the whole description for the final round?
thank you!
uh
no normally it doesnt destroy itself
but the destroy itself thingy only happens when its from_brammeke
which works functionally
Ooooh, I'm seeing now, sorry. I'd blame having just woken up for me misreading but I've been awake for like half the day already, haha
Still, I'd check with a print statement earlier on, just as a sanity check. Because if it does print the key als the key + _alt, you know it's an issue in the localization, rather than with your syntax
you mentioned that earlier
how do you print smth lol
ive been using vs code for the past 2 months for this and i still dont know how to view a print
im like that ratatoile critic guy
"I dont use print lines I boot up the game and if it doesnt work i restart the game"
loc_vars = function(self, info_queue, card)
print(card.ability.extra.from_brammeke == true and self.key .. "_alt" or self.key)
return {
vars = { card.ability.extra.creates, card.ability.extra.rounds },
key = card.ability.extra.from_brammeke == true and self.key .. "_alt" or self.key
}
end
should work in this case. I use print debugging a lot, and it's rarely the most effective way, but it's a good way to just check the state of your code quickly.
Are you using DebugPlus as a mod?
It has a console that will show print statements
But you'll also see them appear in the cmd!
with debugplus it'll print them in a console in game that you can toggle with '/'
add_round_eval_row
guys i need to put a gradient colour on a rarity badge
it won't work it just shows up white
i frogot about it for a while
no one could figure it out last time
and i still dont get it
gifs are still blocked i just
I think I figured out why
there's no rarity definition
where did it go?????
ok
nevermind
i found it
i was searching by the wrong thing
the button that does the symbol for code block is broken on my keyboard
SMODS.Rarity {
key = "tsun_gold_legendary",
default_weight = 0,
badge_colour = SMODS.Gradients.tsun_tsun_gradient_gold,
pools = { ["Joker"] = false },
get_weight = function(self, weight, object_type)
return weight
end,
}
ive tried it both with and without the extra mod prefix
And whats the SMODS.Gradient look like
No
Is the gradient being loaded
it works in the names and descriptions of jokers
i know i probably shouldn't be doing that but
it does work there
just not on rarity badges
gifs are still blocked i wanted to post another one
and you're sure the rarity is loaded after the gradient?
the rarity is in my end of code.lua which is specifically loaded after everything else
so yes i am rather confident it is being loaded last
it's
it's working.
don't know why it's working
don't care how i fixed it
im gonna not touch it now so it stays working
is it possible to add another language in the main menu langauge selection?
it's possible but i don't know how
I'm creating these card objects fully to just exist as placeholder images in the collection. I've set them up to use the key of an existing card object (so jokers, tarots, planets, etc.) so it'll use the sprite for that. Is there an easy way to just have it so a card uses the sprite info from another card?
there's an smods api for that iirc
oh?
iirc if you change the card's center to another card its sprite and description changes but not its effect
i made that mistake once
Smods.Language?
Yeah, the description I wanna keep đ I'm trying to just change the sprite, haha. I've got some weird workarounds for it now that seem to create some issues I can definitely resolve by understanding my code better, but I'm not sure that the way I'm going about it is the most efficient way, as I'm trying to do things when the object gets registered, or when its sprite is set
this is how i change the sprite for tokens. idk if there's a better way
https://github.com/nh6574/JoyousSpring/blob/0a5c0f6951f7f3073acb7f06ee1fafed950eef16/src/jokers/99_99Token.lua#L35
do any of yall know the dimensions of a character in, say, m6x11?
nvm found it on the github page lmao
I think I can use that almost fully. Just need to figure out where I'm going wrong with grabbing the atlas from vanilla objects, haha
đ
đ đ
wrong channel messages are hilarious
i am so confused on how to use SMODS.Language.
prolly bc idek how to make a font
;-;
oh for fonts you can just use SMODS.Font
there a re a whole bunch of parameters but idek what they do, its nt documented
Its about the same as an atlas; you give it a key and specify the path
fonts should be stored in assets/fonts
for any more info go ask ayokori
how will i use the characters.
like. I can't really type them in
it's not really a real language.
well, I mean you could theoretically actually make teh font using software, so that the symbols map to their letters
or what would be their letters
well I was gonna make a toki pona option for fun
so
I think the noto symbols font has some of those
not all of them, but A lot
As far as I'm concerned, you can type them as unicode in your code editor right
I think?
I use VSCode
if yyou can type them in unicode, then all you need is a font that supports the symbols
Its how I put ascii art in a tooltip
dont i need this to be in .ttf? How would I do that.
i guess you coud find a ttf with tose
but thatd take forever
oh and if you're just making a specific part of text have a different font (not in a language), use {f:modprefix_key} in your localization files
đ
you woldnt believe me if I said It took 1 hour to find the font used in a gundam show so yeah you might be cookedđ
đđ đ
oh nvm
i found a .otf of linja pona
heh.
if your using a .otf, make sure to specify that its a .otf in SMODS.Font
if data doesnt match itll crash
got it working â€ïž
ok this is not worth it. nvm đ
oh no its not that bad
i figured out the otf
key = "fire",
path = "SupporterpersonaluseRegular-EazBz.otf"
}``` see
isn't actually sitelen pona
the sitelen pona glyphs, are just a bunch of .glif files
tf do i do with those.
(it's linja pona)
OOOHHHH
huh
i think you gotta put the .glifs in a font maker software, and then export as ttf/otf
like fontforge?
yeah like that
uh i got a .sfd ;-;
yeah this shits whack asf vro
at this point even im lost
like what uses a .sfd????
FontForge, apparently.
well uhhh
i dont think converting filetype will help at all
so.. maybe see if there are export options
i clicked generate fonts... but it wont generate shit
and these are all grayed out
(outline font selection)
hmmm
yeah, Im not one to tell people to give up, but maybe you should
you shouldnt be bashing your head into a wall for a font
real
that and ive only ever used fontforge once, so im not of much help
whats the base soul chance
hey can someone help me
i wanna find if there are all 5 of a specific set of joker, and if there are, destroy it and make the full joker
what on earth am I doing
if next(SMODS.find_card("j_midprefix_key")) and ... then with 5 smods find card
oh im guessing it's 5 specific jokers from the wording but if it's objecttypes then it's different
midprefix đ„
Np man happy to help
i dont know what im doing
where is index
?
you have index there, where did you define it?
(i know the answer is you didn't but I'm pointing it out)
yeah that's the same code.
its a bit more at the top, thats all
Ok, I'm gonna be more clear. Why are you using index there?
oh right, i have no idea
What you need to do is to get the specific joker that is highlighted.
You have G.jokers.highlighted which is a table of the highlighted jokers (We know it's a table because you can use the length operator #). And you also know that the length is 1 so only one joker is highlighted. Therefore you actually want G.jokers.highlighted at index 1
how does one check if someone clicked the discard button?
it didnt work :////// bad code////
is_suit = function(self, suit) return G.P_CARDS[vv[1]].suit == suit end
When I try to run the game it crashes and says that it is not a music track
What's wrong?
You need music in the key.
just like in real life, if the music is not in key, it'll be bad
[ultra beginner here]
I am currently working on a function
SMODS.Joker:take_ownership('joker', -- object key (class prefix not required)
{ -- table of properties to change from the existing object
mult = 10
},
true -- silent | suppresses mod badge
)
would that work? it does not display +10, but I think that display and function are different things
config = {mult = 10}
why does cavendish has
config = { extra = { Xmult = 3, odds = 1000 } }
extra in it?
if youre looking at vanilla its because thunk felt like it
huh I was sure I checked it and it wasn't working, but now it's working, but thank. I'll add you to the mod's description for help
thunk just kinda randomly switches between using/not using an extra table in vanilla
i was looking at ModdedVanilla example mod
ah
well extra is generally best practice for modded jokers
also you should look at vanillaremade instead :P https://github.com/nh6574/VanillaRemade/blob/main/VanillaRemade.lua
how does it matter?
how can I solve this?
card.ability is often used for adding variables by outside sources
so putting stuff in extra prevents stuff getting overridden
path is probably wrong
oh also stuff thats in card.ability doesnt get reset by default when the card is changed into another one
only happens for specific value keys
SMODS.Joker:take_ownership('joker',
{
config = { extra = {mult = 10} }
},
true
)
how so?
vanilla joker does not put it in extra
so when modifying it it should stay in the same place
ah
i see
but it somehow worked for bloodstone
partly...
SMODS.Joker:take_ownership('bloodstone',
{
config = { extra = {odds = 10} }
},
true
)
changing config replaces the full config table, so you'd need to put in the old mult value as well
also bloodstone if the description was accurate đ„
the question is, why did extra work for bloodstone(changed odds from 2 to 10), but didnt for joker(both are vanilla)
because thunk decided to put the odds in extra for bloodstone
but didnt put the mult in extra for jimbo
oh
code moment
it finally works thx!!
???
vanillaremade isnt a 1:1 recreation, its meant as a reference and therefore highlights best practices
ohh
if you want to see the vanilla configs you should open up the balatro exe with 7zip or winrar
and look them up in there
you could but the 1 of the chance isnt stored in a value for vanilla cards, so you would have to add an additional value and override the card calculate and loc_vars to use said value in the chance
fair
You could also use context.mod_probability
you lost me at "isnt stored in a value"
also true
how do you write fancy btw
calculate = function(self, card, context) if context.mod_probability and not context.blueprint then return { numerator = context.numerator * 2 } end end,
like this one in oops all 6s?
Yes.
you can also surround it in triple backticks if youre uisng multiple lines so it becomes a code block
go go gadget long box
I'm trying to make a boss that has a bigger score if you don't have the joker needed, but instead it gives me 10 mult when starting the run
ohh
you should also use set_blind instead of calculate
and then multiply G.GAME.blind.chips
and also do G.GAME.blind.chip_text = number_format(G.GAME.blind.chips) so the text updates
and then G.HUD_blind:recalculate()
how wold I do the part inside the 'if' statement? Everytime I try to write G.GAME.blind.chips inside it, it gives me an error
no problem, I think I understand it now
It's G.GAME.blind.chips not G.GAME.blind.chip
one day i will find the lines
No, use the mod calculate
?
what do you want to do, just increase the odds without conditions?
yes
from 1 in 2 to 2 in 3
"in 3" is easy
you can just copy the calculate in vanillaremade and change the numbers
like you did the config
SMODS.current_mod.calculate = function(self, context) if context.mod_probability and context.trigger_obj.config and context.trigger_obj.config.center and context.trigger_obj.config.center.key == 'j_bloodstone' then return {numerator = context.numerator*2, denominator = context.denominator*1.5} end end
I'm trying to make a joker that scales when you play high card depending on the suit of the card, but it doesnt work at all
What did I do wrong?
i do it with take_ownership
local variables reset every time the function is called
you don't need that logic tho, you can just check if it's a high card in context.individual
how would i make a suit count as all suits but itself
Thanks!! Now it works
local oldcardissuit = Card.is_suit
function Card:is_suit(suit, bypass_debuff, flush_calc)
local g = oldcardissuit(self, suit, bypass_debuff, flush_calc)
if self.base.suit == 'modprefix_key' then return self.base.suit ~= suit end
return g
end
millions must hook
but I'm getting nil on its text, and I just dont understand how the #number# works
what what on earth is modprefix_key
what i am supposed to replace there
yourmodprefix_suitkey
your mod should have a prefix
i know that
and key is the joker key
You mean you want all suits to count as every suit except itself?
A specific suit (not modded)
Then you wouldn't put the mod prefix and it would just be the key.
are the suit keys just the suit's name?
Yes.
calc_dollar_bonus = function(self, card)
local cash = card.ability.extra.cash
card.ability.extra.cash = 0
return cash
end
is it possible for that to happen only when the boss blind is defeated
wrapping that inside of a if G.GAME.blind.boss then should work i think
Itâs okay
oh yeah I'll try
it work thx
Where is context.press_play defined?
src/overrides.lua
how do you add loc_vars to a custom consumable type
what do you mean
do... you think im dumb?
what else could i mean
consumable types don't have descriptions??
for an ITEM in that consumable type
god
and also the box thats under it where it displays the consumable type
well, that's why I asked because they are the exact same as any other consumable or joker
so how do i reference it
what
the same?
eris thank god youre here
no like theres a Tarot section for tarots
thats not loc_vars đ
and a Planets section for planets
its just the key of the consumable type
where do i put minr
for the descriptions
which is what
you can reference vanillaremade for that, look up vremade_Tarot
just copy paste what you put into the consumable type definition
prefixes do not get added
N can you please drop the XY problem link
it feels relevant here
and i dont have the link
thanks
when trying to set the labels field im just getting "attempted to index local center (a string value)"??
thats probably an entirely different issue then
unless youre doing something really wierd somehow though i doubt that
its still showing as error
oh uh i figuyred it out
do i need to put it in dictionary??
yes
then whats labels used for
for labels
i dont recall
under the card
the thing that displays under the card description goes in labels, the collection name goes in dictionary
I want to make a custom Pin object type that gets applied to your run at the start. They would work kind of similarly to Vouchers in that they're a permanent run modifier that has its own CardArea. How do I go about implementing a custom object type like that? (If there's some guide on how to do it that I missed, that would be super helpful.)
looking at updating my jokers, is if context.joker_main then the new if context.cardarea == G.jokers and context.final_scoring_step then
the latter is completely different from the former
I think it makes the most sense to have it be a card object internally even if pins aren't technically "cards"
also context.joker_main is vanilla
that has been the standard for like always
for generic trigger jokers
e.g. jimbo
why did I do this this way
đ
its STILLL not working
is labels inside of a misc table