The Script Block and Identifying Characters

I recieved a question that made me realise I hadn’t explained something about sheet workers. If you have any questions about how things work on Roll20, please send them here or at my Roll20 account, or just ask on the Roll20 Forums – there’s a good chance I’ll see it, and if I don’t, someone more qualified to answer will probably see it.

Script Block

Your sheet workers are placed in the HTML file, in a script block that looks exactly like this:

<script type="text/worker">


</script>Code language: JavaScript (javascript)

Your script block must look exactly like this – don’t skip any part of it and watch out for typos.

The block can be placed anywhere inside your HTML file, but for efficiency reasons is best placed at the end.

You’ll sometimes see advice that you should have only one script block. This was true for a time, but isn’t intended to be the case. There was a period where a bug in Roll20’s code caused all but one script block to be ignored. At that time, you could only have one block.

So you can have multiple script blocks but it’s not a good idea. They can’t see each other and if you have a separate function used by your workers, it must be in the same script block as your workers. So its generally best to just have one script block.

Identifying Which Character

So you’ll have sheet workers that look like this:

on('change:level', () => {
   getAttrs(['level'], values => {
      const level = +values.level || 0;
      setAttrs({
          level_label: "I am level " + level
      })
   });
});Code language: JavaScript (javascript)

And in a Script Block it would look like this:

<script type="text/worker">

   on('change:level', () => {
      getAttrs(['level'], values => {
         const level = +values.level || 0;
         setAttrs({
            level_label: "I am level " + level
         })
      });
   });

</script>Code language: JavaScript (javascript)

There are three functions there that we may not think of as functions – on, getAttrs, setAttrs. Each of them has code running on Roll20’s servers which we never see and cannot interact with. Most of the time we can ignore that and just use them as indicated.

But sometimes there are things about the hidden code it’s useful to know. For example, look at this line:

   on('change:level', () => {Code language: JavaScript (javascript)

We can see that this is watching for changes in the level attribute. But which character is it watching?

The answer is, all of them. This sheet worker is monitoring all characters for changes to an attribute, and when that attribute changes, the sheet worker is triggered. But that change occurred on a specific character, and Roll20 knows which character.

The hidden code takes this into account, so getAttrs kniows which character’s attributes to read, and setAttrs knows which character to update.

It is almost never important to think about this, but it can be useful to understand sometimes.

Running on Startup

Any code placed on your script block runs at startup. “On startup” means when you first load a campaign and every time you refresh the campaign.

It runs only at that time.

Any code you place in the script block that is not in a sheet worker is run at this time. You can use this to create constant variables and functions that exist independently of sheet workers. This what we are doing when we create and use functions like the num function here:

<script type="text/worker">
   const num = (score, fallback = 0) = +score || fallback;

   on('change:level', () => {
      getAttrs(['level'], values => {
         const level = num(values.level);
         setAttrs({
            level_label: "I am level " + level
         })
      });
   });

</script>Code language: JavaScript (javascript)

In this example the num function was created at startup and is now available for any sheet worker placed later in the script block.

Note that sheet workers themselves are also created at this time. Each entire script block is run “on startup”.

Conclusion

You always need a script block to put sheet workers in, and you only need one. All sheet workers can go inside this one block which is best placed at the end of your HTML file.

A sheet worker magically knows which character to modify, and you never need worry about that. Any attributes to be monitored or updated on a character need a sheet worker: that identifies which character to look at and change.

You can create global variables and functions that are available to all sheet workers by placing them at the start of your script block. (Just place them before any sheet workers that use them.)

I hope this helps you understand some less obvious things about sheet workers in Roll20.

Series Navigation<< The Perils of Sheet Worker FunctionsArrays and Dropdowns >>

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.