There are a lot of sections left in advancement, but they are a lot less complex than those first two. We should be able to do them all in this post.
Step 3 – Tracking Skills, Traits, and Extras
This section is more complex than it looks.
Designing the first buttons, for now, is easy – later, we’ll add a feature to stop it being used. But for now, it just adds 1 to the total advances, which automatically redraws the advance track above. This is described in the previous post. Now we need to display the How Many Skills section.
You should be able to come up with HTML and CSS just by looking at it. The sheet worker is more interesting, and we’ll see the advantage pf creating the ranks and skills arrays earlier.
We know there are 6 skills, and each skill level adds a skill of that level (reducing the lowest levels to account for any overflow).
This section shows how many skills you DO have, and how many you SHOULD have, given your skill level. It also uses CSS to do something neat.
on(`change:skill_level ${changes(skills)} sheet:opened`, () => {
getAttrs(['skill_level', ...skills], v => {
const output = {};
// finding out how many skills you DO have
ranks.forEach(rank => output[`${rank}_owned`] = 0);
skills.forEach(skill => {
const rank_this = v[skill];
output[`${rank_this.toLowerCase()}_owned`] = output[`${rank_this.toLowerCase()}_owned`] +1;
});
// finding out how many skills you SHOULD have
const level = int(v.skill_level);
ranks.forEach(rank => output[`${rank}_needed`] = 0);
output[`poor_needed`] = Math.max(0, 3 - level);
output[`fair_needed`] = 1 + (level ? 1 : 0) - (level > 3 ? 1 : 0) - (level > 4 ? 1 : 0);
output[`good_needed`] = 1 + (level > 1 ? 1 : 0);
output[`great_needed`] = 1 + (level > 2 ? 1 : 0);
output[`superb_needed`] = 0 + (level > 3 ? 1 : 0);
output[`spectacular_needed`] = 0+ (level > 4 ? 1 : 0);
// check the numbers are equal
ranks.forEach(rank => {
if(['terrible','legendary','mythic', 'perfect'].includes(rank.toLowerCase()) != 1) {
output[`${rank.toLowerCase()}_check`] = (output[`${rank.toLowerCase()}_needed`] == output[`${rank.toLowerCase()}_owned`]) ? 0 : 1;
};
});
setAttrs(output);
});
});
Code language: JavaScript (javascript)
See that _check
calculation at the end? It checks that you have the correct skills at that rank (by comparing the number of _needed
to _owned
), and sets an attribute to 1 if they are different. Then the CSS changes that row to red if they are different, like this:

In this way, players can see at a glance if they are going wrong.
Then we have the Trait
and Extras
calculations. Again we show how many you have, vs how many you should have. This is in principle very simple.
We are using repeating sections to track the ownership of these, so an use getSectionIDs.length
– the number of rows – to get number owned. And the level_
attribute for how many you should have. In practice, it’s a little more complicated, but that’s the gist of it.
In the next post we’ll finish up advancement, with the special case of experience points and achievements.