Visionaire Studio comes with its own scripting language, which consists of, a combination of: Lua script (http://www.lua.org) and a Visionaire Object Model. The object model is used to access the Visionaire [[Data_Structure|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 manipulated through the scripting language.
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.
----
Online documentation about the Lua scripting Language:
* Programming in Lua: http://www.lua.org/pil/index.html
* Reference Manual: http://www.lua.org/manual/5.1
* AFRLme's Guide to Lua Script: [[Basic_lua:_Index|Basic Lua]]
== Visionaire Object Model ==
== 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 the [[Data_Structure|data structure]] page.
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:
* Learn Lua in 15 Minutes: https://tylerneylon.com/a/learn-lua/
The field types of the data structure are mapped to Lua types in the following way:
{| class="ts"
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]]
! style="text-align:left" | Field Type !! style="text-align:left;width:80%" | Description
|-
| t_link
| userdata ([[#VisionaireObject|VisionaireObject]]) or string which describes the object path. See [[#Accessing_an_object|object access]] for description of the object path.
|-
| t_links
| table (array) with Visionaire Objects (userdata or string, see t_link above) entries, each entry referencing one Visionaire Object.
| table (with entries "x", "y", "width" and "height")
|-
| t_string
| "string"
|-
| t_text
| table with entries "text", "sound" (relative path to sound file for speech output) and "language" (language id).
|-
| t_path
| "string"
|-
| t_sprite
| table with entries "path" (relative path to image file), "position" (t_point for sprite offset in case sprite is used in an animation), "transparency", "transpcolor" (transparent color) and "pause" (pause value in msec in case sprite is used in an animation).
|-
| t_vint
| table with number (integer) entries
|-
| t_vfloat
| table with number (float) entries
|-
| t_vpoint
| table with t_point entries
|-
| t_vrect
| table with t_rect entries
|-
| t_vstring
| table with string entries
|-
| t_vtext
| table with t_text entries
|-
| t_vpath
| table with t_path entries
|-
| t_vsprite
| table with t_sprite entries
|}
== Exported objects ==
== Visionaire object model ==
The following objects are exported to the Lua scripting environment:
* 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.
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. g. scene or button) are stored in one table (called e. g. "Scenes" or "Buttons").
== Exported constants ==
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|data structure]] page. The different [[#Field types|field types]] are listed below.
The following constants 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|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 save games (in the sub directory save games), 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|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
-- Access a VisionaireObject by table index: get the first object in the "Characters" table
local char = Characters[1]
</syntaxhighlight>
=== clearLink ===
Removes a link from the visionaire object. A more convenient alternative to the emptyObject method (''see examples below'').
Object properties are accessed through their fields:
<syntaxhighlight lang="lua">
-- Example of accessing a property of a VisionaireObject
local char = Characters["hero"]
local pos = char.Position
==== Arguments ====
-- This leads to the same result
{| class="ts"
local pos = Characters["hero"].Position
|-
| number || The field which specifies a link to be cleared. The field type must be t_link.
|}
-- Get the integer value ("Int" field) of the "Value" object called "coins"
local num_coins = Values["coins"].Int
==== Example(s) ====
-- The "game" object is directly accessible
<syntaxhighlight>
local scr_pos = game.ScrollPosition
game:clearLink(VGameSpeechLanguage)
</syntaxhighlight>
''versus...''
<syntaxhighlight>
game:setValue(VGameSpeechLanguage, emptyObject)
</syntaxhighlight>
</syntaxhighlight>
=== getBool ===
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:
Returns a boolean value of <span class="green">true</span> ''or'' <span class="red">false</span>.
<syntaxhighlight lang="lua">
<syntaxhighlight>
-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
getBool(number)
-- because the name is not unique; now access the different values by using the object path
</syntaxhighlight>
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"]
==== Arguments ====
-- If the condition name "door_closed" is unique in the project, the following leads to the same result
{| class="ts"
local door_state = Conditions["door_closed"]
|-
</syntaxhighlight>
| number || The field which specifies a boolean value. The field type must be t_bool.
|}
==== Return Values ====
{| class="ts"
|-
| boolean || Current value of the specified field. Will return <span class="green">true</span> ''or'' <span class="red">false</span>.
|}
==== Example(s) ====
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:
* <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.
</syntaxhighlight>
* <span class="inlinecode">parent:</span> Returns the parent object (TVisObj).
* <span class="inlinecode">tableId:</span> The id of the data structure table the object is part of (integer).
=== getFloats ===
=== Field types ===
Returns a table containing multiple float (decimal) values. ''Iteration is required.''
| "string" || 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.
| '''t_links'''
|}
| colspan="2" | table
==== Return Values ====
| a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects
{| class="ts"
|-
|-
| userdata (VisionaireObject) || A VisionaireObject; ''or an empty object if the return value is nil.''
| '''t_vint'''
|}
| colspan="2" | table
| table with number (integer) entries
==== Example(s) ====
<syntaxhighlight>
local scene = getObject("Scenes[Bedroom]")
local deskCond = scene:getObject(".SceneObjects[Desk].ObjectCondition")
</syntaxhighlight>
=== getParent ===
Returns the parent object of the specified VisionaireObject.
<syntaxhighlight>getParent()</syntaxhighlight>
==== Return Values ====
{| class="ts"
|-
|-
| VisionaireObject || The parent object for this object. An object has always a parent which contains it; ''only the '''game''' objects have no parent.''
| '''t_vfloat'''
|}
| colspan="2" | table
| table with number (float) entries
==== Example(s) ====
<syntaxhighlight>
print( getObject("Actions[test]"):getParent() ) -- print the parent object that the "test" action belongs to.
</syntaxhighlight>
=== getPath ===
Returns the path to the media file. This could be an image, an animation, an audio file, or a video file, etc...
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:
<syntaxhighlight>isEmpty()</syntaxhighlight>
* Return Values
;boolean
true if the object is empty, i.e. the VisionaireObject does not reference an object of the visionaire data structure.
Sets a field of the visionaire object. Note that only fields which are marked as 'Scriptable' in the [[Data_Structure|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:
<syntaxhighlight>setValue(number, VARIANT, {flags=1, index = number})</syntaxhighlight>
* 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:
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.
<syntaxhighlight>
-- set character "Tom" to position x(100), y(300)
local tom = getObject("Characters[Tom]")
tom:setValue(VCharacterPosition, {x=100,y=300})
</syntaxhighlight>
Use the global [[Global Command: getObject|getObject]] command to access a VisionaireObject and [[VisionaireObject Commands|object commands]] to get and set property fields:
<syntaxhighlight lang="lua">
-- Example of accessing a VisionaireObject by (a unique) name
local char = getObject("Characters[hero]")
<syntaxhighlight>
-- Example of accessing a VisionaireObject by passing a tuple:
-- set condition "TV is on" to true
-- get the object with id=1 from the table with id=0 (characters table).
local cond = getObject("Conditions[TV is on]")
local char = getObject("(0,1)")
cond:setValue(VConditionValue, true)
</syntaxhighlight>
-- 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]")
<syntaxhighlight>
-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
-- let the "dog" follow the current character
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
local dog = getObject("Characters[dog]")
local is_closed = door_state:getBool(VConditionValue)
local currentCharacter = getObject("Game.GameCurrentCharacter")
Alternatively, you can also access an object by its table-id and object-id. It can be specified by a tuple:<br>
(table-id,object-id)<br>
Example:
<syntaxhighlight>(0,6)</syntaxhighlight>
Selects the object with id 6 from table 0 (characters).
== Editor Functions / Commands ==
* [[Common_Commands|Editor based functions]]
== Player Functions / 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.
* [[Player_Commands|Player based functions]]{{toc}}
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:
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) namelocalchar=Characters["hero"]localcoins=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 letterlocalchar=Characters.hero-- Access a VisionaireObject by table index: get the first object in the "Characters" tablelocalchar=Characters[1]
Object properties are accessed through their fields:
-- Example of accessing a property of a VisionaireObjectlocalchar=Characters["hero"]localpos=char.Position-- This leads to the same resultlocalpos=Characters["hero"].Position-- Get the integer value ("Int" field) of the "Value" object called "coins"localnum_coins=Values["coins"].Int-- The "game" object is directly accessiblelocalscr_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 pathlocalhero_num_coins=Characters["hero"].Values["coins"].Intlocalvillain_num_coins=Characters["villain"].Values["coins"].Intlocalcur_num_coins=game.CurrentCharacter.Values["coins"].Int-- Object paths can be even longerlocaldoor_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 resultlocaldoor_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 charactergame.CurrentCharacter=Characters["villain"]-- Set a condition to trueConditions["door_closed"].Value=true-- Change the integer value of a "Value" objectCharacters["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) namelocalchar=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).localchar=getObject("(0,1)")-- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table namelocaldoor_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)localis_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.