Hello! Just wanted to take this moment to thank everyone in this amazing community for their ingenuity and creativity and wonderful drive. It's really rare for a game to persist for as long as Balatro and I'm so proud that I have been able to be a part of it for the past (almost) two years.
I can't even begin to explain how thankful I am to have the incredible @WilsontheWolf and @cg-223. They have taken care of so much work between now and v0.8.0 and I am so lucky to have them as maintainers. They deserve so much appreciation for keeping up the pressure and making this release happen.
And remember to thank the hardworking people that make the mods, they keep this community alive.
You are obligated to try these mods out: (and legally obligated to try out every mod you see elsewhere, too)
Entropy, Tangents, Matador, LobotomyCorp, Amulet, Hatchet, Gros Balatro, Stocking Stuffer, MrBones, Insignia, MyDreamJournal, Balatro Plus, Arrow, TooManyJokers, Multiverse, 45DegreeRotatedBeatblock, Basslatro, Joyous Spring, Incognito, Galdur, Hyperfixation, Hot Potato, UltraViolet, Qualatro, Corrupted Nether, Fusion Jokers, Fortlatro, 1 in 10000 Chance for Withered Foxy Jumpscare Every Second, BeatblockPlus, Beattools, Scruffy Plays Pikmen, Lovely Mobile Maker Revo's Vault Dilatro, Aikoyori's Shenanigans
Install guide
| OS | Download |
|---|---|
| Windows | lovely-x86_64-pc-windows-msvc.zip |
| Mac (Arm) | lovely-aarch64-apple-darwin.tar.gz |
| Mac (x86) | lovely-x86_64-apple-darwin.tar.gz |
| Linux | lovely-x86_64-unknown-linux-gnu.tar.gz |
Mobile Mods!!!!
@WilsontheWolf has created https://lmm.shorty.systems, it lets you mod Balatro on mobile with lovely by porting the Steam version of the game. Try it out.
Important
BREAKING CHANGES:
- Module patches with
load_now = truethat fail to load or execute now properly propagate errors instead of failing silently. - On Linux native, the mod directory has changed from
~/.config/<game>/Modsto~/.local/share/<game>/Modsto follow XDG standards. You'll need to move your mods to the new location.
Contributors
Big thanks to the following contributors:
- @cg223 for multiple targets support, copy patch payloads, nested folder loading, and runtime API additions
- @WilsontheWolf for the runtime API (
reload_patches, variable store),load_nowerror handling, Linux directory fix, andluaL_loadbufferhook, and lots more - @kasimeka for fixing the
--vanillasegfault on Unix and adding Nix support - @SpomJ for improving Linux installation documentation
- @hliuson for release workflow improvements
Notable Changes
Important
Most mods WILL NOT WORK AS ZIPS until modloaders have added support. NO EXCEPTIONS!
Zip mods
TL;DR: Mods can now be distributed as zip files.
Lovely can now load mods packaged as zips. Packaging is simple, just drop your mod files into the archive into either the top-level or into a folder, both are valid.
mod.zip
lovely.toml
...
works the same as
mod.zip
mod/
lovely.toml
...
Recursive patch loading
TL;DR: Patch files are loaded recursively, clean your lovely dirs.
Patch files inside the lovely/ directory are loaded recursively from subdirectories.
For example:
tangents/
lovely/
questionable_feature.toml
features/
real_feature.toml
content.toml
tweaks/
balanced.toml
Multiple targets per patch
TL;DR: Pattern, regex, and copy patches can target multiple files.
Patch away with reckless abandon:
[[patches]]
[patches.pattern]
target = ["main.lua", "game.lua", "init.lua"]
pattern = "old_code"
payload = "new_code"Copy patch payloads
TL;DR: Copy patch payload field
Copy patches now have an optional payload field that lets you inject code without the fuss of a separate file:
[[patches]]
[patches.copy]
target = "main.lua"
position = "append"
payload = """
-- Inline code here
print("Injected!")
"""Runtime API additions
TL;DR: New Lua APIs for runtime patch manipulation.
The lovely module now exposes several new functions for runtime control:
lovely.reload_patches()- Reload all patches from disk without restarting. This does not reapply patches, you need a restart for that.lovely.apply_patches(buffer_name, buffer_content)- Apply patches to arbitrary buffers at runtime. You can patch shaders with this! And whatever you want, really.lovely.set_var(key, value)- Store a var in the store.lovely.get_var(key)- Retrieve a var from the store.lovely.remove_var(key)- Remove and return a var from the store.
Example usage:
-- Store configuration
lovely.set_var("is_tangents_questionable", "true")
-- Retrieve it later
if lovely.get_var("is_tangents_questionable") == "true" then
panic!("What?")
end
-- Apply patches to a dynamically loaded buffer
local patched = lovely.apply_patches("buffer_name", buffer)
-- Force a patch reload (not a restart)
lovely.reload_patches()Module patches now apply Lovely patches
TL;DR: You can patch injected modules.
Injected modules can now be patch targets! =[lovely modname "filename"]
Bug Fixes
- Fixed hardcoded game names in Linux launch scripts (
run_lovely_linux.sh) - Fixed segfault when running with
--vanillaflag on Unix - Fixed double-panic behavior on Windows
- Fixed panic when obtaining extension from extensionless files
- Fixed incorrect mod directory on Linux (#325)
What's Changed
- Update release.yml by @hliuson in #265
- fix(unix): prevent segfault when run with
--vanillaby @kasimeka in #263 - feat: add nix package and devshell by @kasimeka in #278
- feat: check preload for if lovely was loaded by @WilsontheWolf in #283
- Runtime: Implement native Lua modules v2 by @WilsontheWolf in #285
- feat: reload on lovely module by @WilsontheWolf in #286
- Allow patching lovely modules by @WilsontheWolf in #293
- Add name fields to patches by @cg-223 in #298
- Support nested folders inside Mods/foo/lovely by @cg-223 in #290
- Add Lua-sided apply_patches function by @cg-223 in #300
- feat: lua variable store by @WilsontheWolf in #299
- Allow multiple targets on a patch by @cg-223 in #297
- feat: win hook luaL_loadbuffer by @WilsontheWolf in #305
- feat: lua table helper by @WilsontheWolf in #306
- feat: log path in lua module by @WilsontheWolf in #303
- Check needs_patching before calling apply_patches from Lua by @cg-223 in #310
- feat: only do dwmapi check on windows by @WilsontheWolf in #308
- feat: patch table load is a result by @WilsontheWolf in #307
- Add optional payload field to copy patches by @cg-223 in #318
- Fix double-panic behavior on windows by @ethangreen-dev in #321
- feat: blacklist by @WilsontheWolf in #319
- Add context to error occurring with lovely being mistakenly run by @cg-223 in #322
- Add generic lovely target for C code (liblovely) by @WilsontheWolf in #206
- resolve some clippy warnings by @cg-223 in #324
- fix: wrong dir on linux by @WilsontheWolf in #325
- Add pattern and regex patch benches via criterion + gh action by @ethangreen-dev in #323
- Add linux-native installation instructions by @sqrvrt in #225
- fix: hard coded balatro in
run_lovely_linux.shby @WilsontheWolf in #338 - add extended dump debug info via json sidecar files by @WilsontheWolf in #339
- Add support for zip mods by @ethangreen-dev in #330
- v0.9.0 by @ethangreen-dev in #340
New Contributors
- @hliuson made their first contribution in #265
- @cg-223 made their first contribution in #298
- @sqrvrt made their first contribution in #225
Full Changelog: v0.8.0...v0.9.0