From ESOUI Wiki

Jump to: navigation, search

Elder Scrolls Online uses Havok Script - a small and fast Lua Virtual Machine for games. The version in the game is based on Lua 5.1 with some modifications. Before Update 18 (Summerset) the game used a 32-bit VM, but now we are on a 64-bit build.

All available API methods and variables that are preloaded by the game can be found in the ESOUIDocumentation.txt (you can find it in the update threads on the ESOUI forum or the official forum). For everything else you can refer to the ESOUI Lua source code which is available on github.


Disabled modules

Anything that would grant direct access to the file system or network has been disabled, since ZOS' policy is to not allow any real-time communication with external resources and it would also impose a huge security risk if addons could just access the file system directly. This means that io, os and package have been removed.

ESO also uses a custom security system which enables ZOS to lock methods so they cannot be called by addons (protected = only out of combat use is allowed, private = addons cannot call it). In order to avoid problems with it, the coroutine and debug module have also been removed.

In update 15 a custom os module was added, which exposes the date functions.

In update 18 a custom debug module was added, providing a method traceback() which returns a stack trace.

Differences to Lua 5.1

There are also several points where ESO Lua behaves unlike regular Lua 5.1.

module loading

Since all file access is disabled, ESO takes care of loading additional Lua files when the user interface is initialized for the first time. Addons can specify all files that should be loaded and their order via the manifest file. The files will then just be executed one by one and addons can use the global table to share their functions and variables. Once all files have been loaded, the EVENT_ADD_ON_LOADED will fire.

persisting data

ESO also offers a very restricted way of saving data so it can be used between play sessions. In the manifest one can specify "SavedVariables". Those represent global variable names that can be used to assign tables that get serialized into an <addonname>.lua file in the 'Saved Variables' folder when the UI is unloaded (logout or reloadui). On UI load these tables will then be restored and become accessible once the EVENT_ADD_ON_LOADED fires.


Originally the game would crash to desktop for certain sort functions, due to an infinite loop in the C-code for Lua 5.1. In order to fix this, the sort method has been patched to Lua 5.2 level.

UTF8 strings

Regular Lua only knows single byte ASCII characters, but ESO supports UTF8 which can span more than one byte. This difference can cause issues with many methods if not handled correctly.

Starting with Update 21 (Wrathstone) the utf8 module from Lua 5.3 was added to the game.


The gsub method uses a different implementation, so some patterns will return different results as explained here and here. The UTF8 strings also add to the differences in the behavior.

Additional features

Havok Script brings some features to the table that are not part of regular Lua.

Type Specification

You can specify the type for any variable and the VM will do a type check at runtime. For example the following code will raise a type error.

function myFunction(myParam: number)
--do something

Keep in mind that "nil" is a valid value regardless of the type.


This feature allows you to define new types that behave like a table with string keys. This allows the VM to optimize them for considerably faster access and less memory usage.

hstructure MyType
    id : number
    name : string
local myVar : MyType = hmake MyType { id = 1, name = "test" }

See zo_matrix.lua for an example how it is used ingame.


Currently there are autocompletion projects for the following IDEs and editors:

Personal tools