#Custom Template Patterns

1 messages ยท Page 1 of 1 (latest)

upper wedge
#

I don't know how familiar you are with foundry or JS development so I'll go over some basics and I apologise if you're already familiar.

#

I've got an example that I've implemented as a world script. If you were to do this properly you'd want to do it as a module but a world script has fewer hoops to jump through to get started.

#

So I created a world called Dofus. Then I opened the world folder on my filesystem under the foundry data directory then Data/worlds/dofus and edited the world.json file.

#

I added dofus.js to the scripts array in the world.json and then created a new file called dofus.js in that same folder.

#

Any code I put in there will be loaded when the world starts.

#

So first, I created a custom scene control and added it to the list of controls:

#
Hooks.on('getSceneControlButtons', DofusTemplates.addControls);
#

DofusTemplates.addControls looks like this:

addControls (controls) {
    const templates = controls.find(control => control.name === 'measure');
    templates.tools.unshift({
        name: 'dofus',
        title: 'Dofus Templates',
        icon: 'fas fa-magic'
    });
}
#

There's a bit of an issue with foundry at the moment that makes the next steps more complicated than they need to be.

#

First, I patched TemplateLayer#_onDragLeftStart. I did this in order to add a little bit of information to the new template that gets created so we know that it's a special dofus template later.

#

Also, foundry only understands the already-existing template types like circle, cone, line, etc., and doesn't understand custom ones, so we have to make sure our custom template looks like one of those.

#
TemplateLayer.prototype._onDragLeftStart = (function () {
    const onDragLeftStart = TemplateLayer.prototype._onDragLeftStart;
    return async function (event) {
        const isDofus = game.activeTool === 'dofus';
        if (isDofus) {
            // Set the active tool to circle temporarily so the measured template is
            // created properly.
            ui.controls.control.activeTool = 'circle';
        }

        const template = await onDragLeftStart.apply(this, arguments);

        if (isDofus) {
            template.document.data.update({'flags.dofus-templates.type': 'checkerboard'});
            ui.controls.control.activeTool = 'dofus';
        }
    };
})();
#

This looks a bit weird since we're patching an existing method, but the important code is in the middle.

#

We check if we're using the special tool, then we temporarily change the tool to a circle, then we let foundry work as normal, then we record the extra information and change the tool back to the dofus tool.

#

Then finally we patch MeasuredTemplate#highlightGrid to add our custom grid highlighting logic.

// Make sure this is one of our special templates.
if (!this.id || this.document.data.flags?.['dofus-templates']?.type !== 'checkerboard') {
    return highlightGrid.apply(this, arguments);
}

// ... cut out some code copied from the original method.

// Draw the checkerboard pattern.
for (let r = -nr; r < nr; r++) {
    for (let c = -nc; c < nc; c++) {
        const evenRows = (r + nr) % 2;
        const evenCols = (c + nc) % 2;
        const highlight = evenRows ? evenCols : !evenCols;
        if (!highlight) {
            continue;
        }
        const [gx, gy] = canvas.grid.grid.getPixelsFromGridPosition(row0 + r, col0 + c);
        grid.grid.highlightGridPosition(hl, {x: gx, y: gy, border, color});
    }
}
#

There's some additional code that basically re-implements the code from the original method but I've highlighted the important parts above.

#

And the result is a new checkerboard template:

#

I've also included the whole world script file so you can see how it fits together.

barren arch
#

Hey, First of all thanks a bunch for all this that's amazing ! The results looks so nice, I'm gonna take a look at it later tonight ๐Ÿ˜„ I'm Fairly okay with javascript dev as a whole but i'm lacking on the foundry knowledge haha ๐Ÿ™‚

#

As a take I quick glance so basically you're adding a new button for the custom template (this is cool and allow me to have it quickly at hand) and then basically using the classic shape of the circle and calculating the squares that should be affected by the checker-board pattern and then highlight them right ? Would this also be possible to link this template to an attack / spell on a monster for example ?

upper wedge
#

Yeah it's definitely possible

#

the dnd5e system does this already

#

You can configure the AoE on the attack or spell, and when you use it, the system asks if you'd like to place a template, and it takes care of creating the template for you

#

If you go that route, you won't need your own button, the code that creates the template can add the special data itself

barren arch
#

Well thanks for everything Kim it worked and i'm gonna keep working with that to create my own ๐Ÿ™‚ Have an amazing week !