Mod Scripts: Chat

This page outlines details pertaining to Mod Scripts in regards to chat functions.

Chat Events

chat:message

Triggered whenever a new chat message is received. Note that if the message is of type rollresult, gmrollresult, secretrollresult, or supersecretrollresult, you will need to call JSON.parse() on the content of the message to get an object which contains information on the roll results.

If a player enters a chat message beginning with !, that message has type "api" and is not shown in chat. Scripts use that type for commands. sendChat() also fires chat:message, and those messages have playerid "API".

Callback parameter:

Property Default Value Notes
who "" The display name of the player or character that sent the message. For a GM, this ends with (GM). Strip that suffix before passing who to sendChat if you do not want it in the posted name.
playerid The ID of the player that sent the message. Messages created by sendChat() use "API".
type "general" One of general, rollresult, gmrollresult, secretrollresult, supersecretrollresult, emote, whisper, desc, direct, or api.
content "" The contents of the chat message. If type is rollresult, gmrollresult, secretrollresult, or supersecretrollresult, this will be a JSON string of data about the roll.
origRoll (roll types only) The original text of the roll, eg: 2d10+5 fire damage when the player types /r 2d10+5 fire damage. This is equivalent to the use of content on messages with types other than roll-result types.
inlinerolls Present when content contains inline rolls. In an "api" message the rolls appear in content as $[[0]], $[[1]], and so on, and this array holds the parsed rolls in that order. An entry may include secret: true.
rolltemplate (content contains one or more roll templates only) The name of the template specified.
target (type whisper only) The player ID of the person the whisper is sent to. If the whisper was sent to the GM without using his or her display name (ie, /w gm text instead of /w Riley text when Riley is the GM), or if the whisper was sent to a character without any controlling players, the value will be gm.
target_name (type whisper only) The display name of the player or character the whisper was sent to.
selected Present on player "api" commands when something is selected. Each entry is a plain object {_id, _type}, not a Roll20 object. Omitted when the message comes from sendChat().
secret false true for secret and super-secret rolls and messages.
secrecy "public" "public", "secret", or "super".

Secret and super-secret rolls use these commands (available on both sandbox versions):

  • /secretroll or /sr — type is "secretrollresult", secret is true, secrecy is "secret".
  • /supersecretroll or /ssr — type is "supersecretrollresult", secret is true, secrecy is "super".
  • /secret or /s followed by a message (for example /secret [[1d6]]) — type stays "general", secret is true, secrecy is "secret". Compact secret form of a whisper-to-GM roll: the GM sees the value; the roller sees that a secret roll happened.
  • /supersecret or /ss followed by a message — type stays "general", secret is true, secrecy is "super".

/sr and /ssr are roll commands. They are not ! commands. A message that starts with ! has type "api".

Note: You probably don’t need all of this information. In most cases you’ll only be interested in the overall result of the roll (see the bottom of the first example). However all of it is provided if you want to really dig deeper into the results of a roll.

Roll Result Structure Ex. 1

After you call JSON.parse on the content property of a rollresult, gmrollresult, secretrollresult, or supersecretrollresult message, you’ll get an object with the following format (this is the result from the command /roll {2d6}+5+1t[weather] Attack!)

