Difference between revisions of "Scripting"

From The Official Visionaire Studio: Adventure Game Engine Wiki
m
 
(17 intermediate revisions by 2 users not shown)
Line 1: Line 1:
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:
 +
<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/
  
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.
 
|-
 
| t_int
 
| number (integer)
 
|-
 
| t_float
 
| number (decimal)
 
|-
 
| t_bool
 
| boolean (<span class="green">true</span> ''or'' <span class="red">false</span>)
 
|-
 
| t_point
 
| table (with entries "x" and "y")
 
|-
 
| t_rect
 
| 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.&nbsp;g. scene or button) are stored in one table (called e.&nbsp;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.&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 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'').
 
<syntaxhighlight>clearLink(number)</syntaxhighlight>
 
  
 +
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
|-
 
| style="width: 10%;" | 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>
| style="width: 10%;" | number || The field which specifies a boolean value. The field type must be t_bool.
 
|}
 
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | 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:
<syntaxhighlight>local allowSkipText = game:getBool(VGameAlwaysAllowSkipText)</syntaxhighlight>
+
<syntaxhighlight lang="lua">
 +
-- Lower the brightness of a scene to 80%
 +
Scenes["kitchen"].Brightness = 80
  
 +
-- Make the villain the playable character
 +
game.CurrentCharacter = Characters["villain"]
  
=== getFloat ===
+
-- Set a condition to true
Returns a float (decimal) value.
+
Conditions["door_closed"].Value = true
<syntaxhighlight>getFloat(number)</syntaxhighlight>
 
  
 +
-- Change the integer value of a "Value" object
 +
Characters["hero"].Values["coins"].Int = 47
 +
</syntaxhighlight>
  
==== Arguments ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | number || The field which specifies a number value. The field type must be t_float.
 
|}
 
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | float || A decimal value. For example: 3.141
 
|}
 
  
 +
=== Common VisionaireObject fields ===
  
==== Example(s) ====
+
The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method):
<syntaxhighlight>
+
* <span class="inlinecode">id:</span> The internal id of the object (integer).
getObject("Game.GameCurrentCharacter"):getFloat(VCharacterSize)
+
* <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.''
 
<syntaxhighlight>getFloats(number)</syntaxhighlight>
 
  
 +
The field types of the data structure are mapped to Lua types in the following way:
  
==== Arguments ====
 
 
{| class="ts"
 
{| class="ts"
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a number list. The field type must be t_vfloat.
+
! style="width:10%" | Field Type
|}
+
! style="width:5%" colspan="2" | Lua type/Structure
==== Return Values ====
+
! Description
{| class="ts"
+
|-
 +
| '''t_bool'''
 +
| colspan="2" | boolean
 +
| true or false
 +
|-
 +
| '''t_int'''
 +
| colspan="2" | number
 +
| integer
 +
|-
 +
| '''t_float'''
 +
| colspan="2" | number
 +
| decimal
 
|-
 
|-
| style="width: 10%;" | table || A table containing multiple float (decimal) values.
+
| '''t_string'''
|}
+
| colspan="2" | string
 
+
|  
 
 
=== getId ===
 
Returns the ID of the specified table or object.
 
<syntaxhighlight>getId()</syntaxhighlight>
 
 
 
 
 
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table with the fields '''tableId''' and '''id''' returning the table id and object id of the VisionaireObject.
+
| '''t_path'''
|}
+
| colspan="2" | string
 
+
| file path
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
function checkAnimOwner(n)
 
n = getObject("Animations[" .. n .. "]")
 
-- + --
 
if n:getParent():getId().tableId == eOutfits then
 
  print( n:getName() .. " is a character animation" )
 
else
 
  print( n:getName() .. " is not a character animation" )
 
end
 
end
 
 
 
checkAnimOwner("pick_up") -- check if "pick_up" animation belongs to a character or not.
 
</syntaxhighlight>
 
 
 
 
 
=== getInt ===
 
Returns an integer (number) value.
 
<syntaxhighlight>getInt(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a number value. The field type must be t_int.
+
| rowspan="2" | '''t_point'''
|}
+
| rowspan="2" | table
==== Return Values ====
+
| style="width:15%" | x (int)
{| class="ts"
+
| x coordinate
 
|-
 
|-
| style="width: 10%;" | integer || An integer (number) value.
+
| y (int)
|}
+
| y coordinate
 
 
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
local direction = getObject("Characters[Tom]"):getInt(VCharacterDirection)
 
