From 969bc3b573d19af82c57852e47fc432ee57e983e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 12 Jan 2025 20:00:13 +0100 Subject: [PATCH 1/2] =?UTF-8?q?Liens=20de=20jets=20de=20d=C3=A9s=20dans=20?= =?UTF-8?q?le=20tchat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 3 +- module/actor-sheet.js | 2 +- module/actor/base-actor-reve-sheet.js | 4 +- module/actor/base-actor-sheet.js | 2 +- module/apps/rdd-text-roll-editor.js | 72 ++++++ module/apps/rdd-text-roll.js | 224 ------------------ module/apps/textroll/text-roll-alchimie.js | 79 ++++++ .../textroll/text-roll-carac-competence.js | 88 +++++++ module/apps/textroll/text-roll-formatter.js | 14 ++ module/apps/textroll/text-roll-formula.js | 51 ++++ module/coeur/rdd-coeur.js | 1 - module/item-sheet.js | 3 +- module/journal/journal-sheet.js | 3 +- module/rdd-main.js | 2 +- module/rdd-utility.js | 6 +- ...ables_Maladresse_arm__pXYVWRlCftWdwsBP.yml | 20 +- styles/simple.css | 19 +- system.json | 6 +- templates/apps/link-text-roll-alchimie.hbs | 8 - .../apps/link-text-roll-carac-competence.hbs | 9 - templates/apps/link-text-roll-foundry.hbs | 5 - .../apps/textroll/chat-link-text-roll.hbs | 0 .../apps/textroll/link-text-roll-alchimie.hbs | 14 ++ .../link-text-roll-carac-competence.hbs | 15 ++ .../apps/textroll/link-text-roll-formula.hbs | 10 + 25 files changed, 383 insertions(+), 277 deletions(-) create mode 100644 module/apps/rdd-text-roll-editor.js delete mode 100644 module/apps/rdd-text-roll.js create mode 100644 module/apps/textroll/text-roll-alchimie.js create mode 100644 module/apps/textroll/text-roll-carac-competence.js create mode 100644 module/apps/textroll/text-roll-formatter.js create mode 100644 module/apps/textroll/text-roll-formula.js delete mode 100644 templates/apps/link-text-roll-alchimie.hbs delete mode 100644 templates/apps/link-text-roll-carac-competence.hbs delete mode 100644 templates/apps/link-text-roll-foundry.hbs create mode 100644 templates/apps/textroll/chat-link-text-roll.hbs create mode 100644 templates/apps/textroll/link-text-roll-alchimie.hbs create mode 100644 templates/apps/textroll/link-text-roll-carac-competence.hbs create mode 100644 templates/apps/textroll/link-text-roll-formula.hbs diff --git a/changelog.md b/changelog.md index cfcb7cbc..544646c3 100644 --- a/changelog.md +++ b/changelog.md @@ -7,12 +7,11 @@ - à tous les tokens sélectionnés - sinon, à l'acteur propriétaire d'un Item - sinon, au personnage du joueur - - gestion des blocs secrets dans les descriptions - on peut ajouter des liens "jet de dés" pour appeler une formule dés de foundry - les liens "manipulation alchimiques" peuvent être dans les descriptions, notes, ... - les "manipulation alchimiques" fonctionnent comme tous les autres jets - +- on peut poster les liens "jet de dés" dans le tchat et les utiliser depuis le tchat ## 12.0.33 - la vieillesse d'Astrobazzarh - retour de l'expérience pour les joueurs diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 7831bce3..2c0b26ff 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -19,7 +19,7 @@ import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"; import { RdDItemRace } from "./item/race.js"; -import { RdDTextEditor } from "./apps/rdd-text-roll.js"; +import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; /* -------------------------------------------- */ /** diff --git a/module/actor/base-actor-reve-sheet.js b/module/actor/base-actor-reve-sheet.js index 2e5fa022..a7753af0 100644 --- a/module/actor/base-actor-reve-sheet.js +++ b/module/actor/base-actor-reve-sheet.js @@ -1,4 +1,4 @@ -import { RdDTextEditor } from "../apps/rdd-text-roll.js"; +import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; import { Grammar } from "../grammar.js"; import { ITEM_TYPES } from "../item.js"; import { RdDSheetUtility } from "../rdd-sheet-utility.js"; @@ -49,6 +49,8 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet { }], { renderSheet: true }) ) this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) + this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) + if (this.options.vueDetaillee) { // On carac change diff --git a/module/actor/base-actor-sheet.js b/module/actor/base-actor-sheet.js index c6a3fb7d..00429a92 100644 --- a/module/actor/base-actor-sheet.js +++ b/module/actor/base-actor-sheet.js @@ -5,7 +5,7 @@ import { RdDSheetUtility } from "../rdd-sheet-utility.js"; import { Monnaie } from "../item-monnaie.js"; import { RdDItem, ITEM_TYPES } from "../item.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; -import { RdDTextEditor } from "../apps/rdd-text-roll.js"; +import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; /* -------------------------------------------- */ /** diff --git a/module/apps/rdd-text-roll-editor.js b/module/apps/rdd-text-roll-editor.js new file mode 100644 index 00000000..4ab58bd4 --- /dev/null +++ b/module/apps/rdd-text-roll-editor.js @@ -0,0 +1,72 @@ +import "./xregexp-all.js"; +import { SystemCompendiums } from "../settings/system-compendiums.js"; +import { ACTOR_TYPES } from "../item.js"; +import { TextRollAlchimie } from "./textroll/text-roll-alchimie.js"; +import { TextRollCaracCompetence } from "./textroll/text-roll-carac-competence.js"; +import { TextRollFormula } from "./textroll/text-roll-formula.js"; +import { TextRollManager } from "./textroll/text-roll-formatter.js"; + +const TEXT_ROLL_MANAGERS = [ + new TextRollAlchimie(), + new TextRollCaracCompetence(), + new TextRollFormula()]; + +export class RdDTextEditor { + + static async enrichHTML(text, object) { + const context = { + text, object, + competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), + } + + for (let manager of TEXT_ROLL_MANAGERS) { + context.code = manager.code + context.template = manager.template + context.text = await manager.onReplaceRoll(context); + } + + // TEXT_ROLL_MANAGERS.forEach(async manager => await RdDTextEditor._applyReplaceAll(manager, context)) + return await TextEditor.enrichHTML(context.text, { + relativeTo: object, + secrets: object?.isOwner, + async: true + }) + } + + static async _applyReplaceAll(manager, context) { + context.code = manager.code + context.template = manager.template + context.text = await manager.onReplaceRoll(context); + return context.text + } + + static getEventElement(event) { + return $(event.currentTarget)?.parents(".roll-text-link"); + } + + static async rollText(event, actor) { + const code = TextRollManager.getNode(event)?.data('code') + const manager = TEXT_ROLL_MANAGERS.find(it => it.code == code) + if (manager) { + await manager.onRollText(event, actor) + } + } + + static async chatRollText(event) { + const node = TextRollManager.getNode(event); + if (node) { + const code = node.data('code') + const param = node.data('json') + const manager = TEXT_ROLL_MANAGERS.find(it => it.code == code) + + const text = await TextRollManager.createRollText(manager.template, + param, false) + ChatMessage.create({ + content: text + }) + } + } + static registerChatCallbacks(html) { + html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event)) + } +} \ No newline at end of file diff --git a/module/apps/rdd-text-roll.js b/module/apps/rdd-text-roll.js deleted file mode 100644 index c0249edf..00000000 --- a/module/apps/rdd-text-roll.js +++ /dev/null @@ -1,224 +0,0 @@ -import "./xregexp-all.js"; -import { RdDCarac } from "../rdd-carac.js"; -import { SystemCompendiums } from "../settings/system-compendiums.js"; -import { RdDItemCompetence } from "../item-competence.js"; -import { ACTOR_TYPES, ITEM_TYPES } from "../item.js"; -import { RdDUtility } from "../rdd-utility.js"; -import { Misc } from "../misc.js"; -import { RdDAlchimie } from "../rdd-alchimie.js"; - -const REGEX_ALCHIMIE_TERMES = "(?(\\w|-)+)" -const REGEX_ALCHIMIE_MANIP = "(?(couleur|consistance))" -const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu') -const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') - -const REGEXP_ROLL_CARAC_COMP = "(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)(\\/(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?(/(?[\\+\\-]?\\d+))?" -const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') - -const REGEXP_ROLL_FORMULA = "(?[^\\[\\]]+)" -const XREGEXP_ROLL_FORMULA = XRegExp("@roll\\[" + REGEXP_ROLL_FORMULA + "\\]", 'giu') - - -/** - * classe pour gérer les jets d'alchimie - */ -class TextRollAlchimie { - static async onRollText(event, actor) { - actor = TextRollAlchimie.getSelectedActor(actor) - if (actor) { - const recetteId = event.currentTarget.attributes['data-recette-id']?.value - const manip = event.currentTarget.attributes['data-manip'].value - const termes = event.currentTarget.attributes['data-termes'].value - if (recetteId) { - await actor.effectuerTacheAlchimie(recetteId, manip, termes) - } - else { - const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) - const diff = RdDAlchimie.getDifficulte(termes) - await actor.rollCaracCompetence(carac.code, 'Alchimie', diff) - } - } - } - - static getSelectedActor(actor) { - actor = actor ?? RdDUtility.getSelectedActor() - if (actor && actor.type == ACTOR_TYPES.personnage) { - return actor - } - return undefined - } - - static async onReplaceRoll(context) { - const handler = new TextRollAlchimie(context) - context.text = await handler.replaceManipulationAlchimie() - } - - constructor(context) { - this.context = context - } - - async replaceManipulationAlchimie() { - await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE, async (rollMatch, i) => await this._replaceOneAlchimie(rollMatch, i)) - await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE_MANIP, async (rollMatch, i) => await this._replaceOneAlchimie(rollMatch, i)) - return this.context.text - } - - async _replaceOneAlchimie(rollMatch, i) { - if (rollMatch.termes && rollMatch.manip) { - const manip = rollMatch.manip - await this._replaceManip(manip, rollMatch, i) - } - } - - async _replaceManip(manip, rollMatch, i) { - const termes = rollMatch.termes - const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) - const diff = RdDAlchimie.getDifficulte(termes) - const recette = (this.context.object instanceof Item && this.context.object.type == ITEM_TYPES.recettealchimique) ? this.context.object : undefined - const replacement = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/apps/link-text-roll-alchimie.hbs`, { - manip, - termes, - recette, - carac, - diff - }) - this.context.text = this.context.text.replace(rollMatch[0], replacement); - } -} - -/** - * classe pour gérer les jets de caractéristique/compétence depuis - * les journaux/descriptions - */ -class TextRollCaracCompetence { - - static async onRollText(event, actor) { - const caracCode = event.currentTarget.attributes['data-carac-code']?.value - if (caracCode) { - const competence = event.currentTarget.attributes['data-competence']?.value - const diff = event.currentTarget.attributes['data-diff']?.value - const actors = TextRollCaracCompetence.getSelectedActors(actor) - actors.forEach(async it => await TextRollCaracCompetence.doRoll(it, caracCode, competence, diff)) - } - } - static async doRoll(actor, caracCode, competence, diff) { - caracCode = actor.mapCarac(caracCode) - if (competence) { - if (actor.type == ACTOR_TYPES.personnage) { - await actor.rollCaracCompetence(caracCode, competence, diff) - } - else { - await actor.doRollCaracCompetence(caracCode, competence, diff) - } - } - else { - await actor.rollCarac(caracCode, { diff }) - } - } - - static async onReplaceRoll(context) { - const handler = new TextRollCaracCompetence(context) - context.text = await handler.replaceRollCaracCompetence() - } - - static getSelectedActors(actor) { - const selected = canvas.tokens.controlled.map(it => it.actor).filter(it => it) - if (selected.length > 0) { - return selected - } - actor = actor ?? RdDUtility.getSelectedActor() - if (actor) { - return [actor] - } - return [] - } - - constructor(context) { - this.context = context - } - - async replaceRollCaracCompetence() { - await XRegExp.forEach(this.context.text, XREGEXP_ROLL_CARAC_COMP, async (rollMatch, i) => await this._replaceOne(rollMatch, i)) - return this.context.text - } - - async _replaceOne(rollMatch, i) { - const carac = RdDCarac.caracDetails(rollMatch.carac) - if (carac) { - const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.context.competences, rollMatch.competence) : undefined - const replacement = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/apps/link-text-roll-carac-competence.hbs`, { - carac: carac, - competence: competence?.name, - diff: rollMatch.diff - }) - this.context.text = this.context.text.replace(rollMatch[0], replacement) - } - } -} - -/** - * classe pour gérer les jets de dés (formules Foundry) - */ -class TextRollFoundry { - - static async onReplaceRoll(context) { - const handler = new TextRollFoundry(context.text) - context.text = await handler.replaceRolls() - } - - static async onRollText(event, actor) { - const rollFoundry = event.currentTarget.attributes['data-roll-foundry']?.value - if (rollFoundry) { - const roll = new Roll(rollFoundry) - await roll.evaluate() - await roll.toMessage() - } - } - - constructor(text) { - this.text = text - } - - async replaceRolls() { - await XRegExp.forEach(this.text, XREGEXP_ROLL_FORMULA, async (rollMatch, i) => await this._replaceOne(rollMatch, i)) - return this.text - } - - async _replaceOne(rollMatch, i) { - if (rollMatch.formula) { - const replacement = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/apps/link-text-roll-foundry.hbs`, { - formula: rollMatch.formula, - }) - this.text = this.text.replace(rollMatch[0], replacement) - } - } -} - -export class RdDTextEditor { - - static async enrichHTML(text, object) { - const competences = await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage); - const context = { text, competences, object } - await TextRollAlchimie.onReplaceRoll(context) - await TextRollCaracCompetence.onReplaceRoll(context) - await TextRollFoundry.onReplaceRoll(context) - return await TextEditor.enrichHTML(context.text, { - relativeTo: object, - secrets: object?.isOwner, - async: true - }) - } - - static async rollText(event, actor) { - const rollMode = event.currentTarget.attributes['data-roll-mode']?.value; - switch (rollMode) { - case 'foundry': - return await TextRollFoundry.onRollText(event, actor) - case 'carac': - return await TextRollCaracCompetence.onRollText(event, actor) - case 'alchimie': - return await TextRollAlchimie.onRollText(event, actor) - } - } - -} \ No newline at end of file diff --git a/module/apps/textroll/text-roll-alchimie.js b/module/apps/textroll/text-roll-alchimie.js new file mode 100644 index 00000000..4f96a47e --- /dev/null +++ b/module/apps/textroll/text-roll-alchimie.js @@ -0,0 +1,79 @@ +import "../xregexp-all.js"; +import { ACTOR_TYPES, ITEM_TYPES } from "../../item.js"; +import { RdDCarac } from "../../rdd-carac.js"; +import { RdDUtility } from "../../rdd-utility.js"; +import { RdDAlchimie } from "../../rdd-alchimie.js"; +import { TextRollManager } from "./text-roll-formatter.js"; + +const REGEX_ALCHIMIE_TERMES = "(?(\\w|-)+)" +const REGEX_ALCHIMIE_MANIP = "(?(couleur|consistance))" +const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu') +const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') + +/** + * classe pour gérer les jets d'alchimie + */ +export class TextRollAlchimie { + get code() { return 'alchimie' } + get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-alchimie.hbs` } + + async onReplaceRoll(context) { + const handler = new AlchimieTextBuilder(context) + return await handler.replaceAll() + } + + async onRollText(event, actor) { + actor = this.getSelectedActor(actor) + if (actor) { + const node = TextRollManager.getNode(event) + const recetteId = node.data('recetteid') + const manip = node.data('manip') + const termes = node.data('termes') + if (recetteId) { + await actor.effectuerTacheAlchimie(recetteId, manip, termes) + } + else { + const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) + const diff = RdDAlchimie.getDifficulte(termes) + await actor.rollCaracCompetence(carac.code, 'Alchimie', diff) + } + } + } + + getSelectedActor(actor) { + actor = actor ?? RdDUtility.getSelectedActor() + if (actor && actor.type == ACTOR_TYPES.personnage) { + return actor + } + return undefined + } +} + +class AlchimieTextBuilder { + constructor(context) { + this.context = context + } + + async replaceAll() { + await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) + await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE_MANIP, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) + return this.context.text + } + + async replaceMatch(rollMatch, i) { + if (rollMatch.termes && rollMatch.manip) { + const manip = rollMatch.manip + const termes = rollMatch.termes + const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) + const diff = RdDAlchimie.getDifficulte(termes) + const recette = (this.context.object instanceof Item && this.context.object.type == ITEM_TYPES.recettealchimique) ? this.context.object : undefined + const replacement = await TextRollManager.createRollText(this.context.template, + { + code: this.context.code, + manip, termes, carac, diff, recetteid: recette?.id, + }) + this.context.text = this.context.text.replace(rollMatch[0], replacement); + } + } +} + diff --git a/module/apps/textroll/text-roll-carac-competence.js b/module/apps/textroll/text-roll-carac-competence.js new file mode 100644 index 00000000..dc91300e --- /dev/null +++ b/module/apps/textroll/text-roll-carac-competence.js @@ -0,0 +1,88 @@ +import "../xregexp-all.js"; +import { ACTOR_TYPES } from "../../item.js"; +import { RdDCarac } from "../../rdd-carac.js"; +import { RdDItemCompetence } from "../../item-competence.js"; +import { RdDUtility } from "../../rdd-utility.js"; +import { TextRollManager } from "./text-roll-formatter.js"; + +const REGEXP_ROLL_CARAC_COMP = "(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)(\\/(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?(/(?[\\+\\-]?\\d+))?" +const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') + +/** + * classe pour gérer les jets de caractéristique/compétence depuis + * les journaux/descriptions + */ +export class TextRollCaracCompetence { + get code() { return 'carac' } + get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-carac-competence.hbs` } + + async onReplaceRoll(context) { + const handler = new CaracCompetenceTextBuilder(context) + return await handler.replaceAll() + } + + async onRollText(event, actor) { + const node = TextRollManager.getNode(event) + const caracCode = node.data('carac-code') + if (caracCode) { + const competence = node.data('competence') + const diff = node.data('diff') + const actors = this.getSelectedActors(actor) + actors.forEach(async it => await this.doRoll(it, caracCode, competence, diff)) + } + } + + async doRoll(actor, caracCode, competence, diff) { + caracCode = actor.mapCarac(caracCode) + if (competence) { + if (actor.type == ACTOR_TYPES.personnage) { + await actor.rollCaracCompetence(caracCode, competence, diff) + } + else { + await actor.doRollCaracCompetence(caracCode, competence, diff) + } + } + else { + await actor.rollCarac(caracCode, { diff }) + } + } + + getSelectedActors(actor) { + const selected = canvas.tokens.controlled.map(it => it.actor).filter(it => it) + if (selected.length > 0) { + return selected + } + actor = actor ?? RdDUtility.getSelectedActor() + if (actor) { + return [actor] + } + return [] + } +} + +class CaracCompetenceTextBuilder { + constructor(context) { + this.context = context + } + + async replaceAll() { + await XRegExp.forEach(this.context.text, XREGEXP_ROLL_CARAC_COMP, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) + return this.context.text + } + + async replaceMatch(rollMatch, i) { + const carac = RdDCarac.caracDetails(rollMatch.carac) + if (carac) { + const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.context.competences, rollMatch.competence) : undefined + const replacement = await TextRollManager.createRollText(this.context.template, + { + code: this.context.code, + carac: carac, + competence: competence?.name, + diff: rollMatch.diff, + }) + this.context.text = this.context.text.replace(rollMatch[0], replacement) + } + } +} + diff --git a/module/apps/textroll/text-roll-formatter.js b/module/apps/textroll/text-roll-formatter.js new file mode 100644 index 00000000..40b6bbd9 --- /dev/null +++ b/module/apps/textroll/text-roll-formatter.js @@ -0,0 +1,14 @@ + +export class TextRollManager { + + static async createRollText(template, param, showLink = true) { + return await renderTemplate(template, { + param: param, + options: { showlink: showLink } + }) + } + + static getNode(event) { + return $(event.currentTarget)?.parents(".roll-text-link"); + } +} \ No newline at end of file diff --git a/module/apps/textroll/text-roll-formula.js b/module/apps/textroll/text-roll-formula.js new file mode 100644 index 00000000..416777c1 --- /dev/null +++ b/module/apps/textroll/text-roll-formula.js @@ -0,0 +1,51 @@ +import "../xregexp-all.js"; +import { TextRollManager } from "./text-roll-formatter.js"; + +const REGEXP_ROLL_FORMULA = "(?[^\\[\\]]+)" +const XREGEXP_ROLL_FORMULA = XRegExp("@roll\\[" + REGEXP_ROLL_FORMULA + "\\]", 'giu') + +/** + * classe pour gérer les jets de dés (formules Foundry) + */ +export class TextRollFormula { + get code() { return 'formula' } + get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-formula.hbs` } + + async onReplaceRoll(context) { + const handler = new FormulaTextBuilder(context) + return await handler.replaceAll() + } + + async onRollText(event, actor) { + const node = TextRollManager.getNode(event) + const rollFormula = node.data('roll-formula') + if (rollFormula) { + const roll = new Roll(rollFormula) + await roll.evaluate() + await roll.toMessage() + } + } +} + +class FormulaTextBuilder { + constructor(context) { + this.context = context + } + + async replaceAll() { + await XRegExp.forEach(this.context.text, XREGEXP_ROLL_FORMULA, + async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) + return this.context.text + } + + async replaceMatch(rollMatch, i) { + if (rollMatch.formula) { + const replacement = await TextRollManager.createRollText(this.context.template, + { + code: this.context.code, + formula: rollMatch.formula, + }) + this.context.text = this.context.text.replace(rollMatch[0], replacement) + } + } +} diff --git a/module/coeur/rdd-coeur.js b/module/coeur/rdd-coeur.js index f5a4a7f5..ca8774d2 100644 --- a/module/coeur/rdd-coeur.js +++ b/module/coeur/rdd-coeur.js @@ -1,6 +1,5 @@ import { RdDBaseActor } from "../actor/base-actor.js"; import { ChatUtility } from "../chat-utility.js"; -import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; const INFO_COEUR = 'info-coeur'; diff --git a/module/item-sheet.js b/module/item-sheet.js index 4fe2838d..5e965140 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -13,7 +13,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { ACTOR_TYPES, ITEM_TYPES, RdDItem } from "./item.js"; import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; -import { RdDTextEditor } from "./apps/rdd-text-roll.js"; +import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; /** * Extend the basic ItemSheet for RdD specific items @@ -207,6 +207,7 @@ export class RdDItemSheet extends ItemSheet { this.html.find('input[name="system.cacher_points_de_tache"]').change(async event => await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked })); this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) + this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) if (this.actor) { this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, this.getActionRenderItem())); diff --git a/module/journal/journal-sheet.js b/module/journal/journal-sheet.js index 9e864635..8cdcc75e 100644 --- a/module/journal/journal-sheet.js +++ b/module/journal/journal-sheet.js @@ -1,4 +1,4 @@ -import { RdDTextEditor } from "../apps/rdd-text-roll.js"; +import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; import { SYSTEM_RDD } from "../constants.js"; import { Misc } from "../misc.js"; @@ -24,5 +24,6 @@ export class RdDJournalSheet extends JournalTextPageSheet { super.activateListeners(html); html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) + html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) } } \ No newline at end of file diff --git a/module/rdd-main.js b/module/rdd-main.js index e00089d6..e6e0e879 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -76,7 +76,7 @@ import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire. import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js" import { RdDStatBlockParser } from "./apps/rdd-import-stats.js" import { RdDJournalSheet } from "./journal/journal-sheet.js" -import { RdDTextEditor } from "./apps/rdd-text-roll.js" +import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js" /** * RdD system diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 85cff4ba..66090cfa 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -22,6 +22,7 @@ import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js"; import { RDD_CONFIG } from "./constants.js"; import { RdDBaseActor } from "./actor/base-actor.js"; import { RdDCarac } from "./rdd-carac.js"; +import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; /* -------------------------------------------- */ // This table starts at 0 -> niveau -10 @@ -289,7 +290,8 @@ export class RdDUtility { Handlebars.registerHelper('grammar-apostrophe', (article, str) => Grammar.apostrophe(article, str)); Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args)); - + Handlebars.registerHelper('json-stringify', object => JSON.stringify(object)) + // math Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); Handlebars.registerHelper('repeat', function(n, block) { @@ -695,6 +697,8 @@ export class RdDUtility { RdDCombat.registerChatCallbacks(html) RdDEmpoignade.registerChatCallbacks(html) RdDCoeur.registerChatCallbacks(html) + RdDTextEditor.registerChatCallbacks(html) + // Gestion spécifique message passeurs html.on("click", '.tmr-passeur-coord a', event => { diff --git a/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml b/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml index eb25986e..d7b9deb2 100644 --- a/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml +++ b/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml @@ -22,8 +22,9 @@ results: flags: {} type: text text: >- - Ami bousculé : Le compagnon bousculé doit réussir Empathie/Vigilance à - -1d6 ou être en demi-surprise jusqu’à la fin du round suivant. + Ami bousculé : Le compagnon bousculé doit réussir + @roll[Empathie/Vigilance] à + -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: @@ -72,7 +73,7 @@ results: flags: {} type: text text: >- - Arme choquée : L’arme utilisée joue un jet de Résistance à -2d6 et perd ce + Arme choquée : L’arme utilisée joue un jet de Résistance à -@roll[2d6] et perd ce nombre de points de résistance en cas d’échec. img: icons/svg/d20-black.svg weight: 1 @@ -90,7 +91,7 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise + Déséquilibré : Réussir Agilité/Vigilance à -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -107,7 +108,7 @@ results: - _id: GOYmqZj1Lnc0cKO9 flags: {} type: text - text: 'Faux mouvement : Perte de 2d6 points d’endurance.' + text: 'Faux mouvement : Perte de @roll[2d6] points d’endurance.' img: icons/svg/d20-black.svg weight: 1 range: @@ -124,7 +125,7 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise + Déséquilibré : Réussir Agilité/Vigilance à -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -142,7 +143,7 @@ results: flags: {} type: text text: >- - Arme choquée : L’arme utilisée joue un jet de Résistance à -2d6 et perd ce + Arme choquée : L’arme utilisée joue un jet de Résistance à -@roll[2d6] et perd ce nombre de points de résistance en cas d’échec. img: icons/svg/d20-black.svg weight: 1 @@ -192,8 +193,9 @@ results: flags: {} type: text text: >- - Ami bousculé : Le compagnon bousculé doit réussir Empathie/Vigilance à - -1d6 ou être en demi-surprise jusqu’à la fin du round suivant. + Ami bousculé : Le compagnon bousculé doit réussir + @roll[Empathie/Vigilance] à + -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: diff --git a/styles/simple.css b/styles/simple.css index 01525844..2457de0f 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -1038,10 +1038,20 @@ a.rdd-world-content-link { white-space: nowrap; word-break: break-all; } + +span.content-link, a.content-link { background: hsla(45, 100%, 80%, 0.2); + color: hsla(300, 70%, 20%, 0.8); + font-weight: 560; + padding: 0.1rem 0.3rem; + border: 1px solid var(--color-border-dark-tertiary); + border-radius: 0.25rem; + white-space: nowrap; + word-break: break-all; } + li label.compteur { display: inline-block; flex-direction: row; @@ -1067,15 +1077,6 @@ li label.compteur { max-width: 90%; } -a.roll-text.content-link { - color: hsla(300, 70%, 40%, 0.5); - font-weight: bold; - border: 1px solid var(--color-border-dark-tertiary); - border-radius: 0.25rem; - white-space: nowrap; - word-break: break-all; -} - .window-app.sheet .window-content .tooltip:hover .tooltiptext { top: 2rem; left: 2rem; diff --git a/system.json b/system.json index ae6483e6..fe151af8 100644 --- a/system.json +++ b/system.json @@ -1,9 +1,9 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "12.0.33", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.33/rddsystem.zip", - "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.33/system.json", + "version": "12.0.34", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.34/rddsystem.zip", + "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.34/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": { "minimum": "11", diff --git a/templates/apps/link-text-roll-alchimie.hbs b/templates/apps/link-text-roll-alchimie.hbs deleted file mode 100644 index e52fd8d3..00000000 --- a/templates/apps/link-text-roll-alchimie.hbs +++ /dev/null @@ -1,8 +0,0 @@ - -{{~manip}} {{termes~}} - diff --git a/templates/apps/link-text-roll-carac-competence.hbs b/templates/apps/link-text-roll-carac-competence.hbs deleted file mode 100644 index e692ad4e..00000000 --- a/templates/apps/link-text-roll-carac-competence.hbs +++ /dev/null @@ -1,9 +0,0 @@ - -{{~uppercase carac.label~}} -{{#if competence}} / {{upperFirst competence}}{{/if~}} -{{#if diff}} à {{diff}}{{/if~}} - diff --git a/templates/apps/link-text-roll-foundry.hbs b/templates/apps/link-text-roll-foundry.hbs deleted file mode 100644 index 2d12f06b..00000000 --- a/templates/apps/link-text-roll-foundry.hbs +++ /dev/null @@ -1,5 +0,0 @@ - -{{~formula~}} - diff --git a/templates/apps/textroll/chat-link-text-roll.hbs b/templates/apps/textroll/chat-link-text-roll.hbs new file mode 100644 index 00000000..e69de29b diff --git a/templates/apps/textroll/link-text-roll-alchimie.hbs b/templates/apps/textroll/link-text-roll-alchimie.hbs new file mode 100644 index 00000000..05aeaf4d --- /dev/null +++ b/templates/apps/textroll/link-text-roll-alchimie.hbs @@ -0,0 +1,14 @@ + + + {{~param.manip}} {{param.termes~}} + +{{#if options.showlink}} + +{{/if}} + diff --git a/templates/apps/textroll/link-text-roll-carac-competence.hbs b/templates/apps/textroll/link-text-roll-carac-competence.hbs new file mode 100644 index 00000000..acdc67dc --- /dev/null +++ b/templates/apps/textroll/link-text-roll-carac-competence.hbs @@ -0,0 +1,15 @@ + + + {{~uppercase param.carac.label~}} + {{#if param.competence}} / {{upperFirst param.competence}}{{/if~}} + {{#if param.diff}} à {{param.diff}}{{/if~}} +{{#if options.showlink}} + +{{/if}} + diff --git a/templates/apps/textroll/link-text-roll-formula.hbs b/templates/apps/textroll/link-text-roll-formula.hbs new file mode 100644 index 00000000..bb8b0cf5 --- /dev/null +++ b/templates/apps/textroll/link-text-roll-formula.hbs @@ -0,0 +1,10 @@ + +{{~param.formula~}} +{{#if options.showlink}} + +{{/if}} + From 135e5e46a0b02fb8c2b62e8caff00ea85db4f65c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 12 Jan 2025 22:45:07 +0100 Subject: [PATCH 2/2] Support des maladresses --- changelog.md | 22 +++++------ module/apps/rdd-text-roll-editor.js | 18 ++++++--- module/apps/textroll/text-roll-alchimie.js | 2 +- .../textroll/text-roll-carac-competence.js | 2 +- module/apps/textroll/text-roll-formatter.js | 9 ++--- module/apps/textroll/text-roll-formula.js | 2 +- module/item/signedraconique.js | 2 +- module/rdd-combat.js | 37 +++++++++---------- module/rdd-rolltables.js | 10 +++-- module/rdd-utility.js | 1 - .../sort_D_rision_7q0zFbBhxYdf6OZ2.yml | 2 +- ...ables_Maladresse_arm__pXYVWRlCftWdwsBP.yml | 22 +++++------ ..._Maladresses_non_arm__7Py520wVyrjAgS9j.yml | 22 ++++++----- .../apps/textroll/link-text-roll-alchimie.hbs | 7 ++-- .../link-text-roll-carac-competence.hbs | 7 ++-- .../apps/textroll/link-text-roll-formula.hbs | 7 ++-- templates/chat-demande-attaque-etotal.html | 6 +-- templates/chat-demande-defense.html | 12 +++--- 18 files changed, 98 insertions(+), 92 deletions(-) diff --git a/changelog.md b/changelog.md index 544646c3..01b080d1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,17 +1,17 @@ # 12.0 ## 12.0.34 - la tête d'Astrobazzarh -- on peut ajouter des liens "jet de dés" dans les journaux texte -- on peut ajouter des liens "jet de dés" dans les descriptions, notes, ... -- les liens "jet de dés" peuvent être utilisés pour un acteur, ou les items de l'acteurs -- les liens "jet avec caractéristiques" s'appliquent: - - à tous les tokens sélectionnés - - sinon, à l'acteur propriétaire d'un Item - - sinon, au personnage du joueur +- support de liens "jets de dés" + - on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ... + - avec la syntaxe `@roll[...]` on peut ajouter le lien vers: + - un jet de caractéristique/compétence `@roll[carac/competence/difficulte]` / `@roll[carac/difficulte]` / `@roll[carac/competence]` + - une formule foundry `@roll[2d6]` pour lancer 2d6 + - une manipulation alchimique `@roll[couleur vert-bleu]` + - les liens "jet avec caractéristiques" s'appliquent: + - à tous les tokens sélectionnés + - sinon, à l'acteur propriétaire (dans le cas d'un Item) ou à l'acteur courant + - sinon, au personnage du joueur + - on peut poster les liens dans le tchat pour proposer un jet aux joueurs - gestion des blocs secrets dans les descriptions -- on peut ajouter des liens "jet de dés" pour appeler une formule dés de foundry -- les liens "manipulation alchimiques" peuvent être dans les descriptions, notes, ... -- les "manipulation alchimiques" fonctionnent comme tous les autres jets -- on peut poster les liens "jet de dés" dans le tchat et les utiliser depuis le tchat ## 12.0.33 - la vieillesse d'Astrobazzarh - retour de l'expérience pour les joueurs diff --git a/module/apps/rdd-text-roll-editor.js b/module/apps/rdd-text-roll-editor.js index 4ab58bd4..1cadfbfa 100644 --- a/module/apps/rdd-text-roll-editor.js +++ b/module/apps/rdd-text-roll-editor.js @@ -12,10 +12,14 @@ const TEXT_ROLL_MANAGERS = [ new TextRollFormula()]; export class RdDTextEditor { + static registerChatCallbacks(html) { + html.on("click", '.roll-text', async event => await RdDTextEditor.rollText(event)) + } - static async enrichHTML(text, object) { + static async enrichHTML(text, object, options = {}) { const context = { text, object, + options, competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), } @@ -59,14 +63,16 @@ export class RdDTextEditor { const param = node.data('json') const manager = TEXT_ROLL_MANAGERS.find(it => it.code == code) - const text = await TextRollManager.createRollText(manager.template, - param, false) + const text = await TextRollManager.createRollText( + { + code, + template: manager.template, + options: { showLink: false } + }, + param) ChatMessage.create({ content: text }) } } - static registerChatCallbacks(html) { - html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event)) - } } \ No newline at end of file diff --git a/module/apps/textroll/text-roll-alchimie.js b/module/apps/textroll/text-roll-alchimie.js index 4f96a47e..2e6ff20f 100644 --- a/module/apps/textroll/text-roll-alchimie.js +++ b/module/apps/textroll/text-roll-alchimie.js @@ -67,7 +67,7 @@ class AlchimieTextBuilder { const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) const diff = RdDAlchimie.getDifficulte(termes) const recette = (this.context.object instanceof Item && this.context.object.type == ITEM_TYPES.recettealchimique) ? this.context.object : undefined - const replacement = await TextRollManager.createRollText(this.context.template, + const replacement = await TextRollManager.createRollText(this.context, { code: this.context.code, manip, termes, carac, diff, recetteid: recette?.id, diff --git a/module/apps/textroll/text-roll-carac-competence.js b/module/apps/textroll/text-roll-carac-competence.js index dc91300e..1f0f23c2 100644 --- a/module/apps/textroll/text-roll-carac-competence.js +++ b/module/apps/textroll/text-roll-carac-competence.js @@ -74,7 +74,7 @@ class CaracCompetenceTextBuilder { const carac = RdDCarac.caracDetails(rollMatch.carac) if (carac) { const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.context.competences, rollMatch.competence) : undefined - const replacement = await TextRollManager.createRollText(this.context.template, + const replacement = await TextRollManager.createRollText(this.context, { code: this.context.code, carac: carac, diff --git a/module/apps/textroll/text-roll-formatter.js b/module/apps/textroll/text-roll-formatter.js index 40b6bbd9..7e0dbc05 100644 --- a/module/apps/textroll/text-roll-formatter.js +++ b/module/apps/textroll/text-roll-formatter.js @@ -1,11 +1,10 @@ export class TextRollManager { - static async createRollText(template, param, showLink = true) { - return await renderTemplate(template, { - param: param, - options: { showlink: showLink } - }) + static async createRollText(context, param) { + return await renderTemplate(context.template, { + param, options: context.options + }) } static getNode(event) { diff --git a/module/apps/textroll/text-roll-formula.js b/module/apps/textroll/text-roll-formula.js index 416777c1..5b025024 100644 --- a/module/apps/textroll/text-roll-formula.js +++ b/module/apps/textroll/text-roll-formula.js @@ -40,7 +40,7 @@ class FormulaTextBuilder { async replaceMatch(rollMatch, i) { if (rollMatch.formula) { - const replacement = await TextRollManager.createRollText(this.context.template, + const replacement = await TextRollManager.createRollText(this.context, { code: this.context.code, formula: rollMatch.formula, diff --git a/module/item/signedraconique.js b/module/item/signedraconique.js index 42c34498..f37063a0 100644 --- a/module/item/signedraconique.js +++ b/module/item/signedraconique.js @@ -106,7 +106,7 @@ export class RdDItemSigneDraconique extends RdDItem { } static async randomSigneDescription() { - return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false); + return await RdDRollTables.drawTextFromRollTable("Signes draconiques", {toChat:false}); } } \ No newline at end of file diff --git a/module/rdd-combat.js b/module/rdd-combat.js index fc3d9409..dc4a6035 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -472,15 +472,15 @@ export class RdDCombat { /* -------------------------------------------- */ static registerChatCallbacks(html) { for (let button of [ - '#parer-button', - '#esquiver-button', - '#particuliere-attaque', - '#encaisser-button', - '#appel-chance-defense', - '#appel-destinee-defense', - '#appel-chance-attaque', - '#appel-destinee-attaque', - '#echec-total-attaque', + '.parer-button', + '.esquiver-button', + '.particuliere-attaque', + '.encaisser-button', + '.appel-chance-defense', + '.appel-destinee-defense', + '.appel-chance-attaque', + '.appel-destinee-attaque', + '.echec-total-attaque', ]) { html.on("click", button, event => { const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( @@ -539,22 +539,22 @@ export class RdDCombat { const compId = event.currentTarget.attributes['data-compid']?.value; switch (button) { - case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); - case '#parer-button': return this.parade(attackerRoll, armeParadeId); - case '#esquiver-button': return this.esquive(attackerRoll, compId, competence); - case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll); - case '#echec-total-attaque': return this._onEchecTotal(attackerRoll); + case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); + case '.parer-button': return this.parade(attackerRoll, armeParadeId); + case '.esquiver-button': return this.esquive(attackerRoll, compId, competence); + case '0encaisser-button': return this.encaisser(attackerRoll, defenderRoll); + case '.echec-total-attaque': return this._onEchecTotal(attackerRoll); - case '#appel-chance-attaque': return this.attacker.rollAppelChance( + case '.appel-chance-attaque': return this.attacker.rollAppelChance( () => this.attaqueChanceuse(attackerRoll), () => this._onEchecTotal(attackerRoll)); - case '#appel-chance-defense': return this.defender.rollAppelChance( + case '.appel-chance-defense': return this.defender.rollAppelChance( () => this.defenseChanceuse(attackerRoll, defenderRoll), () => this.afficherOptionsDefense(attackerRoll, defenderRoll, { defenseChance: true })); - case '#appel-destinee-attaque': return this.attacker.appelDestinee( + case '.appel-destinee-attaque': return this.attacker.appelDestinee( () => this.attaqueSignificative(attackerRoll), () => { }); - case '#appel-destinee-defense': return this.defender.appelDestinee( + case '.appel-destinee-defense': return this.defender.appelDestinee( () => this.defenseDestinee(defenderRoll), () => { }); } @@ -967,7 +967,6 @@ export class RdDCombat { async _onAttaqueEchec(rollData) { console.log("RdDCombat.onAttaqueEchec >>>", rollData); await RdDResolutionTable.displayRollData(rollData, this.attacker, 'chat-resultat-attaque.html'); - } /* -------------------------------------------- */ diff --git a/module/rdd-rolltables.js b/module/rdd-rolltables.js index a80e94d5..16e74554 100644 --- a/module/rdd-rolltables.js +++ b/module/rdd-rolltables.js @@ -1,3 +1,4 @@ +import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js"; export class RdDRollTables { @@ -28,8 +29,8 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async drawTextFromRollTable(tableName, toChat) { - const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat); + static async drawTextFromRollTable(tableName, options = {}) { + const drawResult = await RdDRollTables.genericGetTableResult(tableName, options.toChat); return drawResult.text; } @@ -101,9 +102,10 @@ export class RdDRollTables { /* -------------------------------------------- */ static async getMaladresse(options = { toChat: false, arme: false }) { - return await RdDRollTables.drawTextFromRollTable( + const maladresse = await RdDRollTables.drawTextFromRollTable( options.arme ? "Maladresse armé" : "Maladresses non armé", - options.toChat); + options); + return await RdDTextEditor.enrichHTML(maladresse, undefined, {showLink:false}) } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 66090cfa..7d6aff52 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -699,7 +699,6 @@ export class RdDUtility { RdDCoeur.registerChatCallbacks(html) RdDTextEditor.registerChatCallbacks(html) - // Gestion spécifique message passeurs html.on("click", '.tmr-passeur-coord a', event => { let coord = event.currentTarget.attributes['data-tmr-coord'].value; diff --git a/packs_src/sorts-hypnos/sort_D_rision_7q0zFbBhxYdf6OZ2.yml b/packs_src/sorts-hypnos/sort_D_rision_7q0zFbBhxYdf6OZ2.yml index ea0c5bc8..9beab6ca 100644 --- a/packs_src/sorts-hypnos/sort_D_rision_7q0zFbBhxYdf6OZ2.yml +++ b/packs_src/sorts-hypnos/sort_D_rision_7q0zFbBhxYdf6OZ2.yml @@ -19,7 +19,7 @@ system:

