Skip to main content

Events

Multiverse has plenty of registerd callbacks that are executed when a specific event is triggered. To start receiving events, you first have to define the event's corresponding callback function inside your Lua script. You may expect parameters to be passed back to you, some of which are passed by reference.

warning

You may not have multiple definitions of the same callback, even if the second definition is located inside a secondary (require) script file or module. View the example below, where only one OnTurn event will work.

Scripts/script.lua
module = require(get_script_dir() .. 'module.lua')
function OnTurn() end
Scripts/module.lua
local module = {}
function OnTurn() end
return module


Essential ✨​

OnScript​

Description: OnScript is a crucial event and is generally always found inside the main.lua script, which is considered the Parent. This event is triggered when scripts are supposed to be loaded, e.g. level restart, load, etc.

Parameters

TypeNameDescription
UBYTElevelThe current level being loaded by the user.

Code Example

main.lua
function OnScript(level)
if (level == 1) then
AddScript("level_1.lua")
else
AddScript("level_2.lua")
end
end

OnTurn​

Description: This event is triggered every time a game turn has passed. No parameters are being passed to this callback. To fetch the current game turn, use the example below.

Parameters None.

Notes

tip

Use the reserved Game object to call the getTurn method to get the current turn, or alternatively, the method getTurnSecond, depending on the units you want to work with. Do note that one second is equal to 12 game turns!

caution

When using getTurnSecond, it's advisable to check for a valid value. If the turn has already been processed, it will return an ULONG_MAX (0xffffffff). However, getTurn does not require this check.

Code Example

example.lua
function OnTurn()
local turn = Game.getTurnSecond()

-- We ensure we only process the turn once.
if (turn ~= ULONG_MAX) then
Log(string.format("Current turn: %i", turn))
end
end

OnThing​

Description: This event is triggered every time a game object is created, but only for objects created after the first game turn (anything above GT 0).

TypeNameDescription
Thing*thingThe thing object.

Notes

note

The thing object is passed by reference, so you may modify the object inside the callback function.

tip

If you're only interested in parsing spells, OnPlayerSpell will be a better alternative to OnThing, since you won't be having to parse hundreds of objects.

caution

Seralized objects that spawn during the first game turn (i.e. placed through the World Editor) will never trigger this event. This is intentional but might change in the future.

Code Example

example.lua
function OnThing(thing)
Log(string.format("[OnThing] Type: %i, Model: %i, Owner: %i", thing.Type, thing.Model, thing.Owner))
thing.Owner = thing.Owner + 1
if (thing.Owner > TRIBE_GREEN) then thing.Owner = TRIBE_BLUE end
end

OnRegenerate​

Description: This event will trigger when a level is loaded for the first time, or during an on-going level that is restarted.

Parameters

TypeNameDescription
UBYTElevelThe current level the user is playing.

Notes

caution

This event will not trigger when the user loads a game save file of the level, as it has already been generated before.

Code Example

example.lua
function OnRegenerate(level)
initialize_my_important_stuff()
end



Input ✨​

OnKeyDown​

Description: This event will trigger when a key is pressed, the passed argument being the key code that was pressed.

Parameters

TypeNameDescription
TbInputKeykeyKey code that was pressed.

Return It is expected of you to return a boolean, indicating whether you want the game to handle the key event. Returning a true value will tell the input system to not handle the keystroke.

Notes

caution

Not all keys trigger this event – for a full list of possible key codes check the TbInputKey data structure.

Code Example

