From 969bc3b573d19af82c57852e47fc432ee57e983e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 12 Jan 2025 20:00:13 +0100 Subject: [PATCH] =?UTF-8?q?Liens=20de=20jets=20de=20d=C3=A9s=20dans=20le?= =?UTF-8?q?=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}} +