frame(), macroLink, and "TOKEN"

Thoughts, Help, Feature Requests, Bug Reports, Developing code for...

Moderators: dorpond, trevor, Azhrei

Forum rules
PLEASE don't post images of your entire desktop, attach entire campaign files when only a single file is needed, or generally act in some other anti-social behavior. :)
Post Reply
claud9999
Kobold
Posts: 19
Joined: Fri Nov 14, 2008 6:00 pm
Location: Santa Clara, CA
Contact:

frame(), macroLink, and "TOKEN"

Post by claud9999 »

I'd like to have a macro that shows a power in a frame with a link that, when you click the link, calls the macro again but passing in an argument that causes this macro to do something. But it don't work, the macroLink shows up but clicking on it reports "Unknown macro TestPower." It sure seems, according to the MapTool Wiki that I should be able to do this, but I'm guessing there's macroLink() does not support "@TOKEN" like macro()...

In reality, in my mind, macro() [and macroLink()] should support [email protected] or even [email protected] for uniqueness.

I'm able to do something with library macros acting as go-betweens...Just am hoping to get around having to use library tokens if possible.

Sample code, assuming it's on a macro named "TestPower":

Code: Select all

[if(argCount()>0),code: {
    I use the POWER!
}; {
    [frame("power"):{I have the POWER! [macroLink("Use the POWER!","[email protected]","all","testarg")]}]
}]

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

Re: frame(), macroLink, and "TOKEN"

Post by Raoden »

claud9999 wrote:It sure seems, according to the MapTool Wiki that I should be able to do this, but I'm guessing there's macroLink() does not support "@TOKEN" like macro()...

I think it does, as long as the calling macro is Trusted. But I'm not very clear on when macros are Trusted or not, when they're not on library tokens.

In reality, in my mind, macro() [and macroLink()] should support [email protected] or even [email protected] for uniqueness.

A lot of things besides this break if you have tokens with the exact same name. :?

Just am hoping to get around having to use library tokens if possible.

I think if you want any serious amount of automation in your games, sooner or later you really will just need library tokens.

Code: Select all

[if(argCount()>0),code: {
    I use the POWER!
}; {
    [frame("power"):{I have the POWER! [macroLink("Use the POWER!","[email protected]","all","testarg")]}]
}]

Well, at least one problem with your code is the type of argument you're testing for.

You see, macros really only have one argument passed to them, ever. When it seems like they have more than one argument, it's really just using a JSON Array (containing multiple arguments within it) as a workaround.

Therefore, argCount() only counts anything if the macro's argument is, in fact, a JSON Array. argCount() is like json.length(macro.args).

So "testarg" is not going to be recognized by argCount() after it is passed. You can either force macroLink() to pass a JSON array:

Code: Select all

[macroLink("Use the POWER!","[email protected]","all",json.append('[]',testarg))] 

... or you can change the way you're testing the incoming data, using

Code: Select all

