Difference between revisions of "Scripting"

From The Official Visionaire Studio: Adventure Game Engine Wiki
 
(4 intermediate revisions by the same user 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 accessed / 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]]
 
* Simon's [http://www.visionaire-studio.com/luadocs/ Luadocs]
 
  
  
== 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.
  
The field types of the data structure are mapped to Lua types in the following way:
+
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>
{| class="ts"
+
* Reference Manual: https://www.lua.org/manual/5.4/
|-
+
* Programming in Lua: https://www.lua.org/start.html
! style="text-align:left" | Field Type !! style="text-align:left;width:80%" | Description
+
* Lua tutorial: https://www.tutorialspoint.com/lua/index.htm
|-
+
* Learn Lua in 15 Minutes: https://tylerneylon.com/a/learn-lua/
| 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 ==
 
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.
 
  
 +
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]]
  
== Exported constants ==
 
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.
 
  
 +
== Visionaire object model ==
  
== VisionaireObject ==
+
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").
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 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 methods are supported on a VisionaireObject (in alphabetical order):
 
  
 +
=== Accessing objects and fields ===
  
=== clearLink ===
+
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.
Removes a link from the visionaire object. A more convenient alternative to the emptyObject method (''see examples below'').
+
<syntaxhighlight lang="lua">
<syntaxhighlight>clearLink(number)</syntaxhighlight>
+
-- Examples of accessing a VisionaireObject by (a unique) name
 
+
local char = Characters["hero"]
 +
local coins = Values["coins"]
  
==== Arguments ====
+
-- The following syntax is also possible, but be aware that it only works for object names which don't contain
{| class="ts"
+
-- special characters or whitespaces (only A-Z, a-z, 0-9 and underscore allowed) and start with a letter
|-
+
local char = Characters.hero
| style="width: 10%;" | number || The field which specifies a link to be cleared. The field type must be t_link.
 
|}
 
  
==== Example(s) ====
+
-- Access a VisionaireObject by table index: get the first object in the "Characters" table
<syntaxhighlight>
+
local char = Characters[1]
game:clearLink(VGameSpeechLanguage)
 
</syntaxhighlight>
 
''versus...''
 
<syntaxhighlight>
 
game:setValue(VGameSpeechLanguage, emptyObject)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getBool ===
+
Object properties are accessed through their fields:
Returns a boolean value of <span class="green">true</span> ''or'' <span class="red">false</span>.
+
<syntaxhighlight lang="lua">
<syntaxhighlight>
+
-- Example of accessing a property of a VisionaireObject
getBool(number)
+
local char = Characters["hero"]
</syntaxhighlight>
+
local pos = char.Position
  
 +
-- This leads to the same result
 +
local pos = Characters["hero"].Position
  
==== Arguments ====
+
-- Get the integer value ("Int" field) of the "Value" object called "coins"
{| class="ts"
+
local num_coins = Values["coins"].Int
|-
 
| 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) ====
+
-- The "game" object is directly accessible
<syntaxhighlight>
+
local scr_pos = game.ScrollPosition
print( game:getBool(VGameAlwaysAllowSkipText) ) -- print current boolean value of VGameAlwaysAllowSkipText to the log
 
game:setValue(VGameAlwaysAllowSkipText, true) -- set VGameAlwaysAllowSkipText to true
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getFloat ===
+
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 float (decimal) value.
 
<syntaxhighlight lang="lua">getFloat(number)</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
 
|}
 
 
 
==== Example(s) ====
 
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
getObject("Game.GameCurrentCharacter"):getFloat(VCharacterSize)
+
-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
</syntaxhighlight>
+
-- 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
=== getFloats ===
+
local cur_num_coins = game.CurrentCharacter.Values["coins"].Int
Returns a table containing multiple float (decimal) values. ''Iteration is required.''
 