{
  "type":"V", //"V" = "Validated Roll" (this will always be "V" right now)
  "rolls": [
    {
      "type":"G", //"G" indicates a grouped roll. A group is like a series of "sub-rolls" within a roll.
      "rolls": [
        [
          {
            "type":"R", //"R" = "Roll"
            "dice":2, // Number of dice rolled (2dX means 2 dice)
            "sides":6, //Number of sides for the dice (Xd6 means 6 sides)
            "mods":{},
            "results": [ //An array of the results of each roll.
              {
                "v":1 // We rolled a 1 for our first 2d6
              },
              {
                "v":5 //We rolled a 5 for our second 2d6
              }
            ]
          }
        ]
      ],
      "mods":{},
      "resultType":"sum", //The result is a sum (as opposed to a success check)
      "results": [
        {
          "v":6 // In this case, the overall result (total) of the group.
        }
      ]
    },
    {
      "type":"M", //"M" = Math Expression
      "expr":"+5+"
    },
    {
      "type":"R", //"R" = Roll
      "dice":1,
      "table":"weather", //The table property is set to the name of the table used if this roll was made against a table
      "mods":{},
      "sides":2, //You can probably just ignore this for table rolls.
      "results": [
        {
          "v":0, //The "value" of the table item rolled. For text tables this is always 0.
          "tableidx":1, //The index of the item in the table that was rolled.
          "tableItem": { //A copy of the table item object as it existed when the table was rolled.
            "name":"rainy",
            "avatar":"", //This will be a URL to an image if the rollable table uses image icons
            "weight":1,
            "id":"-IpzPx2j_9piP09ceyOv"
          }
        }
      ]
    },
    {
      "type":"C", // "C" = Comment
      "text":" Attack!"
    }
  ],
  "resultType":"sum", //The overall result type of the entire roll
  "total":11 // The overall total of the entire roll (including all sub-groups)
}

Roll Result Structure Ex. 2

An annotated structure for the result of /roll {1d6!!>5}>6 (showing exploding modifications and target successes):

{
  "type":"V",
  "rolls": [
    {
      "type":"G",
      "rolls": [
        [
          {
            "type":"R",
            "dice":1,
            "sides":6,
            "mods": { //Modifications to the roll
              "compounding": { //"compounding" = "Compounding exploding (!!)"
                "comp":">=", //Comparison type
                "point":5 //Comparison point
              }
            },
            "results": [
              {
                "v":13 //Overall dice result. Note that since this is compounding exploding there is only one dice result.
              }
            ]
          }
        ]
      ],
      "mods": {
        "success": {
          "comp":">=",
          "point":6
        }
      },
      "resultType":"sum",
      "results": [
        {
          "v":13
        }
      ]
    }
  ],
  "resultType":"success", // In this case, the result is a count of successes
  "total":1 //Total number of successes
}

Chat Event Example (Implementing Custom Roll Type)

on("chat:message", function(msg) {
  // Players type !d6 3 to roll that many d6 against a target of 4.
  if (msg.type !== "api" || msg.content.indexOf("!d6 ") !== 0) return;
  var numdice = parseInt(msg.content.substring(4), 10);
  if (!numdice || numdice < 1) return;
  var who = msg.who.replace(/ \(GM\)$/, "");
  sendChat(who, "/roll " + numdice + "d6>4");
});

sendChat(speakingAs, input [,callback [, options]] )

You can use this function to send a chat message.

speakingAs can be one of:

  • Any string, in which case that will be used as the name of the person who sent the message. E.g. "Riley"
  • A player’s ID, formatted as "player|-Abc123" where -Abc123 is the ID of the player. If you do this it will automatically use the avatar and name of the player.
  • A character’s ID, formatted as "character|-Abc123". If you do this it will automatically use the avatar and name of the Character.

input should be any valid expression just like the ones used in the Roll20 App. You enter text to send a basic message, or use slash-commands such as /roll, /em, /w, /secretroll (/sr), /supersecretroll (/ssr), /secret (/s), /supersecret (/ss), etc. In addition:

  • You can use Character Attributes with the format @{CharacterName|AttributeName}.
  • You can use Character Abilities with the format: %{CharacterName|AbilityName}.
  • You cannot call macros from sendChat the way a player types #MacroName. A button can run a macro when clicked: [Name](!&#13;#MacroName).
  • @{selected|...} is not expanded inside sendChat. Read msg.selected in a chat:message handler instead.
  • Ordinary messages and whispers can include the HTML tags below. /direct <msg> sends the message with no Markdown and no URL autolinking, and can use the same tags:
<code><span><div><label><a><br><br /><p><b><i><del><strike><u><img>
<blockquote><mark><cite><small><ul><ol><li><hr><dl><dt><dd><sup>
<sub><big><pre><figure><figcaption><strong><em><table><tr><td><th>
<tbody><thead><tfoot><h1><h2><h3><h4><h5><h6>

