MapTool Macros – Basic Attacks

Edit 7/19/2010: Since I first wrote this post, I have learned more about MapTool macros, and you can find the improved information at this post.  However, I’ve left the original post below for posterity – and as an example of how to learn how to improve your macro writing, rather than just giving the finished product.

Warning: Though this post is about “basic” attacks, it’s rather epic in length.  I go through a detailed exercise of building a moderately complex macro from scratch here, which takes time to explain.  You have been warned! 🙂

Continuing my series on writing MapTool macros, it’s time to finally get to something more interesting – player attacks.  I’ve created macros for a player’s melee basic attack and ranged basic attack (very similar to one another), which can be used as the foundation for most attack powers that only target a single enemy.  I’ll talk about multi-enemy attacks in my next post.

In this post, I’ll walk you through the entire process of developing a basic attack macro, starting from a simple macro that rolls a d20, adds the hard-coded attack modifier, rolls the hard-coded damage die and adds the hard-coded damage modifier.  That macro would have to be different for every PC, and it would have to be manually changed every time the PC changes their weapon, goes up a level, etc.  We’ll end up with a generic macro that can be used for almost any PC and that will change with the character.

We’re going to write a Melee Basic Attack macro for Violet, a second-level Ranger who wields a non-magical longsword.  She has Strength of 17 (a +3 modifier) and a +3 proficiency bonus to hit with the longsword.  She’ll also get +1 to hit from half of her level.  Her total attack bonus is therefore +7.  The longsword does d8 damage (plus Violet’s +3 Strength bonus) on a hit.

To create a new macro for a Violet, we’ll click on Violet’s token on the MapTool map.  One of the windows we should see at the bottom of the screen is the Selection window (if you can’t see it, go to Window – Selected).  This window will show the token image and name, with a little bit of text below it that reads, “No Macros.”  We’ll right click where it says “No Macros” and choose Add New Macro.  This will create a new button in that window labeled (new).  Right click on the (new) button and choose Edit.

Now we’re editing the macro.  Start by changing the name from (new) to Melee Basic Attack.  Down in the Command box we’ll type the following:

Attack: [d20+7]
Hit: [d8+3]

When we then click the Melee Basic Attack button, we get:

Violet: Attack: 25 Hit: 11

Now, we could call it a day here.  This works.  If Violet’s player (or anyone else) hovers their mouse over the 25 for the attack roll, it will show a ToolTip that explains this comes from a d20+7 roll (18+7=25).  The same goes for the damage roll.  We can do better, though.

Let’s start with some basic formatting.  Having Violet spout off with a couple of numbers in the chat window works, but it might be nice for her to mention that this is a Melee Basic Attack, that it’s attacking Armor Class, and that it’s dealing regular damage.  It might also be nice to have some line breaks added between the attack roll and the damage roll.  Here is a “prettified version” of the macro:

<b>Melee Basic Attack</b><br>
Attack: <b>[d20+7]</b> versus AC<br>
Hit: <b>[d8+3]</b> damage

The <b> and </b> HTML tags put whatever is between them in bold face.  I’ve put the name of the attack and the numeric results of the rolls in bold face to make them stand out.  I’ve also added <br> tags at the end of each line (except the last one) to create line breaks.  I’ve also added the note that the attack is versus AC and that the hit roll is damage.  Now the output will look more like this:

Violet: Melee Basic Attack
Attack: 21 versus AC
Hit: 7 damage

So, this looks nice now and it works.  If you want to keep things simple, you can stop now.  But every time anything changes for Violet, we’ll have to manually edit the numbers within her attack macros individually.  In an ideal world, we would have Violet’s character sheet in MapTool and our macro could look to that sheet to figure out her Strength modifier, her weapon proficiency, her weapon damage die, any magical enhancement on the weapon and the half-level value.  That way whenever Violet gets new equipment or levels up, we only have to modify that character sheet, not every one of her attack macros.

Fortunately, MapTool does have Properties for tokens.  If you double click on a token and click on its Properties tab, you will see the default basic properties for a token in MapTool listed.  These might be great for some games, but for D&D Fourth Edition I’ve found a different set to be useful.  To change the available properties for your tokens, go to Edit – Campaign Properties.  Click on Basic on the left side of the window that pops up, delete the existing block of properties and replace them with the following:

@Level:1
*@HitPoints:10
*@ArmorClass:10
*@Fortitude:10
*@Reflex:10
*@Will:10
*@Speed:6
*@Initiative:0
*@Strength:10
*@Constitution:10
*@Dexterity:10
*@Intelligence:10
*@Wisdom:10
*@Charisma:10
@MeleeEnhancement:0
@RangedEnhancement:0
@MeleeProficiency:0
@RangedProficiency:0
@MeleeDamageDie:6
@RangedDamageDie:6
@MagicEnhancement:0

