Sheetworker examples for Non-programmers
From Roll20 Wiki
While the majority of Roll20's character sheets are written using only HTML and CSS, sheetworker scripts(javascript) are often necessary to either simplify complicated HTML or add more advanced functionality to a character sheet. For those of us "non-programmers", the examples given on the Sheet Worker Scripts page may be less than exhaustive. This page was created to help better explain how to use sheetworker scripts in your character sheets.
Contents |
Simple Template
(credit: G G)
You really don't need to understand how sheet workers work, to be honest. As long as you copy the change / get attrs / setattrs sections properly, to get the data you operate on with fairly standard programming techniques.
on("change:stat1 change:stat2 sheet:opened", function() { //sheet:opened is optional, but is useful for some workers - the script runs every time the sheet opens. getAttrs(["stat1","stat2"], function(values) { let stat1 = values.stat1; // wrap this in a parseInt function if you need it to be a number let stat2 = parseInt(values.stat2)||0; // like so // ============================ // at this point you have the variables you need to work with. Do whatever you need below, using ifs, switches, for loops, and so on // as you would in other programming languages. You can use very simple stuff, similar to BASIC programming, whatever suits your level of skill. // then once you have done whatever stuff you need to do to get your desired output: // the bit below the line lets you wrap up the sheet worker. // ============================ setAttrs({ stat1:stat1, stat2:stat2 }); }); });
If you have different, more, or less stats, you just need to add them to the change, getattrs, and setattrs lines, and the variable assignments. You really don't need to understand how they work, as long as you can copy them and update them with correct values.
Then you can do what you need with them between the double lines. I hope this helps. In the beginning I was just as befuddled about them as you are, and using a template like this got me started.
Two tips I'd suggest when starting out:
- Keep your attribute names lower case.
- Don't use dashes or other symbols except underscores in attribute names.
- So if you have a name like Health-Value, change it to health_value.
You can break these guidelines when you know what you're doing, but you need to write the sheet workers slightly differently, and it's better to avoid the hassle when starting out.
Auto-calculating Attributes
example 1;(credit: Rabulias)
Your best bet would be to avoid the autocalc fields entirely if you can. Monitor the two other fields and when they change, have a sheetworker that adds them up to the new value. Then you can refer to the new value in other calculations much easier.
on("sheet:opened change:stat_a change:stat_b", function() { getAttrs(["stat_a", "stat_b"], function(values) { setAttrs({ "foo_modchars": parseInt(values["stat_a"],10) || 0 + parseInt(values["stat_b"],10) || 0 }); }); });
example 2;(credit: G G)
I rememebr seeing a script someone wrote to allow you to use autocalc fields within sheet workers, but it's just simpler to use Rabulias's approach.
Add the relevant stats to the on(change:) line, and duplicate the calculation within the sheet worker.
I generally don't put my working in the setattrs call, but before it so i can more easily check it. Something like
on("sheet:opened change:stat_a change:stat_b", function() { getAttrs(["stat_a", "stat_b"], function(values) { var stat_a = parseInt(values["stat_a"],10)||0; var stat_b = parseInt(values["stat_b"],10)||0; var output = stat_a + stat_b; setAttrs({ "foo_modchars": output }); }); });
Helpful Advice
This section may or may not contain specific examples of sheet worker code, however the information provided is invaluable to learning how to implement sheet workers into your character sheet.
Understanding sheet workers.
(credit: Jakob)
Usually, the best way to learn something is to do it! Start solving the problems you want to solve using sheet workers, and learn along the way :).
Now, that probably wasn't very helpful. I could also encourage you to look at code others have written, which you should do; just realize that many sheet authors are also amateurs (such as me), hence the code may not be the most elegantly-written example.
That probably also wasn't helpful. Let me try something else: depending on what your course taught you, much of it (everything dealing with manipulation of the DOM) is not going to be very helpful. Here's some important things you need to keep in mind that might make sheet workers different from what you've learned:
1. Sheet workers are event-driven. Everything interesting your workers do will happen in response to a certain event on the sheet; most of the time, the triggering event will be changing an attribute on the sheet (i.e., the value of some input, be it a checkbox, radio, text, number input, or textarea). This is what the on("change:attr", function () { ...}) is there for: it's about registering a function that's supposed to be executed every time attr changes.
2. Sheet workers can only really do one thing. Sheet workers can change the value of attributes, and that's pretty much it (they can also remove repeating rows, but that's not their main use). If you want your sheet workers to do a thing, ask yourself if it can be accomplished by changing the value of an attribute (this includes being able to (un)check checkboxes), +perhaps some CSS. If yes, you can do it with sheet workers. If not, you cannot.
3. Sheet workers are asynchronous. The main interesting functions you have access to in sheet workers, namely getAttrs, setAttrs, and getSectionIDs, take as their second argument functions that do other stuff. This means that you cannot trust that your code will simply be executed from top to bottom, and have to write in such a way that it makes sense no matter when asynchronous functions are executed. This is often a source of confusion for people.