#💻・modding-dev
1 messages · Page 663 of 1
trying to make a blind that reduces the chips of the scored hand by 225 (min of 5) before the final score is calculated. this subtracts the chips visually, but then it immediately jumps back to what is was before?
calculate = function(self, blind, context)
if not blind.disabled and context.final_scoring_step then
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
G.GAME.current_round.current_hand.chips = math.min(G.GAME.current_round.current_hand.chips - 225, 5)
return true
end
}))
end
end
Remove the event and do return {chip_mod = (-hand_chips)+math.max(hand_chips-225, 5)}
hey guys someone have any guide or tips to start learning how to dev mod on balatro?
tyy
which kind of context is needed to make a matador like joker that gains xmult
context.before doesn't work either
I think matador just checks if it's a specific boss and if the debuff or discard triggers lol
Which is why it barely works right
context.debuffed_hand or G.GAME.blind.triggered and context.joker_main mimic the behavior pretty much.
why would you make another matador
I need a help. I need a code which causes stack overflow but not closes the game instantly
Do you mean the optional features? I have retrigger enabled
SMODS.Sound({key = "song", path = "song.ogg",})
SMODS.Sound({
key = "song",
path = "song.ogg",
pitch = 0.7,
volume = 0.6,
})
SMODS.Atlas{
key = 'Jokers5',
path = 'Jokers5.png',
px = 71,
py = 95,
}
SMODS.Joker{
key = 'xico',
loc_txt = {
name = 'xico khaled',
text = {
"xico khaled on the {C:attention}BEAT",
"{C:inactive}compralo para ver que es lo que hace"
}
},
atlas = 'Jokers5',
rarity = 2,
cost = 5,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = false,
perishable_compat = false,
pos = { x = 0, y = 0 },
config = {
extra = { }
},
calculate = function(self, card, context)
if context.setting_blind or context.joker_main then
return {
sound = "song",
message = "XICO KHALED ON THE BEAT",
}
end
end,
}
Firstly, you can't put cards in other cards, Secondly, context.retrigger_joker_check isn't called on playing cards.
the sound needs your mod prefix in the return
oh yeah that too
So is there not a way to do what I want then
it should be modname_song
on ur joker code
but i believe the crash itself was due to the wrong location of ur sound
Yes, if you want to force-trigger a random joker when a card with that seal is scored and also have mod compatibility.
Unfortunate, thank you anyway
SMODS.Sound({key = "song", path = "song.ogg",})
SMODS.Sound({
key = "song",
path = "song.ogg",
PREFIX ="cocosmod"
pitch = 0.7,
volume = 0.6,
})
no
no
damn
also you're defining the sound twice
joker code,
sound = "cocosmod_song"
the crash is because since u didnt put modname it was looking for the audio in the vanilla assets folder
is there are another requirements for a .ogg file for modding ? because its now say "Could not read Ogg bitstream"
are oggs supported? i've seen wav and mp3 working
also midi but i think that was converted to mp3
its work thank you both
-# I should probably include .xm songs some time.
Guys.
Is it possible to add required score scaling by .5?
Yeah
Thanks, I kind of missed it. 😅
for smods.has_any_suit, does that mean "counts as any suit" like a wild card or "has a suit, any suit" like any non-stone card?
It means it counts as all suits.
I'm confused
It appears no matter what area you set in SMODS.create_card if the set is "Consumeables" it assigns created cards to G.consumeables???
Why...
shortcut, kinda
I realized that I don't even need that by now but it's still feels counter-intuitive idk
You can change the area
can you use SMODS.blueprint_effect with jokers you dont have? i want my joker that copys other joker abilitys based on the joker id (j_xxxx)
I think this is a bug from some missing brackets
where does the game set what's in the shop? i'd like to replace the leftmost booster pack
ah, cheers ^^
What needs to be changed about the blueprint code to do so it does it to the left instead of to the right?
G.jokers.cards[i + 1] -> G.jokers.cards[i - 1]
it might crash if its all the way to the left tho not sure
no, you need extra logic
:< welp guessing i need to make like a ghost card that doesn't actually exist and use that?
<@&1133519078540185692>
crush them
where does the game determine what booster packs appear each shop?
game:update_shop
see that's the thing, it uses G.load_shop_booster which is only defined in that script, and is only ever initialised as nil
i have no idea where it's set
the mods are dead... /j
look a bit below where it uses get_pack
no idea
i think it is used
the areas get saved to "load_"... area_name iirc
ahhhhh ye i see then
-# I love that emoji
this isn't working for some reason:
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''if not G.GAME.first_shop_buffoon and not G.GAME.banned_keys['p_buffoon_normal_1'] then'''
position = 'before'
payload = '''if _key == "shop_pack" and G.GAME.current_round.cardb_next_shop_spectral then print("pog") return G.P_CENTERS['p_spectral_normal_'..(math.random(1, 2))] end'''
match_indent = true```
ignore that i don't reset the next shop spectral variable
it should replace the first pack in the shop with a spectral pack
the result is the variable is set properly, but the patched code doesn't run (i've checked, and the patch is being applied)
FINALLY okay i had to do something completely different lol
i give up trying to do this on my own, how would i make a joker that can use the effects of other jokers you dont have without having to copy the code for that joker into my code?
with great difficulty
you might be able to create the joker you want to copy, copy it, then destroy it
or you could have it create perishable jokers that debuff immeaditely
tried that, destroying a card is context so it created a recures function that caused a stack over flow 🫠
and/or missing texture from more fluff
is it good practise when making new stakes, to have an above_stake paramater such as 'gold'
anyone knows why SMODS has specifically these vanilla blinds in SMODS.Blinds? im curious lol
because it takes ownership of them to change stuff
dunno i dont have it in mine so it must be a mod
what do I put in info queue to show the tooltip of a sticker?
info_queue[#info_queue + 1] = G.P_CENTERS.m_stone
{ key = key, set = 'Other' }
thanks
it was because i had HandyBalatro on 
I know that mod
HEHE
is it possible to prevent func returns in calculate from juicing up the scored card
ah
How would I get the payout dollars from a defeated blind?
nvm, i had another issue that was giving me problem
What do I use to make a collection that isnt under the "Consumables" area? preferably something like the tags tab
<@&1133519078540185692>
i am so lost rn
that just looks like a syntax error to me
syntax error
ah
i added this <eof> they mention and it just errors out im so lost tho ik its probably syntax related
<eof> is not an actual thing in code (afaik) its just short for end of file
^ if you see "<eof> expected" then that usually means you have too many ends in your code
or closing brackets, or anything else of that nature
i think i got it
Since returning has to always be the last thing in a block of code
maybe
I'm trying this as the code is stated but it doesnt work, I'm probably missing something
key = "batman_joker",
pos = { x = 0, y = 0 },
rarity = 1,
cost = 5,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
atlas = 'batman_joker',
soul_pos = nil,
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS.m_gold
end,
calculate = function(self, card, context)
if context.before then
for _, scored_card in ipairs(context.scoring_hand) do
if playing_card:get_id() == 2 or playing_card:get_id() == 3 or playing_card:get_id() == 4 or playing_card:get_id() == 5 then
scored_card:set_ability('m_gold', nil, true)
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
return true
end
}))
end
end
return {
message = localize('k_gold'),
colour = G.C.MONEY
}
end
end
}```
thought i had this down
but it crashes when i play cards
D:
What error do you get?
It's scored_card not playing_card
This is the current untouched code straight from the steamodded source. I probalby need to put this in a function of sorts but this just errors out
is there a 1-line function to find the number of jokers you have from a certain set, or do I need to loop over all jokers individually and count them
You mean a certain pool?
a specific pool that I made myself, yes
No, there isn't a function for that.
this is correct if you remove the optional fields, the problem is that you also need to define create_UIBoc_your_collection_something
I see
what function handles joker calculations? i want to hook into it for a blind where the required score increases if an xmult triggers
No, you should use context.post_trigger
Including or not including playing cards Xmult?
including
Hook eval_card
okie
you should hook SMODS.calculate_individual_effect instead since then the recursive looping over the effect table is done for you
lowkey out of ideas for any other stakes but wish there was a better transition between these two
I don't know how recent this changed, but G.FUNCS.draw_from_deck_to_hand now checks hand size when drawing. Is there a way to get around this when calling the function?
im trying to make a card convert two cards only if you have two specific ranks selected. yes ik the numbers but this just errors out with nil values
SMODS.draw_cards(number)
Log?
When exactly does it crash?
Yep just noticed that too
Might honestly need to be == 2 since you're checking two cards
yeah
poverty
I'm having a bit of a weird issue. I'm trying to make the reward text a custom string (it's supposed to say $20) for this blind. I've got the instance in the collection and the blind select screen working, but here it's just showing 3 exclamation marks? Why is it doing this
my best guess is that it has something to do with the cashout screen?
The default value for G.GAME.current_round.dollars_to_be_earned is '!!!'
ah ok, that makes sense
Is there a way to make a dependency like
this mod Or this one
like
cryptlib or just cryptid
optionally, does it work if i just have both cryptlib and cryptid enabled in my game
you shouldn't need to since cryptid has in its meta that it provides Cryptlib
so like
depending on cryptlib would work if you had either cryptid or cryptlib
also don't use both
well it doesnt lol
thats a bad idea for internal state reasons
oh you're specifying version
i think thats completely borked with how cryptid does the provides
yeah
just to answer your actual question, you can do this by separating each dependency option with |
noted
also the default version of a provided mod is just the version of the mod that provides it
which you could also use to guard the version just based on cryptlib
though note it's not fully future proof if the versions end up overlapping at some points, so this is definitely bad of cryptid to not supply the proper version
Anyone know how to make it so the display size of the card with the gloom enhancement differs between backside and front?
is there a way to get on-screen cards
G.I.CARD
How do you make it so a joker is unlocked by discovering every booster pack?
how do you use generate_ui? i have a joker that has a string var that gets longer so i wanna use DynaText to make it scroll.
generate_ui is for more complicated text box manipulation, if you just want some UI in the box use main_start or main_end
just saw that in the docs ya, trying it rn lol
there is no info on how to use generate_ui because you basically have to understand how the description is made from the code
so it's hard to explain
how do I make a skin I'm working on put in a new Enhancements.png I've made?
That doesn't seem to tell me how to write it with my existing txt but I don't know
i thought i was staring to understand hwo ui works, i do not qwq
loc_vars = function (self, info_queue, card)
return {
vars = {
main_end = {
n = G.UIT.R,
config = {
align = "tm",
padding = 0.1,
scale = 0.75,
colour = G.C.CLEAR,
},
nodes = {
{n=G.UIT.O, config={object = DynaText({string = card.ability.extra.text or 'ERROR', colours = {G.C.BLACK},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1, scale = 0.33*1})}}
}
}
}
}
anyone know why nothing extra gets rendered?
return a table of nodes
your returning a table containing the information for a node
wrap everything inside main_end with a {}
like so?
loc_vars = function (self, info_queue, card)
return {
vars = {
main_end = {{
n = G.UIT.R,
config = {
align = "tm",
padding = 0.1,
scale = 0.75,
colour = G.C.CLEAR,
},
nodes = {
{n=G.UIT.O, config={object = DynaText({string = card.ability.extra.text or 'ERROR', colours = {G.C.BLACK},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1, scale = 0.33*1})}}
}
}}
}
}
cuase its still not rendering anything qwq
not inside vars
omg i mess read the docs lmao ya thats probably the prob XD
also don't do what I said earlier
its at least trying to render now lol still def got something wrong in my ui tho x.x
doing what you said acctually fixed the crash :D
I don't understand how I'm supposed to use this or how to tell it what png to use
which of the two
the playing card one or the other one
Enhancers
For steel, lucky etc
I have a PNG I made, I just want my .lua to recognise what it is
I only needed to change bonus, mult, wild, glass, gold and steel
oh okay
I've downloaded like 6 mods that change the enhancers.png and all of them do it differently, and if I copy their work and rename it to fit in my .lua, it just doesn't work
Why is there no actual documentation on how to change it, like there's "The game reads enhancements as "centre" but then everyone refers to it as "back" but then "centre" in the same line of code
and it just doesn't work?
back is decks
which are on the same sheet
but a different set so malverk needs a seperate texture set for it
Sorry, I don't understand
Also are you actually looking at malverk texture packs
I'm gonna be so real, I have no idea how I'd figure that out
Because a malverk texture pack shouldnt be doing anything with base centers
Are they using
AltTexture {
...
}
AltTexture is for malverk so look at that
And you also need the TexturePack or whatever its called which youll find at the bottom of most malverk mods
The mod I've found thats using Malverk is Dark and Colorful
and it's just on Nexus
it has the normal
assets > 1x/2x
main.lua
I don't know what you mean by texture pack
Have you looked at the malverk example mods
Yeah and none of them use enhancers
I don't know because I tried using the same code wit ha different name, and balatro just ignored the file
And set will be Enhanced instead of whatever else
Is upgrade_poker_hands from SMODS fucky for anyone else? It's not displaying the hand name and it also leaves the chips/mult display at what the hand leveled up to, and when it levels multiple hands it says it's doing a bunch of random subtraction
I'm on 1323c for Polterworx reasons which is probably why, but it'd be handy to know if that ever got fixed
You also need to make sure your mod has a metadata file so it actually loads
Or steamodded header but that will likely be deprecated in the near future
So thing is, I only have a .lua file and my assets
it loads 100% fine
for the cards and all the mod info
I literally just want to load Enhancers.png
I don't want to do anything fancy
https://github.com/Eremel/Malverk?tab=readme-ov-file#defining-a-texturepack did you do this part
im on mobile i cant view that
is there a reverse of G.hand.highlighted built in?
No
My specific thing is that I want to select cards that are not being discarded during context.pre_discard
Oh so it isnt even there
You could loop through G.hand and check if card.highlighted
I just found a template that worked so I don't know what I'm doing otherwise
I was told the DeckSkin stuff works fine and it's all everyone ever sent me
I had no idea Malverk had its own format
Oh yeah DeckSkin is only for the rank/suit sprites
I can only help so much on mobile though
Would you be ok if I sent you a DM and message you tomorrow as it's 1AM for me
Thats ok, there's no rush
it's already deprecated lol
Oh lmao
it's deprecated but i think they were talking about making it unsupported
Yeah thatp
this is wrong and i dont know why am i stupid
ah. thanks
But you should just do G.P_CENTERS.e_negative instead of that if you just need the default negative description for joker slots
wait why
will automatically do the loc_vars and stuff for negative
Instead of needing to do vars manually
ah.
which one is right then
The bottom
kk
Thinking about picking up Balatro modding again
is there a way to add cards to discard during context.pre_discard?
the hook does that
G.E_MANAGER:add_event(Event({
func = function()
local any_selected = nil
local _cards = {}
for _, playing_card in ipairs(G.hand.cards) do
_cards[#_cards + 1] = playing_card
end
for i = 1, 2 do
if G.hand.cards[i] then
local selected_card, card_index = pseudorandom_element(_cards, 'vremade_hook')
G.hand:add_to_highlighted(selected_card, true)
table.remove(_cards, card_index)
any_selected = true
play_sound('card1', 1)
end
end
if any_selected then G.FUNCS.discard_cards_from_highlighted(nil, true) end
return true
end
}))
Yeah but the problem with that is that it's during context.pre_discard so since you have cards selected they get discarded twice, duplicating them and creating ghost card stuff
what are u trying to do
Try just highlighting them without the additional discard call
i feel like that should work?
yeah
if i do that then the added cards don't get discarded and just remain highlighted
G.hand:add_to_highlighted, right?
maybe i just have to hook into the discard function for this one
the problem is that the discard code pre-computes the amount
does any mod use the discard card limit
I've legit been trying to find a way to change the circled text for a specific boss blind for hours now, I don't think I'm able to do it on my own
I know where to patch but absolutely nothing I've tried has worked
the best I've done is make it display the default "!!!" but I can't even remember how I did that
Where are you patching?
into this line in UI definitions:
{n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.current_round, ref_value = 'dollars_to_be_earned'}}, colours = {G.C.MONEY},shadow = true, rotate = true, bump = true, silent = true, scale = 0.45}),id = 'dollars_to_be_earned'}},
I've managed to change similar text in the collection and the blind select screen, those were effortless in comparison to this
is there a way to make the plasma effect without the balance = true (i want to change it from balance to smth else)
You mean you want to balance the chips and mult without returning?
yea i mean without using the 'balance = true' thing
SMODS.calculate_effect({balance = true})?
lemme rephrase my question, how do i check how much mult and how many chips there currently are
what is your goal here exactly
im wanting to make a challenge deck that makes it chips + mult
so you want the final score of a hand to be chips + mult instead of chips x mult?
i have an idea for the stickers to put between the two stakes i made feel free to give me better ideas
lose $1 when hand discard and lose $1 when hand played
you'll want to just have the game switch the SMODS.Scoring_Calculation to add instead of multiply when you start or continue a run on the challenge deck, it's basically built into smods
when hand discard?
like one dollar gone when you play or discard a hand respectivelly, admittedly they probably arent that good
thx!
-# im still kinda new to modding so this is really helpful
so like golden needle but also applied to hands?
yeah pretty much
#1456643778336129127 you can use this as reference it should help you make that idea come to life
i been on that vanillaremade game since the start 🔥
oh lol
it was more at a balancing standpoint if they are good stickers
ohh ok
SMODS.set_scoring_calculation('add')
^ thanks, my good laptop is in for repairs at the moment so i'm not doing so hot with my documentation references lol
thx!
Hey everyone. Do you know how negative numbers in jokers work? I've been trying to make this one give it's chips and mult negatively and can't find a way to do it. It works, but gives positive numbers.
It's the first part of the calculation and the function at the top.
dont use chip_mod and mult_mod
just return chips and mult without any message
like dont use them at all not just for this
Okay, I had seen that it wasn't that necessary before. This is based off another mod.
Thanks, will get back to it.
the easiest way would be to just patch it to recalculate highlighted count after the context calc
hopefully wont break anything
does the mod in question start with c and end in ryptid? /j
hey, so i'm updating my mod that i haven't touched since july, and when starting a new run with it enabled i get this every time. unsure what's causing it
on latest smods and everything
Code?
do you just want me to send it all?
it says "utils.lua" so i'm unsure
so whic file
Your mod's file.
You're setting cardareas to true in your optional features.
Guys!!! It works. omg.
how do i add 2 soul layers to a joker?
preferably using soul_pos.draw
nvmd i think i got it
Is there a way to include global variables in text?
Not in local vars.
Oh, my apologies, yes in localization
return { vars = { global_var_idk } }
nothing's saying you have to put a card's variable in there
you can have it show anything
Wait, sorry, still not communicating right. I don't have a base Joker or object for this message.
Like for example, if I had a message I wanted to write across the screen at a given point, and wanted it to include the profile name, how would I do that
you have to do UI Shit™ for that idk
I see. Won't bother with it then. Thanks for your help.
attention_text is a function that exists
you don't need to do UI Nonsense™ for that
but like. maybe step 1 of "put a profile name in a message on the screen" is "put a message on the screen", hm?
How do you make a UI node not block elements behind it from being clicked
Or whatever UIBox{} creates
node.states.hover.can = false
node.states.click.can = false
How come when I switch this Joker Display code for misprint from a vanilla joker to this modded joker, I get an index error, despite the joker having the correct config items, and making sure the jokers file is loaded before the joker definitions file?
show the full crash log
the crash i showed above wasn't the most updated crash, but this log here is
actually, don't use it that way
modded objects are yet to be injected into prototype pool (in this case G.P_CENTERS)
use SMODS.Jokers.j_uma_goldship instead, at least that's what I think shall work
I’ll give it a test
even after swapping it out in favor of the SMODs... it still crashed
oh, I see
it's a function inside dynatext.string
usually functions don't cause problems
until you invoke it directly at load
vanilla misprint display works because it's already there
at this point I recommend using the joker_display_def way
instead of defining each entry in a separate file, you define joker_display_def field in your joker code as a function that returns the exact same table you would define in JokerDisplay.definitions
since it's a function now, it won't cause problems unless you invoke it at the wrong time
the format shall be as follows:
SMODS.Joker{
..., --your code
joker_display_def = function(JokerDisplay)
return {
text = {...},
reminder_text = {...},
calc_function = function(card)
-- do stuff
end,
}
end,
}
whats the name of the ui element used to make these selector things? wanna add on to my config :3
Pretty sure there is a standalone mod for more speed
Probably just look see how it manages it
@blazing helm
ah its create_option_cycle thx ^w^
does smods come with its own food joker object type i can add to for easier integration/unification with any other mods that might have food joker related effects?
Not yet
How do I loop through the abilities table of a joker? I've tried this code but it keeps erroring:
for statName, statVal in pairs(joker.ability.extra) do
if string.find(string.lower(statName), "chips") then
if jokerChips == 0 then jokerChips = math.floor(100 * joker.config.center.rarity * joker.sell_cost / 4) / 100 end
elseif string.find(string.lower(statName), "mult") then
if jokerMult == 0 then jokerMult = math.floor(100 * joker.config.center.rarity * joker.sell_cost / 8) / 100 end
end
end
(joker is a different joker from the one this code is in)
How are you setting this joker value?
I look through G.jokers.cards and put all the non-eternal ones in a table (like how ceremonial dagger does it)
Then I loop through this table with a simple for _, joker in pairs(destructable_jokers) do loop
Ohh alr, I'll change it so it skips if it doesn't find the extra table
Thanks a bunch

this is what happens when I try to highlight a tag in tutorial
game just hard crashes lmao
does anyone have the custom card skins from the base game? i want to make color edits to the shovel knight and potion craft skins for my own high contrast needs
you can unzip the exe to get them
huh, i never knew you can unzip an exe. neat. thanks
Most programs dont let you unzip exes because the contents are usually pretty much completely obfuscated
Love2d games just happen to be just the source code and love2d library in a zip
so my mod isnt loading, saying theres an invalid metadata file or smth and idk how to solve this
try removing the space in the dependency?
oh ok, thx
ok its still saying its an invalid metadata file
well i did change the prefix but i only use the prefix in one place and i did update it there too
i have one question of do i make my mod work with other mods like jens almenac i really want to have my own mod to be able to get the same things like the effects from cryptid mod on my mod like it can get the same editions
why would it not be able to get other mod editions
idk i was asking that if i need to do something to make it happen like adding something in my code to make it work
you dont
Does anyone know hit there is a way to run code after scoring a hand? I'm hookinh into Card:calculate_joker but I can't seem to get it to run code after the hand is fully done scoring.
what effect are you trying to do?
I have a function that I've made which I'm trying to call
but what is it trying to do
What do you mean?
I'm trying to run code after the hand finishes scoring so I can update my UI
what is the code intended to do then I can tell you the best place to put it
I just want to call self:updateHandsPlayedUI(self) for each joker and I've defined
function Card:updateHandsPlayedUI(card) in my core file
are you using smods
Yep
Also I don't see how it is an xyproblem
we dont know what your ui is or what it's trying to do
so we cant know what after scoring means exactly either
you can probably use an event in context.after in SMODS.current_mod.calculate
Why do you need what my UI does? Everything is working but the problem is that I can only figure out to call my UI function before the hand finishes even if I check context
out of context funny gif
...
Once the hand finishes being played and all the cards start getting discarded
^
well the problem is for example if the best place to put whatever youre needing is with an event like i said or in another function
Thats what I'm trying to figure out
when I'm referencing Card:calculate_joker and check for context.after code still runs at the start of the hand
Thank you! I've tried looking through the docs for it but I couldn't find a page like this and I've just been looking thorugh lovely's dump
there's also this detailing that specific problem https://github.com/nh6574/VanillaRemade/wiki#why-does-the-animation-play-before-scoring-when-the-context-i-put-it-in-occurs-later
Alright, I've managed to get it working. Thank you so much for your help, I'm sorry that I couldn't explain my problem clearly.
Yep, this worked! I had to go back to using G.P_CENTERS.j_uma_goldship.config.extra.min as my definition to read the values, but it worked in the end
I'm trying to run a code that only works on cards without an edition. "if not edition then" and "if not have_edition then" and many variants of it, but it always seems to be set to true for all cards or its a nil value. Trying to "edition and not edition.polychrome" did not differ the results on any card I tested. I started throwing code at the wall to see what sticks, "SMODS.edition(scored_card)" and such. I looked at
but "SMODS.Edition:get_edition_cards" only caused crashes. I can't find a single thing on the SMODS documentation that helps, yet the code for checking for enhancements is incredibly simple.
I'm just trying to make a card foil if it does not already have an edition.
not card.edition?
I fixed this by using love.graphics.stencil
frick I dont have nitro
using that, all cards were turning foil. removing the "not" made no cards turn foil. So it's at least not crashing or giving a nil value, but it is still treating all cards as all not having an edition.
card.edition only exists for cards that have an edition so like
idk
you can use not card.edition and not card.will_be_editioned ig
Oh I didnt realise that link to VanillaRemade was actually showing off more examples. I've got a few more things to try out it seems.
It would help if you shared your code too so people know what you’re trying to do
What on earth?? I was just told I cant post my code here because I dont share a server with the recipient.
SMODS.Joker {
key = "ivy",
name = "Ivy",
rarity = "fuse_fusion",
cost = 19,
unlocked = true,
discovered = false,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
atlas = "fuseforce_jokers",
pos = { x = 2, y = 5 },
config = {
extra = {
x_mult = 1.5,
joker1 = "j_flower_pot",
joker2 = "j_marble"
}
},
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS.m_wild
return {
vars = {
card.ability.extra.x_mult,
localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}
}
}
end,
calculate = function(self, card, context)
if context.setting_blind then
local stone_card = SMODS.create_card { set = "Base", enhancement = "m_stone", area = G.discard }
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
stone_card.playing_card = G.playing_card
table.insert(G.playing_cards, stone_card)
G.E_MANAGER:add_event(Event({
func = function()
stone_card:start_materialize({ G.C.SECONDARY_SET.Enhanced })
G.play:emplace(stone_card)
return true
end
}))
return {
message = localize('k_plus_stone'),
colour = G.C.SECONDARY_SET.Enhanced,
func = function() -- This is for timing purposes, everything here runs after the message
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 = { stone_card } })
end
}
end
if context.before and not context.blueprint then
local stones = 0
local has_edition = card.edition
for _, scored_card in ipairs(context.scoring_hand) do
if next(SMODS.get_enhancements(scored_card)) then
if SMODS.has_enhancement(scored_card, 'm_stone') then
stones = stones + 1
scored_card:set_ability('m_wild', nil, true)
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
return true
end
}))
if not card.edition and not card.will_be_editioned then
--if not SMODS.has_enhancement(scored_card, 'e_polychrome') then
scored_card:set_edition('e_foil', nil, true)
G.E_MANAGER:add_event(Event({
func = function()
scored_card:juice_up()
return true
end
}))
end
end
end
end
if stones > 0 then
return {
message = 'Wild'
}
end
end
if context.individual and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_wild') then
return {
x_mult = card.ability.extra.x_mult
}
end
end
}```
I've exhausted all the options I was given and I just can't get it to actually differentiate between editioned and non-editioned cards. So here's the full code.
And wow Discord is struggling to function too, I guess my code must be really bad.
you're checking card (the joker) instead of scored_card
im assuming, i dont know what the effect is supposed to be
Thank you. You figured it out.
I didn't even think to say I was using this code on playing cards rather than jokers when asking for help. Very sorry.
the problem is not the difference between jokers and playing cards but the variable names. card comes from calculate(self, card, context) and is whatever card is running the calculation, scored_card is the name you have in the loop of scored cards
you could have named them bob and alice and they would have had the same issue
i finally realized which space u meant lmao
clearly i did this wrong...
im looking thru the wiki and i dont c anything
Thats because its not on the wiki and you have to add the scoring calculation yourself, which also isn't on the wiki. Its on a specific update of smods
SMODS.Challenge {
key = 'simple_math',
apply = function(self)
SMODS.set_scoring_calculation('add')
end
end
Also. How would I go about changing a single operator symbol in the calculation UI I have set up without modifying every instance of the * symbol
thx!
well it is on the wiki just not its own page yet https://github.com/Steamodded/smods/wiki/0827#smodsscoring_parameter
OHHH ok thx
i literally cant see whats wrong with this code 😭 nor do i see where to put the second end
You're missing a , after the end.
same as the cards
am i doing this right i kind of took code from paperback
i dont think i am
the first one is Spell cards may appear in the shop and the second one is Spell Packs appear 2X more frequently in the shop
- is your mod prefix
shark? - show the code where you create the SMODS.ConsumableType for spell cards
- yes
- the key is Spell so maybe more like
shark_Spell_rate?
yea it should be shark_Spell_rate
but from there, the vanilla game/smods will automatically handle the rest!
oh nice!
and the rates are correct? iirc the default Tarot rate is 3
so 2 should be more rare? and 4 should be double that?
yea paperback soothsay has a comment that says it's 3 by default
mhm
but the way rates work in-game means that doubling the number doesn't actually double the odds
and quite frankly there's no easy way to handle that in a crossmod-friendly way
tarot merchant (ostensibly "double the odds") sets the rate value to 9.6
the key will be spell_rate
oh
it doesn't add the prefix and it lowercases it
you should add the prefix to the consumabletype tho
ahhh right
hm.
would it be fine to leave it at 2 and 4?
i think so yea
realistically players aren't gonna notice if it's not exactly doubled
you don't need to tell them the number, you can write it as 'increases the odds'
huzzah it works
mmm fair
What causes atlas injection times to be super long? Is it in how long the atlas is? (It's for animated cards, so it's rather large)
possibly, although the bigger issue is having a lot of different atlases
it can help organizationally to split stuff up, but if you go so far as to have a different atlas for every single joker then that's not good
Wait, really?
Because one of my atlases is...7668 by 3028 (1x)
And I figured that was causing the problem
ok that's also an issue lmao
what are you even doing that requires a spritesheet like that
ok a 100 frame animation should only be 710 by 95 at 1x resolution
unless you're drawing at a higher resolution than vanilla sprites
Longest animation is like, 120 frames
honestly i don't think there's much you can do then
this, for example, is what it looks like zoomed alllll the way out
Would separating it to reduce empty space be helpful? e.g. categories by frame-count?
i think so yea
How could I get the SMODS documentation in vs code?
like make this not show random stuff
is there a way to set the font size of the text going into create_badge
keep in mind there are many things that are still not documented from vanilla so not everything will show good suggestions
does the scaling argument not work
Yeah, i misunderstood what it was doing, thanks!
i. what.
it's doing if (not #G.jokers.cards) + G.GAME.joker_buffer >= ...
ohlol
just take out the not and make it <
ok also apparently the edition doesnt work
either i'm adding it wrong or setting the variable wrong
i recommend adding prints to see where the code gets to
ah edition is a table, you should be checking if G.jokers.highlighted[i].edition.key == "e_negative"
(check first to see if the card's edition table exists at all, so you don't try to index a nil value on non-editioned cards)
What's the best way to directly set a blind's requirement, particularly an upcoming one?
How do you make an object buyable?
To clarify, I don't mean to make it appear in the shop. I mean to give it the price and buy buttons like it would have in the shop
create_shop_card_ui(card, type, area) i think
Thanks, will try it
I made wild cards immune to debuffs, and it works, but I'm also trying to update the description to reflect that. This is my duct tape and ramen-ass attempt but it doesn't work
SMODS.Enhancement:take_ownership(
'wild',
{
loc_text = {
text = {
"Can be used",
"as {C:attention}any suit{}",
"{C:attention}Immune{} to {C:red}debuffs"
}
}
}
)
its loc_txt, but localization files also take priority over loc_txt
so to change vanilla descriptions you need to use a localization file
wouldn't be Krus code if I didn't mistype something critical. Aight, I'll look into loc files
https://github.com/Steamodded/smods/wiki/The-Mod-Object#mod-config
https://github.com/Steamodded/smods/wiki/The-Mod-Object#creating-a-config-tab
can i somehow display a line of text on the cashout screen without it giving any dollars?
i do wanna show a number, just without the money functionality
try copying what add_round_eval_row does
im pretty sure you can do it in context.round_eval and it works
yeah something like this
add_round_eval_row({dollars = 0, name='custom', number = card.effect.config.extra.amount, number_colour = G.C.RED, text = localize({set = 'Tag', type='name_text', key = card.effect.config.extra.tag}), text_colour = G.C.BLUE, pitch = 4, card = G.deck})
looks like this
hey guys! is there a way to add images to badges
not with create_badge afaik but you can copy what it does and change the dynatext for a sprite object
How could I make one suit be treated as another?
would it be best to hook into the card.is_suit function?
or is there another way
Yes.
so theres G.GAME.modifiers.enable_rentals_in_shop to enable rentals, is there anything for pinned?
probably not
the only vanilla usage of pinned is one challenge
oh
percentage gaming
i see SMODS.Gradient lets you use update(), what does update return (or modify) exactly to set the color
https://github.com/Steamodded/smods/blob/893c1c6529ca5a4bd9593b20dbdb135be6cd3dc5/src/game_object.lua#L628
default update
Trying to make a joker that wins small blinds for you if your chips are at least 50% of the requirement. That works fine and all, but the end of round screen has these extra blind chips appear
calculate = function(self, card, context)
if context.after and not context.blueprint then
G.E_MANAGER:add_event(Event({
blocking = false,
func = function()
if G.GAME.blind.small and G.GAME.chips >= G.GAME.blind.chips * card.ability.extra.chip_percent then
G.GAME.chips = G.GAME.blind.chips
G.STATE = G.STATES.HAND_PLAYED
G.STATE_COMPLETE = true
end_round()
return true
end
end
}))
end
end
thanks!
A mod im working on. The calculation is as such chips * mult * (charge/battery)
Charge is the amount of "juice" you have left in a run. Once it reaches zero, if you have no way to quickly charge it, the run is (basically) over. Battery is the total amount of Charge you can have, and together they represent the percentage of your score that will actually be applied.
That is very cool
I mentioned this issue a bit ago, but how can I add the Buy UI to this item? Through its method of creation it somehow lost it. I tried the create_shop_card_ui function but that didn't seem to work.
Its possible that it might already has it but it isn't showing. In that case, how can I get it to show?
Code?
I used this function to transform a shop item into another. In context, I used:
create_shop_card_ui(G.shop_jokers.cards[#G.shop_jokers.cards])```
It is also important to note I am using the latest in-development version of SMODS, version BETA 1421c, as it is necessary for some features. It works on the latest full release but not in the in-dev. I don't know what would have changed that I need to account for.
im guessing its the same if i want to add any dynamic text right
yes
can someone help me with the ins and outs of SMODS.set_debuff ?
i'm updating some mods, and these lines seem to crash the game
the code used to use debuff_card
but set_debuff seems to work differently
leaving it as debuff_card hard crashed the game, it wouldn't even go to the crash log
probably because you were doing something else wrong
set_debuff is crashing because it doesnt exist
this is what the set_debuff is according to the github
that's SMODS.current_mod.set_debuff and it's not a function you run, it's a function you define
what's your goal
okay so, there's 2 custom blinds, one debuffs wild and polychrome cards, the other cycles through the suits to debuff every hand
there's also two functions defined in the main.lua that are for removing the debuffs afterwards
how are you debuffing them
here's the wild/polychrome blind
i think the reason is because SMODS.debuff_card calls the recalc_debuff function
instead of using SMODS.debuff_card in recalc_debuff I would just return true
for this blind that should just work im pretty sure
for the other one you might need to call SMODS.recalc_debuff on each card after each hand
Buffing greedy/lusty/wrathful/glutton jokers slightly. Thought this might do it, to my understanding, but it still does +3 mult. An I missing something and am I stupid lol?
SMODS.Joker:take_ownership(
'greedy_joker',
{
config = {
extra = {
s_mult = '4'
}
}
}
)
are you sure this is loading
as far as i can see it should crash because the 4 is a string and you dont have the suit
you just reminded me to define the file path on my main file 💀. I'll do that and define the suit on each joker too
hey chat i'm trying to have a jimbo style tutorial thing pop up and just say 3 lines as a set piece for a trailer
where is a good reference
this is what i did for hot potato
https://github.com/Balatro-Potato-Patch/Hot-Potato/blob/9709c9045ab34514af643f5d9d13089d7babd428/Jtem/events_definitions.lua#L5471
i dont have other references
Okay peam
Made some changes and messed around with localization, and we got it to function and the description correct 👍
am I in the right channel if I need help concerning the making of my mod ?
oh cool thank you
well, then cotext : I'm making a od for me and my gf to play with (light thing I only added 30 jokers for now) but there is two i particular that really messes with me
SMODS.Joker{
key = "x",
atlas = "x",
pos = { x = 0, y = 0 },
config = { extra = { first_discard_done = false } },
rarity = 1, cost = 4,
blueprint_compat = true,
eternal_compat = true,
unlocked = true, discovered = true,
calculate = function(self, card, context)
if context.before and not (context.individual or context.repetition) then
card.ability.extra.first_discard_done = false
end
if context.discard and not card.ability.extra.first_discard_done then
card.ability.extra.first_discard_done = true
if #context.full_hand == 1 then
G.E_MANAGER:add_event(Event({
func = function()
choose_random_highlight(G.hand.cards, 2)
G.FUNCS.discard_cards_from_highlighted(nil, true)
return true
end
}))
return { dollars = 10, card = card }
end
end
end,
loc_vars = function(self, info_queue, card) return {} end
}
and
SMODS.Joker{
key = "y",
atlas = "y",
pos = { x = 0, y = 0 },
config = { extra = { current_rank = nil, pending_destroy = {} } },
rarity = 1, cost = 4,
blueprint_compat = false,
eternal_compat = true,
unlocked = true, discovered = true,
calculate = function(self, card, context)
-- Lazy init
if not card.ability.extra.current_rank then
card.ability.extra.current_rank =
pseudorandom_element({2,3,4,5,6,7,8,9,10,11,12,13,14},
pseudoseed('mia_rank'))
end
-- Reset destroy queue at the start of each hand
if context.before and not (context.individual or context.repetition) then
card.ability.extra.pending_destroy = {}
end
-- Rotate rank at end of round
if context.end_of_round and not (context.individual or context.repetition) then
card.ability.extra.current_rank =
pseudorandom_element({2,3,4,5,6,7,8,9,10,11,12,13,14},
pseudoseed('mia_rank'))
end
if context.individual and context.cardarea == G.play then
if context.other_card:get_id() == card.ability.extra.current_rank then
local roll = pseudorandom('mia_effect')
if roll < (1 / 15) then
local q = card.ability.extra.pending_destroy
q[#q + 1] = context.other_card
return { message = localize('j_destroyed'), card = card, colour = G.C.RED }
elseif roll < (1 / 3) then
local target = context.other_card
G.E_MANAGER:add_event(Event({ func = function()
target:set_ability(G.P_CENTERS.m_wild)
target:juice_up(0.5, 0.3)
return true
end }))
return { message = localize('k_upgrade_ex'), card = card, colour = G.C.GREEN }
else
return { message = localize('k_nope_ex'), card = card, colour = G.C.RED }
end
end
end
if context.after and not (context.individual or context.repetition) then
if #card.ability.extra.pending_destroy > 0 then
for _, target in ipairs(card.ability.extra.pending_destroy) do
local t = target
G.E_MANAGER:add_event(Event({ func = function()
t:start_dissolve()
return true
end }))
end
card.ability.extra.pending_destroy = {}
end
end
end,
loc_vars = function(self, info_queue, card)
local names = {
[2]="2",[3]="3",[4]="4",[5]="5",[6]="6",[7]="7",[8]="8",
[9]="9",[10]="10",[11]="Jack",[12]="Queen",[13]="King",[14]="Ace"
}
return { vars = { names[card.ability.extra.current_rank or 2] or "?" }, key = self.key }
end
}
both of them make in very particular case, sort of "ghost" cards, sometimes just leaving a blank space counted as card but there is nothing, sometimes as omniscient card not on screen always selected even after discard or play, and always hidden face, if the code seems messy it's because I tweak MANY things and ended up with this which is the less buggy version for each, if you need any helper functions used here ask me
You can do the format
```lua
text here
```
For proper code blocks with coloring.
oh thank you I was about to ask how to do it
X is "If first discard of round is only one card, discard 2 additional random cards and earn $10"
Y is "Scored [?] have a 1 in 3 chance to become wild cards, 1 in 15 to be destroyed instead (rank changes every round)"
i havent read all of it yet but use SMODS.destroy_cards(card_to_destroy) instead of start_dissolve
I'll try that
what is the difference and when to use which ?
destroy_cards uses events to not create ghost cards in scoring, you pretty much never need to use start_dissolve over it
oh okay, does it have a destroyed message or anything like this or my custom j_destroyed is still valid ?
you mean another add_event inside the main event ?
yes
why should it help ?
G.E_MANAGER:add_event(Event({ func = function()
G.E_MANAGER:add_event(Event({ func = function()
choose_random_highlight(G.hand.cards, 2)
G.FUNCS.discard_cards_from_highlighted(nil, true)
return true
end
}))
return true
end
}))
like so ?
im guessing that the problem is that youre highlighting cards too early to discard causing you to discard the same cards twice, another event would make it run later
no, it should be inside a func
edited is this better ?
okay I see
also how do you do the little jiggle like the DNA card when enabled before the first discard ?
tried somthing before but it only juiced up on playing a hand
youre missing an end and a return true
oh yep my bad
thank you !
this then
I'll try next time I playtest
I did this when playtesting btw but I'm not sure that it's working
local allowed_jokers = {}
local joker_bag = {}
for key, center in pairs(G.P_CENTERS) do
if center.set == 'Joker' then
if string.find(key, 'mymod') then
table.insert(allowed_jokers, center)
else
center.in_pool = function() return false end
end
end
end
-- [...]
G.pick_random_joker = function(seed)
if #allowed_jokers == 0 then
return nil
end
if #joker_bag == 0 then
for i, joker in ipairs(allowed_jokers) do
joker_bag[i] = joker
end
shuffle(joker_bag)
end
return table.remove(joker_bag)
end
the idea is making something that will one by one give only jokers from my mod and not twice until everyone has already been seen
is there a way to force unlock and discover a joker by key?
SMODS.Joker{
key = "yourmod_your_card",
atlas = "yourmod_your_card",
pos = { x = 0, y = 0 },
rarity = 1, cost = 4,
blueprint_compat = true,
eternal_compat = true,
unlocked = true, discovered = true,
If I understand your question right then these lines are what you are looking for
unlocked = true, discovered = true
no
i'm experiencing a difficult to reproduce bug where i have a consumable that uses set_ability to turn a joker into another joker, which is the intended way to unlock & discover certain jokers in my mod, but for some reason it's being very temperamental and leaving the joker locked
and now that i've seen it happen live, i'm trying to figure out a fallback that will at least patch the issue until i figure out the root cause
I think you can make use of that
calculate = function(self, card, context)
if context.hand then
local center = card.config.center
if not center.unlocked then
center.unlocked = true
end
if not center.discovered then
Card.discover_card(center)
end
end
end,
is it what you are looking for or still not ?
unlock_card(G.P_CENTERS[key])
discover_card(G.P_CENTERS[key])
thanks
where is the function that shuffles the deck at?
CardArea:shuffle in cardarea.lua
thx
Wait, i messed it up
I'm not quite understanding. So the reason the crash is happening is that since recalc_debuff is being defined, but it's also called internally in debuff_card, it's doing an infinite loop? i'm not sure what you mean by just returning true either. then how do i apply the debuff with the proper tag then?
since recalc_debuff is being defined, but it's also called internally in debuff_card, it's doing an infinite loop?
yes
i'm not sure what you mean by just returning true either. then how do i apply the debuff with the proper tag then?
recalc_debuf debuffs the card when you return true
i dont see a reason why you need the debuff source? that would also make it harded for cards that prevent blind debuffs from working
you would return true without using SMODS.debuff_card
How would I edit the chips and mult gained from levelling up a poker hand? I'm trying to reference the base game and mods that tweaks level values, but the structure confuses me
I.E. use a consumable that increases Pluto from +10 chips and +1 mult, to +15 chips and +2 mult?
G.GAME.hands['High Card'].l_chips & G.GAME.hands['High Card'].l_mult
Gotcha, I'll give it a try
assert(SMODS.modify_rank(G.hand.highlighted[i], 1)) what do I replace this with to make it turn a card into a specific rank?
ahhh ok thank u
what if i want to be a queen and have a red seal?
Is it possible to make it so when you play a hand, a joker adds a random card to your played hand?
I also want the joker to still apply if you play 5 cards, turning it into a 6 card hand >:3
you can be whoever you think you are. i believe in you and i'm proud of you for realizing that about your identity /silly
replace "Ace" with "Queen", and change_base only handles rank and suit, so to add a red seal, you'll want to do G.hand.highlighted[i]:set_seal("Red")
So, scratch what I said. I actually wanted to override the base mult and chips gained when a hand levels up. This is what I thought might work, but it doesn't, so I'm messing something up
SMODS.PokerHand:take_ownership(
'High Card',
{
l_chips = 15,
l_mult = 1
}
)
I just imagine this is the equivalent to "if(crash) = don't fucking do that please"
I still have that issue where I get a ghost card out of my "If the first discard of round is exactly one card, discard 2 additional random cards and earn $10" joker and I don't know at all how to fix it after many attempts
SMODS.Joker{
key = "mycard",
atlas = "mycard",
pos = { x = 0, y = 0 },
config = { extra = { first_discard_done = false } },
rarity = 1, cost = 4,
blueprint_compat = true,
eternal_compat = true,
unlocked = true, discovered = true,
calculate = function(self, card, context)
if context.before and not (context.individual or context.repetition) and not context.blueprint then
local eval = function() return G.GAME.current_round.first_discard_done end
juice_card_until(card, eval, true)
card.ability.extra.first_discard_done = false
end
if context.discard and not card.ability.extra.first_discard_done then
card.ability.extra.first_discard_done = true
if #context.full_hand == 1 then
G.E_MANAGER:add_event(Event({ func = function()
choose_random_highlight(G.hand.cards, 2)
G.E_MANAGER:add_event(Event({
func = function()
G.FUNCS.discard_cards_from_highlighted(nil, true)
return true
end
}))
return true
end
}))
return { dollars = 10, card = card }
end
end
end,
loc_vars = function(self, info_queue, card) return {} end
}
here's a clip of what it does in game
https://medal.tv/fr/games/balatro/clips/maSuj2DknMtxdcBjc?invite=cr-MSxmQ3IsNDkxNTIxOTg3&v=3
Regarde Balatro Mod siscard ghost card bug de 3cl1pse_ et des millions d'autres vidéos Balatro sur Medal. #balatro
is there a built in way to shuffle a hand after it's been played?
i think ur missing {} next to the ()
if context.setting_blind and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
func = (function()
G.E_MANAGER:add_event(Event({
func = function()
SMODS.add_card ({key = 'c_lassooftruth_token'})
G.GAME.consumeable_buffer = 0
return true
end
}))
SMODS.calculate_effect({ message = localize('k_plus_tarot'), colour = G.C.PURPLE },
context.blueprint_card or card)
return true
end)
}))
end
}```
this is supposed to create the card upon blind select, but when i select blind the game crashes D:
where would that go? my other uses of take_ownership haven't needed that
oh um nvm then
i thought it was either like
{(
)}
or the inverse
I did this by patching eval_card and faking a retrigger.
I could give it a try, see if it'll help
Is there a way to tell if a debuffed card is a joker?
if card.ability.set == 'Joker'
It didn't give any errors if formatted like ({ }), but it still doesn't work
That still works while debuffed? Must be some deeper issue i'm dealing with
if a function's single input is either a string or a table, lua lets you leave out the parentheses
oh ok
ohh ok
I might shelve the buffed level values for now
WAIT
I didn't have the path set up on my main.lua file
facepalm
oof, glad u were able to figure it out
still need to see if the code works
true
staying organized is awesome, I just keep fucking forgetting to write the paths down lol
It works 🎊
aight time to buff the other hands
Does someone have an answer for this issue ?
maybe full house and steel
something about converting cards to steel when a full house happens
idk
One things for certain… the house always wins
theres a way i can get the pokerhand played level in a calculate?
G.GAME.hands[context.scoring_name].level
thanks bro
unrelated but peak joker
SMODS.current_mod.badge_colour = gradient
thank you :)
I am new to this but I have watched a couple of videos and tutorials, I have downloaded Lovley Injector, the STEAMMODS and all of that stuff and the mod button shows up in my game, but my mod itself does not show up, I was wondering why.
I just found this error message
INFO - [G] 2026-02-23 00:52:45 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\Users\cfcos\AppData\Roaming\Balatro\Mods/LightMods/mod.json, ignoring: [lovely json "libs/json/json.lua"]:185: unexpected character '' at line 1 col 1
how is your mod.json looking like
{
"name": "Light Mods",
"display_name": "Light Mods",
"id": "light_mods",
"prefix": "lm",
"author": ["CFC"],
"description": "Adds to the game",
"version": "1.0.0",
"main_file": "main.lua",
"priority": 0,
"badge_color": "#FF0000",
"badge_text_color": "#FFFFFF",
"dependencies": ["Steamodded"]
}
@wanton jolt I fixed it
I just deleted the file and rewrote the code
yeah
I'm pretty new to modding so I hope that this isn't a stupid question, but how can I change the x/y position of a joker on the screen?
it helps, when someone asks you a follow-up question, to answer it
as opposed to vanishing for a week and then asking the exact same question again as though trapped in a time loop
-# This is not a Minecraft ARG.
this one is giving me nightmares pweaaase 
Guys. Another super quick question.
Where can I find the info for what nil in this means? Or rather what do you put in those places.
(card_type, nil, nil, nil, nil, nil, nil)
Can't find it. 😭
nil is just no value so it doesnt mean anything
But also nobody can answer this without knowing what the function is
wait, really. I usually see this when ppl create cards with a joker. so I thought maybe there would be a way to know what to type in each of those places.
i was wondering why everytime I try to play the challenge to attempt to use the modded joker it crashes, I can give the crash report if that is helpful
I do have the edition and enhancement part, but I cut them out of this
-- =========================
-- FIRE SPINNER JOKER
-- =========================
SMODS.Joker {
key = "fire_spinner",
loc_txt = {
name = "Fire Spinner",
text = {
"If hand is {C:attention}Two Pair{},",
"7s and Aces become",
"{C:red}Burned{} when scored"
}
},
rarity = 3, -- Rare
cost = 8,
blueprint_compat = true,
atlas = "fire_spinner_atlas",
pos = { x = 0, y = 0 },
discovered = true,
calculate = function(self, card, context)
if context.before
and context.scoring_name == "Two Pair"
and context.scoring_hand then
for _, scored_card in ipairs(context.scoring_hand) do
local id = scored_card:get_id()
if id == 7 or id == 14 then
-- Apply the burned edition directly
scored_card:set_edition("e_burned", true)
end
end
end
end
}
SMODS.Challenge {
key = "fire_spinner_challenge",
loc_txt = { name = "Fire Spinner Challenge" }, -- literal name
-- Start-of-run jokers
jokers = {
{
id = "fire_spinner",
eternal = false,
pinned = true,
}
},
}
Clarifying: I cant even enter the challenge because when I click on the button to play it the game goes to the crash report screen
Okay so what does 0.8 mean here?
if context.skip_blind and not card.debuff then
for i = 1, card.ability.extra.jokers do
if G.jokers and #G.jokers.cards < G.jokers.config.card_limit then
local new_joker = create_card('Joker', G.jokers, nil, 0.8, nil, nil, nil, 'skip_reward')```
And why are there so many nil? 🤨
you should use SMODS.create_card instead
there’s docs on smods wiki and vanilla remade wiki
knowing the error message would help
I think the error one is:
card.lua:278: attempt to index local 'center' (a nil value)
Thanks, I actually found it a bit ago and was gonna use it.
But I was curious as to why and how ppl used that.
how do i go about moving the mult score contianer
the id of the joker in the challenge should be its full id
so j_modprefix_name
because when thunk defined function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append), it obligated him and us to type all those nils after the area parameter to reach key_append even if we don't care about the parameters in between
getting around this is what SMODS.create_card was invented for
uuu, I see. Thank you so much, miss.
create_card also has some limitations such as not being able to apply a seal directly upon card init
SMODS.create_card does that normally
and SMODS.add_card goes one further by properly handling putting the card in its area and doing all the relevant calculations
Interesting, will keep it in mind. I was seeing it a lot when reviewing mods.
does anyone here know how i would put a dynatext object (or any ui element) directly on top of a box rather than next to it
working on an alternative for sliders which is more like a progress bar but i want the text actually on top of it and centered

other than the text it works fine and i love it
why does SMODS.GUI.chips_container(scale) not use scale-
pure and utter brilliance one must assume
I'm thinking of putting the text above or below the slider and having it go offset into front
that could work
render a box on top of the box
:)µ
Very quick question. If I surrounded a Joker with if next(SMODS.find_mod("id")) then and endthen would it only be added to the game if the defined mod is detected?
yes, but it's easier to add a dependencies field (array of mod ids) to your joker code
and/or if not next(SMODS.find_mod("some id")) then return nil end at the top of the joker file. if you're doing individual joker files anyway
gotcha
SMODS.Sound({
key = "cocosmod_boostersong",
path = "cocosmod_boostersong.ogg",
pitch = 1,
volume = 1,
music = true,
select_music_track = function(self)
if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
return 1337
end
end
})
key = "cocosmod_boostersong",
i don't see "music" anywhere in here
music = true,
what you've done here is create the field music and set it to true. that isn't what "Your track's sound code must contain the string music" means
oh so how do i do that?
change key to
type the letters "music" somewhere after key =
you have to have the word "music" somewhere in your key
there's nothing in SMODS.Sound called a "sound code"! who typed that?!
i did it but now its says bad argument #1 to 'newDecoder' (filename, file, or fileData expected)
now instead of just instally crash its crash when the principal menu appears
it is the music file now problem?
honestly i haven't the foggiest clue what that error message means
wild guess, your file is in assets/sounds/ and is named exactly cocosmod_boostersong.ogg, correct?
path should not be modified unless file name is changed
no its boostersong.ogg should i change it?
and its /assets/resources/sounds should i change that too?
well. it should be named what path is. otherwise you're directing the computer to look at a file that doesn't exist. if i want you to go to https://crouton.net/ I'm not going to tell you to go to https://duckduckgo.com/?q=crouton&t=fpas&ia=web
DuckDuckGo. Privacy, Simplified.
you've looked at https://github.com/Steamodded/smods/wiki/SMODS.Sound right?
yeah but i dont really understand the part of the API methods
there's exactly one api method and none of your current questions relate to it
yeah the problem got fix and the music plays well the problem now is its crashes because of the background
like
send crash log
its on #⚙・modding-support
that's no longer the crash related to SMODS.Sound
yeah
there it is
wasnt duckduckgo like exposed or smth
If I want to update how much a blind's payout dollars are during a blind, is there a way to update the text shown (similarly to the required chips)?
can i make main_ends go into anything other than the first description box
<@&1133519078540185692>
no
dies
i will note it to pr it after next smods
I fixed it and it still crashes
i read this wrong the first time, this does work btw
dont ping the <@&1133519078540185692> they will get mad if u ping the <@&1133519078540185692> cuz pinging the <@&1133519078540185692> is very bad and it will make the <@&1133519078540185692> very angry if you ping the <@&1133519078540185692>
but why
hello mod
i should post u in #1209506514763522108 cuz ur a mod
blunder
instant death
How could I return played cards to hand?
i think you can hook G.FUNCS.play_cards_from_highighted() in functions/state_events.lua
it has this part
wait a couple of days and do it cleanly 👍
alright what am I doing wrong this time 😭
granted i have no idea what that consumable usage thing is and if smods affects it
i just took fortune teller from vremade and turned tarot into shark_Spell
i dont think thats automatic
gdi
is it the same crash
is this a new feature i lowkey havent updated smods in ages
ok i think its because its not created until you use one
so (G.GAME.consumeable_usage_total.shark_spell or 0)
because the vanilla oens are created at the start of the game
that's just 1 version behind
yes
thx
alwaus update your smods ok it works now? but the locvar isnt...
it's not in 1016
ah
oh no i fell for fools mate by playing f3 then g4 and letting my opponent play e5 and Qh4#
i doo not know why
its the same stuff and i do have #2# written
extern number time;
extern number hovering;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
vec4 tex = Texel(texture, texture_coords);
// Bottom-center origin
vec2 origin = vec2(0.5, 1.0);
float dist = distance(texture_coords, origin);
float gradient = 1.0 - smoothstep(0.0, 1.2, dist);
float pulse = sin(time * 4.0) * 0.5 + 0.5;
vec3 orange = vec3(1.0, 0.4, 0.0);
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 burn_color = mix(orange, red, pulse);
float heat = sin(time * 2.0) * 0.25 + 0.75;
burn_color.r *= heat;
tex.rgb = mix(tex.rgb, burn_color, gradient * 0.6);
return tex * color;
}
Error:
engine/sprite.lua:96: Shader uniform 'mouse_screen_pos' does not exist. A common error is to define but not use the variable.
this wont work, help
is this jokerforge
its pretty easy to tell, is there a .jokerforge file
im guessing the easiest way to tell is for them to tell me if they used joker forge, which is why im asking
I never have to use mouse_screen_pos, so why is it mad at me for it not exsiting?
easiest way to tell if it's jokerforge is [1] = a string
yes
when a polychrome joker triggers, it wont add mult
is context.modify_scoring_hand or context.before first?
ok, do you want to fix that in jokerforge or code it yourself
modify first
perfect, thx
in jokerforge
i would ask here then https://discord.com/invite/eRBByq9AZX
not many people are familiar with it here
how does one check if a mod is cryptid compat
ah
cryptid compat as in they both work or the mod has cryptid specific features
the former
boot them up and hope they dont crash
ykw fair point
if its the latter I would check for demicolon compat on some of the cards
huh?
i don't reckon ive ever heard of demicolon lol
i dont play cryptid too often
card.ability.cry_demicolon_compat
mm
the card force triggers jokers
i should add talisman compat to my mod
what on earth
okay fixed it
what even was the issue 😭
I forgot to call draw_from_play_to_hand after stopping draw_from_play_to_discard
lol
on to the next blind
bumping this
heya question how do you draw a specific card from deck? (in my case card with specific edition)
draw_card(G.deck, G.hand, 90, 'up', nil, card)
what does 90 and 'up' do in this case?
A Balatro mod. Face the Fear, Build the Future. Contribute to Mysthaps/LobotomyCorp development by creating an account on GitHub.
this context.drawing_cards block, replace the enchanted stuff with your edition check
Wondering how to properly remove the card after it hits the 1/4:
SMODS.Edition {
key = "burned",
shader = "burned",
loc_txt = {
name = "Burned",
label = "Burned",
text = {
"1 in 2 chance to give +5 Mult",
"1 in 4 chance to give X4 Mult",
"then be destroyed"
}
},
config = {},
in_shop = false,
pools = {},
weight = 0,
in_pool = function(self, args)
return false
end,
calculate = function(self, card, context)
if context.cardarea == G.play and context.main_scoring then
local roll = pseudorandom(pseudoseed('burned_roll'))
if roll < 0.5 then
return { mult = 5 }
elseif roll < 0.75 then
return {
x_mult = 4,
remove = true
}
end
end
end
}
local effects = {}
if context.main_scoring and context.cardarea == G.play or context.pre_joker then
if SMODS.pseudorandom_probability(card, 'burned_roll', 1, 2) then
table.insert(effects, {mult = 5})
end
end
if context.main_scoring and context.cardarea == G.play or context.post_joker then
if SMODS.pseudorandom_probability(card, 'burned_roll', 1, 4) then
if context.main_scoring then
card.modprefix_destroy = true
else
SMODS.destroy_cards(card)
end
table.insert(effects, {xmult = 4})
end
end
if context.destroy_card and context.destroy_card.modprefix_destroy then
return {remove = true}
end
return SMODS.merge_effects(effects)
do you guys know an example of how to add a new scoring window, ive been reading the documentation over and over again but i cant get it to work
There is example code that just needs your mod prefix adding into that still works afaik
o, where is that
chips x mult x something else
How can I check if a card has a seal, or if it has an edition
if card:get_seal() or card.edition
thanks <3
thx
does get_seal return a table or bool?
It returns the key of the seal that the card has or nil if it doesn't have a seal.
ight that works
would the lists of seals and editions be in G.P_CENTER_POOLS["Seals" or "Editions"]?
You can also do if card.seal
or not meaning the lua operator
not seals, they're not centers
G.P_SEALS iirc
thx
okay hopefully this works
wait minor stupid
tried to index G.P_SEALS lol
okay G.P_CENTER_POOLS["Editions"] is incorrect
thats working fine
its line 478 that's crashing
why that ?
the effect is to add a seal if it doesn't have one yet
oop
any idea what this should be?
You should use the poll functions
whats the arguments for that?
ive seen them but they wont show up with info from the lsp
nvm I got it
You just need SMODS.poll_seal({seed = "X", guaranteed = true}) and similar for editions
yay thats all the blinds done (except acorn)
Where could I find resources to learn how to make a custom UI page?
do you happen to know how to directly set the value of a custom scoring parameter, :modify only adds to it
thank you ❤️
trying to make a joker that gives mult when a debuffed card "scores", but i'm having issues. I have this, but no mult is being gained.
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
if context.other_card.debuff then
return {
mult = card.ability.extra.mult
}
end
end
end
self:modify((-self.current)+number)
Yes, debuffed cards don't score.
thx <3
Figured as much. I've tried some hooks and patches, but still nothing. Any other method I could try?
