#💻・modding-dev
1 messages · Page 596 of 1
How do you use SMODS.Probability?
theres a SMODS.probaillty?
yes but its not documented apparently
you might have to read the code idk or someone else knows
isn't that just a variable/table?
sorry, G.Discard
I haven't look that far into the code yet idk
Main Notes
Added SMODS probability functions
Poker Hands visible property adjustments
Animation adjustments
certificate/marble
card juicing on conditional upgrades
level not updating when levelli...
What is the goal?
I cant find the optional stuff in the wiki anywhere ugh
I want to use contexts related to discards
as in
this yknow
SMODS.current_mod.optional_features = function()
return {
cardareas = {discard = true}
}
end
i like doing eval ease_dollars(math.huge) using debugplus to get infinite monies
and that's why we read other people code for "inspiration"
ive used buncos bits code for a fair few of my jokers
hasnt bunco been outdated for a while
the old code still works and that all i need
A fork exists that is being maintained for modern versions.
if you arent using the fork good god please dont
use vanillaremade as reference instead
the original bunco uses oldcalc
it was just the animation code
holy good pull thank you
the entirety of vanilla remade in the latest smods
question #⚙・modding-general message
your just tinting it blue right?
@timid zinc told me to ask y'all where i can find the G.localization.descriptions thing
Why is one half blue half red and the others blue? Shouldn't it be 2,5 Jokers red and 2,5 Jokers blue?
You can open balatro.exe like a zip file and see the layout of the localization file
shaders are witch magic to me sorry
You can either just change the localization file directly and rezip the file back into an exe (But you wont be able to distribute your mod) or create a mod that accesses G.localization. and changes the values in it
To me too but I need to learn them
No, you would just overwrite the values in the localization file for the mod.
Are you normally not able to edit the en-US.lua file when you open it using that method?
Yes, you have to use software that can edit files within the zip without extracting it, like 7zip.
You can edit it yeah
This
Wait, how do I get the screen size for a shader?
Oh, I was tryna do it with winRAR. Does it not work if u use winRAR?
No, it doesn't, I think.
It seems like you have to delete the file and put in the new edited file if you're using WinRAR
how can a boss blind change the requirements of other blinds in the same ante?
bump
okay wait scratch that
how can a boss blind change other blinds to specific boss blinds?
bump
G.GAME.round_resets.blind_choices.Small = 'modprefix_key' and G.GAME.round_resets.blind_choices.Big = 'modprefix_key'
awesome ^^ thanks
if i reroll into the boss, does it change the small blind and big blind?
no
Nothing's changing as in the patches aren't applying or the showdown blinds don't show up?
the patches are applying, but the showdown blinds don't show up
ok so uh
im trying to make a balatro joker that copies the effect of a random joker
i tried making it in jokerforge but it just isnt working
is it possible to dynamically change the volume of a played sound without replaying it?
Yes, the third input of play_sound is the volume.
but wouldnt running play_sound again just play the sound a second time
Why do you need to call it again?
im trying to make it change the volume mid play
like progressively get louder/quieter over time based on a value
How can I make a mod compatible with older smods version? Like to be playable in multiplayer
Do I need to get rid of SMODS.Back or SMODS.destroy_cards, or what would enable compatibility?
i think i did the text edit thing successfully guys, wish me luck
You want to change the volume of a sound while it's playing?
Perhaps you could change G.ARGS.play_sound.vol
okay, its loaded successfully, apart from the fact that it crashed.
or maybe if theres a way to have multiple music tracks playing at once
one being the sound effect and the other the normal game music
What did you change?
ill give this a try thx
I changed every instance of "Joker" to "Jimbo". I think it might have been the Undertale/Deltarune mod that caused the crash.
Was it case sensitive?
option 1: learn! the people here are very helpful and theres a ton of good resources, and lua is definitely one of the simpler languages to learn
option 2: you could get people to code for you too ig, though this has less chance of actually working
You need to change Jimbo={ back to Joker={ on line 434
Log?
okei c:
No, I just copied it straight from the crash screen in the game
That's what I was thinking.
What's an alternative to SMODS.destroy_cards? There's an incompatibility with an older version of smods, and I'm suspecting that may be the issue
you can use Card:start_dissolve() and then manually calculate the cards destroyed context
Okay, I removed UTDR from my mods folder, it loaded up just fine, but the game crashed when I opened the jokers part of my collection.
nvm found it from this person, gg thanks
can just do this and as long as timer has a value it loops indefinitely
Thank you!
Like the edited localization file?
yeah
okay apparently something did change, but thats just stopping showdowns from spawning in ante 8. how
its not appearing
like im dragging it onto discord and the message just doesnt send when i press enter
What does it look like in the lovely dump?
full function
Does anyone know what in this code could make it not compatible with older steammodded version (1.0.0~BETA-0711a-STEAMODDED so it would work with multiplayer)? The mod loads and the deck is present, but the halving doesn't work
name = "Halving Deck",
key = "halve",
pos = {
x = 1,
y = 4
},
loc_txt = {
name = "Halving Deck",
text = {"At the end of each round,", "destroy half of the deck", "(rounded up)"}
},
_halve_deck = function(self)
if not G.playing_cards then
return 0
end
local eligible = {}
for _, c in ipairs(G.playing_cards) do
if not c.removed and not c.shattered then
eligible[#eligible + 1] = c
end
end
local n = #eligible
if n <= 1 then
return 1
end
local to_destroy = math.ceil(n / 2)
for i = n, 2, -1 do
local j = math.random(i)
eligible[i], eligible[j] = eligible[j], eligible[i]
end
for i = 1, to_destroy do
local _card = eligible[i]
if _card and not _card.removed and not _card.shattered then
_card:start_dissolve()
end
end
return 1
end,
calculate = function(self, back, context)
if context.end_of_round and not context.game_over and context.main_eval then
G.E_MANAGER:add_event(Event({
func = function()
self:_halve_deck()
return true
end
}))
end
end
}```
if i dont patch that the showdown check doesnt ever get reached, though. the check for if it should add a showdown to the pool is in the elseif after
and it would just not check for a showdown at all unless it is the win ante
Have you tried putting a patch that prints eligible_bosses?
it seems to be adding showdowns, but not removing normal bosses
Yes, but they both do the same thing.
so, whats the issue here? should i get rid of one of the two patches?
Yes, try removing the first patch.
same result seemingly
Does time not exist for shaders?
how do i stop a card from getting debuffed?
return prevent_debuff = true in context.debuff_card
ty
Or more specifically: Is there a thing that helps animate the shader?
this isn't working and i can't figure out why,, ,
if context.debuff_card and context.check_enhancement and context.other_card.config.center.key == "m_wild" then
return { prevent_debuff = true }
end





context.debuff_card and context.check_enhancement don't happen at the same time.
What is the goal?
preventing wild cards from getting debuffed
if context.debuff_card and SMODS.has_enhancement(context.debuff_card, 'm_wild') then
return { prevent_debuff = true }
end
ty 
how do i change it from "saved by Mr bones" to something else
change this return value
be aware that it is a localization entry key so you cant do much without a localization file
whats a localisation file?
No, it was changed.
No, it works for both.
oh
but then how does it decide wether to localize or use the raw string
because theres no localize function there
It checks if G.localization.misc.dictionary[G.GAME.saved_text] exists.
ah i see
okay it seems i am mistaken
you can replace the key in saved with just a plain string
localization files are still better though
yes i am
try back.config.center:_halve_deck()
How do you animate shaders, if that's even possible?
time
Elaborate, please?
look into like any shader file, they all have the line extern MY_HIGHP_OR_MEDIUMP number time; near the top
which i can only assume is a time value
This?
#define PRECISION highp
#else
#define PRECISION mediump
#endif
extern PRECISION vec2 learning;
extern PRECISION number dissolve;
extern PRECISION number time;
extern PRECISION vec4 texture_details;
extern PRECISION vec2 image_details;
extern bool shadow;
extern PRECISION vec4 burn_colour_1;
extern PRECISION vec4 burn_colour_2;```
yeah
In the current attempt I completely just pasted the contents of the helper into calculate, and trimmed it down a lot (to a point it lost functionality), but it's still not working for some reason with older steammodded: calculate = function(self, back, context)
```if context.end_of_round and not context.game_over and context.main_eval then
if not G.playing_cards then
return false
end
local n = 0
local to_destroy = #G.playing_cards / 2
for _, c in ipairs(G.playing_cards) do
c:start_dissolve()
n = n + 1
if n >= to_destroy then
break
end
end
return true
end
end```
it works!
awesome
But I feel like when I use time, it isn't animated
print in the context.end_of_round
and are you using sin/cos
Yes
tex.g = 0;
tex.b = 0;```
thank you Eris!
is that blue card
No output, so the code doesn't even get there
okay well idk then
im not really a shader guy i just know some math
Decks don't have context.main_eval in older versions of SMODS
Thank you for the info! Then I'll remove it and try again
yes c:
It works now with the removed of main_eval, thank you!
Do you know if time only works in dissolve_mask?
i dont
how could i make a pack open after a blind without the cashout thing getting in the way. kinda like how cryptid does it with The Decision
steal cryptid's code probably
apparently i have some ssymbol???? can someone help me out
you're missing an end
"steal cryptid's code" why would you wish that upon anyone /j
add another end
i love incorrectly formatted code
hit alt+shift+f
^
That wont work because they don't have the Lua extension.
i have a feeling it's gonna do absolutley nothing but ok
it will tell you when you make an epic blunder
it does many wonderful things
it will definitely do something 😭
probably not for me it wont id think the formatter was wrong and not me 💔
it'll highlight everything
also am i weird for using this one
or is sumneko's like better for balatro
idk i only used sumneko's
idk this is just the one that appeared at the top of the extensions list for lua in vscode lol
this one is by Tencent though which is a controversial company and therefore bad /j
nvm i'm not the weird one
do effect jokers need card abilities even if they don't seem to need any
wdym card abilities
oh i see
this is for the description to show the values
its just so you can easily change the values in the config and be done
instead of manually changing numbers everywhere
so do effect jokers not need them
wdym
what do you mean "effect joker"
nothing needs them, theyre just useful
like something that makes tarot cards sell at buy price idk 😭
scaling jokers need them
quick question: where is the file that contain all calculate context?
actually no what if you just remember 🧠
also anything dealing with random values like the idol
That doesn't exist
oh i mean if no config variables are used in the main code, you don't need the config thing at all
lemme find it
https://github.com/Steamodded/smods/blob/c35acd87d763135d8febf9869860d7cb46a59fa0/lsp_def/utils.lua#L7 this is like the closest thing
yes that
is loc_vars = function(self, info_queue, card) not nessecary either?
no yeah you don't need any loc_vars for that either
what im seeing from other mod's code is it doesnt nessecaryily need calculate = function(self, card, context) either
yes
it says on the SMODS.Joker page what all the required parameters are
and even thats not entirely accurate because you technically dont need a localization entry
im unsure how exactly i increase something's sell value
How do I apply a sticker to every card from the set Joker?
for k, v in pairs(G.I.CARD) do
if v.abilty.set == 'Joker' then
v:add_sticker('modprefix_key', true)
end
end
https://github.com/nh6574/VanillaRemade/tree/main is your friend
copy code from either egg or gift card
Oh, I mean in should_apply for stickers
I should probably reference this more and utdr mod less 🥀
No, sets = {Joker = true}
In should_apply?
no, in the sticker definition
is there a way to have a probability trigger 2 different contexts?
In the config?
What is the goal?
no, sets is a seperate parameter
Like this?
key = "death",
config = { extra = { roundsTillDeath = 3, roundsWithSticker = 0, roundsLeft = 3 } },
badge_colour = HEX '000000',
pos = { x = 0, y = 0 },
sets = {Joker = true},
default_compat = true,
rate = 1.0,
atlas = "death",
unlocked = true,
discovered = true,```
yes
wdym by that
So no should_apply at all?
Yes.
Well, my sticker doesn't get applied to anything
Code?
key = "death",
path = "death.png",
px = 71,
py = 95
})
SMODS.Sticker {
key = "death",
config = { extra = { roundsTillDeath = 3, roundsWithSticker = 0, roundsLeft = 3 } },
badge_colour = HEX '000000',
pos = { x = 0, y = 0 },
sets = { Joker = true },
default_compat = true,
rate = 1.0,
atlas = "death",
unlocked = true,
discovered = true,
calculate = function(self, card, context)
card.ability.cstorm_death.extra.roundsLeft = card.ability.cstorm_death.extra.roundsTillDeath -
card.ability.cstorm_death.extra.roundsWithSticker
if context.end_of_round and not context.repetition and not context.individual then
card.ability.cstorm_death.extra.roundsWithSticker = card.ability.cstorm_death.extra.roundsWithSticker + 1
print(card.ability.cstorm_death.extra.roundsWithSticker)
if card.ability.cstorm_death.extra.roundsWithSticker == card.ability.cstorm_death.extra.roundsTillDeath then
print("DEATH")
G.STATE = G.STATES.GAME_OVER
G.STATE_COMPLETE = false
end
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.cstorm_death.extra.roundsTillDeath, card.ability.cstorm_death.extra.roundsLeft }, key =
self.key }
end
}```
i tried adapting the code to increase a consumable's sell price, but it's still at 1
if context.immediate then
local lock = tag.ID
G.CONTROLLER.locks[lock] = true
tag:yep('+', G.C.PURPLE, function()
SMODS.add_card{key = "j_gros_michel", edition = "e_negative"}
G.CONTROLLER.locks[lock] = nil
tag.triggered = true
return true
end)
tag.triggered = true
return true
end
why this not work
ok thx
this is a stupid question in hindsight so ill ask another one,
how can i have the following line only be called once at the start of context.discard?
card_eval_status_text(card, "extra", nil, nil, nil, {message = localize("k_active_ex")})
if context.pre_discard
more context:
im dealing with pseudorandom_probability() in context.discard and if i try calling it again in context.pre_discard then they wont "match up"
calculate = function (self, card, context)
if context.discard and SMODS.pseudorandom_probability(card, "j_emith_thread", 1, card.ability.extra.odds) and not context.blueprint then
card_eval_status_text(card, "extra", nil, nil, nil, {message = localize("k_active_ex")})
return {
remove = true,
}
end
end
I think atp I'm just gonna give jimbeus a completely different ability this is way to hard for someone like me🥀
What do you mean they wont match up? Also why aren't you putting the message in the return?
two pseudorandom_probability() calls, 2 different values if im understanding it correctly
im not putting message = localize("k_active_ex") in the return cuz then it'll show "Active!" for every destroyed card, i just wanna have it do that once
No, there is no difference.
Also I still don't understand.
G.FUNCS.toggle_shop()
when I use this function the game gets softlocked not even debugging tools work
When are you using it?
inside of tag:yep()
How do I animate joker's sprite?
The way on the image crashes the game
animated sprite for anything other than blinds are not supported
either wait for next smods release or copy from the way other mods do it
how do i shuffle a card created mid-blind into my deck? as opposed to putting it at the bottom or at the top
shuffle the deck after its added
i thought there would be a more dignified way to do this, but okay. thanks!
No, the pull request has not been merged yet, it's not guaranteed to be in the next release.
folks does anyone knows how to remove this wierd black outline?
Ive been using special python file to remove lines but it doesnt seem to work here
or to be more clear, it works but after I re-downloading mod files from repository this bug returns
black line?
Check for any transparent pixels.
none
black outline that occurs with transparent pixels with a colour stored
im pretty sure its mostly an aseprite issue
since it makes transparent pixels black when exporting
while they just dont store a colour normally
Any clue why it's not working?
bruh😭
but its caused by aseprite
theres an aseprite extension that has a built in 1x to 2x scaling
for balatro
Im new to steammodded, does anyone know how to apply stickers?
I'm not entirely sure if I can use the .apply function during a calculate function
card:add_sticker('modprefix_key', true)
thx
Does anyone know how to check if a card has a certain sticker?
This is for a joker card, I want it to destroy the random card when the playing cards are still on screen but after you win. My current code just gets rid of a card you had in hand when you see your money gained, I know it has to do with context.main_eval but unsure what to replace it with
if context.end_of_round and not context.game_over and context.main_eval and not context.blueprint then
local card_ = pseudorandom_element(G.hand.cards, 'seed')
SMODS.destroy_cards(card_)
end
Try setting true as the third input in SMODS.destroy_cards
So it would be like this? Unsure what that would do
if context.end_of_round and not context.game_over and true and not context.blueprint then
local card_ = pseudorandom_element(G.hand.cards, 'seed')
SMODS.destroy_cards(card_)
end
Misread, so it would be like this?
if context.end_of_round and not context.game_over and true and not context.blueprint then
local card_ = pseudorandom_element(G.hand.cards, 'seed')
SMODS.destroy_cards(true)
end
SMODS.destroy_cards(card_, nil, true)
ahhh, okay
The definition of the function is
function SMODS.destroy_cards(cards, bypass_eternal, immediate, skip_anim)
it works, thanks! :)
is it possible to make a stake that debuffs specific ranks?
Anyone knows why may the sound in return not work?
If I play the same sound through play_sound() it works just fine
Hey folks, I'm using the create_slider() function similar tp the one I have replied to, does there have to be a pre-existing version of 'beast_config' or is it created automatically? I'm getting a ```lua
bad argument #2 to 'format' (number expected, got nil)
got it! I needed to return a message alongside sound itself
Good try Ali
It does in fact need to exist ahead of time, solved it
What am I doing wrong? No matter how many cards I play it's always NOT ALLOWED
bump
is this the exact code
well, the variable's name is changed, but my original variable works just fine, I print it in console and it shows the right number. In this case 5
But apart from that, yeah. That's the code
don't check G.hand, check the argument cards
Can someone help me with this shader problem I have? My shader only changes if it gets updated by changing pages or reloading the run instead of being animated and I don't know why
Can you share your shader code? Kinda hard to guess otherwise.
Is there any way to run a function whenever an instance of a card of a specific type is created? As a constructor sort of function?
Right, sorry
I think you could use the global calculate for that
thanks! I'll take a look at that after I get done trying to help with your thing
i get this with gimp too, not sure how to go about it :/
sorry, I'm not super up with how to hook shaders up to balatro, but I have used shaders before elsewhere, can you help me get this running so I can iterate?
I have
SMODS.Shader {
key = "smoke_death",
path = "shaders/smoke_death.fs",
}
and then I picked some cards to add it to and used:
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
card.children.center:draw_shader('smoke_death', nil, card.ARGS.send_to_shader)
end
end,
I'm assuming I'm failing to forward arguments somehow, but I'm not sure which ones
and the documentation is not too good on the wiki
send_vars?
Oh, I just have it as an edition like this:
key = "smokeDeath",
shader = "cstorm_smokeDeath",
}```
and this:
```SMODS.Shader{
key = "smokeDeath",
path = "smokeDeath.fs",
}```
anyone know how to use the new SMODS.Operator? apparently the last update added it and in the process broke my custom one i added using patches and i want to see if i can port it to the new system
i cant seem to get the patch method to work again, not sure why
sorry to pester again, I have:
SMODS.Shader {
key = "smokeDeath_shader",
path = "smokeDeath.fs",
}
SMODS.Edition{
key = "smokeDeath_edition",
shader = "curt_smokeDeath_shader",
}
Where curt_ is the prefix of the skeleton of a mod I happened to be working on at the time. (Doesn't currently contain any shaders or editions to interfere). When I go to look at the editions, it crashes with "smokeDeath_shader" not found, which is odd to me, considering I have it prefixed explicitly. Was this something you ran into?
you know what? I'll just make it its own mod rq.
That's because in the shader file it's called smokeDeath and not smokeDeath_shader
it was failing before I renamed it, but I'll change that back
it might have been failing for an unrelated reason
assets/shaders/
Okay, then that is not the reason it crashes
engine/sprite.lua:109: Shader uniform 'smokeDeath' does not exist.
A common error is to define but not use the variable.
Stack Traceback
using your exact definitions
Hey gang, anyone know how to centre text with newlines? I'll take a look through the backend but it would save some time if there was a convenient way of doing this
in a clean mod
nvm just had to change the patch to work with scoring_parameter_keys instead
current issue with jimbius is that the joker's mult only updates during a round
Have you changed anything in the files or not? And where did you put the SMODS.Edition and SMODS.Shader?
Oh and in SMODS.Edition, does the shader still have the modprefix?
my layout is really simple, all I have is a minimal json to define the mod, (cstorm.json), a lua file containing just:
SMODS.Shader{
key = "smokeDeath",
path = "smokeDeath.fs",
}
SMODS.Edition{
key = "smokeDeath",
shader = "cstorm_smokeDeath",
}
(cstorm.lua) and then the unedited version of your fs under assets/shaders/smokeDeath.fs
{
"id": "test-shader",
"name": "test",
"author": ["OmnipotentEntity"],
"description": "test",
"prefix": "cstorm",
"main_file": "cstorm.lua",
"priority": 99,
"badge_colour": "FFE5B4",
"badge_text_colour": "A58547",
"display_name": "cstorm",
"version": "1.0.0",
"dependencies": [
"Steamodded (>=1.*)",
"Lovely (>=0.6)"
],
"conflicts": [ ],
"provides": [ ],
"dump_loc": false
}
I may be too unfamiliar with lua but could you try taking the elseif out of the calculate?
I don't know what the structure is with updates
this code looks as if this joker will trigger way too often.
every scored card, every hand card, etc etc.
every reroll
?
what seems to be going on with my minimod trying to hoist your fs so I can test it, is that the prefix is getting stripped from the shader name for some reason. @wispy falcon
That's weird
your calculate code runs any time calculate is called and you're not in context.joker_main or in context.blueprint, this is a LOT. But because you're not returning anything when it does trigger you get no visual feedback of this.
Even if this is the case, I think that's fine given that it's not exponential, it's constantly setting the value to the resulting multiplication of two unconnected values
oh that's true as well lol
That said, it should only really be called when either of the variables is detected to have changed
I think the intention is for it to scale.
man i have no idea what any of that means but i am going to restructure this anyways
but maybe not
scales with consumables
Walk with me, what do you not understand, I can elaborate
so if you use one your mult goes down?
i hope so
ok
I copy pasted all of this and above and it works for me...
maybe we're on different versions of smod and/or lovely
let me clean out all of my mods, rq
Do you have the newest version of smods?
I'm at tag 1.0.0-beta-0827c
wonderful
We love technology
well, it seems that rather than being a help, I am being a nusance, so I'm going to bow out
Sorry I couldn't help
It's fine. At least you tried :D
Hello, how can I force an update of the game? I have a joker that creates cards at first draw but those cards aren't affected by opposing boss blinds such as "The Head"?
SMODS.recalc_debuff(card)
I really should make a list of SMODS utils functions
thank you :)
xD maybe I should just read
Hey N', are you familiar with any way to centre UI text with newlines? So like shifting the pivot of the text so that the middle of the text on the middle of the UI element
@azure valley I have good news, I got it to work. All I was missing was float t = smokeDeath.g + time;
Huh... so, well, the vanilla Jokers using a "message" for their +chips, +mult, etc values not abiding by my value manipulation may present a problem for my stake idea.
Functionally, it works, just not with the popups.
-# fuck it, we ball.
@wispy falcon try tex.r *= exp2(sin( time variables) );
as it turns out i was doing this wildly inefficiently
it should fix the color going off the screen problem
if nothing else, it gives a bit of understanding of hlsl shaders
Wait, why does that work?
Whenever I boot the game with my mod,, it gives me that error. I looked at the Mod Metadata page, and the metadata seems fine, so I have no clue what is going on.
align = "cm"?
if I’m understanding the problem correctly, the time variable is doing something weird to make the sine function not work. Trying a sine squared makes it not go negative anymore which sometimes helps
Everything already is I fear
did you try fixing the spaces in the cryptid dependency?
can i see the code
Yeah sure, 1 sec
I'll try that
Now I only need to know how to draw a shader on cards that have a specific sticker
Custom draw function that checks for the sticker and applies the shader if it exists.
Got it
It's in the first return, comment-labeled Text, none of the progress bar commands are used yet, have to send the file cause char limit
It worked, thx
Wait, how do I make a custom draw function? I've never done that before
ohh thats what you meant by newlines, i didnt know it accepted those lmao
no idea, it should work if you make them two different nodes
Will that not make it look more like 2 different sections?
Oh nice, will give it a shot then
Jimbo says +4 Mult, yet +8 Mult was applied... I really don't want to hook localize - and that still wouldn't be accounting for an another Joker of mine that modifies the amount in SMODS.calculate_individual_effect...
so why exactly is he applying +8
Testing a run modifier that affects Chips and Mult operations.
also just replace jimbo with a remade version of him that doesnt hardcode the text
ez ez
bump
I'd need to do that for every Joker that uses message to display their values.
...mainly those that trigger off of context.joker_main.
Whenever I boot the game, it gives an error that it has no end keyword for the if statement at line 56. I have tried adding additional end statements, but to no avail. I dont know if it's because I'm clueless with Lua and I made the mod in Jokerforge, or if it sint my fault lol.
may i have the code i can check with vscode real quick since i know some lua
You can't have code after a return, also install the Lua extension.
maybe have the two card_evals above return
this one
I did install that
Fixed one problem, got another one. Only thing left to do is to get crackin
so im making a boss blind that makes it so if a joker triggers there's a one in four chance for it to be debuffed, problem is when a joker gets debuffed it doesnt act like it's debuffed until the next hand, is there a way to stop the joker from triggering once it's debuffed
The cards looking in this area seemingly aren't functioning at all. (They aren't giving mult when they should)
odd request/question but
is there a way to move cards from 1 card area to another
i think i may know [smods.draw_card... maybe lol] but
yea i'm inclined to agree that it's probably just smods.draw_card
try that first, if that doesn't work uhh look into the Quantify code card from Cryptid (it force-draws a card to your joker slots)
oo alr then ty lol
How do I check to make sure EVERY card scored is a Heart card?
-# And also, how do I debuff a random Joker every Blind?
loop through all scored cards and check if they're hearts
as for 2, check Crimson Heart's code in VanillaRemade for how to debuff a random joker and then adapt it for every blind instead of every round
sorry i went to go play wii party with my twin brother
let me see where i was
okay this was the problem it isnt loading the loc file no error and i did put the initialisation in the main file and its isnt that
okay wait
i am an idiot
i spelt it the uk way so it didnt work added back that z
how about this?
how about this? its based off monopoly property cards
not sure if it should be one or two dollars per joker
not sure which one would more balanced as a common joker
Prob 2 cause even tho golden is $4, rebate can make like $20 so 2 is fine
And 1 feels just like another meh econ joker yknow
Fairly certain that if you're targetting playing cards, the context of interest is context.individual
(and context.card_area == G.play)
wait no im reading this wrong
Okay, got it - v:is_suit("Hearts"), do not target context.other_cards it is nil under context.joker_main
This is REALLY ugly, but it works and that's what I want
i would check context.before for checking if a heart is in the hand, and keep everything else in context.joker_main
also add a break the line after heart_in_hand = true so it doesn't keep looping through cards, just for efficiency's sake
...i would also remove your message section of the first return, given it's going to do the equivalent automatically and you're calling a localization key that's used for when xmult is added
(btw G.C.XMULT doesn't exist... G.C.MULT does)
Alright, almost all of that is noted.
And by that, you mean?
Why check during before?
it's probably not essential but i think it's a bit more fitting for the check, either really works though
use a context.before check for that specific segment, and everything else can stay in a context.joker_main check
when i check if something's in a played hand i use context.before but overall it's pretty much semantics
How does one make a new Balatro suit? Been searching online for a way to make one or atleast get help on making one but couldn’t
Well, all that's done and it works.
Now to just figure out how tf to debuff a random Joker.
is there a context for when a Joker is destroyed?
perma debuff or temporary?
like, does the debuff go away
just curious
Perma
context.joker_type_destroyed iirc, but it triggers for consumables too so make sure to check that the set is "Joker"
oh it triggers on consumables
was just about to ask if there was something else for that
convenient
there's also the contexts for when cards are sold but context.joker_type_destroyed is a catch-all and includes selling
see SMODS.debuff_card()
chat quick question when using malverk how do you make a mod prefix
same as you would in a normal mod i think
Ooooh it's
yea
ok yea another question but
i made the alt texture and texturepack thing but it doesnt show up in the texture list thing malverk has what am i missing?
im unfortunately not a malverk expert cant help you there
lucky for you theres malverk discussion in modding-chat
all the images exist right
yea
what are they named
by that do you mean it's scaled improperly
if the image as a whole is sized incorrectly that could cause issues
yea
ok yea fixed the wrong scaled stuff
and yet it still doesnt work
same error
OK GOOD NEWS
IT WORKS'ISH
IT IS NOW RECOGNISED
ok turns out i put the wrong thing i should've put rank or something and not base but still
G.hand:change_size
thanks
how does one make it a joker only appears after you have a certain enhancement
for _, playing_card in ipairs(G.playing_cards or {}) do
if SMODS.has_enhancement(playing_card, 'm_wild') then
return true
end
end
return false
end```
thanku
enhancement_gate = 'm_modprefix_key'
No problem!
oh wow thats a lot shorter
How can I set force_stickers? None of these work:
context.card.config.center.force_stickers = true
context.card.force_stickers = true
context.card:add_sticker('eternal')```
Set the second input of Card:add_sticker to true
Thank you!
Hi
Uhh... I'm kind of new to Lua coding and Balatro Modding
I'm getting stuck on something
calculate = function(self, card, context)
if context.setting_blind then
return {
d_size = card.ability.d_size,
h_size = card.ability.h_size,
hands = card.ability.hands,
card = self
}
end
-- Surely, this is wrong lol
if context.cardarea == G.play and context.individual and not context.blueprint then
return {
message = localize('k_ace'),
repetitions = card.ability.repetitions,
card = self
}
end
if context.joker_main and context.cardarea == G.jokers then
return {
message = localize('k_ace'),
repetitions = card.ability.repetitions,
card = self
}
end
end
What I'm doing is... A joker that set Hand Size to 1, Set Hand available to 1, Set Discard to 0. And Repeat All Other Joker and card ability 3 more times
The later part can be dealt later, but, how can I change those 3 values first? Like.... What viable to call?
G.hand:change_size((-G.hand.config.card_limit)+1)
ease_hands_played((-G.GAME.current_round.hands_left)+1)
ease_discard(-G.GAME.current_round.discards_left)
Also remove the card = selfs.
Ohhhh I see
Thank you veery much!
I really needed to learn about this lot more than I expected
how do you make custom tooltips? Just in case I want to credit artists/shader creators
I'd like to make joker destroy played aces and kings after scoring. How do I do that?
if context.destroy_card and context.cardarea == G.play and (context.destroy_card:get_id() == 13 or context.destroy_card:get_id() == 14) then return {remove = true} end
real quick how do you change card on the title screen background??
How do I check a joker's key? This one's not working, and I've also tried a few other combinations:
if _joker.card.config.center.key == "j_idol" or _joker.card.config.center.key == "j_blueprint" then
...```
for k, v in pairs(G.jokers.cards) do
if v.config.center.key == 'j_idol' or v.config.center.key == 'j_blueprint' then
end
end
Thank you!
Hey, I wanted to ask if its possible to recalculate the played hand's type during context.before?
context.scoring_name
i am not sure i fully understand, would I for example do context.scoring name = "Straight"? or how exactly would i modify it?
No, context.evaluate_poker_hand
how can my blind debuff the top 7 cards of the deck?
You mean the first 7 drawn cards?
mhmhmhm
effectively the first 7 cards in G.playing_cards
[i'd also like to debuff the last 7 cards]
No, that is not in the deck order.
No, they wouldn't be in the deck anymore.
ah :/ that's problematic
You would probably flag the cards in context.setting_blind and check for that.
If there's anyone around here that's knowledgeable about how LSP stuff works, I'm trying to figure out why the first image does not seem to get its LSP text on hover-over, but the second does
Oh wait, could it just be due to caching?
I'm really bad with understanding how keys can be accessed, how can I make this work?
SMODS.smart_level_up_hand(nil, G.GAME.hands[context.scoring_name].key, false, -1)
end```
context.scoring_name is the key.
Thank you! I thought that was the name not the key
Hi, I want to make a few personal QOL improvements for my PC game, and have a few hopefully basic questions. I'm a Lua noob but an experienced programmer, so that'll be my problem to solve. Just looking for a few pointers and suggestions to help me find my feet after checking out the starter pack. I'd be grateful for references to the source or existing mods. I'm blind, so please no screenshots.
|| 1. I want to add a controler input for toggling the hand sort. For this sort of thing (adding inputs for on-screen controls) is it better to just trigger the on-screen buttons, or call the functions they call? I reckon I can figure out adding entirely new controls if I need to, but just wondering how to plug in to the existing machinery.
-
Speaking of existing machinery, how much of a mission would it be to get the cursor to snap to the hand buttons? It's a bit fiddly to have to D-pad down from the middle of my hand to focus the buttons properly. However, this is probably a really unoriginal thought, maybe there's a reason. Anyhow, I only want this because I'm putting off...
-
Eventually I'm gonna add some special inputs for the BlackHole accessibility mod so that it can quickly report some important game information. I know how to do the talking bit and will figure out the controls bit, but the information bit: is there a handy global dict or something with basic variables like ante (number/boss), current blind, current chips, target chips, current gold, etc? Also the current hand, so I can report changes to it, like drawing new cards after a discard?
||
Thanks.
How to draw a shader on cards that have a specific sticker?
Is the id for Ace 1 or 14?
14
Thank you!
1- Calling the functions directly is usually better. Although I would check if the mod Handy already has this feature.
3- G.GAME holds all those values but their keys are not very intuitive and you will most likely need to look at existing code to find each of them. The VanillaRemade wiki has a lot of them.
thanks :>
bump
use SMODS.DrawStep
Is there an smods function that allows for adding dollars without having to return?
ease_dollars i think
Thank you!
Have you tried printing enh_options?
i have not, i will do that rq
i added a print right here, but the game seems to crash before it runs somehow
it does not show up in the log
it does appear that get_current_pool("Enhanced") is generating seals somehow though
That may be a stupid question, but how do I check how many cards were played by current hand for a joker?
#context.full_hand
thanks
should be full hand for played hand sorry
Hey, I've been trying to make this work. Here's a simplified version of roughly what my code was trying to achieve, but with this structure it causes the hand to update to flush when selecting cards for the next hand, instead of during the current hand. I am not fully sure how context.evaluate_poker_hand works, so sorry if I made an obvious mistake here.
speaking of context.full_hand
why does it just not work sometimes
tried using it in the exact same way as vremade sixth sense but it crashes because context.full_hand is a nil value
nope
this is the whole code
and G.play.cards all used to be context.full_hand but that crashed
weird
the only time i had problems with something in a context being nil it was another mod's fault
the only real thing i could see breaking it is the hook i have do calculate destroy_card for held in hand cards
but i dont change context.full_hand there
so that should just work
can you explain what the goal is?
i am trying to modify the handtype of a played hand to a different one. (In this example, what it would achieve is that when a hand is played, it becomes a flush, but in the real example this would be conditional of course)
So you don't want it when selecting a hand, just after it's played?
yeah, because the joker would modify the hand in context.before and it should then turn the hand type into the correct one pretty much
oh ok, the problem there is that context.before is too late for that
try context.press_play
if you modify the hand in that context then you wouldnt even need evaluate_poker_hand to make it correct
bump
why the cards are just a empty atlas?
SMODS.Atlas{
key="leaf_hc",
px=923,
py=95,
path="hc_leaf_suit.png",
}
SMODS.Atlas{
key="leaf_ui",
px=18,
py=17,
path="Leaf Suit_icon.png",
}
SMODS.Suit{
key="Leaf",
card_key="Leaf",
hc_atlas="leaf_hc",
lc_atlas="leaf_hc",
hc_ui_atlas="leaf_ui",
lc_ui_atlas="leaf_ui",
hc_colour=HEX("fbffd1"),
lc_colour=HEX("fbffd1"),
in_pool = function ()
return false
end,
pos={y=0,x=0,},
ui_pos={x=0,y=0,},
}
yeah that worked. thanks!
<@&1133519078540185692>
guys no nway he has been succesfuly recieved moeny!!!
thanks moderator
Hi, I keep getting this same error with a seal I'm trying to make. It happens before the card is scored and I'm not exactly sure what is causing it.
Code here:
SMODS.Seal{
name = "hch-orange-seal",
key = "orange-seal",
badge_colour = HEX("F29015"),
config = { mult = 5, chips = 20, money = 1, x_mult = 1.5 },
loc_txt = {
-- Badge name (displayed on card description when seal is applied)
label = 'Orange Seal',
-- Tooltip description
name = 'Orange Seal',
text = {
'Creates a Planet card when played, then is destroyed',
}
},
atlas = "orangeSeal",
pos = {x=0, y=0},
-- self - this seal prototype
-- card - card this seal is applied to
calculate = function(self, card, context)
-- main_scoring context is used whenever the card is scored
if context.destroying_card then
G.E_MANAGER:add_event(Event({
trigger = "before",
delay = 0.0,
func = function()
if G.consumeables.config.card_count < G.consumeables.config.card_limit then
local card = create_card("Planet", G.consumeables, nil, nil, nil, nil, nil, "hch_orange")
card:add_to_deck()
G.consumeables:emplace(card)
end
return true
end
}))
return true
end
end,
}
Where do I check for SMODS.last_hand_oneshot? Putting it in context.after or straight into calculate does nothing for me
How do I draw a shader on the card now?
key = "death_shader",
order = 25,
func = function (card, layer)
if card.ability.cstorm_death == true then
end
end
}```
card.children.center:draw_shader('modprefix_key', nil, card.ARGS.send_to_shader)
Why does it not work? Is the if statement wrong?
Yes, it should be if card.ability.cstorm_death
Fair enough
That works, thank you :3
<@&1133519078540185692>
🔫
thanks egg
is there any weird stuff that could happen from putting EMPTY(context.other_ret) in context.retrigger_joker_check
rather than context.post_trigger
does context.other_ret even exist there?
yes
cant imagine anything wierd would happen
i have a working joker using that
the difference is just that itll only work on the first trigger
since thats when retriggers are calculates
that's fine
it's meant to either retrigger a joker or cause it to fail entirely
i guess other joker retrigger effects could break it
i mean with other joker retriggers itll just be
the first trigger fails and everything else goes through
i imagine
would the context stack make it possible to check if a joker is the source of a playing card being added to the deck? context.playing_card_added exists but i'd like to only check if a joker is the source, not sure how to go about that
(SMODS.context_stack[#SMODS.context_stack-1] or {}).caller.ability.set == 'Joker'?
didn't realize caller existed
Could probably use post_trigger too with SMODS.get_previous_context()
is caller a thing with this? i seem to be getting attempt to index a nil value crashes when trying to index it, testing with certificate
No, you need to use what I told you not SMODS.get_previous_context()
my bad, they seem to be equivalent so i wasn't sure
pretty sure that first nil check is where it stops, no scaling occuring
How are you creating the cards?
currently i'm testing with certificate, which calls context.playing_card_added
Certificate calls playing_card_joker_effects({_card}), which itself calls SMODS.calculate_context({playing_card_added = true, cards = cards})
so in the case of certificate it never directly calls playing_card_added?
that's a bit annoying
No, the problem is it happens in an event I think.
hmm
well this implemenation doesn't work in other cases either (legendary joker that scales when a card is created by specific sources)
purple seal didn't scale and neither did judgement
A seal is not a card.
...you would be right
Also it would be caller.ability.consumeable
is there a table for the key for vanilla enhancements
just need a simple check for what enhancement a card has
SMODS.has_enhancement(card, 'm_modprefix_key')
yippee
judgement seems to only create an event that calls create_card() and not use any contexts at all which is definitely annoying
No, card:add_to_deck() calls context.card_added
ah, wasn't aware
how do i ban a card mid-run?
G.GAME.banned_keys.<key> = true
ty
can_use = function(self, card)
return G.consumeables and #G.consumeables.cards < G.consumeables.config.card_limit
end
so when the consumable is in the consumable slot and it has another consumable with it, it doesn't allow me to use it any fixes?
#G.consumeables.cards - 1
I tried this but it caused it to be usable inside the shop despite having no slots to generate cards
Maybe #G.consumeables.cards - (card.area == G.consumeables and 1) or 0
it is the one that I posted
this is from vanilla remade
config = { extra = { numerator = 1, odds = 20}},
loc_vars = function(self, info_queue, card)
local new_numerator, new_denominator = SMODS.get_probability_vars(card, card.ability.extra.numerator, card.ability.extra.odds, 'dream')
return {vars = {new_numerator, new_denominator, other_value}}
end,
calculate = function(self, card, context)
if context.end_of_round and context.game_over == false and not context.blueprint then
if context.individual and context.cardarea == G.hand and not context.other_card.debuff and SMODS.pseudorandom_probability(card, 'cymbal_remancedream', card.ability.extra.numerator, card.ability.extra.odds, 'dream') then
local random_edition = poll_edition("cymbal_remancedream", nil, true, true)
set_edition(random_edition)
end
end
end
trying to make so each card in hand has a 1/20 chance to get a random edition but ithink it's the edition setting part that won't work, any help ?
how would i detect if someone buys a voucher, any voucher
if context.buying_card and context.card.ability.set == 'Voucher'
maybe try context.other_card:set_edition(random_edition, true, true)
worth a shot
how do i get the card i've highlighted in shops/booster packs?
G.shop_jokers.highlighted and G.pack_cards.highlighted
does G.shop_jokers include shop boosters and vouchers
G.shop_vouchers.highlighted and G.shop_booster.highlighted
ty
yeah didn't work, kinda expected it
do you know if it'd be possible to circumvent this? most times cards are created, it's in an event
Have you tried printing SMODS.context_stack?
is it better to use ease_dollars or just returning dollars
Returning is always better.
returning dollars is better because it will handle custom messages and integrate with smods calculation stuff but both should do the same
can you return negative dollar
yes
pog
-# bump
if context.individual and context.end_of_round and context.cardarea == G.hand and not context.blueprint and SMODS.pseudorandom_probability(card, 'cymbal_remancedream', card.ability.extra.numerator, card.ability.extra.odds, 'dream') then
context.other_card:set_edition(poll_edition("cymbal_remancedream", nil, true, true))
end
seems like caller will always be nil? it's not an entry in SMODS.context_stack at all, and print(SMODS.context_stack[#SMODS.context_stack - 1]) just prints as nil
Ah i see, so i had to do all at once then ?
Thanks it worked
no i think the problem is that you weren't doing context.other_card:set_edition
from what card is it
the emperor
ok I will go check it out
hello i have a joker that triggers different effect when a specific enhancement is played
what's wrong with this check? it's not triggering in my testing in game
m_mult isn't a string
heck
you're calling a global value that doesn't exist
it still ain't working
so beginner mistake
i fixed the emperor just now
anyone with more understanding of SMODS.context_stack know how you could scale a joker when something creates a card?
without hardcoding obviously
this doesn't seem to be working,,
What are you banning
tarots
stuff like c_death
Try running eval print(get_current_pool("Tarot")) with debugplus after banning
ok
more question
can i queue multiple return message? like i want the card to show the red add mult popup, then a gold one, then a chip one
do you return messages in an array or something or
Perhaps you would hook SMODS.calculate_context and set a variable to SMODS.current_evaluated_object.ability.set and not delete it so it persists during events?
Use extra
extra = {chips = number}
Putting an extra table in your return will make it always run after the things outside of it
You can also put extra tables inside extra tables
after banning a bunch i got this
Alr, that looks correct
Do any of the banned things still spawn if you spawn in like a charm tag or smth
...i'm stupid lmao
What
its kinda like how jimbor appears right
Yes
ough
Pretty sure every single pool of centers has a default
i see the issue, caller and SMODS.current_evaluated_object were added to smods after 0827c and are only in the dev version
Is there a function that allows you to check whenever a specific joker gets triggered inside of the calculation function? (i.e., Lusty Joker)
bread
i think not all of them because banner adds some
if context.post_trigger and context.other_card.config.center.key == 'j_modprefix_key'
guess this joker will wait until the next smods release lol
P sure banner only adds to non-centers
Since Enhanced and Edition both have c_base and e_base respectively
And then everything else either is a single card (Base) or is a consumable/joker pool
i dont think those are defaults for the pool tho
like for editions i actually added it myself on smods to be e_foil
mult
Not mult_mod
Also you can remove the colours
And the card = cards
Not sure if there's space to add text to indicate that these jokers are ones with matching actors 🤔
This doesn't really seem to be working.
Do you have post_trigger enabled?
Wdym?
SMODS.current_mod.optional_features = function()
return {
post_trigger = true,
}
end
Any advice on how to make a mod. I have no idea what to do but i have an idea 🙂
Thank you 😄
Follow-up. I want to have a message pop up under the joker itself as opposed to the card, but I can't figure out how to make that happen.
message_card = card?
I really am an idiot.
if condition then card:sell_card() end
How do I change the name of this challenge?
documentation is pretty cool
https://github.com/Steamodded/smods/wiki/SMODS.Challenge
I don't get what it means, that's why I'm asking
you know how in your localization file, at the very top level, you have a descriptions table and a misc table
you make a new "challenge_names" table inside the misc table, and then set challengekey = "something" inside that
This doesn't work
death_challenge = "Death..."
},```
you probably need the mod prefix
Also doesn't work
uhhh go check another mod's localization file that has challenges
you have resources
it has to be c_modprefix_key
Thank you
why does this not add the sticker?
How can I check for when a joker gets destroyed (not sold)?
context.joker_type_destroyed
likely because you misspelled the word stickers
ty!
🗣️
happens
me when i apply my sitckers to my card
also this doesn't apply to selling right
It does not
correct
ok nice ty
Any way to make these buffs temporary?
Move the if context.after statements out of the if context.individual statements.
How do I check if the player is in a specific challenge?
G.GAME.challenge == <key>
hmmmm is there a way to attach an invisible cardarea to a joker or something like that
the joker metatables aren't being properly saved if I just put them into extra
for context, I'm trying to figure out if this is possible without being too cursed
probably just put a cardarea somewhere really far ofscreen
Yes, use fake cards.
entropy does something similar for butterfly deck
lol lmao
oh?
good lord
Does everything under G get saved with correct metatables?
since right now the biggest issue is that those get stripped after a reload
No, because it doesn't get saved at all.
..well, that's not correct then
No, it is.
no, because how would I save the joker's state?
You would use card:save and card:load
thank you
as a sidenote, would this work with jokers like four fingers? that one's ability seems to be hardcoded, at least it doesn't seem to function even if I call its calculate function
Yes, if you hook SMODS.find_card
Where do I start for making a Joker mod? There's too many links and resources, I can't tell what to start with.
is there a way to make a joker make a noise when it shows up in a shop or buffoon pack (like an enhancement would such as foil or negative)
Yes, do it in set_ability
Also those are editions.
what does set_ability do?
oh right its all so similar XD
It runs when the card is created.
ill see if i can figure my question out myself in a minute
why does my mod's lovely.toml still patch when my mod doesn't load because of missing dependencies?
because smods is too late to prevent patches at that point
useful
we could be loading mod data and checking dependencies early enough to do it tbf
but smods can't tell lovely what patches to load (yet)
that kinda makes conflicts a pain to use cause if there's a conflict but patches still run and cause an error the user will have to uninstall/add .lovelyignore to a mod by hand instead of just disabling it in game
so guess ill remove conflicts for now
it could also be worked around by bootlooping which is even more of a pain
thinking about it, I'm not sure that actually matters
.lovelyignore being placed should immediately take effect for subsequent files being patched
I should see what I can do with that
ok well now my mod is complaining that the dependency isn't there when it is, am i missing something? i put "Blockbuster: Value Manipulation" in my dependencies and on the steammodded mods list in the crash log screen it says "Blockbuster: Value Manipulation" so that should match surely
any reason why get_current_pool("Enhanced") would be returning a list of seals instead? its kinda fucking up stuff im doing
it should match the id, not the name
ahh ok
that is indeed an issue with how smods loads mods, but the solution to that is writing better lovely patches
assume your mod might load partially; it might only load the lovely patches, it might only load the lua part
did smods ever implement the checking of lovely patches btw? https://discord.com/channels/1334988047229653042/1354270504588017776 for context
I checked there and I'm still confused.
i don't think this was ever implemented
sadge, I've had to manually implement it in 2 different mods I worked on
Is there a list somewhere of all CardAreas in the game?
Ctrl+shift+F for CardArea( in the source code
also worth noting that G.I.CARD exists if you just need a list of every single card
Thank you!
bump
is there like. a better way of doing this? all it does is, if there's a joker next to it that wasn't before it does x2 value manip, and if there was a joker next to it that isn't there anymore it undoes the manip
Firstly it would be next(SMODS.find_card(...))
what would be
In the first if
oh right thx
How do I modify cards in the shop using a deck's calculate function rather than a tag's apply function?
hey question how do you check if you are in a blind currently? i need to check it when joker is added during a blind for example through tarot
if G.GAME.blind.in_blind
thanks
How do you get hand size for a joker in balatro?