<syntaxhighlight>getFloats(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | number || The field which specifies a number list. The field type must be t_vfloat.
 
|}
 
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | table || A table containing multiple float (decimal) values.
 
|}
 
 
 
=== 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.
 
|}
 
  
==== Example(s) ====
+
-- Object paths can be even longer
<syntaxhighlight>
+
local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"]
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.
+
-- If the condition name "door_closed" is unique in the project, the following leads to the same result
 +
local door_state = Conditions["door_closed"]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getInt ===
+
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:
Returns an integer (number) value.
+
<syntaxhighlight lang="lua">
<syntaxhighlight>getInt(number)</syntaxhighlight>
+
-- Lower the brightness of a scene to 80%
 +
Scenes["kitchen"].Brightness = 80
  
 +
-- Make the villain the playable character
 +
game.CurrentCharacter = Characters["villain"]
  
==== Arguments ====
+
-- Set a condition to true
{| class="ts"
+
Conditions["door_closed"].Value = true
|-
 
| style="width: 10%;" | number || The field which specifies a number value. The field type must be t_int.
 
|}
 
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | integer || An integer (number) value.
 
|}
 
  
==== Example(s) ====
+
-- Change the integer value of a "Value" object
<syntaxhighlight>
+
Characters["hero"].Values["coins"].Int = 47
local direction = getObject("Characters[Tom]"):getInt(VCharacterDirection)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getInts ===
+
=== Common VisionaireObject fields ===
Returns a table containing multiple integer (number) values. ''Iteration is required.''
 
<syntaxhighlight>getInts(number)</syntaxhighlight>
 
 
 
  
==== Arguments ====
+
The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method):
{| class="ts"
+
* <span class="inlinecode">id:</span> The internal id of the object (integer).
|-
+
* <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.
| style="width: 10%;" | number || The field which specifies a number list. The field type must be t_vint.
+
* <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).
  
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | table || A table containing multiple integer (number) values.
 
|}
 
  
=== getLink ===
+
=== Field types ===
Returns a VisionaireObject.
 
<syntaxhighlight>getLink(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 link. The field type must be t_link.
+
! style="width:10%" | Field Type
|}
+
! style="width:5%" colspan="2" | Lua type/Structure
==== Return Values ====
+
! Description
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | userdata || A VisionaireObject; ''or an empty object if no object is linked for this field.''
+
| '''t_bool'''
|}
+
| colspan="2" | boolean
 
+
| true or false
==== 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.
+
| '''t_int'''
|}
+
| colspan="2" | number
==== Return Values ====
+
| integer
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || Table containing multiple VisionaireObjects (links).
+
| '''t_float'''
|}
+
| colspan="2" | number
 
+
| decimal
==== 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.
+
| '''t_string'''
|}
+
| colspan="2" | string
 
+
|  
==== 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.
+
| '''t_path'''
|}
+
| colspan="2" | string
==== Return Values ====
+
| file path
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | userdata || A VisionaireObject; ''or an empty object if the return value is nil.''
+
| rowspan="2" | '''t_point'''
|}
+
| rowspan="2" | table
 
+
| style="width:15%" | x (int)
==== Example(s) ====
+
| x coordinate
<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.''
+
| y (int)
|}
+
| y coordinate
 
 
==== 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.
+
| rowspan="4" | '''t_rect'''
|}
+
| rowspan="4" | table
==== Return Values ====
+
| x (int)
{| class="ts"
+
| x coordinate of top left corner
 
|-
 
|-
| style="width: 10%;" | "string" || The path will be returned in unix format ('/' for directories) and relative to the .ved file.
+
| y (int)
|}
+
| y coordinate of top left corner
 
 
=== 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.
+
| width (int)
|}
+
| width of rectangle
==== Return Values ====
 
