### Default Roll Template Example
Source: https://help.roll20.net/hc/en-us/articles/360037257334-How-to-Make-Roll-Templates
An example demonstrating how to populate the default roll template with various properties like name, attack roll, and notes.
```text
&{template:default} {{name=Test Attack}} {{attack=[[1d20]]}}
{{note= This is some note content}} {{Saving Throw= vs Will}}
```
--------------------------------
### Automatic Ammunition Tracking Setup
Source: https://help.roll20.net/hc/en-us/articles/360037773573-D-D-5E-by-Roll20
Step-by-step guide to enable and configure automatic ammunition tracking using the 5th Edition OGL Companion API Script.
```APIDOC
## Automatic Ammunition Tracking Setup
### Description
This tutorial guides you through enabling and configuring the Automatic Ammunition Tracking feature, which requires the Companion API Script.
### Prerequisites
- Companion API Script installed.
### Configuration Steps
1. **Character Sheet Settings**:
* Navigate to the **Settings** (Gear Icon) tab of a character sheet.
* Under **GENERAL OPTIONS**, set **INVENTORY** to "Compendium Compatible".
* Under **GENERAL OPTIONS**, set **AMMO TRACKING** to **ON**.
2. **Add Weapon and Ammunition**:
* Create or drag a missile weapon (e.g., Longbow) from the Compendium to your sheet.
* Create or drag a missile type (e.g., Arrows) from the Compendium to your sheet.
3. **Configure Ammunition Resource**:
* Expand the ammunition item (Arrows) by clicking the "i" icon.
* Select the **USE AS RESOURCE** checkbox. (This is often pre-checked for compendium items).
4. **Link Weapon to Ammunition**:
* On the **CORE** tab, expand the missile weapon (Long Bow) in the **ATTACKS & SPELLCASTING** section by clicking its gear icon.
* In the **AMMUNITION** section, enter the exact name of the ammunition resource (e.g., `Arrows`).
* To spend multiple ammunition pieces per shot, append the quantity after the name, separated by a comma (e.g., `Arrows,2`).
### Usage
Once configured, rolling the linked missile weapon will automatically spend one piece of ammunition, and the chat will log the action. The AMMUNITION section may update with a resource repeating section ID, which is expected behavior.
```
--------------------------------
### Nesting Macros Example
Source: https://help.roll20.net/hc/en-us/articles/360037256794
This example shows how to nest macros. The '#both' macro calls '#attack' and '#damage' macros sequentially. Ensure macros are defined before being called.
```roll20-macro
Macro #damage = /roll 1d4+11
Macro #attack = /roll 1d20+9
Macro #both =
#attack
#damage
```
--------------------------------
### Default Roll Template Example
Source: https://help.roll20.net/hc/en-us/articles/360037257334
An example of how to use the default roll template with various properties like name, attack, note, and saving throw.
```text
&{template:default}} {{name=Test Attack}} {{attack=[[1d20]]}}
{{note= This is some note content}} {{Saving Throw= vs Will}}
```
--------------------------------
### Create a Simple Macro
Source: https://help.roll20.net/hc/en-us/articles/360037256794
Use this macro to send a line of text to chat and roll a d20 with a modifier. It's a basic example for getting started.
```roll20-macro
This is My First Macro!
/roll 1d20 + 5
```
--------------------------------
### Example HTML with Manual Item Numbering
Source: https://help.roll20.net/hc/en-us/articles/360037773493-Character-Sheet-Translation
Shows how to use data-i18n-list-item-num to manually define the order of list items, overriding the default top-down reading order. This example arranges items across columns then down.
```html
```
--------------------------------
### Define startColour and startColourRandom
Source: https://help.roll20.net/hc/en-us/articles/34838734292247-Legacy-Effects-Tool
Example configuration for particle color and color variation using RGBA arrays.
```json
startColour: [220, 35, 0, 1],
startColourRandom: [62, 0, 0, 0.25]
```
--------------------------------
### Roll20 Macro Query Syntax Example
Source: https://help.roll20.net/hc/en-us/articles/360037256794
This example demonstrates the nested query syntax used in Roll20 macros to create interactive prompts with multiple levels of options and labels.
```Roll20 Macro
?{Name of Query|
Label 1, ?{value1|
Label 1A, ?{value1A|
Label 1Ai, value1Ai |
Label 1Aii, value1Aii
} |
Label 1B, ?{value1B|
Label 1Bi, value1Bi |
Label 1Bii, value1Bii
}
} |
Label 2, ?{value2|value2}
}
```
--------------------------------
### Example Turn Order Object Structure
Source: https://help.roll20.net/hc/en-us/articles/360037772793-API-Objects
This is an example of the JSON structure for the turn order. It can contain objects with IDs referencing graphics or custom entries.
```json
[
{
"id":"36CA8D77-CF43-48D1-8682-FA2F5DFD495F",
"pr":"0",
"custom":""
},
{
"id":"-1",
"pr":"12",
"custom":"Test Custom"
}
]
```
--------------------------------
### Select Input Default Setting Example
Source: https://help.roll20.net/hc/en-us/articles/360041542554-Default-Sheet-Settings
For a select input, specify the default selection using the `"default"` or `"value"` key, referencing the key of the desired option. This example shows setting 'Option 2' as the default.
```json
{
"attribute": "select_default",
"displayname": "Select Default",
"type": "select",
"options": {
"option1": "Option 1",
"option2": "Option 2",
"option3": "Option 3"
},
"default": "option2"
}
```
--------------------------------
### Token Marker Commands
Source: https://help.roll20.net/hc/en-us/articles/360041536113
Example script providing chat commands to interact with token markers.
```APIDOC
## Token Marker Chat Commands
### Description
This section details the custom chat commands provided by an example script to manage and query token markers within a Roll20 game.
### Commands
#### `!markernames`
**Description:** Outputs all available token markers to the chat, including their image, name, and ID.
#### `!markerids `
**Description:** Outputs any token markers that match the provided name to the chat.
**Parameters:**
- **name** (string) - Required - The name of the marker to search for.
#### `!settokenmarker `
**Description:** Adds the provided string to the currently selected token's marker list. This command does not validate if the Token Marker exists.
**Parameters:**
- **string** (string) - Required - The marker string to add.
#### `!gettokenmarkers`
**Description:** Outputs the currently selected token's statusmarker attribute to the chat.
### Request Example (for `!settokenmarker`)
```
!settokenmarker Bane::59
```
### Response Example (for `!markernames`)
```html
59: Bane
```
### Response Example (for `!markerids `)
```html
59: Bane
```
### Response Example (for `!gettokenmarkers`)
```
status_wall,status_burning
```
```
--------------------------------
### Log API Sandbox Initialization
Source: https://help.roll20.net/hc/en-us/articles/38597501957015-2025-Change-Log
Displays the version, release date, ready time, and object count for the API sandbox environment.
```text
"##########> Sandbox [DEFAULT 2025-03-03] : Ready fired after 3.13s, 42 objects."
```
--------------------------------
### Get Attributes in Repeating Sections
Source: https://help.roll20.net/hc/en-us/articles/360037773513-Sheet-Worker-Scripts
When inside a repeating section, use prefixed names to get attributes from the same row. This example retrieves SpellDamage and SpellName from the repeating_spells section.
```javascript
on("change:repeating_spells:spelllevel", function() {
getAttrs([
"repeating_spells_SpellDamage",
"repeating_spells_SpellName"
], function(values) {
//values.repeating_spells_SpellDamage and values.repeating_spells_SpellName
//will both be from the same repeating section row that the SpellLevel that changed is in.
});
});
```
--------------------------------
### Trap Macro Example
Source: https://help.roll20.net/hc/en-us/articles/32901366352919-Reactions
A complex macro example that triggers a message, a roll, and a visual effect.
```text
@{selected|character_name} stepped on a trap!
Dex save: /roll 1d20 + @{@{instigator_id}|dexterity_save_roll}
/fx explode-fire @{token_id}
```
--------------------------------
### Initialize and Use Namespaced State
Source: https://help.roll20.net/hc/en-us/articles/360037772793
A complete example showing how to initialize a namespaced state object and use it to persist configuration and counters.
```javascript
on('ready',function() {
"use strict";
// Check if the namespaced property exists, creating it if it doesn't
if( ! state.MyModuleNS ) {
state.MyModuleNS = {
version: 1.0,
config: {
color1: '#ff0000',
color2: '#0000ff'
},
count: 0
};
}
// Using the state properties to configure a message to the chat.
sendChat(
'Test Module',
''+
'State test'+
' '+
''+
'Script v'+state.MyModuleNS.version+' started '+(++state.MyModuleNS.count)+' times!'+
''
);
});
```
--------------------------------
### Damage Dice Input Examples
Source: https://help.roll20.net/hc/en-us/articles/360045613693-Pathfinder-Second-Edition-by-Roll20
Examples of valid dice code formats for the temp or other fields when calculating damage.
```text
3
```
```text
1d4+1
```
--------------------------------
### Multiple Sub-Roll Failure Example
Source: https://help.roll20.net/hc/en-us/articles/360037773133-Dice-Reference
Example demonstrating how to count failures across multiple grouped sub-roll expressions.
```Roll20 Dice Syntax
{4d6+2d8, 3d20+3, 5d10+1}>40f<10
```
--------------------------------
### Single Sub-Roll Failure Examples
Source: https://help.roll20.net/hc/en-us/articles/360037773133-Dice-Reference
Examples demonstrating how to count failures alongside successes in single dice expressions.
```Roll20 Dice Syntax
{3d20+5}>21f<10
```
```Roll20 Dice Syntax
{2d6!}>4f1
```
--------------------------------
### Initialize and Use Namespaced State
Source: https://help.roll20.net/hc/en-us/articles/360037772793-API-Objects
This example demonstrates checking for a namespaced state property and initializing it if it doesn't exist. It then uses the state properties to configure and send a chat message.
```javascript
on('ready',function() {
"use strict";
// Check if the namespaced property exists, creating it if it doesn't
if( ! state.MyModuleNS ) {
state.MyModuleNS = {
version: 1.0,
config: {
color1: '#ff0000',
color2: '#0000ff'
},
count: 0
};
}
// Using the state properties to configure a message to the chat.
sendChat(
'Test Module',
'
State test
'+
'
Script v'+state.MyModuleNS.version+' started '+(++state.MyModuleNS.count)+' times!
'
);
});
```
--------------------------------
### Graphic Object - Token Marker Example
Source: https://help.roll20.net/hc/en-us/articles/360037772793-API-Objects
An example of the JSON structure for a token marker, including its ID, name, tag, and URL.
```APIDOC
## Graphic Object - Token Marker Example
### Description
This example shows the structure of a token marker object, which includes its unique identifier, display name, internal tag, and the URL to its image.
### Request Body
```json
{
"id": 59,
"name": "Bane",
"tag": "Bane::59",
"url": "https://s3.amazonaws.com/files.d20.io/images/59/yFnKXmhLTtbMtaq-Did1Yg/icon.png?1575153187"
}
```
### Response Example
```json
{
"id": 59,
"name": "Bane",
"tag": "Bane::59",
"url": "https://s3.amazonaws.com/files.d20.io/images/59/yFnKXmhLTtbMtaq-Did1Yg/icon.png?1575153187"
}
```
```
--------------------------------
### Demonstrate Asynchronous Function Execution
Source: https://help.roll20.net/hc/en-us/articles/360037772773-Mod-Scripts-API-Advanced-Use-Guide
Examples showing how asynchronous functions return control to the parent scope immediately before completing their background tasks.
```javascript
on('load',function(){
log('Parent Scope - Before call to asynchronous function.');
setTimeout(function(){
log('Asynchronous Function Scope - Doing the Asynchronous function work.');
},10 /* 10 milliseconds */);
log('Parent Scope - after call to asynchronous function.');
});
```
```text
"Parent Scope - Before call to asynchronous function."
"Parent Scope - after call to asynchronous function."
"Asynchronous Function Scope - Doing the Asynchronous function work."
```
```javascript
on('load',function(){
log('Parent Scope - Before call to asynchronous function.');
sendChat('Async Function','Evaluate this: [[1d6]]',function(msg){
log('Asynchronous Function Scope - Doing the Asynchronous function work.');
});
log('Parent Scope - after call to asynchronous function.');
```
--------------------------------
### Send a message with options
Source: https://help.roll20.net/hc/en-us/articles/360037256754-API-Chat
Demonstrates how to send a message with specific options while passing null for the unused callback parameter.
```javascript
sendChat("Status", "All players are logged in.", null, {noarchive:true} );
```
```javascript
sendChat("Name", "Rolling [[3d6]]", null, {use3d: true});
```
--------------------------------
### Send Ping Example
Source: https://help.roll20.net/hc/en-us/articles/360037256774-API-Utility-Functions
Demonstrates various ways to use the sendPing function, including pinging all players, specific players, or a group of players by ID. Requires the 'chat:message' event handler.
```javascript
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);
}
})
```
--------------------------------
### Roll20 Attribute Auto-complete Example
Source: https://help.roll20.net/hc/en-us/articles/360037256794
This example shows how to use the '@' symbol for auto-completing attribute references in Roll20. Typing '@' followed by a few letters will display matching attributes.
```Roll20 Chat
@int
```
--------------------------------
### Implement translation keys in button macros
Source: https://help.roll20.net/hc/en-us/articles/360037773453-Minimum-Requirements-Best-Practices
Use the ^{key} syntax to reference translation strings from the language JSON files.
```text
^{key}
```
--------------------------------
### Example Script for Token Marker Operations
Source: https://help.roll20.net/hc/en-us/articles/360041536113-API-Token-Markers
This script provides functions to interact with token markers, including listing all markers, finding markers by name, setting markers on selected tokens, and retrieving a token's current markers.
```APIDOC
## Token Marker Script Commands
### Description
This script adds several chat commands to your Roll20 game for managing token markers.
### Commands
- **!markernames**
- **Description**: Outputs all available token markers to the chat, including their image, name, and ID.
- **Usage**: Type `!markernames` in the chat.
- **!markerids **
- **Description**: Outputs any token markers that match the provided name to the chat.
- **Usage**: Type `!markerids ` in the chat (e.g., `!markerids Bane`).
- **!settokenmarker **
- **Description**: Adds the provided string to the currently selected token's marker list. This command does not validate if the Token Marker exists.
- **Usage**: Type `!settokenmarker ` in the chat (e.g., `!settokenmarker Bane::59`).
- **!gettokenmarkers**
- **Description**: Outputs the currently selected token's statusmarker attribute to the chat.
- **Usage**: Select a token and type `!gettokenmarkers` in the chat.
### Script Example
```javascript
on("ready", () => {
const tokenMarkers = JSON.parse(Campaign().get("token_markers"));
const getChatMessageFromTokenMarkers = markers => {
let chatMessage = '';
_.each(markers, marker => {
chatMessage += `
${marker.id}: ${marker.name}
`;
});
return chatMessage;
};
on("chat:message", msg => {
if (msg.content.split(" ")[0].toLowerCase() === '!markernames') {
let chatMessage = getChatMessageFromTokenMarkers(tokenMarkers);
sendChat("Token Markers", chatMessage);
} else if (msg.content.split(" ")[0].toLowerCase() === '!markerids') {
const markerName = msg.content.split(" ")[1].toLowerCase();
let results = [];
_.each(tokenMarkers, marker => {
if (marker.name.toLowerCase() === markerName) results.push(marker);
});
log(results);
let chatMessage = getChatMessageFromTokenMarkers(results);
chatMessage = chatMessage || 'Unable to find any matching token markers';
sendChat("Token Markers", chatMessage);
} else if (msg.content.split(" ")[0].toLowerCase() === '!settokenmarker') {
const markerNameToAdd = msg.content.split(" ")[1]; // Keep original case for adding
if (!msg.selected || msg.selected[0]._type !== "graphic") return;
const obj = getObj(msg.selected[0]._type, msg.selected[0]._id);
let currentMarkers = obj.get("statusmarkers").split(',');
if (!currentMarkers.includes(markerNameToAdd)) {
currentMarkers.push(markerNameToAdd);
obj.set("statusmarkers", currentMarkers.join(','));
}
} else if (msg.content.split(" ")[0].toLowerCase() === '!gettokenmarkers') {
if (!msg.selected || msg.selected[0]._type !== "graphic") return;
const obj = getObj(msg.selected[0]._type, msg.selected[0]._id);
const currentMarkers = obj.get("statusmarkers");
sendChat("Token Markers", currentMarkers);
}
});
});
```
```
--------------------------------
### Radio Input Default Setting Example
Source: https://help.roll20.net/hc/en-us/articles/360041542554-Default-Sheet-Settings
Similar to select inputs, the `"default"` or `"value"` key can set the default selection for radio buttons. This example sets 'radio2' as the default.
```json
{
"attribute": "radio_default",
"displayname": "Radio Default",
"type": "radio",
"options": {
"radio1": "Radio 1",
"radio2": "Radio 2",
"radio3": "Radio 3"
},
"default": "radio2"
}
```
--------------------------------
### Get Calculated Attribute Value with Inline Roll
Source: https://help.roll20.net/hc/en-us/articles/360037256794
Wrap an attribute reference in an inline roll `[[...]]` to ensure you get the calculated value rather than the formula itself. This is essential for using dynamic character sheet stats.
```Roll20 Macro
@{selected|character_name} has [[@{selected|action_points}]] points left.
```
--------------------------------
### Automatic Spell Slot Tracking Setup
Source: https://help.roll20.net/hc/en-us/articles/360037773573-D-D-5E-by-Roll20
Instructions for enabling and using the Automatic Spell Slot Tracking feature with the 5th Edition OGL Companion API Script.
```APIDOC
## Automatic Spell Slot Tracking Setup
### Description
This guide explains how to enable and utilize the Automatic Spell Slot Tracking feature, which requires the Companion API Script.
### Prerequisites
- Companion API Script installed.
### Enabling Spell Tracking
1. **Check Status**:
* In the chat input area, type `!5estatus` and press Enter to verify if `spelltracking` is currently `on`.
2. **Activate Feature**:
* If spell tracking is not on, type `!spelltracking on` and press Enter.
* Alternatively, to activate without chat messages, type `!spelltracking quiet` and press Enter.
### How it Works
Once activated, the script automatically manages spell slots:
1. **Spell Tab Update**:
* The number of cast spells for the appropriate level is updated in the **Spell** tab of the character sheet.
2. **Chat Notification**:
* A message appears in the chat detailing the spell level, available spell slots, and used spell slots for that level.
3. **Slot Decrementation**:
* Spell slots are automatically decremented as spells are cast.
4. **Ritual Spells**:
* Spells marked as Rituals do not consume spell slots when cast.
### Manual Adjustment
Spell slot counts can be manually adjusted at any time within the **Spell Page** of the character sheet.
```
--------------------------------
### Global Save Modifier Example (DND 5e)
Source: https://help.roll20.net/hc/en-us/articles/360037773573-D-D-5E-by-Roll20
Example of how to configure a global save modifier in Roll20 for spells like Bless. This adds a 1d4 bonus to saving throws and death saves when enabled, with a visible label in chat.
```Roll20 API
1d4[BLESS]
```
--------------------------------
### playJukeboxPlaylist
Source: https://help.roll20.net/hc/en-us/articles/360037772833-API-Function-Documentation
Starts playback of a specific jukebox playlist.
```APIDOC
## playJukeboxPlaylist
### Description
Starts playing the specified jukebox playlist.
### Parameters
- **PLAYLIST_ID** (String) - Required - The id of the playlist to start playing.
### Returns
- **Void**
```