#💻・modding-dev
1 messages · Page 621 of 1
anyways yeah i deleted it
I fuck up in the dumbest ways man
nah cus like i got no idea where that came from
now try to boot balatro, i believe 0827c was the perpetrator
yh it works
:P
also pretty sure that appeared only after i updated steammodded in the mod manager
don't we all
Can'T blame ya I had been triyng to like, make balatro shaders and well..
right now most of em are like %90 done but just major issues
idk how to make shaders that well
figures but my advice try to port shadertoy shaders into balatro for starters
wait
there we go
the only issue is trying to understand the way how Balatro handles shaders and also how to like import custom images into a shader.
and also try to figure out coords every single time since most coords might turn out wrong
although this is my biggest concern rn
okay so uh i'm getting this error when trying to apply a shader to a card
mod prefix
bruh
i dont think its the consumable type or the consumable. i can get it to use the set, but it has an error and tries to use the default one. i think the bad code is in the booster. heres what i do to create a card
local _card
_card = {
set = "gspectral",
area = G.pack_cards,
skip_materialize = true,
soulable = false
}
return _card
end,
hmmm, i haven't worked on any boosters yet personally
the booster works because it's using the correct default
same. though I was working around with shaders earlier but yet I had a hard time with the texture coords and how to add in extra textures to the shader that wasn't the joker
the "error" text is just a problem with localization btw has nothing to do with the consumabletype
is it possible to define a specific list of cards for SMODS.Back? like you can do with challenge decks
also how would you make custom deck art, like additions to the Customize Deck... selections (in Options)
SMODS.DeckSkin
I can't even define a local variable properly, it seems
Probably because the local is directly in a table
You also do not need the self in the function
...why the ,?
?
Prolly because this is inside of an SMODS.Joker or something of that sort
Which is not where it should go
progress has been made: the game now launches and VS Code has stopped yelling at me in red
how do i make a badge have a description? like how enhancements do on playing cards?
i know you can add a badge with
set_badges = function(self, card, badges)
badges[#badges + 1] = create_badge("(something)", G.C.INACTIVE, G.C.WHITE, 1.0)
end,
got it! (it doesn't work, but atleast the coding tool is happy)
which context check is true when blind is defeated (using this in SMODS.Joker)
context.end_of_round
Use alongside context.main_eval for single trigger effects or context.individual for on held playing cards
i want to add a card like how marble joker does
at the end of round if you defeated the blind
Okay that code is the exact same
but marble does when blind is selected?
Well thats what i just said
calculate = function(self, card, context)
if context.end_of_round and context.main_eval then
local card = SMODS.create_card { set = "Base", rank = 'K', area = G.discard }
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
card.playing_card = G.playing_card
table.insert(G.playing_cards, card)
G.E_MANAGER:add_event(Event({
func = function()
G.play:emplace(card)
return true
end
}))
return {
message = localize('k_plus_card'),
colour = G.C.MONEY,
func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.deck.config.card_limit = G.deck.config.card_limit + 1
return true
end
}))
draw_card(G.play, G.deck, 90, 'up')
SMODS.calculate_context({ playing_card_added = true, cards = { card } })
end
}
end
end
?
Should work
wor*
If not idk im on mobile i cant read this code very well
Yeah it works
G.jokers.config.highlighted_limit = number
if i were to try to retexture the regular joker using malverk what would that code look like
if i extended an SMODS object with only a change to the inject function, would the extended object effectively just be the original with a different inject function?
Yes.
ok thanks :3
crash on line 14, the loc_vars "xmult"
someone be smart please
You don't have a config, also it would be card.ability[self.key].extra.xmult
Yes.
k
would i do this when a run starts or just when balatro is booted up
trying to retexture jokers using malverk can someone give me the code pretty please
In a Game:start_run hook.
Because G.jokers wouldn't exist yet.
is there a way for decks to have certain boss blinds on antes
uhhh
SMODS.Joker {
key = 'balatrue',
loc_txt = {
name = 'Balatrue',
text = {'when a probability succeeds retrigger the source of it'}
},
rarity = 2,
discovered = false,
config = {extra = {repetitions = 1}},
loc_vars = function (self,info_queue,card)
return {vars = {card.ability.extra.repetitions}}
end,
calculate = function (self,card,context)
if (context.repetition or context.retrigger_joker_check) and SMODS.post_prob and SMODS.post_prob[1] then
local passed = false
for _, v in ipairs(SMODS.post_prob) do
if v.trigger_obj == context.other_card then
passed = true
break
end
end
if passed then
return {repetitions = 1}
end
end
end
}```
im trying to make this work for probability jokers and playing cards
thats it
Yes, you need to hook eval_card
like this
No, it's function eval_card(card, context)
local oldevalcard = eval_card
function eval_card(card, context)
local g, post = oldevalcard(card, context)
G.modprefix_poster_prob = SMODS.shallow_copy(SMODS.post_prob)
return g, post
end
how exactly am i supposed to use this now
Replace SMODS.post_prob with G.modprefix_poster_prob
Code?
No, replace all of them also replace modprefix with your mod prefix.
do you get a card's suit with .suit or ?
also is if variable ~= nil same as if variable if you explicitly set variable to nil
card.base.suit
Does it work?
use #1# for your first variable, #2# for your second (if you have one) etc
Try looking at entropy
It adds an extra thing to show the entropy counter on a specific deck
I've dug through this code so many times now and I still can't find what part I'm missing... scouring the documentation isn't helping either, though I could just be blind as a bat--
polychrome = 'Polyamorous' in Localization > misc > labels
Isn't that at the bottom?
@manic rune @ionic cobalt @bold sleet Hey, wanted to reach out and ask if you'd be okay if I incorporated Tonsmith as a provide for my own API mod, Arrow. I'd been working on a music pack selection, but since someone else has already done a bunch of work on this front I might as well ask
decrement should also scale alongside prob_base for the tooltip but doesn't,
and the decrement part of the code isn't triggering from context.after
any fixes?
you should actually return the numerator and denominator instead of the base values in loc_vars
also, context.cardarea doesnt exist in context.after
yeah when i tried that before it just printed nil and nil
afaik
because you put in card.ability.prob_denominator instead of card.ability.extra.prob_denominator i imagine
swapped these as suggested
yeah thats
.
Further elaborate. Are you making another sound replacer?
-# also don't ping bepis for tonsmith. I think they no longer work on it, nor they are interested in the development or state of the mod
doesn't resolve the issue of "chance decreases by x" not scaling from Oops!
is decrementing now though
yeah thats because it is a different variable in loc_vars
Oh! you should likely edit the credits on Github, then
haha text says "ERROR" in context.after
let's fix the issue with "chance decreases by x" first and grab that value for the return text
Can I see your work, by any chance?
But point being, before doing additional work on sound replacement, I figured I could ask if I can just incorporate yours as a provide instead, since it saves me work and makes the framework more familiar for users
Ah
I mostly ended up doing a similar thing, drawing off Malverk
Can I see your work?
If you'd like?
It is mostly curiosity, more than anything.
-# tonsmith doesn't have a license, you could quite literally steal it and call it yours of you wanted. Not that I'd be happy you doing that.
-# or anyone, for that matter
additionally card.ability.extra.prob_base = card.ability.extra.prob_base - card.ability.extra.decrement is being triggered twice despite it only occuring once
I mean I'm aware. I'm asking out of courtesy
An lightweight API Mod for Balatro that adds expandable features introduced in Cardsauce - GitHub - Kekulism/Arrow at VG/credits-system
All sound stuff is currently heavy WIP and not used anywhere
api > music.lua, lovely > music_pack.toml and api > hooks > ui_definitions.lua
So, does your mod mainly implement cardsauce's mechanics?
at least the groundwork for that?
It's the framework that Cardsauce uses, separated into its own mod. I'm currently in the process of reworking Cardsauce to properly use/provide for Arrow itself
Since it's gotten a ton of upgrades since then
Ah.
Keku was the one who suggested an expansion on music selection versus just a config toggle, which led me to find yours
-# so you are the one behind cardsauce?
I'm one of the directors of Cardsauce, and a lead programmer from 2.0 onward
Oh?
Because I assume you are like, relatively somewhat sort of popular, or at least somewhat know in the balatro community?
Anyhow, so again, exactly what did you want to do with Tonsmith?
I wouldn't consider myself popular or known at all
Cardsauce is semi-popular, I am not
At least your mod gets played.
Unline the bs I make.
No matter, that's not the point of this conversation.
Anyway, as I mentioned, I want to implement tonsmith as a provided API by my own mod
per smods metadata docs:
"provides": [
"SomeAPIMod (1.0)"
], // ! Use this if your mod is able to stand in for a different mod and fulfill dependencies on it. This allows the usage of a different ID so both mods can coexist. If you don't specify a valid version, your mod's version is used instead.
reading...
So that means if you have Tonsmith it will be in charge of handing the music (in this case), and if it's absent, Cardsauce will do that instead?
someone please im too impatient lol 😔
Arrow, but yes. Basically, if you as a developer are implementing Arrow, it just fulfills the code of Tonsmith as well, and can be used the same
-# can't help, I haven't touched malverk dev ever.
Otherwise, if you have tonsmith, tonsmith takes priority
Sure thing ig.
Sure. I'll add a credits section for the three credited on tonsmith
Alright.
i fixed it but now a new error when opening textures
-# Oh right uh... Since Tonsmith's code is a fucking disaster, it is possible I complete re-write the mod, so keep that in mind. I will inform you if any major changes are made.
-# *not completely probalby the part that concerns defining a soundpack is going to stay the same, we'll see.
If you want I can also improve the code and send back to you if you like
If I'm gonna be using it for my own purposes, might as well
It's a hot dam disaster right now.
Like, the crimes that go in there to make it work are just horrid.
Honestly it's probably not that bad, it doesn't look substantially odd at a glance
Trust me, it's really bad.
TNSMI.Pack will remain intact, probably, tho.
Since that part is actually decent.
Which is probably what should concern you the most.
How can i test a joker i made?
You open the game, start a run, then open the collection, then, after getting the first mod, you hover over your joker and press [2] to discover it and [3] to spawn it.
https://discord.com/channels/1116389027176787968/1228149931257237664
https://discord.com/channels/1116389027176787968/1372508275794513962
-# the second link is just me advertising more debugging tools lol
Thanks
don't put the prefix in the definition of the sound itself
smods automatically does that for you
in play_sound or Sound.lua? removing it in the lua file didn't fix the issue
Why do lines 293 and 294 trigger as if they're context.before?
because calculation of the whole hand completes before any animations happen. SMODS.destroy_cards and calculate function returns properly add behaviors to the event queue, but the code in those two lines you mentioned execute immediately
the easiest way to get the timing right is probably to add this to your return table on 295:
func = function()
--move lines 293 and 294 in here
end
should i also change the context?
no
even with the changes, the tooltip still updates before the text animation is played
hm maybe i misunderstood how returning the function worked
ok undo that, you'll probably need to manually write the event. i am. not in a great headspace to explain how events work rn sorry lol
okay now im having difficulties probably based off this, how do i change the atlas of it so it copies a different joker
gonna try this
return {
message = tostring( (-1 * card.ability.extra.decrement) * (numerator / card.ability.extra.prob_base) ),
colour = G.C.FILTER,
func = function()
G.E_MANAGER:add_event(Event({
func = function()
numerator = card.ability.extra.prob_base - card.ability.extra.decrement
card.ability.extra.prob_base = card.ability.extra.prob_base - card.ability.extra.decrement
return true
end
}))
end
}
or maybe not
trying to find mod code that resembles what i need
I might not be getting delays correctly
it works now!
Put each of the calls in their own event.
may I see it? also what functions does the center have
i think its delay(), but put the in their own events
does rental on a playing card work by default, or do you need to do some patches to get it to actually drain money?
look through the src
or just try it
No, it doesn't work by default, it triggers twice.
But no you don't need patches to fix it either.
oh huh
oh ic
not the cleanest
https://github.com/nh6574/JoyousSpring/blob/0a5c0f6951f7f3073acb7f06ee1fafed950eef16/src/jokers/99_99Token.lua#L35
https://github.com/nh6574/JoyousSpring/blob/0a5c0f6951f7f3073acb7f06ee1fafed950eef16/src/effects.lua#L1189
by center you mean card.children.center?
sooooo why is my stake not applying all stakes up to gold or appearing above gold stake
by default stakes use your mod prefix so you need to disable it with prefix_config
thanks
is there a way to make my cards have more than 1 config
well not really
but like
context
like if context 1 then config = mult and if context 2 then config = mult, chips
can you elaborate more
i want my card to have different loc vars based of the context
yeah
vars = { card.debuff and 1 or 2 } would make #1# 1 if it's debuffed and 2 if not
uh
im going to be more specific
i feel like making a thing called miracle rank
so for example
lucky cards start getting xmult after it reaches a certain rank
that made it less clear actually
do you want the description to be different?
or just the values?
descriptions and the actual values
im pretty sure descriptions alternate automatically
ok then the issue is the values?
well yeah
then this is still the answer
i just wanna know how to alternate em
idk how to be more clear without having an example from your code
i made up the system
if i had a variable called G.GAME.othe_miracle_rank
and that if its value is greater than or equal to 3
then it would give xmult
(this is for lucky)
vars = { G.GAME.other_miracle_rank > 3 and card.ability.xmult or card.ability.mult }?
but what about config?
you can save anything you want in there, you don't need to change it between levels
oh yeah right
uhhhh
the description and loc vars isnt changing
chat
i know how to change descriptions and stuff but like
i dont at the same time
how would i make a blind disable your ability to rearrange your jokers?
want to make an amber acorn-like which shuffles your jokers and also prevents you from unshuffling them
i know theres the pinned sticker, but...
i feel like i looked into this a while ago for a starspace sticker; there's a property on cards that toggles whether they can be rearranged iirc?
maybe the cardarea as a whole would also have a similar set of properties (other properties that cards can have include selectability and hoverability), but if not, you'll have to disable rearranging for all jokers when the blind activates and re-enable rearranging for all jokers when the blind is defeated/disabled
yeah uh
how do i disable it
what if a joker is created mid-blind though
you'll just have to track that too, in the blind's calculate via context.card_added i think? (the documentation on that is really weird to me, it describes it as "when a non-playing card is added to the deck")
anyway you can disable dragging with card.states.drag.can = false (where "card" is the card object), and re-enable it by setting the same value back to true
actually yea i'm pretty sure it's context.card_added, the function for when any card/joker/etc is acquired is add_to_deck
how do i reset a global variable on starting a new game? so it doesnt persist
Are you storing the variable in G.GAME?
... no... should i be doing that?
does that just do that automatically
Yes, if you are not storing cards in that global variable.
got it
and would it also automatically persist after exiting and reopening balatro?
Yes.
ty
where the hell are you getting these
how do i check for if immutable.tp = 100?
ai
if immutable.tp == 100
ok so, all values should not be affected by cryptid.manipulate, ralsei gains random(1-10) tp by using spectral cards, filling up tp meter to 100 multiplies values of jokers adjacent to ralsei by x2.
that's the purpose
what i'm currently trying to figure out is the tp meter system
..is there niot a context for held in hand effects
am i doing this wrong```lua
if card.ability.immutable.tp == 100 then
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
Cryptid.manipulate(joker, { value = card.ability.immutable.valueincrease })
end
if i < #G.jokers.cards then
Cryptid.manipulate(joker, { value = card.ability.immutable.valueincrease })
end
end
end
end
i stole it from cotton_candy
i was hoping to make a joker that retriggers all gold cards held in hand
if
context.repetition and context.cardarea == G.hand and SMODS.has_enhancement(context.other_card, 'm_gold') then
return {
repetitions = 1
}
end
nvm got it
Yes, joker doesn't exist.
anyone have the x1 joker sheet on hand
what
@moderators see pinned message, ban for using ai
@moderator
how do i ping mods
@Moderator
why dont i have the ping perms
<@&1133519078540185692>
first try
it's not don't do it again
calculate = function(self, card, context)
if context.using_consumeable and not context.blueprint and context.consumeable.ability.set == "Spectral" then
local tpincrease = pseudorandom(pseudoseed("busterb_ralsei"), 1, 10)
card.ability.immutable.tp = card.ability.immutable.tp + tpincrease
SMODS.calculate_effect({ message = "+TP", colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card)
if card.ability.immutable.tp == 100 then
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
Cryptid.manipulate(i, { value = card.ability.immutable.valueincrease })
SMODS.calculate_effect({ message = "X" ..card.ability.immutable.valueincrease, colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card)
end
if i < #G.jokers.cards then
Cryptid.manipulate(i, { value = card.ability.immutable.valueincrease })
SMODS.calculate_effect({ message = "X".. card.ability.immutable.valueincrease, colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card)
end
end
end
end
card.ability.immutable.tp = card.ability.immutable.reset
SMODS.calculate_effect({ message = "TP Reset!", colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card)
end
end
}```
i is a number, not a card.
G.jokers.cards[i-1] and G.jokers.cards[i+1]
in place of card or i or joker or whatever is in the 1st of the parenthesis?
does next(get_X_same(2, hand)) return nil for a 3 of a kind?????
it seems to be, is that.. the intent behind get_X_same? because that does. not seem right at all
oh my fucking god i ran the eval and it does
why.
ok how do i tell whether a hand contains a pair because i thought this would work but it doesn't check for a 3oak apparently :/
i can't use context.poker_hands because this is before hand calc, that'd make it infinite loop
does this work nowlua calculate = function(self, card, context) if context.using_consumeable and not context.blueprint and context.consumeable.ability.set == "Spectral" then local tpincrease = pseudorandom(pseudoseed("busterb_ralsei"), 1, 10) card.ability.immutable.tp = card.ability.immutable.tp + tpincrease SMODS.calculate_effect({ message = "+TP", colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card) if card.ability.immutable.tp == 100 then for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then if i > 1 then Cryptid.manipulate(G.jokers.cards[i+1], { value = card.ability.immutable.valueincrease }) SMODS.calculate_effect({ message = "X" ..card.ability.immutable.valueincrease, colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card) end if i < #G.jokers.cards then Cryptid.manipulate(G.jokers.cards[i-1], { value = card.ability.immutable.valueincrease }) SMODS.calculate_effect({ message = "X".. card.ability.immutable.valueincrease, colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card) end end end end card.ability.immutable.tp = card.ability.immutable.reset SMODS.calculate_effect({ message = "TP Reset!", colour = SMODS.Gradients["busterb_universalgradient"], instant = true}, card) end end
what could I POSSIBLY be doing wrong
bunp
very important
next(get_X_same(2, hand, true))
if you pass true as the third argument it will do what you're looking for
I just basically copied the util functions from my last mod (where it didnt have a problem)
ty!
the reason it has an option to not do what you're looking for is because it uses the function to gather parts._2/parts._3/etc for poker hand evaluation, and those are only exactly pairs/3oaks/etc
are you absolutely sure that your third screenshot is loaded into the mod
you need an extra () at the very end of that line
otherwise the game will not actually run any of the code you load
THE JOKER WORKS
Sorry I was at school, yea card.children.center
how do people go about making something like The Fool but using custom consumable types instead
holup lemme get my src
when using a custom consumable make it set a value in G.GAME for last used ____ consumable
then do SMODS.add_card({key = G.GAME.variable_name})
getting there, gotta set size
Yes, use the mod calculate.
@red flower I got it, but my original joker is wrong size, so uuh close enough 🤷♂️
something like this?
No, card doesn't exist.
ah i forgot
Also you should put your mod prefix on that variable.
should it be other_card then?
No, it's context.consumeable
I see
war is over
Currently incomplete wip of code refactor for readability and conciseness
General goals for this refactor:
Implement SMODS.GameObject to extend TNSMI.MusicPack (renamed for clarity from booster pa...
Feel free to peruse. it's a draft PR because the UI is currently borked as I'm reworking it
if context.end_of_round and not context.repetition and context.game_over == false and not context.blueprint then
play_sound('crit_terminalbootup')
G.E_MANAGER:add_event(Event({
blockable = false,
func = function()
card.children.center:set_sprite_pos({x = 7, y = 0})
delay(1)
G.E_MANAGER:add_event(Event({
blockable = false,
func = function()
card.children.center:set_sprite_pos({x = 8, y = 0})
delay(1)
G.E_MANAGER:add_event(Event({
blockable = false,
func = function()
card.children.center:set_sprite_pos({x = 9, y = 0})
return true;
end
}))
return true;
end
}))
return true
end
}))
end
the game doesn't crash anymore, but the delay doesn't work
Is there some function to get all stickers on a card, or do you need to check them manually one by one?
how do you make animated sprites, I looked into the subway surfers joker in YAHIMOD, but I couldn't really find what does the anim.
iirc just changing the pos in P_CENTERS can do the trick
probably just hooking Game:update is fine
alr cool
If i have all of the soul art (for use in soul_pos in SMODS.Joker) in a different image, and the card art in a different image, how do i use 2 atlases in 1 game object??
like i think balatro (vanilla) does this, the soul thing is in Enhancers.png and the card is in another image.
you can't with the api, you would need to draw it manually
check the soul in vanillaremade
soul_set = 'Tarot',?
no
the hidden bool?
so I'd have to manually do that for each joker I want like this?
i mean ig, but it'll be 1420x4180
i dont see the problem
🤷♂️
oh right uh... tf
will this work or do i have to manually put in soul_pos
pos = { x = 0, y = 0 },
soul_pos = { pos.x + 10, pos.y},
All of my jokers soul_pos is {pos.x+10, pos.y}
Is there an easier way to just do that for all of em?
well apparently it does not
this doesn't work either :\
local _pos = { x = 0, y = 0 },
pos = _pos,
soul_pos = { _pos.x + 10, pos.y},
probably bc i don't think you can define local variable in SMODS.Joker outside of a function;-;
or what if i create a table at the top, like:
local positions = {
'Joker1': {x=0,y=0},
'Joker2': {x=1,y=0},
..etc..
}
and then use it someway in SMODS.Joker
but idk how to
maybe Joker1 could be referencing the key of the joker?
or for each joker i could switch _pos to the position then use it like
local _pos
_pos = {x=0,y=0}
SMODS.Joker{
key = 'joker1',
pos = _pos,
soul_pos = { _pos.x + 10, _pos.y },
}
_pos = {x=1,y=0}
SMODS.Joker{
key = 'joker2',
pos = _pos,
soul_pos = { _pos.x + 10, _pos.y },
}
that didn't work ;-;
by "didn't work" did you mean the game crashed or all jokers used the same pos
crashed
oh
you got it wrong
it should be
local _pos
_pos = {x=0,y=0}
SMODS.Joker{
key = 'joker1',
pos = _pos,
soul_pos = { x = _pos.x + 10, y = _pos.y },
}
_pos = {x=1,y=0}
SMODS.Joker{
key = 'joker2',
pos = _pos,
soul_pos = { x = _pos.x + 10, y = _pos.y },
}
your soul_pos was acting like an array, not a key-value table
ohh thanks
Welp, I figured on how you can replace backgrounds like that.
sick???
share the knowledge
Is this bg with parallax?
I finished drawing and implimenting all 8 of the base lunar cards for catsino!
I felt the art was a bit too samey for each one, so to differentiate them a bit more i added the roman numerals 1 through 8 as shadows on top of the moon. I think im gonna turn the transparency of it down a bit but i think it adds a bit to the look
you should make the number shadows on 4 5 and 6 brighter
turns out, someone made a unpixelated vortex mod and I studied that you can basically replace the already existing shader. Except what I did was that I found this shadertoy shader and decided to port this into balatro: https://www.shadertoy.com/view/MlsyDj
Yeah you can just change the shader that anything in game uses pretty easily
then I usually convert the shadertoy thing into a balaltro shader with the thanks of the background.fs thing and well also I had to like make custom noise shader
config = { extra = { chipamt = 1, chiptotal = 0 } },
loc_vars = function(self, info_queue, center)
return { vars = { center.ability.extra.chipamt, center.ability.extra.chiptotal, } }
end,
update = function(self, card, dt)
if not G.jokers or #G.jokers.cards == 0 then return end
local total_letters = 500
for _, j in ipairs(G.jokers.cards) do
if j ~= card then
local desc_text = ""
local loc_txt = j.config.center and j.config.center.loc_txt
if loc_txt then
if type(loc_txt.text) == "table" then
for _, line in ipairs(loc_txt.text) do
desc_text = desc_text .. " " .. tostring(line)
end
elseif type(loc_txt.text) == "string" then
desc_text = loc_txt.text
end
end
if desc_text == "" then
desc_text = tostring(j.config.center.key or j.ability.name or "")
end
local _, letter_count = string.gsub(desc_text, "[A-Za-z]", "")
total_letters = total_letters - letter_count
end
end
card.ability.extra.chiptotal = total_letters * card.ability.extra.chipamt
end,
calculate = function(self, card, context)
if context.joker_main then
return {
color = G.C.BLUE,
message = "+" .. card.ability.extra.chiptotal,
chip_mod = card.ability.extra.chiptotal,
}
end
end,
}
i have this joker that gives -1 chip for every letter in other jokers, which works great with other modded jokers, however in base balatro jokers it doesnt work
not too much of a difference but i boosted the contrast where its in the dark areas and i do think it makes it pop a lot more
good call!
oh those look cool
How do you convert from shadertoy to a Balatro shader?
I know there's some differences between the shader language love has built-in but I mean in other terms
there's this tutorial: #1371212149908836472 message
I didn't know about that thread. Thanks!
feeling like my brain's in a bit of a knot thinking about lua code so i'm gonna ask for help here
how do i generate a random rank, but not including a specific rank?
doing a while loop to just.. generate again if it rolls that would work but uh. feels very dumb
is that the best way? every other way i can think of feels kinda awkward
that's a fine way to do it
personally i dont like it so i would just make a new list with all ranks but that one
but they're both ok
This can technically work. Performance wise most of the time it'll result in a faster access, but I typically prefer a more reliable result than can be easily benchmarked, so I'd just make a new list filtering out the ones you don't want
There are cheaper hacks you can do than this, but most of them result in a non-uniform distribution
mmmaybe it would be neat if the roman numerals were a soul :o
You could, if you know the index of the rank, do a pseudorandom result of the total number of ranks minus the one you're removing, and then if result >= removed rank index, increment the index by one, and then just access by index
But only if you remove one element, else the logic gets more complicated
Hey guys how do i make a context where a global variable i made up gets changed?
You could use mod calculate
If it's some global that has global effects
Otherwise I'll need more info to advise
SMODS.calculate_context({modprefix_variable_changed = true})
now this is looking better.
What the helly
Well, if you didn'T know I'm testing out custom background shaders.
while I wait to see on how the texture offset as well as texture importing can be helped by someone as I tried my best to like get the texture coords as well as others to work
when does the set_blind() function of a blind trigger?
had it trigger a couple times during testing but now its not triggering anymore and im not sure why?
oh wait does it only trigger when you enter the blind
is there a function that could trigger when the blind first gets placed down
for an ox-like, but without needing to have a global for that because i'm gonna want to run a whole function for when the blind appears to lock in a value and just having a global that constantly gets set with that function seems uh. like it might be too much so id prefer it only happen when the blind shows up
You mean when the ante starts?
yeah, or if the blind is rerolled into it from something like director's cut
same thing as this previous thing, to avoid spoiling What the blind does, it'll choose a random rank when it first gets created and have an effect [to do with that rank], but you're able to see which one it chooses immediately in the blind select menu, so can plan your ante around it
not really something that makes sense to put into a global like all the other "specific effect determined when blind is generated"s like the Ox, so im kinda stumped as i havent seen anything like this anywhere else
maybe Eta or Iota in entropy would have something similar? i'm not sure if that actually picks the random suit/blind beforehand or not tho
why not
trying to code a custom challenge into my mod and although it kinda loads, it comes up with a weird error
nope! those dont set anything until you actually enter the blind
show the code for the challenge?
i made an src folder
SMODS.Challenge {
key = 'silverhatchet',
jokers = {
{ id = 'hatchet_hatchet', eternal = true },
{ id = 'j_certificate', eternal = true },
},
restrictions = {
banned_cards = {
{ id = 'p_standard_normal_1', ids = {
'p_standard_normal_1', 'p_standard_normal_2',
'p_standard_normal_3', 'p_standard_normal_4',
'p_standard_jumbo_1', 'p_standard_jumbo_2',
'p_standard_mega_1', 'p_standard_mega_2' }
},
},
banned_tags = {
{ id = 'tag_standard' },
}
},
}```
the first joker is missing the j_ prefix
also do you have a localization file
yeah
as for it saying ERROR you need to put it in your localization file
whats that
en_us.lua
wait not .json, .lua
doesnt seem like it, no
its where all the names of your stuff goes
it should be like this
https://github.com/nh6574/VanillaRemade/blob/0d158691dc9aac5664bca0e09e531d93519fba04/localization/en-us.lua#L3157
or use loc_txt
oh wait does jokerforge just use loc_txt for everything thats probably it then
how do you use loc_txt for a challenge again
yeah it uses loc_txt
ah then yeah you gotta do that to make your challenge name show up
otherwise it'll just say ERROR
the lack of the j_ prefix is why it was crashing though, thats an easier fix
would loc_txt = { ['name'] = 'Silver Hatchet', ['text'] = { [1] = 'Hatchet and Certificate are eternal', }, ['unlock'] = { [1] = 'Unlocked by default.' } }, work
text and unlock wouldn't do anything afaik
it'd already immediately show the eternal sticker anyways, dont think you need that
but yeah i think the name part would work? somebody else double check though im not entirely sure
that's what it says on the link i posted
anyways still stumped by this
i think you're overthinking it
it's fine to run a function at the start of the ante even if the blind is not selected
you could do it in get_new_boss tho
but what do i do if it then gets rerolled into
oh? 👀
the rank would always be selected at the start of the ante regardless of which boss blind is next up
then, whether your specific blind is set at the start of the ante or rerolled into, it can just read the pre-selected rank
if you want each reroll to be different then yeah you probably need to hook get_new_boss
yea if you go for the start-of-ante route, it'll be the same rank if someone manages to reroll so much they roll into the blind twice
it's sad that reset_game_globals doesn't have an end of ante check
the ox does it at end of round when the blind was a boss blind
i would just use mod calculate with the new ante end context
SMODS.calculate_context(G.GAME.othe_miracle_rank_changed = true})
Would this work as a custom context?
no
Damn
i think you misunderstood something's answer
you use calculate_context to create a context but it can't detect when the value changed
you need to call the function each time the value changes (it's easier to make a function specifically for this)
ante end?
wouldnt that not work on ante 1 then?
is there an ante start context?
not afaik
just use context.ante_change
does that work ante 1
i would just use reset_game_globals for start of run and ante_end for the rest
the real solution is for smods to add an add_to_deck function to blinds
i mean you're told in context.ante_change by how much it changes
just check if it's positive
still doesnt work on ante 1 though
true....
has a pr for that been made yet
no
easy solution is to make it not appear before ante 2
is there a list of every context somewhere or something
cant find it on the wiki
the calculate functions wiki page should be more up to date now, i don't think it's complete yet but it does have ante_change on there
what is your goal
A function that if the said variable is changed
Like for lucky card
Id want to use this context/function to adjust its variables
When you change the variable you would call a context or function.
Yea i guess
instead of variable = variable + 1
you want
function mod_variable(mod)
variable = variable + mod
SMODS.calculate_context{ variable_mod = mod }
end
Can you explain to me how that works
so in the place where you modify the variable you replace it with a function so it also runs the context
and this also allows you to do other checks with that variable more easily
Ok
where are crashlogs stored?
feeling like ive done something horribly wrong as the game is just closing itself without popping up a crashlog
Mods/lovely/log
ty
uh
theres no crashlog the log just. ends 
how am i supposed to figure out what went wrong
Yes, that means the game was in an infinite loop.
It's the sprite for the soul of The Soul
damn do i not even get a stack log to see what was looping 😔
ik that, but the other thing
also i meant is it a card
or smth else
No, it's a Sprite
how do you actually replace the background shader, if i may ask? i thought maybe smth with define_draw_steps but that aint working for me
ok
Sometimes the game gets to a "stack overflow" reason of crash screen, otherwise, a loop like that tends to bypass the error handler and close out.
how do i make a smth like that
local oldmainmenu = Game.main_menu
function Game:main_menu(change_context)
local g = oldmainmenu(self, change_context)
G.shared_sprite = Sprite(0, 0, 71, 95, G.ASSET_ATLAS["modprefix_atlaskey"], {x = 0, y = 0})
return g
end
tyyyyyyyyyyyyyyyy
hey question
how come prints seem to usually fire off twice?
common mod prefix L
gotta love to hate it
Uh my variable is global
seems to be a trend ive noticed with basically every mod
whys it going off tiwce?
boss icon not showing up
this is blinds.png
this is the code (ignore that its set to "the wall" rn, ill fix that)
this is main.lua
Is the top part for initialization and the bottom part for usage?
you gotta specify the atlas in the lua file for the blind, rn it has a position, but doesn't know what file to use
You're not setting the atlas.
Also why is y 31 if there are only 3 blinds?
idk i counted from violet vessel onwards
its based on the position in your sprite atlas, not the position of every blind ever
so no need to account for that
oke
this is what the code looks like rn
the new atlas
ruh roh
i also still get "small blind"
idk what to do
it seems to launch fine
but checking it from, the menu breaks the game
So i use the top one to initialize and the bottom one to calculate?
No, it's 34x34 and the atlas_table should be ANIMATION_ATLAS
frames = 21
whats a good way to have all hearts debuffed while you own a specific joker
and if the joker gets removed in some way i want to remove the debuff from that source while still preserving the debuff if you are in the boss that debuffs hearts
do you know what a function is
this would also debuff future hearts obtained
wdym
also just to get ahead of it, ante_end also needs to check for ante_change
or whatever the other context is called
if context.debuff_card and context.debuff_card:is_suit('Hearts') then return {debuff = true} end
is there a function for converting a numerical rank ID (e.g. 11) into a rank string (e.g 'Jack'), or vice versa?
No, you have to iterate over SMODS.Ranks
But for key to id you can do SMODS.Ranks[key].id
okay next question is there a function for directly getting a rank string from a card
are you getting the id from a card?
yeah from a card
yeah card.base.value
ty!
Well yeah
Im just feeling a little confused
ok uh
im trying to figure out how to downgrade a scored card by one rank
for a boss blind
if context.individual and context.cardarea == G.play then
assert(SMODS.change_base(context.other_card, -1))
return {
message = "Downgrade!"
}
end
end
}
this is the code
its saying that -1 isnt a rank
which is true
It's SMODS.modify_rank
i need more details about what you're confused about because i dont get it
SMODS.Blind {
key = "h_gun",
dollars = 5,
mult = 2,
pos = { x = 0, y = 2 },
boss = { min = 1 },
boss_colour = HEX("cbb9a3"),
atlas = 'CustomBlinds',
loc_txt = {
['name'] = 'The Gun',
['text'] = {
[1] = 'A random rank is debuffed',
[2] = 'every played hand',
},
},
loc_vars = function(self, info_queue, card)
return {vars = {localize((G.GAME.current_round.rankvar_card or {}).rank or 'Ace', 'ranks')}}
end,
set_ability = function(self, card, initial)
G.GAME.current_round.rankvar_card = { rank = 'Ace', id = 14 }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if context.other_card:get_id() == G.GAME.current_round.rankvar_card.id then
return {
debuff = true
}
end
end
if context.cardarea == G.jokers and context.joker_main then
if G.playing_cards then
local valid_rankvar_cards = {}
for _, v in ipairs(G.playing_cards) do
if not SMODS.has_no_rank(v) then
valid_rankvar_cards[#valid_rankvar_cards + 1] = v
end
end
if valid_rankvar_cards[1] then
local rankvar_card = pseudorandom_element(valid_rankvar_cards, pseudoseed('rankvar' .. G.GAME.round_resets.ante))
G.GAME.current_round.rankvar_card.rank = rankvar_card.base.value
G.GAME.current_round.rankvar_card.id = rankvar_card.base.id
end
end
end
end
}```
it not worky
it launches, but the random rank doesnt get debuffed per hand
no, it's a base smods feature
check SMODS.DeckSkin
returning debuff only works in context.debuff_card
does anyone know how to change the amount of joker slots a joker takes up?
card.ability.extra_slots_used
This value can be subtraced from to get something like 1/2 a joker slot right?
Yes, card.ability.extra_slots_used = -0.5
First when initializing the function do i put in the Whooole thing or just the top part, second where do i use that for cards that manipulates the variable and third where do i use that as a context
i don't know what you mean by top part
the function would be used like mod_variable(2)
this increments it by 2
of course don't just call it mod_variable because that's too generic
after you set that up you can use context.variable_mod in any calculate function
how do i make this not trigger per animation
like its funny but i need help
card.ability.extra_slots_used = card.ability.extra_slots_used - 0.5
if context.repetition and context.cardarea == G.play and not context.other_card:is_face() and SMODS.pseudorandom_probability(card, 'jabong_sock', 1, card.ability.extra.odds) then
return {
repetitions = card.ability.extra.repetitions,
message = "Ag",
}
end
end
}```
don't set it in the calculate function at all
you should do it in the config table, i.e.
config = {
extra_slots_used = -0.5,
extra = {
-- whatever other variables the joker has
}
},
that works actually
Straight boostin it
key = card.ability.negative and "j_jabong_jimbyramid_alt" or nil
is fine for my config, right?
no
so the card.ability.negative is fucked then ok got it
also how would I change the language of one specific joker
like just the joker in specific
by config do you mean loc_vars?
also it's card.edition and card.edition.negative
ah thanks
ok so apparently now it crashes
Yes, you need to keep card.edition and
oh
do enhancements have an equivalent to on_remove for when the enhancement is no longer on the card?
No, you're not calling the context, also replace the .s with _s in the function name.
but the variable is called G.GAME.othe_miracle_rank
also i changed it and i can not express this enough
for some unknown reason creating the thing that modifies the miracle rank closes the game
Yes, you can't have .s in function names.
ok
lemme show you the code that i changed it to
do you know why this may close the game?
you are calling the function in calculate which calls the context function which calls calculate which calls the context function etc etc
so stack overflow
yes
which pic
ok
even without the overflow it will just increase the rank all the time
how do i have a joker show multiple text boxes in sequence
wherever you normally have their localization, just do this
text = {
{
"Text box 1",
"goes here"
},
{
"Text box 2",
"goes here"
}
}
so instead of text just being a table of strings, it's a table of tables of strings
the context isnt doing anything to the lucky card
when are we getting horizontal multibox which is just a table of tables of tables of strings
you should add some prints to the if the code reaches that part
ok
it aint printin
return {
message = "text",
extra = { message = "text 2" }
}
i see
code?
what's the part where you use the function
no i mean show me how pic 1 looks like now
you mean anaglyph joker?
what about if the number of messages is arbitrary (e.g. a joker where a coin is flipped until tails)?
where you use the mod_ function
nest extra tables
you can also do return SMODS.merge_effects { { message = "heads" }, { message = "heads" }, { message = "tails" } }
<@&1133519078540185692>
<@&1133519078540185692>
tyvm
is the rank being modified
ty mods
yep
huh weird then
can someon tell me what i did wrong (malverk)
it does have blind support
ohhhhh i have to add the frames = 21
yeah it needs the frame count
does malverk have edition support
Anyone know how to change the textures of Small and Big blind specifically for a mod?
easiest with malverk
Is it possible to rotate the orientation of a UI node through a config table?
For edition visuals do you have to write lines of code like you would with a mechanic or is simpler
It's not as in depth
But programming shaders requires the use of a different language from Lua
I'm not too familiar with making shaders so I can't help you with actually learning the shader language
Do you have to know how to code to do it
i know how to code and i dont know how to do it
Also
Making cool shaders will most likely involve some intensive math
The only ways to make cool shit is to do something I despise
Since a shader essentially can calculate the color of a pixel based off its position and external variables like time if so desired
Everything in high school ruined math for me
I'll probably just draw a mockup and hope someone who knows how to do it can put it in
What kinda shader do u plan on making
Or want to make
Hmm
So a plasma-like effect
I don't think the math will get too terribly bad
3d shader math makes me want to end myself
At least I know it'll be easy for whoever hypothetically codes it in
Give me 2 business days and I will figure out how to make functional balatro shaders
uhh
somethings wrong with my joker
SMODS.Joker {
key = 'spinner',
loc_txt = {
name = 'Spinner',
text = {
"Retrigger all {V:1}#1#{} cards,",
"suit changes every round"
}
},
config = {repetitions = 1},
loc_vars = function(self, info_queue, card)
return {
localize(G.GAME.current_round.spinner_card.suit, 'suits_singular'),
colours = { G.C.SUITS[G.GAME.current_round.spinner_card.suit] }
}
end,
blueprint_compat = true,
perishable_compat = false,
eternal_compat = true,
rarity = 2,
atlas = 'placeholders',
pos = { x = 1, y = 0 },
cost = 5,
calculate = function(self, card, context)
if context.cardarea == G.play and context.repetition and not context.repetition_only then
if not context.other_card.debuff and context.other_card:is_suit(G.GAME.current_round.spinner_card.suit) then
return {
message = 'Again!',
repetitions = card.ability.extra.repetitions,
card = context.other_card
}
end
end
end
}
heres the error
would just do it in F#
Your loc_vars variables are not in vars in the return
?
return {vars = {
localize(G.GAME.current_round.spinner_card.suit, 'suits_singular'),
colours = { G.C.SUITS[G.GAME.current_round.spinner_card.suit] }
}}
is it possible to make a deckskin mod that has compatibility with modded suits and ranks?
not sure
psure you can, i know theautumncircus comes with a deckskin for grab bag's eyes
huh its.. really that simple
suit = "gb_Eyes"
all you gotta do is use the id of the modded suit (plus the mod prefix)
if you're getting errors or its not working, probably you're just forgetting the mod prefix or smth
oo thanks!
i'll look at this and try to figure things out
iterate G.playing_cards and use :change_suit (on the card object)
checkered deck does this
she's asking about deck skins, not a deck itself
ahh yea then that, forget deckskins is a thing
display_ranks are just which ranks will show up in the preview (normally just Jack/Queen/King but you'd probably want to add the apostle to there if you have a custom apostle, for example)
that's exactly what im going to do actually xD
Dont know what is wrong with it
lemme know if you run into any problems or if it works well
actually, could i see how it looks too? whats the deckskin gonna be of?
okay. really stupid question here but whats the function for checking if a card.. is a joker
you don't have any other mods installed?
Nothing, card.ability.set == 'Joker'
No, like only basic mods like cryptid
this is it
It's probably one of those mods. When does it crash?
it starts when its only steamodded and regals
You could ask in their thread https://discord.com/channels/1116389027176787968/1404984180458262599
I will try thanks Lars, it is working now but no talisman I guess
hey y'all, trying to do ui stuff but i think i've missed something and i need a sanity check. why is my ui not being drawn? "wow" is printed when i call suika_bg().
function G.UIDEF.suikamain()
print("wow")
local t = { -- example from the ui guide
{n = G.UIT.ROOT, config = {r = 0.1, minw = 8, minh = 6, align = "tm", padding = 0.2, colour = G.C.BLACK}, nodes = {
{n = G.UIT.C, config = {minw=4, minh=4, colour = G.C.MONEY, padding = 0.15}, nodes = {
{n = G.UIT.R, config = {minw=2, minh=2, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}},
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}}
}},
{n = G.UIT.R, config = {minw=2, minh=1, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}},
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}}
}}
}}
}}
}
return t
end
suika_menu_node = {n=G.UIT.O, config={object = suika_menu}}
function suika_bg()
local suika_menu = UIBox{
definition = G.UIDEF.suikamain(),
config = {align='cm', offset = {x=G.ROOM.T.x,y=0},major = G.ROOM_ATTACH, bond = 'Weak'}
}
return suika_menu
end
bump
I think you need to remove the () from the definition part in suika_bg
takes a function not the output
you have to make a shader named after the already existing shader.
Kinda like this:
are there any mods that have a good example of adding a completely new ui feature, that acts independently of other UI? (eg. DebugPlus's debug menu, HotPot ads)
I'm having some trouble understanding what this part of the UI page on the wiki means. I want to create a new UI feature, but how exactly would I place it in an object node? I get the crash message "engine/ui.lua:242: attempt to index local node (a function value)" when i attempt to eval the suika_bg() function below:
function G.UIDEF.suikamain()
local t = { -- example from the ui guide
{n = G.UIT.ROOT, config = {r = 0.1, minw = 8, minh = 6, align = "tm", padding = 0.2, colour = G.C.BLACK}, nodes = {
{n = G.UIT.C, config = {minw=4, minh=4, colour = G.C.MONEY, padding = 0.15}, nodes = {
{n = G.UIT.R, config = {minw=2, minh=2, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}},
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}}
}},
{n = G.UIT.R, config = {minw=2, minh=1, colour = G.C.RED, padding = 0.15}, nodes = {
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}},
{n = G.UIT.C, config = {minw=1, minh=1, colour = G.C.BLUE, padding = 0.15}}
}}
}}
}}
}
return t
end
function suika_bg()
menu = UIBox{
definition = G.UIDEF.suikamain,
config = {align='tmi', offset = {x=0,y=0},major = G.ROOM_ATTACH, bond = 'Weak'}
}
return menu
end
A UIBox requires a full UI definition tree, so you need to call your UI def function to feed the return. It's trying to create a UI tree without that. But beside that, I believe you have an extra wrapping parenthesis. The root node should be the outermost table
@bold gyro
People who don’t understand UI trying to help with UI smh, thanks for the good explanation winter 👍
Indeed. although I thought want to ask WIN'ter about the texture issue I've been dealing with recently not sure if WIN'ter has an answer to this but yeah. 'Im also still learning about shaders and right now there is soemthing wrong when I try to make a shader that involves with the texture.
I have yet to make an UI but honestly, good to know about how UI worked or how it functions to be honest.
Well one I have made a jpeg shader which it did work. however the texture atlas acted weird as it wasn't rendering exactly what I thought dispite it did only work for the 1st which is a regular joker.
And the other one I had tried to make the deltarune profency with custom textures but it doesn't render the texture but instead it only displays the mixed color version of it. (the 1st two are the issues while the other two are what they supposed to be)
also another thing is it possible for the prophency one to render outside of it's card borders and such?
if you want I can provide the shader code so you can have a look.
the 1st one is supposed to be a jpeg compressed and the other one is obvious to be deltarurne prophency panels
Yes and no. You can manipulate the overall rect of the shader via the vertex shader which can extend beyond the borders of the original card, but I'd you want something that looks more pixel-perfect, you're better off just doing pixel shader effects
The simplest explanation for the first one is probably just that you're using incorrect UV coordinates or not transforming them correctly
Show me your shader code
alright give me a moment
let me show it here temporarily:
Fwiw you can remove the compressed extern and the dummy block with it
The default Balatro shader format won't crash if you don't have the filename extern, it only sends the extern if it exists afaik
Source: have made multiple shaders that don't use it
I see.
oh one more thing:
local depth_blue_path = (TestMod3.path
.."assets/images/depths_blue.png")
local depth_blue_data = assert(NFS.newFileData(depth_blue_path),("Epic fail"))
TestMod3.depthblueimagedata = assert(love.image.newImageData(depth_blue_data),("Epic fail 2"))
TestMod3.depthbluepng = assert(love.graphics.newImage(TestMod3.depthblueimagedata),("Epic fail 3"))
TestMod3.depth_blue_width, TestMod3.depth_blue_height = TestMod3.depthblueimagedata:getDimensions()
local depth_dark_path = (TestMod3.path
.."assets/images/depths_darker.png")
local depth_dark_data = assert(NFS.newFileData(depth_dark_path),("Epic fail"))
TestMod3.depthdarkimagedata = assert(love.image.newImageData(depth_dark_data),("Epic fail 2"))
TestMod3.depthdarkpng = assert(love.graphics.newImage(TestMod3.depthdarkimagedata),("Epic fail 3"))
TestMod3.depth_dark_width, TestMod3.depth_dark_height = TestMod3.depthdarkimagedata:getDimensions()
SMODS.Shader({ key = 'compressed', path = 'compressed.fs' })
SMODS.Shader({
key = 'prophecy',
path = 'prophecy.fs',
send_vars = function(sprite, card)
return {
textureFront = TestMod3.depthbluepng,
textureBack = TestMod3.depthdarkpng,
textureFrontSizeWidth = TestMod3.depth_blue_width,
textureFrontSizeHeight = TestMod3.depth_blue_height,
textureBackSizeWidth = TestMod3.depth_dark_width,
textureBackSizeHeight = TestMod3.depth_dark_height,
useLinearRGBA = true
}
end,
})
I made this image importing thing so it can load the texture for the prophecy one.
and here are the textures I made for the prophency shader edition thing:
but I will remove that dummy block
Okay so I probably do not have the ability to properly debug the jpeg shader given the time and me being on my phone, but my first question on the prophecy shader is that there's a call to clamp a value at the end between 1 and 1, which would result in the final color alpha always being 1
I assume that's unintended
I see. although I did remove the dummy block and gave me this:
Did you also remove the extern declaration for it at the top of the file?
yeah.
plus I don't think "compressed" is used anywhere but that dummy thing is what makes the shader usable if I recall correctly
dunno why it's the cause of that
or even when I add back it wouldn't find any workflow of the compressed
That's what I mean, I've used shaders before that specifically avoid this unused variable
Oh to answer the question about the prophency shader about the clamp thing. If I do recall that it might have been that it was designed that way to render the prophency effect. But there is a shadertoy shader which I found and did attempt to port into balatro.
so for compressed how I can make it useable?
than being unused
Just put the block back for now I suppose. I don't have access to vanilla code right now to look at draw_shader
How do I do this
Other than that I unfortunately did not expect the shaders to be this complicated which is not something I think I'm in a position to look into right now, since I'd probably need to implement the code myself to give you a better look
Sorry orz
I see.
Basically both of these are def solvable problems, and I'm probably the person to ask, I'm just in bed in my phone at 2 AM so my faculties are limited
The thing that strikes me about the jpeg shader is that the simulated compression effect is for Jimbo joker, but slid to the left
maybe looping through the consumables and checking for card b under card a?
Which tells me that there's some scaling issue with how you're using the UV coordinates, since that would be expected if you're not scaling it correctly to the full atlas width for whatever pixels you're finding with the texel function
Yeah, cause I think it was that there was sometihng called the "BlockSize (or BS for short)" that makes te jpeg effect
there are few examples I found on shadertoy that had managed to make the jpeg compresison shaders
Also even though I tried my very best to port the one that wold actually worked and it did work besides that scaling issue that I never encountered before
Off the top of my head, I'd look at how you're using those width and height mod values since the purpose of those values is to get you a UV between 0 and 1, but for larger atlases, your usable UV coordinates are in some smaller range. I used a similar thing specifically to match pixels for shaders of varying atlases to textures I was passing in that were exactly one unit in size
cause last time when I try to port a shadertoy jpeg shader into the gmae somehow it doesn't render.
I think the problem is that you’re just ripping shader toy shaders so you don’t know what the code does
Except I already knew the code does except it's something I want to test that no one had even ever tried to port most of shadertoy stuff into balatro. Now one day I could make my own shader but right now I'm suing shadertoy to atleast study and understand the grounds of it when it comes to porting these into other format of useage of shaders.
MAybe it is a problem but right now I am still learning about trying to port shaders into other ways since apperently when I also saw the tutorial of shadertoy shaders it might be a first step to understand the kind of shaders to work around.
hm... yeah I think it was when I had the other issue of the texutre being scaled differently and in which I discovered one of your codes and decided to put it there to fix it up but yeah that almost lead to another problem.
Is it possible to detect the highest possible hand type in a given hand, or do I just have to iteratr through all possibilities? If so, how would I have to iterate it?
G.FUNCS.get_poker_hand_info(cards) gets a bunch stuff with the highest ranked hand type in those cards being one of them
hello everyone. im trying to reskin the backgrounds of the default boss blinds, how can i do?
how do i check for if a poker hand is lv. 20
if G.GAME.hands['modprefix_key'].level == 20
high card in this case
i think i can just replace modprefix_key with "high card"
No, it's High Card
oh yeah, how do i make sure this only works when a certain mod is enabled
next(SMODS.find_mod("starspace")) then```?
Do you know how I can get the table for playing the possible hand? I'm not sure how to retrieve the table that shows the possible plays of a certain hand in G.FUNCS.get_poker_hand_info
Yes, because it doesn't exist.
Can you explain a bit more?
Is it not the third point here? Or am I mistaken?
No, those are the contained poker hands.
How can I call this table then?
@red flower good news the context works, bad news is that it only affects an individual lucky card
is the idea that all lucky cards permanently change when the rank increases?
Yes
I think i should just give them global variables
instead of doing mult = card.ability.extra.mult just do something like mult = card.ability.extra.mult * G.GAME.variable
or mult + number * variable
I literally did
Oh wait
You mean for the variables or the calculation?
in the return values
Oh no i didnt
But even if i did
What about the description?
Also also
Im trying to make it have an alternate description once the variable reaches 3+
you do the same thing but in loc_vars
Uhhh
my answer is not going to change from the last 2 times i answered this lol
Dam
Can you show an example so i dont set my laptop on fire
can i see the current loc_vars
Ok
Why would your laptop be set on fire
i might screw something up
ok you see how it says card.ability.extra.mult at the bottom?
instead of that you do card.ability.extra.mult * G.GAME.variable
dam this image blurry
I dont understand why its always triggering the thing even if there is a 1 in 2 chance
(but i want it to be card.ability.extra.mult + 2*G.GAME.var)
if it's that then im afraid it is impossible and you have to scratch the project
(/j)
why
/j
how can I change the sell values? I want this one to add its sell value to all other owned jokers
vanilla remade
the idea is correct but the condition is checking if the joker is the same as the one doing the effect, you want ~= instead of ==
also you can use vanilla remades giftcard code as an example
(this is the said code)
OH
nevermind guys im an idiot
i found it
same
Hi friends! I have a bit of a complicated ability this time around, but I'm hoping we'll be able to make it work.
The idea I have for Zamazenta is that it detects the least played poker hand and levels it up. However, since there can be (and often are) multiple hands that have been played the least, I want it to level up all that apply. How would I make this work?
I think the code can work now, but every time I try to add this joker to my deck, the game crashes and the problem seems to be in one of the contexts on line 841
wdym?
Not you
Im dumb, thanks
yay it works
(its pink because i made a gradient of green and miracle sonic pink)
so it changes color like negative text?
yeah
also i changed it again
(just found out gradients work for x colors)
now to rework the rest of the vanilla
Coming once again to ask if there's an easy way to get all stickers on a joker
otherwise i'll just check for the stickers i care about manually lol
wdym?
like some sort of Card:get_stickers() that'd return a table with all the stickers on the card
perish, rental etc
i dont wanna burst your bubble
but i dunno
welp
its time to rework the wheel of fortune
and make it trigger thrice
isn't it a bit too busted? at the very least its 3/4 chance to proc, and in the best case scenario its 3 editions
I should maybe make a Card:get_stickers() at some point
ok fine
trigger twice
at best
and the odds at best is 1 in 3
bruh, when I sell the joker, it adds the sell value TO ITSELF and disintegrates 😭 😭
Yes, but it also adds general content and makes luck based cards more busted
For example
Space joker could now have a 1 in 20 chance to level up all hands
Or hallucination can now have a 1 in 2 chance to either create a tarot or a spectral
Im also going to apply this system to my stuff as well
sounds cool
how do I create a card from a pool ?
SMODS.add_card({pools = 'rare_food_pool', edition = 'e_negative'})
set instead of pools
bump
hello, my game keeps crashing with steam modded and tailsman loaded, nothing else, game runs perfect without them
Hello. Quick question. Is there a way to tell if the player is in a blind or not?
are you playing or what?
check G.STATE
k
G.GAME.blind.in_blind
ty
cursed
Bump
Bump
for non-dev troubleshooting questions i recommend #⚙・modding-general
decided to try to mofidy the splash screen with a new shader code and....
it didn't show the shader I want it to show
see pinned
See pinned
oh im not allowed to talk about making
i thought like
;-;
mb
🍅