Scripting

From The Official Visionaire Studio: Adventure Game Engine Wiki

Visionaire Studio comes with its own scripting language, which consists of, a combination of: Lua script and a Visionaire object model. The object model is used to access the Visionaire data structure in a convenient way. Almost every instance in Visionaire is represented as an object (e. g. scene, character, interface, ...), all of which can be accessed/manipulated through the scripting language.


Lua

Visionaire Studio currently uses Lua version 5.4.0.

If you want to learn more about the language, you may refer to the official online documentation on the Lua website or have a look at some tutorials:

Lua-logo.png


Our community member AFRLme wrote a basic Lua introduction which you can find in this wiki:


Visionaire object model

Each Visionaire project is saved in a hierarchical data structure. Every instance of an object of that data structure is a "VisionaireObject" (TVisObj). All objects of the same type (e. g. scene or button) are stored in one table (called e. g. "Scenes" or "Buttons").

The properties of an object can be accessed by defined fields for the specific table. These fields can contain single values (e. g. integers, strings) or tables of values as well as links to other VisionaireObjects or tables of links to VisionaireObjects. All objects and their fields are documented on the data structure page. The different field types are listed below.


Accessing objects and fields

The data structure tables are globally accessible. Object instances within the tables are usually accessed by their name, but it is also possible to use the table index. The "game" object is not contained in a table but directly accessible.

-- Examples of accessing a VisionaireObject by (a unique) name
local char = Characters["hero"]
local coins = Values["coins"]

-- The following syntax is also possible, but be aware that it only works for object names which don't contain
-- special characters or whitespaces (only A-Z, a-z, 0-9 and underscore allowed) and start with a letter
local char = Characters.hero

-- Access a VisionaireObject by table index: get the first object in the "Characters" table
local char = Characters[1]


Object properties are accessed through their fields:

-- Example of accessing a property of a VisionaireObject
local char = Characters["hero"]
local pos = char.Position

-- This leads to the same result
local pos = Characters["hero"].Position

-- Get the integer value ("Int" field) of the "Value" object called "coins"
local num_coins = Values["coins"].Int

-- The "game" object is directly accessible
local scr_pos = game.ScrollPosition


If other VisionaireObjects are linked in an object property, you can specify the complete object path to access them. This is especially helpful, if you have non-unique object names which cannot be accessed purely by their name:

-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
-- because the name is not unique; now access the different values by using the object path
local hero_num_coins = Characters["hero"].Values["coins"].Int
local villain_num_coins = Characters["villain"].Values["coins"].Int
local cur_num_coins = game.CurrentCharacter.Values["coins"].Int

-- Object paths can be even longer
local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"]

-- If the condition name "door_closed" is unique in the project, the following leads to the same result
local door_state = Conditions["door_closed"]


Writing a field value is just as easy. However, not all fields of the data structure can be changed through script. Please refer to the data structure page:

-- Lower the brightness of a scene to 80%
Scenes["kitchen"].Brightness = 80

-- Make the villain the playable character
game.CurrentCharacter = Characters["villain"]

-- Set a condition to true
Conditions["door_closed"].Value = true

-- Change the integer value of a "Value" object
Characters["hero"].Values["coins"].Int = 47


Common VisionaireObject fields

The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method):

  • id: The internal id of the object (integer).
  • name: The internal name of the object as defined in the editor (string). Not to be confused with the "Name" property (with capitalized "N") which is available for some objects and contains the multi-language object name used in the game.
  • parent: Returns the parent object (TVisObj).
  • tableId: The id of the data structure table the object is part of (integer).


Field types

The field types of the data structure are mapped to Lua types in the following way:

Field Type Lua type/Structure Description
t_bool boolean true or false
t_int number integer
t_float number decimal
t_string string
t_path string file path
t_point table x (int) x coordinate
y (int) y coordinate
t_rect table x (int) x coordinate of top left corner
y (int) y coordinate of top left corner
width (int) width of rectangle
height (int) height of rectangle
t_sprite table path (str) relative path to image file
position (t_point) sprite offset in case sprite is used in an animation
transparency (int)
transpcolor (int) transparent color
pause (int) pause value in milliseconds in case sprite is used in an animation
t_text table text (str)
sound (str) file path to a sound file for this text
language (int) id of the language of this text object
t_link string a link to a VisionaireObject (TVisObj); the object will be returned on access; the link can be set with an object
t_links table a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects
t_vint table table with number (integer) entries
t_vfloat table table with number (float) entries
t_vstring table table with string entries
t_vpath table table with t_path entries
t_vpoint table table with t_point entries
t_vrect table table with t_rect entries
t_vsprite table table with t_sprite entries
t_vtext table table with t_text entries


The old-fashioned "longhand notation"

While the syntax described in the chapter "Accessing objects and fields" is recommended, there is another way of accessing VisionaireObjects. It dates back to the early days of scripting in Visionaire and you may come across script examples which still use this old-fashioned way. It is usually referred to as the "longhand notation" - in contrast to the much simpler "shorthand" from above.

Use the global getObject command to access a VisionaireObject and object commands to get and set property fields:

-- Example of accessing a VisionaireObject by (a unique) name
local char = getObject("Characters[hero]")

-- Example of accessing a VisionaireObject by passing a tuple:
-- get the object with id=1 from the table with id=0 (characters table).
local char = getObject("(0,1)")

-- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table name
local door_state = getObject("Scenes[kitchen].SceneObjects[door].ObjectConditions[door_closed]")

-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
local is_closed = door_state:getBool(VConditionValue)
door_state:setValue(VConditionValue, true)


Add a script

Scripts section

Scripts are generally added in the "Scripts" section of the editor. Each script has to be declared a Definition script or an Execution script by (un)checking the option above the script editor (see image). A definition script is automatically run at game start, while an execution script has to be explicitly called.

In your actions you can make use of scripts by using the Call script and the Execute a script action parts, with the first one allowing you to select from your list of execution scripts and the second one expecting Lua code. You can use the If Lua result action part to build an "if…else" query using Lua code. Besides that, a Lua query can also be part of a Combined condition.