callback is an optional third parameter consisting of a callback function which will be passed the results of the sendChat() call instead of sending the commands to the game. Using sendChat() in this way is asynchronous. The results of the sendChat() command will be an ARRAY of operations, and each individual object will be just like an object you receive during a chat:message event (see above).

You can use this, for example, to perform a roll using the Roll20 roll engine, then get the results of the roll immediately. You could then perform additional modifications to the roll before sending it to the players in the game.

sendChat("Riley", "/roll 1d20+4", function(ops) {
  // ops will be an ARRAY of command results.
  var rollresult = ops[0];
  //Now do something with rollresult, just like you would during a chat:message event...
});

options is an optional fourth parameter to set options for how the message is handled. Options are specified as a javascript object whose properties are the names of the options to set and whose values are the settings for them, generally true as they default to false.

Available options:

  • noarchive – set this to true to prevent the message from being stored in the chat log. This is particularly useful for output that is not part of the story, such as Mod Script Button menus and state information.
  • use3d – You can now generate 3D Dice rolls using the sendChat() function. The syntax is simply: sendChat("Name", "Rolling [[3d6]]", null, {use3d: true}); If you pass a player ID to the name parameter, such as sendChat("player|-ABC123",...) the player’s color will be used for the dice. Otherwise a default white color will be used.

Note: Clients can only show the result of one 3D roll at a time, so making a bunch of separate 3D rolls in a row is not useful. Also note that using 3D rolls does place a bit more strain on the QuantumRoll server, so use your judgement and don’t perform 100 3D rolls in the space of a second. Use 3D rolls when the roll will matter to the player and make an impact on the game.

If you want to adjust these options but do not want to use a callback parameter (third parameter–see above), you can simply pass null in it’s place:

sendChat("Status", "All players are logged in.", null, {noarchive:true} );

Mod Script Command Buttons

Text chat formatting, in Mod Script messages and in macros and abilities, can create command buttons in chat.

To do so using Markdown formatting:

[Attack Roll](!attackroll)

The text in between the brackets will show up in the button, and part in the parentheses is the command to be executed. You can include anything in a normal roll (macros, abilities, queries, etc.), but keep in mind that the command itself will be executed by the player who clicks on it. For example, don’t include @{Character|AC} if everyone who can see the message can’t access that character. Instead, include the actual value as it existed when you sent the command by filling it in yourself before you send the chat message. These buttons work in general messages, whispers, and whispers to the GM. The click runs as the player who clicks, with that player’s playerid and selected.

/direct skips Markdown, so [Attack Roll](!attackroll) will not become a button.

Entering Mod Script Buttons In Chat

You can also type Markdown syntax Mod Script buttons into chat for others to use. Because they will be interpreted by the chat parser, if you want attributes, queries and rolls to be expanded when the button is clicked, you must enter parts of the command with a special syntax (HTML Entities):

Character Replacement
% &#37;
) &#41;
? &#63;
@ &#64;
[ &#91; or &lbrack;
] &#93; or &rbrack;
{ &#123;
} &#125;
| &#124;
, &#44;

This sample button uses some of them:

[Attack Roll](!attackroll &#64;{target|token_id} &#91;[1d6+&#63;{Bonus|0}]&#93;)

You can actually use the Mod Script Buttons to call Macros or Abilities.

Character Replacement
<carriage return> &#13;

To do so, you simply begin the command portion with the special code !&#13; then add the macro call with # or the ability call with &#37; (%):

[Macro](!&#13;#MacroName)

[Ability](!&#13;&#37;{CharName|AbilityName})

Note: At this time, reopening a Macro saved under the Collections tab of the Sidebar causes HTML entities within to be reverted; if the Macro is then saved, so are those reversions. This behavior is not present within Abilities or Ability Command Buttons.

For Ability Command Buttons, if the Ability that creates the button and the Ability it references are both on the same sheet, the syntax is very simple:

[Ability](~AbilityName)

Was this article helpful?
17 out of 26 found this helpful