mirror of
https://github.com/RoY7x/worldbuilding.git
synced 2025-04-30 02:31:41 -04:00
- 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.
153 lines
4.9 KiB
JavaScript
153 lines
4.9 KiB
JavaScript
import { ATTRIBUTE_TYPES } from "./constants.js";
|
|
|
|
/**
|
|
* 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 = ATTRIBUTE_TYPES;
|
|
for ( let attr of Object.values(data.data.attributes) ) {
|
|
attr.isCheckbox = attr.dtype === "Boolean";
|
|
attr.isResource = attr.dtype === "Resource";
|
|
}
|
|
data.shorthand = !!game.settings.get("worldbuilding", "macroShorthand");
|
|
return data;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @override */
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
|
|
// Handle rollable attributes.
|
|
html.find('.items .rollable').click(ev => {
|
|
let button = $(ev.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,
|
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
|
flavor: `<h2>${item.name}</h2><h3>${button.text()}</h3>`
|
|
});
|
|
});
|
|
|
|
// 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 objKeys = Object.keys(attrs);
|
|
let nk = Object.keys(attrs).length + 1;
|
|
let newValue = `attr${nk}`;
|
|
let newKey = document.createElement("div");
|
|
while ( objKeys.includes(newValue) ) {
|
|
++nk;
|
|
newValue = `attr${nk}`;
|
|
};
|
|
newKey.innerHTML = `<input type="text" name="data.attributes.attr${nk}.key" value="${newValue}"/>`;
|
|
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);
|
|
}
|
|
}
|