Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Problem nesting macros that run scripts (5e OGL)

June 16 (1 month ago)

Edited June 16 (1 month ago)

I'm attempting to create a macro that gives a query for selecting the type of healing potion you use, with each option calling a different macro, but cannot get the nesting to work. I'm unsure if it is a limitation of the scripts being utilized, or if my syntax is wrong.

The macro itself (for the sake of testing):

/em quaffs a potion!
!roll20AM --audio,nomenu,play|Potion Sound
#pot-test

The macro that it's trying to call is:

/em quaffs a Potion of Healing!
!roll20AM --audio,nomenu,play|Potion Sound
!modattr --silent --name @{selected|token_name} --repeating_resource_$0_resource_left|-1
!{{
  !token-mod --set bar1_value|+[[2d4+2]]!
  (^){^&template:simple}({)rname=Potion of Healing(}) ({)r1={^&math @^(selected.bar1)-@(selected.bar1)} (}) ({)normal=1(})({)mod=2d4+4(})({)charname=@{selected|token_name} (})
}}
/w @{selected|token_name} You have [[@{selected|repeating_resource_$0_resource_left}-1]] Potions of Healing left.

which works on it's own no problem; I'm currently using a variation of this macro for each healing potion grade, but it's clunky, which is why I'm trying to build a roll query for it. 

I changed what I thought was the correct parts of the syntax for nesting, as follows:

/em quaffs a Potion of Healing!
!roll20AM --audio,nomenu,play|Potion Sound
!modattr --silent --name @{selected|token_name} --repeating_resource_$0_resource_left|-1
!{{
  !token-mod --set bar1_value|+[[2d4+2]]!
  (^){^&template:simple}({)rname=Potion of Healing(}) ({)r1={^&math @^(selected.bar1)-@(selected.bar1)} (}) ({)normal=1(})({)mod=2d4+4(})({)charname=@{selected|token_name} (})
}}
/w @{selected|token_name} You have [[@{selected|repeating_resource_$0_resource_left}-1]] Potions of Healing left.

but I keep getting this error (whether I run it through the roll query macro or by itself):

SyntaxError: Expected "(", ".", "[", "abs(", "ceil(", "d", "floor(", "round(", "t", "{", [ |\t], [+|\-] or [0-9] but "@" found.

 I'm at a total loss here. Help?

June 17 (1 month ago)
timmaugh
Forum Champion
API Scripter

The error you're getting is from an inline roll seeing bad syntax. Attribute calls resolve before inline rolls, so an inline roll isn't expecting to see a @{selected|attribute} formation. When you do HTML replacement on the vertical pipe and closing brace of the @{selected} attribute retrieval in the last inline roll, that's exactly what you're doing: you're disguising the @{selected} syntax so that it doesn't resolve, but then your inline roll tries to resolve... and breaks because the @{selected} formation is still there.

The good news is... attribute calls are going to expand before queries execute, so you don't need to hide this one UNLESS you need to retrieve it AFTER the ChatSetAttr adjustment is made... and you shouldn't. You're accounting for the decrement of -1 potion in the !modattr line, so that value will be correct. The reference to the $0 repeating resource (left) in the inline roll at the end will resolve at the same time as the same reference in the !modattr line... that is, before anything else happens in the message... before the inline roll tries to resolve and before the query will have a chance to break if you didn't replace the HTML character... so it will have the *starting* value (before the ChatSetAttr adjustment), but you account for that by subtracting 1 from it in the inline roll.

TL;DR

Make you last line read like this, and give it a shot:

/w @{selected|token_name} You have [[@{selected|repeating_resource_$0_resource_left}-1]] Potions of Healing left.
June 17 (1 month ago)

Edited June 17 (1 month ago)

I gave that a shot, and now am getting a couple new errors:

No character was found for 'selected|token_name} --repeating_resource_$0_resource_left|-1 !{{ !token-mod --set bar1_value|+[[2d4+2]]! (^){^&template:simple}({)rname=Potion of Healing(}) ({)r1={^&math @^(selected.bar1)-@(selected.bar1)} (}) ({)normal=1(})({)mod=2d4+4(})({)charname=@{selected|token_name} (}) }} /w @{selected'

