Skip to content
96LawDawg edited this page Jan 11, 2025 · 182 revisions

Functions Overview

VTT offers several functions for use in routines. Routines may be placed in buttons and most other widgets, and respond to user events such as clicks as well as to events generated by other routines. Before looking at the specific functions, however, this page offers background information about:

Then you can learn about the specific functions (listed in alphabetical order):

  • AUDIO to play a sound
  • CALL to execute a (sub-)routine
  • CANVAS to execute automations related to the canvas widget *
  • CLICK to trigger a mouse-click on widgets
  • CLONE to duplicate a widget
  • COUNT to determine the number of widgets in a collection or holder
  • DELETE to delete a widget
  • FLIP to flip widgets to their next face
  • FOREACH to iterate over an object, array, string, range of values, or collection
  • GET to get the property value of widgets
  • IF to execute operations based on a condition
  • INPUT to get a response from the user
  • LABEL to change the text of widgets
  • MOVE to move widgets into a holder
  • MOVEXY to move widgets to or on the surface (i.e. outside any holders)
  • RECALL to move back cards into the holder they are related to
  • ROTATE to change the rotation of widgets
  • SCORE to change the score in one or more seats *
  • SELECT to create a collection of widgets for subsequent operations
  • SET to change the property value of widgets
  • SHUFFLE to rearrange the stacking order of widgets randomly
  • SORT to rearrange the stacking order of widgets by order
  • SWAPHANDS to swap widgets in a collection of seats
  • TIMER to execute automations related to the timer widget *
  • TURN to change whose turn it is in a game from among participating seats *
  • VAR to set one or more variables directly *

*CANVAS, SCORE, TIMER, and TURN are functions directly related to one specific widget type. They were created according to the need of the composed widgets created for canvas, scoreboards, timers, and seats.

In addition, a special parameter, skip, is provided to skip any of these operations under a given condition. This function is deprecated and should not be used in new games, as the IF statement provides better functionality and is easier to understand.

Link to code implementation of widgets.

Routines

A routine is a sequence of operations that is executed when a specific action happens. There are several kinds of predefined routines, and you can also define arbitrary routines (all of which must end in the string Routine) for use with the CALL function. The predefined routine names are discussed in more detail below.

An operation is either an invocation of one of the functions listed above, and detailed below, or it is a "var" statement. "var" statements and the dynamic expressions used below are employed to define and use variables inside a routine. They are described in detail in the section on Dynamic Expressions.

Many routines operate on a collection of widgets (which may, of course, contain just a single widget). Collections are discussed further below.

Here's what flipping the top card of a holder to its back side ("face") would look like in a button:

{
  "type": "button",
  "text": "Flip holder",
  "clickRoutine": [
    {
      "func": "FLIP",
      "holder": "<holderID>",
      "count": 1,
      "face": 0
    }
  ],
  "x": 758,
  "y": 721,
  "z": 11,
  "id": "2zye"
}

Each operation needs to be told the specific context in which it operates, so if you wanted to flip AND rotate the top card of a holder, the clickRoutine would be:

{
  "func": "FLIP",
  "holder": "<holderID>",
  "count": 1,
  "face": 0
},
{
  "func": "ROTATE",
  "holder": "<holderID>",
  "count": 1,
  "angle": 90
}

Oftentimes, you want to work with several items at once, like moving the entire card pile or dealing cards to multiple hands/holders. To this effect, some functions allow you to specify a collection or a holder parameter.

  • Use the holder parameter when you want to work with the content of one or more holders
  • Use the collection parameter when you want to work with the widgets themselves, rather than their content

To illustrate the difference:

//Rotate the content of a holder, leaving the holder as-is
{
    "func": "ROTATE"
    "holder": "<holderID>"
    "angle": 90
}

//Rotate the holder itself
{
    "func": "SELECT",
    "property": "id",
    "value": "<holderID>"
},
{
    "func": "ROTATE"
    "angle": 90
}

//Note that this is not working code, but just an illustration of principles

When working with holders, it is important to understand the concept of dropTarget: By default, a holder only allows Cards to be dropped into the holder. You can set dropTarget to some other criterion, or to empty in order to have the holder accept any type of widget. When using button operations that operate on a holder as a source (e.g. FLIP, MOVE, etc.), only those widgets that match the dropTarget are affected, leaving the other widgets inside the holder (where they could still be affected by players). You can also set dropTarget to a value that does not occur, thus preventing any drops into the holder.

If you'd like to better understand a routine, you can get detailed execution information as part of the JSON editor. The JSON editor is accessed by pressing Ctrl-J; instructions are available at Edit-Mode. At the bottom left of the window you will see the legend Show Routine Debug Output. Moving a pointer over this text will reveal a tree-formatted trace of all functions performed during the last routine execution (often but not always a button press). Each line marked with a triangle can be clicked to expand or compress its contents. For most functions, you can also view the original text of the JSON as well as the text after any variable substitutions (e.g. ${x}) have been performed, as well as the contents of all variables and collections after execution completes. For functions such as IF, FOREACH, CALL, and CLICK, as well as in certain other situations (such as enterRoutines being invoked) the expanded text will itself include a list of functions performed by that operation (e.g., in the case of FOREACH, the loopRoutine executions).

Previously, debugging was done using the debug property of each widget. The debug property is no longer a predefined property and will have no effect on the execution of your game.

Predefined Variables

Each routine begins with a number of predefined variables:

  • activeColors - array of colors of active players in the room
  • activePlayers - array of active players' names in the room
  • activeSeats - array of the id of every seat in the room with a seated player
  • mouseCoords - [x,y] array of mouse/cursor coordinates of player clicking the widget
  • playerColor - color of player clicking the widget
  • playerName - name of the player clicking the widget
  • seatID - id of the first seat the active player is in. Set to null if the player is not in a seat
  • seatIndex - index number of the seatID. Set to null if the player is not in a seat
  • thisID - id of the widget that contains the routine

Each routine begins with these predefined collections:

  • activeSeats - a collection consisting of all the seat id`s occupied by any player
  • playerSeats - a collection consisting of all the seat id`s that the active player is in
  • thisButton - a collection consisting of the widget that contains the routine

Predefined Routines