</syntaxhighlight>
 
 
 
 
 
=== getInts ===
 
Returns a table containing multiple integer (number) values. ''Iteration is required.''
 
<syntaxhighlight>getInts(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| number || The field which specifies a number list. The field type must be t_vint.
+
| rowspan="4" | '''t_rect'''
|}
+
| rowspan="4" | table
==== Return Values ====
+
| x (int)
{| class="ts"
+
| x coordinate of top left corner
 
|-
 
|-
| style="width: 10%;" | table || A table containing multiple integer (number) values.
+
| y (int)
|}
+
| y coordinate of top left corner
 
 
 
 
=== getLink ===
 
Returns a VisionaireObject.
 
<syntaxhighlight>getLink(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a link. The field type must be t_link.
+
| width (int)
|}
+
| width of rectangle
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | userdata || A VisionaireObject; ''or an empty object if no object is linked for this field.''
+
| height (int)
|}
+
| height of rectangle
 
 
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
game:getLink(VGameCurrentCharacter)
 
</syntaxhighlight>
 
 
 
 
 
=== getLinks ===
 
Returns a table containing multiple VisionaireObjects.
 
<syntaxhighlight>getLinks(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a link list. The field type must be t_links.
+
| rowspan="5" | '''t_sprite'''
|}
+
| rowspan="5" | table
==== Return Values ====
+
| path (str)
{| class="ts"
+
| relative path to image file
 
|-
 
|-
| style="width: 10%;" | table || Table containing multiple VisionaireObjects (links).
+
| position (t_point)
|}
+
| sprite offset in case sprite is used in an animation
 
 
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
local c_act = getObject("Characters[Tom]"):getLinks(VCharacterActions) -- store all actions associated with Tom into a variable
 
 
 
-- iterate the list by printing each link to the log.
 
for i = 1, #c_act do -- for i = 1 to list total do...
 
print( c_act[i]:getName() ) -- print the name of each action to the log based on current index value (i).
 
end
 
 
 
-- it's also possible to access a specific tables data value by including an index value.
 
print( c_act[1] ) -- print link inside of table index 1.
 
</syntaxhighlight>
 
 
 
 
 
=== getName ===
 
Returns the name of a VisionaireObject. ''This should not be confused with the names included in the properties tab of an object.''
 
<syntaxhighlight>getName()</syntaxhighlight>
 
 
 
 
 
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | "string" || The internal name of the visionaire object (editor). This is the name which is used to access the object.
+
| transparency (int)
|}
+
|  
 
 
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
game:getLink(VGameCurrentScene):getName() -- this would return the "string" name of the current scene.
 
</syntaxhighlight>
 
 
 
 
 
=== getObject ===
 
This is the most common method for accessing all the various fields & tables of the visionaire [[Data_Structure|data structure]].
 
<syntaxhighlight>getObject("string")</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | "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.
+
| transpcolor (int)
|}
+
| transparent color
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | userdata || A VisionaireObject; ''or an empty object if the return value is nil.''
+
| pause (int)
|}
+
| pause value in milliseconds in case sprite is used in an animation
 
 
 
 
==== 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"
 
 
|-
 
|-
| style="width: 10%;" | userdata || The parent object for the specified VisionaireObject. An object has always a parent which contains it; ''only the '''game''' objects have no parent.''
+
| rowspan="3" | '''t_text'''
|}
+
| rowspan="3" | table
 
+
| text (str)
 
+
|  
==== 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...
 
<syntaxhighlight>getPath(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a path value. The field type must be t_path.
+
| sound (str)
|}
+
| file path to a sound file for this text
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | "string" || The path will be returned in unix format ('/' for directories) and relative to the .ved file.
+
| language (int)
|}
+
| id of the language of this text object
 
 
 
 
=== getPaths ===
 
Returns a table containing multiple paths to media files. These could be images, animations, audio files, or video files, etc...
 
<syntaxhighlight>getPaths(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a path list. The field type must be t_vpath.
+
| '''t_link'''
|}
+
| colspan="2" | string
==== Return Values ====
+
| a link to a VisionaireObject (TVisObj); the object will be returned on access; the link can be set with an object
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing multiple paths. The paths will be returned in unix format ('/' for directories) and relative to the .ved file.
+
| '''t_links'''
|}
+
| colspan="2" | table
 
