Building a Character Sheet – Advancing Skills, Traits, and Extras

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.

Leave a Reply

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