{| 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.
+
| height (int)
|}
+
| height of rectangle
 
 
=== 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.
+
| rowspan="5" | '''t_sprite'''
|}
+
| rowspan="5" | table
==== Return Values ====
+
| path (str)
{| class="ts"
+
| relative path to image file
 
|-
 
|-
| style="width: 10%;" | table || A table containing '''x''' & '''y''' coordinate values.
+
| position (t_point)
|}
+
| sprite offset in case sprite is used in an animation
 
 
==== 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.
+
| transparency (int)
|}
+
|  
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || Multiple tables containing '''x''' & '''y''' coordinate values.
+
| transpcolor (int)
|}
+
| transparent color
 
 
=== 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.
+
| pause (int)
|}
+
| pause value in milliseconds in case sprite is used in an animation
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the current '''x''' & '''y''' coordinate values of the specified sprite.
+
| rowspan="3" | '''t_text'''
|}
+
| rowspan="3" | table
 
+
| text (str)
<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.
+
| sound (str)
|}
+
| file path to a sound file for this text
==== Return Values ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the entries '''x''', '''y''', '''width''' & '''height'''.
+
| language (int)
|}
+
| id of the language of this text object
 
 
==== Example(s) ====
 
<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 ===
 
Returns multiple tables (rectangles) containing '''x''', '''y''', '''width''' & '''height''' values. ''A rectangle is essentially a specified area in which something will be placed, such as: the dialog interface, or action text, etc.''
 
<syntaxhighlight>getRects(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a rectangle list. The field type must be t_vrect.
+
| '''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 || Multiple tables containing '''x''', '''y''', '''width''' & '''height'''.
+
| '''t_links'''
|}
+
| colspan="2" | table
 
+
| a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects
=== getSize ===
 
Returns a table containing the width ('''x''') & height ('''y''') of the specified object sprite.
 
<syntaxhighlight>getSize()</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a sprites size (width & height). The field type must be t_sprite.
+
| '''t_vint'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with number (integer) entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the width ('''x''') & height ('''y''') entries of the specified object sprite.
+
| '''t_vfloat'''
|}
+
| colspan="2" | table
 
+
| table with number (float) entries
<syntaxhighlight>
 
local obj = Objects["bottle"].ObjectSprite.SpriteSprite:getSize() -- store size of object sprite into a variable.
 
print(obj.x, obj.y) -- print width & height of said object sprite to the log.
 
</syntaxhighlight>
 
 
 
 
 
=== getSprite ===
 
Returns a sprite. ''A sprite is an image; in other words this could consist of a static image or the current frame of an animation.''
 
<syntaxhighlight>getSprite(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a sprite value. The field type must be t_sprite.
+
| '''t_vstring'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with string entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || A table containing the 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 ms, in case sprite is used in an animation).
+
| '''t_vpath'''
|}
+
| colspan="2" | table
 
+
| table with t_path entries
==== Example(s) ====
 
<syntaxhighlight>
 
getObject("Objects[bottle]"):getLink(VObjectSprite):getSprite(VSpriteSprite)
 
</syntaxhighlight>
 
 
 
 
 
=== getSprites ===
 
Returns a table containing multiple sprites. ''A sprite is an image; in other words this could consist of a static image or the current frame of an animation.''
 
