Scripting 101: How to get started
This tutorial is aimed at people who have coded before but don’t feel comfortable yet to dive straight into the API. It’s good to have some JavaScript knowledge, but not required.
Where do I put my script files?
Scripts have to be created outside of the Tabletop Playground Editor with your favourite editor. We recommend Visual Studio Code, a lightweight editor with code completion for all platforms. After you have created a new package in Tabletop Playground, simply navigate to your package folder and put your script files into the Scripts folder:
[Tabletop Playground Folder]\TabletopPlayground\PersistentDownloadDir\[Name of your package]\Scripts
Any .js script files in this folder can be selected in Tabletop Playground. You can also go to the package folder by clicking the folder icon in the top left when you have your package opened in the editor.
Global vs. object scripts
There are two way to include script files in your project. One global script and objects scripts which are directly associated with individual objects. Note that the following controls and the scripting console are by default only available when starting a preview from the editor. In order to use them in a regular game, go to the Settings, click “Game” and then “Show advanced interface settigns”. Then activate the first option “Scripting UI in Game”.
Global script
The global script can be added through the session options when editing a state for your project.

It is executed once, as soon as the corresponding state is loaded. It is loaded after all objects have been spawned, so it’s a good place to set up all your game related variables and logic.
Object scripts
An object script is directly attached to an object. It can be added either through a template or directly attached to an individual model when editing a state.


When an object is loaded into the world, any attached object script is executed (once). This happens after everything in the world is loaded (so all objects are there and after the global script has been run. If there is both a directly attached script as well as a template script, only the directly attached script gets executed.
Making stuff happen
As mentioned above, scripts are only executed once. So what you do in your script file is to set up any data and methods that you need and then tell Tabletop Playground when to call which of your functions (registering callbacks).
Don’t put any infinite loops inside the script! This will cause the script to hang and potentially crash Tabletop Playground.
For example for an object you can register an onGrab function which gets called by Tabletop Playground, whenever that object gets grabbed. Let’s look at some example code:
// include the api const { refObject } = require('@tabletop-playground/api'); // add a new function to be called by Tabletop Playground when // this object gets grabbed by any player refObject.onGrab.add( function(obj, player) { console.log("I got grabbed by", player.getName()); } );
You can also define the function separately, but you won’t get auto completion for parameters this way. It can help making your code more readable though if you’re writing a long complicated function, or if you want to use the same function in multiple places.
// include the api const { refObject } = require('@tabletop-playground/api'); // define our function grabCallBack = function(obj, player) { console.log("I got grabbed by", player.getName()); } // add a new function to be called by Tabletop Playground when // this object gets grabbed by any player refObject.onGrab.add(grabCallBack);
If you add this script file to an object, whenever any player picks it up, it will put the defined message into the script console:

You probably already noticed the usage of the variable refObject. It’s provided by Tabletop Playground and is the GameObject representation of your object, in the above example the chess piece. We can therefore make use of all the functionality outlined in the API. It’s only available when you attach a script directly to an object.
If you look at the definition of the onGrab function that we used to register our function, the function takes a GameObject (the object being grabbed) and a Player (the player grabbing the object) as parameter, which is why we have to add these parameters to our callback function grabCallBack.
So as a next step, let’s try to add a callback for onTick, which is called on every game tick, many times per second. Be careful what you do inside this method. If you put any complicated computations or queries in here, this can have a bad performance impact!
// include the api const { refObject } = require('@tabletop-playground/api'); // add a callback for on-tick refObject.onTick.add(function(object, deltaTime) { // let's launch the object slowly upwards like a rocket object.applyForce(new Vector(0, 0, 1000)); });
This should launch whatever piece you attach this to slowly upwards. Note that we omitted the second parameter for applyForce (useMass) since it defaults to false which is what we wanted in this situation. If your callback doesn’t seem to work, make sure that you provided all the required parameters.
Global Events
Next we are going to take a look the global script. In generally you want to put all code and callbacks here that is independent of individual objects. Let’s add some global events and try them out!
const { globalEvents } = require('@tabletop-playground/api'); // called whenever a chat message is sent globalEvents.onChatMessage.add(function(player, message) { // show a message on screen of the player who wrote the message player.showMessage("Should you really say something like \"" + message + "\""); }); // called whenever one ore more dice are rolled and sets all dice to six globalEvents.onDiceRolled.add(function(player, dice) { dice.forEach( function(d, index) { // set the dice to 6 (faces 0 to 5) d.setCurrentFace(5); } ); });

The world object
The world object allows you to interact with the world, which is a representation of the currently loaded level and everything that is included in it. It’s especially useful to find all or specific objects and players:
- Load in new objects
- Get a reference for a specific objects or a list of all existing objects
- Draw debug lines
- Line traces or sphere traces