and

Unable to find a player or character with name: @{selected|token_name

Neither of those are cut off, that's the exact text of the errors. Yes, I am running the macro with a token selected.

And just for clarity, this is happening even when I run it as a solo macro, not even from the query macro. The syntax is completely borked somehow.

I tried running it again with the last line that reports potions remaining completely cut, and that created an entirely new problem. This posts in chat:

!token-mod --set bar1_value|+7!

(^){^&template:simple}({)rname=Potion of Healing(}) ({)r1={^&math @^(selected.bar1)-@(selected.bar1)} (}) ({)normal=1(})({)mod=2d4+4(})({)charname=@{selected|token_name} (})
}

The 7 there is the inline roll, which actually rolls and can be moused over to see the math there. After that, we also get:

(From ChatSetAttr):
Errors No character named @{selected|token_name} found. No target characters. You need to supply one of --all, --allgm, --sel, --allplayers, --charid, or --name.

I just... huh?

June 17 (1 month ago)
timmaugh
Forum Champion
API Scripter

OK, in my rush to get you an answer as I was shutting down for the night, I missed that previous lines *also* had @{selected} syntax.

Basically, *everywhere* you have that (and I am drawing a distinction between that syntax and Fetch syntax, which we'll get to in a minute), it will be one of the first things to resolve -- even before your query.

So where you have it in your ChatSetAttr line you do not need to escape it:

!modattr --silent --name @{selected|token_name} --repeating_resource_$0_resource_left|-1

(Note that the later pipe IS escaped because that isn't part of @{selected} syntax... that's part of what ChatSetAttr needs.)

Also, I see another @{selected} reference at the end of the template line in the ZeroFrame batch set. This should be provided EITHER as a normal Roll20 syntax structure without HTML substitutions:

@{selected|token_name}

...OR... it should be rendered as a Fetch construction:

@(selected.token_name)

The Fetch construction *could* be deferred, if you want, but in this case it won't matter... the same token will look like the selected token at both opportunities Fetch has to resolve.


To put a fine point on that (feel free to skip; just presenting this in case you're curious and want to learn), the order of operations will look like:

  • Roll20 attribute constructions resolve (like @{selected} constructions)
  • Your query will resolve
  • Inline rolls will resolve
  • The /em line is sent to chat
  • The ChatSetAttr and Roll20AM commands are sent to the Script Moderator (sandbox) (metascripts have opportunities to work in these lines, if necessary)
  • The line starting the ZeroFrame batch command is sent to the Script Moderator
  • Zeroing in on that message, the metascripts start looping...
  •    ...Fetch will resolve any constructions it sees (this is the first opportunity; at this point, the selected token of the message is STILL the selected token)
  •    ...ZeroFrame will un-defer and dispatch the batch commands individually
  • The whisper command (at the end of the command) is sent to chat
  • THEN the individual commands previously dispatched by ZeroFrame are caught by the Script Moderator
  • Zeroing in on these, the metascripts start looping...
  •     ....since it is a batch-dispatched message, ZeroFrame catches each and restores key information like selected tokens
  •     ...Fetch will resolve any constructions it sees (this is the second opportunity; at this point, the selected token of the message has been restored to what it always was)

Hopefully I haven't missed further @{selected} syntax in your command, but you'll have it in other commands referenced in your overall query, too, so for your ability to do it yourself (in either case) I wanted to explain *why* I was saying to make the changes I'm pointing out. That way you'll know which ones need to change for the future.

One Point About Queries...

You mention that the HTML-substituted line no longer works through chat... this is how it is. Once you encode a character with its HTML replacement, you really need an opportunity for the character to decode back in order for the command to work. A query gives you this opportunity, so typically when you encode/substitute a line like this, you are ONLY intending to use it through/via a query.

There is an alternative, however.

If you saved each of your commands as non-substituted lines in their own abilities on a character sheet (probably a mule character sheet), or as individual macros, then you could still run your query, but use Fetch constructions to retrieve them:

?{Pick command package|Lesser Potion,@(MuleCharacter.Lesser)|Greater Potion,@(MuleCharacter.Greater)|...

Because queries resolve *before* metascripts get involved, those Fetch references to abilities on your mule character won't expand to muddy up your syntax... that means they on longer require HTML substitution. HOWEVER, they will require using ALL Fetch references (instead of @{selected} Roll20 syntax) since your opportunity for resolving *those* formations will have passed before your query resolves (remember, the order of operations has attributes resolving before queries resolve). So change your @{selected} references to be @(selected) references.

Now your individual commands will still work as standalone commands (without having to use the query), but your query will ALSO work (and the syntax will be much cleaner).

One Other Thing...

I don't think you can whisper to a token (as you do in your last line). This is working because every token you run this command on is probably sharing a name with the character it represents, so by the time Roll20 sees the /w command, the recipient is designated as something it recognizes (and knows how to send a message to). Just pointing this out in case you would ever try to run this command with a token that did NOT share a name with its character (obviously running this command with a token that didn't represent a character will throw other errors since you are attempting to modify things on what would be a non-existent character sheet, at that point). You might be better off to change the last whisper recipient to be a character_name reference instead of the token_name you have now.

June 17 (1 month ago)

Edited June 17 (1 month ago)

Your responses are incredible, I'm learning a lot from this post.

I'm making progress here. I've gotten all the errors about selected tokens eliminated, now there's just this populating into the chat:

!token-mod --set bar1_value|+10! (^){^&template:simple}({)rname=Potion of Healing(}) ({)r1={^&math @^(selected.bar1)-@(selected.bar1)} (}) ({)normal=1(})({)mod=2d4+4(})({)charname=Yendalah (}) }}

