Compare commits

...

23 Commits

Author SHA1 Message Date
7e8da49912 Fix Hook init usage in v12, upgrade version 2025-01-14 00:40:42 +01:00
b524716ede Fix Hook init usage in v12 2025-01-14 00:39:28 +01:00
72a9752820 Fix Hook init usage in v12 2025-01-14 00:23:04 +01:00
8e578c6566 Merge pull request 'Fix: lien jets de dés' (#739) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#739
2025-01-13 23:44:45 +01:00
5ac9c682d9 Support difficulté numérique 2025-01-13 22:34:34 +01:00
6de19eb357 Convertir tous les jets de dés dans le tchat 2025-01-13 22:27:13 +01:00
90d096a6df Utilisation des class au lieu d'id
Un seul fichier oublié sur un changement précédent (pas de vrai
sauvegarde dans VSCode...)
2025-01-13 22:03:18 +01:00
c733644f3a Jets de compétence avec carac imposée
Fonctionne maintenant correctement

Pour les créatures/entitées: on fait au mieux, mais ça ne correspond
pas forcément bien, car les carac/compétences ne correspondent
pas toujours
2025-01-13 21:44:02 +01:00
de9d3bbb48 Difficultés aléatoires dans les maladresses 2025-01-13 20:10:11 +01:00
efdffd171c Support de difficultés aléatoires
Par exemple: `@roll[vue/vigil/-1d6]`
pour  "VUE / Vigilance à -1d6"
2025-01-13 19:46:55 +01:00
8406c8434a Fix: lien jets de dés
- les boutons pour envoyer dans le tchat sont affichés
- les jets de carac utilisent bien les compétences et difficulté
2025-01-13 19:25:55 +01:00
a4b474970c Merge pull request 'Fin des liens "jet de dés"' (#738) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#738
2025-01-12 23:02:19 +01:00
135e5e46a0 Support des maladresses 2025-01-12 22:56:11 +01:00
969bc3b573 Liens de jets de dés dans le tchat 2025-01-12 22:56:11 +01:00
a9eb101c9d Merge pull request 'Liens jets de dés' (#737) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#737
2025-01-12 16:15:33 +01:00
d53da1f011 Jets d'alchimie dans descriptions/journaux
On ne se limite plus aux manipulations alchimiques, et les jets
apparaissent comme tous les autres types de jets
2025-01-12 02:38:31 +01:00
ab0f7e563f Ajout de jets de dés dans les compendiums 2025-01-12 00:39:17 +01:00
57c41a0218 Utiliser perception/reve pour les créatures
Ces caractéristiques remplacent toutes les autres
2025-01-11 19:45:58 +01:00
1b75decb18 Utiliser les fenêtres de jets pour les jets 2025-01-11 19:29:29 +01:00
551438f514 Correction sur les liens de jets de dés
- correction jet de rêve actuel
- utilisation du personnage du joueur
2025-01-11 19:04:38 +01:00
792558ac84 Support @roll[2d6] 2025-01-11 17:32:43 +01:00
06aff9a3c0 Liens jets de dés dans les journaux 2025-01-11 02:21:11 +01:00
7e736a00d7 Gestion des blocs secrets dans les descriptions 2025-01-11 02:19:56 +01:00
81 changed files with 857 additions and 377 deletions

View File

@ -1,8 +1,17 @@
# 12.0
## 12.0.34 - la tête d'Astrobazzarh
- 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
- 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
## 12.0.33 - la vieillesse d'Astrobazzarh
- retour de l'expérience pour les joueurs

View File

@ -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";
/* -------------------------------------------- */
/**
@ -45,8 +45,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
cssClass: this.isEditable ? "editable" : "locked",
limited: this.actor.limited,
owner: this.actor.isOwner,
biographie: await RdDTextEditor.enrichHTML(this.actor.system.biographie),
notes: await RdDTextEditor.enrichHTML(this.actor.system.notes),
biographie: await RdDTextEditor.enrichHTML(this.actor.system.biographie, this.actor),
notes: await RdDTextEditor.enrichHTML(this.actor.system.notes, this.actor),
});
foundry.utils.mergeObject(formData.calc, {
surenc: this.actor.computeMalusSurEncombrement(),
@ -222,7 +222,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
}
// Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true))
this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', {resistance:true}))
this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence'))

View File

@ -1850,26 +1850,6 @@ export class RdDActor extends RdDBaseActorSang {
return undefined;
}
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(compName);
await this.openRollDialog({
name: 'jet-competence',
label: 'Jet ' + Grammar.apostrophe('de', competence.name),
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: {
alias: this.getAlias(),
carac: this.system.carac,
selectedCarac: this.getCaracByName(caracName),
selectedCaracName: caracName,
diffLibre: diff,
competence: competence,
show: { title: options?.title ?? '' }
},
callbackAction: r => this.$onRollCompetence(r, options)
});
}
/* -------------------------------------------- */
async rollTache(id, options = {}) {
RdDEmpoignade.checkEmpoignadeEnCours(this)

View File

@ -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";
@ -28,7 +28,7 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
this.html.find('.button-encaissement').click(async event => this.actor.encaisser())
this.html.find('.roll-carac').click(async event => {
this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes['data-carac-name'].value))});
this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes['data-carac-name'].value))})
this.html.find('.roll-competence').click(async event => this.actor.rollCompetence(RdDSheetUtility.getItemId(event)));
this.html.find('.endurance-plus').click(async event => this.actor.santeIncDec("endurance", 1));
this.html.find('.endurance-moins').click(async event => this.actor.santeIncDec("endurance", -1));
@ -48,7 +48,9 @@ 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))
this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event))
if (this.options.vueDetaillee) {
// On carac change

View File

@ -294,6 +294,25 @@ export class RdDBaseActorReve extends RdDBaseActor {
createCallbackAppelAuMoral() { return this.createEmptyCallback(); }
async _onCloseRollDialog(html) { }
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(compName);
await this.openRollDialog({
name: 'jet-competence',
label: competence? 'Jet ' + Grammar.apostrophe('de', competence.name) : `Jet sans compétence (${compName})`,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
rollData: {
alias: this.getAlias(),
carac: this.system.carac,
selectedCarac: this.getCaracByName(caracName),
selectedCaracName: caracName,
diffLibre: diff,
competence: competence,
show: { title: options?.title ?? '' }
},
callbackAction: r => this.$onRollCompetence(r, options)
});
}
/**
* Méthode pour faire un jet prédéterminer sans ouvrir la fenêtre de dialogue
* @param {*} caracName code ou label de la caractéristique. On peut utiliser 'intel' pour Intellect.
@ -344,14 +363,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
competences: this.itemTypes['competence']
},
callbackAction: r => this.$onRollCaracResult(r)
});
})
}
/* -------------------------------------------- */
async rollCarac(caracName, jetResistance = undefined) {
async rollCarac(caracName, options = {}) {
if (Grammar.equalsInsensitive(caracName, 'taille')) {
return
}
foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false })
RdDEmpoignade.checkEmpoignadeEnCours(this)
let selectedCarac = this.getCaracByName(caracName)
console.log("selectedCarac", selectedCarac)
@ -362,7 +381,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
rollData: {
selectedCarac: selectedCarac,
competences: this.itemTypes['competence'],
jetResistance: jetResistance ? caracName : undefined
diffLibre: options.diff ?? 0,
jetResistance: options.resistance ? caracName : undefined
},
callbackAction: r => this.$onRollCaracResult(r)
});

View File

