MapTool – Creating macros from macros, plus encode and decode

MapTool macros can apparently do just about anything, including BUILDING OTHER MACROS! They’re like nanobots; they’re going to take over the world with an army of macros. Save yourselves from the coming macro revolution!

Or take advantage of it by leveraging the power of MapTool macros to build other macros. Why might you want to do such a thing? Well, in my case it’s because I wanted a better way to build monster powers. My previous approach was to have template buttons for every type of macro I might want on a monster, and then delete the buttons I don’t need. That’s a pain in the butt; it would be much easier to just add the macros I need instead of deleting the macros I don’t need.

Thus, I learned about the createMacro() function. This is one of those “exactly what is says on the tin” macros – it creates another macro. I’d say that this is definitely an intermediate to advanced MapTool topic, at least by my standards. You’ll want to have a working knowledge of JSON objects before using createMacro.

Setting up the createMacro input JSON object

The arguments for createMacro are most easily put together in a JSON object. You can set pretty much anything you can think of for a macro button – its name, the colors of the text and background, what group you want it in, what sort order, whether players can edit it and so on. To do this, set up a JSON object with each of these properties set to the value you want.

For instance, let’s say that you want a macro called Longsword to show up in the Attacks group as the 3rd macro, and you want it to have green text. First, set up the JSON object with these properties:

[h: MacroProps='{“autoexecute”:1, “label”:”Longsword”, “group”:”Attacks”, “sortBy”:3, “fontColor”:”green”, “command”:””}’]

Then run the createMacro function with your new properties as the argument:

[h: createMacro(MacroProps)]

Voila! Problem solved. Well, that was a short article…

Oh right – we need some macro text to carry out, don’t we? This particular set of properties has no real instructions to carry out (that’s what “command”:”” means – a blank macro command box). If we’re going to be putting together strings that include macro instructions, we’re going to need to learn about encode() and decode().

encode() and decode()

The encode() function lets you create a string that contains quotes and brackets and so on. You’ll obviously need this sort of thing in your macro command, so it makes sense to encode the various lines of macro text, stick them together in a string list, and plop that into the “command” property of your JSON for createMacro. A useful trick I learned is that if you’re encoding a line break, you have to use \\n to represent it (for “new line”).

I don’t believe encode() is strictly necessary in all of these cases, but it’s getting the job done and I’m sticking with it!

When you’re ready to unpack what you’ve encoded, you can use decode().

A simple example

Let’s say I want to use a macro to create another macro that will roll a die and output the result with a little formatting and a friendly message. I’m going to call the created macro “New Macro 1”. I want it to roll a d6. And I’m going to pass my choice of a d6 to the macro as a variable.

[h: MacroName=”New Macro 1″]
[h: DieSize=6]

Here I’ve set a variable for the name of the macro and another for the die size that I want to roll. Now I’m going to start setting up the “command” text to pass to the createMacro() function.

[h: MyCommand=””]
[h: MyCommand=MyCommand+encode(“[h: DieToRoll=”+DieSize+”]\\n”)]

The first line above initializes a blank string as the variable MyCommand (not strictly necessary, but it helps me follow what’s going on). The second line takes whatever is in MyCommand (a blank string at this point) and adds some encoded text to it.

You’ll note that the text I’m encoding is in double-quotes, and when I want to add the value of my DieSize variable I close the quotes, add a plus sign, then the name of the variable that I want to be evaluted, then another plus sign and re-open the quotes. Note also that I’m encoding a full line of MapTool text, including square brackets, the h: roll option, and the \\n for a line break in the code itself (as opposed to <br>, which would output a line break to the chat window).

[h: MyCommand=MyCommand+encode(“Die Result = <b>[r: roll(1, DieToRoll)]</b> – Good job!”)]

I now add another line of code to the command sting I’m building up. This one is a full line of MapTool code within double quotes – no breaks to bring in variables from this macro, but there is a reference to a variable that exists in the new macro (DieToRoll).

[h: MacroProps='{“autoexecute”:1, “label”:”‘ + MacroName + ‘”, “fontColor”:”green”, “command”:”‘ + decode(MyCommand) + ‘”}’]
[h: createMacro(MacroProps)]

I now build the JSON object that I’ll be using for createMacro. I do want the macro to auto-execute, so I set that property to 1 (true). I’m calling on my MacroName variable for the name. And I’m decoding the MyCommand string as the command text for the new macro.

When I run the macro, I get a new button, labeled “New Macro 1” in green text. If I open up that macro to edit it, I see:

[h: DieToRoll=6]
Die Result = <b>[r: roll(1, DieToRoll)]</b> – Good job!

And when I execute New Macro 1, I get a message in the chat window:

Voila – a macro created from a macro!

Now what?

This is a proof-of-concept: You can indeed create a working macro using a macro. But what I really want to do is to create a macro that will ask me for input, and then use that input to create another macro. For instance, a macro that will ask me for the name of an attack, the damage, whether it’s at-will or encounter or recharge, etc., and then build a new power for a monster with those characteristics.

That, my friends, is the topic of my next post. I have built such a thing, and it is wondrous to behold!

Stay tuned.

-Michael the OnlineDM

3 thoughts on “MapTool – Creating macros from macros, plus encode and decode

  1. I apologize for this in advance:

    YO DAWG! I HEARD YOU LIKE MACROS. SO WE PUT MACROS IN YOUR MACROS SO YOUR MACROS CAN MAKE MACROS!

Leave a Reply