Mod Scripts: Utility Functions

Utility functions are provided to help you work with the Roll20 game space consistently. You can call a utility function from anywhere in your scripts (inside any event callback, for example). The full function reference is on Mod Scripts: Function Documentation.

Underscore.js

You have access to the Underscore.js library (via the _ global object) to help make things easier. Underscore provides helper functions for things like _.each (to iterate through an array of objects). Check out the Underscore documentation for more information.

Logging

log(message)

You can use this function to log output to the Mod Output Console on the Script Editor page. Useful for debugging your scripts and getting a better handle on what’s going on inside the Mod Script Sandbox.

on("change:graphic", function(obj) {
  log("Heard change for object ID: " + obj.id);
});

Mod Script Sandbox v1.5 only. Whenever possible, error messages include a context object naming the Roll20 object involved, for example:

ERROR: toBelow() must be called with a Roll20 graphic, text, or path Object. Called with [Roll20 character -NM0tVij02hIfnoTdihc].

Object Ordering

toFront(obj) and toBack(obj)

These two functions will move an object on the tabletop to the front (or back) of the layer it is currently on. Note that you must pass in an actual object, such as one you receive in an event callback or by calling getObj or findObjs.

toAbove(obj, target) and toBelow(obj, target)

Mod Script Sandbox v1.5 only. Place obj immediately above or below target in the stacking order. target may be a graphic, text, path, or pathv2 object, or the id of such an object. toFront and toBack take the object itself. Those same types also have instance methods toFront(), toBack(), toAbove(target), and toBelow(target).

Random Numbers

randomInteger(max)

Returns a random integer from 1 through max, using the same generator as Roll20 dice. Use this for dice. Math.floor(Math.random() * max) + 1 is evenly distributed for the sizes of dice people actually roll; modulo bias is a different problem (integer % n).

Math.random()

You can call Math.random() like normal in your Mod Scripts, trusting that the results will be random, because the “default” Math.random() in Javascript has been replaced with the cryptographically-secure PRNG that powers Roll20. So existing scripts that use Math.random() can be used with knowing that the results really are as close to random as it’s possible to get on a computer.

For a dice roll, prefer randomInteger(max). It is the same generator the dice engine uses.

Player Is GM

playerIsGM(playerid)

Returns whether that player is currently a GM. It follows promotions and “rejoin as player” without a restart. playerIsGM("API") is false: script-sent chat uses the player id "API", which is not a player in the game.

Character

setDefaultTokenForCharacter(character, token)

Sets the default token for the supplied Character Object to the details of the supplied Token Object. Both objects must already exist. This will overwrite any default token currently associated with the character.

Special Effects (FX)

spawnFx(x, y, type, pageid)

Spawns a brief effect at the location at x,y of type. If you omit the pageid or pass undefined, then the page the players are currently on (playerpageid in the Campaign object) will be used by default.

For built-in effects type should be a string and be one of the following: beam-color, bomb-color, breath-color, bubbling-color, burn-color, burst-color, explode-color, glow-color, missile-color, nova-color, splatter-color

Where “color” in the above is one of: acid, blood, charm, death, fire, frost, holy, magic, slime, smoke, water

For custom effects, type should be the ID of the custfx object for the custom effect.

spawnFxBetweenPoints(point1, point2, type, pageid)

Works the same as spawnFx, but instead of a single point you pass in two points, in the format {x: 100, y: 100}. For example: spawnFxBetweenPoints({x: 100, y: 100}, {x: 400, y: 400}, "beam-acid"). Beam, breath, and splatter effects travel between the two points. Coordinates are page pixels, the same left/top space as graphics. Window and door x/y use the inverted axis and are not these coordinates.

The following effect types must always use spawnFxBetweenPoints instead of spawnFx: beam-color, breath-color, splatter-color

Mod Script Sandbox v1.5 only. Beam-type effects point directly at point2 (an angle calculation bug is corrected).

spawnFxWithDefinition(x, y, definition, pageid)

Spawns an ad-hoc custom effect at x, y. definition is a JavaScript object, not a JSON string. The shape is the same as a Custom FX definition. If you omit pageid or pass undefined, the players’ current page (Campaign().get("playerpageid")) is used.

Jukebox Playlists

playJukeboxPlaylist(playlistid)

Takes the Folder ID (get it from the _jukeboxfolder property in the Campaign object) of the playlist, and will begin playing that playlist for everyone in the game.

stopJukeboxPlaylist()

Does not require any arguments, and will stop any playlist that is currently playing.

Miscellaneous

sendPing(left, top, pageid, playerid, moveAll, visibleTo)

Sends a ping to the tabletop (the same as holding the mouse button). left and top are page pixels. pageid is required. playerid is optional and is the fourth argument: the player the ping is attributed to. Omit it or pass a falsy value and the ping is attributed to "api" (yellow).

Pass true for moveAll to scroll players to that point. visibleTo limits who sees the ping: one player id, an array of ids, or a comma-delimited string. Omit it, or pass "", to ping everyone.

setTimeout delays in the example below are cleared if the sandbox restarts.

on("chat:message", function(msg) {
  if (msg.type !== "api" || msg.content.indexOf("!pingtest") !== 0) return;
  var players = findObjs({_type: "player"});
  if (players.length < 1) return;
  var player1 = players[0].id;
  var player2 = players.length > 1 ? players[1].id : player1;
  var allPlayerIDs = players.map(function(player) { return player.id; });
  var pageid = Campaign().get("playerpageid");
  // pageid is the 3rd argument; playerid is the 4th. null attributes the ping to "api".
  sendPing(300, 300, pageid, null, true);
  setTimeout(function() {
    // "" for visibleTo also pings everyone
    sendPing(1500, 500, pageid, msg.playerid, true, "");
  }, 1000);
  setTimeout(function() {
    sendPing(1200, 500, pageid, null, true, player1);
  }, 2000);
  setTimeout(function() {
    sendPing(900, 100, pageid, player2, true, [player1, player2]);
  }, 3000);
  setTimeout(function() {
    sendPing(300, 300, pageid, player1, true, allPlayerIDs.join());
  }, 4000);
});

A Note on Distances and Grids in Roll20

On a square grid, one unit is 70 pixels. The page’s snapping_increment is how many units each grid space is, scale_number is the distance of one unit, and scale_units is the unit name (often ft). Defaults are 1 unit = 5 ft = 1 square = 70 pixels. A GM can set 1 unit to 10 ft, or each square to 2 units (140 pixels).

Hex grids do not use that 70-pixel square. Window and door positions use an inverted y-axis; graphic left/top do not.

Was this article helpful?
14 out of 21 found this helpful