@ -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";
/* -------------------------------------------- */
/**
@ -36,8 +36,8 @@ export class RdDBaseActorSheet extends ActorSheet {
img: this.actor.img,
name: this.actor.name,
system: this.actor.system,
description: await RdDTextEditor.enrichHTML(this.actor.system.description),
notesmj: await RdDTextEditor.enrichHTML(this.actor.system.notesmj),
description: await RdDTextEditor.enrichHTML(this.actor.system.description, this.actor),
notesmj: await RdDTextEditor.enrichHTML(this.actor.system.notesmj, this.actor),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable),
effects: this.actor.effects
}

View File

@ -81,7 +81,6 @@ export class RdDBaseActor extends Actor {
}
}
static getRealActor(actorId, tokenId) {
if (tokenId) {
let token = canvas.tokens.get(tokenId)
@ -161,8 +160,11 @@ export class RdDBaseActor extends Actor {
return RdDBaseActor.$findCaracByName(carac, name);
}
mapCarac(caracCode) { return caracCode }
getCaracByName(name) {
switch (Grammar.toLowerCaseNoAccent(name)) {
name = this.mapCarac(Grammar.toLowerCaseNoAccent(name))
switch (name) {
case 'reve-actuel': case 'reve actuel':
return this.getCaracReveActuel();
case 'chance-actuelle': case 'chance-actuelle':

View File

@ -1,4 +1,6 @@
import { Grammar } from "../grammar.js";
import { ITEM_TYPES } from "../item.js";
import { LIST_CARAC_AUTRES } from "../rdd-carac.js";
import { RdDBaseActorSang } from "./base-actor-sang.js";
export class RdDCreature extends RdDBaseActorSang {
@ -32,4 +34,16 @@ export class RdDCreature extends RdDBaseActorSang {
}
}
mapCarac(caracCode) {
switch (caracCode) {
case 'vue': case 'ouie': case 'odoratgout': case 'empathie': case 'perception':
return 'perception'
case 'agilite':
return 'force'
case 'force': case 'constitution': case 'taille': case 'reve': case 'volonte':
return caracCode
}
return undefined
}
}

View File

@ -117,4 +117,14 @@ export class RdDEntite extends RdDBaseActorReve {
super.setEntiteReveAccordee(actor)
}
}
mapCarac(caracCode) {
switch (caracCode) {
case 'taille':
case 'reve':
return caracCode
}
return 'reve'
}
}

View File

@ -6,8 +6,8 @@ import { ExportScriptarium } from "./export-scriptarium.js";
import { CATEGORIES_COMPETENCES, CATEGORIES_DRACONIC, Mapping } from "./mapping.js";
export class RdDActorExportSheet extends RdDActorSheet {
static async init() {
await loadTemplates([
static init() {
loadTemplates([
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessure.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessures.hbs",
@ -23,6 +23,7 @@ export class RdDActorExportSheet extends RdDActorSheet {
])
Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false, label: "Feuille simplifiée" })
}
static get defaultOptions() {
return foundry.utils.mergeObject(RdDActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/actor-encart-sheet.hbs",

View File

@ -34,7 +34,6 @@ const XREGEXP_WEAPON_MANIEMENT = "(?<maniement>(" + Misc.join(Object.keys(MANIEM
const XREGEXP_SORT_VOIE = "(?<voies>[OHNT](\\/[OHNT])*)"
const XREGEXP_SORT_NAME = "(?<name>[^\\(]+)"
// const XREGEXP_SORT_CASE = "(?<coord>([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2})+)"
const XREGEXP_SORT_CASE = "(?<coord>([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2}))"
const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE

View File

@ -0,0 +1,78 @@
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 registerChatCallbacks(html) {
html.on("click", '.roll-text', async event => await RdDTextEditor.rollText(event))
}
static async enrichHTML(text, object, options = {showlink:true}) {
const context = {
text,
object,
options,
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);
}
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(
{
code,
template: manager.template,
options: { showLink: false }
},
param)
ChatMessage.create({
content: text
})
}
}
}

View File

@ -1,54 +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 } from "../item.js";
const XREGEXP_ROLL = XRegExp("@roll\\[(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?(/(?<diff>[\\+\\-]?\\d+))?\\]", 'giu')
export class RdDTextEditor {
static async enrichHTML(text) {
const rddTextEditor = new RdDTextEditor(text)
const replacedRolls = await rddTextEditor.replaceRolls()
return await TextEditor.enrichHTML(replacedRolls, { 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))
}
}

View File

@ -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 = "(?<termes>(\\w|-)+)"
const REGEX_ALCHIMIE_MANIP = "(?<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,
{
code: this.context.code,
manip, termes, carac, diff, recetteid: recette?.id,
})
this.context.text = this.context.text.replace(rollMatch[0], replacement);
}
}
}

View File

@ -0,0 +1,98 @@
import "../xregexp-all.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 REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?"
const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?"
const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF
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 = await this.calculDiff(node)
const actors = this.getSelectedActors(actor)
actors.forEach(async it => await this.doRoll(it, caracCode, competence, diff))
}
}
async calculDiff(node) {
const diff = node.data('diff') ?? 0
if (!Number.isInteger(diff)) {
const roll = new Roll(diff)
await roll.evaluate()
await roll.toMessage({ flavor: `La difficulté de ${diff} a donné ${roll.total}` })
return roll.total
}
return diff
}
async doRoll(actor, caracCode, competence, diff) {
caracCode = actor.mapCarac(caracCode)
if (caracCode) {
if (competence) {
await actor.rollCaracCompetence(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,
{
code: this.context.code,
carac: carac,
competence: competence?.name,
diff: rollMatch.diff,
})
this.context.text = this.context.text.replace(rollMatch[0], replacement)
}
}
}

View File

@ -0,0 +1,13 @@
export class TextRollManager {
static async createRollText(context, param) {
return await renderTemplate(context.template, {
param, options: context.options
})
}
static getNode(event) {
return $(event.currentTarget)?.parents(".roll-text-link");
}
}

View File

@ -0,0 +1,51 @@
import "../xregexp-all.js";
import { TextRollManager } from "./text-roll-formatter.js";
const REGEXP_ROLL_FORMULA = "(?<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,
{
code: this.context.code,
formula: rollMatch.formula,
})
this.context.text = this.context.text.replace(rollMatch[0], replacement)
}
}
}

View File

@ -1,6 +1,7 @@
import { Misc } from "./misc.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
/**
@ -198,6 +199,7 @@ export class ChatUtility {
static async onCreateChatMessage(chatMessage, options, id) {
if (chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, {showLink:false}) })
}
}
}

View File

@ -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';

View File

@ -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 : [

View File

@ -1,6 +1,5 @@
import { RdDItemSort } from "./item-sort.js";
import { RdDUtility } from "./rdd-utility.js";
import { RdDAlchimie } from "./rdd-alchimie.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDGemme } from "./rdd-gemme.js";
@ -14,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
@ -98,8 +97,8 @@ export class RdDItemSheet extends ItemSheet {
name: this.item.name,
system: this.item.system,
actorId: this.actor?.id,
description: await RdDTextEditor.enrichHTML(this.item.system.description),
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj),
description: await RdDTextEditor.enrichHTML(this.item.system.description, this.item),
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable),
competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage),
@ -121,18 +120,17 @@ export class RdDItemSheet extends ItemSheet {
formData.competences = formData.competences.filter(it => it.isCompetenceArme())
}
if (this.item.type == ITEM_TYPES.recettecuisine) {
formData.ingredients = await RdDTextEditor.enrichHTML(this.object.system.ingredients)
formData.ingredients = await RdDTextEditor.enrichHTML(this.item.system.ingredients, this.item)
}
if (this.item.type == ITEM_TYPES.extraitpoetique) {
formData.extrait = await RdDTextEditor.enrichHTML(this.object.system.extrait)
formData.texte = await RdDTextEditor.enrichHTML(this.object.system.texte)
formData.extrait = await RdDTextEditor.enrichHTML(this.item.system.extrait, this.item)
formData.texte = await RdDTextEditor.enrichHTML(this.item.system.texte, this.item)
}
if (this.item.type == ITEM_TYPES.recettealchimique) {
const manipulation = RdDAlchimie.processManipulation(this.item, this.actor?.id);
formData.manipulation = await RdDTextEditor.enrichHTML(manipulation)
formData.utilisation = await RdDTextEditor.enrichHTML(this.object.system.utilisation)
formData.enchantement = await RdDTextEditor.enrichHTML(this.object.system.enchantement)
formData.sureffet = await RdDTextEditor.enrichHTML(this.object.system.sureffet)
formData.manipulation = await RdDTextEditor.enrichHTML(this.item.system.manipulation, this.item)
formData.utilisation = await RdDTextEditor.enrichHTML(this.item.system.utilisation, this.item)
formData.enchantement = await RdDTextEditor.enrichHTML(this.item.system.enchantement, this.item)
formData.sureffet = await RdDTextEditor.enrichHTML(this.item.system.sureffet, this.item)
}
if (this.item.type == ITEM_TYPES.gemme) {
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
@ -208,18 +206,8 @@ 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('.alchimie-tache a').click((event) => {
let actor = this._getEventActor(event);
if (actor) {
let recetteId = event.currentTarget.attributes['data-recette-id'].value;
let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value;
let tacheData = event.currentTarget.attributes['data-alchimie-data'].value;
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
} else {
ui.notifications.info("Impossible trouver un acteur pour réaliser cette tache Alchimique.");
}
});
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()));

View File

@ -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});
}
}

View File

@ -0,0 +1,29 @@
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js";
import { SYSTEM_RDD } from "../constants.js";
import { Misc } from "../misc.js";
export class RdDJournalSheet extends JournalTextPageSheet {
static register() {
DocumentSheetConfig.unregisterSheet(JournalEntryPage, "core", JournalTextPageSheet)
DocumentSheetConfig.registerSheet(JournalEntryPage,
SYSTEM_RDD,
RdDJournalSheet, {
types: ["text"],
makeDefault: true,
});
}
async getData(options) {
const journalData = await super.getData(options);
journalData.editor.content = await RdDTextEditor.enrichHTML(journalData.document.text.content, this.object)
return journalData
}
activateListeners(html) {
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))
}
}

View File

@ -1,48 +1,8 @@
/* -------------------------------------------- */
import { Misc } from "./misc.js";
const matchOperations = new RegExp(/@(\w*){([\w\-]+)}/ig);
const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
/* -------------------------------------------- */
export class RdDAlchimie {
/* -------------------------------------------- */
static processManipulation(recette, actorId = undefined) {
let manip = recette.system.manipulation;
let matchArray = manip.match(matchOperations);
if (matchArray) {
for (let matchStr of matchArray) {
let result = matchStr.match(matchOperationTerms);
if (result[1] && result[2]) {
let commande = Misc.upperFirst(result[1]);
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
manip = manip.replace(result[0], replacement);
}
}
}
return manip;
}
/* -------------------------------------------- */
static _alchimieCouleur(recette, couleurs, actorId) {
return RdDAlchimie._alchimieLink(recette, couleurs, actorId, 'couleur', 'Température');
}
/* -------------------------------------------- */
static _alchimieConsistance(recette, consistances, actorId) {
return RdDAlchimie._alchimieLink(recette, consistances, actorId, 'consistance', 'Consistance');
}
static _alchimieLink(recette, termes, actorId, tacheAlchimie, labelTache) {
const difficulte = RdDAlchimie.getDifficulte(termes);
const link = actorId ? ` <a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="${tacheAlchimie}" data-alchimie-data="${termes}">` : '';
const endLink = actorId ? '</a>' : '';
return `<span class="alchimie-tache">${link}${labelTache} ${termes} (${difficulte})${endLink}</span>`;
}
/* -------------------------------------------- */
static getDifficulte(aspects) {
let elements = aspects.split('-');
static getDifficulte(termes) {
let elements = termes.split('-');
let composantes = elements.length;
let distincts = Object.keys(Misc.classifyFirst(elements, it => it)).length;
if (distincts == 1) {
@ -58,5 +18,4 @@ export class RdDAlchimie {
}
return 'intellect';
}
}

View File

@ -77,7 +77,7 @@ export class RdDCarac {
static caracDetails(name) {
let entry = Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.code, description: 'caractéristique', onMessage: m => { } })
if (entry && entry.length > 0) {
if (entry) {
return entry
}
return Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.label, description: 'caractéristique' })

View File

@ -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');
}
/* -------------------------------------------- */

View File

@ -75,6 +75,8 @@ import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"
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-editor.js"
/**
* RdD system
@ -85,9 +87,9 @@ export class SystemReveDeDragon {
static start() {
const system = new SystemReveDeDragon()
Hooks.once('init', async () => await system.onInit())
Hooks.once('init', () => system.onInit())
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d))
Hooks.once('ready', async () => await system.onReady())
Hooks.once('ready', () => system.onReady())
}
constructor() {
@ -121,7 +123,7 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */
/* Foundry VTT Initialization */
/* -------------------------------------------- */
async onInit() {
onInit() {
game.system.rdd = this
this.AppAstrologie = AppAstrologie
@ -185,7 +187,7 @@ export class SystemReveDeDragon {
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet)
await RdDActorExportSheet.init()
RdDActorExportSheet.init()
RdDItemSheet.register(RdDSigneDraconiqueItemSheet)
RdDItemSheet.register(RdDRencontreItemSheet)
@ -196,6 +198,7 @@ export class SystemReveDeDragon {
RdDItemSheet.register(RdDIngredientItemSheet)
RdDItemSheet.register(RdDServiceItemSheet)
RdDItemSheet.register(RdDBlessureItemSheet)
RdDJournalSheet.register()
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
types: [

View File

@ -8,6 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js";
import { ACTOR_TYPES } from "./item.js";
/**
* Extend the base Dialog entity to select roll parameters
@ -62,7 +63,7 @@ export class RdDRoll extends Dialog {
forceDiceResult: -1
}
// Mini patch :Ajout du rêve actuel
if (actor.system.type == "personnage") {
if (actor.type == ACTOR_TYPES.personnage) {
defaultRollData.carac["reve-actuel"] = actor.system.reve.reve
}
@ -131,11 +132,12 @@ export class RdDRoll extends Dialog {
console.log('RdDRoll.activateListeners', this.rollData);
// Update html, according to rollData
if (this.rollData.competence) {
const defaut_carac = this.rollData.competence.system.defaut_carac
if (!this.rollData.selectedCarac && this.rollData.competence) {
// Set the default carac from the competence item
this.rollData.selectedCarac = this.rollData.carac[defaut_carac];
this.html.find("[name='carac']").val(defaut_carac);
this.rollData.selectedCarac = this.rollData.carac[this.actor.mapCarac(this.rollData.competence.system.defaut_carac)]
}
if (this.rollData.selectedCarac) {
this.html.find("[name='carac']").val(RdDCarac.caracDetails(this.rollData.selectedCarac.label).code)
}
if (this.rollData.selectedSort) {
this.setSelectedSort(this.rollData.selectedSort);
@ -173,7 +175,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);

View File

@ -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;
}
@ -103,7 +104,7 @@ export class RdDRollTables {
static async getMaladresse(options = { toChat: false, arme: false }) {
return await RdDRollTables.drawTextFromRollTable(
options.arme ? "Maladresse armé" : "Maladresses non armé",
options.toChat);
options)
}
}

View File

@ -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
@ -106,7 +107,7 @@ export class RdDUtility {
}
/* -------------------------------------------- */
static async preloadHandlebarsTemplates() {
static preloadHandlebarsTemplates() {
const templatePaths = [
//Character Sheets
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html',
@ -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) {
@ -339,7 +341,7 @@ export class RdDUtility {
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
return loadTemplates(templatePaths);
loadTemplates(templatePaths);
}
static getItem(itemId, actorId = undefined) {
@ -695,6 +697,7 @@ 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 => {

View File

@ -184,16 +184,16 @@ system:
value: '+0'
label: +dom
derivee: true
vitesse:
type: string
value: 12/28
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 12/28
label: Vitesse
derivee: true
protection:
type: number
value: 4
@ -207,28 +207,19 @@ system:
value: 0
label: Sur-encombrement
description: >-
<h1>Description</h1>
<p>Description Le chrasme (prononcer krasme) est une sorte de cafard
g&eacute;ant &agrave; carapace de crabe aux jointures poilues. Il mesure en
moyenne 1 m de haut sur 1m50 de long, et peut peser jusqu&rsquo;&agrave; 50
kg. Dot&eacute; de mandibules ac&eacute;r&eacute;es et puissantes, il est
redout&eacute; pour son venin mortel.</p>
<h1>M&oelig;urs</h1>
<p>Le chrasme vit dans les lieux sombres, cavernes et souterrains, o&ugrave;
il se nourrit de tout. Paranos le Moindre affirme qu&rsquo;&agrave;
d&eacute;faut d&rsquo;une meilleure ch&egrave;re, il peut m&ecirc;me se
sustenter de cailloux. Il d&eacute;teste la lumi&egrave;re comme son cousin
de petite taille, mais a toutefois un comportement diff&eacute;rent: au lieu
de fuir, il entre dans une rage f&eacute;roce et se rue sur le porteur de
lumi&egrave;re pour le r&eacute;duire en charpie. Savez-vous, cher Paranos,
que vous nous faites un peu peur ?</p>
<h1>Venin</h1>
<p>@UUID[Compendium.foundryvtt-reve-de-dragon.maladies-et-poisons.Item.cFMUtU6LZG0mKeDl]{Venin
de chrasme}</p> <p></p>
<h1>Description</h1><p>Description Le chrasme (prononcer krasme) est une
sorte de cafard géant à carapace de crabe aux jointures poilues. Il mesure
en moyenne 1 m de haut sur 1m50 de long, et peut peser jusquà 50 kg. Doté
de mandibules acérées et puissantes, il est redouté pour son venin
mortel.</p><h1>Mœurs</h1><p>Le chrasme vit dans les lieux sombres, cavernes
et souterrains, où il se nourrit de tout. Paranos le Moindre affirme quà
défaut dune meilleure chère, il peut même se sustenter de cailloux. Il
déteste la lumière comme son cousin de petite taille, mais a toutefois un
comportement différent: au lieu de fuir, il entre dans une rage féroce et se
rue sur le porteur de lumière pour le réduire en charpie. Savez-vous, cher
Paranos, que vous nous faites un peu peur
?</p><h1>Venin</h1><p>@UUID[Compendium.foundryvtt-reve-de-dragon.maladies-et-poisons.Item.cFMUtU6LZG0mKeDl]{Venin
de chrasme}</p><p></p>
race: ''
notesmj: ''
ownership:
@ -311,7 +302,13 @@ prototypeToken:
texture: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.32
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736537299708
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
flags: {}
_key: '!actors!yL1XStIKWxGnhKvR'

View File

@ -203,10 +203,10 @@ system:
<p>En combat, quand un drakkule r&eacute;ussit une particuli&egrave;re et
cause au moins une blessure l&eacute;g&egrave;re, il reste accroch&eacute;
&agrave; sa victime qui perd alors automatiquement 1d6 points
&agrave; sa victime qui perd alors automatiquement @roll[1d6] points
d&rsquo;endurance par round sous l&rsquo;effet de la saign&eacute;e. Quand
l&rsquo;endurance tombe &agrave; z&eacute;ro, le drakkule continue &agrave;
la vider de son sang &agrave; raison de 1d6 points de vie par round. Le
la vider de son sang &agrave; raison de @roll[1d6] points de vie par round. Le
drakkule ne se d&eacute;tache que <em>bless&eacute; gravement </em>ou
<em>sonn&eacute;</em>. Pour se d&eacute;gager, la victime ne peut utiliser
que Corps &agrave; corps (totaliser 2 points d&rsquo;empoignade) ou une

View File

@ -137,7 +137,7 @@ system:
elles-m&ecirc;mes, leur grincement involontaire est une torture. Toute
personne se trouvant dans un rayon de 10m doit manquer un jet
d&rsquo;OU&Iuml;E &agrave; +5. Si le jet r&eacute;ussit, perte de 1 point
d&rsquo;endurance, puis jet de VOLONT&Eacute; &agrave; -5. Si le jet de
d&rsquo;endurance, puis jet de @roll[volonté/-5]. Si le jet de
VOLONT&Eacute; &eacute;choue, le personnage est sonn&eacute;
jusqu&rsquo;&agrave; la fin du round suivant.</p>

View File

@ -174,8 +174,8 @@ system:
agressivit&eacute; s&rsquo;appliquant aux humano&iuml;des. S&rsquo;agissant
d&rsquo;un pouvoir inn&eacute;, elles n&rsquo;ont ni &agrave; monter dans
les TMR, ni &agrave; d&eacute;penser de points de r&ecirc;ve. La victime
doit jouer un jet de r&eacute;sistance standard, r-8, et en cas
d&rsquo;&eacute;chec, r&eacute;ussir un jet de VOLONT&Eacute; &agrave; -3
doit jouer un jet de r&eacute;sistance standard, @roll[reve-actuel/-8], et en cas
d&rsquo;&eacute;chec, r&eacute;ussir un jet de @roll[Volonté/-3]
pour pouvoir attaquer la harpie. Le JR n&rsquo;est &agrave; jouer
qu&rsquo;une seule fois, tandis qu&rsquo;en cas d&rsquo;&eacute;chec, le jet
de VOLONT&Eacute; est &agrave; jouer tous les rounds. La non

View File

@ -201,7 +201,7 @@ system:
<p>La sir&egrave;ne a un chant attractif pouvant porter jusqu&rsquo;&agrave;
50 m. Toute personne, homme ou femme, percevant ce chant, m&ecirc;me faible
et lointain, doit tenter un jet de VOLONT&Eacute; &agrave; -3. Sur toute
et lointain, doit tenter un jet de @roll[Volonté/-3]. Sur toute
r&eacute;ussite, le personnage est libre de sa d&eacute;cision"; sur tout
&eacute;chec, il est irr&eacute;sistiblement attir&eacute; vers la source du
chant. Quand plusieurs sir&egrave;nes chantent simultan&eacute;ment, le jet
@ -220,7 +220,7 @@ system:
corps, m&ecirc;me visage. Certaines sir&egrave;nes, plus rarement, donnent
des illusions d&rsquo;hommes. Contrairement aux illusions des Yeux
d&rsquo;Hypnos, l&rsquo;illusion des sir&egrave;nes donne lieu &agrave; un
jet de r&eacute;sistance (standard, r-8). Comme pour les chants, ce JR est
jet de r&eacute;sistance (standard, @roll[reve-actuel/-8]). Comme pour les chants, ce JR est
global : s&rsquo;il r&eacute;ussit, toutes les sir&egrave;nes apparaissent
sous leur v&eacute;ritable apparence; s&rsquo;il &eacute;choue, toutes sont
per&ccedil;ues sous leur apparence illusoire.</p>

View File

@ -228,8 +228,8 @@ system:
d&eacute;solations et autres lieux o&ugrave; Thanatos a laiss&eacute; son
empreinte. Ils poss&egrave;dent le m&ecirc;me pouvoir de non
agressivit&eacute; s&rsquo;appliquant aux humano&iuml;des que la harpie. La
victime doit jouer un jet de r&eacute;sistance standard, r-8, et en cas
d&rsquo;&eacute;chec, r&eacute;ussir un jet de VOLONT&Eacute; &agrave; -3
victime doit jouer un jet de r&eacute;sistance standard, @roll[reve-actuel/-8], et en cas
d&rsquo;&eacute;chec, r&eacute;ussir un jet de @roll[Volonté/-3]
pour pouvoir attaquer le tournedent. Le JR n&rsquo;est &agrave; jouer
qu&rsquo;une seule fois, et en cas d&rsquo;&eacute;chec, le jet de
VOLONT&Eacute; est &agrave; jouer tous les rounds. La non agressivit&eacute;

View File

@ -17,9 +17,8 @@ system:
&agrave; long terme, mais tout autant de l&rsquo;empathie pour bluffer lors
des surench&egrave;res.</p>
<p>Pour simuler une partie, jouer un jet de CHANCE &agrave; z&eacute;ro
(ajust&eacute; astrologiquement), suivi d&rsquo;un jet d&rsquo;EMPATHIE/Jeu
&agrave; z&eacute;ro, et additionner les points de t&acirc;che obtenus par
<p>Pour simuler une partie, jouer un jet de @roll[chance/0]
(ajust&eacute; astrologiquement), suivi d&rsquo;un jet d&rsquo;@roll[EMPATHIE/Jeu/0], et additionner les points de t&acirc;che obtenus par
les deux jets. Le vainqueur est celui qui en totalise le plus.</p>
descriptionmj: ''
type: carte

View File

@ -104,7 +104,7 @@ system:
D&egrave;s qu&rsquo;il se sent l&eacute;s&eacute;, offens&eacute;, victime
d&rsquo;un tort m&ecirc;me insignifiant, il&nbsp;faut qu&rsquo;il se venge
et que sa vengeance soit&nbsp;mortelle. Il peut jouer un jet de
VOLONT&Eacute;/ moral &agrave; z&eacute;ro. Si le jet r&eacute;ussit, il
@roll[Volonté/0] (avec moral). Si le jet r&eacute;ussit, il
peut encore laisser couver sa haine ; s&rsquo;il &eacute;choue, il doit agir
imm&eacute;diatement. Il est conseill&eacute; que le gardien des r&ecirc;ves
prenne alors le contr&ocirc;le du personnage s&rsquo;il s&rsquo;agit

View File

@ -104,7 +104,7 @@ system:
pareille. Son moral tombe directement &agrave; -3 et ne pourra pas remonter
tant que durera la possession. Chaque fois qu&rsquo;une action dangereuse se
pr&eacute;sente, incluant toute action de combat y compris l&rsquo;esquive,
la victime doit jouer un jet de VOLONT&Eacute;/moral &agrave; z&eacute;ro.
la victime doit jouer un jet de @roll[Volonté/0] avec moral.
Si ce jet &eacute;choue, la victime ne fait rien que trembler et claquer des
dents.</p>
race: ''

View File

@ -132,8 +132,8 @@ system:
les d&eacute;solations et les ruines. Il combat avec son bec
ac&eacute;r&eacute;. Outre les dommages qu&rsquo;il cause (+dom +1), chaque
fois qu&rsquo;il porte un coup, m&ecirc;me une simple
contusion-&eacute;raflure, sa victime doit r&eacute;ussir un jet de points
de r&ecirc;ve actuels ajust&eacute; n&eacute;gativement au niveau de
contusion-&eacute;raflure, sa victime doit r&eacute;ussir un jet de @roll[reve-actuel]
ajust&eacute; n&eacute;gativement au niveau de
l&rsquo;entit&eacute;, ou perdre 1 point de chance. Les points de chance
ainsi perdus peuvent &ecirc;tre regagn&eacute;s selon la r&egrave;gle
normale. D&eacute;truite, l&rsquo;entit&eacute; ne laisse pour tout vestige

View File

@ -158,8 +158,8 @@ system:
<p>Les quauquemaires hantent les endroits lugubres et d&eacute;sol&eacute;s,
les ruines principalement. Ils chantent au coucher du soleil, et leur chant
est si lugubre, prometteur d&rsquo;angoisse et de cauchemar, que quiconque
l&rsquo;entend et manque un jet de points de r&ecirc;ve actuels
ajust&eacute; n&eacute;gativement au niveau de l&rsquo;entit&eacute;, ne
l&rsquo;entend et manque un jet de points de @roll[reve-actuel] ajust&eacute;
n&eacute;gativement au niveau de l&rsquo;entit&eacute;, ne
fait que des cauchemars hideux au cours de sa prochaine nuit de sommeil. En
termes de r&egrave;gles, cela signifie : pas de souvenir de
l&rsquo;arch&eacute;type et donc pas de jet de stress au matin ; pas de

View File

@ -134,8 +134,8 @@ system:
n&eacute;cropoles, catacombes et autres lieux de s&eacute;pulture. Comme les
autres entit&eacute;s, leur raison d&rsquo;&ecirc;tre est de
d&eacute;truire. Le spectacle d&rsquo;un squelette est d&rsquo;une horreur
tellement contre nature qu&rsquo;il demande un jet de VOLONT&Eacute;
&agrave; -3. En cas d&rsquo;&eacute;chec, le personnage est frapp&eacute;
tellement contre nature qu&rsquo;il demande un jet de @roll[Volonté/-3].
En cas d&rsquo;&eacute;chec, le personnage est frapp&eacute;
d&rsquo;effroi. En termes de r&egrave;gles, il est en demi- surprise
jusqu&rsquo;&agrave; la fin du round suivant. Une fois d&eacute;truit, les
ossements constitutifs du squelette s&rsquo;&eacute;parpillent sur le sol,

View File

@ -19,8 +19,8 @@ system:
dans une pipe ou pr&eacute;par&eacute;e en d&eacute;coction. Dans les deux
cas, une dose doit &ecirc;tre compos&eacute;e de 7 brins. D&egrave;s la dose
absorb&eacute;e (bue ou fum&eacute;e), le consommateur doit jouer un JR
r-force, c&rsquo;est-&agrave;-dire un jet de points de r&ecirc;ve
ajust&eacute; n&eacute;gativement &agrave; la force de l&rsquo;herbe. Si le
r-force, c&rsquo;est-&agrave;-dire un jet de @roll[reve-actuel] ajust&eacute;
n&eacute;gativement &agrave; la force de l&rsquo;herbe. Si le
JR r&eacute;ussit, aucun effet ne se produit"; s&rsquo;il &eacute;choue, le
consommateur gagne imm&eacute;diatement un nombre de points de r&ecirc;ve
&eacute;gal &agrave; la force de l&rsquo;herbe, puis en &eacute;change,

View File

@ -506,8 +506,8 @@ system:
<p style="box-sizing: border-box; user-select: text; color: #191813;
font-family: CaslonAntique; font-size: 16px; letter-spacing: 1px;
text-align: justify; background-color: #f5f5f0;"><strong style="box-sizing:
border-box; user-select: text;">VOLONT&Eacute;/moral &agrave; -
(degr&eacute; d&rsquo;exotisme) + (Cuisine)</strong></p>
border-box; user-select: text;">@roll[Volonté/Cuisibe] (avec moral) &agrave; -
(degr&eacute; d&rsquo;exotisme) </strong></p>
<p style="box-sizing: border-box; user-select: text; color: #191813;
font-family: CaslonAntique; font-size: 16px; letter-spacing: 1px;

View File

@ -23,31 +23,29 @@ system:
<p>Les points de VUE perdus ne peuvent &ecirc;tre regagn&eacute;s que quand
la maladie est enti&egrave;rement gu&eacute;rie. &Agrave; chaque point de
vie regagn&eacute;, jouer un jet de CONSTITUTION ajust&eacute;
vie regagn&eacute;, jouer un jet de @roll[Constitution] ajust&eacute;
n&eacute;gativement par les points de vie toujours manquants. Puis selon le
r&eacute;sultat:</p>
<ul>
<li><strong><em>Particuli&egrave;re&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</em></strong>Regain de 2 points de VUE</li>
<li><strong><em>Particuli&egrave;re</em></strong>&nbsp; Regain de 2 points
de VUE</li>
<li><strong><em>Normale et significative</em></strong>&nbsp; &nbsp; &nbsp;
Regain de 1 point de VUE</li>
<li><strong><em>Normale et significative</em></strong>&nbsp; Regain de 1
point de VUE</li>
<li><strong><em>&Eacute;chec et &Eacute;chec particulier</em></strong>&nbsp;
<li><strong><em>&Eacute;chec et &Eacute;chec particulier</em></strong>&nbsp;
Aucun regain</li>
<li><strong><em>&Eacute;chec total</em>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</strong>Aggravation, re-perte d&rsquo;un point de VUE</li>
<li><strong><em>&Eacute;chec total</em></strong>&nbsp; Aggravation,
re-perte d&rsquo;un point de VUE</li>
</ul>
<p>Si tous les points de vie ont &eacute;t&eacute; regagn&eacute;s et
qu&rsquo;il manque toujours un ou plusieurs points de VUE, jouer un jet de
CONSTITUTION &agrave; z&eacute;ro toutes les 12 heures, et appliquer les
@roll[Constitution/0] toutes les 12 heures, et appliquer les
m&ecirc;mes r&eacute;sultats que ci-dessus.</p>
<p>Une potion d&rsquo;herbes de soin enchant&eacute;e peut faire regagner

File diff suppressed because one or more lines are too long

View File

@ -16,10 +16,10 @@ system:
<p>Il conf&egrave;re un bonus de +5 &agrave; tous les jets de
DEXT&Eacute;RIT&Eacute;, de Tir et de Lancer, et est suivi d&rsquo;une perte
de 1d6 points d&rsquo;endurance.</p>
de @roll[1d6] points d&rsquo;endurance.</p>
enchantement: >-
<p>Si la potion est enchant&eacute;e, l&rsquo;effet magique n&rsquo;a lieu
que si un jet de r&eacute;sistance standard est &eacute;chou&eacute;.</p>
que si un jet de r&eacute;sistance standard @roll[reve-actuel] est &eacute;chou&eacute;.</p>
<p>L&rsquo;effet se produit alors dans le round cons&eacute;cutif au jet de
r&eacute;sistance (au lieu de 2 minutes) et voit sa dur&eacute;e
@ -32,8 +32,8 @@ system:
sur-effet se produise &nbsp;: la perte totale du go&ucirc;t et de
l&rsquo;odorat (ODORAT-GO&Ucirc;T tombe &agrave; z&eacute;ro).</p>
<p>Pour le regain, jouer tous les matins un jet d&rsquo;ODORAT- GO&Ucirc;T
(originel) &agrave; z&eacute;ro et regagner selon le bar&egrave;me des
<p>Pour le regain, jouer tous les matins un jet
@roll[odorat-gout] (originel)et regagner selon le bar&egrave;me des
points de t&acirc;che.</p>
manipulation: >-
<ul><li>Piler à froid <strong>2 doigts de graisse de carpe</strong> et

View File

@ -23,7 +23,8 @@ system:
points d&rsquo;endurance.</p>
enchantement: >-
<p>Si la potion est enchant&eacute;e, l&rsquo;effet magique n&rsquo;a lieu
que si un jet de r&eacute;sistance standard est &eacute;chou&eacute;.</p>
que si un jet de r&eacute;sistance standard @roll[reve-actuel] est
&eacute;chou&eacute;.</p>
<p>L&rsquo;effet se produit alors dans le round cons&eacute;cutif au jet de
r&eacute;sistance (au lieu de 2 minutes) et voit sa dur&eacute;e

View File

@ -18,8 +18,8 @@ system:
<p>Si un personnage ainsi rendu dérisoire participe à un combat, il peut
tenter une fois par round de lancer une plaisanterie en guise dattaque
(tout en esquivant/parant normalement). Il joue pour cela APPARENCE/ Comédie
à -1d4 (ce d4 résume les conditions ponctuelles plus ou moins propices, et
(tout en esquivant/parant normalement). Il joue pour cela @roll[APPARENCE/Comédie/-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 :</p>
@ -56,10 +56,10 @@ system:
</table>
<p>Tous les autres engagés dans la mêlée capables de comprendre la blague, y
compris les compagnons du plaisantin, jouent alors VOLONTÉ/<em>moins
compris les compagnons du plaisantin, jouent alors @roll[Volonté] <em>moins
</em>moral à + (ajustement) + (Comédie facultativement). Tout échec provoque
un état de demi-surprise pour la fin du round et tout le round suivant. En
cas déchec total à son jet dAPPARENCE/Comédie, le plaisantin est le seul à
cas déchec total à son jet d@roll[Apparence/Comédie], le plaisantin est le seul à
rire de sa blague, et entre automatiquement en demi-surprise jusquà la fin
du round suivant.</p>
descriptionmj: ''

View File

@ -7,7 +7,7 @@ system:
description: >-
<p>Ce sort provoque lillusion dune grande fatigue, qui est interprétée
comme une fatigue réelle. La victime marque instantanément 6 cases de
fatigue, puis joue un jet de VOLONTÉ à -5 avec un éventuel bonus de +1 par
fatigue, puis joue un jet de @roll[Volonté/-5] avec un éventuel bonus de +1 par
point de CONSTITUTION au-dessus de 15. Si le jet de VOLONTÉ réussit, il ny
a pas dautre conséquence que les cases de fatigue. Si le jet échoue, tout
dépend alors de lactivité actuelle de la cible. Si elle est en condition de

View File

@ -9,7 +9,7 @@ system:
humano&iuml;des. La suggestion d&rsquo;une id&eacute;e drolatique plonge la
cible dans un irr&eacute;pressible fou-rire, automatique le premier round.
Puis pour les rounds suivants, la cible doit r&eacute;ussir un jet de
VOLONT&Eacute;/ <em>moins </em>moral &agrave; -5, ou continuer &agrave;
@roll[Volonté/-5] <em>moins </em>moral, ou continuer &agrave;
rire. Tant que la cible rit, elle est consid&eacute;r&eacute;e en
<em>demi-surprise</em>.</p>
descriptionmj: ''

View File

@ -25,7 +25,7 @@ system:
pouvant aller de 0 à 7 (1d8-1). Pour en supporter le goût "étrange et venu
dailleurs", les convives doivent réussir un jet de :</p>
<p><strong>VOLONTÉ/moral à - (degré dexotisme) + (Cuisine)</strong></p>
<p><strong>@roll[Volonté/Cuisine] (avec moral) à - (degré dexotisme)</strong></p>
<p>Si le jet est réussi, le personnage nest pas choqué par lexotisme et
peut même en apprécier la gastronomie. Pour tout échec, le personnage est

View File

@ -7,7 +7,7 @@ system:
description: >-
<p>Leffet de Peur ne sapplique quaux humanoïdes. La suggestion dune
horreur intense cause une peur réelle. La victime doit réussir un jet de
VOLONTÉ à -5 ou être sonnée en cas déchec. Le jet de VOLONTÉ doit être
@roll[Volonté/-5] ou être sonnée en cas déchec. Le jet de VOLONTÉ doit être
renouvelé de round en round jusquà ce quil réussisse. Tant quil échoue,
la victime reste en <em>demi-surprise</em>.</p>
descriptionmj: ''

View File

@ -18,7 +18,7 @@ system:
impossible dobtenir le sosie parfait de quelquun, tout comme il est
difficile à un peintre dobtenir un portrait parfaitement ressemblant. Si un
haut-rêvant désire donner à sa cible la même apparence que quelquun
dautre, il doit jouer un jet de VUE à -8, et obtiendra une ressemblance
dautre, il doit jouer un jet de @roll[Vue/-8], et obtiendra une ressemblance
plus ou moins approchante selon son genre de résultat. Inventer un humanoïde
anonyme quoique doté de traits spécifiques (blond, gros nez, une verrue au
menton, etc.) sobtient sans problème. Comme toujours en ce qui concerne

View File

@ -18,7 +18,7 @@ system:
@UUID[Compendium.foundryvtt-reve-de-dragon.rappel-des-regles.JournalEntry.ZmMoOtUdgjMd4cNs]{Conflit
de sens}. Le cri illusoire dun animal doit être le cri dun animal connu,
et vouloir donner à un humanoïde la même voix que quelquun dautre demande
un jet dOUÏE à -8, avec les mêmes remarques que pour Transfiguration. Noter
un jet d@roll[Ouie/-8], avec les mêmes remarques que pour Transfiguration. Noter
que seule la voix est changée, sans affecter en rien le contenu du discours.
Enfin, de même que la taille reste la même pour les illusions visuelles, le
volume sonore de lillusion auditive est celui de la cible. Une souris ne

View File

@ -37,9 +37,9 @@ system:
créateur de l'objet et non de l'utilisateur, et quand le sort a une durée
HN, c'est également l'heure de naissance du créateur. Le seul paramétrage
inutile est l'heure de naissance de la cible en prévision du jet de
résistance. Quand un JR est possible, il est toujours r-8, quelle que soit
la cible. S'il réussit, le sort se dissipe aussitôt sans revenir vers
l'utilisateur.</p>
résistance. Quand un JR est possible, il est toujours @roll[reve-actuel/-8],
quelle que soit la cible. S'il réussit, le sort se dissipe aussitôt sans
revenir vers l'utilisateur.</p>
<p>L'objet réussit son lancer, sans jet de dés. Lancer un sort via un objet
magique n'est pas plus économique en points de rêve que de la lancer

View File

@ -12,9 +12,9 @@ system:
arr&ecirc;tant totalement la vue. De l&rsquo;int&eacute;rieur, il est
pareillement impossible de voir ce qui se passe &agrave;
l&rsquo;ext&eacute;rieur"; on peut seulement tenter de voir ce qui se passe
&agrave; l&rsquo;int&eacute;rieur en r&eacute;ussissant un jet de VUE
ajust&eacute; n&eacute;gativement par le nombre de points de r&ecirc;ve
d&eacute;pens&eacute;s.</p>
&agrave; l&rsquo;int&eacute;rieur en r&eacute;ussissant un jet de
@roll[Vue] ajust&eacute; n&eacute;gativement par le nombre de points de
r&ecirc;ve d&eacute;pens&eacute;s.</p>
descriptionmj: ''
draconic: Oniros
duree: HN

View File

@ -19,7 +19,7 @@ system:
zombis, et contrairement aux entités de cauchemar incarnées qui peuvent
dépasser cette limite, la caractéristique RÊVE d'un squelette invoqué ne
peut jamais dépasser sa caractéristique TAILLE. Sa hideur est telle que
quiconque l'aperçoit doit réussir un jet de VOLONTÉ à -3 ou être en
quiconque l'aperçoit doit réussir un jet de @roll[VOLONTÉ/-3] ou être en
demi-surprise jusqu'à la fin du round suivant.</p>
<p>Un squelette invoqué est aux ordres de son invocateur et n'agit qu'aux

View File

@ -13,7 +13,7 @@ system:
à zéro) ou subir en retour l'effet de son sort.</p>
<p>Le flétrissement n'est pas définitif. Chaque jour, à lextrême fin du
Château Dormant, la victime peur jouer un jet d'APPARENCE à zéro en prenant
Château Dormant, la victime peur jouer un jet d'@roll[APPARENCE/0] en prenant
non pas son APPARENCE actuelle, mais son APPARENCE initiale. Toute réussite
: regain de 1 point en APPARENCE et de 2 points de Beauté. Tout échec : pas
de regain pour aujourd'hui. Dans tous les cas, ni l'APPARENCE ni la Beauté

View File

@ -10,7 +10,7 @@ system:
maîtrise. Cette dernière est automatique, comme avec les écailles de Narcos,
mais au lieu de coûter des points de rêve, elle coûte un nombre de
<em>points de vie</em> égal au nombre de griffes, chaque point de vie perdu
s'accompagnant d'une perte d'1d6 points d'endurance. Il n'y a pas de jet de
s'accompagnant d'une perte d'@roll[1d6] points d'endurance. Il n'y a pas de jet de
résistance. La maîtrise (et la perte de points de vie) a lieu au moment où
l'objet contenant la griffe est utilisé selon sa fonction : arme frappant,
bague au doigt, bracelet au poignet, etc. Si l'objet n'a pas de fonction

View File

@ -8,7 +8,7 @@ system:
<p>Le principe de fonctionnement de la griffe morbide de Thanatos est
analogue à celui de la simple griffe. C'en est une variante plus mortelle.
La maîtrise ayant lieu, la victime perd autant de points de vie qu'il y a de
griffes morbides, ainsi que 1d6 points d'endurance par point de vie perdu,
griffes morbides, ainsi que @roll[1d6] points d'endurance par point de vie perdu,
puis joue une JR standard r-8. JR réussi, l'effet s'arrête là ; JR échoué,
le mal s'est implanté en elle. Tous les jours, à l'extrême fin du Château
Dormant, la victime de la griffe morbide doit tenter un jet de Vie et en

View File

@ -4,7 +4,7 @@ type: souffle
img: systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp
system:
description: >-
<p>Le vieillissement est de 1d7 ans. Jouer un jet de Constitution ajusté
<p>Le vieillissement est de 1d7 ans. Jouer un jet de @roll[Constitution] ajusté
négativement au nombre dannées perdues. En cas déchec, perte définitive
dun point en Constitution.</p>
descriptionmj: ''

View File

@ -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/-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: 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:
@ -72,7 +73,7 @@ results:
flags: {}
type: text
text: >-
Arme choquée : Larme utilisée joue un jet de Résistance à -2d6 et perd ce
Arme choquée : Larme 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 @roll[Agilité/Vigilance/-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 dendurance.'
text: 'Faux mouvement : Perte de @roll[2d6] points dendurance.'
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 @roll[Agilité/Vigilance/-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 : Larme utilisée joue un jet de Résistance à -2d6 et perd ce
Arme choquée : Larme 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
@ -175,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:
@ -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/-1d6] ou être en
demi-surprise jusquà la fin du round suivant.
img: icons/svg/d20-black.svg
weight: 1
range:

View File

@ -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/-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,8 +57,8 @@ results:
flags: {}
type: text
text: >-
Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise
jusquà la fin du round suivant.
Déséquilibré : Réussir @roll[Agilité/Vigilance/-1d6]
ou être en demi-surprise jusquà la fin du round suivant.
img: icons/svg/d20-black.svg
weight: 1
range:
@ -73,7 +74,7 @@ results:
- _id: kyAKakRIPGKr6Gdy
flags: {}
type: text
text: 'Faux mouvement : Perte de 2d6 points dendurance.'
text: 'Faux mouvement : Perte de @roll[2d6] points dendurance.'
img: icons/svg/d20-black.svg
weight: 1
range:
@ -90,8 +91,8 @@ results:
flags: {}
type: text
text: >-
Déséquilibré : Réussir Agilité/Vigilance à -1d6 ou être en demi-surprise
jusquà la fin du round suivant.
Déséquilibré : Réussir @roll[Agilité/Vigilance/-1d6]
ou être en demi-surprise jusquà la fin du round suivant.
img: icons/svg/d20-black.svg
weight: 1
range:
@ -107,7 +108,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 +125,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/-1d6] ou être en
demi-surprise jusquà la fin du round suivant.
img: icons/svg/d20-black.svg
weight: 1
range:

View File

@ -10,7 +10,8 @@ system:
rêves, soit un Passeur, soit un Messager, dès quelle est visitée par le
demi-rêve du haut-rêvant. Il ny a pas de d7 à tirer, le haut-rêvant choisit
librement ce quil préfère, et la rencontre est considérée automatiquement
maîtrisée, Fleurs, Messagers et Passeurs ayant une force de 2d6 points. Dès
maîtrisée, Fleurs, Messagers et Passeurs ayant une force de @roll[2d6]
points. Dès
quelle a offert son présent, la cité redevient normale en ce qui concerne
le tirage des rencontres; il ny a quun seul présent par cité. La tête de
Dragon prend fin dès que toutes les cités (22) ont été visitées; entretemps,

View File

@ -5,13 +5,13 @@ flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp
system:
description: >-
<p>Un jet dEmpathie à zéro permet de rendre amical un animal non agressif
ou de rendre neutre un animal agressif. Les animaux restent neutres\amicaux
<p>Un jet d@roll[empathie/0] permet de rendre amical un animal non agressif
ou de rendre neutre un animal agressif. Les animaux restent neutres/amicaux
jusquà ce quun événement significatif, agression ou autre, vienne tout
remettre en question. Ce nest pas un lien magique. Un seul jet par animal.
Un animal rendu neutre par ce don ne peut pas ensuite être rendu amical par
un second jet. Enfin létendue de la neutralité\ amitié de lanimal dépend
de chaque espèce et est à décider dans chaque cas particulier par le gardien
un second jet. Enfin létendue de la neutralité/amitié de lanimal dépend de
chaque espèce et est à décider dans chaque cas particulier par le gardien
des rêves. Cumulable.</p>
descriptionmj: ''
frequence: 6
@ -24,7 +24,12 @@ folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.33
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736617623199
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
_key: '!items!wlbbh75GZWks3Ehb'

View File

@ -5,9 +5,9 @@ flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp
system:
description: >-
<p>Un jet dEmpathie à zéro permet de deviner la direction du nord, et dune
manière générale de retrouver une certaine direction quand on est perdu ou
par manque de visibilité (nuit, brouillard, souterrain, etc.).
<p>Un jet d@roll[empathie/0] permet de deviner la direction du nord, et
dune manière générale de retrouver une certaine direction quand on est
perdu ou par manque de visibilité (nuit, brouillard, souterrain, etc.).
Cumulable.</p>
descriptionmj: ''
frequence: 6
@ -20,7 +20,12 @@ folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.33
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736617654367
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
_key: '!items!slnKVCfHbLwbXi4Z'

View File

@ -5,10 +5,10 @@ flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp
system:
description: >-
<p>Un jet de Volonté à zéro permet de sendormir instantanément et de dormir
au moins jusquà la fin de la prochaine heure, même sans aucun point de
fatigue. Permet également de se réveiller au bout dun laps de temps donné,
"programmé" au moment de sendormir. Cumulable.</p>
<p>Un jet de @roll[Volonté/0] permet de sendormir instantanément et de
dormir au moins jusquà la fin de la prochaine heure, même sans aucun point
de fatigue. Permet également de se réveiller au bout dun laps de temps
donné, "programmé" au moment de sendormir. Cumulable.</p>
descriptionmj: ''
frequence: 6
hautrevant: false
@ -20,7 +20,12 @@ folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.33
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736617674311
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
_key: '!items!N6guZDGzzZjt9GrR'

View File

@ -5,8 +5,8 @@ flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp
system:
description: >-
<p>Un jet dEmpathie à zéro permet de deviner que lon vous ment, sans pour
autant connaître la teneur du mensonge. Ne sapplique quau mensonge
<p>Un jet d@roll[empathie/0] permet de deviner que lon vous ment, sans
pour autant connaître la teneur du mensonge. Ne sapplique quau mensonge
volontaire, pas au mensonge par omission ni par ignorance. Cumulable.</p>
descriptionmj: ''
frequence: 6
@ -19,7 +19,12 @@ folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.33
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736617720094
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
_key: '!items!OZZbiBiLlM6Y8lEY'

View File

@ -5,10 +5,10 @@ flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp
system:
description: >-
<p>Un jet de VUE à zéro permet de distinguer une aura bleutée délimitant les
zones magiques dOniros ou entourant les objets enchantés ou les créatures
soumises à leffet dun sort ou dun rituel. Un seul essai par zone, objet
ou personnage. Cumulable.</p>
<p>Un jet de @roll[vue/0] permet de distinguer une aura bleutée délimitant
les zones magiques dOniros ou entourant les objets enchantés ou les
créatures soumises à leffet dun sort ou dun rituel. Un seul essai par
zone, objet ou personnage. Cumulable.</p>
descriptionmj: ''
frequence: 6
hautrevant: false
@ -20,7 +20,12 @@ folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
systemVersion: 12.0.33
coreVersion: '12.331'
createdTime: null
modifiedTime: 1736617743760
lastModifiedBy: Hp9ImM4o9YRTSdfu
compendiumSource: null
duplicateSource: null
_key: '!items!QWouooLkM7pE2yG1'

View File

@ -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,14 +1077,6 @@ li label.compteur {
max-width: 90%;
}
.alchimie-tache {
font-weight: bold;
background: rgb(182, 180, 179);
border: 1px solid rgba(72, 46, 28, 1);
border-radius: 0.25rem;
color: rgba(212, 27, 27, 0.5);
}
.window-app.sheet .window-content .tooltip:hover .tooltiptext {
top: 2rem;
left: 2rem;

View File

@ -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.35",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.35/rddsystem.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.35/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
"minimum": "11",

View File

@ -1,8 +0,0 @@
<span><a class="roll-carac-competence content-link"
{{#if competence}}data-competence="{{competence}}"{{/if~}}
{{#if diff}}data-diff="{{diff}}"{{/if~}}
data-carac-code="{{carac.code}}">
{{~uppercase carac.label~}}
{{#if competence}} / {{upperFirst competence}}{{/if~}}
{{#if diff}} à {{diff}}{{/if~}}
</a></span>

View File

@ -0,0 +1,13 @@
<span class="content-link roll-text-link"
data-code="{{param.code}}"
data-json="{{json-stringify param}}"
data-manip="{{param.manip}}"
data-termes="{{param.termes}}"
{{#if recetteid}}data-recetteid="{{param.recetteid}}"{{/if}}>
<a class="roll-text" data-tooltip="{{upperFirst param.carac.label}}/Alchimie à {{param.diff}}">
{{~param.manip}} {{param.termes~}}
</a>
{{~#if options.showlink}}
<a class="chat-roll-text" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
{{/if~}}
</span>

View File

@ -0,0 +1,14 @@
<span class="content-link roll-text-link"
data-code="{{param.code}}"
data-json="{{json-stringify param}}"
data-carac-code="{{param.carac.code}}"
{{#if param.competence}}data-competence="{{param.competence}}"{{/if~}}
{{#if param.diff}}data-diff="{{param.diff}}"{{/if~}}>
<a class="roll-text">
{{~uppercase param.carac.label~}}
{{#if param.competence}} / {{upperFirst param.competence}}{{/if~}}
{{#if param.diff}} à {{param.diff}}{{/if~}}</a>
{{~#if options.showlink}}
<a class="chat-roll-text" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
{{/if~}}
</span>

View File

@ -0,0 +1,9 @@
<span class="content-link roll-text-link"
data-code="{{param.code}}"
data-json="{{json-stringify param}}"
data-roll-formula="{{param.formula}}">
<a class="roll-text">{{~param.formula~}}</a>
{{~#if options.showlink}}
<a class="chat-roll-text" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
{{/if~}}
</span>

View File

@ -3,21 +3,21 @@
<br>
{{#if (eq attacker.type 'personnage')}}
{{#unless essais.attaqueChance}}
<a class='chat-card-button' id='appel-chance-attaque'
<a class='chat-card-button appel-chance-attaque'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Faire appel à la chance</a>
</a>
<br>
{{/unless}}
{{#if (gt attacker.system.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-attaque'
<a class='chat-card-button appel-destinee-attaque'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Utiliser la destinée</a>
</a>
<br>
{{/if}}
{{/if}}
<a class='chat-card-button' id='echec-total-attaque'
<a class='chat-card-button echec-total-attaque'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Tirer la maladresse !
</a>

View File

@ -2,19 +2,19 @@
<h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4>
{{#if isForce}}
<br>
<a class="chat-card-button" id="particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}">
<a class="chat-card-button particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}">
Attaquer en Force
</a>
{{/if}}
{{#if isRapide}}
<br>
<a class="chat-card-button" id="particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}">
<a class="chat-card-button particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}">
Attaquer en Rapidité
</a>
{{/if}}
{{#if isFinesse}}
<br>
<a class="chat-card-button" id="particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}">
<a class="chat-card-button particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}">
Attaquer en Finesse
</a>
{{/if}}

View File

@ -20,14 +20,14 @@
{{#if essais.defense}}
{{#unless essais.defenseChance}}
{{#if (eq defender.type 'personnage')}}
<a class='chat-card-button' id='appel-chance-defense'
<a class='chat-card-button appel-chance-defense'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Faire appel à la chance</a>
</a>
<br>
{{/if}}
{{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}}
<a class='chat-card-button' id='appel-destinee-defense'
<a class='chat-card-button appel-destinee-defense'
data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'>
Utiliser la destinée</a>
</a>
@ -36,7 +36,7 @@
{{/unless}}
{{else}}
{{#each armes as |arme key|}}
<a class='chat-card-button' id='parer-button'
<a class='chat-card-button parer-button'
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
data-armeid='{{arme._id}}'>
Parer avec {{arme.name}}
@ -52,7 +52,7 @@
<br>
{{/each}}
{{#if mainsNues}}
<a class='chat-card-button' id='parer-button'
<a class='chat-card-button parer-button'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
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|}}
<a class='chat-card-button' id='esquiver-button'
<a class='chat-card-button esquiver-button'
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
{{esquive.name}}
@ -76,7 +76,7 @@
{{/if}}
{{/if}}
{{/unless}}
<a class='chat-card-button' id='encaisser-button'
<a class='chat-card-button encaisser-button'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Encaisser à {{plusMoins dmg.total}}
{{#if (eq dmg.mortalite 'non-mortel')~}}

View File

@ -1,7 +1,7 @@
{{#if @root.competences}}
<div class="form-group">
<label for="roll-carac-competence">Compétence</label>
<select name="roll-carac-competence" class="roll-carac-competence" data-dtype="String">
<label for="roll-text">Compétence</label>
<select name="roll-text" class="roll-text" data-dtype="String">
{{#select ''}}<option value="">Sans compétence</option>
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-competence.html"}}
{{/select}}