diff --git a/module/actor-sheet.js b/module/actor-sheet.js index c14aee91..6d12a300 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -148,16 +148,16 @@ export class RdDActorSheet extends ActorSheet { /* -------------------------------------------- */ async creerObjet() { - let itemType = $("#creer-equipement").val(); + let itemType = $(".item-type").val(); await this.actor.createOwnedItem({ name: 'Nouveau ' + itemType, type: itemType }, { renderSheet: true }); } /* -------------------------------------------- */ async selectObjetType() { - let itemType = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"]; - let options = 'Selectionnez le type d\'équipement'; - for (let typeName of itemType) { - options += '' + typeName + '' + let typeObjets = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"]; + let options = `Selectionnez le type d'équipement`; + for (let typeName of typeObjets) { + options += `${typeName}` } options += ''; let d = new Dialog({ @@ -173,7 +173,28 @@ export class RdDActorSheet extends ActorSheet { }); d.render(true); } - + + /* -------------------------------------------- */ + async selectTypeOeuvre() { + let typeOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu" ]; + let options = `Selectionnez le type d'oeuvre`; + for (let typeName of typeOeuvres) { + options += `${typeName}` + } + options += ''; + let d = new Dialog({ + title: "Créer une oeuvre", + content: options, + buttons: { + one: { + icon: '', + label: "Créer l'oeuvre", + callback: () => this.creerObjet() + } + } + }); + d.render(true); + } /* -------------------------------------------- */ /** @override */ activateListeners(html) { @@ -221,12 +242,15 @@ export class RdDActorSheet extends ActorSheet { ev.preventDefault(); } }); - html.find('#creer-tache').click(ev => { + html.find('.creer-tache').click(ev => { this.createEmptyTache(); }); - html.find('#creer-un-objet').click(ev => { + html.find('.creer-un-objet').click(ev => { this.selectObjetType(); }); + html.find('.creer-une-oeuvre').click(ev => { + this.selectTypeOeuvre(); + }); html.find('#nettoyer-conteneurs').click(ev => { this.actor.nettoyerConteneurs(); }); diff --git a/module/actor.js b/module/actor.js index 8097e01c..8817b883 100644 --- a/module/actor.js +++ b/module/actor.js @@ -171,8 +171,8 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ getReveActuel() { - const actorData = Misc.data(this); - return Misc.toInt(actorData.data.reve?.reve?.value ?? actorData.data.carac.reve.value); + const templateData = Misc.templateData(this); + return Misc.toInt(templateData.reve?.reve?.value ?? templateData.carac.reve.value); } /* -------------------------------------------- */ getChanceActuel() { @@ -1427,9 +1427,8 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async moralIncDec(ajustementMoral) { - + const actorData = Misc.data(this); if (ajustementMoral != 0) { - const actorData = Misc.data(this); let moral = Misc.toInt(actorData.data.compteurs.moral.value) + ajustementMoral if (moral > 3) { // exaltation const exaltation = Misc.toInt(actorData.data.compteurs.exaltation.value) + moral - 3; @@ -1613,6 +1612,12 @@ export class RdDActor extends Actor { return 0; } + /* -------------------------------------------- */ + appliquerExperience(rollData) { + const callback = this.createCallbackExperience(); + if (callback.condition(rollData)) { callback.action(rollData); } + } + /* -------------------------------------------- */ createCallbackExperience() { return { @@ -1683,11 +1688,11 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _appliquerAjoutExperience(rollData, display = true) { if (!this.isPersonnage()) return; - let xpResult = this.appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence); + let xpResult = await this.appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence); if (display && xpResult.result) { let xpmsg = "Points d'expérience gagnés ! Carac: " + xpResult.xpCarac + ", Comp: " + xpResult.xpCompetence; let message = { - whisher: ChatMessage.getWhisperRecipients(["GM", this.name]), + whisher: ChatUtility.getWhisperRecipientsAndGMs(this.name), content: "" + rollData.selectedCarac.label + "" + xpmsg, } ChatMessage.create(message); @@ -1948,6 +1953,32 @@ export class RdDActor extends Actor { RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html'); } + async rollCaracCompetence(caracName, compName, diff) { + const carac = this.getCaracByName(caracName); + if (!carac) { + ui.notifications.warn(`${this.name} n'a pas de caractéristique correspondant à ${caracName}`) + return; + } + const competence = this.getCompetence(compName); + if (compName && !competence) { + ui.notifications.warn(`${this.name} n'a pas de compétence correspondant à ${compName}`) + return; + } + let rollData = { + alias: this.name, + caracValue: Number(carac.value), + selectedCarac: carac, + competence: competence, + finalLevel: (competence?.data.niveau ?? 0) + diff, + diffLibre: diff, + showDice: true, + show: { title: "Jets multiples" } + }; + await RdDResolutionTable.rollData(rollData); + this.appliquerExperience(rollData); + RdDResolutionTable.displayRollData(rollData, this) + } + /* -------------------------------------------- */ async rollCompetence(name) { let rollData = { competence: this.getCompetence(name) } @@ -2249,9 +2280,9 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async chanceActuelleIncDec(value, limit = true) { - chance = Math.max(Misc.templateData(this).compteurs.chance.value + value, 0); + let chance = Math.max(Misc.templateData(this).compteurs.chance.value + value, 0); if (limit) { - chance = Math.min(chance.value, this.getChance()) + chance = Math.min(chance, this.getChance()) } await this.updateCompteurValue("chance", chance); } @@ -2262,7 +2293,7 @@ export class RdDActor extends Actor { if (destinee > 0) { ChatMessage.create({ content: `${this.name} a fait appel à la Destinée !` }); destinee--; - await this.updateCompteurValue( "destinee", destinee); + await this.updateCompteurValue("destinee", destinee); onSuccess(); } else { @@ -2313,7 +2344,7 @@ export class RdDActor extends Actor { } if (xpCarac > 0) { let carac = duplicate(Misc.templateData(this).carac); - let selectedCarac = RdDActor._findCaracByName(carac, caracName); + let selectedCarac = RdDCarac.findCarac(carac, caracName); if (!selectedCarac.derivee) { selectedCarac.xp = Misc.toInt(selectedCarac.xp) + xpCarac; await this.update({ "data.carac": carac }); @@ -2360,39 +2391,17 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - getCaracByName(caracName) { - switch (caracName) { - case 'reve-actuel': case 'Rêve actuel': - return { - label: 'Rêve actuel', - value: this.getReveActuel(), - type: "number" - }; - case 'chance-actuelle': case 'Chance actuelle': - return { - label: 'Chance actuelle', - value: this.getChanceActuel(), - type: "number" - }; - } - return RdDActor._findCaracByName(Misc.templateData(this).carac, caracName); + getCaracAndActuel() { + let caracs = { + 'reve-actuel': { label: 'Rêve actuel', value: this.getReveActuel(), type: "number" }, + 'chance-actuelle': { label: 'Chance actuelle', value: this.getChanceActuel(), type: "number" } + }; + mergeObject(caracs, Misc.templateData(this).carac); + return caracs } - /* -------------------------------------------- */ - static _findCaracByName(carac, name) { - name = name.toLowerCase(); - switch (name) { - case 'reve-actuel': case 'rêve actuel': - return carac.reve; - case 'chance-actuelle': case 'chance actuelle': - return carac.chance; - } - for (const [key, value] of Object.entries(carac)) { - if (name == key || name == value.label.toLowerCase()) { - return carac[key]; - } - } - return carac[name]; // Per default + getCaracByName(caracName) { + return RdDCarac.findCarac(this.getCaracAndActuel(), caracName); } /* -------------------------------------------- */ @@ -3070,22 +3079,20 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ _deleteStatusEffectsByIds(effectIds, options) { this.deleteEmbeddedEntity('ActiveEffect', effectIds, options); - this.applyActiveEffects(); } /* -------------------------------------------- */ - async addStatusEffectById(id, options = { renderSheet: true }) { + async addStatusEffectById(id, options = { renderSheet: false }) { const statusEffect = CONFIG.statusEffects.find(it => it.id == id); await this.addStatusEffect(statusEffect, options); } /* -------------------------------------------- */ - async addStatusEffect(statusEffect, options = { renderSheet: true }) { + async addStatusEffect(statusEffect, options = { renderSheet: false }) { this.deleteStatusEffectById(statusEffect.id, options); const effet = duplicate(statusEffect); effet["flags.core.statusId"] = effet.id; await this.createEmbeddedEntity('ActiveEffect', effet, options); - this.applyActiveEffects(); } /* -------------------------------------------- */ diff --git a/module/item-competence.js b/module/item-competence.js index a399e6fd..7f234e77 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -1,3 +1,5 @@ +import { Grammar } from "./grammar.js"; + const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], ["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"]]; @@ -61,7 +63,7 @@ export class RdDItemCompetence extends Item { return categorieCompetences; } static getNiveauBase(category) { - return categorieCompetences[category].level; + return categorieCompetences[category].base; } static getLabelCategorie(category) { return categorieCompetences[category].label; @@ -183,8 +185,20 @@ export class RdDItemCompetence extends Item { /* -------------------------------------------- */ static findCompetence(list, name) { - name = name.toLowerCase(); - return list.find(it => it.name.toLowerCase() == name && (it.type == "competence" || it.type == "competencecreature")) + name = Grammar.toLowerCaseNoAccent(name); + const competences = list.filter(it => Grammar.toLowerCaseNoAccent(it.name).includes(name) && (it.type == "competence" || it.type == "competencecreature")); + if (competences.length == 0) { + return undefined; + } + let competence = competences.find(it => Grammar.toLowerCaseNoAccent(it.name) == name); + if (competence) { + return competence; + } + if (competences.length>1) { + const names = competences.map(it => it.name).reduce((a, b) => `${a}${b}`); + ui.notifications.info(`Plusieurs compétences possibles:${names}La première sera choisie: ${competences[0].name}`); + } + return competences[0]; } /* -------------------------------------------- */ diff --git a/module/rdd-carac.js b/module/rdd-carac.js index 6dbe169c..368a8005 100644 --- a/module/rdd-carac.js +++ b/module/rdd-carac.js @@ -38,6 +38,29 @@ const tableCaracDerivee = { export class RdDCarac { + /* -------------------------------------------- */ + static findCarac(carac, name) { + name = Grammar.toLowerCaseNoAccent(name); + const pairs = Object.entries(carac) + .filter(([key, value]) => key.includes(name) || Grammar.toLowerCaseNoAccent(value.label).includes(name)); + + let c = pairs.find(([key, value]) => key == name || Grammar.toLowerCaseNoAccent(value.label) == name); + if (c) { + return c[1]; + } + + pairs.sort((a, b) => a[0].length- b[0].length); + if (pairs.length > 0) { + c = pairs[0][1]; + if (pairs.length > 1) { + const labels = pairs.map(pair => pair[1].label).reduce((a, b) => `${a}${b}`); + ui.notifications.info(`Plusieurs caractéristiques possibles:${labels}La première sera choisie: ${c.label}.`); + } + return c; + } + return undefined; + } + static isAgiliteOuDerivee(selectedCarac) { return selectedCarac?.label.match(/(Agilité|Dérobée)/); } diff --git a/module/rdd-commands.js b/module/rdd-commands.js index dddfdb2c..db0985d7 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -11,9 +11,9 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRRencontres } from "./tmr-rencontres.js"; -import { TMRType, TMRUtility } from "./tmr-utility.js"; +import { TMRUtility } from "./tmr-utility.js"; -const rddRollNumeric = /(\d+)\s*([\+\-]?\d+)?\s*(s)?/; +const rddRollNumeric = /$(\d+)\s*([\+\-]?\d+)?\s*(s)?/; /* -------------------------------------------- */ export class RdDCommands { @@ -64,9 +64,11 @@ export class RdDCommands { descr: `Effectue un jet de dés dans la table de résolution. Exemples: /rdd ouvre la table de résolution /rdd 10 3 effectue un jet 10 à +3 - /rdd 10 +2 effectue un jet 10 à +2 /rdd 15 -2 effectue un jet 15 à -2 - /rdd 15 0 s effectue un jet 15 à 0, avec significative requise` + /rdd 15 0 s effectue un jet 15 à 0, avec significative requise + /rdd Vue Vigilance -2 effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés + /rdd vol déser +2 effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés + ` }); rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); @@ -217,6 +219,27 @@ export class RdDCommands { await this.rollRdDNumeric(msg, carac, diff, significative); return; } + + let actors = canvas.tokens.controlled.map(it => it.actor).filter(it => it); + if (actors && actors.length > 0){ + let length = params.length; + let diff = Number(params[length-1]); + if (Number.isInteger(Number(diff))){ + length --; + } + else { + diff = 0; + } + const caracName = params[0]; + const compName = length>1 ? params.slice(1, length).reduce((a, b) => `${a} ${b}`): undefined; + for (let actor of actors) { + await actor.rollCaracCompetence(caracName, compName, diff); + } + return; + } + else{ + ui.notifications.warn("Sélectionnez au moins un personnage pour lancer les dés") + } } } diff --git a/module/rdd-main.js b/module/rdd-main.js index 2b7d2e43..0d030779 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -46,7 +46,8 @@ Hooks.once("init", async function () { game.system.rdd = { TMRUtility, RdDUtility, - RdDHotbar + RdDHotbar, + RdDResolutionTable } /* -------------------------------------------- */ diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 34573582..8764eb4d 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -553,7 +553,10 @@ export class RdDUtility { // Gestion du bouton payer html.on("click", '#payer-button', event => { let sumdenier = event.currentTarget.attributes['data-somme-denier'].value; - let quantite = event.currentTarget.attributes['data-quantite'].value; + let quantite = 1; + if ( event.currentTarget.attributes['data-quantite'] ) { + quantite = event.currentTarget.attributes['data-quantite'].value; + } let jsondata = event.currentTarget.attributes['data-jsondata'] let objData if (jsondata) { diff --git a/module/tmr/periple.js b/module/tmr/periple.js index feba1a2b..ae5050f7 100644 --- a/module/tmr/periple.js +++ b/module/tmr/periple.js @@ -22,7 +22,7 @@ export class Periple extends Draconique { code() { return 'periple' } - tooltip(linkData) { return `Votre Périple passe par ${this.tmrDescr(linkData)}` } + tooltip(linkData) { return `Votre Périple passe par ${this.tmrLabel(linkData)}` } img() { return 'icons/svg/acid.svg' } createSprite(pixiTMR) { diff --git a/system.json b/system.json index 87a6205c..d003b074 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", "description": "Rêve de Dragon RPG for FoundryVTT", - "version": "1.3.36", + "version": "1.3.40", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", diff --git a/templates/actor-creature-sheet.html b/templates/actor-creature-sheet.html index 599c23a8..339e7c61 100644 --- a/templates/actor-creature-sheet.html +++ b/templates/actor-creature-sheet.html @@ -200,7 +200,7 @@ {{!-- Equipment Tab --}} Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.attributs.encombrement.value}} {{calc.surEncombrementMessage}} - - Créer un objet + Créer un objet {{#if options.isGM}} - Vider tout les conteneurs {{/if}} diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index ebadca90..e3b57b5c 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -461,6 +461,7 @@ {{!-- Connaissances Tab --}} + Créer une oeuvre Oeuvres diverses : {{#each data.chants as |chant id|}} @@ -526,7 +527,7 @@ {{/each}} - TâchesCréer une nouvelle Tâche + TâchesCréer une nouvelle Tâche {{#each data.taches as |tache id|}} {{tache.name}} ({{tache.data.points_de_tache_courant}}/{{tache.data.points_de_tache}}) @@ -723,7 +724,7 @@ Estimation de l'équipement : {{numberFormat calc.prixTotalEquipement decimals=2}} Sols - Créer un objet + Créer un objet {{#if options.isGM}} - Vider tout les conteneurs {{/if}} diff --git a/templates/actor-vehicule-sheet.html b/templates/actor-vehicule-sheet.html index b63c3391..f006ba4f 100644 --- a/templates/actor-vehicule-sheet.html +++ b/templates/actor-vehicule-sheet.html @@ -69,7 +69,7 @@ {{!-- Equipment Tab --}} Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.capacite_encombrement}} {{calc.surEncombrementMessage}} - - Créer un objet + Créer un objet {{#if options.isGM}} - Vider tout les conteneurs {{/if}} diff --git a/templates/chat-resultat-sort.html b/templates/chat-resultat-sort.html index b17920a9..7eb6b543 100644 --- a/templates/chat-resultat-sort.html +++ b/templates/chat-resultat-sort.html @@ -24,6 +24,12 @@ +{{#if rolled.isETotal}} +Le sort a des effets imprévus! +{{else if rolled.isSuccess}} +{{#unless isSortReserve}} {{{selectedSort.data.description}}} +{{/unless}} +{{/if}} diff --git a/templates/item-nombreastral-sheet.html b/templates/item-nombreastral-sheet.html new file mode 100644 index 00000000..3e343898 --- /dev/null +++ b/templates/item-nombreastral-sheet.html @@ -0,0 +1,30 @@ + + + + + + + + + {{!-- Sheet Body --}} + + + Nombre + + + + Nombre valide ? + + + + Index du jour concerné + + + + Label du jour + + + + + +