The Script Editor
To edit your game scripts, click on the “Mod Scripts” link in the Game Details page for your game (the same place where options such as the “Chat Log” and “Copy/Extend Game” are located). You will be presented with several features:
- A list of tabs along the top. Your game can have multiple scripts for ease of organization. Note that all scripts will still run in the same context, meaning that you shouldn’t have multiple scripts trying to overwrite the same values at the same time or you could get unintended results.
- A script code editor. You can use this editor or edit your scripts in an external editor of choice and then paste them in here.
- A Mod Output Console located along the bottom (see below).
Whenever you click the “Save Scripts” button, the sandbox for your game will be restarted (losing any in-memory data which hasn’t been persisted in the state object or in Roll20 objects). This also applies if you add a new script, delete a script, or toggle a script to enable/disable it.
The Mod Output Console
The Mod Output Console is the “window” into your scripts. Since Mod Scripts run in a sandbox, you don’t have direct access to them while they are running in order to view information on the script’s results or errors. The Mod Output Console displays this information out of the sandbox so you can view it while you are editing your scripts. All log() commands will show here, as well as any errors that are encountered during the execution of your scripts. For more information, see the article on Debugging scripts.
Mod Script Sandbox v1.5 only. Whenever possible, error messages include a context object so you can see which Roll20 object was involved (type and id).
Reactive Scripts: Listen to Events, Modify Objects
The first (and most simple type) of Mod Script usage is to react to changes on the tabletop, and then respond with additional functionality to the changed objects. This type of script is composed of a number of functions which listen to events that happen during the game. Then it will modify objects that are passed during those events, which will change what happens on the tabletop.
on("change:graphic", function(obj) {
obj.set({
left: obj.get("left") + 70
});
});As you can see, we created a simple on function which will be executed anytime the change:graphic event is heard. The function is passed the graphic object, obj. To make a change, we just modify obj using the set function – whatever properties we change will be detected and changed on the tabletop.
You must use set and get to set and get current values on objects or your changes will not be saved. (See the Objects reference for a listing of object types and their properties, as well as a listing of all events and what arguments each event is passed.)
Proactive Scripts: Do Things Without User Intervention
In addition to reacting to user events, you can also do things with Mod Scripts automatically that aren’t tied to a specific event from the players. For example, let’s have a token that patrols back and forth on the map.
Note: Although this type of script is not dependent on user interaction, the Mod Scripts for your game will still only run when at least one person is connected to your game.
on("ready", function() {
//Wait until the ready event fires so we know the game is completely loaded.
//Get a reference to our patrolling token.
var patroltoken = findObjs({_type: "graphic", name: "Guard A"})[0]; //We know there is a token in the Game called "Guard A".
var direction = -1*70; //Walk left 70 pixels.
var stepstaken = 0; //How many steps have we walked in the current direction?
setInterval(function() {
if(stepstaken > 3) {
//Switch directions!
direction = direction * -1; //will "flip" the direction we're walking
stepstaken = 0; //reset steps back to 0.
}
patroltoken.set("left", patroltoken.get("left") + direction); //walk!
stepstaken++;
}, 5000); //take an action every 5 seconds
});A Treatise on Asynchronous Functions
Some values are not available immediately. Character and handout fields such as bio, notes, gmnotes, and character _defaulttoken require a callback on get():
character.get("bio", function(bio) {
log(bio);
});sendChat can take an optional callback so roll results are returned to your script instead of posted to chat. onSheetWorkerCompleted runs after the current stack of sheet workers finishes.
Mod Script Sandbox v1.5 only. character.createToken is asynchronous because it must fetch _defaulttoken asynchronously. The created graphic is passed to a callback, not returned.
Keep in mind that prev on change events does not contain the text of those asynchronous fields. If you need the previous blob value, cache it yourself.