#💻・modding-dev
1 messages · Page 702 of 1
yo i have a bug
im trying to
disable boss blind before scoring if played hand is a flush
i tried context.before, i tried context.initial_scoring_step
they both just cause the blind to be disabled after scoring
okay sprites are just so much better for this application
i wanna put a list of sprites into my UI
i don't wanna put them into nodes
i want one node containing all the sprites
how can i do that?
wait lemme try something first, i might be able to do something else
okay didn't work
i'm a badass
good luck, me of tomorrow
is the only way to add stuff to existing UI lovelypatching?
is there a way to get the amount of times a specific poker hand is contained in played hand? like the 2 pairs in a two pair, or the three of a kind and 3 (4?) pairs in a full house?
I think so?
you could try doing shenanigans with the active UIBox
#context.poker_hands['modprefix_key']
that worked thank you
for example, what if i wanted to add another node after voucher_col
yeah just patch that
figures
for some reason i thought something with add_child but that's whole new ui elements
since that's in a return you can also hook that function and find the subtable to add the nodes in
how can i make the joker level up the high card by 5?
return {
level_up = 5,
level_up_hand = "High Card"
}
context.press_play could work
yea i ended up trying that and it worked
why the level just increase by 1 visually and not doubling?
how would i track the number of cards retriggered in played hand?
not the number of retriggers total, but, rather, the number of cards that retriggered (so a max total of 5, typically)
you can watch context.post_trigger for every time a joker returns a table with repetitions > 0
and do a flag for each card in played hand that gets it
that's really smart thank you
No, you should hook SMODS.calculate_repetitions
oh ok i'll try that then
ohg true
i evidently did something wrong; it just doesn't retrigger
Director
X1.25 Mult, retrigger this Joker once for every card in played hand that retriggered
SMODS.Joker {
key = "j_director",
name = "Director",
config = { extra = { xmult = 1.25 } },
pos = { x = 5, y = 4 },
cost = 7,
rarity = 2,
atlas = "joker",
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult } }
end,
calculate = function(self, card, context)
if context.before then
card.ability.extra.retriggered_cards = {}
end
if context.joker_main then
local retrigger_count = 0
if card.ability.extra.retriggered_cards then
for _ in pairs(card.ability.extra.retriggered_cards) do
retrigger_count = retrigger_count + 1
end
end
card.ability.extra.retriggered_cards = nil
return {
xmult = card.ability.extra.xmult,
repetitions = retrigger_count
}
end
end
}
-- hook calculate_repetitions for director functionality
local SMODS_calculate_repetitions_ref = SMODS.calculate_repetitions
SMODS.calculate_repetitions = function(card, context, reps)
local director_joker = nil
for _, joker in ipairs(G.jokers.cards) do
if joker.config.center.key == "j_bof_j_director" then
director_joker = joker
break
end
end
if director_joker and context.cardarea == G.play then
if not director_joker.ability.extra.retriggered_cards then
director_joker.ability.extra.retriggered_cards = {}
end
director_joker.ability.extra.retriggered_cards[card] = true
end
return SMODS_calculate_repetitions_ref(card, context, reps)
end
that's not how you retrigger a joker
you're telling me THAT'S what's wrong
plus a joker cannot retrigger itself the traditional way
😭
Firstly, you can't store cards in card.ability, Secondly, you can't return repetitions in context.joker_main, Thirdly, you need to check that the return of the old SMODS.calculate_repetitions has one or more elements.
oh man this isn't as simple as i thought then
you can't store objects inside any save table
they're replaced with "MANUAL_REPLACE"
local oldsmodscalculaterepetitions = SMODS.calculate_repetitions
SMODS.calculate_repetitions = function(card, context, reps)
card.modprefix_retriggered = nil
local g = oldsmodscalculaterepetitions(card, context, reps)
if next(g) then
card.modprefix_retriggered = true
end
return g
end
calculate = function(self, card, context)
if context.joker_main then
return {xmult = card.ability.extra.xmult}
end
if context.retrigger_joker_check and context.other_card == card then
local count = 0
if G.play.cards and next(G.play.cards) then
for k, v in pairs(G.play.cards) do
if v.modprefix_retriggered then
count = count+1
end
end
return {repetitions = count}
end
end
end
ohh yeah don't i need to enable the smods optional feature too
i forgot about retrigger_joker_check
which is quite a dummy move
thank you so much
oh uh this makes it so that normal card triggers activate it too
i can probably figure that out
What's the proper way to change the suit of a card? Is Card:change_suit fine or it has to be SMODS.set_base?
or some other secret third thing
You can use either but SMODS.change_base is usually preferred.
Noted, thank you
what could be the reason as to why xchips and xmult causes this error?
what's the code
discord is not letting me write the whole block so ill split it into halves
if context.setting_blind and not (context.blueprint_card or card).getting_sliced then
-- Older, probably terrible code, TODO: add the passive feature later, im having an aneurysm trying to figure it out
local actives = {
"joker_main",
"individual",
"discard"
}
local passives = {
"before",
"after",
"end_of_round",
"setting_blind",
"pre_discard",
"open_booster",
"skipping_booster",
"buying_card",
"selling_card",
"first_hand_drawn",
"other_drawn",
"using_consumeable",
"skip_blind",
"playing_card_added",
"card_added",
"modify_ante",
"ante_change",
}
local active_calcs = {
"chips",
"mult",
"xchips",
"xmult",
"dollars",
"score",
"xscore",
"blindsize",
"xblindsize",
}
card.ability.extra.active_context = CalcLib.get_random_items(actives, 1, "TTactivecontext")[1]
card.ability.extra.active_calculation = CalcLib.get_random_items(active_calcs, 1, "TTactivecalc")[1]
print(card.ability.extra.active_context)
print(card.ability.extra.active_calculation)
end
if card.ability.extra.active_context and context[card.ability.extra.active_context] then
-- Resource = {Min, Max, Decimals}
local active_calcs_ref = {
chips = {15, 30, 0},
mult = {2, 15, 0},
xchips = {0.9, 1.25, 2},
xmult = {0.9, 1.25, 2},
dollars = {1, 3, 0},
score = {G.GAME.chips * 0.1, G.GAME.chips * 0.65, 2},
xscore = {0.9, 1.2, 2},
blindsize = {G.GAME.blind.chips * 0.05, G.GAME.blind.chips * 0.35, 0},
xblindsize = {0.95, 1.3, 2}
}
local resource = card.ability.extra.active_calculation
local details = active_calcs_ref[resource]
if card.ability.extra.active_context == "individual" and context.cardarea ~= G.play then return end
return {
[resource] = math.floor(pseudorandom("TTrandom") * (details[2] * (10 ^ details[3]) - details[1] * (10 ^ details[3])) + details[1] * (10 ^ details[3])) / (10 ^ details[3])
}
end
end
it claims that variables hand_chips and mult are set to nil apparently
What is the goal?
making a joker that does something random every round
i want to temporarily (if a global variable is true) make every scored card give a $1, what would i need to hook?
dont hook anything
use mod calculate
I think it's a global calculate for the mod
like this?
SMODS.current_mod.calculate = function(card, context)
-- do stuff
end
si
what? why is this happening?
i just manually removed the dependency, but, that's weird
SMODS changed its method of checking dependencies not too long ago, and that change broke any mod using “>=1.*”
Ah.
how would I add another description row to a (vanilla) Playing Card.?
For Jokers I did (the code below) in loc_vars, but it's not like vanillla objects have a loc_vars function I can edit.
local main_end = {}
local fv = card.ability.extra.flavored_cookie_bonuses
if fv and fv.walnut_stock and fv.walnut_stock > 0 then
info_queue[#info_queue+1] = {
set = 'Other',
key = 'cl_walnut_stock',
vars = { fv.walnut_stock }
}
end
for _, data in ipairs(card.ability.extra_rows) do
local nodes = {}
local vars = {}
for _, var in ipairs(data.vars) do
vars[#vars + 1] = card.ability.extra.flavored_cookie_bonuses[var]
end
localize{type = "other", key = data.key, vars = vars, nodes = nodes}
for _, _nodes in ipairs(nodes) do
table.insert(main_end, {config = {align = "cm"}, n = G.UIT.R, nodes = _nodes})
end
end
local res = old_loc(self, info_queue, card)
res.main_end = main_end
return res
A lovely patch could probably forcefully add an info queue, but I'm still not well-versed in lovey patching
my mod still works after like a year ❤️ goated
Default Joker, Default Joker
owww nevermind
boowop
managed to do it with a hook:
local old_generate_ui = Card.generate_UIBox_ability_table
function Card.generate_UIBox_ability_table(self)
local t = old_generate_ui(self)
if G.GAME and G.GAME.snickerdoodle_active and G.GAME.snickerdoodle_active > 0 then
t.main[#t.main+1] = {
{
n = G.UIT.R,
config = { align = "cm", no_fill = true, padding = 0.05 },
nodes = {
{ n = G.UIT.T, config = { text = "Snickerdoodle: ", scale = 0.3, colour = G.C.UI.TEXT_DARK,shadow = false } },
{ n = G.UIT.T, config = { text = "$" .. G.GAME.snickerdoodle_active, scale = 0.3, colour = G.C.MONEY, shadow = false } }
}
}
}
end
return t
end
That makes sense
i think this one is a talisman crash
uhhhh
invisible consumable?
mouse hover over there reveals nothing
aand now its back to normal
uhh help
the log looks like this
is applying vanilla seal somehow different than applying modded seal
i have a joker that apply a seal and it works fine for my modded seal
but for some reason when it gets a vanilla seal it doesnt apply
uhh im gonna have to copy the rest of the code for it to make sense in context
so what it is meant to do is that it checks the enhancement, seal, and edition of each scored card, and then count a tally for each type of enhancement, seal, and edition
and then if something is present on at least half of the scored cards, it applies it to the rest of the hand
currently from what i can tell it is counting everything correctly, and it is applying enhancement and edition perfectly fine
if the seal is a modded seal from my mod it also gets applied correctly, but when i test it with vanilla seals it wouldn't be applied
if you replace key with "Red" or something it doesnt work either?
is there a list of all vouchers, jokers etc in game?
balatro > collection
:3
also https://jokerforge.jaydchw.com/keys i guess
wdym?
you can use G.P_CENTERS.'obj_key' or you can see it in vanilla code in game.lua
i mean one i can search through in a joker or something
there are a couple, depends for what purpose
can i do rarity/weight in an SMODS.Tag object if i have object_weights = true in Optional Features? (and will the rarity/weight actually factor in? (like spawning))
well that needs another question then, can i check the attributes of a joker even if they arent in play? like check its variables and such
i will be after checking them yeah
then you dont need to check
no i need to check it first
unless by attribute you dont mean literal SMODS.Attributes
anyway, please just say what the effect is lol
basically its a joker that challenges you to find a joker in your run and gives you hints on what joker it is, so i want to check the variables of the joker to generate hints and to also choose the joker
i see, then i would probably use SMODS.get_clean_pool to generate only jokers that are in the pool
https://github.com/Steamodded/smods/wiki/Utility#smodsget_clean_pool_type-_rarity-_legendary-_append
then you can check the values by doing G.P_CENTERS[key] for each or pick a random one first and then check
okay thanks ill give that a shot
that dead ahh channel bruh 😭
i mean im there too, i just dont know what the issue is
i imagine thats the case for other people
so i have this right now
using this function for localisation:
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
if not card then
card = self:create_fake_card()
end
local target = {
type = 'descriptions',
key = self.key,
set = self.set,
nodes = desc_nodes,
AUT = full_UI_table,
vars = specific_vars or {}
}
local res = {}
if self.loc_vars and type(self.loc_vars) == 'function' then
res = self:loc_vars(info_queue, card) or {}
target.vars = res.vars or target.vars
target.key = res.key or target.key
target.set = res.set or target.set
target.scale = res.scale
target.text_colour = res.text_colour
if desc_nodes == full_UI_table.main then
full_UI_table.box_starts = res.box_starts
full_UI_table.box_ends = res.box_ends
end
end
if desc_nodes == full_UI_table.main and not full_UI_table.name then
full_UI_table.name = self.set == 'Enhanced' and 'temp_value' or localize { type = 'name', set = target.set, key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or target.vars or {} }
elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then
desc_nodes.name = localize { type = 'name_text', key = res.name_key or target.key, set = target.set }
if (not full_UI_table.from_detailed_tooltip or full_UI_table.info[1] == desc_nodes)
and not full_UI_table.no_styled_name then
desc_nodes.name_styled = {}
localize { type = 'name', key = res.name_key or target.key, set = target.set, nodes = desc_nodes.name_styled, fixed_scale = 0.63, no_pop_in = true, no_shadow = true, y_offset = 0, no_spacing = true, no_bump = true, vars = target.vars }
desc_nodes.name_styled = SMODS.info_queue_desc_from_rows(desc_nodes.name_styled, true)
desc_nodes.name_styled.config.align = "cm"
end
end
if specific_vars and specific_vars.debuffed and not res.replace_debuff then
target = {
type = 'other',
key = 'debuffed_' ..
(specific_vars.playing_card and 'playing_card' or 'default'),
nodes = desc_nodes,
AUT = full_UI_table,
}
end
if res.main_start then
desc_nodes[#desc_nodes + 1] = res.main_start
end
localize(target)
if res.main_end then
desc_nodes[#desc_nodes + 1] = res.main_end
end
desc_nodes.background_colour = res.background_colour
end```
how do i remove the description box if the localisation doesn't have one, and how do i remove the set badge?
i'm extending SMODS.Center
Forgive me if this is the wrong place to ask, but does anyone know if it’s possible to get access to balatro’s background shaders (i.e., title screen, blinds, boss blind, arcana pack, etc.) via modding? I’m trying to recreate a dynamic PC wallpaper based on Balatro which uses GLSL shaders, and I want it to be able to “react” in the same way the background does when entering blinds or booster packs.
you can unzip the .exe and get access to the shader files yeah, how it does the specific changes in colours you would need to find in the game code but it isn't hard
No its cause i tried to ban every blind from appearing
Does banner do anything other than banning jokers i have to know
does it ban tags i never got to that
I had no idea you could unzip an exe. Fascinating
that would probably be because its pretty useless for like 99% of them
love2d "compilation" just happens to be putting the source code in a zip along with the love2d stuff
?softban 523823232655294464 scam
I couldn't find that user
how would you modify the rules for a base game challenge
i dont want my mod to break base game challenges by adding things that are meant to be banned
How did I get so lucky with finding these resources LMAO
got this error again
lemme see if i can recreate it
i found this
SMODS.Sound{
key="mega",
path="mega.ogg",
pitch=0.7,
volume=0.6,
}```
but it seems to work fine
ok thats REALLY strange - i have no idea how to recreate this error
currently piecing stuff into death's code to make my own card lmao
i may not be a good coder, but i am a good thief
i just installed notepad++
that works
unfortunately there's no vantablack mode for np++ but the dark mode works just fine for me
how does one get the chips of a card
card:get_chip_bonus()
what is that
idk
😭
getting there... off-centrely...
ok so my locals are being local and its causing a crash at line 65
oop forgor line nums
ah
the stupidest code you've ever seen
actually its stupider than i thought because i accidentally put 0 instead of 1
✨woops✨
i like it
NOW its the stupidest code you've seen
Literally just get rid of the loop
i may be a little
==
also thats not correct, G.hand.highlighted is in the order that they were selected
BUT THIS WOULD BE SUCH CLEAN CODE NOOOOOOOOO
i know
this is de page
this did not work the way i thought it did
i need to not be lazy and detect both leftmost AND rightmost instead of just saying "not leftmost"
trying to create another shop that can be accessed on the shop screen
but u can only enter it if u have a specific consumable
but i have no idea how to do that
because im smart
great job mods
mods sniped that post fast
larger section of the code
can someone help me set up a atlas for my mod?
it's
it's just a series of images
i know but when i test my mod it pulls from the vanilla atlas and not the one I set for it to pull from
you misspelt atlas
how do you make a consumable give hiker-like chips
Code?
just that there is a crash in a file for a joker does not necessarily mean the crash was caused by having the joker
how about when its across mods and in unrelated code
if G.GAME.paperback.da_capo_suit == 'None' then is aparently the code that breaks when i use my consumable
is pool valid in SMODS.add_card? i tried using it and it crashed my game
are you perchance running something outside of a run that is only supposed to happen during runs?
-# lots of running in that sentence
It should be set instead of pool
well the issue is i have two types of fish, small and big
SMODS.ConsumableType({
key = "Fish",
primary_colour = { 1.0, 0.6, 0.7, 1 },
secondary_colour = { 0.85, 0.45, 0.55, 1 },
collection_rows = { 4, 4 }, --TODO: make { 6, 6 } when legendary fishes are added
shop_rate = 0,
default = "i_bass_s"
})
SMODS.ObjectType({
key = "fish_s",
default = "i_bass_s"
})
SMODS.ObjectType({
key = "fish_b",
default = "i_bass_b"
})
if context.setting_blind then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.4,
func = function()
if G.consumeables.config.card_limit - #G.consumeables.cards >= 0 then
play_sound("timpani")
card:juice_up(0.3, 0.5)
SMODS.add_card({
pool = "fish_s",
key_append = "f_nuwa_fuxi"
})
end
return true
end
}))
end
if context.end_of_round and context.main_eval then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.4,
func = function()
if G.consumeables.config.card_limit - #G.consumeables.cards >= 0 then
play_sound("timpani")
card:juice_up(0.3, 0.5)
SMODS.add_card({
pool = "fish_b",
key_append = "f_nuwa_fuxi"
})
end
return true
end
}))
end
first codeblock are type defs and second is joker code
Yes, it should be set instead of pool in SMODS.add_card
i see thank you
it just created a default joker; all of my fish have one of the following
pool = "fish_b",
pool = "fish_s",
Is there anyway to change the x$ per y$?
interest?
x is equal to G.GAME.interest_amount, to the moon uses this
the y isnt controlled by an external value though so you would have to do some patching for that
Such as?
idk what exactly so just look at vanilla interest code ig
oh yea
i know entropy has something that makes it per 4$ but i have no clue how thats done
It should be pools = {['poolkey'] = true}
thank you
if i want to assign attributes to a custom joker, do i just add that in the joker parameters? the wiki says "definition" and i don't know if that's the same thing
Yes, that's the same thing.
Wait how do i use custom functions that i made and how do i make a description pop up?
i love maxwell, it can put minus permabonus on a card
my mod is all about disabling and enabling specific parts of itself in order to allow the player to have an experience that they prefer. currently, i do this by only loading files that have been enabled. this means that if the player has an item in a specific set during a run, that set is disabled, and the run is continued, the game will crash since the item just doesn't exist in-code anymore. this is pretty much intentional. however, i'd like to make it so that, when the game crashes due to this, a custom message is shown on the crash screen. every time i try to do this, it seems as if it activates just after the actual crash. how would i accomplish this? the crash is attached.
You can "patch" into the overridden error handler and add stuff there into the err table. Specifically looking for if #sanitizedmsg ~= #msg then as pattern, adding table.insert(err, "The run contains an item that's part of a disabled set.") or something before.
alternately, you could do the thing smods does to detect version updates and erase the run in progress if a set has been disabled
Should probably warn the player that the run will be deleted if the game starts up with a change to set contents.
does the obelisk have the hands attribute? getting two different answers from this page
a quick check of attributes.lua says no
how would i make a ui text elemt use {E:1}?
{ n = G.UIT.R, config = { align = "cm", padding = 0.3 }, nodes = {
{ n = G.UIT.T, config = { text = "Bundles Of Fun", scale = 1.2, colour = G.C.GOLD, shadow = true, emboss = 0.05 } }
}},
i was able to do it using float but now i'm trying to get another one to use {E:2} to do the little bumping animation
{ n = G.UIT.R, config = { align = "cm" }, nodes = {
{ n = G.UIT.O, config = { object = DynaText({
string = { { string = localize("warning") } },
colours = { SMODS.Gradients.warning_text },
scale = 1,
shadow = true,
emboss = 0.05
})}}
}},
warning = "{E:2}WARNING",
you need the UI Nodes
it'll make the dynatext for you
you need something liek this
local loc_nodes = {}
localize{type = "other", vars = {card.ability.extra.xmult}, key = "synthb_blackjack", nodes = loc_nodes}
for i, nodes in ipairs(loc_nodes) do
loc_nodes[i] = {n = G.UIT.R, config = {align = "cm"}, nodes = nodes}
end
return {n = G.UIT.C, config = {padding = 0.05, align = "cm"}, nodes = loc_nodes}
turns out i just needed to add bump = true to it lol
any help?
how do i make a playing card Card object
it should be as part of deck or just for showing somewhere?
but usually it's ```lua
SMODS.create_card({ key = "c_base", front = "H_2" })
it will create 2 of Hearts
just for showing somewhere
then use example above
this is probably obvious but how do you get what deck someone is using, thinking about making a joker that has a different effect for each deck
no im not gonna do modded decks 😭 (ill probably have a base fallback condition)
function MOD.get_selected_deck()
if G.STATE == G.STATES.MENU then
return
end
local ret = G.GAME.selected_back and G.GAME.selected_back.effect and G.GAME.selected_back.effect and G.GAME.selected_back.effect.center.key
return ret
end
Thanks
What does no_fill specifically do in UINodes?
Tried looking in source code and still doesn't make sense, and I tried referring to frostice's lsps but it's kinda ambiguous
@keen atlas sorry for ping, wondering if you know abt this
i dont remember
i see, no worries
lowkey i never noticed this
using colour = G.C.CLEAR probably does what its intended to do though
oh wait tis children
no_fill is not related to the node's background color
from the looks of it it'll prevent its colour from appearing in its children
oh
...wait
i'll double check
now that you say that
Yeah no it's not related to background color
When you have C, width of all R in it will try to match widest one, unless you specidically disable it
only appearance in ui.lua
oooh
that makes sense
nice that there's a way to disale it
Ah, I see
but it's not useful because even if you do, alignment will not care
aka element will not center itself because it will think that it's fill all space already
because yes
vanilla oversight and nothing you can do about it
rip
the humble lovely patch
then it may affect any other UI
Unless you make it as unique property
I know that fill works for R inside C, but I dont remember when it was working for C inside R
it's kinda inconsistent (for me) and I usually avoid it
i want this to affect the bottommost card in deck, but it seems to just affect a random one. is there any way to have this functionality?
if context.setting_blind then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 0.4,
func = function()
if G.deck and G.deck.cards and #G.deck.cards > 0 then
G.deck.cards[#G.deck.cards]:set_ability(G.P_CENTERS.m_lucky)
end
return true
end
}))
end
also, how would make it so that probabilities are guaranteed for all cards? is there any easy way to make it so that this effect only occurs in a specific context (e.g., while in a boss blind)?
if context.fix_probability and G.GAME.blind.boss then
return {numerator = context.denominator}
end
Put the event in an event.
sorry for ghost ping fixed it
Makin my joker now 🔥 might be a little strong but I made him a rare
He ranges from tame to diet perkeo..kinda
red deck: +1 discard
blue deck: +1 hand
yellow deck: x1.5 mult if you have >=10 bucks
green deck: $1 for each joker owned
black deck: +1 joker slot, -1 discard
magic deck: its constellation but for tarot card consumes
nebula deck: at end of shop, takes 2 dollars to create a negative planet card of most played hand
ghost deck: at end of shop, takes 3 dollars to create a negative spectral card
what I have so far
Abandoned deck gonna be uhhh
🤷♂️ idk
and checkered is gonna be annoying
sir you are in modding-dev
er I guess its been a hot minute, this worked wonders btw!
why do my packs not have a localization in-game?
SMODS.Booster {
key = "i_tackle_normal_1",
...
SMODS.Booster {
key = "i_tackle_normal_2",
...
SMODS.Booster {
key = "i_tackle_jumbo_1",
...
SMODS.Booster {
key = "i_tackle_jumbo_2",
...
...
Other = {
p_bof_i_tackle_normal = {
name = "Tackle Pack",
text = {
"Choose {C:attention}#1#{} of up to {C:attention}#2#",
"{C:fish}Fish{} cards"
}
},
p_bof_i_tackle_jumbo = {
name = "Jumbo Tackle Pack",
text = {
"Choose {C:attention}#1#{} of up to {C:attention}#2#",
"{C:fish}Fish{} cards"
}
},
...
Are you returning key = self.key:sub(1, -3) in loc_vars?
nope! thank you; never knew that existed lol
How do you check if a voucher is redeemed? (Im looking for antimatter and the crystal ball specifically)
im manipulating joker/consumable piles when u gain a joker, but then I gotta undo it when its removed
Actually, eh
I could just save the max slots when joker is added in a new variable
but ig if u redeem it after
hmm
eh w/e tough luck if u do
🙂
How're you manipulating the slots?
Im takin the total slots you have, and then dividing it equally
and adding 1 if its uneven
(plasma deck wysguy)
pretty sure you can just use G.GAME.used_vouchers.key
So 5 joker slots and 2 consumable slots become 4 joker slots 4 consumable slots
and then if u sell the joker, back to 5 and 2
Save what they are before and after you change them and when the joker is removed set them to before+(current-after)
oo thats a good idea
Also why is consumables misspelled in the code
or am I having a brain fart
it's always been like that
not that it's correctly spelled
first time ive interacted with consumables
it's just always "consumeables"
there are some other bad misspellings in the code that somehow stuck like "caino" for canio and "selzer" for seltzer
lol
oh apparently the reason for both of these is simply because it was misspelled as such in early versions of the game and thunk didn't bother to change 'em internally after they were fixed in-game which is funny
Alright cool I did it, technically if u redeem a voucher after adding the joker the voucher gets respected but A. im lazy B. im kinda ok with the voucher still doing what it says
It's not like im wording this joker's description lol
Anyway time to make erratic deck
I gonna make this one funny
now all I need to do is a base condition
tho I could just kick him out of the pool if ur not using a vanilla deck
buut thats boring
tempted to make him do nothing
lol
but u dont know he'd do nothing
the ultimate troll
but its a rare card that would feel mean
bumpy bump
tyyy
Hey I was wondering if it's possible to transform certains cards after the hand scored,
I using other_card in context.after but it crashes the game and right now the stone card is created after the joker triggers (I have other jokers that triggers on stone card, that I don't want to trigger if this one is placed before)
if context.individual and context.cardarea == G.play and (SMODS.has_enhancement(context.other_card, "m_gold") or SMODS.has_enhancement(context.other_card, "m_steel")) then
return {
dollars = card.ability.extra.dollars, context.other_card:set_ability(G.P_CENTERS["m_stone"]),
}
end
end```
Yes, context.other_card doesn't exist in context.after
is there a way to have access to those after the hand scored ?
context.scoring_hand
how do i make it so that my consumable only activates on jokers and other consumables? not doing the check allows it to activate on itself, and doing the check makes it such that it just doesn't activate on any consumable
calculate = function(self, card, context)
if context.other_joker or (context.other_consumeable and context.other_consumeable ~= self) then
return {
xmult = card.ability.extra.xmult
}
end
end,
It should be card not self
thank you
i'm trying to take ownership of perkeo to make it so that it can't duplicate legendary fish, but it's not working at all - the localization nor the effect
the logic works, but visual are not it, is there a way to change this (keep the card until score is applied and changes only at this moment?)
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and
(SMODS.has_enhancement(context.other_card, 'm_gold') or SMODS.has_enhancement(context.other_card, 'm_steel')) then
return {
dollars = card.ability.extra.dollars,
}
end
if context.after and not context.blueprint then
for i = 1,#context.scoring_hand,1 do
if SMODS.has_enhancement(context.scoring_hand[i], 'm_gold') or SMODS.has_enhancement(context.scoring_hand[i], 'm_steel') then
context.scoring_hand[i]:set_ability(G.P_CENTERS["m_stone"],true,1)
end
end
end
end
I believe this is a bug fixed in this PR 1375
How would I make a hand thats condition is its all face cards?
I wanna add Blaze to my mod
Feels too complicated for me to make rn, gonna try and add a gun (The Brainstorm of Ceremonial Dagger)
ok nevermind
how do i create a copy of a (random) card in the player's deck?
how do i test the default values in my config.lua, so i can see what they look like when the mod is first opened? seems like no matter what i do it saves what i had the values set to most recently
remove the config file in the save folder, one folder up from mods
there should be a config folder
what part are you having problems with
I'm doing this, but it's not actualy adding to the deck?, like i see the cards get added there, but clicking on the deck still shows 13 of all suits
-- find the target card
local target = GLUE.FUNCS.get_random_target(G.deck, function() return true end, 'cl_stroopwafel_cookie')
if target then
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
for i = 1, 3 do
local _copy = GLUE.FUNCS.copy_to_area(target, G.deck, nil, true)
table.insert(G.deck.cards, _copy)
end
G.deck:shuffle()
return true
end
}))
end
-# uploaded the lib funcs
you need to insert it to G.playing_cards not the deck, there are a couple of steps you're missing you should check DNA
or wait a bit for the next smods that adds SMODS.copy_card
oh ok
should i emplace them?
emplacing them seemed to work, so
in G.playing_cards? no it's not an area, emplacing them in G.deck is correct
yeah g.deck
i was trying this but i see why i got confused with it now, the config file doesn't get created until i update one of the values in-game
hmm. small problem, due to the layering of the tiles, bonds are going underneath other tiles
why am i doing this to myself 😭
okay new plan
draw the tiles, then draw the bonds over that, then draw the elements on top
using the same negative padding trick as before
You are speaking gibberish to me. (The most advanced Joker I've made is the goddamn Wiimote)
ui stuff is always gibberish
it is genuinely the most miserable part of balatro modding
hi all! i'm planning out the code structure for a joker that makes all jokers with a specific attribute twice as likely to appear. at first, i was thinking about something with add_to_deck / remove_from_deck and then looping over all jokers with the attribute and multiplying/dividing the individual weight of each, but i didn't see an API function for this so i abandoned that line of thought
i did find an approach in the Manifold mod that should work, which works by patching into functions/common_events.lua and conditionally duplicates entries into the pool generation function (https://github.com/ouiiskey/Manifold/blob/main/lovely/manifold.toml)
this seems like it will work for my purposes, but i'm not sure what best practice is - is there anything in API i'm missing before i resort to a lovely patch?
its not super terrible once you figure it out at least to some degree [she says speaking from her own experience but] but good GRIEF it is tedious
😭
i think a recent SMODS update allows you to return a weight value which overwrites the usual weight value
unless im misunderstanding what you're doing
a lot of things takes a while to reach smods wiki
that sounds promising!! i'm fine with reading the code, what's the name of the function?
i think it was like context.modify_weight as an optional feature or something
SMODS has weight object in the work (or it released idk Im not uptodate w features)
Oh oops Kusane was faster mb
Can someone tell me what I'm doing wrong with this code?
SMODS.Atlas{
key = "vouchers",
path = "Vouchers.png",
px = 71,
py = 95,
}
SMODS.Voucher{
key = "black_paint",
atlas = "vouchers",
pos = {
x = 2,
y = 0,
},
config = {
extra = {
suitless_mode = "Suit"
}
},
cost = 10,
redeem = function(self, card)
G.suitless_mode = card.ability.extra.suitless_mode
end,
in_pool = function(self, args)
if G.playing_cards then
for k, v in ipairs(G.playing_cards) do
if v.base.suit == "bra_suitless" then
return true
end
end
end
return false
end
}
SMODS.Voucher{
key = "washing_machine",
atlas = "vouchers",
pos = {
x = 2,
y = 1,
},
config = {
extra = {
suitless_mode = "Wild"
}
},
cost = 10,
requires = "v_bra_black_paint",
redeem = function(self, card)
G.suitless_mode = card.ability.extra.suitless_mode
end,
}
I've checked the code many times with the wiki and compared it to other working mods, but nothing is working. They display normally in the collection, but whenever I start a run, it throws this error
though this feature does mkae it so that the rng queue now returns different values from how vanilla normally would do with the same seed
so if you for some reason you care about that, then that's something to be aware of
ah, that's unfortunate, it's not the worst thing but it def is a consideration 🤔 i will look into it :3 thank you both!!
:3
requires should be a table of strings
Oh, my goodness, thank you.
I knew it'd be something silly
i didnt realize you could make it HAVE more than one requirement
voucher merge valley when
is it possible to dynamically change the fps of an animated atlas
You can change the FPS of any given AnimatedSprite.
.current_animation.FPS
G.jokers.cards[1].children.center.current_animation.FPS on first held Joker, as example.
thank you
It could be worse, it could be the scoring calculation loop
oopsie poopsie
where would be a good place to put a photosensitivity warning
salty ghost inventing transmutation machine 
I can send you some code later that does this if you need an example
that'd be nice, tysm!
theoretically you could either adjust the loading screen image like how Wormhole does or add a popup on first finished load like aikoyori’s maybe?
that and the readme too
🤔
also, from a card, how would i get the card's key?
card.config.center.key or card.config.center_key, pick any
alr ty
this is what debugging looks like 😭
interesting
how should i go about hooking vanilla methods of picking random cards
secret genius??? (looks the same but there are two stacks of tiles here)
like overriding what card castle chooses for example
soon salty ghost will realize about existence of cutting-edge technology 

ghostsalt : :3
ghostpepper : >:3
the title screen as soon as you download the mod
nooooo
There's should be unified way to display photosensitivity warning
ghostpepper when caroline roper enters the room: omg hihi :3
And unified config for that, in SMODS prefferably
reduced motion:
what if instead of
ghostpepper
it was
realhumanketchup
Reduced motion and photosensitivity is different things isnt it
I guess
actually i do now wonder how often they get the carolina reaper joke
or do they somehow not get it from anyone
not often actually ^^
oh sorgy i was still talking about caroline roper
who said that mod needs new mechanics to be good?
tom lum is also close to tom yum
freind
two out of three hosts are spicy food adjacent
god i cant spel
friend
i dont make good jokers
i just implemented something that wasnt a new mechanic but i like it
it's something that probably 0.2 people will notice if i wasnt too giddy to infodump about it
ok vro
infodump to me im bored
i js got the new glove in slap battles on roblox 12 minutes after it came out
so i dont have much else to do
play my mechanic slop
ok so it needs a bit of context
right
no time to play vro, i need press button on keyboard
i have a joker called "Pick A Card, Any Card" where it picks a random card from a standard 52 deck, and it gives chips, mult, and xmult if a scored card matches its colour, suit, and rank respectively
basically a slightly wilder misprint in a sense
ok......
it only reveals what card it picks after you pressed play so it is basically random
very innovative idea
...idol?
hol on stay with me
i dont see myself using it but ill keep listening
separately, there is another joker called Cyclomancy, where it tells you a card, and it scales its xmult value whenever the card it's telling you is scored
and then it pick a new card
unlike most random card jokers where it picks a new random card regularly, the card it's telling you does not change UNTIL you score the card it tells you,
so you have something to work with
ok make sense so far?
uh huh
stay with me
i tihnk
no you lost me at joker

so the first gimmick is that Cyclomancy does NOT pick a card randomly
its so funtion
ok...
instead, it generates a stacked deck of a specific kind and cycle through them
salty ghost so close
wait are you making opus magnum
and so if you know that it is picking from a stacked deck, you can know what the next card it will tell you to play is
ok ok
so instead of being random chance and hoping it hit, you can actualy plan for it
make sense?
but wait there's more
ok ok
the second gimmick is that, if you have BOTH Cyclomancy AND Pick A Card, Any Card, then Pick A Card will also cycle through THE SAME DECK instead of picking a random card
gif jumpscare

so once you cotton what deck Cyclomancy is using, you can always plan for your next move
to scale both cards with max efficiency
anyway if possible i would also like Cyclomancy to hook vanilla cards as well but that's a whole nother can of worm
gr no i hate u gr
wormcan
hnnnnng
he say balatro not peak
the creashure is growing
wow what a tech
balatro, but peaker
there can I not be executed by guillotine now
like a chud
bro doesnt use ms paint
i think thats a good thing
not again
fire
picks a random color on your screen
every number in the hex code adds up to become mult
that color's red value is +mult, green is money, blue is chips
well-known number F:
ok u got me with that one
throb nog
Anyone knows whats wrong with my code?
Im trying to make this joker
spwan this joker on destruction
the joker you're trying to create doesn't exist
you forgot your mod prefix
isnt the prefix :key = "monitoringbestfriendedition", ?
no your mod prefix
oooooooh
mhm
thank you soo much
wait wh
the existence of cards is causing reality to shatter
you can do pools = { ["pool_key"] = true }, ???
is that a new smods thing or can you always do that
as opposed to pools = { pool_key = true }?
what does it do?
that's a lua thing
kinda old by now, you need to make an SMODS.ObjectType for them to work
attributes are just easier now except for some specific cases
i thought cardareas would help. uh. no
TTS game when they're loading in:
guys help me out
js made this but i dont know what it does
its gotta be techy
not some dumb bs
+5 mult
+101 Mult
im sorry that was the wrong reaction
actually i might make it check your gpu usage
Make it automatically create a new mod
+3 Mult times your Windows number
Real idea I tried to make before
am i even able to check like actual computer stuff
mac -1 mult
+1 Mult per opened window 🥺
Technically, yes, but you'd be opening the Command Prompt or the Terminal each time it is checked due to needing to call specific commands and reading their output each time.
darn
You'd also need to execute a different command for Windows and Mac/Linux.
darn again
Sends a random prompt to Copilot
+10 Mult per Bullet Points in its response
screw ai
Something something window size idk
At least you can check the game's own resolution.
Brianblast
+0.001 Mult per pixel the game window contains
idk the multiplier how big are windows, each side is in the thousands so there's gonna be millions of pixels
Xmult equal to the aspect ratio of the window
+Something Mult but randomly makes the window very small and moves it away
rhythm doctor bosses:
forces window size to be small and you need to move it around to find a windows logo for it to give X3 mult
+0.01 Mult per pixel per second your cursor is moving
X3 Mult if this mod is not running on a PC
good ending : steam deck
bad ending :
X3 Mult but if you lose sends a screenshot of your gameover screen to a random steam friend
aha!! i found my bug
X0.25 Mult per Steam friends that are currently online
If they are currently playing Balatro, gain an additional X0.5 Mult
Destroy this card if any friend has TModLoader open
it's completely unrelated to the cards
i put my if statements in incorrectly 😭
it doesn't create a blank cell if it finds a tiled cell with no elements
+10 Mult per 1 Ethereum in this wallet
[mod creator's wallet id]
Ok NOW what happend?
j_Refreshed_monitoringbestfriendedition
You saw NOTHING
why do you have so many mods enable when testing your own mod
What kind of a key is that 😭
like generally unless you're making crossmod content you might want to disable them
just so you can be absolutely sure that the problem is from your mod
and not from some datatype clashes or some shit
but also it is funny to see self reports in logs
thank you
i mean thats the name of the song
so retro yahimod
an ortalab version of so retro
it sure is something
balatro the minigame engine
yeah debug mode is now completely useless 😭
OMG IT WORKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
I wrote a patch to make debug outlines thin, transparent, and not blue - unfortunately I'm not on my PC so I can't share it
But it's a possible thing you can do
drawing bounds by using ui is interesting choice
wait maybe i'm thinking about this all wrong...
i could maybe add the bonds to the elements with a drawstep
hmm
very much so
32p gaming
means i don't have to make a grid with a different coordinate system on top
The nodes are center objects? You could like have a drawstep go on if nodes are next to each other and show half a pipe in a specific direction
ah no that's not how it works
Oop
only some elements have bonds between them
it's a neat idea though ^u^
mm now i'm wondering if i should do it like that
if context.modify_weights then
if context.pool_types.Joker then
for k, _ in pairs(context.pool) do
if G.P_CENTERS[k].attributes.mult then
context.pool[k].weight = 20
end
end
end
end
something like this would make jokers with the mult attribute have double weight (I can't test it rn but I am 90% sure this works)
where in G.SETTINGS is the reduced motion setting
that makes sense
wow, that's really elegant - that seems like it should work? iirc default weight is 10 from what i scanned on the documentation. tysm, i'll test this when i get back from work ❤️
how do i tell a card to stop passively wiggling?
(i don't mean juice_until, i mean the thing cards do when they're sitting there or being hovered over)
actually how do i stop a card from moving or juicing generally
it's dissolve shader + cardarea align_cards()
right but how do i stop that
idk
cool :)
likely some CardArea:align_cards patch to stop your cards moving, or put them in a different area type that doesn't have the wiggle
depends on how you're managing areas
wahoo ^u^ (working, i haven't applied the offset yet)
what is the entropy for the games pseudorandom system
isnt it mouse position and time since you opened the game?
bump?
i'm trying to figure out what's going wrong here
bwump
balatro is the new geometry dash
in the fact that its essentially a game engine now
it's very close to the love2d engine i think
assert(SMODS.load_file("./items/jokers/operatingsystem.lua"))() -- Operating System```
guys this does not load my guys in
my file structure is
Mods > invalidated > items > jokers
can you increase the time that a message shows up for?
where is this
just do assert(SMODS.load_file("items/jokers/X.lua"))()
sick
oh ight
nah that still dont work
i still have a bunch of my jokers in a seperate file outside the folder, if that matters
i think just those jokers
it crashes as soon as i open it
lemme ss the log
oh if its a crash then its probably not to do with the loading i have been proven wrong
add delay = num into your return
and change num too obv
ok hold on i changed it to this
for _, file in ipairs(jokers_src) do
assert(SMODS.load_file("src/jokers/" .. file))()
end```
and it loaded
it loaded just the two jokers i put in there
so ima put everything else in there
is it possible to return multiple instances of mult? like, instead of this stacking to return +30 mult, it gives +10 mult 3 times?
at least on the title screen, i assume its just time since you opened the game
which doesnt work, since the thing im triggering happens at the exact same time after you open the game every time
meaning it'll always do the same exact thing every time
so im gonna do the unthinkable and use normal math.random()
you can use SMODS.calculate_effect to run the same effects as a normal return without actually returning
its useful for sending messages and the like
you can also do this
return {
mult = 10,
extra = {
mult = 10
extra = {
mult = 10
}
}
}
how would you create a perishable copy of a card
That's a technology we're talking about
All left for you is cover field in a box with defined w/h, r and no_overflow = true
and it's easy win
got round to testing now, here's a fixed version
if context.modify_weights then
if context.pool_types.Joker then
for _, v in pairs(context.pool) do
if G.P_CENTERS[v.key] and G.P_CENTERS[v.key].attributes and G.P_CENTERS[v.key].attributes.mult then
context.pool[v.key].weight = 20
end
end
end
end
What's the difference between card and self again?
self is prototype object, card is usually an actual tangible copy of it, be it a playing card, Joker, etc.
When would I use self?
Very rarely, but usually for deck objects and/or Vouchers?
would replacing a card's click function require you use self over card?
i just noticed that aikoshen does it for the menu_card that opens solitaire
well
in any method self is an instance of whatever class the method is for
in any SMODS objects this usually isnt useful though, as you rarely need a value from the prototype object
wait I had no idea you could do that...
lifesaver maybe
I'll figure out the finite board first though
and then add an infinite board mode later
is there a good way to stop/kill a sound while it's playing?
how does the extra thing work?
it's like a second return table
how can i have a boss blind trigger an effect if an xmult effect goes off? is there something i need to hook into?
Probably context.post_trigger
Patch or hook into this (in SMODS' game_object.lua), example patch;
# SMODS.Scoring_Parameters patch
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/game_object.lua"]'''
pattern = '''if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 then'''
position = "after"
payload = '''
your code (indent optional)
'''
match_indent = true
Trynna have a joker "choose" a random Tarot when in shop, tried to at least start trying having it choose when added to deck (cuz idk how to instantiate stuff before it gets in shop(yet)), but even it doesn't work (crashes, ability is nil), does anyone know what I did wrong?
loc_vars = function(self, info_queue, card)
return {
vars = {card.ability.extra.tarot or 0,
colours = {
G.C.SECONDARY_SET.Tarot,
{1, 1, 1, 1}
}
}
}
end,
add_to_deck = function(self, card, from_debuff)
self.ability.extra.tarot = pseudorandom_element(G.P_CENTER_POOLS.Tarot, "seed").key
end,
and remember to use events
i have this and it's working fine enough, thank you though
only thing i'm still trying to figure out is detecting xmult on cards
well either you use something like the above patch or you hook into SMODS.trigger_effects I guess
No, that wouldn't work for things that return xmult in extra
oh, okay
card.ability
also what you want is set_ability
instead of add_to_deck
thanks, works! Alas, i don't know how to show it in the description of the card (w/o the localize, it's the c_tarotcardname, and with, its ERROR)
loc_vars = function(self, info_queue, card)
return {
vars = {localize(card.ability.extra.tarot),
}
}
end,
set_ability = function(self, card)
card.ability.extra.tarot = pseudorandom_element(G.P_CENTER_POOLS.Tarot, "seed").key
end,
tried to copy the mail in rebate and other jokers like that too but doesnt work either
this is probably a dumb question but how do i make a joker give extra joker slots while i'm holding it c:
card_limit = number
stole from cryptid and edited it a little, but i want to put the perishable sticker on the created cards
how do
where can i find a sorted list of ranks?
_card:add_sticker('perishable', true)
SMODS.Rank.obj_buffer
ty
why doesn't my joker function? it never seems to give me money
If final hand of round exceeds score requirement, earn $9 at end of round
SMODS.Joker {
key = "j_firedancer",
name = "Firedancer",
config = { extra = { dollars = 9, triggered = false } },
-- pos = { x = 0, y = 0 },
cost = 6,
rarity = 2,
atlas = "placeholder",
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.dollars } }
end,
calculate = function(self, card, context)
if context.end_of_round and not context.blueprint then
if G.GAME.round_resets.hands_left == 0 then
card.ability.extra.triggered = true
end
end
end,
calc_dollar_bonus = function(self, card)
if card.ability.extra.triggered then
card.ability.extra.triggered = false
return card.ability.extra.dollars
end
end
}
is there a plasma deck toggle in balatro or is the only way you can do it is in context.final_scoring_step
you can do it in any scoring step but yes you need to do it manually
Balanced!
i think because when you're doing context.end_of_round, the hand's already been reset back because you beat the blind
and so it will never equal 0
it doesn't reset until you cash out afaik
and by afaik i mean i just tested it but idk if that specific variable is reset for some thunk-ish reason
assuming you're responding to me, this doesn't work either
SMODS.Joker {
key = "j_firedancer",
name = "Firedancer",
config = { extra = { dollars = 9, triggered = false } },
-- pos = { x = 0, y = 0 },
cost = 6,
rarity = 2,
atlas = "placeholder",
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.dollars } }
end,
calculate = function(self, card, context)
if context.after and not context.blueprint then
if G.GAME.round_resets.hands_left == 0 then
if context.hand_chips + context.mult >= G.GAME.blind.chips then
card.ability.extra.triggered = true
end
end
end
end,
calc_dollar_bonus = function(self, card)
if card.ability.extra.triggered then
card.ability.extra.triggered = false
return card.ability.extra.dollars
end
end
}
you can use SMODS.last_hand_oneshot
but it should be hand_chips and mult without the context
ok
so just this?
SMODS.Joker {
key = "j_firedancer",
name = "Firedancer",
config = { extra = { dollars = 9 } },
-- pos = { x = 0, y = 0 },
cost = 6,
rarity = 2,
atlas = "placeholder",
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.dollars } }
end,
calc_dollar_bonus = function(self, card)
if SMODS.last_hand_oneshot then
return card.ability.extra.dollars
end
end
}
i haven't seen this used anywhere else so if this is wrong do pray tell
ok this seems to work with the exception that it doesn't care whether or not it's the final hand of the round
got it working
sorry for the ping
i meant in the context but that's good
how does one find where the G.STATES get set, I cant find them in my lovely dump
I'm tryna make a new state for an addition in my mod
globals.lua in the lovely dump, you have to search for self.STATES because it's set in an initialization function for the G object
happy to help
err lastly what happens if i set a new STATE as the same number as another?
big problems lol
any code that expects the second state will also potentially trigger during the state that you're defining, which you obviously don't want
mmhm
i suggest picking a fairly big number, e.g. my alchemy mod's cauldron state uses G.STATES.QUINT_CAULDRON = 55555
so i js gotta pray any other mod that does smth like this dont got my number
are the numbers innately important? like is higher number mean more priority?
yea i don't think the numbers themselves are relevant, and i doubt any comparisons are being made apart from ==
so you could probably get away with making the state a string that contains your mod prefix
true..
wait holup where am i using this number
because I thought i just use G.STATES.NAME
this was a really good base to consult, tyvm!! for posterity, this is what ended up working (G.P_CENTERS appears to be indexed by joker key rather than table index)
if context.modify_weights and context.pool_types.Joker then
for idx, v in pairs(context.pool) do
if G.P_CENTERS[v.key] and G.P_CENTERS[v.key].attributes.mult then
context.pool[idx].weight = 20
end
end
end
yea you do
but G.STATES.NAME is the number internally
it's just a label that's applied so the code is readable
it is more likely that a mod conflicts while switching states tbh
gonna ask this one again cuz i've been trying to figure it out for a bit now with no luck
Knowing that play_sound('HouseRules_rigoletto', 1, 1) plays my audio correctly, why does the exact same key not work when used from a quip's sound attribute? Should I be using another attribute or doing something wacky with assets/sounds/rigoletto.wav file, say quips dont work well with custom sounds yet? Can't seem to figure it out
Code?
SMODS.Sound {
key = 'rigoletto',
path = 'rigoletto.wav',
}
local function HRcreateRigolettoQuip(quipTag, curType, times)
SMODS.JimboQuip {
key = "Rigoletto_" .. curType .. "Quip_" .. quipTag,
extra = {
text_key = "HouseRules_" .. curType .. "Quip_" .. quipTag,
center = "j_HouseRules_rigolettoHidden",
sound = 'HouseRules_rigoletto',
times = times,
juice = { 0.3, 0.7 },
delay = 0.25,
particle_colours = {
G.C.BLACK,
G.C.JOKER_GREY,
G.C.GREY,
},
materialize_colours = {
G.C.BLACK,
G.C.JOKER_GREY,
G.C.GREY,
}
},
...
Probably nobody can help with this because is already messing with internal code, but i cant change balatro internal sfx even when they have the exact same name and title
are you sure that you converted it into an ogg file correctly?
let me see, just in case
all are ogg
if you just renamed it it likely won't work since there's some other stuff that needs to be changed
but... idk, i will download audacity just in case
Yep, this is correct.
.OGG and .MP3 / .WAV use different codecs (i think), so just renaming them won't suffice.
now it works
Having more problems finding stuff related to this, where is the shop ui made? and how would I copy that so I can have my own ui built in
is an incredibly stupid question but how do u see if/what edition a joker has
I have context.other_joker.edition but uh thats giving me a table and im blanking on how u get the specific type and not the table itself
there are no stupid questions, except for my own
(basically checking to see if another joker is negative, and giving a mult if it is like baseball card)
.edition.negative
oh
thanks
hmm
still getting the error
calculate = function(self, card, context)
if context.other_joker and card ~= context.other_joker then
print(context.other_joker.edition.negative)
return {
x_mult = card.ability.extra.x_mult,
colour = G.C.RED,
card = card
}
end
end,
just testing it right now I know im throwing it in the if statement
nvm i think i found it
dont ask me why I have card ~= context.other_joker
reworked the effect but, forgot
lol
if context.other_joker and context.other_joker.edition and context.other_joker.edition.negative
how do i make it so that hidden consumables can't spawn at all?
Sometimes I wish nils were assumed to be false but I know that is incredibly neanderthal
are they not?
considering I crash
if nil then is false
nvm
im dumb
I mean, still my statement is neanderthal
but thats not waht I was getting at
i see
I guess I meant to say is you can index a nil field, it'd just always return false
idk if im makin sense
if u cant tell im like, incredibly new to programming lol
went to school for it but that was years ago and college is incredibly basic with it
@long sun
[[patches]]
[patches.pattern]
target = "engine/node.lua"
pattern = '''
love.graphics.setColor({0,0,1,1})
love.graphics.setLineWidth(3)
'''
position = "at"
payload = '''
love.graphics.setColor({0,1,0,0.5})
love.graphics.setLineWidth(1)
'''
match_indent = true
setColor table is a list of numbers from 0 to 1, basically HEX() values
yay!! thanks :D
Did anyone else know abt this with dynatext colors?
colours entry has multiple colours:
colours = {
G.C.GREEN,
G.C.RED,
G.C.YELLOW,
G.C.PURPLE
}
yeah?
oh, i mean like did anyone know abt this behavior with dynatext
ah, i see
this is me being in the dark because i can't find documentation on a bunch of this stuff
you and everyone else trying to learn abt dynatext, lmao
that's for localization, not dynatext
Is it even possible to put a card with no edition in the editions menu because every time I say to put one with no edition (to mirror vanilla's "base") my coder for some reason creates a new edition just with no shader
how do you think localized text works?
Anyone knows why it doesnt work?
its supposed to be a 1 in 4 chance of applying a random edition to a scoring card
my point is im currently working with (or at least studying) dynatext via DynaText() not localization
I'd bump it to 1 in 5
Is base treated as an edition itself or just with no edition
it isnt
So no edition
even if it was it whould say "Upgraded!"
It is an edition, but a card cannot have it.
it doesnt even says "Upgraded!"
I'm asking because putting another "base" card in the editions menu to mirror vanilla's seems like the most straightforward thing ever yet it's the one thing I've had the most trouble conveying apparently
Like I tell the coder bar for bar "Add a rekoj with no edition to the editions menu make the name and description the same as vanilla's "base""
But they create a new edition anyway and apply that to it instead
So I'm wondering if what I'm asking is if it's even possible
whatever im just gonna give it another ability
if context.individual and context.cardarea == G.play and SMODS.pseudorandom_probability(card, self.key, 1, card.ability.extra.odds) then
local edition = SMODS.poll_edition({guaranteed = true})
context.other_card:set_edition(edition, false, false, true)
return {message = localize('k_upgrade_ex')}
end
is there any way to make this happen? i've been trying to make it occur before the crash but i can't seem to make it work
why is it that in my patch that it cant seem to find the line in the script?
[[patches]] # Set up cardarea for the state PERK
[patches.pattern]
target = "cardarea.lua"
pattern = '''({[G.STATES.SHOP]=1, [G.STATES.TAROT_PACK]=1'''
position = "at"
payload = '''({[G.STATES.SHOP]=1, [G.STATES.TAROT_PACK]=1, [G.STATES.PERK]=1'''
match_indent = false
I've tried several ways, removing certain parts from pattern, making match_indent true and false, but it doesnt seem to beable to find it
I know i have the pattern's string right but it still refuses to find it
Have you tried preventing the crash, then triggering the crash?
The pattern of pattern patches needs to be the entire line.
I've also tried that
I've copied the entire line
but i guess ill try again regardless
i'm not sure how i would prevent the crash, but i'll attempt this.
Nvm i mustve missed smth before ty though
im running into a problem where if u have 2 of this joker, uh, it makes your money negative
if context.setting_blind then
if G.GAME.dollars > 0 then
return {
message = 'DEATHKILL ONLINE',
ease_dollars(-G.GAME.dollars),
colour = G.C.MONEY,
delay = 1.2,
}
end
end
probably not explaining this correctly, but in my screen cap selecting the blind sets my money to -1
when it should be 0
local oldcardload = Card.load
function Card:load(cardTable, other_card)
if not G.P_CENTERS[cardTable.save_fields.center] and cardTable.save_fields.center:find('modprefix_') then
error 'message'
end
return oldcardload(cardTable, other_card)
end
Wait
I can just multiply your dollar amount by 0
this feels a little duct taped, but w/e
No, put true as the second input of ease_dollars
That worked thank you
Fixed another joker that does ease_dollars similarly
❤️
where the hell does the reroll button have the function to reroll the jokers, like not the function itself but more the part of the script that calls the function
i cant find it anywhere
How to reset a value at the start of a new run
hi
yay
im still heavily confused on this
probably in button callbacks
well thats the thing
ive looked everywhere
for the past 30 minutes
i can only find G.FUNCS.can_reroll()
I found G.FUNCS.reroll_shop()