As noted above, all routines start with a number of predefined variables and collections. In addition, some of the predefined routines below provide additional variables and/or collections.

  • clickRoutine: A clickRoutine may be placed in any widget, and if that widget is clicked (and its clickable property is true), the clickRoutine will be executed. clickRoutines can also be executed by other routines or functions, even if the clickable property is false so long as the correct parameters are provided in the function. clickRoutines have no additional predefined variables or collections.
  • changeRoutine: A changeRoutine will be triggered whenever any property of the widget it is in changes. The routine will have preset variables property, oldValue and value, representing the property name together with its old and new values. In addition, you can define change routines that fire only when a particular property changes; a routine named fooChangeRoutine (note the capital C) will fire when the property foo of the containing widget changes.
  • gameStartRoutine: A gameStartRoutine is triggered once when a player loads a new game from the game shelf or public library, but not from a saved game in progress. The JSON in this routine will activate immediately and delays the players' ability to start using the room until the routine is finished. Note that because of the timing, the routine does not show up in the JSON Editor debug console. Also, you can have more than one of these routines in a room. They will execute in the order in which the widgets are loaded into the room.
  • globalUpdateRoutine: A globalUpdateRoutine will be triggered when any property of any widget changes. If you want to restrict execution to changes in a particular property, use <propertyName>GlobalUpdateRoutine (for example, ownerGlobalUpdateRoutine will fire only when the owner value of any widget changes so you could update a label with the count of player owned cards). This form is preferred since otherwise you will be receiving many notifications, for example when the x or y property of any widget changes. The general form will have preset variables widgetID, property, oldValue and value, representing the widget whose property has changed, the property name, and its old and new values, as well as a predefined collection widget containing the single widget whose id is widgetID. The form <propertyName>GlobalUpdateRoutine will receive the same presets, except that it will not receive a property variable.
  • enterRoutine: An enterRoutine will be called whenever a new child gets added to the widget it is in. The routine will have the preset variable oldParentID, referring to the previous parent of the child, and the preset collection child, containing the id of the new child. (Note that if the parent changes as a result of a programmatic action, this will work as [likely] expected. But if the parent changes as the result of a user dragging the widget, the old parent will be lost when the widget is "picked up", so that oldParentID will be null. One way around this problem is to add a parentChangeRoutine to the widget which stores a non-null old parent somewhere that the enterRoutine can find it.)
  • leaveRoutine: A leaveRoutine will be called whenever a child gets removed from the widget it is in. The routine will have the preset collection child, containing the id of the departing child. See the note below concerning when and how many times a leaveRoutine will activate.
  • loopRoutine: A loopRoutine forms the body of a FOREACH operation (see below). The details of the additional presets are described there.
  • thenRoutine / elseRoutine: These routines form the then and else branches of an IF operation. No additional presets are provided to these routines. See the description of the IF operation for details.

Custom routines which are names ending in Routine with some other arbitrary prefix, are intended for use with the CALL operation. The predefined variables and collections are described in the CALL documentation.

leaveRoutine: Due to issues from the original coding that will probably never be changed, leaveRoutine may activate multiple times for every event, thus making leaveRoutine complicated. The chart below illustrates some of those difficulties. One factor to consider is whether the holder has dropShadow set to true (the VTT default). If the holder makes piles, then the situation is further complicated because the pile is also a widget that will cause the routine to activate when it is created, deleted, or dragged into or out of the holder. The chart below assumes there are no piles. There are techniques to avoid these problems, but as a best practice, you should not use coding that relies on leaveRoutine activating only one time. For example, incrementing or decrementing a counter based on a leaveRoutine is not a good idea, but doing a complete recount of those widgets would be fine.

How Moved Into holder Out of holder Into holder with shadow Out of holder with shadow
Manually - 1 + 1* 2 + ?* 1 + 3*
SET parent - 1 - 1
MOVE - 2 - 2
MOVEXY n/a 1 n/a 1
RECALL - 2 - 2
DELETE n/a 1 n/a 1

1+1 (first time activates when widget is picked up; second time when majority of widget leaves holder)

2+? (activates twice for every time a shadow appears; if player holds onto widget and does not drop it but repeatedly moves it in and out of holder, routine activates twice each time)

1+3 (first time activates when widget is picked up; the other three times when majority of widget leaves holder)

Collections

A collection is, as its name implies, a collection of widgets. Collections can be created in two different ways.

  • A SELECT statement will create a collection and name it according to the collection parameter. If no collection parameter is provided, it will be named DEFAULT.
  • Alternatively, in some situations it may be preferable to create a collection "on the fly". Such a collection is an anonymous unnamed collection, and is available only within the statement in which it is defined. For example
  {
    "func": "SET",
    "collection": [ "widget1",
                    "widget2",
                    "widget3"
                   ],
    "property": "x",
    "value": 150
  }

will set the x property of each of the three named widgets to 150. If any of the strings in the array following the collection key does not name a widget, that string is silently ignored.


Comments

VTT supports comments inside of routines of all types and inside of functions. Buttons are available in the JSON Editor to help. For example, depending on where the cursor is placed in the routine, you can get the following placeholder comment entries:

"clickRoutine": [
    {
      "func": "CLICK",
      "comment": "Write a quick comment to make the operation more human-readable."
    },
    {
      "func": "CLONE"
    },
    "// Comment",
    {
      "func": "FOREACH",
      "loopRoutine": [
        {
          "func": "MOVE",
          "comment": "Write a quick comment to make the operation more human-readable."
        },
        "// Comment",
        {
          "func": "FLIP"
        }
      ]
    }
  ]

AUDIO

This function causes a sound to play. A url for the audio file is required. Audio will not play on any device until the user interacts with the webpage.

Parameters:

  • source: url - the url of the audio file. It can play an audio clip from another website, or audio assets can be uploaded through the JSON editor. (defaults to "")
  • maxVolume: number - the maximum volume is set by the game maker on a range from 0 to 1 where 1 is equal to 100%. The actual volume played will be the product of the game maker's maxVolume setting and the volume setting chosen by the player with the volume slider. The game maker can thus equalize the volume of all the sounds in their game, while the player still has some control over the overall volume. (defaults to 1)
  • length: milliseconds - length the audio clip should play in milliseconds. Null will play full duration. (defaults to null)
  • player: playerName - limits which player will hear the sound. Player also accepts arrays of names. Null which means every player hears the sound. (defaults to null)
  • count: number or "loop" - the number of times the sound clip will play. Defaults to 1. "loop" plays an infinite loop. If set to 0, sound will not play. If length is anything other than null, the count parameter is ignored.
  • silence: true/false - when true, all sound playing in the room is stopped. Defaults to false.
  • [type: deprecated. Including or excluding an audio type will not affect the AUDIO function. Note: iOS and Safari do not natively support ogg files.]
    {
      "func": "AUDIO",
      "source": "https://website.org/sounds/soundfile.mp3",
      "volume": 1,
      "player": "${playerName}"
    }

An example with an array for player. Only the 2 players in the array would hear the audio. An array of player names could also be created in a function and stored in a variable.

    {
      "func": "AUDIO",
      "source": "https://website.org/sounds/soundfile.mp3",
      "volume": 1,
      "player": ["${playerName}", "guest321"]
    }

CALL

This function allows the execution of a custom routine defined in the same or another widget. It is most useful for "bundling" a sequence of operations that you want to use several times in order to avoid redundancy and improve readability.

All collections and variables that exist at the time when the call is made are inherited by the sub-routine. Additional variables can be set ad-hoc using the arguments parameter.

Each CALL returns both a variable and a collection. The variable to be returned from the called routine is the variable named result within that routine. It is returned as the variable result in the caller unless the variable parameter (see below) is provided in the call. The collection returned from the called routine is always the collection result. Note that if the caller routine already has a collection named result, if the callee does not change result collection, it will be unchanged after the call completes. Conversely, if the callee does change result collection, the previous definition in the caller will have been overwritten upon return.

