diff --git a/dev-notes.md b/dev-notes.md new file mode 100644 index 00000000..9816dda6 --- /dev/null +++ b/dev-notes.md @@ -0,0 +1,61 @@ +# Actor notes + +> The Actor#getData default implementation gives you the following for use in sheet rendering: + +``` + actor -> the Actor instance + data -> a cloned copy of Actor#data + items -> a cloned copy of Actor#data#items + effects -> a cloned copy of Actor#data#effects +``` + +> if all you need is a safe copy of `Actor#data`, you'll be much better off by simply defining your own function and avoiding all the wasted work that the parent class does which will slow down your sheet +```js +getData(options) { + return { + data: foundry.utils.deepClone(this.object.data) + } +} +``` + +who knows, maybe you don't even need to copy your actor data, skip the copy and it's even faster: +```js +getData(options) { + return { + data: this.object.data + } +} +``` + + +Atropos19/02/2021 +There are two recommended ways to create owned items in 0.8.0: +```js +await Item.create(itemData, {parent: actor}); +await actor.createEmbeddedDocuments("Item", itemDataArray); +``` + + +You can update an embedded item in one of two ways: +```js +//Method 1: + +const item = actor.items.get(itemId); +item.update(data); + +//Method 2: +actor.updateEmbeddedDocuments("Item", [{_id: itemId, ...}]); +``` + + +I noticed adding an ActiveEffect to an actor in code using + +```js +this.createEmbeddedDocuments('ActiveEffect', [effet], options); +this.applyActiveEffects(); +``` + +Atropos — Aujourd’hui à 14:42 +Two notes on this: +1. You don't actually need to call this.applyActiveEffects() because this will happen automatically whenever an effect is created/updated/deleted +2. If you want to suppress the automatic display of the sheet for the newly created document, you can pass options.renderSheet = false as part of your options object \ No newline at end of file diff --git a/module/actor.js b/module/actor.js index c2e5d737..457134ea 100644 --- a/module/actor.js +++ b/module/actor.js @@ -57,33 +57,33 @@ export class RdDActor extends Actor { * This overrided create() function adds initial items * Namely: Basic skills, money, * - * @param {Object} data Barebones actor data which this function adds onto. + * @param {Object} actorData Barebones actor data which this function adds onto. * @param {Object} options (Unused) Additional options which customize the creation workflow. * */ - static async create(data, options) { + static async create(actorData, options) { // Case of compendium global import - if (data instanceof Array) { - return super.create(data, options); + if (actorData instanceof Array) { + return super.create(actorData, options); } - const isPersonnage = data.type == "personnage"; + const isPersonnage = actorData.type == "personnage"; // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (data.items) { - let actor = super.create(data, options); + if (actorData.items) { + let actor = super.create(actorData, options); if (isPersonnage) { - await actor.checkMonnaiePresence(data.items); + await actor.checkMonnaiePresence(actorData.items); } return actor; } - const competences = await RdDUtility.loadCompendium(RdDItemCompetence.actorCompendium(data.type)); - data.items = competences.map(it => Misc.data(it)); + const competences = await RdDUtility.loadCompendium(RdDItemCompetence.actorCompendium(actorData.type)); + actorData.items = competences.map(it => Misc.data(it)); if (isPersonnage) { - data.items = data.items.concat(Monnaie.monnaiesData()); + actorData.items = actorData.items.concat(Monnaie.monnaiesData()); } - return super.create(data, options); + return super.create(actorData, options); } /* -------------------------------------------- */ @@ -245,8 +245,14 @@ export class RdDActor extends Actor { getObjet(id) { return id ? this.data.items.find(it => it.id == id) : undefined; } + listItemsData(type) { + return this.filterItemsData(it => it.type == type); + } + filterItemsData(filter) { + return this.data.items.map(it => Misc.data(it)).filter(filter); + } getItemOfType(id, type) { - return id ? this.data.items.find(it => it.id == id && it.type == type) : undefined; + return id ? this.data.items.find(it => it.id == id && Misc.data(it).type == type) : undefined; } getMonnaie(id) { return this.getItemOfType(id, 'monnaie'); @@ -344,7 +350,7 @@ export class RdDActor extends Actor { async _recupereChance() { // On ne récupère un point de chance que si aucun appel à la chance dans la journée if (this.getChanceActuel() < this.getChance() && !this.getFlag('foundryvtt-reve-de-dragon', 'utilisationChance')) { - await this.chanceActuelleIncDec(1); + await this.chanceActuelleIncDec(1); } // Nouveau jour, suppression du flag await this.unsetFlag('foundryvtt-reve-de-dragon', 'utilisationChance'); @@ -925,7 +931,7 @@ export class RdDActor extends Actor { // gestion conteneur/contenu if (item.conteneurId) { // l'Objet était dans un conteneur let newConteneurId = itemMap[item.conteneurId]; // Get conteneur - let newConteneur = this.data.items.find(subItem => subItem._id == newConteneurId); + let newConteneur = this.getObjet(newConteneurId); let newItemId = itemMap[item.id]; // Get newItem @@ -955,8 +961,7 @@ export class RdDActor extends Actor { async computeEncombrementTotalEtMalusArmure() { let encTotal = 0; let newMalusArmure = 0; - for (const item of this.data.items.filter(it => Misc.templateData(it).encombrement != undefined)) { - let itemData = item.data; // v0.8 normalization + for (const itemData of this.filterItemsData(it => it.data.encombrement)) { if (itemData.type == 'armure' && itemData.data.equipe) { // Armure équipée, intégration du malus armure total newMalusArmure += itemData.data.malus; } @@ -987,14 +992,10 @@ export class RdDActor extends Actor { let prixTotalEquipement = 0; // prix total de l'équipement est la somme du cout de chaque équipement multiplié par sa quantité. - for (const item of this.data.items) { - let itemData = item.data; // v0.8 normalization - if (itemData.data && itemData.data.cout != undefined) { - if (!Number(itemData.data.cout)) itemData.data.cout = 0; // Auto-fix - if (itemData.data.quantite == undefined) itemData.data.quantite = 1; // Auto-fix - if (itemData.data.cout < 0) itemData.data.cout = 0; // Auto-fix - prixTotalEquipement += Number(itemData.data.cout) * Number(itemData.data.quantite); - } + for (const itemData of this.filterItemsData(it => it?.data.cout)) { + const cout = Math.min(Number(itemData.data.cout) ?? 0, 0); + const quantite = Math.min(Number(itemData.data.quantite) ?? 1, 1); + prixTotalEquipement += cout * quantite; } // Mise à jour valeur totale de l'équipement this.prixTotalEquipement = prixTotalEquipement; @@ -1113,7 +1114,7 @@ export class RdDActor extends Actor { } buildTMRInnaccessible() { - const tmrInnaccessibles = this.data.items.filter(it => Draconique.isCaseTMR(it) && + const tmrInnaccessibles = this.filterItemsData(it => Draconique.isCaseTMR(it) && EffetsDraconiques.isInnaccessible(it)); return tmrInnaccessibles.map(it => it.data.coord); } @@ -1664,7 +1665,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async checkCompetenceXP(compName, newXP = undefined) { - let competence = RdDItemCompetence.findCompetence(this.data.items, compName); + let competence = this.getCompetence(compName); if (competence && newXP && newXP == competence.data.xp) { // Si édition, mais sans changement XP return; } @@ -1831,7 +1832,7 @@ export class RdDActor extends Actor { let addMsg = ""; let rencSpecial = this.data.items.find(item => EffetsDraconiques.isMauvaiseRencontre(item)); if (rencSpecial) { - rencSpecial = duplicate(rencSpecial); // To keep it + rencSpecial = Misc.data(rencSpecial); // To keep it if (rencSpecial.type != 'souffle') { this.deleteEmbeddedDocuments('Item', [rencSpecial._id]); // Suppression dans la liste des queues addMsg = " La queue a été supprimée de votre fiche automatiquement"; @@ -2318,7 +2319,8 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ checkDesirLancinant() { - let queue = this.data.items.filter((item) => item.name.toLowerCase().includes('lancinant')); + let queue = this.filterItemsData(it => it.type == 'queue' || it.type == 'ombre') + .filter(it => Grammar.toLowerCaseNoAccent(it.name).includes('desir lancinant')); return (queue.length > 0); } @@ -2368,7 +2370,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async ajouteNombreAstral(data) { // Gestion expérience (si existante) - data.competence = RdDItemCompetence.findCompetence(this.data.items, "astrologie"); + data.competence = this.getCompetence("astrologie"); data.selectedCarac = Misc.templateData(this).carac["vue"]; this._appliquerAjoutExperience(data); @@ -2380,7 +2382,7 @@ export class RdDActor extends Actor { await this.createEmbeddedDocuments("Item", [item]); // Suppression des anciens nombres astraux - let toDelete = this.data.items.filter(it => it.data.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); + let toDelete = this.listItemsData('nombreastral').filter(it => it.data.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); const deletions = toDelete.map(it => it._id); await this.deleteEmbeddedDocuments("Item", deletions); @@ -2443,12 +2445,12 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getSortList() { - return this.data.items.filter(it => it.data.type == "sort"); + return this.listItemsData("sort"); } /* -------------------------------------------- */ countMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente - let countMonteeLaborieuse = this.data.items.filter(it => EffetsDraconiques.isMonteeLaborieuse(it)).length; + let countMonteeLaborieuse = this.filterItemsData(it => EffetsDraconiques.isMonteeLaborieuse(it)).length; if (countMonteeLaborieuse > 0) { ChatMessage.create({ content: `Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent ${countMonteeLaborieuse} Point de Rêve de plus.`, @@ -2502,7 +2504,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ rollArme(compName, armeName = undefined) { - let arme = armeName ? this.data.items.find(it => it.name == armeName && RdDItemArme.isArme(it)) : undefined; + let arme = armeName ? this.data.items.find(it => Misc.data(it).name == armeName && RdDItemArme.isArme(it)) : undefined; let competence = this.getCompetence(compName); if (arme || armeName || (competence.type == 'competencecreature' && competence.data.iscombat)) { @@ -2915,10 +2917,10 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async effectuerTacheAlchimie(recetteId, alchimieName, alchimieData) { - let recette = this.data.items.find(item => item.type == 'recettealchimique' && item.id == recetteId); + let recette = this.getItemOfType(recetteId, 'recettealchimique'); const actorData = Misc.data(this); if (recette) { - let competence = this.data.items.find(item => item.type == 'competence' && item.name.toLowerCase() == "alchimie"); + let competence = this.getCompetence("alchimie"); let diffAlchimie = RdDAlchimie.getDifficulte(alchimieData); let rollData = { recette: recette, diff --git a/module/item-monnaie.js b/module/item-monnaie.js index 0b3224d2..4aae467b 100644 --- a/module/item-monnaie.js +++ b/module/item-monnaie.js @@ -30,7 +30,7 @@ export class Monnaie { } static filtrerMonnaies(items) { - return items.filter(it => it.type == 'monnaie'); + return items.filter(it => Misc.data(it).type == 'monnaie'); } static monnaiesManquantes(items) { diff --git a/module/item-sheet.js b/module/item-sheet.js index 229df96a..c2873161 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -73,7 +73,7 @@ export class RdDItemSheet extends ItemSheet { console.log(formData.competences); } if ( formData.type == 'recettealchimique' ) { - RdDAlchimie.processManipulation(formData.item, this.actor && this.actor.id ); + RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id ); } if ( this.actor ) { formData.isOwned = true; diff --git a/module/rdd-alchimie.js b/module/rdd-alchimie.js index 4028bc1d..4fac68ac 100644 --- a/module/rdd-alchimie.js +++ b/module/rdd-alchimie.js @@ -1,68 +1,56 @@ /* -------------------------------------------- */ import { Misc } from "./misc.js"; +const matchOperations = new RegExp(/@(\w*){([\w\-]+)}/ig); +const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i); /* -------------------------------------------- */ export class RdDAlchimie { /* -------------------------------------------- */ - static processManipulation( recette, actorId = undefined ) { + static processManipulation(recetteData, actorId = undefined) { //console.log("CALLED", recette, recette.isOwned, actorId ); - let manip = duplicate(recette.data.manipulation); - let reg1 = new RegExp(/@(\w*){([\w\-]+)}/ig); - let matchArray = manip.match( reg1 ); - if ( matchArray ) { - for( let matchStr of matchArray) { - let reg2 = new RegExp(/@(\w*){([\w\-]+)}/i); - let result = matchStr.match(reg2); + let manip = recetteData.data.manipulation; + let matchArray = manip.match(matchOperations); + if (matchArray) { + for (let matchStr of matchArray) { + let result = matchStr.match(matchOperationTerms); //console.log("RESULT ", result); - if ( result[1] && result[2]) { - let commande = Misc.upperFirst( result[1] ); - let replacement = this[`_alchimie${commande}`](recette, result[2], actorId); - manip = manip.replace( result[0], replacement); + if (result[1] && result[2]) { + let commande = Misc.upperFirst(result[1]); + let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId); + manip = manip.replace(result[0], replacement); } } } - recette.data.manipulation_update = manip; + recetteData.data.manipulation_update = manip; } /* -------------------------------------------- */ - static _alchimieCouleur( recette, couleurs, actorId ) { - let replacement - if ( actorId ) { - replacement = `couleur ${couleurs}`; + static _alchimieCouleur(recette, couleurs, actorId) { + if (actorId) { + return `couleur ${couleurs}`; } else { - replacement = `couleur ${couleurs} `; + return `couleur ${couleurs} `; } - return replacement; } /* -------------------------------------------- */ - static _alchimieConsistance( recette, consistances, actorId ) { - let replacement - if ( actorId ) { - replacement = `consistance ${consistances}`; + static _alchimieConsistance(recette, consistances, actorId) { + if (actorId) { + return `consistance ${consistances}`; } else { - replacement = `consistance ${consistances} `; + return `consistance ${consistances} `; } - return replacement; - } /* -------------------------------------------- */ - static getDifficulte( aspects ) { - let aspectsArray = aspects.split('-'); - let diff = 0; - let nbDifferent = 0; - let aspectsHash = {} - for (let colconst of aspectsArray) { - if ( aspectsHash[colconst] ){ // Deja present, augmente difficulté de 1 - diff -= 1; - } else { - nbDifferent++; - aspectsHash[colconst] = colconst; // Keep track - } + static getDifficulte(aspects) { + let elements = aspects.split('-'); + let composantes = elements.length; + let distincts = Object.keys(Misc.classifyFirst(elements, it => it)).length; + if (distincts == 1) { + composantes--; } - diff = diff - ((nbDifferent>1) ? nbDifferent : 0); // Ca doit marcher .... - return Math.min(0, diff); // Pour être sur + return Math.min(0, -composantes); } } diff --git a/module/rdd-astrologie-joueur.js b/module/rdd-astrologie-joueur.js index b1d6d45c..dd5ae006 100644 --- a/module/rdd-astrologie-joueur.js +++ b/module/rdd-astrologie-joueur.js @@ -8,50 +8,51 @@ import { Misc } from "./misc.js"; */ export class RdDAstrologieJoueur extends Dialog { - /* -------------------------------------------- */ - static async create(actor, dialogConfig) { - - let data = { nombres: this.organizeNombres( actor), - dates: game.system.rdd.calendrier.getJoursSuivants( 10 ), - etat: actor.getEtatGeneral(), - ajustementsConditions: CONFIG.RDD.ajustementsConditions, - astrologie: RdDItemCompetence.findCompetence( actor.data.items, 'Astrologie') - } - const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data); - let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 }; - if (dialogConfig.options) { - mergeObject(options, dialogConfig.options, { overwrite: true }); - } - return new RdDAstrologieJoueur(html, actor, data); - } - /* -------------------------------------------- */ - constructor(html, actor, data ) { + static async create(actor, dialogConfig) { + + let data = { + nombres: this.organizeNombres(actor), + dates: game.system.rdd.calendrier.getJoursSuivants(10), + etat: actor.getEtatGeneral(), + ajustementsConditions: CONFIG.RDD.ajustementsConditions, + astrologie: RdDItemCompetence.findCompetence(actor.data.items, 'Astrologie') + } + const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data); + let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 }; + if (dialogConfig.options) { + mergeObject(options, dialogConfig.options, { overwrite: true }); + } + return new RdDAstrologieJoueur(html, actor, data); + } + + /* -------------------------------------------- */ + constructor(html, actor, data) { let myButtons = { - saveButton: { label: "Fermer", callback: html => this.quitDialog() } - }; - + saveButton: { label: "Fermer", callback: html => this.quitDialog() } + }; + // Get all n // Common conf let dialogConf = { content: html, title: "Nombres Astraux", buttons: myButtons, default: "saveButton" }; - let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 } ; + let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 }; super(dialogConf, dialogOptions); - + this.actor = actor; this.dataNombreAstral = duplicate(data); } - + /* -------------------------------------------- */ static organizeNombres(actor) { - let itemNombres = actor.data.items.filter( (item) => item.type == 'nombreastral'); + let itemNombres = actor.listItemsData('nombreastral'); let itemFiltered = {}; - for ( let item of itemNombres) { - if ( itemFiltered[item.data.jourindex] ) { + for (let item of itemNombres) { + if (itemFiltered[item.data.jourindex]) { itemFiltered[item.data.jourindex].listValues.push(item.data.value); } else { itemFiltered[item.data.jourindex] = { - listValues: [ item.data.value ], + listValues: [item.data.value], jourlabel: item.data.jourlabel } } @@ -60,21 +61,22 @@ export class RdDAstrologieJoueur extends Dialog { } /* -------------------------------------------- */ - requestJetAstrologie( ) { - let data = { id: this.actor.data._id, - carac_vue: Misc.data(this.actor).data.carac['vue'].value, - etat: this.dataNombreAstral.etat, - astrologie: this.dataNombreAstral.astrologie, - conditions: $("#diffConditions").val(), - date: $("#joursAstrologie").val() - } - if ( game.user.isGM) { - game.system.rdd.calendrier.requestNombreAstral( data ); + requestJetAstrologie() { + let data = { + id: this.actor.data._id, + carac_vue: Misc.data(this.actor).data.carac['vue'].value, + etat: this.dataNombreAstral.etat, + astrologie: this.dataNombreAstral.astrologie, + conditions: $("#diffConditions").val(), + date: $("#joursAstrologie").val() + } + if (game.user.isGM) { + game.system.rdd.calendrier.requestNombreAstral(data); } else { game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_request_nombre_astral", - data: data - } ); + data: data + }); } this.close(); } @@ -87,7 +89,7 @@ export class RdDAstrologieJoueur extends Dialog { /* -------------------------------------------- */ activateListeners(html) { super.activateListeners(html); - + $(function () { $("#diffConditions").val(0); }); diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 6ca2da0a..0827d520 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -199,7 +199,7 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ syncPlayerTime(calendrier) { this.calendrier = duplicate(calendrier); // Local copy update - this.updateDisplay(); // Then update + this.updateDisplay(); } /* -------------------------------------------- */ @@ -247,21 +247,19 @@ export class RdDCalendrier extends Application { console.log(request); let jourDiff = this.getLectureAstrologieDifficulte(request.date); let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat); - let rolled = await RdDResolutionTable.rollData({ + let rollData= { caracValue: request.carac_vue, finalLevel: niveau, showDice: false - }); + }; + await RdDResolutionTable.rollData(rollData); let nbAstral = this.getNombreAstral(request.date); - let nbAstralFaux = nbAstral; + request.rolled = rollData.rolled; request.isValid = true; - request.rolled = rolled; - if (!rolled.isSuccess) { + if (!request.rolled.isSuccess) { request.isValid = false; - while (nbAstralFaux == nbAstral) { - nbAstralFaux = new Roll("1d12").evaluate( { async: false} ).total; - } - nbAstral = nbAstralFaux; + let nbAstralFaux = new Roll("1d11").evaluate( { async: false} ).total; + nbAstral = nbAstral==nbAstralFaux ? 12 : nbAstralFaux; // Mise à jour des nombres astraux du joueur let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date); astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstralFaux }); @@ -338,7 +336,7 @@ export class RdDCalendrier extends Application { if (game.user.isGM) { dateHTML = dateHTML + " - NA: " + this.getCurrentNombreAstral(); } - for (let handle of document.getElementsByClassName("calendar-move-handle")) { + for (let handle of document.getElementsByClassName("calendar-date-rdd")) { handle.innerHTML = dateHTML; } for (let heure of document.getElementsByClassName("calendar-heure-texte")) { diff --git a/styles/simple.css b/styles/simple.css index 8f14b3aa..7b875ce2 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -1093,12 +1093,7 @@ ul, li { .calendar-date-rdd { font-family: "GoudyAcc"; color: #CCC; - font-weight: bold; - font-size: 1.10rem; opacity: 90; -} -#calendar-move-handle { - font-family: "GoudyAcc"; font-size: 13px; line-height: 1; text-align: center; diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 47bf86d4..149670f2 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -461,8 +461,19 @@ {{!-- Connaissances Tab --}}