Character Vault
Any Concept / Any System
Compendium
Your System Come To Life
Roll20 for Android
Streamlined for your Tablet
Roll20 for iPad
Streamlined for your Tablet

Personal tools

Difference between revisions of "Mod:Utility Functions"

From Roll20 Wiki

Jump to: navigation, search
m (Jukebox Playlists)
 
(15 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{apibox}}
+
{{revdate}}{{HCbox| {{hc|articles/360037256774-API-Utility-Functions Here}} }}
  
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).
 
  
 +
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).
 +
{{apibox}}
 
==Underscore.js==
 
==Underscore.js==
You have access to the Underscore.js library (via the <code>_</code> global object) to help make things easier. Underscore provides helper functions for things like <code>_.each</code> (to iterate through an array of objects). Check out the [http://underscorejs.org Underscore documentation] for more information.  
+
You have access to the '''Underscore.js''' library (via the <code>_</code> global object) to help make things easier. Underscore provides helper functions for things like <code>_.each</code> (to iterate through an array of objects). Check out the [http://underscorejs.org Underscore documentation] for more information.  
  
 
==Logging==
 
==Logging==
Line 10: Line 11:
 
'''log(message)'''
 
'''log(message)'''
  
You can use this function to log output to the API console on the Script Editor page. Useful for debugging your scripts and getting a better handle on what's going on inside the API sandbox.
+
You can use this function to log output to the [[API:Use_Guide#The_API_Console|API console]] on the Script Editor page. Useful for debugging your scripts and getting a better handle on what's going on inside the API sandbox.
  
<pre data-language="javascript">
+
<pre data-language="javascript" style="overflow:auto;white-space:pre-wrap;">
 
on("change:graphic", function(obj) {     
 
on("change:graphic", function(obj) {     
 
   log("Heard change for object ID: " + obj.id);
 
   log("Heard change for object ID: " + obj.id);
Line 22: Line 23:
 
'''toFront(obj)''' and '''toBack(obj)'''
 
'''toFront(obj)''' and '''toBack(obj)'''
  
These two functions will move an object on the tabletop to the front (or back) of 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 <code>getObj</code> or <code>findObjs</code>.
+
These two functions will move an object on the tabletop to the front (or back) of [[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 <code>getObj</code> or <code>findObjs</code>.
  
  
Line 35: Line 36:
 
'''Math.random()'''
 
'''Math.random()'''
  
You can call Math.random() like normal in your API 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.
+
You can call <code>Math.random()</code> like normal in your API 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, [[QuantumRoll]]. 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.
  
Do not use Math.random() if even distribution of numbers in a range are desired. While Math.random() gives you as good of a random number as Roll20 can manage the math to turn that random number into a range with even distribution (like a dice roll) is not as straight forward as multiplication with a modulo or a floor call. Use '''randomInteger(max)''' for those cases.
+
Do not use Math.random() if even distribution of numbers in a range are desired. While Math.random() gives you as good of a random number as Roll20 can manage, the math to turn that random number into a range with even distribution (like a dice roll) is not as straight forward as multiplication with a modulo or a floor call. Use '''randomInteger(max)''' for those cases.
  
 
==Player Is GM==
 
==Player Is GM==
 
'''playerIsGM(playerid)'''
 
'''playerIsGM(playerid)'''
  
The Player Is GM function returns a boolean response on whether a player in the game is a GM or not. The function will always return the correct answer depending on the current moment, so even if a GM chooses to re-join as a player or a player is promoted to a GM mid-game, playerIsGM() will respond accordingly without any need to clear a cache or restart the API sandbox.
+
The '''<code>playerIsGM()</code>''' function returns a boolean response on whether a [[player]] in the game is a [[GM]] or not. The function will always return the correct answer depending on the current moment, so even if a GM chooses to re-join as a player or a player is promoted to a GM mid-game, <code>playerIsGM()</code> will respond accordingly without any need to clear a cache or restart the API sandbox.
 +
 
 +
== Character ==
 +
 
 +
'''setDefaultTokenForCharacter( character, token )'''
 +
 
 +
Sets the [[Journal#Default_Token|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 [[Journal#Character_Tabs|character]].
  
 
== Special Effects (FX) ==
 
== Special Effects (FX) ==
Line 48: Line 55:
 
'''spawnFx(x, y, type, pageid)'''
 
'''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.  
+
Spawns a brief effect at the location at x,y of type. If you omit the <code>pageid</code> or pass <code>'undefined'</code>, 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:<code>beam-color</code>, <code>bomb-color</code>, <code>breath-color</code>, <code>bubbling-color</code>, <code>burn-color</code>, <code>burst-color</code>, <code>explode-color</code>, <code>glow-color</code>, <code>missile-color</code>, <code>nova-color</code>, <code>splatter-color</code>
 
For built-in effects type should be a string and be one of the following:<code>beam-color</code>, <code>bomb-color</code>, <code>breath-color</code>, <code>bubbling-color</code>, <code>burn-color</code>, <code>burst-color</code>, <code>explode-color</code>, <code>glow-color</code>, <code>missile-color</code>, <code>nova-color</code>, <code>splatter-color</code>
Line 54: Line 61:
 
Where "color" in the above is one of:  <code>acid</code>, <code>blood</code>, <code>charm</code>, <code>death</code>, <code>fire</code>, <code>frost</code>, <code>holy</code>, <code>magic</code>, <code>slime</code>, <code>smoke</code>, <code>water</code>
 
Where "color" in the above is one of:  <code>acid</code>, <code>blood</code>, <code>charm</code>, <code>death</code>, <code>fire</code>, <code>frost</code>, <code>holy</code>, <code>magic</code>, <code>slime</code>, <code>smoke</code>, <code>water</code>
  
For custom effects, type should be the ID of the custfx object for the custom effect.
+
For custom effects, type should be the ID of the <code>custfx</code> object for the custom effect.
  
 
'''spawnFxBetweenPoints(point1, point2, type, pageid)'''
 
'''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"); The effect will "travel" between the two points for effects that support that (the same ones that allow agency on the client side).
+
Works the same as <code>spawnFx</code>, but instead of a single point you pass in two points, in the format <code>{x: 100, y: 100}</code>.
 +
 
 +
{{ex}}
 +
<pre  data-language="javascript" style="overflow:auto;white-space:pre-wrap;">spawnFxBetweenPoints({x: 100, y: 100}, {x: 400, y: 400}, "beam-acid")</pre>
 +
 
 +
The effect will "travel" between the two points for effects that support that (the same ones that allow agency on the client side).
  
 
The following effect types must always use spawnFxBetweenPoints instead of spawnFx: <code>beam-color</code>, <code>breath-color</code>, <code>splatter-color</code>
 
The following effect types must always use spawnFxBetweenPoints instead of spawnFx: <code>beam-color</code>, <code>breath-color</code>, <code>splatter-color</code>
Line 66: Line 78:
 
Spawns an ad-hoc custom effect using the JSON for some effect definition at the location x,y. 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.
 
Spawns an ad-hoc custom effect using the JSON for some effect definition at the location x,y. 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.
  
definitionJSON is a javascript object following the JSON specification for [[Custom FX|Custom FX]].
+
<code>definitionJSON</code> is a javascript object following the JSON specification for [[Custom FX|Custom FX]].
  
 
==Jukebox Playlists==
 
==Jukebox Playlists==
 
+
{{Jukebox}}
 
=== UNAVAILABLE ===
 
=== UNAVAILABLE ===
 
[http://blog.roll20.net/post/150968376980/in-regards-to-soundcloud "In Regards to SoundCloud"]
 
[http://blog.roll20.net/post/150968376980/in-regards-to-soundcloud "In Regards to SoundCloud"]
Line 84: Line 96:
  
 
== Miscellaneous ==
 
== Miscellaneous ==
 +
'''sendPing(left, top, pageid, (optional) playerid, (optional) moveAll, (optional) visibleTo)'''
  
'''sendPing(left, top, pageid, (optional) playerid, (optional) moveAll)'''
+
Sends a "ping" the tabletop (the same as if a player holds down their mouse button). You must specify the top/left coordinates, and the pageid of the page to be pinged. You can optionally specify the ID of a player who performed the ping -- if you don't "api" will be assumed and the ping will be yellow.
  
Sends a "ping" the tabletop (the same as if a player holds down their mouse button). You must specify the top/left coordinates, and the pageid of the page to be pinged. You can optionally specify the ID of a player who performed the ping -- if you don't "api" will be assumed and the ping will be yellow. You can also pass in "true" for the moveAll option if you want to move the player's screens to that location as well.
+
You can pass in "true" for the moveAll option if you want to move the players' views to that location as well.
  
<pre data-language="javascript">
+
You can set the player IDs in visibleTo for the players who can see or be moved by the ping. This is presented as a single player ID, an array, or a comma-delimited string.
//Example:
+
 
on('ready', function() {
+
<pre data-language="javascript" style="overflow:auto;white-space:pre-wrap;">
  sendPing(500, 500, Campaign().get('playerpageid'), null, true); //Sends a ping to 500,500 on the page players are currently on, using the yellow color and moving the player's screens.
+
on("chat:message", function(msg) {
});
+
  // Enter "!pingtest" into the chat to run the test
 +
  if(msg.type == "api" && msg.content.indexOf("!pingtest") !== -1) {
 +
 +
    // to get a specific player, use findObjs({_type: "player"})[i].id instead of null for the 3rd parameter
 +
    players = findObjs({_type: "player"});
 +
    player1 = players[1].id;
 +
    player2 = players[2].id;
 +
 +
    // Create an array of all player's IDs
 +
    var allPlayerIDs = players.map(function(player) {
 +
      return player['id'];
 +
    });
 +
 +
    // Ping everyone on this page to the same location.
 +
    sendPing(300, 300, Campaign().get('playerpageid'), null, true);
 +
    setTimeout(function() {
 +
        // Ping everyone on this page to the same location
 +
        sendPing(1500, 500, Campaign().get('playerpageid'), msg.playerid, true, "");
 +
    }, 1000);
 +
    setTimeout(function() {
 +
        // Ping only the specified player to this location
 +
        sendPing(1200, 500, Campaign().get('playerpageid'), null, true, player1);
 +
    }, 2000);
 +
    setTimeout(function() {
 +
        // Ping an array of player IDs (player 1 and 2) to this location
 +
        sendPing(900, 100, Campaign().get('playerpageid'), player2, true, [player1, player2]);
 +
    }, 3000);
 +
    setTimeout(function() {
 +
        // Ping a comma-separated list supplied as a string to this location
 +
        sendPing(300, 300, Campaign().get('playerpageid'), player1, true, allPlayerIDs.join());
 +
    }, 4000);
 +
 +
  }
 +
})
 
</pre>
 
</pre>
  
Line 103: Line 149:
 
* Therefore, 5 ft = 1 unit = 1 square
 
* Therefore, 5 ft = 1 unit = 1 square
  
However, the GM can change both the size of the grid, as well as the scale of the distance. 1 unit is always 70 pixels, but the GM could change the settings such that 1 unit is now 10ft (meaning 70 pixels = 10ft), or that each grid space is 2 units (meaning each grid space is now 140 pixels).  
+
However, the [[GM]] can change both the size of the grid, as well as the scale of the distance. 1 unit is always 70 pixels, but the GM could change the settings such that 1 unit is now 10ft (meaning 70 pixels = 10ft), or that each grid space is 2 units (meaning each grid space is now 140 pixels).  
  
[[Category:API|Utility Functions]]
+
[[Category:API Development]]

Latest revision as of 06:38, 9 June 2024

Attention: This page is community-maintained. For the official Roll20 version of this article, see the Help Center for assistance: Here .


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).

Contents

[edit] 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.

[edit] Logging

log(message)

You can use this function to log output to the API console on the Script Editor page. Useful for debugging your scripts and getting a better handle on what's going on inside the API sandbox.

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

[edit] Object Ordering

toFront(obj) and toBack(obj)

These two functions will move an object on the tabletop to the front (or back) of 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.


[edit] Random Numbers

randomInteger(max)

Use This Function For Dice! This function accounts for Modulo Bias which ensures that the resulting random numbers are also evenly distributed between 1 and MAX.

Returns a random integer, with the lowest value being 1, and the highest value being max. This is the same functionality that Roll20 uses to power its dice rolls, and these numbers have been statistically and rigorously proven to be random.

Math.random()

You can call Math.random() like normal in your API 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, QuantumRoll. 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.

Do not use Math.random() if even distribution of numbers in a range are desired. While Math.random() gives you as good of a random number as Roll20 can manage, the math to turn that random number into a range with even distribution (like a dice roll) is not as straight forward as multiplication with a modulo or a floor call. Use randomInteger(max) for those cases.

[edit] Player Is GM

playerIsGM(playerid)

The playerIsGM() function returns a boolean response on whether a player in the game is a GM or not. The function will always return the correct answer depending on the current moment, so even if a GM chooses to re-join as a player or a player is promoted to a GM mid-game, playerIsGM() will respond accordingly without any need to clear a cache or restart the API sandbox.

[edit] 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.

[edit] 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}.


Example:

spawnFxBetweenPoints({x: 100, y: 100}, {x: 400, y: 400}, "beam-acid")

The effect will "travel" between the two points for effects that support that (the same ones that allow agency on the client side).

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

spawnFxWithDefinition(x, y, definitionJSON, pageid)

Spawns an ad-hoc custom effect using the JSON for some effect definition at the location x,y. 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.

definitionJSON is a javascript object following the JSON specification for Custom FX.

[edit] Jukebox Playlists

u Jukebox

[edit] UNAVAILABLE

"In Regards to SoundCloud"

Note: Using SoundCloud functions will not throw errors, but they no longer do anything.

playJukeboxPlaylist(playlistid)

The play function takes in 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()

The stop function does not require any arguments, and will stop any playlist that is currently playing.

[edit] Miscellaneous

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

Sends a "ping" the tabletop (the same as if a player holds down their mouse button). You must specify the top/left coordinates, and the pageid of the page to be pinged. You can optionally specify the ID of a player who performed the ping -- if you don't "api" will be assumed and the ping will be yellow.

You can pass in "true" for the moveAll option if you want to move the players' views to that location as well.

You can set the player IDs in visibleTo for the players who can see or be moved by the ping. This is presented as a single player ID, an array, or a comma-delimited string.

on("chat:message", function(msg) {
  // Enter "!pingtest" into the chat to run the test
  if(msg.type == "api" && msg.content.indexOf("!pingtest") !== -1) {
 
    // to get a specific player, use findObjs({_type: "player"})[i].id instead of null for the 3rd parameter
    players = findObjs({_type: "player"});
    player1 = players[1].id;
    player2 = players[2].id;
 
    // Create an array of all player's IDs
    var allPlayerIDs = players.map(function(player) {
      return player['id'];
    });
 
    // Ping everyone on this page to the same location.
    sendPing(300, 300, Campaign().get('playerpageid'), null, true);
    setTimeout(function() {
        // Ping everyone on this page to the same location
        sendPing(1500, 500, Campaign().get('playerpageid'), msg.playerid, true, "");
    }, 1000);
    setTimeout(function() {
        // Ping only the specified player to this location
        sendPing(1200, 500, Campaign().get('playerpageid'), null, true, player1);
    }, 2000);
    setTimeout(function() {
        // Ping an array of player IDs (player 1 and 2) to this location
        sendPing(900, 100, Campaign().get('playerpageid'), player2, true, [player1, player2]);
    }, 3000);
    setTimeout(function() {
        // Ping a comma-separated list supplied as a string to this location
        sendPing(300, 300, Campaign().get('playerpageid'), player1, true, allPlayerIDs.join());
    }, 4000);
 
  }
})

[edit] A Note on Distances and Grids in Roll20

In Roll20, a "unit" is always 70 pixels on the screen. The "unit" is the building block that distance and the grid are built on top of. By default:

  • 1 unit = 5 ft
  • 1 unit = 1 grid square
  • Therefore, 5 ft = 1 unit = 1 square

However, the GM can change both the size of the grid, as well as the scale of the distance. 1 unit is always 70 pixels, but the GM could change the settings such that 1 unit is now 10ft (meaning 70 pixels = 10ft), or that each grid space is 2 units (meaning each grid space is now 140 pixels).