const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets export class CreatureSheet extends HandlebarsApplicationMixin(ActorSheetV2) { /** @inheritDoc */ static DEFAULT_OPTIONS = { position: {width: 520, height: 480}, classes: ['dsa41', 'sheet', 'actor', 'creature'], tag: 'form', form: { submitOnChange: true, closeOnSubmit: false, handler: CreatureSheet.#onSubmitForm }, actions: { openEmbeddedDocument: CreatureSheet.#openEmbeddedDocument, removeAttack: CreatureSheet.#removeAttack, addAttack: CreatureSheet.#addAttack, roll: CreatureSheet.#dieRoll, editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage, } } static TABS = { sheet: { tabs: [], initial: 'meta' } } /** @inheritDoc */ static PARTS = { form: { template: `systems/DSA_4-1/templates/actor/creature/main-sheet.hbs` }, meta: { template: `systems/DSA_4-1/templates/actor/creature/tab-meta.hbs` }, attacks: { template: `systems/DSA_4-1/templates/actor/creature/tab-attacks.hbs` }, description: { template: `systems/DSA_4-1/templates/actor/creature/tab-description.hbs` }, loot: { template: `systems/DSA_4-1/templates/actor/creature/tab-loot.hbs` }, visibility: { template: `systems/DSA_4-1/templates/actor/creature/tab-visibility.hbs` }, } _getTabsConfig(group) { const tabs = foundry.utils.deepClone(super._getTabsConfig(group)) const tabDef = [ {id: 'meta', group: 'sheet', label: 'Meta'}, {id: 'attacks', group: 'sheet', label: 'Attacken'}, {id: 'description', group: 'sheet', label: 'Beschreibung'}, {id: 'loot', group: 'sheet', label: 'Loot'}, {id: 'visibility', group: 'sheet', label: 'Sichtbarkeit'}, ] for (const tab of tabDef) { if (game.user.isGM || this.document.system.visibility[tab.id]) { tabs.tabs.push(tab) } } return tabs } _configureRenderOptions(options) { super._configureRenderOptions(options) if (options.window) { options.window.title = this.document.name } return options } /** * Handle form submission * @this {AdvantageSheet} * @param {SubmitEvent} event * @param {HTMLFormElement} form * @param {FormDataExtended} formData */ static async #onSubmitForm(event, form, formData) { event.preventDefault() await this.document.update(formData.object) } static #openEmbeddedDocument(event, target) { const dataset = target.dataset const id = dataset.itemId ?? dataset.id this.document.items.get(id).sheet.render(true) } static async #removeAttack(evt) { const {index} = evt.srcElement.dataset; let sans = Array.from(this.document.system.attacks) sans.splice(index, 1) await this.document.update({'system.attacks': sans}) } static async #dieRoll(evt) { const {rollType, rollName, roll} = evt.srcElement.dataset; let r = new Roll(roll, this.document.getRollData()); const label = `${rollType} (${rollName})` await r.toMessage({ speaker: ChatMessage.getSpeaker({actor: this.document}), flavor: label, rollMode: game.settings.get('core', 'rollMode'), }) } static async #addAttack() { const name = this.element.querySelector('#attack_name').value const at = this.element.querySelector('#attack_at').value const pa = this.element.querySelector('#attack_pa').value const tp = this.element.querySelector('#attack_tp').value const newAttack = { name, at, pa, tp } await this.document.update({'system.attacks': [...this.document.system.attacks, newAttack]}) this.element.querySelector('#attack_name').value = "" this.element.querySelector('#attack_at').value = "" this.element.querySelector('#attack_pa').value = "" this.element.querySelector('#attack_tp').value = "" } /** @override */ async _prepareContext(options) { const context = await super._prepareContext(options) const actorData = context.document context.attacks = [] context.actor = actorData actorData.system.attacks.forEach((attack, index) => { context.attacks.push({ namepath: `system.attacks.${index}.name`, name: attack.name, atpath: `system.attacks.${index}.at`, at: attack.at, papath: `system.attacks.${index}.pa`, pa: attack.pa, tppath: `system.attacks.${index}.tp`, tp: attack.tp, index: index, }) }) context.metaRevealed = actorData.system.visibility.meta context.attacksRevealed = actorData.system.visibility.attacks context.descriptionRevealed = actorData.system.visibility.description context.lootRevealed = actorData.system.visibility.loot context.inventoryItems = [] actorData.items.forEach((item, index) => { if (item.type === "Equipment") { context.inventoryItems.push({ index: index, id: item._id, quantity: item.system.quantity, name: item.name, icon: item.img }) } }) return context } _canDragDrop(event, options) { return game.user.isGM } _canDrag(event, options) { return true } async _onDrop(event) { const data = TextEditor.implementation.getDragEventData(event); const actor = this.actor; //const allowed = Hooks.call("dropActorSheetData", actor, this, data); // if (allowed === false) return; // Dropped Documents const documentClass = foundry.utils.getDocumentClass(data.type) if (documentClass) { const document = await documentClass.fromDropData(data); if (document.type === "Equipment") { // No duplication by moving items from one actor to another if (document.parent && document.parent !== this.actor) { document.parent.items.get(document._id).delete() } await this._onDropDocument(event, document) } } } _onRender(context, options) { new foundry.applications.ux.DragDrop.implementation({ dropSelector: ".window-content", dragSelector: ".equipment", permissions: { drop: this._canDragDrop.bind(this), drag: this._canDrag.bind(this) }, callbacks: { dragstart: this._onDragStart.bind(this), drop: this._onDrop.bind(this) } }).bind(this.element) } }