Making Roll20 Spell Macros

Preparing

The Framework

Get a load of this:

That is the Roll20 D&D 3.5 spell macro framework in a nutshell. So what does all this gobbledy-gook mean?

I’m glad you asked…

Programming Typography

This section introduces a few concepts to make programming these macros at least a little easier. If you want to skip straight ahead to programming

Amazing Grace Characters

In order to balance the quirks of what Notepad++ considers a hyperlink against the needs of speedy editing, the concept of “grace characters” is introduced here. A grace character aids in the editing or understanding of programming code, particularly when used in the Roll20 macros used for these spells.

Roll20 hyperlinks, like those in Discord, have brackets around the text to be hyperlinked followed immediately by the hyperlink in parentheses, like so: [Hyperlinked text](https://wherethisgoes). Certain punctuation will cause Notepad++ to extend the underlined portion to include the right parenthesis and characters beyond that, so that if the hyperlink is double-clicked in Notepad++ to test it, a 404 error results. A grace space (defined below) just after the underlined portion) prevents this.

Here are the grace characters defined so far:

A Murder of Pilcrows

A pilcrow, Also known as the paragraph mark, is this symbol: . In this text, it is used whenever a carriage return/linefeed is to be used⁠—​basically, any place one would press the Enter key while typing text in.

Handy HTML Entities

The Hypertext Markup Language (HTML)⁠—​the very language used to display the very text you are reading⁠—​includes a variety of very useful characters for programming Roll20 macros (and writing web pages in general). All HTML entities begin with an ampersand (&) and end with a semicolon (;). The text inbetween can be a word, abbreviation, or a decimal or hexadecimal code as needed.

Using these entities in Roll20 macros requires a bit of convoluted thinking, as the macro itself will be displayed here in HTML, which means that without a bit of preprocessing, an HTML entity you put in the macro text will be used in displaying the page the macro is shown on and won’t then be available for copying and pasting that code into the macro field when it is added to a character sheet. However, if the ampersand characters are themselves converted to the HTML entity (&), they will show up in the macro instead of being used to display in the macro.

For example, a common way to fake a paragraph indent in these macros is to start the paragraph with four non-breaking spaces. The HTML entity for a non-breaking space is  . If a string of those are typed at the beginning of a new paragraph in a {{notes}} field, they will appear in the textbox but won’t be available to actually copy into the macro itself. Converting each ampersand into its own HTML entity, however, allows the entity to display as the code in the textbox so it can be used in the macro itself.

Here is a table of more commonly used HTML entities, starting with the one mentioned in the previous paragraph. These have been “pre-escaped”⁠—​that is, the ampersand entities have been preinserted so one can just copy the code and paste it directly into a Roll20 macro. Remember that in Notepad++, Ctrl+E will convert a selected character (or characters) into their HTML entity.

HTML Entities
EntityDescription
 Non-breaking space. Such a space will not be separated automatically by a web page from text coming after it when a web browser displays it. Four of these in a row can be used to fake a paragraph indent in a Roll20 macro, like so:
    
&Ampersand. This can be used to display a “&” character without a web browser treating it as the beginning of an HTML entity. In fact, that very code was used to display the ampersand between the quotes in the previous sentence.
×Multiplication symbol. Don’t use an "x" when you mean “×”⁠—​it’s sloppy.

Using the Framework, Line by Line

First, copy the Roll20 Spell Macro Framework above into a new Notepad++ file.

  1. Do not change the &{template:DnD35StdRoll} line. This tells the macro to use a particular template to format the spell macro on the screen.
  2. Do not change the {{spellflag=true}} line. This tells the template that a spell macro is being displayed and to adjust formatting accordingly.
  3. Do not change the {{name=@{character_name}}} line. This displays the character’s first name at the top of the macro so everyone knows who is casting the spell.
  4. Replace SPELL_NAME1 and SPELL_NAME2 with the name of the spell.
    1. If the spell name that replaced SPELL_NAME2 starts with lesser, greater, improved, superior, or mass, select that spell name and use Alt+Ins to move that word to the end of the selected spell name prior to the next step.
    2. Select the spell name you just replaced SPELL_NAME2 with. Use Alt+F to convert it to A35 file name format.
    3. In that same URL, replace BOOK_CODE with the book code for a particular publication within the URL. Delete the grace quote before it; this was keeping BOOK_CODE and SPELL_NAME2 separated from the URL for easier selection.
  5. In the {{School}} tag, do the following:
    1. Replace SPELL_SCHOOL with the school the spell belongs to.
    2. If the spell has a subschool, replace SPELL_SUBSCHOOL with its name between the parentheses. Otherwise, delete SPELL_SUBSCHOOL and the parentheses.
    3. If the spell has descriptors, replace DESCRIPTORS with those descriptors between the square brackets. Otherwise, delete DESCRIPTORS and the square brackets.
    4. Any later references to @{sf-SPELL_SCHOOL} should be changed to match the school of the spell for any applicable spell focus. This spell school must be converted to all lower case letters, which can be done in Notepad++ by selecting the school and pressing Ctrl+U.
  6. In the {{Level}} tag, replace CLASSES_LEVELS with a list of all classes that can cast the spell, and follow each class name with the level at which that class can cast the spell. Do not abbreviate class names, and split any reference to Sorcerer/Wizard into its separate classes (e.g. “Sorcerer/Wizard 4” would become “Sorcerer 4, Wizard 4”), re-alphabetizing the list as needed.
  7. In the {{Components}} tag, replace COMPONENTS to match the spell’s actual components. If a material component has a cost of one gold piece or more, put a dollar sign after it, like so: M$.
  8. For the {{Casting Time}} tag, replace “1 standard action” with the actual casting time if it is not 1 standard action. (Most spells have a casting time of 1 standard action.)

In all following steps, change @{casterlevel} to @{arcanecasterlevel} or @{divinecasterlevel} as appropriate. If a spell can be cast by both arcane and divine spellcasters, two separate macros will be needed, one with @{arcanecasterlevel} in place of @{casterlevel} and the other with @{divinecasterlevel} instead. If the spells are of different levels for different classes, separate versions may be needed for those as well if the spells have saving throws. If all cases, replace the SPELL_LEVEL in all @{spelldcSPELL_LEVEL} to match the spell level, which is always 0–9. Delete the grace quote that was in front of SPELL_LEVEL.

  1. For the {{Range}} tag, replace RANGE with one of the following:
    1. If the range is Close, replace it with:
      Close ([[ 25 + 5 * floor( ( @{casterlevel} [CL] + @{clmod} [CL mod] ) / 2 ) ]]ft. )
    2. If the range is Medium, replace it with:
      Medium ([[ 100 + 10 * ( @{casterlevel} [CL] + @{clmod} [CL mod] ) ]]ft. )
    3. If the range is Long, replace it with:
      Long ([[ 400 + 40 * ( @{casterlevel} [CL] + @{clmod} [CL mod] ) ]]ft. )
    4. In all other cases, replace it with the verbatim range as printed.

Not all of the next three “TEA” lines, {{Target}}, {{Effect}}, or {{Area}} are used, except in rare cases like limited wish, wish, and miracle. A very few spells may combine two of the tags. Still, most of the time, you will delete the two lines not used. In cases where there are caster level dependent effects, see Caster Level Formulae for details on how to include these. Otherwise, paste the text verbatim after the appropriate tag and delete the others.

  1. {{Target}} line: if there is potentially more than one target, change “Target” to “Targets”. If the spell only targets one creature, you may allow the caster to select that target by using the attribute @{target|token_name}, which displays the name assigned to the targeted token. This target selection only occurs once per execution of the macro no matter how often @{target|token_name} is repeated in a given spell macro.
  2. {{Effect}} line: if the effect is not level dependent, paste the text verbatim.
  3. {{Area}} line: if the effect is not level dependent, paste the text verbatim. If it has the “(S)” (shapeable) marker, replace that text with the following:
    [(S)](https://kaabbott.synology.me/a35/Rules/Magic#Shapeable)
  4. {{Duration}} tag:
    1. If the spell’s duration is not level dependent, paste the text verbatim.
    2. If it has the “(D)” (dismissable) marker, replace that text with the following:
      [(D)](https://kaabbott.synology.me/a35/Rules/Magic#Dismissable)
  5. {{Saving Throw}} line:
    1. If the range of the spell is Personal, delete this line.
    2. If the line ends in “(harmless)”, replace that text with this:
      ([harmless](https://kaabbott.synology.me/a35/Rules/Magic#harmless ))
    3. If the line ends in “(object)”, replace that text with this:
      ([object](https://kaabbott.synology.me/a35/Rules/Magic#object ))
    4. If the line ends in “(harmless, object)”, replace that text with this:
      ([harmless](https://kaabbott.synology.me/a35/Rules/Magic#harmless), [object](https://kaabbott.synology.me/a35/Rules/Magic#object ))
  6. {{Spell Resistance}} line:
    1. If the range of the spell is Personal, delete this line.
    2. If the line ends in “(harmless)”, replace that text with this:
      ([harmless](https://kaabbott.synology.me/a35/Rules/Magic#harmless ))
    3. If the line ends in “(object)”, replace that text with this:
      ([object](https://kaabbott.synology.me/a35/Rules/Magic#object ))
    4. If the line ends in “(harmless, object)”, replace that text with this:
      ([harmless](https://kaabbott.synology.me/a35/Rules/Magic#harmless), [object](https://kaabbott.synology.me/a35/Rules/Magic#object ))
  7. Only include the {{Caster level check}} line for single target spells that allow spell resistance.
  8. {{notes}} line: This is the big one. See Notes on {{Notes}} below.

Remove from between tags when finished, but not from within {{notes}} tag. The easiest way to do this in Notepad++ is to select everything but {{notes}} and press Ctrl+J, then delete the between {{notes}} and the previous tag.

Notes on {{Notes}}

The {{notes}} tag is where the bulk of the work on a new Roll20 spell macro is done, and where the most mistakes creep in. It’s where one explains just what happens when the spell is cast. Often, one uses a summary of the descriptive text of the spell (“Omit needless words!”), inserting Roll20 dice calculations and the like as needed.

Have a basket full of {{notes}} notes:

What in Blazes is “clmod”?!

The added attribute, clmod, is present in almost every Roll20 spell macro in Archive Three-Five. It is short for caster level modifier. In D&D 3.5, there are a great many feats, traits, and class abilities that can modify a spell’s caster level, which affects its range, damage (if any), and a host of other things. The clmod attribute is a placeholder for these variables. How it is used depends on the feats or other circumstances in play. Here follows a list of them and how they can be handled.

Granted Domain Powers: These cleric domains have a granted power that increases caster level for particular spells: Chaos, Craft, Creation, Envy, Evil, Good, Gnome, Healing, Illusion, Knowledge, Law, Oracle, Purification, and Summoner. The easiest way to handle them is to copy the spell macros to add a new attribute with a variant of clmod⁠—​say, clmod-gp (“gp” for “granted power”) and set that attribute to 1. After that, append “-gp” to any instance of clmod in macros that would be affected by that particular granted power. This can be done right in the text box of the A35 macro just before it is copied (it won’t be saved there), in the macro field of the spell on the Roll20 character sheet, or in a separate text editor.

Spellgifted Trait: The spellgifted trait grants +1 caster level to spells of a selected school of magic and the cost of –⁠1 to the caster level of all other schools. This can be handled by adding another attribute like clmod-sg and setting it to 1, then setting clmod to -1. After that, change clmod to clmod-sg in the macros of spells belonging to the favored school.

Caster Level Formulae

Making Choices: The Select Function

Casting spells often mean making choices, because many spells can work in more than one way. In Roll20 macros, these choices are handled by the select function, works in two different ways:

Data Entry: This form of the select function displays a prompt followed by a field to enter a response, in this form:

?{ PROMPT | DEFAULT_VALUE }

PROMPT is the text that tells the user what is being entered. DEFAULT_VALUE is what displays in the following field as the default value.

An interesting behavior of at least this version of the select function is that if one repeats the exact same function with the same PROMPT and DEFAULT_VALUE in more than one place in a macro, it will only ask the question once. This is actually a feature, not a bug, as one can then use the same answer to that prompt in more than one place. See the macros in the water breathing spell as an example.

Dropdown: This form of the select function displays a dropdown box with the choices available to the player. It takes the following form:

?{ PROMPT | ITEM1, RESULT1 | ITEM2, RESULT2 | ITEM3, RESULT3, … }

PROMPT is the text that tells the user what they are choosing from the drop-down box. Each ITEM clause is a text that summarizes that choice in the list box when the select function executes. Each RESULT is the resulting text that is displayed.

It is in the RESULT text where things can go wrong, and quickly.

The select function will break if certain characters are used in the RESULT clauses because those characters are used to control the function. For example, you can’t put a comma directly in a RESULT clause because the select function uses that in the command to separate the ITEM and RESULT clauses. Likewise, you can’t use curly braces (“{}”) or bar characters (“|”) because the select function uses those as well.

There is, of course, a workaround.

You can convert those characters within RESULT clauses to HTML entities, and they will display as the proper characters when the ?{} function executes. For example, you can replace the comma (,) with the , entity. The examples below illustrate this.

Broken Example:

?{Right Choice, This is the right choice! | Wrong Choice, This choice is wrong, wrong, WRONG!}

When executed, the function will see the first comma in “This choice is wrong, wrong, WRONG!” and truncate the rest of the text. The correct version is this:

Corrected Example:

?{Right Choice, This is the right choice! | Wrong Choice, This choice is wrong, wrong, WRONG!}

Notepad++ uses Ctrl+E to convert a selected character or characters into the appropriate HTML entities so you don’t have to remember or type them.