From December to January I had the privilege of working with Neato on her self-titled Balatro mod – Neato Jokers.
The pack features 15 new vanilla-like jokers, covering a range of themes including:
- Content Creators
- Arrested Development
- Always Sunny in Philadelphia
The tools
Balatro is written entirely in Lua, a language I learned to hate from Liquipedia. However, I decided that committing to learning the language was worth the effort for a project as cool as this. The Balatro modding community has also produced useful tools to aid development:
- Steamodded, a framework that makes it easier to create new spins on existing Balatro features, such as jokers, blinds and decks.
- DebugPlus, in-game tooling that allows you to cheat in cards and manipulate the game to make testing easier.
- Lovely, an injector for any entirely new features. Lovely also works for any other games that use the LÖVE game engine.
Since me, Neato and our more senior programmer, Larswijn were all working on a single main file at first, we quickly ran into issues with combining our work. After many iterations we now have two separate file loaders. The first is for common functions and “hooks” that I’ll explain below. The second loads the new jokers from their individual files. Since GitHub tracks different files separately, we can now integrate the latest stable version into our development branches any time more than one of us working on a feature at once.
Hooks explained
By default, everything in Lua is globally scoped. My day job usually requires me to program in C, which locally scopes variables declared within a function by default. In my opinion Lua’s way of doing things is hateful, but for modding purposes, we can exploit this to extend existing functions:
-- common.lua:136-141 (23/03/2025 / 4b76969)
local old_Card_get_chip_mult = Card.get_chip_mult
function Card:get_chip_mult()
-- hook seems best for mod compat?
local mult = old_Card_get_chip_mult(self)
return mult + (self.ability.perma_mult or 0)
end
We save the existing function to a newly named variable, then overwrite the existing function. We call the existing function within the overwritten version since we still want it to do everything it did before.
Lovely patches explained
Frosted Prime Rib was one of the first jokers I programmed. Similar to Hiker from the base game, it gives additional +Chips and +Mult to playing cards when played. After 22 hands, it defrosts and is destroyed. The base game already facilitates cards giving +Mult (e.g. the Mult Card enhancement), and initially the card was programmed to modify the mult value of the card directly. Unfortunately, this didn’t result in the +Mult being displayed on the tooltip for affected playing cards. Initially we worked around this with a Lovely patch (commit):
-- (03/12/2024 / 2bfef00)
-- lovely.toml:14-18
payload = '''
if specific_vars.bonus_mult then
localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {specific_vars.bonus_mult}}
end
'''
-- localization/en-us.lua:4-8
card_extra_mult = {
text = {
"{C:mult}+#1#{} extra mult",
},
},
Later, English localizations and programming to support +Mult, xMult and +$ on cards separate from enhancements were added to Steamodded, which is how the mod works today.
Hopefully this serves as a little ramp-up for anyone looking to make their own contribution to the weird and wonderful world of Balatro modding. If you have questions about the mod, feel free to ask in the Neato Jokers thread within the Balatro Discord!

Leave a reply to Jake Doran Cancel reply