+
| a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects
 
 
=== getPoint ===
 
Returns a table containing '''x''' & '''y''' coordinate values.
 
<syntaxhighlight>getPoint(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a point value. The field type must be t_point.
+
| '''t_vint'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with number (integer) entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing '''x''' & '''y''' coordinate values.
+
| '''t_vfloat'''
|}
+
| colspan="2" | table
 
+
| table with number (float) entries
 
 
==== Example(s) ====
 
<syntaxhighlight>
 
animPos = getObject("ActiveAnimations[test]"):getPoint(VAnimationCurrentPosition) -- store current coordinate values into a variable
 
print(animPos.x, animPos.y) -- print the x & y values to the log.
 
</syntaxhighlight>
 
 
 
 
 
=== getPoints ===
 
Returns multiple tables containing '''x''' & '''y''' coordinate values.
 
<syntaxhighlight>getPoints(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a point list. The field type must be t_vpoint.
+
| '''t_vstring'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with string entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || Multiple tables containing '''x''' & '''y''' coordinate values.
+
| '''t_vpath'''
|}
+
| colspan="2" | table
 
+
| table with t_path entries
 
 
=== getPosition ===
 
Returns a table containing the current '''x''' & '''y''' coordinates of the specified sprite.
 
<syntaxhighlight>getPosition()</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a sprites position (x & y). The field type must be t_sprite.
+
| '''t_vpoint'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with t_point entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the current '''x''' & '''y''' coordinate values of the specified sprite.
+
| '''t_vrect'''
|}
+
| colspan="2" | table
 
+
| table with t_rect entries
 
 
<syntaxhighlight>
 
local obj = Objects["bottle"].ObjectSprite.SpriteSprite:getPosition() -- store position into a variable.
 
print(obj.x, obj.y) -- print the x, y coordinates of said object sprite to the log.
 
</syntaxhighlight>
 
 
 
 
 
=== getRect ===
 
Returns a table (rectangle) consisting of '''x''', '''y''', '''width''' & '''height'''. ''A rectangle is essentially a specified area in which something will be placed, such as: the dialog interface, or action text, etc.''
 
<syntaxhighlight>getRect(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a rectangle value. The field type must be t_rect.
+
| '''t_vsprite'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with t_sprite entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the entries '''x''', '''y''', '''width''' & '''height'''.
+
| '''t_vtext'''
 +
| colspan="2" | table
 +
| table with t_text entries
 
|}
 
|}
  
  
==== Example(s) ====
+
=== The old-fashioned "longhand notation" ===
<syntaxhighlight>
 
-- let's say I have a scene that is 1280x720px & I want to limit the playable area to specific portion of the scene...
 
getObject("Scenes[bedroom]"):setValue( VSceneScrollableArea, { x = 320, y = 180, width = 640, height = 360 } ) -- 50% of scene size from center of scene.
 
 
 
-- math: x = width ÷ 4, y = height ÷ 4, width = width ÷ 2, height = height ÷ 2
 
</syntaxhighlight>
 
 
 
  
=== getRects ===
+
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.
  
Lua Syntax:
+
Use the global [[Global Command: getObject|getObject]] command to access a VisionaireObject and [[VisionaireObject Commands|object commands]] to get and set property fields:
<syntaxhighlight>getRects(number)</syntaxhighlight>
+
<syntaxhighlight lang="lua">
*Arguments
+
-- Example of accessing a VisionaireObject by (a unique) name
;number
+
local char = getObject("Characters[hero]")
The field which specifies a rectangle list. The field type must be t_vrect.
 
*Return Values
 
;table (list of table with '''x''', '''y''', '''width''' and '''height''' entries)
 
Table with t_rect entries representing the specified field.
 
  
 +
-- 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)")
  
=== getSize ===
+
-- 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]")
  
Lua Syntax:
+
-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
<syntaxhighlight>getSize()</syntaxhighlight><br/>
+
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
*Arguments
+
local is_closed = door_state:getBool(VConditionValue)
;none
+
door_state:setValue(VConditionValue, true)
The field which specifies a sprites size (width & height). The field type must be t_sprite.
 
*Return Values
 
;table
 
Table with t_sprite entries representing the specified field.
 
 
 
<syntaxhighlight>
 
local obj = Objects["bottle"].ObjectSprite.SpriteSprite:getSize()
 
print(obj.x, obj.y)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getSprite ===
+
== Add a script ==
 
 
Lua Syntax:
 
<syntaxhighlight>getSprite(number)</syntaxhighlight>
 
*Arguments
 
;number
 
The field which specifies a sprite value. The field type must be t_sprite.
 
*Return Values
 
;table
 
See t_sprite field type.
 
 
 
 
 
=== getSprites ===
 
 
 
Lua Syntax:
 
<syntaxhighlight>getSprites(number)</syntaxhighlight>
 
*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:
 
<syntaxhighlight>getStr(number)</syntaxhighlight>
 
*Arguments
 
;number
 
The field which specifies a string value. The field type must be t_string.
 
*Return Values
 
;string
 
Current value of specified field.
 
 
 
Example:
 
<syntaxhighlight>
 
local str = getObject("Values[test]"):getStr(VValueString)
 
print(str)
 
</syntaxhighlight>
 
 
 
 
 
=== getTexts ===
 
 
 
Lua Syntax:
 
<syntaxhighlight>getTexts(number)</syntaxhighlight>
 
*Arguments
 
;number
 
The field which specifies a text languages value. The field type must be t_vtext.
 
*Return Values
 
;table
 
Table with t_text entries representing the specified field.
 
 
 
 
 
=== getTextStr ===
 
 
 
Lua Syntax:
 
<syntaxhighlight>getTextStr(number, <languageId>)</syntaxhighlight>
 
*Arguments
 
;number
 
The field which specifies a text languages value. The field type must be t_link to Text.
 
;languageId (optional)
 
The text will be returned for the language with this id. If parameter is missing then the text will be returned in the currently active language.
 
*Return Values
 
;string
 
Text string in given language.
 
* Example:
 
<syntaxhighlight>
 
local button = getObject("Buttons[Talk]")
 
local langEn = getObject("Languages[English]")
 
local langDe = getObject("Languages[German]")
 
-- print name of talk command in current language
 
print(button:getTextStr(VButtonName))
 
-- print English name of talk command
 
print(button:getTextStr(VButtonName, langEn:getId().id))
 
-- print German name of talk command
 
print(button:getTextStr(VButtonName, langDe:getId().id))
 
</syntaxhighlight>
 
 
 
 
 
=== isAnyObject ===
 
 
 
Lua Syntax:
 
<syntaxhighlight>isAnyObject()</syntaxhighlight>
 
* 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:
 
<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.
 
 
 
 
 
=== setName ===
 
 
 
Sets the internal name of the visionaire object.
 
 
 
Lua Syntax:
 
<syntaxhighlight>setName(string)</syntaxhighlight>
 
*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|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:
 
<syntaxhighlight>
 
-- set character "Tom" to position x(100), y(300)
 
local tom = getObject("Characters[Tom]")
 
tom:setValue(VCharacterPosition, {x=100,y=300})
 
</syntaxhighlight>
 
 
 
 
 
<syntaxhighlight>
 
-- set condition "TV is on" to true
 
local cond = getObject("Conditions[TV is on]")
 
cond:setValue(VConditionValue, true)
 
</syntaxhighlight>
 
 
 
 
 
<syntaxhighlight>
 
-- let the "dog" follow the current character
 
local dog = getObject("Characters[dog]")
 
local currentCharacter = getObject("Game.GameCurrentCharacter")
 
dog:setValue(VCharacterFollowCharacter, currentCharacter)
 
</syntaxhighlight>
 
 
 
 
 
== 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:
 
<syntaxhighlight>local mother = getObject("Characters[Mother]")</syntaxhighlight>
 
 
 
 
 
<syntaxhighlight>local cond = getObject("Scenes[Forest].SceneObjects[Tree].ObjectCondition")</syntaxhighlight>
 
 
 
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:
 
<syntaxhighlight>Game.CharacterLinks[Tom]</syntaxhighlight>
 
 
 
 
 
<syntaxhighlight>Scenes[Room].SceneObjects[start].SceneConditions[game started?]</syntaxhighlight>
 
 
 
 
 
<syntaxhighlight>Characters[Tom].CharacterInterfaces[Tom-MI3]</syntaxhighlight>
 
 
 
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:

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.