OnlineDM Mailbag #2: MapTool versus Fantasy Grounds

Welcome back to the exceedingly irregular OnlineDM Mailbag series! My first mailbag column came back in November 2011, and now in July 2012 I’m finally getting around to the second. I’d love to do more of these, so if you have a question you’d like me to answer on the blog, please send it to me at

Tobold writes:

Hi Michael!

I was looking into virtual tables for D&D 4th edition, not necessarily
to run a multiplayer game on, but for preparing my “real table”
campaign by playtesting combat encounters. I know you are a big
MapTools fan, but I’ve also seen several people claiming Fantasy
Grounds 2 was good. Did you ever try Fantasy Grounds 2? Do you have an
educated opinion of which program is better, MapTools or Fantasy
Grounds 2?

OnlineDM answers:

I do know that Fantasy Grounds 2 is quite popular, and from the people I’ve spoken to about it I believe that it’s a great tool. I haven’t personally used it, though, despite the research I’ve done into it.

My conclusion is that Fantasy Grounds is the “pretty” version of MapTool. The 3D dice rolling is very popular. The user interface is designed to look like you’re sitting at an actual wooden table. There are the equivalent of MapTool frameworks built for lots of games, including 4e.

However, I come down firmly on the side of MapTool for my own games. The biggest reason, frankly, is that it’s free. If you want to buy a Fantasy Grounds license that will let you run an unlimited number of games for anyone who wants to play, it’s going to cost you $150. For MapTool – nada. That’s a big deal to me; not that I can’t afford the $150, but MapTool does everything that FG2 does, so why would I pay for FG2?

I love the full customizability of MapTool. I can use it in a very bare-bones way, or I can go nuts with programming the fanciest stuff I can imagine. FG2 allows for this kind of development, too, but again, why pay for it?

Basically, I haven’t seen anything from FG2 that has ever tempted me to pay for it when MapTool is free. If MapTool had failings that FG2 addressed, I’d definitely give FG2 a shot. But it doesn’t have those failings, at least not in my games. I’m totally happy with MapTool and see no reason to pay to switch.

So, just to be clear, I think that Fantasy Grounds is a cool program, and I’m sure that lots of people will find it to be worthwhile. But for me, since I’m already very comfortable with MapTool, I wouldn’t want to pay the kind of money it would cost to use FG2 in the way I use MapTool (letting an unlimited number of people play in games that I host without having to pay a cent).

-Michael the OnlineDM

OnlineDM1 on Twitter

OnlineDM Mailbag #1: Simple IF statements in MapTool

A suggestion from Benoit (who, based on this blog post, seems to be the person behind Roving Band of Misfits) prompted me to start a mailbag series. Welcome to issue #1! I’d love to get more mailbag questions, so if you have an issue you’d like to see me address, please drop me a line at

Question from Benoit:

I have a lot of trouble with simple “If” statements. I found a few examples in the forums, but I can’t seem to write my own.

Answer from OnlineDM:

Thanks for the question, Benoit! IF statements are an important part of most programming languages, including MapTool. Let’s do some examples

Concept #1: There are two different IF statements in MapTool

MapTool is a bit of an odd language in that you can have two different structures for the same thing. An IF statement, for instance, can either be a roll option or a function.

IF statement roll option

A roll option comes “before the colon” in MapTool macros. One common roll option is h: which causes the result of the line of code to be hidden (useful for assigning a value of a variable without printing anything to the chat window).

The syntax for an IF statement roll option is:

  • [if(Foo>Bar): Thing you do if Foo is greater than Bar; Thing you do if Foo is not greater than Bar]

For instance, here’s a very simple two-line macro

[h: Variable=InputVariable]
[if(Variable>10): "The variable is greater than ten"; "The variable is not greater than ten"]

The first line brings up an input box that asks the user to type in a number, which is assigned to Variable. The second line uses the IF roll option to see if Variable > 10 and then displays the appropriate message.

Note that you don’t have to specify the “if not” part of this second line if you don’t want to. If I want to display a message if Variable>10 but do nothing otherwise:

[h: Variable=InputVariable]
[if(Variable>10): "The variable is greater than ten"]

In this particular case, I’d output a blank line to the chat window if Variable is less than or equal to ten. This is more useful in cases where I’m doing things behind the scenes that are hidden rather than outputting them to the chat window.

Note that if you have another roll option you want to use at the same time as the IF roll option (such as the h: roll option to make the output hidden), you’ll put that other roll option before the IF statement, separated by a comma:

[h: Variable=InputVariable]
[h, if(Variable>10): "The chat window won't actually display this because I used the h roll option, too!"]

