diff --git a/module/actor.js b/module/actor.js index 9051a483..06dd5956 100644 --- a/module/actor.js +++ b/module/actor.js @@ -236,29 +236,35 @@ export class RdDActor extends Actor { return RdDItemCompetence.findCompetence(this.data.items, name); } /* -------------------------------------------- */ + getObjet(id) { + return id ? this.items.find(it => it._id == id) : undefined; + } + getItemOfType(type, id) { + return id ? this.data.items.find(it => it._id == id && it.type == type) : undefined; + } getTache(id) { - return this.data.items.find(item => item.type == 'tache' && item._id == id); + return this.getItemOfType(id, 'tache'); } getMeditation(id) { - return this.data.items.find(item => item.type == 'meditation' && item._id == id); + return this.getItemOfType(id, 'meditation'); } getChant(id) { - return this.data.items.find(item => item.type == 'chant' && item._id == id); + return this.getItemOfType(id, 'chant'); } getDanse(id) { - return this.data.items.find(item => item.type == 'danse' && item._id == id); + return this.getItemOfType(id, 'danse'); } getMusique(id) { - return this.data.items.find(item => item.type == 'musique' && item._id == id); + return this.getItemOfType(id, 'musique'); } getOeuvre(id, type = 'oeuvre') { - return this.data.items.find(item => item.type == type && item._id == id); + return this.getItemOfType(type, id); } getJeu(id) { - return this.data.items.find(item => item.type == 'jeu' && item._id == id); + return this.getItemOfType(id, 'jeu'); } getRecetteCuisine(id) { - return this.data.items.find(item => item.type == 'recettecuisine' && item._id == id); + return this.getItemOfType(id, 'recettecuisine'); } /* -------------------------------------------- */ getBestDraconic() { @@ -271,6 +277,7 @@ export class RdDActor extends Actor { getDemiReve() { return Misc.templateData(this).reve.tmrpos.coord; } + /* -------------------------------------------- */ async deleteSortReserve(sortReserve) { let reserve = duplicate(Misc.templateData(this).reve.reserve); @@ -768,42 +775,55 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ validateConteneur(itemId, conteneurId) { - let conteneurDest = this.items.find(conteneur => conteneurId == conteneur.id); // recup conteneur - let conteneurSrc = this.items.find(conteneur => itemId == conteneur.id && conteneur.type == 'conteneur'); - if (conteneurSrc) { // 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 conteneurSrc.data.data.contenu) { - let subObjet = this.items.find(subobj => id == subobj.id); - if (subObjet && subObjet.id == conteneurDest.id) { - ui.notifications.warn("Impossible de déplacer un conteneur parent dans son fils !"); - return false; // Loop detected ! - } - if (subObjet && subObjet.type == 'conteneur') { - return this.validateConteneur(subObjet.id, 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; } - /* -------------------------------------------- */ - getRecursiveEnc(objet) { - let sumEnc = 0; - if (objet.type == 'conteneur') { - for (let id of objet.data.data.contenu) { - let subobjet = this.items.find(objet => (id == objet.id)); - if (subobjet) { - if (subobjet && subobjet.type == 'conteneur') { - sumEnc += this.getRecursiveEnc(subobjet); - } else { - sumEnc += Number(subobjet.data.data.encombrement) * Number(subobjet.data.data.quantite); - } + _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 + for (let id of Misc.templateData(item).contenu) { + let subObjet = this.getObjet(id); + if (subObjet?.id == conteneurId) { + return true; // Loop detected ! + } + if (subObjet?.type == 'conteneur') { + return this._isConteneurContenu(subObjet, conteneurId); } } - sumEnc += Number(objet.data.data.encombrement) - } else { - sumEnc += Number(objet.data.data.encombrement) * Number(objet.data.data.quantite); } - return sumEnc; + return false; + } + + /* -------------------------------------------- */ + getRecursiveEnc(objet) { + if (!objet) { + return 0; + } + const tplData = Misc.templateData(objet); + if (objet.type != 'conteneur') { + return Number(tplData.encombrement) * Number(tplData.quantite); + } + const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getObjet(idContenu))); + return encContenus.reduce((a, b) => a + b, 0) + + 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); } /* -------------------------------------------- */ @@ -811,34 +831,39 @@ export class RdDActor extends Actor { * pour recevoir le nouvel objet */ testConteneurCapacite(itemId, conteneurId) { - if (!conteneurId) return true; // pas de conteneur (porté sur soi), donc toujours OK. - let conteneur = this.items.find(conteneur => conteneurId == conteneur.id); // recup conteneur + let conteneur = this.getObjet(conteneurId); // recup conteneur (ou undefined) //console.log("Conteneur trouvé : ", conteneur); - if (conteneur && conteneur.type == "conteneur") { - // Calculer le total actuel des contenus - let encContenu = this.getRecursiveEnc(conteneur) - Number(conteneur.data.data.encombrement); - let nouvelObjet = this.items.find(objet => (itemId == objet.id)); // On chope l'objet - let newEnc = (nouvelObjet) ? this.getRecursiveEnc(nouvelObjet) : 0; // Calculer le total actuel du nouvel objet - //console.log( currentEnc, newEnc, conteneur.data.data.capacite, conteneur.name); - if (nouvelObjet && ((encContenu + newEnc) > Number(conteneur.data.data.capacite))) { - ui.notifications.warn("Capacité d'encombrement insuffisante dans le conteneur !"); - return false; - } + 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.items.find(conteneur => conteneurId == conteneur._id); // recup conteneur - if (conteneur && conteneur.type == 'conteneur') { // Si présent - for (let subId of conteneur.data.data.contenu) { - let subObj = this.items.find(subobjet => subId == subobjet._id); // recup conteneur - if (subObj && subObj.type == 'conteneur') { - this.buildSubConteneurObjetList(subId, deleteList); - } - if (subObj) // Robust... + let conteneur = this.getObjet(conteneurId); + if (conteneur?.type == 'conteneur') { // Si c'est un conteneur + for (let subId of Misc.templateData(conteneur).contenu) { + let subObj = this.getObjet(subId); + if (subObj) { + if (subObj.type == 'conteneur') { + this.buildSubConteneurObjetList(subId, deleteList); + } deleteList.push({ id: subId, conteneurId: conteneurId }); + } } } } @@ -858,11 +883,10 @@ export class RdDActor extends Actor { /** Supprime un item d'un conteneur, sur la base * de leurs ID */ async enleverDeConteneur(itemId, conteneurId) { - if (!conteneurId) return; // pas de conteneur (porté sur soi) - let conteneur = this.items.find(conteneur => conteneurId == conteneur.id); // recup conteneur - if (conteneur) { // Si présent - let data2use = duplicate(conteneur.data); - //console.log("Suppression du conteneur1", conteneurId, itemId, conteneur.data.data.contenu); + let conteneur = this.getObjet(conteneurId); + if (conteneur?.type == 'conteneur') { // Si présent + let data2use = duplicate(Misc.data(conteneur)); + //console.log("Suppression du conteneur1", conteneurId, itemId, data2use.data.contenu); let contenu = data2use.data.contenu; let index = contenu.indexOf(itemId); while (index >= 0) { // Force cleanup, itemId is unique @@ -877,10 +901,9 @@ export class RdDActor extends Actor { /** Ajoute un item dans un conteneur, sur la base * de leurs ID */ async ajouterAConteneur(itemId, conteneurId) { - if (!conteneurId) return; // pas de conteneur (porté sur soi) - let conteneur = this.items.find(conteneur => conteneurId == conteneur.id); - if (conteneur && conteneur.data.type == 'conteneur') { - let data2use = duplicate(conteneur.data); + let conteneur = this.getObjet(conteneurId); + if (conteneur?.type == 'conteneur') { + let data2use = duplicate(Misc.data(conteneur)); data2use.data.contenu.push(itemId); await this.updateEmbeddedEntity("OwnedItem", data2use); } @@ -889,10 +912,10 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ /** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */ async nettoyerConteneurs() { - let conteneurList = this.items.filter(conteneur => conteneur.type == 'conteneur'); + let conteneurs = this.items.filter(it => it.type == 'conteneur'); let conteneurFixedList = []; - for (let conteneur of conteneurList) { - if (conteneur.data.data.contenu.length > 0) { + for (let conteneur of conteneurs) { + if (Misc.templateData(conteneur).contenu.length > 0) { conteneurFixedList.push({ _id: conteneur._id, 'data.contenu': [] }); } } @@ -1051,7 +1074,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async ajouterRefoulement(value = 1) { let refoulement = Misc.templateData(this).reve.refoulement.value + value; - let total = new Roll("1d20").evaluate( {async: false}).total; + let total = new Roll("1d20").evaluate({ async: false }).total; if (total <= refoulement) { refoulement = 0; await this.ajouterSouffle({ chat: true }); @@ -2127,7 +2150,7 @@ export class RdDActor extends Actor { async rollDanse(id) { const actorData = Misc.data(this); const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }; - const oeuvre = duplicate(this.getOeuvre(id, artData.art)); + const oeuvre = duplicate(this.getItemOfType(id, artData.art)); const selectedCarac = this._getCaracDanse(oeuvre); if (oeuvre.data.agilite) { artData.forceCarac['agilite'] = duplicate(actorData.data.carac.agilite); @@ -2149,7 +2172,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async rollMusique(id) { const artData = { art: 'musique', verbe: 'Jouer' }; - const oeuvre = duplicate(this.getOeuvre(id, artData.art)); + const oeuvre = duplicate(this.getItemOfType(id, artData.art)); await this._rollArt(artData, "ouie", oeuvre); } @@ -2181,7 +2204,7 @@ export class RdDActor extends Actor { async rollOeuvre(id) { const artData = { art: 'oeuvre', verbe: 'Interpréter' }; - const oeuvre = duplicate(this.getOeuvre(id)); + const oeuvre = duplicate(this.getItemOfType(id, artData.art)); await this._rollArt(artData, oeuvre.data.default_carac, oeuvre); } @@ -2799,14 +2822,13 @@ export class RdDActor extends Actor { || entite.isEntiteCauchemarAccordee(this)) { return true; } - - let rolled = await RdDResolutionTable.roll(this.getReveActuel(), - Number(entite.data.data.carac.niveau.value)); - const actorData = Misc.data(this); + const tplData = Misc.templateData(this); + let rolled = await RdDResolutionTable.roll(this.getReveActuel(), - Number(tplData.carac.niveau.value)); const rollData = { alias: this.name, rolled: rolled, entite: entite.name, - selectedCarac: actorData.data.carac.reve + selectedCarac: tplData.carac.reve }; if (rolled.isSuccess) { @@ -2890,7 +2912,7 @@ export class RdDActor extends Actor { if (dataObj) { dataObj.payload.data.cout = sumDenier / 100; // Mise à jour du prix en sols , avec le prix acheté dataObj.payload.data.quantite = quantite; - await this.createEmbeddedDocuments('Item',[dataObj.payload]); + await this.createEmbeddedDocuments('Item', [dataObj.payload]); msg += `
Et l'objet ${dataObj.payload.name} a été ajouté à votre inventaire.`; } } else { @@ -2958,15 +2980,8 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ listeVehicules() { - const actorData = Misc.data(this); - return this._buildActorLinksList( - actorData.data.subacteurs?.vehicules ?? [], - vehicle => { - return { - id: vehicle.id, name: vehicle.data.name, categorie: vehicle.data.data.categorie, - structure: vehicle.data.data.structure, img: vehicle.data.img - }; - }); + const listeVehichules = Misc.templateData(this).subacteurs?.vehicules ?? []; + return this._buildActorLinksList(listeVehichules, vehicle => RdDActor._vehicleData(vehicle)); } /* -------------------------------------------- */ @@ -2979,12 +2994,27 @@ export class RdDActor extends Actor { return this._buildActorLinksList(Misc.templateData(this).subacteurs?.montures ?? []); } - _buildActorLinksList(links, actorTransformation = it => { return { id: it.id, name: it.data.name, img: it.data.img }; }) { + _buildActorLinksList(links, actorTransformation = it => RdDActor._buildActorData(it)) { return links.map(link => game.actors.get(link.id)) .filter(it => it != null) .map(actorTransformation); } + static _vehicleData(vehicle) { + const vehicleData = Misc.data(vehicle); + return { + id: vehicle.id, + name: vehicleData.name, + img: vehicleData.img, + categorie: vehicleData.data.categorie, + structure: vehicleData.data.structure, + }; + } + + static _buildActorData(it) { + return { id: it.id, name: it.data.name, img: it.data.img }; + } + /* -------------------------------------------- */ async pushSubacteur(actor, dataArray, dataPath, dataName) { let alreadyPresent = dataArray.find(attached => attached.id == actor.data._id); diff --git a/module/item-sheet.js b/module/item-sheet.js index 5803f4b6..b8877907 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -124,7 +124,7 @@ export class RdDItemSheet extends ItemSheet { event.preventDefault(); let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value); - this.object.data.data.base = level; + Misc.templateData(this.object).base = level; $("#base").val( level ); } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 79ea86d7..4650e50f 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -968,7 +968,7 @@ export class RdDCombat { surprise: this.defender.getSurprise(true), needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade), needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade), - carac: this.defender.data.data.carac, + carac: Misc.templateData(this.defender).carac, show: {} }; defenderRoll.diviseurSignificative = this._getDiviseurSignificative(defenderRoll); @@ -1067,7 +1067,7 @@ export class RdDCombat { competence: competence, surprise: this.defender.getSurprise(true), surpriseDefenseur: this.defender.getSurprise(true), - carac: this.defender.data.data.carac, + carac: Misc.templateData(this.defender).carac, show: {} }; rollData.diviseurSignificative = this._getDiviseurSignificative(rollData); @@ -1252,7 +1252,7 @@ export class RdDCombat { return true; } - let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.data.data.carac.niveau.value)); + let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(Misc.templateData(this.defender).carac.niveau.value)); let message = { content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "
", diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 41f0d635..741662e8 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -256,30 +256,37 @@ export class RdDUtility { .concat(formData.potions) .concat(formData.herbes) .concat(formData.ingredients); - formData.competences = (formData.itemsByType.competence??[]).concat(formData.itemsByType.competencecreature??[]); + 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 dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop let objetId = dragData.id || dragData.data._id; console.log("DRAG", dragData); if (dragData.type == 'Item') { - if (dropID) { // Dropped over an item !!! - if (actorSheet.objetVersConteneur[objetId] != dropID && objetId != dropID) { - if (actorSheet.actor.validateConteneur(objetId, dropID) && actorSheet.actor.testConteneurCapacite(objetId, dropID)) { - await actorSheet.actor.enleverDeConteneur(objetId, actorSheet.objetVersConteneur[objetId]); - await actorSheet.actor.ajouterAConteneur(objetId, dropID); + 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); + } } } } - if (dragData.actorId && dragData.actorId != actorSheet.actor.id) { // Un acteur est à l'origine de l'item -> deplacement - console.log("Moving objects"); - actorSheet.actor.moveItemsBetweenActors(objetId, dragData.actorId); - return false; - } actorSheet.actor.computeEncombrementTotalEtMalusArmure(); } else if (dragData.type == "Actor") { actorSheet.actor.addSubacteur(objetId); @@ -540,7 +547,7 @@ export class RdDUtility { html.on("click", '#payer-button', event => { let sumdenier = event.currentTarget.attributes['data-somme-denier'].value; let quantite = 1; - if ( event.currentTarget.attributes['data-quantite'] ) { + if (event.currentTarget.attributes['data-quantite']) { quantite = event.currentTarget.attributes['data-quantite'].value; } let jsondata = event.currentTarget.attributes['data-jsondata'] @@ -643,7 +650,7 @@ export class RdDUtility { /* -------------------------------------------- */ static async confirmerSuppression(actorSheet, li) { let itemId = li.data("item-id"); - let objet = actorSheet.actor.items.find(item => item._id == itemId); + let objet = actorSheet.actor.getObjet(itemId); let msgTxt = "

Etes vous certain de vouloir supprimer cet objet ?"; let buttons = { delete: {