I figured it was time to get a thread going on the new Custom Roll Parsing and see what people have come up with so far. The examples below are probably not beginner-friendly, but the posts are already long enough without going into the workings of setAttrs, getAttrs and so forth - they've been omitted from the code with the assumption that anyone interested in putting startRoll() through its paces will know how to use the basic sheetworkers.
The new startRoll() function, combined with action buttons, offers a bunch of new functionality to explore, as a roll sent to chat can now have custom functions run before it, during it, after it, and even passed through to the next roll. The startRoll() function itself is the main meat of the recent-ish Custom Roll Parsing update, and it's also the first time Roll20 have exposed a Promisified, async/await-ready function for sheet authors. The async/await pattern is great for keeping code tidy & controlled by avoiding callback hell.
To really take advantage of startRoll's promisified version, we need our other major sheetworkers to return Promises. Luckily, OnyxRing got this figured out already - here's the original thread.
I've been using a condensed version, but it's functionally the same as OR's original, and takes the same parameters as Roll20's base functions (obviously):
Your getAttrs call would then look like this:
let attrs = await asw.getAttrs(['attr1', 'attr2']);
That's it. As long as you don't forget the word 'await', you can now access those attributes with attrs.attr1, attrs.attr2, and so on.
I won't dwell on the async coding part - but all the examples I provide use the above framework. Synchronous versions of all the examples are certainly possible, but.... yeah, probably not alot of fun if you're dealing with a complex, multi-part roll function.
We can also assume that each of these functions is running from a type="action" button and its associated event handler, e.g.
<button type="action" name="act_test">Uninstall Windows</button>
on('clicked:test', (ev) => testFunction(ev));
So, provided you have the usual requirements - minimal HTML to provide some test buttons, a legal script block, and an event listener to attach each main function to your HTML test button - all of the following examples should work copy & pasted into a sheet. They're not terribly useful by themselves, but you should be able to see them working.
Also, something I find generally helpful for reading posts with code on Roll20, a quick Stylus addition:
.postcontent pre {
white-space:pre-wrap!important;
}
.postcontent div {
white-space:pre-wrap;
word-break: break-word;
}
This should wrap code-boxes, and force VS Code lines to wrap when they hit the edge of the black background.
1. Let's Go Fishing - pre-roll data grab
Trick number 1 is pretty straight-forward. Sometimes you might want to fish for some data before starting your roll. A couple of examples:
1. You might want to set up your roll template based on input from the Player. Maybe you want to Query the player on which weapon to use for the attack?
2. You could put a generic button on your damage template, so anyone can click it to apply the damage to their selected token.
All we do is send an API roll to chat (assuming you don't want it to be visible) and use startRoll's functionality to pinch the data from the roll object:
Not a terribly amazing example as it's so simple - you could achieve the outcome with a simple roll button, but hopefully it gets across the concept of how to pinch text input from a roll.
A second example, making better use of our new functions. Let's say we've got a "Heal Target" action button on the character sheet - we can now coax the heal roll to actually apply the HP to the target. This is probably not ideal sheet design, allowing a player to adjust the HP on another sheet - a better approach would probably be to whisper a second button to the target allowing them to accept the heal and apply the adjustment. But we'll stick with the automatic approach for this example.
Like before, we use a function to grab the data we need with an invisible API roll, then use that info for our actual roll. The difference here is we use OnyxRing's clever function to switch the active character in the sandbox so we can apply the HP change to the target: