Scripting Basics

You can enhance your packages by programming in JavaScript. There are multiple ways of using JavaScript in TabletopPlayground: you can attach scripts to in-game objects, object templates, or globally to a game state. You can also use a JavaScript console while creating states in the editor, or even while hosting a game!

Writing scripts

Your scripts need to be located in the “Scripts” subfolder of your package (find your packages in your in your install dir under TabletopPlayground/PersistentDownloadDirs). In that folder, you can find a “typings” folder with some files, most importantly “tp.d.ts”. This is a TypeScript file containing definitions and descriptions for the API. It can serve as an API documentation, and if you include it using /// <reference path="typings/tp.d.ts">/> as the first line in your scripts (edited in the Scripts directory of your package), our recommended script editor Visual Studio Code (VS Code) will give you autocompletion and show documentation in tooltips.

There are a few global variables that you can use to interact with the game: The world object has many methods for finding players and objects, including 3D queries for objects using various shapes (lines, boxes, spheres, etc.). It also has methods to draw points and lines in the world to help visualize and debug your scripts.

Then there’s globalEvents. It contains various hooks to which you can attach callback functions to trigger behavior when certain events happen in the game. For example, the following code will print a message to the JavaScript console whenever a player leaves the game: globalEvents.onPlayerLeft.add(function(player) {console.log("Didn't like " + player.getName() + " anyway");});

The last global variable is not available in the global script, or in the console. It can only be used in scripts attached to objects in game or object templates. refObject is the referenced object. It has lots of functions to manipulate the object or get information about it. Usually, you will want your object specific code to run when something happens with the object, so refObject also provides callback hooks. These callbacks always get the referenced object as first parameter. For example, the following code prints who released an object where, whenever any player releases it: refObject.onReleased.add(function(object, player) {console.log(player.getName() + " released at " + object.getPosition());});

Using scripting

The scripting UI elements (including the console) are active when you create game states in the editor. You can attach a global script to the game state in the session options, or to every object in their object properties. Objects also have a unique ID that you can find in their properties. You can use the id to get the object in scripts or the console with world.getObjectById.

When editing an object template in the editor, you can also attach a script in the object properties pane. The script will be used by default for all objects of that type, but it can be overridden by specifying a script for a particular object when creating a state. Objects in existing states are also not affected by changing the script of their object template.

When you create object scripts, you should include a different file than tp.d.ts in order to get proper tooltips for the refObject variable. For general object scripts, you can use /// <reference path="typings/game-object.d.ts">/> as the first line of your file. If you use special methods of particular object types, you can include their files instead of game-object.d.ts, for example card.d.ts if you write a script that is (only) used for cards.

While you are editing and testing your scripts, you’ll often want to reload them quickly in game. When you are editing game states, there are two additional entries in the context menu: “Reload Scripts” will reload and execute all configured scripts, but not change the current JavaScript context. “Reset Scripting” also reloads and executes all scripts, but discards the entire JavaScript context before, so scripts are executed in a clean environment just like when loading a game state.

Debugging and external consoles

When your scripts get more complex, you may want a way to step through your code in order to find errors. Or maybe you are used to the feature-packed JavaScript consoles of the Chrome Browser or VS Code? No problem! Tabletop Playground supports the V8 inspector protocol to connect external applications.

First, you have to execute world.startDebugMode(). You can run the command from the console or from a script, but remember that you should remove it from your scripts before you upload your package. Once the inspector protocol is running, you can connect the Chrome Dev Tools by going to the following URL in Chrome: devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=localhost:9229. You can now use the Chrome Dev Tools console in addition to the in-game console! Both have access to the same JavaScript context.

If you want to use the VS Code console or debugger, you have to configure the connection: go to the Debugger (bug icon in on the left), then open your launch.json by clicking on the small gear on the upper left. Paste the following configuration:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Inspector",
            "type": "node",
            "protocol": "inspector",
            "request": "attach",
            "address": "localhost",
            "port": 9229
        }
    ]
}

Save the new config, and press “Start debugging” (the green arrow next to the config button). The debug console from VS Code should now be connected. If you use VS Code to edit your files in the Scripts folder of the package, you can also set breakpoints that will halt execution and enable you to step through the code. You may need to reload your scripts after you start debugging for breakpoints to work.

Close Menu