Macros:Branching and Looping
This page details the branching and looping structures in MapTool. With the exception of the Block If statement, these are all roll options and should follow the general form for roll options:
[option1[,option2]: body]
These may be combined with other roll options (note that in some examples, they are combined with the Hidden Roll option (h) to hide the default output of the loop or branch).
Branching
Block IF()
Introduced: Version 1.3.b38
Usage
[h: if(condition, true_value, false_value)]
Example
[h: val=12]
[h: if(val > 10, "Value is greater", "Value is less")]
Returns Value is greater.
Notes
You cannot make an assignment inside a block-IF statement. For example:
[if(Ability=="Strength", AbilityModifier=4, "")]
will return a "Could not execute the command: null" error. Instead, write the statement like so:
[AbilityModifier = if(Ability=="Strength", 4, "")]
If you wish to make assignments (or must make multiple assignments based on an condition) use the IF( ) roll option and CODE option instead.
IF Option
Introduced: Version 1.3.b46
This IF is a roll option (as mentioned above), but operates similarly to the block-style if.
Usage
[IF(condition): true_body; false_body]
- or
[IF(condition): true_body]
Either the true_body or false_body will be used, depending on the value of condition. If the false_body is not given but the condition is false, then there is no output.
Example
[h:val=12]
[h,IF(val == 12): newVal=12*12]
New Value = [r:newVal]
Outputs New Value = 144.
SWITCH Option
Introduced: Version 1.3.b46
SWITCH chooses among several options and executes code based on the switch expression.
Usage
[SWITCH(expression):
case case1: body1;
case case2: body2;
default: default_body]
Example
[h:powerType="at-will"]
[SWITCH(powerType):
case "at-will": "You may use this power as much as you like";
case "encounter": "You may only use this power once per encounter";
case "daily": "You may only use this power once per day"]
Outputs "You may use this power as much as you like"
MACRO Option
Introduced: Version 1.3.b46
MACRO runs the named macro, inserting its text into chat.
Usage
[MACRO("macro_name@location"): macro_arguments]
The called macro sees a variable called macro.args which contains the value of macro_arguments. The called macro can set a variable called macro.return, which becomes available to the calling macro. Other than macro.return, the called macro shares no variables with the calling macro.
Examples
[MACRO("getDamage@Lib:combat"): damageRoll]
Calls the macro "getDamage" which resides on a library token called "Lib:combat", and passes the variable damageRoll as an argument to the called macro.
Location Requirements
The location can be one of the following:
- TOKEN - the currently impersonated token
- Library Token - a Library Token in the current campaign
- this - if the macro is calling another macro in the same library, "this" may be used instead of retyping the full library token name
Notes
When a token macro calls another macro, the macro instructions in the called macro are executed against the calling token, unless the focus is explicitly changed to another token via either a roll option or the switchToken() function.
TOKEN Option
Introduced: Version 1.3.b48
TOKEN executes a series of instructions against a token specified in the argument to [TOKEN():], rather than against the token running the macro.
This is a temporary change in the token that has the "focus" - only the instructions following the colon are applied to the designated token; following the end of that instruction block, operations resume being performed against the token running the macro.
To permanently switch (for the duration of the macro) the token against which macro commands are executed, see the switchToken() function.
Usage
[token(token_identifier): ]
Executes the roll against token specified by token_identifier, which can either be the token name or token id.
Examples
[h:target="Orc 5"]
[h,token(target): targetAC = getProperty("AC")]
Uses the getProperty() function to retrieve the property AC from the token named "Orc 5", and assigns that value to the variable targetAC. targetAC can be used in future calculations, such as determining whether an attack hits. If the TOKEN option was not used, the macro would have looked for the property AC on the token currently running the macro.
Looping
COUNT Option
Introduced: Version 1.3.b41
The COUNT option executes a statement a specified number of times, storing the number of the current iteration in a variable called roll.count.
Usage
[COUNT(num): body]
[COUNT(num, separator): body]
The roll.count variable will take on values from 0 to (number of loops - 1). The optional separator (default ", ") is printed between each iteration.
Example
[h:numHits=3]
[COUNT(numHits): Damage = Damage + 1d12]
Will iterate the Damage = Damage + 1d12 operation 3 times, separating the result of each iteration with the default separator (a comma). An optional second argument to COUNT() allows the setting of a different separator.
FOR Option
Introduced: Version 1.3.b46
Executes a statement for a number of iterations based on a start and end value.
Usage
[FOR(var, start, end): body]
[FOR(var, start, end, stepsize): body]
[FOR(var, start, end, stepsize, separator): body]
The var variable counts from start to end during the loop. The optional stepsize (default +1) is added to var at each iteration.
Example
[FOR(i,10,0,-2): "i is now " + i]
Counts down even numbers from 10 to 0.
FOREACH Option
Introduced: Version 1.3.b46
Iterates over the contents of a string list in the format "item1, item2, item3"
Usage
[FOREACH(var, list): body]
[FOREACH(var, list, output_separator): body]
[FOREACH(var, list, output_separator, list_separator): body]
Example
[h: enemyList="Orcs, Goblins, Ogres, Trolls"]
[FOREACH(enemy, enemyList, "<br>"): "You really hate " + enemy]
Outputs
You really hate Orcs You really hate Goblins You really hate Ogres You really hate Trolls
WHILE Option
Introduced: Version 1.3.b46
Repeatedly executes a statement until a condition becomes false.
Usage
[WHILE(condition): body]
[WHILE(condition, separator): body]
Example
[h:num=10]
[WHILE(num>=0): num = num-1]
Outputs 9,8,7,6,5,4,3,2,1
Code Execution
CODE
Introduced: Version 1.3.b46
The CODE option is used in conjunction with looping / branching options to execute multiple statements within a single "block" of a loop or branch, allowing the creation of more complex loops and branches.
Usage
[CODE: { code_block }]
The code_block is a collection of text and macro code, enclosed in a single {} pair. Everything within the {} is treated as a single block for the purposes of any looping or branching options.
Example
[h:num=5]
[WHILE(num > 0), CODE:
{
This is iteration [r:num] <br>
There are [r:num-1] iterations left<br>
[num=num-1]
}]
Outputs
This is iteration 5 There are 4 iterations left 4, This is iteration 4 There are 3 iterations left 3, This is iteration 3 There are 2 iterations left 2, This is iteration 2 There are 1 iterations left 1, This is iteration 1 There are 0 iterations left 0
NOTE: the digit output at the beginning of each line is an artifact of the WHILE loop's evaluation of num - since this roll does not have the h option active, the result of that evaluation is displayed.
Nested CODE Blocks
To nest CODE:{} blocks, use a second CODE:{ } option, like so:
[h:d20roll=1d20]
[h:attackRoll=d20roll+AttackBonus]
[h,IF(attackRoll >= 16),CODE:
{
[IF(d20roll == 20),CODE:
{
The attack is a critical hit!
[h:damage=critDamage]
};
{
The attack is hit!
[h:damage=regDamage]
};]
};
{
The attack misses!
};]
MapTool can only handle two levels of nested code.