Sitemap
Joseph Ewert

Joseph Ewert

Hello everyone! Stick around and learn something new about Unity! I also have a portfolio page at https://squirreltalegames.com

Lua Time!

5 min readJan 31, 2025

Alright… It is finally time to dive into some Lua! Yay.

Have you ever written code, and then returned to it multiple years later to review it? Well that’s us today! Something that I was happy about, is that I kept the Lua portion of the bot. I did not have to re-write this at all, so most of what we see will be me cleaning up the code.

Before we dive in, we need to understand the flow of how the bot works.

I felt like MS Paint diagram today.

So our C# bot gets the user text from chat, converts it into a Lua command, and sends it to an Oven.Bake file. Our Lua part will read this file, and execute the code, deleting it once complete. Easy peasy, right? Not so easy.

Press enter or click to view image in full size

This is the back bone of our Lua. This is the function that actually executes the command that is loaded from the oven.

The first line is from the Isaac API. Basically, it runs a function to get the room the player is in.

Next is a little trick I cooked up. “arandomspot” is written weird right? This allows our injected Lua code to get a random spot in our current room.

Finally we are using Lua’s load function. This runs the string that is passed to it as literal code.

Before we end, we want to clear the command we just executed. We set our commandExecution variable to noCommandsInQueue. What is “noCommandsInQueue”?

Press enter or click to view image in full size

We have some strings pre-defined for several things. This is at the start of the script defined as a global variable. Our “noCommandsInQueue” variable is just a print command that prints out a pre-defined string into a display console.

Get Joseph Ewert’s stories in your inbox

Join Medium for free to get updates from this writer.

Now how do we deal with Oven.Bake?

Press enter or click to view image in full size

We have this nifty guy. This is a function that is ran on a timer (to keep it from running every frame) that reads the top line of Oven.Bake. This is also why our copy of Binding of Isaac has to run with — luadebug turned on. This reads the “selected” line in the file, and then captures it in the commandExecution variable. If its nil or null, it tells the debug text to update in the onscreen debug text.

Press enter or click to view image in full size

Next, let’s look at the logic for removing the lines in the Oven.Bake file. Our remove logic is separated from our read logic so if something goes wrong with one or the other (and trust me it did while constructing this beast), we can look at either read or remove.

The first 2 lines are a simple null check (as a primary C#-per nil was an adjustment). We then get ourselves an array and a reference to 1.

“For in do”… Fus ro Dah? This is a for loop in Lua. We are then reading our file, and capturing everything except the first line into our array. Once done, we close the file. We back in the first line, opened it in read mode.

We open the file again in write mode, and then use a for loop to write the array to the file. We then close the file.

Fun fact about Lua and io mode: It does not support read and write at the same time. I am sure I could make this more efficient if I went further down a Lua rabbit whole (or a more experienced Lua coder could), but I am satisfied with how it ran in testing.

Press enter or click to view image in full size

Moar functions! This is our timer controller. This function runs our timer for inbetween commands. It uses some global variables set up. This is basically what we are using to keep it from running IO actions on every frame. Trust me. No one wants that. This is honestly a really simple timer pattern that adds to the timer, and then resets itself once it reaches the max value.

You may be wondering “Hey wait a sec, you just showed me a bunch of functions. But nothing calls these functions! You’re tricking me aren’t you?”

Press enter or click to view image in full size

This is what you were looking for. Coming from Unity, I constructed all of the Lua to run off of an Update() styled function. This function is called every frame by the Post_Update callback from the Isaac main code via a nice subscription and event.

The function itself is pretty simple. We check if our timer is active. If so, handle the timer functions. If the timer is going off, read the top line of oven.bake, execute that line of code, then remove it from the oven.bake file. And of course, we reset the timer at the end using an int as a bool. Lua does not have a boolean type, so we just used an int.

Phew. That covers most of it! There’s a few small things (like our debug text or player grab) but all of that is mostly Isaac specific code. If you are interested this project is open sourced, so you can check it out!

Now let’s move on to the C# bot next… Send help. I may need it.

--

--

Joseph Ewert
Joseph Ewert

Written by Joseph Ewert

Hello everyone! Stick around and learn something new about Unity! I also have a portfolio page at https://squirreltalegames.com