diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 46ccb270..1f0c37a4 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -161,7 +161,7 @@ export class RdDActorSheet extends ActorSheet { /* -------------------------------------------- */ async _onDrop(event) { - let toSuper = await RdDUtility.processItemDropEvent(this, event); + let toSuper = await this.actor.processItemDropEvent(event, this.objetVersConteneur); if (toSuper) { super._onDrop(event); } diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js index 5ef1944c..13ac3c1e 100644 --- a/module/actor-vehicule-sheet.js +++ b/module/actor-vehicule-sheet.js @@ -68,7 +68,7 @@ export class RdDActorVehiculeSheet extends ActorSheet { /* -------------------------------------------- */ async _onDrop(event) { - let toSuper = await RdDUtility.processItemDropEvent(this, event); + let toSuper = await this.actor.processItemDropEvent(event, this.objetVersConteneur); if ( toSuper) { super._onDrop(event); } diff --git a/module/actor.js b/module/actor.js index e98339a8..c6c67f35 100644 --- a/module/actor.js +++ b/module/actor.js @@ -826,22 +826,8 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - validateConteneur(itemId, conteneurId) { - const dest = this.getObjet(conteneurId); - if (dest?.type != 'conteneur') { - ui.notifications.warn(`Impossible de déplacer un objet (${item.name}) vers un ${dest.type} qui n'est pas un conteneur (${dest.name}) !`); - return false; - } - const item = this.getObjet(itemId); - if (this._isConteneurContenu(item, conteneurId)) { - ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${dest.name} !`); - return false; // Loop detected ! - } - return true; - } - _isConteneurContenu(item, conteneurId) { - if (item?.type == 'conteneur') { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant + if (Misc.data(item)?.type == 'conteneur') { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant for (let id of Misc.templateData(item).contenu) { let subObjet = this.getObjet(id); if (subObjet?.id == conteneurId) { @@ -869,41 +855,6 @@ export class RdDActor extends Actor { + Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/ } - /* -------------------------------------------- */ - isConteneurSuffisant(itemId, conteneurId) { - if (!conteneurId) { - // on peut toujours vider son sac - return true; - } - return this.validateConteneur(itemId, conteneurId) && this.testConteneurCapacite(itemId, conteneurId); - } - - /* -------------------------------------------- */ - /** Teste si le conteneur de destination a suffisament de capacité - * pour recevoir le nouvel objet - */ - testConteneurCapacite(itemId, conteneurId) { - let conteneur = this.getObjet(conteneurId); // recup conteneur (ou undefined) - //console.log("Conteneur trouvé : ", conteneur); - if (conteneur?.type != "conteneur") { - return true; - } - - const tplConteneur = Misc.templateData(conteneur); - // Calculer le total actuel des contenus - let encContenu = this.getRecursiveEnc(conteneur) - Number(tplConteneur.encombrement); - let nouvelObjet = this.getObjet(itemId); - let newEnc = this.getRecursiveEnc(nouvelObjet); // Calculer le total actuel du nouvel objet - //console.log( currentEnc, newEnc, tplConteneur.capacite, conteneur.name); - if (nouvelObjet && ((encContenu + newEnc) > Number(tplConteneur.capacite))) { - ui.notifications.warn( - `Le conteneur ${conteneur.name} a une capacité de ${tplConteneur.capacite}, et contient déjà ${encContenu}. - Impossible d'y ranger: ${nouvelObjet.name} d'encombrement ${newEnc}!`); - return false; - } - return true; - } - /* -------------------------------------------- */ buildSubConteneurObjetList(conteneurId, deleteList) { let conteneur = this.getObjet(conteneurId); @@ -931,9 +882,8 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ /** Supprime un item d'un conteneur, sur la base * de leurs ID */ - async enleverDeConteneur(itemId, conteneurId) { - let conteneur = this.getObjet(conteneurId); - if (conteneur?.type == 'conteneur') { // Si présent + async enleverDeConteneur(itemId, conteneur) { + if (conteneur?.isConteneur()) { // Si présent let data2use = duplicate(Misc.data(conteneur)); //console.log("Suppression du conteneur1", conteneurId, itemId, data2use.data.contenu); let contenu = data2use.data.contenu; @@ -949,9 +899,8 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ /** Ajoute un item dans un conteneur, sur la base * de leurs ID */ - async ajouterAConteneur(itemId, conteneurId) { - let conteneur = this.getObjet(conteneurId); - if (conteneur?.type == 'conteneur') { + async ajouterDansConteneur(itemId, conteneur) { + if (conteneur?.isConteneur()) { let data2use = duplicate(Misc.data(conteneur)); data2use.data.contenu.push(itemId); await this.updateEmbeddedDocuments('Item', [data2use]); @@ -972,6 +921,74 @@ export class RdDActor extends Actor { await this.updateEmbeddedDocuments('Item', conteneurFixedList); } + /* -------------------------------------------- */ + async processItemDropEvent(event, objetVersConteneur) { + let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); + console.log("DRAG", this.id, dragData); + let itemId = dragData.id || dragData.data._id; + if (dragData.type == 'Item') { + if (dragData.actorId && dragData.actorId != this.id) { + console.log("Moving objects", dragData); + this.moveItemsBetweenActors(itemId, dragData.actorId); + return false; + } + if (dragData.actorId == this.id) { + // rangement + const destId = $(event.target).parents(".item").attr("data-item-id"); + const srcId = objetVersConteneur[itemId]; + if (srcId != destId && itemId != destId) { // déplacement de l'objet + const item = this.getObjet(itemId); + const dest = this.getObjet(destId); + const src = this.getObjet(srcId); + if (!dest) { + // on peut toujours vider son sac + await this.enleverDeConteneur(itemId, src); + } + else if (!dest.isConteneur()) { + // regrouper? + await this.regrouperEquipementsSimilaires(item, dest); + } + else if (this.conteneurPeutContenir(dest, item)) { + // déplacer? + await this.enleverDeConteneur(itemId, src); + await this.ajouterDansConteneur(itemId, dest); + } + } + } + this.computeEncombrementTotalEtMalusArmure(); + } + if (dragData.type == "Actor") { + this.addSubacteur(itemId); + } + return true; + } + + conteneurPeutContenir(dest, item) { + const destData = Misc.data(dest); + if (destData?.type != 'conteneur') { + ui.notifications.warn(`Impossible de déplacer un objet (${item.name}) vers un ${destData.type} qui n'est pas un conteneur (${dest.name}) !`); + return false; + } + if (this._isConteneurContenu(item, conteneurId)) { + ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`); + return false; // Loop detected ! + } + + // Calculer le total actuel des contenus + let encContenu = this.getRecursiveEnc(dest) - Number(destData.data.encombrement); + let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet + + // Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet + if (Number(destData.data.capacite) < encContenu + newEnc) { + ui.notifications.warn( + `Le conteneur ${dest.name} a une capacité de ${destData.data.capacite}, et contient déjà ${encContenu}. + Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`); + return false; + } + return true; + + } + /* -------------------------------------------- */ async moveItemsBetweenActors(itemId, sourceActorId) { let itemsList = [] @@ -995,7 +1012,7 @@ export class RdDActor extends Actor { let newItemId = itemMap[item.id]; // Get newItem console.log('New conteneur filling!', newConteneur, newItemId, item); - let contenu = duplicate(newConteneur.data.contenu); + let contenu = duplicate(Misc.templateData(newConteneur).contenu); contenu.push(newItemId); await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'data.contenu': contenu }]); } @@ -1005,6 +1022,13 @@ export class RdDActor extends Actor { } } + async regrouperEquipementsSimilaires(item, dest) { + if (item.isEquipementSimilaire(dest)) { + await dest.quantiteIncDec(Misc.templateData(item).quantite); + await this.deleteEmbeddedDocuments('Item', [item.id]); + } + } + /* -------------------------------------------- */ detectSurEncombrement() { return Math.max(0, Math.ceil(Number(this.encTotal) - this.getEncombrementMax())); @@ -3386,7 +3410,7 @@ export class RdDActor extends Actor { nbBrinsReste: newQuantite } this.diminuerQuantiteObjet(herbeData._id, herbeData.nbBrins); - + ChatMessage.create({ whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html`, messageData) @@ -3396,7 +3420,7 @@ export class RdDActor extends Actor { async diminuerQuantiteObjet(id, nb, options = { supprimerSiZero: false }) { const item = this.getObjet(id); - if (item){ + if (item) { await item.diminuerQuantite(nb, options); } } diff --git a/module/item.js b/module/item.js index ffe491a8..39346eee 100644 --- a/module/item.js +++ b/module/item.js @@ -4,7 +4,8 @@ import { RdDUtility } from "./rdd-utility.js"; const typesObjetsEquipement = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"]; const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]; -const encBrin = 0.00005; +const encBrin = 0.00005;// un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc + /* -------------------------------------------- */ export class RdDItem extends Item { @@ -16,17 +17,42 @@ export class RdDItem extends Item { return typesObjetsOeuvres; } + isConteneur() { + return Misc.data(this).type == 'conteneur'; + } + + isAlcool() { + const itemData = Misc.data(this); + return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise; + } + + isPotion() { + return Misc.data(this).type == 'potion'; + } + + isEquipement() { + return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type); + } + + getEnc() { + const itemData = Misc.data(this); + switch (itemData.type) { + case 'herbe': + return encBrin; + } + return itemData.data.encombrement + } + prepareDerivedData() { super.prepareDerivedData(); - const itemData = Misc.data(this); - if (RdDItem.getTypeObjetsEquipement().includes(itemData.type)) { + if (this.isEquipement(this)) { this._calculsEquipement(); } - if (itemData.type == 'potion') { + if (this.isPotion()) { this.prepareDataPotion() } + const itemData = Misc.data(this); itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false }); - } prepareDataPotion() { @@ -42,7 +68,7 @@ export class RdDItem extends Item { _calculsEquipement() { const tplData = Misc.templateData(this); - const quantite = Misc.data(this).type == 'conteneur' ? 1 : (tplData.quantite ?? 0); + const quantite = this.isConteneur() ? 1 : (tplData.quantite ?? 0); const enc = this.getEnc(); if (enc != undefined) { tplData.encTotal = Math.max(enc, 0) * quantite; @@ -52,15 +78,6 @@ export class RdDItem extends Item { } } - getEnc() { - const itemData = Misc.data(this); - switch (itemData.type) { - case 'herbe': - return encBrin; - } - return itemData.data.encombrement - } - getActionPrincipale(options = { warnIfNot: true }) { const itemData = Misc.data(this); if ((itemData.data.quantite ?? 0) <= 0) { @@ -80,31 +97,53 @@ export class RdDItem extends Item { return undefined; } - isAlcool() { - const itemData = Misc.data(this); - return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise; - } - async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { if (options.diminuerQuantite == false) return; + await this.quantiteIncDec(-nombre, options); + } + + async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { const itemData = Misc.data(this); const quantite = itemData.data.quantite; if (quantite != undefined) { - const reste = Math.max(quantite - nombre, 0); + const reste = Math.max(quantite + nombre, 0); - if (options.supprimerSiZero && reste == 0) { - ui.notifications.notify(`${itemData.name} supprimé de votre équipement`); - await this.delete(); + if (reste == 0) { + if (options.supprimerSiZero){ + ui.notifications.notify(`${itemData.name} supprimé de votre équipement`); + await this.delete(); + } + else { + ui.notifications.notify(`Il ne vous reste plus de ${itemData.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`); + await this.update({ "data.quantite": 0 }); + } } else { - ui.notifications.notify(`Quantité de ${itemData.name} réduite de ${nombre}.${reste == 0 - ? "Il ne vous en reste plus, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer." - : ""}`); await this.update({ "data.quantite": reste }); } } } + /* -------------------------------------------- */ + // détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité + isEquipementSimilaire(other) { + const itemData = Misc.data(this); + const otherData = Misc.data(other); + const tplData = Misc.templateData(this); + const otherTplData = Misc.templateData(other); + if (!this.isEquipement()) return false; + if (itemData.type != otherData.type) return false; + if (itemData.name != otherData.name) return false; + if (tplData.quantite == undefined) return false; + + for (const [key, value] of Object.entries(tplData)) { + if (['quantite', 'encTotal', 'prixTotal'].includes(key)) continue; + if (value != otherTplData[key]) return false; + } + return true; + } + + /* -------------------------------------------- */ async postItem() { console.log(this); diff --git a/module/rdd-utility.js b/module/rdd-utility.js index a0bd3da4..db6ef01c 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -281,41 +281,6 @@ export class RdDUtility { formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []); } - /* -------------------------------------------- */ - static async processItemDropEvent(actorSheet, event) { - let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); - console.log(dragData, actorSheet.actor.id); - let objetId = dragData.id || dragData.data._id; - console.log("DRAG", dragData); - if (dragData.type == 'Item') { - if (dragData.actorId) { - if (dragData.actorId != actorSheet.actor.id) { - console.log("Moving objects", dragData); - actorSheet.actor.moveItemsBetweenActors(objetId, dragData.actorId); - return false; - } - else { - // rangement - const destId = $(event.target).parents(".item").attr("data-item-id"); - const srcId = actorSheet.objetVersConteneur[objetId]; - - if (srcId != destId && objetId != destId && actorSheet.actor.isConteneurSuffisant(objetId, destId)) { - if (srcId) { - await actorSheet.actor.enleverDeConteneur(objetId, srcId); - } - if (destId) { // Dropped over an item !!! - await actorSheet.actor.ajouterAConteneur(objetId, destId); - } - } - } - } - actorSheet.actor.computeEncombrementTotalEtMalusArmure(); - } else if (dragData.type == "Actor") { - actorSheet.actor.addSubacteur(objetId); - } - return true; - } - /* -------------------------------------------- */ static buildArbreDeConteneur(actorSheet, formData) { actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant)