From 792558ac84f155767ae7d52f76e6f8fa63eb5e9c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 11 Jan 2025 17:32:43 +0100 Subject: [PATCH] Support @roll[2d6] --- changelog.md | 3 +- module/actor/base-actor-reve-sheet.js | 2 +- module/apps/rdd-text-roll.js | 138 +++++++++++++----- module/constants.js | 16 +- module/item-sheet.js | 2 +- module/journal/journal-sheet.js | 2 +- module/rdd-main.js | 1 + module/rdd-roll.js | 2 +- ...bs => link-text-roll-carac-competence.hbs} | 2 +- templates/apps/link-text-roll-foundry.hbs | 3 + templates/partial-roll-competences.html | 4 +- 11 files changed, 119 insertions(+), 56 deletions(-) rename templates/apps/{link-text-roll.hbs => link-text-roll-carac-competence.hbs} (84%) create mode 100644 templates/apps/link-text-roll-foundry.hbs diff --git a/changelog.md b/changelog.md index 1f3b5e0b..6c9c2de4 100644 --- a/changelog.md +++ b/changelog.md @@ -3,8 +3,9 @@ - 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 de dés" d'"un item non lié à un acteur agit sur les tokens sélectionnés +- les liens "jet de dés" d'un item non lié à un acteur agit sur les tokens sélectionnés - gestion des blocs secrets dans les descriptions +- on peut ajouter des liens "jet de dés" pour appeler une formule de foundry ## 12.0.33 - la vieillesse d'Astrobazzarh - retour de l'expérience pour les joueurs diff --git a/module/actor/base-actor-reve-sheet.js b/module/actor/base-actor-reve-sheet.js index 6d387ae5..6c0fc1ff 100644 --- a/module/actor/base-actor-reve-sheet.js +++ b/module/actor/base-actor-reve-sheet.js @@ -48,7 +48,7 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet { } }], { renderSheet: true }) ) - this.html.find('.roll-carac-competence').click(async event => await RdDTextEditor.rollText(event, this.actor)) + this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) if (this.options.vueDetaillee) { // On carac change diff --git a/module/apps/rdd-text-roll.js b/module/apps/rdd-text-roll.js index 0dd65f91..bc99b087 100644 --- a/module/apps/rdd-text-roll.js +++ b/module/apps/rdd-text-roll.js @@ -4,55 +4,113 @@ import { SystemCompendiums } from "../settings/system-compendiums.js"; import { RdDItemCompetence } from "../item-competence.js"; import { ACTOR_TYPES } from "../item.js"; -const XREGEXP_ROLL = XRegExp("@roll\\[(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)(\\/(?[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?(/(?[\\+\\-]?\\d+))?\\]", '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 de caractéristique/compétence depuis + * les journaux/descriptions + */ +class TextRollCaracCompetence { + + static async onReplaceRoll(context) { + const competences = await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage); + const handler = new TextRollCaracCompetence(context.text, competences) + context.text = await handler.replaceRollCaracCompetence() + } + + 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 path = RdDCarac.caracDetails(caracCode)?.path + const actors = actor ? [actor] : canvas.tokens.controlled.map(it => it.actor).filter(it => it) + actors.filter(it => foundry.utils.getProperty(it, path) != undefined) + .forEach(it => it.doRollCaracCompetence(caracCode, competence, diff)) + } + } + + constructor(text, competences) { + this.text = text + this.competences = competences + } + + async replaceRollCaracCompetence() { + await XRegExp.forEach(this.text, XREGEXP_ROLL_CARAC_COMP, async (rollMatch, i) => await this._replaceOne(rollMatch, i)) + return this.text + } + + async _replaceOne(rollMatch, i) { + const carac = RdDCarac.caracDetails(rollMatch.carac) + if (carac) { + const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.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.text = this.text.replace(rollMatch[0], replacement) + } + } +} + +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 rddTextEditor = new RdDTextEditor(text) - const replacedRolls = await rddTextEditor.replaceRolls() - return await TextEditor.enrichHTML(replacedRolls, { + const context = { text } + await TextRollCaracCompetence.onReplaceRoll(context) + await TextRollFoundry.onReplaceRoll(context) + return await TextEditor.enrichHTML(context.text, { relativeTo: object, secrets: object?.isOwner, async: true }) } - constructor(text) { - this.original = text - } - - async replaceRolls() { - if (!this.updated) { - this.updated = this.original - await XRegExp.forEach(this.original, XREGEXP_ROLL, async (rollMatch, i) => await this._replaceOneRoll(rollMatch)) - } - return this.updated - } - - async _replaceOneRoll(rollMatch) { - const carac = RdDCarac.caracDetails(rollMatch.carac); - const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), - rollMatch.competence) : undefined - - if (carac) { - - const replacement = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/apps/link-text-roll.hbs`, { - carac: carac, - competence: competence?.name, - diff: rollMatch.diff - }); - this.updated = this.updated.replace(rollMatch[0], replacement); - } - } - static async rollText(event, actor) { - const caracCode = event.currentTarget.attributes['data-carac-code'].value; - const competence = event.currentTarget.attributes['data-competence']?.value; - const diff = event.currentTarget.attributes['data-diff']?.value - - const path = RdDCarac.caracDetails(caracCode)?.path - const actors = actor ? [actor] : canvas.tokens.controlled.map(it => it.actor).filter(it => it) - actors.filter(it => foundry.utils.getProperty(it, path) != undefined) - .forEach(it => it.doRollCaracCompetence(caracCode, competence, diff)) + await TextRollCaracCompetence.onRollText(event, actor) + await TextRollFoundry.onRollText(event, actor) } + } \ No newline at end of file diff --git a/module/constants.js b/module/constants.js index a930be62..58088ed8 100644 --- a/module/constants.js +++ b/module/constants.js @@ -1,13 +1,13 @@ -export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon'; -export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon'; -export const LOG_HEAD = 'RdD | '; +export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon' +export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon' +export const LOG_HEAD = 'RdD | ' -export const HIDE_DICE = 'hide'; -export const SHOW_DICE = 'show'; +export const HIDE_DICE = 'hide' +export const SHOW_DICE = 'show' -export const ENTITE_INCARNE = 'incarne'; -export const ENTITE_NONINCARNE = 'nonincarne'; -export const ENTITE_BLURETTE = 'blurette'; +export const ENTITE_INCARNE = 'incarne' +export const ENTITE_NONINCARNE = 'nonincarne' +export const ENTITE_BLURETTE = 'blurette' export const RDD_CONFIG = { niveauEthylisme : [ diff --git a/module/item-sheet.js b/module/item-sheet.js index 3f2b6bde..13cf5e91 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -208,7 +208,7 @@ export class RdDItemSheet extends ItemSheet { this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).actionHerbe(this.item)); 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-carac-competence').click(async event => await RdDTextEditor.rollText(event, this.actor)) + this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) this.html.find('.alchimie-tache a').click((event) => { let actor = this._getEventActor(event); if (actor) { diff --git a/module/journal/journal-sheet.js b/module/journal/journal-sheet.js index 852a2d15..9e864635 100644 --- a/module/journal/journal-sheet.js +++ b/module/journal/journal-sheet.js @@ -23,6 +23,6 @@ export class RdDJournalSheet extends JournalTextPageSheet { activateListeners(html) { super.activateListeners(html); - html.find('.roll-carac-competence').click(async event => await RdDTextEditor.rollText(event, this.actor)) + html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) } } \ No newline at end of file diff --git a/module/rdd-main.js b/module/rdd-main.js index 126d3278..e00089d6 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -76,6 +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" /** * RdD system diff --git a/module/rdd-roll.js b/module/rdd-roll.js index c7c69271..b76e64b0 100644 --- a/module/rdd-roll.js +++ b/module/rdd-roll.js @@ -173,7 +173,7 @@ export class RdDRoll extends Dialog { this.updateRollResult(html); this.html.find("[name='diffLibre']").val(this.rollData.diffLibre); }); - this.html.find('.roll-carac-competence').change((event) => { + this.html.find('.roll-text').change((event) => { const competence = event.currentTarget.value this.rollData.competence = this.rollData.competences.find(it => Grammar.equalsInsensitive(it.name, competence)) this.updateRollResult(html); diff --git a/templates/apps/link-text-roll.hbs b/templates/apps/link-text-roll-carac-competence.hbs similarity index 84% rename from templates/apps/link-text-roll.hbs rename to templates/apps/link-text-roll-carac-competence.hbs index 2e8c306d..93652db1 100644 --- a/templates/apps/link-text-roll.hbs +++ b/templates/apps/link-text-roll-carac-competence.hbs @@ -1,4 +1,4 @@ - diff --git a/templates/apps/link-text-roll-foundry.hbs b/templates/apps/link-text-roll-foundry.hbs new file mode 100644 index 00000000..7902ab20 --- /dev/null +++ b/templates/apps/link-text-roll-foundry.hbs @@ -0,0 +1,3 @@ + +{{~formula~}} + diff --git a/templates/partial-roll-competences.html b/templates/partial-roll-competences.html index 10785bd6..e69a9063 100644 --- a/templates/partial-roll-competences.html +++ b/templates/partial-roll-competences.html @@ -1,7 +1,7 @@ {{#if @root.competences}}
- - {{#select ''}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-competence.html"}} {{/select}}