import { PegasusUtility } from "./pegasus-utility.js"; /** * Extend the basic ItemSheet with some very simple modifications * @extends {ItemSheet} */ export class PegasusItemSheet extends ItemSheet { /** @override */ static get defaultOptions() { return mergeObject(super.defaultOptions, { classes: ["fvtt-pegasus-rpg", "sheet", "item"], template: "systems/fvtt-pegasus-rpg/templates/item-sheet.html", dragDrop: [{ dragSelector: null, dropSelector: null }], width: 620, height: 550, tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}] }); } /* -------------------------------------------- */ _getHeaderButtons() { let buttons = super._getHeaderButtons(); // Add "Post to chat" button // We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry! buttons.unshift( { class: "post", icon: "fas fa-comment", onclick: ev => { } }) return buttons } /* -------------------------------------------- */ /** @override */ setPosition(options = {}) { const position = super.setPosition(options); const sheetBody = this.element.find(".sheet-body"); const bodyHeight = position.height - 192; sheetBody.css("height", bodyHeight); if (this.item.type.includes('weapon')) { position.width = 640; } return position; } /* -------------------------------------------- */ async getData() { const objectData = this.object let itemData = foundry.utils.deepClone(objectData) let formData = { title: this.title, id: this.id, type: objectData.type, img: objectData.img, name: objectData.name, editable: this.isEditable, cssClass: this.isEditable ? "editable" : "locked", optionsDiceList: PegasusUtility.getOptionsDiceList(), data: itemData.system, description: await TextEditor.enrichHTML(this.object.system.description, {async: true}), limited: this.object.limited, options: this.options, owner: this.document.isOwner, mr: (this.object.type == 'specialisation'), isGM: game.user.isGM } if (this.object.type == "power") { formData.effects = await TextEditor.enrichHTML(this.object.system.effects, {async: true}) formData.purchasedeffects = await TextEditor.enrichHTML(this.object.system.purchasedeffects, {async: true}) } this.options.editable = true console.log("ITEM DATA", formData, this); return formData; } /* -------------------------------------------- */ _getHeaderButtons() { let buttons = super._getHeaderButtons(); buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.postItem() }); return buttons } /* -------------------------------------------- */ postItem() { let chatData = this.item.system if (this.actor) { chatData.actor = { id: this.actor.id }; } // Don't post any image for the item (which would leave a large gap) if the default image is used if (chatData.img.includes("/blank.png")) { chatData.img = null; } // JSON object for easy creation chatData.jsondata = JSON.stringify( { compendium: "postedItem", payload: chatData, }); renderTemplate('systems/fvtt-pegasus-rpg/templates/post-item.html', chatData).then(html => { let chatOptions = PegasusUtility.chatDataSetup(html); ChatMessage.create(chatOptions) }); } /* -------------------------------------------- */ async viewSubitem(ev) { let field = $(ev.currentTarget).data('type'); let idx = Number($(ev.currentTarget).data('index')); let itemData = this.object.system[field][idx]; if (itemData.name != 'None') { let spec = await Item.create(itemData, { temporary: true }); spec.system.origin = "embeddedItem"; new PegasusItemSheet(spec).render(true); } } /* -------------------------------------------- */ async deleteSubitem(ev) { let field = $(ev.currentTarget).data('type'); let idx = Number($(ev.currentTarget).data('index')); let oldArray = this.object.system[field]; let itemData = this.object.system[field][idx]; if (itemData.name != 'None') { let newArray = []; for (var i = 0; i < oldArray.length; i++) { if (i != idx) { newArray.push(oldArray[i]); } } this.object.update({ [`system.${field}`]: newArray }); } } /* -------------------------------------------- */ async manageSpec() { let itemData = this.object.system.specialisation[0]; if (itemData.name != 'None') { let spec = await Item.create(itemData, { temporary: true }); spec.system.origin = "embeddedItem"; new PegasusItemSheet(spec).render(true); } } /* -------------------------------------------- */ /** @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.object.options.actor.getOwnedItem(li.data("item-id")); item.sheet.render(true); }); html.find('.delete-spec').click(ev => { this.object.update({ "system.specialisation": [{ name: 'None' }] }); }); html.find('.delete-subitem').click(ev => { this.deleteSubitem(ev); }); html.find('.stat-choice-flag').click(ev => { let idx = $(ev.currentTarget).data("stat-idx"); let array = duplicate(this.object.system.statincreasechoice); array[Number(idx)].flag = !array[Number(idx)].flag; this.object.update({ "system.statincreasechoice": array }); }); // Update Inventory Item html.find('.item-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); let itemId = li.data("item-id"); let itemType = li.data("item-type"); }); html.find('.view-subitem').click(ev => { this.viewSubitem(ev); }); html.find('.view-spec').click(ev => { this.manageSpec(); }); } /* -------------------------------------------- */ async addAbility(event, item) { let newItem = duplicate(item) newItem._id = randomID(item.id.length); console.log("ABB", event, item) if (event.toElement.className == 'drop-abilities') { let abilityArray = duplicate(this.object.system.abilities); abilityArray.push(newItem); await this.object.update({ 'system.abilities': abilityArray }); } if (event.toElement.className == 'drop-optionnal-abilities') { let abilityArray = duplicate(this.object.system.optionnalabilities); abilityArray.push(newItem); await this.object.update({ 'system.optionnalabilities': abilityArray }); } } /* -------------------------------------------- */ async addRacePerk(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id); if (event.toElement.className == 'drop-race-perk') { let perkArray = duplicate(this.object.system.perks); perkArray.push(newItem); await this.object.update({ 'system.perks': perkArray }); } } /* -------------------------------------------- */ async addSpecialisation(item) { let newItem = duplicate(item) newItem._id = randomID(item.id.length) let specArray = [newItem]; await this.object.update({ 'system.specialisation': specArray }); } /* -------------------------------------------- */ async addRoleSpecialisation(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); console.log("Add spec", event, newItem); if (event.toElement.className == 'drop-spec1') { let specArray = duplicate(this.object.system.specialisationsplus1); specArray.push(newItem); await this.object.update({ 'system.specialisationsplus1': specArray }); } if (event.toElement.className == 'drop-spec2') { let specArray = duplicate(this.object.system.specincrease); specArray.push(newItem); await this.object.update({ 'system.specincrease': specArray }); } } /* -------------------------------------------- */ async addRolePerk(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-perk2') { let perkArray = duplicate(this.object.system.perks); perkArray.push(newItem); await this.object.update({ 'system.perks': perkArray }); } if (event.toElement.className == 'drop-specialperk1') { let perkArray = duplicate(this.object.system.specialperk); perkArray.push(newItem); await this.object.update({ 'system.specialperk': perkArray }); } } /* -------------------------------------------- */ async addRoleAbility(event, item) { let newItem = duplicate(item) newItem._id = randomID(item.id.length) if (event.toElement.className == 'drop-specialability') { let abiArray = duplicate(this.object.system.specialability) abiArray.push(newItem) await this.object.update({ 'system.specialability': abiArray }) } } /* -------------------------------------------- */ async addPower(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-spec-power') { let powArray = duplicate(this.object.system.powers); powArray.push(newItem); await this.object.update({ 'system.powers': powArray }); } } /* -------------------------------------------- */ async addAbilityPower(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-ability-power') { let powArray = duplicate(this.object.system.powersgained); powArray.push(newItem); await this.object.update({ 'system.powersgained': powArray }); } } /* -------------------------------------------- */ async addAbilityEffect(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-ability-effect') { let powArray = duplicate(this.object.system.effectsgained); powArray.push(newItem); await this.object.update({ 'system.effectsgained': powArray }); } } /* -------------------------------------------- */ async addAbilitySpec(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-ability-spec') { let powArray = duplicate(this.object.system.specialisations); powArray.push(newItem); await this.object.update({ 'system.specialisations': powArray }); } } /* -------------------------------------------- */ async addAbilityWeaponArmor(event, item) { let newItem = duplicate(item); newItem._id = randomID(item.id.length); if (event.toElement.className == 'drop-ability-weapon') { let weaponArray = duplicate(this.object.system.attackgained); weaponArray.push(newItem); await this.object.update({ 'system.attackgained': weaponArray }); } if (event.toElement.className == 'drop-ability-armor') { let armorArray = duplicate(this.object.system.armorgained); armorArray.push(newItem); await this.object.update({ 'system.armorgained': armorArray }); } } /* -------------------------------------------- */ async addPerkSpecialisation(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-spec-perk') { //console.log("PER SPEC", event) let key = event.toElement.dataset["key"]; if (key == 'affectedspec') { await this.object.update({ 'system.features.affectedspec.value': newItem.name }); } else { await this.object.update({ 'system.features.gainspecdice.value': newItem.name }); } } } /* -------------------------------------------- */ async addPerkEffect(event, item) { let newItem = duplicate(item) if (event.toElement.className == 'drop-perk-effect') { let effectArray = duplicate(this.object.system.effectsgained) effectArray.push(newItem) await this.object.update({ 'system.effectsgained': effectArray }) } } /* -------------------------------------------- */ async addEffectPower(event, item) { let newItem = duplicate(item) if (event.toElement.className == 'drop-power-effect') { let effectArray = duplicate(this.object.system.effectsgained) effectArray.push(newItem); await this.object.update({ 'system.effectsgained': effectArray }) } } /* -------------------------------------------- */ async addEffectSpec(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-effect-spec') { let specArray = duplicate(this.object.system.recoveryrollspec); specArray.push(newItem); await this.object.update({ 'system.recoveryrollspec': specArray }); } if (event.toElement.className == 'drop-effect-specaffected') { let specArray = duplicate(this.object.system.specaffected); specArray.push(newItem); await this.object.update({ 'system.specaffected': specArray }); } } /* -------------------------------------------- */ async addEffectItem(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-equipment-effect') { let effectArray = duplicate(this.object.system.effects); effectArray.push(newItem); await this.object.update({ 'system.effects': effectArray }); } } /* -------------------------------------------- */ async addEffectVirtueVice(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-virtue-vice-effect') { let effectArray = duplicate(this.object.system.effectsgained); effectArray.push(newItem); await this.object.update({ 'system.effectsgained': effectArray }); } } /* -------------------------------------------- */ async addViceToVirtue(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-virtue-vice') { let viceArray = duplicate(this.object.system.unavailablevice); viceArray.push(newItem); await this.object.update({ 'system.unavailablevice': viceArray }); } } /* -------------------------------------------- */ async addVirtueToVice(event, item) { let newItem = duplicate(item); if (event.toElement.className == 'drop-vice-virtue') { let virtueArray = duplicate(this.object.system.unavailablevirtue); virtueArray.push(newItem); await this.object.update({ 'system.unavailablevirtue': virtueArray }); } } /* -------------------------------------------- */ async _onDrop(event) { let data = event.dataTransfer.getData('text/plain') let dataItem = JSON.parse( data) let item = fromUuidSync(dataItem.uuid) if (item.pack) { item = await PegasusUtility.searchItem(item) } if (!item) { ui.notifications.warn("Unable to find relevant item - Aborting drag&drop " + data.uuid) return } if (this.object.type == 'virtue' ) { if (item.type == 'effect') { return this.addEffectVirtueVice(event, item); } if (item.type == 'vice') { return this.addViceToVirtue(event, item); } } if (this.object.type == 'vice' ) { if (item.type == 'effect') { return this.addEffectVirtueVice(event, item); } if (item.type == 'virtue') { return this.addVirtueToVice(event, item); } } if (this.object.type == 'weapon' || this.object.type == 'armor' || this.object.type == 'shield' || this.object.type == 'equipment' || this.object.type == 'vehiclemodule' || this.object.type == 'vehicleweaponmodule') { if (item.type == 'effect') { return this.addEffectItem(event, item); } } if (this.object.type == 'power') { if (item.type == 'effect') { return this.addEffectPower(event, item); } } if (this.object.type == 'effect') { if (item.type == 'specialisation') { return this.addEffectSpec(event, item); } } if (this.object.type == 'race') { if (item.type == 'ability') { return this.addAbility(event, item); } if (item.type == 'perk') { return this.addRacePerk(event, item); } } if (this.object.type == 'perk') { if (item.type == 'specialisation') { return this.addPerkSpecialisation(event, item) } if (item.type == 'effect') { return this.addPerkEffect(event, item); } } if (this.object.type == 'specialisation') { if (item.type == 'power') { return this.addPower(event, item); } } if (this.object.type == 'ability') { if (item.type == 'effect') { return this.addAbilityEffect(event, item); } if (item.type == 'power') { return this.addAbilityPower(event, item); } if (item.type == 'specialisation') { return this.addAbilitySpec(event, item); } if (item.type == 'weapon' || item.type == 'armor') { return this.addAbilityWeaponArmor(event, item); } } if (this.object.type == 'role') { if (item.type == 'specialisation') { return this.addRoleSpecialisation(event, item) } if (item.type == 'perk') { return this.addRolePerk(event, item) } if (item.type == 'ability') { return this.addRoleAbility(event, item) } } ui.notifications.warn("This item can not be dropped over another item") } /* -------------------------------------------- */ get template() { let type = this.item.type; return `systems/fvtt-pegasus-rpg/templates/item-${type}-sheet.html`; } /* -------------------------------------------- */ /** @override */ _updateObject(event, formData) { return this.object.update(formData); } }