example.lua
function OnKeyDown(key)
if (key == TbInputKey.LB_KEY_Q) then
Log("'Q' key down!)
end
end

OnKeyUp​

Description: This event will trigger when a key is released, the passed argument being the key code that was released.

Parameters

TypeNameDescription
TbInputKeykeyKey code that was released.

Notes

caution

Not all keys trigger this event – for a full list of possible key codes check the TbInputKey data structure.

Code Example

example.lua
function OnKeyUp(key)
if (key == TbInputKey.LB_KEY_Q) then
Log("'Q' key released!)
end
end

OnMouse​

Description: This event will trigger when a mouse button is pressed, the passed argument being a MouseEvent.

Parameters

TypeNameDescription
MouseEventeventMouse event containing the button type and state, as well as the click location in screen space.

Return It is expected of you to return a boolean, indicating whether you want the game to handle the click event or not. Returning a true value will tell the input system to not handle the click. This is useful for cases where you want to create your own scripted GUI and consume the click events yourself.

Notes

note

The event will fire even whilst inside the main game menu or during a game pause.

Code Example

example.lua
function OnMouse(event)
if (event.Button == TbInputKey.LB_KEY_MOUSE0 and event.Down == true) then
Log(string.format("Left mouse button click at screen pos: %i, %i", e.Pos.X, e.Pos.Y))
end
end

OnChat​

Description: This event will trigger when a message is sent using the TAB + F11 chatbox, the passed argument being the message sent.

Parameters

TypeNameDescription
stringmessageMessage sent by the user.

Code Example

example.lua
function OnChat(message)
if (message == "/surrender") then
Log("I surrender!")
end
end



Serialization ✨​

OnSave​

Description: This event will trigger when the user saves the game. You may use this event to save the state of your variables.

Parameters

TypeNameDescription
SLONGslotThis is the save slot chosen by the user.

Notes

tip

You can either save individual variables or tables containing one or more elements.

warning

Saving will fail on local objects – ensure they're global before attempting to do so. To create a global table, simply declare it outside the scope of a function – there's no global keyword.

function my_function()
local MyCoolTable = { error="this table is only 'visible' in this function block!" }
end
...
SaveTable("MyCoolTable", slot) -- error, cannot find this table defined anywhere!

Code Example

example.lua
MyTable = { Foo=0, Bar=1 }
MySecondTable = {nil, 42, Foo=1, Bar=function() Log("Bar") end}

function OnSave(slot)
SaveTable("MyTable", slot)
SaveTable("MySecondTable", slot)
end

OnLoad​

Description: This event will trigger when the user loads a game save file. You may use this event to load the previous state of your variables.

Parameters

TypeNameDescription
SLONGslotThis is the save slot chosen by the user.

Notes

Code Example

example.lua
-- Based on the OnSave code example above,
-- 'MyTable' and 'MySecondTable' were previously serialized.

function OnLoad(slot)
LoadTable("MyTable", slot)
LoadTable("MySecondTable", slot)
end



Sound ✨​

OnSoundPlay​

Description: This event will trigger when a sound from the custom music engine starts playing.

Parameters

TypeNameDescription
stringnameThis is the name of the playing sound file.

Code Example

example.lua
function OnSoundPlay(name)
Log(string.format("Now playing: %s", name))
end

OnSoundStop​

This event will trigger when a sound from the custom music engine stops playing.

Parameters

TypeNameDescription
SoundReceiverInfosriThis is a data structure containing the sound name and the reason it stopped playing.

Notes

warning

Trying to play a custom music track from within this function will result in a crash, instead call the play method somewhere else, i.e inside OnTurn.

Code Example

example.lua
function OnSoundStop(sri)
Log(string.format("Stopped playing: %s, reason: %i", sri.FileName, sri.Reason))
end



Drawing ✨​

OnFrame​

This event will trigger every time a frame has finished rendering – essential for drawing text, sprites or shapes to the screen space.

Parameters None.

Notes

tip

Get and cache a reference to the object gnsi to get the current screen width and height. You will most certainly need this for drawing inside OnFrame!

_gnsi = gnsi() -- global variable and called only once
...
local scrW, scrH = _gnsi.ScreenW, _gnsi.ScreenH

Code Example

example.lua
function OnFrame()
local scrW, scrH = _gnsi.ScreenW, _gnsi.ScreenH
local x, y = math.floor(scrW / 2), math.floor(scrH / 2)
DrawBox(x, y, 220, 30, 0)
PopSetFont(P3_V_LARGE_FONT, 0)
DrawTextStr(x, y, "Hello from Lua!")
end


OnSpriteFrame​

This event will trigger every after the engine draws a sprite to the screen. It does not receive events from GUI drawing.

Parameters

TypeNameDescription
SpriteFrameEvent*frameThis is a data structure containing information about the sprite frame that has just been rendered.

Notes

note

This event is useful for drawing your own text, sprites or shapes in world space, but introduces quite a bit of overhead.

caution

There's a possibility for the frame to contain a non T_PERSON object, as a result of a few unique objects being rendered through this pipeline.

warning

The structure SpriteFrameEvent and OnSpriteFrame event is subject to heavy API changes in future Multiverse updates.


OnAnimSpriteFrame​

This event will trigger every after the engine draws a person sprite to the screen.

Parameters

TypeNameDescription
SpriteFrameEvent*frameThis is a data structure containing information about the sprite frame that has just been rendered.

Notes

note

This event is useful for drawing your own text, sprites or shapes in world space, but introduces quite a bit of overhead.

caution

There's a possibility for the frame to contain a non T_PERSON object, as a result of a few unique objects being rendered through this pipeline.

warning

The structure SpriteFrameEvent and OnAnimSpriteFrame event is subject to heavy API changes in future Multiverse updates.

Code Example

hp_bars_example.lua
function OnAnimSpriteFrame(frame)
if (frame.Thing.Type == T_PERSON) then
if (frame.Thing.Model == M_PERSON_MEDICINE_MAN) then
local life = frame.Thing.u.Pers.Life
local bar_w, bar_h = 100, 8
local x, y = frame.x - (bar_w / 2), frame.y - frame.h - 10
DrawBox(x, y, bar_w+2, bar_h+2, COLOUR(CLR_BLACK))
DrawBox(x, y, bar_w, bar_h, COLOUR(CLR_BLACK))
local life_bar_w = math.floor((bar_w * (life)) / frame.Thing.u.Pers.MaxLife)
if (life > 0) then DrawBox(x, y, life_bar_w, bar_h, COLOUR(CLR_RED)) end
local life_str = string.format("%i / %i", life, frame.Thing.u.Pers.MaxLife)
PopSetFont(P3_SMALL_FONT_NORMAL, 0)
DrawTextStr(math.floor((x - (string_width(life_str) / 2)) + (bar_w / 2)), y, life_str)
end
end
end

Code Result




Other ✨​

OnPlayerHintDisplay​

This event will trigger when a hint is being displayed by the game. See PlayerHintDisplay for more details..

Hint example.

Parameters

TypeNameDescription
PlayerHintDisplay*hintThis is a data structure containing information about the hint.

Code Example

example.lua
function OnPlayerHintDisplay(hint)
Log(string.format("Hint StrId: %i, hint.StrId))
end

OnPlayerSpell​

This event will trigger when a spell is being cast. It is similar to the OnThing event, but you're guaranteed to only parse spells.

Parameters

TypeNameDescription
Thing*thingThe spell object.

Notes

note

The thing object is passed by reference, so you may modify the object inside the callback function.

tip

If you're only interested in parsing spells, OnPlayerSpell will be a better alternative to OnThing, since you won't be having to parse hundreds of objects.

Code Example

example.lua
function OnPlayerSpell(thing) 
if (thing.Owner == TRIBE_BLUE) then
thing.Model = M_SPELL_FIRESTORM
end
end

OnDamage​

This event will trigger when a person receives damage. Visit this page for more information about the DamageEvent structure.

Parameters

TypeNameDescription
DamageEventeventThe damage event, this being a data structure.

Notes

caution

Not all damage sources will trigger this event.

Code Example

example.lua
function OnDamage(event)
if (event.DamagingPlayer == TRIBE_RED) then
event.Thing.u.Pers.Life = event.Thing.u.Pers.Life + math.floor(event.Damage * 2) -- heal the person
end
end

OnDeinit​

This event will trigger when a script is being removed, i.e script is no longer active.

Parameters None.

Notes

note

This event gives you the opportunity to clean up after yourself.

Code Example None.


OnLoadPalTables​

This event will trigger when the game generates the ghost and fade color tables.

Parameters

TypeNameDescription
UBYTElevelCurrent level being played.

Notes

warning

This event might become deprecated as there's no use for it any longer.

Code Examples None.


OnFrontEnd​

This event will trigger every time the user goes back into the main menu screen.

Parameters None.

Notes

caution

The event can only be called by a Parent script.

Code Examples

main.lua
function OnFrontEnd()
Log("User has entered the front end menu!")
end

OnFrameCredits​

It is expected of you to return a boolean, indicating whether you want the game to draw the original scrolling credits text. Returning a true value will tell the game not to draw the credits text.

Parameters None.

Notes

caution

The event can only be called by a Parent script.

Code Examples

main.lua
function OnFrameCredits()
-- Draw a red background
DrawBox(0,0,800,600,COLOUR(CLR_RED))
return true
end

OnFrontEndFrame​

Called every frame whilst inside front end menus. For example, main menu, level select menu, in-game pause menu, etc.

Parameters None.

Code Examples

main.lua
function OnFrontEndFrame()
-- Draw a red background
DrawBox(0,0,800,600,COLOUR(CLR_RED))
end