Guide to onTokenMove: Difference between revisions
m (Taustin moved page guide to onTokenMove to Guide to onTokenMove) |
m (Text replacement - "source>" to "syntaxhighlight>") |
||
Line 46: | Line 46: | ||
[{"x":50,"y":50},{"x":0,"y":0}] | [{"x":50,"y":50},{"x":0,"y":0}] | ||
--> | --> | ||
</ | </syntaxhighlight> | ||
Line 92: | Line 92: | ||
[r,if(attackRoll > Dexterity):"You have triggered a trap and sustained "+roll+" hits.<br>"] | [r,if(attackRoll > Dexterity):"You have triggered a trap and sustained "+roll+" hits.<br>"] | ||
};{}] | };{}] | ||
</ | </syntaxhighlight> | ||
An example of a Teleport macro: | An example of a Teleport macro: | ||
Line 131: | Line 131: | ||
[goto(targetToken)] | [goto(targetToken)] | ||
};{}] | };{}] | ||
</ | </syntaxhighlight> | ||
Please note that there already exists a drop-in [http://forums.rptools.net/viewtopic.php?f=46&t=16066] that facilitates Traps and Teleports (among other things), which you can find on the forum. The tricky part is to get multiple 'special pads' working next to each other in combination with multiple tokens move. | Please note that there already exists a drop-in [http://forums.rptools.net/viewtopic.php?f=46&t=16066] that facilitates Traps and Teleports (among other things), which you can find on the forum. The tricky part is to get multiple 'special pads' working next to each other in combination with multiple tokens move. | ||
Line 155: | Line 155: | ||
<span style="color:red;font-weight:bold;">Move limit exceeded.</span> | <span style="color:red;font-weight:bold;">Move limit exceeded.</span> | ||
}] | }] | ||
</ | </syntaxhighlight> | ||
==Exposure of Fog on gridless maps== | ==Exposure of Fog on gridless maps== | ||
Line 163: | Line 163: | ||
<!-- clear fog only if pc token moved --> | <!-- clear fog only if pc token moved --> | ||
[h, if( isPC() ): exposeFOW()] | [h, if( isPC() ): exposeFOW()] | ||
</ | </syntaxhighlight> | ||
[[Category:Cookbook]] | [[Category:Cookbook]] |
Revision as of 17:10, 14 March 2023
... and all related stuff
Recently a great new feature has been added to MapTool. This guide shall aide you to use it. Every time a token is moved (by the user) a specific macro is called. This macro can even cancel that move.
Events
Just like onCampaignLoad
the new events are macros on a lib:token that have to be named like the event. Note that (and this is different to onCampaignLoad
) these events should be only defined on a single, unique Lib:token - doing otherwise can lead to unexpected behaviour. To state it clearly: there should not be two Lib:tokens in a campaign file with these macros on it at the same time.
onTokenMove
The event macro onTokenMove
is called whenever any token on the TOKEN layer is moved via the user interface. So the event is NOT triggered for movement on the hidden,object or background layer. That tokens path is available as content of macro.args
. The moved token is the token in context, so you can get its id with currentToken().
onMultipleTokensMove
The event macro onMultipleTokensMove
is only called when more than one tokens are moved at once. The macro.args
contain a json array with all moved tokens ids. The is no token context.
Note that, before onMultipleTokensMove
is actually called, onTokenMove
is called for each single token.
If you use both events at the same time it is recommended that you use the tokens.moveCount
variable in onTokenMove
and abort if its >1 and let onMultipleTokensMove
handle it.
If you dont know what event to use you probably want to use onTokenMove
.
How to set it up
- You need a Library Token. You'll find some details if you follow that link, but its simply a token named "Lib:something" that is a NPC and visible to players.
- On this token you place macros. If you want to use the event onTokenMove you create a macro named
onTokenMove
on it.
Thats it. Yeah, it is so simple. For what you can really do with this you can see the examples below.
Special Variables
There are some special variables that are needed or useful in context of these events.
tokens.denyMove
has to be set to 1
to cancel the current movement.
tokens.moveCount
contains the number of tokens moved.
Paths
In context of these events there will sometimes be specified or returned a path or a list of coordinates. These are in this specific format:
it is a json array containing json objects for each points. Each json object defines the keys x
and y
with the map coordinates.
<source lang="mtmacro" line> [h: samplePath = json.append("",
json.set("", "x", 50, "y", 50), json.set("", "x", 0, "y", 0)
)]
</syntaxhighlight>
If you have to construct coordinate arrays by hand you can use a simple drop-in tool that you can download here: rptools-forums: shapeBuilder
Related Functions
There are a number of functions that are very useful in combination with the onMove-events.
getLastPath()
getLastPath() returns the last path. Note that - if you use this in onTokenMove
- it returns exactly the same as macro.args
. (requires b74+)
movedOverPoints(arrayOfCoordinates)
movedOverPoints() returns an array of coordinates with all "hit" cells within a shape formed by the specified array of coordinates. (requires b75+)
movedOverToken(tokenName, [lastPath])
movedOverToken() returns an array of coordinates with all "hit" cells where the moved token crosses the specified token. (requires b74+)
Note that before b77 the token must be specified by name - not id.
getMoveCount()
getMoveCount() returns the calculated move cost according to the selected move metric. (requires b76+)
Examples
Lets now give you some simple examples for most commons use cases.
Traps/Teleporting
An example of a trap macro:
<source lang="mtmacro" line> [h:] [h:] [h:] [h:lastPath = getLastPath(1)] [h:] [h:trapPadTriggered = movedOverToken("Spear Trap",lastPath)] [r, if(!json.isEmpty(trapPadTriggered)), CODE:{ [h:] [h:me = getSelectedNames()] [h:switchToken(me)]
[h:attackRoll = d20]
[h:roll=1d6]
[h,if(attackRoll > Dexterity):HP=HP-roll]
[r,if(attackRoll > Dexterity):"You have triggered a trap and sustained "+roll+" hits.
"]
};{}]
</syntaxhighlight>
An example of a Teleport macro: <source lang="mtmacro" line> [h:]
[h:] [Token(padName): startCentreX = getTokenX(1)] [Token(padName): startCentreY = getTokenY(1)] [Token(teleportEndName): endCentreX = getTokenX(1)] [Token(teleportEndName): endCentreY = getTokenY(1)] [h:] [h, Token(targetToken):CurrentX = getTokenX()] [h, Token(targetToken):CurrentY = getTokenY()] [h:] [h:NewX = CurrentX + endCentreX - startCentreX] [h:NewY = CurrentY + endCentreY - startCentreY] [h:] [h, Token(targetToken):moveToken(NewX, Newy , 1 )] [h:] [goto(targetToken)]
};{}] </syntaxhighlight> Please note that there already exists a drop-in [1] that facilitates Traps and Teleports (among other things), which you can find on the forum. The tricky part is to get multiple 'special pads' working next to each other in combination with multiple tokens move.
Movement cost tracking
A often requested feature is to track allowed movement. With the new events we can do that.
The example expects the movement to be tracked with a property named Movement. You have to reset this property to some kind of max movement every round - eg by hand or by hooking it in your initiative handler.
<source lang="mtmacro" line>
[h: mov = getProperty("Movement")] [h: usedMov = getMoveCount()]
[r, if( mov >= usedMov ), code: {
[h: mov = mov - usedMov] [h: setProperty("Movement", mov)]
};{
[h: tokens.denyMove = 1]
Move limit exceeded.
}] </syntaxhighlight>
Exposure of Fog on gridless maps
Fog does not get cleared on gridless maps. But we can do this by using a simple onTokenMove-event. <source lang="mtmacro" line> [h, if( isPC() ): exposeFOW()] </syntaxhighlight>