It also does whisper the character about potions remaining, but none of the math is happening with it (not reducing potions, the token health is not being altered.)

I also attempted to try your macro mule suggestion, but cannot get it to call any ability or attribute; it just puts the text of the command into the chat (i.e. "@(MuleCharacter.Lesser)" just coming up in the chat). If I try adding an ! before the command, it crashes the sandbox lol

June 17 (1 month ago)
timmaugh
Forum Champion
API Scripter

Hmm... so what is happening, there, is that something is interfering with ZeroFrame capturing the full command between...

!{{

...and...

}}

(which you have HTML-subbed out, as required by the query inclusion).

The 2 lines are reaching the chat as a single message... which tells me either 1) something is breaking ZeroFrame's control/ownership over that batch of instructions, or 2) something about passing through the query is muddying the line break between the 2 lines... so that by the time ZeroFrame sees the command line, it sees all of it as a single thing.

It's likely something closer to #2 than #1... so try this.... (I'm not in a place where I can test, but when I get home later i can take a look if you're still having issues).

Add this syntax token at the end of the TokenMod line:

{&nl}

That is a "line break" character to ZeroFrame, which should have the effect of forcing the 2 batched commands to stay as 2 commands rather than mashing together.

Thinking it through in the order of operations... it should survive the query... and then whether it resolves as a part of the parent message or after ZeroFrame gets the batched commands, it should get processed first, before the individual commands are parsed out of the batch.

Color me... 86.4% sure this will work. =D

(But like I said, if it doesn't, let me know and I'll try to take a look later.)

June 17 (1 month ago)

Edited June 17 (1 month ago)

Nah, that didn't do anything other than add {&nl} to the text that pops up. I tried both as posted and also with the } substituted, nothing.

June 19 (1 month ago)

I've given up on this and just built a chat menu with API buttons. Does exactly what I want, and looks clean.

June 20 (1 month ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter


Sandwich said:

I've given up on this and just built a chat menu with API buttons. Does exactly what I want, and looks clean.


I almost always opt for this. Nesting queries and calls give me headaches. If you haven't perused the wiki page for Chat Menus, there may be helpful info there.

June 20 (1 month ago)
timmaugh
Forum Champion
API Scripter

Yeah, once you get into nesting *multi-line* commands... you're really pushing the system into places it doesn't want to go.