Parameters:

  • routine: routine name - specifies the name of the routine to execute (routine names must end with "Routine")
  • widget: widget id - specifies the widget that contains the routine (defaults to the current widget)
  • variable: variable name - this variable stores the value passed from the called sub-routine (defaults to "result")
  • return: true/false - if set to false, execution of subsequent statements in the routine containing the CALL will be skipped. That is, it will be as if the CALL had been the last statement in its routine. The default is true, so that execution will proceed normally after the CALL. Note that this execution process does not work for enterRoutines
  • arguments: JSON object - any properties of this object are passed as variables to the called routine (optional)
{
  "type": "button",
  "text": "Click me",
  "clickRoutine": [
    {
      "func": "CALL",
      "routine": "randomValueRoutine",
      "arguments": { 
        "min": -90,
        "max": 90
      }
    },
    {
      "func": "ROTATE",
      "holder": "<holderID>",
      "count": 999,
      "angle": "${result}"
    }
  ],
  "randomValueRoutine": [
    "var range = ${max} - ${min}",
    "var r = random",
    "var r = ${r} * ${range}",
    "var result = ${r} + ${min}"
  ],
  "x": 758,
  "y": 721,
  "z": 11,
  "id": "2zye"
}

This example shows the use of a sub-routine to calculate a random value in a given range (expressed by min and max) and then rotate all widgets in the given holder by this random value. Note that in the last step of the randomValueRoutine, the random value is stored in the variable "result" in order to pass it back to the clickRoutine, in which it is then used for the ROTATE operation. Note: for integer values, randInt or randRange would be easier to use.

CANVAS

This function simplifies the control of canvas widgets using routines. the mode parameter is what will determine which kind of automation is going to be executed. The CANVAS function allows you to choose a color to draw with, change colors in the color map and draw using automations.

Parameters:

  • canvas: canvas id (or an array)- specifies the target canvas (defaults to null)
  • collection: collection - specifies the collection of widgets to make changes to (defaults to DEFAULT collection)
  • color: string - ONLY used in mode "change" as the input of the new color (defaults to vtt blue)
  • mode: set/ inc/ dec/ change/ reset/ setPixel - specifies the mode to be applied to the canvas (the other parameters may be ignored depending on the mode)
    • set: uses the value to choose the active color of the color map with which the player can draw. Note that 0 is the first color in the color map used as the background color (it will loop in the color map if necessary) (color does not work in this mode)
    • inc / dec: uses "value" to choose the active color of the color map with which the player can draw (it will loop in the color map if necessary)
    • change: uses "color" as the new value for the color of index "value" in the color map (it will loop in the color map if necessary). If the canvas already contains pixels of the old color they will all be replaced by the new color
    • reset: set all pixels to the the first color of the color map erasing the canvas
    • setPixel: Add one pixel in position "x", "y" with the color of index "value" (color does not work in this mode).
  • value: number - only used as a reference to the index of a color in the color map (defaults to 1)
  • x and y: number - only used in mode setPixel to locate the place to draw pixel (defaults to 0). Must be positive number on the canvas based on the resolution. The max value of x and y is the same as resolution.

Mode change example:

 {   
      "func": "CANVAS",
      "canvas": "k8ek",
      "mode": "change",
      "color": "silver",
      "value": 3
 }

Mode setPixel example:

 {
      "canvas": "k8ek",
      "mode": "setPixel",
      "x": 50,
      "y": 50,
      "value": 3
  }

Code for the reset button in the composed widget:

{
  "type": "button",
  "id": "tqvl-Reset",
  "parent": "tqvl",
  "x": -50,
  "y": 0,
  "width": 50,
  "height": 50,
  "movable": false,
  "movableInEdit": false,
  "clickRoutine": [
    {
      "func": "CANVAS",
      "canvas": "${PROPERTY parent}",
      "mode": "reset"
    }
  ],
  "css": "border-radius: 50% 0% 0% 0%;  border-width: 1px;  --wcBorder: #555; --wcBorderOH: black; --wcMainOH: #0d2f5e; ",
  "text": "Reset"
}

Code for the color selection button in the composed widget:

{
  "type": "button",
  "id": "tqvl-Color",
  "parent": "tqvl",
  "x": -50,
  "y": 50,
  "width": 50,
  "height": 50,
  "movable": false,
  "movableInEdit": false,
  "clickRoutine": [
    "var parent = ${PROPERTY parent}",
    {
      "func": "CANVAS",
      "canvas": "${parent}",
      "mode": "inc",
      "value": 1
    },
    "var color = ${PROPERTY colorMap OF $parent} getIndex ${PROPERTY activeColor OF $parent}",
    {
      "func": "SET",
      "collection": "thisButton",
      "property": "color",
      "value": "${color}"
    }
  ],
  "color": "#1F5CA6",
  "css": "border-radius: 0% 0% 0% 50%;  border-width: 1px; background-color: var(--color);  --wcBorder: #555; --wcBorderOH: black  "
}

This section still lacks examples for setPixel mode and change mode. Set mode works pretty similar to inc and dec

CLICK

This function clicks widgets as if they were clicked by a player.

When a collection is applied with the count parameter, each object in the collection is clicked once before repeating the procedure.

Parameters:

  • collection: collection - specifies the collection of widgets to click (defaults to DEFAULT collection)
  • count: number - specifies how many times the click is triggered (defaults to 1)
  • mode: respect / ignoreClickable / ignoreClickRoutine / ignoreAll - specifies how to handle clicks on the widget (see below)
{
  "func": "CLICK",
  "collection": "myCollection",
  "count": 2
}

The mode parameter requires some explanation. In general, widgets have a clickable property, which indicates whether anything happens when the widget is clicked. They may also have a default function when clicked (for example, a card will be flipped, and a spinner spun). Finally, they may have a clickRoutine which, if present, overrides the default function. The mode parameter allows a finer level of control over the interactions among these features:

  • "mode": "respect": This is the default. If clickable is false, no action will be taken. Otherwise, the clickRoutine will be executed if present. If no clickRoutine is present, the default widget action will be performed.
  • "mode": "ignoreClickable": The setting of clickable is irrelevant. The clickRoutine will be executed if present. If no clickRoutine is present, the default widget action will be performed.
  • "mode": "ignoreClickRoutine": If clickable is false, no action will be taken. Otherwise, the default widget action will be performed. (That is, this is the same as "mode": "respect", but any clickRoutine will be ignored.)
  • "mode": "ignoreAll": The setting of clickable is irrelevant. The default widget action will be performed. (That is, this is the same as "mode": "ignoreClickable", but any clickRoutine will be ignored.)

These modes may be used, for example, to have a widget that is not clickable by the users but that you can still click with buttons, or to have a click routine in a spinner that can be ignored programmatically to just perform the basic spinner function. One common use is to allow a widget that already has a primary function on click (such as sitting in a seat or flipping a checker) to do that plus utilize additional functions. For example, to have a seat widget do this, put all the additional functions at the beginning and add an ignoreClickRoutine mode at the end. This causes the seat to CLICK itself a second time but the second time ignores all the additional JSON functions

