mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-04-30 02:31:41 -04:00
- Added a new "Formula" attribute type for both actors and items. - When iterating through attributes, formula attributes are noted in an array so that they can be iterated through in a second pass to evaluate their referenced attributes. The second iteration just handles attribute replacement rather than rolling the formula, that's deferred until the attributes are used in an actual roll formula. - Items also have the same behavior. If an attribute isn't on the item, it will fall back to check the parent actor instead. - Likely areas with issues would be formula attributes that reference other formula attributes, or item formula attributes that reference actor formula attributes.
130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
/**
|
|
* Extend the basic ActorSheet with some very simple modifications
|
|
* @extends {ActorSheet}
|
|
*/
|
|
export class SimpleActorSheet extends ActorSheet {
|
|
|
|
/** @override */
|
|
static get defaultOptions() {
|
|
return mergeObject(super.defaultOptions, {
|
|
classes: ["worldbuilding", "sheet", "actor"],
|
|
template: "systems/worldbuilding/templates/actor-sheet.html",
|
|
width: 600,
|
|
height: 600,
|
|
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}],
|
|
dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @override */
|
|
getData() {
|
|
const data = super.getData();
|
|
data.dtypes = ["String", "Number", "Boolean", "Formula"];
|
|
for ( let attr of Object.values(data.data.attributes) ) {
|
|
attr.isCheckbox = attr.dtype === "Boolean";
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @override */
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
|
|
// Everything below here is only needed if the sheet is editable
|
|
if (!this.options.editable) return;
|
|
|
|
// 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);
|
|
});
|
|
|
|
// 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 or Remove Attribute
|
|
html.find(".attributes").on("click", ".attribute-control", this._onClickAttributeControl.bind(this));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @override */
|
|
setPosition(options={}) {
|
|
const position = super.setPosition(options);
|
|
const sheetBody = this.element.find(".sheet-body");
|
|
const bodyHeight = position.height - 192;
|
|
sheetBody.css("height", bodyHeight);
|
|
return position;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
async _onClickAttributeControl(event) {
|
|
event.preventDefault();
|
|
const a = event.currentTarget;
|
|
const action = a.dataset.action;
|
|
const attrs = this.object.data.data.attributes;
|
|
const form = this.form;
|
|
|
|
// Add new attribute
|
|
if ( action === "create" ) {
|
|
const nk = Object.keys(attrs).length + 1;
|
|
let newKey = document.createElement("div");
|
|
newKey.innerHTML = `<input type="text" name="data.attributes.attr${nk}.key" value="attr${nk}"/>`;
|
|
newKey = newKey.children[0];
|
|
form.appendChild(newKey);
|
|
await this._onSubmit(event);
|
|
}
|
|
|
|
// Remove existing attribute
|
|
else if ( action === "delete" ) {
|
|
const li = a.closest(".attribute");
|
|
li.parentElement.removeChild(li);
|
|
await this._onSubmit(event);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @override */
|
|
_updateObject(event, formData) {
|
|
|
|
// Handle the free-form attributes list
|
|
const formAttrs = expandObject(formData).data.attributes || {};
|
|
const attributes = Object.values(formAttrs).reduce((obj, v) => {
|
|
let k = v["key"].trim();
|
|
if ( /[\s\.]/.test(k) ) return ui.notifications.error("Attribute keys may not contain spaces or periods");
|
|
delete v["key"];
|
|
obj[k] = v;
|
|
return obj;
|
|
}, {});
|
|
|
|
// Remove attributes which are no longer used
|
|
for ( let k of Object.keys(this.object.data.data.attributes) ) {
|
|
if ( !attributes.hasOwnProperty(k) ) attributes[`-=${k}`] = null;
|
|
}
|
|
|
|
// Re-combine formData
|
|
formData = Object.entries(formData).filter(e => !e[0].startsWith("data.attributes")).reduce((obj, e) => {
|
|
obj[e[0]] = e[1];
|
|
return obj;
|
|
}, {_id: this.object._id, "data.attributes": attributes});
|
|
|
|
// Update the Actor
|
|
return this.object.update(formData);
|
|
}
|
|
}
|