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

Using a Query to Select a Token within a Macro

I am really new to coding Macros, so please forgive me if my question seems simple to everyone.  I am trying to create a Macro that will querry me which character and then output information to chat (using the default template.  I can get the info if I use a macro AFTER i click a token, but I am trying to learn as much as I can.  Here is the code for click and then using a macro. &{template:default}{{name=Character Info: @{selected|character_name}}} {{Hit Points: @{selected|hp}/@{selected|hp|max}}} {{Spell Save DC: @{selected|spell_save_dc}}} {{Spell Attack Bonus: +@{selected|spell_attack_bonus}}} Also, i do not know how to post the code into a "code Box"
1672899931

Edited 1672932534
You will need to replace each '@{selected|' with '@{CHARACTERNAME|', so this should work: !?{Which Character?|Character1|Character2|Character3} &{template:default}{{name=Character Info: @{"?{Which Character?}"|character_name}}} {{Hit Points: @{"?{Which Character?}"|hp}/@{"?{Which Character?}"|hp|max}}} {{Spell Save DC: @{"?{Which Character?}"|spell_save_dc}}} {{Spell Attack Bonus: +@{"?{Which Character?}"|spell_attack_bonus}}} You'll have to be careful if any of those Character Names include any special characters, as those can break queries and macros.  Whoops, sorry, I shouldn't have responded late at night - you can't use queries this way inside of an ability/attribute reference because of Roll20 Order of Operations. If you're using the D&D 5E by Roll20 character sheet, you may also be interested in a Universal Chat Menu  approach instead. To put change your text to 'code' format, select the text then click on the small dropdown box at the top left of the window and select 'code':
@Jarren Thanks for your reply!  I may still have something wrong.  I substituted my character names for your CHaracter1 etc and got the following: Here is the code from the first attempt: !?{Which Character?|Bane Ragehorn|Igden|Misha|Poe|Raiskin|Ska} &{template:default}{{name=Character Info: @{"?{Which Character?}"|character_name}}} {{Hit Points: @{"?{Which Character?}"|hp}/@{"?{Which Character?}"|hp|max}}} {{Spell Save DC: @{"?{Which Character?}"|spell_save_dc}}} {{Spell Attack Bonus: +@{"?{Which Character?}"|spell_attack_bonus}}} And the code from the second attemp !?{Which Character?|Bane Ragehorn|Igden|Misha|Poe|Raiskin|Ska} &{template:default}{{name=Character Info: @{"?{Which Character?}"|character_name}}} {{Hit Points: @{"?{Which Character?}"|hp}/@{"?{Which Character?}"|hp|max}}} {{Spell Save DC: @{"?{Which Character?}"|spell_save_dc}}} {{Spell Attack Bonus: +@{"?{Which Character?}"|spell_attack_bonus}}} What did I miss?  Thanks again.
1672917636

Edited 1672918558
I have never tried using a Query inside of character attribute call like that, I didn't think it was possible. I tried messing around with the altered code Jarren had suggested but kept getting the same error you did. I'm also not too familiar with the default template, but I think you are missing an " = " sign in each of the sections after the first "name" section. I believe this is what you are trying to accomplish: ?{Which Character?| Bane Ragehorn, &{template:default}{{name=Character Info: @{Bane Ragehorn|character_name}}} {{Hit Points:= @{Bane Ragehorn|hp}/@{Bane Ragehorn|hp|max}}} {{Spell Save DC:= @{Bane Ragehorn|spell_save_dc}}} {{Spell Attack Bonus:= +@{Bane Ragehorn|spell_attack_bonus}}} | Igden, &{template:default}{{name=Character Info: @{Igden|character_name}}} {{Hit Points:= @{Igden|hp}/@{Igden|hp|max}}} {{Spell Save DC:= @{Igden|spell_save_dc}}} {{Spell Attack Bonus:= +@{Igden|spell_attack_bonus}}} | Misha, &{template:default}{{name=Character Info: @{Misha|character_name}}} {{Hit Points:= @{Misha|hp}/@{Misha|hp|max}}} {{Spell Save DC:= @{Misha|spell_save_dc}}} {{Spell Attack Bonus:= +@{Misha|spell_attack_bonus}}} | Poe, &{template:default}{{name=Character Info: @{Poe|character_name}}} {{Hit Points:= @{Poe|hp}/@{Poe|hp|max}}} {{Spell Save DC:= @{Poe|spell_save_dc}}} {{Spell Attack Bonus:= +@{Poe|spell_attack_bonus}}} | Raiskin, &{template:default}{{name=Character Info: @{Raiskin|character_name}}} {{Hit Points:= @{Raiskin|hp}/@{Raiskin|hp|max}}} {{Spell Save DC:= @{Raiskin|spell_save_dc}}} {{Spell Attack Bonus:= +@{Raiskin|spell_attack_bonus}}} | Ska, &{template:default}{{name=Character Info: @{Ska|character_name}}} {{Hit Points:= @{Ska|hp}/@{Ska|hp|max}}} {{Spell Save DC:= @{Ska|spell_save_dc}}} {{Spell Attack Bonus:= +@{Ska|spell_attack_bonus}}}} Hopefully that works for you! I can't test 100% without making characters with those names, but tested a miniature version and it seemed to work. Edit: I should have mentioned if you are going to use this as a Macro and not an Ability Macro on a character sheet, you should save a copy of the code, if you ever open the macro up after putting this code in there, it will revert all of the " } " substitutions back to the " } " which will break the macro. I would suggest creating a macro character sheet named something like "Macros" and setting it up as a character ability and then creating a Macro that just calls on that ability, which you would do by creating the Macro and using: %{Macros|character-info} * "Macros" being the name of the character sheet you create and "character-info" being the name of the ability you put on that character sheet. The reason for doing it this way is that you can open the ability and alter the code without it reverting the character substitutions and messing up the macro.
1672929575
timmaugh
Forum Champion
API Scripter
Just by way of explanation (and an alternative), queries-in-attributes don't work because of Roll20's  order of operations . Attributes are expanded before queries are resolved, so you'll never get the data you're looking for. One alternative is to do as Hardcore Hero just demonstrated, and embed the entire output in the query. The downside is that you have to create a new entry in the query for every character (or token, depending on what you're doing), and you have to escape certain HTML characters that act like control characters for the parsing of the query (the pipe, comma, and right-brace). That's why you'll see things like: } | , } ... and why you'll get the suggestion to use a character sheet as a macro mule, since they don't revert these HTML substitutions to their resolved display counterparts. (DGMW, using a mule sheet is still a good suggestion, regardless! ... there are more benefits than just not-having-to do HTML replacements over and over.) However, one other option is to use metascripts (even for standard output like a template). Metascript Option 1 Metascripts, since they are scripts, operate in the time period after Roll20 parsers have already handled the message. That means that we can let queries resolve, and use their returned value as part of a "go get this from that sheet" process. Since we can rely on the query being resolved, we no longer need to embed a bunch of template syntax in each option. We can agnosticize the output a bit.  To do this, we're going to use the metascripts Fetch and ZeroFrame (see the Output paragraph, below, for the ZeroFrame portion). First, we're going to turn a standard Roll20 attribute retrieval construction like this: @{Character|attribute} ...into a Fetch construction for that same attribute: @(Character|attribute) OR @(Character.attribute) Then we'll use your query to provide either the character or the attribute (or, hell, both). Here is asking for the character: @(?{Which Character?|Bob the Hirsute|Toe Jam|Cletus|Honky}.attribute) By the time Fetch sees that in the command line, it will look something like: @(Cletus|attribute) ...and Fetch will go get the attribute from the Cletus sheet. Metascript Option 2 We can hold to something closer to what you initially asked about (basically: can I select a character without having to select a character) by adding SelectManager to the mix and changing our Fetch constructions slightly. (We'll also still require ZeroFrame; I'll show why in the Output paragraph, below). SelectManager can virtually select tokens using a {&select...} tag: {&select Bob the Hirsute, Cletus} And since it runs after the R20 parsers, the token selected can be chosen from a query: {&select ?{Which Character?|Bob the Hirsute|Toe Jam|Cletus|Honky} } Nothing is actually changed on the VTT, but for the purposes of the scripts that will see the message after SelectManager makes this change, it will appear that the token you selected from the dropdown will be "selected." Once you've got that in place, you can change your Fetch constructions to use the selected token: @(selected.attribute) (obviously to return an attribute the token will have to be set up to represent a character, and that character will have to have the attribute -- otherwise you'll get an empty string returned to your command line -- see the Fetch documentation for more info). Output Since we'd be using metascripts to accomplish this, the message has to start out as a bangsy message, intended for the Script Moderator. Bangsy messages don't hit chat: !You will never see this message. You'll never see that line hit the chat because instead of being sent to the chat output, it is sent to the Script Moderator. To output a message at the end, you can use the {&simple} tag from ZeroFrame: !You'll see this message.{&simple} The simple tag can go anywhere in the message. As long as that portion of the message survives until ZeroFrame sees it, ZeroFrame will halt further mod script processing after the metascripts and will instead output a message. ("Survive" in the sense that if you put the {&simple} tag in a query option that you don't choose, or in an APILogic IF conditional that doesn't pass true/false testing, then it won't remain in the command line.) Putting it all together, here is an example command line doing what you want to do: !/w gm &{template:default}{{name=Proof of Concept}}{{Character=@(selected.character_name)}}{{Attribute Value=@(selected.hp)}}{&select ?{Which character?|Cletus|Leroy|McMackleSmacker} }{&simple}
1672954096

Edited 1672954971
Thanks to everyone! This has been a journey ,,, and is still going ... Latest Update: I tried what Timmaugh said with the Metascript (Opt 2) and it almost worked!  I changed the name, character names and ran it.  Initially, it looked good: query box with characters, I picked the first and submitted. No output was delivered at all and tried several variations.  Eventually I had to remove the initial !.   It ran and delivered output Here is a Screen grab of the output:  ... and here is the code: /w gm &{template:default}{{name=Character Info}}{{Character=@(selected.character_name)}}{{Hit Points=@(selected.hp)}}{&select ?{Which character?|Bane Ragehorn|Igden|Misha|Poe|Raiskin|Ska} }{&simple} I have tried multiple changes (one at a time, test, revert and try new change ...) and the output is either the same -OR- the earlier script erroe (depending on what change I made in that run. I will eventually try Jarren's UCM option, but I want to figure this out first.  Roll20 does not get to laugh at me when I keep failing Macro Saving Rolls ! Edit: Hardcore Hero's idea of using a Macro Mule (all hail the MacroBeast) worked - but I still choose not to be mocked by the Roll20 Tech DM's!  ANy other ideas on what I doing wrong?
1672957049
timmaugh
Forum Champion
API Scripter
For the metascript option, do you have Fetch, SelectManager, and ZeroFrame installed? You will need the opening bang (!) to trigger metascript operations, but since you didn't get a chat output it sounds like ZeroFrame wasn't installed. I just tried your macro in my game, changing only the names of the characters to match my characters:
Timmaugh, that helped a LOT!  I did not have them installed.  Now I do and all is great - except that no info populates for Bane Ragehorn.  He is in the dropdown, the frame and titles (on the right side), but his name and hp are not there.  I double-checked to make sure Token was linked to the char sheet and that his name was spelled correctly.  Is there an issue because there is a space in his character name?
1673015425
timmaugh
Forum Champion
API Scripter
The space in the name shouldn't matter. Things to look at: 1) I don't know what system you're using, but make sure that Bane Ragehorn actually has an hp attribute by selecting a token representing him and entering @{selected|hp} into the chat. Certain systems, like 5E, have different attribute names for NPCs vs PCs. 2) Make sure you AREN'T actually using the standard Roll20 constructions (ie, @{selected|hp} ), but rather their Fetch equivalents (ie, @(selected.hp) ). This is because the retrieval (Fetch) has to happen after the selection (SelectManager), which has to happen after the roll query resolution. 3) Confirm that all three scripts are installed. 4) You can add a default value to each of your Fetch constructions so you can see that it is at least seeing the construction and replacing it with data. The default would be in square brackets just inside the closing paren: @(selected.hp[not found]) That way, if the hp attribute isn't found, your template should show you "not found" in that spot. Try those steps and let us know.