From 0a3f578bf3d7ae540d7a2c8008ca87dfcfeaf611 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 2 Jan 2021 04:28:43 +0100 Subject: [PATCH] #42 Tchat message fin parade, esquive inclus deterioration arme de parade inclus recul sous le choc --- module/actor.js | 43 ++-- module/item-arme.js | 44 +++- module/rdd-combat.js | 247 ++++++++++------------- module/rdd-commands.js | 6 +- module/rdd-resolution-table.js | 91 ++++----- module/rdd-roll-resolution.js | 6 +- module/rdd-roll.js | 1 + module/rdd-utility.js | 2 + packs/equipement.db | 9 +- system.json | 2 +- templates/chat-resultat-appelchance.html | 16 +- templates/chat-resultat-attaque.html | 80 ++++---- templates/chat-resultat-competence.html | 23 +-- templates/chat-resultat-esquive.html | 50 +++++ templates/chat-resultat-general.html | 21 +- templates/chat-resultat-parade.html | 63 ++++++ templates/chat-resultat-rdd.html | 30 --- templates/chat-resultat-sort.html | 15 +- templates/chat-resultat-tache.html | 16 +- 19 files changed, 428 insertions(+), 337 deletions(-) create mode 100644 templates/chat-resultat-esquive.html create mode 100644 templates/chat-resultat-parade.html delete mode 100644 templates/chat-resultat-rdd.html diff --git a/module/actor.js b/module/actor.js index ee98948b..86ed59b0 100644 --- a/module/actor.js +++ b/module/actor.js @@ -204,6 +204,7 @@ export class RdDActor extends Actor { getEncombrementTotal() { return this.encTotal ? Math.floor(this.encTotal) : 0 } + /* -------------------------------------------- */ async deleteSortReserve(sortReserve) { let reserve = duplicate(this.data.data.reve.reserve); @@ -212,13 +213,18 @@ export class RdDActor extends Actor { let newTable = []; for( i=0; i < len; i++) { if (reserve.list[i].coord != sortReserve.coord && reserve.list[i].sort.name != sortReserve.sort.name ) - newTable.push(reserve.list[i]); + newTable.push(reserve.list[i]); } if ( newTable.length != len ) { reserve.list = newTable; await this.update( {"data.reve.reserve": reserve } ); } } + + /* -------------------------------------------- */ + getDiviseurSignificative() { + return this.getSurprise() == 'demi' ? 2 : 1; + } /* -------------------------------------------- */ getSurprise() { @@ -1512,8 +1518,7 @@ export class RdDActor extends Actor { this.currentTMR.maximize(); // Re-display TMR } // Final chat message - let chatOptions = { content: await RdDResolutionTable.explainRollDataV2(rollData, 'chat-resultat-sort.html') } - ChatUtility.chatWithRollMode(chatOptions, this.name) + await RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-sort.html'); if (myReve.value == 0) { // 0 points de reve ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); @@ -1525,7 +1530,7 @@ export class RdDActor extends Actor { async rollCarac( caracName ) { let rollData = { selectedCarac: this.getCaracByName(caracName), - needSignificative : !this.isEntiteCauchemar() && this.data.data.sante.sonne.value + diviseur : this.getDiviseurSignificative() }; const dialog = await RdDRoll.create(this, rollData, @@ -1535,7 +1540,7 @@ export class RdDActor extends Actor { label: 'Jet ' + Grammar.apostrophe('de', rollData.selectedCarac.label), callbacks: [ this.createCallbackExperience(), - { action: this._rollCaracResult } + { action: this._onRollCaracResult } ] } ); @@ -1543,22 +1548,16 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async _rollCaracResult(rollData) { - rollData.show = { - title: rollData.selectedCarac.label, - points: true - }; + async _onRollCaracResult(rollData) { // Final chat message - let chatOptions = { content: await RdDResolutionTable.explainRollDataV2(rollData) } - - ChatUtility.chatWithRollMode(chatOptions, this.name) + await RdDResolutionTable.displayRollData(rollData, this.name); } /* -------------------------------------------- */ async rollCompetence( name ) { let rollData = { competence: this.getCompetence(name), - needSignificative : !this.isEntiteCauchemar() && this.data.data.sante.sonne.value + diviseur : this.getDiviseurSignificative() } if (rollData.competence.type == 'competencecreature') { @@ -1611,7 +1610,7 @@ export class RdDActor extends Actor { competence.data.defaut_carac = tache.data.carac; // Patch ! let rollData = { competence: competence, - needSignificative : this.data.data.sante.sonne.value, + diviseur : this.getDiviseurSignificative(), tache: tache, diffConditions: tache.data.difficulte, editLibre: false, @@ -1642,9 +1641,7 @@ export class RdDActor extends Actor { this.updateEmbeddedEntity( "OwnedItem", rollData.tache); this.santeIncDec( "fatigue", rollData.tache.data.fatigue); - ChatUtility.chatWithRollMode({ - content: await RdDResolutionTable.explainRollDataV2(rollData, 'chat-resultat-tache.html') - }, this.name); + RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-tache.html'); } /* -------------------------------------------- */ @@ -1655,10 +1652,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _competenceResult(rollData) { - rollData.show = {points:true}; - ChatUtility.chatWithRollMode({ - content: await RdDResolutionTable.explainRollDataV2(rollData, 'chat-resultat-competence.html') - }, this.name); + RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-competence.html') } /* -------------------------------------------- */ @@ -1682,6 +1676,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async _appelChanceResult(rollData) { + // TODO: const message = { user: game.user._id, alias: this.name, @@ -1693,9 +1688,7 @@ export class RdDActor extends Actor { } ChatMessage.create(message); - ChatUtility.chatWithRollMode({ - content: await RdDResolutionTable.explainRollDataV2(rollData, 'chat-resultat-appelchance.html') - }, this.name); + RdDResolutionTable.displayRollData(rollData, this.name, 'chat-resultat-appelchance.html') } /* -------------------------------------------- */ diff --git a/module/item-arme.js b/module/item-arme.js index e0490e15..4d01b10d 100644 --- a/module/item-arme.js +++ b/module/item-arme.js @@ -1,4 +1,19 @@ + +const nomCcategorieParade = { + "sans-armes": "Sans arme / armes naturelles", + "hast": "Armes d'hast", + "batons": "Bâtons", + "boucliers": "Boucliers", + "dagues": "Dagues", + "epees-courtes": "Epées courtes", + "epees-longues": "Epées longues", + "epees-lourdes": "Epées lourdes", + "haches": "Haches", + "lances": "Lances", +} + + export class RdDItemArme extends Item { /* -------------------------------------------- */ @@ -20,6 +35,12 @@ export class RdDItemArme extends Item { return armeData; } + /* -------------------------------------------- */ + static getNomCategorieParade(it) { + const categorie = it.data? RdDItemArme.getCategorieParade(it) : it; + return nomCcategorieParade[categorie]; + } + /* -------------------------------------------- */ static getCategorieParade(arme) { if (arme.data.categorie_parade) { @@ -56,33 +77,34 @@ export class RdDItemArme extends Item { return 'sans-armes'; } - /* -------------------------------------------- */ - static isArmeParade(arme) { - return RdDItemArme.getCategorieParade(arme); - } - /* -------------------------------------------- */ static needParadeSignificative(armeAttaque, armeParade) { + // categories d'armes à la parade (cf. page 115 ) let attCategory = RdDItemArme.getCategorieParade(armeAttaque); let defCategory = RdDItemArme.getCategorieParade(armeParade); // bouclier et mêmes catégorie: peuvent se parer sans difficulté - if (defCategory == 'bouclier') { + if (defCategory == 'boucliers') { return false; } - if (attCategory == defCategory) { + // Parer avec une hache ou une arme d’hast exige toujours une signi$cative + if (defCategory.match(/(hast|haches)/)) { + return true; + } + if (defCategory == attCategory) { return false; } // les épées se parent entre elles - if (attCategory.match(/epees-/) && defCategory.match(/epees-/)) { + if (defCategory.match(/epees-/) && attCategory.match(/epees-/)) { return false; } - if (attCategory == 'dagues' && defCategory == 'epees-courtes') { + // l'épée gnome pare la dague + if (defCategory == 'epees-courtes' && attCategory == 'dagues') { return false; } - if (attCategory.match(/epees-(courtes|legeres)/) && defCategory == 'dagues') { + // la dague pare les épées courtes et légères + if (defCategory == 'dagues' && attCategory.match(/epees-(courtes|legeres)/)) { return false; } - // Manage weapon categories when parrying (cf. page 115 ) return true; } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 55bc810d..4f712223 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -18,7 +18,9 @@ export class RdDCombat { static createUsingTarget(attacker) { const target = RdDCombat.getTarget(); if (target == undefined) { - ui.notifications.warn("Vous devez choisir une seule cible à attaquer!"); + ui.notifications.warn((game.user.targets && game.user.targets.size > 1) + ? "Vous devez choisir une seule cible à attaquer!" + : "Vous devez choisir une cible à attaquer!"); } const defender = target ? target.actor : undefined; const defenderTokenId = target ? target.data._id : undefined; @@ -124,7 +126,6 @@ export class RdDCombat { /* -------------------------------------------- */ static isEchec(rollData) { switch (rollData.surprise) { - case 'demi': return !rollData.rolled.isSign; case 'totale': return true; } return rollData.rolled.isEchec; @@ -132,7 +133,7 @@ export class RdDCombat { /* -------------------------------------------- */ static isEchecTotal(rollData) { - if (rollData.arme && rollData.surprise == 'demi') { + if (!rollData.attackerRoll && rollData.surprise) { return rollData.rolled.isEchec; } return rollData.rolled.isETotal; @@ -140,7 +141,7 @@ export class RdDCombat { /* -------------------------------------------- */ static isParticuliere(rollData) { - if (rollData.arme && rollData.surprise) { + if (!rollData.attackerRoll && rollData.surprise) { return false; } return rollData.rolled.isPart; @@ -149,7 +150,6 @@ export class RdDCombat { /* -------------------------------------------- */ static isReussite(rollData) { switch (rollData.surprise) { - case 'demi': return rollData.rolled.isSign; case 'totale': return false; } return rollData.rolled.isSuccess; @@ -216,7 +216,7 @@ export class RdDCombat { if (rollData.selectedCarac.label == "Mêlée" && rollData.diffLibre < 0) { message += `
Attaquer en Rapidité -
Attaquer en Finesse"; +
Attaquer en Finesse ` } game.system.rdd.rollDataHandler[this.attackerId] = rollData; @@ -237,9 +237,7 @@ export class RdDCombat { cible: this.target ? this.defender.data.name : 'la cible', isRecul: (rollData.particuliereAttaque == 'force' || rollData.tactique == 'charge') } - ChatUtility.chatWithRollMode( - { content: await RdDResolutionTable.explainRollDataV2(rollData, 'chat-resultat-attaque.html') }, - this.name) + await RdDResolutionTable.displayRollData(rollData, this.attacker.name, 'chat-resultat-attaque.html'); if (!await this.accorderEntite('avant-defense')) { return; @@ -267,7 +265,7 @@ export class RdDCombat { if (this.defender.getSurprise() != 'totale') { // parades - for (const arme of this._filterArmesParade(this.defender.data.items, rollData.competence.data.categorie)) { + for (const arme of this._filterArmesParade(this.defender.data.items, rollData.competence, rollData.arme)) { message += "
Parer avec " + arme.name + ""; } // corps à corps @@ -288,18 +286,24 @@ export class RdDCombat { } /* -------------------------------------------- */ - _filterArmesParade(items, categorie) { - switch (categorie) { + _filterArmesParade(items, competence) { + switch (competence.data.categorie) { case 'tir': case 'lancer': return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers') default: + // Le fléau ne peut être paré qu’au bouclier p115 + if (competence.name == "Fléau"){ + return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers') + } return items.filter(item => RdDItemArme.getCategorieParade(item)); } } /* -------------------------------------------- */ async _onAttaqueEchecTotal(rollData) { + // TODO: remplacer par un chat message pour laisser le joueur choisir un appel à la chance _avant_ + // https://gitlab.com/LeRatierBretonnien/foundryvtt-reve-de-dragon/-/issues/85 console.log("RdDCombat.onEchecTotal >>>", rollData); let chatOptions = { content: "Echec total à l'attaque! " @@ -308,15 +312,12 @@ export class RdDCombat { ChatUtility.chatWithRollMode(chatOptions, this.attacker.name) } + /* -------------------------------------------- */ - _onAttaqueEchec(rollData) { + async _onAttaqueEchec(rollData) { console.log("RdDCombat.onAttaqueEchec >>>", rollData); - let chatOptions = { - content: "Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "" - + RdDResolutionTable.explainRollData(rollData) - + (this.target ? "
Cible : " + this.defender.data.name : "") - } - ChatUtility.chatWithRollMode(chatOptions, this.attacker.name) + await RdDResolutionTable.displayRollData(rollData, this.attacker.name, 'chat-resultat-attaque.html'); + } /* -------------------------------------------- */ @@ -328,8 +329,7 @@ export class RdDCombat { /* -------------------------------------------- */ async parade(attackerRoll, armeParadeId) { - - let arme = this._findArmeParade(armeParadeId); + let arme = RdDItemArme.getArmeData(armeParadeId ? this.defender.getOwnedItem(armeParadeId) : null); console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme); @@ -353,32 +353,23 @@ export class RdDCombat { dialog.render(true); } - _findArmeParade(armeParadeId) { - return RdDItemArme.getArmeData(armeParadeId ? this.defender.getOwnedItem(armeParadeId) : null); - } - _prepareParade(attackerRoll, armeParade) { const isCreature = this.defender.isCreature(); const compName = armeParade.data.competence; - const competence = this.defender.getCompetence(compName); const armeAttaque = attackerRoll.arme; - if (compName != competence.name) { - // TODO: toujours utiliser competence.name ... - ui.notifications.warn("Différence entre compétence " + competence.name + " et compétence de l'arme " + compName); - } - let rollData = { forceValue: this.defender.getForceValue(), diffLibre: attackerRoll.diffLibre, attackerRoll: attackerRoll, - competence: competence, + competence: this.defender.getCompetence(compName), arme: armeParade, surprise: this.defender.getSurprise(), - surpriseDefenseur: this.defender.getSurprise(), - needSignificative: this._needSignificative(attackerRoll) || RdDItemArme.needParadeSignificative(armeAttaque, armeParade), - needResist: this._needResist(armeAttaque, armeParade), - carac: this.defender.data.data.carac + needParadeSignificative: this.needParadeSignificative(attackerRoll, armeParade), + diviseur: this._getDiviseurSignificative(attackerRoll, armeParade), + needResist: this._needArmeResist(armeAttaque, armeParade), + carac: this.defender.data.data.carac, + show: {} }; if (isCreature) { RdDItemCompetence.setRollDataCreature(rollData); @@ -387,12 +378,29 @@ export class RdDCombat { } /* -------------------------------------------- */ - _needSignificative(attackerRoll) { - return attackerRoll.particuliereAttaque == 'finesse'; + _getDiviseurSignificative(attackerRoll, armeParade = undefined) { + let facteurSign = this.defender.getDiviseurSignificative(); + if (RdDCombat.isAttaqueFinesse(attackerRoll)) { + facteurSign *= 2; + } + if (this.needParadeSignificative(attackerRoll, armeParade)) { + facteurSign *= 2; + } + return Math.min(4, facteurSign); + + } + + static isAttaqueFinesse(attackerRoll) { + return attackerRoll && attackerRoll.particuliereAttaque == 'finesse'; + } + + needParadeSignificative(attackerRoll, armeParade) { + return attackerRoll.arme && armeParade && + RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade); } /* -------------------------------------------- */ - _needResist(armeAttaque, armeParade) { + _needArmeResist(armeAttaque, armeParade) { // Epées parant une arme de bois (cf. page 115 ), une résistance est nécessaire let attCategory = RdDItemArme.getCategorieParade(armeAttaque); let defCategory = RdDItemArme.getCategorieParade(armeParade); @@ -405,29 +413,27 @@ export class RdDCombat { console.log("RdDCombat._onParadeParticuliere >>>", rollData); if (!rollData.attackerRoll.isPart) { // TODO: attaquant doit jouer résistance et peut être désarmé p132 + ChatUtility.chatWithRollMode({ + content: `L'attaquant doit jouer résistance et peut être désarmé (p132)` + }, this.defender.name) } - let chatOptions = { - content: "Vous pouvez utiliser votre arme pour une deuxième parade!" - } - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) } /* -------------------------------------------- */ async _onParadeNormale(rollData) { console.log("RdDCombat._onParadeNormale >>>", rollData); - let chatOptions = { - content: "Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "" - + RdDResolutionTable.explainRollData(rollData) - + "
Attaque parée!" - } - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) - await this.computeRecul(rollData, false); + await this.computeRecul(rollData); await this.computeDeteriorationArme(rollData); + + await RdDResolutionTable.displayRollData(rollData, this.defender.name, 'chat-resultat-parade.html'); + } /* -------------------------------------------- */ async _onParadeEchecTotal(rollData) { + // TODO: remplacer par un chat message pour laisser le joueur choisir un appel à la chance _avant_ + // https://gitlab.com/LeRatierBretonnien/foundryvtt-reve-de-dragon/-/issues/85 console.log("RdDCombat._onParadeEchecTotal >>>", rollData); let chatOptions = { content: "Echec total à la parade! " @@ -440,24 +446,11 @@ export class RdDCombat { async _onParadeEchec(rollData) { console.log("RdDCombat._onParadeEchec >>>", rollData); - let explications = "
Parade échouée, encaissement ! "; - explications += RdDBonus.description(rollData.surprise); - if (rollData.needSignificative) { - explications += " Significative nécessaire!"; - } + await this.computeRecul(rollData); - let chatOptions = { - content: "Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "" - + RdDResolutionTable.explainRollData(rollData) - + explications - } + await RdDResolutionTable.displayRollData(rollData, this.defender.name, 'chat-resultat-parade.html'); - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) - - await this.computeRecul(rollData, true); - // TODO: gestion message pour chance/encaissement this._sendMessageEncaisser(rollData.attackerRoll); - } /* -------------------------------------------- */ @@ -494,8 +487,9 @@ export class RdDCombat { competence: competence, surprise: this.defender.getSurprise(), surpriseDefenseur: this.defender.getSurprise(), - needSignificative: this._needSignificative(attackerRoll), - carac: this.defender.data.data.carac + diviseur: this._getDiviseurSignificative(attackerRoll), + carac: this.defender.data.data.carac, + show: {} }; if (this.defender.isCreature()) { @@ -508,24 +502,22 @@ export class RdDCombat { _onEsquiveParticuliere(rollData) { console.log("RdDCombat._onEsquiveParticuliere >>>", rollData); let chatOptions = { - content: "Vous pouvez esquiver une deuxième attaque!" + content: "Vous pouvez esquiver une deuxième esquive!" } ChatUtility.chatWithRollMode(chatOptions, this.defender.name) } /* -------------------------------------------- */ - _onEsquiveNormale(rollData) { + async _onEsquiveNormale(rollData) { console.log("RdDCombat._onEsquiveNormal >>>", rollData); - let chatOptions = { - content: "Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "" - + RdDResolutionTable.explainRollData(rollData) - + "
Attaque esquivée!" - } - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) + + await RdDResolutionTable.displayRollData(rollData, this.defender.name, 'chat-resultat-esquive.html'); } /* -------------------------------------------- */ async _onEsquiveEchecTotal(rollData) { + // TODO: remplacer par un chat message pour laisser le joueur choisir un appel à la chance _avant_ + // https://gitlab.com/LeRatierBretonnien/foundryvtt-reve-de-dragon/-/issues/85 console.log("RdDCombat._onEsquiveEchecTotal >>>", rollData); let chatOptions = { content: "Echec total à l'esquive'! " @@ -537,32 +529,23 @@ export class RdDCombat { async _onEsquiveEchec(rollData) { console.log("RdDCombat._onEsquiveEchec >>>", rollData); - let explications = "
Esquive échouée, encaissement ! "; - explications += RdDBonus.description(rollData.surprise); - if (rollData.needSignificative) { - explications += " Significative nécessaire!"; - } + await this.computeRecul(rollData); - let chatOptions = { - content: "Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "" - + RdDResolutionTable.explainRollData(rollData) - + explications - } + await RdDResolutionTable.displayRollData(rollData, this.defender.name, 'chat-resultat-esquive.html'); - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) - - await this.computeRecul(rollData, true); this._sendMessageEncaisser(rollData.attackerRoll); } - /* -------------------------------------------- */ async computeDeteriorationArme(rollData) { const attackerRoll = rollData.attackerRoll; - if (rollData.arme && attackerRoll) { // C'est une parade - // Est-ce que l'attaque est une particulière, en force ou charge et que l'attaque n'en est pas une ? - if ((rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.tactique == 'charge') - && !rollData.rolled.isPart) { + // Est-ce une parade normale? + if (rollData.arme && attackerRoll && !rollData.rolled.isPart) { + // Est-ce que l'attaque est une particulière en force ou une charge + if (rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.tactique == 'charge') { + + rollData.show = rollData.show || {} + const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor; let resistance = Misc.toInt(rollData.arme.data.resistance); let msg = ""; @@ -572,72 +555,66 @@ export class RdDCombat { finalLevel: - dmg, showDice: false }); - if (resistRoll.isSuccess) { // Perte de résistance - msg = "Votre " + rollData.arme.name + " tient le choc de la parade. " + if (resistRoll.rolled.isSuccess) { // Perte de résistance + rollData.show.deteriorationArme = 'resiste'; } else { resistance -= dmg; if (resistance <= 0) { this.defender.deleteEmbeddedEntity("OwnedItem", rollData.arme._id); - msg = "Sous la violence de la parade, votre " + rollData.arme.name + " s'est brisée sous le coup!"; + rollData.show.deteriorationArme = 'brise'; } else { this.defender.updateEmbeddedEntity("OwnedItem", { _id: rollData.arme._id, 'data.resistance': resistance }); - msg = "En parant, vous endommagez votre " + rollData.arme.name + ", qui perd " + dmg + " de résistance. "; + rollData.show.deteriorationArme = 'perte'; + rollData.show.perteResistance = dmg; } } - // Jet de désarmement - if (resistance > 0 && !rollData.arme.name.toLowerCase().includes('bouclier')) { // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) + // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) + if (resistance > 0 && !RdDItemArme.getCategorieParade(rollData.arme) == 'boucliers') { let desarme = await RdDResolutionTable.rollData({ caracValue: this.defender.data.data.carac.force.value, finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg, showDice: false }); - if (desarme.isEchec) { - msg += "Vous ne parvenez pas à garder votre arme en main, elle tombe au sol à vos pieds"; + rollData.show.desarme = desarme.rolled.isEchec; + if (desarme.rolled.isEchec) { + rollData.show.desarme = true; } } - ChatMessage.create({ - content: msg, - user: game.user._id, - whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM")] - }); } } } /* -------------------------------------------- */ - async computeRecul(rollData, encaisser = undefined) { // Calcul du recul (p. 132) - if (rollData.arme || encaisser) { - if ((rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.tactique == 'charge') { - let reculNiveau = Misc.toInt(this.defender.data.data.carac.taille.value) - (rollData.attackerRoll.forceValue + rollData.attackerRoll.arme.data.dommagesReels); - let recul = await RdDResolutionTable.rollData({ - caracValue: 10, - finalLevel: reculNiveau, - showDice: false - }); + async computeRecul(rollData) { // Calcul du recul (p. 132) + const attaque = rollData.attackerRoll; + if (this._isAttaqueCauseRecul(attaque)) { - let msg = ""; - if (recul.isSuccess) { - msg = " Vous ne reculez pas malgré la force du coup."; - } else { - let chute = await RdDResolutionTable.rollData({ - caracValue: this.defender.data.data.carac.agilite.value, - finalLevel: reculNiveau, - showDice: false - }); - if (!chute.isSuccess || recul.isETotal) { - msg = "Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round."; - } else { - msg = "La violence du choc vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round."; - } - } - ChatMessage.create({ - content: msg, - user: game.user._id, - whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM")] - }); + let impactRecul = this._computeImpactRecul(attaque); + const agilite = this.defender.data.data.carac.agilite.value; + + let rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impactRecul, showDice: false }); + + if (rollRecul.isSuccess) { + rollData.show.recul = 'encaisse'; + } else if (rollRecul.isETotal) { + rollData.show.recul = 'chute'; + } + else { + let chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impactRecul, showDice: false }); + rollData.show.recul = (chute.isSuccess) + ? 'recul' + : 'chute'; } } } + _isAttaqueCauseRecul(attaque) { + return attaque.particuliereAttaque == 'force' || attaque.tactique == 'charge'; + } + + _computeImpactRecul(attaque) { + return Misc.toInt(this.defender.data.data.carac.taille.value) - (attaque.forceValue + attaque.arme.data.dommagesReels); + } + /* -------------------------------------------- */ _sendMessageEncaisser(rollData) { let message = "" + this.defender.name + " doit:" + this._buildMessageEncaisser(rollData); diff --git a/module/rdd-commands.js b/module/rdd-commands.js index f85ac974..f5808330 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -187,11 +187,11 @@ export class RdDCommands { caracValue: carac, finalLevel: diff, showDice: true, - needSignificative: significative, - show: { title: "Table de résolution", points: true } + diviseur: significative ? 2 : 1, + show: { title: "Table de résolution" } }; await RdDResolutionTable.rollData(rollData); - msg.content = await RdDResolutionTable.explainRollDataV2(rollData); + msg.content = await RdDResolutionTable.buildRollDataHtml(rollData); ChatUtility.chatWithRollMode(msg, game.user.name); } diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index 3183cec0..a9a43544 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -1,6 +1,10 @@ +import { ChatUtility } from "./chat-utility.js"; +import { RdDItemArme } from "./item-arme.js"; import { Misc } from "./misc.js"; import { RdDBonus } from "./rdd-bonus.js"; +import { RdDCombat } from "./rdd-combat.js"; import { RdDDice } from "./rdd-dice.js"; +import { RdDRollTables } from "./rdd-rolltables.js"; /** * difficultés au delà de -10 @@ -82,25 +86,30 @@ export class RdDResolutionTable { static explain(rolled) { let message = "
Jet : " + rolled.roll + " sur " + rolled.score + "% "; if (rolled.caracValue != null && rolled.finalLevel != null) { - message += (rolled.needSignificative ? "(significative sur " : "(") + message += (rolled.diviseur > 1 ? `(1/${rolled.diviseur} de ` : "(") + rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") "; } message += '' + rolled.quality + '' return message; } - static async explainRollDataV2(rollData, template = 'chat-resultat-general.html') { + static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') { rollData.ajustements = RdDResolutionTable._buildAjustements(rollData); rollData.show = rollData.show || {}; - let html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData); - return html; + return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData); + } + + static async displayRollData(rollData, userName, template = 'chat-resultat-general.html') { + + let html = await RdDResolutionTable.buildRollDataHtml(rollData, template); + ChatUtility.chatWithRollMode({ content: html }, userName) } static _buildAjustements(rollData) { let list = []; if (rollData.competence) { - list.push({ label: rollData.competence.name, value: rollData.competence.data.niveau}); + list.push({ label: rollData.competence.name, value: rollData.competence.data.niveau }); } if (rollData.tactique) { const surprise = RdDBonus.find(rollData.tactique); @@ -124,64 +133,61 @@ export class RdDResolutionTable { list.push({ label: 'Moral', value: rollData.selectedCarac != undefined && rollData.moral != undefined && rollData.selectedCarac.label == 'Volonté' ? rollData.moral : undefined }); } if (RdDResolutionTable.isAjustementAstrologique(rollData)) { - list.push({ label: 'Astrologique', value: rollData.ajustementAstrologique||0 }); + list.push({ label: 'Astrologique', value: rollData.ajustementAstrologique || 0 }); } if (rollData.rolled.bonus && rollData.selectedSort) { - list.push({ label: 'Bonus de case', value: rollData.rolled.bonus, unit: '%' }); + list.push({ descr: `Bonus de case: ${rollData.rolled.bonus}%` }); + } + if (rollData.diviseur > 1) { + list.push({ descr: `Facteur significative ×${RdDResolutionTable._getFractionHtml(rollData.diviseur)}` }); + } + if (RdDCombat.isAttaqueFinesse(rollData.attackerRoll)) { + list.push({ descr: 'Attaque particulière en finesse' }); + } + if (rollData.needParadeSignificative) { + const catAttaque = RdDItemArme.getNomCategorieParade(rollData.attackerRoll.arme); + const catParade = RdDItemArme.getNomCategorieParade(rollData.arme); + list.push({ descr: `${catAttaque} vs ${catParade}` }); + } + if (rollData.surprise) { + list.push({ descr: RdDBonus.find(rollData.surprise).descr }); } return list; } - - static explainRollData(rollData) { - let parts = RdDResolutionTable._buildAjustementsList(rollData); - let message = parts.length > 0 ? "
Difficulté " + parts.reduce((a, b) => a + ' / ' + b) : ""; - - return message+ RdDResolutionTable.explain(rollData.rolled) - } - - - static _buildAjustementsList(rollData) { - let parts = []; - if (rollData.diffLibre != undefined) { - parts.push(`libre: ${rollData.diffLibre}`); + static _getFractionHtml(diviseur) { + if (!diviseur || diviseur <= 1) return undefined; + switch (diviseur || 1) { + case 2: return '½'; + case 4: return '¼'; + default: return '1/' + diviseur; } - if (rollData.diffConditions != undefined) { - parts.push(`conditions: ${Misc.toSignedString(rollData.diffConditions)}`); - } - if (rollData.etat != undefined) { - parts.push(`état: ${rollData.etat}`); - } - if (rollData.selectedCarac != undefined && rollData.moral != undefined && rollData.selectedCarac.label == 'Volonté') { - parts.push(`moral: ${rollData.moral}`); - } - return parts; } /* -------------------------------------------- */ static async rollData(rollData) { - rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData.bonus, rollData.needSignificative, rollData.showDice); + rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData.bonus, rollData.diviseur, rollData.showDice); return rollData; } /* -------------------------------------------- */ - static async roll(caracValue, finalLevel, bonus = undefined, needSignificative = undefined, showDice = true) { + static async roll(caracValue, finalLevel, bonus = undefined, diviseur = undefined, showDice = true) { let chances = this.computeChances(caracValue, finalLevel); this._updateChancesWithBonus(chances, bonus); - this._updateChancesNeedSignificative(chances, needSignificative); + this._updateChancesFactor(chances, diviseur); chances.showDice = showDice; let rolled = await this.rollChances(chances); rolled.caracValue = caracValue; rolled.finalLevel = finalLevel; rolled.bonus = bonus; - rolled.needSignificative = needSignificative; + rolled.factor = RdDResolutionTable._getFractionHtml(diviseur); return rolled; } /* -------------------------------------------- */ - static _updateChancesNeedSignificative(chances, needSignificative) { - if (needSignificative) { - let newScore = Math.floor(Number(chances.score) / 2); + static _updateChancesFactor(chances, diviseur) { + if (diviseur && diviseur > 1) { + let newScore = Math.floor(Number(chances.score) / diviseur); mergeObject(chances, this._computeCell(null, newScore), { overwrite: true }); } } @@ -261,16 +267,7 @@ export class RdDResolutionTable { /* -------------------------------------------- */ static _computeReussite(chances, roll) { - const reussite = reussites.find(x => x.condition(chances, roll)); - if (chances.needSignificative) { - if (reussite.isSign) { - return reussiteNormale; - } - if (reussite.isSuccess) { - return echecNormal; - } - } - return reussite; + return reussites.find(x => x.condition(chances, roll)); } /* -------------------------------------------- */ diff --git a/module/rdd-roll-resolution.js b/module/rdd-roll-resolution.js index 6a3b87cd..cc6c3277 100644 --- a/module/rdd-roll-resolution.js +++ b/module/rdd-roll-resolution.js @@ -1,4 +1,3 @@ -import { ChatUtility } from "./chat-utility.js"; import { Misc } from "./misc.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; @@ -23,7 +22,7 @@ export class RdDRollResolution extends Dialog { let defRollData = { - show: { title: titleTableDeResolution, points: true }, + show: { title: titleTableDeResolution }, ajustementsConditions: CONFIG.RDD.ajustementsConditions, difficultesLibres: CONFIG.RDD.difficultesLibres, etat: 0, @@ -64,8 +63,7 @@ export class RdDRollResolution extends Dialog { async onAction(html) { await RdDResolutionTable.rollData(this.rollData); console.log("RdDRollResolution -=>", this.rollData, this.rollData.rolled); - const message = { content: await RdDResolutionTable.explainRollDataV2(this.rollData) }; - ChatUtility.chatWithRollMode(message, game.user.name) + await RdDResolutionTable.displayRollData(rollData, game.user.name) } /* -------------------------------------------- */ diff --git a/module/rdd-roll.js b/module/rdd-roll.js index 8230efe2..d9d6275f 100644 --- a/module/rdd-roll.js +++ b/module/rdd-roll.js @@ -31,6 +31,7 @@ export class RdDRoll extends Dialog { static _setDefaultOptions(actor, rollData) { let defaultRollData = { + alias: actor.name, ajustementsConditions: CONFIG.RDD.ajustementsConditions, difficultesLibres: CONFIG.RDD.difficultesLibres, etat: actor.data.data.compteurs.etat.value, diff --git a/module/rdd-utility.js b/module/rdd-utility.js index dc780b90..0a01ab55 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -200,6 +200,8 @@ export class RdDUtility { // messages tchat 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html', + 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html', + 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-general.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-tache.html', diff --git a/packs/equipement.db b/packs/equipement.db index 5c814646..bd649d1f 100644 --- a/packs/equipement.db +++ b/packs/equipement.db @@ -1,5 +1,6 @@ {"_id":"0Vgscex1VV4ybSUQ","name":"Bonnet de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.05,"equipe":false,"resistance":0,"qualite":0,"cout":0.06},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bonnet_laine.webp","effects":[]} {"_id":"0ylGrNMzulUaKFP9","name":"Boralm","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

Poudre brune apparaissant sur les parois des grottes.

\n

VUE/Alchimie à -1.

","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Cavernes","rarete":"","categorie":"Alchimie","cout":0.03},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/boralm.webp","effects":[]} +{"_id":"1Dc4KzZageae7lhI","name":"Balles de jongleur","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":4,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.32},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/balle_jongleur.webp","effects":[]} {"_id":"1O7IJiQSDYxJ5VsD","name":"Bouclier moyen","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"0","force":"11","resistance":15,"competence":"Bouclier","cout":6,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_moyen.webp","effects":[]} {"_id":"2y61gBIFbATQaKDl","name":"1 m2 de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/tissu_laine.webp","effects":[]} {"_id":"3DJePXhrDWQxbUeM","name":"Dé à jouer en os","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/des_en_os.webp","effects":[]} @@ -137,6 +138,8 @@ {"_id":"hVgd4APvAW8sbXf0","name":"Grande hache","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","force":"13","resistance":8,"competence":"Hache à 2 mains","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"haches","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/grande_hache.webp","effects":[]} {"_id":"hjsIxUmanyz5otLJ","name":"Marmite de fer (3 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1.5,"encombrement":0.6,"equipe":false,"qualite":0,"contenu":[],"cout":0.6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/marmite.webp","effects":[]} {"_id":"huvZ4dMPpn9gk9km","name":"Sel","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":null},"flags":{"core":{"sourceId":"Item.fLEyryhRi8Nw37SP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sel.webp","effects":[]} +{"_id":"iCvphbPdxUcfqetd","name":"Aumônière","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"

Comme une bourse, mais sous forme d'une coque en cuir rigide.

","capacite":0.25,"encombrement":0,"equipe":false,"qualite":0,"cout":0.2,"contenu":[]},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aumoniere.webp","effects":[]} +{"_id":"iGHudg5kBOfYWgwV","name":"Arc","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Nie jusqu'à 2 points d'armure.

\n

Rechargement 1/2 round (s'il tire en début de round, il pourra recharger durant le reste du round pour tirer de nouveau au début du round suivant).

","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"0","resistance":0,"competence":"Arc","cout":10,"portee_courte":10,"portee_moyenne":20,"portee_extreme":50,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arc.webp","effects":[]} {"_id":"ijCebH1Pr3LmzdOj","name":"Épée cyane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Long cimeterre à l’acier bleuté, exclusivement fabriqué par les Cyans ou Hommes bleus.

","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"11","resistance":12,"competence":"Epée à 1 main","cout":25,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-lourdes","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_cyane.webp","effects":[]} {"_id":"iq8ZZgphxOUgC1bi","name":"Flûte traversière de roseau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.08,"equipe":false,"resistance":0,"qualite":0,"cout":0.12},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/flute_traversiere.webp","effects":[]} {"_id":"iuSOVPBsK8Zg6hoY","name":"1 m² de bâche","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bache.webp","effects":[]} @@ -149,7 +152,7 @@ {"_id":"keLCmhsbxHK39UIy","name":"Mirobolant","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

Fluide.

\n

Liquide rougeâtre clair et sans dépot.

","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/mirobolant.webp","effects":[]} {"_id":"lJMKVPB5zlG9UqMD","name":"Pourpoint de velours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":8},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pourpoint_velours.webp","effects":[]} {"_id":"lKkYFkzWVs2TZDZP","name":"Petit pot de fard","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fard.webp","effects":[]} -{"_id":"lOI2HVu3B6EDY4sE","name":"Arbalète","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Nie jusqu'à 2 points d'armure.

\n

Rechargement 1 round.

","quantite":1,"encombrement":3,"equipe":false,"dommages":"3","force":"0","resistance":0,"competence":"Arbalète","cout":30,"portee_courte":15,"portee_moyenne":30,"portee_extreme":70,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arbalete.webp","effects":[]} +{"_id":"lOI2HVu3B6EDY4sE","name":"Arbalète","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Nie jusqu'à 2 points d'armure.

\n

Rechargement 1 round.

","quantite":1,"encombrement":3,"equipe":false,"dommages":"3","force":"0","resistance":0,"competence":"Arbalète","cout":30,"portee_courte":15,"portee_moyenne":30,"portee_extreme":70,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arbalete.webp","effects":[]} {"_id":"lq7pjDQESNbZOQ3n","name":"1 m2 de soie ou de velours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/tissu_velours.webp","effects":[]} {"_id":"m9yuZjp9DK7pSqPK","name":"Lanterne à bougie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.1,"encombrement":1,"equipe":false,"qualite":0,"contenu":[],"cout":3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/lanterne_bougie.webp","effects":[]} {"_id":"mOZodpJYobvmZO9o","name":"Le Narcolepton","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

Cet ouvrage ne peut être assimilé que si l’on possède un niveau minimum de zéro en voie de Narcos. Il confère un bonus de synthèse de +3 aux sept Écailles de Protection présentées dans les règles (Venin, Maladie, Feu, Magie, Projectiles, Lames, Griffes et crocs), mais aucun bonus de points de sorts. Sa difficulté de lecture est de -4, son assimilation requiert 24 points de tâche, périodicité une heure.

","auteur":"anonyme","quantite":1,"difficulte":-4,"points_de_tache":24,"encombrement":0,"xp":"","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} @@ -197,7 +200,3 @@ {"_id":"zQWlnUsd8bPySujd","name":"Aiguille à coudre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aiguille.webp","effects":[]} {"_id":"zYI8mDiysWtmsSyy","name":"Carquois","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"","capacite":2,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/carquois.webp","effects":[]} {"_id":"zlDa1vwmls6Uf4pt","name":"Bourse de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.01,"equipe":false,"qualite":0,"contenu":[],"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bourse.webp","effects":[]} -{"_id":"iCvphbPdxUcfqetd","name":"Aumônière","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"

Comme une bourse, mais sous forme d'une coque en cuir rigide.

","capacite":0.25,"encombrement":0,"equipe":false,"qualite":0,"cout":0.2,"contenu":[]},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aumoniere.webp","effects":[]} -{"_id":"iGHudg5kBOfYWgwV","name":"Arc","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Nie jusqu'à 2 points d'armure.

\n

Rechargement 1/2 round (s'il tire en début de round, il pourra recharger durant le reste du round pour tirer de nouveau au début du round suivant).

","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"0","resistance":0,"competence":"Arc","cout":10,"portee_courte":10,"portee_moyenne":20,"portee_extreme":50,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arc.webp","effects":[]} -{"_id":"1Dc4KzZageae7lhI","name":"Balles de jongleur","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":4,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.32},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/balle_jongleur.webp","effects":[]} -{"_id":"lOI2HVu3B6EDY4sE","name":"Arbalète","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

Nie jusqu'à 2 points d'armure.

\n

Rechargement 1 round.

","quantite":1,"encombrement":3,"equipe":false,"dommages":"3","force":"0","resistance":0,"competence":"Arbalète","cout":30,"portee_courte":15,"portee_moyenne":30,"portee_extreme":70,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arbalete.webp","effects":[]} diff --git a/system.json b/system.json index d6b82a72..6fe94213 100644 --- a/system.json +++ b/system.json @@ -5,7 +5,7 @@ "version": "1.2.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.8", - "templateVersion": 75, + "templateVersion": 76, "author": "LeRatierBretonnien", "esmodules": [ "module/rdd-main.js", "module/hook-renderChatLog.js" ], "styles": ["styles/simple.css"], diff --git a/templates/chat-resultat-appelchance.html b/templates/chat-resultat-appelchance.html index 03029d69..4207b101 100644 --- a/templates/chat-resultat-appelchance.html +++ b/templates/chat-resultat-appelchance.html @@ -1,19 +1,23 @@

- Appel à la chance: - + {{alias}} fait appel à la chance +
{{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} - {{#if ajustements}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
- {{/if}}
= {{rolled.score}}%

{{rolled.roll}} : {{rolled.quality}}
{{~#if rolled.isSuccess}}
-Un point de chance est dépensé, l'action peut être retentée! +Un point de chance est dépensé, l'action peut être retentée! {{/if}} diff --git a/templates/chat-resultat-attaque.html b/templates/chat-resultat-attaque.html index dfdcefb3..b2158636 100644 --- a/templates/chat-resultat-attaque.html +++ b/templates/chat-resultat-attaque.html @@ -1,53 +1,57 @@

- Attaque {{arme.name}} -
{{selectedCarac.label}} / {{competence.name}} - à {{diffLibre}} -
- + {{alias}} attaque: {{arme.name}} +
{{selectedCarac.label}} / {{competence.name}}, difficulté {{diffLibre}} +
{{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} - {{#if ajustements}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 - sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
- {{/if}}
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% + {{#if rolled.factor}}{{/if}} = {{rolled.score}}%

{{rolled.roll}} : {{rolled.quality}}

{{#if tactique}} -
- {{#if (eq tactique 'charge')}} - charge - C'est une charge, vos parades auront un -4 et vous ne pouvez pas esquiver! - {{ else if (eq tactique 'feinte')}} - feinte +
+ {{#if (eq tactique 'charge')}} + charge + C'est une charge, vos parades auront un -4 et vous ne pourrez pas esquiver! + {{ else if (eq tactique 'feinte')}} + feinte Votre feinte peut faire mouche! - {{/if}} -
+ {{/if}} +
{{/if}}
- {{show.cible}} doit se défendre à {{diffLibre}}, ou encaisser à - {{~#if (eq dmg.mortalite 'non-mortel')}} - ({{numberFormat dmg.total decimals=0 sign=true}}) (dommages non-mortel) - {{else if (eq dmg.mortalite 'mortel')}} - {{numberFormat dmg.total decimals=0 sign=true}}. - {{else}} - {{numberFormat dmg.total decimals=0 sign=true}} (entités de cauchemar) - {{~/if}}. - {{#if show.isRecul}}Si votre adversaire n'esquive pas, il devra résister à l'impact ou reculer sous le choc!{{/if}} - Le coup vise: {{dmg.loc.label}}. - -
-{{#if (eq particuliereAttaque 'rapidite')}} -
- -
Votre attaque rapide vous permet une deuxième attaque, ou défense supplémentaire! -
-
-{{/if}} \ No newline at end of file + {{#if rolled.isSuccess}} + {{show.cible}} doit se défendre à {{diffLibre}}, ou encaisser à + {{~#if (eq dmg.mortalite 'non-mortel')}} + ({{numberFormat dmg.total decimals=0 sign=true}}) (dommages non-mortel) + {{else if (eq dmg.mortalite 'mortel')}} + {{numberFormat dmg.total decimals=0 sign=true}}. + {{else}} + {{numberFormat dmg.total decimals=0 sign=true}} (entités de cauchemar) + {{~/if}}. + {{#if show.isRecul}}Si votre adversaire n'esquive pas, il devra résister à l'impact ou reculer sous le choc!{{/if}} + Le coup vise: {{dmg.loc.label}}. + + + {{#if (eq particuliereAttaque 'rapidite')}} +
+ +
Votre attaque rapide vous permet une deuxième attaque, ou défense supplémentaire! +
+ {{/if}} + {{else}} + Votre attaque a échoué! + {{/if}} +
\ No newline at end of file diff --git a/templates/chat-resultat-competence.html b/templates/chat-resultat-competence.html index 84cc1697..f870fa06 100644 --- a/templates/chat-resultat-competence.html +++ b/templates/chat-resultat-competence.html @@ -1,32 +1,31 @@

- {{#if show.title}}{{show.title}}: {{/if}} + {{alias}} {{#if show.title}}{{show.title}}: {{/if}} {{#if selectedCarac}}{{selectedCarac.label}} {{#if competence}} / {{competence.name}}{{/if}} {{/if}} -
- +
{{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} - {{#if ajustements}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
- {{/if}}
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% + {{#if rolled.factor}}{{/if}} = {{rolled.score}}%

{{rolled.roll}} : {{rolled.quality}}
-{{#if show.points}}
- {{rolled.ptTache}} points de tâche{{#if rolled.ptQualite}}, ajustement Qualité {{numberFormat rolled.ptQualite decimals=0 sign=true}}{{/if}} + {{#if rolled.ptTache}}{{rolled.ptTache}} points de tâche{{/if}}{{#if rolled.ptQualite}}{{#if rolled.ptTache}},{{/if}} ajustement Qualité {{numberFormat rolled.ptQualite decimals=0 sign=true}}{{/if}}
-{{/if}} {{~#if show.explications}} -{{#unless show.points}}
{{/unless}}
{{show.explications}}
diff --git a/templates/chat-resultat-esquive.html b/templates/chat-resultat-esquive.html new file mode 100644 index 00000000..c46440ab --- /dev/null +++ b/templates/chat-resultat-esquive.html @@ -0,0 +1,50 @@ +

+ {{alias}} esquive: {{selectedCarac.label}} / {{competence.name}}, difficulté {{diffLibre}} +
+ {{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} +
+
Ajustements
+ {{#each ajustements as |item key|}} +
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
+ {{/each}} +
+
+ {{#if rolled.factor}}{{/if}} = {{rolled.score}}% +

+
{{rolled.roll}} : {{rolled.quality}}
+
+
+ {{#if rolled.isSuccess}} + Attaque esquivée! + {{#if rolled.isPart}} + + Vous pouvez faire une deuxième esquive! + {{/if}} + {{else}} + Votre esquive a échoué! + {{/if}} +
+ +{{#if (eq show.recul 'encaisse')}}
Vous ne reculez pas malgré la violence du coup.
+{{else if (eq show.recul 'chute')}}
Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round.
+{{else if (eq show.recul 'recul')}}
La violence du choup vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round.
+{{/if}} + +{{#if attackerRoll.tactique}} +
+ {{#if (eq attackerRoll.tactique 'charge')}} + charge + C'était une charge, les parades de votre adversaire auront un -4 et il ne pourra pas esquiver! + {{ else if (eq attackerRoll.tactique 'feinte')}} + feinte + C'était une feinte! + {{/if}} +
+{{/if}} diff --git a/templates/chat-resultat-general.html b/templates/chat-resultat-general.html index 84cc1697..d8df8658 100644 --- a/templates/chat-resultat-general.html +++ b/templates/chat-resultat-general.html @@ -1,32 +1,33 @@

- {{#if show.title}}{{show.title}}: {{/if}} + {{alias}} {{#if show.title}}{{show.title}}: {{/if}} {{#if selectedCarac}}{{selectedCarac.label}} {{#if competence}} / {{competence.name}}{{/if}} {{/if}} -
- +
{{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} {{#if ajustements}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
{{/if}}
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% + {{#if rolled.factor}}{{/if}} = {{rolled.score}}%

{{rolled.roll}} : {{rolled.quality}}
-{{#if show.points}}
- {{rolled.ptTache}} points de tâche{{#if rolled.ptQualite}}, ajustement Qualité {{numberFormat rolled.ptQualite decimals=0 sign=true}}{{/if}} + {{#if rolled.ptTache}}{{rolled.ptTache}} points de tâche{{/if}}{{#if rolled.ptQualite}}{{#if rolled.ptTache}},{{/if}} ajustement Qualité {{numberFormat rolled.ptQualite decimals=0 sign=true}}{{/if}}
-{{/if}} {{~#if show.explications}} -{{#unless show.points}}
{{/unless}}
{{show.explications}}
diff --git a/templates/chat-resultat-parade.html b/templates/chat-resultat-parade.html new file mode 100644 index 00000000..b0d61ca9 --- /dev/null +++ b/templates/chat-resultat-parade.html @@ -0,0 +1,63 @@ +

+ {{alias}} pare: {{arme.name}} +
{{selectedCarac.label}} / {{competence.name}}, difficulté {{diffLibre}} +
+ {{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} +
+
Ajustements
+ {{#each ajustements as |item key|}} +
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
+ {{/each}} +
+
+ {{#if rolled.factor}}{{/if}} = {{rolled.score}}% +

+
{{rolled.roll}} : {{rolled.quality}}
+
+
+ {{#if rolled.isSuccess}} + Attaque parée! + {{#if rolled.isPart}} + + Vous pouvez utiliser votre arme pour une deuxième parade! + {{/if}} + {{else}} + Votre parade a échoué! + {{/if}} +
+ +{{#if (eq show.recul 'encaisse')}}
Vous ne reculez pas malgré la violence du coup.
+{{else if (eq show.recul 'brise')}}
Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round.
+{{else if (eq show.recul 'perte')}}
La violence du choup vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round.
+{{/if}} + +{{#if (eq show.deteriorationArme 'resiste')}} +
Votre {{arme.name}} résiste au choc de la parade.
+{{else if (eq show.deteriorationArme 'resiste')}} +
Sous la violence de la parade, votre {{arme.name}} s'est brisée!
+{{else if (eq show.deteriorationArme 'resiste')}} +
En parant, vous endommagez votre {{arme.name}} qui perd {{show.perteResistance}} de résistance.
+{{/if}} + +{{#if show.desarme}} +
Vous ne parvenez pas à garder votre arme en main, elle tombe à vos pieds.
+{{/if}} + +{{#if attackerRoll.tactique}} +
+ {{#if (eq attackerRoll.tactique 'charge')}} + charge + C'était une charge, les parades de votre adversaire auront un -4 et il ne pourra pas esquiver! + {{ else if (eq attackerRoll.tactique 'feinte')}} + feinte + C'était une feinte! + {{/if}} +
+{{/if}} diff --git a/templates/chat-resultat-rdd.html b/templates/chat-resultat-rdd.html deleted file mode 100644 index 464a6eac..00000000 --- a/templates/chat-resultat-rdd.html +++ /dev/null @@ -1,30 +0,0 @@ -

- {{#if show.title}}{{show.title}}: {{/if}} -
- - {{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} - {{#if ajustements}} -
-
Ajustements
- {{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
- {{/each}} -
- {{/if}} -
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% -

-
{{rolled.roll}} : {{rolled.quality}}
-{{#if show.points}} -
-
- {{rolled.ptTache}} points de tâche{{#if rolled.ptQualite}}, ajustement Qualité {{numberFormat rolled.ptQualite decimals=0 sign=true}}{{/if}} -
-{{/if}} -{{~#if show.explications}} -{{#unless show.points}}
{{/unless}} -
- {{show.explications}} -
-{{/if}} diff --git a/templates/chat-resultat-sort.html b/templates/chat-resultat-sort.html index 25aadb1c..e4033a15 100644 --- a/templates/chat-resultat-sort.html +++ b/templates/chat-resultat-sort.html @@ -1,17 +1,24 @@

- {{#if isSortReserve}}Mise en réserve{{else}}Lancement{{/if}} du sort {{selectedSort.name}} (r {{selectedSort.data.ptreve_reel}}) + {{alias}} {{#if isSortReserve}}met en réserve{{else}}lance{{/if}} le + {{selectedSort.data.isrituel}}rituel{{else}}sort{{/if}} + {{selectedSort.name}} (r {{selectedSort.data.ptreve_reel}})
{{competence.name}}: {{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% + {{#if rolled.factor}}{{/if}} = {{rolled.score}}%

Pour {{selectedSort.data.ptreve_reel}} points de rêve en {{coordLabel}} ({{coord}})
diff --git a/templates/chat-resultat-tache.html b/templates/chat-resultat-tache.html index d8a068e6..87b70e8e 100644 --- a/templates/chat-resultat-tache.html +++ b/templates/chat-resultat-tache.html @@ -1,18 +1,22 @@

- {{tache.name}}: Tâche {{selectedCarac.label}} / {{competence.name}} + {{alias}} travaille à sa tâche {{tache.name}} +
{{selectedCarac.label}} / {{competence.name}} {{rolled.caracValue}} à {{numberFormat rolled.finalLevel decimals=0 sign=true}} - {{#if ajustements}}
Ajustements
{{#each ajustements as |item key|}} -
{{item.label}}: {{numberFormat item.value decimals=0 sign=true}}{{#if item.unit}}{{item.unit}}{{/if}}
+
+ {{#if item.descr}} + {{{item.descr}}} + {{else}} + {{item.label}}: {{numberFormat item.value decimals=0 sign=true}} + {{/if}} +
{{/each}}
- {{/if}}
- {{#if rolled.needSignificative}}{{/if}} = - {{rolled.score}}% + {{#if rolled.factor}}{{/if}} = {{rolled.score}}%

{{rolled.roll}} : {{rolled.quality}}