#💻・modding-dev
1 messages · Page 122 of 1
Does anyone know what I did wrong?
use card instead of self
help me pls
its an issue with whatever your claimh.lua file is
you dont have a closing bracket
I'd recommend not using Notepad to write the code, as it will probably cause you a lot of unnoticed mistakes
^^
how to change deck's atlas
by using the atlas property
using the
SMODS.Deck:new("Anti-Mista Deck", "mista", {mista_hater = true}, {["atlas"] = "geriolish_1", x = 0, y = 0}, loc_def["mista"])
```method
hasnt the .Deck method been deprecated for the .Back one
Hey! Mind if i take some of your time for my issue regarding disabling discards when a specific card is selected? You absolutely dont have to but if you feel like it, id appreciate some help :)
Essentially, I'm pattern patching the G.FUNCS.can_discard method and want to check if a certain card in the selected cards has a specific key and disable the discard button accordingly without breaking other mods in the process.
These are my patches:
# Crowded Discard Disable
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = 'G.FUNCS.can_discard = function(e)'
position = 'after'
match_indent = true
payload = '''
local has_crowd = false
for i = 1, #G.hand.highlighted do
if G.hand.highlighted[i].key == 'crowd' then
has_crowd = true
break
end
end
'''
# Crowded Discard Disable
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''
if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
'''
position = 'after'
match_indent = true
payload = '''
elseif has_crowd then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
'''
and this is the original function im patching:
G.FUNCS.can_discard = function(e)
if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 then
e.config.colour = G.C.UI.BACKGROUND_INACTIVE
e.config.button = nil
else
e.config.colour = G.C.RED
e.config.button = 'discard_cards_from_highlighted'
end
end
Sorry, I haven't used lovely patches
That's alright, thank you for your time anyway 
Does anyone know how to make your mod load multiple lua files for each individual card?
Yall, is there a way to know when the wheel of fortune has failed?
I'm trying to trigger a joker off of it, but atm idk if anyone or any mod has already done this
I need to know
Require/import them?
Relative from the current file
It's a lua feature, so you can find it via that
I dont know, Im new to this
But I mean like I would have multiple lua files for each joker and I want the mod to load all of them
How would I do something like that
You can also look into using SMODS.load_file(filehere)().
oh huh
Also, NFS.getDirectoryItems(folder) might be nice, it returns a table with everything in a folder, but you'll have to set up local whatever = SMODS.current_mod.path because unlike SMODS.load, it doesn't automatically start off in your mod folder, so you'll have to include where to start.
NFS stands for Native File System, by the way.
Anyways, this
Does anyone know this?
There's definitely a way, and I think I remember seeing someone ask before, I don't remember what the way was though.
Don't know how good of a solution is is, but you could probably search up "The Wheel of Fortune" and make it call a calculate with a custom context provided,
hey guys, how easy is it to create the 52 cards with skins and upload them for myself?
( not the art part but the dev part )
hi, I'm trying to mod Balatro for the first time and I was wondering how I would go about adding more things (like for example a slider) to the games options menu (the "Game" Tab specifically)?
For context, I am trying to expand a mod called "IncreaseJokerCap" (by AkitaAttribute) (not for distribution, just for my own learning).
My current code looks like this:
table.insert(G.SETTINGS, base_jokers)
G.SETTINGS.base_jokers = 10
setting_tabRef = G.UIDEF.settings_tab
function G.UIDEF.settings_tab(tab)
local setting_tab = setting_tabRef(tab)
if tab == 'Game' then
local jCount = create_slider({label = 'Max Joker Count',w = 4, h = 0.4, ref_table = G.SETTINGS, ref_value = 'base_jokers', min = 1, max = 9})
table.insert(G.UIDEF.settings_tab, jCount)
end
return setting_tab
end
Every time I open the settings the game just closes without any errors. Why could this be?
you shouldn't really expand the game settings tab, it's bad practice
you should have a config tab for your mod instead
aight, thanks for the info
for the actual code here, what's wrong is that your inserting into G.UIDEF.settings_tab instead of the returned settings_tab
Wym? I need to hijack the existing use_consumable function for that, and idk how to do that
ok
where do i find the textures folder?
in my resources folder there are no textures
( im on macos )
You'd do that through a lovelly.toml patch.
Re-extract in case the extraction got interrupted, maybe? That's where it should be.
ill try yeah
7z Balatro.app
7-Zip [64] 17.05 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
p7zip Version 17.05 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,12 CPUs x64)
Command Line Error:
Unsupported command:
Balatro.app```
apparently i had to run 7z x balatro.app
https://github.com/Steamodded/smods/wiki/SMODS.Center#smodsjoker
https://github.com/Steamodded/smods/tree/main/example_mods/Mods/ExampleJokersMod
hm.
its essentially the card name, except in some cases when its a name for the kind of joker (such as the hand mult jokers)
I DID IT
? whats the ability here? 👀
lose a card slot permanently for this round for an upside
depending on how many slots are gone, the upside is better
disabling the discard and play button is just so you cant remove the card :D
You could do it directly; if you search the Steamodded code for that key you should find the code that does exactly that
Thanks!
programmer's art
i am rewriting this this is confusing
what's the mod that allows you to click on collection item to get it
use DebugPlus and then when youre in the collection you can hover over an item and press ctrl+3
wait how are you applying mult
how to ignore debuff from joker card?
why is it becoming 0 LOL
like if the boss blind debuffs the card, ignore it and calculate anyway
i thought i was smart in using Xmult_mod = 0 and using mult to set to the whatever mult i want
LMAO
that's like adding 1 then multplying by 0
this is why most jokers start at x1 mult instead of x0
it's supposed to start at 1
found it
it's
SMODS.debuff_card(card, 'prevent_debuff', card)
```this card prevents debuff by itself, making debuffs useless against this card
how to make perishable_compat on custom card to false
@spring lantern here you go
i could probably word it better
actually coding this isn't too bad apart from the lack of intellisense
actually i meant autocompletion
no
it just swaps the current mult with the store mult and gives x1.5
i meant for it to be at least uncommon
that makes more sense
I think it is too cracked
Ew
??????????
Wtf is that art lmao
The joker gameplay is good tho ggs
how to add unbreakable sticker? (successor of eternal sticker, attempt to replace/remove will not result that card be destroyed)
Isnt that already what eternal does
why do you need something higher than eternal

cryptid boss blind (specifically vermillion virus) can replace eternal card to something else
Well thats a problem of the mod
so basically this is an oddly specific sticker to counter one boss blind
Making a new sticker would not solve the problem tbh
Its just that the dev forgot that eternal was a thing or didnt make it a thing
probably intentional
If you want to fix that, you can take ownership of that said boss blind and make it not do its effect if eternal is on the joker
cryptid's boss blinds should not be your problem
You should make your mod based on vanilla experience
Like
Make your mod for people who use only your mod
is this a better programmer art
Yes
Still pretty black and white but
Better
programmer art
I got the wheel of fortune working, its a dumb hack:
-- This joker gains +1 Mult for every failed Wheel of Fortune
calculate = function(self, card, context)
if context.joker_main then
return {
mult_mod = card.ability.mult,
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.mult } },
}
elseif context.using_consumeable and not context.blueprint and context.consumeable.ability.name == 'The Wheel of Fortune' then
sendDebugMessage("Detected use of Wheel", "NijntjeCard")
local aimed_jokers = {}
for k, v in pairs(context.consumeable.eligible_strength_jokers) do
aimed_jokers[k] = v
end
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0,
blocking = false,
blockable = true,
func = function()
local succeeded = false
for k, v in pairs(aimed_jokers) do
if v.edition then
succeeded = true
end
end
if not succeeded then
sendDebugMessage("Wheel failed, adding mult", "NijntjeCard")
card.ability.mult = card.ability.mult + card.ability.extra.mult
G.E_MANAGER:add_event(Event({
func = function()
card_eval_status_text(card, 'extra', nil, nil, nil,
{ message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } } }); return true
end
}))
else
sendDebugMessage("Wheel succeeded, NOT adding mult", "NijntjeCard")
end
return true
end
}))
end
end
just go on the minecraft wiki and slap that bad boy on there /j
Fr
Or steal some texture pack stuff
(dont)
Sorry for the spam, just wanted to post the code here in case anyone from the future wants to do a funny thing after 
and the passive effect that runs along with love.main()?
what
an passive effect that runs no matter what
What for
that thing
Idk I don't even think you do that but
Yeah
i am going to make a spectral card just to spite that
Maybe just check if it was destroyed and if it was just spawn it back
remove any stickers but -1 hand and -1 hand size
Fr
eternally renting
is this Joker too strong
shouldn't it be -1 hand instead?
i am not a good player but -1 makes more sense to me
yea -1 makes more sense
anyway i feel like this has synergy with what i am making
for some reason
maybe
ill change the mult to 2
how to create consumable?
you love some programmer arrt
so like if my hand would score 10x30 and I havent scaled this yet it becomes 10x1?
yea
no scaling
lol I cant draw either
outright replace the mult
not saying i can't draw just that i want to focus on the function first
ah I see
cryptid already has absolute
create_card
kinda
absolute sticker?
can be cool if you somehow alternate between all chips and all mult
it literally just moves your mult in current to the next hand and x1.5
i changed it to x2
maybe too overpowered?
tho this technically discourage play to discard
is there a built in function for reloading the a GUI?
or is there some other way to update ui elements when a value is updated through some other means?
(example: a button sets a value, which can also be set by a slider, however the slider does not update to show said value).
How can I add a new property to the Card object with Hooks? Im doing it with lovely rn but maybe theres a different way
just add it to card.ability
this worked
is there a way to track chip and mult change lol
wdym
what do you need to do that for
because that's the effect i want to achieve
every time either one of them change trigger card effect
oops sorry i read that as why
trying to make this joker say it unlocks with black stake but localize doesnt wanna work
not sure if this is a locked_loc_vars glitch or something
pretty sure i put in the right key, which the value is "stake_black"
i think stake descriptions are in Other
the internal game code says this https://i.imgur.com/HZZS87O.png
okay I might be mistaken
yeah its weird
I hardcoded the description to say Black Stake and just used the colors but i imagine this may be an issue for other modders who arent comfortable with doing that
I'd like to request that someone narrow down this UI issue, because it's really weird, and I can't narrow down the issue any further, it's like the check that the toggle creates doesn't exist the second time arround. I've at least narrowed it down to this section and it's reproducible, but I don't know where to go from here.
The main thing, is that it works perfectly the first time normally, but if you reload the page in any way, interacting with the toggle causes a crash because it can't change if the checkmark is invisible or visible, even though it obviously exists, as, well, you can see it still.
How would I make a joker that makes blinds take less chips to beat?
And how would I change the scaling if you have a different joker in your inventory (goes from x0.5 to sqrt)
G.GAME.blind.chips for one blind, G.GAME.starting_params.ante_scaling for future blinds
im not sure about he scaling option
try looking at double scale from cryptid
can probably just change the required chips (TGTM already showed the var you need to change) during the setting_blind context
Would it just check all the jokers in the inventory and use a series of if thens?
For changing from half to sqrt?
what "scaling" are you talking about here?
I want it so that if you have a different joker in your inventory, instead of halving the required chips, it takes the square root
oh for the first joker you mentioned?
Yes
how do you add 1 hand for a round, like ease_discards? ease_hands doesnt work
within the first joker's calculate, probably iterate through G.jokers checking if card.label or card.config.center_key is what you expect
im so ingrained in control s, i do it when im messaging in discord 😭
ease_hands_played
also lol
no how do i watch for scoring change lol
like if there is a way to do it directly i'd like to know
I don’t believe there is in vanilla
run function every time the score changes
😭
hook to mod_chips and mod_mult?
how do i hook
function original_function()
return variable
end
-- your code
local function_ref = original_function
function original_function()
-- code that runs BEFORE the original function is called
local ret = function_ref
-- code that runs AFTER the original function is called
return ret
end
local ret = function_ref()
thats a lot of lines
You are going to love this solution:
remove the maxw = 2.5, maxh = 0.8, and it should no longer crash
Is that actually it
What the actual hell, thanks.
malverk broke
AltTexture({
key = 'suit_planets',
set = 'Planet',
path = 'classic_planets.png',
loc_txt = {
name = 'Classic Suit Planets'
},
keys = {
"c_cry_Timantti",
"c_cry_Klubi",
"c_cry_Sydan",
"c_cry_Lapio"
},
localization = {
c_cry_Timantti = {
name = 'Timantti'
},
c_cry_Klubi = {
name = 'Klubi'
},
c_cry_Sydan = {
name = 'Sydan'
},
c_cry_Lapio = {
name = 'Lapio'
},
}
})
TexturePack{
key = 'classic_planets',
textures = {
'cry_suit_planets',
},
loc_txt = {
name = 'Classic Planets',
text = {
'Revert planet name changes'
}
}
}
i have only 10 runes to go, but then i have to make them actually look nice (animations, sounds, etc.)
this might sound dumb but how do i make the card show triggger animation in hook
super weird that my pack doesn't apply cus it even shows the correct sprite in the texture menu, but it doesn't actually change anything
i think i am falling victim for the x y problem
i want a joker that watches if the score changes then adds +1 mult to itself every 2, 3, 4, ... times (the times needed increases every mult increases)
i got the times part but the watching score change is a bit more complicated than just card scoring i think
actually hold on lemme cook for a bit
how would i play a sound effect during a joker’s message display?
like a sound effect plays when that message is triggered to show up
no clue why it triggered twice
what would be the best way to remove cards from the entire deck
wrong video sorry
maybe it counts changing both of them as a different thing
i rly don't know lol
That is separated into cards in deck, cards held and cards played, technically. Though, I have this that destroys cards left in the deck.
thats alot of steel mikus
Okay im gonna ask this question again cuz im new to this stuff and i think i need to reword my question.
Im making a joker card that will flip the values of your mult and chips. However, im not sure how to do this, let alone put it within a joker card. Ive been searching through the wiki and source code and such but i cant seem to find and example of something like this. This is the code i have rn:
-- Flipped Joker --
SMODS.Joker {
key = "fJoker",
loc_txt = {
name = "Flipped Joker",
text = {
"Swaps Chips and Mult values"
}
},
rarity = 3,
atlas = "R3Jokers",
pos = {x = 0, y = 0},
cost = 8,
calculate = function(self, card, context)
if context.joker_main then
---SWAPPING CODE HERE
return {
message = "Swapped!"
}
end
end
}
Again, ive been searching through the wiki and cant seem to figure this stuff out. Id assume theres some way to get/set the current chip/mult values, but i cant find anything on this topic.
this is probably a patch thing
No, actually.
oh
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/cd64a554e94ca5e8705af16abe9b432f605c0673/togastuff.lua#L313 Have a look at one of mine that does just that, but for scoring cards.
is it not possible to just modify G.playing_cards(?)
or is that only one subset
Or... well, I guess that may contain all the cards, not sure. Head empty, no thought.
seems like it does? ig ill try
Im not very good at reading balatro mod code yet. Does that code flip the values for the hand played?
Can you send me this in dms? Can investigate for you
hand_chips and mult are global variables for currently scored chips and mult, respectively. mod_chips and mod_mult assign values and update_hand_text reflects the changed variables on HUD.
when a joker is being added to the deck, how to check if its full or not?
G.jokers.config.card_limit for actual Joker slot limit, #G.jokers.cards for amount of Jokers held.
Ahhh okay. So this is what ive been looking for it seems. Thank you, this stuff is really confusing to me.
thanks
don't forget joker_buffer or whatev, might want to check Riff-Raff's code
SMODS.eval_this(context.blueprint_card or card, {
chip_mod = card.ability.extra.chips,
message = localize{
type = 'variable',
key = 'a_chips',
vars = {card.ability.extra.chips},
play_sound('hpfx_thumbsup')
},```
i thought something like this would have worked, but the sound always seems to play BEFORE the message, when i need it to play WITH it
then you play the sound while creating the message
I don't think the docs are updated, but in the latest steamodded you should be able to return a sound
(based on #1209564621644505158 message)
let me try that out then
sent
something like this should work right?lua if context.end_of_round and context.game_over then local steel_cards = {} for k, v in pairs(G.playing_cards) do if v.config.center == G.P_CENTERS.m_steel then steel_cards[#steel_cards+1] = k end end if self.ability.steel_cards == G.GAME.round_resets.ante then for i=#steel_cards, 1, -1 do G.playing_cards[i]:start_dissolve(nil, i ~= #steel_cards) end [more code here] end end
why is it superbuffing the joker help
whatever it is overwrites the preexisiting mult-chips i had set
Is anyone able to help me make a single custom Joker? I have no experience whatsoever, but I already made the Joker art and I know what it will do. I just want myself as a Joker.
someone left debug stuff in
that was me
-# ik
it wont break anything if i take it out will it
Playing on a branch is something new
i went too new 😔
Nope, it was just there for testing purposes
Didn't notice I committed that lmfao
oh phew lmao
truly on the bleeding edge
just wondering if there is a way to change the mod name tag colour?
You able to help me? Sorry if you didnt want to be pinged, I don't know who does and doesn't know stuff around here and it seems you have created something before
you can have a badge_colour in your mod's metadata
as in, in the steamodded header? or in a seperate metadata file
ahh ok ty
I suggest you switch to json metadata
Is anyone able to help me make a single custom Joker? I don't know how to do anything, all I know is I want a Joker that starts with xMult and then adds xMult to itself when a High Card is played
steamodded header uses BADGE_COLOR but header is also outdated
I have the art for it
but this is also supported in headers
hold on I can help you, just lemme get back to my desk
Bet, you're a g
https://github.com/Steamodded/smods/blob/main/example_mods/Mods/ExampleJokersMod/ModdedVanilla.lua
using this as a point of reference can also help
aight i'm here
i can call if you want, whatever works for you
That works
I found this in the emplace logic and... is it possible for a non-joker to end up in G.jokers.cards? 🤔
hm i've followed this and its still not changing..
Hey, I'm trying to get a simple "if current hand score higher than the blind's goal score" function to work, but trying to "if hand_chips*mult >.." gives me an error about trying to do arithmetics with global hand_chips- Any idea how to make it work?
what is the specific error?
Gonna screenshot real quick-
probably
ah well ill keep trying after i make some food
It's not a joker admittedly
It's a voucher that gives you 5$ if your current hand reaches higher than the goal's score, so an overkill/one shot type of deal
It has been a bit complicated since it's not a joker admittedly lmao but little by little I managed to make it work, at least the basic functions of it- But now I'm stuck with this last part
Here is the function that hosts the hand_chips * mult condition, which is what just kinda breaks
"overkill_bonus" is just turned to true when the voucher is purchased
-# i
-# forgot to ask where it's kept
better_calc.toml, lines 206 to 233
right thanks
yeah, in very old version jokers and consumables shared same card area
i should
not have done that i think
yes
hello yall
hey
Did you just straight delete it?
i deleted one line i should not have
i fixed it
works properly without the 20buff now
I mean in a natural way
interesting 🤔
Is it possible to generate a random number within a certain range that's also seed-based
I'm trying to make a roulette, and I wanna be sure it always hits something
im going to go insane
for some reason my mult is being set to 0 before each scoring?
im trying to add a card that saves you (like mr bones) and it works perfectly so all i need to do is find out how to change One line of text (the "Saved by Mr. Bones" blind ending text)
i think this is going to require at least one patch
oh hey i figured it out
oh this is just a general thing ok
i think this is plenty OP
can it disable itself
no
is there a context for starting the round
banned from scoring ig
scoring is now illegal 🗣️
steamodded branch,,,,,
is the joker fair
lmaowut
if you are cracked at this game you can try soloing this card
i guess it works but not practical
is there a way to make a consumable make a joker both a specific edition + put a sticker on it at the same time?
i assume its not too bad right?
Change the edition then add the sticker
for stickers, the Card:set_eternal, Card:set_rental and Card:set_perishable methods exist
i was going to try make a shader that was a border+icon PNG and a gradient but that seems too hard to do? so my solution is the gradient plus a custom sticker
dunno if im overthinking it here but thats what i've landed on
I think making the shader do both is overthinking
a shader for me atm looks like a really daunting task to do, but i want to make this edition for my cards
guess its back to aseprite for a custom sticker LOL
Is there a way I can check if a Joker has changed position in the Joker area as I drag it?
what are you trying to do?
for example if a Blueprint is to its left then the Blueprint would be destroyed
I was wondering that the other day. Afaik there's no built-in method that gets called when that happens, but I just use the joker's update method (called every frame) and loop through each card in the jokers card area until you find your current card
I would porbably just check the card to the left when you do calculate
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
position = i
end
end
oh ty, what do you mean by joker's update method?
anyone know a joker that works like abstract
If you scroll down to the list of methods for centers, one of them is called "update." it gets called every frame. You can just define your own version of it when you define your joker
isn't abstract just +mult for every joker you have?
you can just do your counting inside your calculate and loc vars functions
Realistically I doubt it. Even if you did something crazy and got like 20 jokers, you're looping through 20 things per frame. Not hard for your computer to do at all
update does run every frame so it can cause performance issues if you do a lot, but it's probably not a big deal
I'd be worried if that number exceeded 100 maybe
yeah
im tryign to make a joker that gives xprobability based on how many jokers there are
thank you both 🫡
I'll test it asap
#G.jokers.cards gets your current number of jokers
I was thinking it might be possible to make a "lazy_update" that only triggers at a few times, such as, before calculation, before rendering ui box, etc.
might be handy
z`yeah i know that but i need context
just look at how abstract works
i did but its context is just "else
Can you elaborate on what context are you looking for? When do you want this to trigger?
I dont knwo thats why im here
probably joker_main
i was like an oops all sixes when jokers are in the tray
I see, so you want all probabilities modified
i tried doing that
I'm confused now
i want a joker that can dynamiclt increse / decrese how much probabilti it is based on how many jokers
atlease how can i check if any joker is added or removed from deck
probably update makes the most sense
or from the tray
oops uses add_to_deck
but yours changes
I guess you could hook Card:add_to_deck and Card:remove_from_deck
isnt that for that card
Jokers count as cards, you just need to check if the card being added is a joker or not
Here's the code for oops all 6's:
When you first get it:
for k, v in pairs(G.GAME.probabilities) do
G.GAME.probabilities[k] = v*2
end
When you lose it:
for k, v in pairs(G.GAME.probabilities) do
G.GAME.probabilities[k] = v/2
end
So you would just replace that v*2 with whatever way you want to manipulate the game's probabilities
And trigger that whenever you gain or lose a joker
For future reference, if you open card.lua in Balatro's game files, you can search for the name if the joker you're interested in and see how it's been implemented in the real game
ive got this calculation code for a joker, and everything seems to be working fine. The only issue is that the messages colors are all orange. How do i change the color to make it red for the mults and blue for the chips?
calculation code:
calculate = function(self, card, context)
if context.joker_main then
if pseudorandom('NerdyJoker') < G.GAME.probabilities.normal / card.ability.extra.cc then
if pseudorandom('NerdyJoker') < G.GAME.probabilities.normal / card.ability.extra.mc then
if pseudorandom('NerdyJoker') < G.GAME.probabilities.normal / card.ability.extra.xc then
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.extra.xmult } },
Xmult_mod = card.ability.extra.Xmult
}
end
return {
message = localize { type = 'variable', key = 'a_mult', vars = { card.ability.extra.mult } },
mult_mod = card.ability.extra.mult
}
end
return {
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } },
chips_mod = card.ability.extra.chips
}
end
end
end
add colour = G.C.WHATEVER to the return table
e.g. G.C.CHIPS or G.C.MULT
also chips_mod should be chip_mod
thanks
your nested if's cause me pain
i mean its not even close to the monstrosities committed by local thunk
ikr
lol
also, is there a G.C.XMULT? or would it just be G.C.MULT for both mult and Xmult
nervously looks at card.lua
the latter
I dont have the best coding practices... this just seemed slightly more correct in my brain lol
a better way would be to use elseifs
Is there documentation anywhere for all the possible flags that can show up in context? Because I don't think the Joker Calculation page on the smods github shows them all
ill edit it to that, that definitely makes more sense
it's incomplete with respect to better calc / retrigger api
we should update it soon-ish
Is there a simple way to take ownership of all jokers to make a global change?
don't think so
like what
what do you want to do?
Anyone think i should change these values?
not sure X3 mult may be a bit much
x3 mult is wildly stronger than the other values, yeah
currently theres a 1/7 chance that it actually gives X3. But yeah maybe 2X or 2.5X?
the mult has a 2/7 chance also\
and the chips 4/7
I was thinking the most direct way to implement a certain joker feature was to make every other joker check something when it stopped being debuffed, but I decided against it
what feature
also jokers know when they're buffed
thought i should buff the other values cuz they felt a little weak for an Uncommon joker. But i also nerfed the Xmult
I think 5 Chips is worth about 1 Mult
so should it be 7 mult?
Not necessarily
I was thinking more like 50 Chips, but this card does multiple things so you can adjust where the power is
just realised i was calculating chances wrong and so i was getting more XMults than i thought i should
this did not work
Im trying to add 4 bucks when discarding a face card and it shows a yellow square. I dont know how to fix this issue. Is it just colour = G.C.MONEY ?
idk how to compress the message so its not a wall of text. If someone knows, Ill just dm my code if there are issues
just send it
SMODS.Joker {
key = 'Foxy',
loc_txt = {
name = 'Foxy the Fox Pirate (RAWR)',
text = {
"Gain {C:money}$#1#{} each time",
"you discard a {C:attention}face{} card"
}
},
config = { extra = { money = 4 } },
rarity = 2,
atlas = 'AthensBaltro',
pos = { x = 5, y = 0 },
cost = 6,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.money } }
end,
-- Evaluate bonuses for each discarded card
calculate = function(self, card, context)
if context.discard and context.other_card then
-- Ensure the other_card exists and is a face card
if context.other_card:is_face() then
local bonus = card.ability.extra.money
if bonus > 0 then
return {
money_mod = bonus,
card = context.other_card
}
end
end
end
end,
-- Provide the total dollar bonus at the end of the round (SMODS-specific hook)
calc_dollar_bonus = function(self, card)
-- Default to the configured extra money value
return card.ability.extra.money
end
}```
```lua
put your code in between this so it looks nice kthx
```
this ^
guys what is colour required in
thanks
why are you also trying to add the money at end of round
change money_mod to dollars + i think you need a message
colour = G.C.MONEY for the color
Alright what am I missing lol
Progress has been made, but i'm taking a break for now
how should i phrase this so that its less confusing
Iron Savior: Prevents death, destroy 1 random Steel Card for each Ante
the actual function feels pretty simple (if youre on Ante 10, itll destroy 10 steel cards [if you have that many]) i just dont know how to phrase it
Prevents death and destroys up to #1# random Steel Card(s) | Increase cards destroyed by 1 when Boss Blind is defeated
ohhh true i forgot variables exist
How would i manipulate the pool flag of existing cards. basically i want to make a deck in which all planet cards are secret, only showing up once you have played them. this is strong so ofc ill add some negative as well such as -1 joker slot.
but ye, how can i make all planets cards secret; only add to pool after play?
am i just an idiot why did this not work
if G.jokers and card.added_to_deck then
for k, v in pairs(G.GAME.probabilities) do
G.GAME.probabilities[k] = v*card.ability.extra.odd_change
end
end
if G.jokers and card.remove_from_deck then
for k, v in pairs(G.GAME.probabilities) do
G.GAME.probabilities[k] = v/card.ability.extra.odd_change
end
end
end,```
i have no experience with the update function so im not sure. but can G.Jokers and add/remove be true at same time?
this absolutely should not be in the update function
Fanta
Adding to the if statement by adding an elseif
Gonna bump this since it's not night time anymore lol
My best guess is I’m using the wrong variable for deck size? If that’s so then idk what the correct one would be
youre computing card_limit - 52
abandoned deck pop off!
which cascades through the entire function
isn't this literally 3e * -0/1000 if you have default deck size
which evaluates to negative zero
also G.deck.config.card_limit can be funky
you probably dont want the -1 * and you probably also want to add some base value like 1
you should use #G.playing_cards
the deck card limit doesn't update when adding cards in a blind until they're shuffled back into the deck
also this
how do i change the color of text in the joker description to match a suit color?
see castle in the example jokers mod
Found it, thanks
This is how I'm coming up with the equation btw
f(x) = the mult it should be giving
and if f(52) then it should be 3
youre missing a power
between math.exp(1) and the rest of the equation where you have a multiplication
thats supposed to be a power
I can’t believe I didn’t realize that was supposed to be a power. Thank you
id still recommend adding a +1 to the equation though (and reducing scaling by 1 if you want to keep the cap at 3x)
its not unfeasible to hit 86 cards at which point your card starts getting worse than 1x
does anyone know if there's a way to trigger a joker ability when a played card is retriggered (due to either a seal or a joker preferably, but if just jokers that's fine)
What exactly does the pseudorandom function output? Trying to make a roulette with some random outcomes
if it's just given a seed, it returns a double between 0 and 1
if you give it a min and max values, it returns an integer within those bounds
Epic 👍
There we go lmao
woop woop
only problem now is it crashes when viewing from collections on the menu cuz there's no fallback for #G.playing_cards
store that into local var, if not exist set to smth else
trigger_effect = function(self, args)
-- all jokers are negative and rental
-- on joker creation (be that shop or pack or other):
-- apply negative and rental
end
how do i in deck.trigger_effect access when joker are created?
printing(args) was unhelpful
How can i change the maximum joker variable? Or really what im asking is what is the variable if it is there
i got u
apply = function()
G.GAME.starting_params.joker_slots = 0
end,
I wish I could help but I have done nothing with decks yet lol
aww shucks
ignoring deck, do you now how to get args/G/context of joker creation?
Off the top of my head I do not
I am very confused, the joker doesn't show up in the collection of jokers, am i missing something?
--- STEAMODDED HEADER
--- MOD_NAME: Yonka-Card
--- MOD_ID: Yonkagor
--- MOD_AUTHOR: [Flote]
--- MOD_DESCRIPTION: Adds Jokers based on the Yoncats
----------------------------------------------
------------MOD CODE -------------------------
local MOD_ID = "Yonkagor"
local jokers = {
Seadrive = {
name = "Seadrive Joker",
slug = "Seadrive",
config = {
extra = {
mult = 4, -- Updated for Joker 2
}
},
spritePos = {x = 0, y = 0},
loc_txt = {
name = "Seadrive",
text = "{C:mult}+#1# {} Mult"
},
rarity = 1,
cost = 2,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
functions = {
loc_def = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
calculate = function(self, context)
if context.joker_main then
return {
mult_mod = self.ability.extra.mult,
message = localize {
type = 'variable',
key = 'a_mult',
vars = { self.ability.extra.mult }
}
}
end
end
}
}
}
im holding everything together by tape
to define a joker you need to call SMODS.Joker
you need a key for your joker
loc_def should be loc_vars
loc_vars and calculate need to be in the main table
yes this^
you're piecing together stuff from code made for old old steamodded^
also please use the new header format
my apologies, thank you
-# though this was still the more convenient way to write code for 0.x steamodded compared to doing direct arguments
the frick is ```lua
SMODS.Joker:new(name, slug, config, spritePos, loc_txt, rarity, cost, unlocked, discovered, blueprint_compat, eternal_compat, effect, atlas, soul_pos)
the fuck!?
-# we don't talk about 0.x APIs
not enough arguments. needs more
like perishable_compat
if context.type == 'store_joker_modify' then
_context.card.temp_edition = true
self:yep('+', G.C.DARK_EDITION,function()
_context.card.temp_edition = nil
_context.card:set_edition({negative = true}, true)
_context.card.ability.couponed = true
_context.card:set_cost()
G.CONTROLLER.locks[lock] = nil
return true
end)
_applied = true
following is in tag.lua. gotta work out how to apply to my deck
tags get an apply function
signature (as per docs) is apply(self, tag, context) where self is the tag's prototype as always, tag is the Tag object as referred to as self in the snippet you sent above, and context is.. well, context
how to make a joker give mult for every scoring glass card?
i know, i am looking at tag. im asking how to have my deck trigger this when back has no apply function, and that wouldnt even work, for this isnt when the deck applies, but when jokers are created in shop
oh i didn't see the bottom part
you should be able to patch into create_card_for_shop to send a Back:trigger_effect with the same context
then you can use a trigger_effect function in your deck to catch that
my bad
oh no, how do i patch? i thought i would only need the back:trigger_effect
do back effects get the same contexts as tags?
they dont even get context, only self, and args
what's the fix to the attempt to concatenate global 'i' (a nil value) crash? it's something to do with the state events file
this has been my biggest gripe, the diff functions get diff vars. context/G/args each contain a lot but different things, and which you have access to can determine whether your creation will be easy or hard 😅
args is also a context-type table
?
i might have used this wrong. Im attempting to make a joker that takes up two slots (Really it just does the opposite of a negative card) Heres my code if you see an issue with it, because right now the joker slots stay the same.
code:
add_to_deck = function(self, card, from_debuff)
G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots + card.ability.extra.ajoker
end,
remove_from_deck = function(self, card, from_debuff)
G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots - card.ability.extra.ajoker
end,
they don't
but they should
you previously said starting slots, which is different to mid game alteration, or not. i missread 😅 sorry
G.jokers.config.card_limit = G.jokers.config.card_limit + 1
oh lol. Thanks.
how to add a cryptid enhancement deck for a custom enhancement?
wdym?
if the call to trigger_effect is added, it can just pass the same table that tags would receive as context as args
or, variable names are arbitrary and there's nothing wrong with calling the deck argument context too
are you saying i can do this:
trigger_effect = function(self, args)
print(context)
print(args)
end
no
What should it be
I'm saying you can do trigger_effect = function(self, context)
add_to_deck and remove_from_deck
ill try that later. for now im pivoting
But isn't that for the card itself
I want it to detect other Jokers getting added/removed
I'm not saying that does anything, it just doesn't make a difference
throw it in calculate then
we can add the tag contexts for decks into steamodded i think
Ok how would I do that then
use context.buying_card and context.selling_card
But that's buying and selling
I want destroying to count too
or hook add_to_deck and remove_from_deck
if you put it in update, every card will increase it every frame
-- Green Joker
SMODS.Joker:take_ownership('Green Joker', {
config = { self.ability.extra.hand_add = 2 }
})
what am i doing wrong here? this crashes complaining about the = should be }
first time attempting take ownership
key is 'j_green_joker' first of all, take_ownership doesn't accept names
ahh
second that's not valid syntax
specifically this ```lua
config = { self.ability.extra.hand_add = 2 }
aight, what is?
should be this ```lua
config = { extra = { hand_add = 2 } }
my bad, needs to be this
i should know the config structure of groker at this point
all i know is that in the games code
elseif self.ability.name == 'Green Joker' then loc_vars = {self.ability.extra.hand_add, self.ability.extra.discard_sub, self.ability.mult}
and i want hand add to be 2
hypotheically, can i run the SMODS.Atlas and change the photo for each card or do i just need one big photo with all the cards
ok, thats working, guess i just need to also specify the discard. i should be able to work that out. thanks for the help 🙂
you can have an individual atlas for each card. it creates a bit more overhead but shouldn't be too bad
okay, just checking bc it makes my life easier
to be sure, the Atlas and joker's Atlas should be the same
yes
thanks
getting this error and i dont know why
line 55:```lua
local rchance = pseudorandom('NerdyJoker') * card.ability.extra.c
card.ability.extra.c is nil
do you need self. in front?
How do I hook
line 45 is where i defined it: ```lua
config = { extra = { chips = 50, mult = 10, xmult = 2.5, c = 10, mc = 2.5, xc = 1 } },
lemme check
everywhere else i did card.ability.extra it worked fine
huh
did you start a new run or reload an old one?
reloaded an old one
try starting a new one
pretty sure config doesn't reset when you reload a run for... obvious reasons
oh ye, i just ran into that myself
how do i change enchancements of cards?
how do i do the gray text, for example how Judgment Tarot Card has (Must have room) on it
Better Calc 2 bugfixes have been merged yea
nope, not yet
aww
There might be but no more critical issues at least
it wasnt done yet when i last checked a few hours ago
I think all the issues from now will be stuff like message and juice up placements being wonky
well thats why i noted 'new' cuz ive been checking often
is there a page on the wiki for the custom color text for the mult and chips
I'll type up some new docs for it tomorrow
i remember seeing it but i dont know where
in localization texts?
yea, like a list of these, {C:mult}+#1#
oh wait
im blind
but for that, is there a name for the grey text
i know the Judgment Tarot card has it for the "Must have room" section
I think they're at globals.lua:345?
anyway that one exactly is {C:inactive}
ohh, thank you very much
you can also just search through localization/en-us.lua and you should be able to find all the ones Thunk uses
oh right, didnt think of that
made this game-breaking joker
i made a funny challenge
amazing how one line of text can completely change everything
does this seem too OP?
that does the same as another mod
bruh
rlly?
i cant remember the name and ive uninstalled and installed stuff too many times
but theres one that takes an extra slot and gives x2 mult iirc
'
i see theres a way to see what PokerHand the player played but is there a way to see what jokers to player has
okay
its been a while since ive used Lua, It crashes whenever i press M
SMODS.Keybind{
key = 'CheckJokers',
key_pressed = 'm',
action = function(self)
sendInfoMessage(G.jokers.cards, "Yonkagor")
end,
}
What's the stacktrace for the crash?
That's crazy cause I'm referencing it a bunch for one of my jokers
it doesn't exist all the timne
so wait, how do i check what joker the player has
like on the title screen
What's the context where you're pressing m? Is it on the title screen or during a run?
G.jokers is uninitialized, which is while you're getting an error
is it a different error?
let me double check
oh yeah it seems sendInfoMessage doesn't like tables
oh right, i should convert that to a string
also if you are just testing code you may want to checkout DebugPlus's eval command
I kind of want to try to keep it as "Vanilla" as i can
for development of stuff?
yea :3
to check, this should work, yes?
SMODS.Keybind{
key = 'CheckJokers',
key_pressed = 'm',
action = function(self)
local temp = G.joker.cards
sendInfoMessage(table.concat(temp, ", "), "Yonkagor")
end,
}
it didnt
tprint or inspect are probably what you want
okay
Print() also accepts tables but it will probably truncate it
me reading the smods example mods and theyre literally just wrong
which one
yup, that's too many jokers (1332/9)
anyway i'm gonna use vaccum cleaner to get rid of fork bombs
can you tech me the commands sir wizard. ive only been using the tab menu and print outs. didnt know any commands
there is a help command
oh nice
They're mostly less useful than the tab menu sadly
Yeah I should watch, it would save a lot of time I'm sure
I also want to see if I can make watch joker work with any type of center
eval is very helpful thx
is there any doc that outlines the entire object trees of G, args, context?
there is so much simply printing/evaling any is too much
context is documented
running inspect(value) may result in something a bit more graspable
the seal example mod puts the name and text locales in a description variable which doesnt work lol
Does anyone know if there is a way to apply a plasma-like effect using a joker? Looks like the current mult and chips aren't part of context
I just patched into it
adding a few & gave my seed searcher a 50% speed boost lmao
yeah that's probably what ill have to do. been avoiding that because i have zero idea how to do that but time to learn
this is the relevant part of the patch
[[patches]]
[patches.pattern]
target = "back.lua"
pattern = "if self.name == 'Plasma Deck' and args.context == 'final_scoring_step' then"
position = "at"
payload = '''
if (self.name == 'Plasma Deck' or calculate_balance()) and args.context == 'final_scoring_step' then
'''
match_indent = true
overwrite = true
Where's the documentation for context? I've been gleaning info about it from the joker scoring page on the smods github
hi all!
how do i make a joker move when a card triggers it?
i tried to recreate code from the example mod jokers' walkie talkie 2, but the actual walkie talkie wiggles when the +10 chip +4 mult triggers, while the example mod doesn't, any advice?
card:juice_up(0.5, 0.5) iirc
https://github.com/Steamodded/smods/wiki/Guide-‐-Joker-Calculation and #1247703015222149120 (I think the ladder is mostly in the former)
just had that same problem, pretty sure the problem is that the return should have card = card, not card = context.other_card
thank you so much! this worked perfectly!
sorry if this is a stupid question since i have no experience with patching yet: with this, do you then just patch in a calculate_balance function which checks if a certain joker is held?
more or less yes
ok perfect thanks
how to not activate consumable during rounds? (activating the consumable that activates booster pack during blind causes to freak out like this)
for example:
can_use() returns false during round, active pack
can_use() returns true during shopping, etc
you're looking for a context i think, though i don't actually know what the specific context you want is called
no, for example:
can_use() returns false during round, active pack
can_use() returns true during shopping, etc
yes
you want can_use to check the context
Is there a way to check if any discards have been used at the end of the round? im making a joker that does something based on this and im not sure how you check
check delayed gratification
how do i do that?
unzip the game's .exe file to get the source code, them look through it to see how delayed gratification does the thing
do you know what file joker code is stored in?
working on my first joker... how do I make x2 look all fancy like with other xmult jokers?
in the text for the description you can put {X:mult, C:white} before the number then {} after
like "This joker gives {X:mult, C:white}X10{} Mult"
excellent
while I'm here I might as well ask how to pick a card from deck The Idol style
i think theres some example jokers on the wiki for both checking rank and suit
hold on lemme find it
check walkie talkie and castle i think
that folder doesn't exist apparently
weird, i clicked the link and it also say that
did the example mods just disappear?
https://github.com/Steamodded/examples Example Mods moved to here
oh so this like just happend
i was confused with the fact i still had a tab open to it
aight this should be good food to get most of the way to this joker then
Someone know where i can find the code for delayed grat? i could only find something that said Effect: "discard dollars" but didnt have the code for it.
nvm i found where the ability code is at
oh my gosh how do i supposed to fix that thing
SMODS.Consumable {
key = 'spectral_dumber',
set = 'Spectral',
loc_txt = {
name = 'Spectral Pack Ticket',
text = {
"Use this card",
"to get free",
"Spectral Pack",
}
},
rarity = 4,
atlas = 'geriolish_1',
pos = { x = 0, y = 1 },
cost = 78,
use = function(self, card, context, copier)
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.15,
func = function()
local key = 'p_spectral_normal_1'
local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2,
G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true})
card.cost = 0
card.from_tag = true
G.FUNCS.use_card({config = {ref_table = card}})
card:start_materialize()
return true
end
}))
return true
end,
can_use = function(self, card)
return not G.GAME.blind.disabled
end,
}
```this thing breaks too much
so I'm trying to make sense of the very bottom of Castle 2's code... is it basically "extending" Game.init_game_object and SMODS.current_mod.reset_game_globals?
Im attempting to make my own legendary joker that gains X0.5 mult at the end of the round if no discards were used, but everytime it scores it just say ERROR on the message, and at the end of the round, it crashes the game. Im getting this error message too:
heres my code for the joker:
SMODS.Joker {
key = "roland",
loc_txt = {
name = "Roland",
text = {
"Gains {X:mult,C:white}X#2#{} Mult after",
"defeating blind if no",
"discards were used",
"{C:inactive}(Currently {X:mult,C:white}X#1#{C:inactive} Mult)"
}
},
config = { extra = { xmult = 1.0, gain = 0.5 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, card.ability.extra.gain } }
end,
rarity = 4,
atlas = "R3Jokers",
pos = { x = 4, y = 0 },
soul_pos = { x = 4, y = 1 },
cost = 14,
blueprint_compat = true,
calculate = function(self, card, context)
if context.joker_main then
return {
Xmult_mod = card.ability.extra.xmult,
message = localize { type = 'variable', key = 'a_Xmult', vars = { card.ability.extra.xmult } },
colour = G.C.MULT
}
end
if context.end_of_round and G.GAME.current_round.discards_used == 0 and not context.blueprint then
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.gain
return {
message = 'Upgraded!',
colour = G.C.MULT,
card = card
}
end
end
}
Anyone know what this is?
i sorta partly copied alot of it of the wiki
okay so i fixed the error text in the message but it still crashes
bringing back a demon from the past
Ah hell nah
anyone wanted to play on the pre-1.0.1 stakes post update?
no?
partitally fixed with AddTag
key = 'spectral_dumber',
set = 'Spectral',
loc_txt = {
name = 'Spectral Pack Ticket',
text = {
"Use this card",
"to get free",
"Spectral Pack",
}
},
rarity = 4,
atlas = 'geriolish_1',
pos = { x = 0, y = 1 },
cost = 78,
use = function(self, card, context, copier)
--[[G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 3,
func = function()
local key = 'p_spectral_normal_1'
local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2,
G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true})
card.cost = 0
card.from_tag = true
G.FUNCS.use_card({config = {ref_table = card}})
card:start_materialize()
return true
end
})) ]]
add_tag(Tag('tag_ethereal'))
return true
end,
can_use = function(self, card)
return not G.GAME.blind.disabled
end,
}
Anyone?
huh did you know the logic for booster packs costing more per stake is still in the game
i didn't
what i'd do is look at the lovely dump to figure out where it crashed
where do you find the dump?
%appdata%\Balatro\mods\lovely\dump
it's a copy of the game's source tree with lovely patches applied
how to get every card?
i checked and found this:
for ii = 1, #effects do
--if this effect came from a joker
if effects[ii].card then
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = (function() effects[ii].card:juice_up(0.7);return true end)
}))
end
--If dollars
if effects[ii].h_dollars then
ease_dollars(effects[ii].h_dollars)
card_eval_status_text(G.hand.cards[i], 'dollars', effects[ii].h_dollars, percent)
end
--Any extras
if effects[ii].extra then
card_eval_status_text(G.hand.cards[i], 'extra', nil, percent, nil, effects[ii].extra)
end
end
but im not quite sure why it thinks that the ii variable isnt a number considering its set to 1
wait
yeah im stummped
i made it but unstable
SMODS.Consumable {
key = 'popbob',
set = 'Spectral',
loc_txt = {
name = 'popbob',
text = {
"Use this card to",
"get every cards",
"(including modded ones)",
"to your deck",
}
},
rarity = 4,
atlas = 'geriolish_1',
pos = { x = 0, y = 1 },
cost = 78,
use = function(self, card, context, copier)
G.E_MANAGER:add_event(Event({
func = function()
for h,_ in pairs(G.P_CENTERS) do
local card2 = create_card('Jokers', G.jokers,nil,nil,nil,nil, h)
card2:add_to_deck()
G.jokers:emplace(card2)
card2:start_materialize()
end
end
}))
add_tag(Tag('tag_ethereal'))
return true
end,
can_use = function(self, card)
return not G.GAME.blind.disabled
end,
}
you should probably check if the set is Joker
here is balatro after i used popbob
didn't expect to be that strong
Someone help me here, im drowning in lines of code that im too dumb to understand! I cant fully tell if the issue is on smods end or my end
YOOOOO I FINALLY GOT IT TO WORK
To think it was just because i needed to redownload smods
bruh
its scaling the card 7 times 😭
got it working fully finally
How does one start modding Balatro?
ive got this whole customer service thing--
ok quick question
- Are you wanting to make a mod, or download one?
- Do you have Steamodded installed?
1, make.
2, Yes, because mods are fun.
Not quite sure which version, admittedly.
Well, which I have installed.
ok cool!!
To start, you should look at Steamodded's example mods, there's a bunch for whatever types of things you wanna make (poker hands, jokers, decks, etc.)
Then we can look at the wiki for more specific things like what centers are in the first place
you can see in the main menu of balatro
top right
the latest version of steamodded has a breaking calculation change that not many mods have adapted to
so you should get the old_calc version: https://github.com/Steamodded/smods/archive/refs/tags/old-calc.zip
just wondering what changed
thats good, you could go to old-calc for alpha-1304a for the latest non-broken version
but youre mostly fine ngl so
i think youre good to start making your mod
any questions about making the mod go here
and you can make your own #1209506514763522108 post for the mod
thats like
more of an uncommon/common or smth to me
though do take more opinion before changing it
def not legendary material though
also how do all of you get the legendary background art
like the lines
the idea came from someone on steam. Attempting to follow the whole historical jesters theme with legendarys
I go to the games source files and get the jokers.png
there you can just copy and paste anything you want to work off of
ah ok
i havent extracted the exe yet so
i probably should ngl
thx
rat? i was a rat once. they locked us in a room. a rubber room with a human. and human makes me crazy!
that aside i thought the art said poland
P.oland to be exact
i see that now that you mention it
maybe i should thicken the R's line there actually
every time i hear Roland i think of the musical instrument manufacturer
oooookay so i tested it out and it definitely feels like legendary material. It just needs you to have a bit of mult and its great\
how can i apply sticker(rental) to a joker?
oh hello zero
joker:set_rental(true) maybe? not sure, I'm looking at some other mod's code
trigger_effect = function(self, args) -- can maybe do self,context? says john smods
print("-----------------------------")
if args.buying_card and args.card.add_to_deck and args.card.ability.set=="Joker" then
-- print(args.card.label) --key
-- print(args.card.edition.type) --string
args.card.set_edition({negative = true}, true)
making negative isnt even working :/
I also had a q - is there some way to create a global listener type thing, essentially getting calls to calculate but not tied to having a particular joker, so that I can manage global variables in the background whether or not a particular joker has been bought?
that worked! and my set edition worked once i changed . to :
however this is only working on jokers from shop and not packs :/
this is how i listen to the calculation 😭 it's janky
mmm what's the particular joker in this case
hi
woo!
the joker activation seems a bit
too complicated
so i went with the non original route and
trigger_effect = function(self, args)
-- working with cards from shop but not from packs
if args.card.add_to_deck and args.card.ability.set=="Joker" then
args.card:set_edition({negative = true}, true)
args.card:set_rental(true)
print(args.card)
end
end,
Any idea how to trigger this on jokers bought from packs?
well thats interesting. the jokers do no spawn as negative or rental, they only become it when bought, and only from shop, pack jokers dont get the changes.
however... a non affected joker when sold gains negative and rental as its sold, during the animation ... 🤔
so add_to_deck triggers upon selling ???
so do i just unzip the exe (trying to get like textures and stuff
yes
thx
mod idea: Jokers with gold sticker have a chance to spawn with red seal
could be fun but also could get pretty crazy
could someone kindly give me an example of Xmult usage in joker. just as i get to that steammodded has removed their example folder :/
and oddly enough i havent made any jokers with xmult yet
fuck
XD
WHY WULD THEY DO THAT 😭
the quasi is kind OP
Is it possible to do custom card animations?
Not sprite animations, card movements like moving it around, the pulse animations, etc etc
to make a different repository
Probably with shaders
😭
calculate = function(self, card, context)
if context.main then
local wild_count = 1
for _, card in pairs(context.scoring_hand) do
if card.edition.type == 'wild' then
wild_count = wild_count + 1
end
end
return {
-- message = localize { type = 'variable', key = 'a_xmult', vars = { wild_count } },
Xmult_mod = wild_count
}
end
end
what have i done wrong? the joker just isnt doing anything. just sitting there with silent treatment mockingly XD
I believe its context.joker_main
yup, i believe im stupid
wait what. then what is it?
oh enhancement
print(card.label)
print(card.ability.effect)
these both print 'Wild Card'
calculate = function(self, card, context)
if context.joker_main then
local wild_count = 1
for _, card in pairs(context.scoring_hand) do
if card.label == 'Wild Card' then
wild_count = wild_count + 1
end
end
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { wild_count } },
Xmult_mod = wild_count
}
end
end
Working!
or should i change it to X1 per wild card. (min 1)?
its just that X0 is uhh, bad
rather than min 1, maybe (Starts at 1X)
I'm trying to create the following joker: "This joker gains +4 Mult when you leave a shop without buying anything". I know how I'd check for "buying something" via context in calculate, but the issue is that this card only starts tracking once it's been bought. So for instance, if you bought a Judgement from a shop, then used it and it generated this joker, then left the shop, the joker would think nothing has been bought and would incorrectly trigger.
I figure what I'd need to do here is track the 'haven't bought anything this shop' outside of this joker and somewhere global instead, that way I can just have this joker check it and it'd always be accurate - but I don't know where I'd hook up this sort of 'calculate outside of the context of any specific joker' thing
I quite literally just made a Joker that does something very similar. Here's how I did it
where is this code though?
In calculate
this looks like its inside your joker's calculate?
but so if you did what I described - buy something, then spawn the joker - it'd think nothing has been bought this shop and trigger, right?
I missed that part of it, however you could hook up a global table variable to the buy button via Lovely patches and have it be cleared every time the shop is exited. Within the calculate you'd just check if the table "== {}" or not
Not sure how involved that would be though
You could probably just assume that when the joker is created something has been bought
Alternativly you could use a lovely patch or hook to store the purchase made somewhere in G.GAME and then just check that value
it bothers me knowingly allowing an edge case to slip through
What parts of the source code are responsible for rendering the display bars for Jokers and Consumables? I want to create a brand new display at the red rectangle, it would also help to know what mods do this as well
this is my first time hearing of lovely patch, I'll go look into that
They will be your best friend if you wanna do anything with vanilla functions
what do you mean display bar?
My guess is a card area
Basically lol
I need to figure out making new card areas at some point too for this Astrology card idea
I dunno how to describe it
Card area, the place to store Jokers/Consumables/similar card types
A brand new one at the marked place
yeah card area is the correct term
I'm not familar with properly making them, but I know that #1226234529413468190 and I think #1225831216939536394 both add new ones
Sick
i think i made it worse
What are those debuffs lmao
Trying to look through footage on Betmma, they don't have the extra card area
Is it activated by something
hmm, I shall apply the philosophy of "tweak the design rather than bulldoze source code" and instead say "This Joker gains +4 Mult when you enter and leave a shop without buying anything", implying that the joker needs to witness entering the shop to trigger
There ya go

i changed it to be simpler
Cool idea but goodness just thinking about trying to do that hurts my head
just like how quasi connectivity makes you frustrated when you begin redstoning
Lmfao
i made it worse
why do the jokers just become super big for a second
_card:juice_up(5,1)
stop juicing them up so much
thats alot of juice for one up
that's enough juice to banter about football with two pioneer probes
(the value was 56 yesterday)
wait a minute, is there even a context hook for beginning a shop
uhmmmmmmm
That sounds like a flip book
Amazing
does anyone know where the art for the game is stored? i wanted to make a graphical mod that just changes the face art for some of the cards but idrk where to start/get files names and whatnot
what's the main scoring loop in the game
i am changing the approach to how i track score
extract the game files
then resources/textures/?x/

