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 .
×

Action Buttons, Custom Roll Parsing, and Selected Tokens

1769781047
Finderski
Pro
Sheet Author
Compendium Curator
Goal: Select a token, click an action button, and get a basic stat block for the selected token I know I can use an action button to kick off a custom roll parser script that can easily collect all the numeric information from a selected token. But is there a way for that same action button to get to get non-numeric information (for example the charater_name, or a list of feats from a repeating section, etc.)?
1769790039
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Hey Finderski! Can you provide more information? What sheet do you want to do this with? API solution or vanilla macro? There are several methods that people have come up with for this. (If your goal is doing this with the 2024 D&D sheet, the options might be more limited.)
1769790837
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Should be possible. Need a few clarifications though. Is the token representing the character you are running the sheetworker on? Are you wanting to get token only info like token name or bar values?
1769801103
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Derp! I totally forgot to check what forum I was in. Never mind me, I'll be over here in the corner remembering how to read. :D
1769842188
Finderski
Pro
Sheet Author
Compendium Curator
Scott C. said: Should be possible. Need a few clarifications though. Is the token representing the character you are running the sheetworker on? Are you wanting to get token only info like token name or bar values? Scott, for this sheet, all the sheets will have the sheet worker, of course, but I have a "hidden" tab for the, so the idea is for me to have a GM Sheet, and then I want to click on a character token, hit my action button and pull all the stats I need from that character (e.g. the character's name, HP, AC, attributes, mutations (which are in a repeating section, etc.) So, not interested in Token info, just character sheet info.  This is for Gamma World 2e, which is rather complex, so I'm trying to make it as easy as possible, for me...and if possible, maybe for the players down the road.
1769842240
Finderski
Pro
Sheet Author
Compendium Curator
keithcurtis said: Derp! I totally forgot to check what forum I was in. Never mind me, I'll be over here in the corner remembering how to read. :D LOL - no worries. :)
1769849211

Edited 1769849557
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Gotcha, so you're trying to trigger the "roll" on one sheet and get data from another. I think what you are going to want to just use the straight cross sheet communication trick; essentially you treat startRoll as a POST request or the vanilla JS fetch function. You'll need the following hidden buttons (button names can of course be changed as you see fit): HTML <button type="action" name="act_receive" style="display:none;></button> <button type="action" name="act_receive-info" style="display:none;></button> <!-- and then the button you are actually clicking of course --> JS // adapted from K-scaffold, which itself adapted from Oosh's Adventures in StartRoll forum post // utility to BASE64 encode/decode data for passing data inside ability button calls. const RE = { chars: { '"': '%quot;', ',': '%comma;', ':': '%colon;', '}': '%rcub;', '{': '%lcub;', }, escape(data) { return typeof data === 'object' ? `KDATA${btoa(JSON.stringify(data))}` : `KSTRING${btoa(data)}`; }, unescape(string) { const isData = typeof string === 'string' && ( string.startsWith('KDATA') || string.startsWith('KSTRING') ); return isData ? ( string.startsWith('KDATA') ? JSON.parse(atob(string.replace(/^KDATA/,''))) : atob(string.replace(/^KSTRING/,'')) ) : string; } }; // utility for sending the cross sheet communication. const send = async function(charRef,data,buttonName = 'receive'){ const dataString = RE.escape(data);   // Note that the character name attribute call is essential. It essnetially jumpstarts the target sheet's connection with the database to ensure that the attribute data will actually be available to getAttrs // The character ID call that is done below may not jumpstart as it is treated a little differently from character name. const roll = await startRoll(`!@{${charRef}|character_name}%{${charRef}|${buttonName}||${dataString}}&{noerror}`); finishRoll(roll.rollId); }; on('clicked:get-info', () => { getAttrs(['character_name''attributes to get on gm sheet'],async (attrs) =>{ // we can get non numerical data out of rolls by storing them in the roll tag. const roll = await startRoll('!{{query=[[0[response=@{character_id}]]]}}'); finishRoll(roll.rollId); // extract the character id of the target character from the roll tag. const targetID = roll.results.query.expression.replace(/^.+?response=|\]$/g,''); send(targetID,{ from: attrs.character_name, action: 'some key that your recipient function will know how to respond to' }) }) }) // then we also listen for "clicks" of the hidden receive button. on('clicked:receive',async (event) => { // the originalRollId is the information that we added after that double || above. const data = RE.unescape(event.originalRollId); getAttrs(['character_name','attributes you will need to reply to the request'],async (attrs) => { // easiest method is to just return the attrs object you get from getAttrs send(data.from,{ from: attrs.character_name, attrs },'recieve-info'); }); }); // then we also listen for "clicks" of the hidden receive-info button. on('clicked:receive-info',(event) => { const data = RE.unescape(event.originalRollId); getAttrs(['character_name','attributes you will need in order to work with the passed data'], (attrs) => { // work with sheetworkers as you normally would, except you now have `data.attrs` which is a record of the attribute data that the other sheet passed back. }); }); You can see this technique live in the Walking Dead character sheet with its embedded NPCs, Locations, and Factions.
1769884657

Edited 1769885265
vÍnce
Pro
Sheet Author
@Scott  There's so much I don't know...  lol Thank you
1769890892
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Heh, you and me both Vince!
1769904319
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Also, Finderski, note that if you just want that statblock output to chat, you could do that in the on('clicked:recieve') listener and not even need the third listener, just pass the attributes from the first sheet that you'll need in the message to the second sheet.
1770156903
Finderski
Pro
Sheet Author
Compendium Curator
Awesome! Thanks, Scott. I'll try this out and let you know when I run into problems...LOL
1770467026
Finderski
Pro
Sheet Author
Compendium Curator
Scott, I'm trying to parse the functions you gave above so I know how to use them, but I'm stuck, because all the getAttrs are for the character I'm clicking the button on, or seems to be. I realize that in one function I'm going to trigger a hidden button to gather all that information, but in my head, I think I may be thinking about this all the wrong way. Let me know if I've got this... Here my screen: I'm on my GM Screen character sheet and I'm going to add a row in a repeating section for each of the PCs. I click add to add a row and that presents the Get Character Info Button The get-info action button is triggered when I click it This kicks off the sheet work for the get-info The getAttrs call gets the character name and ID for the GM Sheet, and I suppose I should get the repeating section ID? a roll is started with a roll template though no template is specifically identified (I didn't realize we could do that?) I feel like this is where I need to add the "selected" tag? Should it actually be:  !{{query=[[0[response=@{selected|character_id}]]]}} The worker then triggers the send function send function is triggered data is cleaned data contains two keys:  1) from, which is the character name for the GM Sheet, and 2) action, which would the action I want the send function to execute I'm not sure how or when to use the "action" value received in this function? Start a roll using the character reference ID and it calls the Receive action button that's hidden. How did we get the originalRollId passed into the send function? The receive button is triggered (but it seems like it should be the receive button on the GM Sheet, not the selected token's sheet, unless my question in 2.3.1 above is correct?). Assuming this is targeting the player's sheet (via the selected token), this is where I do my getAttrs on that sheet and drop everything into a variable called attrs? Once I have all the information from that player's sheet, we call send again, only this time, we tell it to trigger the receive-info on the GM Sheet Receive Info action button is triggered I use data.attrs to fill in my repeating section ID with the info I got from the players sheet Process Done Did I understand that correctly?