Introduction to Scripting

Scripting is a vast topic so in the scope of these documents we can merely introduce you to the subject. Even though you can do a lot in the Dungeon Editor without ever touching scripting, I would encourage you to try it out since doing scripts, even very simple ones, will open a lot of new possibilities for your level designs. If you want to get started in programming in general, I think scripting in the Dungeon Editor is a good starting point since you can start off with very easy and simple scripts and then build up from there.

Level scripting in Legend of Grimrock 2 is done using a programming language called Lua which is a very flexible language with a simple syntax and it’s a great language for getting started in programming too. Prior knowledge of Lua won’t be absolutely necessary here but I won’t be covering the details of Lua programming here either so even a cursory knowledge of scripting or programming in general will be helpful. But I’m sure you can get quite far even with just copying and pasting these examples and modifying them for your purposes too. I’m certain the modding community will also produce a great amount of scripts that will be available for anyone to use.

The game console is a very helpful tool when it comes to scripting (or for level design in general) and you can enable the console by editing the grimrock.cfg file (usually located in your “\Documents\Almost Human\Legend of Grimrock 2”). Then, you can access the console in the game preview window by pressing the tilde key (under Esc and above Tab) and run lines of script there. If the console doesn’t show up, you may also need to modify the value of consoleKey from 220 to 192, depending on your keyboard layout. Also, messages that are printed from scripts will be displayed on the console and to get started with some practical stuff, let’s learn how to print a traditional “Hello world!” message!

Hello world
Scripts in the levels are contained in script_entity assets that you add to the map. Their location in the level typically doesn’t affect their functionality but for the sake of clarity it is usually a good idea to place the script entity close to what the script relates to. The scripts will be run when the dungeon is started for the first time but we can also run functions from the script entities by using the connectors from buttons, pressure plates, timers and other actuators. If we want to create a script that prints a message to the console any time when a button on a wall is pressed we would need to add a script entity to the level with the following script in it:

-- hello world script
function hello()
    print("Hello world!")

The first line of the script is a comment, as indicated by the two dashes in front of the line, and therefore it will not be interpreted as code. In the following line we define a new function that we decide to simply call “hello” and next, between the function definition and its end statement, we have the piece of script that actually runs when some event in the game calls the hello-function.

The script is now completed but at this point if you would run the preview, the script would essentially do nothing since we don’t call the hello function from anywhere in the level yet, so let’s add a wall_button somewhere into the level and add a connector to the button and set the script entity as its target. At this point, the Action-field of the connector should show the name of the function (“hello”) so we can start the preview and press the wall button to see if “Hello world!” is printed to the console on top of the screen.

Any text printed using the print() function will only be visible on the console. If you need to output text that the player will also see, you should use hudPrint() instead. If you want to clear the console from printed text, you can do so by pressing the CLR-button above the Preview window.

So in practice, functions are a handy way for you to run pieces of script triggered by events (such as button presses, timers, monster deaths etc.) in the game. One script entity can contain multiple functions: just remember to pick the correct one when adding a connector. Now that we have the very basics covered, you can move on to a more advanced tutorial where we describe how to create a classic combination lock puzzle.