Si un personnage ainsi rendu dérisoire participe à un combat, il peut tenter une fois par round de lancer une plaisanterie en guise d’attaque (tout en esquivant/parant normalement). Il joue pour cela @roll[APPARENCE/Comédie] - à -@roll[1d4] (ce d4 résume les conditions ponctuelles plus ou moins propices, et + à @roll[-1d4] (ce d4 résume les conditions ponctuelles plus ou moins propices, et il est en fait soustrait du bonus de +4 conféré par le sort). Puis selon la réussite, on obtient un ajustement :

diff --git a/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml b/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml index d7b9deb2..b6dcd07f 100644 --- a/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml +++ b/packs_src/tables-diverses/tables_Maladresse_arm__pXYVWRlCftWdwsBP.yml @@ -22,9 +22,9 @@ results: flags: {} type: text text: >- - Ami bousculé : Le compagnon bousculé doit réussir - @roll[Empathie/Vigilance] à - -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. + Ami bousculé : Le compagnon bousculé doit réussir + @roll[Empathie/Vigilance] à @roll[-1d6] ou être en + demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: @@ -40,7 +40,7 @@ results: - _id: APqyDePFzBaROB6i flags: {} type: text - text: 'Chute : Encaissement à -1d6 sur la table des Coups non mortels.' + text: 'Chute : Encaissement à @roll[-1d6] sur la table des Coups non mortels.' img: icons/svg/d20-black.svg weight: 1 range: @@ -73,7 +73,7 @@ results: flags: {} type: text text: >- - Arme choquée : L’arme utilisée joue un jet de Résistance à -@roll[2d6] et perd ce + Arme choquée : L’arme utilisée joue un jet de Résistance à @roll[-2d6] et perd ce nombre de points de résistance en cas d’échec. img: icons/svg/d20-black.svg weight: 1 @@ -91,7 +91,7 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -@roll[1d6] ou être en demi-surprise + Déséquilibré : Réussir @roll[Agilité/Vigilance] à @roll[-1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -125,7 +125,7 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -@roll[1d6] ou être en demi-surprise + Déséquilibré : Réussir @roll[Agilité/Vigilance] à @roll[-1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -143,7 +143,7 @@ results: flags: {} type: text text: >- - Arme choquée : L’arme utilisée joue un jet de Résistance à -@roll[2d6] et perd ce + Arme choquée : L’arme utilisée joue un jet de Résistance à @roll[-2d6] et perd ce nombre de points de résistance en cas d’échec. img: icons/svg/d20-black.svg weight: 1 @@ -176,7 +176,7 @@ results: - _id: c61AFRaP9poCmr9B flags: {} type: text - text: 'Chute : Encaissement à -1d6 sur la table des Coups non mortels.' + text: 'Chute : Encaissement à @roll[-1d6] sur la table des Coups non mortels.' img: icons/svg/d20-black.svg weight: 1 range: @@ -194,8 +194,8 @@ results: type: text text: >- Ami bousculé : Le compagnon bousculé doit réussir - @roll[Empathie/Vigilance] à - -@roll[1d6] ou être en demi-surprise jusqu’à la fin du round suivant. + @roll[Empathie/Vigilance] à @roll[-1d6] ou être en + demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: diff --git a/packs_src/tables-diverses/tables_Maladresses_non_arm__7Py520wVyrjAgS9j.yml b/packs_src/tables-diverses/tables_Maladresses_non_arm__7Py520wVyrjAgS9j.yml index 0d458b14..4e5efc79 100644 --- a/packs_src/tables-diverses/tables_Maladresses_non_arm__7Py520wVyrjAgS9j.yml +++ b/packs_src/tables-diverses/tables_Maladresses_non_arm__7Py520wVyrjAgS9j.yml @@ -22,8 +22,9 @@ results: flags: {} type: text text: >- - Ami bousculé : Le compagnon bousculé doit réussir Empathie/Vigilance à - -1d6 ou être en demi-surprise jusqu’à la fin du round suivant. + Ami bousculé : Le compagnon bousculé doit réussir + @roll[Empathie/Vigilance] à @roll[-1d6] ou être en + demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: @@ -39,7 +40,7 @@ results: - _id: 1DtaMqWygL8BjZjw flags: {} type: text - text: 'Chute : Encaissement à -1d6 sur la table des Coups non mortels.' + text: 'Chute : Encaissement à @roll[-1d6] sur la table des Coups non mortels.' img: icons/svg/d20-black.svg weight: 1 range: @@ -56,7 +57,8 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise + Déséquilibré : Réussir @roll[Agilité/Vigilance] + à @roll[-1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -73,7 +75,7 @@ results: - _id: kyAKakRIPGKr6Gdy flags: {} type: text - text: 'Faux mouvement : Perte de 2d6 points d’endurance.' + text: 'Faux mouvement : Perte de @roll[2d6] points d’endurance.' img: icons/svg/d20-black.svg weight: 1 range: @@ -90,7 +92,8 @@ results: flags: {} type: text text: >- - Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise + Déséquilibré : Réussir @roll[Agilité/Vigilance] + à @roll[-1d6] ou être en demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 @@ -107,7 +110,7 @@ results: - _id: NY1uI3k3YbJKQddk flags: {} type: text - text: 'Chute : Encaissement à -1d6 sur la table des Coups non mortels.' + text: 'Chute : Encaissement à @roll[-1d6] sur la table des Coups non mortels.' img: icons/svg/d20-black.svg weight: 1 range: @@ -124,8 +127,9 @@ results: flags: {} type: text text: >- - Ami bousculé : Le compagnon bousculé doit réussir Empathie/Vigilance à - -1d6 ou être en demi-surprise jusqu’à la fin du round suivant. + Ami bousculé : Le compagnon bousculé doit réussir + @roll[Empathie/Vigilance] à @roll[-1d6] ou être en + demi-surprise jusqu’à la fin du round suivant. img: icons/svg/d20-black.svg weight: 1 range: diff --git a/templates/apps/textroll/link-text-roll-alchimie.hbs b/templates/apps/textroll/link-text-roll-alchimie.hbs index 05aeaf4d..929a9f30 100644 --- a/templates/apps/textroll/link-text-roll-alchimie.hbs +++ b/templates/apps/textroll/link-text-roll-alchimie.hbs @@ -3,12 +3,11 @@ data-json="{{json-stringify param}}" data-manip="{{param.manip}}" data-termes="{{param.termes}}" - {{#if recetteid}}data-recetteid="{{param.recetteid}}"{{/if}} -> + {{#if recetteid}}data-recetteid="{{param.recetteid}}"{{/if}}> {{~param.manip}} {{param.termes~}} -{{#if options.showlink}} +{{~#if options.showlink}} -{{/if}} +{{/if~}} diff --git a/templates/apps/textroll/link-text-roll-carac-competence.hbs b/templates/apps/textroll/link-text-roll-carac-competence.hbs index acdc67dc..af0528c8 100644 --- a/templates/apps/textroll/link-text-roll-carac-competence.hbs +++ b/templates/apps/textroll/link-text-roll-carac-competence.hbs @@ -3,13 +3,12 @@ data-json="{{json-stringify param}}" data-carac-code="{{param.carac.code}}" {{#if competence}}data-competence="{{param.competence}}"{{/if~}} - {{#if diff}}data-diff="{{param.diff}}"{{/if~}} -> + {{#if diff}}data-diff="{{param.diff}}"{{/if~}}> {{~uppercase param.carac.label~}} {{#if param.competence}} / {{upperFirst param.competence}}{{/if~}} {{#if param.diff}} à {{param.diff}}{{/if~}} -{{#if options.showlink}} +{{~#if options.showlink}} -{{/if}} +{{/if~}} diff --git a/templates/apps/textroll/link-text-roll-formula.hbs b/templates/apps/textroll/link-text-roll-formula.hbs index bb8b0cf5..35adcb41 100644 --- a/templates/apps/textroll/link-text-roll-formula.hbs +++ b/templates/apps/textroll/link-text-roll-formula.hbs @@ -1,10 +1,9 @@ + data-roll-formula="{{param.formula}}"> {{~param.formula~}} -{{#if options.showlink}} +{{~#if options.showlink}} -{{/if}} +{{/if~}} diff --git a/templates/chat-demande-attaque-etotal.html b/templates/chat-demande-attaque-etotal.html index c72007d7..2364ddc5 100644 --- a/templates/chat-demande-attaque-etotal.html +++ b/templates/chat-demande-attaque-etotal.html @@ -3,21 +3,21 @@
{{#if (eq attacker.type 'personnage')}} {{#unless essais.attaqueChance}} - Faire appel à la chance
{{/unless}} {{#if (gt attacker.system.compteurs.destinee.value 0)}} - Utiliser la destinée
{{/if}} {{/if}} - Tirer la maladresse ! diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index 4a8a0bd7..7357e12c 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -20,14 +20,14 @@ {{#if essais.defense}} {{#unless essais.defenseChance}} {{#if (eq defender.type 'personnage')}} - Faire appel à la chance
{{/if}} {{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}} - Utiliser la destinée @@ -36,7 +36,7 @@ {{/unless}} {{else}} {{#each armes as |arme key|}} - Parer avec {{arme.name}} @@ -52,7 +52,7 @@
{{/each}} {{#if mainsNues}} -
Parer à mains nues à {{diffLibre}}{{#if arme.nbUsage}} (Utilisations : {{arme.nbUsage}}){{/if}} @@ -61,7 +61,7 @@ {{/if}} {{#if (ne attaqueCategorie 'tir')}} {{#each esquives as |esquive key|}} - {{esquive.name}} @@ -76,7 +76,7 @@ {{/if}} {{/if}} {{/unless}} - Encaisser à {{plusMoins dmg.total}} {{#if (eq dmg.mortalite 'non-mortel')~}}