If you want to do just one thing in the case where a particular condition is true, the simple IF roll option is a good way to do it.

The IF roll option with the CODE roll option

What if you want to do multiple things if a particular condition is true? Then you want to use the CODE roll option alongside the IF roll option.

[h: Variable=InputVariable]
[if(Variable>10), CODE:
 Can you believe the variable is greater than 10?
 [h: DoubleVariable=Variable*2]
 And if you double the variable, you get [DoubleVariable]!
 What do you know? The variable is not greater than 10.
 [h: HalfVariable=Variable/2]
 And if you cut the variable in half, you get [HalfVariable].

Now instead of just doing one thing when a particular condition is true, I can do several. I accomplish this by sticking the CODE statement after the IF statement (separated by a comma) and then the colon. Then I have the code to execute for the “true” case of the IF statement enclosed in curly braces, followed by a semicolon and then the code to execute for the “false” case of the IF statement inside another set of curly braces.

I can do as much stuff as I like within those curly braces. Note that once I’m in curly braces, it’s just like being outside of square brackets. Text typed normally will be printed straight to the chat window, and any code I want to execute (such as assigning variables or printing their values) is enclosed in square brackets. I can even do more IF statements and CODE blocks inside these curly braces if I need to (though you can only go two layers of curly braces deep in MapTool).

The IF function

The other way to test a condition using an IF statement is to use the IF function. Functions in MapTool come “after the colon”.

[h: Variable=InputVariable]
[h: NewVariable=if(Variable>10, Variable*2, Variable/2)]
The new variable is [NewVariable].

In this example, the IF statement comes after the colon. I’m specifically using the IF function here to assign the value of a new variable, conditional on an existing variable. The syntax is completely different:

  • [NewFoo = IF(Foo>Bar, Value of NewFoo if Foo is greater than Bar, Value of NewFoo if Foo is not greater than Bar)]

You’ll note that now the “what to do” part for both the true and false cases are within the parentheses of the IF statement instead of outside the parentheses as they were for the IF roll option. They’re separated from the condition being tested by a comma (instead of a closed parenthesis and colon as in the roll option), and the “true” and “false” options are separated from one another by a comma as well (instead of a semicolon as in the roll option).

There’s no way to use CODE blocks here. So far in my own MapTool programming, I’ve only used the IF function for the particular purpose of assigning the value of a variable or other very simple tasks. I use the IF roll option much more frequently.

Concept #2: How to test conditions

I’ll wrap up with some notes on syntax. The syntax to check whether Foo is greater than Bar, Foo is less than Bar, Foo is greater than or equal to Bar and Foo is less than or equal to Bar is all exactly what you would expect:

[If(Foo>Bar): ... ]
[If(Foo<Bar): ... ]
[If(Foo>=Bar): ... ]
[If(Foo<=Bar): ... ]

Less obvious is how to check whether Foo is not equal to Bar – you use an exclamation point followed by an equals sign:

[If(Foo!=Bar): ... ]

The worst of all comes on the check you’ll likely use most often: Seeing whether Foo is equal to Bar. For this, you need to use a double equals sign:

[If(Foo==Bar): ... ]

If you try what you’ll no doubt try at some point [if(Foo=Bar):…], you’ll get an error message from MapTool.

I’ll also note that you might want to check to see whether a variable is equal to a particular string (some text rather than a number). In that case, you need to make sure the value you’re checking for is enclosed in quotes.

[h: Variable=FavoriteColor]
[if(Variable=="Blue"): "My favorite color is blue, too!"; "I see. Well, I prefer blue."]

Note the syntax. First, I’m using the IF roll option (before the colon), not the function. Second, I’m using the double equals sign to check for equality. Third, I’m enclosing “Blue” in quotes to see if that’s what’s been entered for Variable. If I enter Red or Nothing or 75 into the input box, I’ll get a message in the chat window saying “I see. Well, I prefer blue.” But if I enter Blue into the input box, I’ll get a message in the chat window saying “My favorite color is blue, too!”

If I forget the quotes around the word Blue in parentheses, I’ll get a second input box asking me for the value of Blue. MapTool will think that Blue is a variable that I haven’t assigned a value to, instead of a string that I want to check Variable against.


Well Benoit, I hope you found this to be helpful! MapTool is a bit of a wonky language, but it can get you where you need to go most of the time. Understanding the ins and outs of the IF roll option and the IF function will take you a long way.

Remember everyone, send me your future mailbag questions at

-Michael the OnlineDM

OnlineDM1 on Twitter