"clickRoutine": [
    { -- any functions you want --    
    },
    {
      "func": "CLICK",
      "collection": "thisButton",
      "mode": "ignoreClickRoutine"
    }

CLONE

This function creates copies of all widgets in a given collection, replicating all properties of the original (except for id). Optionally, new properties can be added to each clone, and the location of the clones can be offset from the location of the original.

In addition, each clone is given a property clonedFrom: <id of original>.

Note that if widgets in the source collection have children, those children will not be cloned.

Parameters:

  • source: collection - specifies the input source for the cloning process (defaults to DEFAULT)
  • count: number - the number of copies of each original to create (default: 1)
  • xOffset: number - the x offset applied to the cloned widget(s) relative to the position of the original widget (default: 0). When "recursive":true, then only the x value of the root widgets are modified.
  • yOffset: number - the y offset applied to the cloned widget(s) relative to the position of the original widget (default: 0). When "recursive":true, then only the y value of the root widgets are modified.
  • properties: array of properties - properties to be set in each cloned widget. When "recursive":true, then only the properties of the root widgets are set.
  • recursive: true/false - if true, all descendants of the source will also be cloned (default: false)
  • collection: collection name - specifies a collection to receive all the widgets created by this command (defaults to DEFAULT). Note that this must be a named collection - an anonymous collection (array) does not make sense since this is an output collection. When "recursive":true, then only the root widgets are included in the collection.
{
  "func": "CLONE",
  "source": "myCollection",
  "xOffset": 20,
  "yOffset": 20,
  "properties": {
      "css": "background-color:red",
      "width": "${myComputedWidth}"
  },
  "collection": "myClones"
}

COUNT

This function determines the size of a collection and stores the result in a variable.

Parameters:

  • collection: collection - specifies the collection of widgets to counts (defaults to DEFAULT collection).
  • holder: holder id (or an array) - specifies the holder that contains the widgets to count (optional). When counting a holder, only child widgets that match the holder's dropTarget property are included. Note that the widgets specified here need not be holders.
  • owner: playerName - filters the widgets in the collection or holder to only count widgets owned by the specified player. The default value, null, results in no filtering by owner.
  • variable: variable name - specifies the variable to store the result in (defaults to variable "COUNT").

For example,

{
  "func": "COUNT",
  "collection": "myCollection",
  "variable": "myVariableName"
}

where myCollection contains the widgets holder1, deck1, and holder2, will return the size of the collection itself, namely 3. In contrast,

{
  "func": "COUNT",
  "holder": ["holder1", "deck1", "holder2"],
  "variable": "myVariableName"
}

will count the number of children of each of these widgets that match their dropTarget specification and return that value.

DELETE

This function removes all widgets in a given collection. It is primarily intended to remove cloned widgets, but can be used for any purpose.

Note that this function does not delete any children of the widgets being deleted; any such children will be changed to be on the tabletop rather than in their now-deleted parent.

Parameters:

  • collection: collection - specifies the collection containing the widgets to be deleted (defaults to DEFAULT)
{
  "func": "DELETE",
  "collection": "myCollection"
}

FLIP

This function flips cards and basic widgets to the given face number (for "normal" cards, 0 would be the back and 1 would be the front). If no parameter face is given, they will just be flipped to their "next" face, which is determined by the faceCycle property ("forward", "backward" or "random"). If the holder parameter is a seat, then only the widgets belonging to that seat will be flipped.

Parameters:

  • holder: holderID (or an array) - specifies the holder that contains the widgets to flip (optional)
  • collection: collection - specifies the collection of widgets to flip (defaults to DEFAULT collection)
  • count: number - limits the amount of flipped widgets (defaults to "all"). Can be 0 to flip none, "all" to flip every selected widget, a positive number to flip that many of the selected widgets, or a negative number to leave that many of the selected widgets not flipped.
  • face: number - specifies the target face number. When omitted, flips to the next or a random face as configured in the widgets faceCycle property
  • faceCycle: forward/backward/random - allows to temporarily override the faceCycle property for this operation
{
  "func": "FLIP",
  "collection": "myCollection",
  "faceCycle": "backward"
}
{
  "func": "FLIP",
  "holder": "<holderID>",
  "count": 0,
  "face": 0
}

FOREACH

This function allows for iteration over a collection, object, array, string, or range of values. The loopRoutine parameter specifies the actions to be taken.

If a parameter in is present as "in": "<element>", then <element> is assumed to be an object, an array, or a string. In each case, the loopRoutine is provided with a key and a value on each call. For an object, each key and value is taken from the keys and values in the object. For an array or a string, the key is the 0-origin position of the element, and the value is the element itself.

If a parameter range is present, it takes the format [start, end, step]. The loopRoutine is called once for each element of the resulting range, passing the range element as value. Each of start, end, and step can be numbers or variables. range also accepts a short form such as "range": 5 or "range": [5], where 5 is end and both start and step are automatically set to 1. If start and end are included but step is omitted, step is assumed to be 1 if start < end and -1 if start > end.

If a parameter collection is present, the loopRoutine will be called once for each widget in the collection. The routine will receive a variable, widgetID, and a DEFAULT collection that contains the one widget of the current iteration.

If in, collection, and range parameters are provided, in takes precedence over range, which takes precedence over collection. If none of these is supplied, the function will operate on the DEFAULT collection.

Note that the supplied values (key, value, widgetID, and the DEFAULT collection) in the loopRoutine are treated as local to that routine, and changes to them will not affect identically-named objects in the parent. However, any changes to other variables that are defined in the parent will survive the call and remain permanent.

Here is a simple example:

  "clickRoutine": [
    "var start = 0",
    "var end = 6",
    "var step = 2",
    {
      "func": "FOREACH",
      "range": [
        "${start}",
        "${end}",
        "${step}"
      ],
      "loopRoutine": [
        "var myResult = 'hello' + ${value}"
      ]
    }
  ]

The myResult variable will be set to "hello0", "hello2", "hello4", and "hello6" as the `loopRoutine' steps through each iteration.

As another example, suppose ${myArray} is an array of strings.

"clickRoutine": [
  "var string = ''",
  {
    "func": "FOREACH",
    "in": "${myArray}",
    "loopRoutine": [
      "var string = ${string} + ${value}"
    ]
  }
]

concatenates all the string in ${myArray} and returns the result in the variable string.

Finally, the routine

"clickRoutine": [
  {
    "func": "SELECT",
    "property": "myProperty",
    "collection": "myCollection"
  },
  {
    "func": "FOREACH",
    "collection": "myCollection",
    "loopRoutine": [
      {
        "func": "CALL",
        "routine": "myRoutine",
        "arguments":
          {
            "widget": "${widgetID}"
          }
      }
    ]
  }
]

invokes the routine named myRoutine in the current widget, passing it in turn each widget in the collection myCollection.

GET

This function reads a given property (default id) of a single widget in a collection, or determines an aggregated property value of multiple widgets in a collection, and stores the result in a variable.

Parameters:

  • collection: collection - specifies the collection of widgets to use (defaults to DEFAULT collection).
  • property: property name
    • Scalar value: In the form "property": "foobar", GET will return the value of the "foobar" property from the widget(s) in the collection.
    • Array value: In the form "property": ["css","default","background"], GET will return the value of the subproperty of an object from the widget(s) in the collection. In this example, it will return the value "red" if the css is: "css":{"default":{"background":"red"}}. The array form of GET uses the value at the 0 index position as the name of the property and subsequent values are layers within the object.
  • variable: variable name - specifies the variable to store the result in (defaults to the name of the property parameter).
  • aggregation: first / last / sum / average / median / min / max / array - specifies how the value is determined for multiple widgets (defaults to "first")
  • skipMissing: true / false - allows to skip properties that have no value (not even "" or 0)
{
  "func": "GET",
  "collection": "myCollection",
  "property": "width",
  "aggregation": "sum",
  "variable": "myVariableName"
}

IF

This function checks a condition (e.g. is x >= 10 ?) that is evaluated as true or false, and then branches into the corresponding thenRoutine or elseRoutine before continuing with the remaining operations in the current routine.

Typically, you specify one or two operands (like x and 10 in the example above) and their relation (like >=). Alternatively, you can use the condition parameter to evaluate something that is computed outside the IF operation.

Any variables or collections of the main routine are also available in the then/else routines and are affected by their operations as usual.

Parameters:

  • condition: number or string - a value that is evaluated as true or false
  • relation: < / <= / == / != / >= / > - the comparison operator for operand 1 & 2 (defaults to ==)
  • operand1: number or string - the value being compared to operand2
  • operand2: number or string - the value to compare against (omitted to compare against null)
  • thenRoutine: routine - the routine to execute if the condition evaluated as true
  • elseRoutine: routine - the routine to execute if the condition evaluated as false
"clickRoutine": [
    {
      "func": "IF",
      "operand1": "${aNumber}",
      "relation": ">=",
      "operand2": 4,
      "thenRoutine": [
        {
          "func": "SELECT",
          "property": "id",
          "mode": "set",
          "value": "flipThis"
        }
      ],
      "elseRoutine": [
        {
          "func": "SELECT",
          "property": "id",
          "mode": "set",
          "value": "flipThat"
        }
      ]
    },
    {
      "func": "FLIP"
    }
]

This example checks if the variable aNumber is equal or greater than 4. If yes, it selects widget "flipThis", else widget "flipThat". It then flips the selected widget.

INPUT

This function shows an overlay with input controls so you can ask the user for input. If the user presses the confirm button, the routine will continue and user input will be stored in the designated variables. If the user presses the cancel button, the routine stops complete there and no further commands in that JSON routine are executed. If both cancelButtonIcon and cancelButtonText are explicitly set to null, then the cancel button will be hidden and players cannot exit out of the overlay without making a selection or using the escape key.

Parameters:

  • cancelButtonIcon: name of VTT-Symbol - specifies an icon to be displayed on cancel button (defaults to null). Must match name of a VTT-Symbol. If used simultaneously with text, appears before text.
  • cancelButtonText: text - text shown in cancel button (defaults to "Cancel"). If both cancelButtonText and cancelButtonIcon are explicitly set to null, then the cancel button will not be display.
  • confirmButtonIcon: name of VTT-Symbol - specifies an icon to be displayed on confirm button (defaults to null). Must match name of a VTT-Symbol. If used simultaneously with text, appears before text.
  • confirmButtonText: text - text shown in cancel button (defaults to "Go"). Can be used simultaneously with icon.
  • header: text - specifies the header text displayed at the top of the overlay. Appears above a title, if used. Cannot be customized with css. Mainly retained for backwards compatibility.
  • fields: array of field definitions - specifies what type of input field to display and where to store the returned input if any.

The field types are listed below, along with field-specific parameters. In addition, there are parameters that are common to a group of fields; these are described below.

  • type:
    • checkbox: displays a checkbox - stores true or false
    • choose: displays images or faces of a widget - stores result as variable and as a collection
      • collection: text - the name of collection the widgets will be stored in
      • faces: array - if the mode is set to "faces", then this array limits the faces shown to the player
      • holder: id or array of ids - widgets in this holder will be displayed for players to choose from
      • max: number - the maximum number of selections the player can make
      • mode: _"widgets" or "faces" (defaults to "widgets) - specifies whether individual widgets or the faces on widgets will be displayed for players
      • propertyOverride: object - used to set a specific property/properties while the widgets are displayed. For example: {"activeFace": 1} can be used to show the face up side of cards that are face down in the room
      • scale: number - alters the size of the widgets as they are displayed in the overlay.
      • source: id or array of ids or a named collection - widgets to be displayed for players to choose from. If both source and holder paramaters are included, the source parameter will be ignored.
      • visibleChildWidgets: boolean or "all" - determines which child widgets of the source or holder widgets will be displayed. Defaults to false. When true, will display child widgets except those in a holder and matching the holder's dropTarget. When "all", will display all child widgets.
    • color: displays a color picker - stores a hex color code (e.g. for coloring gaming pieces or player colors). Note that the appearance of the color picker may vary among browsers and/or operating systems.
    • number: displays a number input field - stores numeric value
      • min: number - the lowest allowed value for a number input field using the built-in scrolling tool; users can type a lower value that will be stored in the variable
      • max: number - the highest allowed value for a number input field using the built-in scrolling tool; users can type a higher value that will be stored in the variable
    • palette:displays colored radio buttons-stores the selected value. Unlike the color field, this offers a consistent viewing experience across browsers and forces the players to choose from a curated palette of options.
      • colors: array - displays the color choices available to the player. Accepts most color formats (html-friendly, hex, rgb, rgba, hsl, hsla).
    • select: displays a dropdown - stores a string. See below for more detailed information about select.
      • options: array - the selectable options for a select dropdown:
        • value: string - the value that will be set to the variable when this option was selected by the player
        • text: string - the text that will be shown to the player for this option (the entry in the dropdown) - if omitted the value will be displayed instead
        • select: boolean - if set to true, that option will be the default value, and will be displayed in the input dialog.
    • string: displays a text input field - stores a string. Optionally may add a Javascript regular expression
      • regex: regex - will limit the user to responses that match the regular expression. For example, ^[0-9]+$ forces an entry consisting only of numbers.
      • regexHint: text - this is the prompt that players see if the response does not meet the regex criteria. If no hint is provided, a default prompt shows the regex and informs the player that the string needs to comply with it.
    • subtitle: displays text - displays text in the overlay to provide instructions or context. Can also be placed anywhere to provide visual variety and can be customized with css.
    • switch: displays a slider switch - stores "on" or "off"
    • text: displays text - displays text in the overlay to provide instructions or context. May not be customized with css.
    • title: displays text - displays text in the overlay to provide instructions or context. Can also be placed anywhere to provide visual variety and can be customized with css.

For those field types that accept input and return a value (checkbox, choose, color, number, string, select, and switch), the following additional parameters can be used.

  • label: string - to be displayed next to the input field
  • value: various the initial value for the input field (for checkbox: true = checked, false = not-checked; defaults to false; for choose the widget that is selected when the overlay opens; for switch: left = off, right = "on"; defaults to "off"; for select, specifies the initial value of the dropdown)
  • variable: variable name - specifies the variable in which to store the value/result.

For the select field, there is also an options field that defines the possibilities for what the user can scroll and select. The options field is an array of objects, and each object specifies an entry in the dropdown. An entry consists of a value, which specifies the string to be placed in the variable if that option is selected, together with the text to be displayed for that option. In addition, you can indicate which option will initially be displayed by declaring "selected": true inside that option. Note that if both "selected": true and value are used to define the starting option, then the information in value overrides "selected": true. The following example helps illustrate the point except that you would normally only use either "value": "en-US" or "selected": true and not both unless you use a dynamic property as the value and programmatically override the selected option:

{
  "func": "INPUT",
  "fields": [
   {
      "type": "select",
      "label": "Choose language",
      "variable": "language",
      "value": "en-US",
      "options": [
        {
          "value": "en-US",
          "text": "English",
          "selected": true
        },
        {
          "value": "de-DE",
          "text": "German"
        }
      ]
    }
  ]
}

For the remaining field types (subtitle, title, and text), the only parameter is

  • text: string - the text that will be shown to the player.

A complete example of an input statement follows:

{
  "func": "INPUT",
  "fields": [
   {
      "type": "title",
      "text": "A header text for the overlay.",
      "css": "background-color:var(--VTTblue);color:white;"
    },
    {
      "type": "text",
      "text": "Stay a while and listen!"
    },
    {
      "type": "checkbox",
      "label": "Do you want to shuffle?",
      "variable": "shuffle",
      "value": true
    },
    {
      "type": "choose",
      "label": "Pick a dice face",
      "source": [
        "dice1"
      ],
      "mode": "faces",
      "variable": "face"
    },
    {
      "type": "color",
      "label": "Which color would you like?",
      "variable": "myColor",
      "value": "${playerColor}"
    },
    {
      "type": "number",
      "label": "Which number do you like?",
      "variable": "myNumber",
      "value": 10,
      "min": 1,
      "max": 100
    },
    {
      "type": "string",
      "label": "Credit card?",
      "variable": "myCard",
      "value": "555-2483 63"
    },
    {
      "type": "select",
      "label": "Best Crypto",
      "variable": "crypto",
      "options": [
        {
          "value": "DOGE",
          "text": "Dogecoin"
        },
        {
          "value": "BTC",
          "text": "Bitcoin"
        }
      ]
    },
   {
     "type": "subtitle",
     "text": "Include Expansions:",
     "css": "background-color: purple;color:white;"
    },
    {
     "type": "switch",
     "label": "Rise of Khan",
     "variable": "includedeck",
     "value": "on"
    }
  ],
  "cancelButtonIcon": "cancel",
  "cancelButtonText": "Cancel",
  "confirmButtonIcon": "restart_alt",
  "confirmButtonText": "Restart Game"
}

LABEL

This function changes the text (property) of widgets.

Parameters:

  • label: labelID (or an array) - specifies the widget(s) to be affected
  • collection: collection - specifies the collection of widgets to change (defaults to DEFAULT collection)
  • mode: set / inc / dec / append - specifies how the value should be treated (defaults to set)
  • value: string or number - specifies the value to be applied (defaults to 0)

The mode can be one of "set", "inc", "dec", and "append" (if left out, it will default to "set"). Setting it to "inc" or "dec" will always treat the current value as a number (defaulting to 0 if it is not).

The value parameter can be a string or a number and if left out, it will default to 0.

{
  "func": "LABEL",
  "label": "<labelID>",
  "mode": "set",
  "value": 4
}

MOVE

This function moves widgets into a target holder. If the target of the move is an occupied seat, then the move will instead direct the widgets to the hand associated with the seat. In this case, if the hand is set to childPerOwner, the owner will be set to the player in the seat.

Parameters:

  • from: widgetID (or an array) - specifies the widget(s) that contains the widgets to move. In the typical case, this would be a holder, but could be any widget with child widgets. If from is not specified, then the "DEFAULT" collection will be moved.
  • collection: collection - specifies the collection that is to be moved (defaults to "DEFAULT"). When using a collection, omit the from parameter.
  • to: widgetID (or an array) - specifies the widget(s) that widgets should be moved into. In the typical case, this would be a holder or seats, but could be any widget.
  • count: number - limits the amount of moved widgets (defaults to 1). Can be 0 to move none, "all" to move every selected widget, a positive number to move that many of the selected widgets, or a negative number to leave that many of the selected widgets not moved.
  • fillTo: number - fills the target holders/seats up to this number (defaults to null). If specified, then count is ignored.
  • face: number - optionally sets the face of the moved widgets to the given value (see FLIP). If omitted, the widgets will be left as they are.

Note that both count and fillTo will move an entire group to one of the to widgets. If there are enough widgets remaining in the from source, then it will move to the next destination. The order that the function picks targets for moving to is not well understood, so if there are less widgets in the from source than are required, game designers may want to account for that in the JSON in some other way.

If the dropTarget property (when moving to a holder) does not match the widgets being moved, the widgets will become children of the holder, but will keep the original x,y coordinates. In other words, they will not follow the stackOffset rules for aligning child widgets.

{
  "func": "MOVE",
  "from": "<holderID>",
  "to": "<holderID>",
  "count": 0
}

MOVEXY

This function moves widgets to a specific position on the surface (i.e. outside any holders). In case the widgets are currently contained in another widget (e.g. pile or holder), they will be moved out before being moved to the given coordinates.

Parameters:

  • from: holderID (or an array) - specifies the holder that contains the widgets to move
  • collection: collection - not yet supported
  • count: number - limits the amount of moved widgets (defaults to 1). Can be 0 to move none, "all" to move every selected widget, a positive number to move that many of the selected widgets, or a negative number to leave that many of the selected widgets not moved.
  • x: number - the x position on the surface (defaults to 0)
  • y: number - the y position on the surface (defaults to 0)
  • resetOwner: true/false - specifies whether the owner property of the widget is reset to null (defaults to true)

The parameter z can optionally set the z-order of the widget. If omitted, the z-order will be determined automatically.

The parameter face can optionally set the face of the moved widgets to the given value (see FLIP). If omitted, the widgets will be left as they are.

Please note that the moved widgets can form piles as if they were moved by players. They will NOT be placed into any holders though, even if the coordinates match perfectly. Use MOVE for that.

{
  "func": "MOVEXY",
  "from": "<holderID>",
  "count": 2,
  "face": 0,
  "x": 100,
  "y": 100,
  "z": 100
}

RECALL

This functions moves cards back into the holder they are associated with via deck. All cards belonging to that deck will be moved to the holder. Do not use this operation on holders that have no deck!

Note that cards are the only widgets with a deck property. In case you add this property to other widgets, they would be affected by this operation as well.

Parameters:

  • excludeCollection: collection - specifies a collection of cards that will not be subject to recall (default: null).
  • holder: holderID (or an array)- specifies the holder that contains the cards to recall.
  • inHolder: true/false - determines whether cards that are not in holders are affected as well. The default is true causing all cards to be recalled. If set to false, cards that are in holders will not be recalled.
  • owned: true/false - determines whether cards owned by a player (the "owner" property is not null) are affected as well. The default is true, causing all cards of the deck to be recalled. If false then cards owned by players are not recalled.
{
  "func": "RECALL",
  "holder": "<holderID>",
  "owned": false
}

ROTATE

This function changes the rotation of widgets. If the holder parameter is a seat, then only the widgets belonging to that seat will be rotated.

Parameters:

  • holder: holderID (or an array) - specifies the holder that contains the widgets to rotate
  • collection: collection - specifies the collection of widgets to change (defaults to DEFAULT collection)
  • angle: number - specifies by how many degrees the widgets will be rotated (positive numbers indicate clockwise rotation; defaults to 90)
  • count: number - limits the amount of rotated widgets (defaults to 1). Can be 0 to rotate none, "all" to rotate every selected widget, a positive number to rotate that many of the selected widgets, or a negative number to leave that many of the selected widgets not rotated.
  • mode: set or add - specifies whether the rotation is changed by or set to the given angle (defaults to add)
{
  "func": "ROTATE",
  "holder": "<holderID>",
  "count": 1,
  "angle": 90,
  "mode": "add"
}

SCORE

This function modifies a property, named score by default, in one or more seats.

Parameters:

  • mode: set / inc / dec - specifies how the value should be treated (defaults to set)
  • property: property name. The property containing the score arrays (defaults to score)
  • seats: seat id (or array), or null (default). Specifies which seat or seats are to be affected. If null, specifies that every seat in the room should be affected.
  • round: integer / null (default). If integer, this is the 1-based index value of the score arrays to be changed. If null, will append a new round to the score of each affected seat before applying the specified operation.
  • value: number / null. The amount by which each score is to be affected. If null, value is 1 when mode is inc or dec, and 0 when mode is set.

If round exceeds the number of rounds for a particular seat, the missing rounds for that seat will be filled with zeros before the operation is performed. Note, however, that a null value for round will add a new scoring round to each seat without equalizing the number of rounds among the seats.

As an example, to add 1 to the scores in round 2 for seats Seat3 and Seat5, one could do:

{
  "func": "SCORE",
  "round": 2,
  "seats": ["Seat3", "Seat5"]
}

SCORE cannot be used to modify team scores directly; instead, you must modify the player scores and let the scoreboard compute the new team scores.

SCORE is used when using rounds. If the scoreboard is using totals only, use SET to change the score property.

It is not necessary to use SCORE when using a scoreboard. The scoreboard has a built-in scoring overlay that activates by default when the scoreboard is clicked. When using automation to change the scoreboard values, use SCORE.

SELECT

This function first identifies widgets that match the criteria given by the source, type, property, relation, value, and max parameters. The mode parameter then defines how that set of widgets gets used to determine the result of the SELECT function, which is returned in the collection given by the collection parameter (or the DEFAULT collection if there is no collection parameter). That collection is sorted as requested by the sortBy parameter.

Note that when selecting piles (e.g. by selecting all from the surface), their content is added to the collection instead of the pile widgets themselves. This greatly facilitates dealing with widgets without knowing whether they are currently stacked in a pile or not. If you want to actually SELECT a pile, look at the last example below.

Parameters:

  • source: all or collection - specifies the input source for the selection process (defaults to all)
  • type: widget type - limits the selection to widgets of the given type (defaults to all)
  • property: property name - specifices the property to match against the criteria
  • relation: < / <= / == / === / != / >= / > / in - specifies the comparator (defaults to ==). Note that VTT treats == as == which means that == does not work as a similar JavaScript expression would.
  • value: any type (array for relation in)- specifies the value(s) to compare against (defaults to null)
  • max: number - limits the amount of selected widgets from source (defaults to 999999 if omitted, so it is essentially unlimited)
  • collection: collection - specifies the collection to be created/changed (defaults to DEFAULT collection). Note that this must be a named collection - an anonymous collection (array) does not make sense since this is an output collection.
  • mode: set / add / remove / intersect - set (the default) replaces the contents of collection by the selected widgets. add extends collection by the selected widgets. remove removes from collection any selected widgets that are also in collection. Finally, intersect replaces collection by the set of selected widgets that are also in collection (that is, it removes from collection any selected widgets that are not in collection).
  • sortBy: allows to sort the collection, can be a property name, key object, or array keys (see key in SORT) - the collection is sorted AFTER adding elements to it
{
  "func": "SELECT",
  "source": "all",
  "property": "width",
  "relation": ">=",
  "value": 50,
  "max": 5,
  "collection": "myCollectionName",
  "mode": "set"
}
{
  "func": "SELECT",
  "type": "card",
  "property": "cardType",
  "relation": "in",
  "value": [ "type1", "type2" ]
}
{
  "func": "SELECT",
  "property": "parent",
  "value": "holderID",
  "mode": "set",
  "sortBy": {
    "key": "z",
    "reverse": true
  }
}

The following example shows how to SELECT all the piles in a room:

{
  "func": "SELECT",
  "type": "pile",
  "property": "type",
  "value": "pile"
}

SET

This function changes the given widgets' property.

Parameters:

  • collection: collection - specifies the collection of widgets to be affected (defaults to DEFAULT collection)
  • property: property name - specifies the property to be affected (defaults to "parent")
  • relation: '=' or any operation - specifies whether the values will be set or computed using the given operation
  • value: any type - specifies the value to apply (defaults to null)
{
  "func": "SET",
  "collection": "myCollection",
  "property": "width",
  "relation": "=",
  "value": 100
}
{
  "func": "SET",
  "collection": "myCollection",
  "property": "height",
  "relation": "+",
  "value": 20
}

SET can also be used to set the value of more complex objects and not just simple values. For example, to set the dropTarget:

{
  "func": "SET",
  "property": "dropTarget",
  "value": {
    "type": "card"
  }
}

Or to set inheritFrom:

{
  "func": "SET",
  "property": "inheritFrom",
  "value": {
    "${PROPERTY parent}": [
      "card"
    ]
  }
}

However, if the more complex object contains a predefined variable, such as thisID then when the new clickRoutine is passed, that variable will be converted to the id of the passing widget. To avoid that, create a custom property, such as "addThisRoutine", which contains all of the code to be put in the clickRoutine. Then use the following to SET it in the other widget while maintaining the variable as is:

{
  "func": "SET",
  "property": "clickRoutine",
  "value": "${PROPERTY addThisRoutine}"
}

SHUFFLE

This function "shuffles" widgets, i.e. randomizes their stacking order (z position)

If widgets with various rotations and types happen to be in a holder, they will simply end up in a different order but not re-aligned. It is recommended to use this operation on holders that auto-align their content. If the holder parameter is a seat, then only the widgets belonging to that seat will be shuffled.

Parameters:

  • holder: holderID (or an array) - specifies the holder that contains the widgets to shuffle
  • collection: collection - specifies the collection of widgets to shuffle (defaults to DEFAULT collection)
{
  "func": "SHUFFLE",
  "holder": "<holderID>"
}

SORT

This function rearranges widgets, i.e. it changes their stacking order (z position) according to the given sort criteria.

Widgets with null values are sorted to the bottom of a pile of widgets, and widgets with identical key values retain their relative stacking order.

If the sorted widgets are not in a pile or holder that arranges its child widgets, the sorted widgets may not appear to change at all - only the stacking order changes. It is recommended to use this operation on holders that auto-align their content. If the holder parameter is a seat, then only the widgets belonging to that seat will be sorted.

Parameters:

  • holder: holderID (or an array) - specifies the holder that contains the widgets to sort
  • collection: collection - specifies the collection of widgets to sort if no holder is specified (defaults to DEFAULT collection)
  • key: property name, key object, or array of property names and/or key objects - see below
  • reverse: true/false - reverse the order after sorting by key (defaults to false)
  • locales: special - see locales argument in JavaScript documentation
  • options: special - see options argument in JavaScript documentation
  • rearrange: true/false when set to false the widgets are not rearranged in the room, only the order in the collection changes (only applies when sorting a collection, defaults to true)

SORT key

In its simplest usage, key simply takes the name of a property as a string. The widgets will be sorted by the value of that property from lowest to highest.

{
  "func": "SORT",
  "holder": "<holderID>",
  "key": "<propertyName>"
}

To make a SORT button for a hand that will sort cards only for the player pressing the button, you can use the following to implement the predefined variable ${seatID} (which is the id of the seat of the player pressing the button):

{
    "func": "SORT",
    "holder": "${seatID}",
    "key": "rank"
}

If an array is provided, then each element is treated as a key. Keys are applied from the first array element to the last. Widgets will be sorted based on the first key in the array that returns sort values that are not considered equal (based on locales and options).

{
  "func": "SORT",
  "holder": "<holderID>",
  "key": [
    "<propertyName1>",
    "<propertyName2>"
  ]
}

Separate options for each key can be provided by providing an object as a key instead of just a property name. The property name is provided as key within the object. options and locales override any values set in the main function block. Unlike reverse in the main function block, reverse in the key object does not reverse the order of widgets with matching sort values. An array specifying the order that values should be sorted in can be provided in the key object as order. Any values found in the order array come before all other values. Key object and property names can be mixed in the same key array.

{
  "func": "SORT",
  "holder": "hand",
  "key": [
    {
      "key": "suit",
      "order": [
        "C",
        "D",
        "S",
        "H",
      ]
    },
   "rankA"
  ]
}

Important: The property referenced in key applies a standard string comparison unless the values are actually numbers. So if you want to compare numeric strings, either ensure they are padded with zeros ("02" or "002" rather than "2", because a string value of "11" is considered to be less than "2", as the first character of the string is of lower value) or use the "numeric" option as in the following example (numeric option does not sort negatives before positives):

{
  "func": "SORT",
  "holder": "<holderID>",
  "key": "<propertyName>",
  "reverse": false,
  "options": {
    "numeric": true
  }
}

SWAPHANDS

This function swap cards in the hands of the given collection of seats. This avoids the need for an intermediate location and to manage the MOVE of the cards manually.

When SWAPHANDS involves more than two seats, it is instead a rotation with each player passing their cards to the next player in order.

Parameters:

  • interval: integer - Used as specified below under direction to indicate how many positions each seat's hand is passed around the table (defaults to 1)
  • direction: forward/backward/random - specifies the way that the "next player" that each hand is passed to will be identified:
    • forward or backward: the active players from among the seats being considered (see seats) are sorted into a list in index order. The position of the next player in the list is the position of the current player in the list plus (or minus, in the case of backward) the value in turn. Computations are done modulo the length of the list.
    • random: the order of the seats is randomized with each seat passing to one other
  • source: all or collection - specifies the collection of seats involved in the swap (default is all). If the collection is named "all" but does not actually contain all occupied seats then all occupied seats will still be used.

The hand property on each seat in the given collection of source is used to identify the cards which will be passed, and also as the destination for cards which are received by that seat.

Example usage:

{
  "func": "SWAPHANDS"
}

TIMER

This function simplifies the control of timer widgets using routines. the mode parameter is what will determine which kind of automation is going to be executed. The TIMER function allows you to change the time in timers and pause or unpause them.

Parameters:

  • timer: timerID - specifies the timer to modify. If timerID is not the id of a timer, the operation will be ignored.
  • collection: collection - specifies the collection of timers to use if no timer is specified. Widgets in the collection that are not timers will be ignored. Defaults to DEFAULT collection.
  • mode: set/ inc/ dec/ pause/ start/ toggle/ reset - specifies the mode to be applied to the timer (the other parameters may be ignored depending on the mode) (defaults to toggle)
    • set: uses value as the new value of timer's milliseconds
    • inc / dec: increases or decreases timer's milliseconds by value
    • pause: sets timer's paused to true
    • start: sets timer's paused to false
    • toggle: toggle timer's paused between true and false
    • reset: sets timer's milliseconds to timer's start value and sets timer's paused to true
  • value: number/string - value in milliseconds to be applied by set/ inc/ dec. If a string is given, the value used will be the numeric value stored in a property with that name (thus for example "value": "start" will use the timer's start value). (defaults to 0)
  • seconds: number - similar to value but this parameter is converted to milliseconds by multiplying by 1000 before executing. Note that this value must be a number; there is no conversion of a string to a property name as there is for value. (defaults to 0)

Code for the reset button in the composed widget:

  "clickRoutine": [
    {
      "func": "TIMER",
      "timer": "${PROPERTY parent}",
      "mode": "reset"
    }

Code for the toggle button:

  "clickRoutine": [
    {
      "func": "TIMER",
      "timer": "${PROPERTY parent}"
    }
  ]

TURN

In a game with several seat widgets, this function can be used to change whose turn it is.

Parameters:

  • turn: This parameter, which should be an integer or one of the values "first" or "last", is used as specified below under turnCycle to choose the next player to move.
  • turnCycle: This string parameter specifies the way in which the next player will be selected:
    • forward or backward: the active players from among the seats being considered (see source, below) are sorted into a list in index order. The position of the next player in the list is the position of the current player in the list plus (or minus, in the case of backward) the value in turn. Computations are done modulo the length of the list.
    • random: chooses a player at random from among active seats. turn is ignored.
    • position: if turn = "first", chooses the active player with the smallest index. If turn = "last", chooses the active player with the largest index.
    • seat: sets the turn to the specified id of a seat
  • source: all or collection - specifies the collection of widgets from which the set of seats to be considered is taken. The default is all; that is, all occupied seats at the table are considered when deciding whose turn it is next. If a seat has "skipTurn":true, then that seat will not be included in TURN operation even if the seat is part of the source. If the collection is named "all" but does not actually contain all occupied seats then all occupied seats will still be used as the source.
  • collection: collection name - returns a collection containing the seat whose turn it is now (defaults to TURN). Note that this must be a named collection - an anonymous collection (array) does not make sense since this is an output collection.

VAR

This function can set multiple variables directly and simultaneously. For simple cases, use something like "var x = ${PROPERTY x}" see Variable Declarations. However, using this function, you can directly set any alphanumeric or Unicode inside of a string without worrying about escape sequences and you can also set arrays or object literals.

Parameters:

  • variables: object - specifies the variables and the values to be set.

Example:

  "func": "VAR",
  "variables": {
      "thisX": 4,
      "thatX": "${PROPERTY x OF anotherWidgetID}",
      "thisString": "You have ${COUNT} cards.",
      "someObject": {
         "key1": "value1",
         "key2": "value2"
      },
      "myArray": [
       1,
       5,
       9
      ]
    }

skip

skip is deprecated and should not be used in new games; IF should be used in its place. Some existing games may still use skip.

If the value of the skip parameter evaluates to true (pretty much everything but empty strings, zeros, false or null), this operation will be skipped. skip may be used as a parameter to any of the functions above.

Clone this wiki locally