#💻・modding-dev
1 messages · Page 57 of 1
code if someone wants to look https://github.com/WilsontheWolf/Talisman
Is there any documentation on custom configs or maybe I can borrow from something? 👀
yes and I'm saying that it's effort for every qol mod to set up
keyboard controller example mod 
cryptid for custom tabs
and idk, like galdur or something for a more normal config tab
and additionally it's all cool when it's one tab that you add in settings, but when the end user has 5 mods that add tab in settings, it makes the menu cluttered
is this where steamodded splits into a loader and a coremod API?
😹
i mean I'd rather not
I dunno
it's harder to maintain
idk, just... embrace smods as a standard?
/j i do get that it's overkill and mostly not needed for some qol mods
the lazy solution is to have config UI be steamodded-exclusive and only support non-smods through editing the cfg file
I literally only use SMODS.load_file and the mod description/config tab stuff but I'd rather people install steamodded and avoid some headaches
Having config options that change position in the menus depending on what’s installed seems a sure fire way to confuse the hell out of everyone who even struggles with basic reading comprehension to install any mods
Maybe someone has to just make a lovley mod that adds support for smods config via some api and then just integrates with smods if it exists
we should call that MoreDependencies
Hey I know a lovely mod that adds support for smods config already!
The issue is it's hard to get users to install a separate mod for a mod to work
It’s called Steamodded 🙃
same thing, we're already doing that
Honestly I would just recommedn people get steamodded. It isn't obtrusive by itself and most mods already depend on it so most people already have it
You could alos just not have config if smods isn't installed
Everyone has to install lovely anyway, I don’t see how adding an extra step makes it particularly more complicated for people
I stand by the position that multiple different core mods are a bad idea
I don't think multiple core mods is a bad idea but multiple core mods that do the same job probably are
yeah that's mainly what I'm concerned about
Unless one is just straight-up a replacement for the other such as when one is abandoned
Speaking of modifying core mpds I had a cursed idea to fork love2d and integrate lovely functionality into it so that we don't get anti virused
actually brilliant
How would we make Balatro use that version of Love2D?
love balatro.exe
me when i replace love.dll
Balatros exe is a zip and can be loaded by any version of love
Well at least across the same major versiin
Its a shame meth is busy and no-one else really understands how to modify lovely that much.
I'd like to see a feature where patches also get run through lua_load instead of just luaL_loadbuffer, I just don't even know rust properly
Like I think I know the root cause of the restart issue but I just can't fix it cause I'd have to rewrite a decent chunk of lovlet and my rust skills aren't that good.
Also rust seems like the wrong language for a dylib injector
Specifically?
didn't meth use rust because that's what was most familiar to them?
Probably
Steamodded made love.event.quit('restart') work, at least if that isn't borked somehow
I saw it in the commit history
Probably needs testing to make sure it actually does its thing tho
pretty sure it didn't, we just made our own version that completely restarts the process
I do SMODS[mod_id] to check for existance of a different mod right?
SMODS.Mods[mod_id]
or you can put it in an object's dependencies if you're trying to create an object that needs another mod to exist
nah just building in mod compat for galdur
though note this isn't bullet proof
the mod object may exist without the mod being loaded
ah yes I have just discovered this
So technically what you need is something like (SMODS.Mods[mod_id] or {}).can_load
at least that's the shortest way to phrase it
also, still looking for some thoughts on making stake scaling follow a formula past base game scaling, #💻・modding-dev message
hard to judge balance-wise
but the jumps from 6->7 vs. 7->8 seem too irregular
quadratic vs. exponential means antes 6 and 7 will diverge quickly
scaling level 6:
5: 45.000
6: 180.000
7: 810.000
8: 1.600.000
yeah I was concerned about 7 and 8
i guess what feels wrong is that the scaling (i.e. first derivative) is constant between ante 7 and 8
maybe 50000 and 100000 incrementing is better
hm lemme experiment with it
Then endless rolls around and suddenly you're facing faster-than-exponential ante scaling
Doesn't quite sit right with me that you end up at the superexponential score wall soon after winning, rather than after much longer
Even if it was merely exponential up until ante 20, most builds would stop being able to keep up before then
how dare you find issue with this calcullation
at least this scaling is consistent throughout the stake difficulty though
ante 4 and 5 😠
yeah...
this holds up somewhat nicely
the cubic sort of keeps things connected better
the exponential ante 8 is still gonna outscale it, obviously
but it feels right to have the final boss ante have the score jump instead of ante 7
yeah that looks smoother
here's n=10 for reference
1: 300
2: 1700
3: 7400
4: 31000
5: 65000
6: 450000
7: 3000000
8: 26000000
4 and 5 is way too flat compared to the rest
Is a score of ~100000 where builds that can't figure out a way to fit in xMult start to fall off even if they are very good in other ways? That might explain the peculiar ante requirement curve
maybe ante 5 can live between linear and quadratic and just scale as nlog(n)
I think it taking off at 6 is probably okay, it still gives you time to assemble a working play space
log_2 is definitely too harsh
I made it work but it breaks the require lovely and also it stops logging to the console
consider 15000+5000n*ln(n):
n=4:
4: 13700
5: 42700 (start rounding off?)
6: 92000
n=5:
4: 16600
5: 55200
6: 132000
n=6:
4: 19500
5: 68800
6: 180000
n=10:
4: 31000
5: 130000
6: 450000
it sure looks smoother
yeah i rounded these quite arbitrarily
What's the working formula at this point
1: 300
2: 700+100n
3: 1400+600n
4: 2100+2900n (jank)
5: 15000+5000n*ln(n)
6: 12000+8000(n+1)(n/2)
7: 10000+25000(n+1)(n/3)^2
8: 50000*2^(n-1)
oops
What does n stand for? Some kind of difficulty level?
uh what did you do
2^((log n)^2) gives a growth rate faster than any polynomial, but slower than exponential
ok so here's an idea
I'd say n=10 is within the limits of where this formula doesn't make the jumps between 7->8 vs. 8->9 look ridiculous
what if they all used the same degree polynomial
just quadratic line-of-best-fit them all
You could probably tune it somehow to give a formula that is slightly gentler at ante 8 very high stakes
anything beyond that is just off
I suppose the other option is to include the ante level in the formulas
Also, a bit more description about how the ante 4 formula is jank?
53 mil at n=10 with this * 50.000
this is default ante 4 values 5000/8000/9000. I don't know how you make a similar formula out of these
I just ended up ignoring them 🤷♂️
(it's asymptotic, you probably will need to tweak constants around to make it work)
same for other ones that dampen
highlighted: n=1,2,3,5,10,30
n=4:
300, 1100, 4400, 12500, 38000, 92000, 185000, 350000
n=5:
300, 1200, 5000, 17000, 55000, 132000, 285000, 550000
n=10:
300, 1700, 8000, 54500, 200000, 452000, 1160000, 2300000
can you put the ante 9 values on the graph too for reference?
n=30:
300, 3700, 20000, 454500, 1780000, 3732000, 10910000, 21800000
i think those are just constant multiples of ante 8
I can add the endless formula tho
3->4 seems a little harsh
4 is one that I kinda filled the gaps on, I can try and make it less harsh
3 should be 600x + 1400 too
tried to make ante 4-5 smoother
ante 8 being quadratic quickly gets to a point where it doesn't feel like a single level of ante scaling matters that much (2.3 mil at 10, 2.8 mil at 11)
1.5^(log_2(n)^2)*80000 gives something more reasonable for ante 8
tbh I think that's fine
you could maybe then set it to whatever level you want if you want a big challenge
I feel like 6, 7 and 8 don't occupy enough space
although maybe it is an issue
feel free to work with the desmos graph I sent, I'll go do some other things now
but ideally the space gaps would increase ye
I am not nearly well practiced enough in math to manipulate these graphs right now
Is it me or the way tooltips are handled was changed recently?
yeah it was
i gave them columns and made them align on the right side of the popup if the card is on the left side of the screen
trying a quartic for ante 8, issue is that ante 9 is way too close
that's true
Plotting the logarithms of the scores might help with visualizing the curves
could swap out the constant 1.6 for A_8/A_7
They’re custom tailored, not random
Instead of making curves for each Ante, have you tried making curves for each Stake?
these formulas are in terms of ante though
we're not defining what the scaling would be for fractional ante, so such a curve doesn't exist
what would a curve for a stake even do?
I feel like the lowest Stake is a_n ~ 300*2^n, then a_n ~ 300*4^n, and finally a_n ~ 300*6^n, where a_n is Ante n
if each curve corresponds to a specific level of scaling, the x axis would correspond to ante, no?
But I think the pattern per Stake is clearer, as I just mentioned
but that's not what we're trying to do?
that literally isn't flexible enough
You can extrapolate from this pattern to new Stakes
My point is: I think the base score of each Ante grows exponentially, so if you want to create new Stakes, they should also scale exponentially
it's not that simple
maybe if you look at the 3 data points we have for ante 8, that looks exponential
but within one stake?
Yes, as I said, I think each Ante is in the same order of magnitude as a constant times the previous Ante
Like here
Also the assumption that thunk started with the lowest Stake following the pattern a_n = 300*2^n and then tweaked it until it worked sounds reasonably human behaviour
sure
it's just that we don't get that level of tweaking with a "nice" formula with this approach
The tweaking was human made by adjusting the values manually. I think trying to adjust the numbers automatically is missing the forest for the trees
I mean if you want to sit down and tweak numbers for an infinitely scaling system, go ahead
Do you only want to fit a small number of extra Stakes?
Even then I think starting from the next even exponents make sense
Or you can make it superexponential if it’s for like Cryptid or something
Thunk adjusted the numbers via playtesting, which I think makes more sense than trying to overfit a formula to 24 points on a grid
which you can do for a closed system of 24 points, you don't get the same luxury when designing an infinitely expandable system
Quick, what does the next "antes scale faster" stake ante 4 score requirement look like
okay how is this for endless scaling https://www.desmos.com/calculator/y3nandk3ls
If you want to tweak these exponentials further, you can fit a polynomial to the residuals
Maybe relative/log residuals instead of absolute residuals
I'm not entirely sure what the 0.75 is supposed to mean, but I think the 1.6 has to do with fitting the scaling of antes 7 and 8 as a starting factor
Tryna make a Joker right here, whole effect is gonna be that every poker hand now contains a straight (or higher)
So, a flush house now contains straight, high cards are straights, flushes are straight flushes, cuz they have straights... Uhhhh
How would we define this 
this graph looks better
Still not fully happy with ante 6
it stays a bit too close to ante 5
hear me out
looks better asymptotically imo, but is a bit close to ante 7 at the low end now
also sqrt(ln(x)), ew
I think 8 might go a bit too fast too
unless I am misreading, thats 800000 on scaling 4
compared to 200000 on 3
that looks better
I'll leave it there, gonna go to sleep
oh nice, a function that is never used
👀
looks good
"dang this Lovely Mod guy makes a lot of mods"
maybe the grey lovely mod text could be on the second line
yeah but then I would have to figure out how to put it there
is that second image not putting it there already?
I mean the size and colour
oh right yeah
ok eval time
maybe I should add a way to grab a ui element in debugplus
but that mgiht be a bit too much work
I like the second one, but maybe have it in the greyed out text like the one above?
🔥
lovely mods in the crash log
there's a note!
huh
mod.debugInfo as a table of strings shows like the crashing example there (<key>: <value>) or just a string just shows whatveer your string is
the version field I put there is kinda useless since we got offical version info now
but I am too lasy to chnage it
Does anyone know where the documentation for the create_card function is? I keep seeing it everywhere but I don't know what all the parameters do.
it's in functions/common_events.lua
Unsure what we're messing up here. Saying something about line 45 (blue dot on left) not having curr_obj defined.
Are we improperly defining f(), which defines curr_obj? This was working a bit ago so
Is there a way for a Joker to add a specific Tarot Card?
like spawn one?
look at how the fool spawns it's tarot
you should be able to use the same code
how do i go about making a language mod? (so i can just simply change text string like balatro university)
Doesn't seem like it, it uses a special variable to pick the last tarot
Sure but just pass your own thing instead if that variable
What would I pass?
I don't gave my computer to check but see what is stored in that variable
Its probably either the slug or the center if I had to guess
Found it, just have to pass the slug in that argument instead
Thanks for the help!
Hey guys, does the Joker art need to created at 142 x 190 or 71 x 95? a bit confused
there's always a 1x and a 2x file that you need, so technically both
usually the 2x is a basic upscale of the 1x
I see, that makes sense then
So just make it 71x95, then just resize it to 142 x 190 for 2x file 👍
Is there a template image somewhere for the Joker card borders?
Pins in fan art channel
Im assuming the best way to learn how to code Jokers is by looking at other Joker mods files and unraveling the process that way.
this too
https://github.com/Steamopollys/Steamodded/wiki/05.-SMODS.Center#smodsjoker for general API understanding
https://discord.com/channels/1116389027176787968/1247703015222149120 for the reference on which context to use
will do, ty
#⚙・modding-general message this could also be helpful
oh yea I forgot about that
but yes, zombie-ing other mods jokers is a viable optionj
hmm, would there be any way to add a glass-card like effect to all cards in hand?
by that i mean give each individual card a chance to break
Never heard that expression
This is incredible
yeah, but you'd need to add card eval with lovely patch for it
ill see what i can pull up
Is it possible to make a shader that applies to everything underneath the card? (for ex. making a glass that blurs things)
What do you mean by things underneath the card?
not possible
shader only processes pixel on the sprite itself
so you could have semi transparent card + blur applied to the card's sprite, but it wouldn't blur the stuff from another sprite/canvas, so it wont dynamically change
damn, no postprocessing
love the logo on it
lol. My wife is an artist so shes gonna do all the art if I can wrap my head around how to code them
So lucky
When you're done with your first 3 jokers it will be an easy slide from there.
I sure hope so, I want to make a Joker that scales xmult with your interest earned but i bet that would be a nightmare to code properly.
Mmh I dont think there's a context to fetch your interest? You'll have to make your own context during payout, but that requires knowing how to do lovely injection
Still it should be achievable
I wonder if G.GAME.interest_amount resets to 0 after payout
A more tedious solution would be calculating the interesting, saving it somewhere and apply it at the end of round
The problem may be that interest is calculated after the blind defeat, since there are factors that can reduce or increase your money, like Golden Joker or that one boss blind that takes money for each card
So yea, calculating the interest on the go would be better, not like there are many factors applied
Yikes, i have so much to learn
All you need for that actually are 3 parameters: your current amount of money, jokers held in hand and vouchers purchased
Manually checking this kind of staff sounds not really cool because in this case joker incompatible with other mods, if they decide adjust interest calculations
ugh, how should finding the max stake work with non linear stakes
pool order
True, though idk if you can make the game calculate the interest during the scoring
In theory you can make it call the interest function during the scoring, but idk if it will work properly
pool order as in the first one with the highest level or the last one with the highest level?
I will try when I get more experience and confident enough to try n make it happen, I imagine i would probably need the help of others if possible, but here is the concept mockup art and description we threw together for this Joker. (Not the correct size or borders, just thrown together for fun)
oh, i remember seeing that on the reddit!
That was me and the wife! That post got like 1.6k upvotes, i want to make them real
Last one, ascending order and whatnot
I guess it doesnt really matter
im not entirely sure where to go about getting the functions of this joker to work, i know i need to use eval_card in some way but i have found very little in either the game source code or on the discord about that
SMODS.Joker { -- Mini Hakkero
key = 'minihakkero',
loc_txt = {
name = 'Mini Hakkero',
text = {'{C:green}#1# in 8{} chance to {C:attention}destroy{}',
'a randomly played card.',
'Permanently increase payout by {C:money}$#2#{}',
'when card is destroyed.',
'{C:inactive}(Currently earn{} {C:money}$#3#{} {C:inactive}at end of round.){}' }
},
config = {extra = {money_mod = 1, money = 1}},
rarity = 3,
pos = {x = 2,y = 0},
atlas = 'jokeratlas',
cost = 9,
unlocked = true,
discovered = true,
blueprint_compat = false,
loc_vars = function(self, info_queue, center)
return {vars = {G.GAME.probabilities.normal, center.ability.extra.money_mod, center.ability.extra.money}}
end
}
closest thing that comes to mind is the glass stake in the cryptid mod but im still looking at it to see how it works
Question. Can I somehow rotate boss blind chip?
Yes
🤔
And this even don't broke blind:wiggle() ?
what
Uhh...
I have this blind. I want on specific moment rotate sprite by 180 degrees.
You can do the same thing you’d do to rotate cards
Which one, if not secret?
I think you can just set the blablabla.T.R or whatever it is to the value you want
I think it might be measured in radians but I’m not sure
how does lovely patch priority work?
do cryptid decks work with shaders in galdur for you?
the edition ones?
yeah
yes they have shaders
I must have broken it on my local version
whats the best way to check if another mod is loaded?
SMODS.Mods["mod_id"]
that won't tell you if it's turned off or not though
(SMODS.MODS['mod_id'] or {}).can_load
ty
heck
oops I left caps on
Mods not MODS
also if i have a localization file no i not have to put any loc txts in my code?
yes
cool
I think I've finished the stake stuff 🎉
🥳
there are some errors when you continue a run after installing or removing stakes
omg thanks
I'll take another look at my alt texture rewrite at some point
yeah, really isn't top priority to have in though
how major are the stake changes
Which Mod? (Galdur only changes Stake selection)
didnt eremel say they were going to do stake stuff for smods in general unless im misremembering?
considering smods' stakes are currently unfinished
It’s mostly just adding support for non linear stakes
yeah i tried doing some of that but looking back i should've learned more before trying to contribute
for non-linear stakes currently smods doesnt check whether the run info should have "stakes" button (its coded to put the button if the stake is anything but white) and the "also applies" ui in that menu is coded to check if its G.GAME.stake > 2 instead of checking if the stake itself needs an "also applies" list
I haven’t touched any of the in run menu stuff at the moment
does anyone know how shop loading from save file works? i have added this patch of code after the if not shop_exists then block which adds a value to a card's ability. after loading from file, that card no longer has that value in its ability
it's loaded later
there's a debug when you load save file while in shop
smth like couldnt find shop area or whatever
and that forces area to be loaded later
I dont remember where exactly the code is, but you can probably find it by searching debug message
Hi guys, does anyone know how to get jokers description, both localized and unlockalized? I need to create a function that checks if there is word "currently" in the description.
i want to make this happen twice
how
how do i make it like, make 2 of the planets instead of one of them
the game only loads the localization for the currently selected language
to get just the raw text you can do localize{type = "raw_descriptions", set = "Joker", key = "j_joker"}
but it'll be in the currently selected language bcos of that
you put it in a loop
for example you can do for i = 1, 2 do <code> end if you need it to happen twice
although you should probably add a check in the code to see if there's space in the consumable slots before creating the card
if self.ability.name == 'The Emperor' or self.ability.name == 'The High Priestess' then
for i = 1, math.min((self.ability.consumeable.tarots or self.ability.consumeable.planets), G.consumeables.config.card_limit - #G.consumeables.cards) do
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function()
if G.consumeables.config.card_limit > #G.consumeables.cards then
play_sound('timpani')
local card = create_card((self.ability.name == 'The Emperor' and 'Tarot') or (self.ability.name == 'The High Priestess' and 'Planet'), G.consumeables, nil, nil, nil, nil, nil, (self.ability.name == 'The Emperor' and 'emp') or (self.ability.name == 'The High Priestess' and 'pri'))
card:add_to_deck()
G.consumeables:emplace(card)
used_tarot:juice_up(0.3, 0.5)
end
return true end }))
end
delay(0.6)
end
Have a look at what the game does for emp, and hp.
for i = 1, math.min((self.ability.consumeable.tarots or self.ability.consumeable.planets), G.consumeables.config.card_limit - #G.consumeables.cards) do
specifically
it makes me cry everytime I see someone setting an edition with {edition = true}
How exactly do i look at the vanilla jokers code within Balatros game file
Extract the Balatro exe and look in card.lua
G.Consumables 💀
<@&1133519078540185692>
💀
yeet
🔫
ty
oh someone got it before me
Ah
egg!!!!!
we both got it

vonnegut + Egg
that guy
xD
Probably an easy question, but is there a way to get the slug of a tarot card used from context.consumeable?
Hmm, hopefully i dont mess this up lol
I tried to use context.consumeable.ability.name for this, but I think it gives the proper name instead of the slug.
context.consumeable.config.center_key
Thank you!
trying to test the stakes PR rn, but talisman overrides get_blind_amount so i can't easily test with cryptid stakes 💀
lol nws
just thinking about what to do with talisman
the override probably has to stay, so do we make SMODS.get_blind_amount talisman-compatible?
or should talisman need to have its own override of that function too
Cant talisman just hook the function instead of overriding?
And just throw the return from get_blind_amount in tobig()?
I see
comment on the talisman override
Maybe talisman just needs to override this too then
i hate these types of overrides, but I'm also not sure how I feel about having the compat be on smods' side
fair enough
heyo. Is there some modding resources collection somewhere or is my best bet just running of smods examples
(Ive been struck by alcohol fueled inspiration)
there's a good chunk of mods you can take inspiration from in here
What do you want to make?
A gunslinger themed joker set
tldr:
Guns: Can be reloaded, burning a bullet joker and inheriting it's effects. Up to 5 bullets. Reloading any more will override the first bullets added.
- Golden gun. Destroys any golden cards playe and gains x0.4 mult per card destroyed like this.
Havent thrown anything else onto paper yet, but you get the general idea
thanks m8
also btw galdur is amazing
im a software dev by trade, mainly just lacked a place to start chewing away from xd
(sorry, reading back through chat to catch up) Rust is as good of a choice as C++ imho, they're both equally powerful low-level languages.
What you get through is really great safety assurances and (more importantly) a really good toolchain
Idk it just seems odd you gave to declare a bunch of c methods and unsafe code, feels like it defeats the point of rust
But idk I'm not a professional on the matter
I have an updated version of the luasteam library I want to package with my mod. Is there a way I can patch this in to override the existing luasteam?
it's possible to load DLLs from arbitrary locations using the FFI library. If you want to avoid having users replace DLLs in the game folder, you can do that and replace require 'luasteam' with the code for loading your lib instead
I was truing to do that at one point and couldn't get it to eork
The game kept crasbing
it worked for tolk
I probably was skill issued
It was also quite early on in modding and I wasnt so familiar with lua
That could work for sure. But how could I package platform specific binaries with the mod?
I guess I could have separate download paths for different platforms
I think you could just include all copys and point the game to them manually (?)
you can get the OS via love.system.getOS() and just load the different binaries conditionally
Can give that a shot. New to lua modding but this is kinda the last step before I can release a (very early) first build so I’m hoping to get it working
does G have a list of all the in game suits and ranks?
including ones w mods
SMODS.Suits / SMODS.Ranks
^
that includes base game as well i take it
base game by itself doesn't have anything of the sort actually
it's all just hardcoded
oh
it's one of the first things I wanted to change
it doesnt matter that the base game is hardcoded cuz i doubt we getting Deck of Cards V2 any time soon.
probably not
no it's just a pain to work with, so i replaced it
for modding ofc
mhm
ranks and suits are fully rationalized unlike some other stuff
cough cough deck effects
Rust's stdlib eventually calls unsafe extern libc functions, what's important is that those calls can be wrapped with checked "safe" code
... which to be fair lovely does not do lmao
So wait does this mean your available to make lovley changes now?
classic thunk
ah yes
wtf forwarding messages now
based feature actually
you're talking about lovely intercepting load() calls?
I can't imagine it would be too difficult but it does rely on consistent chunk names
I have consistent chunk names
for the most part, this came up because I switched to load()ing most smods files instead of lovely injecting them for better crash readability, rn this means mods can't patch steamodded's overrides
Basically, the main issue is that the lovely module get's de-registered
That module gets injected during lovely's runtime init phase, prior to patch application.
Runtime init is started through DllMain, which is fired when the lovely dll is initially loaded into the Balatro process.
Well it'd injected in this once block that well ony runs once so when the lua runtime is restsrted it is removed
Yeah, if the runtime is restarted but the process does not then the lovely module won't be re-injected.
Yrs I would like it to be
Simply because the event chain for lovely module injection is only fired when the process is created
Yeah, shouldn't be too difficult
I couldn't figure it out
Oh also the test case has been removed you'll have to patch smods to test it
can't you just debug eval it
Replaxd this with return "restart" https://github.com/Steamopollys/Steamodded/blob/main/core/StackTracePlus.lua#L746
love.event.quit('restart')
You nerd to kill the threads too
I'm bad at typing
😭
Being bad at typing seems unfortunate for a dev
O have spell check in my ide
Those syntax errors T_T
General workflow is
- Inject some sort of fn hook into whatever reloads the lua runtime
- Inject the lovely module as a part of rt init as normal.
- If the reload hook is hit then we unset the runtime init flag which, on the next
lual_loadbuffercall, will cause the lovely runtime to be reset and reloaded.
I'll need to look into how this is implemented on the C++ side of things
Hold on I can find the method
Loves main thread is a loop and it doesn't exit if restarted
I tried to hook this call but got skill issued iirc https://github.com/love2d/love/blob/main/src/love.cpp#L191
Also you'll probably have to run the main function of the platform lovely code as well
Iirc
But it's not nessicary
Just reloading patches would be handy
And I think fixed stdout
How do I add to the Hands count on the left?
G.GAME.hands iirc
so I just do G.GAME.hands = G.GAME.hands + 3?
Try it and see
ok
There actually might be a function like ease_hands which does the effect on the display
Not sure
and destroying a joker is just self:start_dissolve() according to the Mr. Bones code
unless that's not how SMODS handles it
yea?
any mods that have smods dependency I can snoop through?
Wdym?
Oh
i put it in example mods iirc
ah cool
just --- DEPENDENCIES: [Steamodded>=1.0.0-ALPHA-0812c]
12c is current version right?
yeah, the one including stake update
Wow do we have version comparision now?
yeah
just mod IDs
Wow that means I can remove the version.lua I have in my smods directory that's untracked me messing with versions
lol
V_MT = {
__eq = function(a, b)
return a.major == b.major and
a.minor == b.minor and
a.patch == b.patch and
a.rev == b.rev
end,
__le = function(a, b)
if a.major ~= b.major then return a.major < b.major end
if a.minor ~= b.minor then return a.minor < b.minor end
if a.patch ~= b.patch then return a.patch < b.patch end
return a.rev <= b.rev
end,
__lt = function(a, b)
return a <= b and not (a == b)
end,
__call = function(_, str)
str = str or '0.0.0'
local _, _, major, minor, patch, rev = string.find(str, '^(%d-)%.(%d+)%.?(%d*)(.*)$')
local t = {
major = tonumber(major),
minor = tonumber(minor),
patch = tonumber(patch) or 0,
rev = rev,
}
return setmetatable(t, V_MT)
end
}
V = setmetatable({}, V_MT)
V_MT.__index = V
function V.is_valid(v)
if getmetatable(v) ~= V_MT then return false end
return(pcall(function() return V() <= v end))
end
Wait in your version comparison algorithm is 1.0.0 greater than or lesser than 1.0.0-ALPHA-0812c?
lesser, since the empty string is the least of strings
Fun
it's not fully semver-compliant in that
Debian has it where if you do ~ehstver it lower than just emoty
So 1.0.0~beta1 is lwer than 1.0.0
For example
yeah i probably should have an empty revision compare as greater than any non-empty revision
that's the patch number though
1.0.0 is lesser than 1.0.0-1 which would be like a hotfix
I would reserver a character that is lower than empty space like debian does
ah
#⚙・modding-general message I posted in wrong channel
hm okay
V_MT = {
__eq = function(a, b)
return a.major == b.major and
a.minor == b.minor and
a.patch == b.patch and
a.rev == b.rev
end,
__le = function(a, b)
if a.major ~= b.major then return a.major < b.major end
if a.minor ~= b.minor then return a.minor < b.minor end
if a.patch ~= b.patch then return a.patch < b.patch end
if a.beta ~= b.beta then return a.beta < b.beta end
return a.rev <= b.rev
end,
__lt = function(a, b)
return a <= b and not (a == b)
end,
__call = function(_, str)
str = str or '0.0.0'
local _, _, major, minor, patch, rev = string.find(str, '^(%d-)%.(%d+)%.?(%d*)(.*)$')
local t = {
major = tonumber(major),
minor = tonumber(minor),
patch = tonumber(patch) or 0,
rev = rev,
beta = rev:sub(1,1) == '~' and -1 or 0
}
return setmetatable(t, V_MT)
end
}
so this ig
1.0.0~ALPHA-1208d
Yeah something like that
I'd also like to use it for my mods dev builds so if someone depends on v1.2.0+ then v1.2.0~beta1 won't match
this is gonna break existing version dependencies though
not too big a deal since idk that too many mods are doing it yet
I'll change the example mods though
Why does this effect crash the game?
return {
x_mult = card.ability.extra.Xmult,
card = context.other_card
}
end```
Nvm, found out why, I was missing context.individual in if statement
how does the joker text work
name = ' ',
text = {' ' , ' '}
}```
yeah im referring to the substitution into the text
with curly brackets
i just dont know what any of the individual things mean
how would I include the number of jokers they have in the text for example
Is there a way to set current chips and/or mult to a certain number, regardless of what it was before?
rook (background wip)
cba
cba?
cba
there's a chess piece mod which idk where it went
and there's a cba joker in morefluff
is there anything on the wiki about joker atlases with floating bits
like legendaries
i swear i remember the term soul pos from somewhere
but i cant find it
ah thank you
I'm trying to test this Joker effect by making it set base chips and mult to 0 at the start of the hand. Right now, it doesn't do anything, though.
hand_chips = 0
mult = 0
end```
A more simple way might be to create a lovely function which calls the Love2d restart AND restarts the lua runtime
do you know why the area doesn't have card ability though
so I was messing around and I made it possivle to unlokc blinds with DebugPlus but I can't get it to redo the text without a lovely patch or some super jank code (blame
). WOuld you all be okay with it just not showing up or should I try getting it to do the text?
it is properly unlocked so you can back out and go back in to the collection to work it
if your curious it;s because this peice of code uses a local variable for discovered instead of the blinds (which is where it gets the local varible from)
also get softlocked
my first modded joker :o
thanks! :D
O-O
is there like an aseprite plugin or sojmething that allows you to export sprites at both the 1x and 2x resolution in the proper folders and stuff? so i dont have to like keep exporting it twice whenever i wanna do stuff? its a little slow rn
not really
heck
I have two scripts for automating this stuff
one adds a transparent pixel outline like the base game does (and aseprite doesn't even see them, because it treats everything with alpha value of 0 as an empty space)
and the other one takes all sprites and upscales them
would you be able to share the latter?
finally got this working
does the wording make sense? you can include any other card in the hand, but there can be no more or less than one king if u want to gain mult
yeah that's clear enough
splendid
OOPS
me when i G.Jokers
splendid
i should probably safeguard that 💀
THE ROOK
I can't even consistetly get the crash but it happened like 3 times already in total
Accidentally make white stake unplayable 💀
looking at smods stake update is kinda my joker moment bcos im looking at the code and its like
just a lot of the things ive messed with myself for the stakes in archipelago
the timing is unfortunate cus i'll have to rush an update by tonight, but im very glad that i'll be albe to trim and simplify a lot of code
huh
yippee
is it stable enough to play in slightly bigger asyncs
i mean it was
rn no idea on how compatible it is with current smods after the stake update, but i'll get on that tonight
i'm stuck in an async with every muse dash song so it'll be a while until i can play a game with this
#1255696773599592458 message I’m not able to investigate it right now though
does this work as a showdown blind
i thought it would adjust the hand eval as if the card wasn't there to begin with 💀
that would be too evil
it would normally but when implementing the devour i decided to keep the empty space for effect
not talking about the space
(the devour effect was made for a joker and im just reusing it because i can)
ah
like this would re-evaluate as high card unless you have 4fingers
mechanically the card is still there, just unscored
oh my god is white stake still broken
on one hand that could be a fun evil twist to it but tbh im not sure if i want to mess with hand eval
damn
works fine on base, i need to know what mod is causing that interaction
rn what im hearing from ppl i talk to about the mod is "too annoying" and "maybe could work for the boss, but not for the joker"
cryptid?
likely
if it's not updated, maybe..
well it's on the latest commit rn
not getting it unless there's some further specifics?
it's cryptid
then why can't i reproduce it
also uh this one doesn't even have cryptid #1255696773599592458 message
i can't work on fixing it if i don't have a setup to replicate
uhh tf i can't repro either
I don’t think so, since you don’t really care about losing cards after the final boss
Cards destroyed on earlier antes have more impact
there will definitely be a weaker version of it as a normal boss so longterm effects of removing cards will be there for the other boss
Otherwise, debuffing a single card from scoring seems quite weak
I think the Boss could be a non-Showdown Boss as is
with the showdown blind the intent is going after builds that rely on strong card-related effects
Then you make a stronger Showdown version
what about "1 in 2 chance to destroy each played card instead of scoring"
or 1 in 3
so it has a chance to strike multiple cards (or not strike anything)
what if the check is reversed
so 1 in 2 to score, otherwise destroy it
wait
what if the chance of destruction decreases with each destroyed card
theres no difference xd
oops all 6s
ig
i'll try that
Doesn’t really change my opinion
new config screen 👀
btw shouldn't all stakes be unlocked regardless of the setting if you're playing an unlocked profile?
errr probably yeah
I think there were some people who didn't want that, I'm not sure what base game does?
base game lets you select stake freely on unlocked profiles
does smods.blind have any way to store variables that persist when loading a save?
hook to Blind:save and Blind:load
there's no 'free' table like extra for blinds unfortunately
but if you don't want to, these variables G.GAME.blind.hands_sub, G.GAME.blind.discard_sub are saved automatically

another challenge
@night pagoda I think it was you who requested this
yup, awesome!
looks a bit weird, idk
tbh I like this alignment much more
yeah that's not terrible actually
unrelatedly, looks like we borked something with saving runs
i can't get a run to save at all
new galdur release go and break it friends
worlds most silliest boss
1 in (cards removed) to destroy
(cards in the deck) in (cards total) to NOT reset it back to 1 in 1
cards removed as in any form of card removal
a classic tale
as expected it took several hours for me to figure out how to make this work
a steamodded update about 2 weeks ago added base game eternal/rental sticker registrations (https://github.com/Steamopollys/Steamodded/commit/0b833575b4a2eb012799ce92dc6e7c47e07c2c91), which is having a fun side effect with Less Intrusive Stickers - beforehand, the sprite on its sheet that replaced the eternal sticker did nothing (still showed the full size sticker) but now it is showing both at once!
tried debugging this for a while but i'm not familiar enough with the way things work to understand why the old one isn't being replaced properly...
is this enough boss blinds
eternal eternal sticker, makes the Joker have the eternal sticker in the next runs
almost
oh god
i could see the vision honestly
oh, i've figured out why this is happening - it's because the Sticker class sets G.shared_stickers but doesn't set G.shared_sticker_eternal
just need to figure out how to do that only for the eternal sticker without hardcoding it into the class method
how
All M Jokers 
am i cooked chat
how did you know
Wow..... I mean uhm, yea I'm just that good
i think i could make that if got that idea any other day
its a memory issue at that point
makes sense
luajit only gets the bottom 2gb
pal, im gonna do you one better
100,000 decks :O
i tried that yes
4 SPF (seconds per frame)
Imagine having to flick through all those one by one
procedural joker generation
Someone did that, right?
let's try the simplest possible one
i mean RNJoker exists...
you could just yoink that code
it almost worked
if you actually wanted to have that many objects, it might be needed to load them lazily lmao
I imagine the references alone almost take up too much space
good progress, the game told us what happened
and its ALL Very Fair Deck....
i think i still need to lower the number tho
yeah I remember getting that as well
500k might be more reasonable but should still crash
31 bit references are 4 bytes by themselves, add another few for the key
hm
we're in
at a ridiculous like 5 seconds per frame
Actually more like 2-3
And we’re dead
you can't actually construct a GameObject, so not that
the depth of the metatable chain also doesn't matter, the object itself just has one metatable reference
and keys are always required, so the only way to make it cheaper is to have something that doesn't insert into pools
"Will it blend?"
Sounds?
Atlii?
omg
okay but now you gotta discover them
it crashed after this but that's the farthest I could get
nah these two are the most expensive
filesystem things
I'm thinking either Blinds or UndiscoveredSprite, but the latter requires an atlas string and a pos table
Decks don’t have a pool, right?
they do
how else would they display in order when selecting one
generally all centers have pools
Oh shit yeah
I think I really think I need a tutorial or something to start doing this lol, all I did was change another joker to using ^mult instead of xmult and it was working fine for an entire day, now today without any changes my game crashes on startup for some reason, lol
Is there any jokers i can use as a reference that can both add AND reduce total Xmult based on specific conditions?
i have a question, how do i add a new type of consumable ?
nvm, did something stupid before going to bed yesterday apparently, I think I know what's causing it
i don't really understand the wiki
then you need to ask more specific questions
Asking this again because I didn't get a response the first time:
I'm trying to test this Joker effect by making it set base chips and mult to 0 at the start of the hand. Right now, it doesn't do anything, though. Is there a way to set base chips and mult at the start of the hand?
hand_chips = 0
mult = 0
end```
you need to also set the hand text iirc
i managed to make the new type, i made a undiscovered sprite but when i launch the game i get this error
What do you mean?
Why debug panel binded to Tab button 
ask thunk 🤷
looks like you put a wrong atlas key somewhere?
I want to make a bind for quick opening run info, Tab should be perfect, but it's occupied by debug panel. 
Maybe I should use "`" instead?
not all keyboards have that easily available
what should i put in the "pos" line ?
something like { x = 0, y = 0 }
oh okay
where these numbers are the x/y position of the sprite on the atlas, starting from 0,0 in the top left
Could have it as the default and have a keybind config, maybe.
It should. Easy to say btw 
I'm curious that lovely mods doesn't have convenient place for settings
I think there's been a few mods that have keybind config options you could borrow from, but I can't name them off the top of my head. Unless you're doing a lovely mod.
does loc_txt work differently for stickers than other game objects? the loc_txt on this sticker does not seem to show.
are you on latest steamodded?
i'm on 1.0.0-ALPHA-0731a-STEAMODDED
would that just be label = "name"?
yeah
ok, thanks👍
How do I do that?
i think this: update_hand_text({delay = 0}, {mult = 0, chips = 0 })
Now it's changing the hand text but not actually changing the values. It just looks like it is, but the hand still scores the same
and you're assigning to mult and hand_chips?
Yes
if context.before and not context.blueprint then
hand_chips = 0
mult = 0
update_hand_text({delay = 0}, {mult = 0, chips = 0 })
end
end,```
Im trying to make a joker that calculates a +0.08x Mult on 8s scored and a -0.04x penalty on all non 8's scored. How do I code it to check for MULTIPLE card ranks to penalize?
Use or or not.
I see ty
What happens if you try putting that in a return block, just looking at flint? Might not work, though, since it's a blind and this is a joker.
My other suggestion is G.GAME.current_round.current_hand.mult and .chips, as well as .mult_text and .chip_text, which, you can look through the structure of Game:init_game_object() in game.lua for other possible variables you could access.
how do you make custom consumable types show in shop?
Look for SMODS.ConsumableType in Steamodded
Neither of these work, unfortunately. Looking at the eval_play flow, it seems that hand_chips and mult are always recalculated after context.before to account for any level-ups, but that definitely throws a wrench in what I'm trying to do. Anyone know of a solution?
you could hook Blind:modify_hand() to check for your joker instead
I’ve never done anything like that before. How do you do it?
local bmh = Blind.modify_hand
function Blind:modify_hand(cards, poker_hands, text, mult, hand_chips)
if next(SMODS.find_card('j_prefix_your_joker')) then
return 0, 0, true
end
return bmh(self, cards, poker_hands, text, mult, hand_chips)
end
So I put this in my main lua (do I need the j_prefix_ part before my id?), now how do I do with it? It does nothing currently (no matter what I try in the find_card function).
prefix should be whatever your mod prefix is
if you didn't specify one, it's the first 4 characters of your mod ID in lowercase
Do I need the j_?
yes
Works now, thank you!
The settings menu
You can look at how talisman does it
Also you can have a dummy smod file that just adds a conifg using steamodded
I'm working on making a system that works with both steamodded and vanilla for DebugPlus but you pretty much have to roll something yourself for vanilla with lovley
The issue with a universal system for lovely mods is either you have to:
- have all the code to do stuff yourself but also play nice with others (cryptid and talisman do this but are made by the same dev)
- depend on sometbing else the user has to install (and if we're getting users to install other stuff, might as well use steamodded since most people already have it
- everyone has their own way with an inconsistent user experience
how would I transform this into an effect that triggers on a club card's scoring rather than once per hand from the joker? I tried to look at the base game jokers but couldn't really tell what I was looking at, lol
Look at the things that use context.individual
Context.individual is the one used when played cards are scored
Should help
ok! I will try checking in there
I feel like I'm close here now maybe, a couple crashes and some bizarre things with it being a held in hand effect for a bit somehow, but I think I'm getting there
something here is crashing it now, lol
hmm, I feel like I'm close, let me try seeing what happens without the cardarea again, cuz it wasn't crashing back then
I just realized it's also not scoring the mult anymore, huh
Seeing a crash log would hekp
here is crash log (I am using the example joker in joker evolution to for testing, since I don't really know how to set up my own mod yet, lol)
What's on line 44 of your mod's main.lua?
my joker
all I know about the crash so far is that without this line, it doesn't happen
Load file is returning an error. I believe assert(SMODS.load_file("data/example_joker.lua)()
Should throw the errir
hmm
Did you forget to put an end to your if statement?
wrong syntax
the first and has nothing afterwards
also you need three ends but have two
If you merge the two ifs then it should work
try seeing how Vouchers do it
thanku! I will try changing the ands, I'm not sure where the 3rd end is placed but I will do
they use a set variable from G.Game, this uses a different type being a modded consumable type.
Again if you merge the ifs you only need two
One for each function scope, one for each if and do scope IIRC
Try seeing if Steamodded creates those variables
I think I may have messed something up here
hold on, wait, I think my brain my be braining
nope, lol
wait, I merged and added but I think I only needed to do one, lol
It should have two
I have changed the first then to an and now, crash still appears 😭
but what's the crash
here's the log
me whem cryptid deck
i might be cooking
though i dont think you can actually win with this deck lmfao
why not
you cant win if its seeded
i spent like 30 minutes trying to fix something
all i needed to do was add like 4 lines of code and change G.GAME.seeded to false
Can someone look at my custom Joker? It is partially functional, very new to this so im certainly missing some key info to get it working properly!
if context.other_card:get_id() == not 8 then 💀
that's not quite how that works
just use else..
To add to that, not equal in lua is ~=
While == not doesnt crash, its not doing what I assume you want it to
most certainly not. not 8 is the logical inverse of the number 8, which is false
<Card>:get_id() however always returns a number, so the condition is never fulfilled
hey i literally have owned a computer for 1 year of my life, this is pretty ambitious of me to even try, lol but ty
gotta start somewhere amirite
yes! ty for the help
for getting more familar with lua itself, this is a great resource: https://www.lua.org/pil/contents.html
Im honestly shocked that it even launched the game without crashing lol
I did make a couple other extremely basic jokers that just give +mult and chips so im heading in the right direction
Ok so the Joker as of now is calculating that 8s are being played and Xmult is being added to the total xmult counter on the card correctly, however, no Xmult is actually being applied to the hand score. Also "not 8s" lol which ive changed to ~= 8 are still not actually reducing the total xmult.
oh wow, i would think itd be !=
i didnt have to use it yet but exclamation is more common in other languages
Yeah I was surprised by that myself too
I realized this doesn’t quite work due to how ranks are checked for in the game. I’m trying to think of a rework
The best I came up with so far is making them all suits and Face cards but I’m not too satisfied
WORLDS SMALLEST CARDAREA
huh i didn't catch that somehow, that block is inside the if context.other_card:get_id() == 8 then block
The entire xmult reduction penalty wouldnt even function when i changed it to check for 7s specifically. Went in the game, played a 7, no penalty. I definitely messed something up big time.
yeah like I said
you're still inside the if block that checks for exclusively 8s when you're looking for non-8s
Basically this is your structure
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then -- individual scoring card
if context.other_card:get_id() == 8 then -- card is an 8
if context.individual and context.cardarea == G.play then -- does nothing, already checked for
if context.other_card:get_id() ~= 8 then -- always false, since we know the card is an 8
end
end
if context.joker_main then -- always false, still evaluating individual scoring cards
end
end
end
end
Hmm, ok
this is what it should be like
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then -- individual scoring card
if context.other_card:get_id() == 8 then -- card is an 8
else -- card is not an 8
end
end
if context.joker_main then -- separate context
end
end
! ok
Ok so it is now calculating penalties! How would Iprevent the XMult from reducing below 1.0X? And the only other issue is that the xmult is not being applied to the hand score
have you made sure it's fully separate like in the structure I sent?
for preventing reduction below 1.0X, you can do something like this
if context.other_card:get_id() == 8 then
elseif card.ability.extra.Xmult > 1 then
end
It worked! Now i just gotta fix the xmult being applied!
I think the hardest part is the formatting, ill get it tho
How would I make a joker that has a chance to destroy a played card?
glass cards seem to work on something that i cant really reverse engineer into a joker
look at hanged man.
if you want to find how to destroy the cards, or if you're struggling to figure out how to do it on card trigger, there's an event for that.
How do I put badge localization to a SMODS.Sticker?
if you're using loc_txt, loc_txt.label
ty!
not sure if im not ordering things correctly here or if theres something else not working
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and not context.blueprint and not context.before and not context.after then
local destroyed_cards = {}
if pseudorandom('minihakkero') < G.GAME.probabilities.normal/self.config.extra.odds then
for i,v in ipairs(context.fullhand)
for i=#G.play, 1, -1, do
destroyed_cards[#destroyed_cards+1] = G.play[i]
end
card.ability.extra.money = card.ability.extra.money + card.ability.extra.money_mod
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')})
return {calculated = true}
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
for i=#G.play, 1, -1 do
local card = G.play[i]
if card.ability.name == 'Glass Card' then
card:shatter()
else
card:start_dissolve(nil, i == #G.play)
end
end
end
end
end
end
Im struggling getting this xmult structured i guess, cant get it to apply
look at my structure again
you still have
if context.individual and context.cardarea == G.play then
-- ...
if context.joker_main then
-- ...
end
end
Some major errors,
- Too many checks. You have a check to if if a card is 8 already, and
elseonly activates if thatiffails the check. You don't need to check again. - You also don't need another
context.individualcheck, you're still in theifarea from the initial check ofif context.individual - Also, your
if context.joker_mainwas inside of thatif context.individual, which are mutually exclusive. Ifcontext.individualis true, thencontext.joker_maincan't ever be true, but it's only being checked for whilecontext.individualis true.
also this is lua, else if is elseif
Here's a copy with the code cleaned up and functional, use it to compare and see where you went wrong.
i mean yeah
but it creates the need for an extra end
if condition1 then
else if condition2 then
else if condition3 then
else if condition4 then
end end end end
Thank you guys, i see what you mean about the else check, oof, im looking through now and learning my mistakes, my first time trying an even somewhat complex joker
Pretty sure you don't need the context.before and context.after if you already have context.individual, but, my guess would immediately be to try switching self.config.extra.cards to card.config.extra.odds, and I'm pretty sure fullhand is spelt full_hand. Try using some sendDebugMessage('Whatever string you want here'), and then see what stage it's getting stuck on, and then look at that area more closely.
also there's an improper double for loop that's returned from
oh thank you for the debug message i was sort of wondering to myself how i could do that
ive gotten it to almost work? it doesnt crash on startup but when i play a hand with the joker the game just locks up
I'd assume it's from the loop mentioned here, if you sprinkle some sendDebugMessages around, maybe you'll find where it loops, or if something else is going on?
i just removed one of the for statements since i dont think it was actually doing anything
that's too professional