Jump to content

Recommended Posts

Howdy :beguiled: I can sure explain you the basics of it and provide a full example for making one ! If you need any extra help in your joker creation, I suggest you first start looking in the following files which will show you various scoring examples, and how to add in the cards visual and audio effects. And if something is still not clear do ask and I'll provide more context as I'll try to keep that short

Useful files :
- scripts/prefabs/balatro_score_utils
- scripts/widgets/redux/balatrowidget

 

Wirlywings example Joker scripts, and assets :

balatro.lua

joker.zip

To get your joker working I suggest setting an exclusive file for it that you modimport() from your modmain, and make sure you add the new anim file to the mod Assets.

 

Now to get into details, bit by bit on how it was done :

Up to line 15 we're fetching the essentials for defining our joker, and make sure it is all present in case some update was to change things so we safely go beyond that point. You can notice a function named CherryUpvalue used twice and its to give us access to buried variables inside other functions closure, that's our shovel to get the BaseJoker model and insert ours in-game. In case your mod doesn't have a wrapper around debug.getupvalue like the UpvalueHacker tool which you could use, I can provide you this one to get that done (in modmain or wherever before your balatro file uses it)

Spoiler
function CherryUpvalue(fn, upvalue_name, set_upvalue)
	if fn == nil or upvalue_name == nil then
		return
	end
	
	local i = 1
	while true do
		local val, v = debug.getupvalue(fn, i)
		
		if not val then
			break
		end
		if val == upvalue_name then
			if set_upvalue then
				debug.setupvalue(fn, i, set_upvalue)
			end
			
			return v, i
		end
		i = i + 1
	end
end

 

With that done, it gets funnier from here, you can now add in your joker, setting its name, and description, which you'll notice is a string which isn't present in this file, but you can add it just before or in your string files such as this :
STRINGS.BALATRO.JOKER_WIRLYWINGS = "Each unique face card kept in hand\n+2 mult"

 

Next, you're already at the step of making your joker mechanisms

This is done in two times. First, you will be creating your joker base class and make it calculate the scoring for "the server side". My joker (and most others) rely on the OnCardsDiscarded function and card data provided which happens automatically when you're dealing or skipping, but you can also use OnGameStarted (used with Wanda), OnNewCards (Webber, Wendy...) or OnGameFinished (Warly) for your joker. You are not even confined to be using these or a single one, and could think of some other effects if you're experienced but at least those 4 are automatic while the minigame progress, and all that matters is getting your numbers right into AddChips and/or AddMult

So you can see here the Wirlywings joker is scoring extra mult whenever a non-duplicate face card rank is kept in hand (works wonders on a lucky high Straight or Flush !), to make your own effect, do read how the other jokers are done in the files above and you'll get the swing of it quick

 

 

And last we take care of the BalatroWidget interface

To add our joker "client side" scoring + all the effects such as playing cards & joker rotations + the chips and mult sounds and satisfying growing numbers.
A lot of stuff but this is all done by putting together functions into the same queue which you have many examples of in this widget file.
All that matters is that you put all of this in a special Scoring function exclusive to your joker, and hook the ReceiveDeal function to trigger the scoring if we're using that one joker. You decide if you want to do this one card at a time or all at once.

You have to be cautious about getting the same results between this and the server scoring functions otherwise you'll end up in surprise having wrong scores like the Wendy joker does...

 

The StartSelectJoker & StartPlayGame functions at the end is just a fix to show our joker in the selections, and the one selected, because otherwise it would be invisible so in the OverrideSymbol functions change the second param to your build file name, and third to the name of the joker folder.
Once the anim .zip file is compiled you can delete the anim.bin one inside and keep just the build and atlas.

 

And this is really just it, make sure you remane things accordingly, this is more an example than a tutorial but I hope you make the best of it. :encouragement:

Edited by ADM
  • Like 3
  • Thanks 1

Today I was asked for an empty joker card, realized I didn't post this originally so if this can help anyone else, this is what I prepared and used for the model above. It isn't perfect but consider doing a mini touch up on the background given all jokers have a unique grain on the card.

joker_empty.png.2f6c88448629cac61c99a0418e9654e9.png

  • Like 3

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...