The @ symbol in front of each property means that only the owner of the token and the GM (that’s you, Sparky) will be able to see the property’s value.  The * in front of some properties means that the property and its value on the character’s stat sheet that will pop up when you mouse over the token (though they will only be visible to the token’s owner, of course).  The colon with a number after it sets the default value for the property (and as far as I can tell is the only way that you can make the values editable for any given token).  The reason that I’ve made the properties visible to the owner and GM only is that I will be using them for monsters as well as PCs, and I don’t want the PCs seeing the monsters’ defenses, hit points, etc.

Once you’ve saved these as your default properties, you can double click on your PC’s token (Violet in this case) and change the values.  The important ones for this macro are Strength (17), MeleeDamageDie (10), MeleeProficiency (3), MeleeEnhancement (0) and Level (2).  I’ve set the rest of them as well, as you can see in this image of Violet’s token properties.

Token Properties

Now that Violet has values for Strength and so on, we can use them in our macro and then just edit Violet’s properties when she levels up or gets a new sword.  This requires somewhat fancier programming in the MapTool macro – beginning with the idea of a variable.

To establish a variable in a MapTool macro, you can do something as simple as writing: [MyVariable=10].  This would establish a variable called MyVariable and assign it a value of 10, which you could then use later in your macro (such as [MyOtherVariable = MyVariable + 5], giving MyOtherVariable a value of 15).  If you write it just like that, though, MapTool with send a message to the chat window with the value of the variable.  So a random “Violet: 10” would pop up.  Since we don’t want to actually send anything to the chat window when we declare the variable, we will denote this line as being hidden from chat by putting h: at the beginning of the declaration:

[h: MyVariable=10]

Technically this h: is a “roll option” in the MapTool lingo.  Remember that these macros are fundamentally constructed to roll dice, though you can also send text to the chat window and do more complex things.  There are lots of roll options you can use at the beginning of your bracketed code, such as gm: or just g: to show the result of the roll in the chat window for the GM but to hide it from the players.  In any case, we’ll be using lots of hidden lines in our macros since we don’t want every calculation showing up in chat – just the results.

Next, we need to know how to get the value of the properties that we’ve set for Violet so we can use them in our macro.  Fortunately, MapTool has a function called getProperty that does exactly this.  To figure out Violet’s melee proficiency bonus (which goes into the calculation of the attack bonus), we use the following code:

[h: Prof=getProperty(“MeleeProficiency”)]

This creates a variable called Prof, which is equal to the value of the property called MeleeProficiency.  Yes, the quotes and the parentheses are required.

What about Violet’s strength modifier?  We need to get the value of the Strength property, subtract ten from it, divide that by two and then round down.  Here’s the code to do all that:

[h: SkillMod=FLOOR((getProperty(“Strength”)-10)/2)]

The FLOOR function does the rounding down (CEIL or CEILING would round up).  Note that I’m calling this SkillMod to make it easier to re-use this code for other attacks that might use other skills, such as the Ranged Basic Attack that would use Dexterity.  Using similar logic to get some other properties, we’re able to write code that will let us calculate the attack bonus and damage bonus for the melee basic attack:

[h: SkillMod=FLOOR((getProperty(“Strength”)-10)/2)]

[h: DamageDie=getProperty(“MeleeDamageDie”)]
[h: HalfLevel=FLOOR(getProperty(“Level”)/2)]
[h: Prof=getProperty(“MeleeProficiency”)]
[h: Enh=getProperty(“MeleeEnhancement”)]

[h: AttackBonus=SkillMod+HalfLevel+Prof+Enh]
[h: DamageBonus=SkillMod+Enh]

Now we can go back to our earlier prettified macro and substitute in the AttackBonus and DamageBonus variables.  We can also use the ROLL function to take advantage of the fact that the damage die is now a variable rather than hard coded.  With the ROLL function, you tell MapTool the number of dice and the number of sides on each die you want to roll, so a d20 would be [ROLL(1,20)].  Put the lines of code above first, followed by these:

<b>Melee Basic Attack</b><br>
Attack: <b>[d20+AttackBonus]</b> versus AC<br>
Hit: <b>[ROLL(1,DamageDie)+DamageBonus]</b> damage

The output will look exactly the same as before, but now we shouldn’t have to touch the macro when things change for Violet.

There’s still one little wrinkle in our plans here, though – what happens if the d20 for the attack roll comes up on a natural 20?  That, my friends, would be a critical hit and should result in maximum damage.  It’s entirely possible to roll a natural 20 with this macro and not notice, in which case you might just take the regular result of the damage roll rather than taking the maximum possible damage.  To fix this, we need to get a little fancier.

