Difference between revisions of "Scripting"

From The Official Visionaire Studio: Adventure Game Engine Wiki
(Created page with "== General == Visionaire 3.0 comes with a Scripting language which is a combination of Lua (http://www.lua.org) and a Visionaire Object Model. The object model is used to acc...")
 
 
(100 intermediate revisions by 4 users not shown)
Line 1: Line 1:
== General ==
+
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.
  
Visionaire 3.0 comes with a Scripting language which is a combination of Lua (http://www.lua.org) 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, ...) which can be manipulated through the scripting language.<br>
 
  
Online documentation about scripting Language:
+
== Lua ==
* Programming in Lua: http://www.lua.org/pil/index.html
+
Visionaire Studio currently uses Lua version 5.4.0.
* Reference Manual: http://www.lua.org/manual/5.1/
 
  
== Visionaire Object Model ==
+
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:
 +
<div style="float:right;margin:20px 0 30px 30px">[[File:Lua-logo.png]]</div>
 +
* Reference Manual: https://www.lua.org/manual/5.4/
 +
* Programming in Lua: https://www.lua.org/start.html
 +
* Lua tutorial: https://www.tutorialspoint.com/lua/index.htm
 +
* Learn Lua in 15 Minutes: https://tylerneylon.com/a/learn-lua/
  
All objects can be accessed and manipulated through the scripting language. All objects of the same type (e.g. scene or button) are stored in one table. The properties of an object can be accessed by defined fields for the specific table. All objects and its fields are documented in [[Data Structure 3.x|Visionaire Data Structure]].
 
  
The field types of the data structure are mapped to Lua types in the following way:
+
Our community member ''AFRLme'' wrote a basic Lua introduction which you can find in this wiki:
 +
* [[Basic_lua:_Index|Basic Lua: AFRLme's guide to Lua script]]
  
{| class="gruen" border="1"
 
| valign="top" align="center" |
 
'''Field Type'''
 
| valign="top" align="center" |
 
'''Lua Type'''
 
|-
 
| valign="top" |
 
t_link
 
| valign="top" |
 
userdata ([[#VisionaireObject|VisionaireObject]]) or string which describes the object path. See [[#Accessing_an_object|object access]] for description of the object path.
 
|-
 
| valign="top" |
 
t_links
 
| valign="top" |
 
table (array) with Visionaire Objects (userdata or string, see t_link above) entries, each entry referencing one Visionaire Object.
 
|-
 
| valign="top" |
 
t_int
 
| valign="top" |
 
number (integer)
 
|-
 
| valign="top" |
 
t_float
 
| valign="top" |
 
number
 
|-
 
| valign="top" |
 
t_bool
 
| valign="top" |
 
boolean
 
|-
 
| valign="top" |
 
t_point
 
| valign="top" |
 
table (with entries "x" and "y")
 
|-
 
| valign="top" |
 
t_rect
 
| valign="top" |
 
table (with entries "x", "y", "width" and "height")
 
|-
 
| valign="top" |
 
t_string
 
| valign="top" |
 
string
 
|-
 
| valign="top" |
 
t_path
 
| valign="top" |
 
string
 
|-
 
| valign="top" |
 
t_sprite
 
| valign="top" |
 
table (with entry "path" and optional entries "x", "y", "cutting" (t_rect) and "transparent" (t_point))
 
|-
 
| valign="top" |
 
t_vint
 
| valign="top" |
 
table with number (integer) entries
 
|-
 
| valign="top" |
 
t_vfloat
 
| valign="top" |
 
table with number (float) entries
 
|-
 
| valign="top" |
 
t_vpoint
 
| valign="top" |
 
table with t_point entries
 
|-
 
| valign="top" |
 
t_vrect
 
| valign="top" |
 
table with t_rect entries
 
|-
 
| valign="top" |
 
t_vstring
 
| valign="top" |
 
table with string entries
 
|-
 
| valign="top" |
 
t_vpath
 
| valign="top" |
 
table with t_path entries
 
|-
 
| valign="top" |
 
t_vsprite
 
| valign="top" |
 
table with t_sprite entries
 
|}
 
  
== Exported objects ==
+
== Visionaire object model ==
  
The following objects are exported to the Lua scripting environment:
+
Each Visionaire project is saved in a hierarchical [[Data_Structure|data structure]]. Every instance of an object of that data structure is a "VisionaireObject" (TVisObj). All objects of the same type (e.&nbsp;g. scene or button) are stored in one table (called e.&nbsp;g. "Scenes" or "Buttons").
* currentAction: a visionaire object which represents the action where the current script was called from.
 
* emptyObject: an empty visionaire object.
 
* game: the game object. This is the same as calling getObject("Game") but faster and easier to use.
 
  
== Exported constants ==
+
The properties of an object can be accessed by defined fields for the specific table. These fields can contain single values (e.&nbsp;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|data structure]] page. The different [[#Field types|field types]] are listed below.
  
The following contants are exported to the Lua scripting environment:
 
* all fields which are used to reference attributes of visionaire objects. The fields are all listed in the [[Data Structure 3.x|Visionaire Data Structure]] documentation. To reference a field use a 'V' and the field name. E.g. VDialogPartAvailable to reference the field DialogPartAvailable.
 
* all visionaire tables. These constants start with an 'e' and then the plural table name. E.g. for the table Action the constant is eActions.
 
* DIVIDING_POINT: a table with entries '''x''' and '''y''' which specifies a point which is used to separate multiple polygons. Usually a point list (t_vpoint field) can contain multiple polygons (e.g. ObjectPolygon which is used for the object boundaries). In this point list a point which is equal to DIVIDING_POINT marks the end of the current polygon.
 
* localAppDir: directory where the savegames (in the sub directory savegames), the messages.log file and possible dumps are written to. This directory is also used for the config.ini in case the project file is given as command line parameter for the player.
 
  
== VisionaireObject ==
+
=== Accessing objects and fields ===
  
Every instance of an object of the visionaire data structure is a VisionaireObject. With this object it is possible to read and manipulate the attributes of all objects.
+
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.
 +
<syntaxhighlight lang="lua">
 +
-- Examples of accessing a VisionaireObject by (a unique) name
 +
local char = Characters["hero"]
 +
local coins = Values["coins"]
  
The following methods are supported on a VisionaireObject (in alphabetical order):
+
-- 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
  
=== clearLink ===
+
-- Access a VisionaireObject by table index: get the first object in the "Characters" table
 +
local char = Characters[1]
 +
</syntaxhighlight>
  
Removes a link from the visionaire object. This is only a convenient method and has the same effect as calling setValue with emptyObject as value.
 
  
Lua Syntax:
+
Object properties are accessed through their fields:
<pre>clearLink(number)</pre>
+
<syntaxhighlight lang="lua">
*Arguments
+
-- Example of accessing a property of a VisionaireObject
;number
+
local char = Characters["hero"]
The field which specifies a link to be cleared. The field type must be t_link.
+
local pos = char.Position
  
=== getBool ===
+
-- This leads to the same result
 +
local pos = Characters["hero"].Position
  
Lua Syntax:
+
-- Get the integer value ("Int" field) of the "Value" object called "coins"
<pre>getBool(number)</pre>
+
local num_coins = Values["coins"].Int
*Arguments
 
;number
 
The field which specifies a boolean value. The field type must be t_bool.
 
*Return Values
 
;boolean
 
Current value of specified field.
 
  
Example:
+
-- The "game" object is directly accessible
local allowSkipText = game:getBool(VGameAlwaysAllowSkipText)
+
local scr_pos = game.ScrollPosition
 +
</syntaxhighlight>
  
=== getFloat ===
 
  
Lua Syntax:
+
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:
<pre>getFloat(number)</pre>
+
<syntaxhighlight lang="lua">
*Arguments
+
-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
;number
+
-- because the name is not unique; now access the different values by using the object path
The field which specifies a number value. The field type must be t_float.
+
local hero_num_coins = Characters["hero"].Values["coins"].Int
*Return Values
+
local villain_num_coins = Characters["villain"].Values["coins"].Int
;number
+
local cur_num_coins = game.CurrentCharacter.Values["coins"].Int
Current value of specified field.
 
  
=== getFloats ===
+
-- Object paths can be even longer
 +
local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"]
  
Lua Syntax:
+
-- If the condition name "door_closed" is unique in the project, the following leads to the same result
<pre>getFloats(number)</pre>
+
local door_state = Conditions["door_closed"]
*Arguments
+
</syntaxhighlight>
;number
 
The field which specifies a number list. The field type must be t_vfloat.
 
*Return Values
 
;table
 
Table with t_float entries representing the specified field.
 
  
=== getId ===
 
  
Lua Syntax:
+
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|data structure]] page:
<pre>getId()</pre>
+
<syntaxhighlight lang="lua">
* Return Values
+
-- Lower the brightness of a scene to 80%
;table
+
Scenes["kitchen"].Brightness = 80
A table with the fields '''tableId''' and '''id''' returning the table id and object id of the VisionaireObject.
 
  
Example:
+
-- Make the villain the playable character
-- writes to the log file if the animation with the name 'animname' (must be set before)
+
game.CurrentCharacter = Characters["villain"]
-- is a character animation
 
local anim = getObject("Animations[" .. animname .. "]")
 
if anim:getParent():getId().tableId == eOutfits then
 
  print("character animation")
 
else
 
  print("no character animation")
 
end
 
  
=== getInt ===
+
-- Set a condition to true
 +
Conditions["door_closed"].Value = true
  
Lua Syntax:
+
-- Change the integer value of a "Value" object
<pre>getInt(number)</pre>
+
Characters["hero"].Values["coins"].Int = 47
*Arguments
+
</syntaxhighlight>
;number
 
The field which specifies a number value. The field type must be t_int.
 
*Return Values
 
;number
 
Current value of specified field.
 
  
Example
 
local direction = getObject("Characters[Mother]"):getInt(VCharacterDirection)
 
  
=== getInts ===
+
=== Common VisionaireObject fields ===
  
Lua Syntax:
+
The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method):
<pre>getInts(number)</pre>
+
* <span class="inlinecode">id:</span> The internal id of the object (integer).
*Arguments
+
* <span class="inlinecode">name:</span> 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.
;number
+
* <span class="inlinecode">parent:</span> Returns the parent object (TVisObj).
The field which specifies a number list. The field type must be t_vint.
+
* <span class="inlinecode">tableId:</span> The id of the data structure table the object is part of (integer).
*Return Values
 
;table
 
Table with t_int entries representing the specified field.
 
  
=== getLink ===
 
  
Lua Syntax:
+
=== Field types ===
<pre>getLink(number)</pre>
 
*Arguments
 
;number
 
The field which specifies a link. The field type must be t_link.
 
*Return Values
 
;userdata (VisionaireObject)
 
The linked object or an empty object if no object is linked for this field.
 
  
=== getLinks ===
+
The field types of the data structure are mapped to Lua types in the following way:
  
Lua Syntax:
+
{| class="ts"
<pre>getLinks(number)</pre>
+
|-
*Arguments
+
! style="width:10%" | Field Type
;number
+
! style="width:5%" colspan="2" | Lua type/Structure
The field which specifies a link list. The field type must be t_links.
+
! Description
*Return Values
+
|-
;table (list of VisionaireObject)
+
| '''t_bool'''
Table containing all linked visionaire objects.
+
| colspan="2" | boolean
 
+
| true or false
=== getName ===
+
|-
 
+
| '''t_int'''
Lua Syntax:
+
| colspan="2" | number
<pre>getName()</pre>
+
| integer
* Return Values
+
|-
;string
+
| '''t_float'''
The internal name of the visionaire object. This is the name which is used to access the object and also shown in the editor. This name is not shown to the user in the game - therefor always a language dependent text is used.
+
| colspan="2" | number
 
+
| decimal
=== getObject ===
+
|-
 
+
| '''t_string'''
Lua Syntax:
+
| colspan="2" | string
<pre>getObject(string)</pre>
+
|
* Arguments
+
|-
;string
+
| '''t_path'''
Path to a Visionaire Object. The path has to start with a dot '.' and then a field name (field type must either be t_link or t_links). For t_links fields you must specify an object name in brackets ('[',']'). For t_link fields there are no brackets. The path is relative to this object. See [[Scripting#Accessing_an_object|object access]] for description of the object path.
+
| colspan="2" | string
* Return Values
+
| file path
;userdata (VisionaireObject)
+
|-
The found visionaire object or an empty object if no object was found.
+
| rowspan="2" | '''t_point'''
* Example:
+
| rowspan="2" | table
local scene = getObject("Scenes[Bedroom]")
+
| style="width:15%" | x (int)
local deskCond = scene:getObject(".SceneObjects[Desk].ObjectCondition")
+
| x coordinate
 
+
|-
=== getParent ===
+
| y (int)
 
+
| y coordinate
Lua Syntax:
+
|-
<pre>getParent()</pre>
+
| rowspan="4" | '''t_rect'''
* Return Values
+
| rowspan="4" | table
;VisionaireObject
+
| x (int)
The parent object for this object. An object has always a parent which contains it - only the game object has no parent.
+
| x coordinate of top left corner
 
+
|-
=== getPath ===
+
| y (int)
 
+
| y coordinate of top left corner
Lua Syntax:
+
|-
<pre>getPath(number)</pre>
+
| width (int)
*Arguments
+
| width of rectangle
;number
+
|-
The field which specifies a path value. The field type must be t_path.
+
| height (int)
*Return Values
+
| height of rectangle
;string
+
|-
Current value of specified field. The path will be returned in unix format ('/' for directories) and relative to the .ved file.
+
| rowspan="5" | '''t_sprite'''
 
+
| rowspan="5" | table
=== getPaths ===
+
| path (str)
 
+
| relative path to image file
Lua Syntax:
+
|-
<pre>getPaths(number)</pre>
+
| position (t_point)
*Arguments
+
| sprite offset in case sprite is used in an animation
;number
+
|-
The field which specifies a path list. The field type must be t_vpath.
+
| transparency (int)
*Return Values
+
|
;table
+
|-
Table with t_path entries representing the specified field.
+
| transpcolor (int)
 
+
| transparent color
=== getPoint ===
+
|-
 
+
| pause (int)
Lua Syntax:
+
| pause value in milliseconds in case sprite is used in an animation
<pre>getPoint(number)</pre>
+
|-
*Arguments
+
| rowspan="3" | '''t_text'''
;number
+
| rowspan="3" | table
The field which specifies a point value. The field type must be t_point.
+
| text (str)
*Return Values
+
|
;table
+
|-
A table representing the value of the specified field. The table contains the entries '''x''' and '''y'''.
+
| sound (str)
 
+
| file path to a sound file for this text
=== getPoints ===
+
|-
 
+
| language (int)
Lua Syntax:
+
| id of the language of this text object
<pre>getPoints(number)</pre>
+
|-
*Arguments
+
| '''t_link'''
;number
+
| colspan="2" | string
The field which specifies a point list. The field type must be t_vpoint.
+
| a link to a VisionaireObject (TVisObj); the object will be returned on access; the link can be set with an object
*Return Values
+
|-
;table
+
| '''t_links'''
Table with t_point entries representing the specified field.
+
| colspan="2" | table
 
+
| a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects
=== getRect ===
+
|-
 
+
| '''t_vint'''
Lua Syntax:
+
| colspan="2" | table
<pre>getRect(number)</pre>
+
| table with number (integer) entries
*Arguments
+
|-
;number
+
| '''t_vfloat'''
The field which specifies a rectangle value. The field type must be t_rect.
+
| colspan="2" | table
*Return Values
+
| table with number (float) entries
;table
+
|-
A table representing the value of the specified field. The table contains the entries '''x''', '''y''', '''width''' and '''height'''.
+
| '''t_vstring'''
 
+
| colspan="2" | table
=== getRects ===
+
| table with string entries
 
+
|-
Lua Syntax:
+
| '''t_vpath'''
<pre>getRects(number)</pre>
+
| colspan="2" | table
*Arguments
+
| table with t_path entries
;number
+
|-
The field which specifies a rectangle list. The field type must be t_vrect.
+
| '''t_vpoint'''
*Return Values
+
| colspan="2" | table
;table (list of table with '''x''', '''y''', '''width''' and '''height''' entries)
+
| table with t_point entries
Table with t_rect entries representing the specified field.
+
|-
 
+
| '''t_vrect'''
=== getSprite ===
+
| colspan="2" | table
 
+
| table with t_rect entries
Lua Syntax:
+
|-
<pre>getStr(number)</pre>
+
| '''t_vsprite'''
*Arguments
+
| colspan="2" | table
;number
+
| table with t_sprite entries
The field which specifies a sprite value. The field type must be t_sprite.
+
|-
*Return Values
+
| '''t_vtext'''
;table
+
| colspan="2" | table
A table representing the value of the specified field. The table contains the entries '''path''', '''x''', '''y''', '''cutting''' (t_rect) and '''transparency'''.
+
| table with t_text entries
 
+
|}
=== getSprites ===
 
 
 
Lua Syntax:
 
<pre>getSprites(number)</pre>
 
*Arguments
 
;number
 
The field which specifies a sprite list. The field type must be t_vsprite.
 
*Return Values
 
;table
 
Table with t_sprite entries representing the specified field.
 
 
 
=== getStr ===
 
 
 
Lua Syntax:
 
<pre>getStr(number)</pre>
 
*Arguments
 
;number
 
The field which specifies a string value. The field type must be t_string.
 
*Return Values
 
;string
 
Current value of specified field.
 
 
 
=== isAnyObject ===
 
 
 
Lua Syntax:
 
<pre>isAnyObject()</pre>
 
* Return Values
 
;boolean
 
true if the object represents any object (isEmpty would return true because the object does not represent an object of the data structure). This is needed for actions where the user can set "[Any item]" for actions which should be executed in case an item was used.
 
 
 
=== isEmpty ===
 
 
 
Lua Syntax:
 
<pre>isEmpty()</pre>
 
* Return Values
 
;boolean
 
true if the object is empty, i.e. the VisionaireObject does not reference an object of the visionaire data structure.
 
 
 
=== setName ===
 
 
 
Sets the internal name of the visionaire object.
 
 
 
Lua Syntax:
 
<pre>setName(string)</pre>
 
*Arguments
 
;string
 
The new internal name.
 
 
 
=== setValue ===
 
 
 
Sets a field of the visionaire object. Note that only fields which are marked as 'Scriptable' in the [[Data Structure 3.x|Visionaire Data Structure]] documentation should be modified. If the field is not marked as scriptable then changes to this field are often not recognized (or sometimes not immediately). Further changes to these fields will usually not be stored in savegames for performance reasons.
 
 
 
Lua Syntax:
 
<pre>setValue(number, VARIANT, {flags=1, index = number})</pre>
 
* Arguments
 
;number
 
Data field which will be set.
 
;VARIANT
 
Value to set. The type of the value must match the type of the field. E.g. if the field type is t_int then the value type must be a number (int). If the field type is t_rect then the value type must be a table with the entries "x", "y", "width" and "height".
 
* Flags
 
;index
 
If specified then an existing list element at the given index will be modified. In this case the field type must be of a list-type (t_vint, t_links, ...).
 
 
 
* Examples
 
local tom = getObject("Characters[Tom]")
 
-- set character "tom" to position 100,300
 
tom:setValue(VCharacterPosition, {x=100,y=300})
 
 
 
local cond = getObject("Conditions[TV is on]")
 
cond:setValue(VConditionValue, true)
 
 
 
-- let the "dog" follow the current character
 
local dog = getObject("Characters[dog]")
 
local currentCharacter = getObject("Game.GameCurrentCharacter")
 
dog:setValue(VCharacterFollowCharacter, currentCharacter)
 
 
 
== Accessing an object ==
 
 
 
Use the [[GetObject|getObject]] command to access a visionaire object. Pass an object path to the command to get the visionaire object.
 
 
 
Examples:
 
local mother = getObject("Characters[Mother]")
 
 
 
local cond = getObject("Scenes[Forest].SceneObjects[Tree].ObjectCondition")
 
 
 
Whenever an object path is needed you can specify it the following way:<br>
 
1. start with a Table (as is shown in the table column of the Visionaire Data Structure).<br>
 
2. if this table is not "Game" (this table has only one object) then you have to write the name of the object inside bracktes ('[' and ']').<br>
 
3. either goto 7. or continue with 4.<br>
 
4. write a dot '.' and then a fieldname of this object (the field type must either be t_link or t_links).<br>
 
5. if the field type is t_links then goto 2., else goto 6.<br>
 
6. either goto 7. or goto 4. (access another link)<br>
 
7. done. A valid object is specified.<br>
 
  
Examples:
 
Game.CharacterLinks[Tom]
 
  
Scenes[Room].SceneObjects[start].SceneConditions[game started?]
+
=== The old-fashioned "longhand notation" ===
  
Characters[Tom].CharacterInterfaces[Tom-MI3]
+
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.
  
Alternatively, you can also access an object by its table-id and object-id. It can be specified by a tuple:<br>
+
Use the global [[Global Command: getObject|getObject]] command to access a VisionaireObject and [[VisionaireObject Commands|object commands]] to get and set property fields:
(table-id,object-id)<br>
+
<syntaxhighlight lang="lua">
 +
-- Example of accessing a VisionaireObject by (a unique) name
 +
local char = getObject("Characters[hero]")
  
Example:
+
-- Example of accessing a VisionaireObject by passing a tuple:
(0,6)
+
-- get the object with id=1 from the table with id=0 (characters table).
 +
local char = getObject("(0,1)")
  
Selects the object with id 6 from table 0 (characters).
+
-- 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]")
  
== Commands  ==
+
-- 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)
 +
</syntaxhighlight>
  
* [[VisObjectCmds|Object access]]
 
  
=== Commands for Visionaire Player only ===
+
== Add a script ==
  
* [[VisPlayerCmds|Player commands]]
+
[[File:Script.png|thumb|250px|Scripts section]]
 +
Scripts are generally added in the "Scripts" section of the editor. Each script has to be declared a <span class="inlinecode">Definition script</span> or an <span class="inlinecode">Execution script</span> 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.
  
{{i18n|Scripting}}
+
In your actions you can make use of scripts by using the [[Action_Parts#Call_script|Call script]] and the [[Action_Parts#Execute_a_script|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 [[Action_Parts#If_Lua_result|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 [[Conditions_and_Values#Conditions|Combined condition]].
 +
{{toc}}

Latest revision as of 12:54, 16 January 2024

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.