https://wiki.rptools.info/api.php?action=feedcontributions&user=Lwoestman&feedformat=atomRPTools Wiki - User contributions [en]2024-03-28T18:49:56ZUser contributionsMediaWiki 1.40.1https://wiki.rptools.info/index.php?title=Feature_List&diff=8982Feature List2020-09-14T23:02:02Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Feature List}}<br />
Originally compiled for MapTool version 1.3b86 and may be missing some of the more recent features. It still covers the main features of MapTool.<br />
<br />
==Software==<br />
*MapTool is Java based, meaning it is platform independent (e.g. runs on Window, Mac, Linux etc.)<br />
*Open Source<br />
*Free<br />
<br />
==Extensive Community of Users==<br />
MapTool is supported by an active and lively community on a variety of social media platforms.<br />
*Large [https://forums.rptools.net/ community forum] with years of history.<br />
*[https://discord.gg/crpk7FM Discord Server]<br />
*[https://www.facebook.com/RPTools/ Facebook Page]<br />
*Large number of user-created [https://www.youtube.com/results?search_query=maptool+tutorial video tutorials].<br />
<br />
==Maps==<br />
*Supports virtually infinite maps, limited only by each connected computer's memory resources<br />
*Ability to create maps, even in real time during a game using built-in drawing tools and drop-in image support<br />
*Ability to drag and drop images from virtually anywhere into MapTool to use as maps, tokens, objects, etc.<br />
** Can accept from the system clipboard, file browsers, web browsers, TokenTool, chat software, etc. <br />
*Ability to view PDF files as folders of images from the Resource Library so they can be added directly<br />
*Built-in drawing tools with texture support<br />
*Support for 4 layers of map drawing:<br />
**'''background''' here you either draw maps or drag images to become maps both from outside MapTool or from within MapTool<br />
**'''object''' here you can again draw and drag images both from outside MapTool or from the internal library<br />
**'''hidden''' same as other layers but everything in this layer is visible to the GM only<br />
**'''Token''' the actual layer where the players and the GM have their tokens which they can move around. Has the same drawing and dragging support as the other layers<br />
*Multiple map support<br />
*Export and Import function for MapTool type maps<br />
*Hi-res Screenshot support<br />
<br />
==Fog of War==<br />
*Option for individual character fog of war, otherwise FoW is shared by the entire party<br />
*Hard fog for undiscovered areas<br />
*Soft fog for previously discovered areas but outside Line of Sight (note, no items on the token layer show to players if the item is in soft fog)<br />
*Option to reset the fog<br />
*Option to manually clear fog<br />
*Option to manually recreate fog<br />
*Option to have player movement clear fog automatically<br />
<br />
==Grid==<br />
*Different types of grids:<br />
**Square<br />
**Hex (Horizontal Hex)<br />
**Vex (Vertical Hex)<br />
**Isometric (as of 1.4)<br />
*Grid color<br />
*Grid size<br />
*Grid offset<br />
*Toggle snap to grid<br />
*Grid is positioned above the background and below the objects to give a sense of depth in the maps<br />
*Ability to [[Auto Resize]] imported map images to quickly fit the grid (as of 1.4)<br />
<br />
==Library Support==<br />
*MapTool includes a built-in library with:<br />
**Tokens (e.g. Hero, Dragon, Troll)<br />
**Objects (e.g. door, wall, table)<br />
**Textures (e.g. Grass, Cobble stones, Mud)<br />
**States (e.g. Stunned, Blinded, Dazed)<br />
**Other stuff like Overlays, example Maps, Health Bars, Dice, Cards<br />
*Option to download from RPTools other available resources packs like maps, tokens and objects<br />
*Option to extend the resource library with material localized on your own PC<br />
<br />
==Frameworks==<br />
Through the MapTool forum and its very lively community frameworks have been created which give support for the following RPG games:<br />
*D&D 3.5 Ed<br />
*D&D 4 Ed (English, French and Spanish)<br />
*D&D 5 Ed<br />
*Pathfinder<br />
*Warhammer 40k - Dark Heresy<br />
*Warhammer 40k - Roque Trader<br />
*Warhammer 40k - Deathwatch<br />
*Warhammer 40k - Black Crusade<br />
*Warhammer 40k - Only War<br />
*Warhammer 2nd Ed<br />
*Warhammer 3rd Ed<br />
*Call of Cthulhu 5.6 Ed<br />
*Call of Cthulhu 6 Ed<br />
*Call of Cthulhu 7 Ed<br />
*Fate 3.0<br />
*Hackmaster<br />
*Dragon Age<br />
*Savage Worlds<br />
*Hero 5th ed.<br />
*HarnMaster 3<br />
*Star Wars<br />
*Bash<br />
*Gurps<br />
*Gumshoe<br />
*Ars Magica 5h Ed.<br />
*Dogs in the Vineyard<br />
*A couple of board games<br />
<br />
==Script language (Macro support)==<br />
*MapTool provides a script language with which the above Frameworks have been developed<br />
*There exists an active and up-to-date Wiki with support for the script language<br />
*There are several 'drop-in' resources available through the forum<br />
<br />
==Tables==<br />
*MapTool provides a support for [[Introduction to Tables|basic lookup tables]] with text or images keyed to dice rolls or ranges.<br />
*Using the UI or chat commands, tables can return a random result to the chat window.<br />
*Macro scripting functions can automate and chain the creation and use of tables.<br />
<br />
==Preferences==<br />
*A LOT of settings are provided to personalize MapTool to your needs<br />
<br />
==Interface==<br />
*Different panels are available: <br />
**Initiative Panel: contains images of the active tokens and their respective initiative number<br />
**Global Panel: contains macros that are locally stored (on the PC) and are independent of the active Framework (i.o.w. always there).<br />
**Campaign Panel: contains macros that are applicable for the campaign (Framework)<br />
**Selection Panel: contains macros specifically for the currently selected Token(s)<br />
**Impersonate Panel: same as Selection only this always applies to a single Token<br />
**Table Panel: Panel with the tables<br />
**Resource Library Panel: here the Resources are available<br />
**Map explorer Panel: here one can see which tokens are on the map and in which layer<br />
**Draw explorer Panel: here one can see drawings by layer and edit their properties<br />
**Connection Panel: shows who's connected through the (inter)net to your game<br />
*Panels can be: <br />
**Docked or Undocked (floating)<br />
**Hidden<br />
**Auto-hidden, accordion style, ie, when you mouse near the edge where the panel is set to auto-hide, it pops out for use and hides itself once you mouse out.<br />
**Docked panels may also be dragged into tabbed groups of multiple panels<br />
*Full screen support<br />
*Zoom option (which is definitely necessary with the possibility of very very very large maps)<br />
<br />
==Tools==<br />
*Force view<br />
*Force Zoom Level<br />
*Lock movement<br />
*Lock Zoom<br />
<br />
==Different Languages==<br />
*English<br />
*French<br />
*Italian<br />
*Japanese<br />
*Spanish<br />
*German<br />
*Polish<br />
*Russian<br />
<br />
==Tokens==<br />
*Maptool differentiates between PC's and NPC's<br />
*Option to set Ownership of tokens (so player can Own NPC tokens or multiple PCs)<br />
*Option to set 'vision' of a token:<br />
**Night vision<br />
**Normal vision<br />
**Arc/Cone, Circle, or Square<br />
**Range<br />
*Option to set 10 different sizes including free-size (technically, objects are "free size" and tokens are "native size")<br />
*Local properties (like Strength and Toughness) are completely customizable per token<br />
*Stat sheet on mouse over token, again completely customizable (and can be hidden for all tokens)<br />
*States can be set per token<br />
*Health bars, either standard or again completely customizable (can also be used for Ammo, Stamina, etc.)<br />
*Shape, different shapes are supported:<br />
**Square<br />
**Circle<br />
**Top Down (rotates entire token when facing is set, token is also not limited to its square) (that last part applies to all tokens)<br />
*Option to set token visibility (e.g. all clients can see the token or only owners can see the token)<br />
<br />
==Light==<br />
*set different ranges<br />
*set different shapes (Square, Circle, Cone with an arc ranging from 1 to 360 degrees)<br />
*set different colors<br />
*set layers of lights (e.g. first yellow and then an outer ring of red)<br />
*set auras (don't shed light, but can be used to show ranges of weapons, for example)<br />
*set auras visible to self, all, or GM-only<br />
*Create different groups of light<br />
<br />
==Chat box==<br />
*loads of chat commands <br />
*smiley support<br />
*can handle html commands<br />
*broadcast option<br />
*impersonate token and talk from that token<br />
*whisper to a single token (so the rest won't see the message) or GM only<br />
*(show/hide) typing notifications<br />
*different colors<br />
*scroll lock<br />
*allow macro commands to be typed straight into the chat<br />
<br />
==Maptool summarized in one picture==<br />
[[Image:DHFWOverviewScreenshot.jpg|This is a combination of native Maptool functionality and a campaign (W40K) created in maptool.]]<br />
<br />
==Drop-in: Bag of Tricks==<br />
This is not a default feature which comes with Maptool, but something you need to install.<br />
This drop-in will roughly add an additional 80 features like Teleports, animated doors, automatic VBL manipulation, token grouping, extended tables, debug tools, etc. etc. It can be found [http://forums.rptools.net/viewtopic.php?f=46&t=16066 here]. The web-post includes a full list of all features, tutorials on how to use and install it. <br />
<br />
<br />
[[Category:MapTool]]<br />
--[[User:Wolph42|Wolph42]] 15:18, 11 May 2011 (UTC)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Sample_Ruleset&diff=8981Sample Ruleset2020-09-14T22:01:59Z<p>Lwoestman: /* Derived Attributes */</p>
<hr />
<div>This is a small roleplaying game system created by Phergus for use in examples and samples for RPTools applications. As noted on the original thread, this is not meant to be a mature and balanced system, but rather a system that contains enough aspects to highlight a good selection of application features. See the [http://forums.rptools.net/viewtopic.php?f=12&t=6343 original thread] for more details.<br />
<br />
==Characters==<br />
===Primary Attributes===<br />
Primary attributes are determined using a point system. Starting characters are given {{code|14}} points to distribute among their four primary attributes. Each primary attribute must at least have a value of {{code|1}}, but can be no higher than {{code|6}}.<br />
* '''Strength (Str)'''<br />
* '''Dexterity (Dex)'''<br />
* '''Intelligence (Int)'''<br />
* '''Endurance (End)'''<br />
'''Summary:''' Total of {{code|14}} points. Minimum of {{code|1}}. Maximum of {{code|6}}.<br />
<br />
===Derived Attributes===<br />
Characters possess three derived attributes. ''Hit Points'' are determined by multiplying ''Endurance'' by {{code|6}}. Each character class has a different ''Armor'' score; ''Armor'' can also be increased by powers. Base ''Movement'' is equal to a character's ''Dexterity''.<br />
* '''Hit Points (HP)'''<br />
* '''Armor (AR)'''<br />
* '''Movement (MV)'''<br />
'''Summary:''' (''Endurance'')x{{code|6}} ''Hit Points''. ''Armor'' determined by class. ''Movement'' equals ''Dexterity''.<br />
<br />
===Classes===<br />
At character creation, players get to choose a class for their character. The chosen class determines beginning powers and ''Armor''.<br />
{| cellpadding="5" cellspacing="0"<br />
|- bgcolor=#e0ddd5 align=left<br />
! Class !! Beginning Powers !! Armor<br />
|-<br />
| Warrior || Sword, Shield Bash, Bow, Shield, Torch ||align=center| 6<br />
|- bgcolor=#eeede9<br />
| Rogue || Dagger, Hide, Backstab, Pick Lock, Torch ||align=center| 2<br />
|-<br />
| Wizard || Dagger, Staff, Light, Lightning Bolt, Fire Ball ||align=center| 1<br />
|- bgcolor=#eeede9<br />
| Priest || Mace, Heal, Protect, Banish Undead, Torch ||align=center| 4<br />
|}<br />
<br />
==Combat==<br />
===Initiative===<br />
Each combatant rolls for initiative at the beginning of each round. Initiative roll is {{code|1d6}} + ''Dexterity''. Each combatant acts in order of initiative, highest to lowest, each round.<br />
<br />
===Movement===<br />
Combatants can use a power or move each round. When moving, a combatant can move a number of squares/hexes equal to their ''Movement''.<br />
<br />
===Attack Roll===<br />
An attack power requires a roll to determine if it succeeds. If the roll is {{code|15}} or higher after applying any bonuses, the attack power succeeds.<br />
* '''Melee Attacks''' - Roll {{code|1d20}} + ''Strength'' + Power Attack Bonus<br />
* '''Ranged Attack''' - Roll {{code|1d20}} + ''Dexterity'' + Power Attack Bonus<br />
* '''Spell Attack''' - Roll {{code|1d10}} + ''Intelligence'' + Power Attack Bonus<br />
'''Summary:''' A {{code|15+}} on the attack roll succeeds.<br />
<br />
===Damage Roll===<br />
If an attack power succeeds in hitting the target, determined damage by rolling {{code|1d6}}, apply the power damage bonus, add the relevant attack attribute, and finally subtract the target's ''Armor''. Subtract the result from the target's ''Hit Points''.<br><br />
'''Summary:''' {{code|1d6}} + (Power Damage Bonus) + (Attack Attribute Bonus) - Armor<br />
<br />
==Powers==<br />
PCs/NPCs have Powers that represent their attacks and abilities. Beginnning PCs have 5 powers. NPCs will have a variable number but at least 1. Two types of powers: Attack & Other. During any combat round a PC/NPC may have 1 non-attack Power active and may use 1 Power to attack.<br />
<br />
====Attack Powers====<br />
{| cellpadding="5" cellspacing="0"<br />
|- bgcolor=#e0ddd5 align=left<br />
! Name !! Attack Bonus !! Damage Bonus !! Range !! Special<br />
|-<br />
| Backstab || +4 || 2x || - || Must attack from rear and have been hidden previous round.<br />
|- bgcolor=#eeede9<br />
| Banish Undead || +0 || +8 || 4 || Only works on Undead. With a roll of 6 on a d6 the Undead is Enraged and gains +2 damage for 3 rounds.<br />
|-<br />
| Bite I || -1 || -2 || - || <br />
|- bgcolor=#eeede9<br />
| Bite II || -1 || -1 || - || Infects target on a roll of 5+, reduces Strength by 2.<br />
|-<br />
| Bow || +0 || +1 || 8 || <br />
|- bgcolor=#eeede9<br />
| Chilling Touch || -1 || +2 || - || Freezing touch does damage and reduces Dexterity by 2.<br />
|-<br />
| Claw || -2 || +2 || - || <br />
|- bgcolor=#eeede9<br />
| Curse || +0 || +0 || 3 || Pain from attack reduces Intelligence by 2.<br />
|-<br />
| Dagger || +0 || -1 || 2 || Melee or ranged.<br />
|- bgcolor=#eeede9<br />
| Fire Ball || -1 || +0 || 4 || Does damage to target and all in the immediately adjacent squares/hexes.<br />
|-<br />
| Heal || * || - || 4 || Heals target (self/other) for 2d6. *No roll to hit.<br />
|- bgcolor=#eeede9<br />
| Lightning Bolt || +1 || +4 || 6 || Single target<br />
|-<br />
| Mace || +1 || +1 || - || <br />
|- bgcolor=#eeede9<br />
| Shield Bash || -1 || 1/2 || - || Stuns foe with a 4+ on a d6 for 3 rounds.<br />
|-<br />
| Staff || +0 || +0 || - || <br />
|- bgcolor=#eeede9<br />
| Summon Undead || - || - || 2 || Summons 1 zombie.<br />
|-<br />
| Sword || +2 || +2 || - || <br />
|}<br />
<br />
====Other Powers====<br />
{| cellpadding="5" cellspacing="0"<br />
|- bgcolor=#e0ddd5 align=left<br />
! Name !! Range !! Special<br />
|-<br />
| Hide || - || Hides Rogue from enemies. Cannot attack except for Backstab.<br />
|- bgcolor=#eeede9<br />
| Light || - || Illuminates a 6 square/hex radius around Wizard.<br />
|-<br />
| Pick Lock || - || Opens Lock on 1d6 + Dexterity > Lock Difficulty.<br />
|- bgcolor=#eeede9<br />
| Protect || 4 || Gives +4 Armor to target. (self/other)<br />
|-<br />
| Shield || - || Adds +2 Armor. Can't be used with Shield Bash.<br />
|- bgcolor=#eeede9<br />
| Torch || - || Illuminates a 3 square/hex radius around character.<br />
|}<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Introduction_to_Tokens&diff=8980Introduction to Tokens2020-09-14T21:52:31Z<p>Lwoestman: /* Creating a New Token */</p>
<hr />
<div>{{Beginner}}<br />
==Introduction to MapTool Tokens==<br />
<br />
As mentioned in the [[Introduction_to_Mapping| Introduction to Mapping]] guide, a [[Macros:Glossary#T|token]] is the MapTool jargon for a visual marker that is placed on a map within the MapTool software. The most intuitive use for tokens is to represent characters in the game - in other words, tokens take the place of miniatures on the virtual tabletop. <br />
<br />
===Assumptions===<br />
<br />
This guide assumes that you have read the [[Introduction_to_Mapping|Introduction to Mapping]], and that you know how to:<br />
<br />
* Add folders to your Resource Library, and update/add images to those folders so that they appear in your resource library<br />
* Create a map in MapTool<br />
* Place tokens on a map, and move them around<br />
* Change token names, GM names, labels<br />
* Change the token's size<br />
* Change the token's image<br />
* Move tokens from one layer to another<br />
<br />
If you don't know how to do these things, please read the Introduction to Mapping guide - otherwise, the stuff below might not make much sense!<br />
<br />
Finally, this guide will be written predominantly from the point of view of the GM -- someone who has complete control over all token settings and campaign properties. Players (that is, individuals who join a game in the role of "Player") are restricted from changing many things in a particular campaign.<br />
<br />
===MapTool's Layers===<br />
<br />
Although most MapTool users use the term "token" to refer only to images representing characters and creatures on a map, in reality, the word "token" refers to ''any'' image item that is dropped onto a map in MapTool. The way a particular token is handled is dependent on the Map Layer onto which it is placed. These layers are explained below, because they are important in understanding how to work with tokens.<br />
<br />
*Items dropped on the '''Token''' layer are what we most commonly consider "tokens" - these represent characters, monsters, NPCs - the people and creatures of the game. <br />
*Items dropped on the '''Object''' layer are most commonly images representing furniture, chests, and ''things'' in the game world - something that a person can manipulate or use. MapTool still considers them to be tokens, of course (everything is a token to MapTool - it's very singleminded) but for clarity's sake, most users call them ''Objects'' to distinguish them from tokens that represent ''characters''.<br />
*Items dropped on the '''Background''' layer are typically things that make up the map - walls, cliffs, dirt, grass. They might be unique, but are most often "stamped" onto the map over and over again, either in a pattern or because you're using several copies of the same image (for instance, using several copies of a wall image to make a complete room). Because of this, many users will call these images ''stamps''. <br />
<br />
====The Hidden Layer====<br />
<br />
You'll note that I didn't discuss the '''Hidden''' layer in the above paragraph. That's because the Hidden Layer has a slightly different purpose. <br />
<br />
While the Token, Object, and Background layers have a fairly intuitive relationship in terms of how one might think of the world -- I'm a ''person or creature'', that item over there is an ''object'', and surrounding us is the ''background'' -- the Hidden Layer is the things you ''cannot see''. In MapTool, anything placed on the Hidden Layer is visible only to the GM until he or she decides to move it to one of the other layers.<br />
<br />
Generally, you'll want to put characters and objects on this layer - there aren't many reasons to put a background stamp on the hidden layer, although I'm sure you can think of a couple. <br />
<br />
Suffice it to say, when you place a token on a MapTool map, it pays to be aware of which layer you placed it on!<br />
<br />
==Creating a New Token==<br />
<br />
Creating a token is as simple as dragging an image from the [[Macros:Glossary#R|Resource Library]] onto the Token Layer of a map. In addition to a few default tokens, MapTool has several great token packs freely available for download through the RPTools Library tab of the {{ui location|File > Add Resource to Library...}} dialog. You can also drag an image directly from your file system into your map view in MapTool and it will create a token out of it.<br />
<br />
But how do you create custom token images yourself, or find custom tokens for your game? There are several options.<br />
<br />
===Download an Image===<br />
<br />
MapTool's user community has created a wealth of token images that are available for use. Visit the [https://forums.rptools.net RPTools Forums] or check out the #artwork channel pins on the [https://discordapp.com/invite/hbn2bfn MapTool Discord Server] for help finding the hundreds of token images already out there.<br />
<br />
===Create one Using TokenTool===<br />
<br />
Another option is to create your own images using [http://www.rptools.net/index.php?page=tokentool TokenTool], a program built by the makers of MapTool to create token images quickly and easily.<br />
<br />
To create an image using TokenTool:<br />
<br />
1. Download TokenTool and open it by double-clicking on the file with the extension '''.jar''' (this is a Java "JAR file" which will run a java program). <br />
<br />
2. Find an image you like (be cautious about copyright!) and drag it onto the left pane of the TokenTool window (this is the part with the small green ring and a black background). <br />
<br />
3. When the image appears, drag it around with the mouse until the portion you want for your token is inside the green ring. You'll see a preview of what the token will look like in the upper right side of the TokenTool window.<br />
* '''Tip''': You can use the mouse wheel or the zoom buttons to adjust the image's size until it looks just right. <br />
* '''Tip''': You can change the look and color of the border, the final size of the token, and many other settings by using the drop-down menus on the right-hand side of the TokenTool window.<br />
<br />
4. When you get it where you like it, go to '''File > Save Token''', and save the newly created token in a directory that is either already in your Resource Library, or is one you plan to add to your resource library. Note that the file will be saved in PNG format (this is a good thing! it allows for transparency so your token isn't slopping outside the border!). <br />
<br />
5. Go back to MapTool and add or refresh your Resource Library, and there you'll see your new token! Drag it onto a map, and you're good to go. <br />
<br />
===Draw One Yourself===<br />
<br />
You can create a token image of your own by using an art program and saving the file in PNG or JPG format, in a directory that is either in your Resource Library, or a directory you plan to add to your Resource Library. PNG format is the recommended format for MapTool tokens because it allows for transparency and, basically, looks the best. <br />
<br />
You can of course combine drawing your own image with using TokenTool to create handsome and neatly formed tokens.<br />
<br />
==Editing a Token==<br />
<br />
Editing a token means changing any of the token's characteristics, be that its image, its name(s), or its configured settings. Changing token names, image, and size are covered in [[Introduction_to_Mapping|Introduction to Mapping]]. <br />
<br />
The following sections deal with the various options, tabs, and drop-down boxes in the '''Edit Token''' Dialog. <br />
<br />
===Token Type===<br />
<br />
Tokens have 2 possible types in MapTool: NPC and PC. These will be familiar to players of roleplaying games because they stand for "Player Character" and "Non-Player Character," and the most common use of this "type" setting is to distinguish between the two groups during actual play. <br />
<br />
In general, tokens belonging to your players should have the type "PC." Tokens belonging to ''you'' should have the type "NPC". <br />
<br />
[[Image:Token_Edit_Notes.png|thumb|The '''Edit Token''' dialog]]<br />
<br />
'''NOTE''': The ''type'' of a token does not have any bearing on who may manipulate that token or view it's properties - instead, that power is granted to the ''owner'' or ''owners'' of a token. As GM, you are considered to have ownership of all tokens on all maps in the campaign. See [[Introduction_to_Tokens#Ownership|Ownership]], below, for more details. <br />
<br />
To change the token type:<br />
<br />
1. Double-click the token to open the '''Edit Token''' dialog.<br />
<br />
2. In the upper-right corner, use the drop-down box to select PC or NPC. <br />
<br />
3. Click '''OK'''.<br />
<br />
===Notes===<br />
<br />
[[Image:Token_Edit_Notes.png|thumb|The Notes Tab of the '''Edit Token''' dialog]]<br />
<br />
The Notes tab presents two areas where you can enter notes about the token. These fields support basic HTML tags, so you can format the note. <br />
<br />
The upper text field is there for notes that are available and visible to anyone who wishes to see. The lower field (titled '''GM Notes''') is for notes that only the GM(s) should see. <br />
<br />
Notes are a little tricky - MapTool has a way to display them in a nifty popup, but you have to do a couple things first. <br />
<br />
# Enter information in the notes field of a token.<br />
# Place that token on the '''Object Layer''' or the '''Background Layer''' by right-clicking and selecting '''Change To >'''<br />
# Switch back to the '''Token Layer'''<br />
<br />
Now, you'll notice that when you put your mouse cursor over the token, the cursor will change to a hand. If you double-click, instead of the normal '''Edit Token''' dialog, you'll see a small popup in the lower-left corner of the map, which will display the notes.<br />
<br />
The major lesson is that -- while Token notes can be accessed in many ways -- one of the more common uses is to place notes and reminders on tokens and objects that will be on either the Object or Background layer.<br />
<br />
===Properties===<br />
<br />
[[Image:Token_Edit_Properties.png|thumb|The '''Properties''' tab]]<br />
<br />
'''Properties''' are a topic that deserve their own guide, as they are '''heavily''' involved in the creation and use of token macros. This guide won't go into excruciating detail about properties, but will instead deal with only the most basic information about them. <br />
<br />
Every token dropped onto a map in MapTool automatically gains a set of '''properties''', which can basically be thought of as stats, characteristics, or traits (you know, the numbers on a character sheet). In effect, each token is carrying around it's own built-in character sheet. In programming terms, properties can thought of as variables that can be set to different values, and then used later by macros. <br />
<br />
* '''Note: although people frequently refer to "token properties," the properties that are visible in the Edit Token dialog are only those properties that are set up for the specific campaign.<br />
<br />
When you click on the '''Properties''' tab in the '''Edit Token''' dialog, you'll see a list of the properties that are currently set up for the '''Campaign''' you're using. If you've opened up a new campaign (or just started MapTool), you will see the ''default property set'', which looks like:<br />
<br />
* Strength<br />
* Dexterity<br />
* Constitution<br />
* Intelligence<br />
* Wisdom<br />
* Charisma<br />
* HP<br />
* AC<br />
* Defense<br />
* Movement<br />
* Elevation<br />
* Description<br />
<br />
For the rest of this guide, examples using properties will use the list above. <br />
<br />
The property list you see is in a table (or spreadsheet) layout, with the property name on the left, and a blank space on the right. In the space on the right, you can enter the value you want to assign to that property. You can enter text, numbers, or in more advanced cases, macro statements as the value for a particular property.<br />
<br />
Once you do that, and hit '''OK''', that property '''on that token''' will be assigned the value you enter. Later on, if you write macros, you can refer to those properties to make calculations or roll dice.<br />
<br />
Since properties are such a major topic on their own, check out the [[Introduction to Properties]] guide for detailed information.<br />
<br />
===VBL===<br />
<br />
[[Image:Token_Edit_VBL.png|thumb|The '''VBL''' tab]]<br />
<br />
Tokens can have VBL applied to them so they can block [[Introduction to Lights and Sights|lights and sight]]. <br />
<br />
* Generate Token VBL: Creates VBL on the token automatically from the token's image. This totally regenerates the VBL every time it is clicked.<br />
* Color Selection: Use the eye-dropper to pick a color in the image to be turned into VBL. Defaults to using transparent areas of the image.<br />
* Color Sensitivity: Adjusts how closely to match the selected color or transparency.<br />
** Inverse VBL Color Selection<br />
'''VBL Optimization'''<br />
* Level: The distance a line segment between two points can be from the edge of an image. A higher level will reduce the total number of points but may not follow as closely to cave walls and other irregular surfaces.<br />
* Method: Choose between Douglas Peucker(default), Topology Preserving, VW Simplifier and No Optimization.<br />
* Clear Token VBL: Resets the VBL on this token, totally clearing it.<br />
&nbsp;<br />
* Move VBL To Map: Copies the Token VBL to the Map's VBL layer. If Erase Source VBL is {{Checked}}, this also clears the token's VBL. <br />
* Move VBL From Map: The inverse, replacing any Token VBL with any VBL which overlaps the token's occupied square. If Erase Source VBL is {{Checked}}, this also clears the map VBL which was copied.<br />
** Erase Source VBL: When {{Checked}}, clears source VBL in the above two operations.<br />
<br />
'''Token Visibility'''<br />
* Is Visible over FoW: Allows the whole token to render above [[Fog of War]] if some of it is visible (controlled by Visibility Tolerance). This is helpful for figure tokens on isometric maps, so they don't appear cut off at the waist when partially visible or up against VBL. Also useful on doors, pillars or other map objects that block line of sight but are difficult for players to spot if partially covered by [[Fog of War]].<br />
*: ''Note'': If Vision is Off on a map, this setting will always display the token over hard fog of war regardless of VBL, Token Sight, or Map Vision Distance. This can cause issues on maps with many 'Visible over FoW' doors, as all the doors will all appear over the hard fog which can spoil the map for players.<br />
* Visibility Tolerance: How many of the 9 zones of the token need to be in Line of Sight of another token to be revealed to it. Has no effect if Vision on the map is set to 'Off'.<br />
<br />
* Hide Token Image Preview: When {{Checked}} hides the token image preview and only shows the VBL in the preview area.<br />
<br />
'''VBL Preview'''<br />
<br />
Shows the token image with VBL if present. When generating VBL the Original Point Count will appear in red and the Optimized Point Count will appear in green.<br />
<br />
<br style="clear:both;"/><br />
<br />
===State===<br />
<br />
[[Image:Token_Edit_State.png|thumb|The '''State''' tab]]<br />
<br />
[[Image:State-example.jpg|thumb|This token has a state applied - the small red image is the "state image" superimposed on the token image]]<br />
<br />
'''[[Token State|States]]''' are visual markers that can be applied to a token (typically appearing as an image superimposed on the token) that can be used for any sort of reminder that you might need in a game. For instance, if you want a marker that a particular NPC token is "dead", you can set the state "Dead" on the token, and whatever image you've selected to indicate "Dead" will appear on the token.<br />
<br />
The default states that load when MapTool starts are:<br />
<br />
* Dead<br />
* Disabled<br />
* Hidden<br />
* Prone<br />
* Incapacitated<br />
* Other<br />
* Other 2<br />
* Other 3<br />
* Other 4<br />
<br />
{{Clear}}<br />
<br />
====Health Bar====<br />
<br />
[[Image:Bar-example.jpg|thumb|This token has a ''bar'' applied, superimposed on the token. The bar can be set to reflect different quantities via macros]]<br />
<br />
The State tab also contains the setting information for the '''[[Bars]]''' that the token displays or can display. These bars are shown superimposed over the token (at the top, bottom, or sides), and can be used to track things like health (or ammunition, magic, or anything that can be lost or expended).<br />
<br />
<br style="clear:both;"/><br />
<br />
===Macros===<br />
<br />
As of MapTool version 1.3.b54, the Macros tab is no longer enabled. This tab originally held the token macros, but as macro capabilities became more advanced, this tab became less and less useful, until finally, it was removed. It is present in earlier versions, though, if you want to take a look.<br />
<br />
===Speech===<br />
<br />
[[Image:Token_Edit_Speech.png|thumb|The '''Speech''' tab]]<br />
<br />
This tab contains the token's '''speech''' list. You can use this tab to configure sayings, aphorisms, battlecries, and anything you might want your token to "say" in chat. There are two fields for each speech item: <br />
<br />
* '''ID''': This field is the short identifier you assign to a speech item; the ID is used in chat to refer to the full text of the speech. It can be alphanumeric, so you could use number, or letters, or a mix. It cannot have any spaces in it, though!<br />
* '''Speech Text''': This is the actual text that will be displayed in the chat window. <br />
<br />
To use a speech item, do the following:<br />
<br />
# Select the token you want to have "say" something<br />
# In the chat window, enter '''/tsay (ID)''', where "(ID)" is replaced by the actual ID of the speech item. So if you wanted to howl your battlecry - which you've cleverly given the ID "bcry" - you would select your token, and enter '''/tsay bcry''' in the chat window.<br />
<br />
===Ownership===<br />
<br />
[[Image:Token_Edit_Ownership.png|thumb|The '''Ownership''' tab]]<br />
<br />
Token '''ownership''' determines who among the players [[Introduction_to_Game_Hosting|connected to the game]] is allowed to select, move, or view the details of a given token. <br />
<br />
If you are the owner of a token, you may select it, double-click on it to open and edit it, and move it around on the map. If you are ''not'' an owner of a particular token, you are limited to looking at it on the map -- you will not be able to select, move, or view its properties and configuration.<br />
<br />
To set an owner, simply check the box next to that individual's name. The names shown in the box will be the names of each player (including the GM) connected to the game (so if you're looking at the Ownership tab when nobody else is connected, you'll see only your own name). If you want to give ownership to all players, just check '''All Players'''.<br />
<br />
(Note that the selection of options when the server is started must include '''Strict token ownership''' if you want the functionality described above. See [[Introduction to Game Hosting#Starting Up a MapTool Server]] for details on server options.)<br />
<br />
===Config===<br />
<br />
[[Image:Token_Edit_Config.png|thumb|The '''Config''' tab]]<br />
<br />
This tab contains a number of settings that affect how the token looks, moves, and interacts with MapTool. <br />
<br />
====Shape====<br />
<br />
Tokens can have four shapes in MapTool:<br />
<br />
* '''Top Down''': top-down tokens are usually hand-drawn or rendered images of creatures, objects, and people as if you were looking down from an aerial view. Setting the token shape to '''Top-down''' tells MapTool to allow the token image to rotate when you right-click on the token and select '''Change Facing''' (that way, your top-down token can turn to face its enemies!)<br />
* '''Circle''': circular tokens are like pogs or poker chips - round images that represent the creature or character. Because they are markers and not meant to be realistic "top-down" views of a creature, when you select Change Facing, instead of rotating the image - which would look bad - a small yellow arrow appears to indicate facing.<br />
* '''Square''': square tokens work like circular tokens, except that they are...wait for it...square.<br />
* '''Figure''': figure tokens have been introduced from Maptool 1.4 and like top-down tokens are usually images of creatures or people but this time designed to appear as though you are looking at a miniature figure on a table. Figure tokens are specifically designed so that if they are higher than they are wide, they will extend beyond the top of the cell.<br />
<br />
====Size====<br />
<br />
A token can be given a number of sizes, which scale the token image larger or smaller. <br />
<br />
The available size depend on the map grid used when [[Introduction_to_Mapping|setting up a map]]. If you set a map with a grid (hexagonal or square), you will have the ''Free Size'' option (which lets you scale the token as you need), or a number of sizes from "Fine" to "Colossal" (if you play D&D, you'll probably recognize them). <br />
<br />
If you do not set a grid when you create the map, you will be able to scale the token along a number scale, from -11 to +20. <br />
<br />
====Properties====<br />
<br />
This field allows you to indicate which of the available property sets in the campaign this token has. The designer of a campaign can set up different sets of properties to be used by different tokens (for instance, a set of properties for player character tokens, and a different set of properties for non-player character tokens). This field lets you pick which property set to use.<br />
<br />
====Has Sight====<br />
<br />
This field allows you to indicate what kind of [[Introduction to Lights and Sights|sight]] the token possesses. '''Sight''' settings allow the gamemaster to simulate darkness, light, hidden objects, and hiding enemies.<br />
<br />
====Image Table====<br />
<br />
Introduced in Maptool 1.4, this field allows you to link a table to the token. If the token is given a facing, then the facing value will be used to select an image from the table which will replace the normal image of the token. This is frequently combined with the "Figure" token shape on isometric maps to simulate a 3D effect.<br />
<br />
====Snap to Grid====<br />
<br />
This checkbox simply indicates that the token snaps to the existing grid when it is moved. If unchecked, the token does not pay any heed to the grid when it is dragged around on the map.<br />
<br />
====Visible to Players====<br />
<br />
This checkbox lets you designate a particular token as invisible to players - when checked, no player connected to the game will be able to see the token or interact with it in any way.<br />
<br />
====Terrain Modifier====<br />
<br />
Drop down selection of Terrain Modifier Type and numeric field to enter Terrain Modifier Value. Note that tokens or objects must not be set to Free Size for the terrain modifier to apply to all grid cells it covers. <br />
<br />
* '''NONE''' - No modifier is applied to movement into the grid cells covered by the associated token, object or stamp.<br />
* '''MULTIPLY''' - Movement cost into the cell is multiplied by the value field. Values less than 1.0 enhance movement. Think escalator, moving walkway or a highway.<br />
* '''ADD''' - Adds the value to the movement cost of entering a cell.<br />
* '''BLOCK''' - Blocks movement entirely. See ''Ignore Terrain'' setting below.<br />
<br />
====Token Opacity====<br />
<br />
Set the opacity, i.e. transparency, of a token from 0 to 100% opaque (default).<br />
<br />
====Ignore Terrain====<br />
<br />
Tokens can be set to ignore zero or more Terrain Modifier Types (Ctrl-Click for multi-select).<br />
<br />
====Layout, Portrait, and Handout====<br />
<br />
There are three fields dealing with the token's visual appearance:<br />
<br />
* '''Layout''': this shows how the token will look on the map<br />
* '''Portrait''': this is a separate image that will appear in the lower left corner of the map screen when you hover over the token<br />
* '''Handout''': this lets you designate an image to appear when you right-click on the token and select '''Show Handout'''<br />
<br />
[[Category:MapTool]][[Category:Tutorial]][[Category:Feature Guide]]<br />
{{Languages|Introduction to Tokens}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=tokenTool&diff=8979tokenTool2020-09-14T21:40:57Z<p>Lwoestman: </p>
<hr />
<div>[[Category:TokenTool]]<br />
[[Image:TokenToolUIwithBackground.png|400px|right|Interface showing background image and portrait image.]] <br />
TokenTool is a image creation tool for producing ''tokens'' for use in Virtual TableTop(VTT) applications such as MapTool, Roll20, Fantasy Grounds and others. To get started making tokens right away, visit the [[TokenTool Quickstart]].<br />
<br />
== Features ==<br />
* Make tokens from multiple image types (PNG, JPG, BMP, GIF, ...)<br />
* Saves tokens in standard PNG format with transparency<br />
* Load images directly from PDF files<br />
* Screen capture to grab images for your tokens<br />
* Drag'n'drop to the TokenTool window from your computer desktop or browser<br />
* Save portrait option to save both your token and a portrait image<br />
* 150+ token overlays/bases included in Hex, Round and Square styles<br />
* Add your own token overlays in PNG or Photoshop .psd formats<br />
* Choose background color or add a separate background image for portrait images that are partially transparent<br />
* Add bases to top-down token images.<br />
<br />
== Interface ==<br />
[[Image:TokenToolInterface.png|thumb|right|A summary of the TokenTool interface. Click to expand.]]<br />
Token Tool has a visual interface that uses drag n' drop functionality to help you rapidly create tokens.<br />
<br />
=== Menus ===<br />
<br />
; File<br />
: Open PDF - This will browse a PDF document and let you select extracted images throughout.<br />
: Manage Overlays - Add and Remove overlays. Learn about [[Creating TokenTool Overlays]].<br />
: Save As - Save your token as a PNG with transparency (if applicable).<br />
: Exit - TokenTool will save your current image and settings for next launch.<br />
; Edit <br />
: Capture Screen - Select a portion of your screen to bring into TokenTool as the selected layer.<br />
: Copy Image - Copies the current token image to the clipboard.<br />
: Paste Image - Pastes the clipboard image into the selected layer. <br />
; Help<br />
: Reset Settings<br />
: About TokenTool<br />
<br />
=== Canvas Panel ===<br />
The Canvas panel is where you can drop images into the portrait and background layers and pan and zoom images to design your token.<br />
* Drag and drop an image into the '''center''' of the screen to replace the Portrait image<br />
* Drag and drop an image into the '''edge''' of the screen to replace the Background image<br />
* Click and drag the mouse to pan the image on the selected layer.<br />
* Scroll the mouse up/down to zoom the image on the selected layer in/out.<br />
* Choose which image (Portrait or Background) you are panning/zooming with the layer selector in the top right of the canvas area.<br />
<br />
=== Token Preview ===<br />
This is what your final token will look like with the current settings. <br />
* You can drag and drop directly from the preview directly into MapTool, your system's file browser, or any other program that supports it.<br />
* Use the 'Save Options' accordion panel to select filename and portrait export options when dragging from the Token Preview.<br />
<br />
=== Options Panels ===<br />
Select different accordion panels to configure your token settings.<br />
* '''Save Options''': Here you can configure the filename the token will have when it is dragged from the Token Preview. You can also configure an option 'Portrait' to export with the token, which is the Portrait image without the overlay or clipping. Optionally, portraits can have the Background layer show through any transparent parts of the Portrait image in exported portraits.<br />
* '''Background Options''': This panel lets you set or clear the background image and background color.<br />
* '''Portrait Options''': This panel lets you set or clear the portrait image. It also lets you affect the opacity of the portrait, blur it, or increase 'glow' to affect its colors and brightness.<br />
* '''Overlay Options''': This panel lets you browse your collection of overlays. The available overlays can be changed in {{ui location|File > Manage Overlays}} (learn about [[Creating TokenTool Overlays]]). Additionally you can set whether the overlay sits over the Portrait or above it, the overlay size, and whether the overlay confines the canvas or not.<br />
<br />
=== See Also ===<br />
* [[TokenTool Quickstart]]<br />
* [[Creating TokenTool Overlays]]<br />
* [[Introduction to Tokens]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=TokenTool_Quickstart&diff=8978TokenTool Quickstart2020-09-14T21:35:41Z<p>Lwoestman: </p>
<hr />
<div>[[Category:TokenTool]][[Category:Tutorial]]<br />
{{Beginner}}<br />
This is the Quick Start Guide to using TokenTool v2.1, the premiere token creation tool for Virtual TableTop programs.<br />
<br />
You can get TokenTool 2.1 at [https://www.rptools.net/toolbox/token-tool/ RPTools.net] or on the official TokenTool repository on [https://github.com/RPTools/TokenTool/releases GitHub].<br />
<br />
== User Interface ==<br />
;Canvas Panel<br />
:In the Canvas panel of the UI you position and size your desired image in relation to the Token Ring or Overlay with your mouse. Left-click and drag to position. Use the mouse-wheel to size the image.<br />
;Token Preview<br />
:In the upper right you can see what the resulting token image will look like when you save it.<br />
;Overlay Selection<br />
:In the lower right you can choose your Token Overlay from the list of different types and styles. The pixel dimensions of the selected Overlay are displayed below the name.<br />
;Token Size<br />
:The image size of the resulting token is shown in the bottom right. You should set the token size to be the same or smaller than that of the selected Overlay.<br />
<br />
[[File:TokenToolGUIBasic.png|400px|TokenTool GUI]]<br />
<br />
If you want to follow along with the next steps, go ahead and click on Overlay Option then locate a token overlay that you want to use. Once you select it, the overlay will appear on the Canvas.<br />
<br />
== Creating a Token ==<br />
Say I need to create a token for an Orc warrior princess. In my web browser I go to [https://images.google.com Google Image Search] and enter ''orc warrior princess'' as my search terms. I like the 3rd one that comes up by [https://oksanadiada.artstation.com/projects/vda2O Oksana Diada]. I click on the entry in the search list and then right-click on the image to ''Copy Image''. Back in TokenTool, I hit Ctrl-V (or use the Edit menu) to paste my orc princess into the Canvas. You can also drag-n-drop an image from your computer onto the Canvas area.<br />
<br />
The image I have chosen is quite large but that's okay. Using the mouse-wheel I can quickly resize it to fit within the token overlay I've chosen. I get something like this:<br />
<br />
[[File:TokenToolOrcPrincessExample.png|400px|Orc Princess Token Example]]<br />
<br />
== Saving a Token ==<br />
With my token complete, I need only left-click on the Token Preview to drag the token image from the Token Preview area to my computer or directly into MapTool. I can also save it from the File menu to my computer.<br />
<br />
[[File:ExampleToken.png|256px|Example Token]]<br />
<br />
My Orc Warrior Princess is ready!<br />
<br />
== Further Reading ==<br />
This QuickStart Guide only touched upon the basics of using TokenTool. <br />
<br />
* The [[TokenTool]] page has general information about the user interface<br />
* Read the [[Creating TokenTool Overlays]] article to start making your own custom overlays<br />
* Experiment with the various options on your own to get a feel for what else it can do!<br />
<br />
==See Also==<br />
* [[TokenTool]]<br />
* [[Token|MapTool Tokens]]<br />
* [[Token Types]]<br />
* [[Library_Token|Library Token]]<br />
* [[Image_Token|Image Token]]<br />
* [[Introduction_to_Tokens|Introduction to Tokens]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Token&diff=8977Token2020-09-14T21:28:10Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Token}}<br />
''This article is about the token file format used in MapTool. For more general information about tokens, read the [[Introduction to Tokens]].''<br />
<br />
=Token: token=<br />
<br />
Every object that can be dropped down on a map and manipulated by the GM or the players is a ''token'' of some type. The possible token types are [[Image Token]], [[Library Token]], [[PC Token]], and [[NPC Token]]. In addition, when images are dropped onto a [[map layer]] other than the '''Token''' layer, they take on the name ''object'' or ''stamp'' instead. (The term ''stamp'' is often used to denote an image that is placed repeatedly, sometimes in a pattern, whereas ''object'' means a less often used image. A forest would be full of '''tree stamps''' but an office building would have ''table and chair objects''.)<br />
<br />
This page discusses how tokens and objects are saved externally; the overall file format as well as some specifics about how to manipulate the contents of the '''.rptok''' file.<br />
<br />
==Overall File Format==<br />
<br />
Tokens can be saved by the token owner by right-clicking on the token and choosing '''Save As...''', then navigating to a directory and entering a filename. The filename will automatically have '''.rptok''' appended to the end to indicate that the file contains token contents. The actual format of the file, however, is an ordinary ZIP file! This means you can rename the file to end with '''.zip''' and treat it as any other ZIP file. There are a number of features related to this:<br />
<br />
* All tokens are automatically stored in a compressed format.<br />
* All tokens can contain multiple data files inside<br />
** One file is called '''content.xml'''<br />
** Another file is called '''properties.xml'''<br />
** A directory is also included called '''assets'''<br />
*** The token image is stored here,<br />
*** The token portrait is stored here, and<br />
*** The token handout is stored here.<br />
** The last file is called '''thumbnail'''<br />
<br />
==Examining the Contents of a Token File==<br />
<br />
Because the token files are ZIP files, you can easily extract the images or other data from the token. To do so, unpack the ZIP file into a directory on your computer. Look inside the '''assets''' directory and you'll see multiple filenames. They will appear to be random strings of letters and numbers, but actually the are checksums of the image they contain. You can think of a checksum as a ''summary'' of the content. These files don't have filename extensions so you may not be able to view the content unless you use a program that ignores the filename extension and looks at the content instead. One example utility that does that is the GNU Image Manipulation Program, or GIMP for short.<br />
<br />
Note that some versions of MapTool (which ones?) store the asset as the image data encoded in XML. This makes the image unviewable using _any_ standard graphics tool. Trevor has said that this is a bug and future versions will use the actual graphics image format (JPG or PNG).<br />
<br />
==Modifying the Images or Other Data Inside a Token File==<br />
<br />
Modifying the images used in the token is more complex, however. Here are the required pieces of the puzzle:<br />
<br />
# Locate the new image(s) to be stored in the token,<br />
# Calculate the checksum of the image (it's an MD5 checksum),<br />
# Rename the image file to be the checksum, removing any filename extension in the process,<br />
# Move the new file into the '''assets''' directory,<br />
# Record the name of the old image from the '''assets''' directory, and<br />
# Remove the old image from the '''assets''' directory.<br />
<br />
Sounds easy, right? But that's only half of it. It turns out that just dumping images into the '''assets''' directory wouldn't tell MapTool enough about the image, such as what size to scale it to and whether it represented the portrait or handout image. Those details are stored in the '''content.xml''' file. This file is '''NOT''' in the '''assets''' directory, but is at the top level of the unpacked ZIP file.<br />
<br />
If you open the '''content.xml''' file use a text editor. Do not use a word processor or saving the file could corrupt the contents with extra information created by the word processor. Use a program such as Notepad or TextPad to perform any editing. Obviously, an editor that understands the XML syntax can make editing much easier.<br />
<br />
You need to locate the portion of the XML file that refers to the portrait image (if you were planning to replace the portrait) and replace the 16-character checksum from the old asset with the 16-character checksum of the new asset. Fortunately, you recorded that information as you performed the steps given above! But fear not -- if you did not record the old checksum value, you can simply delete the entire top-level directory and unpack the ZIP archive again, starting from the beginning.<br />
<br />
The simplest way to make the change is to perform a string search for the old checksum, replacing it with the new one whenever you find it.<br />
<br />
After you've made all of your replacements, use a ZIP utility to create a ZIP file containing the contents of the top-level directory and everything below it in the directory structure (which currently means the '''assets''' directory). Be sure that the directory structure is preserved because the '''assets''' directory must be there. Now the file can be dragged and dropped into MapTool! You can change the filename extension to '''.rptok''' if you like, but MapTool isn't particular about the name of the file, only about the contents.<br />
<br />
==See Also==<br />
* [[Token Types]]<br />
* [[Library_Token|Library Token]]<br />
* [[Image_Token|Image Token]]<br />
* [[TokenTool QuickStart|TokenTool QuickStart Guide]]<br />
* [[Introduction_to_Tokens|Introduction to Tokens]]<br />
<br />
<br />
[[Category:Token]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macro_Tips_and_Tricks&diff=8976Macro Tips and Tricks2020-09-14T17:40:43Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Macro Tips and Tricks}}<br />
[[Category:MapTool]][[Category:Tutorial]]{{Beginner}}<br />
====<br />
<br />
<blockquote><br />
<source lang="mtmacro" line><br />
[h:existingString = "The skill name you entered is "]<br />
[h:concatString = existingString+skill+"."]<br />
[r:concatString]<br />
</source><br />
</blockquote><br />
<br />
{{Languages|Macro Tips and Tricks}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macro_Tips_and_Tricks&diff=8975Macro Tips and Tricks2020-09-14T17:39:49Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Macro Tips and Tricks}}<br />
[[Category:MapTool]][[Category:Tutorial]]{{Beginner}}<br />
====<br />
<br />
<blockquote><br />
<source lang="mtmacro" line><br />
[h:existingString = "The skill name you entered is "]<br />
[h:concatString = existingString+skill+"."]<br />
[r:concatString]<br />
</source><br />
</blockquote><br />
<br />
{{Languages|Marcro Tips and Tricks}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macro_Tips_and_Tricks&diff=8974Macro Tips and Tricks2020-09-14T17:39:10Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Marcro Tips and Tricks}}<br />
[[Category:MapTool]][[Category:Tutorial]]{{Beginner}}<br />
====<br />
<br />
<blockquote><br />
<source lang="mtmacro" line><br />
[h:existingString = "The skill name you entered is "]<br />
[h:concatString = existingString+skill+"."]<br />
[r:concatString]<br />
</source><br />
</blockquote><br />
<br />
{{Languages|Marcro Tips and Tricks}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Label_Method)&diff=8973Updating Macro Buttons Using a Macro (Label Method)2020-09-14T17:37:23Z<p>Lwoestman: </p>
<hr />
<div>==Updating the Label of our macro buttons using DnD4e as an Example.==<br />
<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems. <br />
<br />
Let's assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the macro button to blue if the power has been used. If you want another way to do this without using different groups see Tracking Used DnD 4e Powers (Macro Prefix Method)<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting label of buttons in the "Encounter Powers" group===<br />
So first we create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume that you create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
This macro will get the labels of all the macros with [[Macros:Functions:getMacros|getMacros()]]. It will then loop through all of these labels and get the index for each [[Macro_Button|macro button]] with that label. Then it will check to see if the macro label ends with the text "(Used)" if it does and it is in the "Encounter Powers" group it will use the [[Macros:Functions:replace|replace()]] function to replace the " (Used)" with nothing ("") there by removing it from the label.<br />
<br />
You can test this by creating a macro on your [[Token|token]] called "Something or other (Used)" with a group of "Encounter Powers", impersonating the token and clicking on the "Short Rest" [[Macro_Button|macro button]]. <br />
<br />
<br />
[[image:ButtonSomethingOrOtherUsed.png]] [[image:ButtonSomethingOrOtherNotUsed.png]]<br />
<br />
===Extended Rest, resetting label of buttons in the "Encounter Powers" and "Daily Powers"group===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter:" or "Daily:". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group.<br />
For "Short Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
</source><br />
<br />
Where for "Extended Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
</source><br />
<br />
The pattern (Daily|Encounter) Powers matches both the "Daily Powers" and "Encounter Powers" strings. Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the label you would change the lines to <br />
<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Round Powers")]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter) Powers")]<br />
</source><br />
<br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter|Daily) Powers")]<br />
</source><br />
<br />
===Marking Powers as Used===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "Burning Hands (Used)"]<br />
</source><br />
Replacing both occurrences of "Burning Hands" with the label of your [[Macro_Button|macro button]]. So lets try it, on your [[Token|token]] create a [[Macro_Button|macro button]] called "Sleep<br />
" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "label=Sleep (Used)")] <br />
</source><br />
Click on the button and hopefully you should see it change.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example) <br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro buttons]] with the specified name and if it finds one and it is in the "Daily Powers" group it will append " (Used)" to it. If you have more than one button it will append " (Used)" to each one as you push one of the buttons.<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h, macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
<br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will change to "Lay On Hands (Used)".<br />
<br />
Fine you say but I would like to stop players using powers that are used (or in the case of multi use powers where there are no non-used ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]]. Change it to the following <br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isEnc = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange3.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Prefix_Method)&diff=8972Updating Macro Buttons Using a Macro (Prefix Method)2020-09-14T17:36:52Z<p>Lwoestman: </p>
<hr />
<div>==Updating color of our macro buttons using DnD4e as an example==<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems.<br />
<br />
For the first set up let's assume that we have prefixed our powers with "Daily:" for daily powers and "Encounter:" for encounter powers, and we want to set the color of the [[Macro_Button|macro button]] to blue if the power has been used. If you want another way to do this without having to place "Daily:" or "Encounter:" in front of your power see [[Tutorials:Macros:UpdatingMacroButtons:DnD4ePowersGroup | Tracking Used DnD 4e Powers (Macro Group Method)]]<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting color of buttons starting with "Encounter:"===<br />
So first we will create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume you just create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "Encounter:.*"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
The way the above macro works is by getting a list of the macros [[Macros:Functions:getMacros|getMacros()]] which will return all the labels of the [[Macro_Button|macro buttons]] on the [[Current Token]]. Since a [[Token|token]] can contain multiple [[Macro_Button|macro buttons]] with the same label the function [[Macros:Functions:getMacroIndexes|getMacroIndexes()]] is used to return the unique index of each [[Macro_Button|macro button]] for each of the labels. Then we use [[Macros:Functions:getMacroProps|getMacroProps()]] to get the properties of the [[Macro_Button|macro button]] in a [[Macros:string property list|string property list]]. The color of the [[Macro_Button|macro button]] is extracted from this using [[Macros:Functions:getStrProp|getStrProp()]] and we check to see if it is "blue", if it is we also check to see if the label of the button starts with "Encounter:" and set the value of isBlue based on this. Then if isBlue is true (non zero) we use [[Macros:Functions:setMacroProps|setMacroProps()]] to change the color back to the default. <br />
<br />
You can test this macro by dragging a [[Token|token]] onto the map and adding a [[Macro_Button|macro button]] to it called "Encounter:Something or other" and set it to blue in the creation dialog.<br />
<br />
[[image:ButtonSomethingOrOtherBlue.png]] [[image:ButtonSomethingOrOtherDefault.png]]<br />
<br />
===Extended Rest, resetting color of buttons starting with "Encounter:" or "Daily:"===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter:" or "Daily:". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "(Daily|Encounter):.*"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the prefix of the [[Macro_Button|macro button]]. In the "Short Rest" [[Macro_Button|macro button]] we had <br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "Encounter:.*"), 1, 0)]<br />
</source><br />
Where in the "Extended Rest" [[Macro_Button|macro button]] it is<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "(Daily|Encounter):.*"), 1, 0)]<br />
</source><br />
The pattern ''(Daily|Encounter):.*'' matches a string that starts with either "Daily:" or "Encounter:". <br />
Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and you prefix them with "Round:", for your "New Round" macro which resets the color you would change the lines to<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "Round:.*"), 1, 0)]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "(Round|Encounter):.*"), 1, 0)]<br />
</source><br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(macro, "(Round|Encounter|Daily):.*"), 1, 0)]<br />
</source><br />
<br />
===Using Powers, or getting the blues...===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Encouner:Burning Hands", "color=blue")]<br />
</source><br />
Replacing the "Encounter:Burning Hands" with the label of your [[Macro_Button|macro button]].<br />
So lets try it, on your token create a [[Macro_Button|macro button]] called "Daily:Sleep" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Daily:Sleep", "color=blue")]<br />
</source> <br />
Click on the button and hopefully you should see it change to blue.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example)<br />
<br />
Drag a new [[Token:token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UsePower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[color = getStrProp(getMacroProps(button), "color")]<br />
[if(color=="default"): setMacroProps(button, "color=blue")]<br />
[if(color=="default"): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro button]]s with the specified name searching for one that is the default color, once it finds one it sets its color to blue and sets found=1 so no other buttons are changed (as of 1.3b48 there is no way to break out of a loop).<br />
<br />
Now create a [[Macro_Button|macro button]] called "Daily:Lay On Hands" and copy the following in<br />
<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
</source><br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Daily:Lay On Hands" buttons will turn blue.<br />
<br />
Fine you say but I would like to stop players using powers that are blue (or in the case of multi use powers where there are no non blue ones remaining).<br />
<br />
We can do that by changing the "UsePower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]].<br />
Change it to the following<br />
<br />
===Sorry Sir/Madam, you have already used that!===<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[color = getStrProp(getMacroProps(button), "color")]<br />
[if(color=="default"): setMacroProps(button, "color=blue")]<br />
[if(color=="default"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
And change the [[Token:token]]'s "Daily:Lay On Hands" macro code (don't forget to change all the duplicates too)<br />
<source lang="mtmacro" line><br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
Oooh tingly!<br />
</source><br />
<br />
Then clickity, clickity, click on the "Daily:Lay On Hands" buttons and when you have none left you should get the following dialog<br />
<br />
[[image:PowerUsedDialog.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange1.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Label_Method)&diff=8971Updating Macro Buttons Using a Macro (Label Method)2020-09-14T17:31:35Z<p>Lwoestman: </p>
<hr />
<div>==Updating the Label of our macro buttons using DnD4e as an Example.==<br />
<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems. <br />
<br />
Let's assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the macro button to blue if the power has been used. If you want another way to do this without using different groups see Tracking Used DnD 4e Powers (Macro Prefix Method)<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting label of buttons in the "Encounter Powers" group===<br />
So first we create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume that you create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
This macro will get the labels of all the macros with [[Macros:Functions:getMacros|getMacros()]]. It will then loop through all of these labels and get the index for each [[Macro_Button|macro button]] with that label. Then it will check to see if the macro label ends with the text "(Used)" if it does and it is in the "Encounter Powers" group it will use the [[Macros:Functions:replace|replace()]] function to replace the " (Used)" with nothing ("") there by removing it from the label.<br />
<br />
You can test this by creating a macro on your [[Token|token]] called "Something or other (Used)" with a group of "Encounter Powers", impersonating the token and clicking on the "Short Rest" [[Macro_Button|macro button]]. <br />
<br />
<br />
[[image:ButtonSomethingOrOtherUsed.png]] [[image:ButtonSomethingOrOtherNotUsed.png]]<br />
<br />
===Extended Rest, resetting label of buttons in the "Encounter Powers" and "Daily Powers"group===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter:" or "Daily:". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group.<br />
For "Short Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
</source><br />
<br />
Where as for "Extended Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
</source><br />
<br />
The pattern (Daily|Encounter) Powers matches both the "Daily Powers" and "Encounter Powers" strings. Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the label you would change the lines to <br />
<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Round Powers")]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter) Powers")]<br />
</source><br />
<br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter|Daily) Powers")]<br />
</source><br />
<br />
===Marking Powers as Used===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "Burning Hands (Used)"]<br />
</source><br />
Replacing both occurrences of "Burning Hands" with the label of your [[Macro_Button|macro button]]. So lets try it, on your [[Token|token]] create a [[Macro_Button|macro button]] called "Sleep<br />
" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "label=Sleep (Used)")] <br />
</source><br />
Click on the button and hopefully you should see it change.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example) <br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro buttons]] with the specified name and if it finds one and it is in the "Daily Powers" group it will append " (Used)" to it. If you have more than one button it will append " (Used)" to each one as you push one of the buttons.<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h, macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
<br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will change to "Lay On Hands (Used)".<br />
<br />
Fine you say but I would like to stop players using powers that are used (or in the case of multi use powers where there are no non-used ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]]. Change it to the following <br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isEnc = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange3.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Group_Method)&diff=8970Updating Macro Buttons Using a Macro (Group Method)2020-09-14T17:31:07Z<p>Lwoestman: </p>
<hr />
<div>==Updating color of our macro buttons using DnD4e as an example==<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems.<br />
<br />
Let's assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the [[Macro_Button|macro button]] to blue if the power has been used. If you want another way to do this without using different groups see [[Tutorials:Macros:UpdatingMacroButtons:DnD4ePowersPrefix | Tracking Used DnD 4e Powers (Macro Prefix Method)]]<br />
<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting color of buttons in the "Encounter Powers" group===<br />
So first we will create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume you just create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
The way the above macro works is by getting a list of the macros [[Macros:Functions:getMacros|getMacros()]] which will return all the labels of the [[Macro_Button|macro buttons]] on the [[Current Token]]. Since a [[Token|token]] can contain multiple [[Macro_Button|macro buttons]] with the same label the function [[Macros:Functions:getMacroIndexes|getMacroIndexes()]] is used to return the unique index of each [[Macro_Button|macro button]] for each of the labels. Then we use [[Macros:Functions:getMacroProps|getMacroProps()]] to get the properties of the [[Macro_Button|macro button]] in a [[Macros:string property list|string property list]]. The color of the [[Macro_Button|macro button]] is extracted from this using [[Macros:Functions:getStrProp|getStrProp()]] and we check to see if it is "blue", if it is we also check to see if it is in the "Encounter Powers" group, and set the value of isBlue based on this. Then if isBlue is true (non zero) we use [[Macros:Functions:setMacroProps|setMacroProps()]] to change the color back to the default. <br />
<br />
You can test this macro by dragging a [[Token|token]] onto the map and adding a [[Macro_Button|macro button]] to it called "Something or other" in the "Encounter Powers" group and set it to blue in the creation dialog.<br />
<br />
[[image:ButtonSomethingOrOtherBlueGroup.png]] [[image:ButtonSomethingOrOtherDefaultGroup.png]]<br />
<br />
===Extended Rest, resetting color of buttons starting with "Encounter Powers" or "Daily Powers"===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter Powers" or "Daily Powers". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group of the [[Macro_Button|macro button]]. In the "Short Rest" [[Macro_Button|macro button]] we had <br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
</source><br />
Where in the "Extended Rest" [[Macro_Button|macro button]] it is<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
</source><br />
The pattern ''(Daily|Encounter) Powers'' matches both the "Daily Powers" and "Encounter Powers" strings.<br />
Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the color you would change the lines to<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Round Powers", 1, 0)]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter) Powers"), 1, 0)]<br />
</source><br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter|Daily) Powers"), 1, 0)]<br />
</source><br />
<br />
===Using Powers, or getting the blues...===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "color=blue")]<br />
</source><br />
Replacing the "Burning Hands" with the label of your [[Macro_Button|macro button]].<br />
So lets try it, on your token create a [[Macro_Button|macro button]] called "Sleep" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "color=blue")]<br />
</source> <br />
Click on the button and hopefully you should see it change to blue.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example).<br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro button]]s with the specified name searching for one that is the default color and a daily power, once it finds one it sets its color to blue and sets found=1 so no other buttons are changed (as of 1.3b48 there is no way to break out of a loop).<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in<br />
<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h,macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will turn blue.<br />
<br />
Fine you say but I would like to stop players using powers that are blue (or in the case of multi use powers where there are no non blue ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]].<br />
Change it to the following<br />
<br />
===Sorry Sir/Madam, you have already used that!===<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
And change the [[Token|token]]'s "Lay On Hands" macro code (don't forget to change all the duplicates too)<br />
<source lang="mtmacro" line><br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
Oooh tingly!<br />
</source><br />
<br />
Then clickity, clickity, click on the "Daily:Lay On Hands" buttons and when you have none left you should get the following dialog<br />
<br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Encounter Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Encounter Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange2.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Group_Method)&diff=8969Updating Macro Buttons Using a Macro (Group Method)2020-09-14T17:20:50Z<p>Lwoestman: </p>
<hr />
<div>==Updating color of our macro buttons using DnD4e as an example==<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems.<br />
<br />
Lets assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the [[Macro_Button|macro button]] to blue if the power has been used. If you want another way to do this without using different groups see [[Tutorials:Macros:UpdatingMacroButtons:DnD4ePowersPrefix | Tracking Used DnD 4e Powers (Macro Prefix Method)]]<br />
<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting color of buttons in the "Encounter Powers" group===<br />
So first we will create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume you just create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
The way the above macro works is by getting a list of the macros [[Macros:Functions:getMacros|getMacros()]] which will return all the labels of the [[Macro_Button|macro buttons]] on the [[Current Token]]. Since a [[Token|token]] can contain multiple [[Macro_Button|macro buttons]] with the same label the function [[Macros:Functions:getMacroIndexes|getMacroIndexes()]] is used to return the unique index of each [[Macro_Button|macro button]] for each of the labels. Then we use [[Macros:Functions:getMacroProps|getMacroProps()]] to get the properties of the [[Macro_Button|macro button]] in a [[Macros:string property list|string property list]]. The color of the [[Macro_Button|macro button]] is extracted from this using [[Macros:Functions:getStrProp|getStrProp()]] and we check to see if it is "blue", if it is we also check to see if it is in the "Encounter Powers" group, and set the value of isBlue based on this. Then if isBlue is true (non zero) we use [[Macros:Functions:setMacroProps|setMacroProps()]] to change the color back to the default. <br />
<br />
You can test this macro by dragging a [[Token|token]] onto the map and adding a [[Macro_Button|macro button]] to it called "Something or other" in the "Encounter Powers" group and set it to blue in the creation dialog.<br />
<br />
[[image:ButtonSomethingOrOtherBlueGroup.png]] [[image:ButtonSomethingOrOtherDefaultGroup.png]]<br />
<br />
===Extended Rest, resetting color of buttons starting with "Encounter Powers" or "Daily Powers"===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter Powers" or "Daily Powers". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group of the [[Macro_Button|macro button]]. In the "Short Rest" [[Macro_Button|macro button]] we had <br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
</source><br />
Where in the "Extended Rest" [[Macro_Button|macro button]] it is<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
</source><br />
The pattern ''(Daily|Encounter) Powers'' matches both the "Daily Powers" and "Encounter Powers" strings.<br />
Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the color you would change the lines to<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Round Powers", 1, 0)]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter) Powers"), 1, 0)]<br />
</source><br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter|Daily) Powers"), 1, 0)]<br />
</source><br />
<br />
===Using Powers, or getting the blues...===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "color=blue")]<br />
</source><br />
Replacing the "Burning Hands" with the label of your [[Macro_Button|macro button]].<br />
So lets try it, on your token create a [[Macro_Button|macro button]] called "Sleep" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "color=blue")]<br />
</source> <br />
Click on the button and hopefully you should see it change to blue.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example).<br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro button]]s with the specified name searching for one that is the default color and a daily power, once it finds one it sets its color to blue and sets found=1 so no other buttons are changed (as of 1.3b48 there is no way to break out of a loop).<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in<br />
<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h,macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will turn blue.<br />
<br />
Fine you say but I would like to stop players using powers that are blue (or in the case of multi use powers where there are no non blue ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]].<br />
Change it to the following<br />
<br />
===Sorry Sir/Madam, you have already used that!===<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
And change the [[Token|token]]'s "Lay On Hands" macro code (don't forget to change all the duplicates too)<br />
<source lang="mtmacro" line><br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
Oooh tingly!<br />
</source><br />
<br />
Then clickity, clickity, click on the "Daily:Lay On Hands" buttons and when you have none left you should get the following dialog<br />
<br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Encounter Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Encounter Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange2.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Label_Method)&diff=8968Updating Macro Buttons Using a Macro (Label Method)2020-09-14T17:16:52Z<p>Lwoestman: </p>
<hr />
<div>==Updating the Label of our macro buttons using DnD4e as an Example.==<br />
<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems. <br />
<br />
Lets assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the macro button to blue if the power has been used. If you want another way to do this without using different groups see Tracking Used DnD 4e Powers (Macro Prefix Method)<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting label of buttons in the "Encounter Powers" group===<br />
So first we create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume that you create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
This macro will get the labels of all the macros with [[Macros:Functions:getMacros|getMacros()]]. It will then loop through all of these labels and get the index for each [[Macro_Button|macro button]] with that label. Then it will check to see if the macro label ends with the text "(Used)" if it does and it is in the "Encounter Powers" group it will use the [[Macros:Functions:replace|replace()]] function to replace the " (Used)" with nothing ("") there by removing it from the label.<br />
<br />
You can test this by creating a macro on your [[Token|token]] called "Something or other (Used)" with a group of "Encounter Powers", impersonating the token and clicking on the "Short Rest" [[Macro_Button|macro button]]. <br />
<br />
<br />
[[image:ButtonSomethingOrOtherUsed.png]] [[image:ButtonSomethingOrOtherNotUsed.png]]<br />
<br />
===Extended Rest, resetting label of buttons in the "Encounter Powers" and "Daily Powers"group===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter:" or "Daily:". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[foreach(macro,getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[foreach(index, getMacroIndexes(macro)), code: {<br />
[h:props = getMacroProps(index)]<br />
[label = getStrProp(props, "label")]<br />
[isUsed = matches(label, ".* \\(Used\\)")]<br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
[if(isUsed && isEnc): setMacroProps(index, "label="+<br />
replace(label, " \\(Used\\)", ""))]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress the macros output --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group.<br />
For "Short Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Encounter Powers")]<br />
</source><br />
<br />
Where as for "Extended Rest" it is<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Encounter|Daily) Powers")]<br />
</source><br />
<br />
The pattern (Daily|Encounter) Powers matches both the "Daily Powers" and "Encounter Powers" strings. Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the label you would change the lines to <br />
<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "Round Powers")]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter) Powers")]<br />
</source><br />
<br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers<br />
<source lang="mtmacro" line start=14><br />
[isEnc = matches(getStrProp(props, "group"), "(Round|Encounter|Daily) Powers")]<br />
</source><br />
<br />
===Marking Powers as Used===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros<br />
<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "Burning Hands (Used)"]<br />
</source><br />
Replacing both occurrences of "Burning Hands" with the label of your [[Macro_Button|macro button]]. So lets try it, on your [[Token|token]] create a [[Macro_Button|macro button]] called "Sleep<br />
" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "label=Sleep (Used)")] <br />
</source><br />
Click on the button and hopefully you should see it change.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example) <br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code<br />
<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro buttons]] with the specified name and if it finds one and it is in the "Daily Powers" group it will append " (Used)" to it. If you have more than one button it will append " (Used)" to each one as you push one of the buttons.<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h, macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
<br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will change to "Lay On Hands (Used)".<br />
<br />
Fine you say but I would like to stop players using powers that are used (or in the case of multi use powers where there are no non-used ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]]. Change it to the following <br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isDay = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isDay == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isDay == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers<br />
<source lang="mtmacro" line><br />
[found = 0]<br />
[indexes = getMacroIndexes(macro.args)]<br />
[foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[label = getStrProp(props, "label")]<br />
[isPower = matches(label, macro.args)]<br />
[isEnc = matches(getStrProp(props, "group"), <br />
"Daily Powers")]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): <br />
setMacroProps(button, "label=" + label + " (Used)")<br />
]<br />
[if(isPower == 1 && isEnc == 1 && found == 0): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange3.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Group_Method)&diff=8967Updating Macro Buttons Using a Macro (Group Method)2020-09-14T17:07:54Z<p>Lwoestman: </p>
<hr />
<div>==Updating color of our macro buttons using DnD4e as an example==<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this example is for DnD4e the technique is applicable for many other systems.<br />
<br />
Lets assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the [[Macro_Button|macro button]] to blue if the power has been used. If you want another way to do this without using different groups see [[Tutorials:Macros:UpdatingMacroButtons:DnD4ePowersPrefix | Tracking Used DnD 4e Powers (Macro Prefix Method)]]<br />
<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting color of buttons in the "Encounter Powers" group===<br />
So first we will create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume you just create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it.<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
The way the above macro works is by getting a list of the macros [[Macros:Functions:getMacros|getMacros()]] which will return all the labels of the [[Macro_Button|macro buttons]] on the [[Current Token]]. Since a [[Token|token]] can contain multiple [[Macro_Button|macro buttons]] with the same label the function [[Macros:Functions:getMacroIndexes|getMacroIndexes()]] is used to return the unique index of each [[Macro_Button|macro button]] for each of the labels. Then we use [[Macros:Functions:getMacroProps|getMacroProps()]] to get the properties of the [[Macro_Button|macro button]] in a [[Macros:string property list|string property list]]. The color of the [[Macro_Button|macro button]] is extracted from this using [[Macros:Functions:getStrProp|getStrProp()]] and we check to see if it is "blue", if it is we also check to see if it is in the "Encounter Powers" group, and set the value of isBlue based on this. Then if isBlue is true (non zero) we use [[Macros:Functions:setMacroProps|setMacroProps()]] to change the color back to the default. <br />
<br />
You can test this macro by dragging a [[Token|token]] onto the map and adding a [[Macro_Button|macro button]] to it called "Something or other" in the "Encounter Powers" group and set it to blue in the creation dialog.<br />
<br />
[[image:ButtonSomethingOrOtherBlueGroup.png]] [[image:ButtonSomethingOrOtherDefaultGroup.png]]<br />
<br />
===Extended Rest, resetting color of buttons starting with "Encounter Powers" or "Daily Powers"===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter Powers" or "Daily Powers". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it.<br />
<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group of the [[Macro_Button|macro button]]. In the "Short Rest" [[Macro_Button|macro button]] we had <br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
</source><br />
Where in the "Extended Rest" [[Macro_Button|macro button]] it is<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
</source><br />
The pattern ''(Daily|Encounter) Powers'' matches both the "Daily Powers" and "Encounter Powers" strings.<br />
Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the color you would change the lines to<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Round Powers", 1, 0)]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers.<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter) Powers"), 1, 0)]<br />
</source><br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers.<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter|Daily) Powers"), 1, 0)]<br />
</source><br />
<br />
===Using Powers, or getting the blues...===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros.<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "color=blue")]<br />
</source><br />
Replacing the "Burning Hands" with the label of your [[Macro_Button|macro button]].<br />
So lets try it, on your token create a [[Macro_Button|macro button]] called "Sleep" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "color=blue")]<br />
</source> <br />
Click on the button and hopefully you should see it change to blue.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example)<br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code.<br />
<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro button]]s with the specified name searching for one that is the default color and a daily power, once it finds one it sets its color to blue and sets found=1 so no other buttons are changed (as of 1.3b48 there is no way to break out of a loop).<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in.<br />
<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h,macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will turn blue.<br />
<br />
Fine you say but I would like to stop players using powers that are blue (or in the case of multi use powers where there are no non blue ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]].<br />
Change it to the following<br />
<br />
===Sorry Sir/Madam, you have already used that!===<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
And change the [[Token|token]]'s "Lay On Hands" macro code (don't forget to change all the duplicates too).<br />
<source lang="mtmacro" line><br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
Oooh tingly!<br />
</source><br />
<br />
Then clickity, clickity, click on the "Daily:Lay On Hands" buttons and when you have none left you should get the following dialog.<br />
<br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers.<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Encounter Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Encounter Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange2.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_a_Macro_(Group_Method)&diff=8966Updating Macro Buttons Using a Macro (Group Method)2020-09-14T17:06:26Z<p>Lwoestman: /* Updating color of our macro buttons using DnD4e as an example */</p>
<hr />
<div>==Updating color of our macro buttons using DnD4e as an example==<br />
For an example I will use DnD4e powers; when a power is used it will then update the button to show this. Although this is example is for DnD4e the technique is applicable for many other systems.<br />
<br />
Lets assume that you have macro groups named "Daily Powers" and "Encounter Powers" where we place all of our powers, and we want to set the color of the [[Macro_Button|macro button]] to blue if the power has been used. If you want another way to do this without using different groups see [[Tutorials:Macros:UpdatingMacroButtons:DnD4ePowersPrefix | Tracking Used DnD 4e Powers (Macro Prefix Method)]]<br />
<br />
<br />
<br />
'''Version update:''' <br />
This tutorial was written before 1.3b50. As of 1.3b50 you can use [[Macros:Functions:getMacroButtonIndex|getMacroButtonIndex]] to determine the index of the button that was pressed. Instead of setting/getting the properties of the button by name you can use the index of the button in place of the name, this way you will not run the risk of updating buttons with the same name.<br />
<br />
<br />
===Short Rest, resetting color of buttons in the "Encounter Powers" group===<br />
So first we will create a [[Macro_Button|macro button]] called "Short Rest", for this tutorial I will assume you just create it as a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] --just remember to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check mark-- you can just as easily create these as macros in [[Token:library token|library token]] macros and call them from from [[Macro_Button|macro buttons]] on your [[Token|tokens]].<br />
<br />
[[image:ShortRest1MacroButton.png]]<br />
<br />
So create the "Short Rest" [[Macro_Button|macro button]] and copy the following code into it.<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
The way the above macro works is by getting a list of the macros [[Macros:Functions:getMacros|getMacros()]] which will return all the labels of the [[Macro_Button|macro buttons]] on the [[Current Token]]. Since a [[Token|token]] can contain multiple [[Macro_Button|macro buttons]] with the same label the function [[Macros:Functions:getMacroIndexes|getMacroIndexes()]] is used to return the unique index of each [[Macro_Button|macro button]] for each of the labels. Then we use [[Macros:Functions:getMacroProps|getMacroProps()]] to get the properties of the [[Macro_Button|macro button]] in a [[Macros:string property list|string property list]]. The color of the [[Macro_Button|macro button]] is extracted from this using [[Macros:Functions:getStrProp|getStrProp()]] and we check to see if it is "blue", if it is we also check to see if it is in the "Encounter Powers" group, and set the value of isBlue based on this. Then if isBlue is true (non zero) we use [[Macros:Functions:setMacroProps|setMacroProps()]] to change the color back to the default. <br />
<br />
You can test this macro by dragging a [[Token|token]] onto the map and adding a [[Macro_Button|macro button]] to it called "Something or other" in the "Encounter Powers" group and set it to blue in the creation dialog.<br />
<br />
[[image:ButtonSomethingOrOtherBlueGroup.png]] [[image:ButtonSomethingOrOtherDefaultGroup.png]]<br />
<br />
===Extended Rest, resetting color of buttons starting with "Encounter Powers" or "Daily Powers"===<br />
For an extended rest we want to reset the color of any [[Macro_Button|macro buttons]] that start with either "Encounter Powers" or "Daily Powers". So create a [[Introduction_to_Macro_Writing#Campaign Macros|campaign macro]] called "Extended Rest" (don't forget to check the [[Macros:Apply to Selected Tokens|Apply to Selected Tokens]] check box) and copy the following code into it.<br />
<br />
<source lang="mtmacro" line><br />
[abort(hasImpersonated())] <!-- Abort macro if no token is impersonated --><br />
<br />
[h,foreach(macro, getMacros()), code: {<br />
<!-- <br />
== each label can appear more than once (i.e. more than one<br />
== button with same label, so we need to get all the button<br />
== indexes for a label<br />
--><br />
<br />
[h,foreach(index, getMacroIndexes(macro)), code: {<br />
[props = getMacroProps(index)]<br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
[h,if(isBlue): setMacroProps(index, "color=default")]<br />
}]<br />
}]<br />
[abort(0)] <!-- Suppress output text --><br />
</source><br />
<br />
The only difference between this macro and the previous one is where it checks the group of the [[Macro_Button|macro button]]. In the "Short Rest" [[Macro_Button|macro button]] we had <br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Encounter Powers", 1, 0)]<br />
</source><br />
Where in the "Extended Rest" [[Macro_Button|macro button]] it is<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Daily|Encounter) Powers"), 1, 0)]<br />
</source><br />
The pattern ''(Daily|Encounter) Powers'' matches both the "Daily Powers" and "Encounter Powers" strings.<br />
Hopefully from this you can see how to add powers with different durations, say you wanted to add powers that could be used once per round and place them in the "Round Group", for your "New Round" macro which resets the color you would change the lines to<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
getStrProp(props, "group") == "Round Powers", 1, 0)]<br />
</source><br />
<br />
And for your "Short Rest" you would change it to refresh encounter and round powers.<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter) Powers"), 1, 0)]<br />
</source><br />
And for your "Extended Rest" you would change it to refresh daily, encounter and round powers.<br />
<source lang="mtmacro" line start=12><br />
[isBlue = if(getStrProp(props, "color") == "blue" &&<br />
matches(getStrProp(props, "group"),<br />
"(Round|Encounter|Daily) Powers"), 1, 0)]<br />
</source><br />
<br />
===Using Powers, or getting the blues...===<br />
So now all that is left is to set the color of the buttons when they are used. As of 1.3b48 there is no way to determine which button has been pressed from a macro, but what you can do is to add code like the following to your power macros.<br />
<br />
<source lang="mtmacro" line><br />
[h: setMacroProps("Burning Hands", "color=blue")]<br />
</source><br />
Replacing the "Burning Hands" with the label of your [[Macro_Button|macro button]].<br />
So lets try it, on your token create a [[Macro_Button|macro button]] called "Sleep" in the group called "Daily Powers" and in the button place the following code<br />
<source lang="mtmacro" line><br />
Watch, the watch, you are getting sleepy, your eyelids are getting heavy.... [h: setMacroProps("Sleep", "color=blue")]<br />
</source> <br />
Click on the button and hopefully you should see it change to blue.<br />
<br />
===Multiple Power Buttons with the same name===<br />
A word of warning though: the above method will change the color of all buttons with that label so if you have duplicates and only want to set one (you may want to implement multi use per day powers as multiple buttons for example)<br />
<br />
Drag a new [[Token|token]] onto the map and change its name to Lib:DnD4ePowers, and create a [[Macro_Button|macro button]] called "UseDailyPower", then copy in the following code.<br />
<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
</source><br />
This will loop through all of the indexes for the [[Macro_Button|macro button]]s with the specified name searching for one that is the default color and a daily power, once it finds one it sets its color to blue and sets found=1 so no other buttons are changed (as of 1.3b48 there is no way to break out of a loop).<br />
<br />
Now create a [[Macro_Button|macro button]] called "Lay On Hands" and copy the following in.<br />
<br />
<source lang="mtmacro" line><br />
Oooh tingly!<br />
[h,macro("UseDailyPower@Lib:DnD4ePowers"): "Lay On Hands"]<br />
</source><br />
Duplicate that a few times and then when you click on on of the buttons then one of the "Lay On Hands" buttons will turn blue.<br />
<br />
Fine you say but I would like to stop players using powers that are blue (or in the case of multi use powers where there are no non blue ones remaining).<br />
<br />
We can do that by changing the "UseDailyPower" macro we created above on the Lib:DnD4ePowers [[Token:library token|library token]].<br />
Change it to the following<br />
<br />
===Sorry Sir/Madam, you have already used that!===<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Daily Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Daily Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
And change the [[Token|token]]'s "Lay On Hands" macro code (don't forget to change all the duplicates too).<br />
<source lang="mtmacro" line><br />
[h,macro("UsePower@Lib:DnD4ePowers"): "Daily:Lay On Hands"]<br />
Oooh tingly!<br />
</source><br />
<br />
Then clickity, clickity, click on the "Daily:Lay On Hands" buttons and when you have none left you should get the following dialog.<br />
<br />
[[image:PowerUsedDialogGroup.png]]<br />
<br />
It ain't pretty but the concept is there and you can easily expand on it to pretty it up.<br />
<br />
While we are at it we should add a "UseEncounterPower" macro to Lib:DnD4ePowers.<br />
<source lang="mtmacro" line><br />
[h: found = 0]<br />
[h: indexes = getMacroIndexes(macro.args)]<br />
[h, foreach(button, indexes), code: {<br />
[if(found==0), code: {<br />
[props = getMacroProps(button)]<br />
[group = getStrProp(props, "group")]<br />
[color = getStrProp(props, "color")]<br />
[if(color=="default" && group == "Encounter Powers"): <br />
setMacroProps(button, "color=blue")<br />
]<br />
[if(color=="default" && group == "Encounter Powers"): found=1]<br />
}]<br />
}]<br />
<!-- if "free" one is not found then inform user they can't do it --><br />
[if(found==0), code: {<br />
[dialog("PowerUsed"): {<br />
<title>Can Not Use Power</title><br />
<meta name="temporary" content="true"><br />
You have already used [r: macro.args]<br />
}]<br />
}]<br />
[abort(found)] <!-- Abort the macro if an unused power was not found --><br />
</source><br />
<br />
You can also use this for cases where there is only a single button for a power.<br />
<br />
You can download this part of the tutorial in in a [http://lmwcs.com/maptool/campaigns/ButtonChange2.cmpgn campaign file] which was made using MapTool 1.3b48.<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macro_Button&diff=8965Macro Button2020-09-13T22:19:23Z<p>Lwoestman: </p>
<hr />
<div>[[Image:Macrobuttons.jpg|frame|Sample View of Macro Buttons]]<br />
Macro Buttons are user-clickable buttons that execute a macro with a single click (as opposed to having to type the entire macro to chat). When a macro is created, it automatically generates a labeled button (the label is the name given by the macro author to the macro).<br />
<br />
The screenshot below shows some example macro buttons. Note that buttons can have varying button and font colors, and can be sorted and arranged in various ways. <br />
<br />
When the macro button is clicked, the contents of the macro are populated to the Chat Panel and the commands are parsed and executed.<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Updating_Macro_Buttons_Using_Macros&diff=8964Updating Macro Buttons Using Macros2020-09-13T22:14:40Z<p>Lwoestman: </p>
<hr />
<div>==Dynamically Updating a Token's Macro Buttons==<br />
Some times you want to modify the label of a [[Token]]'s [[Macro_Button|macro button]] from within a macro; this could be to visually represent a spell or power as having been used or even indicating that it is available for use. <br />
<br />
A quick note on some of these examples: before 1.3b51 it was only possible to have 2 levels deep of {{code|code:}} blocks, so some of the examples do things a little differently than you would if you could have multiple levels of {{code|code:}} blocks to avoid running into the problem. Also before 1.3b50 there was no way to get the index of the button that had been pressed, these tutorials show you how to "guess" the button that is pressed. As of 1.3b50 you can use the function {{func|getMacroButtonIndex}} to determine exactly which macro button has been clicked on the token.<br />
<br />
This tutorial is broken into several parts; although DnD4e is used to explain the concepts they are just as valid for any other system where you want to track if a skill has already been used or not.<br />
<br />
* [[Updating Macro Buttons Using a Macro (Prefix Method)]]<br />
* [[Updating Macro Buttons Using a Macro (Group Method)]]<br />
* [[Updating Macro Buttons Using a Macro (Label Method)]]<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=getLibProperty&diff=8963getLibProperty2020-09-13T21:54:29Z<p>Lwoestman: </p>
<hr />
<div>{{MacroFunction<br />
|name=getLibProperty<br />
|version=1.3b48<br />
|description=Returns the value of a [[Token:token property{{!}}token property]] from a [[Token:library token{{!}}library token]]. If the lib argument is not specified then the [[Token:token property{{!}}token property]] will be retrieved from the [[Token:library token{{!}}library token]] that the macro is currently running from.<br />
<br />
Unlike {{func|getProperty}}, this function will not retrieve the default value of a campaign property. Default values are generally programmed as local variables in a macro, then overridden with the result of this function if this function returns a value. An example is shown below.<br />
<br />
|usage=<br />
<source lang="mtmacro" line><br />
getLibProperty(name)<br />
getLibProperty(name, lib)<br />
</source><br />
<br />
'''Important Note'''<br />
As mentioned in the introduction, if the value of the property on the Token equals the default value, the function will return nothing! This means that if e.g. you set the default property to <br />
<source lang="mtmacro" line><br />
Weapons : Shotgun, Pistol, Revolver<br />
</source><br />
And you leave the e.g. the value on the token lib:Compendium unchanged, so it will also contain the value "Shotgun, Pistol, Revolver", then<br />
<source lang="mtmacro" line><br />
[getLibProperty("Weapons", "lib:Compendium")]<br />
</source><br />
will return nothing!<br />
<br />
<br />
|examples=<br />
To get the "init" [[Token:token property{{!}}token property]] from the [[Token:library token{{!}}library token]] that a macro is running from use<br />
<source lang="mtmacro" line><br />
[getLibProperty("init")]<br />
</source><br />
<br />
To get the "init" [[Token:token property{{!}}token property]] from the [[Token:library token{{!}}library token]] if the library token has such a property. If not, use a default value of "default".<br />
<source lang="mtmacro" line><br />
[result = getLibProperty("init")]<br />
[IF(result == ""): result = "default" ]<br />
</source><br />
<br />
To get the "init" [[Token:token property{{!}}token property]] from a [[Token:library token{{!}}library token]] called "lib:Attacks" use<br />
<source lang="mtmacro" line><br />
[getLibProperty("init", "lib:Attacks")]<br />
</source><br />
}}<br />
[[Category:Token Library Function]][[Category:Property Function]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Library_Token&diff=8962Library Token2020-09-13T21:48:58Z<p>Lwoestman: /* Creating a Library Token */</p>
<hr />
<div>{{Languages|Library Token}}<br />
Introduced in MapTool version 1.3b46, the Library Token is a special token type that acts as a library of properties and trusted macros that may be accessed and called by other macros. <br />
<br />
==Library Token Naming==<br />
<br />
All library tokens must have a name in the format "Lib:''name''", to indicate that they are to serve as a Library Token and not a "normal" token. Example library token names might be:<br />
<br />
*Lib:test<br />
*Lib:combat<br />
*Lib:gamemaster<br />
<br />
==Creating a Library Token==<br />
<br />
To create a Library Token, do the following:<br />
<br />
# Drag a new token on to one of the maps in your campaign. The map does not need to be visible to players.<br />
# Rename it with a name in the format '''Lib''':''name'' (''e.g.'', '''Lib:DnD''', '''Lib:GameRules''', etc.). <br />
# Right click on the token and make sure that '''Visible to Players''' is checked.<br />
# Set the token type to NPC (upper right corner of the Token Configuration dialog).<br />
<br />
After that, you have a Library Token. Note that you cannot have two library tokens with the same name in the same campaign (even if they're on different maps!). <br />
<br />
Once again, the requirements are:<br />
<br />
* The library token must be visible to players (make sure Visible to Players is set in the right-click context menu).<br />
* The library token need not be on the "Token" layer (you can keep it on the "Hidden" layer to hide it from players, although "Visible to Players" must still be set to true).<br />
* The library token must have a name in the format "Lib:''name''".<br />
* The library token must be present on ''only one'' map in the campaign file.<br />
<br />
==Library Tokens and Trusted Macros==<br />
<br />
Library Tokens may run [[Trusted Macro|Trusted Macros]] or utilize trusted macro functions provided they meet one of the following criteria:<br />
* The library token is '''not owned by any players''', OR<br />
* The macros on the library token are '''not player-editable'''.<br />
<br />
If the Library Token does not meet at least one of those criteria, ''it cannot run trusted macros.'' This allows players to create their own personal library tokens for various ''un''trusted macros they wish to run, while at the same time preventing players from altering or manipulating any token or other element of the campaign for which they do not have permission to do so.<br />
<br />
==Library Token Macros==<br />
<br />
Library token macros are created and edited like macros on any token. Macros on a library token may be called using the [[Macros:Branching_and_Looping#MACRO_Option| [MACRO(): ]]] roll option. Since Library token macros are trusted, they may perform operations not available to regular tokens.<br />
<br />
==Library Token Properties==<br />
<br />
Library token properties should be set and retrieved by using the {{func|setLibProperty}} and {{func|getLibProperty}} functions. <br />
<br />
Note that {{func|getLibProperty}} does '''NOT''' return default campaign property values, instead returning an empty string if the property is not set on the Library token. This is often useful for library tokens to prevent unintended errors that could be caused by unexpected default property values.<br />
<br />
=== The 'libversion' property ===<br />
The special 'libversion' property can be set on a library token to be output with <code>getInfo("client")</code>. The library token's name and the libversion will be a key/value pair in the nested "library tokens" object of the resulting {{func|getInfo}} JSON object. The libversion property value will be displayed 'as-is'; any macro code in libversion will be displayed instead of processed.<br />
<br />
To edit libversion, you can either add libversion to the Library Token's property list in the Campaign Preferences and then edit the token's properties directly, or set it via the chat panel or a macro using the {{func|setLibProperty}} function.<br />
<br />
When creating and improving upon a library token as a 'plugin' others use in their games, updating libversion with new releases is good practice. You may consider using [https://semver.org/ Semantic Versioning] to help give version numbers meaning for your users.<br />
<br />
==Library Token onCampaignLoad==<br />
<br />
Most users will find it worthwhile to add an [[onCampaignLoad]] macro to your Lib token that will use {{func|defineFunction}} to make your Lib macros accessible like the built-in macro functions and recognized by the macro editor.<br />
<br />
==See Also==<br />
* [[Token|MapTool Tokens]]<br />
* [[Token Types]]<br />
* [[Image_Token|Image Token]]<br />
* [[TokenTool QuickStart|TokenTool QuickStart Guide]]<br />
* [[Introduction_to_Tokens|Introduction to Tokens]]<br />
<br />
<br />
[[Category:Token]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macros:Branching_and_Looping&diff=8961Macros:Branching and Looping2020-09-13T21:41:26Z<p>Lwoestman: /* Usage */</p>
<hr />
<div>{{Intermediate}}<br />
== Introduction ==<br />
This page details the branching and looping structures in MapTool. With the exception of the block {{func|if}} statement, these are all [[Macros:Roll:types | roll options]] and should follow the general form for roll options:<br />
<br />
<source lang="mtmacro" line><br />
[option1[,option2]: body]<br />
</source><br />
<br />
These may be combined with other roll options (note that in some examples, they are combined with the [[Macros:Roll:types#.5B_.5D_Hidden_Rolls | Hidden Roll]] option ({{code|h}}) to hide the default output of the loop or branch). <br />
<br />
'''If you wish to combine roll options in a single statement, separate the roll options with a comma, and place the colon at the end of the sequence of roll options. Note that some combinations have unpredictable results, such as using {{roll|if}} with {{roll|macro}}.''' <br />
<br />
For example, if you want to combine a Hidden Roll, {{roll|token}}, and {{roll|foreach}} option in a single statement, you would enter the line like so:<br />
<br />
<source lang="mtmacro" line><br />
[h,token("JoeRandom"),foreach(item, TokensItemList): "This item's name is "+item+"!"]<br />
</source><br />
<br />
<br />
==Branching==<br />
<br />
===IF Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
This {{roll|if}} is a roll option (as mentioned above), but operates similarly to the block-style {{func|if}}.<br />
<br />
====Usage====<br />
<source lang="mtmacro" line><br />
[if(condition): true_body; false_body]<br />
</source><br />
<br />
;or<br />
<source lang="mtmacro" line><br />
[if(condition): true_body]<br />
</source><br />
<br />
Either the {{code|true_body}} or {{code|false_body}} will be used, depending on the value of {{code|condition}}. If the {{code|false_body}} is not given but the {{code|condition}} is {{false}}, then there is no output.<br />
<br />
====Example====<br />
<source lang="mtmacro" line><br />
[h:val=12]<br />
[h,if(val == 12): newVal=12*12]<br />
New Value = [r:newVal]<br />
</source><br />
<br />
Outputs {{code|New Value {{=}} 144}}.<br />
<br />
====Note====<br />
For an alternate method for evaluating "if" conditions, see the function {{func|if}}. Note that the {{roll|if}} roll option cannot be (usefully) combined with the {{roll|macro}} roll option as the roll options are not guaranteed to be executed in any particular order. This means that the {{func|if}} function is a better choice in those cases.<br />
<br />
===SWITCH Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
{{roll|switch}} chooses among several options and executes code based on the switch expression. <br />
<br />
*'''<span style="color: #FF0000;">Note</span>''' that the {{code|expression}} is a regular expression, so metacharacters such as {{code|*}} and {{code|()}} will need to have backslashes in front of them if you want to match them literally.<br />
<br />
====Usage====<br />
<br />
<source lang="mtmacro" line><br />
[switch(expression):<br />
case case1: body1;<br />
case case2: body2;<br />
default: default_body]<br />
</source><br />
or with a code block:<br />
<source lang="mtmacro" line><br />
[switch(expression), code:<br />
case case1: {body1};<br />
case case2: {body2};<br />
default: {default_body}]<br />
</source><br />
<br />
====Example====<br />
<source lang="mtmacro" line><br />
[h:powerType="at-will"]<br />
[switch(powerType):<br />
case "at-will": "You may use this power as much as you like";<br />
case "encounter": "You may only use this power once per encounter";<br />
case "daily": "You may only use this power once per day"<br />
]<br />
</source><br />
<br />
Outputs {{code|You may use this power as much as you like}}<br />
<br />
Using a code block:<br />
<source lang="mtmacro" line><br />
[h:powerType="at-will"]<br />
[switch(powerType), code:<br />
case "at-will": {<br />
[r:token.name]:<br><br />
[r:"You may use this power as much as you like"]<br />
};<br />
case "encounter": {<br />
[r:token.name]:<br><br />
[r:"You may only use this power once per encounter"]<br />
};<br />
case "daily": {<br />
[r:token.name]:<br><br />
[r:"You may only use this power once per day"]<br />
};<br />
]<br />
</source><br />
<br />
Using regex:<br />
<source lang="mtmacro" line><br />
[h:powerType=".*sword.*"]<br />
[switch(powerType):<br />
case "flail": "one-handed weapon; two-handed does Str*2 damage";<br />
case "shortsword": "used for jabs, so is a puncturing weapon";<br />
case "longsword": "a slashing weapon"<br />
]<br />
</source><br />
Outputs {{code|used for jabs, so is a puncturing weapon}}. Notice that the first matching clause was the one that the {{roll|switch}} option found.<br />
<br />
===MACRO Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
{{roll|macro}} runs the named macro, inserting its text into chat.<br />
<br />
====Usage====<br />
<br />
<source lang="mtmacro" line><br />
[macro("macro_name@location"): macro_arguments]<br />
</source><br />
<br />
The called macro sees a variable called [[Macros:Special_Variables:macro.args|{{code|macro.args}}]] which contains the value of {{code|macro_arguments}}. The called macro can set a variable called [[Macros:Special_Variables:macro.return|{{code|macro.return}}]], which becomes available to the calling macro. Other than {{code|macro.return}}, the called macro shares no variables with the calling macro.<br />
<br />
====Examples====<br />
<br />
<source lang="mtmacro" line><br />
[macro("getDamage@Lib:combat"): damageRoll]<br />
</source><br />
<br />
Calls the macro {{code|getDamage}} which resides on a [[Token:library_token|library token]] called {{code|Lib:combat}}, and passes the variable {{code|damageRoll}} as an argument to the called macro. <br />
<br />
====Location Requirements====<br />
<br />
The {{code|location}} can be one of the following:<br />
<br />
# {{code|TOKEN}} - the currently impersonated token (use the word {{code|TOKEN}}, not the token's name)<br />
# {{code|Library Token}} - a [[Token:library_token|Library Token]] in the current campaign<br />
# {{code|this}} - if the macro is calling another macro in the same library, {{code|this}} may be used instead of retyping the full library token name<br />
<br />
====Notes====<br />
<br />
When a token macro calls another macro, the macro instructions in the ''called'' macro are executed against the ''calling'' token (in other words, the macro uses properties available on the calling token and applies all results to that token), unless the focus is explicitly changed to another token via either a roll option, or the {{func|switchToken}} function, or the {{func|getLibProperty}} function.<br />
<br />
Also, as of at least 1.3.b50, a variable must be given for {{code|macro_arguments}}, or the <br />
''"Could not execute the command: Undefined function: MACRO"''<br />
error will result. However, the variable given as {{code|macro_arguments}} doesn't have to be used.<br />
<br />
===TOKEN Option===<br />
<br />
'''Introduced''': Version 1.3.b48<br />
<br />
{{roll|token}} executes a series of instructions against a token specified in the argument rather than against the token running the macro. <br />
<br />
This is a temporary change in the token that has the "focus" - only the instructions following the colon are applied to the designated token; following the end of that instruction block, operations resume being performed against the token running the macro.<br />
<br />
To permanently switch (for the duration of the macro) the token against which macro commands are executed, see the {{func|switchToken}} function.<br />
<br />
====Usage====<br />
<br />
<source lang="mtmacro" line><br />
[token(token_identifier): ]<br />
</source><br />
<br />
Executes the roll against the token specified by {{code|token_identifier}}, which can either be the token name or token id.<br />
<br />
====Examples====<br />
<br />
<source lang="mtmacro" line><br />
[h:target="Orc 5"]<br />
[h,token(target): targetAC = getProperty("AC")]<br />
</source><br />
<br />
Uses the {{func|getProperty}} function to retrieve the property {{code|AC}} from the token named {{code|"Orc 5"}}, and assigns that value to the variable {{code|targetAC}}. {{code|targetAC}} can be used in future calculations, such as determining whether an attack hits. If the {{roll|token}} option was not used, the macro would have looked for the property {{code|AC}} on the token currently ''running'' the macro. Note also that this function is considered [[Macros:TrustedMacros|trusted]].<br />
<br />
==Looping==<br />
<br />
===COUNT Option===<br />
<br />
'''Introduced''': Version 1.3.b41<br />
<br />
The {{roll|count}} option executes a statement for a specified number of times, storing the number of the current iteration in a variable called {{code|[[roll.count]]}}. <br />
<br />
====Usage====<br />
<source lang="mtmacro" line><br />
[count(num): body]<br />
[count(num, separator): body]<br />
</source><br />
<br />
The {{code|[[roll.count]]}} variable will take on values from {{code|0}} to {{code|(number of loops - 1)}}. The optional separator (default {{code|","}}) is printed between each iteration.<br />
<br />
====Example====<br />
<source lang="mtmacro" line><br />
[h:numHits=3]<br />
[count(numHits): Damage = Damage + 1d12]<br />
</source><br />
<br />
This will iterate the {{code|Damage {{=}} Damage + 1d12}} operation 3 times, separating the result of each iteration with the default separator (a comma). An optional second argument to {{roll|count}} allows the setting of a different separator.<br />
<br />
===FOR Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
Executes a statement for a number of iterations based on a start and end value.<br />
<br />
====Usage====<br />
<br />
<source lang="mtmacro" line><br />
[for(var, start, end): body]<br />
[for(var, start, end, stepsize): body]<br />
[for(var, start, end, stepsize, separator): body]<br />
</source><br />
<br />
The {{code|var}} variable counts from {{code|start}} to {{code|1}} short of {{code|end}} during the loop (so the {{code|end}} number will not be part of the loop). The optional {{code|stepsize}} (default {{code|+1}}) is added to {{code|var}} at each iteration. The loop does ''not'' evaluate when {{code|var}} reaches {{code|end}}.<br />
<br />
====Example====<br />
<source lang="mtmacro" line><br />
[for(i,10,0,-2): "i is now " + i]<br />
</source><br />
<br />
Counts down even numbers from 10 to 2.<br />
<br />
===FOREACH Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
Iterates over the contents of a string list in the format {{code|"item1, item2, item3"}}, the contents of a JSON Array, or the keys of a JSON Object.<br />
<br />
====Usage====<br />
<source lang="mtmacro" line><br />
[foreach(var, list): body]<br />
[foreach(var, list, output_separator): body]<br />
[foreach(var, list, output_separator, list_separator): body]<br />
[foreach(var, jsonarray): body]<br />
[foreach(var, jsonarray, output_separator): body]<br />
[foreach(var, jsonobject): body]<br />
[foreach(var, jsonobject, output_separator): body]<br />
</source><br />
<br />
====Example Using a List ====<br />
<source lang="mtmacro" line><br />
[h: enemyList="Orcs, Goblins, Ogres, Trolls"]<br />
[foreach(enemy, enemyList, "<br>"): "You really hate " + enemy]<br />
</source><br />
<br />
Outputs:<br />
You really hate Orcs<br />
You really hate Goblins<br />
You really hate Ogres<br />
You really hate Trolls<br />
<br />
====Example Using a JSON Array ====<br />
<source lang="mtmacro" line><br />
[h: weapons = json.append("[]", "Longsword", "Dagger", "Bow")]<br />
[foreach(wpn, weapons): wpn]<br />
</source><br />
<br />
Outputs:<br />
Longsword, Dagger, Bow<br />
<br />
====Example Using a JSON Object ====<br />
<source lang="mtmacro" line><br />
[h: weaponData = json.set("{}",<br />
"Name": "Longsword",<br />
"Damage": "1d6",<br />
"Type": "Slashing",<br />
"Weight": 30,<br />
)]<br />
[foreach(field, weaponData): field]<br />
</source><br />
<br />
Outputs:<br />
Name, Damage, Type, Weight<br />
<br />
If you really wanted to see the key ''and'' the data, try this:<br />
<br />
<source lang="mtmacro" line><br />
[h: weaponData = json.set("{}",<br />
"Name": "Longsword",<br />
"Damage": "1d6",<br />
"Type": "Slashing",<br />
"Weight": 30,<br />
)]<br />
[foreach(field, weaponData):<br />
field + ": " + json.get(weaponData, field)]<br />
</source><br />
<br />
Outputs:<br />
Name: Longsword, Damage: 1d6, Type: Slashing, Weight: 30<br />
<br />
''P.S.: Note the trailing comma after the Weight field in the {{func|json.set}} function? It's ignored. But putting it in makes it easier to copy/paste new lines into the function...''<br />
<br />
===WHILE Option===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
Repeatedly executes a statement until a condition becomes false.<br />
<br />
====Usage====<br />
<source lang="mtmacro" line><br />
[while(condition): body]<br />
[while(condition, separator): body]<br />
</source><br />
<br />
====Example====<br />
<source lang="mtmacro" line><br />
[h:num=10]<br />
[while(num>=0): num = num-1]<br />
</source><br />
<br />
Outputs {{code|9,8,7,6,5,4,3,2,1}}<br />
<br />
==Code Execution==<br />
<br />
===CODE===<br />
<br />
'''Introduced''': Version 1.3.b46<br />
<br />
The {{roll|code}} option is used in conjunction with looping / branching options to execute multiple statements within a single "block" of a loop or branch, allowing the creation of more complex loops and branches. <br />
<br />
====Usage====<br />
<source lang="mtmacro" line><br />
[code: { code_block }]<br />
</source><br />
<br />
The {{code|code_block}} is a collection of text and macro code, enclosed in a single {{code|{<nowiki>}</nowiki>}} pair. Everything within the {{code|{<nowiki>}</nowiki>}} is treated as a single block for the purposes of any looping or branching options.<br />
<br />
====Example====<br />
<br />
<source lang="mtmacro" line><br />
[h:num=5]<br />
[while(num > 0), code:<br />
{<br />
This is iteration [r:num] <br><br />
There are [r:num-1] iterations left<br><br />
[num=num-1]<br />
}]<br />
</source><br />
<br />
Outputs:<br />
<br />
This is iteration 5 There are 4 iterations left<br />
4, This is iteration 4 There are 3 iterations left<br />
3, This is iteration 3 There are 2 iterations left<br />
2, This is iteration 2 There are 1 iterations left<br />
1, This is iteration 1 There are 0 iterations left<br />
0<br />
<br />
'''NOTE''': the digit output at the beginning of each line is an artifact of the {{roll|while}} loop's evaluation of {{code|num}} - since this roll does not have the {{roll|h}} option active, the result of that evaluation is displayed.<br />
<br />
====Nested CODE Blocks====<br />
<br />
To nest {{code|code:{<nowiki>}</nowiki>}} blocks, use a second {{roll|code}} option, like so:<br />
<br />
<source lang="mtmacro" line><br />
[h:d20roll=1d20]<br />
[h:attackRoll=d20roll+AttackBonus]<br />
[h,if(attackRoll >= 16),code:<br />
{<br />
[if(d20roll == 20),code:<br />
{<br />
The attack is a critical hit!<br />
[h:damage=critDamage]<br />
};<br />
{<br />
The attack is a hit!<br />
[h:damage=regDamage]<br />
}]<br />
};<br />
{<br />
The attack misses!<br />
}]<br />
</source><br />
<br />
MapTool can only handle two levels of nested code.<br />
<br />
==Additions==<br />
<br />
Conditional Operators:<br />
* {{code|>}} - Greater than<br />
* {{code|<}} - Less than<br />
* {{code|>{{=}}}} - Greater than or equal to<br />
* {{code|<{{=}}}} - Less than or equal to<br />
* {{code|{{=}}{{=}}}} - Equal to<br />
* {{code|!{{=}}}} - Not equal<br />
<br />
Logical Operators:<br />
* {{code|&&}} - And<br />
* {{code|&brvbar;&brvbar;}} - Or<br />
<br />
It is important to note that the ''Equal'' condition operator must be two equal signs. If you are checking for a text string, place quotes around the text.<br />
<br />
Operator Precedence:<br />
* {{code|( )}} - Parentheses are always done first; they can be nested<br />
* {{code|!}} - Logical NOT<br />
* {{code|&&}} - Logical AND<br />
* {{code|&brvbar;&brvbar;}} - Logical OR<br />
<br />
[[Category:Tutorial]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8940Forms tutorial2020-09-06T22:48:44Z<p>Lwoestman: /* Click-based Target selection */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as a key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specify the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressions are evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesn't work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesn't work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''HTML formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to HTML inputs. <br />
To remove the HTML tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so are by using an image table or image tokens. I won't explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It not only sends the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you to some kinds of events that MapTool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 MapTool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping information about selected tokens and such.<br />
<br />
To set it up you have to define an HTML header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And I don't say they do it intentionally.<br />
<br />
So you should protect your macros against trouble-making user inputs. For example a comma inside of an item of a comma separated list breaks the list.<br />
<br />
So it's always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex HTML forms can take time ===<br />
<br />
Just be aware of this. Building and rendering HTML and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Don't make things complicated if you do not want to have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching HTML forms ===<br />
<br />
Since building HTML forms can take serious amounts of time it is a good practice to store built form HTML in a token property and reuse it as long it doesn't have to be rebuilt. It's especially effective if you build complex stuff by accessing lots of properties - usually the case if you build character sheets. When creating complex HTML structures and storing them into a token property you're asking for trouble so it's common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token.<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you don't like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while an unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have an initially checked checkbox you can set it as checked like this (regardless of being predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for teaching me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in MapTool. They are a great way to precisely align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what to display.<br />
<br />
We want more eye candy, so we will use CSS. As we like separating CSS rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very different ways to select targets of an action. The clickbased targeting (first done by Rumble) works best in MapTool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, e.g. "Attack" that opens a frame. In that frame you can enter additional information like modifiers. While that frame is open you select (with the mouse on the map) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Let's start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro is aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he does if he is the GM or owns the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into a different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesn't modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8938Forms tutorial2020-09-06T22:41:54Z<p>Lwoestman: /* Character sheet/editor */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as a key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specify the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressions are evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesn't work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesn't work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''HTML formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to HTML inputs. <br />
To remove the HTML tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so are by using an image table or image tokens. I won't explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It not only sends the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you to some kinds of events that MapTool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 MapTool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping information about selected tokens and such.<br />
<br />
To set it up you have to define an HTML header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And I don't say they do it intentionally.<br />
<br />
So you should protect your macros against trouble-making user inputs. For example a comma inside of an item of a comma separated list breaks the list.<br />
<br />
So it's always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex HTML forms can take time ===<br />
<br />
Just be aware of this. Building and rendering HTML and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Don't make things complicated if you do not want to have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching HTML forms ===<br />
<br />
Since building HTML forms can take serious amounts of time it is a good practice to store built form HTML in a token property and reuse it as long it doesn't have to be rebuilt. It's especially effective if you build complex stuff by accessing lots of properties - usually the case if you build character sheets. When creating complex HTML structures and storing them into a token property you're asking for trouble so it's common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token.<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you don't like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while an unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have an initially checked checkbox you can set it as checked like this (regardless of being predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for teaching me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in MapTool. They are a great way to precisely align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what to display.<br />
<br />
We want more eye candy, so we will use CSS. As we like separating CSS rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8937Forms tutorial2020-09-06T22:37:34Z<p>Lwoestman: /* Good advice */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as a key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specify the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressions are evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesn't work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesn't work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''HTML formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to HTML inputs. <br />
To remove the HTML tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so are by using an image table or image tokens. I won't explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It not only sends the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you to some kinds of events that MapTool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 MapTool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping information about selected tokens and such.<br />
<br />
To set it up you have to define an HTML header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And I don't say they do it intentionally.<br />
<br />
So you should protect your macros against trouble-making user inputs. For example a comma inside of an item of a comma separated list breaks the list.<br />
<br />
So it's always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex HTML forms can take time ===<br />
<br />
Just be aware of this. Building and rendering HTML and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Don't make things complicated if you do not want to have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching HTML forms ===<br />
<br />
Since building HTML forms can take serious amounts of time it is a good practice to store built form HTML in a token property and reuse it as long it doesn't have to be rebuilt. It's especially effective if you build complex stuff by accessing lots of properties - usually the case if you build character sheets. When creating complex HTML structures and storing them into a token property you're asking for trouble so it's common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token.<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you don't like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while an unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have an initially checked checkbox you can set it as checked like this (regardless of being predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for teaching me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in MapTool. They are a great way to precisely align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8936Forms tutorial2020-09-06T22:22:42Z<p>Lwoestman: /* Events */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as a key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specify the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressions are evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesn't work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesn't work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''HTML formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to HTML inputs. <br />
To remove the HTML tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so are by using an image table or image tokens. I won't explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It not only sends the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you to some kinds of events that MapTool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 MapTool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping information about selected tokens and such.<br />
<br />
To set it up you have to define an HTML header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And i dont say they do it intentionally.<br />
<br />
So you should protect your macros against trouble making user inputs. For example can a comma inside of an item of a comma separated list break the list.<br />
<br />
So its always always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex html forms can take time ===<br />
<br />
Just be aware of this. Building and rendering html and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Dont make things complicated if you do not have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching html forms ===<br />
<br />
Since building html forms can take serious amounts of time its a good practice to store build form html in a token property and reuse it as long it doesnt have to be rebuild. Its especially effective if you build complex stuff by accessing lots of property - usually the case if you build character sheets. When creating complex html structures and storing them into a token property you're asking for trouble so its common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you dont like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while a unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have a initially checked checkbox you can set it as checked like this (regardless of beeing predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for learning me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in maptool. They are a great way to precisly align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8933Forms tutorial2020-09-06T21:32:26Z<p>Lwoestman: /* The input fields */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as a key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specify the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressions are evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesn't work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesn't work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''HTML formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to HTML inputs. <br />
To remove the HTML tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so are by using an image table or image tokens. I won't explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It not only sends the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you some kind of event maptool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 maptool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping informations about selected tokens and such.<br />
<br />
To set it up you have to define a html header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And i dont say they do it intentionally.<br />
<br />
So you should protect your macros against trouble making user inputs. For example can a comma inside of an item of a comma separated list break the list.<br />
<br />
So its always always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex html forms can take time ===<br />
<br />
Just be aware of this. Building and rendering html and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Dont make things complicated if you do not have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching html forms ===<br />
<br />
Since building html forms can take serious amounts of time its a good practice to store build form html in a token property and reuse it as long it doesnt have to be rebuild. Its especially effective if you build complex stuff by accessing lots of property - usually the case if you build character sheets. When creating complex html structures and storing them into a token property you're asking for trouble so its common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you dont like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while a unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have a initially checked checkbox you can set it as checked like this (regardless of beeing predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for learning me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in maptool. They are a great way to precisly align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8932Forms tutorial2020-09-06T21:18:17Z<p>Lwoestman: /* About forms */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now let's begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. An HTML page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible HTML in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''MapTool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in MapTool don't support more recent versions of HTML/CSS. Don't blame MapTool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we don't have a submit button and second MapTool doesn't know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, let's call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as a string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm macro).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now let's make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now it's pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specifiy the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressionsare evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesnt work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesnt work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''html formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to html inputs. <br />
To remove the html tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so is by using an image table or image tokens. I wont explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It does not only send the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you some kind of event maptool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 maptool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping informations about selected tokens and such.<br />
<br />
To set it up you have to define a html header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And i dont say they do it intentionally.<br />
<br />
So you should protect your macros against trouble making user inputs. For example can a comma inside of an item of a comma separated list break the list.<br />
<br />
So its always always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex html forms can take time ===<br />
<br />
Just be aware of this. Building and rendering html and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Dont make things complicated if you do not have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching html forms ===<br />
<br />
Since building html forms can take serious amounts of time its a good practice to store build form html in a token property and reuse it as long it doesnt have to be rebuild. Its especially effective if you build complex stuff by accessing lots of property - usually the case if you build character sheets. When creating complex html structures and storing them into a token property you're asking for trouble so its common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you dont like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while a unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have a initially checked checkbox you can set it as checked like this (regardless of beeing predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for learning me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in maptool. They are a great way to precisly align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8931Forms tutorial2020-09-06T21:07:59Z<p>Lwoestman: /* Where can you use forms? */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically wherever html is interpreted you could create a form. But it is really useful to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now lets begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. A html page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible html in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''Maptool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in maptool don't support more recent versions of HTML/CSS. Dont blame maptool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we dont have a submit button and second maptool doesnt know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, lets call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm-macros).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now lets make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now its pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specifiy the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressionsare evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesnt work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesnt work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''html formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to html inputs. <br />
To remove the html tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so is by using an image table or image tokens. I wont explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It does not only send the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you some kind of event maptool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 maptool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping informations about selected tokens and such.<br />
<br />
To set it up you have to define a html header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And i dont say they do it intentionally.<br />
<br />
So you should protect your macros against trouble making user inputs. For example can a comma inside of an item of a comma separated list break the list.<br />
<br />
So its always always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex html forms can take time ===<br />
<br />
Just be aware of this. Building and rendering html and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Dont make things complicated if you do not have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching html forms ===<br />
<br />
Since building html forms can take serious amounts of time its a good practice to store build form html in a token property and reuse it as long it doesnt have to be rebuild. Its especially effective if you build complex stuff by accessing lots of property - usually the case if you build character sheets. When creating complex html structures and storing them into a token property you're asking for trouble so its common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you dont like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while a unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have a initially checked checkbox you can set it as checked like this (regardless of beeing predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for learning me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in maptool. They are a great way to precisly align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Forms_tutorial&diff=8930Forms tutorial2020-09-06T21:05:19Z<p>Lwoestman: /* What is this about? */</p>
<hr />
<div>[[Category:Tutorial]]<br />
<br />
{{Advanced}}<br />
<br />
= HTML forms covered in fish =<br />
<br />
''A tutorial to creating html forms for maptool.''<br />
<br />
== What is this about? ==<br />
<br />
The [[input|input()]] function is a great way to get data from the user. It is simple to use as well. But it limits you in the ways you can design the resulting dialog. You might even miss features like multi-line textboxes. Maybe you want keep a dialog open to send it when you are ready, but still want the other maptool features to work - and not freeze.<br />
<br />
If you can't create the user interaction with [[input|input()]] you have to create an html form. And here I explain to you how to do that.<br />
<br />
But be aware! An input pauses your macro, creates a pop up dialog and creates variables containing the entered data all by itself. With html forms you have to split the process into (at least) two macros and make all that by yourself.<br />
<br />
I assume you know how to write simple macros and create/use lib:tokens. All my code examples will be located on a [[Library Token|lib:token]] named "Lib:token".<br />
<br />
'''NOTE''' I'm not the first one who tried to explain this. There is a nice tutorial on using html frames for creating a character sheet that covers even css embedding and tab page creation: [[Introduction to Dialogs and Frames]].<br />
<br />
== Where can you use forms? ==<br />
<br />
Maptool accepts html in uncountable places and theoretically where ever html is interpreted you could create a form. But really useful is it to place your html form either in a [[dialog (roll option)|dialog]] or a [[frame (roll option)|frame]]. A frame is a dockable window while a dialog is floating above the rest of the UI. A dialog has a close button as default while a frame has no buttons other than those you create there.<br />
<br />
Both commands (or to be more specific: roll options) open some kind of window. Both frames and dialogs are named so when you use code that would open a window, it will update the content of an open window with the same name if that exists.<br />
<br />
You can close dialogs in macro with [[closeDialog|closeDialog()]] and in later versions you can close frames as well ([[closeFrame|closeFrame()]]).<br />
<br />
Lets create a macro "openFrame" so that we can display a form.<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
here will be a fishy form<br />
}]<br />
</source><br />
<br />
For my following examples we will use this slightly changed openFrame-macro:<br />
<source line lang="mtmacro"><br />
[frame("myForm"): {<br />
<h3>my form:</h3><br />
[r, macro("displayForm@Lib:token"): ""]<br />
}]<br />
</source><br />
<br />
And probably you can guess: all the form related code will be placed in a displayForm-macro. So we can forget about opening the frame and concentrate all on forms. Yay.<br />
<br />
== About forms ==<br />
<br />
Now lets begin with that form. HTML supports user editable forms and a good variety of input fields that can be placed in such a form. A html page (your frame for example) can even contain multiple forms (but you'll only receive the content of one of them).<br />
<br />
For general syntax information about the {{code|<form>}}-tag and the input fields I find [[http://www.w3schools.com/html/html/forms.asp w3schools.com]] quite helpful.<br />
<br />
We begin at the start and create a form with two text input fields.<br />
<source line lang="html4strict"><br />
<!-- this example displays correctly but does nothing --><br />
<form><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br />
</form><br />
</source><br />
<br />
Note that you can place all possible html in such a form so you can easily design it any way you want. Create tables, use CSS, fonts, colors, ... '''Maptool only supports HTML3.2 and [[Supported CSS Styles|CSS1]]'''. This is because the java controls being used in maptool don't support more recent versions of HTML/CSS. Dont blame maptool ;)<br />
<br />
While this is pretty handy you don't get the data your user enters yet. First we dont have a submit button and second maptool doesnt know where to send that data.<br />
<br />
If we do it right a form - if submitted - calls another macro, lets call that 'processForm', and passes the entered data as macro.args.<br />
You can receive this data as string property list or as json which I prefer. If you prefer string property lists you have to omit the method field of the form tag (and change the processForm-macros).<br />
<br />
We specify the called macro using [[macroLinkText|macroLinkText()]]. You should not specify the macro.args here as it will interfere with the form data.<br />
<br />
Now lets make my little form work:<br />
<source line lang="mtmacro"><br />
[h: processorLink = macroLinkText("processForm@Lib:token", "all")]<br />
<form action="[r:processorLink]" method="json"><br />
Character name: <input type="text" name="charName"><br><br />
Strength: <input type="text" name="str"><br><br />
<input type="submit" name="myForm_btn" value="Okay"><br />
</form><br />
</source><br />
<br />
And create the processForm-macro.<br />
<source line lang="mtmacro"><br />
<pre><br />
[r: json.indent(macro.args,2)]<br />
</pre><br />
</source><br />
With this setup we can very easily find out how a specific form packs the data entered and how we could work with that. For this tutorial this processForm-macro will do.<br />
<br />
The output we receive from this example is<br />
<source line lang="mtmacro"><br />
{<br />
"charName": "the fishy dude",<br />
"str": "7",<br />
"myForm_btn": "Okay"<br />
}<br />
</source><br />
Now its pretty easy to access the name and strength using [[json.get|json.get()]].<br />
<br />
== The input fields ==<br />
<br />
<br />
Now let me introduce you to the input fields in detail. Some are a little tricky in how they send their data - so there will be advice about that as well.<br />
<br />
In general all input fields should be given a name. This name will be used in the resulting json data as key.<br />
<br />
[[image:Cif_forms_tutorial_example_input_fields.png]]<br />
<br />
=== Text fields ===<br />
<br />
<source line lang="html4strict"><br />
<input type="text" name="" size="" maxlength="" value=""><br />
</source><br />
This is your standard one line text input field. The width of the field can be set with {{code|size}} and the maximum length of the input with {{code|maxlength}}. If you set a {{code|value}} your field will appear filled with that.<br />
<br />
You can have a password type text field as well if you set<br />
<br />
<source line lang="html4strict"><br />
<input type="password" name="" size="" maxlength="" value=""><br />
<br />
</source><br />
<br />
=== Multi line text fields ===<br />
<br />
If you need multiple lines you use<br />
<source line lang="html4strict"><br />
<textarea name="" cols="" rows=""><br />
Enter your text here...<br />
</textarea><br />
</source><br />
You can specifiy the size of that text box with {{code|cols}} and {{code|rows}}. A preset text would be written between the open and closing tags.<br />
<br />
'''TRICK:''' You can process the content of a textarea line by line if you use the following trick. By using [[encode|encode()]] on the complete content you change line breaks into {{code|%0A}}. Then you can use string list functions using {{code|%0A}} as separator.<br />
<br />
As example let me show you a processForm macro that adds all numbers you enter in the textarea - one number per line. Dice expressionsare evaluated.<br />
<source line lang="mtmacro"><br />
[h:'<!-- processForm -->']<br />
[h: formData = macro.args]<br />
[h:'<!-- get the content of a textarea named "textarea" -->']<br />
[h: text = json.get(formData, "textarea")]<br />
[h:'<!-- encode it -->']<br />
[h: text = encode(text)]<br />
[h:'<!-- loop through the content -->']<br />
[h: sum=0]<br />
[h, foreach(line, text, "", "%0A"), code: {<br />
[h:'<!-- decode line again -->']<br />
[h: decodedLine = decode(line)]<br />
[h, if(isNumber(decodedLine):<br />
sum = sum + decodedLine;<br />
sum = sum + eval(decodedLine)<br />
]<br />
}]<br />
[h:'<!-- and output. done. -->']<br />
[r: sum]<br />
</source><br />
<br />
=== Drop down lists ===<br />
<br />
<source line lang="html4strict"><br />
<select name="" size=""><br />
<option>A</option><br />
<option>B</option><br />
<option selected="selected">C</option><br />
</select><br />
</source><br />
'''NOTE''' {{code|multiple}} doesnt work, only one entry appears in the resulting json. Known bug.<br />
<br />
=== Radio buttons ===<br />
<br />
<source line lang="html4strict"><br />
A<input type="radio" name="group1" value="A" checked="checked"><br />
B<input type="radio" name="group1" value="B"><br />
C<input type="radio" name="group1" value="C"><br />
<br />
A<input type="radio" name="group2" value="A" checked="checked"><br />
B<input type="radio" name="group2" value="B"><br />
C<input type="radio" name="group2" value="C"><br />
</source><br />
<br />
=== Checkboxes ===<br />
<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="group1" value="A"> A<br />
<input type="checkbox" name="group1" value="B"> B<br />
<input type="checkbox" name="group1" value="C"> C<br />
<input type="checkbox" name="group1" value="D" checked="checked"> D<br />
</source><br />
'''NOTE''' unchecked boxes don't appear in the json; only checked ones will.<br />
So test if a box is checked by using {{code|json.contains}} on the field name.<br />
<br />
See my [[Forms tutorial#Predefine checkboxes|"Good advice" tip #4]] for another way to treat this (you can predefine the value with a 0-value).<br />
<br />
'''NOTE''' multiple selection doesnt work as well. So do not name the checkboxes alike.<br />
<br />
=== Hidden data ===<br />
<br />
<source line lang="html4strict"><br />
<input type="hidden" name="" value=""><br />
</source><br />
Since you cannot send additional information to your form processor using the args parameter of {{code|macroLinkText}} you have to send it piggyback with the form data. This can be done with invisible fields.<br />
<br />
Unfortunately, assigning a [[JSON Array]] or a [[JSON Object]] as a value can cause the JSON to get mangled. To have it parse properly, a work around is to replace the quote marks {{code|"}} around the value by {{code|'}}; another work around is to encode the json first, and decode it in the {{code|macroLinkText}} macro.<br />
<br />
=== Buttons ===<br />
<br />
<source line lang="html4strict"><br />
<input type="submit" name="" value=""><br />
</source><br />
The button caption is set via the {{code|value}} parameter.<br />
<br />
'''NOTE''' only the pressed button appears in the json. If you use multiple buttons use [[json.contains|json.contains()]] to identify it. Predefining the key/name could probably help (see checkboxes).<br />
<br />
'''NOTE''' You can use '''html formatting''' inside of the button caption (value parameter). You have to enable this by beginning with {{code|<html>}} like this:<br />
<br />
<source lang="mtmacro"><br />
<br />
<input type="submit" value="<html><b>Button</b></html>"><br />
<br />
</source><br />
<br />
You can't apply any kind of CSS to html inputs. <br />
To remove the html tags from the submitted value you can use code like this<br />
<br />
<source line lang="mtmacro"><br />
<br />
[H: submit = json.get(macro.args,"submit")]<br />
[H: submit = replace(submit,"<[^>]*?>","")]<br />
<br />
</source><br />
<br />
=== Image buttons ===<br />
<br />
First you have to get the asset of the image you want to place on a button. Good ways to do so is by using an image table or image tokens. I wont explain that here in more detail.<br />
<source line lang="html4strict"><br />
<input type="image" src="" name="" value=""><br />
</source><br />
<br />
This image button submits the form exactly as a submit button does. As {{code|src}} you have to set an image asset. Note that you cannot used resized assets (using the ASSETxSIZE notation or specifying the size on asset generating function calls).<br />
<br />
It does not only send the button name and value but also the coordinates where you clicked in the image. This could be used for some pretty UI.<br />
<br />
<source line lang="mtmacro"><br />
<!-- this image button pushed .. --><br />
<br />
<input type="image" src="[r:getImage("Image:Attack")]" name="img_btn" value="image button clicked"><br />
<br />
<!-- .. would send this args --><br />
{<br />
"img_btn.value": "image button clicked",<br />
"img_btn.x": "21",<br />
"img_btn.y": "13"<br />
}<br />
</source><br />
<br />
== Events ==<br />
<br />
Since I'll use this in one of my examples (see below) let me very shortly introduce you some kind of event maptool supports and how to set it up. A discussion about this can be found in the [http://forums.rptools.net/viewtopic.php?p=143242#p143242 maptool forums] and a list of events on the [[:Category:Event]] page.<br />
<br />
Maptool macros can react on three events: if a token is changed, if token selection is changed and if impersonation is changed. You can specifiy a macro that is called if one event happens.<br />
<br />
This will work if a frame is open at that moment. The onChangeToken-event is a little bit tricky. First it is fired numerous times and not only if you'd expect it. Second is your macro can change tokens and so fire the event and call itself… what could cause problems.<br />
<br />
The other two events are pretty easy to use and quite handy for dumping informations about selected tokens and such.<br />
<br />
To set it up you have to define a html header and specify a specific link element. So your frame content should begin like this:<br />
<source line lang="html4strict"><br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='macroLink'><br />
</head><br />
<body><br />
</source><br />
Replace {{code|macroLink}} by an actual macroLinkText-call to a macro of your choice. A common practice is to call the frame opening macro itself to actualize the content. the {{code|rel}} parameter is set either {{code|onChangeSelection}}, {{code|onChangeImpersonated}} or {{code|onChangeToken}}.<br />
<br />
== Good advice ==<br />
<br />
=== Always encode user input ===<br />
<br />
It is always wise to trust in the dumbness of users. If they can break things they will. And i dont say they do it intentionally.<br />
<br />
So you should protect your macros against trouble making user inputs. For example can a comma inside of an item of a comma separated list break the list.<br />
<br />
So its always always good to use [[encode|encode()]] on user input (and [[decode|decode()]] to .. well .. decode it again).<br />
<br />
=== Building complex html forms can take time ===<br />
<br />
Just be aware of this. Building and rendering html and collecting and displaying lots of data and images and fields can take serious time. If your frame is updated frequently it could cause speed issues.<br />
<br />
Think about storing calculated frame content, only updating the necessary parts. Reduce the number of updates to the needed minimum. (See Caching)<br />
<br />
Dont make things complicated if you do not have speed issues but be prepared to fight them if you do.<br />
<br />
=== Caching html forms ===<br />
<br />
Since building html forms can take serious amounts of time its a good practice to store build form html in a token property and reuse it as long it doesnt have to be rebuild. Its especially effective if you build complex stuff by accessing lots of property - usually the case if you build character sheets. When creating complex html structures and storing them into a token property you're asking for trouble so its common practice to encode them first before you store them.<br />
It's also best to store character sheets (token specific) onto the (n)pc token and general forms like weapon list, skill list, etc. onto a lib:token<br />
<br />
Here an example of 'caching' a charactersheet. <br />
<br />
<source line lang="mtmacro"><br />
[h: rebuild = macro.args]<br />
[h: id = currentToken()]<br />
[h: output = getProperty("charSheetCache", id)]<br />
<br />
[h, if(rebuild || output == ""), code: {<br />
[h: output = "here you build"]<br />
[h: output = output + "your mega complex character sheet"]<br />
...<br />
[h: output = encode(output)]<br />
<br />
[h:'<!-- though it might be better to define a UDF for that -->']<br />
[h:'<!-- e.g: output = encode(createSheetContent()) -->']<br />
<br />
[h: setProperty("charSheetCache", output, id)]<br />
};{}]<br />
<br />
[frame("Character Sheet"):{<br />
[r: decode(output)]<br />
}]<br />
</source><br />
<br />
<br />
A nice technique to individualize cached forms/html is described here: [http://forums.rptools.net/viewtopic.php?f=20&t=16324&start=0 Making cached structures dynamic (Load BIG forms FAST)]<br />
<br />
=== Don't forget the token context ===<br />
When you work with macrolinks you can easily lose the token context. If you happen to work with explicit ids and get/setProperty() a lot that may be no problem for you.<br />
<br />
However it does change the chat output. If a macrolink is called with unknown token context instead of token image and name the chat line begins with user name.<br />
<br />
If you dont like this always specify the token context in your {{func|macroLink}} and {{func|macroLinkText}} calls.<br />
<br />
An example of this can be found in the [http://forums.rptools.net/viewtopic.php?p=170425#p170425 forum].<br />
<br />
=== Predefine checkboxes ===<br />
<br />
Checkboxes only create data in macro.args if they are checked. There is a neat trick to always create the relevant data even if it is unchecked.<br />
Predefine the key/value-pair using a hidden input with a 0 (of course you have to use the same name as your checkbox has). A checked checkbox will overwrite a predefined 0 while a unchecked checkbox (as it does not generate anything) won't overwrite a predefined 1.<br />
<br />
If you want to have a initially checked checkbox you can set it as checked like this (regardless of beeing predefined or not)<br />
<source line lang="html4strict"><br />
<input type="checkbox" name="surprised" value="1" checked="checked" /><br />
</source><br />
Big thanks to wolph42 for learning me this.<br />
<br />
=== Don't shy away from layout tables ===<br />
<br />
In webdesign layout tables might be a no-go. Don't be afraid of them in maptool. They are a great way to precisly align your form elements. Let me demonstrate how different a simple layout table looks compared to a very simplistic inline approach.<br />
<br />
[[Image:Cif forms tutorial example layout table.png]]<br />
<br />
<source line lang="mtmacro"><br />
[frame("test"): {<br />
<br />
<h3>this is ugly</h3><br />
Value <input type="text" size="5" /><br><br />
Option1<input type="checkbox" /><br><br />
Option2<input type="checkbox" /><br><br />
<input type="submit"><br><br />
<br />
<h3>this is pretty</h3><br />
<table><br />
<tr><br />
<td>Value</td><br />
<td><input type="text" size="5" /></td><br />
</tr><br />
<tr><br />
<td>Option1</td><br />
<td><input type="checkbox" /></td><br />
</tr><br />
<tr><br />
<td>Option2</td><br />
</td><input type="checkbox" /><br />
</td><br />
<tr><br />
<td colspan="2"><input type="submit" /></td><br />
</tr><br />
</table><br />
<br />
}]<br />
</source><br />
<br />
== The big examples ==<br />
<br />
=== Character sheet/editor ===<br />
<br />
Lets create an character sheet and editor for the [[Sample Ruleset|maptool sample ruleset]] using what we learned so far.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example1.png]]<br />
<br />
First we need a frame. We want it to auto-update with the selected content. We pass the selected tokens to the character sheet generating macro so we know what do display.<br />
<br />
We want more eyecandy, so we will use css. As we like separating css rules from the content we will place it in its own macro.<br />
<br />
'''openCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: link = macroLinkText("openCharacterSheet@Lib:token", "none")]<br />
[frame("csheet"): {<br />
<html><br />
<head><br />
<link rel="onChangeSelection" type="macro" href="[r:link]"><br />
<link rel="stylesheet" type="text/css" href="css@Lib:token"></link><br />
</head><br />
<body><br />
[r, macro("characterSheet@Lib:token"): getSelected()]<br />
</body><br />
</html><br />
}]<br />
</source><br />
<br />
'''css'''<br />
<source line lang="css"><br />
.odd { background-color: #FFFFFF }<br />
.even { background-color: #EEEEAA }<br />
th { background-color: #113311; color: #FFFFFF }<br />
</source><br />
<br />
Then we have to actually build the character sheet. Since selection will cause this to be called we have to deal with empty and multiple selections. We'll just don't create any output then.<br />
<br />
'''characterSheet'''<br />
<source line lang="mtmacro"><br />
[h: id = macro.args]<br />
[r, if(listCount(id)!=1), code: {};{<br />
<br />
[h: link = macroLinkText("editCharacterSheet@Lib:token", "all")]<br />
<form action="[r:link]" method="json"><br />
<input type="hidden" name="id" value="[r:id]"><br />
<h1>[r:getName(id)]</h1><br />
<br />
<table width="*"><br />
<tr><br />
<th colspan="2">Primary Attributes</th><br />
</tr><br />
<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td><input type="text" name="[r:attrib]" value="[r:getProperty(attrib, id)]" size="3" align="right"></td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
<br />
<tr><br />
<th colspan="2">Secondary Attributes</th><br />
</tr><br />
[h: attributes = "Hit Points, Armor, Movement"]<br />
[h: row = "odd"]<br />
[r, foreach(attrib, attributes, ""), code: {<br />
<tr class="[r:row]"><br />
<td><b>[r:attrib]:</b></td><br />
<td>[r:getProperty(attrib, id)]</td><br />
</tr><br />
[h: row = if(row=="odd", "even", "odd")]<br />
}]<br />
[h: classes = "Warrior, Rogue, Wizard, Priest"]<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<tr class="[r:row]"><br />
<td><b>Class:</b></td><br />
<td><br />
<select name="CharClass" size="1"><br />
[r, foreach(c, classes, ""), code: {<br />
<option [r, if(c==CharClass): "selected"]>[r:c]</option><br />
}]<br />
</select><br />
</td><br />
</tr><br />
<br />
<input type="submit" name="edit_btn" value="Submit changes"><br />
</form><br />
}]<br />
</source><br />
<br />
If the submit button is pressed we want to save the changes back to the token.<br />
<br />
'''editCharacterSheet'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args] <br />
[h: id = json.get(arguments, "id")]<br />
<br />
[h:'<!-- set primary attributes -->']<br />
[h: attributes = "Strength, Dexterity, Intelligence, Endurance"]<br />
[h, foreach(attrib, attributes), code: {<br />
[h: val = json.get(macro.args, attrib)]<br />
[h, if(! isNumber(val)): val=eval(val)]<br />
[h:'<!-- allowed values are 1..6 -->']<br />
[h: val = min(max(val,1), 6)]<br />
[r: setProperty(attrib, val, id)]<br />
}]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
[h: setProperty("Class", json.get(macro.args, "CharClass"), id)]<br />
[h: setProperty("Movement", getProperty("Dexterity",id), id)]<br />
<br />
[h: CharClass = getProperty("CharClass", id)]<br />
<br />
[h, switch(CharClass):<br />
case "Warrior": val=6;<br />
case "Rogue": val=2;<br />
case "Wizard": val=1;<br />
case "Priest": val=4;<br />
default: val=0<br />
]<br />
[h: setProperty("Armor", val, id)]<br />
<br />
[h: setProperty("Hit Points", 6*getProperty("Endurance",id), id)]<br />
<br />
Changes saved to [r: getName(id)].<br />
[h, macro("openCharacterSheet@Lib:token"): id]<br />
</source><br />
<br />
If you'd want to play with this you'd surely come up with lots of improvements .. great! I would as well. But this should be enough to demonstrate building a character sheet or editor with html forms.<br />
<br />
'''Download''' this example:[http://www.bastian-dornauf.de/example1.rptok example1.rptok](token is saved with b73) Drop this libtoken into an empty map and toy around with it.<br />
<br />
=== Click-based Target selection ===<br />
<br />
There are very differen ways how to select targets of an action. The clickbased targeting (first done by Rumble) works best in maptool version b70 or later with the "unowned selection" feature.<br />
<br />
<br />
[[image:Cif_forms_tutorial_screenshot_example2.png]]<br />
<br />
You impersonate or select the active token. Then you execute a macro, eg "Attack" that opens a frame. In that frame you can enter additional infos like modifier. While that frame is open you select ((with the mouse on the map)) the target(s) of the attack. The frame has a button that actually performs the attack.<br />
<br />
Lets start with the macro that opens that frame.<br />
<br />
'''openActionFrame'''<br />
<br />
This macro first determines what token should be considered the ''active'' token. A token impersonated would be preferred. Otherwise the selection is taken. If no or multiple tokens are selected the macro us aborted.<br />
<br />
Then the macro checks if the user has the right to perform actions with that token - he has if he is GM or own the token.<br />
<br />
After that the current selection is cleared and the frame displaying code is called.<br />
<br />
If you have different actions to perform here would the place to branch into different actionFrames according to the chosen action.<br />
<br />
<source line lang="mtmacro"><br />
[h: chosenAction = macro.args]<br />
[h, if(hasImpersonated()): activeId = getImpersonated(); activeId = getSelected()]<br />
[h, if(listCount(activeId)!=1): assert(0, "You have to select only one token")]<br />
[h: gm = isGM()]<br />
[h: owned = isOwner(getPlayerName(), activeId)]<br />
[h, if(gm || owned): ""; assert(0, "You have no right to act with this token.")]<br />
[h: deselectTokens()]<br />
<br />
[h:'<!-- call right actionFrame for chosenAction -->']<br />
[r, macro("actionFrame@Lib:tkn"): activeId]<br />
</source><br />
<br />
<br />
Now we need a way for the user to call this macro. This can be either a campaign or a token macro - depending on your taste.<br />
<br />
'''Attack'''<br />
<br />
<source line lang="mtmacro"><br />
[r, macro("openActionFrame@Lib:token"):"Attack"] <br />
</source><br />
<br />
''Note'' that I send {{code|"Attack"}} to the frame opening macro and that this is placed in a variable named {{code|chosenAction}}. It is never used. If you want to support different actions (like ranged and melee attacks) you could, right after the comment, branch - depending on {{code|chosenAction}} - into different actionFrame.<br />
<br />
'''actionFrame'''<br />
This is pretty simple. It shows a frame and uses the {{code|onChangeSelection}}-event to display the targets.<br />
<br />
<source line lang="mtmacro"><br />
[h: activeId = macro.args]<br />
[h: selection = getSelected()]<br />
[h: link = macroLinkText("actionFrame@Lib:tkn", "none", activeId)]<br />
[h: perform= macroLinkText("performAction@Lib:tkn", "all")]<br />
[frame("Action"): {<br />
<html><br />
<head><br />
<link rel='onChangeSelection' type='macro' href='[r:link]'><br />
</head><br />
<body><br />
<b>Attacker:</b><br><br />
[r, token(activeId): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
<br><br />
<b>Targets:</b> <br><br />
[r, foreach(id, selection, " "), code: {<br />
[r, token(id): strformat("<img src='%s' alt='%s'>", getTokenImage(50), getName())]<br />
}]<br />
<form action="[r:perform]" method="json"><br />
<input type="text" name="mods" value="0"><br><br />
<input type="submit" name="btn_submit" value="Perform action"><br />
<input type="hidden" name="id" value="[r:activeId]"><br />
<input type="hidden" name="targets" value="[r:selection]"><br />
}]<br />
</source><br />
<br />
'''performAction'''<br />
<source line lang="mtmacro"><br />
[h: arguments = macro.args]<br />
[h: id = json.get(arguments, "id")]<br />
[h: targets = json.get(arguments, "targets")]<br />
[h, if(listCount(targets)<1): abort(0)]<br />
[h:'<!-- target and performer could be the same -->']<br />
[h:'<!-- target could be one or many -->']<br />
<br />
[h:'<!-- roll the attack -->']<br />
<b>Melee attack:</b><br><br />
[r, foreach(target, targets, "<br>"), code: {<br />
<b>[r: getName(id)]</b> rolls<br />
[r, token(id): rollResult = 1d20 + Strength]<br />
[r, if(rollResult>=15), code: {<br />
and hits <b>[r:getName(target)]</b> for<br />
[r: dmg = 1d6 + getProperty("Strength", id) - getProperty("Armor", target)]<br />
points of damage.<br />
[h: setProperty("Hit Points", getProperty("Hit Points", target) - max(0,dmg), target)]<br />
};{and misses [r:getName(target)]}]<br />
}]<br />
</source><br />
This macro does the actual attack. The attacker and the targets are submitted via {{code|macro.args}}. The rest is the usual dice rolling and comparing to target numbers and stuff...<br />
<br />
Again this could be done better. It doesnt modify the roll by the entered mods. It does not even model the sample ruleset right. You'd want to support attack powers and maybe set states for being wounded or dead.<br />
<br />
But it demonstrates how to target .. the rest is up to you.<br />
<br />
'''Download''' a lib token for this example [http://www.bastian-dornauf.de/example2.rptok example2.rptok] (token is saved with b73)</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=json.path.set&diff=8925json.path.set2020-09-05T22:38:32Z<p>Lwoestman: </p>
<hr />
<div>{{MacroFunction<br />
|name=json.path.set<br />
|version=1.5.5<br />
|description=<br />
Change an element in a nested [[JSON Array]]. Additional information on how to specify the path is available [https://github.com/json-path/JsonPath here].<br />
<br />
|usage=<br />
<source lang="mtmacro" line><br />
json.path.set(json, path, value)<br />
</source><br />
<br />
'''Parameters'''<br />
{{param|json|The json element in which the [[JSON Array]] is nested.}}<br />
{{param|path|The path to the element in the [[JSON Array]].}}<br />
{{param|value|The value to change.}}<br />
<br />
<br />
|examples=<br />
Suppose we have the following nested json:<br />
<source lang="mtmacro" line><br />
[h:troll = json.set("{}", "name", "Troll", "HP", 75, "Attacks", json.append("Claw", "Bite"))]<br />
[h:orc = json.set("{}", "name", "Orc", "HP", 13, "Attacks", json.append("Sword", "Punch"))]<br />
[h:monsters = json.set("{}", "Troll", troll, "Orc", orc)]<br />
</source><br />
<br />
To replace the Punch to an Axe, we can run<br />
<br />
<source lang="mtmacro" line><br />
[monsters = json.path.set(monsters, "Orc.Attacks.[1]", "Axe")]<br />
</source><br />
<br />
To change all "Sword" attacks to "Greatsword", we can run<br />
<br />
<source lang="mtmacro" line><br />
[monsters = json.path.set(monsters, "*.Attacks[?(@ == 'Sword')]", "Great Sword")]<br />
</source><br />
<br />
}}<br />
<br />
[[Category:JSON Function]]<br />
[[Category:JSON Path Function]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=matches&diff=8918matches2020-09-02T01:06:19Z<p>Lwoestman: </p>
<hr />
<div>{{MacroFunction<br />
|name=matches<br />
|version=1.3b48<br />
|description=<br />
Returns 1 if a string matches pattern or 0 if it does not. The pattern can be a [[Macros:regular expression|regular expression]]. Matches performs a while string comparison, so the pattern must match the whole of the input string and not only part of it.<br />
<br />
|usage=<br />
<source lang="mtmacro" line><br />
matches(str, pattern)<br />
</source><br />
<br />
|examples=<br />
<source lang="mtmacro" line><br />
[r: matches("This is a test", "test")]<br />
[r: matches("test", "test")]<br />
[r: matches("This is a test", ".*test")]<br />
<br />
</source><br />
Returns <br />
<pre><br />
0<br />
1<br />
1<br />
</pre><br />
}}<br />
[[Category:String Function]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=getMatchingProperties&diff=8917getMatchingProperties2020-09-02T00:58:56Z<p>Lwoestman: </p>
<hr />
<div>{{MacroFunction<br />
|name=getMatchingProperties<br />
|version=1.3b54<br />
|description=<br />
Returns a [[String List]] or [[JSON Array]] with names of the [[Token Property|Token Properties]] on a specific [[Token]] that match the given pattern.<br />
<br />
|usage=<br />
<source lang="mtmacro" line><br />
getMatchingProperties(pattern)<br />
getMatchingProperties(pattern, delim)<br />
getMatchingProperties(pattern, delim, id)<br />
getMatchingProperties(pattern, delim, id, mapname)<br />
</source><br />
'''Parameters'''<br />
{{param|pattern|A [[Macros:regular_expression|regular expression(regex)]] that represents the pattern the properties should match.}}<br />
{{param|delim|The delimiter used in the [[String List]] that is returned, defaults to {{code|","}}. Returns a [[JSON Array]] if {{code|"json"}} is specified.}}<br />
{{param|id|The token {{code|id}} of the token that is checked for properties that match the given pattern, defaults to the [[Current Token]]. {{TrustedParameter}} }}<br />
{{param|mapname|The name of the map to find the token. Defaults to the current map.}}<br />
<br />
|examples=<br />
Say you wanted to keep an inventory list for the [[Token]] you could prefix all of your inventory properties with {{code|Inv:''Category'':}}. For example {{code|Inv:Weapon:Longsword}}.<br />
<br />
Then to loop through all of the inventory properties you could use <br />
<source lang="mtmacro" line><br />
[foreach(item, getMatchingProperties("Inv:.*")): {<br />
<!-- Do something really exciting here --><br />
}]<br />
</source><br />
<br />
Or the following to loop through all the weapons<br />
<source lang="mtmacro" line><br />
[foreach(item, getMatchingProperties("Inv:Weapon:.*")): {<br />
<!-- Do something really exciting here --><br />
}]<br />
</source><br />
<br />
Or even all the armor and all the shields.<br />
<source lang="mtmacro" line><br />
[foreach(item, getMatchingProperties("Inv:(Armor|Shield):.*")): {<br />
<!-- Do something really exciting here --><br />
}]<br />
</source><br />
<br />
<br />
|also=<br />
{{func|getMatchingLibProperties}} {{func|getPropertyNames}}<br />
<br />
|changes=<br />
{{change|1.5.4|Added {{code|mapname}} parameter option.}}<br />
<br />
}}<br />
[[Category:Property Function]][[Category:Token Function]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Introduction_to_Properties&diff=8914Introduction to Properties2020-08-26T21:00:59Z<p>Lwoestman: /* Moving On from Here */</p>
<hr />
<div>{{Languages|Introduction to Properties}}{{Beginner}}<br />
==Campaign Properties==<br />
<br />
One of the most useful features in MapTool is the capability of [[Introduction_to_Tokens|tokens]] to carry around a set of '''Properties''', attached to that token, that can be manipulated by macros and can be used to create quick displays of information. Basically, token properties are like built-in character sheets.<br />
<br />
However, because they are so useful, the MapTool developers have created many different ways to use them and manipulate them. This guide will address creating Campaign Property Sets, setting them to have default values, and using them to manipulate the Statsheet.<br />
<br />
==The Sample Ruleset, or MTRPG==<br />
<br />
In order to have useful examples as we move through this tutorial, several MapTool users and contributors developed the [[Sample Ruleset]] -- a simple roleplaying game system developed specifically to illustrate parts of MapTool. For this guide, we're going to call these rules the MapTool RPG - or MTRPG for short, and what we're going to do is create a new Campaign File and set up some ''campaign properties'' that correspond to attributes of the MTRPG.<br />
<br />
==The Campaign Properties Window==<br />
<br />
[[Image:Edit-campaign-props.png|thumb|The Edit Menu, showing the Campaign Properties option]]<br />
<br />
To get started with Campaign Properties, the first thing you'll need to do is go to '''Edit > Campaign Properties''', and open the Campaign Properties window. In this window, you'll see several tabs and a whole lot of information.<br />
<br />
When you open up the '''Campaign Properties''' window, you'll see it has six tabs. Briefly, they are:<br />
<br />
* '''Token Properties''': this houses all the property sets that a token in the current campaign may have<br />
* '''Repositories''': this is where you can designate an online "[[Introduction to Campaign Repositories |repository]]" to hold campaign files, especially images, to improve load times and speed when you host or play an online game<br />
* '''Sight''': this tab is where you configure the settings for vision in the current campaign<br />
* '''Light''': this tab is where you configure light sources and auras for the current campaign<br />
* '''States''': this tab lets you configure [[Token:state|token states]] for the current campaign<br />
* '''Bars''': this is where you configure [[bar.name|token bars]] for the current campaign<br />
<br />
At the bottom of the window are buttons to Import, Export, and Import Predefined Campaign Properties.<br />
* '''Import''': this button will allow you to load an exported set of Campaign Properties replacing the current set. Campaign Properties files have a .mtprops extension.<br />
* '''Export''': this button will allow you to export the current set of Campaign Properties.<br />
* '''Import Predefined''': this button will load the property set selected in the drop-down menu to the right. '''[Added in 1.6.0]'''<br />
<br />
This guide will only address the first tab, '''Token Properties'''.<br />
<br />
==The Token Properties Tab==<br />
<br />
[[Image:Camp-props.png|thumb|The '''Token Properties Tab''' in Campaign Properties]]<br />
<br />
The first visible tab is the Token Properties tab. This appears relatively uncomplicated, but it's home to some really nifty potential. There are 3 text fields in this tab:<br />
<br />
* '''Name:''' this is the name of the property set you're currently viewing. When you open the campaign properties window, this is blank.<br />
* '''Token Type:''' this column on the left side is not editable, but it will list the names of all the available property sets, or Token Types, defined in the current campaign. If you have no campaign loaded, the only entry will be '''Basic'''<br />
* A large text area where you enter the properties for the current campaign. It will be blank when first loaded, but if you select a property set from the '''Token Type''' list on the left side, you will see the names and default values of the properties in that set.<br />
<br />
===Token Type===<br />
<br />
In this field, you'll see the names of the different "Property Types" (you can think of them as property ''sets'') that are configured in the current campaign. If you have no campaign loaded, the default property set will be called ''Basic''. The '''Token Type''' field is not directly editable by the user.<br />
<br />
===Name===<br />
<br />
This is a simple text field where you can enter the name you want to give the property set. This name will, when you update the set, appear in the '''Token Type''' list to the left, and it becomes the name for that particular set of properties. Names can be anything you like; many users create sets called "NPC" for games where NPC stats and traits differ from those of player characters, for example.<br />
<br />
===Properties===<br />
<br />
This is where it gets funky. In this text area, you can create any and every property you can think of, which can reflect every possible number or statistic an RPG character might have (and many properties that they don't have -- lots of users create properties that are useful for when they write macros, but wouldn't appear on any character sheet!).<br />
<br />
==Creating Properties==<br />
<br />
===Properties with No Default Value===<br />
<br />
[[Image:Basic-default-props.png|thumb|The default set of properties in the Basic property set]]<br />
<br />
If you look at [[Sample_Ruleset#Primary_Attribute|MTRPG's Primary Attributes]], you will see that there are four separate attributes that are the basic attributes of a character: ''Strength'', ''Dexterity'', ''Intelligence'', and ''Endurance''. We're going to get rid of the default properties, and put new ones in their place. <br />
<br />
1. Go to '''Edit > Campaign Properties'''. You'll see in the left side, under ''Token Type'', that the only entry is "Basic." We're going to create a new property set.<br />
<br />
2. In the '''Token Type''' list on the left, select ''Basic''. When you do this, you'll see a whole bunch of properties with all kinds of symbols like @, #, and so forth. <br />
<br />
3. In the text area with all the properties, use your mouse to highlight them all, and hit Delete on your keyboard. Go ahead - don't be shy!<br />
<br />
4. Leave the '''Name''' field alone - MapTools must always have a ''Basic'' property set, so you can't change that name.<br />
<br />
[[Image:Default-props-replaced.png|thumb|The default properties have been deleted, and replaced by the four Primary Attributes of MTRPG]]<br />
<br />
5. In the text area below the '''Name''' field, enter the name of each of the four Primary Attributes in MTRPG, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength<br/><br />
Dexterity<br/><br />
Intelligence<br/><br />
Endurance</tt></blockquote><br />
<br />
When done, your properties window should look like the screenshot on the right. <br />
<br />
6. Once you've finished entering the properties you want, click the button labeled '''Update'''. Don't panic! The properties will disappear, but if you select the ''Basic'' list from the left, your properties will reappear in the main text area.<br />
<br />
7. Click '''OK''' to confirm all of your changes and close the '''Campaign Properties''' window. <br />
<br />
8. Go to '''File > Save Campaign As''' and save your campaign as '''MTRPG.cmpgn'''. You've now created a new campaign file, with a new set of campaign properties. <br />
<br />
When you create properties like this -- just listing the values one after the other -- and then open a token, you will see that these properties have no value. That does not mean that they are equal to zero, or equal to a blank line - they literally have ''no value''. This doesn't mean much for most purposes, but it is an important distinction in macro writing terms (in programming, there's a big difference between a blank string, and an actually ''empty'' variable!). <br />
<br />
Once properties are updated, all of the tokens on the map will be updated with the new properties, and any new tokens you drop on the map will "inherit" the properties you set up.<br />
<br />
<div><br />
<p style="background-color:yellow; padding:5px"><br />
'''NOTE''': While Property names can have spaces in them, this can make accessing and using those properties in Macros difficult. If you have a property called "Hit Points", it is generally better to enter it as ''HitPoints'' without the space.<br />
</p><br />
</div><br />
<br />
===Creating Properties with Default Values===<br />
<br />
[[Image:Newprops-defvalues.png|thumb|The MTRPG properties now have default values]]<br />
<br />
Now, in MTRPG, the minimum value an attribute can have is 1. So, it makes sense to set the ''default value'' of these properties to 1 (that way, every new token will at least have the minimum value an attribute can have). To do this:<br />
<br />
1. Open the Campaign Properties window.<br />
<br />
2. Select the ''Basic'' property set.<br />
<br />
3. In the Basic Properties set, edit your properties so they now read (see the image, as well):<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength:1<br><br />
Dexterity:1<br><br />
Intelligence:1<br><br />
Endurance:1<br></tt><br />
</blockquote><br />
<br />
4. Click '''Update'''.<br />
<br />
By placing a colon at the end of the name of each attribute, and putting the number 1 after the colon, you have instructed MapTool that the default value for those properties is 1 (in other words, whatever value you put after the colon becomes the ''default value'' for that property). You'll note that at the bottom of the Token Properties tab there is a key describing the various options you can set on a property.<br />
<br />
Now, if you drag a new token onto the map and look at its properties (double-click on the token and go to the Properties Tab in the '''Edit Token''' dialog), you will see that the new token has the default values. <br />
<br />
By the way: don't worry about any tokens you may have already set the property values on - setting up or changing the default values will ''not'' override the properties you've already set. MapTool is smart enough to handle that.<br />
<br />
===Displaying Properties in the Statsheet===<br />
<br />
[[Image:Statsheet-props.png|thumb|The Statsheet showing the campaign properties you've set up. You'll see how to make these appear in this section]]<br />
<br />
MapTool has a neat feature called the '''Statsheet''', which is briefly mentioned in the [[Introduction to Tokens]] - basically, it is an automatic popup that appears in the lower left corner of the map, when you hover over a token. <br />
<br />
You may be saying, "Wait...when I hover over my token, there's no statsheet! Where is it?" The reason you don't see it yet is that the Statsheet is governed by the Campaign Properties - it displays the token's properties (along with a larger version of the token's image) - but ''only'' when a couple requirements are met:<br />
<br />
* The properties are set up to display on the statsheet; and<br />
* The properties that are displayed actually have a value<br />
<br />
====Setting Properties to Display====<br />
<br />
[[Image:Newprops-visible.png|thumb|Note the asterisk in front of each property name, enabling that property to appear on the Statsheet]]<br />
<br />
If you look at the bottom of the '''Token Properties''' tab in the '''Campaign Properties''' dialog, you'll see a key showing how to set up a property to display in the Statsheet. There are three display options, each of which is indicated by putting a symbol in front of the property name:<br />
<br />
# '''<nowiki>*</nowiki>''': an asterisk means "show this property on the statsheet"<br />
# '''@''': means "only show this property to the owner of the token (and the GM)"<br />
# '''<nowiki>#</nowiki>''': means "only show this property to the GM (not even the token owner can see it)"<br />
<br />
The asterisk is '''required''' for any stat to display at all - if you don't have an asterisk first, it won't show no matter what else you put on there. The @ and # symbols, on the other hand, are optional. <br />
<br />
So, for our new game, we're going to set all of the properties to be visible to everyone (by just using a star). To do this, open up your properties, and edit them to look like this:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br></tt><br />
</blockquote><br />
<br />
Now, when you hover over a token, you'll see the Statsheet pop up (see the screenshot, above) with the values in the Strength, Dexterity, Intelligence, and Endurance properties. Also, since even brand new tokens have a default value, the Statsheet will appear for all tokens.<br />
<br />
====Short Names====<br />
<br />
[[Image:Newprops-shortnames.png|thumb|The campaign properties now have Short Names established for each]]<br />
<br />
Sometimes, property names can get pretty long (or look unfriendly - no spaces, and all that). MapTool lets you put a ''Short Name'' in for each property. To do that, you just enter the short name in parentheses after the property name, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength(Str):1<br><br />
*Dexterity(Dex):1<br><br />
*Intelligence(Int):1<br><br />
*Endurance(End):1<br></tt><br />
</blockquote><br />
<br />
These short names are displayed in the Statsheet instead of the full name of the property. There is no limit on length of the ''Short Name'' but the purpose is to have a more presentable name on the Statsheet.<br />
<br />
'''Short Names are for display purposes only - when referencing properties in macros, you must use the full property name.'''<br />
<br />
===Creating Derived Properties===<br />
<br />
[[Image:Newprops-derived.png|thumb|The properties ''HitPoints'' and ''Movement'' now have macro code instructing MapTool to derive them from other, existing properties]]<br />
<br />
[[Image:Statsheet-with-allnewprops.png|thumb|The Statsheet showing all of the properties, including the derived ones]]<br />
<br />
Okay, now let's do something pretty cool. In a lot of roleplaying games, there are character attributes that are derived from other stats - for instance, in the ''Savage Worlds'' rules, your "Parry" stat is based on your ''Fighting'' ability; likewise, in Dungeons & Dragons, your "Hit Points" are derived partly from your "Constitution" score. <br />
<br />
Now, you could create these other derived attributes as separate properties and manually enter the values in when you make a new token - but how about we allow MapTool to calculate these derived values? That's right - MapTool's campaign properties can not only be numbers and text, but also calculations and equations based on other properties that the token has. <br />
<br />
In MTRPG, there are three ''derived'' stats: Hit Points, Armor, and Movement. These stats have the short names "HP", "AR," and "MV." For this example, we're going to set up ''Hit Points'' and ''Movement'' to be calculated from existing properties. We'll leave Armor until later (it takes a bit more complex a calculation to figure out the armor value, and we're taking it slow). <br />
<br />
First, we need to add properties for these three derived values:<br />
<br />
1. Open up the Basic property set. <br />
<br />
2. Beneath ''Endurance'', enter the following:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP)<br><br />
*Armor(AR)<br><br />
*Movement(MV)<br></tt><br />
</blockquote><br />
<br />
You'll notice at this point, we've set no default values. Don't hit '''Update''' just yet - let's enter some macro code to create a derived value.<br />
<br />
We can see from the [[Sample Ruleset|MTRPG]] rules that ''Hit Points'' is equal to the value of ''Endurance'' multiplied by 6. Replicating this calculation in the campaign properties is very simple. Edit the ''Hit Points'' property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP):{Endurance * 6}</tt><br />
</blockquote><br />
<br />
What we've done here is enter a default value for the property (remember, default values are whatever comes after the colon), and used some [[Introduction to Macro Writing|macro code]] to instruct MapTool to perform a calculation in order to find the value for the properties. Two thing are happening here:<br />
<br />
# We've enclosed the calculations in { }, which warns MapTool that the text enclosed inside the brackets is to be handled like a macro, and not just plain text<br />
# Inside the brackets, we've said, "Find the value of the ''Endurance'' property, multiply it by 6, and make that result the value of the ''Hit Points'' property"<br />
<br />
Now, to handle the ''Movement'' attribute, our job is even simpler: we need to instruct MapTool to get the value of the ''Dexterity'' property, and assign that same value to the ''Movement'' property. To do so, edit the Movement property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Movement(MV):{Dexterity}</tt><br />
</blockquote><br />
<br />
When you are finished, your full property set should look like:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br><br />
*HitPoints(HP):{Endurance * 6}<br><br />
*Armor(AR)<br><br />
*Movement(MV):{Dexterity}<br></tt><br />
</blockquote><br />
<br />
And when you hover your mouse over a token, the Statsheet should look like the screenshot to the right. Remember, even though we've said that ''Armor'' should be displayed on the statsheet, the statsheet only shows properties that have a value - ''Armor'' is still empty, so it won't show up until you give it a value.<br />
<br />
==Saving Your Campaign==<br />
<br />
At this point, you've created a bunch of campaign properties, placed a token on the map, and messed around with manipulation of the properties you made. You should probably save your work in a ''Campaign'' file. This will save the tokens, properties you created, and all the information you put into the campaign so far. <br />
<br />
Also, this will let you work on the campaign further, trying tricks from the other MapTool tutorials.<br />
<br />
To save your campaign:<br />
<br />
# Go to '''File -> Save Campaign As...'''<br />
# In the dialog, enter a file name. Something like '''MTRPG.cmpgn''' is good!<br />
# Click '''OK'''<br />
<br />
Your campaign will now be saved, and you can open it up whenever you feel like it, and work on it some more!<br />
<br />
Please note that campaigns saved in one version of MapTool will not open properly in an ''older'' version of MapTool; however most campaign files created in an older version can be opened in the newest version (this isn't guaranteed, though...MapTool is evolving at all times!)<br />
<br />
==Some Technical Details==<br />
<br />
A couple of times in this guide and in other guides the token properties have been described as "those properties that are ''visible''" in this campaign, or the properties set up "''for this campaign''." There's a reason for phrasing it like this. <br />
<br />
See, a token - if you cut one open and looked at its inner workings - is an XML file that contains a ''ton'' of information. It has information about its image, its size, its vision, light, shape, and - of course - its properties. What's important to understand here is that the token will remember not only the properties from the MTRPG, but if it was ever saved as an '''.rptok''' file or brought in from another campaign file, it will remember the properties from that campaign too. They won't be visible, but they're stored in the token even so. <br />
<br />
So, in reality, a set of Campaign Properties really indicates those properties that:<br />
<br />
* You can see if you open up a token by double-clicking on it, and<br />
* You can directly edit by clicking in the cell next to them<br />
<br />
This may sound like a recipe for disaster - what if you set up a property that was already set up but is hidden? Fortunately, MapTool will not, when running a macro, attempt to access any hidden properties unless you ''specifically'' instruct it to do so, using two special macro functions. So rest assured, you cannot accidentally access a property that's not set up in the Campaign Properties.<br />
<br />
In summary, if a Property Type (such as the default ''Basic'' property type) has a property named '''HP''', it will be stored in the token under the XML name '''HP'''. If another property type (such as a user-defined ''Pathfinder'' property type) also has a property named '''HP''', they will both be referencing the same data on the token. Modifying the value of '''HP''' when the token is ''Basic'' and then changing the token ''Pathfinder'' will show the same value for '''HP'''.<br />
<br />
==Moving On from Here==<br />
<br />
MapTool supports very elaborate properties and derived properties, with a number of math functions and operations. A couple of the most common ones you might want to use are (the examples are not necessarily part of MTRPG; they're just examples):<br />
<br />
* '''Basic math operators''': addition (+), subtraction (-), multiplication (*), and division (/)<br />
** '''Example''': <tt>HitPoints: {Endurance * 6}</tt><br />
* '''Rounding''': there are some ''functions'' to let you round numbers when you divide<br />
** '''Floor''': the floor() function rounds ''down''. '''Example''': <tt>HitPoints:{floor(Constitution / 2)}</tt> would divide Constitution by two, and round down<br />
** '''Ceiling''': the ceil() function works like floor(), but rounds up. '''Example''': <tt>HitPoints:{ceil(Constitution/2)}</tt><br />
<br />
You ''can'' execute macros from properties. However, if there is an error, then it is possible to get into a sort of "infinite loop", so be sure to save frequently if you're going to try that approach. You might want to have a macro that is called from the property definition. That lets you test the macro without using the property and thus avoid the above infinite loop. When it has been tested thoroughly, then you can invoke it from the property.<br />
[[Category:MapTool]][[Category:Tutorial]]<br />
{{Languages|Introduction to Properties}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Introduction_to_Properties&diff=8913Introduction to Properties2020-08-26T20:59:39Z<p>Lwoestman: /* Moving On from Here */</p>
<hr />
<div>{{Languages|Introduction to Properties}}{{Beginner}}<br />
==Campaign Properties==<br />
<br />
One of the most useful features in MapTool is the capability of [[Introduction_to_Tokens|tokens]] to carry around a set of '''Properties''', attached to that token, that can be manipulated by macros and can be used to create quick displays of information. Basically, token properties are like built-in character sheets.<br />
<br />
However, because they are so useful, the MapTool developers have created many different ways to use them and manipulate them. This guide will address creating Campaign Property Sets, setting them to have default values, and using them to manipulate the Statsheet.<br />
<br />
==The Sample Ruleset, or MTRPG==<br />
<br />
In order to have useful examples as we move through this tutorial, several MapTool users and contributors developed the [[Sample Ruleset]] -- a simple roleplaying game system developed specifically to illustrate parts of MapTool. For this guide, we're going to call these rules the MapTool RPG - or MTRPG for short, and what we're going to do is create a new Campaign File and set up some ''campaign properties'' that correspond to attributes of the MTRPG.<br />
<br />
==The Campaign Properties Window==<br />
<br />
[[Image:Edit-campaign-props.png|thumb|The Edit Menu, showing the Campaign Properties option]]<br />
<br />
To get started with Campaign Properties, the first thing you'll need to do is go to '''Edit > Campaign Properties''', and open the Campaign Properties window. In this window, you'll see several tabs and a whole lot of information.<br />
<br />
When you open up the '''Campaign Properties''' window, you'll see it has six tabs. Briefly, they are:<br />
<br />
* '''Token Properties''': this houses all the property sets that a token in the current campaign may have<br />
* '''Repositories''': this is where you can designate an online "[[Introduction to Campaign Repositories |repository]]" to hold campaign files, especially images, to improve load times and speed when you host or play an online game<br />
* '''Sight''': this tab is where you configure the settings for vision in the current campaign<br />
* '''Light''': this tab is where you configure light sources and auras for the current campaign<br />
* '''States''': this tab lets you configure [[Token:state|token states]] for the current campaign<br />
* '''Bars''': this is where you configure [[bar.name|token bars]] for the current campaign<br />
<br />
At the bottom of the window are buttons to Import, Export, and Import Predefined Campaign Properties.<br />
* '''Import''': this button will allow you to load an exported set of Campaign Properties replacing the current set. Campaign Properties files have a .mtprops extension.<br />
* '''Export''': this button will allow you to export the current set of Campaign Properties.<br />
* '''Import Predefined''': this button will load the property set selected in the drop-down menu to the right. '''[Added in 1.6.0]'''<br />
<br />
This guide will only address the first tab, '''Token Properties'''.<br />
<br />
==The Token Properties Tab==<br />
<br />
[[Image:Camp-props.png|thumb|The '''Token Properties Tab''' in Campaign Properties]]<br />
<br />
The first visible tab is the Token Properties tab. This appears relatively uncomplicated, but it's home to some really nifty potential. There are 3 text fields in this tab:<br />
<br />
* '''Name:''' this is the name of the property set you're currently viewing. When you open the campaign properties window, this is blank.<br />
* '''Token Type:''' this column on the left side is not editable, but it will list the names of all the available property sets, or Token Types, defined in the current campaign. If you have no campaign loaded, the only entry will be '''Basic'''<br />
* A large text area where you enter the properties for the current campaign. It will be blank when first loaded, but if you select a property set from the '''Token Type''' list on the left side, you will see the names and default values of the properties in that set.<br />
<br />
===Token Type===<br />
<br />
In this field, you'll see the names of the different "Property Types" (you can think of them as property ''sets'') that are configured in the current campaign. If you have no campaign loaded, the default property set will be called ''Basic''. The '''Token Type''' field is not directly editable by the user.<br />
<br />
===Name===<br />
<br />
This is a simple text field where you can enter the name you want to give the property set. This name will, when you update the set, appear in the '''Token Type''' list to the left, and it becomes the name for that particular set of properties. Names can be anything you like; many users create sets called "NPC" for games where NPC stats and traits differ from those of player characters, for example.<br />
<br />
===Properties===<br />
<br />
This is where it gets funky. In this text area, you can create any and every property you can think of, which can reflect every possible number or statistic an RPG character might have (and many properties that they don't have -- lots of users create properties that are useful for when they write macros, but wouldn't appear on any character sheet!).<br />
<br />
==Creating Properties==<br />
<br />
===Properties with No Default Value===<br />
<br />
[[Image:Basic-default-props.png|thumb|The default set of properties in the Basic property set]]<br />
<br />
If you look at [[Sample_Ruleset#Primary_Attribute|MTRPG's Primary Attributes]], you will see that there are four separate attributes that are the basic attributes of a character: ''Strength'', ''Dexterity'', ''Intelligence'', and ''Endurance''. We're going to get rid of the default properties, and put new ones in their place. <br />
<br />
1. Go to '''Edit > Campaign Properties'''. You'll see in the left side, under ''Token Type'', that the only entry is "Basic." We're going to create a new property set.<br />
<br />
2. In the '''Token Type''' list on the left, select ''Basic''. When you do this, you'll see a whole bunch of properties with all kinds of symbols like @, #, and so forth. <br />
<br />
3. In the text area with all the properties, use your mouse to highlight them all, and hit Delete on your keyboard. Go ahead - don't be shy!<br />
<br />
4. Leave the '''Name''' field alone - MapTools must always have a ''Basic'' property set, so you can't change that name.<br />
<br />
[[Image:Default-props-replaced.png|thumb|The default properties have been deleted, and replaced by the four Primary Attributes of MTRPG]]<br />
<br />
5. In the text area below the '''Name''' field, enter the name of each of the four Primary Attributes in MTRPG, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength<br/><br />
Dexterity<br/><br />
Intelligence<br/><br />
Endurance</tt></blockquote><br />
<br />
When done, your properties window should look like the screenshot on the right. <br />
<br />
6. Once you've finished entering the properties you want, click the button labeled '''Update'''. Don't panic! The properties will disappear, but if you select the ''Basic'' list from the left, your properties will reappear in the main text area.<br />
<br />
7. Click '''OK''' to confirm all of your changes and close the '''Campaign Properties''' window. <br />
<br />
8. Go to '''File > Save Campaign As''' and save your campaign as '''MTRPG.cmpgn'''. You've now created a new campaign file, with a new set of campaign properties. <br />
<br />
When you create properties like this -- just listing the values one after the other -- and then open a token, you will see that these properties have no value. That does not mean that they are equal to zero, or equal to a blank line - they literally have ''no value''. This doesn't mean much for most purposes, but it is an important distinction in macro writing terms (in programming, there's a big difference between a blank string, and an actually ''empty'' variable!). <br />
<br />
Once properties are updated, all of the tokens on the map will be updated with the new properties, and any new tokens you drop on the map will "inherit" the properties you set up.<br />
<br />
<div><br />
<p style="background-color:yellow; padding:5px"><br />
'''NOTE''': While Property names can have spaces in them, this can make accessing and using those properties in Macros difficult. If you have a property called "Hit Points", it is generally better to enter it as ''HitPoints'' without the space.<br />
</p><br />
</div><br />
<br />
===Creating Properties with Default Values===<br />
<br />
[[Image:Newprops-defvalues.png|thumb|The MTRPG properties now have default values]]<br />
<br />
Now, in MTRPG, the minimum value an attribute can have is 1. So, it makes sense to set the ''default value'' of these properties to 1 (that way, every new token will at least have the minimum value an attribute can have). To do this:<br />
<br />
1. Open the Campaign Properties window.<br />
<br />
2. Select the ''Basic'' property set.<br />
<br />
3. In the Basic Properties set, edit your properties so they now read (see the image, as well):<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength:1<br><br />
Dexterity:1<br><br />
Intelligence:1<br><br />
Endurance:1<br></tt><br />
</blockquote><br />
<br />
4. Click '''Update'''.<br />
<br />
By placing a colon at the end of the name of each attribute, and putting the number 1 after the colon, you have instructed MapTool that the default value for those properties is 1 (in other words, whatever value you put after the colon becomes the ''default value'' for that property). You'll note that at the bottom of the Token Properties tab there is a key describing the various options you can set on a property.<br />
<br />
Now, if you drag a new token onto the map and look at its properties (double-click on the token and go to the Properties Tab in the '''Edit Token''' dialog), you will see that the new token has the default values. <br />
<br />
By the way: don't worry about any tokens you may have already set the property values on - setting up or changing the default values will ''not'' override the properties you've already set. MapTool is smart enough to handle that.<br />
<br />
===Displaying Properties in the Statsheet===<br />
<br />
[[Image:Statsheet-props.png|thumb|The Statsheet showing the campaign properties you've set up. You'll see how to make these appear in this section]]<br />
<br />
MapTool has a neat feature called the '''Statsheet''', which is briefly mentioned in the [[Introduction to Tokens]] - basically, it is an automatic popup that appears in the lower left corner of the map, when you hover over a token. <br />
<br />
You may be saying, "Wait...when I hover over my token, there's no statsheet! Where is it?" The reason you don't see it yet is that the Statsheet is governed by the Campaign Properties - it displays the token's properties (along with a larger version of the token's image) - but ''only'' when a couple requirements are met:<br />
<br />
* The properties are set up to display on the statsheet; and<br />
* The properties that are displayed actually have a value<br />
<br />
====Setting Properties to Display====<br />
<br />
[[Image:Newprops-visible.png|thumb|Note the asterisk in front of each property name, enabling that property to appear on the Statsheet]]<br />
<br />
If you look at the bottom of the '''Token Properties''' tab in the '''Campaign Properties''' dialog, you'll see a key showing how to set up a property to display in the Statsheet. There are three display options, each of which is indicated by putting a symbol in front of the property name:<br />
<br />
# '''<nowiki>*</nowiki>''': an asterisk means "show this property on the statsheet"<br />
# '''@''': means "only show this property to the owner of the token (and the GM)"<br />
# '''<nowiki>#</nowiki>''': means "only show this property to the GM (not even the token owner can see it)"<br />
<br />
The asterisk is '''required''' for any stat to display at all - if you don't have an asterisk first, it won't show no matter what else you put on there. The @ and # symbols, on the other hand, are optional. <br />
<br />
So, for our new game, we're going to set all of the properties to be visible to everyone (by just using a star). To do this, open up your properties, and edit them to look like this:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br></tt><br />
</blockquote><br />
<br />
Now, when you hover over a token, you'll see the Statsheet pop up (see the screenshot, above) with the values in the Strength, Dexterity, Intelligence, and Endurance properties. Also, since even brand new tokens have a default value, the Statsheet will appear for all tokens.<br />
<br />
====Short Names====<br />
<br />
[[Image:Newprops-shortnames.png|thumb|The campaign properties now have Short Names established for each]]<br />
<br />
Sometimes, property names can get pretty long (or look unfriendly - no spaces, and all that). MapTool lets you put a ''Short Name'' in for each property. To do that, you just enter the short name in parentheses after the property name, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength(Str):1<br><br />
*Dexterity(Dex):1<br><br />
*Intelligence(Int):1<br><br />
*Endurance(End):1<br></tt><br />
</blockquote><br />
<br />
These short names are displayed in the Statsheet instead of the full name of the property. There is no limit on length of the ''Short Name'' but the purpose is to have a more presentable name on the Statsheet.<br />
<br />
'''Short Names are for display purposes only - when referencing properties in macros, you must use the full property name.'''<br />
<br />
===Creating Derived Properties===<br />
<br />
[[Image:Newprops-derived.png|thumb|The properties ''HitPoints'' and ''Movement'' now have macro code instructing MapTool to derive them from other, existing properties]]<br />
<br />
[[Image:Statsheet-with-allnewprops.png|thumb|The Statsheet showing all of the properties, including the derived ones]]<br />
<br />
Okay, now let's do something pretty cool. In a lot of roleplaying games, there are character attributes that are derived from other stats - for instance, in the ''Savage Worlds'' rules, your "Parry" stat is based on your ''Fighting'' ability; likewise, in Dungeons & Dragons, your "Hit Points" are derived partly from your "Constitution" score. <br />
<br />
Now, you could create these other derived attributes as separate properties and manually enter the values in when you make a new token - but how about we allow MapTool to calculate these derived values? That's right - MapTool's campaign properties can not only be numbers and text, but also calculations and equations based on other properties that the token has. <br />
<br />
In MTRPG, there are three ''derived'' stats: Hit Points, Armor, and Movement. These stats have the short names "HP", "AR," and "MV." For this example, we're going to set up ''Hit Points'' and ''Movement'' to be calculated from existing properties. We'll leave Armor until later (it takes a bit more complex a calculation to figure out the armor value, and we're taking it slow). <br />
<br />
First, we need to add properties for these three derived values:<br />
<br />
1. Open up the Basic property set. <br />
<br />
2. Beneath ''Endurance'', enter the following:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP)<br><br />
*Armor(AR)<br><br />
*Movement(MV)<br></tt><br />
</blockquote><br />
<br />
You'll notice at this point, we've set no default values. Don't hit '''Update''' just yet - let's enter some macro code to create a derived value.<br />
<br />
We can see from the [[Sample Ruleset|MTRPG]] rules that ''Hit Points'' is equal to the value of ''Endurance'' multiplied by 6. Replicating this calculation in the campaign properties is very simple. Edit the ''Hit Points'' property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP):{Endurance * 6}</tt><br />
</blockquote><br />
<br />
What we've done here is enter a default value for the property (remember, default values are whatever comes after the colon), and used some [[Introduction to Macro Writing|macro code]] to instruct MapTool to perform a calculation in order to find the value for the properties. Two thing are happening here:<br />
<br />
# We've enclosed the calculations in { }, which warns MapTool that the text enclosed inside the brackets is to be handled like a macro, and not just plain text<br />
# Inside the brackets, we've said, "Find the value of the ''Endurance'' property, multiply it by 6, and make that result the value of the ''Hit Points'' property"<br />
<br />
Now, to handle the ''Movement'' attribute, our job is even simpler: we need to instruct MapTool to get the value of the ''Dexterity'' property, and assign that same value to the ''Movement'' property. To do so, edit the Movement property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Movement(MV):{Dexterity}</tt><br />
</blockquote><br />
<br />
When you are finished, your full property set should look like:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br><br />
*HitPoints(HP):{Endurance * 6}<br><br />
*Armor(AR)<br><br />
*Movement(MV):{Dexterity}<br></tt><br />
</blockquote><br />
<br />
And when you hover your mouse over a token, the Statsheet should look like the screenshot to the right. Remember, even though we've said that ''Armor'' should be displayed on the statsheet, the statsheet only shows properties that have a value - ''Armor'' is still empty, so it won't show up until you give it a value.<br />
<br />
==Saving Your Campaign==<br />
<br />
At this point, you've created a bunch of campaign properties, placed a token on the map, and messed around with manipulation of the properties you made. You should probably save your work in a ''Campaign'' file. This will save the tokens, properties you created, and all the information you put into the campaign so far. <br />
<br />
Also, this will let you work on the campaign further, trying tricks from the other MapTool tutorials.<br />
<br />
To save your campaign:<br />
<br />
# Go to '''File -> Save Campaign As...'''<br />
# In the dialog, enter a file name. Something like '''MTRPG.cmpgn''' is good!<br />
# Click '''OK'''<br />
<br />
Your campaign will now be saved, and you can open it up whenever you feel like it, and work on it some more!<br />
<br />
Please note that campaigns saved in one version of MapTool will not open properly in an ''older'' version of MapTool; however most campaign files created in an older version can be opened in the newest version (this isn't guaranteed, though...MapTool is evolving at all times!)<br />
<br />
==Some Technical Details==<br />
<br />
A couple of times in this guide and in other guides the token properties have been described as "those properties that are ''visible''" in this campaign, or the properties set up "''for this campaign''." There's a reason for phrasing it like this. <br />
<br />
See, a token - if you cut one open and looked at its inner workings - is an XML file that contains a ''ton'' of information. It has information about its image, its size, its vision, light, shape, and - of course - its properties. What's important to understand here is that the token will remember not only the properties from the MTRPG, but if it was ever saved as an '''.rptok''' file or brought in from another campaign file, it will remember the properties from that campaign too. They won't be visible, but they're stored in the token even so. <br />
<br />
So, in reality, a set of Campaign Properties really indicates those properties that:<br />
<br />
* You can see if you open up a token by double-clicking on it, and<br />
* You can directly edit by clicking in the cell next to them<br />
<br />
This may sound like a recipe for disaster - what if you set up a property that was already set up but is hidden? Fortunately, MapTool will not, when running a macro, attempt to access any hidden properties unless you ''specifically'' instruct it to do so, using two special macro functions. So rest assured, you cannot accidentally access a property that's not set up in the Campaign Properties.<br />
<br />
In summary, if a Property Type (such as the default ''Basic'' property type) has a property named '''HP''', it will be stored in the token under the XML name '''HP'''. If another property type (such as a user-defined ''Pathfinder'' property type) also has a property named '''HP''', they will both be referencing the same data on the token. Modifying the value of '''HP''' when the token is ''Basic'' and then changing the token ''Pathfinder'' will show the same value for '''HP'''.<br />
<br />
==Moving On from Here==<br />
<br />
MapTool supports very elaborate properties and derived properties, with a number of math functions and operations. A couple of the most common ones you might want to use are (the examples are not necessarily part of MTRPG; they're just examples):<br />
<br />
* '''Basic math operators''': addition (+), subtraction (-), multiplication (*), and division (/)<br />
** '''Example''': <tt>HitPoints: {Endurance * 6}</tt><br />
* '''Rounding''': there are some ''functions'' to let you round numbers when you divide<br />
** '''Floor''': the floor() function rounds ''down''. '''Example''': <tt>HitPoints:{floor(Constitution / 2)}</tt> would divide Constitution by two, and round down<br />
** '''Ceiling''': the ceil() function works like floor(), but rounds up. '''Example''': <tt>HitPoints:{ceil(Constitution/2)}</tt><br />
<br />
You ''can'' execute macros from properties. However, if there is an error, then it is possible to get into a sort of "infinite loop", so be sure to save frequently if you're going to try that approach. You might want to have a macro that is called from the property definition. That lets you test the macro without using the property and thus avoid the above infinite loop. When it has been tested thouroughly, then you can invoke it from the property.<br />
[[Category:MapTool]][[Category:Tutorial]]<br />
{{Languages|Introduction to Properties}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Introduction_to_Properties&diff=8912Introduction to Properties2020-08-26T20:58:49Z<p>Lwoestman: /* Moving On from Here */</p>
<hr />
<div>{{Languages|Introduction to Properties}}{{Beginner}}<br />
==Campaign Properties==<br />
<br />
One of the most useful features in MapTool is the capability of [[Introduction_to_Tokens|tokens]] to carry around a set of '''Properties''', attached to that token, that can be manipulated by macros and can be used to create quick displays of information. Basically, token properties are like built-in character sheets.<br />
<br />
However, because they are so useful, the MapTool developers have created many different ways to use them and manipulate them. This guide will address creating Campaign Property Sets, setting them to have default values, and using them to manipulate the Statsheet.<br />
<br />
==The Sample Ruleset, or MTRPG==<br />
<br />
In order to have useful examples as we move through this tutorial, several MapTool users and contributors developed the [[Sample Ruleset]] -- a simple roleplaying game system developed specifically to illustrate parts of MapTool. For this guide, we're going to call these rules the MapTool RPG - or MTRPG for short, and what we're going to do is create a new Campaign File and set up some ''campaign properties'' that correspond to attributes of the MTRPG.<br />
<br />
==The Campaign Properties Window==<br />
<br />
[[Image:Edit-campaign-props.png|thumb|The Edit Menu, showing the Campaign Properties option]]<br />
<br />
To get started with Campaign Properties, the first thing you'll need to do is go to '''Edit > Campaign Properties''', and open the Campaign Properties window. In this window, you'll see several tabs and a whole lot of information.<br />
<br />
When you open up the '''Campaign Properties''' window, you'll see it has six tabs. Briefly, they are:<br />
<br />
* '''Token Properties''': this houses all the property sets that a token in the current campaign may have<br />
* '''Repositories''': this is where you can designate an online "[[Introduction to Campaign Repositories |repository]]" to hold campaign files, especially images, to improve load times and speed when you host or play an online game<br />
* '''Sight''': this tab is where you configure the settings for vision in the current campaign<br />
* '''Light''': this tab is where you configure light sources and auras for the current campaign<br />
* '''States''': this tab lets you configure [[Token:state|token states]] for the current campaign<br />
* '''Bars''': this is where you configure [[bar.name|token bars]] for the current campaign<br />
<br />
At the bottom of the window are buttons to Import, Export, and Import Predefined Campaign Properties.<br />
* '''Import''': this button will allow you to load an exported set of Campaign Properties replacing the current set. Campaign Properties files have a .mtprops extension.<br />
* '''Export''': this button will allow you to export the current set of Campaign Properties.<br />
* '''Import Predefined''': this button will load the property set selected in the drop-down menu to the right. '''[Added in 1.6.0]'''<br />
<br />
This guide will only address the first tab, '''Token Properties'''.<br />
<br />
==The Token Properties Tab==<br />
<br />
[[Image:Camp-props.png|thumb|The '''Token Properties Tab''' in Campaign Properties]]<br />
<br />
The first visible tab is the Token Properties tab. This appears relatively uncomplicated, but it's home to some really nifty potential. There are 3 text fields in this tab:<br />
<br />
* '''Name:''' this is the name of the property set you're currently viewing. When you open the campaign properties window, this is blank.<br />
* '''Token Type:''' this column on the left side is not editable, but it will list the names of all the available property sets, or Token Types, defined in the current campaign. If you have no campaign loaded, the only entry will be '''Basic'''<br />
* A large text area where you enter the properties for the current campaign. It will be blank when first loaded, but if you select a property set from the '''Token Type''' list on the left side, you will see the names and default values of the properties in that set.<br />
<br />
===Token Type===<br />
<br />
In this field, you'll see the names of the different "Property Types" (you can think of them as property ''sets'') that are configured in the current campaign. If you have no campaign loaded, the default property set will be called ''Basic''. The '''Token Type''' field is not directly editable by the user.<br />
<br />
===Name===<br />
<br />
This is a simple text field where you can enter the name you want to give the property set. This name will, when you update the set, appear in the '''Token Type''' list to the left, and it becomes the name for that particular set of properties. Names can be anything you like; many users create sets called "NPC" for games where NPC stats and traits differ from those of player characters, for example.<br />
<br />
===Properties===<br />
<br />
This is where it gets funky. In this text area, you can create any and every property you can think of, which can reflect every possible number or statistic an RPG character might have (and many properties that they don't have -- lots of users create properties that are useful for when they write macros, but wouldn't appear on any character sheet!).<br />
<br />
==Creating Properties==<br />
<br />
===Properties with No Default Value===<br />
<br />
[[Image:Basic-default-props.png|thumb|The default set of properties in the Basic property set]]<br />
<br />
If you look at [[Sample_Ruleset#Primary_Attribute|MTRPG's Primary Attributes]], you will see that there are four separate attributes that are the basic attributes of a character: ''Strength'', ''Dexterity'', ''Intelligence'', and ''Endurance''. We're going to get rid of the default properties, and put new ones in their place. <br />
<br />
1. Go to '''Edit > Campaign Properties'''. You'll see in the left side, under ''Token Type'', that the only entry is "Basic." We're going to create a new property set.<br />
<br />
2. In the '''Token Type''' list on the left, select ''Basic''. When you do this, you'll see a whole bunch of properties with all kinds of symbols like @, #, and so forth. <br />
<br />
3. In the text area with all the properties, use your mouse to highlight them all, and hit Delete on your keyboard. Go ahead - don't be shy!<br />
<br />
4. Leave the '''Name''' field alone - MapTools must always have a ''Basic'' property set, so you can't change that name.<br />
<br />
[[Image:Default-props-replaced.png|thumb|The default properties have been deleted, and replaced by the four Primary Attributes of MTRPG]]<br />
<br />
5. In the text area below the '''Name''' field, enter the name of each of the four Primary Attributes in MTRPG, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength<br/><br />
Dexterity<br/><br />
Intelligence<br/><br />
Endurance</tt></blockquote><br />
<br />
When done, your properties window should look like the screenshot on the right. <br />
<br />
6. Once you've finished entering the properties you want, click the button labeled '''Update'''. Don't panic! The properties will disappear, but if you select the ''Basic'' list from the left, your properties will reappear in the main text area.<br />
<br />
7. Click '''OK''' to confirm all of your changes and close the '''Campaign Properties''' window. <br />
<br />
8. Go to '''File > Save Campaign As''' and save your campaign as '''MTRPG.cmpgn'''. You've now created a new campaign file, with a new set of campaign properties. <br />
<br />
When you create properties like this -- just listing the values one after the other -- and then open a token, you will see that these properties have no value. That does not mean that they are equal to zero, or equal to a blank line - they literally have ''no value''. This doesn't mean much for most purposes, but it is an important distinction in macro writing terms (in programming, there's a big difference between a blank string, and an actually ''empty'' variable!). <br />
<br />
Once properties are updated, all of the tokens on the map will be updated with the new properties, and any new tokens you drop on the map will "inherit" the properties you set up.<br />
<br />
<div><br />
<p style="background-color:yellow; padding:5px"><br />
'''NOTE''': While Property names can have spaces in them, this can make accessing and using those properties in Macros difficult. If you have a property called "Hit Points", it is generally better to enter it as ''HitPoints'' without the space.<br />
</p><br />
</div><br />
<br />
===Creating Properties with Default Values===<br />
<br />
[[Image:Newprops-defvalues.png|thumb|The MTRPG properties now have default values]]<br />
<br />
Now, in MTRPG, the minimum value an attribute can have is 1. So, it makes sense to set the ''default value'' of these properties to 1 (that way, every new token will at least have the minimum value an attribute can have). To do this:<br />
<br />
1. Open the Campaign Properties window.<br />
<br />
2. Select the ''Basic'' property set.<br />
<br />
3. In the Basic Properties set, edit your properties so they now read (see the image, as well):<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
Strength:1<br><br />
Dexterity:1<br><br />
Intelligence:1<br><br />
Endurance:1<br></tt><br />
</blockquote><br />
<br />
4. Click '''Update'''.<br />
<br />
By placing a colon at the end of the name of each attribute, and putting the number 1 after the colon, you have instructed MapTool that the default value for those properties is 1 (in other words, whatever value you put after the colon becomes the ''default value'' for that property). You'll note that at the bottom of the Token Properties tab there is a key describing the various options you can set on a property.<br />
<br />
Now, if you drag a new token onto the map and look at its properties (double-click on the token and go to the Properties Tab in the '''Edit Token''' dialog), you will see that the new token has the default values. <br />
<br />
By the way: don't worry about any tokens you may have already set the property values on - setting up or changing the default values will ''not'' override the properties you've already set. MapTool is smart enough to handle that.<br />
<br />
===Displaying Properties in the Statsheet===<br />
<br />
[[Image:Statsheet-props.png|thumb|The Statsheet showing the campaign properties you've set up. You'll see how to make these appear in this section]]<br />
<br />
MapTool has a neat feature called the '''Statsheet''', which is briefly mentioned in the [[Introduction to Tokens]] - basically, it is an automatic popup that appears in the lower left corner of the map, when you hover over a token. <br />
<br />
You may be saying, "Wait...when I hover over my token, there's no statsheet! Where is it?" The reason you don't see it yet is that the Statsheet is governed by the Campaign Properties - it displays the token's properties (along with a larger version of the token's image) - but ''only'' when a couple requirements are met:<br />
<br />
* The properties are set up to display on the statsheet; and<br />
* The properties that are displayed actually have a value<br />
<br />
====Setting Properties to Display====<br />
<br />
[[Image:Newprops-visible.png|thumb|Note the asterisk in front of each property name, enabling that property to appear on the Statsheet]]<br />
<br />
If you look at the bottom of the '''Token Properties''' tab in the '''Campaign Properties''' dialog, you'll see a key showing how to set up a property to display in the Statsheet. There are three display options, each of which is indicated by putting a symbol in front of the property name:<br />
<br />
# '''<nowiki>*</nowiki>''': an asterisk means "show this property on the statsheet"<br />
# '''@''': means "only show this property to the owner of the token (and the GM)"<br />
# '''<nowiki>#</nowiki>''': means "only show this property to the GM (not even the token owner can see it)"<br />
<br />
The asterisk is '''required''' for any stat to display at all - if you don't have an asterisk first, it won't show no matter what else you put on there. The @ and # symbols, on the other hand, are optional. <br />
<br />
So, for our new game, we're going to set all of the properties to be visible to everyone (by just using a star). To do this, open up your properties, and edit them to look like this:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br></tt><br />
</blockquote><br />
<br />
Now, when you hover over a token, you'll see the Statsheet pop up (see the screenshot, above) with the values in the Strength, Dexterity, Intelligence, and Endurance properties. Also, since even brand new tokens have a default value, the Statsheet will appear for all tokens.<br />
<br />
====Short Names====<br />
<br />
[[Image:Newprops-shortnames.png|thumb|The campaign properties now have Short Names established for each]]<br />
<br />
Sometimes, property names can get pretty long (or look unfriendly - no spaces, and all that). MapTool lets you put a ''Short Name'' in for each property. To do that, you just enter the short name in parentheses after the property name, like so:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength(Str):1<br><br />
*Dexterity(Dex):1<br><br />
*Intelligence(Int):1<br><br />
*Endurance(End):1<br></tt><br />
</blockquote><br />
<br />
These short names are displayed in the Statsheet instead of the full name of the property. There is no limit on length of the ''Short Name'' but the purpose is to have a more presentable name on the Statsheet.<br />
<br />
'''Short Names are for display purposes only - when referencing properties in macros, you must use the full property name.'''<br />
<br />
===Creating Derived Properties===<br />
<br />
[[Image:Newprops-derived.png|thumb|The properties ''HitPoints'' and ''Movement'' now have macro code instructing MapTool to derive them from other, existing properties]]<br />
<br />
[[Image:Statsheet-with-allnewprops.png|thumb|The Statsheet showing all of the properties, including the derived ones]]<br />
<br />
Okay, now let's do something pretty cool. In a lot of roleplaying games, there are character attributes that are derived from other stats - for instance, in the ''Savage Worlds'' rules, your "Parry" stat is based on your ''Fighting'' ability; likewise, in Dungeons & Dragons, your "Hit Points" are derived partly from your "Constitution" score. <br />
<br />
Now, you could create these other derived attributes as separate properties and manually enter the values in when you make a new token - but how about we allow MapTool to calculate these derived values? That's right - MapTool's campaign properties can not only be numbers and text, but also calculations and equations based on other properties that the token has. <br />
<br />
In MTRPG, there are three ''derived'' stats: Hit Points, Armor, and Movement. These stats have the short names "HP", "AR," and "MV." For this example, we're going to set up ''Hit Points'' and ''Movement'' to be calculated from existing properties. We'll leave Armor until later (it takes a bit more complex a calculation to figure out the armor value, and we're taking it slow). <br />
<br />
First, we need to add properties for these three derived values:<br />
<br />
1. Open up the Basic property set. <br />
<br />
2. Beneath ''Endurance'', enter the following:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP)<br><br />
*Armor(AR)<br><br />
*Movement(MV)<br></tt><br />
</blockquote><br />
<br />
You'll notice at this point, we've set no default values. Don't hit '''Update''' just yet - let's enter some macro code to create a derived value.<br />
<br />
We can see from the [[Sample Ruleset|MTRPG]] rules that ''Hit Points'' is equal to the value of ''Endurance'' multiplied by 6. Replicating this calculation in the campaign properties is very simple. Edit the ''Hit Points'' property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*HitPoints(HP):{Endurance * 6}</tt><br />
</blockquote><br />
<br />
What we've done here is enter a default value for the property (remember, default values are whatever comes after the colon), and used some [[Introduction to Macro Writing|macro code]] to instruct MapTool to perform a calculation in order to find the value for the properties. Two thing are happening here:<br />
<br />
# We've enclosed the calculations in { }, which warns MapTool that the text enclosed inside the brackets is to be handled like a macro, and not just plain text<br />
# Inside the brackets, we've said, "Find the value of the ''Endurance'' property, multiply it by 6, and make that result the value of the ''Hit Points'' property"<br />
<br />
Now, to handle the ''Movement'' attribute, our job is even simpler: we need to instruct MapTool to get the value of the ''Dexterity'' property, and assign that same value to the ''Movement'' property. To do so, edit the Movement property to read:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Movement(MV):{Dexterity}</tt><br />
</blockquote><br />
<br />
When you are finished, your full property set should look like:<br />
<br />
<blockquote style="background-color:lightgray; width:30%;"><tt><br />
*Strength:1<br><br />
*Dexterity:1<br><br />
*Intelligence:1<br><br />
*Endurance:1<br><br />
*HitPoints(HP):{Endurance * 6}<br><br />
*Armor(AR)<br><br />
*Movement(MV):{Dexterity}<br></tt><br />
</blockquote><br />
<br />
And when you hover your mouse over a token, the Statsheet should look like the screenshot to the right. Remember, even though we've said that ''Armor'' should be displayed on the statsheet, the statsheet only shows properties that have a value - ''Armor'' is still empty, so it won't show up until you give it a value.<br />
<br />
==Saving Your Campaign==<br />
<br />
At this point, you've created a bunch of campaign properties, placed a token on the map, and messed around with manipulation of the properties you made. You should probably save your work in a ''Campaign'' file. This will save the tokens, properties you created, and all the information you put into the campaign so far. <br />
<br />
Also, this will let you work on the campaign further, trying tricks from the other MapTool tutorials.<br />
<br />
To save your campaign:<br />
<br />
# Go to '''File -> Save Campaign As...'''<br />
# In the dialog, enter a file name. Something like '''MTRPG.cmpgn''' is good!<br />
# Click '''OK'''<br />
<br />
Your campaign will now be saved, and you can open it up whenever you feel like it, and work on it some more!<br />
<br />
Please note that campaigns saved in one version of MapTool will not open properly in an ''older'' version of MapTool; however most campaign files created in an older version can be opened in the newest version (this isn't guaranteed, though...MapTool is evolving at all times!)<br />
<br />
==Some Technical Details==<br />
<br />
A couple of times in this guide and in other guides the token properties have been described as "those properties that are ''visible''" in this campaign, or the properties set up "''for this campaign''." There's a reason for phrasing it like this. <br />
<br />
See, a token - if you cut one open and looked at its inner workings - is an XML file that contains a ''ton'' of information. It has information about its image, its size, its vision, light, shape, and - of course - its properties. What's important to understand here is that the token will remember not only the properties from the MTRPG, but if it was ever saved as an '''.rptok''' file or brought in from another campaign file, it will remember the properties from that campaign too. They won't be visible, but they're stored in the token even so. <br />
<br />
So, in reality, a set of Campaign Properties really indicates those properties that:<br />
<br />
* You can see if you open up a token by double-clicking on it, and<br />
* You can directly edit by clicking in the cell next to them<br />
<br />
This may sound like a recipe for disaster - what if you set up a property that was already set up but is hidden? Fortunately, MapTool will not, when running a macro, attempt to access any hidden properties unless you ''specifically'' instruct it to do so, using two special macro functions. So rest assured, you cannot accidentally access a property that's not set up in the Campaign Properties.<br />
<br />
In summary, if a Property Type (such as the default ''Basic'' property type) has a property named '''HP''', it will be stored in the token under the XML name '''HP'''. If another property type (such as a user-defined ''Pathfinder'' property type) also has a property named '''HP''', they will both be referencing the same data on the token. Modifying the value of '''HP''' when the token is ''Basic'' and then changing the token ''Pathfinder'' will show the same value for '''HP'''.<br />
<br />
==Moving On from Here==<br />
<br />
MapTool supports very elaborate properties and derived properties, with a number of math functions and operations. A couple of the most common ones you might want to use are (the examples are not necessarily part of MTRPG; they're just examples):<br />
<br />
* '''Basic math operators''': addition (+), subtraction (-), multiplication (*), and division (/)<br />
** '''Example''': <tt>HitPoints: {Endurance * 6}</tt><br />
* '''Rounding''': there are some ''functions'' to let you round numbers when you divide<br />
** '''Floor''': the floor() function rounds ''down''. '''Example''': <tt>HitPoints:{floor(Constitution / 2)}</tt> would divide Constitution by two, and round down<br />
** '''Ceiling''': the ceil() function works like floor(), but rounds up. '''Example''': <tt>HitPoints:{ceil(Constitution/2)}</tt><br />
<br />
You ''can'' execute macros from properties. However, if there is an error, then it is possible to get into a sort of "infinite loop", so be sure to save frequently if you're going to try that approach. You might want to have a macro that is called from the property definition. That lets you test the macro the without using the property and thus avoid the above infinite loop. When it has been tested thouroughly, then you can invoke it from the property.<br />
[[Category:MapTool]][[Category:Tutorial]]<br />
{{Languages|Introduction to Properties}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Bag_of_Tricks&diff=8911Bag of Tricks2020-08-25T02:04:35Z<p>Lwoestman: /* Using the automatic remote execution function from Bag of Tricks */</p>
<hr />
<div>=Bag of Tricks=<br />
A large collection of macros and resources for MapTool compiled by Wolph42.<br />
<br />
You can download the [https://forums.rptools.net/viewtopic.php?f=46&t=28409&p=274496#p274496 Bag of Tricks] from the RPTools forums.<br />
<br />
Note that the BoT contains far more material, macros, functions and tools then the below two functions. The BoT also contains a detailed manual with description of all available functions, including these two below. This article was written because from a 'macro function' perspective they are the two most relevant macros that the BoT contains. <br />
<br />
==Using the automatic remote execution function from ''Bag of Tricks''==<br />
Usually in a macro you would like the execution of a macro on the computer of those users who own the token in context. Or maybe you want to execute a macro on ALL clients but you have to figure out who the current 'executer' is and run the macro for that client separately as the {{func|execLink}} is only executed on remote clients. To make this a bit easier, I've created a couple of functions which are part of the [https://forums.rptools.net/viewtopic.php?f=46&t=28409&p=274496#p274496 Bag of Tricks (BoT)]. If you have the ''BoT'' installed, then the following functions are available to you:<br />
<br />
==bot_execAllPlayers()==<br />
This macro executes the macro {{code|macroName}} on ALL SELECTED clients. So in contrast of {{code|broadcast(execLink())}}, you do not have to worry about who is executing the macro since everyone does.<br />
<source lang="mtmacro"><br />
bot_execAllPlayers (macroName, arguments, [players], [output_to])<br />
</source><br /><br />
{{param|macroName|name of the macro to execute; e.g. {{code|runThisMacro@lib:token}}}}<br />
{{param|arguments|the arguments to pass to the macro (in the form of a JSON array)}}<br />
{{param|players|a list of PLAYER names where to execute on (not token names). Defaults to all players}}<br />
{{param|output to|Send resulting output of macro to whom ({{code|self}}, {{code|gm}}, {{code|all}}, {{code|none}}, {{code|gm-self}}, ''list''). Defaults to none}}<br />
<br /><br />
<br />
''Example use:''<br />
<br />
*Executing the macro {{code|update()}} located at {{code|lib:Token}}, with the parameters {{code|"Hello World"}} and {{code|"2"}} on the PC of user {{code|Tim}}, with the output of the result going to all connected systems:<br />
<source lang="mtmacro" line><br />
[h: bot_execAllPlayers("update@lib:Token", json.append("","Hello World", 2), "Tim", "all")]<br />
</source><br /><br />
*The same but now for all players<br />
<source lang="mtmacro" line><br />
[h: bot_execAllPlayers("update@lib:Token", json.append("","Hello World", 2), bot_all(), "all")]<br />
</source><br /><br />
The {{code|bot_all()}} function is another ''BoT'' function that returns the names of all players that are logged in. See below for more info. <br />
<br />
==bot_message()==<br />
If you want to use a different message format, one is availalbe through this functions.<br />
*{{code|bot_message(0:message [, 1:headertxt, 2:color (bgcolor-txtcolor), 3:userList, 4:token, 5:target, 6:broadcast])}}<br />
Broadcasts a preformatted message to all users (default). The message consists out of a black (bg) and white (txt) header (default) and a delimited textbox below it, containing the message. When the message is left empty ('') only the header will be displayed. bot_message contains the following optional parameters (only message is required):<br />
{{param|message|The message displayed}}<br />
{{param|headerText|This defaults to: ''. The text in the header, note that the 'token' parameter is set in the header as well on the left side. E.g. when token is 'Wolf' and headerTxt is 'Attacks' the header will read 'Wolf Attacks'}}<br />
{{param|color|This defaults to 'black-white'. Here you can set the backgroundcolor-textcolor of the header. You can choose also to only set the backgroundcolor. Some examples: 'red', 'black-yellow', yellow-red'.}}<br />
{{param|userlist|Defaults to all(). Here you can set to whom the message should be send. You can either fill in a user name yourself (NOT TOKEN NAME!) e.g. 'Frank' or you can make use of one of the user functions defined here below, e.g. all(), gm(), ownergm().}}<br />
{{param|token|Defaults to ''. Here you can give the name of the token to which the message reflects. The effect is that the image and name of the token appears left in the header}}<br />
{{param|target|Defaults to ''. Here you can give the name of another token to which the message reflects. The effect is that the image of tha token appears right in the header}}<br />
{{param|broadcast|Defaults to 0 the message is NOT broadcasted but the entire structure is returned. This is usefull is you want to e.g. embed the result in another message; (1) (default) the message is immediately broadcasted}}<br />
<br />
''A couple examples of use:''<br />
<source lang="mtmacro" line>[resultMsg = bot_message('Hello world', 'Header', 'black-white', bot_all(), 'Wolf', '', 0)]</source><br />
<source lang="mtmacro" line>[bot_message("Hellow world")]</source><br />
<source lang="mtmacro" line>[bot_message("this message is shown to gm only", "GM Only", "red-yellow", bot_gm())]</source><br />
<source lang="mtmacro" line>[bot_message("this message is shown to all but gm", "The rest", "yellow-red", bot_ngm())]</source><br />
[[Image:Example_Message.jpg]]<br />
<source lang="mtmacro" line>[h:bot_message(token.name+" Takes damage", "is attacked","red-white",bot_all(),"Dragon", "Eagle")]</source><br />
[[Image:Example_Message2.jpg]]<br />
<br />
<br />
The following functions can be used in conjunction with bot_message() and return a JSON ARRAY (e.g. ["Frank","Jim","Suzy"])<br><br />
{{param|bot_all()|all users}}<br />
{{param|bot_gm()|gm(s) only}}<br />
{{param|bot_ngm()|all but NOT gm(s)}}<br />
{{param|bot_self()|initiator of the macro}}<br />
{{param|bot_nself()|all but NOT initiator of the macro}}<br />
{{param|bot_selfgm()|gm(s) and initiator of the macro}}<br />
{{param|bot_nselfgm()|all but NOT gm(s) and initiator of the macro}}<br />
{{param|bot_ownergm()|gm(s) and owners of the currentToken. So NOT the token that you might give as a parameter to the bot_message() function but the token that is currentToken() at that moment.}}<br />
{{param|bot_nownergm()|all but NOT gm(s) and owners of the current token}}<br />
<br />
The 'bot_' prefixes in all these function are added as a precaution to make sure that there are no conflicts with a framework in which you use the ''BoT''. If you however want to use these 'retrieve user' functions but without the 'bot_' prefix you need to create your own set of user defined functions.<br />
<br />
[[Category:Cookbook]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Bag_of_Tricks&diff=8910Bag of Tricks2020-08-25T02:03:18Z<p>Lwoestman: /* Bag of Tricks */</p>
<hr />
<div>=Bag of Tricks=<br />
A large collection of macros and resources for MapTool compiled by Wolph42.<br />
<br />
You can download the [https://forums.rptools.net/viewtopic.php?f=46&t=28409&p=274496#p274496 Bag of Tricks] from the RPTools forums.<br />
<br />
Note that the BoT contains far more material, macros, functions and tools then the below two functions. The BoT also contains a detailed manual with description of all available functions, including these two below. This article was written because from a 'macro function' perspective they are the two most relevant macros that the BoT contains. <br />
<br />
==Using the automatic remote execution function from ''Bag of Tricks''==<br />
Usually in a macro you would like the execution of a macro on a player's computer those users who own the token in context. Or maybe you want to execute a macro on ALL clients but you have to figure out who the current 'executer' is and run the macro for that client separately as the {{func|execLink}} is only executed on remote clients. To make this a bit easier, I've created a couple of functions which are part of the [https://forums.rptools.net/viewtopic.php?f=46&t=28409&p=274496#p274496 Bag of Tricks (BoT)]. If you have the ''BoT'' installed, then the following functions are available to you:<br />
<br />
==bot_execAllPlayers()==<br />
This macro executes the macro {{code|macroName}} on ALL SELECTED clients. So in contrast of {{code|broadcast(execLink())}}, you do not have to worry about who is executing the macro since everyone does.<br />
<source lang="mtmacro"><br />
bot_execAllPlayers (macroName, arguments, [players], [output_to])<br />
</source><br /><br />
{{param|macroName|name of the macro to execute; e.g. {{code|runThisMacro@lib:token}}}}<br />
{{param|arguments|the arguments to pass to the macro (in the form of a JSON array)}}<br />
{{param|players|a list of PLAYER names where to execute on (not token names). Defaults to all players}}<br />
{{param|output to|Send resulting output of macro to whom ({{code|self}}, {{code|gm}}, {{code|all}}, {{code|none}}, {{code|gm-self}}, ''list''). Defaults to none}}<br />
<br /><br />
<br />
''Example use:''<br />
<br />
*Executing the macro {{code|update()}} located at {{code|lib:Token}}, with the parameters {{code|"Hello World"}} and {{code|"2"}} on the PC of user {{code|Tim}}, with the output of the result going to all connected systems:<br />
<source lang="mtmacro" line><br />
[h: bot_execAllPlayers("update@lib:Token", json.append("","Hello World", 2), "Tim", "all")]<br />
</source><br /><br />
*The same but now for all players<br />
<source lang="mtmacro" line><br />
[h: bot_execAllPlayers("update@lib:Token", json.append("","Hello World", 2), bot_all(), "all")]<br />
</source><br /><br />
The {{code|bot_all()}} function is another ''BoT'' function that returns the names of all players that are logged in. See below for more info. <br />
<br />
==bot_message()==<br />
If you want to use a different message format, one is availalbe through this functions.<br />
*{{code|bot_message(0:message [, 1:headertxt, 2:color (bgcolor-txtcolor), 3:userList, 4:token, 5:target, 6:broadcast])}}<br />
Broadcasts a preformatted message to all users (default). The message consists out of a black (bg) and white (txt) header (default) and a delimited textbox below it, containing the message. When the message is left empty ('') only the header will be displayed. bot_message contains the following optional parameters (only message is required):<br />
{{param|message|The message displayed}}<br />
{{param|headerText|This defaults to: ''. The text in the header, note that the 'token' parameter is set in the header as well on the left side. E.g. when token is 'Wolf' and headerTxt is 'Attacks' the header will read 'Wolf Attacks'}}<br />
{{param|color|This defaults to 'black-white'. Here you can set the backgroundcolor-textcolor of the header. You can choose also to only set the backgroundcolor. Some examples: 'red', 'black-yellow', yellow-red'.}}<br />
{{param|userlist|Defaults to all(). Here you can set to whom the message should be send. You can either fill in a user name yourself (NOT TOKEN NAME!) e.g. 'Frank' or you can make use of one of the user functions defined here below, e.g. all(), gm(), ownergm().}}<br />
{{param|token|Defaults to ''. Here you can give the name of the token to which the message reflects. The effect is that the image and name of the token appears left in the header}}<br />
{{param|target|Defaults to ''. Here you can give the name of another token to which the message reflects. The effect is that the image of tha token appears right in the header}}<br />
{{param|broadcast|Defaults to 0 the message is NOT broadcasted but the entire structure is returned. This is usefull is you want to e.g. embed the result in another message; (1) (default) the message is immediately broadcasted}}<br />
<br />
''A couple examples of use:''<br />
<source lang="mtmacro" line>[resultMsg = bot_message('Hello world', 'Header', 'black-white', bot_all(), 'Wolf', '', 0)]</source><br />
<source lang="mtmacro" line>[bot_message("Hellow world")]</source><br />
<source lang="mtmacro" line>[bot_message("this message is shown to gm only", "GM Only", "red-yellow", bot_gm())]</source><br />
<source lang="mtmacro" line>[bot_message("this message is shown to all but gm", "The rest", "yellow-red", bot_ngm())]</source><br />
[[Image:Example_Message.jpg]]<br />
<source lang="mtmacro" line>[h:bot_message(token.name+" Takes damage", "is attacked","red-white",bot_all(),"Dragon", "Eagle")]</source><br />
[[Image:Example_Message2.jpg]]<br />
<br />
<br />
The following functions can be used in conjunction with bot_message() and return a JSON ARRAY (e.g. ["Frank","Jim","Suzy"])<br><br />
{{param|bot_all()|all users}}<br />
{{param|bot_gm()|gm(s) only}}<br />
{{param|bot_ngm()|all but NOT gm(s)}}<br />
{{param|bot_self()|initiator of the macro}}<br />
{{param|bot_nself()|all but NOT initiator of the macro}}<br />
{{param|bot_selfgm()|gm(s) and initiator of the macro}}<br />
{{param|bot_nselfgm()|all but NOT gm(s) and initiator of the macro}}<br />
{{param|bot_ownergm()|gm(s) and owners of the currentToken. So NOT the token that you might give as a parameter to the bot_message() function but the token that is currentToken() at that moment.}}<br />
{{param|bot_nownergm()|all but NOT gm(s) and owners of the current token}}<br />
<br />
The 'bot_' prefixes in all these function are added as a precaution to make sure that there are no conflicts with a framework in which you use the ''BoT''. If you however want to use these 'retrieve user' functions but without the 'bot_' prefix you need to create your own set of user defined functions.<br />
<br />
[[Category:Cookbook]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Macros:Roll:types&diff=8909Macros:Roll:types2020-08-25T01:39:09Z<p>Lwoestman: /* [ ] Rolls */</p>
<hr />
<div>{{Languages|Macros:Roll:types}}<br />
==[]/{} Roll Types and Options==<br />
Text that you type into MapTool or execute from a [[Macro_Button|macro button]] is scanned for [ ] and { } blocks. The text within these blocks is evaluated and the output from this evaluation is placed into the string in its place.<br />
<br />
==={ } Rolls===<br />
When the text is contained within { } then the text is evaluated and the output copied in its place without any special formatting.<br />
For example {2 + 2} produces<br />
[[Image:Brace2Plus2.png]]<br />
<br />
===[ ] Rolls===<br />
Text that is within [ ] is evaluated, the output from [ ] is inserted with a tool tip that displays the details of the evaluation -- the tool tip can be displayed by leaving the mouse pointer over the result. For example [2 + 2] produces<br />
<br />
[[Image:2Plus2ToolTip.png]]<br />
<br />
There are also several options that can be used within [ ] to change the formatting. Options are specified after the [ and the option string is terminated with a ':'. If you have more than one option then you need to separate them with a ',' eg [opt1, opt2: ...], if there are any arguments for an option they are enclosed within (). All options are case insensitive, so [opt: ...] is the same [OPT: ...].<br />
<br />
===[ ] Hidden Rolls===<br />
'''[h: ]''', '''[hide: ]''', '''[hidden: ]''' evaluates the text after the ':' but completely discards the output. This is useful for setting variables or other similar tasks where you want to change something but not display any output. <!-- [h: 2 + 2] would display.<br />
<br />
[[Image:2Plus2Hidden.png]] --><br />
<!-- The above is no longer accurate due to the following, added in b58: --><br />
<br />
If a chat message would appear empty because everything in it is hidden from the player, the message is not displayed.<br />
<br />
===[ ] Expanded Rolls===<br />
'''[e: ]''', '''[expanded: ]''' evaluates the text after the ':' and displays the detailed output of the evaluation. [e: 2 + 2 ] would display.<br />
<br />
<br />
[[Image:2Plus2Expanded.png]]<br />
<br />
<br />
===[ ] Result Rolls===<br />
'''[r: ]''', '''[result: ]''' evaluates the text after the ':' and displays the plain output without any formatting or tool tips, the result is the same as using { }. [r: 2 + 2] would display.<br />
<br />
[[Image:2Plus2Result.png]]<br />
<br />
<br />
===[ ] Unformatted Rolls===<br />
'''[u: ]''', '''[unformatted: ]''' evaluates the text after the ':' and displays the detailed output without coloring or tool tips. [u: 2 + 2 ] would display.<br />
<br />
[[Image:2Plus2Unformatted.png]]<br />
<br />
<br />
===[ ] Tool Tip Rolls===<br />
'''[t: ]''', '''[tooltip: ]''' evaluates the text after the ':' and displays the result with a tool tip that displays the details of the evaluation -- the tool tip can be displayed by leaving the mouse pointer over the result. For example [t: 2 + 2] produces.<br />
<br />
[[Image:2Plus2T.png]]<br />
<br />
You can also specify an argument for the tooltip option. If you specify an argument then this argument is evaluated and displayed, the text after the ':' is evaluated and used as the tool tip. [t("four"): 2 + 2] produces.<br />
<br />
[[Image:2Plus2T-Four.png]]<br />
<br />
==Related Pages==<br />
<br />
* [[Dice_Expressions|Dice Expressions]]<br />
* [[Macros:Roll:output|Roll Visibility Options]]<br />
* [[Macros:Branching_and_Looping|Branching and Looping Roll Options]]<br />
{{Languages|Macros:Roll:types}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Dice_Expressions&diff=8908Dice Expressions2020-08-24T01:53:36Z<p>Lwoestman: /* Game-Specific Dice Expressions */</p>
<hr />
<div>MapTool's chat window and macro system supports several of the most common dice expressions based on the formats '''XdY''' and '''dY'''.<br />
<br />
In the tables below, the variable ''Y'' is described as the "number of sides" on the dice being rolled; in reality the dice roller is picking a random number between 1 and ''Y''. The end result is the same. <br />
<br />
Additionally, in the expressions, capital letters signify an argument you must provide, while the lower-case letters are a fixed part of the dice expression. For example, in the expression '''XdYsS''', you replace ''X'', ''Y'', and ''S'' with numbers to indicate the number of dice, how many sides the dice have, and what number indicates a success, respectively. The lower case "d" and "s" are left alone. Also, only one expression may be used at a time. For example, you could not combine the expressions of dropping low dice and keeping high dice.<br />
<br />
Finally, note that when entering a dice roll directly in chat, you need to use the /roll [[Chat:Commands|Chat Command]] to execute the roll. In a macro, you would enclose the roll expression in square brackets. For example, if you wanted to roll one twenty sided die, one six sided die, and add 8 to the result:<br />
<br />
''Directly in chat'': <pre>/roll 1d20+1d6+8</pre><br />
<br />
''In a [[Macros:introduction|macro]]'': <pre>[1d20+1d6+8]</pre><br />
<br />
You may also access these dice expressions directly using macro functions, see [[:Category:Dice Function]].<br />
<br />
==General Dice Expressions==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Expression <br />
! style="background-color:#e0ddd5;" |Function<br />
! style="background-color:#e0ddd5;" |Description<br />
! style="background-color:#e0ddd5;" |Example<br />
|-<br />
| '''XdY''' || || Roll ''X'' dice with ''Y'' sides each. If X is not included, roll 1 die with ''Y'' sides and present the sum of all rolls in chat || ''/roll 1d20'' rolls one twenty-sided die and presents the total roll in chat<br />
|-<br />
| '''XdYdN''' || drop || Roll ''X'' dice with ''Y'' sides each, and drop the lowest ''N'' dice afterwards || ''/roll 4d6d1'' rolls four six-sided dice, drops the lowest roll, and presents the total in the chat window<br />
|-<br />
| '''XdYkN''' || keep || Roll ''X'' dice with ''Y'' sides each, and keep the highest ''N'' dice afterwards || ''/roll 4d6k3'' rolls four six-sided dice, keeps the highest 3 rolls, and presents the total in the chat window<br />
|-<br />
| '''XdYrL''' || reroll || Roll ''X'' dice with ''Y'' sides each, repeatedly rerolling any results lower than ''L'' || ''/roll 3d8r2'' rolls three eight-sided dice, repeatedly rerolls any dice that are lower than 2 until all dice rolls are higher than or equal to 2, and then sums and presents the total in chat<br />
|-<br />
| '''XdYrkL''' || reroll once & keep || Roll ''X'' dice with ''Y'' sides each, rerolling any results lower than ''L'' and keeping the new values || ''/roll 2d6rk3'' rolls two six-sided dice, rerolling (once) any dice that are lower than 3, and presents the total in chat<br />
|-<br />
| '''XdYrcL''' || reroll once & choose || Roll ''X'' dice with ''Y'' sides each, rerolling any results lower than ''L'' and choosing the higher values || ''/roll 2d6rc3'' rolls two six-sided dice, rerolling (once) any dice that are lower than 3 but choosing the higher of the two results, and presents the total in chat<br />
|-<br />
| '''XdYsT''' || success || Roll ''X'' dice with ''Y'' sides each, and count any rolls that meet or exceed ''T'' (the "target number")|| ''/roll 4d6s4'' rolls four six-sided dice, and counts any individual roll that exceeds four, presenting the number of "successes" in chat<br />
|-<br />
| '''XdYe''' || explode || Roll ''X'' dice with ''Y'' sides each, and reroll any dice that roll ''Y'', add the new roll to the total || ''/roll 2d6e'' rolls two six-sided dice, and if either rolls a 6, it is rerolled and added to the total (this continues until neither die rolls a 6).<br />
|-<br />
| '''XdYesT''' || exploding success || As success rolls, above, but the individual dice can "explode" (''i.e.'', they are rerolled if they roll their maximum value) || ''/roll 4d6es8'' will roll 4 six-sided dice, explode any that roll their maximum, and then total the rolls that exceed 8<br />
|-<br />
| '''XdYo''' || open || Roll ''X'' dice with ''Y'' sides each, and explode any dice that roll ''Y'', then return the value of all rolls, as well as the highest roll || ''/roll 5d6o'' rolls 5 six-sided dice, and explodes any that roll 6<br />
|-<br />
| '''XdYdhZ''' || drop high || Roll ''X'' dice of ''Y'' sides, and drop the ''Z'' highest || ''/roll 5d10DH2'' rolls five ten-sided dice, drops the two highest, and presents the total in the chat window<br />
|-<br />
| '''XdYklZ''' || keep low || Roll ''X'' dice of ''Y'' sides, and keep the ''Z'' lowest || ''/roll 5d6kl3'' rolls five six-sided dice, keeping the three lowest, and presents the total in the chat window<br />
|-<br />
| '''XdYsZlW''' || subtract || Roll ''X'' dice of ''Y'' sides, subtract ''Z'' from each roll with a lower bound of ''W'' || ''/roll 5d6s1l2'' rolls five six-sided dice, subtracting 1 from each with a lower bound of 2, and presents the total in the chat window<br />
|-<br />
| '''XdYaZuW''' || add || Roll ''X'' dice of ''Y'' sides, add ''Z'' to each roll with an upper bound of ''W'' || ''/roll 5d6a1u6'' rolls five six-sided dice, adding 1 to each with an upper bound of 6, and presents the total in the chat window<br />
|-<br />
| '''XdYlZ''' || lower bound || Roll ''X'' dice of ''Y'' sides, with a lower bound of ''Z'' || ''/roll 5d6l2'' rolls five six-sided dice, replacing any results lower than 2 with 2, and presents the total in the chat window<br />
|-<br />
| '''XdYuZ''' || upper bound || Roll ''X'' dice of ''Y'' sides, with an upper bound of ''Z'' || ''/roll 5d6u4'' rolls five six-sided dice, replacing any results higher than 4 with 4, and presents the total in the chat window<br />
|}<br />
<br />
==Game-Specific Dice Expressions==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Expression<br />
! style="background-color:#e0ddd5;" |Game&nbsp;System<br />
! style="background-color:#e0ddd5;" |Function<br />
! style="background-color:#e0ddd5;" |Description<br />
|-<br />
| '''XdYh''' || Hero || Stun Dice || Rolls ''X'' dice with ''Y'' sides each, keeping track of the results for hero rolls for body damage. Where a roll of 1 = 0 body damage, a roll of ''Y'' = 2 body damage and a roll in between these two values = 1 body damage.<br />
|-<br />
| '''XdYb''' || Hero || Body Dice || Returns the body damage from the last XdYb Hero Stun Dice roll as long as ''X'' and ''Y''<br />
matches the Stun Dice roll<br />
|-<br />
| '''Xdf''' || Fudge || Fudge Dice || Rolls ''X'' [https://www.fudgerpg.com/ Fudge] dice (which return -1, 0, or 1), summing the dice and returning the sum<br />
|-<br />
| '''Xdu''' || Ubiquity || Ubiquity Dice || Rolls ''X'' Ubiquity dice, which return 0 or 1, summing the result and returning that value to chat<br />
|-<br />
| '''Xsr4''' || Shadowrun 4th Ed. || Shadowrun Basic Roll || Roll ''X'' number of 6 sided dice. Output the number of Hits (Rolls 5 or above) and the numbers of Ones rolled. If the number of Ones is half or more of ''X'', display '''Glitch'''. If the number of Ones is half or more of ''X'' and there are no Hits, display '''Critical Glitch'''.<br />
|-<br />
| '''Xsr4gT''' || Shadowrun 4th Ed. || Shadowrun Gremlin Roll || Roll ''X'' number of 6 sided dice. Output the number of Hits (Rolls 5 or above) and the numbers of Ones rolled. If the number of Ones is half or more of ''X'' minus ''T'', display '''Glitch'''. If the number of Ones is half or more of ''X'' minus ''Y'' and there are no Hits, display '''Critical Glitch'''.<br />
|-<br />
| '''Xsr4e''' || Shadowrun 4th Ed. || Shadowrun Exploding Roll || Roll ''X'' number of 6 sided dice. Output the number of Hits (Rolls 5 or above) and the numbers of Ones rolled. Reroll any 6 adding it to the pool. If the number of Ones is half or more of ''X'', display '''Glitch'''. If the number of Ones is half or more of ''X'' and there are no Hits, display '''Critical Glitch'''.<br />
|-<br />
| '''Xsr4egT''' || Shadowrun 4th Ed. || Shadowrun Exploding Gremlin Roll || Roll ''X'' number of 6 sided dice. Output the number of Hits (Rolls 5 or above) and the numbers of Ones rolled. Reroll any 6 adding it to the pool. If the number of Ones is half or more of ''X'' minus ''T'', display '''Glitch'''. If the number of Ones is half or more of ''X'' minus ''T'' and there are no Hits, display '''Critical Glitch'''.<br />
|-<br />
| '''XdYq#+Z''' || DragonQuest || - || Rolls ''X'' dice of ''Y'' sides, adding ''Z'' to each die, summing the result and returning that value to chat<br />
|-<br />
| '''XdYq#-Z''' || DragonQuest || - || Rolls ''X'' dice of ''Y'' sides, subtracting ''Z'' from each die with a minimum of 1, summing the result and returning that value to chat<br />
|}<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Chat_Commands&diff=8907Chat Commands2020-08-24T01:43:47Z<p>Lwoestman: /* Built-in Commands */</p>
<hr />
<div>{{Languages|Chat Commands}}<br />
<br />
MapTool's chat system supports a number of "slash commands" (that is, commands preceded by a "/" character) that execute particular actions when typed directly into chat.<br />
<br />
==General Usage==<br />
<br />
To use a chat command, you type directly into the chat window, using the following format: <br />
<br />
<source lang="mtmacro" line><br />
/command argument<br />
</source><br />
<br />
where ''command'' is one of the commands in the table below, and ''argument'' is an appropriate argument (a dice roll, or a string of text, etc.) upon which the command acts.<br />
<br />
'''NOTE''': Remember, the commands shown below are always preceded by a forward slash ('''/''') character.<br />
<br />
'''NOTE''': Slash commands will only work correctly in a MapTool macro if they are the first text in the macro. This is a result of macros simply being text that is "stored up" until it's pushed into the chat window where it's executed. However, many chat commands have related macro functions that can achieve the same effect within only a part of a chat message. Those functions are pointed out below where applicable.<br />
<br />
==Built-in Commands==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#abcdef;" |Command<br />
! style="background-color:#abcdef;" |Built-in Alias (if any)<br />
! style="background-color:#abcdef;" |Description<br />
|-<br />
| about || a || Opens About window<br />
|-<br />
| addtokenstate || tsa || Add a new token state that can be set on tokens<br />
|-<br />
| alias || alias || Create a command alias<br />
|-<br />
| clear || clr || Clear the chat window<br />
|-<br />
| clearaliases || || Clear all aliases<br />
|-<br />
| color || cc || Change your chat text color. Color must be in hexadecimal format, e.g. ''/cc #ff0099''<br />
|-<br />
| emit || e || Broadcast text to all connected players without revealing who sent it (GM-only command)<br />
|-<br />
| emote || me || Broadcast an emote to all connected players<br />
|- <br />
| emotes || mes || Broadcast an emote to all connected players, adding the possessive (<b>'s</b>) to the end of the token name.<br />
|- <br />
| gm || togm || Send text to GM exclusively (see {{roll|g}})<br />
|-<br />
| goto || g || Go to location or go to token, e.g. ''/goto X,Y'' or ''/goto tokenname'' (see {{func|goto}})<br />
|-<br />
| help || h || Display a list of available commands<br />
|-<br />
| impersonate || im || Speak as if you were someone or something else (typically, speak as if you were a token) <br />
|- <br />
| loadaliases || || Load a file that contains aliases, one per line, with a : between the name and the value (just as if you were typing it in)<br />
|-<br />
| loadtokenstates || tsl || Load all of the token states from a file<br />
|-<br />
| ooc || || Out-of-character chat (chat is enclosed in double parentheses)<br />
|-<br />
| reply || rep || Reply to the last player to whisper to you<br />
|- <br />
| roll || r || Roll dice (using a [[Chat:Dice | Dice Expression]]) and broadcast result to all players (see {{func|roll}})<br />
|-<br />
| rollgm || rgm || Roll dice and broadcast result only to yourself and the GM<br />
|-<br />
| rollme || rme || Roll dice and show the result only to yourself<br />
|-<br />
| rollsecret || rsec|| Roll dice and show the result only to the GM (hiding the result from even yourself)<br />
|-<br />
| savealiases || || Save all current aliases to a file<br />
|-<br />
| savetokenstates || tss || Save the current set of token states to a file<br />
|-<br />
| say || s || Broadcast a message to all connected players<br />
|-<br />
| self || || Send a message only to yourself (see {{roll|s}})<br />
|-<br />
| settokenproperty || stp || Set the value of a [[Token:token_property|Token Property]] (see {{func|setProperty}})<br />
|-<br />
| settokenstate || sts || Set the value of a [[Token:state|Token State]] (see {{func|setState}})<br />
|-<br />
| table || tbl || Run a table lookup, e.g. ''/tbl tablename value-to-lookup'' (see {{func|table}})<br />
|-<br />
| texturenoise || tn || Turn Perlin noise on/off and get/set values.<br />
|-<br />
| tmacro || tm || Run the given macro on the selected token (see {{roll|macro}})<br />
|-<br />
| tsay || ts || Say the given speech on the selected token (see {{func|getSpeech}})<br />
|-<br />
| version || v || Outputs MapTool version to chat.<br />
|-<br />
| whisper || w || Send a message to a specific player (see {{roll|w}})<br />
|}<br />
[[Category:MapTool]]<br />
{{Languages|Chat Commands}}</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Glossary&diff=8906Glossary2020-08-22T19:17:49Z<p>Lwoestman: /* T */</p>
<hr />
<div>__NOTOC__<br />
==B==<br />
;Bar<br />
:One, two, or multi-image graphical elements displayed on a token used to indicate the status of a consumable resource such as Hit Points.<br />
<br />
==C==<br />
<br />
;Campaign or Campaign file<br />
:A zipped XML file with the '''.cmpgn''' file extension containing [[Introduction to Tokens|tokens]], [[Introduction to Mapping|maps]], token [[Introduction to Macro Writing|macros]], campaign macros, campaign [[Introduction to Properties|properties]], and [[Token Property|token properties]].<br />
<br />
;Campaign Macro<br />
:A macro specific to a campaign file. These macros are available to players and the GM, and are displayed in the Campaign Macros window.<br />
<br />
==D==<br />
<br />
;Dialog<br />
:A modeless (''i.e.'', does not require user interaction) popup generated by the [[Tutorials:Macros:DialogsAndFramesIntro | dialog]] roll option. <br />
<br />
==F==<br />
<br />
;Frame<br />
:A dockable MapTool window that can be generated via the [[Tutorials:Macros:DialogsAndFramesIntro | frame]] roll option.<br />
<br />
==G==<br />
<br />
;Global Macro<br />
:Macros that are available regardless of the campaign file currently loaded in MapTool, and regardless of whether the instance of MapTool is a server or a client. Global macros are ''only'' available to the running instance.<br />
<br />
==H==<br />
<br />
;Halo<br />
:A colored border that appears around a token on the map. The Halo can be set via the right-click menu to one of several pre-set colors, or set and changed via macro by changing the variable [[token.halo]].<br />
<br />
==I==<br />
<br />
;Image token<br />
:A special token that contains an image that may be referenced by other macros. <br />
<br />
;Initiative Panel<br />
:A dockable panel in MapTool that provides simple initiative tracking functionality. <br />
<br />
==L==<br />
<br />
;Library Token<br />
:A special token designed to hold a library of macros (similar to a function library) that can be called by token macros, campaign macros, and global macros. Often called "Lib:tokens."<br />
<br />
==M==<br />
<br />
;Macro<br />
:A series of text instructions used to automate processes in MapTool. See [[Introduction to Macro Writing]] for more details.<br />
<br />
;Map<br />
:An image file displayed in the map display area in MapTool. This image is shared among all connected players and the GM.<br />
<br />
==P==<br />
;Pion<br />
:Marqueur visuel représentant habituellement un personnage, un PNJ ou un monstre.<br />
<br />
;Property<br />
:Generic term for a variable contained in a token; a more explicit term is [[Token Property]].<br />
<br />
==R==<br />
<br />
;Resource Library<br />
:The library of images, tokens, and other resources that MapTool can access. The Resource Library appears as a set of folders in the Library window in MapTool's main interface. These folders are links that point to locations on your computer's hard drive - if you add a folder to the resource library, MapTool becomes aware of that folder's contents, and they can be dragged from the Library window onto a MapTool map, or selected via several different dialogs.<br />
<br />
;Roll Option<br />
:One of several "switches" that alter how the macro code following the switch is executed. Roll options (also called roll formatting options) are always in the format [option(''arguments''): ''body of roll'']. Simple options include [[Macros:Roll:types|[h: ]]] (hides output of roll) or [[Macros:Roll:types|[t: ]]] (creates a "tooltip roll"), while more complex options include [[Macros:Branching_and_Looping|[SWITCH(): ]]] and [[Macros:Branching_and_Looping|[IF(): ]]].<br />
<br />
==S==<br />
<br />
;State<br />
:Also called a [[Token:state|token state]], a state is a binary condition that is set for a given token.<br />
<br />
;String List<br />
:A string containing a list of items in the format "item1, item2, item3,..."<br />
<br />
;String Property List<br />
:A string containing key-value pairs in the format "key1=value1; key2=value2; key3=value3;..."<br />
<br />
==T==<br />
<br />
;Token<br />
:A visual marker that is dropped on a MapTool map. Tokens usually represent characters, monsters, or NPCs, and often including an image as well as a set of [[Token Property|token properties]] which define the attributes of the creature or character.<br />
<br />
;Token Bar<br />
:One, two, or multi-image graphical elements displayed on a token that are typically used to visually indicate the status of consumable or expendable resources such as Hit Points or Ammunition.<br />
<br />
;Token Id<br />
:A string that uniquely identifies a specific token. Many macro functions operate on the current token by default but allow a '''token id''' to be given so that operations are applied against that token instead. When a token id is provided MapTool checks the string against (1) the token name, (2) the token's ''''GM Name'''', and (3) the internal identifier for the token. The first two are self-explanatory, but the third one is not normally visible anywhere within MapTool. Token ids can be obtained by calling [[getTokens]], for example, and will appear as a long string of uppercase letters and digits.<br />
<br />
;Token State<br />
:A binary (i.e., it has two possible values, 1 or 0) variable that is set for a given token, frequently used for conditions or statuses that affect a particular character in a game (for example "Bloodied" or "Fatigued"). Token states often have images associated with them that appear as overlays on the token.<br />
<br />
;Trusted Macro<br />
:A macro run from a Library token or run by the GM, that cannot be edited by a player.<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Glossary&diff=8905Glossary2020-08-22T19:14:59Z<p>Lwoestman: /* M */</p>
<hr />
<div>__NOTOC__<br />
==B==<br />
;Bar<br />
:One, two, or multi-image graphical elements displayed on a token used to indicate the status of a consumable resource such as Hit Points.<br />
<br />
==C==<br />
<br />
;Campaign or Campaign file<br />
:A zipped XML file with the '''.cmpgn''' file extension containing [[Introduction to Tokens|tokens]], [[Introduction to Mapping|maps]], token [[Introduction to Macro Writing|macros]], campaign macros, campaign [[Introduction to Properties|properties]], and [[Token Property|token properties]].<br />
<br />
;Campaign Macro<br />
:A macro specific to a campaign file. These macros are available to players and the GM, and are displayed in the Campaign Macros window.<br />
<br />
==D==<br />
<br />
;Dialog<br />
:A modeless (''i.e.'', does not require user interaction) popup generated by the [[Tutorials:Macros:DialogsAndFramesIntro | dialog]] roll option. <br />
<br />
==F==<br />
<br />
;Frame<br />
:A dockable MapTool window that can be generated via the [[Tutorials:Macros:DialogsAndFramesIntro | frame]] roll option.<br />
<br />
==G==<br />
<br />
;Global Macro<br />
:Macros that are available regardless of the campaign file currently loaded in MapTool, and regardless of whether the instance of MapTool is a server or a client. Global macros are ''only'' available to the running instance.<br />
<br />
==H==<br />
<br />
;Halo<br />
:A colored border that appears around a token on the map. The Halo can be set via the right-click menu to one of several pre-set colors, or set and changed via macro by changing the variable [[token.halo]].<br />
<br />
==I==<br />
<br />
;Image token<br />
:A special token that contains an image that may be referenced by other macros. <br />
<br />
;Initiative Panel<br />
:A dockable panel in MapTool that provides simple initiative tracking functionality. <br />
<br />
==L==<br />
<br />
;Library Token<br />
:A special token designed to hold a library of macros (similar to a function library) that can be called by token macros, campaign macros, and global macros. Often called "Lib:tokens."<br />
<br />
==M==<br />
<br />
;Macro<br />
:A series of text instructions used to automate processes in MapTool. See [[Introduction to Macro Writing]] for more details.<br />
<br />
;Map<br />
:An image file displayed in the map display area in MapTool. This image is shared among all connected players and the GM.<br />
<br />
==P==<br />
;Pion<br />
:Marqueur visuel représentant habituellement un personnage, un PNJ ou un monstre.<br />
<br />
;Property<br />
:Generic term for a variable contained in a token; a more explicit term is [[Token Property]].<br />
<br />
==R==<br />
<br />
;Resource Library<br />
:The library of images, tokens, and other resources that MapTool can access. The Resource Library appears as a set of folders in the Library window in MapTool's main interface. These folders are links that point to locations on your computer's hard drive - if you add a folder to the resource library, MapTool becomes aware of that folder's contents, and they can be dragged from the Library window onto a MapTool map, or selected via several different dialogs.<br />
<br />
;Roll Option<br />
:One of several "switches" that alter how the macro code following the switch is executed. Roll options (also called roll formatting options) are always in the format [option(''arguments''): ''body of roll'']. Simple options include [[Macros:Roll:types|[h: ]]] (hides output of roll) or [[Macros:Roll:types|[t: ]]] (creates a "tooltip roll"), while more complex options include [[Macros:Branching_and_Looping|[SWITCH(): ]]] and [[Macros:Branching_and_Looping|[IF(): ]]].<br />
<br />
==S==<br />
<br />
;State<br />
:Also called a [[Token:state|token state]], a state is a binary condition that is set for a given token.<br />
<br />
;String List<br />
:A string containing a list of items in the format "item1, item2, item3,..."<br />
<br />
;String Property List<br />
:A string containing key-value pairs in the format "key1=value1; key2=value2; key3=value3;..."<br />
<br />
==T==<br />
<br />
;Token<br />
:A visual marker that is dropped on a MapTool map. Tokens usually represent characters, monsters, or NPCs, and often including an image as well as a set of [[Token Property|token properties]] which define the attributes of the creature or character.<br />
<br />
;Token Bar<br />
:One, two, or multi-image graphical elements displayed on a token that are typically used to visually indicate the status of consumable or expendable resource such as Hit Points or Ammunition.<br />
<br />
;Token Id<br />
:A string that uniquely identifies a specific token. Many macro functions operate on the current token by default but allow a '''token id''' to be given so that operations are applied against that token instead. When a token id is provided MapTool checks the string against (1) the token name, (2) the token's ''''GM Name'''', and (3) the internal identifier for the token. The first two are self-explanatory, but the third one is not normally visible anywhere within MapTool. Token ids can be obtained by calling [[getTokens]], for example, and will appear as a long string of uppercase letters and digits.<br />
<br />
;Token State<br />
:A binary (i.e., it has two possible values, 1 or 0) variable that is set for a given token, frequently used for conditions or statuses that affect a particular character in a game (for example "Bloodied" or "Fatigued"). Token states often have images associated with them that appear as overlays on the token.<br />
<br />
;Trusted Macro<br />
:A macro run from a Library token or run by the GM, that cannot be edited by a player.<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Glossary&diff=8904Glossary2020-08-22T19:06:33Z<p>Lwoestman: /* C */</p>
<hr />
<div>__NOTOC__<br />
==B==<br />
;Bar<br />
:One, two, or multi-image graphical elements displayed on a token used to indicate the status of a consumable resource such as Hit Points.<br />
<br />
==C==<br />
<br />
;Campaign or Campaign file<br />
:A zipped XML file with the '''.cmpgn''' file extension containing [[Introduction to Tokens|tokens]], [[Introduction to Mapping|maps]], token [[Introduction to Macro Writing|macros]], campaign macros, campaign [[Introduction to Properties|properties]], and [[Token Property|token properties]].<br />
<br />
;Campaign Macro<br />
:A macro specific to a campaign file. These macros are available to players and the GM, and are displayed in the Campaign Macros window.<br />
<br />
==D==<br />
<br />
;Dialog<br />
:A modeless (''i.e.'', does not require user interaction) popup generated by the [[Tutorials:Macros:DialogsAndFramesIntro | dialog]] roll option. <br />
<br />
==F==<br />
<br />
;Frame<br />
:A dockable MapTool window that can be generated via the [[Tutorials:Macros:DialogsAndFramesIntro | frame]] roll option.<br />
<br />
==G==<br />
<br />
;Global Macro<br />
:Macros that are available regardless of the campaign file currently loaded in MapTool, and regardless of whether the instance of MapTool is a server or a client. Global macros are ''only'' available to the running instance.<br />
<br />
==H==<br />
<br />
;Halo<br />
:A colored border that appears around a token on the map. The Halo can be set via the right-click menu to one of several pre-set colors, or set and changed via macro by changing the variable [[token.halo]].<br />
<br />
==I==<br />
<br />
;Image token<br />
:A special token that contains an image that may be referenced by other macros. <br />
<br />
;Initiative Panel<br />
:A dockable panel in MapTool that provides simple initiative tracking functionality. <br />
<br />
==L==<br />
<br />
;Library Token<br />
:A special token designed to hold a library of macros (similar to a function library) that can be called by token macros, campaign macros, and global macros. Often called "Lib:tokens."<br />
<br />
==M==<br />
<br />
;Macro<br />
:A series of text instructions used to automate processes in MapTool. See [[Macros:introduction | Macro Introduction]] for more details.<br />
<br />
;Map<br />
:An image file displayed in the map display area in MapTool. This image is shared among all connected players and the GM. <br />
<br />
==P==<br />
;Pion<br />
:Marqueur visuel représentant habituellement un personnage, un PNJ ou un monstre.<br />
<br />
;Property<br />
:Generic term for a variable contained in a token; a more explicit term is [[Token Property]].<br />
<br />
==R==<br />
<br />
;Resource Library<br />
:The library of images, tokens, and other resources that MapTool can access. The Resource Library appears as a set of folders in the Library window in MapTool's main interface. These folders are links that point to locations on your computer's hard drive - if you add a folder to the resource library, MapTool becomes aware of that folder's contents, and they can be dragged from the Library window onto a MapTool map, or selected via several different dialogs.<br />
<br />
;Roll Option<br />
:One of several "switches" that alter how the macro code following the switch is executed. Roll options (also called roll formatting options) are always in the format [option(''arguments''): ''body of roll'']. Simple options include [[Macros:Roll:types|[h: ]]] (hides output of roll) or [[Macros:Roll:types|[t: ]]] (creates a "tooltip roll"), while more complex options include [[Macros:Branching_and_Looping|[SWITCH(): ]]] and [[Macros:Branching_and_Looping|[IF(): ]]].<br />
<br />
==S==<br />
<br />
;State<br />
:Also called a [[Token:state|token state]], a state is a binary condition that is set for a given token.<br />
<br />
;String List<br />
:A string containing a list of items in the format "item1, item2, item3,..."<br />
<br />
;String Property List<br />
:A string containing key-value pairs in the format "key1=value1; key2=value2; key3=value3;..."<br />
<br />
==T==<br />
<br />
;Token<br />
:A visual marker that is dropped on a MapTool map. Tokens usually represent characters, monsters, or NPCs, and often including an image as well as a set of [[Token Property|token properties]] which define the attributes of the creature or character.<br />
<br />
;Token Bar<br />
:One, two, or multi-image graphical elements displayed on a token that are typically used to visually indicate the status of consumable or expendable resource such as Hit Points or Ammunition.<br />
<br />
;Token Id<br />
:A string that uniquely identifies a specific token. Many macro functions operate on the current token by default but allow a '''token id''' to be given so that operations are applied against that token instead. When a token id is provided MapTool checks the string against (1) the token name, (2) the token's ''''GM Name'''', and (3) the internal identifier for the token. The first two are self-explanatory, but the third one is not normally visible anywhere within MapTool. Token ids can be obtained by calling [[getTokens]], for example, and will appear as a long string of uppercase letters and digits.<br />
<br />
;Token State<br />
:A binary (i.e., it has two possible values, 1 or 0) variable that is set for a given token, frequently used for conditions or statuses that affect a particular character in a game (for example "Bloodied" or "Fatigued"). Token states often have images associated with them that appear as overlays on the token.<br />
<br />
;Trusted Macro<br />
:A macro run from a Library token or run by the GM, that cannot be edited by a player.<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Shortcut_Keys&diff=8903Shortcut Keys2020-08-22T18:57:36Z<p>Lwoestman: </p>
<hr />
<div>{{Languages|Shortcut Keys}}<br />
Most of the Shortcut Keys in Maptool 1.3b76+ can be found in the menus; some however are not listed. These "stealth" keys are marked in ''italic''.<br />
<br />
Here is a comprehensive list of all known keystrokes. Most keystrokes require that the map window have the keyboard focus.<br />
<br />
Note that '''Meta''' means '''Ctrl''' on Windows and Linux, and '''Cmd''' on OSX. Also note that most of these can be changed in the translation files, so these settings are primarily for the English locale.<br />
<br />
==Light/Vision Related==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''Meta+K''' || Toggle display of light source icons <br />
|-<br />
| '''Meta+I''' || Clear fog visible by selected token(s) <br />
|-<br />
| '''Meta+P''' || Clear fog visible by selected token(s) along last moved path<br />
|-<br />
| '''Meta+Shift+O''' || Restore fog-of-war to entire map except area currently visible to selected token(s) <br />
|-<br />
| '''Meta+W''' || Toggle fog-of-war on/off (GM only) <br />
|}<br />
<br />
<br />
==Drawing Tools Related==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''Meta+LeftMouseButton''' || Snap to grid while drawing<br />
|-<br />
| '''Alt+LeftMouseButton''' || Draw from centre (vs corner to corner) <br />
|-<br />
| '''Shift+LeftMouseButton''' || Erase <br />
|}<br />
<br />
<br />
==Map Related==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''Spacebar''' || Show a pointer (arrow) on the map<br />
|-<br />
| '''Meta+Spacebar''' || Show a pointer (talk-balloon)<br />
|-<br />
| '''Shift+Spacebar''' || Show a pointer (think-balloon)<br />
|-<br />
| '''Spacebar''' || Adds a waypoint while moving (as does middle mouse button)<br />
|-<br />
| '''Meta+G''' || Toggle grid on/off (current client only)<br />
|-<br />
| '''Meta+Shift+S''' || Create screenshot<br />
|-<br />
| '''Meta+Shift+D''' || Clear all drawings<br />
|-<br />
| '''Meta+Z''' || Undo last drawing<br />
|-<br />
| '''Meta+R''' || Redo last drawing (only when drawing tool is active)<br />
|-<br />
| '''Meta+Alt+Enter''' || Toggle full screen map<br />
|-<br />
| '''=''' || Set zoom to 1:1 and back on second press<br />
|-<br />
| '''-''' || Zoom out<br />
|-<br />
| '''+''' || Zoom in<br />
|-<br />
| '''Z''' || (keep it pressed) inverse mouse scroll zoom<br />
|-<br />
| '''Meta+H''' || Toggle map (in)visible to player(s) (GM only)<br />
|-<br />
| '''Meta+Shift+A''' || Grid settings (spacing, alignment, color) (GM only)<br />
|-<br />
| '''Meta+N''' || New map (GM only)<br />
|-<br />
| '''Meta+Shift+P''' || Toggle player view (GM only)<br />
|-<br />
| '''Meta+Shift+F''' || Center players on current view continuously (GM only)<br />
|-<br />
| '''Meta+F''' || Center players on current view (GM only)<br />
|-<br />
| '''Meta+E''' || Force players to current map (GM only)<br />
|}<br />
<br />
==Token Related==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''Meta+T''' || Toggle token name display.<br />
|-<br />
| '''T''' || select next token (Shift=previous) on map.<br />
|-<br />
| Digits on numeric keypad || Move in the direction of the digit (7=NW, 9=NE, 1=SW, 3=SE).<br />
|-<br />
| '''D''', '''NumPad5''', or '''Home''' || Drop selected tokens after moving (when using arrow keys).<br />
|-<br />
| '''Shift+MouseWheel''' || Rotate facing of token. '''MouseWheel_Up''' = clockwise. '''Ctrl'''=rotate by 1 degree. Otherwise angle controlled by '''Preferences'''. When the token is set to '''TOP_DOWN''' (double-click on token > '''Config''' tab > '''Shape''') the whole token will rotate instead of the yellow facing arrow.<br />
|-<br />
| '''Shift+LeftArrow''' and '''Shift+RightArrow''' ||<br />
On ''TOKEN'' layer: Same as '''Shift+MouseWheel''': rotate token.<br />
<br />
On all other layers: Move token per pixel instead of per cell.<br />
|-<br />
| '''Meta+R''' || Turn on token facing. With a mouse click set the facing in the direction of the mouse pointer. Angle controlled as for '''Shift+MouseWheel'''. Use '''Delete''' to remove facing.<br />
|-<br />
| '''Meta+Shift+L''' || Lock Player Movement (GM Only)<br />
|-<br />
| '''Shift+MouseOver''' || Mouseover on a token normally displays a statsheet; holding down '''Shift''' turns off the statsheet.<br />
|}<br />
<br />
==Chat Related==<br />
<br />
See [[Chat Commands]] for specifics on the '''/''' commands.<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''/''' || Macro command (press '''Enter''' to complete)<br />
|-<br />
| '''Meta+Enter''' || Toggle chat frame visibility<br />
|}<br />
<br />
==Standard==<br />
<br />
{| class="wikitable" border="1" style="border-collapse:collapse;"<br />
! style="background-color:#e0ddd5;" |Keystroke <br />
! style="background-color:#e0ddd5;" |Description <br />
|-<br />
| '''Meta+O''' || Open Campaign File...<br />
|-<br />
| '''Meta+S''' || Save Campaign<br />
|-<br />
| '''Meta+A''' || Save Campaign As...<br />
|-<br />
| '''Meta+X''' || Cut (tokens only)<br />
|-<br />
| '''Meta+C''' || Copy (tokens only)<br />
|-<br />
| '''Meta+V''' || Paste (tokens only)<br />
|}<br />
<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=Network_Connection_Problems_and_Solutions&diff=8901Network Connection Problems and Solutions2020-08-21T01:53:36Z<p>Lwoestman: /* 3 - The packets make it to your router and are rejected. */</p>
<hr />
<div>== Network Connection Problems and Solutions ==<br />
<br />
This is an import from the Network FAQ PDF v1.7 from [http://forums.rptools.net/viewtopic.php?f=22&t=3370] with a little bit of cleanup. The PDF looks better. :)<br />
<br />
=== Assumptions ===<br />
<br />
MapTool will start. If you do not get the MapTool splash screen or the default '''Grasslands''' background map when you start MapTool, this document will not help you.<br />
<br />
=== Symptoms ===<br />
<br />
When someone else attempts to connect to your server, their MapTool seems to pause for a long time with the ''Connecting'' message and then finally times out and gives up. The error message may say “Connection timeout” or it may be something more generic like “Could not load campaign” (which indicates an inability for the network to pass data back and forth).<br />
<br />
The server running on the hosting computer is not seen by Internet connection testing tools such as [http://CanYouSeeMe.org/]. These testing tools should be started after the MapTool server has been started via the '''File → Start Server...''' dialog. More discussion of these tools is covered after the next section on terminology and theory of operation.<br />
<br />
=== Background Information ===<br />
<br />
MapTool uses TCP/IP to make a connection from each client to the server. Without going into a lot of nitty-gritty detail about how TCP/IP works, I will provide a short (and amazingly accurate) analogy of TCP/IP using the phone system.<br />
<br />
The rest of this section can be skipped if you are confident of your knowledge in networking basics and already know the difference between a “switch” and a “router”. However, forum users will expect you to be familiar with the information in this section if you ask for help there. At a minimum you should be familiar with the terminology.<br />
<br />
==== A simple network ====<br />
<br />
The picture below depicts multiple computers on a local area network (LAN). Each computer is labeled with a ''hostname'' – a name used to uniquely refer to that particular computer. You can think of these names just like the names of your friends, your family, your employer, and so on: when you want to talk to one of these people, you look up their phone number in the phonebook and then pick up the phone and dial.<br />
<br />
[[Image:lan1.png]]<br />
<br />
In the picture, let's assume that PC1 is the MapTool server and PC2 and PC3 are MapTool clients. In order for the clients to contact the server, they need some way to locate PC1 on the network. This is the phonebook look up that was discussed in the last paragraph. One look up technique is called '''DNS''' (Domain Naming Service) and is very common on the Internet. The primary function of DNS is to convert hostnames into IP addresses very similar to the way you use a phonebook to convert a person's name into their phone number. However, if you dial the number of your best friend very often, are you going to have to look it up in the phonebook? Probably not! You probably have it memorized or stored in your local contact list. TCP/IP is the same way: if you know the IP address of a machine you can use that instead of the hostname (and TCP/IP will remember the information itself for a short amount of time).<br />
<br />
MapTool provides functionality similar to DNS called the '''RPTools Registry'''. When you open the '''File → Connect to Server'''... window, you'll see a list of MapTool servers that have registered with [RPTools.net]. This allows a player to just double-click the correct entry in order to attempt a connection. The MapTool client will contact the [RPTools.net] web site and retrieve the IP address of the server. Once it has this information, the client will use the IP address of the server to make a connection. So the IP address is the "phone number" that you use to contact the server. The client now knows how to contact the server and send/receive data. However, the [RPTools.net] technique is only for connecting to MapTool servers outside your own LAN – on your LAN you should pick a server from the '''LAN''' tab. (In fact, it's likely that using the RPTools registry will fail even if your server is working fine; this is discussed in more detail later. This is because ISPs tend to ignore packets coming from your IP address that are destined for your IP address. They think you've misconfigured something so they ignore that traffic!)<br />
<br />
Whenever the client wants to send a packet of data to the server, it prepends the IP address and puts it out onto the network. Each machine between the client and server forwards the packet to the next one in the link. In the picture above, there are no intermediate machines since all machines are connected to the same wire, but when communicating over the Internet there will be tens or hundreds of intermediate machines. An example of an intermediate machine is shown in the next picture.<br />
<br />
When you call your family or friends, the phone number is all you need to make contact. But if they are at work, you may need to use more than a phone number – you may need an extension number as well. In the terms of TCP/IP, that extension number is the '''port number''' that the server allocates when it starts. This port number allows multiple applications on a single machine to be "listening" for incoming phone calls. The default port number for MapTool is '''51234'''. Other default port numbers include 80 for web servers and 25 for email servers. Port numbers less than 1024 are reserved for well-known server applications and those from 1024 to 5000 are reserved for local use, so if you change the MapTool port number, '''be sure to choose one larger than 5000'''!<br />
<br />
In summary, the IP address and the port number uniquely identify an application on the computer and are used to deliver packets between the two computers, the same way that a phone number and extension number uniquely identify a person or department in a company.<br />
<br />
When a MapTool server starts it lets other machines on the same network know of its existence. This is evidenced by the MapTool clients being able to go to the '''LAN''' tab when they choose '''File → Connect to Server'''... and see the server appear in the list. This technique is similar to the phone company giving you a new phonebook that has been updated with new contact information every time someone in your neighborhood changes their phone number! In the real world that doesn't happen, but in the electronic world it's ''required'' because things can change so quickly. (It doesn't really work like this, but this is a functional description and not a technical breakdown of how TCP/IP works! :)).<br />
<br />
<br />
==== Connecting outside your own network ====<br />
<br />
When all of the computers, both server and client(s), are on the same network the situation is pretty simple as we discussed above. But what happens when the server is remote from the clients? In this situation, routing the client's phone call through a lot of other machines is required before the phone rings at the server's location. And if you've ever tried to contact the CEO of a company directly, you can be sure that their secretary is going to run interference!<br />
<br />
[[Image:lan2.png]]<br />
<br />
One of the jobs of the CEO's secretary is to filter incoming messages and decide which ones get to the executive and which ones don't. This is why it can be of more importance to have the secretary's ear than the CEO's! In comparison to a network, the router's job is the same as the secretary's.<br />
<br />
I'm using the term ''router'' pretty loosely here. In this guide, I use the term router to mean any device between your computer and the Internet whose job is to filter network data. The primary goal of a router is to protect your computers from those on the Internet – it doesn't let them succeed in connecting to your computer. Secondary goals are to allow multiple IP addresses within your home while only allocating a single IP address on the Internet. But we're getting ahead of ourselves a little bit...<br />
<br />
In the case of MapTool, when a client calls a server, it's possible that the server's router might block that incoming request. In that situation, the client hears a ring-ring on their end, but the MapTool server never knows that the call was even made because the router blocked it. This will be reported as '''Connection Failed: timeout''' or something similar. In the picture above, any time PC2 or PC3 tries to contact PC1, they have to get through the router first. Most commercial routers have firewall software built into them. Routers that cost thousands of dollars will have more sophisticated firewalls than the "home use" router you bought at the BigBox store, but the goal of filtering traffic remains the same. And that brings us to our next topic...<br />
<br />
==== Port forwarding and UPnP ====<br />
<br />
Most routers, just like most secretaries, can be told that some traffic is more important than other traffic and that it should be routed directly through. Can you imagine how much trouble the CEO would be in if he didn't take his wife's (or her husband's) call in a timely manner? A good secretary can actually figure some of this out on their own. For example, the CEO calls his wife and they chat for a few minutes. When the wife calls back in five or ten minutes, you can bet that the secretary will simply route it straight through. Computer firewalls can be told to do the same thing. This is called '''port forwarding'''.<br />
<br />
Essentially, when a call to a certain IP address and port number is about to be blocked by the router, it will check its exception list. If the exception list says to go ahead and allow the call to proceed, the router forwards the call to the IP address and port number of the CEO's desk. This is what happens when you have a router sitting between your Internet connection (DSL, cable modem, satellite, dial-up, or any other type) and your home computer(s). The router will act as a firewall and not allow any incoming phone calls unless you've specified a list of exceptions. The actual technique for how to accomplish this varies from router to router, so the MapTool forums recommend that the home user visit [http://www.portforward.com/] and search for their particular router model for instructions.<br />
<br />
Note that port forwarding can be turned on and left that way or it can be enabled on the router only when it is going to be used. For security purposes, it is best to only have it turned on when you need it and turn it off when you're done. Note that the router doesn't block outbound calls that the CEO makes; the CEO can pick up the phone and dial his wife without the secretary stopping the call. This is like running a browser and connecting to a web site – the router doesn't get in the way. But if the web site were to try contacting your browser directly, the request would be blocked.<br />
<br />
This is a problem for us: we '''want''' to run a MapTool server and we '''want''' the router to let that traffic through! Because routers (and firewalls) are ''supposed'' to be blocking exactly that kind of traffic, we don't have any choice. We must visit that URL given above and figure out how to configure our routers. Unfortunately, not everyone relishes the idea of reprogramming their router the way I do! Yes, hard to believe, but not everyone is a geek. ''(Geek = cool and trendy computer person, Nerd = not-so-cool and trendy computer person, and Dork = totally un-cool computer-person-wannabe. You see? I told you there was a lot of terminology in this section!)''<br />
<br />
So there's another technique that can be used: the CEO could explicitly tell the secretary something like, "any calls that come in on extension 80 should be routed directly to my desk." Now the secretary can pass calls directly to the CEO and not worry about needing to filter them. Maybe the CEO is expecting a call from a certain individual and wants to take the call immediately. Or perhaps the CEO has a "private line" that the secretary monitors but allows calls to "ring through". Having such an automated system for your router is called '''UPnP''', short for '''Universal Plug-n-Play'''. (An alternative is called '''NAT-PMP''', but they are functionally the same so the second one won't be mentioned again. Besides, MapTool only supports UPnP at this point.)<br />
<br />
If you have turned on this feature on your router, then the MapTool 1.3.b23+ server, or any other program running on your network, can tell the router to allow certain ports through for a limited period of time. You will need to refer to your router manual for instructions on how to verify that this feature is enabled. As mentioned above, you can visit [http://www.portforward.com/] and find your router's manual. If this feature is turned on in your router you can try enabling it in MapTool by checking the '''Use UPnP''' checkbox in the '''File → Start a Server'''... window.<br />
<br />
'''You must not use both port forwarding and UPnP!''' If you try to use both at the same time, most secretaries will simply become confused and not know what to do at all when a call comes in – you don't want that do you?!<br />
<br />
==== Network Address Translation (NAT) ====<br />
<br />
Unfortunately, many companies don't have enough phone lines for each employee to be on the phone all at the same time. (Well, ''maybe'' that's unfortunate. I can think of a few situations where that's not such a bad thing!) When a customer calls the company, they use a single phone number. The switchboard operator for the company will convert the number the customer dialed into the internal number used by the company's phone system (sometimes called a PBX). <br />
<br />
The Internet requires such a feature. There are only a certain number of IP addresses that can be used, so '''network address translation''' was devised to help prevent them from being used up too quickly. For example, the author has a cable modem at home. Connected to the cable modem is a router. This router is assigned a ''public IP address'' by my ISP, but the rest of the computers in the house receive a randomly assigned ''private IP address'' from the router. Most routers use random IP addresses in the range of '''192.168.0.2-192.168.0.100''' or something similar. The computers attached to the router don't realize that they are receiving random IP addresses – they just take what they get and are happy with it! You can use MapTool's '''File → Connection Information'''... menu option to determine what your private IP address is, as well as your public IP address of your router.<br />
<br />
When one of my devices, such as my laptop, makes an outbound connection, the router keeps track of my private IP address so that when the response comes back, it can send the response to my laptop and not to my wife's desktop or the TiVo or the laser printer.<br />
<br />
===== Advanced NAT Scenario =====<br />
<br />
One issue with this technique is that to any computer outside my home the IP address looks the same for every computer inside the house. This is why port forwarding is important. When a call comes in to the router for port '''51234''', the router forwards it to a preprogrammed private IP address. Using this scheme, can I run multiple MapTool servers on my home network and have different outside computers connect to them? It might appear that the answer is "no" because there's only one "port 51234". However, if a different port number is assigned to each MapTool server, the router can be configured to forward each port to a different private IP address. For example, my laptop, my wife's desktop, and my TiVo are all on the same network (not really, but we can pretend they are for the sake of this example). I could forward port 80 on the router to the TiVo, then when I'm out of town on business I could find out which shows the TiVo has recorded by visiting port 80. I could forward port 55555 to my laptop (port 51234) and port 55556 to my wife's desktop (port 51234). Notice how the destination port is the same on those last two, but the public port numbers are different? This would allow multiple MapTool servers on the internal network to be accessed by different outside computers. This is exactly like having a company with multiple public phone numbers. When a customer calls the company, the secretary figures out who the call is for and sends it to the right person. The fact that there are two “John Smith” employees doesn't confuse the secretary because the port forwarding works as a different extension number for each one.<br />
<br />
The last example is probably pretty confusing and there's no shame in going back and reading the last few sentences two or three times. Go ahead... I'll wait.<br />
<br />
Basically, that last example says that the router has two phone extensions configured (ports 55555 and 55556) and each one is sent to a different location inside the company. The first goes to my laptop, the other goes to my wife's desktop. But I don't want to have to change the port number in MapTool, so I just leave it 51234.<br />
<br />
To use a configuration in which the MapTool port number doesn't change, I can't use UPnP. If I did, and I tried to run MapTool on both my laptop and my wife's machine at the same time, the router couldn't accommodate both of us – only one of us could have extension 51234. So I'd have to reprogram the port forwarding manually on the router. This is also not a good choice if you're going to use the RPTools Registry feature since the port number MapTool will give the MapTool registry is not the one your router will be configured for. Remember: when a player tries to connect to your server, they will use the outside extension number. If you've manually set up port forwarding and used a different internal and external port number then the wrong number will be stored in the registry.<br />
<br />
If I was willing to use different ports for MapTool, then I could use UPnP. Because UPnP doesn't require you to reprogram your router, this is the one I recommend. Especially when you consider that you could get a different private IP address every time you power up your computer! (Remember earlier when I said the router will give you a randomly assigned IP address? The truth is that you will probably get the same address every time, but to be safe you should treat it as though your machine gets a different address at each reboot.) This is a much better solution because if you fill in the '''RPTools.net Alias''' field on the '''File → Start Server'''... dialog, this port number that is saved in the MapTool registry and is the port that other clients will attempt to connect to.<br />
<br />
Full disclosure: there are various attacks that can be performed against your router if you have UPnP enabled These attacks can '''only''' occur from '''inside''' your network. While this makes it more difficult for the attack to work, it is possible that a malicious remote user could trick your browser or other software into programming your router to open ports that you didn't want or need to be open. While that is definitely '''A Bad Thing''', then truth is that if you've got malware in your network, having an open port on your router is the least of your trouble! (Remember: any outbound traffic is allowed, including traffic from malware. So the attacker's code can connect to and download additional programs from any site on the Internet if they're inside your network.)<br />
<br />
===== Two Routers and the “Double-NAT” Problem =====<br />
<br />
The big issue with NAT is something called '''double-NAT'''. What if there are '''two''' routers between the outside computer(s) and the inside server? It becomes impossible for UPnP to handle this, and while the configuration of both routers is possible, often the home user doesn't have control over the more public one.<br />
<br />
Sometimes the home user can put the outside router in ''bridged'' mode, which essentially turns off the firewall in that router and tells it to pass all connections straight through. This effectively eliminates that router from the picture. This is a good choice in cases where your ISP has provided you with equipment and your control over that equipment is limited. In all other cases of double-NAT, running a MapTool server will require a VPN solution. Beyond mentioning the Hamachi program (which is popular on the MapTool forums), further discussion of VPNs is beyond the scope of this document. Be sure to ask on the forums if you have this issue. When enough interest is shown, this document will be updated. (It has happened. See FAQ#12 below for more information.)<br />
<br />
By the way, the double-NAT problem is very common in certain circumstances. For example, university dorms, where the student has a router, but the university has their own as well! The university may have their router programmed to block '''ALL''' incoming traffic that is not a response to a previous request. Other examples include hotel wireless, coffee shop wireless, and other public access points.<br />
<br />
==== It's a two-way street ====<br />
<br />
The last thing to point out is that all communication must be two-way to be useful. Yet the secretary on either end will always allow incoming data if the request initiated from that end in the first place! We talked about this above, when we discussed the overall flow of the network traffic. We said that the secretary doesn't get in the way of outbound calls, only inbound calls. And only the server will have inbound calls so only the server needs to have port forwarding configured.<br />
<br />
[[Image:lan3.png]]<br />
<br />
For example, when you type a URL into a browser, the browser makes the outbound request and the router allows the response to come back in. The same thing will apply to MapTool; if the client sends a packet to the server, the client's router will allow the server's response to get through. This is one of the security issues in a router; it cannot block traffic that is a result of a request made by an internal source. (This is the primary issue with cross-site scripting attacks, which is when a script embedded on a web page makes a request that the user doesn't know about and then sends the information to another location, also without the user's knowledge or consent! Since the script is operating from inside the company's router, the router cannot know that it should block the traffic.)<br />
<br />
In the following section, a series of common MapTool connection problems will be discussed, including the symptoms and possible solutions.<br />
<br />
== Step-by-Step Problem Diagnosis ==<br />
<br />
These next steps attempt to solve your network problem without resorting to the (sometimes slow) turn around time on the forums or in Discord. If you head to the forums and don't have the answers to the questions asked by these steps, you'll be directed here and told to start at '''Step 1''' and progress through them until a step fails. Some steps may not apply to your situation and you can skip them. For example, '''Step 5''' discusses wireless clients not connecting while wired clients do; if you're not concerned about wireless clients, you can skip that step. Be prepared to identify which steps you skipped and why you skipped them when you ask for help. There's a section later in the document which describes what information you'll need to provide when you post on the forum. <br />
<br />
'''These steps ''must ''be done in the order presented here or the results are ''meaningless ''!'''<br />
<br />
=== When I click the ''Test Connection ''button on the ''Start Server ''window, I get an error, "unable to see your computer from the Internet." What causes this and how do I correct it? ===<br />
<br />
The '''Test Connection''' button talks to a server on the Internet.<br />
(This button has been replaced with the '''Networking Help''' button in current builds of MapTool. If that's the case for you, check the last paragraph of this step for help.)<br />
Because you're making an outbound call, your secretary (er, router) will be making the actual call for you and is responsible for making sure that all data from you is sent to the other system.<br />
If this server out there on the Internet receives a call from your secretary, it will put the current conversation on hold and call you back using your secretary's IP address and the port number in the '''port number''' field.<br />
This is just like a MapTool client would do if you were the server for an online MapTool session.<br />
But what happens if your secretary doesn't allow that incoming call to go through?<br />
In that case, you'll get the error message referenced in the question, "Unable to see your computer from the Internet."<br />
<br />
To fix this problem, you either need to enable the UPnP option when you start your MapTool server (and configure your router to enable UPnP) or you need to enable port forwarding on your router and configure it to send all requests for extension number '''51234'''<br />
(or whatever port you're using for MapTool) to your computer on the LAN.<br />
'''Don't do both!''' ''(Most routers will require that you give them a private IP address to identify your computer; see the section below, How to Find Network Information in order to determine that number.)''<br />
<br />
Another possible solution is to put the machine that will be running the MapTool server into the router's ''de-militarized zone'' or DMZ. This essentially eliminates all protective services of the router and is not recommended for long-term use. However, if your MapTool server works while your computer is in the DMZ you have narrowed down the problem to an issue with the router.<br />
<br />
It is also possible that your operating system has a firewall installed that blocks the network packets once they arrive at your machine. This will be handled in more detail in '''Step 6''', but keep going through these steps one at a time.<br />
<br />
Also note that if the '''Services.RPTools.net''' server is down or some point between you and that server doesn't forward your request, this test will appear to fail. If you think the problem is that the RPTools server might be down (check the '''Announcements''' forum at [http://forums.rptools.net/] for information), there's currently not another server available for you to try. You can use a public service though. For example, you could start a MapTool server (so that an application is listening on the port) and then test it by visiting [http://www.CanYouSeeMe.org/] using a web browser. You will be asked for the port number that you want to test and you should enter the same value as you gave MapTool when you started the server. The web site will check to see if the secretary is allowing the call in and report either Error or Success.<br />
<br />
===I have a server running, but if I start MapTool again in a separate window ''on the same machine'' it cannot connect as a client! Why not?===<br />
<br />
There must be a firewall or antivirus setting on the server machine that is not allowing connections to the port you used when you started the MapTool server. Unless you change it, the default port is '''51234'''. When connecting to a MapTool server on the same machine, you should be using '''127.0.0.1''' as the IP address — you cannot use an RPTools server alias.<br />
<br />
Linux users: On some distributions we've seen comments in the forums that their machine had incorrect entries in the '''/etc/hosts''' file that caused MapTool to fail. You may want to check your file and ensure that it does not contain an entry for your hostname that points to '''127.0.0.1 '''or '''127.0.1.1'''. If it does, comment out that entry and copy the hostname to the end of the line that contains '''localhost'''.<br />
<br />
=== I have a server running, but clients wired into my local network can't see my server on the "LAN" tab in the ''Connect to Server...'' window. Why not? ===<br />
<br />
When a client selects the '''LAN''' tab, it sends out a request on the LAN for servers to identify themselves. All servers on the LAN are supposed to respond so that they can be shown in the list of machines. Either the server machine is running software that blocks the request from getting to the MapTool application (firewall or virus protection software) or the MapTool client has software that is blocking the server's response so that the client never sees it (this is less likely, but if it is the problem it will be because of a firewall package on the client). <br />
<br />
Try turning off the firewall at one or both ends of the connection and try again. Once you isolate which machine is causing the problem, you can configure the software on that machine to allow traffic through on the specific port that MapTool is using and then turn the software back on again. '''DO NOT LEAVE YOUR FIREWALL TURNED OFF INDEFINITELY!'''<br />
<br />
Note that this automatic discovery process is based on UDP/IP and not TCP/IP. Because it only works on the local LAN, there's no need to allow UDP traffic through your router if you are configuring port forwarding manually on your router. There's more information in the next question.<br />
<br />
=== I have a server running and clients wired into my local network can see the server on the LAN tab, but they get errors when they try to connect! Why doesn't it work? ===<br />
<br />
Different ports are used for locating servers than for connecting to servers. Locating servers is done with UDP (a networking protocol) and connecting to servers is done with TCP (another networking protocol). It's possible that a firewall on one of the machines is blocking TCP but not UDP. This is a rare occurrence though, so if turning off the firewall doesn't fix this problem, post on the '''RPTools.net''' forums for additional help. (Read the very last section at the end of this document for how to post to '''RPTools.net''') <br />
<br />
=== I have a server running and local wired clients can connect, but not those using the same router via wireless! Why not? ===<br />
<br />
This is most likely caused by a router that refuses to send packets from the wireless portion of the network to the wired portion. Some routers may come configured this way to prevent wireless users from accessing your local network – they can only access the Internet in this configuration. You will need to check the manual for your router to determine if this is the case. You might find the information in the router manual under ''wireless bridging'' or ''LAN bridging'' or even just wireless connections to your LAN. You will need to reprogram your router before this step will succeed and you can continue to the next step.<br />
<br />
If you don't have your router manual, you can check at [http://portforward.com/] to see if they have it. You'll need your router's specific model to search for it.<br />
<br />
=== I have a server running and both wired and wireless local clients can connect, but not clients that are on the Internet! Why not?===<br />
<br />
There is likely a device blocking the request as it travels from the client to the server. Common sources for this would be your router or the routers of your ISP. These routers don't block traffic between two machines on the same LAN, which is why local computers can reach the server. This is especially common in university and corporate environments where the owner of the network isn't thrilled about have random packets entering their network from the outside. (Gee, I wonder why not!?)<br />
<br />
You can check the port forwarding configuration of your router, but the problem may be with your network provider's router and I doubt they will let you modify those settings. This can be tested by removing your router from the network completely and plugging your Internet connection directly into your MapTool server machine. If this configuration works, your router was blocking the traffic. If this doesn't work, it was some other hop in the route that is blocking the packet. If you do this, you have removed the protective features of the router, so try to get your router back into place as soon as possible.<br />
<br />
You should also check whether your problem is the '''double-NAT''' problem mentioned in the '''Background''' section at the beginning of the document.<br />
<br />
=== Is it faster for remote clients to connect to my MapTool server using ''Direct ''or through ''RPTools.net''? ===<br />
<br />
They are both the same. The three tabs on the '''File → Connect to Server...''' window simply offer different ways of identifying the public IP address of the server, but once the IP address has been found the client talks directly to the server. If the server was started with the '''RPTools.net Alias''' field filled in with a game name, the client can immediately see which version of MapTool they should be using and they can start the connection by simply double-clicking on the entry in the listbox. This makes it very simple for the client as they don't need to know the IP address or the port number. (They still need to enter a Player Name and a password, if necessary.)<br />
<br />
=== Why does MapTool even have three tabs on the ''Connect to Server...'' window anyway? What are they for? ===<br />
<br />
The '''File → Connect to Server'''... window gives the client three ways to connect to the server. The '''LAN''' tab should only (and '''always'''!) be used by clients who are connected to the same network as the server, such as those wired to the same router as the server or those using a wireless connection to the same router as the server. Those clients will all have the same network subnet mask (this is like an "area code" in the telephone analogy at the top of this document) so packets can flow directly from the client to the server.<br />
<br />
The '''RPTools.net''' tab shows only those MapTool servers that were told to register themselves when the server was started. There is a text field called '''RPTools.net Alias''' on the '''File → Start a Server...''' window that may be filled in or left empty. When empty, the server is private because its information is not sent to '''RPTools.net'''. This means clients can only connect if you give them your public IP address and port number (see the next paragraph).<br />
<br />
When filled in, your server's version number and public IP address (what shows up in the '''File → Connection Information...''' window as the “External IP Address”) is saved on the '''RPTools.net '''server. This allows a client to simply choose the server from a list instead of typing in an IP address — much simpler! And they can see which version of MapTool they need as well. (Note that the '''RPTools.net Alias''' probably will not work to connect from a client to a server when both are on the same LAN! Use the '''LAN''' tab instead. See the first paragraph of this step and read the '''Background''' section, “A simple network,” to learn why.)<br />
<br />
The '''Direct''' tab is for those cases where the server is NOT registered on '''RPTools.net''' (so it's a private server as discussed in the previous paragraphs) and yet the clients still need to connect somehow! The required information is the public IP address and the port number of the MapTool server. The public IP address is available from the '''File → Connection Information...''' menu option.<br />
<br />
=== I'm getting an exception in a popup window while executing MapTool. What does "exception" mean and how do I correct it? ===<br />
<br />
An exception happens when the Java runtime environment detects an error condition that the program hasn't been written to specifically detect. As it turns out, Java requires the programmer to detect and handle some exceptions but not others. The "other" category includes what are called runtime exceptions. Runtime exceptions are things that are unlikely to happen so the programmer doesn't have to account for them, but they can only be detected when the program is executed, not when it's compiled. Examples are things like '''FileNotFoundException''' or '''IOException'''. Here are some of the common exceptions that can occur and things to check as possible problems. This list is not exhaustive; it's just the common ones:<br />
<br />
# '''InvocationTargetException''': This exception is the result of the program trying to convert a string of characters into an object that will be used internally. Examples include converting a hostname into an IP address and converting a dotted-decimal IP address into its internal format. If you see this exception, try to determine if some data that you provided to MapTool had a typo in it and fix the typo.<br />
<br />
# '''ClassNotFoundException''': This exception happens when a Java program tries to locate some code that it needs and can't find it. Common causes include a corrupted installation (try reinstalling) or an incorrect '''CLASSPATH '''setting. (The '''CLASSPATH '''tells the Java runtime environment where to look for pieces of compiled code. It is normally set automatically during the installation process.)<br />
<br />
# '''NullPointerException''': This is a straight-up programming error. :) It represents the program trying to access data using an invalid variable. If you receive one of these, please check to see if it has already been reported on our forums. If not, you may copy and paste the block of text that corresponds to the exception into a posting there for the developers to look at. Note that pasting an image of the error is not helpful, as our programmers can't extract the text information that we actually need.<br />
<br />
=== None of the above are problems for me, yet one specific network card for one particular computer doesn't work. Do you have any ideas? ===<br />
<br />
There have been reports that many network cards might require that certain options be modified on Windows systems. There are no reports of macOS- or Linux-specific cases of this problem.<br />
<br />
To check this, open the '''Windows Device Manager''' and open the properties for your network interface. In the '''Properties''' tab should be a drop-down list of various options for your hardware. The two that most frequently are problems are '''Hardware Checksumming''' (also called '''Checksum Offload''' and other names) and '''Jumbo Frames'''. The first one tries to do some math related to error checking on the network card instead of using your computer's CPU and while this is a good idea in general, sometimes the card doesn't get it right and network packets are considered corrupted by other computers when they really aren't. The second one is a similar issue where larger packets than normally allowed on a network are sent, confusing other machines on the network. If these features are turned on, turn them off and see if that helps, or vice versa. (You may need to reboot after changing these settings as some drivers only apply changes when they are initialized.)<br />
<br />
Some users who have upgraded to Windows 7 have had problems with Atheros network cards. The problem appears as an inability for clients to connect – and stay connected – to the MapTool server, typically with an error on the client about “unable to load campaign”. This appears to happen with the Atheros cards that identify themselves as '''AR8121/AR8113/AR8114 PCI-E Ethernet Controller(NDIS6.20)'''. This is discussed more at [http://forums.rptools.net/viewtopic.php?f=3&t=11916&start=30] To correct the problem:<br />
<br />
From '''Network Connection / Adapter Settings''': Atheros network adapter properties → Advanced tab → Transmit Buffers property. My default value was '''256'''. Changing the value to '''512''' solved the problem.<br />
<br />
=== What if MapTool chooses the wrong network interface? ===<br />
<br />
You might find that the '''Local Address''' reported by MapTool is not the one that you think should be used. For example, you might know that your router hands out private IP addresses in the range of 192.168.1.x and yet MapTool is reporting a number such as 0.1.0.4 in the '''File → Connection Information...''' window. It might be that Windows has assigned an IP address to a device and MapTool is using that address and not the one for your actual network. Some web camera drivers do this under Windows or I wouldn't have bothered to mention it here. :)<br />
<br />
If this is the situation for you, you can change which interfaces are searched first when an application runs by changing the '''Network Binding Order'''. Under Windows XP, go to the '''Control Panel''' and open the '''Network Connections''' window. Go to the '''Advanced Menu''' and then '''Advanced Settings'''. Under the '''Adapters and Bindings''' section, select the device with the bogus IP address and use the arrows to move it so that it appears below your normal network device (either your wired or wireless network). Click '''OK''' to save your changes and exit the window. (Thanks to '''Phergus''' on our forums for this information.)<br />
<br />
Other operating systems are not likely to have this problem, but searching Google for "network binding order" or "interface binding order" should help you find the documentation for your operating system.<br />
<br />
=== Are there other network interface issues I need to know about? ===<br />
<br />
One user on the RPTools forum has indicated that their modem hardware created a '''Network Connection''' and the '''Services''' tab had '''Static NAT''' configured. Clearing that option allowed the '''Test Connection''' feature of MapTool to work. Apparently, they were a victim of the "double-NAT" discussed above.<br />
<br />
Another issue that has been reported on the forum is that the Cisco VPN client needs to be disabled for the duration of the MapTool server session. This probably has something to do with the VPN software adding itself to the top of the '''Network Binding Order''', as discussed in the previous question, but that has not been verified by this author. Other VPN software applications may require the same fix.<br />
<br />
It's possible that the organization that provides your Internet access is blocking certain types of access. This is common on University campuses, for example. In this case, you may wish to try '''Hamachi''' as it can work around this issue. Essentially, the Hamachi folks provide a server on the Internet. All of the machines that need to be connected connect to the Hamachi server. This server gives you a "private IP network" that only applies to your collection of machines, and each machine in your private network is given a different virtual IP address. Now you can use MapTool with those virtual IP addresses and everything will work! You'll need to use the '''Direct''' tab when clients are connecting to the server because the RPTools Registry will have the router's external IP address and not the Hamachi address. The reason this works is that each machine is connecting to the Hamachi server, so all connections are outbound connections – and outbound connections are rarely blocked because people wouldn't be able to reach web servers if they were! Hamachi provides a virtual private network amongst your group of machines. There are other techniques that can accomplish the same thing. OpenVPN is one competitor but it's meant for true enterprise-level networking and is not the simplest thing to configure. And regardless of which software package you use, you'll need at least one machine that is visible from the Internet to act as the VPN server – the folks at Hamachi provide that server for you.<br />
<br />
Many users of MapTool also use a voice-over-IP solution as well. The most popular (based on the forums at RPTools.net) appear to be '''Ventrilo''', '''TeamSpeak''', and '''Skype''' (and lately, '''Discord''' is extremely popular). And lately, the '''Dolby Axon''' software has been getting good reviews, although there are no Mac nor Linux clients yet. Lately, '''Mumble''' and '''Oovoo''' have seen comments from satisfied users – Mumble (open source) can emulate the other programs, and Oovoo provides video feeds in addition to audio. They each have their pros and cons, so if you haven't tried any of them you may want to give each one a fair shake before settling on a particular package. And check the RPTools.net forum as comparison threads pop up regularly as each one leapfrogs the others in capabilities. At the time of this writing, '''Discord''' seems to have the majority of users (it has audio as well as video capable, and includes screen sharing as well). If you're going to be using Ventrilo and you have Mac or Linux users in your gaming group, be sure to configure the Ventrilo server to use the '''Speex''' audio codec, since it's the only non-proprietary one that's supported and hence, the only one available for macOS and Linux.<br />
<br />
== How to Find Network Information ==<br />
<br />
There are times when you'll need your network information in order to configure your router or your computer. The important information is in the table below. You should locate that information (examples below) and fill in the third column, as you'll probably need it to configure port forwarding on your router.<br />
<br />
{| class="wikitable" border="1"<br />
<br />
! Information needed !! Comparison from the telephone analogy !! Your specific value<br />
|-<br />
| IP Address || Your phone number on the network ||<br />
|-<br />
| Gateway Address || The phone company you get your service from ||<br />
|-<br />
| Network (subnet) mask || Similar to an area code ||<br />
|}<br />
<br />
'''IP Address''' – this is your "phone number" on the network. In a home network, it's typically a private IP Address in the range of 192.168.x.x or 10.x.x.x or even 172.12.x.x-172.16.x.x.<br />
<br />
'''Gateway IP Address''' – this is the name of the secretary in your office. In other words, your router's private IP address. :) Your router also has an IP address used to connect to your ISP, but that one is called the WAN Address.<br />
<br />
'''Network Mask''' (also called Subnet Mask) – this is the area code of the phone book that you are listed in. In simple networks, this number can be wrong and data might still be delivered properly, but if you're connected to the Internet, it's important that the subnet mask be correct.<br />
<br />
For a home network it is very likely that IPv4 is being used. This is a relatively short sequence of four numbers with periods between the numbers. The '''Network Mask''' is also expressed using this format. Here is an example: '''192.168.42.87''', network mask '''255.255.255.0'''<br />
<br />
The best way to determine the IP information is to use MapTool itself. This is because your computer might have multiple IP addresses and you won't know which one MapTool is actually using. From the '''File''' menu, choose '''Connection Information...''' You'll get both your local address (your IP address on the LAN) as well as your external address (the address that Internet clients should use). Note that the local address is ONLY used by clients directly on your LAN such as those wired into the same router or those using a wireless connection to that router, while the external address is ONLY used by clients outside of your LAN. In some cases they may be the same value, but that doesn't change the previous sentence. :)<br />
<br />
[[Image:lan4.png]]<br />
<br />
<br />
In the example above, my LAN IP address is '''10.4.15.176''' and my external address is '''12.48.201.241'''. If I had clients on my LAN (such as friends who were sitting around the table with me), I would have them use the LAN tab and they wouldn't need an address at all. Or I could give them the local address and they would use the Direct tab. If there were others who were logging in remotely, I would fill in the '''RPTools.net Alias''' field and let them use the RPTools tab, unless I didn't want my game listed in the registry. Then I'd give them the external address and they would use the Direct tab also. (That example is from a recent hotel visit. Using UPnP, I have been able to host MapTool servers from both wired and wireless Internet connections while traveling.)<br />
<br />
There is also a tool on the '''Help''' menu, '''Gather Debug Info...''' When using it to gather your machine's configuration, do not remove any information from what you report on the forum. People get freaked out for some reason over their public IP address or their gateway address being listed, but none of that is information that isn't already publicly available. And in fact, ''must'' be publicly available or your Internet connection wouldn't work in the first place!<br />
<br />
On Windows, you can double-click on the network connection icon in the system tray and then click on the '''Support''' tab and the '''Details...''' button to see all of the details. Use this technique to obtain the gateway address and the network subnet mask. On macOS, full details are available in the '''System Properties''' under the '''Network''' application.<br />
<br />
=== When all else fails, here's what you need to post on RPTools.net for others to help you ===<br />
<br />
First, you'll be asked if you went through the diagnostic steps above. If you haven't, no one may answer your post. However, if you've taken the time to go through those steps and you post the results of each step, you're likely to get an answer very quickly.<br />
<br />
Second, you will likely be asked if there are any exception popup windows. This will be useful information for the community in helping you resolve your issue. If you get an exception, use copy/paste and include it in your forum post. If you miss the exception for some reason, they are also stored in a file called '''log.txt''' in a directory named '''.maptool-rptools''' – you can use your system's Search function to find the file (it'll be under whatever your operating system defines as your “home directory”).<br />
<br />
When posting to the forum include the following information about your system. Most of this can be obtained using the troubleshooting tools referred to above under the How to Find Network Information heading:<br />
<br />
# Version of MapTool itself;<br />
# Version of Windows, Linux, or macOS;<br />
# Version of the Java Runtime Environment;<br />
# Contents of the '''Help -> Gather Debug Info...''' window (use copy/paste, not a screen shot);<br />
# IP address reported as the Local Address in MapTool's Connection Information... window; and<br />
# How far you've gotten in the list of FAQ steps as described above.<br />
<br />
And if you have any comments or additions for this FAQ, please make them known! If something would help even one person, then we want to include it here. Thank you!<br />
<br />
== Examples ==<br />
<br />
This user was able to accomplish steps 1 through 4 and step 5 didn't apply to them. But step 6 failed. This scenario is based on server machine S and remote player P. Local machines inside the same home were able to connect to S, but the remote player cannot.<br />
<br />
==== 1 - The packets from P are being blocked by the player's router as they leave his machine. ====<br />
<br />
Very unlikely. Most home routers will automatically pass anything from the LAN to the WAN (from the local network to the Internet) without restriction.<br />
<br />
==== 2 - The packets from P make it onto the Internet, but never get to your router. ====<br />
<br />
Possible, but also unlikely. This would require that some router between your player and you is choosing to dump the packets in the bit bucket. While this is possible, the routers comprising that portion of the Internet are typically managed by experienced personnel and such an issue would be detected and corrected very quickly.<br />
<br />
==== 3 - The packets make it to your router and are rejected. ====<br />
<br />
This is quite likely because one of the primary purposes of a router is to block unknown or unexpected traffic from getting inside. That's why routers are capable of protecting your LAN in the first place!<br />
<br />
Configuring the router to block most traffic but allow some traffic through is called port forwarding. You can configure this permanently on the router (this FAQ references http://www.portforward.com/ for model-specific instructions) or you can hope your router is new enough to support UPnP and has it enabled (it probably does) and you can enable that feature when you start the MapTool server.<br />
<br />
==== 4 - The router is allowing the packet through, but machine S is blocking it. ====<br />
<br />
It is not likely that S is blocking the traffic as other machines on the LAN have connected successfully (based on the background in the first paragraph). As I said above, some computer firewalls might be able to block non-local traffic, but these software firewalls are not typically installed on home machines.<br />
<br />
==== 5 - Machine S is receiving the initial connection request, but its response is blocked by the router between S and the Internet. ====<br />
<br />
This is possible, but also unlikely. As mentioned under #1 and #4, the router's job is to allow outbound traffic and block incoming traffic. It's unlikely your router is blocking the outbound response.<br />
<br />
==== 6 - Same as #2. ====<br />
<br />
Unlikely to be the problem for the same reasons as #2.<br />
<br />
==== 7 - When the response gets to your player's router, it blocks the response from going in. ====<br />
<br />
The response is marked as such: a response. The router will block such a packet if and only if the packet does not correspond to an outbound request. In this case, it does correspond to a request made by machine P. For example, player P wants to open a connection to IP address 1.2.3.4. His router passes the packet onto the Internet. The response comes back from IP address 4.3.2.1 (instead of 1.2.3.4). The router will ignore it and not deliver it to player P. The end result is a Connection Timeout error by player P.<br />
<br />
There you have a sample of the troubleshooting process. More will be added over time.</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=MapTool_Preferences&diff=8899MapTool Preferences2020-08-20T20:53:19Z<p>Lwoestman: /* Advanced Options */</p>
<hr />
<div>{{note|'''Note:''' Screenshots in this article are shown with the default settings, which might not necessarily be the ''recommended'' settings for your use.}}{{Beginner}}<br />
__TOC__<br />
==Interactions Tab==<br />
[[Image:prefs_tab_interactions.png|left|thumb|300px|Interactions Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Maps===<br />
[[Image:Prefs_Interactions_Tab_-_Maps.png|frame|right|Maps Section]] <br />
* '''New maps have Fog of War'''<br />
: Determines if new maps should have [[Fog of War]] enabled when created. If you use [[Fog of War]], it might seem obvious to have this {{Checked}}; however, when creating multiple maps for a new campaign, it is often useful to to disable this feature to assist with rapid map creation since even as a GM you will be unable to clearly view a map covered in [[Fog of War]]. After completing a map, it is a simple process to re-enable [[Fog of War]].<br />
* '''New maps visible to players'''<br />
: Determines if new maps should be set as Player Visible when created. Although there are exceptions, typically having this <span style="font-size: 24px; line-height: 1px; color: red; font-weight: bold; vertical-align: sub;">&#10003;</span>unchecked is the optimal setting; that way you won't unintentionally leave a map visible to players.<br />
* '''New Map Grid Type'''<br />
** '''Square''' [[Image:gridSquare.png|sub]]<br />
** '''Horizontal Hex''' [[Image:gridHorizontalHex.png|sub]]<br />
** '''Vertical Hex''' [[Image:gridVerticalHex.png|sub]]<br />
** '''Isometric''' [[Image:gridIsometric.png|sub]]<br />
: Determines the default grid type of new maps when created. You are free to create maps without a grid type, and also a grid type different than the one specified here, but you can not set the Default Grid Type to none.<br />
* '''New Map Grid Size'''<br />
: Represents the default amount of pixels you want MapTool to use drawing each grid cell at full resolution. The default setting of {{code|50}} pixels is adequate for most computers, but higher-end computers can handle {{code|100}} pixels or even {{code|200}} pixels for very high-end computers. There is no requirement that you use specific sizes, but {{code|50}} pixels and {{code|100}} pixels are commonly used. This setting will also determine how large an image appears when placed on a map layer when 'Start Freesize' is not checked for that layer.<br />
* '''New Map Units Per Cell'''<br />
: Sets the amount of units that each grid cell represents. The ambiguous "unit" is used in this case because you decide what "unit" means. If you want each grid cell to represent 5 feet, this would be set to {{code|5}}. If you want each grid cell to represent 4 kilometers, this would be set to {{code|4}}. This is often referred to as ''Distance Per Cell''. As of v1.5.1 MapTool supports a floating point number for this value.<br />
* '''New Map Vision Distance'''<br />
: The maximum distance that [[PC Token]]s can expose [[Fog of War]] after [[Light]]s, [[Sight]]s, and [[Vision Blocking Layer]]s are taken into account. It is important to note that this setting is measured in ''Distance Per Cell''.<br />
* '''New Map Light'''<br />
: The light setting for new maps. Choose from ''Off'', ''Day'' and ''Night''. (As of MT v1.5.11)<br />
* '''Movement metric'''<br />
** '''ONE_TWO_ONE''' specifies that every second diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''ONE_ONE_ONE''' specifies that diagonal movement will calculate the same as non-diagonal movement. <br />
** '''MANHATTAN''' specifies that every diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''NO DIAGONALS''' specifies that [[Token]]s can only move non-diagonally.<br />
: Determines how movement should be calculated when a [[Token]] moves diagonally on maps using a Square or Isometric grid. This affects the total distance displayed beneath a [[Token]] when it is moving, or when its previous path is displayed; it is calculated based on ''Distance Per Cell''. Maps with Hex grid types ignore this setting and instead calculate movement in any direction using the ''Distance Per Cell''.<br />
<br />
===Tokens===<br />
[[Image:Prefs_Interactions_Tab_Tokens.png|frame|right|Tokens Section]] <br />
* '''Start Snap to Grid'''<br />
: Determines if [[Token]]s will default to having '''Snap to Grid''' {{Checked}}. Having this setting {{Checked}} is optimal for maps that use a grid, but even on such maps there are cases when you might want to temporarily disable this setting(e.g. when placing a lot of "prop" [[Token]]s on the Object layer while drawing a map). <br />
* '''New tokens visible to players'''<br />
: Determines if new [[Token]]s have the '''Visible''' option {{Checked}} upon creation. The optimal setting for this really depends on your play style; if you have a lot of random encounters and build them during play, you may find it useful to have this setting disabled. <br />
* '''Warn when tokens are deleted'''<br />
: When {{Checked}} MapTool asks for confirmation whenever deleting a [[Token]].<br />
* '''Duplicate Token Numbering'''<br />
** '''Increment'''<br />
** '''Random'''<br />
: Will automatically generate numbers for [[Token]]s with duplicate names upon creation to distinguish them. '''Increment''' will leave the first token unnumbered, but will number each duplicate after that starting with the number {{code|1}} (e.g. Troll, Troll 1, Troll 2). '''Random''' will create a random two-digit or greater number for the token, even if there are no duplicates on the map yet. '''Random''' might be considered the optimal setting, as it gives your players no indication of how many copies of that [[Token]] can be expected to exist.<br />
* '''Show Numbering on'''<br />
** '''Name'''<br />
** '''GM Name'''<br />
** '''Both'''<br />
: Specifies where the number that derived from '''Duplicate Token Numbering''' is applied. '''Name''' appends the number after the name (derived from '''New Token Naming'''). '''GM Name''' places the number within the ''GM Name'' field of the [[Token]] options. '''Both''' appends the number after the name, and places it within the ''GM Name'' field of the [[Token]] options. <br />
: <span style="color:red;">'''Note'''</span>: It is generally recommended that you set this preference to '''Name''' or '''Both''', and not '''GM Name'''. Any [[Macro Introduction|Macros]] which refer to tokens by name rather than by token ID will break/behave unpredictably when a map has multiple tokens with the same name.<br />
* '''New Token Naming'''<br />
** '''Use Filename'''<br />
** '''Use "Creature"'''<br />
: Determines what the name will be when creating a new [[Token]], or what the ''Name'' field will be pre-filled with in a new [[Token]] dialog. '''Use Filename''' specifies that the name will be derived from the name of the file that was added to your Resource Library (e.g. if you add the file ''uglytroll.jpg'' to your Resource Library, tokens created from that image will begin with the name ''uglytroll''). '''Use "Creature"''' defaults all new [[Token]]s to being named "Creature" (without quotes). <br />
* '''Start Freesize'''<br />
: If you are using a map with a grid, [[Token]]s typically default to the size of one grid cell upon creation. Having this setting {{Checked}} allows you to have them default to the image's ''Native Size''. ''Native Size'' tokens moved to another layer become ''Freesize'', which can be resized by dragging a handle in their lower right corner.<br />
* '''Show Dialog on New Token'''<br />
: When this setting is {{Checked}}, a ''New Token'' dialog will open when you drag an image onto the map, allowing you to set some options prior to creation. If you disable this setting, all new tokens will be created with the default settings derived from previous settings in this section.<br />
* '''Stat Sheet Portrait Size''' ''(Set to 0 to disable portaits)''<br />
: Sets the width (in pixels) of the portrait that is displayed in the lower left corner of the map when mousing over certain [[Token]]s; the image is resized proportionately. A portrait is displayed under a few different circumstances; if the [[Token]] has properties that are set to display on the stat sheet, and those properties have values, the portrait will display the token image. If the [[Token]] has a portrait image set, it will display with or without a stat sheet. Why might you want to set this to {{code|0}}? Besides the obvious reason of not displaying the portrait, you might want to use a stat sheet, but not want a portrait displayed with it; or perhaps you don't want to use a stat sheet or a portrait, but would like to have the portrait image 'slot' usable for other purposes, like inside a Dialog or Frame.<br />
* '''Show Portrait on mouseover'''<br />
: When {{Checked}}, displays the token's Portrait image in the lower left corner when the cursor is hovered over the token.<br />
* '''Show stat sheet on mouseover'''<br />
: When {{Checked}}, displays the token's stat sheet in the lower left corner (to the right of the portrait) when the cursor is hovered over the token.<br />
* '''Stat sheet requires Shift key'''<br />
: Requires the Shift key be held down when the cursor is hovered over the token in order to display the stat sheet when {{Checked}}. Has no effect if ''Show stat sheet on mouseover'' is unchecked. MapTool only checks if the Shift key is depressed when the cursor first passes over a token and then either displays or suppresses the stat sheet, meaning you cannot use this setting to 'toggle' the statsheet on and off with the shift key without also moving the cursor.<br />
* '''Force Token Facing Arrow'''<br />
: Displays a yellow facing arrow on all tokens with a facing value when {{Checked}}, even on top-down tokens which normally omit them.<br />
* '''Snap Token while dragging'''<br />
: Tokens will snap to the grid as they are dragged when {{Checked}}. When unchecked, the token's path and destination are still highlighted.<br />
* '''Hide Mouse Pointer while dragging'''<br />
: MapTool hides the cursor arrow while dragging tokens within the map view when {{Checked}}.<br />
<br />
===Chat===<br />
Chat autosave settings now reside in the 'Application' tab of the Preferences window. <br />
[[Image:prefs_interactions_chat.png|frame|right|Chat Section]] <br />
* '''Show Avatar per line'''<br />
: The image for the impersonated token is shown next to any chat output it creates, when this is {{Checked}}. This is a client-side setting and does not effect any other clients connected to the same game.<br />
* '''Insert Smilies'''<br />
: Replaces common smiley(emoticon) character sequences with graphical smilies when this is {{Checked}}. If you use a lot of macros, it is recommended that you turn this off, as it could cause some complications if any of your macro code is interpreted as a smiley.<br />
* '''Use ToolTips for Inline Rolls'''<br />
: Sets the default display ([[:Category:Display Roll Option|Display Roll Option]]) for rolls in the chat panel. Will use {{roll|tooltip}} if this is {{Checked}}, otherwise it will default to {{roll|expanded}}.<br />
* '''Suppress ToolTips for MacroLinks'''<br />
: MacroLinks normally show tooltips that state information about the link target as an anti-cheating device. When {{Checked}}, these tooltips are disabled.<br />
* '''Typing Notification Duration Seconds'''<br />
: The number of seconds before typing notifications in the top left of the Map View disappear after a player's last keystroke.<br />
* '''Typing Notification Color'''<br />
: Color of the text for typing notifications.<br />
* '''Show Chat Notification Background'''<br />
: When {{Checked}} shows a graphic behind typing notifications. Can be helpful to provide consistently contrasting background for the notifications.<br />
* '''Trusted Prefix Background'''<br />
: Sets a custom background for macro output that comes from a [[Trusted Macro]].<br />
* '''Trusted Prefix Foreground'''<br />
: Sets a custom foreground (text color) for macro output that comes from a [[Trusted Macro]].<br />
<br />
===Macro Editor===<br />
[[Image:Prefs_Interactions_Tab_Macro_Editor.png|frame|right|Macro Editor Section]]<br />
* '''Style Theme'''<br />
: Select from a variety of themes for macro editor windows.<br />
<div style="clear: both"></div><br />
<br />
===Objects===<br />
[[Image:Prefs_Interactions_Tab_Objects.png|frame|right|Objects Section]] <br />
* '''Start Snap to Grid'''<br />
: Tokens created on map's Object layer will automatically be set to '''Snap to Grid''' if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Tokens created on a map's Object layer will automatically be set to '''Freesize''' if this is {{Checked}}.<br />
<br />
===Backgrounds===<br />
[[Image:Prefs_Interactions_Tab_Backgrounds.png|frame|right|Backgrounds Section]] <br />
* '''Start Snap to Grid'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Snap to Grid''', if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Freesize''', if this is {{Checked}}.<br />
<br />
===Facing===<br />
[[Image:Prefs_Interactions_Tab_Facing.png|frame|right|Facing Section]] <br />
* '''On Edges'''<br />
: A token's facing will snap to the edges when {{Checked}}. Edges are the lines that make up a grid cell.<br />
* '''On Vertices'''<br />
: A token's facing will snap to the vertices when {{Checked}}. Vertices are the points that connect the lines that make up a grid cell.<br />
<br />
==Accessibility Tab==<br />
[[Image:prefs_tab_accessibility.png|thumb|right|300px|Accessibility Tab on the Preferences Dialog]]<br />
* '''Chat Font Size'''<br />
: The default size of the font in the chat panel; measured in points.<br />
* '''ToolTip Initial Delay'''<br />
: The time it takes for a tooltip to display when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
* '''ToolTip Dismiss Delay'''<br />
: The time it takes for a tooltip to disappear when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
<br />
<div style="clear: both"></div><br />
<br />
==Application Tab==<br />
[[Image:prefs_tab_application.png|left|thumb|300px|Application Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Save===<br />
[[Image:prefs_application_save.png|frame|right|Save Section]] <br />
* '''Campaign autosave every [ ] min'''<br />
: Saves an autosave copy of your campaign in the interval specified in <code>%{appHome}/autosave</code>. This will not overwrite your campaign file, but rather create a file which is updated every time it automatically saves. Autosave is only a temporary file, useful in case MapTool crashes. When MapTool is properly closed, the Autosave file is deleted. Note the interval is the time between the last save completing and the start of the next one.<br />
: As a troubleshooting aid, the AutoSaveManager will switch from measuring the autosave interval in minutes to seconds when the [[log.setLevel|log level]] for that package is set to “DEBUG”.<br />
* '''Save reminder on close'''<br />
: Displays a dialog when attempting to close the program with unsaved changes to your campaign when {{Checked}}.<br />
* '''Time between chat log autosaves'''<br />
: The amount of time in minutes between the autosaving of the chat log.<br />
* '''Autosave chat log filename'''<br />
: The filename that will be used when automatically saving your chat log.<br />
* '''File Sync Directory'''<br />
: Specify a path to a local cloud-synced directory to determine relative path external files such as Hero Lab portfolios.<br />
* '''1.3b50 Compatability Mode''' <br />
: <code>This setting has been removed. You can use File > Export Campaign As... to save campaigns for MapTool versions as far back as 1.4.0.</code><br />
: Due to some changes in how certain data is stored in the campaign file in versions after 1.3b50, they might not be compatible with version 1.3b50 and earlier. If this is {{Checked}} your campaign will be saved in the older format, allowing it to be opened in older versions, but losing some of the new features.<br />
<br />
===Map Visuals===<br />
[[Image:Prefs_Application_Tab_Map_Visuals.png|frame|right|Map Defaults Section]] <br />
* '''Halo line width'''<br />
: Controls the width of the [[Halo]] border when it is displayed on a [[Token]].<br />
* '''Use halo color for vision'''<br />
: When this setting is {{Checked}}, hovering over a token with [[Vision]] overlays the token's visible area with the token's [[Halo]] color. This overlay is a translucent layer controlled by the '''Halo opacity''' setting. <br />
* '''Halo opacity'''<br />
: Controls the opacity of the optional overlay enabled by the '''Use halo color for vision''' setting. This does not control the actual [[Halo|Halo's]] outline opacity, which is always completely opaque. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Aura opacity'''<br />
: Controls the opacity of color overlays provided by [[Aura|Auras]] enabled on tokens. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Light opacity'''<br />
: Controls the opacity of color overlays provided by [[Introduction_to_Lights_and_Sights#Light_Sources|Light Sources]] enabled on tokens. This also affects 'personal' lights defined in a token's [[Vision]] setting. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Fog opacity'''<br />
: Controls the opacity of the black layer of 'Soft Fog' that is left in previously explored areas when [[Fog of War]] is enabled. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Auto-expose fog on token movement (GM Only)'''<br />
: Will automatically expose [[Fog of War]] after moving a [[Token]] if {{Checked}}. This setting is intended to help test Fog of War and VBL when not hosting a game. When running a server, this setting is ignored in favor of the settings in the 'Start Server' dialog.<br />
<br />
===Performance===<br />
[[Image:Prefs_Application_Tab_Performance.png|frame|right|Performance Section]]<br />
* '''Fill selection box'''<br />
: When {{Checked}}, the selection box which appears when dragging to select tokens in the Map View will contain a translucent blue fill. Less powerful devices running MapTool may see a small performance gain from unchecking this setting.<br />
* '''Frame Rate Cap''' <code>New in MapTool 1.5.7</code><br />
: Sets the maximum frame rate for the map renderer. Less powerful devices running MapTool may see a performance gain by lowering this setting.<br />
<br />
===Initiative Defaults===<br />
[[Image:Prefs_Application_Tab_Initiative_Defaults.png|frame|right|Initiative Section]]<br />
* '''Hide NPCs from players on new maps'''<br />
: When {{Checked}}, automatically enables 'Hide NPCs' in the [[Initiative Panel]] on new maps. This setting doesn't show connected players [[NPC Tokens]] on the Initiative Panel.<br />
* '''Give Owners Permission in new campaigns'''<br />
: This automatically enables the 'Owner Permissions' setting in the [[Initiative Panel]] on new maps when {{Checked}}. The setting mainly lets players with token ownership add their tokens to or remove their tokens from the initiative list and advance the initiative when it is their token's turn.<br />
* '''Lock Player Movement in new campaigns'''<br />
: When {{Checked}}, new maps will have 'Lock Player Movement' automatically enabled in the [[Initiative Panel]]. This setting prevents players who do not own the token with initiative from moving any tokens.<br />
* '''Show Initiative Gain Message'''<br />
: When initiative advances to a [[PC Token]] token and this is {{Checked}}, a simple 'Token Name has received initiative' message is displayed for all players in chat. This is ignored for [[NPC Token|NPC Tokens]].<br />
<br />
===Client===<br />
[[Image:Prefs_Application_Tab_Client.png|frame|right|Client Section]]<br />
* '''Fit GM View'''<br />
: When {{Checked}} and the GM uses 'Center Players on Current View', the Map View will zoom out as necessary to accommodate the entire GM view. If unchecked, the zoom level will be set to match the GM's Map View, which will occlude part of the map if your Map View areas are different sizes.<br />
<br />
===Macro Panels===<br />
[[Image:Prefs_Application_Tab_Macro_Panels.png|frame|right|Macro Panels Section]] <br />
* '''Default: Allow Players to Edit Macros'''<br />
: In order for a macro to be considered a [[Trusted Macro]], players must not be able to edit it. This setting determines if a new macro should default to allowing players to edit if {{Checked}}. Disabling this setting can be very useful if you intend to create a lot of macros that you intend to be trusted.<br />
<br />
===UPnP===<br />
[[Image:Prefs_Application_Tab_UPnP.png|frame|right|UPnP Section]]<br />
* '''Discovery Timeout'''<br />
: The timeout period in milliseconds MapTool will wait when searching for UPnP gateways before giving up.<br />
<br />
===Macro Permissions===<br />
[[Image:Prefs_Application_Tab_Macro_Permissions.png|frame|right|Macro Permissions Section]]<br />
* '''Enable External Macro Access'''<br />
: When {{Checked}}, [[Introduction to Macro Writing|Macros]] may call functions that access your drive and http services. Some examples (not a complete list) of functions which will be enabled are [[RESTful Functions Overview|REST Functions]], [[exportData]], and [[getEnvironmentVariable]].<br />
<div style="clear: both"></div><br />
<br />
==Sounds Tab==<br />
[[Image:prefs_tab_sounds.png|thumb|right|300px|Sounds Tab on the Preferences Dialog]]<br />
* '''Play system sounds'''<br />
: When {{Checked}}, MapTool will play a sound when new content is sent to the chat panel.<br />
* '''Play streams'''<br />
: When {{Checked}}, streams started with [[playStream]] will be allowed to play.<br />
* '''Only when window not focused'''<br />
: When {{Checked}}, the sound that MapTool plays when new content is sent to the chat panel will only play if MapTool is not the application that has focus.<br />
* '''Turn on Syrinscape Integration'''<br />
: When clicking <code>syrinscape-fantasy:</code> links in MapTool, the Syrinscape Fantasy Player will be allowed to automatically open when this setting is {{Checked}}. This has no effect on [[Syrinscape Integration]] using the REST API and Online Player.<br />
<br />
==Startup Tab==<br />
[[Image:Prefs_Startup_Tab.png|thumb|300px|frame|left|Startup Tab of Preferences Dialog]]<br />
<div style="clear: both"></div><br />
<br />
===JVM Memory Settings===<br />
[[Image:Prefs_Startup_Tab_JVM_Settings.png|frame|right|JVM Memory Section]]<br />
These preferences are somewhat advanced. To better understand how MapTool uses memory settings, read about [[Stack Size]]. If you are having Stack Overflow errors and need to modify these settings for more reliable performance, read about [[Avoiding Stack Overflow]]. If you need help resetting MapTool memory settings, check out [https://www.rptools.net/2019/04/resetting-maptool/ Resetting MapTool JVM Settings] on the RPTools blog.<br />
<br />
These three settings are memory sizes in bytes. The letter at the end can be K, M, or G signifying Kilobytes, Megabytes, or Gigabytes. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Maximum heap size (-Xmx)'''<br />
: The maximum amount of total memory (RAM) MapTool can use at once, usually entered in Gigabytes (G). For heavy frameworks with many assets, you may have to raise this value. 4G is a generous default value for nearly all users with at least 8GB of RAM.<br />
* '''Initial & minimum heap size (-Xms)'''<br />
: The minimum amount of memory (RAM) which MapTool will always reserve for use, usually entered in Gigabytes (G). Oracle recommends this setting be the same as the Maximum heap size. Doing so may provide performance gains by reducing garbage collection operations. This value should not be higher than the Maximum heap size.<br />
* '''Thread stack size (-Xss)'''<br />
: The memory each particular Java thread has reserved for its use, usually entered in Megabytes (M). Raising this value may allow more complex macros to be run, but it should generally be kept as low as possible. 4M is a generous default value that allows most macros to work just fine. To help understand this value, a simple campaign using short macros or no macros may be able to run successfully with a value as low as 256K, while a campaign containing extremely large macros may need 5M or 6M to avoid stack overflow.<br />
<br />
===Advanced Options===<br />
[[Image:Prefs_Startup_Tab_Advanced_Options.png|frame|right|Advanced Options Section]]<br />
These options are used for development and troubleshooting. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Enable assertions'''<br />
: Developers often test MapTool with this option {{Checked}} to enable additional Java checks so they can find additional warnings or errors. This setting is not recommended for normal users as it lowers performance.<br />
* '''Disable Direct3d Pipeline'''<br />
: When {{Checked}}, MapTool will not use Direct3D. This is mainly used by developers, but if you are having visual issues you can try using this setting to see if your problem is resolved. If so, it may indicate you need new drivers from your video card manufacturer.<br />
* '''Enable OpenGL Pipeline'''<br />
: This option may help resolve visual issues when {{Checked}} by enabling OpenGL rendering. You do not need to check 'Disable Direct3d Pipeline' in order to use this setting.<br />
* '''Initialize AWT before JavaFX'''<br />
: Developers can use this.<br />
<br />
===Language Override===<br />
[[Image:Prefs_Startup_Tab_Language_Override.png|frame|right|Language Override Section]]<br />
* '''Language'''<br />
: Select the user interface language for MapTool. Changes to this setting take effect upon restarting MapTool.<br />
<br />
===Additional Options===<br />
[[Image:Prefs_Startup_Tab_Additional_Options.png|frame|right|Additional Options Section]]<br />
* '''Data Directory'''<br />
: The local directory where MapTool saves asset cache data, autosaves, backups, configuration files, and more. Changes to this setting take effect upon restarting MapTool.<br />
<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=MapTool_Preferences&diff=8898MapTool Preferences2020-08-20T20:51:26Z<p>Lwoestman: /* JVM Memory Settings */</p>
<hr />
<div>{{note|'''Note:''' Screenshots in this article are shown with the default settings, which might not necessarily be the ''recommended'' settings for your use.}}{{Beginner}}<br />
__TOC__<br />
==Interactions Tab==<br />
[[Image:prefs_tab_interactions.png|left|thumb|300px|Interactions Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Maps===<br />
[[Image:Prefs_Interactions_Tab_-_Maps.png|frame|right|Maps Section]] <br />
* '''New maps have Fog of War'''<br />
: Determines if new maps should have [[Fog of War]] enabled when created. If you use [[Fog of War]], it might seem obvious to have this {{Checked}}; however, when creating multiple maps for a new campaign, it is often useful to to disable this feature to assist with rapid map creation since even as a GM you will be unable to clearly view a map covered in [[Fog of War]]. After completing a map, it is a simple process to re-enable [[Fog of War]].<br />
* '''New maps visible to players'''<br />
: Determines if new maps should be set as Player Visible when created. Although there are exceptions, typically having this <span style="font-size: 24px; line-height: 1px; color: red; font-weight: bold; vertical-align: sub;">&#10003;</span>unchecked is the optimal setting; that way you won't unintentionally leave a map visible to players.<br />
* '''New Map Grid Type'''<br />
** '''Square''' [[Image:gridSquare.png|sub]]<br />
** '''Horizontal Hex''' [[Image:gridHorizontalHex.png|sub]]<br />
** '''Vertical Hex''' [[Image:gridVerticalHex.png|sub]]<br />
** '''Isometric''' [[Image:gridIsometric.png|sub]]<br />
: Determines the default grid type of new maps when created. You are free to create maps without a grid type, and also a grid type different than the one specified here, but you can not set the Default Grid Type to none.<br />
* '''New Map Grid Size'''<br />
: Represents the default amount of pixels you want MapTool to use drawing each grid cell at full resolution. The default setting of {{code|50}} pixels is adequate for most computers, but higher-end computers can handle {{code|100}} pixels or even {{code|200}} pixels for very high-end computers. There is no requirement that you use specific sizes, but {{code|50}} pixels and {{code|100}} pixels are commonly used. This setting will also determine how large an image appears when placed on a map layer when 'Start Freesize' is not checked for that layer.<br />
* '''New Map Units Per Cell'''<br />
: Sets the amount of units that each grid cell represents. The ambiguous "unit" is used in this case because you decide what "unit" means. If you want each grid cell to represent 5 feet, this would be set to {{code|5}}. If you want each grid cell to represent 4 kilometers, this would be set to {{code|4}}. This is often referred to as ''Distance Per Cell''. As of v1.5.1 MapTool supports a floating point number for this value.<br />
* '''New Map Vision Distance'''<br />
: The maximum distance that [[PC Token]]s can expose [[Fog of War]] after [[Light]]s, [[Sight]]s, and [[Vision Blocking Layer]]s are taken into account. It is important to note that this setting is measured in ''Distance Per Cell''.<br />
* '''New Map Light'''<br />
: The light setting for new maps. Choose from ''Off'', ''Day'' and ''Night''. (As of MT v1.5.11)<br />
* '''Movement metric'''<br />
** '''ONE_TWO_ONE''' specifies that every second diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''ONE_ONE_ONE''' specifies that diagonal movement will calculate the same as non-diagonal movement. <br />
** '''MANHATTAN''' specifies that every diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''NO DIAGONALS''' specifies that [[Token]]s can only move non-diagonally.<br />
: Determines how movement should be calculated when a [[Token]] moves diagonally on maps using a Square or Isometric grid. This affects the total distance displayed beneath a [[Token]] when it is moving, or when its previous path is displayed; it is calculated based on ''Distance Per Cell''. Maps with Hex grid types ignore this setting and instead calculate movement in any direction using the ''Distance Per Cell''.<br />
<br />
===Tokens===<br />
[[Image:Prefs_Interactions_Tab_Tokens.png|frame|right|Tokens Section]] <br />
* '''Start Snap to Grid'''<br />
: Determines if [[Token]]s will default to having '''Snap to Grid''' {{Checked}}. Having this setting {{Checked}} is optimal for maps that use a grid, but even on such maps there are cases when you might want to temporarily disable this setting(e.g. when placing a lot of "prop" [[Token]]s on the Object layer while drawing a map). <br />
* '''New tokens visible to players'''<br />
: Determines if new [[Token]]s have the '''Visible''' option {{Checked}} upon creation. The optimal setting for this really depends on your play style; if you have a lot of random encounters and build them during play, you may find it useful to have this setting disabled. <br />
* '''Warn when tokens are deleted'''<br />
: When {{Checked}} MapTool asks for confirmation whenever deleting a [[Token]].<br />
* '''Duplicate Token Numbering'''<br />
** '''Increment'''<br />
** '''Random'''<br />
: Will automatically generate numbers for [[Token]]s with duplicate names upon creation to distinguish them. '''Increment''' will leave the first token unnumbered, but will number each duplicate after that starting with the number {{code|1}} (e.g. Troll, Troll 1, Troll 2). '''Random''' will create a random two-digit or greater number for the token, even if there are no duplicates on the map yet. '''Random''' might be considered the optimal setting, as it gives your players no indication of how many copies of that [[Token]] can be expected to exist.<br />
* '''Show Numbering on'''<br />
** '''Name'''<br />
** '''GM Name'''<br />
** '''Both'''<br />
: Specifies where the number that derived from '''Duplicate Token Numbering''' is applied. '''Name''' appends the number after the name (derived from '''New Token Naming'''). '''GM Name''' places the number within the ''GM Name'' field of the [[Token]] options. '''Both''' appends the number after the name, and places it within the ''GM Name'' field of the [[Token]] options. <br />
: <span style="color:red;">'''Note'''</span>: It is generally recommended that you set this preference to '''Name''' or '''Both''', and not '''GM Name'''. Any [[Macro Introduction|Macros]] which refer to tokens by name rather than by token ID will break/behave unpredictably when a map has multiple tokens with the same name.<br />
* '''New Token Naming'''<br />
** '''Use Filename'''<br />
** '''Use "Creature"'''<br />
: Determines what the name will be when creating a new [[Token]], or what the ''Name'' field will be pre-filled with in a new [[Token]] dialog. '''Use Filename''' specifies that the name will be derived from the name of the file that was added to your Resource Library (e.g. if you add the file ''uglytroll.jpg'' to your Resource Library, tokens created from that image will begin with the name ''uglytroll''). '''Use "Creature"''' defaults all new [[Token]]s to being named "Creature" (without quotes). <br />
* '''Start Freesize'''<br />
: If you are using a map with a grid, [[Token]]s typically default to the size of one grid cell upon creation. Having this setting {{Checked}} allows you to have them default to the image's ''Native Size''. ''Native Size'' tokens moved to another layer become ''Freesize'', which can be resized by dragging a handle in their lower right corner.<br />
* '''Show Dialog on New Token'''<br />
: When this setting is {{Checked}}, a ''New Token'' dialog will open when you drag an image onto the map, allowing you to set some options prior to creation. If you disable this setting, all new tokens will be created with the default settings derived from previous settings in this section.<br />
* '''Stat Sheet Portrait Size''' ''(Set to 0 to disable portaits)''<br />
: Sets the width (in pixels) of the portrait that is displayed in the lower left corner of the map when mousing over certain [[Token]]s; the image is resized proportionately. A portrait is displayed under a few different circumstances; if the [[Token]] has properties that are set to display on the stat sheet, and those properties have values, the portrait will display the token image. If the [[Token]] has a portrait image set, it will display with or without a stat sheet. Why might you want to set this to {{code|0}}? Besides the obvious reason of not displaying the portrait, you might want to use a stat sheet, but not want a portrait displayed with it; or perhaps you don't want to use a stat sheet or a portrait, but would like to have the portrait image 'slot' usable for other purposes, like inside a Dialog or Frame.<br />
* '''Show Portrait on mouseover'''<br />
: When {{Checked}}, displays the token's Portrait image in the lower left corner when the cursor is hovered over the token.<br />
* '''Show stat sheet on mouseover'''<br />
: When {{Checked}}, displays the token's stat sheet in the lower left corner (to the right of the portrait) when the cursor is hovered over the token.<br />
* '''Stat sheet requires Shift key'''<br />
: Requires the Shift key be held down when the cursor is hovered over the token in order to display the stat sheet when {{Checked}}. Has no effect if ''Show stat sheet on mouseover'' is unchecked. MapTool only checks if the Shift key is depressed when the cursor first passes over a token and then either displays or suppresses the stat sheet, meaning you cannot use this setting to 'toggle' the statsheet on and off with the shift key without also moving the cursor.<br />
* '''Force Token Facing Arrow'''<br />
: Displays a yellow facing arrow on all tokens with a facing value when {{Checked}}, even on top-down tokens which normally omit them.<br />
* '''Snap Token while dragging'''<br />
: Tokens will snap to the grid as they are dragged when {{Checked}}. When unchecked, the token's path and destination are still highlighted.<br />
* '''Hide Mouse Pointer while dragging'''<br />
: MapTool hides the cursor arrow while dragging tokens within the map view when {{Checked}}.<br />
<br />
===Chat===<br />
Chat autosave settings now reside in the 'Application' tab of the Preferences window. <br />
[[Image:prefs_interactions_chat.png|frame|right|Chat Section]] <br />
* '''Show Avatar per line'''<br />
: The image for the impersonated token is shown next to any chat output it creates, when this is {{Checked}}. This is a client-side setting and does not effect any other clients connected to the same game.<br />
* '''Insert Smilies'''<br />
: Replaces common smiley(emoticon) character sequences with graphical smilies when this is {{Checked}}. If you use a lot of macros, it is recommended that you turn this off, as it could cause some complications if any of your macro code is interpreted as a smiley.<br />
* '''Use ToolTips for Inline Rolls'''<br />
: Sets the default display ([[:Category:Display Roll Option|Display Roll Option]]) for rolls in the chat panel. Will use {{roll|tooltip}} if this is {{Checked}}, otherwise it will default to {{roll|expanded}}.<br />
* '''Suppress ToolTips for MacroLinks'''<br />
: MacroLinks normally show tooltips that state information about the link target as an anti-cheating device. When {{Checked}}, these tooltips are disabled.<br />
* '''Typing Notification Duration Seconds'''<br />
: The number of seconds before typing notifications in the top left of the Map View disappear after a player's last keystroke.<br />
* '''Typing Notification Color'''<br />
: Color of the text for typing notifications.<br />
* '''Show Chat Notification Background'''<br />
: When {{Checked}} shows a graphic behind typing notifications. Can be helpful to provide consistently contrasting background for the notifications.<br />
* '''Trusted Prefix Background'''<br />
: Sets a custom background for macro output that comes from a [[Trusted Macro]].<br />
* '''Trusted Prefix Foreground'''<br />
: Sets a custom foreground (text color) for macro output that comes from a [[Trusted Macro]].<br />
<br />
===Macro Editor===<br />
[[Image:Prefs_Interactions_Tab_Macro_Editor.png|frame|right|Macro Editor Section]]<br />
* '''Style Theme'''<br />
: Select from a variety of themes for macro editor windows.<br />
<div style="clear: both"></div><br />
<br />
===Objects===<br />
[[Image:Prefs_Interactions_Tab_Objects.png|frame|right|Objects Section]] <br />
* '''Start Snap to Grid'''<br />
: Tokens created on map's Object layer will automatically be set to '''Snap to Grid''' if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Tokens created on a map's Object layer will automatically be set to '''Freesize''' if this is {{Checked}}.<br />
<br />
===Backgrounds===<br />
[[Image:Prefs_Interactions_Tab_Backgrounds.png|frame|right|Backgrounds Section]] <br />
* '''Start Snap to Grid'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Snap to Grid''', if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Freesize''', if this is {{Checked}}.<br />
<br />
===Facing===<br />
[[Image:Prefs_Interactions_Tab_Facing.png|frame|right|Facing Section]] <br />
* '''On Edges'''<br />
: A token's facing will snap to the edges when {{Checked}}. Edges are the lines that make up a grid cell.<br />
* '''On Vertices'''<br />
: A token's facing will snap to the vertices when {{Checked}}. Vertices are the points that connect the lines that make up a grid cell.<br />
<br />
==Accessibility Tab==<br />
[[Image:prefs_tab_accessibility.png|thumb|right|300px|Accessibility Tab on the Preferences Dialog]]<br />
* '''Chat Font Size'''<br />
: The default size of the font in the chat panel; measured in points.<br />
* '''ToolTip Initial Delay'''<br />
: The time it takes for a tooltip to display when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
* '''ToolTip Dismiss Delay'''<br />
: The time it takes for a tooltip to disappear when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
<br />
<div style="clear: both"></div><br />
<br />
==Application Tab==<br />
[[Image:prefs_tab_application.png|left|thumb|300px|Application Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Save===<br />
[[Image:prefs_application_save.png|frame|right|Save Section]] <br />
* '''Campaign autosave every [ ] min'''<br />
: Saves an autosave copy of your campaign in the interval specified in <code>%{appHome}/autosave</code>. This will not overwrite your campaign file, but rather create a file which is updated every time it automatically saves. Autosave is only a temporary file, useful in case MapTool crashes. When MapTool is properly closed, the Autosave file is deleted. Note the interval is the time between the last save completing and the start of the next one.<br />
: As a troubleshooting aid, the AutoSaveManager will switch from measuring the autosave interval in minutes to seconds when the [[log.setLevel|log level]] for that package is set to “DEBUG”.<br />
* '''Save reminder on close'''<br />
: Displays a dialog when attempting to close the program with unsaved changes to your campaign when {{Checked}}.<br />
* '''Time between chat log autosaves'''<br />
: The amount of time in minutes between the autosaving of the chat log.<br />
* '''Autosave chat log filename'''<br />
: The filename that will be used when automatically saving your chat log.<br />
* '''File Sync Directory'''<br />
: Specify a path to a local cloud-synced directory to determine relative path external files such as Hero Lab portfolios.<br />
* '''1.3b50 Compatability Mode''' <br />
: <code>This setting has been removed. You can use File > Export Campaign As... to save campaigns for MapTool versions as far back as 1.4.0.</code><br />
: Due to some changes in how certain data is stored in the campaign file in versions after 1.3b50, they might not be compatible with version 1.3b50 and earlier. If this is {{Checked}} your campaign will be saved in the older format, allowing it to be opened in older versions, but losing some of the new features.<br />
<br />
===Map Visuals===<br />
[[Image:Prefs_Application_Tab_Map_Visuals.png|frame|right|Map Defaults Section]] <br />
* '''Halo line width'''<br />
: Controls the width of the [[Halo]] border when it is displayed on a [[Token]].<br />
* '''Use halo color for vision'''<br />
: When this setting is {{Checked}}, hovering over a token with [[Vision]] overlays the token's visible area with the token's [[Halo]] color. This overlay is a translucent layer controlled by the '''Halo opacity''' setting. <br />
* '''Halo opacity'''<br />
: Controls the opacity of the optional overlay enabled by the '''Use halo color for vision''' setting. This does not control the actual [[Halo|Halo's]] outline opacity, which is always completely opaque. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Aura opacity'''<br />
: Controls the opacity of color overlays provided by [[Aura|Auras]] enabled on tokens. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Light opacity'''<br />
: Controls the opacity of color overlays provided by [[Introduction_to_Lights_and_Sights#Light_Sources|Light Sources]] enabled on tokens. This also affects 'personal' lights defined in a token's [[Vision]] setting. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Fog opacity'''<br />
: Controls the opacity of the black layer of 'Soft Fog' that is left in previously explored areas when [[Fog of War]] is enabled. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Auto-expose fog on token movement (GM Only)'''<br />
: Will automatically expose [[Fog of War]] after moving a [[Token]] if {{Checked}}. This setting is intended to help test Fog of War and VBL when not hosting a game. When running a server, this setting is ignored in favor of the settings in the 'Start Server' dialog.<br />
<br />
===Performance===<br />
[[Image:Prefs_Application_Tab_Performance.png|frame|right|Performance Section]]<br />
* '''Fill selection box'''<br />
: When {{Checked}}, the selection box which appears when dragging to select tokens in the Map View will contain a translucent blue fill. Less powerful devices running MapTool may see a small performance gain from unchecking this setting.<br />
* '''Frame Rate Cap''' <code>New in MapTool 1.5.7</code><br />
: Sets the maximum frame rate for the map renderer. Less powerful devices running MapTool may see a performance gain by lowering this setting.<br />
<br />
===Initiative Defaults===<br />
[[Image:Prefs_Application_Tab_Initiative_Defaults.png|frame|right|Initiative Section]]<br />
* '''Hide NPCs from players on new maps'''<br />
: When {{Checked}}, automatically enables 'Hide NPCs' in the [[Initiative Panel]] on new maps. This setting doesn't show connected players [[NPC Tokens]] on the Initiative Panel.<br />
* '''Give Owners Permission in new campaigns'''<br />
: This automatically enables the 'Owner Permissions' setting in the [[Initiative Panel]] on new maps when {{Checked}}. The setting mainly lets players with token ownership add their tokens to or remove their tokens from the initiative list and advance the initiative when it is their token's turn.<br />
* '''Lock Player Movement in new campaigns'''<br />
: When {{Checked}}, new maps will have 'Lock Player Movement' automatically enabled in the [[Initiative Panel]]. This setting prevents players who do not own the token with initiative from moving any tokens.<br />
* '''Show Initiative Gain Message'''<br />
: When initiative advances to a [[PC Token]] token and this is {{Checked}}, a simple 'Token Name has received initiative' message is displayed for all players in chat. This is ignored for [[NPC Token|NPC Tokens]].<br />
<br />
===Client===<br />
[[Image:Prefs_Application_Tab_Client.png|frame|right|Client Section]]<br />
* '''Fit GM View'''<br />
: When {{Checked}} and the GM uses 'Center Players on Current View', the Map View will zoom out as necessary to accommodate the entire GM view. If unchecked, the zoom level will be set to match the GM's Map View, which will occlude part of the map if your Map View areas are different sizes.<br />
<br />
===Macro Panels===<br />
[[Image:Prefs_Application_Tab_Macro_Panels.png|frame|right|Macro Panels Section]] <br />
* '''Default: Allow Players to Edit Macros'''<br />
: In order for a macro to be considered a [[Trusted Macro]], players must not be able to edit it. This setting determines if a new macro should default to allowing players to edit if {{Checked}}. Disabling this setting can be very useful if you intend to create a lot of macros that you intend to be trusted.<br />
<br />
===UPnP===<br />
[[Image:Prefs_Application_Tab_UPnP.png|frame|right|UPnP Section]]<br />
* '''Discovery Timeout'''<br />
: The timeout period in milliseconds MapTool will wait when searching for UPnP gateways before giving up.<br />
<br />
===Macro Permissions===<br />
[[Image:Prefs_Application_Tab_Macro_Permissions.png|frame|right|Macro Permissions Section]]<br />
* '''Enable External Macro Access'''<br />
: When {{Checked}}, [[Introduction to Macro Writing|Macros]] may call functions that access your drive and http services. Some examples (not a complete list) of functions which will be enabled are [[RESTful Functions Overview|REST Functions]], [[exportData]], and [[getEnvironmentVariable]].<br />
<div style="clear: both"></div><br />
<br />
==Sounds Tab==<br />
[[Image:prefs_tab_sounds.png|thumb|right|300px|Sounds Tab on the Preferences Dialog]]<br />
* '''Play system sounds'''<br />
: When {{Checked}}, MapTool will play a sound when new content is sent to the chat panel.<br />
* '''Play streams'''<br />
: When {{Checked}}, streams started with [[playStream]] will be allowed to play.<br />
* '''Only when window not focused'''<br />
: When {{Checked}}, the sound that MapTool plays when new content is sent to the chat panel will only play if MapTool is not the application that has focus.<br />
* '''Turn on Syrinscape Integration'''<br />
: When clicking <code>syrinscape-fantasy:</code> links in MapTool, the Syrinscape Fantasy Player will be allowed to automatically open when this setting is {{Checked}}. This has no effect on [[Syrinscape Integration]] using the REST API and Online Player.<br />
<br />
==Startup Tab==<br />
[[Image:Prefs_Startup_Tab.png|thumb|300px|frame|left|Startup Tab of Preferences Dialog]]<br />
<div style="clear: both"></div><br />
<br />
===JVM Memory Settings===<br />
[[Image:Prefs_Startup_Tab_JVM_Settings.png|frame|right|JVM Memory Section]]<br />
These preferences are somewhat advanced. To better understand how MapTool uses memory settings, read about [[Stack Size]]. If you are having Stack Overflow errors and need to modify these settings for more reliable performance, read about [[Avoiding Stack Overflow]]. If you need help resetting MapTool memory settings, check out [https://www.rptools.net/2019/04/resetting-maptool/ Resetting MapTool JVM Settings] on the RPTools blog.<br />
<br />
These three settings are memory sizes in bytes. The letter at the end can be K, M, or G signifying Kilobytes, Megabytes, or Gigabytes. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Maximum heap size (-Xmx)'''<br />
: The maximum amount of total memory (RAM) MapTool can use at once, usually entered in Gigabytes (G). For heavy frameworks with many assets, you may have to raise this value. 4G is a generous default value for nearly all users with at least 8GB of RAM.<br />
* '''Initial & minimum heap size (-Xms)'''<br />
: The minimum amount of memory (RAM) which MapTool will always reserve for use, usually entered in Gigabytes (G). Oracle recommends this setting be the same as the Maximum heap size. Doing so may provide performance gains by reducing garbage collection operations. This value should not be higher than the Maximum heap size.<br />
* '''Thread stack size (-Xss)'''<br />
: The memory each particular Java thread has reserved for its use, usually entered in Megabytes (M). Raising this value may allow more complex macros to be run, but it should generally be kept as low as possible. 4M is a generous default value that allows most macros to work just fine. To help understand this value, a simple campaign using short macros or no macros may be able to run successfully with a value as low as 256K, while a campaign containing extremely large macros may need 5M or 6M to avoid stack overflow.<br />
<br />
===Advanced Options===<br />
[[Image:Prefs_Startup_Tab_Advanced_Options.png|frame|right|Advanced Options Section]]<br />
These options are used for development and troubleshooting. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Enable assertions'''<br />
: Developers often test MapTool with this option {{Checked} to enable additional Java checks so they can find additional warnings or errors. This setting is not recommended for normal users as it lowers performance.<br />
* '''Disable Direct3d Pipeline'''<br />
: When {{Checked}}, MapTool will not use Direct3D. This is mainly used by developers, but if you are having visual issues you can try using this setting to see if your problem is resolved. If so, it may indicate you need new drivers from your video card manufacturer.<br />
* '''Enable OpenGL Pipeline'''<br />
: This option may help resolve visual issues when {{Checked}} by enabling OpenGL rendering. You do not need to enable 'Disable Direct3d Pipeline' in order to use this setting.<br />
* '''Initialize AWT before JavaFX'''<br />
: Developers can use this<br />
<br />
===Language Override===<br />
[[Image:Prefs_Startup_Tab_Language_Override.png|frame|right|Language Override Section]]<br />
* '''Language'''<br />
: Select the user interface language for MapTool. Changes to this setting take effect upon restarting MapTool.<br />
<br />
===Additional Options===<br />
[[Image:Prefs_Startup_Tab_Additional_Options.png|frame|right|Additional Options Section]]<br />
* '''Data Directory'''<br />
: The local directory where MapTool saves asset cache data, autosaves, backups, configuration files, and more. Changes to this setting take effect upon restarting MapTool.<br />
<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=MapTool_Preferences&diff=8897MapTool Preferences2020-08-20T20:49:27Z<p>Lwoestman: /* Sounds Tab */</p>
<hr />
<div>{{note|'''Note:''' Screenshots in this article are shown with the default settings, which might not necessarily be the ''recommended'' settings for your use.}}{{Beginner}}<br />
__TOC__<br />
==Interactions Tab==<br />
[[Image:prefs_tab_interactions.png|left|thumb|300px|Interactions Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Maps===<br />
[[Image:Prefs_Interactions_Tab_-_Maps.png|frame|right|Maps Section]] <br />
* '''New maps have Fog of War'''<br />
: Determines if new maps should have [[Fog of War]] enabled when created. If you use [[Fog of War]], it might seem obvious to have this {{Checked}}; however, when creating multiple maps for a new campaign, it is often useful to to disable this feature to assist with rapid map creation since even as a GM you will be unable to clearly view a map covered in [[Fog of War]]. After completing a map, it is a simple process to re-enable [[Fog of War]].<br />
* '''New maps visible to players'''<br />
: Determines if new maps should be set as Player Visible when created. Although there are exceptions, typically having this <span style="font-size: 24px; line-height: 1px; color: red; font-weight: bold; vertical-align: sub;">&#10003;</span>unchecked is the optimal setting; that way you won't unintentionally leave a map visible to players.<br />
* '''New Map Grid Type'''<br />
** '''Square''' [[Image:gridSquare.png|sub]]<br />
** '''Horizontal Hex''' [[Image:gridHorizontalHex.png|sub]]<br />
** '''Vertical Hex''' [[Image:gridVerticalHex.png|sub]]<br />
** '''Isometric''' [[Image:gridIsometric.png|sub]]<br />
: Determines the default grid type of new maps when created. You are free to create maps without a grid type, and also a grid type different than the one specified here, but you can not set the Default Grid Type to none.<br />
* '''New Map Grid Size'''<br />
: Represents the default amount of pixels you want MapTool to use drawing each grid cell at full resolution. The default setting of {{code|50}} pixels is adequate for most computers, but higher-end computers can handle {{code|100}} pixels or even {{code|200}} pixels for very high-end computers. There is no requirement that you use specific sizes, but {{code|50}} pixels and {{code|100}} pixels are commonly used. This setting will also determine how large an image appears when placed on a map layer when 'Start Freesize' is not checked for that layer.<br />
* '''New Map Units Per Cell'''<br />
: Sets the amount of units that each grid cell represents. The ambiguous "unit" is used in this case because you decide what "unit" means. If you want each grid cell to represent 5 feet, this would be set to {{code|5}}. If you want each grid cell to represent 4 kilometers, this would be set to {{code|4}}. This is often referred to as ''Distance Per Cell''. As of v1.5.1 MapTool supports a floating point number for this value.<br />
* '''New Map Vision Distance'''<br />
: The maximum distance that [[PC Token]]s can expose [[Fog of War]] after [[Light]]s, [[Sight]]s, and [[Vision Blocking Layer]]s are taken into account. It is important to note that this setting is measured in ''Distance Per Cell''.<br />
* '''New Map Light'''<br />
: The light setting for new maps. Choose from ''Off'', ''Day'' and ''Night''. (As of MT v1.5.11)<br />
* '''Movement metric'''<br />
** '''ONE_TWO_ONE''' specifies that every second diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''ONE_ONE_ONE''' specifies that diagonal movement will calculate the same as non-diagonal movement. <br />
** '''MANHATTAN''' specifies that every diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''NO DIAGONALS''' specifies that [[Token]]s can only move non-diagonally.<br />
: Determines how movement should be calculated when a [[Token]] moves diagonally on maps using a Square or Isometric grid. This affects the total distance displayed beneath a [[Token]] when it is moving, or when its previous path is displayed; it is calculated based on ''Distance Per Cell''. Maps with Hex grid types ignore this setting and instead calculate movement in any direction using the ''Distance Per Cell''.<br />
<br />
===Tokens===<br />
[[Image:Prefs_Interactions_Tab_Tokens.png|frame|right|Tokens Section]] <br />
* '''Start Snap to Grid'''<br />
: Determines if [[Token]]s will default to having '''Snap to Grid''' {{Checked}}. Having this setting {{Checked}} is optimal for maps that use a grid, but even on such maps there are cases when you might want to temporarily disable this setting(e.g. when placing a lot of "prop" [[Token]]s on the Object layer while drawing a map). <br />
* '''New tokens visible to players'''<br />
: Determines if new [[Token]]s have the '''Visible''' option {{Checked}} upon creation. The optimal setting for this really depends on your play style; if you have a lot of random encounters and build them during play, you may find it useful to have this setting disabled. <br />
* '''Warn when tokens are deleted'''<br />
: When {{Checked}} MapTool asks for confirmation whenever deleting a [[Token]].<br />
* '''Duplicate Token Numbering'''<br />
** '''Increment'''<br />
** '''Random'''<br />
: Will automatically generate numbers for [[Token]]s with duplicate names upon creation to distinguish them. '''Increment''' will leave the first token unnumbered, but will number each duplicate after that starting with the number {{code|1}} (e.g. Troll, Troll 1, Troll 2). '''Random''' will create a random two-digit or greater number for the token, even if there are no duplicates on the map yet. '''Random''' might be considered the optimal setting, as it gives your players no indication of how many copies of that [[Token]] can be expected to exist.<br />
* '''Show Numbering on'''<br />
** '''Name'''<br />
** '''GM Name'''<br />
** '''Both'''<br />
: Specifies where the number that derived from '''Duplicate Token Numbering''' is applied. '''Name''' appends the number after the name (derived from '''New Token Naming'''). '''GM Name''' places the number within the ''GM Name'' field of the [[Token]] options. '''Both''' appends the number after the name, and places it within the ''GM Name'' field of the [[Token]] options. <br />
: <span style="color:red;">'''Note'''</span>: It is generally recommended that you set this preference to '''Name''' or '''Both''', and not '''GM Name'''. Any [[Macro Introduction|Macros]] which refer to tokens by name rather than by token ID will break/behave unpredictably when a map has multiple tokens with the same name.<br />
* '''New Token Naming'''<br />
** '''Use Filename'''<br />
** '''Use "Creature"'''<br />
: Determines what the name will be when creating a new [[Token]], or what the ''Name'' field will be pre-filled with in a new [[Token]] dialog. '''Use Filename''' specifies that the name will be derived from the name of the file that was added to your Resource Library (e.g. if you add the file ''uglytroll.jpg'' to your Resource Library, tokens created from that image will begin with the name ''uglytroll''). '''Use "Creature"''' defaults all new [[Token]]s to being named "Creature" (without quotes). <br />
* '''Start Freesize'''<br />
: If you are using a map with a grid, [[Token]]s typically default to the size of one grid cell upon creation. Having this setting {{Checked}} allows you to have them default to the image's ''Native Size''. ''Native Size'' tokens moved to another layer become ''Freesize'', which can be resized by dragging a handle in their lower right corner.<br />
* '''Show Dialog on New Token'''<br />
: When this setting is {{Checked}}, a ''New Token'' dialog will open when you drag an image onto the map, allowing you to set some options prior to creation. If you disable this setting, all new tokens will be created with the default settings derived from previous settings in this section.<br />
* '''Stat Sheet Portrait Size''' ''(Set to 0 to disable portaits)''<br />
: Sets the width (in pixels) of the portrait that is displayed in the lower left corner of the map when mousing over certain [[Token]]s; the image is resized proportionately. A portrait is displayed under a few different circumstances; if the [[Token]] has properties that are set to display on the stat sheet, and those properties have values, the portrait will display the token image. If the [[Token]] has a portrait image set, it will display with or without a stat sheet. Why might you want to set this to {{code|0}}? Besides the obvious reason of not displaying the portrait, you might want to use a stat sheet, but not want a portrait displayed with it; or perhaps you don't want to use a stat sheet or a portrait, but would like to have the portrait image 'slot' usable for other purposes, like inside a Dialog or Frame.<br />
* '''Show Portrait on mouseover'''<br />
: When {{Checked}}, displays the token's Portrait image in the lower left corner when the cursor is hovered over the token.<br />
* '''Show stat sheet on mouseover'''<br />
: When {{Checked}}, displays the token's stat sheet in the lower left corner (to the right of the portrait) when the cursor is hovered over the token.<br />
* '''Stat sheet requires Shift key'''<br />
: Requires the Shift key be held down when the cursor is hovered over the token in order to display the stat sheet when {{Checked}}. Has no effect if ''Show stat sheet on mouseover'' is unchecked. MapTool only checks if the Shift key is depressed when the cursor first passes over a token and then either displays or suppresses the stat sheet, meaning you cannot use this setting to 'toggle' the statsheet on and off with the shift key without also moving the cursor.<br />
* '''Force Token Facing Arrow'''<br />
: Displays a yellow facing arrow on all tokens with a facing value when {{Checked}}, even on top-down tokens which normally omit them.<br />
* '''Snap Token while dragging'''<br />
: Tokens will snap to the grid as they are dragged when {{Checked}}. When unchecked, the token's path and destination are still highlighted.<br />
* '''Hide Mouse Pointer while dragging'''<br />
: MapTool hides the cursor arrow while dragging tokens within the map view when {{Checked}}.<br />
<br />
===Chat===<br />
Chat autosave settings now reside in the 'Application' tab of the Preferences window. <br />
[[Image:prefs_interactions_chat.png|frame|right|Chat Section]] <br />
* '''Show Avatar per line'''<br />
: The image for the impersonated token is shown next to any chat output it creates, when this is {{Checked}}. This is a client-side setting and does not effect any other clients connected to the same game.<br />
* '''Insert Smilies'''<br />
: Replaces common smiley(emoticon) character sequences with graphical smilies when this is {{Checked}}. If you use a lot of macros, it is recommended that you turn this off, as it could cause some complications if any of your macro code is interpreted as a smiley.<br />
* '''Use ToolTips for Inline Rolls'''<br />
: Sets the default display ([[:Category:Display Roll Option|Display Roll Option]]) for rolls in the chat panel. Will use {{roll|tooltip}} if this is {{Checked}}, otherwise it will default to {{roll|expanded}}.<br />
* '''Suppress ToolTips for MacroLinks'''<br />
: MacroLinks normally show tooltips that state information about the link target as an anti-cheating device. When {{Checked}}, these tooltips are disabled.<br />
* '''Typing Notification Duration Seconds'''<br />
: The number of seconds before typing notifications in the top left of the Map View disappear after a player's last keystroke.<br />
* '''Typing Notification Color'''<br />
: Color of the text for typing notifications.<br />
* '''Show Chat Notification Background'''<br />
: When {{Checked}} shows a graphic behind typing notifications. Can be helpful to provide consistently contrasting background for the notifications.<br />
* '''Trusted Prefix Background'''<br />
: Sets a custom background for macro output that comes from a [[Trusted Macro]].<br />
* '''Trusted Prefix Foreground'''<br />
: Sets a custom foreground (text color) for macro output that comes from a [[Trusted Macro]].<br />
<br />
===Macro Editor===<br />
[[Image:Prefs_Interactions_Tab_Macro_Editor.png|frame|right|Macro Editor Section]]<br />
* '''Style Theme'''<br />
: Select from a variety of themes for macro editor windows.<br />
<div style="clear: both"></div><br />
<br />
===Objects===<br />
[[Image:Prefs_Interactions_Tab_Objects.png|frame|right|Objects Section]] <br />
* '''Start Snap to Grid'''<br />
: Tokens created on map's Object layer will automatically be set to '''Snap to Grid''' if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Tokens created on a map's Object layer will automatically be set to '''Freesize''' if this is {{Checked}}.<br />
<br />
===Backgrounds===<br />
[[Image:Prefs_Interactions_Tab_Backgrounds.png|frame|right|Backgrounds Section]] <br />
* '''Start Snap to Grid'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Snap to Grid''', if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Freesize''', if this is {{Checked}}.<br />
<br />
===Facing===<br />
[[Image:Prefs_Interactions_Tab_Facing.png|frame|right|Facing Section]] <br />
* '''On Edges'''<br />
: A token's facing will snap to the edges when {{Checked}}. Edges are the lines that make up a grid cell.<br />
* '''On Vertices'''<br />
: A token's facing will snap to the vertices when {{Checked}}. Vertices are the points that connect the lines that make up a grid cell.<br />
<br />
==Accessibility Tab==<br />
[[Image:prefs_tab_accessibility.png|thumb|right|300px|Accessibility Tab on the Preferences Dialog]]<br />
* '''Chat Font Size'''<br />
: The default size of the font in the chat panel; measured in points.<br />
* '''ToolTip Initial Delay'''<br />
: The time it takes for a tooltip to display when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
* '''ToolTip Dismiss Delay'''<br />
: The time it takes for a tooltip to disappear when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
<br />
<div style="clear: both"></div><br />
<br />
==Application Tab==<br />
[[Image:prefs_tab_application.png|left|thumb|300px|Application Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Save===<br />
[[Image:prefs_application_save.png|frame|right|Save Section]] <br />
* '''Campaign autosave every [ ] min'''<br />
: Saves an autosave copy of your campaign in the interval specified in <code>%{appHome}/autosave</code>. This will not overwrite your campaign file, but rather create a file which is updated every time it automatically saves. Autosave is only a temporary file, useful in case MapTool crashes. When MapTool is properly closed, the Autosave file is deleted. Note the interval is the time between the last save completing and the start of the next one.<br />
: As a troubleshooting aid, the AutoSaveManager will switch from measuring the autosave interval in minutes to seconds when the [[log.setLevel|log level]] for that package is set to “DEBUG”.<br />
* '''Save reminder on close'''<br />
: Displays a dialog when attempting to close the program with unsaved changes to your campaign when {{Checked}}.<br />
* '''Time between chat log autosaves'''<br />
: The amount of time in minutes between the autosaving of the chat log.<br />
* '''Autosave chat log filename'''<br />
: The filename that will be used when automatically saving your chat log.<br />
* '''File Sync Directory'''<br />
: Specify a path to a local cloud-synced directory to determine relative path external files such as Hero Lab portfolios.<br />
* '''1.3b50 Compatability Mode''' <br />
: <code>This setting has been removed. You can use File > Export Campaign As... to save campaigns for MapTool versions as far back as 1.4.0.</code><br />
: Due to some changes in how certain data is stored in the campaign file in versions after 1.3b50, they might not be compatible with version 1.3b50 and earlier. If this is {{Checked}} your campaign will be saved in the older format, allowing it to be opened in older versions, but losing some of the new features.<br />
<br />
===Map Visuals===<br />
[[Image:Prefs_Application_Tab_Map_Visuals.png|frame|right|Map Defaults Section]] <br />
* '''Halo line width'''<br />
: Controls the width of the [[Halo]] border when it is displayed on a [[Token]].<br />
* '''Use halo color for vision'''<br />
: When this setting is {{Checked}}, hovering over a token with [[Vision]] overlays the token's visible area with the token's [[Halo]] color. This overlay is a translucent layer controlled by the '''Halo opacity''' setting. <br />
* '''Halo opacity'''<br />
: Controls the opacity of the optional overlay enabled by the '''Use halo color for vision''' setting. This does not control the actual [[Halo|Halo's]] outline opacity, which is always completely opaque. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Aura opacity'''<br />
: Controls the opacity of color overlays provided by [[Aura|Auras]] enabled on tokens. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Light opacity'''<br />
: Controls the opacity of color overlays provided by [[Introduction_to_Lights_and_Sights#Light_Sources|Light Sources]] enabled on tokens. This also affects 'personal' lights defined in a token's [[Vision]] setting. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Fog opacity'''<br />
: Controls the opacity of the black layer of 'Soft Fog' that is left in previously explored areas when [[Fog of War]] is enabled. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Auto-expose fog on token movement (GM Only)'''<br />
: Will automatically expose [[Fog of War]] after moving a [[Token]] if {{Checked}}. This setting is intended to help test Fog of War and VBL when not hosting a game. When running a server, this setting is ignored in favor of the settings in the 'Start Server' dialog.<br />
<br />
===Performance===<br />
[[Image:Prefs_Application_Tab_Performance.png|frame|right|Performance Section]]<br />
* '''Fill selection box'''<br />
: When {{Checked}}, the selection box which appears when dragging to select tokens in the Map View will contain a translucent blue fill. Less powerful devices running MapTool may see a small performance gain from unchecking this setting.<br />
* '''Frame Rate Cap''' <code>New in MapTool 1.5.7</code><br />
: Sets the maximum frame rate for the map renderer. Less powerful devices running MapTool may see a performance gain by lowering this setting.<br />
<br />
===Initiative Defaults===<br />
[[Image:Prefs_Application_Tab_Initiative_Defaults.png|frame|right|Initiative Section]]<br />
* '''Hide NPCs from players on new maps'''<br />
: When {{Checked}}, automatically enables 'Hide NPCs' in the [[Initiative Panel]] on new maps. This setting doesn't show connected players [[NPC Tokens]] on the Initiative Panel.<br />
* '''Give Owners Permission in new campaigns'''<br />
: This automatically enables the 'Owner Permissions' setting in the [[Initiative Panel]] on new maps when {{Checked}}. The setting mainly lets players with token ownership add their tokens to or remove their tokens from the initiative list and advance the initiative when it is their token's turn.<br />
* '''Lock Player Movement in new campaigns'''<br />
: When {{Checked}}, new maps will have 'Lock Player Movement' automatically enabled in the [[Initiative Panel]]. This setting prevents players who do not own the token with initiative from moving any tokens.<br />
* '''Show Initiative Gain Message'''<br />
: When initiative advances to a [[PC Token]] token and this is {{Checked}}, a simple 'Token Name has received initiative' message is displayed for all players in chat. This is ignored for [[NPC Token|NPC Tokens]].<br />
<br />
===Client===<br />
[[Image:Prefs_Application_Tab_Client.png|frame|right|Client Section]]<br />
* '''Fit GM View'''<br />
: When {{Checked}} and the GM uses 'Center Players on Current View', the Map View will zoom out as necessary to accommodate the entire GM view. If unchecked, the zoom level will be set to match the GM's Map View, which will occlude part of the map if your Map View areas are different sizes.<br />
<br />
===Macro Panels===<br />
[[Image:Prefs_Application_Tab_Macro_Panels.png|frame|right|Macro Panels Section]] <br />
* '''Default: Allow Players to Edit Macros'''<br />
: In order for a macro to be considered a [[Trusted Macro]], players must not be able to edit it. This setting determines if a new macro should default to allowing players to edit if {{Checked}}. Disabling this setting can be very useful if you intend to create a lot of macros that you intend to be trusted.<br />
<br />
===UPnP===<br />
[[Image:Prefs_Application_Tab_UPnP.png|frame|right|UPnP Section]]<br />
* '''Discovery Timeout'''<br />
: The timeout period in milliseconds MapTool will wait when searching for UPnP gateways before giving up.<br />
<br />
===Macro Permissions===<br />
[[Image:Prefs_Application_Tab_Macro_Permissions.png|frame|right|Macro Permissions Section]]<br />
* '''Enable External Macro Access'''<br />
: When {{Checked}}, [[Introduction to Macro Writing|Macros]] may call functions that access your drive and http services. Some examples (not a complete list) of functions which will be enabled are [[RESTful Functions Overview|REST Functions]], [[exportData]], and [[getEnvironmentVariable]].<br />
<div style="clear: both"></div><br />
<br />
==Sounds Tab==<br />
[[Image:prefs_tab_sounds.png|thumb|right|300px|Sounds Tab on the Preferences Dialog]]<br />
* '''Play system sounds'''<br />
: When {{Checked}}, MapTool will play a sound when new content is sent to the chat panel.<br />
* '''Play streams'''<br />
: When {{Checked}}, streams started with [[playStream]] will be allowed to play.<br />
* '''Only when window not focused'''<br />
: When {{Checked}}, the sound that MapTool plays when new content is sent to the chat panel will only play if MapTool is not the application that has focus.<br />
* '''Turn on Syrinscape Integration'''<br />
: When clicking <code>syrinscape-fantasy:</code> links in MapTool, the Syrinscape Fantasy Player will be allowed to automatically open when this setting is {{Checked}}. This has no effect on [[Syrinscape Integration]] using the REST API and Online Player.<br />
<br />
==Startup Tab==<br />
[[Image:Prefs_Startup_Tab.png|thumb|300px|frame|left|Startup Tab of Preferences Dialog]]<br />
<div style="clear: both"></div><br />
<br />
===JVM Memory Settings===<br />
[[Image:Prefs_Startup_Tab_JVM_Settings.png|frame|right|JVM Memory Section]]<br />
These preferences are somewhat advanced. To better understand how MapTool uses memory settings, read about [[Stack Size]]. If you are having Stack Overflow errors and need to modify these settings for more reliable performance, read about [[Avoiding Stack Overflow]]. If you need help resetting MapTool memory settings, check out [https://www.rptools.net/2019/04/resetting-maptool/ Resetting MapTool JVM Settings] on the RPTools blog.<br />
<br />
These three settings are memory sizes in bytes. The letter at the end can be K, M, or G signifying Kilobytes, Megabytes, or Gigabytes. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Maximum heap size (-Xmx)'''<br />
: The maximum amount of total memory (RAM) MapTool can use at once, usually entered in Gigabytes (G). For heavy frameworks with many assets, you may have to raise this value. 4G is a generous default value for nearly all users with at least 8GB of RAM.<br />
* '''Initial & minimum heap size (-Xms)'''<br />
: The minimum amount of memory (RAM) which MapTool will always reserve for use, usually entered in Gigabytes (G). Oracle recommends setting be the same as the Maximum heap size. Doing so may provide performance gains by reducing garbage collection operations. This value should not be higher than the Maximum heap size.<br />
* '''Thread stack size (-Xss)'''<br />
: The memory each particular Java thread has reserved for its use, usually entered in Megabytes (M). Raising this value may allow more complex macros to be run, but it should generally be kept as low as possible. 4M is a generous default value that allows most macros to work just fine. To help understand this value, a simple campaign using short macros or no macros may be able to run successfully with a value as low as 256K, while a campaign containing extremely large macros may need 5M or 6M to avoid stack overflow.<br />
<br />
===Advanced Options===<br />
[[Image:Prefs_Startup_Tab_Advanced_Options.png|frame|right|Advanced Options Section]]<br />
These options are used for development and troubleshooting. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Enable assertions'''<br />
: Developers often test MapTool with this option {{Checked} to enable additional Java checks so they can find additional warnings or errors. This setting is not recommended for normal users as it lowers performance.<br />
* '''Disable Direct3d Pipeline'''<br />
: When {{Checked}}, MapTool will not use Direct3D. This is mainly used by developers, but if you are having visual issues you can try using this setting to see if your problem is resolved. If so, it may indicate you need new drivers from your video card manufacturer.<br />
* '''Enable OpenGL Pipeline'''<br />
: This option may help resolve visual issues when {{Checked}} by enabling OpenGL rendering. You do not need to enable 'Disable Direct3d Pipeline' in order to use this setting.<br />
* '''Initialize AWT before JavaFX'''<br />
: Developers can use this<br />
<br />
===Language Override===<br />
[[Image:Prefs_Startup_Tab_Language_Override.png|frame|right|Language Override Section]]<br />
* '''Language'''<br />
: Select the user interface language for MapTool. Changes to this setting take effect upon restarting MapTool.<br />
<br />
===Additional Options===<br />
[[Image:Prefs_Startup_Tab_Additional_Options.png|frame|right|Additional Options Section]]<br />
* '''Data Directory'''<br />
: The local directory where MapTool saves asset cache data, autosaves, backups, configuration files, and more. Changes to this setting take effect upon restarting MapTool.<br />
<br />
[[Category:MapTool]]</div>Lwoestmanhttps://wiki.rptools.info/index.php?title=MapTool_Preferences&diff=8896MapTool Preferences2020-08-20T20:48:07Z<p>Lwoestman: /* Macro Permissions */</p>
<hr />
<div>{{note|'''Note:''' Screenshots in this article are shown with the default settings, which might not necessarily be the ''recommended'' settings for your use.}}{{Beginner}}<br />
__TOC__<br />
==Interactions Tab==<br />
[[Image:prefs_tab_interactions.png|left|thumb|300px|Interactions Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Maps===<br />
[[Image:Prefs_Interactions_Tab_-_Maps.png|frame|right|Maps Section]] <br />
* '''New maps have Fog of War'''<br />
: Determines if new maps should have [[Fog of War]] enabled when created. If you use [[Fog of War]], it might seem obvious to have this {{Checked}}; however, when creating multiple maps for a new campaign, it is often useful to to disable this feature to assist with rapid map creation since even as a GM you will be unable to clearly view a map covered in [[Fog of War]]. After completing a map, it is a simple process to re-enable [[Fog of War]].<br />
* '''New maps visible to players'''<br />
: Determines if new maps should be set as Player Visible when created. Although there are exceptions, typically having this <span style="font-size: 24px; line-height: 1px; color: red; font-weight: bold; vertical-align: sub;">&#10003;</span>unchecked is the optimal setting; that way you won't unintentionally leave a map visible to players.<br />
* '''New Map Grid Type'''<br />
** '''Square''' [[Image:gridSquare.png|sub]]<br />
** '''Horizontal Hex''' [[Image:gridHorizontalHex.png|sub]]<br />
** '''Vertical Hex''' [[Image:gridVerticalHex.png|sub]]<br />
** '''Isometric''' [[Image:gridIsometric.png|sub]]<br />
: Determines the default grid type of new maps when created. You are free to create maps without a grid type, and also a grid type different than the one specified here, but you can not set the Default Grid Type to none.<br />
* '''New Map Grid Size'''<br />
: Represents the default amount of pixels you want MapTool to use drawing each grid cell at full resolution. The default setting of {{code|50}} pixels is adequate for most computers, but higher-end computers can handle {{code|100}} pixels or even {{code|200}} pixels for very high-end computers. There is no requirement that you use specific sizes, but {{code|50}} pixels and {{code|100}} pixels are commonly used. This setting will also determine how large an image appears when placed on a map layer when 'Start Freesize' is not checked for that layer.<br />
* '''New Map Units Per Cell'''<br />
: Sets the amount of units that each grid cell represents. The ambiguous "unit" is used in this case because you decide what "unit" means. If you want each grid cell to represent 5 feet, this would be set to {{code|5}}. If you want each grid cell to represent 4 kilometers, this would be set to {{code|4}}. This is often referred to as ''Distance Per Cell''. As of v1.5.1 MapTool supports a floating point number for this value.<br />
* '''New Map Vision Distance'''<br />
: The maximum distance that [[PC Token]]s can expose [[Fog of War]] after [[Light]]s, [[Sight]]s, and [[Vision Blocking Layer]]s are taken into account. It is important to note that this setting is measured in ''Distance Per Cell''.<br />
* '''New Map Light'''<br />
: The light setting for new maps. Choose from ''Off'', ''Day'' and ''Night''. (As of MT v1.5.11)<br />
* '''Movement metric'''<br />
** '''ONE_TWO_ONE''' specifies that every second diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''ONE_ONE_ONE''' specifies that diagonal movement will calculate the same as non-diagonal movement. <br />
** '''MANHATTAN''' specifies that every diagonal movement will calculate as twice the ''Distance Per Cell''.<br />
** '''NO DIAGONALS''' specifies that [[Token]]s can only move non-diagonally.<br />
: Determines how movement should be calculated when a [[Token]] moves diagonally on maps using a Square or Isometric grid. This affects the total distance displayed beneath a [[Token]] when it is moving, or when its previous path is displayed; it is calculated based on ''Distance Per Cell''. Maps with Hex grid types ignore this setting and instead calculate movement in any direction using the ''Distance Per Cell''.<br />
<br />
===Tokens===<br />
[[Image:Prefs_Interactions_Tab_Tokens.png|frame|right|Tokens Section]] <br />
* '''Start Snap to Grid'''<br />
: Determines if [[Token]]s will default to having '''Snap to Grid''' {{Checked}}. Having this setting {{Checked}} is optimal for maps that use a grid, but even on such maps there are cases when you might want to temporarily disable this setting(e.g. when placing a lot of "prop" [[Token]]s on the Object layer while drawing a map). <br />
* '''New tokens visible to players'''<br />
: Determines if new [[Token]]s have the '''Visible''' option {{Checked}} upon creation. The optimal setting for this really depends on your play style; if you have a lot of random encounters and build them during play, you may find it useful to have this setting disabled. <br />
* '''Warn when tokens are deleted'''<br />
: When {{Checked}} MapTool asks for confirmation whenever deleting a [[Token]].<br />
* '''Duplicate Token Numbering'''<br />
** '''Increment'''<br />
** '''Random'''<br />
: Will automatically generate numbers for [[Token]]s with duplicate names upon creation to distinguish them. '''Increment''' will leave the first token unnumbered, but will number each duplicate after that starting with the number {{code|1}} (e.g. Troll, Troll 1, Troll 2). '''Random''' will create a random two-digit or greater number for the token, even if there are no duplicates on the map yet. '''Random''' might be considered the optimal setting, as it gives your players no indication of how many copies of that [[Token]] can be expected to exist.<br />
* '''Show Numbering on'''<br />
** '''Name'''<br />
** '''GM Name'''<br />
** '''Both'''<br />
: Specifies where the number that derived from '''Duplicate Token Numbering''' is applied. '''Name''' appends the number after the name (derived from '''New Token Naming'''). '''GM Name''' places the number within the ''GM Name'' field of the [[Token]] options. '''Both''' appends the number after the name, and places it within the ''GM Name'' field of the [[Token]] options. <br />
: <span style="color:red;">'''Note'''</span>: It is generally recommended that you set this preference to '''Name''' or '''Both''', and not '''GM Name'''. Any [[Macro Introduction|Macros]] which refer to tokens by name rather than by token ID will break/behave unpredictably when a map has multiple tokens with the same name.<br />
* '''New Token Naming'''<br />
** '''Use Filename'''<br />
** '''Use "Creature"'''<br />
: Determines what the name will be when creating a new [[Token]], or what the ''Name'' field will be pre-filled with in a new [[Token]] dialog. '''Use Filename''' specifies that the name will be derived from the name of the file that was added to your Resource Library (e.g. if you add the file ''uglytroll.jpg'' to your Resource Library, tokens created from that image will begin with the name ''uglytroll''). '''Use "Creature"''' defaults all new [[Token]]s to being named "Creature" (without quotes). <br />
* '''Start Freesize'''<br />
: If you are using a map with a grid, [[Token]]s typically default to the size of one grid cell upon creation. Having this setting {{Checked}} allows you to have them default to the image's ''Native Size''. ''Native Size'' tokens moved to another layer become ''Freesize'', which can be resized by dragging a handle in their lower right corner.<br />
* '''Show Dialog on New Token'''<br />
: When this setting is {{Checked}}, a ''New Token'' dialog will open when you drag an image onto the map, allowing you to set some options prior to creation. If you disable this setting, all new tokens will be created with the default settings derived from previous settings in this section.<br />
* '''Stat Sheet Portrait Size''' ''(Set to 0 to disable portaits)''<br />
: Sets the width (in pixels) of the portrait that is displayed in the lower left corner of the map when mousing over certain [[Token]]s; the image is resized proportionately. A portrait is displayed under a few different circumstances; if the [[Token]] has properties that are set to display on the stat sheet, and those properties have values, the portrait will display the token image. If the [[Token]] has a portrait image set, it will display with or without a stat sheet. Why might you want to set this to {{code|0}}? Besides the obvious reason of not displaying the portrait, you might want to use a stat sheet, but not want a portrait displayed with it; or perhaps you don't want to use a stat sheet or a portrait, but would like to have the portrait image 'slot' usable for other purposes, like inside a Dialog or Frame.<br />
* '''Show Portrait on mouseover'''<br />
: When {{Checked}}, displays the token's Portrait image in the lower left corner when the cursor is hovered over the token.<br />
* '''Show stat sheet on mouseover'''<br />
: When {{Checked}}, displays the token's stat sheet in the lower left corner (to the right of the portrait) when the cursor is hovered over the token.<br />
* '''Stat sheet requires Shift key'''<br />
: Requires the Shift key be held down when the cursor is hovered over the token in order to display the stat sheet when {{Checked}}. Has no effect if ''Show stat sheet on mouseover'' is unchecked. MapTool only checks if the Shift key is depressed when the cursor first passes over a token and then either displays or suppresses the stat sheet, meaning you cannot use this setting to 'toggle' the statsheet on and off with the shift key without also moving the cursor.<br />
* '''Force Token Facing Arrow'''<br />
: Displays a yellow facing arrow on all tokens with a facing value when {{Checked}}, even on top-down tokens which normally omit them.<br />
* '''Snap Token while dragging'''<br />
: Tokens will snap to the grid as they are dragged when {{Checked}}. When unchecked, the token's path and destination are still highlighted.<br />
* '''Hide Mouse Pointer while dragging'''<br />
: MapTool hides the cursor arrow while dragging tokens within the map view when {{Checked}}.<br />
<br />
===Chat===<br />
Chat autosave settings now reside in the 'Application' tab of the Preferences window. <br />
[[Image:prefs_interactions_chat.png|frame|right|Chat Section]] <br />
* '''Show Avatar per line'''<br />
: The image for the impersonated token is shown next to any chat output it creates, when this is {{Checked}}. This is a client-side setting and does not effect any other clients connected to the same game.<br />
* '''Insert Smilies'''<br />
: Replaces common smiley(emoticon) character sequences with graphical smilies when this is {{Checked}}. If you use a lot of macros, it is recommended that you turn this off, as it could cause some complications if any of your macro code is interpreted as a smiley.<br />
* '''Use ToolTips for Inline Rolls'''<br />
: Sets the default display ([[:Category:Display Roll Option|Display Roll Option]]) for rolls in the chat panel. Will use {{roll|tooltip}} if this is {{Checked}}, otherwise it will default to {{roll|expanded}}.<br />
* '''Suppress ToolTips for MacroLinks'''<br />
: MacroLinks normally show tooltips that state information about the link target as an anti-cheating device. When {{Checked}}, these tooltips are disabled.<br />
* '''Typing Notification Duration Seconds'''<br />
: The number of seconds before typing notifications in the top left of the Map View disappear after a player's last keystroke.<br />
* '''Typing Notification Color'''<br />
: Color of the text for typing notifications.<br />
* '''Show Chat Notification Background'''<br />
: When {{Checked}} shows a graphic behind typing notifications. Can be helpful to provide consistently contrasting background for the notifications.<br />
* '''Trusted Prefix Background'''<br />
: Sets a custom background for macro output that comes from a [[Trusted Macro]].<br />
* '''Trusted Prefix Foreground'''<br />
: Sets a custom foreground (text color) for macro output that comes from a [[Trusted Macro]].<br />
<br />
===Macro Editor===<br />
[[Image:Prefs_Interactions_Tab_Macro_Editor.png|frame|right|Macro Editor Section]]<br />
* '''Style Theme'''<br />
: Select from a variety of themes for macro editor windows.<br />
<div style="clear: both"></div><br />
<br />
===Objects===<br />
[[Image:Prefs_Interactions_Tab_Objects.png|frame|right|Objects Section]] <br />
* '''Start Snap to Grid'''<br />
: Tokens created on map's Object layer will automatically be set to '''Snap to Grid''' if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Tokens created on a map's Object layer will automatically be set to '''Freesize''' if this is {{Checked}}.<br />
<br />
===Backgrounds===<br />
[[Image:Prefs_Interactions_Tab_Backgrounds.png|frame|right|Backgrounds Section]] <br />
* '''Start Snap to Grid'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Snap to Grid''', if this is {{Checked}}. <br />
* '''Start Freesize'''<br />
: Images dropped on a map's Background layer will automatically be set to '''Freesize''', if this is {{Checked}}.<br />
<br />
===Facing===<br />
[[Image:Prefs_Interactions_Tab_Facing.png|frame|right|Facing Section]] <br />
* '''On Edges'''<br />
: A token's facing will snap to the edges when {{Checked}}. Edges are the lines that make up a grid cell.<br />
* '''On Vertices'''<br />
: A token's facing will snap to the vertices when {{Checked}}. Vertices are the points that connect the lines that make up a grid cell.<br />
<br />
==Accessibility Tab==<br />
[[Image:prefs_tab_accessibility.png|thumb|right|300px|Accessibility Tab on the Preferences Dialog]]<br />
* '''Chat Font Size'''<br />
: The default size of the font in the chat panel; measured in points.<br />
* '''ToolTip Initial Delay'''<br />
: The time it takes for a tooltip to display when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
* '''ToolTip Dismiss Delay'''<br />
: The time it takes for a tooltip to disappear when hovering the mouse over an element that possesses a tooltip; measured in miliseconds.<br />
<br />
<div style="clear: both"></div><br />
<br />
==Application Tab==<br />
[[Image:prefs_tab_application.png|left|thumb|300px|Application Tab on the Preferences Dialog]]<br />
<div style="clear: both"></div><br />
===Save===<br />
[[Image:prefs_application_save.png|frame|right|Save Section]] <br />
* '''Campaign autosave every [ ] min'''<br />
: Saves an autosave copy of your campaign in the interval specified in <code>%{appHome}/autosave</code>. This will not overwrite your campaign file, but rather create a file which is updated every time it automatically saves. Autosave is only a temporary file, useful in case MapTool crashes. When MapTool is properly closed, the Autosave file is deleted. Note the interval is the time between the last save completing and the start of the next one.<br />
: As a troubleshooting aid, the AutoSaveManager will switch from measuring the autosave interval in minutes to seconds when the [[log.setLevel|log level]] for that package is set to “DEBUG”.<br />
* '''Save reminder on close'''<br />
: Displays a dialog when attempting to close the program with unsaved changes to your campaign when {{Checked}}.<br />
* '''Time between chat log autosaves'''<br />
: The amount of time in minutes between the autosaving of the chat log.<br />
* '''Autosave chat log filename'''<br />
: The filename that will be used when automatically saving your chat log.<br />
* '''File Sync Directory'''<br />
: Specify a path to a local cloud-synced directory to determine relative path external files such as Hero Lab portfolios.<br />
* '''1.3b50 Compatability Mode''' <br />
: <code>This setting has been removed. You can use File > Export Campaign As... to save campaigns for MapTool versions as far back as 1.4.0.</code><br />
: Due to some changes in how certain data is stored in the campaign file in versions after 1.3b50, they might not be compatible with version 1.3b50 and earlier. If this is {{Checked}} your campaign will be saved in the older format, allowing it to be opened in older versions, but losing some of the new features.<br />
<br />
===Map Visuals===<br />
[[Image:Prefs_Application_Tab_Map_Visuals.png|frame|right|Map Defaults Section]] <br />
* '''Halo line width'''<br />
: Controls the width of the [[Halo]] border when it is displayed on a [[Token]].<br />
* '''Use halo color for vision'''<br />
: When this setting is {{Checked}}, hovering over a token with [[Vision]] overlays the token's visible area with the token's [[Halo]] color. This overlay is a translucent layer controlled by the '''Halo opacity''' setting. <br />
* '''Halo opacity'''<br />
: Controls the opacity of the optional overlay enabled by the '''Use halo color for vision''' setting. This does not control the actual [[Halo|Halo's]] outline opacity, which is always completely opaque. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Aura opacity'''<br />
: Controls the opacity of color overlays provided by [[Aura|Auras]] enabled on tokens. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Light opacity'''<br />
: Controls the opacity of color overlays provided by [[Introduction_to_Lights_and_Sights#Light_Sources|Light Sources]] enabled on tokens. This also affects 'personal' lights defined in a token's [[Vision]] setting. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Fog opacity'''<br />
: Controls the opacity of the black layer of 'Soft Fog' that is left in previously explored areas when [[Fog of War]] is enabled. This value can be a number from 0 (transparent) to 255 (opaque).<br />
* '''Auto-expose fog on token movement (GM Only)'''<br />
: Will automatically expose [[Fog of War]] after moving a [[Token]] if {{Checked}}. This setting is intended to help test Fog of War and VBL when not hosting a game. When running a server, this setting is ignored in favor of the settings in the 'Start Server' dialog.<br />
<br />
===Performance===<br />
[[Image:Prefs_Application_Tab_Performance.png|frame|right|Performance Section]]<br />
* '''Fill selection box'''<br />
: When {{Checked}}, the selection box which appears when dragging to select tokens in the Map View will contain a translucent blue fill. Less powerful devices running MapTool may see a small performance gain from unchecking this setting.<br />
* '''Frame Rate Cap''' <code>New in MapTool 1.5.7</code><br />
: Sets the maximum frame rate for the map renderer. Less powerful devices running MapTool may see a performance gain by lowering this setting.<br />
<br />
===Initiative Defaults===<br />
[[Image:Prefs_Application_Tab_Initiative_Defaults.png|frame|right|Initiative Section]]<br />
* '''Hide NPCs from players on new maps'''<br />
: When {{Checked}}, automatically enables 'Hide NPCs' in the [[Initiative Panel]] on new maps. This setting doesn't show connected players [[NPC Tokens]] on the Initiative Panel.<br />
* '''Give Owners Permission in new campaigns'''<br />
: This automatically enables the 'Owner Permissions' setting in the [[Initiative Panel]] on new maps when {{Checked}}. The setting mainly lets players with token ownership add their tokens to or remove their tokens from the initiative list and advance the initiative when it is their token's turn.<br />
* '''Lock Player Movement in new campaigns'''<br />
: When {{Checked}}, new maps will have 'Lock Player Movement' automatically enabled in the [[Initiative Panel]]. This setting prevents players who do not own the token with initiative from moving any tokens.<br />
* '''Show Initiative Gain Message'''<br />
: When initiative advances to a [[PC Token]] token and this is {{Checked}}, a simple 'Token Name has received initiative' message is displayed for all players in chat. This is ignored for [[NPC Token|NPC Tokens]].<br />
<br />
===Client===<br />
[[Image:Prefs_Application_Tab_Client.png|frame|right|Client Section]]<br />
* '''Fit GM View'''<br />
: When {{Checked}} and the GM uses 'Center Players on Current View', the Map View will zoom out as necessary to accommodate the entire GM view. If unchecked, the zoom level will be set to match the GM's Map View, which will occlude part of the map if your Map View areas are different sizes.<br />
<br />
===Macro Panels===<br />
[[Image:Prefs_Application_Tab_Macro_Panels.png|frame|right|Macro Panels Section]] <br />
* '''Default: Allow Players to Edit Macros'''<br />
: In order for a macro to be considered a [[Trusted Macro]], players must not be able to edit it. This setting determines if a new macro should default to allowing players to edit if {{Checked}}. Disabling this setting can be very useful if you intend to create a lot of macros that you intend to be trusted.<br />
<br />
===UPnP===<br />
[[Image:Prefs_Application_Tab_UPnP.png|frame|right|UPnP Section]]<br />
* '''Discovery Timeout'''<br />
: The timeout period in milliseconds MapTool will wait when searching for UPnP gateways before giving up.<br />
<br />
===Macro Permissions===<br />
[[Image:Prefs_Application_Tab_Macro_Permissions.png|frame|right|Macro Permissions Section]]<br />
* '''Enable External Macro Access'''<br />
: When {{Checked}}, [[Introduction to Macro Writing|Macros]] may call functions that access your drive and http services. Some examples (not a complete list) of functions which will be enabled are [[RESTful Functions Overview|REST Functions]], [[exportData]], and [[getEnvironmentVariable]].<br />
<div style="clear: both"></div><br />
<br />
==Sounds Tab==<br />
[[Image:prefs_tab_sounds.png|thumb|right|300px|Sounds Tab on the Preferences Dialog]]<br />
* '''Play system sounds'''<br />
: When {{Checked}}, MapTool will play a sound when new content is sent to the chat panel.<br />
* '''Play steams'''<br />
: When {{Checked}}, streams started with [[playStream]] will be allowed to play.<br />
* '''Only when window not focused'''<br />
: When {{Checked}}, the sound that MapTool plays when new content is sent to the chat panel will only play if MapTool is not the application that has focus.<br />
* '''Turn on Syrinscape Integration'''<br />
: When clicking <code>syrinscape-fantasy:</code> links in MapTool, the Syrinscape Fantasy Player will be allowed to automatically open when this setting is {{Checked}}. This has no effect on [[Syrinscape Integration]] using the REST API and Online Player.<br />
<br />
==Startup Tab==<br />
[[Image:Prefs_Startup_Tab.png|thumb|300px|frame|left|Startup Tab of Preferences Dialog]]<br />
<div style="clear: both"></div><br />
<br />
===JVM Memory Settings===<br />
[[Image:Prefs_Startup_Tab_JVM_Settings.png|frame|right|JVM Memory Section]]<br />
These preferences are somewhat advanced. To better understand how MapTool uses memory settings, read about [[Stack Size]]. If you are having Stack Overflow errors and need to modify these settings for more reliable performance, read about [[Avoiding Stack Overflow]]. If you need help resetting MapTool memory settings, check out [https://www.rptools.net/2019/04/resetting-maptool/ Resetting MapTool JVM Settings] on the RPTools blog.<br />
<br />
These three settings are memory sizes in bytes. The letter at the end can be K, M, or G signifying Kilobytes, Megabytes, or Gigabytes. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Maximum heap size (-Xmx)'''<br />
: The maximum amount of total memory (RAM) MapTool can use at once, usually entered in Gigabytes (G). For heavy frameworks with many assets, you may have to raise this value. 4G is a generous default value for nearly all users with at least 8GB of RAM.<br />
* '''Initial & minimum heap size (-Xms)'''<br />
: The minimum amount of memory (RAM) which MapTool will always reserve for use, usually entered in Gigabytes (G). Oracle recommends setting be the same as the Maximum heap size. Doing so may provide performance gains by reducing garbage collection operations. This value should not be higher than the Maximum heap size.<br />
* '''Thread stack size (-Xss)'''<br />
: The memory each particular Java thread has reserved for its use, usually entered in Megabytes (M). Raising this value may allow more complex macros to be run, but it should generally be kept as low as possible. 4M is a generous default value that allows most macros to work just fine. To help understand this value, a simple campaign using short macros or no macros may be able to run successfully with a value as low as 256K, while a campaign containing extremely large macros may need 5M or 6M to avoid stack overflow.<br />
<br />
===Advanced Options===<br />
[[Image:Prefs_Startup_Tab_Advanced_Options.png|frame|right|Advanced Options Section]]<br />
These options are used for development and troubleshooting. Changes to these settings take effect upon restarting MapTool.<br />
<br />
* '''Enable assertions'''<br />
: Developers often test MapTool with this option {{Checked} to enable additional Java checks so they can find additional warnings or errors. This setting is not recommended for normal users as it lowers performance.<br />
* '''Disable Direct3d Pipeline'''<br />
: When {{Checked}}, MapTool will not use Direct3D. This is mainly used by developers, but if you are having visual issues you can try using this setting to see if your problem is resolved. If so, it may indicate you need new drivers from your video card manufacturer.<br />
* '''Enable OpenGL Pipeline'''<br />
: This option may help resolve visual issues when {{Checked}} by enabling OpenGL rendering. You do not need to enable 'Disable Direct3d Pipeline' in order to use this setting.<br />
* '''Initialize AWT before JavaFX'''<br />
: Developers can use this<br />
<br />
===Language Override===<br />
[[Image:Prefs_Startup_Tab_Language_Override.png|frame|right|Language Override Section]]<br />
* '''Language'''<br />
: Select the user interface language for MapTool. Changes to this setting take effect upon restarting MapTool.<br />
<br />
===Additional Options===<br />
[[Image:Prefs_Startup_Tab_Additional_Options.png|frame|right|Additional Options Section]]<br />
* '''Data Directory'''<br />
: The local directory where MapTool saves asset cache data, autosaves, backups, configuration files, and more. Changes to this setting take effect upon restarting MapTool.<br />
<br />
[[Category:MapTool]]</div>Lwoestman