I’ll start by saying that I like the ToolTip mouse-over function that shows players the breakdown of the die roll.  It’s not just a 22, it’s a d20 that came up on 15 plus an attack bonus of 7.  We’re getting into some programming that is going to have to roll the attack one time and then store the result as a variable, which means that when we show that variable, we’ll lose the d20 ToolTip.  So, things are going to look a little different because I’m going to start explicitly printing out the breakdown of the attack and damage rolls.

We’re going to need to roll the d20 for the attack once and store the result.  While we’re at it, we might as well roll the damage die once and store the result, along with figuring out what the max damage would be in case of a crit.  Below the earlier lines where we were defining variables, we add these lines:

[h: d20roll=d20]
[h: DamageRoll=roll(1,DamageDie)]

[h: AttackRoll=d20roll+AttackBonus]
[h: MaxDamage=DamageDie+DamageBonus]
[h: RegularDamage=DamageRoll+DamageBonus]

Now we’ve defined the result of rolling a d20 for the attack as a variable called d20roll and the result of rolling the damage die as a variable called DamageRoll.  This means that we can output the result of the attack roll and then check to see if there was a critical hit.  If there was a crit, we want to call out this fact and make sure the damage is maxed.  If not, we want to print the normal damage roll output.  This means that we need to get into the IF function in MapTool.  I won’t go into all of it here – I’ll just show the final version.  The gory details of using IF statements in MapTool can be found in the excellent MapTool wiki, so I won’t rehash them.

<b>Melee Basic Attack</b><br>
Attack: [d20roll] + [AttackBonus] = <b>[AttackRoll]</b> versus AC<br>
[if(d20roll==20), CODE:
{<font color=Red>–CRITICAL HIT–</font><br>
Damage: [DamageDie] + [DamageBonus] = <b>[MaxDamage]</b> damage
};
{Damage: [DamageRoll] + [DamageBonus] = <b>[RegularDamage]</b> damage}
]

Yes, this is a little bit complicated.  Basically, I print the name of the attack and the result of the attack roll (broken down into the d20 and the attack bonus).  I then check to see if there was a crit.  If there was, I print –CRITICAL HIT– in red (that’s the <font folor=Red> and </font> HTML tags) and then print the max damage breakdown.  If there wasn’t a crit, I print the normal damage breakdown.  The square brackets, curly brackets, parentheses and colons all have to be handled just right, and the CODE statement is a little touchy, too.  The wiki can explain it all.

In the end, we’re left with a snazzy little macro that efficiently handles melee basic attacks with critical hits, getting all of its information from the character token’s properties.  I haven’t included code to check for extra damage from a magical weapon on a critical hit, but that would be easy enough.  It would require a new property that tells you what the bonus damage die from your weapon is and then some extra code in the MaxDamage calculation to account for it.  As they say in textbooks, this is left as an exercise for the reader. Similarly, making this into a macro for Ranged Basic Attack is as simple as replacing the word Strength with Dexterity and Melee with Ranged in the macro code.

I hope you find this macro construction process to be helpful.  In my next macro article, I’ll show you how I’ve programmed in multi-attack abilities.   The final version of the Melee Basic Attack macro is below.

[h: SkillMod=FLOOR((getProperty(“Strength”)-10)/2)]

[h: DamageDie=getProperty(“MeleeDamageDie”)]
[h: HalfLevel=FLOOR(getProperty(“Level”)/2)]
[h: Prof=getProperty(“MeleeProficiency”)]
[h: Enh=getProperty(“MeleeEnhancement”)]

[h: AttackBonus=SkillMod+HalfLevel+Prof+Enh]
[h: DamageBonus=SkillMod+Enh]

[h: d20roll=d20]
[h: DamageRoll=roll(1,DamageDie)]

[h: AttackRoll=d20roll+AttackBonus]
[h: MaxDamage=DamageDie+DamageBonus]
[h: RegularDamage=DamageRoll+DamageBonus]

<b>Melee Basic Attack</b><br>
Attack: [d20roll] + [AttackBonus] = <b>[AttackRoll]</b> versus AC<br>
[if(d20roll==20), CODE:
{<font color=Red>–CRITICAL HIT–</font><br>
Damage: [DamageDie] + [DamageBonus] = <b>[MaxDamage]</b> damage
};
{Damage: [DamageRoll] + [DamageBonus] = <b>[RegularDamage]</b> damage}
]

7 thoughts on “MapTool Macros – Basic Attacks

    • Yes, you can put decimal numbers, although I’m not sure why you would want to. There’s nothing special to it – you just enter 3.2 as the value for DamageBonus, or whatever you’re trying to do.

  1. Thank you would Mich for writing this. It’s really thorough and easy to understand. I’ve been trying to learn some basic programming for a couple years but I never got far. I was able to use all this information and I’m looking forward to learning more.

Leave a Reply to Kathy Cancel reply