mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-07-04 05:37:11 -04:00
9: Add POC for actor templates
- This commit adds a proof-of-concept for retrieving actor template types. These are actors using the `worldbuilding.isTemplate` flag set to true. If there are multiple actors with that flag set to true, clicking the create actor button will pull up a prompt to choose from one of those types, which will then create an actor by duplicating the template actor's data. The flag will be unset on the new actor.
This commit is contained in:
parent
d3f030b4f7
commit
bac1d023c3
10 changed files with 270 additions and 85 deletions
181
module/simple.js
181
module/simple.js
|
@ -8,6 +8,7 @@
|
|||
import { SimpleActor } from "./actor.js";
|
||||
import { SimpleItemSheet } from "./item-sheet.js";
|
||||
import { SimpleActorSheet } from "./actor-sheet.js";
|
||||
import { preloadHandlebarsTemplates } from "./templates.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
|
@ -89,4 +90,184 @@ Hooks.once("init", async function() {
|
|||
return value.slugify({strict: true});
|
||||
});
|
||||
|
||||
// Preload template partials.
|
||||
preloadHandlebarsTemplates();
|
||||
});
|
||||
|
||||
/**
|
||||
* Adds the actor template context menu.
|
||||
*/
|
||||
Hooks.on("getActorDirectoryEntryContext", (html, options) => {
|
||||
// Define an actor as a template.
|
||||
options.push({
|
||||
name: game.i18n.localize("SIMPLE.DefineTemplate"),
|
||||
icon: '<i class="fas fa-stamp"></i>',
|
||||
condition: li => {
|
||||
const actor = game.actors.get(li.data("entityId"));
|
||||
return !actor.getFlag("worldbuilding", "isTemplate");
|
||||
},
|
||||
callback: li => {
|
||||
const actor = game.actors.get(li.data("entityId"));
|
||||
actor.setFlag("worldbuilding", "isTemplate", true);
|
||||
}
|
||||
});
|
||||
|
||||
// Undefine an actor as a template.
|
||||
options.push({
|
||||
name: game.i18n.localize("SIMPLE.UnsetTemplate"),
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
condition: li => {
|
||||
const actor = game.actors.get(li.data("entityId"));
|
||||
return actor.getFlag("worldbuilding", "isTemplate");
|
||||
},
|
||||
callback: li => {
|
||||
const actor = game.actors.get(li.data("entityId"));
|
||||
actor.setFlag("worldbuilding", "isTemplate", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Adds the item template context menu.
|
||||
*/
|
||||
Hooks.on("getItemDirectoryEntryContext", (html, options) => {
|
||||
// Define an item as a template.
|
||||
options.push({
|
||||
name: game.i18n.localize("SIMPLE.DefineTemplate"),
|
||||
icon: '<i class="fas fa-stamp"></i>',
|
||||
condition: li => {
|
||||
const item = game.items.get(li.data("entityId"));
|
||||
return !item.getFlag("worldbuilding", "isTemplate");
|
||||
},
|
||||
callback: li => {
|
||||
const item = game.items.get(li.data("entityId"));
|
||||
item.setFlag("worldbuilding", "isTemplate", true);
|
||||
}
|
||||
});
|
||||
|
||||
// Undefine an item as a template.
|
||||
options.push({
|
||||
name: game.i18n.localize("SIMPLE.UnsetTemplate"),
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
condition: li => {
|
||||
const item = game.items.get(li.data("entityId"));
|
||||
return item.getFlag("worldbuilding", "isTemplate");
|
||||
},
|
||||
callback: li => {
|
||||
const item = game.items.get(li.data("entityId"));
|
||||
item.setFlag("worldbuilding", "isTemplate", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Adds the actor template selection dialog.
|
||||
*/
|
||||
ActorDirectory.prototype._onCreate = async (event) => {
|
||||
// Do not allow the creation event to bubble to other listeners
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
_simpleDirectoryTemplates('actor');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the item template selection dialog.
|
||||
*/
|
||||
ItemDirectory.prototype._onCreate = async (event) => {
|
||||
// Do not allow the creation event to bubble to other listeners
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
_simpleDirectoryTemplates('item');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the entity template dialog.
|
||||
*
|
||||
* Helper function to display a dialog if there are multiple template types
|
||||
* defined for the entity type.
|
||||
*
|
||||
* @param {string} entityType - 'actor' or 'item'
|
||||
*/
|
||||
async function _simpleDirectoryTemplates(entityType = 'actor') {
|
||||
// Retrieve the collection and class.
|
||||
const entityCollection = entityType == 'actor' ? game.actors : game.items;
|
||||
const cls = entityType == 'actor' ? Actor : Item;
|
||||
|
||||
// Query for all entities of this type using the "isTemplate" flag.
|
||||
let entities = entityCollection.filter(a => a.data.flags?.worldbuilding?.isTemplate === true);
|
||||
|
||||
// Initialize variables related to the entity class.
|
||||
let ent = game.i18n.localize(cls.config.label);
|
||||
|
||||
// Setup entity data.
|
||||
let type = entityType == 'actor' ? 'character' : 'item';
|
||||
let createData = {
|
||||
name: `New ${ent}`,
|
||||
type: type,
|
||||
folder: event.currentTarget.dataset.folder
|
||||
};
|
||||
|
||||
// If there's more than one entity template type, create a form.
|
||||
if (entities.length > 0) {
|
||||
// Build an array of types for the form, including an empty default.
|
||||
let types = [{
|
||||
value: null,
|
||||
label: game.i18n.localize("SIMPLE.NoTemplate")
|
||||
}];
|
||||
|
||||
// Append each of the user-defined actor/item types.
|
||||
types = types.concat(entities.map(a => {
|
||||
return {
|
||||
value: a.data.name,
|
||||
label: a.data.name
|
||||
}
|
||||
}));
|
||||
|
||||
// Render the entity creation form
|
||||
let templateData = {upper: ent, lower: ent.toLowerCase(), types: types},
|
||||
dlg = await renderTemplate(`systems/worldbuilding/templates/sidebar/entity-create.html`, templateData);
|
||||
|
||||
// Render the confirmation dialog window
|
||||
new Dialog({
|
||||
title: `Create ${createData.name}`,
|
||||
content: dlg,
|
||||
buttons: {
|
||||
create: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: `Create ${ent}`,
|
||||
callback: html => {
|
||||
// Get the form data.
|
||||
const form = html[0].querySelector("form");
|
||||
mergeObject(createData, validateForm(form));
|
||||
|
||||
// Store the type and name values, and retrieve the template entity.
|
||||
let templateActor = entityCollection.getName(createData.type);
|
||||
|
||||
// If there's a template entity, handle the data.
|
||||
if (templateActor) {
|
||||
// Update the object with the existing template's values.
|
||||
createData = mergeObject(templateActor.data, createData, {inplace: false});
|
||||
createData.type = templateActor.data.type;
|
||||
// Clear the flag so that this doesn't become a new template.
|
||||
delete createData.flags.worldbuilding.isTemplate;
|
||||
}
|
||||
// Otherwise, restore to a valid entity type (character/item).
|
||||
else {
|
||||
createData.type = type;
|
||||
}
|
||||
|
||||
cls.create(createData, {renderSheet: true});
|
||||
}
|
||||
}
|
||||
},
|
||||
default: "create"
|
||||
}).render(true);
|
||||
}
|
||||
// Otherwise, just create a blank entity.
|
||||
else {
|
||||
cls.create(createData, {renderSheet: true});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue