#đ»ă»modding-dev
1 messages · Page 55 of 1
you need to put the check box and the 'example' test in a seperate columns, and have those columns in a row
probably
This is very scuffed. And I have that.
Actually, maybe I don't have the colums themselves in a row.
No, I do.
{n = G.UIT.R, config = {r = 0, align = 'tm', minw = 4, minh = 0}, nodes = {
{n = G.UIT.C, config = {r = 0, align = 'tl', minw = 0.8, minh = 3}, nodes = {
{n = G.UIT.R, config = {r = 0, align = 'tm', minw = 0, minh = 0.8}, nodes = {
create_toggle{label = '', active_colour = G.C.SO_2.Clubs, scale = 1, w = 0, shadow = true, ref_table = config, ref_value = 'Testing'}}},
{n = G.UIT.C, config = {r = 0, align = 'tr', minw = 3, minh = 3}, nodes = {
{n = G.UIT.R, config = {r = 0, align = 'tm', minw = 3, minh = 0}, nodes = {
{n = G.UIT.T, config = {text = 'Example', align = 'tm', scale = 0.5, colour = G.C.UI.TEXT_LIGHT}}}}}}
}}}},```
Iâm really not qualified to help with that lol
https://cdn.discordapp.com/attachments/1211320933650792468/1266272221987475516/image.png?ex=66b45d67&is=66b30be7&hm=63835ab22612ff4f986da39a09773f92e2d86a130f02c7970dd5a2e3cd8caff9&
It took me like an hour and a half to make this UI
And I still need to add things to it (like another box and colors to check if the info matches)
it might be smth to do w the minw
(And pages for both multiple checks in a run and more mods than can fit on screen)
for the joker retrigger api stuff
i have the lovely patches
in a toml
and the lua file
do i need more?
my code for this joker is literally identical to boredom apart from it just checks if each joker sell value is less than the one that retriggers them
Iâd recommend working off of the Steamodded pull request
ah is that where it went
Because I made some changes to it
i tried looking for the stuff on the git and couldnt find it
ill give that a go
thanks
yw
math is beautiful
Thank you math
Try swapping where you use rows and columns
Keep the toggles and text elements in rows or switch them into columns?
Can you send me a screenshot rather than text? My mobile editor wraps lines and itâs awful to read ui code
Just put it before in the code, looks a lot better already, though definitely needs tweaking.
I think itâs needs to be structured as a row with two columns inside, where each column contains one of the elements
Iâd add a align=âclâ on the row too, with align=âcmâ on the columns
I think
So much better already, thanks.
Could throw a box in there to space it out too
Next is that I want to make Extra feel like it's attached to the bottom of the option cycle, any idea here?
Might after, but, I want to make sure I have all the basics down before beautifying it.
Put some negative padding on the row itâs in and reduce the text scale
Oh, putting padding on the toggle label would space it further away too
You can do negative padding?
Alright, looks closer together, still needs more tweaking, but definitely a step in the right direction. Should be able to figure it out from here, thanks so much.
Glory to the User Interface Wizard.
Look forward to seeing what this will be used for!
Can you show me the code?
sure
calculate = function(self, card, context)
if context.retrigger_joker_check and not context.retrigger_joker then
if context.other_card.sell_cost < card.sell_cost then
return {
message = localize('k_again_ex'),
repetitions = card.ability.extra,
card = card
}
end
end
end,```
yeah
^^
im gonna have to add some more checks to my code because it retriggers stuff like gros michel chance to break lol
but the core functionality is there
Does anyone know how you could potentially get a like, "ID" of a joker? If they're stored like numerically at all somehow in the game's code
true
If you want to find every Joker with a key, Steamodded provides SMODS.find_card
I was more thinking of trying to implement something similar to the Spindown Dice from Isaac where it would be a consumable that would change the Joker numerically up or down on use
but idk if that specically will be possible if it's just based on keys rather then like numeric positioning if that makes sense
The Jokers are loaded into the collection in order
đ€ true
Though with different mods it could be inconsistent
Intended
You can take ownership of Gros Michel if you donât want your mod to do that
order
Wonât work with modded Jokers tho
Yesnât
Itâs the order theyâre loaded in
But they arenât necessarily loaded in the same order all the time
It depends on the specific modâs implementation, and other mods being installed or not
But usually youâll have vanilla and modded content segregated
And again segregated per mod
complicated way to say priority and alphabetical order
But itâs not alphabetical
It would mostly be based on priority first and then alphabetical second tho
within the same mod, it uses the order they're registered in in code
Which may or may not be consistent
it usually is
yeah sure but that's not what you're supposed to do anyways
I agree but people do it anyways
I use ipairs with a table that both lists the Jokers in order and has non-integer keys holding Booleans to decide if the Joker is added or not
I got it from Autumn
I meant that as in, you don't need a convoluted loader for your modded objects like cryptid has
just split your files up with SMODS.load_file and call the constructors directly
there's no need for the indirection
I mean thatâs what I do; hold on
I think I looked at your mod for a reference on how to use NDS.load because I didnât understand Cryptid
It mightâve been another one
I have since updated while looking at Cryptid tho
the way you use NFS.load is that you don't, you let steamodded do it now
else you get useless stack traces
i did use NFS.load, but all jokers were in order of listed?
they should always be, but that wasn't my point
unrelated question, how the hell do you update these dynatexts on demand
@frosty dock what's the Steamodded alternative now?
SMODS.load_file
Hands and Discards?
why is my connection so bad
Hands and Discards? Or Round and Ante? Or all?
did you really need to ping me
i'm looping through all the dynatexts and updating them but for some reason they aren't redrawn
You didn't reply to the previous question, so yes
okay nevermind that, i just needed to pass true to first_pass
How do I set the sell_cost of a joker to 1 when it is spawned? I tried card:set_cost() but that calculates the sell_value based on the cost of the joker every time and then adds the extra values specified.
You can do what set_cost does but directly change the sell value
Yeah, but when something like Gift Card is in effect, it calls the original set_cost and adds the sell value based on editions and whatnot, basically overwriting what I wrote
maybe hook into set_cost then
Oh, I could probably hook into it like you said and do a if self.ability.name == x check
Yeah ok. Let me try that. Thanks
@frosty dock SMODS.load_file doesn't let me set up custom messages smh my head
wdym custom messages
VictinsCollection :: Failed to load "..joker_name.." with error "..error
oh you totally can
it returns a function the same way NFS.load would
or an error message if it failed to load
yeah
It works but sendDebugMessage doesn't
Do you have the right level set in the steamodded config?
what
steamodded has a log level setting now (in Mods > config)
by default it only shows info and higher
huh
Is there a prefix on modded joker name values? This code works when Blueprint is in the name area, but not my modded Joker's name.
no, but don't use name, use center keys
Oh, I see now with the debug message. The name value is literally just it's full prepended key.
So do I still use self.ability.name or is there a different way to access it?
uh look at SMODS.find_card maybe
it's self.config.center.key
Sweet, thanks!
oh, should I use that function instead?
No that one just finds Jokers by the key
or Consumeables
But it uses card.config.center.key
is there a function called whenever the deck is modified that i can hook smth to?
Modified how
like any change to the deck
what's a change to the deck
check_for_unlock might be the way to go
like if you add/remove a card, change suits, change ranks
enhancements, seals
Only adding and removing cards is changing the deck
The rest isn't
And there are hooks for those two
okay by my definition of changing the deck then
which is why I asked
But keep in mind cards are added and removed from the deck when debuffed
You could hook into use consumable too
yeah ik
yeah im gonna hook it to emplace, remove and use consumable
think thats the best way
I don't think you can catch every modded effect
Ok, so I got this code to work for the Joker, but if there're any other Jokers that modify its sell value, it still overwrites it. I think I know why, but I can't for the life of me think of an alternative, other than hardcoding specific joker names to work with it (Which I want to avoid)
-- set_cost hook for Wish You Were Here
local set_cost_ref = Card.set_cost
function Card.set_cost(self)
if self.config.center.key == "j_pape_wish_you_were_here" then
if self.ability.extra_value == 0 then
self.sell_cost = 1
else
self.sell_cost = self.sell_cost + self.ability.extra_value
end
else
set_cost_ref(self)
end
end
im gonna hook to the check_for_unlock
because use consumable, emplace, and remove all call that anyway
Have you read set_cost?
Yeah, that's what i've been basing this logic off of
And I know why Gift Card is resetting the Joker's sell value, I just can't think of an alternative way to implement it
Why?
Ok, so from my understanding (which is probably wrong lol) Gift Card is calling set_cost(), and it doesn't match up with the if statement in my set_cost() hook, so it goes to the original function (in my else statement). In there, it calculates the original sell_value based on half the cost to buy (which I set to 6 in the joker config) which is 3. Then it calculates the edition bonuses and adds the extra_value provided by gift card with the previous extra costs applied
I mean, then your if statement is the issue, no?
I now understand the appeal of UI.
Yeah, it is when a Joker other than my Joker calls set_cost(). I could add all the jokers that add sell_value to that if statement with ors, but I wanted to prevent that so as to work with other modded jokers
Do they do anything yet?
which i guess is only gift card in this case lol
How do they create an issue?
Unless you coded your if condition wrong, it should go directly to it
Just call the reference and do your check afterwards?
That's what I do
In fact
Your implemention is bad because it doesn't change the cost of the Joker if it works
So e.g. other effects can't change its cost
(Tags, etc.)
They do cycle through config, but I use an opt_callback to save the cycle changes that calls this code,
G.FUNCS.Balu_cycle_save = function(args)
local test = args.cycle_config.ref_value
config[test] = args.cycle_config.current_option
end
Unsure if there's a better way.
Yeah, I thought it would, since gift card's logic loops through each joker and calls set_cost with that joker's data, but it doesn't for some reason.
Just call the reference and do your check afterwards?
I tried that before but it kept resetting because it was getting called on my joker which I didn't want
like here
`why is that not
function update_new_moon()
local suits = {}
local suit_order = {
Spades = 1,
Hearts = 2,
Clubs = 3,
Diamonds = 4,
}
local values = {}
local value_order = {
['Ace'] = 1,
['King'] = 2,
['Queen'] = 3,
['Jack'] = 4,
['10'] = 5,
['9'] = 6,
['8'] = 7,
['7'] = 8,
['6'] = 9,
['5'] = 10,
['4'] = 11,
['3'] = 12,
['2'] = 13,
}
for k, v in pairs(G.playing_cards) do
if v.ability.effect ~= 'Stone Card' then
suits[v.base.suit] = (suits[v.base.suit] or 0) + 1
values[v.base.value] = (values[v.base.value] or 0) + 1
end
end
local common_suit = {'Spades', 0}
local common_value = {'Ace', 0}
for k, v in pairs(suits) do
if v > common_suit[2] then
common_suit = {k, v}
elseif v == common_suit[2] then
if suit_order[k] < suit_order[common_suit[1]] then
common_suit = {k, v}
end
end
end
for k, v in pairs(values) do
if v > common_value[2] then
common_value = {k, v}
elseif v == common_value[2] then
if value_order[k] < value_order[common_value[1]] then
common_value = {k, v}
end
end
end
new_moon.debuff = {
suit = common_suit[1],
value = common_value[1],
}
end```
ik the code itself is horrible
This is how I just updated my code
but idk why G.playing_cards is nil
when is it called
during a run
when is it called
local check_for_unlock_ref = check_for_unlock
function check_for_unlock(args)
check_for_unlock_ref(args)
if G.STAGE == G.STAGES.RUN then
update_new_moon()
end
end```
I think check_for_unlock is called before you enter a run
Oh you want it to update dynamically when you add a card to your deck?
I don't think that's a good idea
when i leave and re etner the run it breaks
Make it work like Ox
nah i want it work like this
I guess one way I could fix it is by setting the Joker's cost to 1 initially and then if its available to buy in the shop only THEN temporarily set it to the correct cost value.
Maybe because check_for_unlock is called when you continue a run
Hold on
and I'm telling you you should want to not want that ;P
Bumping this for @wintry solar since there was a flood of messages right after I sent this.
You can set the table you want to modify as the actual reference
As the ref_table, and leave ref_value blank?
Let me just put my kid to bed and then Iâll show you
I mean my code works
although I need to make it works with Editions I guess
Does SMODS.Edition have a cost value for vanilla and modded Editions?
They do, but I'm not sure how to access it
Oh, nice. So your code sets the placeholder Joker's sell value to 1 and then it never gets reset?
local game_update_ref = Game.update
function Game:update(dt)
game_update_ref(self, dt)
if self.playing_cards then
update_new_moon()
end
end```
fixed it :)
No, it sets it to 0 and Gift Card updates it to 1
Then 2, etc.
what is the initial cost in your joker definition?
Idk
like, to purchase it in the shop
that's my real issue; it keeps referencing that value when doing the calculations
0
I don't know if it's a good idea to run this every frame
Yeah, so I want it to cost $6 in the shop, but when its purchased, set it to 1
Problem is that value is directly referenced in the set_cost function
I don't think changing the cost would matter
Because the minimum cost is 1 anyways
so even though I put 0 it would be updated to 1
So the value it uses is never the value I put
But the result doesn't change
I changed the cost to 100 and it works
Hmm. Can I see your code? That seems exactly what I want lol
@stray warren but swap the order of 0 or self.ability.extra_value
that was a silly error
Oh you're using the wrong key
we got double digits
https://github.com/Steamopollys/Steamodded/wiki/10.-SMODS.PokerHand
A Balatro ModLoader. Contribute to Steamopollys/Steamodded development by creating an account on GitHub.
(yes that means poker hands are merged)
@stray warren try j_paperback_wish_you_were_here
but again do it after you call the original function
Ok, your function fixed it. Although the prefix was pape and not paperback. Thank you, this was giving me a headache lol
I could've sworn I tried that before, but oh well
Is it? I thought it was paperback on GitHub
that's the mod id
There's no predefined --- PREFIX: so it's the first four
Yeah, it's only 3 digits, so it's the full mod_id
yeah it takes the mod ID, not the name
it's the first 4 chars of the mod ID in lowercase, so it'll just be the first 3 if it's only 3 chars long
why does it only use 4 chars
as to not make keys overly long?
If that was added recently I also think it breaks the Royal flush example
is that Aura?
but actually I do need to fix the royal flush example
but seriously I can't stop thinking about it after realizing that XD
I thought you meant forcing prefixes to be 4 or less characters
What broke with it?
I just merged the new poker hand API
Is Reverie mod only for 0.9.8 Steamodded?
for now
Well, time to downgrade, just to make sure my mod is working fine 
so clean
actually I should make the 'royal' part of it its own PokerHandPart just to demonstrate
I was reading through your Example Joker Mod as a newbie mod creator (and it's really well put together, even if I still have questions, which I'll have to discover myself), and I found this line. Are King and Ace supposed to have the same id or is this a typo?
actually maybe not
that's a typo, king is 13
Yeah, typo, thanks for catching it.
Makes sense. Thanks!
So say you have a config table like this
config = {
test1 = X,
test2 = Y
}```
you can set `ref_table = 'config'` and `ref_value = 'test1'` and it'll set it as whatever your option selector is iirc'
small correction, ref_value = 'test_1'
Wait all this work and I just remembered it's meant to ignore Edition changes to sell value lol
Didn't want to work for me, I had it as something like
return {
test = true,
cycle_test = {
'Testing',
'Testing 2'
}
}
And it didn't seem to effect it in any way, tried quotes and various other things.
what did you put in your cycle definition?
not my point, but fair enough
It had ref_table = config which was the current path stuff, and ref_value = 'cycle_test'. Options were options = {'Testing', 'Testing 1'}, thouugh I did try it without the options first, and it just had nil.
loc_vars = function(self, info_queue, card)
return {vars = {self.debuff.value .. 's', self.debuff.suit}}
end,
collection_loc_vars = function(self)
return {vars = {self.debuff.value .. 's', self.debuff.suit}}
end,```
uh
loc vars works
colletion loc vars doesnt
uh
that is not me
i think
well i mean it must be
but
oh i think its saturn
is that an issue?
it might be if it used 0.x versioning since the game does some logic with that on startup
but it's just bad practice
its not smth i added to saturn myself
but ill bare that in mind
oh do i have to pass colours to blinds?
i was wondering if i could change the colours
Will also say that the opt_callback I use to save the current option just sets the value to a number, by the way.
yeah
is there an example mod i can read to see how
thank you
might be worth putting that on the wiki, unless it is and im blind in which case sorry
@shell tangle use opt_callback = 'test_framework_cycle_callback'
that will adjust your ref_table correctly
I assume this is a function located in Steamodded?
no
this is in source code
I knew I'd seen thunk use a ref_table in an option cycle
base game function actually
Any thoughts on a lovely patch to make it the default opt_callback?
is there an easier way to pass it a completely diff loc text than this
loc_txt = {
name = 'New Moon',
text = {
'#1# #2# #3# #4#',
'#5# #6##7##8#',
},
},```
I don't see why it shouldn't be the default
Whatever the Ox does
not really
i want a completely different text
All (most common rank) ... is too long and looks bad imo
âeach card withâ?
Oh? How do you use that?
I have some fake text which I look for so I can create custom boxes and text
doesn't look like I did lmao
like adding a Credits box to Jokers
its alright my way works
even if it is scuffed
What should current_option be with this? It changes it to a string, but, now current option is nil. Tried config['Testing'], but, no luck.
uhhh good question
Is there a debug line of code for outputting a message? Like, just so we can debug if part of a play is going thru
sendDebugMessage().
I think it's going to be easier to just not use this built in function and write a new one
Back to what I had, then.
I would do something like this.
config = {
test = {
options = {A, B, C},
value = 1
}
}
create_option_cycle({current_option = config.test.value, options = config.test.options, ref_table = config.test, ref_value = 'value', opt_callback = 'callback_func'})
G.FUNCS.callback_func = function(args)
args = args or {}
if args.cycle_config and args.cycle_config.ref_table and args.cycle_config.ref_value then
args.cycle_config.ref_table[args.cycle_config.ref_value] = args.to_key
end
end
I believe this will work
Just to prevent crashes if the table doesn't exist yet, or?
just an example of what the table could look like
G.FUNCS.Balu_cycle_save = function(args)
local ref = args.cycle_config.ref_value
config[ref] = args.cycle_config.current_option
end
``` Here's mine which has been working, but, I obviously haven't put it under any stress testing yet.
yeah that'll work
I suppose I wrote mine as a more generalised case
you could use mine on any option slider
I also have my options located within the create cycle function, rather than in the config area.
yeah that's fine too
interestingly, having them in the config area would allow them to by dynamic too
Complete side note, how is an info_queue thing structured again?
array of tables that have a set and key
does context.cards_destroyed not work?
oh. I saw on a different thread that it was context.destroying_cards
But that context doesn't work on Jokers or consumables, does it? I'm currently looking through your post, so sorry if that's already answered
I don't think there's a check for destroying those
base game can't destroy them, right?
Well Madness can destroy Jokers, but I don't think consumables can be destroyed
oh true
And I don't even know where to begin to add new contexts 
what are you trying to do?
Is there a way to get the total chips scored by a hand at the end of a hand?
I have a Joker that gains mult when any card is destroyed; Jokers or playing cards
and i guess consumables if there was a mod that added that
uhhh you could maybe hook Card:start_dissolve and check for card.getting_sliced and run a calculate joker there with a new context
Let me try that
I may have done something wrong; is getting_sliced a child of self in this function?
local start_dissolve_ref = Card.start_dissolve
function Card.start_dissolve(self, dissolve_colours, silent, dissolve_time_fac, no_juice)
start_dissolve_ref(self, dissolve_colours, silent, dissolve_time_fac, no_juice)
if self.getting_sliced then
self:calculate_joker({destroying_cards = true})
end
end
or am I calling calculate_joker incorrectly?
Thatâs a very popular custom context that many people have added
Betmma does, I know other people have but I donât remember all of them
function Card:start_dissolve
then remove self from the function definition
actually, does that even matter?
Are you talking about the . or :? I've seen it used interchangeably in multiple different mods
I figured other people had that idea. I'll check Betmma's implementation, cause I can't seem to get this one to work
IIRC I donât think Betmmaâs is good because they use the colors passed to the dissolve function to check đ
Theyâre not interchangeable
checking getting_sliced also isn't perfect to be fair
When will SMODS add this custom context v_v
Would I even need a getting_sliced check, since if it's dissolving it's probably been destroyed anyway? Or am I missing something
When you sell itâs dissolved too
oh yeah duh
Cards are only not dissolved when theyâre shattered and exploded I think
Maybe exploding cards also dissolves them I forget
Oh, so my implementation wouldn't work for glass cards
Not quite
You can destroy glass cards in other ways
And theyâre shattered instead
I think itâs inconsistent but I donât remember
they still call that context iirc
But only if theyâre destroyed by the Glass cardâs effect I think
that sounds wrong
Surely cryptid has a context for it
Also remember to add a key to your custom contexts
local start_dissolve_ref = Card.start_dissolve
function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice)
if self.getting_sliced then
for i=1, #G.jokers.cards do
G.jokers.cards[i]:calculate_joker({destroying_cards = true, destroyed_card = self})
end
end
start_dissolve_ref(self, dissolve_colours, silent, dissolve_time_fac, no_juice)
end
I think this is what you need
So I would check for that context or remove_playing_cards
yeah
probably needs to throw a check in somewhere to make sure the card that is calculating isn't being destroyed, although I guess that depends on the effect
Yeah, I actually noticed that and added it in there. Let me see if this works đ€
Donât forget to test selling cards
Ok, selling cards doesn't trigger it, and it gives mult when cards are destroyed; although it only gives mult once, no matter how many cards are destroyed
how did you destroy the cards?
if (context.destroying_cards or context.remove_playing_cards) and not context.blueprint then
if context.destroyed_card ~= card then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
return {
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult_mod } }
}
end
end
I destroyed playing cards with the hanged man and a joker with Madness
check for context.removed and then the size of it
it contains all the removed cards
the context.destroyed_card should only ever contain one card
Yeah. It should call calculate joker on each card destroyed, right?
yes
but the default ones on playing cards call it once on the whole set of destroyed cards
oh so that's where the context.removed comes into play
yeah
if (context.destroying_cards or context.remove_playing_cards) and not context.blueprint then
if context.destroyed_card ~= card then
if context.removed then
for i=1, #context.removed do
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
end
end
return {
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult_mod } }
}
end
end
you can remove the for loop by doing card.ability.extra.mult + (#context.removed * cart.ability.extra.mult_mod), but looks good
Oops, forgot to modify the mult when a Joker is destroyed. But thank you, it all seems to be working as expected now
I wonder if card.ability.extra.mult + ((#context.removed + #context.destroyed) * cart.ability.extra.mult_mod) would work
Let me try it lol
Well it wouldn't though, because if only a Joker is destroyed, context.removed would be nil, right?
yeah, I'm not sure how doing # on a nil object works
it might error, or it might be 0
You can throw a or 0
Or maybe or {}
Actually donât all cards have a remove_from_deck? Or only Jokers?
I think it's just jokers, but it calls when debuffed anyway
is this better than using tooltips?
But there is a from_debuff argument
What do you mean?
the current labels are in tooltips on hover
Oh when you hover over the option?
yeah
I split it up into two distinct if statements. Do you see any issues with this?
if not context.blueprint then
if context.destroying_cards then
if context.destroyed_card and context.destroyed_card ~= card then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {card.ability.extra.mult_mod}}})
end
elseif context.remove_playing_cards then
if context.removed then
card.ability.extra.mult = card.ability.extra.mult + ((#context.removed or 0) * card.ability.extra.mult_mod)
card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {card.ability.extra.mult_mod * (#context.removed or 0)}}})
end
end
end
ew, formatting broke
is that supposed to be a_xmult?
nope, nice catch
Actually, I'll probably just make it say Upgrade! like some base jokers do
and first argument has to be card and not self
Noticed something weird. When scoring, it gives the mult for the score, and then shows +0 mult. I'm assuming it has something to do with remove_playing_cards?
https://medal.tv/games/balatro/clips/iqCj8YpBpf1QcQHqW/d1337yU9yWhY?invite=cr-MSxjaTEsNTQ1MjA2MTEs
Watch Untitled and millions of other Balatro videos on Medal, the largest Game Clip Platform.
Actually, not sure what's causing that
I imagine it always calls the removed_playing_cards context, so you'll need to check that context.removed isn't nil
hmm, that's not it. I added this line if context.removed and context.removed ~= nil then and it's still showing that
but those mean the same thing, right?
it just doesn't get called if it's empty anyway
can I see the entire calcualte function?
calculate = function(self, card, context)
if not context.blueprint then
if context.destroying_cards then
if context.destroyed_card and context.destroyed_card ~= card then
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {card.ability.extra.mult_mod}}})
end
elseif context.remove_playing_cards then
if context.removed and context.removed ~= nil then
card.ability.extra.mult = card.ability.extra.mult + ((#context.removed or 0) * card.ability.extra.mult_mod)
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {card.ability.extra.mult_mod * (#context.removed or 0)}}})
end
end
end
if context.joker_main then
if card.ability.extra.mult > 0 then
return {
mult_mod = card.ability.extra.mult,
card = card,
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } }
}
end
end
end,
(#context.removed or 0) change this to just #context.removed
Still doing it. should I put card_eval_status_text in its own conditional?
throw a #context.removed > 0 instead of the nil check?
That did the trick. Thanks!
I understand contexts and how to create them a lot better now
when creating them you just need to make sure you're passing through everything that might be useful
Need a bit of assistance with this Jonklers code
From what we understand we kinda messed up and are having em read every single card that's played and, affecting every card that's played. Instead of just, reading once and doing it once.
Unsure how to set it so that it only Does it per the card that it is? Since, it also crashes if we play something like a two pair with kings and two's. (Probably because the rank isn't supposed go any lower than 2)
Any help would be appreciated ^^
Try switching the for k, v in pairs (G.play.cards) do to context.other_card instead?
how do you check if played hand contains a certain hand?
You don't need a for loop for it either, it goes 1 by 1, so just run a check on context.other_card to make sure it's not 2.
Pretty sure the hand name is stored in context.scoring_name.
if the scored hand contains another hand
At a quick look, Trousers just checks for either Two Pair or Full House,
Also, it uses context.poker_hands.
poker_hands contains all the valid poker_hands that are contained in the hand
Didn't know. Should update my example mod, because the runner in it is using scoring_name.
context.before instead of context.individual? we thought they were exclusive with eachother
They are, but you aren't necessarily using context.individual in any way, it's just repeating the code 5 times, because it's checking context.individual for each card.
You can still check for G.play.hand in context.before, I'm pretty sure, though.
Good news is that this method worked
Bad news is the scoring is registering it as the prev rank instead of the new one
You'd probably want to switch to context.before for that, then, since the checks for context.indivdual is, I think the step right after the chips of the card are given.
swapping context.individual with context.before doesn't trigger the cards, just skips over it
What is the new code?
Also gotta decide if we want retriggers to affect ranks
Grabbed from my context.before checking joker,
-- Check for Spades in played hand.
if context.cardarea == G.jokers and context.before and not context.blueprint then
local suit = ""
for k, v in ipairs(context.scoring_hand) do
if v:is_suit('Spades') then card.ability.extra.broken = true end
end
end```
Ah, it's because context.other_card is unique to context.individual, so you need to switch back to the for loop method.
Also, will say that G.play.hand, I'm pretty sure will use all cards, including non-scored cards, so maybe switch to context.scoring_hand as well.
Go and read the calculation breakdown I linked and see if that helps you understand contexts and what information you have available with them, it seems like youâre basing your knowledge off something else?
We've been using your post as a breakdown since we started this mod lol
This might just be our own skill issue
Will say that the guide is kind of indigestible at first, just because it's a lot of steps, but, yeah, once it starts clicking, everything makes sense.
You've figured out where context.individual gets triggered and where context.other_card is used now, but that's too far ahead for what you want to do.
So go back a few steps, and see what you can do with context.before.
Yeah this seems like you want the effect to happen before scoring, which is a big hint for context.before (similar logic for after too)
All the in between ones are a bit fiddly
We need a flow chart for this stuff tbh lol
Would probably be a good idea.
I mean it would be a pretty dull flow chart, itâs just a linear evaluation
Maybe more like a timeline then lol
But thatâs what my guide is, itâs just not in beginner friendly terminology at the moment
I do think a flow chart would work, just because it can be easier for some to see it visually with arrows, than piece it together in order through text.
Iâll get round to rewriting it at some point
Without the descriptions of what the parts do, I think the flowchart would feel similar to a more legible table of contents/glossary, of sorts, which I do think would help out people just starting out with it.
Good(?) news is it's doing all the cards only once now, so retriggers aren't gonna be affected
Tho the scoring is still of issue. We're not sure if it's because of the code snippits at 42-66? Because they're in the event manager maybe.
How do you add a vanilla tooltip to a joker?
Right now all I want is to add the Lucky Card tooltip to a Joker that makes cards Lucky
vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords )
{
// Take pixel color (rgba) from `texture` at `texture_coords`, equivalent of texture2D in GLSL
vec4 tex = Texel(texture, texture_coords);
// Position of a pixel within the sprite
vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba;
tex.a = 0.5 * tex.a;
number one = sneaky.x / sneaky.x;
// required
return dissolve_mask(tex*colour*one, texture_coords, uv);
}```
i have no idea what im doing with shaders tbh
i watched a 15 min yt vid
does anyone know where im going wrong here?
i just want to reduce the alpha
Thinking our big issue is this chunk of code, which is in the events manager
This is what we use to change the rank of our cards. The events are included in the 2nd image, priority is delta and gamma... beta is supposed to be after that.
How does the event manager work?
Actually frick that might be impossible (or out of our skillset)
If the way the calculation triggers work is true, then the scoring_hand is already populated even before the context.before
So, only way to affect it would be to modify scoring_hand somehow during that step
can you hook smth to the button callback for when you press play hand
use calculate joker to figure out if it should
then do it
no idea what youre actually trying to do but it looks cool
Yknow what close enough
'It's a feature'
Gonna change the card description to say it'll do it after score is calculated
I'm trying to make an effect that gains chips whenever an 8 is scored, a la Wee Joker, and I have everything except the Upgrade message that pops up on the joker. I tried copying the Wee Joker code for the message, and it crashed my game. Any help?
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
extra = {focus = self, message = localize('k_upgrade_ex')},
card = self,
colour = G.C.CHIPS
}
end```
Where is Blind fight UI being called? I know that somewhere in UI_definitions.lua, but search by G.UIDEF gave nothing useful (or is it called by a different function?)
is this in the calculate function?
i think replace self with card
Still makes the game crash whenever an 8 is scored
Crash report for the record
Whoops, I didn't do that, and once I did it worked. Thanks!
(I only changed the card = self to card = card)
nws
once you sent the error message w juice_up causing an issue i thought it was for sure the focus bit
how do you get the amount of cash-out money?
What function pulls the Blind UI up and down? I have found the one that calls for it in game.lua:2349 (which is inside of function Game:start_run(args)), as well as the declaration of it in UI_definitions.lua:1210, but those are not hooked to the beginning or an end of the fight, where is it then? Search by folder gave only the 5 that are in game.lua
Ones in game.lua also kill the UI on run end, but nothing more of it
blind.lua, G.HUD_blind.alignment.offset.y
Thanks!
I keep getting this error message whenever I try to boot up the game. What can I do to fix this?
What is in game.lua:1069 exactly?
???
But from what I can guess you saved a custom sprite in a weird, unreadable for Balatro way
Did you?
nope, that's an out of memory crash
Might be it, but I haven't touched my custom sprites for a while. I'll remove it to test it anyway.
it should go away if you close some programs running on your machine
bruh
it seems to happen a lot if steam is trying to sync ur balatro with the cloud
at least for me when debugging my mods
Closed some programs and got it working again đ
yup its already been done
steamodded tech support do you know much about shaders?
What do you need?
im literally only trying to change the alpha lol
but it wont do it for some reason
and also when i try and use time in any of my shaders it doesnt seem to update
this is supposed to be transparent
or translucent actually
{
// Take pixel color (rgba) from `texture` at `texture_coords`, equivalent of texture2D in GLSL
vec4 tex = Texel(texture, texture_coords);
// Position of a pixel within the sprite
vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba;
tex.a = tex.a * 0.5;
number one = sneaky.x / sneaky.x;
// required
return dissolve_mask(tex*colour*one, texture_coords, uv);
}```
i watched one 15 min yt video so i dont think im qualified for using these things
Time should be shadername.r
Let me just check is the new shader stuff got merged too
oh so i cant just use time
Iâd need to check some of my shaders out hold on
nws
For the alpha put override_base_shader = true on your shader object
shadername.y + time is what I use
Oh thereâs probably a shadow one you want to add too
ignore_shadow = true
Yeah because youâre playing with transparency you can see the shadow through the card
both are in shader example mod
wiki probably doesn't even have shaders section
I think I covered them in the edition wiki briefly
edition mentions a few things
the example mod was too confusing for my small brain
The example mod isnât great tbh, stupid made some fixes to it but it was hastily thrown together for internal testing mostly, it was never designed for other people to use as an example
is there any simple way to change the visual effect/text when redeeming a voucher
Text - probably via localisation, which is pretty easy
You can prob also override the atlas and pos for sprite
The effect though is in shaders\voucher.fs, which is its own can of worms. It is not a texture on an atlas, it is a shader fully scripted in this file
i meant as in the behaviour of the voucher going to the middle of the screen and saying "[name] redeemed"
ok doing some investigating its a part of card:redeem, now i just need to check whether theres an easy way to change the event that happens
What you need to change is in
top_dynatext = DynaText({string = localize{type = 'name_text', set = self.config.center.set, key = self.config.center.key}, colours = {G.C.WHITE}, rotate = 1,shadow = true, bump = true,float=true, scale = 0.9, pop_in = 0.6/G.SPEEDFACTOR, pop_in_rate = 1.5*G.SPEEDFACTOR})
bot_dynatext = DynaText({string = localize('k_redeemed_ex'), colours = {G.C.WHITE}, rotate = 2,shadow = true, bump = true,float=true, scale = 0.9, pop_in = 1.4/G.SPEEDFACTOR, pop_in_rate = 1.5*G.SPEEDFACTOR, pitch_shift = 0.25})
self:juice_up(0.3, 0.5)
play_sound('card1')
play_sound('coin1')
self.children.top_disp = UIBox{
definition = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={
{n=G.UIT.O, config={object = top_dynatext}}
}},
config = {align="tm", offset = {x=0,y=0},parent = self}
}
self.children.bot_disp = UIBox{
definition = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={
{n=G.UIT.O, config={object = bot_dynatext}}
}},
config = {align="bm", offset = {x=0,y=0},parent = self}
}
return true end }))```
, mainly UI description
Mainly this documentation, but it is still confusing
#đ»ă»modding-dev message
my issue is more of "how do i do that w/o rewriting the function" but ig i dont need to necessarily change the visual effect, i can just add my own second event to it to achieve the effect i want
Lovely
true but ive already made up my mind on just tackling on a second event for this instead of trying to messing with the initial one
you can always ping me for ui questions
How to animate UIBox alignment properly?
how do you get the amount of cash-out money?
function add_round_eval_row(config) in common_events.lua
And I guess G.GAME.current_round.dollars = config.dollars specifically
It may be just a part of the sum though
and ref functions
wdym
Thatâs for hooking
depending on the function you can also use ref functions to rewrite the functionality
it depends on the use case
but yeah, it is mainly for hooking
ye but the way they asked an injection seemed more applicable
ah, i didnt read the whole thread, just skimmed
mildly torturing the game
dvd screensaver?
What do you mean, animate?
oh this is phenomenal
unrelated - ive been working on some thing and have been wondering on an actual good way to implement it user wise. i made some spectrals which modify poker hands in a specific way for each spectral on use to put it, but im torn on how it should actually like, select which hand to modify in a way that you actually get to pick which one to modify w/o it being extremely easy to pick the bestest one ever, like how opening a spectral or tarot pack only gives u a limited amount of options so you cant just immediately add red seals and insane enhancements to ur best cards immediately
my initial idea was "using it modifies the next hand played" but then i feel like its too easy to pick which one gets modified. other ideas include last hand played (but i think that has the same problem), hand for next planet card (breaks with cryptid i think and also takes 9 years to use), and uhm random hand played (bad). if anyone can come up with any idea of how said spectrals should select which hand in an actually intuitive way thatd be phenomenal, im so lost rn
Movement transition
đ€·ââïž
I havenât looked at any animation stuff
I believe @zealous glen has though?
@regal wolf Saturn still causes the ERROR localization string issue
are u sure ur on the latest version
from the devlop branch
Mods menu of steamodded
maybe not latest steamodded
Actually is latest steamodded
I meant for djynasty
I can see the version on your ss
you have no other mods that could break it, right?
Same line, if commented, causes the issue to go away https://github.com/OceanRamen/Saturn/blob/803e27af9211504b99a4303aaae582dee3094db0/UI/ui_functions.lua#L7
how do you make a basic tag that opens a certain booster pack?
thought that line was removed
odd
(What was it doing, anyways? Just copypaste straggler?)
I havenât looked at UI movement specifically, but I think it all works with the same system
You can move things manually or try to use existing functions that move them
Take a look at how the Blind Selection UI moves when you reroll a boss or how a Blind UI moves in on the top left after you select a Blind, those are my best guesses for suggestions, unless you have something specific in mind
Also Saturn seems to interact badly with Steamodded's tag collection viewer
Because I don't understand how transition works for this vanilla ui elements, i'll do it in ungabunga way: manually move every frame 
Anyway thanks
Itâs already taken care of for vanilla elements AFAIK, you just need to give the final position
But if you do it manually, use an ease Event
Sounds useful
no, remanence of old method
Works nice, thanks!
Joker idea:
Chimera
If played hand has three or fewer cards, each scoring card has every rank and suit
Actually it should be scoring hand so that not every three cards form a 3OAK
messing around for fun, I think I got a fun idea but idk how I could balance it better
(not written on the card but the effect always happens last to ensure the hand that triggered the effect doesn't score)
I wouldnât word it that way, I think, but Iâm not sure how I would word it
I think debuffing the hand like Psychic is better but then it doesnât score at all
I considered trying that but by the time jokers begin calculating it's too late for a hand debuff afaik
You can hook debuff_hand and check if the Joker exists
Not everything needs to be inside calculate
And in fact not everything is
Golden Joker, Pareidolia, etc.
Still looking for opinions on this
To be clear, you probably want to hook Blind.debuff_hand and use SMODS.find_card. Maybe add a warning like Psychic does
If it debuffed the hand then you wouldn't get use of 90% of scaling jokers (only ones trigger though debuffed hands and context.after) which would make this joker very much not worth being rare.
Unless this isn't intended to be beneficial to you.
I still costs a hand to play.
I mean thatâs what an extra hand does
that's also a thing I'm thinking about bcos it's definitely a synergy that might be work keeping
worth*
I think it might but I couldnât think of a better wording that kept it
I think even debuffing the hand itâs as good as Burglar
Trying to use an atlas to sprite my jokers for the first time. I put Jimbo as a placeholder, but why are they so small?
And as good as Drunkard
Did you make 2x bigger?
Idk what you mean by that, sorry
The game uses 1x sized assets and 2x sized assets
Oh, is that why there's two folders?
I think you just have the same 1x assets twice
I was really confused why there were two of them
assets in the 2x folder are twice the resolution
So these sprites need to be 142x190?
Only in the 2x folder
It works now, thanks!
it's a hand at a cost of a hand, unless you can't make a high card with 4 cards you can cycle the entire deck w/o the cost of wasting hands/discards
Oh I misread it
How about
When you play a hand with 2 or fewer scoring cards, +1 hand and ?
footage with old description but it's mechanically the same as the current one
Also that feels Legendary worthy
I prefer this because it emphasizes that you get +1 Hand as a reward for doing a specific action
I had thought it was just a flat +1 like the Voucher
(Handy? Grabby?)
grabber
Then again Iâm biased towards a more MTG-sequel templating
can't be about the amount of scoring cards bcos with that description any pair/high card triggers it
Ah youâre looking specifically for cards that donât score
ye
Anyways you can just go with:
When you play a hand with 3 or more cards that donât score, +1 hand andâŠ
honestly now that you pointed that out idk why I used if instead of when
Actually thatâs a very common templating âerrorâ from what Iâve seen
I know YGO uses âifâ for similar triggered effects
(Itâs more complicated)
But I think regarding the English language itâs how people conceptualize these kinds of cause-and-effect phenomenons
Also given that it allows you to dig through your entire deck, I think debuffing the hand is more than fair enough. As I said I think even with debuffing the hand itâs a Legendary tier effect
Joker design is impressive, but it's too op imo 
Adding a limit like "3 times per round" would be nice i think
I've considered adding limits to it like "the first played hand" or "the last hand of the round", the former turns it into a drunkard with extra steps, but the latter is one of the things I'm considering
making it so the power to cycle the entire deck forces you to play your strongest hand kinda makes sense
one of the problems with adding such limits though is that it adds more text onto a card that barely fits 3 lines
Dagger exists
L Corp 
Ultimately you can choose if you want to stay close to Balatro standards or stray further away
I think if you have the forced X0 Mult youâre already straying away
Also, if you place Jimbo after Kirigiri-san, does it adds +4 mult after x0?
Maybe combine this with simplifying the condition. May I make a suggestion that takes it in a different direction?
the effect is coded to go last
I'm all ears
It needs a bit of work still but:
When you play your final hand of round, if it has no face-down cards, +1 hand and draw your next cards face-down
So the detective becomes the player trying to find out what they drew
that's actually rlly clever
I like the idea of face-down synergy. Me and at least like 3 other people have had the idea of making scoring face-down cards give xMult. But I think they need enablers
If you want to move further from your original idea, maybe something along these lines would work
unfortunately can't really go further than what you've suggested (thematic limitation - the joker is based on a card from a different game) but I really like the face down cards idea
does dangling ropes have a card game
is it one of those white schwarma games
not an official one
The second google result is a Reddit post saying âthe official Danganronpa card gameâ
First time hearing about an official one but that's cool
Tbf it seems to have been released only in Japan probably
the game the original card is from is kinda like town of salem and the original effect is "when using your ability (investigation), you can use an investigation item as a free action"
which is why the whole cycling the deck using hands thing
I think if you use face-down cards it could be any hand
Although I prefer encouraging the player to play face-down cards
it could be any hand but it can't cover the whole deck
bcos you'll eventually run out of face up cards
Thatâs why I said it could be any hand
splendid
By the way, do you have an opinion on this idea @opal spade
stone synergy
I guess thatâs true
I was trying to avoid it upgrading hands so I wonder how that would work
it being a shortcut/four fingers for 3oak isn't really that big of a deal imo because 3oak as a hand is just ok
Yeah but I donât want it to make just any three cards into 3OAK
At least 3 Stone cards to 3OAK requires some effort
I think this effect is about Uncommon in terms of strength, though I could see Rare for wackiness
seems like an uncommon to me
ye
Is it possible to change the size of a Joker's hitbox like with Half Joker, Square Joker, Photograph, and Wee Joker?
Yes
How does one do that?
Take a look at how those Jokers do it
What coding language is mostly used for balatro modding?
I want to get into modding my self and i got a great idea i want to add
Lua
The Steamodded wiki
Looking at the code for resizing Jokers, and I found the code that does it in the Card:set_sprites and Card:set_ability functions, but I don't know how to recreate that for my own cards...
Check the Steamodded wiki
I'll check tmr! Thanks đ
I tried to use the code for photograph to manipulate my Joker's size, but I'm pretty sure I'm doing it wrong since nothing's happening (and I have no idea what I'm doing). Here's what I put in my Joker
if (card.discovered or self.bypass_discovery_center) then
self.children.card.scale.y = self.children.card.scale.y/1.2
end
end,
set_sprites = function(self, card, front)
if (card.discovered or self.bypass_discovery_center) then
H = H/1.2
self.T.h = H
end
end,```
that should be crashing the game, most likely
Well it doesn't, it just does nothing
I'm pretty sure your selfs need to be replaced with card
All of them?
all of them within the functions, of course
though if it does nothing, that means it's not being run at all
can I see the surrounding code?
key = "lucky_penny",
rarity = 1,
discovered = true,
pos = {x = 0, y = 0},
cost = 3,
config = {extra = {mult = 15, chips = 90, odds = 2}},
loc_vars = function(self, info_queue, card)
return {vars = {card.ability.extra.mult, card.ability.extra.chips, card.ability.extra.odds, (G.GAME.probabilities.normal or 1)}}
end,
loc_txt = {
name = "Lucky Penny",
text = {
"{C:green}#4# in #3#{} chance of {C:mult}+#1#{} Mult.",
"Otherwise, {C:chips}+#2#{} Chips."
}
},
set_ability = function(self, card, initial, delay_sprites)
if (card.discovered or card.bypass_discovery_center) then
card.children.card.scale.y = card.children.card.scale.y/1.2
end
end,
set_sprites = function(self, card, front)
if (card.discovered or card.bypass_discovery_center) then
H = H/1.2
card.T.h = H
end
end,
calculate = function(self, card, context)
if context.joker_main then
if pseudorandom('lucky_penny') < G.GAME.probabilities.normal/card.ability.extra.odds then
return {
mult_mod = card.ability.extra.mult,
message = localize{type = 'variable', key = 'a_mult', vars = {card.ability.extra.mult}}
}
else
return {
chip_mod = card.ability.extra.chips,
message = localize{type = 'variable', key = 'a_chips', vars = {card.ability.extra.chips}}
}
end
end
end,
atlas = "lucky_penny"
}```
It still does nothing
(The sprite stuff I mean, everything else works fine)
Is there a Joker anybody knows of that works with enhancement gates (for reference)?
mystjokers' scratch card is gated behind lucky cards iirc
Found out how to get this to work. For future reference:
local W, H = card.T.w, card.T.h
local scale = 65/71
card.children.center.scale.y = card.children.center.scale.x
H = W
card.T.h = H*scale
card.T.w = W*scale
end,```
Thanks, I'll check it out
No joke, I was just trying to figure out the exact same thing, so I'm glad somebody else was trying to figure it out too
Glad that I went back and added that answer!
(I hate it when I'm looking back at old threads to find the answer to a question and they're like "nvm, figured it out" and I'm like "HOW!?")
fr (Stack Overflow comes to mind)
Also can I see what your joker looks like to wrap my head around what I'm looking at in this code?
Although I'm now having a problem where when a save with the joker is loaded, this happens to the sprite
I think I saw something about using the load function on the joker to fix that
At least that's what i saw on the Steamodded wiki
Yeah, I couldn't figure out how to use load properly. I tried this but it led to the above image
local W, H = G.CARD_W, G.CARD_H
local scale = 65/71
card.children.center.scale.y = card.children.center.scale.x
H = W
card.T.h = H*scale
card.T.w = W*scale
end,```
Where'd you get the numbers for the scale? The '65' and '71'
65 is the width of my joker and 71 is the total width of all jokers
Ok. So I need to calculate the width of my joker and put it there. I notice your Joker is a circle, but mine is a small rectangle (Other Joker for scale) so I'm just trying to figure out the logic for calculating this scale
The width is in number of pixels. Also that planet card is like super good
All art credit goes to PaperMoon, I can't draw anything to save my life
Maybe I should also get an artist lmao
Btw, what'd you put in your set_sprites function?
I donât have one
weird. My texture gets super tiny when I put what you wrote
Yeah, I got the hitbox where I want it, just the texture is super small lol
Did you put the double sized textures in the 2x folder?
Yeah, they're 2x
Idk then đ€·
This is what I have to get the hitbox where it is now
set_ability = function(self, card, initial, delay_sprites)
local W, H = card.T.w, card.T.h
local w_scale, h_scale = 33/71, 43/95
card.T.h = H*h_scale
card.T.w = W*w_scale
end,
Maybe itâs because youâre missing the middle line?
It squished
Are you using the atlas to get your sprite?
Yeah, I am. So I did this code, and I got the height to look right. The x, not so much lol
set_ability = function(self, card, initial, delay_sprites)
local W, H = card.T.w, card.T.h
local w_scale, h_scale = 33/71, 43/95
card.children.center.scale.y = card.children.center.scale.y * h_scale
card.children.center.scale.x = card.children.center.scale.x * w_scale
card.T.h = H*h_scale
card.T.w = W*w_scale
end,
I didnât use the main atlas to get this sprite. I used a completely separate atlas to specify a different sprite size
I think it has to do with the sprite being in the middle of the 71x95 area defined
I'm gonna try moving it all the way to the left
move it to top left
a few cryptid jokers that do this have their sprites at top left so maybe that will help
Okay I managed to make it not bug out when reloading by doing this
card.T.h = card.T.h * 65/95
card.T.w = card.T.w * 65/71
end,
set_sprites = function(self, card, front)
card.children.center.scale.y = card.children.center.scale.y * 65/95
card.children.center.scale.x = card.children.center.scale.x * 65/71
end,
load = function(self, card, card_table, other_card)
card.T.h = card.T.h * 65/95
card.T.w = card.T.w * 65/71
end,```
(Though it does bug out weirdly at the moment when you add it from the debug menu, but that's a non-issue)
Moving to top left worked. Also, I added two pixels to the calculated width and height to account for the 1px transparent border on the regular joker sprites to get it aligned perfectly
Sweet. Thanks for your help!
I like the card on the left very much
It will be a part of the Paperback mod (once I get around to implementing it) so check that out if you wish
It honestly seems like this coding isn't that hard...
But my idea that i want to implement kinda isn't a new joker?
Its far, far worse
items in shop cost 40% more
wtf am i not getting
Thatâs not how to reference the shader key, it needs to just be âholographic2â
Skibidi 
implemented this
the blueprint compat makes it still able to cycle the deck but i feel like having that synergy between two rares is fine
also because you wont be able to see the cards ur throwing away half the time nvm i forgot playing cards flips them lol, although you'd still have to play them to see them so
Ok, so let me see if I've got this right. You can't hook into functions that aren't in a class, so you have to do a lovely patch in those instances?
i think you can hook into them just fine
How would I do it? This code is syntactically incorrect, and its referencing itself
local level_up_hand_ref = level_up_hand
function level_up_hand(card, hand, instant, amount)
level_up_hand_ref(self, card, hand, instant, amount)
-- Do stuff
end
that should work
the thing with Lovely patches is more that you can't hook into the middle of functions
it's not self referential, theka reference keeps pointing to the original
oh wait the self is wrong
you don't need self here
It's saying undefined global 'self' and that amount doesn't fit in the arguments for level_up_hand. It's thinking self is a passed-in parameter
In fact you cna always have the same incoming and outgoing arguments if you just avoid the colon syntax sugar
Ok, so this code should do what I think it will, right?
local level_up_hand_ref = level_up_hand
function level_up_hand(card, hand, instant, amount)
level_up_hand_ref(card, hand, instant, amount)
-- Do stuff
calculate_joker({level_up_hand = true})
end
Class:func() is just Class.func(self)
Hey folks! I was wondering how easy or complicated it is to learn how to make custom decks for the game? I have zero programming experience of any kind, so I'm just wondering if this is the kind of thing I could pick up in a day or 2 of learning or if it would take a more extended period of time to work out?
Stick by the Steamodded wiki and you'll be able to do a few things
This channel will help you along the way too
I'm getting this crash when I upgrade a hand
It seems like it called calculate_joker just fine, but can't access the config for the card
When a hand gets leveled up, I want my Joker to do something
you aren't calling anything
Oh, I see
calculate_joker must be done with an actual joker
And in that loop, check if that Joker's name is my joker, call calculate_joker
Cool, shouldn't make that mistake again. Thanks!
what is the line of code that would add a certain amount of money to my balance
ease_dollars()
No, it adds
ok
jollars
do you just put it there and it counts as code
do you prelude it with anything
or does this itself add money
without anything before it
it adds money
The function itself adds money
it adds (retracts) money by a specified amount while doin the animation and playing the sound
Has anyone tried to open a booster pack after other booster pack is opened?
?
I'm getting either booster pack layered on top of the shop, or it does this after finishing:
to code/implement that I mean
I want to open a booster pack right after skipping it
Or rather, so the pack opening is triggered by skipping
nvm, I think I figured it out
I think the wording needs work still but cool! Also I think it might be okay if it worked for any hand but Iâm not sure
In any case, keeping the effect, maybe:
If final hand of round has no face-down cards, +1 Hand then draw cards face-down
it being specifically on the final hand keeps blueprint in check + gives a good direct synergy to dusk and acrobat (+ whatever modded final hand jokers there are) so I feel like keeping the current effect as is (outside of rewording it) is for the best
only a couple jokers going to be like that but it will be a couple of them because I already have an effect idea for another one + art in process
I mean if it were any hand it would still work with Dusk and Acrobat
ye but being specifically on the last one gives a more explicit push into that direction
I think âfinal handâ could be a bit unintuitive for players when you can play the final hand repeatedly, but I wouldnât change the wording
I'm trying to make an ability to reroll booster packs (via Voucher)
But there's a thing that I can't figure out: currently, after the pack is done opening, it requires one tick of being outside of pack to get back again, because otherwise it puts me in empty limbo instead of shop/game. This one tick triggers tags and other stuff, causing some nasty things to happen.
Any ideas? Maybe I can somehow open the next pack immideately without going into the shop/game?
This is my code currently (it is from lovely patch but I put it in an empty file for better visibility):
im so confused
the colourblind one literally has mult_mod
but is still giving chips
would it be calculated in joker on joker effects?
is there any way to make an uibox not block objects below it?
ig i'll ping the uiboxmancer @wintry solar
visibility or click?
I donât know the issue exactly but you probably want to hook whatever function updates the pack state
For example, from High Card mod I made my own Joker that plays a hand over and over
So it required a bit more fine-tuned control of how the game updates the states
the issue is that I need at least one tick of being in the shop, if there's no that tick I appear in an "empty" state
uhhh, I'm pretty sure the mouse knows all of the elements, so it's just finding a way to ignore the text one
after closing the pack
how does that work
Thatâs what Iâm trying to suggest. Make it work without changing the state
I think youâre changing states for a single tick
I am saying to not do that
yup, I just don't know what to do to get there
I can hook alright, but have no idea which thing exactly
Again thereâs probably a update_name_of_state function
All the vanilla ones are in the same file
Try searching uh update_hand_played maybe?
Actually I think all of them are called in sequence in Game:update
Just make sure it will work for the Steamodded packs
the way I'm doing it now accounts for the steamodded packs
But this should be hookable if itâs like replaying a hand
oh got it! just needed to add args.AT.states.hover.can = false
And that works for Steamodded packs
can't find such function, I think states are simply switched by rewriting
without a function
They are, but itâs inside those functions
Again look for Game:update
I'm still confused, because I can't inject in *_PACK state because that's not really what I need, the thing that needs replacement can be any state (not only shop), tags can open booster packs outside of it. Rerouting so it doesn't go to the shop after reroll won't solve every other state
My idea is to not switch states
Just reset the Booster pack state
Also update_hand_played definitely exists
For example, for Tarot Pack, try cleaning up what it creates and set G.STATE_COMPLETE = false
it might also help to look at the function that advances the state, since this one doesnât seem to do it automatically
I think that would be G.FUNCS.end_consumeable
Wait, but If I do G.STATE_COMPLETE = false for the Tarot Pack it will just simply lock it from loading
end_consumable I use already, yep
What do you mean?
G.STATE_COMPLETE makes the state load, after it loads it gets set back to false automatically
seems irrelevant to the problem
Itâs the other way around
nope
Look at update_arcana_pack
Youâre looking at the wrong state update func to on
Also
it's the one you told me lol
If you read just before
Youâll see it changes states first
Which is why it sets it back to false
Because I didnât know the name of the Booster state update functions
So I just told you the name of one I remembered
Because I knew the rest were in the same file
ahhh okay