[if( macro.args != "" ), code:  

instead of the if statement that utilizes [wfunc]argCount[/wfunc].
"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

prestidigitator
Dragon
Posts: 317
Joined: Fri Apr 23, 2010 8:17 pm

Re: frame(), macroLink, and "TOKEN"

Post by prestidigitator »

I believe you might have to use the result of [wfunc]getMacroLocation[/wfunc] rather than "@TOKEN". If the user is just clicking on a link (or virtually clicking on it through the client's automatic link execution feature), how does it know the context in which you wrote "@TOKEN"?
"He knows not how to know who knows not also how to un-know." --Sir Richard Burton

claud9999
Kobold
Posts: 19
Joined: Fri Nov 14, 2008 6:00 pm
Location: Santa Clara, CA
Contact:

Re: frame(), macroLink, and "TOKEN"

Post by claud9999 »

First let me describe in more detail my goal and my concern about having to use a library token.

In my D&D 4E campaign, I am building macros for my (naive) players to use. The intent is to show the "power card" in a frame, and if/when they click the "use" link, they /say the flavor text, g: the rolls, change the group of the macro button (I find it easiest to move them to a "USED" group) and automagically decrement ammunition. Obviously only some powers use ammo, some use ammo, etc. If I rely on a library macro, I have to pass a whole lot of parameters and/or code through the macroLink() to support the execution of the "business logic" in that macro. If, instead, the link could just call the same power macro, the code is all in the same place.

For example, the parameters through the macroLink, if I were to use the library function, would be:

Token ID
Macro IDx
"flavor text" (for the token to "/say")
"business logic" (toggle, ammo, dice rolls, etc.)

Raoden wrote:
claud9999 wrote:In reality, in my mind, macro() [and macroLink()] should support [email protected] or even [email protected] for uniqueness.

A lot of things besides this break if you have tokens with the exact same name. :?


Note I said "token id" not "token name"...Anyways, just clarifying.

So "testarg" is not going to be recognized by argCount() after it is passed. You can either force macroLink() to pass a JSON array:

Code: Select all

[macroLink("Use the POWER!","[email protected]","all",json.append('[]',testarg))] 

... or you can change the way you're testing the incoming data, using

Code: Select all

[if( macro.args != "" ), code:  

instead of the if statement that utilizes [wfunc]argCount[/wfunc].


Ah, thanks for the clarification. (Is this indicated in the maptool wiki somewheres?) Actually in my library token sample, I used strPropFromVars() to pass my parameters, but same diff.

prestidigitator wrote:I believe you might have to use the result of [wfunc]getMacroLocation[/wfunc] rather than "@TOKEN". If the user is just clicking on a link (or virtually clicking on it through the client's automatic link execution feature), how does it know the context in which you wrote "@TOKEN"?


Ah the wiki doc for macro() indicates the use of @TOKEN, and the macroLink indicates that the second arg is the same format as for macro(). If @TOKEN does not work for macroLink it should be indicated on the wiki. (I haven't updated the wiki 'cause I don't know if it's a bug or intentional that macroLink() doesn't support @TOKEN.)

Anyways, I've tried [wfunc]getMacroLocation[/wfunc] and it seems to get me closer, but the macroLink, when clicked, reports:

Must specify a location for the macro "Token:test token" to be run from.

I've tried adding "currentToken()" to the macroLink arg list, and no luck...Reports same...Hrm, so close.

Code: Select all

[h: arglen = length(arg(0))]
[h: currentTokenId = currentToken()]
[r: "tok: " + currentTokenId]
[if(arglen > 0), code: {
[r: "foo"]
}; {
[frame("power"): {
Test Power
[macroLink("use power", getMacroLocation(), "all", "bogusarg", currentTokenId)]
}]
}]

claud9999
Kobold
Posts: 19
Joined: Fri Nov 14, 2008 6:00 pm
Location: Santa Clara, CA
Contact:

Re: frame(), macroLink, and "TOKEN"

Post by claud9999 »

Oh, and also saying getMacroName() + "@" + getMacroLocation() doesn't work either, reporting:

Macros from other tokens are only available if the token name starts with "Lib:".

Here's the code for your copy/paste joy:

Code: Select all

[h: arglen = length(arg(0))]
[h: currentTokenId = currentToken()]
[r: "tok: " + currentTokenId]
[if(arglen > 0), code: {
[r: "foo"]
}; {
[frame("power"): {
Test Power
[macroLink("use power", getMacroName() + "@" + getMacroLocation(), "all", "bogusarg", currentTokenId)]
}]
}]

prestidigitator
Dragon
Posts: 317
Joined: Fri Apr 23, 2010 8:17 pm

Re: frame(), macroLink, and "TOKEN"

Post by prestidigitator »

Oh. Yeah. That's true. In order to call another macro (using either [wroll]macro[/wroll] or a macro link, I believe), that macro has to be on a library token. It's a pretty simple operation to move code from a normal token to a library token and then leave skeleton code in place that simply calls the library token macro....
"He knows not how to know who knows not also how to un-know." --Sir Richard Burton

User avatar
biodude
Dragon
Posts: 444
Joined: Sun Jun 15, 2008 2:40 pm
Location: Montréal, QC

Re: frame(), macroLink, and "TOKEN"

Post by biodude »

As I understand, this is a token macro (not a campaign macro), and you want the macrolink to trigger the same macro as the one that created the frame? Did you try using "[email protected]"? I could be wrong, but it might not have the same restrictions as "@token" or other locations intended for use with Lib:tokens.

For these "self-executing" macrolinks, I often just define the location with:

Code: Select all

[H: macro.loc = getMacroName() +"@this" ]


But sometimes this works instead:

Code: Select all

[H: macro.loc = getMacroName() +"@"+ getMacroLocation() ]


But, I'm used to using Lib macros, not token macros, so I could be wrong.
"The trouble with communicating is believing you have achieved it"
[ d20 StatBlock Importer ] [ Batch Edit Macros ] [ Canned Speech UI ] [ Lib: Math ]

prestidigitator
Dragon
Posts: 317
Joined: Fri Apr 23, 2010 8:17 pm

Re: frame(), macroLink, and "TOKEN"

Post by prestidigitator »

I don't think you can use "@this" in a link at all, because when a link is executed it's not done from an running macro, so MapTool won't know what "this" is. Even [wfunc]execLink[/wfunc] interprets the link from outside the context of the running macro (definitely when deferred; I suspect also when run in parallel without being deferred).
"He knows not how to know who knows not also how to un-know." --Sir Richard Burton

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

Re: frame(), macroLink, and "TOKEN"

Post by Raoden »

prestidigitator wrote:I don't think you can use "@this" in a link at all, because when a link is executed it's not done from an running macro, so MapTool won't know what "this" is.

I do this all the time. It determines the "this" when it creates the link, not when the link is clicked.

claud9999 wrote:Macros from other tokens are only available if the token name starts with "Lib:".

This makes me suspect that you're not going to get what you want without library tokens. If the "@this" thing works, great. If not, you might also be able to do what you want by rewriting the "Use" button as a <form> element, allowing the players to use a power by submitting an HTML form rather than clicking on a macroLink. But I suspect you'll eventually just need library tokens.

claud9999 wrote:For example, the parameters through the macroLink, if I were to use the library function, would be:

Token ID
Macro IDx
"flavor text" (for the token to "/say")
"business logic" (toggle, ammo, dice rolls, etc.)

For the first one -- Token ID -- you can just use the optional fifth parameter of macroLink() to run it on a token, rather than passing the token ID as an argument.

For the next one, Macro ID -- why? It seems like you should be calling the macro you need anyway. Why bother passing the called macro an argument that tells it which macro it is? This part makes me suspect that I'm still not quite understanding your problem right. :(

For the others -- there are ways of passing a bunch of parameters without it being too much of a headache. You might just have to do that.

Perhaps my favorite is to just save all the variables you need as Properties (possibly hidden properties) on the token that is running the macro.

Or ... you could call a different macro for each Power. I think that's actually what I'd recommend. It means you have to write a gazillion macros, yes, but each of them will be relatively simple, as opposed to the Macro From Hell with a gazillion if/then branches. Then, you could hard-code all of the Power-specific information (including flavor text) on the pertinent macro. Wait, I guess that makes it hard for the display frame to access the information. Hmmm.

Maybe do like the 3.5e Spell Library people do, and have a Lib token that just has all the Powers' stats and flavor texts as its Properties?

Raoden wrote:A lot of things besides this break if you have tokens with the exact same name. :?


Note I said "token id" not "token name"...Anyways, just clarifying.

Yeah, maybe I was misunderstanding this too. It seemed like you were saying that calling a macro should require token ID rather than token Name in case several tokens had the same name. But I'm suspecting that's not what you actually meant.

Ah, thanks for the clarification. (Is this indicated in the maptool wiki somewheres?)

Well, [wfunc]argCount[/wfunc] does say "The argCount() function is used to determine the number of arguments that have been passed to a user defined function." Not a called macro, just a user defined function.

But yeah, the wiki could stand to be more explicit on the issue. I had to figure it out myself just by running a lot of [debug( macro.args )] lines at the beginning of macros that weren't working.

Ah the wiki doc for macro() indicates the use of @TOKEN, and the macroLink indicates that the second arg is the same format as for macro(). If @TOKEN does not work for macroLink it should be indicated on the wiki. (I haven't updated the wiki 'cause I don't know if it's a bug or intentional that macroLink() doesn't support @TOKEN.)

It absolutely does support @TOKEN ... but only for library tokens, apparently. Yes, that should be indicated on the wiki if it's not.
"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

Post Reply

Return to “MapTool”