#💻・modding-dev
1 messages · Page 657 of 1
i mean i don't want to wholly ban vanilla jokers on this deck
What you could do is add all of your jokers to a pool and pull a key from that pool on context.create_shop_card when the chance hits
Is there a way to prevent a joker from being targeted by something
that's what i've done so far, though i'm unsure how to only pull the key, like i know you can do smods.add_card{set = "modprefix_jokers"} but that creates the card
Like say the banana command I got can I make it where it can ignore specific jokers
you can just return the set in that context for it to create the card
you dont need to grab the key manually for this
Kinda yeah
Got a command that can replace a joker with a banana
But I got a couple ones I wanna make where won't target them
So u can use those to battle back against chat messing with your stuff
Yes, you would check if card.config.center.key ~= 'j_modprefix_key'
so would i do return {set = "modprefix_jokers"} in this case, or just return "modprefix_jokers"?
The first one
neither
Wait no
astra can probably type it faster
return {
shop_create_flags = {
set = ‘modprefix_jokers’
}
}```
Like this?
if G.jokers.card.config.center.key ~= 'j_ttv_f'
if #G.jokers.cards > 0 then
G.jokers.cards[random]:set_ability(G.P_CENTERS[RanCreate])
end
end
end
end```
G.jokers.card is not a thing
ty both
forgot the s but more or less is this right
I PR’d that system too so I feel silly for forgetting the shop_create_flags key lolol
wait should it be set or pool since the mod jokers are still in the joker set they're just in their own custom pool
Set
no that's still wrong, i dont usually correct typos by saying that lol
the problem is that G.jokers.cards is a table of cards not an individual card
The set argument also allows custom pool keys
i dont know what you want to do since i wasnt readying your conversation but the basic logic for that condition is wrong there
then you need to check that G.jokers.cards[random] is not that
and reroll if it is i guess
or you can make a table without the joker in the first place
whenever a joker gets replaced i crash with "attempt to concatnate local 'rarity' (a nil value)", and i don't see any of my files in the traceback, did i go wrong somewhere that i can't see?
looping P_CENTERS directly before load wont have modded jokers
ah
-# i probably would have caught that given the print on 1418 but i just had that there to copypaste into eval
i have code that dynamically adds jokers from my mod to a pool if you need it
how would i make sure it runs after load then? and yeah that'd be good to look at sure
i dont really use these so it might not work correctly
specifically i just realized it might add things twice after language is changed
yep lol
i never noticed before
but the logic would be similar, you just need to hook another function or add a flag to that one so it doesnt run twice
does :inject_card handle rarities as well?
no, you would still need to add that
why does using this crash the game? how do i index the seal?
you're passing a table containing the seal key not the seal key
Use card.ability.extra.seal instead of card.ability.extra
how would i manipulate edition's probabilities
a specific one or all
all
you can use G.GAME.edition_rate but its not guaranteed modded rarities use it
the easier way i think is to hook poll_edition
i just want to mess with vanilla rarities for now
then just use that variable
so if i wanted to boost negative edition, i just do G.GAME.edition_rate.negative ?
no, it's global
if you want one by one you would need to hook the get_weight functions i think
each edition's individual weight includes G.GAME.edition_rate in the formula
i see
Is there a way to make a return message linger for a bit?
delay
Merci
cryptid code is unsightreadable, how do i make a SMODS.Blind function that updates constantly (like every frame or so)
i dont think you can with the api, you would need to hook update
well i have a variable in an update hook, but idk how to...
i want to update the blind locs every frame
i have the variable that gives me the value i want to change them to
but i dont know how to force the locs to update with the variable
like what, do i just shove G.GAME.blind:set_text() in the hook???
ah that i dont know
i know set_text has some problems because i tried just that and it didnt update properly
pain
i cant read through all of these tables to try figure out how tf cryptid does it
it hurts to look at
Likely the timer variable there is used in a patch to handle the text
So I'd look for any references to patience_virtue_timer in toml files
Where are the rarities and keys of jokers stored?
G.P_CENTER_POOLS.Joker
So, how would I check if an owned joker's rarity is one in particular, or if it is a particular joker?
ah i get what youre saying now
joker:is_rarity(rarity)
joker.config.center.key == "key"
Thank you!
prolly stupid question but how can i get the hand size value
G.hand.config.card_limit
i tried that but i got this
Code?
oh wait the crash only happens if i hover over it in the collection in the main menu
key = "rw_gourmand", --name used by the joker.
config = { extra = { xmult = 1, mod_xmult = 0.25 } }, --variables used for abilities and effects.
pos = { x = 0, y = 0 }, --pos in spritesheet 0,0 for single sprites or the first sprite in the spritesheet.
rarity = 3, --rarity 1=common, 2=uncommen, 3=rare, 4=legendary
cost = 0, --cost to buy the joker in shops.
blueprint_compat=true, --does joker work with blueprint.
eternal_compat=true, --can joker be eternal.
unlocked = true, --is joker unlocked by default.
discovered = true, --is joker discovered by default.
effect=nil, --you can specify an effect here eg. 'Mult'
soul_pos=nil, --pos of a soul sprite.
atlas = 'rw_gourmand', --atlas name, single sprites are deprecated.
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mod_xmult, card.ability.extra.xmult + math.max((card.ability.extra.mod_xmult * (G.hand.config.card_limit - 8)), 1)} }
end,
calculate = function(self, card, context)
if context.joker_main and context.cardarea == G.jokers then
return {
x_mult = card.ability.extra.xmult + math.max((card.ability.extra.mod_xmult * (G.hand.config.card_limit - 8)), 1)
}
end
end
}```
(G.hand and G.hand.config.card_limit or 0) - 8
ok thanks
well now it seems the localization file decided to misbehave ingame
it still gives 3x mult like its supposed to it just isnt displaying it properly
wait nvm it just straight up doesnt work with the or 0
So, I've got this calculate function, with the intent to give a value of x mult for each of one kind of joker, and a different value for each of a different joker. However, the return ends the loop, so it only happens for the first card. Now, the question being, how do I get around this, so that it triggers on every applicable joker?
calculate = function(self, card, context)
if context.joker_main then
for i = 1, #G.jokers.cards do
if G.jokers.cards[i].config.center.key == "j_willatro_swooned_joker" then
return {
message_card = G.jokers.cards[i],
x_mult = card.ability.extra.small_xmult
}
end
if G.jokers.cards[i].config.center.key == "j_willatro_black_knife" then
return {
message_card = G.jokers.cards[i],
x_mult = card.ability.extra.big_xmult
}
end
end
end
end
Thank you again, oh wise one!
nvm issue is magically solved
for quantum enhancements would a card that has both quantum lucky and regular lucky trigger differently in any way or just treated the exact same as regular lucky
to be fair i don't see any differences 😭
how do i make a mod description uibox thingy
i can't figure out how to SMODS.current_mod.custom_ui
i said uibox
what uibox
--how do you copy a joker's ability "again"?
calculate = function(self, card, context)
if context.ante_change then
SMODS.scale_card(card, {
ref_table = card.ability.extra,
ref_value = "repetitions",
scalar_value = "morerepeat",
colour = G.C.RED
})
end
local other_joker = nil
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i + 1] end
end
for _ = 1, math.min(card.ability.immutable.max_retriggers, card.ability.extra.repetitions) do
local ret = SMODS.blueprint_effect(card, other_joker, context)
if ret then
ret.colour = G.C.RED
end
return ret
end
end,```
Heelppp help mee
like this
You need to use SMODS.merge_effects
return SMODS.merge_effects?
No, you would put every ret in a table then do SMODS.merge_effects(effects)
No, then retriggers wouldn't work and the timing would be wrong.
SMODS.calculate_effect only works for returns that are evaluated via SMODS.calculate_individual_effect
Which is just scoring, messages, func and dollars
and extra
Everyone is telling me to use merge_effects, ill do this when I come back
local other_joker
for k, v in pairs(G.jokers.cards) do
if v == card then other_joker = G.jokers.cards[k+1] end
end
local effects = {}
for i=1, math.min(card.ability.immutable.max_retriggers, card.ability.extra.repetitions) do
local effect = SMODS.blueprint_effect(card, other_joker, context)
if effect then
effect.colour = G.C.RED
table.insert(effects, effect)
end
end
return SMODS.merge_effects(effects)
Bump
how do i forcibly discard something
SMODS.Joker {
key = 'repeater',
faction = 'resonance',
rarity = 3,
atlas = AA.G.JokerAtlas.key,
pos = { x = 0, y = 0 },
config = { extra = { repetitions = 5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.repetitions, card.ability.extra.repetitions > 1 and 'times' or 'time' } }
end,
calculate = function(self, card, context)
if context.repetition and context.cardarea == G.play then
if next(context.poker_hands['High Card']) then
return {
repetitions = card.ability.extra.repetitions,
message = localize('k_again_ex')
}
end
end
if context.after and not context.blueprint and not context.retrigger_joker then
if next(context.poker_hands['High Card']) then
local held_cards = {}
for _, v in ipairs(G.hand.cards) do
held_cards[#held_cards + 1] = v
end
if #held_cards > 0 then
-- discard cards here
end
end
end
end
}
G.hand:add_to_highlighted(card); G.FUNCS.discard_cards_from_highlighted()
i dont want from highlighted tho
i just want to wipe the entire hand in this instance
Yes, you would highlight every card in hand then discard the highlighted cards.
oh i see what ur saying now
okok
should i attachthis to an event
actually
if it scores the high card, ill set a config flag
then ill check post scoring for that config flag as well as the conext
the context sets the flag to false again, then discards
its buggy rn
wait im tired i already did that
yeah ill wrap it in an event
and then take the discard out of the loop\
thats what was breaking it
I just woke up is this the bootleg thing lol
Eyes are still crusted over
yes 😭
does it look similar?
i genuinely cannot tell what i need to do based on your image 😭
Like I said it's fine if you couldnt
Probably gonna be scraping the bootleg idea and just merge them into the twitch pack
Because how little jokers there are
Too many default jimbos
can you like describe it, my eyes are not master
the bootleg idea or the shader
really hard to explain the shader other than the few pictures I showed lol
guess it's one of those things you had to have experienced first hand to understand the look of it
maybe this is a better photo
Is latest SMODS break assets loading or smth
Why this crashes? File 100% exist for 1x and 2x
is the png named the same thing
and in the assets/x1 and x2 folder?
looks like it can't find ur sprite sheet
It works on stable SMODS but on latest it is not for some reason
i'm on the latests dev haven't had that issue
redownloaded it and fired it up and looks like it's working fine for me
1408c
maybe its another mod causing the crash?
I see
hi i hate ui anyone know why the text isn't being put on separate columns?
{n = G.UIT.R,
config = {
align = "cl",
padding = 0.2,
minw = 6
}, nodes = {
{n = G.UIT.O, config = { object = ellecard }},
{n = G.UIT.C, config = {align = "cl"}, nodes = {
{n = G.UIT.T, config = {text = "A mod by this goober.", scale = .4, colour = G.C.WHITE}},
{n = G.UIT.T, config = {text = "(and featuring her characters)", scale = .3, colour = G.C.WHITE}}
}}
}}```
@keen atlas your utils break atlases loading. You probably delay constructing atlases image and image_data, but while game already started and starting animation appears, atlases is not ready and as result it crashes
thanks for more info
I added prints to see is creating smods atlases work at all and it fixed an issue
Looks like small desync or smth
columns, or rows?
Game dont like when you combine different type of UI elements
Wrap G.UIT.O in G.UIT.C
No, game dont like when you conbine G.UIT.R and G.UIT.C in same parent (it freaks out)
ah
ty it works now
i love balatro uiboxes they're totally not scuffed at all in the slightest
I really should consider full balala UI course or smth
what would be a good condition to be met to spawn a banana
1 in 6 chance with each played hand?
well thing it want to make to work with a this
so you don't have a dead joker if u get it and can't find a banana
probably gonna remove the banana command
i mean
you still have a dead joker if you find monkey and not other one, regardless of the conditional
should be fixed now
curious what it was
smods.atlas was called before the hook is initialized
I see
its this two
SMODS.Atlas {
key = 'mod_tags',
path = 'mod_tags.png',
px = 34,
py = 34,
}
SMODS.Atlas {
key = 'achievements',
path = 'default_achievements.png',
px = 66,
py = 66,
}
yeah no you can scrap that idea 😭
Can I somehow get regular game dump, not modified by your utils? I cant files I'm looking for
lol
that's a bummer, but I may be able to live with it
i tried man
no time man
I have different issue
Holy shit I found why deck blinds in deck selection menu and fixed it
And you know what? it was caused by quantum enhancements
quantum enhancements...
i finally added this
cool
@wintry solar I found what cause of deck blinking on deck selection. You know what is this? Quantum enhancements 
I need a bit your help with fixing of this thing because it looks so wrong and by itself should cause a LOT more issues
regular day in SMODS development land
This issue is like 4 month old and no one ever tried to check out
I'll explain what causes it in smods discord
no one tried because it's a galdur-less issue for galdur-less people : )
i think it's not a quantum enhancements thing, it looks like it was the patch to make it so set_ability properly resizes the card
how do u add multiple sets of jokers to a booster?
any idea why this patch isn't working?
you can't match mid line like that iirc
do u have to use pools for multi sets of jokers?
return {
set = "ttv_Temu_jokers", 'jokers',
edition = "e_ttv_bootleg",
area = G.pack_cards,
skip_materialize = true,
soulable = true
}```
or am I capatble of doing it this way in boosters
set can be only one string per card.
set = 'Joker'
And no, the t.set check only does strings.
However, you can use i to determine what card should use regular set or your own, being a number.
trying to add the vanilla and custom jokers into it
so any joker that comes from it is a bootleg edition
I can use pools
for the custom jokers
but need away to add the vanilla jokers
Then just use the set = 'Joker', really.
If you want to guarantee the first generated card to be from your own pool, then set = i == 1 and "ttv_Temu_jokers" or "Joker".
Conditional definition.
set can only be a string.
But with that, if i == 1, then the string will be "ttv_Temu_jokers", otherwise, "Joker".
oh so like when the jokers get low starts using vanilla jokers?
just trying fill the pack with jokers so jimbos don't appear
where would I have to patch to get purple seals to act as gold and blue seals?
Ive gotten red seals working but not the other 2
wait i'm dumb if I just put joker that means all custom jokers show up to lol
All, yes.
thanks
works
main issue is i'd still like it to be random
not have the temu jokers always in front
but this works for now
nvm got it working
just have to make a random number thing later
how do you change the pos of a Sprite?
sprite:set_sprite_pos({x = num, y = num)}
thanks ^U^
Is it possible to refresh or reroll booster packs in a shop?
in localization , there are j_ for joker ; v_ for voucher ; c_ for consumable , what is poker hand and rarity?
nothing
those don't have class prefixes
(they do still use your mod prefix of course)
...well, rarity is k_modprefix_key.
oh right that's a thing
i don't think it's a class prefix per se but idk what it is. it acts like a class prefix except for the part where k doesn't stand for what it is
that's only for localization tho, it's not the class prefix
it's not k_prefix_rarity in-game
and the locs also have to be in two places and be lowercase so they have more quirks
-# True-
oops doesn't increase the odds text
might have to nerf or make the monkey joker rarer
are you using the probability vars functions for it
loc_vars = function(self, info_queue, card)
local new_numerator, new_denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_ttv_monkey2')
return {vars = {new_numerator, new_denominator}}
end,
just oops and the two jokers made it to ante 5
you think that's balanced or broken with a 1/4 odds?
to basically get a free 2x mult
anyone know what the delay_sprites argument in set_ability() is?
It, well, adjust how sprites behave
by default when you set ability visual looks changes immediately
But you can pass some values to adjust it
It makes it so the sprites are set in an event.
Like when Vampire eats ehnancements they're delayed
vampire uses it; other cards might not want that
depends on when the setting ability happens, really
how do i use it to set the card's atlas pos when it's made
card.children.center:set_sprite_pos()
or other function which sets atlas and pos, cant say which one from my head
in Other ?
ty
thanks for your help
updating to lovely 0.9.0 caused this line to break
this previously formed a full path but idk what to use now
now crashes with the error [SMODS Lemniscate "modules/shaders.lua"]:46: Could not open file C:/Users/[redacted]/AppData/Roaming/Balatro/Mods/AlexisFinishers/assets/shaders/raised_spiral.png. Does not exist.
@rough furnace fuck it you probably know what happened here
I'm not familiar with sandboxed mod path is that a smods thing?
Curious your loading a PNG from your shaders folder
it's a resource used by a shader
and sandboxed mod path is a variable my mod stores
kind of a misnomer
How is it defined?
Also is this with the new smods or just new lovely
Its more likely I broke something path related in preflight than lovely broke something
Actually I think I normalized the path it probably would mess with a path trimmer
You probably should be using SMODS.NFS (or the NFS glovla pre preflight) so it works no matter what the mod dir is
E.g. https://github.com/Steamodded/smods/blob/bbaffdee3bf10b3b6496f693dd932de8720e40d9/src/core.lua#L19
Just change that to your mod.path and probably don't need the legal check
both new smods and lovely
Lovely shouldn't have changed anything but preflight likely dif
ah
The method your using probably didn't work on Linux with default config, and if someone changed their mod path, and will probably break with zip loading too
ah
now i have to rewrite my entire mod's loading code i guess
Nativefs is a drop in replacement for love.filesystem
ok this would've died on linux anyway
But you probably will need to anyways to support zip loading
I could probably make a patch if you wanted and I had the code
good luck with that tbh
I've touched some bad code @gaunt thistle
i also have this massive thing that's supposed to load before any other mod
Oh your already using NFS
yea there at least
It would just be the sandbox stuff you worry about
also have this lovely patch
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
# Load multiple library files before other mods can load
## loadMods()
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/loader.lua"]'
pattern = '''boot_print_stage('Loading Mods')'''
position = "before"
payload = '''
-- Lemniscate: Initial Loading
-- Many items, including added classes and many tables, are forcibly loaded early for mod compatibility purposes
boot_print_stage("Lemniscate: Initial Loading")
-- find mod directory
-- gets replaced later by the path from the SMODS mod object
local info = NFS.getDirectoryItemsInfo(modsDirectory)
Lemniscate.mod_path = ""
for i, v in pairs(info) do
if v.type == "directory" and NFS.getInfo(modsDirectory .. "/" .. v.name .. "/Lemniscate.json") then
Lemniscate.mod_path = modsDirectory .. "/" .. v.name
break
end
end
-- load init.lua
local lem_init_path = Lemniscate.mod_path .. "/modules/preload/init.lua"
local lem_init, err = NFS.read(lem_init_path)
if not lem_init then error("Error reading file '/modules/preload/init.lua' for mod with ID 'Lemniscate': " .. err) end
local chunk, err = load(lem_init, '=[SMODS Lemniscate "/modules/preload/init.lua"]')
if not chunk then error("Error processing file '/modules/preload/init.lua' for mod with ID 'Lemniscate': " .. err) end
if err then
sendErrorMessage("Lemniscate :: Failed to load /modules/preload/init.lua with error: " .. err)
else
chunk()
sendDebugMessage("Lemniscate :: Loaded library file /modules/preload/init.lua")
end
-- Start actual mod loading
'''
match_indent = true
Oh cool I broke that
guh
New loafer dir
oh god
Why are you manually figuring out your path?
It should exist at that point I think?
because i'm dumb and decided to reference talisman's code
Do you work without smods?
no
i'm already realizing doing that was a bad idea
since i can just get the path from SMODS.Mods.lemniscate
Also I think SMODS.load_file also exists at that point
good to know
what do you load before other mods?
currently a few classes and tables that i want other mods to be able to access regardless of priority
I dont like this part at all
well i can get rid of it now with nfs
It probably would be simplest to just put your code that loads sooner in a alua file, add a lovely module then add a a patch that requires your module
Your also assuming it's in a folder called balatro which isn't even the case in every default case
yea
So what you're trying to do
now Lemniscate.mod_path is just defined as SMODS.Mods.Lemniscate.path in the init patch i posted
also this is an example of the sort of thing i'm loading early
wdym
nvm I see
fyk you can get your sandboxed path properly by removing part returned by require("lovely").mod_dir
it returns mods folder
ah
tbh i wouldn't be unwilling to rewrite the loader code again
the ui code is staying messy though
Also if your zip loaded your sandbox path is some weird shit like __SMODS_MOUNT__/mod.zip (possibly with a folder in it)
my mod will immediately crash if it has a nested folder so
yea
That's how I load mod at all, very hacky probably
If a zip has a folder both smods and lovely habdlr it correctly but it will be a folder deeper in the internal smods mount
Smods provides NFS and the mod.path will always work with it. BTW the NFS global isn't Recommended for newer smods you should use SMODS.NFS (local NFS = SMODS.NFS of NFS for compatibility
I can do that
i can just use smods nfs
I cant afford this luxury
I was loading all filed via modules before but I decided to enough
debugplus localization when
Its not a high priority
I suspect the next lovely build might provide some sort of fs api, if anything to help mods that are zip loaded
nice
Well 2.0 release is a good pivot to check out zip mods loading at all
cant say I'm super in it but generally a good direction for modding
Maybe kinda late but definitely good
Unfortunately if you don't have smods you habe to manually find your zip file and then mount it to access the contents
eh?
there's no api for it but you can
is it even possible to patch into files in preflight
hi. im gonna be annoying and ask a question i asked a few days ago... im still confused on it.
how do i detect when a specific joker (ex: jolly joker) is in your possession?
How do you roll for booster packs like the game does?
Also how do you get the amount of booster packs that the shop can store?
it returns a table of the found cards (therefore the next) so you can also do ipairs loops or stuff with it
check SMODS.add_booster_to_shop for both answers
Along with getting the boosters themselves to spawn?
Sorry for all the questions but yeah- oh thanks
what's the smods wiki page for ipairs?
ah.
so check the lua docs i guess
So you want to say that I need to figure out is mod in archive firs, if so - mount it and only after that do stuff right
that explains why im struggling so much
it just iterates over every integer index of a table, starting at 1 and ending before the first nil value
Yeah (you can use the lovely hack to get your mod path and then just kinda check if it's a file or folder)
I mean. Makes sense to me. Unless lovely were to somehow provide it
looks easy for me
i managed to do it in jokerdisplay with negative knowledge of how lovely works
Yeah just not as easy as NFS.whatever(SMODS.current_mod.path)
I already have lovely hack mod dir
What file would that be in?
Basically a way how I load mod
I'll take into account this nuances, thanks
new smods murdered my mod i guess
unless i want to split it in two just to load the classes separately
incredibly annoying honestly
can't load this early anymore
yes
Definitely possible
You can still patch the loader its just a new path
somehow i haven't been able to patch it but i'll try
Basically I load my mod before other SMODS ones (sometimes it's a problem), probably that's type of behavious you're looking for right
Its something like =[lovely SMODS.preflight.loader "src/preflight/loader.lua"]
DebugPlus just patches into the main file to load sooner than other mods
Makes sense because you intented to load asap
Yeah but you could patch the end of it before SMODS core
thx
anyway, I need to implement + test zip loading & make new release
tried this and yeaaaaaa
Oops! The game crash
this game fault down the stairs
I dont like that NFS.mount still relies on love2d implementation which uses relative paths
So I need to get relative path

yea i know
When this happens you can still copy the ereor
I can't find the booster limit in the function, I'm guessing it's G.GAME.shop.booster_max?
good to know
i just checked logs
it's in the one below that i think
It's just extra boosters which I'm guessing modifies the limit
I hope to fix that in the crags handler rewrite
Oh thx
are you able to help test this on linux by any chance
Yeaj
alrighty
i'll send it via dms if that's fine by you
Sure
I hate .mount because there's no way to tell which folder was as input and which as output
it doesnt work and I cant say why because literally no info
oh yea, I forgot that nativefs ignores what mount does
you have them set to friends only
Peak files loading
is Handy.NFS just SMODS.NFS or NFS
False
did the steamodded thread stop existing?
You might though
oh yea i do
to prevent bot spam
Yeah discord doesnt allow you to send me a DM if I could respond to ot
damn
seems like it
guh
good time to put it in #1456641762591510671
at mods
Question aboutSMODS.calculate_effect. Is there a way to make the message appear at the top of a card instead of the bottom?
no, it's hardcoded based on the area
I think it's actually based on screen position iirc
dang, loading from zip a bit trickier than I expect. This mount is stinky
without archive my setup with mounting works, with archive dont
oh nvm
Oh come on
it's using the zip dir path
couldn't you theoreticly patch something then?
okay I see. i'm working on an effect that can target some cards being drawn before they arrive into your hand, and i wasn't liking the text being at the bottom
probably have to hook the deck as a location with a specific placement, if i'm right about that
I mean I dont care how SMODS loads own stuff
My stuff loaded properly
Why SMODS fail
yeah you almost always can
cant you use an event so it displays after theyre drawn?
If this such a headache I can load mod icon image manually, no problem
for what i'm doing, i would prefer the instant message instead of after they are drawn
are you messing with your mod object path?
smods isn't using the right path for zip loaidng
All I do is
Oh I see what you're mean. I mounting archive to temp dir where I can load stuff
Random bullshit go
in that file can your print SMODS.current_mod.path and SMODS.current_mod.load_type
oh I am thinking of tooltips nvm
...wait, discord appears to has removed the ability to search for posts from specific people? 
I found it by searchng for steamo
something in N's discord probaly broke or weird discord issue
i can search by people fine
just not aure in modding
now i can lol
ah yeah
actually nvm It's my issue, I'm loading atlases manually aswell and I forgot to change path
weird because i clicked on the name but i might have backspaced
in other mods, (at least in the yahimod) i see the function message = "" (which makes a joker have a custom string under it) but when i use it, it crashes my game, how do they do it?
whats the crash
calculate = function(self, card, context)
if context.joker_main then
...
message = "AHHHHHHH"
oh
calculate = function(self, card, context)
if context.joker_main then
...
return { message = "AHHHHHHH" }
return {
card = card,
message = "AHHHHHHHH"
}
end
you dont need card
ohhh
oh neat
if you want to change the card use message_card instead
do you only need card if it modifies a scoring value?
you never need it
That's wild. When it loaded from zip it doesnt appear in mods list anymore but still works
And crash logs are scuffed
I guess I need leave zip shenanigans for next day, too much stuff is happening here
oh
whats the point of it?
it's used internally, i think it used to be set manually but now smods does it automatically
ah
i think it might have been needed as a result of thunk's "put everything in one big calculate" methodology
@rough furnace now game starts and mod fully works etc etcm but SMODS doesnt know about existence of my mod anymore
All I did is mounted archive content to other folder, that's it
and this is the dev branch?
can i see logs?
I'm checking on latest release
zip mods don't work on latest rleease
hm, I'll check latest then
this is what Big Calculate doesn't want you to know
I dont liek the fact that I need specific smods version for this to work
smods needed changes and there hasn't been a release since they were made
Where are cards when they are drawn to hand? Are they in some sort of limbo state? Or is there a way to tell?
card.area has the area but it will be either G.hand, G.deck or nil
On latest SMODS again filed cannot load, I guess they're extracted to somewhere else or executed from different place right
yeah the zip is mounted and then theres a special hack to nfs to allow it to be used like a normal dir
oh my god that's such a headache
I need more time and pation to make it work probably
Not today for sure
I can take a look later if you want
if you were relying on a patch to loader that would have broke
I cant say for sure what is wrong anymore
seems to be nil. check in place and things seem to be working as intended
how do I get a joker to play a sound at the same time a message occurs instead of when the hand is played?
SORRY FOR ASKING SO MUCH
You beat me
dw this is what the channel is for
Don't feel bad for asking!!
people who ask lots of questions are awesome
The more questions you ask, the more you learn, the better you are at making mods
thank you guys 🥹

no useful info in crash so instead I can filly explain what I'm doing and where things go wrong
maybe it's useful to me but explanation probably helps too
put it both before and after the message and it just does the same thing D:
So I'm setting up mount for mod folder in next way
That's case for folder, all works as intented, mod and SMODS is happy
may i see the code
For reading file data I'm using this. Handy.LOCAL_PATH is where mod was mounted to
In case of folder all files is found and all fine. In case of .zip it cannot find files so crash
you're method can't find files or smods can't?
calculate = function(self, card, context)
if context.joker_main then
return {
play_sound("moneyprinter_scream"),
message = "scream.mp3",
}
swapping did nothing, obviously its not ACTUALLY an mp3 just no one knows what an OGG is
my method
it has to be sound = "moneyprinter_scream"
i.e. love.filesystem.read("/Mods/HandyBalatro_39874283/src/...") is retuning nil
While same thing as folder return file as intented
how do i get whether a given mod's over a certain version?
print love.filesystem.getDirectoryItems("Mods/HandyBalatro_XXXX"
in my mod i'm using love.graphics.newImage( love.image.newImageData(NFS.newFileData( SMODS.current_mod.path .. "assets/palettes/"..v.path) ) )
THANK YOU
empty table
when does your code run?
so that would be after smods loads mods then?
check V
?
V("2.0.0") > V("1.5.1")
np
So this means SMODS already mounter this archive and second mount just does nothing
seems like it
It will be at __SMODS_MOUNTS__/File.zip (possibly nested)
you can also just use SMODS.NFS on the mod.path
so you cna SMODS.NFS.getDirectoryItems(SMODS.Mods.Handy.path) (or whatever you id is)
even while zip loaded
I'll see if the only mount once is a nativefs thing and if so, if I can fix it
If I unmount it SMODS will explode right
only if it needs to access your files
probably
I could probably expose the path on the mod object
okay other question, is check local use_native_fs = (SMODS and SMODS.NFS) or not SMODS and true or false valid
I think so
remeber the path that works with smods is not the one lovely provides
I probably would just check if the mod object exists in smods and if not smods doesn't supoort zip loading
but if smods is present you should be able to use (SMODS.NFS or NFS) to access your files using mod.path
That's not enough because I need check is current version of SMODS supports it in a firt place
if it doesn't support it there won't be a mod object for your mod
In this case game will crash trying to log my mod
One minute
I guess it depends how you handle it
In case of release SMODS this happens
it tries to call SMODS.log_crash_info and it tried to index my mod as SMODS oe, but it doent exist and explode
oh you're using the SMODS api someow?
Is there a generator for legendary joker back textures?
the assert helper should't crash not sure who made that i'll see what I can do later
you can see that source = SMODS
but mod is not loaded into smods at all
It is not present in list
that should be handled better because anyone can set those to any arbitry string
I'll give up for now. I spend 2+ hours messing aroud with it
At least it was fun
I can make separate branch so you can test it on my mod
what happened 😭
We trying to implement loading from archive without smods
rust using the lua c api
mount function sucks so much so far
ethan you should invent a new filesystem for balatro modding
you should invent a new os for balatro modding
just invent, doent matter what exactly
GambleOS, the polar opposite in every way to TempleOS
@rough furnace here's separate branch with all I was done to try to make it work.
Again, sorry for spending your time. https://github.com/SleepyG11/HandyBalatro/tree/v2.0-archives-loading
All this is optional so if you dont want that's okay, I can live with folders for a while
Thanks
Where is the code for calculating glass cards at?
smods game_object
thx
you should take ownership for this one
patching time
how does that work?
ive never done that before
you will see an example there because thats what smods does
amazing
oh okay looking at this i just need to change a number into a table lookup
would it be better to patch it for that?
how do i detect player losses
context.game_over
is there a way to change the sprite of the current joker
card.children.center:set_sprite_pos({ x = #, y = # }) will change the sprite position of card to whatever you want (on the atlas that it was initialized on)
is there a function that's called on the joker when it's created in the shop?
create_card_for_shop
awesome thx
there's also two calculate contexts, context.create_shop_card and context.modify_shop_card, that might be more helpful for what you're trying to do
(what are you trying to do exactly?)
while playing my mod, i noticed one of my multi-form jokers was created in the shop with the wrong graphic. so i want to force it to be a specific graphic when created in the shop
so i think context.create_shop_card would be best
nope
hang on lemme find this
I had the same issue
for that, you should actually handle it with the set_sprites function in the joker
with melt ice cream
i haven't used the set_sprites function ever since it started creating errors that i brought here and no-one knew how to fix. i change the graphic a different way
set sprites is just a function thats called when the sprites are set
set_sprites = function(self, card, front)
if card.ability and card.ability.immutable and card.ability.immutable.atlas_index <= 3 then
card.children.center.atlas = G.ASSET_ATLAS["foo_FooJokers" .. card.ability.immutable.atlas_order[card.ability.immutable.atlas_index][card.ability.immutable.atlas_type or 1]]
card.children.center:set_sprite_pos({x = 0, y = 0})
end
end
ignore the atlas assignment I was doing a stupid
chat how do i recalc_debuff in mod.calculate?
You mean you want to debuff a card in mod calculate?
ive been informed i should use SMODS.current_mod.set_debuff instead
errr I'm trying to understand how shortcut works so I can make a similar hook, but all I'm finding digging through the code is the hook itself which returns true and calls it a day. Where should I be looking to find what I'm looking for, here?
function get_straight in smods overrides
ok so I should probably create a hook on get_straight and change my function there
that tracks
idk what youre trying to do so i cant confirm
Trying to allow a single gap in straights indicated by a king, so like, 1-2-K-6-7 that's a straight
Its definitely a straight check
then yeah probably
I removed a patch done from a .toml file but it still shows up here, anyone know what's up?
im assuming you closed the file and ran the game again
It updated when I booted up the game again
meaning that something's putting the patch in still
I tried removing that patch in the dump but it didn't work
yeah that wont do anything
Where do I go to get rid of the patch?
the toml file
I already got rid of it from my mod
then you either didnt save or there's a second copy or something
Uhhhh nvm it works now
god dammit tickini...
Anyone know a better way to implement this?
how do i run the round win check?
wait i think i found it
nvmd
bc i'm testing something that increases the score outside of the scoring loop
nvmd i found it i think
fr ithis time lol
(i just do the comparison myself and then end_round())
needed to do a bit more but i just referenced the dp code
was trying to follow the steammodded guide and got this warning on the cmd line
Oh god we should remove that from the guide
wait what?
what am i supposed to do then?
Download the latest release
Or if you are desperate to use git you need to target the stable branch
im a bit confused. i already have steammodded on my mods folder, but i assume for development it's a different thing i need to download?
i dont really want to use git
it just confuses me more
download zip
the put smod-main folder in %appdata%/roaming/balatro/mods
aight
2 smods
delete the old smods
ok
it had come with the polterworx modpack
so when i create a new mod should i keep it in the balatro mods folder from the start?
Yes
uhh
Most undefined variables you can ignore
what about duplicate fields? this type also appears abunch
You can also ignore that
Honestly not too sure why you’re digging thru Cartomancer either but go off
oh i just picked a random mod since all of them were giving out warnings
cartomance was just the one i opened first
it just kinda did it automatically
after i installed the Lua extension. if there's a way to disable it i'll do it
I mean yes it will show you the errors but it won’t do anything. Just ignore anything that’s not in your own project folder
If you just want to use git for purposes of managing a mod, rather than get into the deeper features, github desktop is a great tool. For the baseline features, it's a lot more accessible
i actually installed that to try and use it with some school project, but it never worked so i gave up on trying to use it
so github seems to hate me just as much
Can confirm, I use Github Desktop myself and it’s very nice to use
ok, commiting directly from vscode seems to work, and the repository appears on my github account
but im still really confused on what github desktop is supposed to do
im just seem to be stuck on a repository that a friend made for an old project. but i never personally controlled that repository so i dont know what to do
if vscode works i would just stick to that i think it's easy enough
yeah it reminds me of how intelij works. only other time i managed to work with github was following a minecraft modding tutorial
yeah i use the github vscode stuff for my repo management mostly
wasnt there an unlock everyhting option somewhere? would be useful for testing
yes, the profile menu
i thought so too but i dont see any relevant option
should be there if you didnt use it
but also try this https://discord.com/channels/1116389027176787968/1386785075991150824
i mean, i've added more mods since i've used it so maybe that's why
yeah if you used it once then it doesnt reset, thats why that mod exists
does anywhere on the vanilaremade wiki explain these format strings?
"{V:1}#1#{} difficulty"
it's in the smods wiki
where can i find the vanilla atlas definitions? i think theyre somewhere in the lovely folder but idk which file
what do you need them for
theyre not defined like smods
theyre in function Game:set_render_settings() in game.lua
well then nvm. i kinda got what i was looking for by just looking at the textures directly
i guess i wanted an example of the same mod having its own atlas definition and using it
Besties why isn't my achievement getting achieved
EDIT: because i was on an unlocked profile and didn't add bypass_all_unlocked = true to the achievement defintion
The check_for_unlock is getting reached if I put a debug print there
so i changed some visual things, but something broke the mult functionality of the example. besides the mult value, i didnt touch the calculate function. i even compared it to the example from the wiki again. Am i missing something?
yes
btw alt f5 will restart the game instantly
new table entires
text = {line one, line two, line three}
oh i see
i was looking at the vanilla remade examples and noticed different joker triggering conditions were given differnt ability variable names. suit jokers were s_mult and hand jokers were t_mult. is this important or is it just for better readibility?
i just copied vanilla names, theyre not important
if they're joker specific then the names matter however much you want them to
(which usually isn't at all)
hi! am i misunderstanding juice_card_until or is that not how you pass extra variables
(the issue is it does not juice even though flaming is true
Remove the not
We all have those moments lmao
i mean it does say until when it's while
^ this, the function is named in a dumb way
Alright how can I get if an achievement is earned?
Okay, why don't earned achievements reset when the profile is reset?
Grrrr
that's also vanilla behavior i believe
achievements are stored in the device
So how do I debug them........
Where exactly are they saved?
Okay it's in settings.jkr...
if this is your achievement you can set reset_on_startup https://github.com/Steamodded/smods/wiki/SMODS.Achievement#api-documentation-smodsachievement
Good to know, thanks
for some reason, i get an error that extra is a nil value (extra.flaming exists)
- you should be doing this in set_sprites
- the same issue will happen in set_sprites, you need to put it in an event because the function runs before the ability table is set up on the card
I have a problem where for some reason I can't modify my card to score with an specify seal if you have a joker
everytime it crashes
SMODS.Joker {
key = 'r_wolf',
atlas = 'Joker',
pos = { x = 5, y = 4 },
rarity = 3,
cost = 5,
blueprint_compat = false,
eternal_compat = true,
config = { extra = { seal = 'fnaf_vip' } },
loc_vars = function(self, info_queue, card)
info_queue[#"Info"_queue + 1] = {key = "fnaf_sprite_WIP", set = "Other"}
info_queue[#"Info"_queue + 1] = {key = "fnaf_code_WIP", set = "Other"}
info_queue[#"Info"_queue + 1] = G.P_SEALS[card.ability.extra.seal]
end,
calculate = function(self, card, context)
if context.modify_scoring_hand and context.other_card.seal == card.ability.extra.seal then
return {
add_to_hand = true
}
end
end
}```
SMODS.Seal {
key = 'vip',
atlas = 'Enhancers',
pos = { x = 5, y = 0 },
badge_colour = G.C.GREEN,
always_scores = false,
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = {key = "fnaf_sprite_WIP", set = "Other"}
end,
}
You should be doing context.other_card:get_seal() instead of context.other_card.seal also did you start a new run?
let me check to see if it worked
ok it worked thanks
does anyone know why my hook makes enhancements retrigger?
local get_enchs_hook = SMODS.get_enhancements
function SMODS.get_enhancements(card)
local list = get_enchs_hook(card)
if #SMODS.find_card("j_elle_drago")>0 then list.m_wild = nil end
return list
end```
even if i make it function SMODS.get_enhancements(card) return get_enchs_hook(card) end it still does it twice
but if i comment the hook out then it's fixed
did you accidentally do the hook twice?
ohhh
can you only have 1 of each hook?
it's also worth mentioning
the retrigger that happens has extra_enhancement = true in the context table
No, the problem is you forgot the extra_only input.
i didn't have a 2nd hook anyways
you can, but if you used the same local variable name in the same scope, it would have unexpected side effects
but forgetting a parameter would definitely do that :p
Yes, if that's the main file in your JSON
how does it look like
what about the json
-# FUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU-
would you believe me if i said i forgot the json
yes
ok good because i did
what do i do with the json
how do i make a json and what do i do with it
guys, I might have messed up big time. I wanted to refactor G.jokers into G.consumables inside a single function and it somehow propagated into every single mention of G.jokers across all files, including the lovely and SMODS. I hope I don't have to redownload everything
yes or wherever you want
oh ok
i have done the same recently lol, if you are in vscode you can just go remove the commits with git or ctrl z
You can't have quotes within quotes
oh
anything else?
cause it didn't even load
wait
can i do these 'blablabla'
instead of "blablabla">
I don't think you can use single quotes for a JSON string(?), but you can escape them \ or use single quotes within in the string (so "text 'quote' more")
idk, nothing else that stood out as much as those quotes did
ok
round 2!
ok it's in the game!!!
but it can't find the file
i think i should change the name from "main.lua" 😭
should i change it to "phighting.lua" or smth?
the main_file in the json specifies which file it will load
just make sure it matches with the actual filename of where your code is
how do i grab a random list of like 1-3 (or just any amount) of jokers the player has and remove them?
thanks
what have i done wrong now
it says "Failed to collect file data for Atlas phight_joker"
the file path not correct
holy ball 🙏
it will look for assets/1x/sword
which it is under
file extension
do you have a 2x as well?
png, probably
yup
sword.png
the file is literally called "sword"
show
oh ok
turn on whatever this is called in english file explorer
HIGHLY recommended you turn on file name extensions
it's a png file
and itll show the full name
yeah thats it
So do sword.png
i changed it
It should work
the path needs to be sword.png
oh wait
you already did
sorry im not much help i literally started modding like 2 days ago 😭
i've never done this before so it's fine lol
?
this would not crash loading the atlas
Ah
plus pos has a default value
Do you have a x1 and x2 image
yep.
Hmmm
the files do say sword.png right
hold on i may have fixed it

