Raoden's Quick'n'Dirty Token Manager

These are tools and utilities that make it easier to run games. This includes Lib: macro tokens dropped into MapTool to manage the game, a conversion file for CharacterTool to allow use in MapTool, or just about anything else you can think of -- except graphics with macros and anything specific to a particular campaign framework. Those are already covered by the Tilesets subforum and the Links and External Resources forum.

Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

The link is the link above and the error is the title of the code was cut off because I think I used [wfunc]varsFromStrProp[/wfunc] to declare variables locally.. the title had ; in it, so the rest of the string was ignored, hence the string for "title" was shorter than expected.

No worries on the fix... I'm sure, as you said about no complaints for a year, it's not really a thing that comes up alot. I just got lucky on my first try :D.

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

Here's an error I'm getting:
 Invalid condition in IF(json.type( piece ) == "UNKNOWN") roll option.       Statement options (if any): if( json.type( piece ) == "UNKNOWN" ), code       Statement Body (first 200 characters): { [h: linkArg = json.append( '[]', key, pathPiece )]
[r: field]
[r: macroLink( piece, "[email protected]", "self", linkArg, id )] [r, if( arrayKey ): " " ] [r


I'm clicking on an object with the following contents:

Code: Select all

{
    "Spell": "[r: spell.acidarrow.spell = \"Acid Arrow\"][h: spell.acidarrow.spell_name = \"Spell\"]",
    "School": "[r: spell.acidarrow.school = \"Conjuration\"][h: spell.acidarrow.school_name = \"School\"]",
    "Subschool": "[r: spell.acidarrow.subschool = \"Creation\"][h: spell.acidarrow.subschool_name = \"Subschool\"]",
    "Descriptor": "[r: spell.acidarrow.descriptor = \"Acid\"][h: spell.acidarrow.descriptor_name = \"Descriptor\"]",
    "Level": "[r: spell.acidarrow.level = \"Sorcerer/Wizard 2\"][h: spell.acidarrow.level_name = \"Level\"]",
    "Spell Components": "[r: spell.acidarrow.spellcomponents = \"V, S, M, F\"][h: spell.acidarrow.spellcomponents_name = \"Spell Components\"]",
    "Casting Time": "[r: spell.acidarrow.castingtime = \"1 standard action\"][h: spell.acidarrow.castingtime_name = \"Casting Time\"]",
    "Range": "[r: spell.acidarrow.range = \"Long (400 ft. + 40 ft./level)\"][h: spell.acidarrow.range_name = \"Range\"]",
    "Target": "[r: spell.acidarrow.target = \"\"][h: spell.acidarrow.target_name = \"Target\"]",
    "Area": "[r: spell.acidarrow.area = \"\"][h: spell.acidarrow.area_name = \"Area\"]",
    "Effect": "[r: spell.acidarrow.effect = \"One arrow of acid\"][h: spell.acidarrow.effect_name = \"Effect\"]",
    "Duration": "[r: spell.acidarrow.duration = \"1 round + 1 round per three levels\"][h: spell.acidarrow.duration_name = \"Duration\"]",
    "Saving Throw": "[r: spell.acidarrow.savingthrow = \"None\"][h: spell.acidarrow.savingthrow_name = \"Saving Throw\"]",
    "Spell Resistance": "[r: spell.acidarrow.spellresistance = \"No\"][h: spell.acidarrow.spellresistance_name = \"Spell Resistance\"]",
    "Material Components": "[r: spell.acidarrow.materialcomponents = \"Powdered rhubarb leaf and an adder's stomach.\"][h: spell.acidarrow.materialcomponents_name = \"Material Components\"]",
    "Focus": "[r: spell.acidarrow.focus = \"a dart\"][h: spell.acidarrow.focus_name = \"Focus\"]",
    "XP Cost": "[r: spell.acidarrow.xpcost = \"\"][h: spell.acidarrow.xpcost_name = \"XP Cost\"]",
    "Reference": "[r: spell.acidarrow.reference = \"SRD 3.5\"][h: spell.acidarrow.reference_name = \"Reference\"]",
    "Short Description": "[r: spell.acidarrow.shortdescription = \"Ranged touch attack; 2d4 damage for 1 round +1 round/three levels.\"][h: spell.acidarrow.shortdescription_name = \"Short Description\"]",
    "Description": "[r: spell.acidarrow.description = \"<p>A magical arrow of acid springs from your hand and speeds to its target. You must succeed on a ranged touch attack to hit your target. The arrow deals 2d4 points of acid damage with no splash damage. For every three caster levels (to a maximum of 18th), the acid, unless somehow neutralized, lasts for another round, dealing another 2d4 points of damage in that round.</p> <p/>\"][h: spell.acidarrow.description_name = \"Description\"]"
}

It's a valid json, just in case if you were wondering. I got the contents locally with the following code:

Code: Select all

[dialog("D"):{<pre>[R: json.indent(replace(getProperty("spell.acidarrow"),"<","&lt;"))]</pre>}]

If it wasn't a json, it would have crashed. My thought is the text editing field you create can't handle some of the characters. I'm not sure. Other than this little set back, it's been really useful for me checking to make sure I'm creating the correct hidden properties.

edit: Okay, the json.type does not like strings that resemble arrays or objects. I'm seeing if there is a work around so you can know what the type is of a string, but that is proving difficult.

edit: Here's a conundrum. When piece = '{am.lib.glp("spell.acidarrow")}'.

Code: Select all

[dialog("D"):{<pre>[R: (replace(piece,"<","&lt;"))]</pre>}]
[h: input("pause")]
[R: a = json.type(piece)] <!-- with this line a null point exception -->
   <tr>
   [ if( json.type( piece ) == "UNKNOWN" ), code: { <!-- without the above, this does not error -->


edit: I'm having one of these moments.

I figured out a work around so [wfunc]json.type[/wfunc] doesn't explode in my face.

Code: Select all

[H: jType = json.append("",data)]
[H: jType = json.type(json.get(jType,0))]

You "have to" have them on separate lines for it to work. This fixes the problem from above when clicking the link. I did notice another "bug", which isn't all that bad for my purposes, but <p> breaks the link when in the text. I'm going to assume html in a macrolink is processed, so you should probably do a text = replace(text,"<","&lt;") to fix the macro link text (perhaps show the html in a tooltip?). Also, it would be nice when editing a property that is long to have the input be a bit bigger. Perhaps have a min/max set the field size based on the text inside.

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

Okay, I updated the token with the fixes and the other tweaks I mentioned.

[spoiler=/// NOTES \\\]

Code: Select all

Updates for v2.1
  * Made input text when modifying long strings, longer
  * Links to update text fields have html neutralized, size
      limit and a tooltip to show contents in html.
  * Fix made for json.type error for special strings
  * Display of object keys that begin/end with a space
      (see bottom for related error)
 
Modified macros:
  QnD.editProps.input
  QnD.json.replace   
  subFrame.Tokens.Properties
  json.layout.editable

Not fixed
  * Key names that begin/end with a space break the link
      "path". This requires the path to be changed to a json in
      all locations and get rid of the listGet because it trims
      the path string items. (I found this because I have an
      object that saves the macro group names where one of
      them starts with a space.)
[/spoiler]
Attachments
Lib.TokenManager_v2.1.rptok
MT v1.3b86
(52.84 KiB) Downloaded 139 times

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

I found another limitation, which is really a MT limitation and that the list of variables can't exceed 1000 names because of the MT loop limitation. This can be fixed by breaking the loop with a deferred call and passing the built output so far.

aRTy
Kobold
Posts: 3
Joined: Sat Apr 21, 2012 7:10 am

Re: Raoden's Quick'n'Dirty Token Manager

Post by aRTy »

Since resetProperty now actually deletes properties, one can use that. I wrote a macro out of personal need and then realised others might have use for it. I took a few looks at the token manager macros, but don't feel really comfortable replacing the corresponding macros with my stuff. So I'll just post what I got:

The main macro. It produces a list with checkboxes. The user can either delete specific selected properties or exclude them from deletion (while deleting everything else). You'll get a dialog to confirm the selection you made.
[spoiler=delete selected properties]

Code: Select all

[h: propertyList = getMatchingProperties(".*",", ")]

[h, s: assert( listCount(propertyList), "No properties set.", 0)]

[h: checkCounter = 0]

[h: propertyListDisplay = "label|<html>Select properties for deletion<br><br></html>|<html><span></span></html>|LABEL|SPAN=TRUE##invertSelection|0|Invert selection (keep selected)|CHECK"]

[h, foreach(property, propertyList), code:
   { [h: propertyListDisplay = listAppend(propertyListDisplay, "check"+checkCounter+"|1|"+listGet(propertyList, checkCounter)+"|CHECK","##")]
   [h: checkCounter = checkCounter + 1] }
 ]

[h: askReset= input(propertyListDisplay)]
[h: abort(askReset)]

[h: propertyListDeselected = ""]

[h, for(i,checkCounter-1,-1,-1), if( eval("check"+i) == 0), code:
   { [h: propertyListDeselected = listAppend(propertyListDeselected, listGet(propertyList, i) ) ]
   [h: propertyList = listDelete(propertyList, i) ] };
   {} ]

[h: propertyListDeselected = listSort(propertyListDeselected,"A")]

[h, switch(invertSelection), code:
   case0: { [h: resetList = propertyList] [h: confirmList = replace(propertyListDeselected, ",", "<br>")]
      [h: confirmText = "All properties <b>except</b> the following will be deleted:<br><br>"] };
   case1: { [h: resetList = propertyListDeselected] [h: confirmList = replace(propertyListDeselected, ",", "<br>")]
      [h: confirmText = "<b>Only</b> the following properties will be deleted:<br><br>"] }
 ]

[h, if( listCount(confirmList) == 0 ), code:
   { [h, switch(invertSelection), code:
      case0: { [h: confirmList = "<i>All will be deleted.</i>"]};
      case1: { [h, s: assert( 0, "No property was selected for deletion.", 0)] }
   ]}; {}
 ]

[h: confirmReset = input(
"junk|<html>"+confirmText + confirmList+"</html>|<html><span></span></html>|LABEL|SPAN=TRUE")]
[h: abort(confirmReset)]

[h: resetAmount = listCount(resetList)]

[foreach(propertyName, resetList, ""), code:
   { [h: resetProperty(propertyName) ] }
 ]
 [r: resetAmount] [r: if(resetAmount != 1,"properties","property")] deleted.
[/spoiler]

A trivial macro which posts a list of all properties into the chat. I prefered it for a quick overview.
[spoiler=list all properties]

Code: Select all

[h: propertyList = getMatchingProperties(".*", ", ")]
[r, s, if( listCount(propertyList) == 0): "No properties set."; propertyList]
[/spoiler]
Attachments
list all & delete selected properties.mtmacset
(1.41 KiB) Downloaded 88 times

the_meek
Cave Troll
Posts: 99
Joined: Fri Aug 01, 2008 9:18 am

Re: Raoden's Quick'n'Dirty Token Manager

Post by the_meek »

Recently started using this. I love it. It's really a must-have for anybody using "hidden" properties. Just wanted to thank Raoden and aliasmask.

the_meek
Cave Troll
Posts: 99
Joined: Fri Aug 01, 2008 9:18 am

Re: Raoden's Quick'n'Dirty Token Manager

Post by the_meek »

I've got an error that has me stumped. On a library token that I'm storing the cache for a frame on, I'm getting the following error:

Code: Select all

 Invalid condition in IF(json.type( value ) != "ARRAY" && json.type( value ) != "OBJECT") roll option.
  Statement options (if any): r, if( json.type( value ) != "ARRAY" && json.type( value ) != "OBJECT" ), code
  Statement Body (first 200 characters): { [H: length = min(max(length(value),0),80)] [H: mValue = replace(substring(value,0,length),"","<")] [H: tValue = replace(value,'"','"')] [H, if(! startsWi

This code is in the "subFrame.Tokens.Properties" macro. If I pull out the IF and the "else", it works. Is there a downside to this, other than not being able to use the JSON editor?

Here's the property that's setting it off:

Code: Select all

[H: TempIDProps = getMatchingLibProperties("class.[0-9]+.name", Token.Library)]
[
H: ClassIDs = "[]"]
[
H: HighLevel = 0]
[
H, FOREACH(Property, TempIDProps, ""), IF(getLibProperty(Property, Token.Library) != ""), CODE: {
    [SlotsJSON = getLibProperty(replace(Property, "name", "spellslots"), Token.Library)]
    [IF(! json.isEmpty(SlotsJSON)), CODE: {
        [ClassIDs = json.append(ClassIDs, Property)]
        [C(9): HighLevel = if(json.get(SlotsJSON, roll.count) != 0 && roll.count + 1 > HighLevel, roll.count + 1, HighLevel)]
    }; {}]
};
 {}]
<
table width="100%">
    <tr>
        <th colspan=[R: HighLevel + 1]>Spells per Day</th>
    <tr class="subheading">
        <th>CLASS</th>
        [R, C(HighLevel, ""): strformat('<th class="minwidth">LV%{roll.count}</th>')]
    [R, FOREACH(Property, ClassIDs, ""), CODE: {
        [H: ClassName = getLibProperty(Property, Token.Library)]
        [H: StringID = strfind(Property, "class.([0-9]+).name")]
        [H: ClassID = getGroup(StringID, 1, 1)]
        [H: SlotsJSON = getLibProperty(strformat("Class.%{ClassID}.SpellSlots"), Token.Library)]
        <tr [R, IF(! band(1, roll.count)): 'class="stripe"']>
            <td><span title="Edit [R: ClassName] spells per day.">[R: macroLink(ClassName, "[email protected]", "none", ClassID)]</span></td>
            [R, C(HighLevel, ""): strformat('<td align="center">%d</td>', json.get(SlotsJSON, roll.count) + 0)]
    }]
    <tr class="subheading">
        <td colspan=[R: HighLevel + 1] align="center">[R: macroLink("ADD NEW", "[email protected]", "none", -1)]</td>
    <tr class="subheading"><td colspan=[R: HighLevel + 1]>&nbsp;</td>
</
table> 

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

What version of the token manager are you using?

json.type can't handle strings that start and end with {} or [] if they're are not jsons. I think 2.1 has an updated json.type (I think). Anyway, if not, this is the code I use:

Code: Select all

@@ @json.type
[HjType json.append("",arg(0))]
[
HjType oldFunction(json.get(jType,0))]
[
Hmacro.return = jType]

!!
 

I didn't look at your code because it seems unrelated to error. (no matching if statement) This may not be the cause of your error but I'm guessing it is.

the_meek
Cave Troll
Posts: 99
Joined: Fri Aug 01, 2008 9:18 am

Re: Raoden's Quick'n'Dirty Token Manager

Post by the_meek »

That makes sense. I'm on 2.1, but it doesn't look like there's a json.type() included. I'll override it with your code. Thanks a ton.

Edit: Created json.type macro, defined the function, tried to open the frame... no dice. Still the same error. Weird. It works on the dozen other very similar properties. I can live without the JSON editor though.

Another edit: I moved the <table> line up to the beginning and it works fine.

User avatar
aliasmask
Deity
Posts: 8667
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Raoden's Quick'n'Dirty Token Manager

Post by aliasmask »

Whatever was happening was seeming to break your json formatting.

User avatar
Raoden
Dragon
Posts: 381
Joined: Fri Dec 18, 2009 2:33 am
Location: San Diego

Re: Raoden's Quick'n'Dirty Token Manager

Post by Raoden »

Probably because it started with a '[' but didn't end with one? I dunno ... I've sadly lost much of the knowledge of MapTool code that I had back when I made this tool. :?
"Fairy tales do not tell children the dragons exist. Children already know that dragons exist. Fairy tales tell children the dragons can be killed."
- G. K. Chesterton

Wonderful HTML/CSS reference * Color Manager * Token Manager 2.0

Elorebaen
Dragon
Posts: 365
Joined: Sat Dec 22, 2007 5:37 pm

Re: Raoden's Quick'n'Dirty Token Manager

Post by Elorebaen »

Question: I would like to be able to select a number of tokens, and change all of their names at once, while have sequential numbers added. So instead of "orc, orc 1, orc 2, etc", I could change them all to "monster, monster 1, etc, etc," after the party has made their Knowledge checks.

Could this token manager do that? Have any macro ideas for this?

Thank you!

User avatar
CoveredInFish
Demigod
Posts: 3104
Joined: Mon Jun 29, 2009 10:37 am
Location: Germany
Contact:

Re: Raoden's Quick'n'Dirty Token Manager

Post by CoveredInFish »

The token manager is not up to this - it is a tool to edit the properties, even hidden, of a single token - but a short macro can do it.

Code: Select all

[h: tokens = getSelected()]
[h: index = 1]
[h: abort(input("name|Monster|TEXT"))]
[h, foreach(id, tokens), code: {
  [setName(strformat("%s %s", name, index), id)]
  [h: index = index + 1]
}]

User avatar
wolph42
Deity
Posts: 9852
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Raoden's Quick'n'Dirty Token Manager

Post by wolph42 »

CoveredInFish wrote:The token manager is not up to this - it is a tool to edit the properties, even hidden, of a single token - but a short macro can do it.

Code: Select all

[h: tokens = getSelected()]
[h: index = 1]
[h: abort(input("name|Monster|TEXT"))]
[h, foreach(id, tokens), code: {
  [setName(strformat("%s %s", name, index), id)]
  [h: index = index + 1]
}]


//Highly off topic
I see you've updated your sig as well. Does that mean that the MT doc project is now fully disbanded?

Elorebaen
Dragon
Posts: 365
Joined: Sat Dec 22, 2007 5:37 pm

Re: Raoden's Quick'n'Dirty Token Manager

Post by Elorebaen »

CoveredInFish wrote:The token manager is not up to this - it is a tool to edit the properties, even hidden, of a single token - but a short macro can do it.

Code: Select all

[h: tokens = getSelected()]
[h: index = 1]
[h: abort(input("name|Monster|TEXT"))]
[h, foreach(id, tokens), code: {
  [setName(strformat("%s %s", name, index), id)]
  [h: index = index + 1]
}]


Wow, awesome! That worked perfectly. Thank you!

Post Reply

Return to “Drop-In Macro Resources”