Ah, how I love to geek out with new MapTool macros!
Some months ago, I was going to be running a Living Forgotten Realms adventure that involved underwater combat, which meant that elevation could come into play. I wanted to have a visible way of displaying a token’s elevation right on the token itself, so I settled on using some token states that would display a number from 1 to 9 on the upper right corner of the token, representing its elevation.
However, I later realized that having a generic number to stick on a token is a useful thing. For instance, a later battle with a hydra showed me that it would be nice to have an indicator for the number of heads. Furthermore, I’d like to be able to display higher numbers as well, just in case.
Enter the new Elevation macro. First, I should explain that this macro requires you to have a certain set of token states (downloadable as a full set of properties and states here for online use or here for projector use) that include “_0” through “_9” for the ones digit and “0_” through “9_” for the tens digit. You’ll need an Elevation property on your token. And then you’ll need a macro like this one, which you can keep on either the Campaign or Global window.
[h: x=input("NewElevation|0|What is the token's new elevation?")] [h: abort(x)]
The code above brings up an input window that asks for the new elevation and ends the macro if the user chooses the Cancel option.
[h: SelectedTokens=getSelected()] [FOREACH(TokenID, SelectedTokens, " "), CODE:
This creates a list of token IDs called SelectedTokens, then starts a loop through each of the tokens, performing the following code on them. Thus, you could set the elevation for a group of three monsters all to the same level at once if you wished.
{[h: OldElevation=getProperty("Elevation",TokenID)]
Figure out the token’s current Elevation property; assign it to the OldElevation variable.
[if(NewElevation>99), CODE: {[assert(1==0,add("<b>Error</b>: Elevation cannot be higher than 99"),0)]}; {}] [if(NewElevation<0), CODE: {[assert(1==0,add("<b>Error</b>: Elevation cannot be lower than 0"),0)]}; {}]
Give an error message if the user tries to enter a new elevation that’s over 99 or less than zero.
[h: OldTensDigit=FLOOR(OldElevation/10)] [h: OldOnesDigit=OldElevation-10*OldTensDigit] [h: NewTensDigit=FLOOR(NewElevation/10)] [h: NewOnesDigit=NewElevation-10*NewTensDigit]
Figure out the tens digit and ones digit of both the old and new elevations. I don’t know if MapTool has a modulus function, so I went with an alternative way of getting the ones digit (pretty elegant in the end, I think).
[h: OldOnesState=add("_", OldOnesDigit)] [h: OldTensState=add(OldTensDigit, "_")] [h: NewOnesState=add("_", NewOnesDigit)] [h: NewTensState=add(NewTensDigit, "_")]
Since the states are called “_1” and “_2” and so on for the ones, and “1_” and “2_” and so on for the tens, I need to concatenate some strings to set up the names of the old and new states (in preparation for removing the old states and adding the new).
[h: setState(OldOnesState,0,TokenID)] [h: setState(OldTensState,0,TokenID)] [h: setState(NewOnesState,1,TokenID)] [h: setState(NewTensState,1,TokenID)]
And here I actually set those states. The old states get set to zero (turned off) while the new states get set to one (turned on). Thus, if the token is changing from an elevation of 13 to an elevation of 20, I’m turning off “1_” and “_3” and turning on “2_” and “_0”.
[h: setProperty("Elevation", NewElevation, TokenID)]
Since I’m changing the elevation states, I need to make sure I also change the elevation value on the token itself so that the macro will work again the next time I run it (the new elevation after this go-through will become the old elevation for the next time I run the macro).
[if(NewElevation<10),CODE:{[h: setState(NewTensState,0,TokenID)]};{}]
This is just for prettiness’ sake; if the new elevation is between 1 and 9, I want to drop the zero from the tens place so the elevation will show up as “7” instead of “07” for instance.
[if(NewElevation==0),CODE:{ [h: setState(NewOnesState,0,TokenID)] [h: setState(NewTensState,0,TokenID)]};{}]
Further prettiness; If the new elevation is zero, I want no elevation states to be displayed at all, so I now remove the new states that I just added.
} ]
And here I close the FOREACH loop and the Code brackets that I started way up at the top.
This macro is useful any time you want to stick a visible number on a token for whatever reason. Now that I’ve got it working, I’ll be interested to see how often it will come up. My suspicion is that I’ll end up using it a lot.
As always, please let me know what macro questions you have or any requests for new macros. I love this stuff!
Note: All macros were generated with version 1.3.b66 of MapTool.
Campaign template for online use, including this and all of my other macros
Campaign template, formatted for projector use
Campaign properties for online use
Campaign properties for projector use
Download the elevation macro alone
The full elevation macro code:
[h: x=input("NewElevation|0|What is the token's new elevation?")] [h: abort(x)] [h: SelectedTokens=getSelected()] [FOREACH(TokenID, SelectedTokens, " "), CODE: {[h: OldElevation=getProperty("Elevation",TokenID)] [if(NewElevation>99), CODE: {[assert(1==0,add("<b>Error</b>: Elevation cannot be higher than 99"),0)]}; {}] [if(NewElevation<0), CODE: {[assert(1==0,add("<b>Error</b>: Elevation cannot be lower than 0"),0)]}; {}] [h: OldTensDigit=FLOOR(OldElevation/10)] [h: OldOnesDigit=OldElevation-10*OldTensDigit] [h: NewTensDigit=FLOOR(NewElevation/10)] [h: NewOnesDigit=NewElevation-10*NewTensDigit] [h: OldOnesState=add("_", OldOnesDigit)] [h: OldTensState=add(OldTensDigit, "_")] [h: NewOnesState=add("_", NewOnesDigit)] [h: NewTensState=add(NewTensDigit, "_")] [h: setState(OldOnesState,0,TokenID)] [h: setState(OldTensState,0,TokenID)] [h: setState(NewOnesState,1,TokenID)] [h: setState(NewTensState,1,TokenID)] [h: setProperty("Elevation", NewElevation, TokenID)] [if(NewElevation<10),CODE:{[h: setState(NewTensState,0,TokenID)]};{}] [if(NewElevation==0),CODE:{ [h: setState(NewOnesState,0,TokenID)] [h: setState(NewTensState,0,TokenID)]};{}] } ]
Thank you for this. I haven’t tested it, but I assume that it works. Prior to this I would do a side view or cross-section of an underwater scene, but you are still locked into two-dimensions. This would definitely allow a more three-dimensional aspect to the game and, as you said, could have other uses. Bravo!
Thanks for the comment – I’m glad you found this to be useful!
There is another one on the RPTools forums that uses auras to easily discern elevation. The higher the elevation the bluer the aura. It is pretty neat. I am waiting for the one that has the token shift offcenter and puts a pseudo base under the token like you would use with real miniatures. There was talk about it like 2 years ago(IIRC), but haven’t seen anything since. Now the new hotness is onTokenMove and automatic token creation using statblocks or DDI files.
The auras sound pretty! Not quite what I’m looking for, but I’ll bet it looks nice.
I remember seeing a thread or two on the RPTools forums about the offset and a shadow for tokens at higher altitude; that too would look nifty. I’ll stick with the numbers for my own game, but it’s always cool to see what people can create.
As for automatic token creation, I know that there are a number of frameworks out there to automate the process, which is awesome. My own game is pretty simple in comparison to what those power users have built!
Well, old post but I couldn’t get this to work. Gives an error
Illegal argument type java.lang.String, expecting java.math.BigDecimal
just from copy/pasting it in.
Thank you very much for this
[h: x=input(“NewElevation|0|What is the token’s new elevation?”)]
[h: abort(x)]
I was looking everywhere how to have an input with a default of 0 and use abort together with it.