The Glest Wiki

Lua is the scripting language used by Glest for all scripted scenarios and tutorials. It allows dialogue with the player, and allows you control over the enemy, such as to make a scenario where you must destroy the enemy villages in order, or something were you must survive a special enemy attack with different starting units. It can be made so you can have missions where your goal is to protect a certain unit, such as a summoner or an allies castle. You have full control over what the foe does, and this is very handy for making a unique scenario. All tutorials are scripted. They are simply easy scenarios that teach you as they go.


The best part about lua is that the lua used in Glest is very easy to learn, only a bit harder than the XMLs, and easier than learning to model. lua script is placed in between the scripts tag of the scenario XML, and should have an included .lng file in the same directory if dialogue is used (more on this later).

Lua is a straight forward language in Glest, existing simply of commands, many which check to see if event A has occured, then event B can start.

The basics of lua are simple. In Glest, a command does a certain function to a certain unit, faction, team, or the screen. Comments can be placed with --, where everything after the -- is commented out until the end of the line. The most important thing to remember is that the faction numbers are 0, 1, 2, and 3. NOT 1, 2, 3, 4. Player 1 is known as player 0 here. This is called the faction index, and is used in many functions that affect a faction/player. Lastly, remember that lua is case sensitive. createUnit is not the same as CreateUnit.

Unit IDs[]

First of all, an important concept to understand is that all units in glest have a unique number assigned to them, and lua needs to use this number to control the units. However, you don't have to directly know the numbers, and you'll never use the number itself. We will always use variables and functions to get these unit IDs. The best way to get a unit ID is right after we create the unit (with createUnit()) by using the command lastCreatedUnit(), which gives the unit ID of the last created unit.

So if we use a variable, such as myVar (variables in lua are loosely typed and do not need to be declared in any way), we can say myVar=lastCreatedUnit(), so now the unit ID of the last created unit is stored in 'myVar'. Note that we can only get the unit ID of a unit when we create them, so we cannot get IDs of units later.


You can use lua coordinates for anything that needs a position. These are in the format of {x,y}, and replace common queries such as startLocation() and unitPosition(). Firstly, lets look at how they work. Maps are split into tiles. Each tile is 2 x 2 cells. So a 128 x 128 map is measured in tiles. However, glest uses CELLS instead of tiles for lua positions, so that means a 128 x 128 map is actually 256 x 256 cells. However, these are INDEXED, like many lua functions and arrays, meaning they start at 0. Also, the very last row and very last column (in TILES) cannot be used to place things, since there is not enough room. So in short, the map starts at 0,0: the first top left cell. The last useable cell is 254,254 here, at the bottom righthand corner.

So that's how cells work. Now, let's look at how we can use attributes from queries for positions. We know that the startLocation(0) command would get faction 0's start location's {x,y} coordinates, but suppose we wanted to have it appear 20 tiles (40 cells) north of the start location. How would we do that? Simple. The startLocation() query will return both the x and y in the braces. However, startLocation(0)[1] will return JUST the x value, and startLocation(0)[2] will return JUST the y value. So if we wanted 40 cells north of the startLocation (y axis, starting from the top), we'd use {startLocation(0)[1],startLocation(0)[2]-40}. All location queries will return the x value if a [1] is placed after it, and a y value if a [2] is placed after it.


GAE v0.2.13 and later can use lua timers. To use one, you must first call setTimer('timer_name', 'game', #, true). The first value is the timer name, which lets you reference it. The second value is either game or real. Game is recommended, because it changes based on the player's game speed (ie: if the player increases the speed, the timer ticks by faster. This keeps players from cheating by slowing down the game speed and giving themselves more time). Real is simply miliseconds. If you use game, then bear in mind that it is world refreshes. The world refreshes 40 times per second on normal speed.

So if you want the timer to be set for 5 seconds, you'll need 5*40=200 as a value, which brings us to the third attribute, which is the value (seconds in real, refreshes in game). The last value is whether or not the timer is an interval (repeating) timer. If true, it keeps doing the timer over and over (ie: to create a unit every X seconds), and if false, its a one time timer (such as to create something just once after a certain amount of time).

To tell Lua what we want the game to do when the timer reaches zero, we need a <timer name="timer_name"></timer> tag somewhere in the XML (remember that XML tags must be outside of the Lua code, meaning, say, after the closing tag of &lt;unit-died&gt;, NOT inside of those tags (only lua goes inside). This XML tag can contain whatever Lua code you want to be executed when the timer runs up.

To stop a timer, we simply use stopTimer('timer_name'), which will stop the selected timer. Note that there is no way to restart a timer, though you can create a new one.

Events and Triggers[]

GAE 0.2.12 and later supports events in lua. Events are blocks of code executed when certain conditions (the trigger) become true. For example, you might set an event so once a unit enters a certain area, he would get ambushed. Events first need to be named with registerEvent(). All lua code for events must also be stored in a XML block called <unitEvent name="event_name"></unitEvent>. If the event is going to be triggered by entering an area, you must also register that area with registerRegion().

Now for the trigger, you can use either setUnitTrigger(), which applies to a single unit, but offers more conditions (triggers), including when they are attacked, when they enter an area, when their HP is below a certain value, etc. OR, setFactionTrigger() is currently limited to just when a unit enters a region. When the condition is fullfilled, the XML block for that event will be executed.

LNG files[]

.lng or language files hold all the dialogue for scenarios, their advantage is that they can be translated into other languages. They should be in the format <scenario_name>_<language>.lng. For example, if the scenario is called storming, then the english lng file will be called storming_english.lng. English should be the priority, while other languages are optional.

The lng files are in the same format as an ini, and lines that start with ; are comments.

Lines in the .lng file are simply <tagName>=text string.

The tagName is the name used to refer to the lng in the lua script, such as showMessage('message-tag', 'message-topic'). This lng file would need two tags, message-tag and message-topic. Note that text strings are unrestricted, and can contain any ASCII characters and punctuation. They can have capital letters as well, and go until the end of the line. Note that if you go too long, the dialogue box may not have room to fit the message. If that's the case, split it down into seperate messages.

List of Lua Commands[]

For Lua commands shared by all engines, including regular Glest, please see Lua/Commands. For MegaGlest, see MG/Lua. For GAE, see GAE/Lua.

External Links[]