<syntaxhighlight>getSprites(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a sprite list. The field type must be t_vsprite.
+
| '''t_vpoint'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with t_point entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | table || Multiple tables containing the 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 ms, in case sprite is used in an animation).
+
| '''t_vrect'''
|}
+
| colspan="2" | table
 
+
| table with t_rect entries
=== getStr ===
 
Returns a "string" value. ''A "string" can consist of a mixture of plain text, numbers & symbols.''
 
<syntaxhighlight>getStr(number)</syntaxhighlight>
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | number || The field which specifies a string value. The field type must be t_string.
+
| '''t_vsprite'''
|}
+
| colspan="2" | table
==== Return Values ====
+
| table with t_sprite entries
{| class="ts"
 
 
|-
 
|-
| style="width: 10%;" | "string" || A "string" value consisting of a mixture of text, numbers & symbols.
+
| '''t_vtext'''
 +
| colspan="2" | table
 +
| table with t_text entries
 
|}
 
|}
 
==== Example(s) ====
 
<syntaxhighlight>
 
local str = getObject("Values[test]"):getStr(VValueString) -- store string value of "test" into a variable.
 
print(str) -- print said "string" to the log file.
 
</syntaxhighlight>
 
  
  
=== getTexts ===
+
=== The old-fashioned "longhand notation" ===
Returns a table containing multiple text (name) language values.
 
<syntaxhighlight>getTexts(number)</syntaxhighlight>
 
  
 +
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.
  
==== Arguments ====
+
Use the global [[Global Command: getObject|getObject]] command to access a VisionaireObject and [[VisionaireObject Commands|object commands]] to get and set property fields:
{| class="ts"
+
<syntaxhighlight lang="lua">
|-
+
-- Example of accessing a VisionaireObject by (a unique) name
| style="width: 10%;" | number || The field which specifies a text languages value. The field type must be t_vtext.
+
local char = getObject("Characters[hero]")
|}
 
==== Return Values ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | table || A table containing multiple text (name) language entries for the specified VisionaireObject.
 
|}
 
  
==== Example(s) ====
+
-- Example of accessing a VisionaireObject by passing a tuple:
''iterate through texts belonging to a specified object (shorthand).''
+
-- get the object with id=1 from the table with id=0 (characters table).
<syntaxhighlight>
+
local char = getObject("(0,1)")
local txt = Objects["test"].ObjectName.TextTextLanguages
 
  
for i = 1, #txt do
+
-- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table name
if txt[i].language == Languages["English"]:getId().id then
+
local door_state = getObject("Scenes[kitchen].SceneObjects[door].ObjectConditions[door_closed]")
  print( txt[i].text )
 
end
 
end
 
</syntaxhighlight>
 
''same as above, but using the getObject method (longhand).''
 
<syntaxhighlight>
 
local txt = getObject("Objects[test].ObjectName"):getTexts(VTextTextLanguages)
 
  
for i = 1, #txt do
+
-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
if txt[i].language == getObject("Languages[English]"):getId().id then
+
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
  print( txt[i].text )
+
local is_closed = door_state:getBool(VConditionValue)
end
+
door_state:setValue(VConditionValue, true)
end
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
  
=== getTextStr ===
+
== Add a script ==
Returns the text belonging to the specified object; ''based on specified language.''
 
<syntaxhighlight>getTextStr(number, <languageId>)</syntaxhighlight>
 
 
 
 
 
 
 
==== Arguments ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | number || The field which specifies a text languages value. The field type must be t_link to Text.
 
|-
 
| style="width: 10%;" | languageId || 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 ====
 
{| class="ts"
 
|-
 
| style="width: 10%;" | "string" || The "string" value of the specified text of a VisionaireObject belonging to the given languageId.
 
|}
 
 
 
==== Example(s) ====
 
''get the text belonging to the currently active language for the specified object.''
 
<syntaxhighlight>
 
getObject("Buttons[talk]"):getTextStr(VButtonName)
 
</syntaxhighlight>
 
''get the text belong to the given language for the the specified object.''
 
<syntaxhighlight>
 
getObject("Buttons[talk]"):getTextStr( VButtonName, getObject("Languages[English]"):getId().id ) -- get text belong to "English" language.
 
getObject("Buttons[talk]"):getTextStr( VButtonName, getObject("Languages[German]"):getId().id ) -- get text belong to "German" language.
 
</syntaxhighlight>
 
 
 
 
 
=== isAnyObject ===
 
Returns a boolean value of <span class="green">true</span> ''or'' <span class="red">false</span>,  depending on whether or not VisionaireObject is returned???? (not actually sure about this one - never used it before).
 
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]]
+
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}}
 
{{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.