mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-04-30 02:31:41 -04:00
Update Simple Worldbuilding for Foundry 0.8.x Compatibility
This commit is contained in:
parent
ee8814b76a
commit
fb0add4cbc
11 changed files with 295 additions and 301 deletions
|
@ -4,8 +4,13 @@
|
|||
"SETTINGS.SimpleInitFormulaN": "Initiative Formula",
|
||||
"SETTINGS.SimpleInitFormulaL": "Enter an initiative formula, such as d20+@dex",
|
||||
|
||||
"SIMPLE.NotifyInitFormulaUpdated": "Initiative formula was updated to:",
|
||||
"SIMPLE.NotifyInitFormulaInvalid": "Initiative formula was invalid:",
|
||||
"SIMPLE.ItemCreate": "Create Item",
|
||||
"SIMPLE.ItemEdit": "Edit Item",
|
||||
"SIMPLE.ItemDelete": "Delete Item",
|
||||
"SIMPLE.ItemNew": "New Item",
|
||||
|
||||
"SIMPLE.NotifyInitFormulaUpdated": "Initiative formula was updated to",
|
||||
"SIMPLE.NotifyInitFormulaInvalid": "Initiative formula was invalid",
|
||||
"SIMPLE.NotifyGroupDuplicate": "Attribute group already exists.",
|
||||
"SIMPLE.NotifyGroupAttrDuplicate": "Attribute group already exists as an attribute.",
|
||||
"SIMPLE.NotifyGroupAlphanumeric": "Attribute group names may not contain spaces or periods.",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { EntitySheetHelper } from "./helper.js";
|
||||
import {ATTRIBUTE_TYPES} from "./constants.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
|
@ -6,9 +7,9 @@ import { EntitySheetHelper } from "./helper.js";
|
|||
*/
|
||||
export class SimpleActorSheet extends ActorSheet {
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["worldbuilding", "sheet", "actor"],
|
||||
template: "systems/worldbuilding/templates/actor-sheet.html",
|
||||
width: 600,
|
||||
|
@ -21,42 +22,35 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
EntitySheetHelper.getAttributeData(data);
|
||||
data.shorthand = !!game.settings.get("worldbuilding", "macroShorthand");
|
||||
return data;
|
||||
const context = super.getData();
|
||||
EntitySheetHelper.getAttributeData(context.data);
|
||||
context.shorthand = !!game.settings.get("worldbuilding", "macroShorthand");
|
||||
context.systemData = context.data.data;
|
||||
context.dtypes = ATTRIBUTE_TYPES;
|
||||
return context;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if ( !this.options.editable ) return;
|
||||
if ( !this.isEditable ) return;
|
||||
|
||||
// Handle rollable items and attributes
|
||||
html.find(".items .rollable").on("click", this._onItemRoll.bind(this));
|
||||
// Attribute Management
|
||||
html.find(".attributes").on("click", ".attribute-control", EntitySheetHelper.onClickAttributeControl.bind(this));
|
||||
html.find(".groups").on("click", ".group-control", EntitySheetHelper.onClickAttributeGroupControl.bind(this));
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Item Controls
|
||||
html.find(".item-control").click(this._onItemControl.bind(this));
|
||||
html.find(".items .rollable").on("click", this._onItemRoll.bind(this));
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.deleteOwnedItem(li.data("itemId"));
|
||||
li.slideUp(200, () => this.render(false));
|
||||
});
|
||||
|
||||
// Add draggable for macros.
|
||||
// Add draggable for Macro creation
|
||||
html.find(".attributes a.attribute-roll").each((i, a) => {
|
||||
a.setAttribute("draggable", true);
|
||||
a.addEventListener("dragstart", ev => {
|
||||
|
@ -64,12 +58,33 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
ev.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Add or Remove Attribute
|
||||
html.find(".attributes").on("click", ".attribute-control", EntitySheetHelper.onClickAttributeControl.bind(this));
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// Add attribute groups.
|
||||
html.find(".groups").on("click", ".group-control", EntitySheetHelper.onClickAttributeGroupControl.bind(this));
|
||||
/**
|
||||
* Handle click events for Item control buttons within the Actor Sheet
|
||||
* @param event
|
||||
* @private
|
||||
*/
|
||||
_onItemControl(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Obtain event data
|
||||
const button = event.currentTarget;
|
||||
const li = button.closest(".item");
|
||||
const item = this.actor.items.get(li?.dataset.itemId);
|
||||
|
||||
// Handle different actions
|
||||
switch ( button.dataset.action ) {
|
||||
case "create":
|
||||
const cls = getDocumentClass("Item");
|
||||
return cls.create({name: game.i18n.localize("SIMPLE.ItemNew"), type: "item"}, {parent: this.actor});
|
||||
case "edit":
|
||||
return item.sheet.render(true);
|
||||
case "delete":
|
||||
return item.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -80,11 +95,11 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
*/
|
||||
_onItemRoll(event) {
|
||||
let button = $(event.currentTarget);
|
||||
let r = new Roll(button.data('roll'), this.actor.getRollData());
|
||||
const li = button.parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
r.roll().toMessage({
|
||||
user: game.user._id,
|
||||
const item = this.actor.items.get(li.data("itemId"));
|
||||
let r = new Roll(button.data('roll'), this.actor.getRollData());
|
||||
return r.toMessage({
|
||||
user: game.user.id,
|
||||
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||
flavor: `<h2>${item.name}</h2><h3>${button.text()}</h3>`
|
||||
});
|
||||
|
@ -92,11 +107,11 @@ export class SimpleActorSheet extends ActorSheet {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
formData = EntitySheetHelper.updateAttributes(formData, this);
|
||||
formData = EntitySheetHelper.updateGroups(formData, this);
|
||||
return this.object.update(formData);
|
||||
/** @inheritdoc */
|
||||
_getSubmitData(updateData) {
|
||||
let formData = super._getSubmitData(updateData);
|
||||
formData = EntitySheetHelper.updateAttributes(formData, this.object);
|
||||
formData = EntitySheetHelper.updateGroups(formData, this.object);
|
||||
return formData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { EntitySheetHelper } from "./helper.js";
|
||||
|
||||
/**
|
||||
* Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
|
||||
* Extend the base Actor document to support attributes and groups with a custom template creation dialog.
|
||||
* @extends {Actor}
|
||||
*/
|
||||
export class SimpleActor extends Actor {
|
||||
|
||||
/** @override */
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
/** @inheritdoc */
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
this.data.data.groups = this.data.data.groups || {};
|
||||
this.data.data.attributes = this.data.data.attributes || {};
|
||||
}
|
||||
|
@ -16,8 +16,19 @@ export class SimpleActor extends Actor {
|
|||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
static async createDialog(data={}, options={}) {
|
||||
return EntitySheetHelper.createDialog.call(this, data, options);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Roll Data Preparation */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritdoc */
|
||||
getRollData() {
|
||||
const data = super.getRollData();
|
||||
|
||||
// Copy the actor's system data
|
||||
const data = this.toObject(false).data;
|
||||
const shorthand = game.settings.get("worldbuilding", "macroShorthand");
|
||||
const formulaAttributes = [];
|
||||
const itemAttributes = [];
|
||||
|
@ -41,10 +52,11 @@ export class SimpleActor extends Actor {
|
|||
delete data.abil;
|
||||
delete data.groups;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Apply shorthand syntax to actor roll data.
|
||||
* @param {Object} data The actor's data object.
|
||||
|
@ -53,9 +65,9 @@ export class SimpleActor extends Actor {
|
|||
*/
|
||||
_applyShorthand(data, formulaAttributes, shorthand) {
|
||||
// Handle formula attributes when the short syntax is disabled.
|
||||
for ( let [k, v] of Object.entries(data.attributes) ) {
|
||||
for ( let [k, v] of Object.entries(data.attributes || {}) ) {
|
||||
// Make an array of formula attributes for later reference.
|
||||
if ( v.dtype == "Formula" ) formulaAttributes.push(k);
|
||||
if ( v.dtype === "Formula" ) formulaAttributes.push(k);
|
||||
// Add shortened version of the attributes.
|
||||
if ( !!shorthand ) {
|
||||
if ( !(k in data) ) {
|
||||
|
@ -68,7 +80,7 @@ export class SimpleActor extends Actor {
|
|||
data[k] = {};
|
||||
for ( let [gk, gv] of Object.entries(v) ) {
|
||||
data[k][gk] = gv.value;
|
||||
if ( gv.dtype == "Formula" ) formulaAttributes.push(`${k}.${gk}`);
|
||||
if ( gv.dtype === "Formula" ) formulaAttributes.push(`${k}.${gk}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,22 +88,25 @@ export class SimpleActor extends Actor {
|
|||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Add items to the actor roll data object. Handles regular and shorthand
|
||||
* syntax, and calculates derived formula attributes on the items.
|
||||
* @param {Object} data The actor's data object.
|
||||
* @param {string[]} itemAttributes
|
||||
* @param {Boolean} shorthand Whether or not the shorthand syntax is used.
|
||||
*/
|
||||
_applyItems(data, itemAttributes, shorthand) {
|
||||
// Map all items data using their slugified names
|
||||
data.items = this.data.items.reduce((obj, i) => {
|
||||
let key = i.name.slugify({strict: true});
|
||||
let itemData = duplicate(i.data);
|
||||
data.items = this.items.reduce((obj, item) => {
|
||||
const key = item.name.slugify({strict: true});
|
||||
const itemData = item.toObject(false).data;
|
||||
|
||||
// Add items to shorthand and note which ones are formula attributes.
|
||||
for ( let [k, v] of Object.entries(itemData.attributes) ) {
|
||||
// When building the attribute list, prepend the item name for later use.
|
||||
if ( v.dtype == "Formula" ) itemAttributes.push(`${key}..${k}`);
|
||||
if ( v.dtype === "Formula" ) itemAttributes.push(`${key}..${k}`);
|
||||
// Add shortened version of the attributes.
|
||||
if ( !!shorthand ) {
|
||||
if ( !(k in itemData) ) {
|
||||
|
@ -104,7 +119,7 @@ export class SimpleActor extends Actor {
|
|||
if ( !itemData[k] ) itemData[k] = {};
|
||||
for ( let [gk, gv] of Object.entries(v) ) {
|
||||
itemData[k][gk] = gv.value;
|
||||
if ( gv.dtype == "Formula" ) itemAttributes.push(`${key}..${k}.${gk}`);
|
||||
if ( gv.dtype === "Formula" ) itemAttributes.push(`${key}..${k}.${gk}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +130,7 @@ export class SimpleActor extends Actor {
|
|||
if ( !itemData[k] ) itemData[k] = {};
|
||||
for ( let [gk, gv] of Object.entries(v) ) {
|
||||
itemData[k][gk] = gv.value;
|
||||
if ( gv.dtype == "Formula" ) itemAttributes.push(`${key}..${k}.${gk}`);
|
||||
if ( gv.dtype === "Formula" ) itemAttributes.push(`${key}..${k}.${gk}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,12 +140,13 @@ export class SimpleActor extends Actor {
|
|||
if ( !!shorthand ) {
|
||||
delete itemData.attributes;
|
||||
}
|
||||
|
||||
obj[key] = itemData;
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
_applyItemsFormulaReplacements(data, itemAttributes, shorthand) {
|
||||
for ( let k of itemAttributes ) {
|
||||
// Get the item name and separate the key.
|
||||
|
@ -151,30 +167,32 @@ export class SimpleActor extends Actor {
|
|||
if ( !!shorthand ) {
|
||||
// Handle grouped attributes first.
|
||||
if ( data.items[item][k][gk] ) {
|
||||
formula = data.items[item][k][gk];
|
||||
data.items[item][k][gk] = EntitySheetHelper.replaceData(formula.replace('@item.', `@items.${item}.`), data, {missing: "0"});
|
||||
formula = data.items[item][k][gk].replace('@item.', `@items.${item}.`);
|
||||
data.items[item][k][gk] = Roll.replaceFormulaData(formula, data);
|
||||
}
|
||||
// Handle non-grouped attributes.
|
||||
else if ( data.items[item][k] ) {
|
||||
formula = data.items[item][k];
|
||||
data.items[item][k] = EntitySheetHelper.replaceData(formula.replace('@item.', `@items.${item}.`), data, {missing: "0"});
|
||||
formula = data.items[item][k].replace('@item.', `@items.${item}.`);
|
||||
data.items[item][k] = Roll.replaceFormulaData(formula, data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Handle grouped attributes first.
|
||||
if ( data.items[item]['attributes'][k][gk] ) {
|
||||
formula = data.items[item]['attributes'][k][gk]['value'];
|
||||
data.items[item]['attributes'][k][gk]['value'] = EntitySheetHelper.replaceData(formula.replace('@item.', `@items.${item}.attributes.`), data, {missing: "0"});
|
||||
formula = data.items[item]['attributes'][k][gk]['value'].replace('@item.', `@items.${item}.attributes.`);
|
||||
data.items[item]['attributes'][k][gk]['value'] = Roll.replaceFormulaData(formula, data);
|
||||
}
|
||||
// Handle non-grouped attributes.
|
||||
else if ( data.items[item]['attributes'][k]['value'] ) {
|
||||
formula = data.items[item]['attributes'][k]['value'];
|
||||
data.items[item]['attributes'][k]['value'] = EntitySheetHelper.replaceData(formula.replace('@item.', `@items.${item}.attributes.`), data, {missing: "0"});
|
||||
formula = data.items[item]['attributes'][k]['value'].replace('@item.', `@items.${item}.attributes.`);
|
||||
data.items[item]['attributes'][k]['value'] = Roll.replaceFormulaData(formula, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Apply replacements for derived formula attributes.
|
||||
* @param {Object} data The actor's data object.
|
||||
|
@ -182,11 +200,9 @@ export class SimpleActor extends Actor {
|
|||
* @param {Boolean} shorthand Whether or not the shorthand syntax is used.
|
||||
*/
|
||||
_applyFormulaReplacements(data, formulaAttributes, shorthand) {
|
||||
// Evaluate formula attributes after all other attributes have been handled,
|
||||
// including items.
|
||||
// Evaluate formula attributes after all other attributes have been handled, including items.
|
||||
for ( let k of formulaAttributes ) {
|
||||
// Grouped attributes are included as `group.attr`, so we need to split
|
||||
// them into new keys.
|
||||
// Grouped attributes are included as `group.attr`, so we need to split them into new keys.
|
||||
let attr = null;
|
||||
if ( k.includes('.') ) {
|
||||
let attrKey = k.split('.');
|
||||
|
@ -195,15 +211,11 @@ export class SimpleActor extends Actor {
|
|||
}
|
||||
// Non-grouped attributes.
|
||||
if ( data.attributes[k]?.value ) {
|
||||
data.attributes[k].value = EntitySheetHelper.replaceData(data.attributes[k].value, data, {missing: "0"});
|
||||
// TODO: Replace with:
|
||||
// data.attributes[k].value = Roll.replaceFormulaData(data.attributes[k].value, data, {missing: "0"});
|
||||
data.attributes[k].value = Roll.replaceFormulaData(data.attributes[k].value, data);
|
||||
}
|
||||
// Grouped attributes.
|
||||
else {
|
||||
if ( attr ) {
|
||||
data.attributes[k][attr].value = EntitySheetHelper.replaceData(data.attributes[k][attr].value, data, {missing: "0"});
|
||||
}
|
||||
else if ( attr ) {
|
||||
data.attributes[k][attr].value = Roll.replaceFormulaData(data.attributes[k][attr].value, data);
|
||||
}
|
||||
|
||||
// Duplicate values to shorthand.
|
||||
|
|
172
module/helper.js
172
module/helper.js
|
@ -3,7 +3,6 @@ import { ATTRIBUTE_TYPES } from "./constants.js";
|
|||
export class EntitySheetHelper {
|
||||
|
||||
static getAttributeData(data) {
|
||||
data.dtypes = ATTRIBUTE_TYPES;
|
||||
|
||||
// Determine attribute type.
|
||||
for ( let attr of Object.values(data.data.attributes) ) {
|
||||
|
@ -61,7 +60,7 @@ export class EntitySheetHelper {
|
|||
// Add label fallback.
|
||||
if ( !gv.label ) gv.label = gk;
|
||||
// Add formula bool.
|
||||
if ( gv.dtype == "Formula" ) {
|
||||
if ( gv.dtype === "Formula" ) {
|
||||
gv.isFormula = true;
|
||||
}
|
||||
else {
|
||||
|
@ -75,7 +74,7 @@ export class EntitySheetHelper {
|
|||
// Add label fallback.
|
||||
if ( !v.label ) v.label = k;
|
||||
// Add formula bool.
|
||||
if ( v.dtype == "Formula" ) {
|
||||
if ( v.dtype === "Formula" ) {
|
||||
v.isFormula = true;
|
||||
}
|
||||
else {
|
||||
|
@ -94,7 +93,7 @@ export class EntitySheetHelper {
|
|||
// Closing the form/sheet will also trigger a submit, so only evaluate if this is an event.
|
||||
if ( event.currentTarget ) {
|
||||
// Exit early if this isn't a named attribute.
|
||||
if ( event.currentTarget.tagName.toLowerCase() == 'input' && !event.currentTarget.hasAttribute('name')) {
|
||||
if ( (event.currentTarget.tagName.toLowerCase() === 'input') && !event.currentTarget.hasAttribute('name')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -108,7 +107,7 @@ export class EntitySheetHelper {
|
|||
// Prevent attributes that already exist as groups.
|
||||
let groups = document.querySelectorAll('.group-key');
|
||||
for ( let i = 0; i < groups.length; i++ ) {
|
||||
if (groups[i].value == val) {
|
||||
if (groups[i].value === val) {
|
||||
ui.notifications.error(game.i18n.localize("SIMPLE.NotifyAttrDuplicate") + ` (${val})`);
|
||||
el.value = oldVal;
|
||||
attrError = true;
|
||||
|
@ -132,24 +131,21 @@ export class EntitySheetHelper {
|
|||
/**
|
||||
* Listen for click events on an attribute control to modify the composition of attributes in the sheet
|
||||
* @param {MouseEvent} event The originating left click event
|
||||
* @private
|
||||
*/
|
||||
static async onClickAttributeControl(event) {
|
||||
event.preventDefault();
|
||||
const a = event.currentTarget;
|
||||
const action = a.dataset.action;
|
||||
|
||||
// Perform create and delete actions.
|
||||
switch ( action ) {
|
||||
case "create":
|
||||
EntitySheetHelper.createAttribute(event, this);
|
||||
break;
|
||||
return EntitySheetHelper.createAttribute(event, this);
|
||||
case "delete":
|
||||
EntitySheetHelper.deleteAttribute(event, this);
|
||||
break;
|
||||
return EntitySheetHelper.deleteAttribute(event, this);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Listen for click events and modify attribute groups.
|
||||
* @param {MouseEvent} event The originating left click event
|
||||
|
@ -158,14 +154,11 @@ export class EntitySheetHelper {
|
|||
event.preventDefault();
|
||||
const a = event.currentTarget;
|
||||
const action = a.dataset.action;
|
||||
|
||||
switch ( action ) {
|
||||
case "create-group":
|
||||
EntitySheetHelper.createAttributeGroup(event, this);
|
||||
break;
|
||||
return EntitySheetHelper.createAttributeGroup(event, this);
|
||||
case "delete-group":
|
||||
EntitySheetHelper.deleteAttributeGroup(event, this);
|
||||
break;
|
||||
return EntitySheetHelper.deleteAttributeGroup(event, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,24 +174,24 @@ export class EntitySheetHelper {
|
|||
const label = button.closest(".attribute").querySelector(".attribute-label")?.value;
|
||||
const chatLabel = label ?? button.parentElement.querySelector(".attribute-key").value;
|
||||
const shorthand = game.settings.get("worldbuilding", "macroShorthand");
|
||||
|
||||
// Use the actor for rollData so that formulas are always in reference to the parent actor.
|
||||
const rollData = this.actor.getRollData();
|
||||
let formula = button.closest(".attribute").querySelector(".attribute-value")?.value;
|
||||
|
||||
// If there's a formula, attempt to roll it.
|
||||
if ( formula ) {
|
||||
// Get the machine safe version of the item name.
|
||||
let replacement = null;
|
||||
if ( formula.includes('@item.') && this.item ) {
|
||||
let itemName = this.item.name.slugify({strict: true});
|
||||
let itemName = this.item.name.slugify({strict: true}); // Get the machine safe version of the item name.
|
||||
replacement = !!shorthand ? `@items.${itemName}.` : `@items.${itemName}.attributes.`;
|
||||
formula = formula.replace('@item.', replacement);
|
||||
}
|
||||
formula = EntitySheetHelper.replaceData(formula, rollData, {missing: null});
|
||||
// Replace `@item` shorthand with the item name and make the roll.
|
||||
|
||||
// Create the roll and the corresponding message
|
||||
let r = new Roll(formula, rollData);
|
||||
r.roll().toMessage({
|
||||
user: game.user._id,
|
||||
return r.toMessage({
|
||||
user: game.user.id,
|
||||
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||
flavor: `${chatLabel}`
|
||||
});
|
||||
|
@ -218,7 +211,7 @@ export class EntitySheetHelper {
|
|||
*/
|
||||
static getAttributeHtml(items, index, group = false) {
|
||||
// Initialize the HTML.
|
||||
let result = '<div>';
|
||||
let result = '<div style="display: none;">';
|
||||
// Iterate over the supplied keys and build their inputs (including whether or not they need a group key).
|
||||
for (let [key, item] of Object.entries(items)) {
|
||||
result = result + `<input type="${item.type}" name="data.attributes${group ? '.' + group : '' }.attr${index}.${key}" value="${item.value}"/>`;
|
||||
|
@ -231,12 +224,13 @@ export class EntitySheetHelper {
|
|||
|
||||
/**
|
||||
* Validate whether or not a group name can be used.
|
||||
* @param {string} groupName Groupname to validate
|
||||
* @param {string} groupName The candidate group name to validate
|
||||
* @param {Document} document The Actor or Item instance within which the group is being defined
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static validateGroup(groupName, entity) {
|
||||
let groups = Object.keys(entity.object.data.data.groups);
|
||||
let attributes = Object.keys(entity.object.data.data.attributes).filter(a => !groups.includes(a));
|
||||
static validateGroup(groupName, document) {
|
||||
let groups = Object.keys(document.data.data.groups || {});
|
||||
let attributes = Object.keys(document.data.data.attributes).filter(a => !groups.includes(a));
|
||||
|
||||
// Check for duplicate group keys.
|
||||
if ( groups.includes(groupName) ) {
|
||||
|
@ -255,7 +249,6 @@ export class EntitySheetHelper {
|
|||
ui.notifications.error(game.i18n.localize("SIMPLE.NotifyGroupAlphanumeric"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -283,7 +276,7 @@ export class EntitySheetHelper {
|
|||
while ( objKeys.includes(newValue) ) {
|
||||
++nk;
|
||||
newValue = `attr${nk}`;
|
||||
};
|
||||
}
|
||||
|
||||
// Build options for construction HTML inputs.
|
||||
let htmlItems = {
|
||||
|
@ -364,7 +357,7 @@ export class EntitySheetHelper {
|
|||
const form = app.form;
|
||||
let newValue = $(a).siblings('.group-prefix').val();
|
||||
// Verify the new group key is valid, and use it to create the group.
|
||||
if ( newValue.length > 0 && EntitySheetHelper.validateGroup(newValue, app) ) {
|
||||
if ( newValue.length > 0 && EntitySheetHelper.validateGroup(newValue, app.object) ) {
|
||||
let newKey = document.createElement("div");
|
||||
newKey.innerHTML = `<input type="text" name="data.groups.${newValue}.key" value="${newValue}"/>`;
|
||||
// Append the form element and submit the form.
|
||||
|
@ -374,6 +367,8 @@ export class EntitySheetHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Delete an attribute group.
|
||||
* @param {MouseEvent} event The originating left click event
|
||||
|
@ -410,15 +405,15 @@ export class EntitySheetHelper {
|
|||
|
||||
/**
|
||||
* Update attributes when updating an actor object.
|
||||
*
|
||||
* @param {Object} formData Form data object to modify keys and values for.
|
||||
* @returns {Object} updated formData object.
|
||||
* @param {object} formData The form data object to modify keys and values for.
|
||||
* @param {Document} document The Actor or Item document within which attributes are being updated
|
||||
* @returns {object} The updated formData object.
|
||||
*/
|
||||
static updateAttributes(formData, entity) {
|
||||
static updateAttributes(formData, document) {
|
||||
let groupKeys = [];
|
||||
|
||||
// Handle the free-form attributes list
|
||||
const formAttrs = expandObject(formData).data.attributes || {};
|
||||
const formAttrs = foundry.utils.expandObject(formData)?.data?.attributes || {};
|
||||
const attributes = Object.values(formAttrs).reduce((obj, v) => {
|
||||
let attrs = [];
|
||||
let group = null;
|
||||
|
@ -453,14 +448,14 @@ export class EntitySheetHelper {
|
|||
}, {});
|
||||
|
||||
// Remove attributes which are no longer used
|
||||
for ( let k of Object.keys(entity.object.data.data.attributes) ) {
|
||||
for ( let k of Object.keys(document.data.data.attributes) ) {
|
||||
if ( !attributes.hasOwnProperty(k) ) attributes[`-=${k}`] = null;
|
||||
}
|
||||
|
||||
// Remove grouped attributes which are no longer used.
|
||||
for ( let group of groupKeys) {
|
||||
if ( entity.object.data.data.attributes[group] ) {
|
||||
for ( let k of Object.keys(entity.object.data.data.attributes[group]) ) {
|
||||
if ( document.data.data.attributes[group] ) {
|
||||
for ( let k of Object.keys(document.data.data.attributes[group]) ) {
|
||||
if ( !attributes[group].hasOwnProperty(k) ) attributes[group][`-=${k}`] = null;
|
||||
}
|
||||
}
|
||||
|
@ -470,18 +465,20 @@ export class EntitySheetHelper {
|
|||
formData = Object.entries(formData).filter(e => !e[0].startsWith("data.attributes")).reduce((obj, e) => {
|
||||
obj[e[0]] = e[1];
|
||||
return obj;
|
||||
}, {_id: entity.object._id, "data.attributes": attributes});
|
||||
}, {_id: document.id, "data.attributes": attributes});
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Update attribute groups when updating an actor object.
|
||||
*
|
||||
* @param {Object} formData Form data object to modify keys and values for.
|
||||
* @returns {Object} updated formData object.
|
||||
* @param {object} formData The form data object to modify keys and values for.
|
||||
* @param {Document} document The Actor or Item document within which attributes are being updated
|
||||
* @returns {object} The updated formData object.
|
||||
*/
|
||||
static updateGroups(formData, entity) {
|
||||
static updateGroups(formData, document) {
|
||||
// Handle the free-form groups list
|
||||
const formGroups = expandObject(formData).data.groups || {};
|
||||
const groups = Object.values(formGroups).reduce((obj, v) => {
|
||||
|
@ -498,7 +495,7 @@ export class EntitySheetHelper {
|
|||
}, {});
|
||||
|
||||
// Remove groups which are no longer used
|
||||
for ( let k of Object.keys(entity.object.data.data.groups) ) {
|
||||
for ( let k of Object.keys(document.data.data.groups) ) {
|
||||
if ( !groups.hasOwnProperty(k) ) groups[`-=${k}`] = null;
|
||||
}
|
||||
|
||||
|
@ -506,42 +503,71 @@ export class EntitySheetHelper {
|
|||
formData = Object.entries(formData).filter(e => !e[0].startsWith("data.groups")).reduce((obj, e) => {
|
||||
obj[e[0]] = e[1];
|
||||
return obj;
|
||||
}, {_id: entity.object._id, "data.groups": groups});
|
||||
|
||||
}, {_id: document.id, "data.groups": groups});
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Replace referenced data attributes in the roll formula with the syntax `@attr` with the corresponding key from
|
||||
* the provided `data` object. This is a temporary helper function that will be replaced with Roll.replaceFormulaData()
|
||||
* in Foundry 0.7.1.
|
||||
*
|
||||
* @param {String} formula The original formula within which to replace.
|
||||
* @param {Object} data Data object to use for value replacements.
|
||||
* @param {Object} missing Value to use as missing replacements, such as {missing: "0"}.
|
||||
* @return {String} The formula with attributes replaced with values.
|
||||
* @see ClientDocumentMixin.createDialog
|
||||
*/
|
||||
static replaceData(formula, data, {missing=null,depth=1}={}) {
|
||||
// Exit early if the formula is invalid.
|
||||
if ( typeof formula != "string" || depth < 1) {
|
||||
return 0;
|
||||
static async createDialog(data={}, options={}) {
|
||||
|
||||
// Collect data
|
||||
const documentName = this.metadata.name;
|
||||
const folders = game.folders.filter(f => (f.data.type === documentName) && f.displayed);
|
||||
const label = game.i18n.localize(this.metadata.label);
|
||||
const title = game.i18n.format("ENTITY.Create", {entity: label});
|
||||
|
||||
// Identify the template Actor types
|
||||
const collection = game.collections.get(this.documentName);
|
||||
const templates = collection.filter(a => a.getFlag("worldbuilding", "isTemplate"));
|
||||
const defaultType = this.metadata.types[0];
|
||||
const types = {
|
||||
[defaultType]: game.i18n.localize("SIMPLE.NoTemplate")
|
||||
}
|
||||
// Replace attributes with their numeric equivalents.
|
||||
let dataRgx = new RegExp(/@([a-z.0-9_\-]+)/gi);
|
||||
let rollFormula = formula.replace(dataRgx, (match, term) => {
|
||||
let value = getProperty(data, term);
|
||||
// If there was a value returned, trim and return it.
|
||||
if ( value ) {
|
||||
return String(value).trim();
|
||||
}
|
||||
// Otherwise, return either the missing replacement value, or the original @attr string for later replacement.
|
||||
else {
|
||||
return missing != null ? missing : `@${term}`;
|
||||
}
|
||||
});
|
||||
return rollFormula;
|
||||
for ( let a of templates ) {
|
||||
types[a.id] = a.name;
|
||||
}
|
||||
|
||||
// Render the entity creation form
|
||||
const html = await renderTemplate(`templates/sidebar/entity-create.html`, {
|
||||
name: data.name || game.i18n.format("ENTITY.New", {entity: label}),
|
||||
folder: data.folder,
|
||||
folders: folders,
|
||||
hasFolders: folders.length > 1,
|
||||
type: data.type || templates[0]?.id || "",
|
||||
types: types,
|
||||
hasTypes: true
|
||||
});
|
||||
|
||||
// Render the confirmation dialog window
|
||||
return Dialog.prompt({
|
||||
title: title,
|
||||
content: html,
|
||||
label: title,
|
||||
callback: html => {
|
||||
|
||||
// Get the form data
|
||||
const form = html[0].querySelector("form");
|
||||
const fd = new FormDataExtended(form);
|
||||
let createData = fd.toObject();
|
||||
|
||||
// Merge with template data
|
||||
const template = collection.get(form.type.value);
|
||||
if ( template ) {
|
||||
createData = foundry.utils.mergeObject(template.toObject(), createData);
|
||||
createData.type = template.data.type;
|
||||
delete createData.flags.worldbuilding.isTemplate;
|
||||
}
|
||||
|
||||
// Merge provided override data
|
||||
createData = foundry.utils.mergeObject(createData, data);
|
||||
return this.create(createData, {renderSheet: true});
|
||||
},
|
||||
rejectClose: false,
|
||||
options: options
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { EntitySheetHelper } from "./helper.js";
|
||||
import {ATTRIBUTE_TYPES} from "./constants.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
|
@ -6,9 +7,9 @@ import { EntitySheetHelper } from "./helper.js";
|
|||
*/
|
||||
export class SimpleItemSheet extends ItemSheet {
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["worldbuilding", "sheet", "item"],
|
||||
template: "systems/worldbuilding/templates/item-sheet.html",
|
||||
width: 520,
|
||||
|
@ -20,26 +21,30 @@ export class SimpleItemSheet extends ItemSheet {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
getData() {
|
||||
const data = super.getData();
|
||||
EntitySheetHelper.getAttributeData(data);
|
||||
return data;
|
||||
const context = super.getData();
|
||||
EntitySheetHelper.getAttributeData(context.data);
|
||||
context.systemData = context.data.data;
|
||||
context.dtypes = ATTRIBUTE_TYPES;
|
||||
return context;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
/** @inheritdoc */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
if ( !this.isEditable ) return;
|
||||
|
||||
// Rollable attributes
|
||||
// Attribute Management
|
||||
html.find(".attributes").on("click", ".attribute-control", EntitySheetHelper.onClickAttributeControl.bind(this));
|
||||
html.find(".groups").on("click", ".group-control", EntitySheetHelper.onClickAttributeGroupControl.bind(this));
|
||||
html.find(".attributes").on("click", "a.attribute-roll", EntitySheetHelper.onAttributeRoll.bind(this));
|
||||
|
||||
// Add draggable for macros.
|
||||
// Add draggable for Macro creation
|
||||
html.find(".attributes a.attribute-roll").each((i, a) => {
|
||||
a.setAttribute("draggable", true);
|
||||
a.addEventListener("dragstart", ev => {
|
||||
|
@ -47,24 +52,15 @@ export class SimpleItemSheet extends ItemSheet {
|
|||
ev.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
||||
}, false);
|
||||
});
|
||||
|
||||
// Add or Remove Attribute
|
||||
html.find(".attributes").on("click", ".attribute-control", EntitySheetHelper.onClickAttributeControl.bind(this));
|
||||
|
||||
// Add attribute groups.
|
||||
html.find(".groups").on("click", ".group-control", EntitySheetHelper.onClickAttributeGroupControl.bind(this));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
|
||||
// Handle attribute and group updates.
|
||||
formData = EntitySheetHelper.updateAttributes(formData, this);
|
||||
formData = EntitySheetHelper.updateGroups(formData, this);
|
||||
|
||||
// Update the Actor with the new form values.
|
||||
return this.object.update(formData);
|
||||
_getSubmitData(updateData) {
|
||||
let formData = super._getSubmitData(updateData);
|
||||
formData = EntitySheetHelper.updateAttributes(formData, this.object);
|
||||
formData = EntitySheetHelper.updateGroups(formData, this.object);
|
||||
return formData;
|
||||
}
|
||||
}
|
||||
|
|
22
module/item.js
Normal file
22
module/item.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {EntitySheetHelper} from "./helper.js";
|
||||
|
||||
/**
|
||||
* Extend the base Item document to support attributes and groups with a custom template creation dialog.
|
||||
* @extends {Item}
|
||||
*/
|
||||
export class SimpleItem extends Item {
|
||||
|
||||
/** @inheritdoc */
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
this.data.data.groups = this.data.data.groups || {};
|
||||
this.data.data.attributes = this.data.data.attributes || {};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
static async createDialog(data={}, options={}) {
|
||||
return EntitySheetHelper.createDialog.call(this, data, options);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
// Import Modules
|
||||
import { SimpleActor } from "./actor.js";
|
||||
import { SimpleItem } from "./item.js";
|
||||
import { SimpleItemSheet } from "./item-sheet.js";
|
||||
import { SimpleActorSheet } from "./actor-sheet.js";
|
||||
import { preloadHandlebarsTemplates } from "./templates.js";
|
||||
|
@ -35,7 +36,8 @@ Hooks.once("init", async function() {
|
|||
};
|
||||
|
||||
// Define custom Entity classes
|
||||
CONFIG.Actor.entityClass = SimpleActor;
|
||||
CONFIG.Actor.documentClass = SimpleActor;
|
||||
CONFIG.Item.documentClass = SimpleItem;
|
||||
|
||||
// Register sheet application classes
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
|
@ -74,21 +76,12 @@ Hooks.once("init", async function() {
|
|||
* @param {boolean} notify - Whether or not to post nofications.
|
||||
*/
|
||||
function _simpleUpdateInit(formula, notify = false) {
|
||||
// If the formula is valid, use it.
|
||||
try {
|
||||
new Roll(formula).roll();
|
||||
const isValid = Roll.validate(formula);
|
||||
if ( !isValid ) {
|
||||
if ( notify ) ui.notifications.error(`${game.i18n.localize("SIMPLE.NotifyInitFormulaInvalid")}: ${formula}`);
|
||||
return;
|
||||
}
|
||||
CONFIG.Combat.initiative.formula = formula;
|
||||
if (notify) {
|
||||
ui.notifications.notify(game.i18n.localize("SIMPLE.NotifyInitFormulaUpdated") + ` ${formula}`);
|
||||
}
|
||||
}
|
||||
// Otherwise, fall back to a d20.
|
||||
catch (error) {
|
||||
CONFIG.Combat.initiative.formula = "1d20";
|
||||
if (notify) {
|
||||
ui.notifications.error(game.i18n.localize("SIMPLE.NotifyInitFormulaInvalid") + ` ${formula}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,8 +91,8 @@ Hooks.once("init", async function() {
|
|||
return value.slugify({strict: true});
|
||||
});
|
||||
|
||||
// Preload template partials.
|
||||
preloadHandlebarsTemplates();
|
||||
// Preload template partials
|
||||
await preloadHandlebarsTemplates();
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -172,68 +165,3 @@ Hooks.on("getItemDirectoryEntryContext", (html, options) => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
async function _onCreateEntity(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return _simpleDirectoryTemplates(this, event);
|
||||
}
|
||||
ActorDirectory.prototype._onCreateEntity = _onCreateEntity; // For 0.7.x+
|
||||
ItemDirectory.prototype._onCreateEntity = _onCreateEntity;
|
||||
ActorDirectory.prototype._onCreate = _onCreateEntity; // TODO: for 0.6.6
|
||||
ItemDirectory.prototype._onCreate = _onCreateEntity;
|
||||
|
||||
/**
|
||||
* Display the entity template dialog.
|
||||
*
|
||||
* Helper function to display a dialog if there are multiple template types defined for the entity type.
|
||||
* TODO: Refactor in 0.7.x to play more nicely with the Entity.createDialog method
|
||||
*1
|
||||
* @param {EntityCollection} entityType - The sidebar tab
|
||||
* @param {MouseEvent} event - Triggering event
|
||||
*/
|
||||
async function _simpleDirectoryTemplates(collection, event) {
|
||||
|
||||
// Retrieve the collection and find any available templates
|
||||
const entityCollection = collection.tabName === "actors" ? game.actors : game.items;
|
||||
const cls = collection.tabName === "actors" ? Actor : Item;
|
||||
let templates = entityCollection.filter(a => a.getFlag("worldbuilding", "isTemplate"));
|
||||
let ent = game.i18n.localize(cls.config.label);
|
||||
|
||||
// Setup default creation data
|
||||
let type = collection.tabName === "actors" ? 'character' : 'item';
|
||||
let createData = {
|
||||
name: `${game.i18n.localize("SIMPLE.New")} ${ent}`,
|
||||
type: type,
|
||||
folder: event.currentTarget.dataset.folder
|
||||
};
|
||||
if ( !templates.length ) return cls.create(createData, {renderSheet: true});
|
||||
|
||||
// Build an array of types for the form, including an empty default.
|
||||
let types = [{
|
||||
value: null,
|
||||
label: game.i18n.localize("SIMPLE.NoTemplate")
|
||||
}].concat(templates.map(a => { return { value: a.id, label: a.name } }));
|
||||
|
||||
// Render the confirmation dialog window
|
||||
const templateData = {upper: ent, lower: ent.toLowerCase(), types: types};
|
||||
const dlg = await renderTemplate(`systems/worldbuilding/templates/sidebar/entity-create.html`, templateData);
|
||||
return Dialog.confirm({
|
||||
title: `${game.i18n.localize("SIMPLE.Create")} ${createData.name}`,
|
||||
content: dlg,
|
||||
yes: html => {
|
||||
const form = html[0].querySelector("form");
|
||||
const template = entityCollection.get(form.type.value);
|
||||
if ( template ) {
|
||||
createData = mergeObject(template.data, createData, {inplace: false});
|
||||
createData.type = template.data.type;
|
||||
delete createData.flags.worldbuilding.isTemplate;
|
||||
}
|
||||
createData.name = form.name.value;
|
||||
return cls.create(createData, {renderSheet: true});
|
||||
},
|
||||
no: () => {},
|
||||
defaultYes: false
|
||||
});
|
||||
}
|
11
system.json
11
system.json
|
@ -2,10 +2,9 @@
|
|||
"name": "worldbuilding",
|
||||
"title": "Simple World-Building",
|
||||
"description": "A minimalist game system which provides configurable Actor and Item templates to support free-form system agnostic game-play.",
|
||||
"version": 0.40,
|
||||
"minimumCoreVersion": "0.6.6",
|
||||
"compatibleCoreVersion": "0.7.3",
|
||||
"templateVersion": 2,
|
||||
"version": "0.5.0",
|
||||
"minimumCoreVersion": "0.8.4",
|
||||
"compatibleCoreVersion": "0.8.6",
|
||||
"author": "Atropos",
|
||||
"esmodules": ["module/simple.js"],
|
||||
"styles": ["styles/simple.css"],
|
||||
|
@ -22,7 +21,7 @@
|
|||
"primaryTokenAttribute": "health",
|
||||
"secondaryTokenAttribute": "power",
|
||||
"url": "https://gitlab.com/foundrynet/worldbuilding/",
|
||||
"manifest": "https://gitlab.com/foundrynet/worldbuilding/raw/master/system.json",
|
||||
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-040/worldbuilding-release-040.zip",
|
||||
"manifest": "https://gitlab.com/foundrynet/worldbuilding/raw/0.5.x/system.json",
|
||||
"download": "https://gitlab.com/foundrynet/worldbuilding/-/archive/release-050/worldbuilding-release-050.zip",
|
||||
"license": "LICENSE.txt"
|
||||
}
|
||||
|
|
|
@ -2,18 +2,20 @@
|
|||
|
||||
{{!-- Sheet Header --}}
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100" />
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}" height="100" width="100" />
|
||||
<div class="header-fields">
|
||||
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name" /></h1>
|
||||
<h1 class="charname">
|
||||
<input name="name" type="text" value="{{data.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
<div class="resource">
|
||||
<input type="text" name="data.health.value" value="{{data.health.value}}" data-dtype="Number" />
|
||||
<input type="number" name="data.health.value" value="{{systemData.health.value}}"/>
|
||||
<span> / </span>
|
||||
<input type="text" name="data.health.max" value="{{data.health.max}}" data-dtype="Number" />
|
||||
<input type="number" name="data.health.max" value="{{systemData.health.max}}"/>
|
||||
</div>
|
||||
<div class="resource">
|
||||
<input type="text" name="data.power.value" value="{{data.power.value}}" data-dtype="Number" />
|
||||
<input type="number" name="data.power.value" value="{{systemData.power.value}}"/>
|
||||
<span> / </span>
|
||||
<input type="text" name="data.power.max" value="{{data.power.max}}" data-dtype="Number" />
|
||||
<input type="number" name="data.power.max" value="{{systemData.power.max}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
@ -29,14 +31,14 @@
|
|||
<section class="sheet-body">
|
||||
|
||||
{{!-- Biography Tab --}}
|
||||
<div class="tab biography" data-group="primary" data-tab="description">
|
||||
{{editor content=data.biography target="data.biography" button=true owner=owner editable=editable}}
|
||||
<div class="tab description" data-group="primary" data-tab="description">
|
||||
{{editor content=systemData.biography target="data.biography" button=true owner=owner editable=editable rollData=rollData}}
|
||||
</div>
|
||||
|
||||
{{!-- Owned Items Tab --}}
|
||||
<div class="tab items" data-group="primary" data-tab="items">
|
||||
<ol class="item-list">
|
||||
{{#each actor.items as |item id|}}
|
||||
{{#each data.items as |item id|}}
|
||||
<li class="item flexrow" data-item-id="{{item._id}}">
|
||||
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
|
||||
<h4 class="item-name">{{item.name}}</h4>
|
||||
|
@ -75,12 +77,15 @@
|
|||
{{/each}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
<a class="item-control" title="{{ localize "SIMPLE.ItemEdit" }}" data-action="edit"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control" title="{{ localize "SIMPLE.ItemDelete" }}" data-action="delete"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
<p>
|
||||
<a class="item-control" title="{{ localize "SIMPLE.ItemCreate" }}" data-action="create"><i class="fas fa-plus"></i> {{ localize "SIMPLE.ItemCreate" }}</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{!-- Attributes Tab --}}
|
||||
|
@ -94,14 +99,14 @@
|
|||
</header>
|
||||
|
||||
{{!-- Render the attribute list partial. --}}
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-attributes.html" attributes=data.ungroupedAttributes dtypes=dtypes}}
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-attributes.html" attributes=systemData.ungroupedAttributes dtypes=dtypes}}
|
||||
|
||||
{{!-- Render the grouped attributes partial and control. --}}
|
||||
<div class="groups">
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-groups.html" attributes=data.groupedAttributes groups=data.groups dtypes=dtypes}}
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-groups.html" attributes=systemData.groupedAttributes groups=systemData.groups dtypes=dtypes}}
|
||||
|
||||
<div class="group-controls flexrow">
|
||||
<input class="group-prefix" type="text" val=""/>
|
||||
<input class="group-prefix" type="text" value=""/>
|
||||
<a class="button group-control" data-action="create-group"><i class="fas fa-plus"></i>Add Attribute Group</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<form class="flexcol {{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}" />
|
||||
<div class="header-fields">
|
||||
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
|
||||
<h1 class="charname">
|
||||
<input name="name" type="text" value="{{data.name}}" placeholder="Name" />
|
||||
</h1>
|
||||
<div class="resource">
|
||||
<label>Quantity</label>
|
||||
<input type="text" name="data.quantity" value="{{data.quantity}}" data-dtype="Number" />
|
||||
<input type="number" name="data.quantity" value="{{systemData.quantity}}"/>
|
||||
</div>
|
||||
<div class="resource">
|
||||
<label>Weight</label>
|
||||
<input type="text" name="data.weight" value="{{data.weight}}" data-dtype="Number" />
|
||||
<input type="number" name="data.weight" value="{{systemData.weight}}"/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
@ -25,7 +27,7 @@
|
|||
|
||||
{{!-- Description Tab --}}
|
||||
<div class="tab" data-group="primary" data-tab="description">
|
||||
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
|
||||
{{editor content=systemData.description target="data.description" button=true owner=owner editable=editable rollData=rollData}}
|
||||
</div>
|
||||
|
||||
{{!-- Attributes Tab --}}
|
||||
|
@ -39,14 +41,13 @@
|
|||
</header>
|
||||
|
||||
{{!-- Render the attribute list partial. --}}
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-attributes.html" attributes=data.ungroupedAttributes dtypes=dtypes}}
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-attributes.html" attributes=systemData.ungroupedAttributes dtypes=dtypes}}
|
||||
|
||||
{{!-- Render the grouped attributes partial and control. --}}
|
||||
<div class="groups">
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-groups.html" attributes=data.groupedAttributes groups=data.groups dtypes=dtypes}}
|
||||
|
||||
{{> "systems/worldbuilding/templates/parts/sheet-groups.html" attributes=systemData.groupedAttributes groups=systemData.groups dtypes=dtypes}}
|
||||
<div class="group-controls flexrow">
|
||||
<input class="group-prefix" type="text" val=""/>
|
||||
<input class="group-prefix" type="text" value=""/>
|
||||
<a class="button group-control" data-action="create-group"><i class="fas fa-plus"></i>Add Attribute Group</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<form id="entity-create" autocomplete="off" onsubmit="event.preventDefault();">
|
||||
<div class="form-group">
|
||||
<label>{{localize "Name"}}</label>
|
||||
<input type="text" name="name" placeholder="{{localize 'ENTITY.CreateNew'}} {{upper}}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{localize "Type"}}</label>
|
||||
<select name="type">
|
||||
{{#each types}}
|
||||
<option value="{{this.value}}">{{this.label}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
Loading…
Add table
Reference in a new issue