From 91717a329020afefac84cfacc391861e29494b58 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck <vincent.vandeme@gmail.com> Date: Tue, 3 Dec 2024 23:25:58 +0100 Subject: [PATCH] =?UTF-8?q?Bouton=20"don=20de=20haut-r=C3=AAve"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pour permettre au MJ de rendre un personnage haut rêvant sans avoir à chercher dans les compendiums --- module/actor-sheet.js | 2 + module/actor.js | 14 +- module/apps/rdd-import-stats.js | 159 +++++++++--------- module/item/tete.js | 25 +++ module/rdd-main.js | 2 + module/rdd-utility.js | 4 +- module/settings/system-compendiums.js | 14 +- templates/actor-sheet.html | 5 +- .../{haut-revant.html => haut-revant.hbs} | 2 +- templates/actor/non-haut-revant.hbs | 41 +++++ templates/actor/non-haut-revant.html | 34 ---- 11 files changed, 175 insertions(+), 127 deletions(-) create mode 100644 module/item/tete.js rename templates/actor/{haut-revant.html => haut-revant.hbs} (99%) create mode 100644 templates/actor/non-haut-revant.hbs delete mode 100644 templates/actor/non-haut-revant.html diff --git a/module/actor-sheet.js b/module/actor-sheet.js index b41baf20..19254bb0 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -214,6 +214,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { }); // Boutons spéciaux MJs this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ")) + this.html.find('.don-de-haut-reve').click(async event => this.actor.addDonDeHautReve()) + this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible()) } diff --git a/module/actor.js b/module/actor.js index badb3492..ccd83847 100644 --- a/module/actor.js +++ b/module/actor.js @@ -38,6 +38,8 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDCombatManager } from "./rdd-combat.js"; +import { RdDItemTete } from "./item/tete.js"; +import { SystemCompendiums } from "./settings/system-compendiums.js"; export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] @@ -87,7 +89,7 @@ export class RdDActor extends RdDBaseActorSang { } $computeIsHautRevant() { - this.system.attributs.hautrevant.value = this.itemTypes['tete'].find(it => Grammar.equalsInsensitive(it.name, 'don de haut-reve')) + this.system.attributs.hautrevant.value = this.itemTypes[ITEM_TYPES.tete].find(it => RdDItemTete.isDonDeHautReve(it)) ? "Haut rêvant" : ""; } @@ -989,6 +991,16 @@ export class RdDActor extends RdDBaseActorSang { }); } + /* -------------------------------------------- */ + async addDonDeHautReve() { + if (!game.user.isGM || this.isHautRevant()) { + return + } + const donHR = await RdDItemTete.teteDonDeHautReve() + if (donHR) { + this.createEmbeddedDocuments('Item', [donHR.toObject()]) + } + } /* -------------------------------------------- */ async reinsertionAleatoire(raison, accessible = tmr => true) { diff --git a/module/apps/rdd-import-stats.js b/module/apps/rdd-import-stats.js index 894f594f..bf6c23bc 100644 --- a/module/apps/rdd-import-stats.js +++ b/module/apps/rdd-import-stats.js @@ -5,12 +5,12 @@ import { RdDBaseActorReve } from "../actor/base-actor-reve.js"; import { Grammar } from "../grammar.js"; import { Misc } from "../misc.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; +import { RdDItemTete } from "../item/tete.js"; const WHITESPACES = "\\s+" const NUMERIC = "[\\+\\-]?\\d+" const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")" -const XREGEXP_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)" + WHITESPACES + NUMERIC_VALUE + "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?" @@ -23,10 +23,11 @@ const compParser = { } const XREGEXP_SORT_VOIE = "[OHNT\\/]+" +const XREGEXP_SORT_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-']+)" const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)"; const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE - + WHITESPACES + XREGEXP_NAME + + WHITESPACES + XREGEXP_SORT_NAME + WHITESPACES + XREGEXP_SORT_CASE + WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))" + WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))" @@ -104,7 +105,7 @@ export class RdDStatBlockParser { return "vaisseau"; } - static async parseStatBlock(statString, type = "npc") { + static async parseStatBlock(statString) { //statString = statBlock03; if (!statString) { @@ -122,10 +123,10 @@ export class RdDStatBlockParser { statString = statString.trim(); // TODO: check for entite - let actorType = RdDStatBlockParser.parseActorType(statString); + let type = RdDStatBlockParser.parseActorType(statString); // Now start carac - let actorData = foundry.utils.deepClone(game.model.Actor[actorType]); + let actorData = foundry.utils.deepClone(game.model.Actor[type]); for (let key in actorData.carac) { let caracDef = actorData.carac[key]; // Parse the stat string for each caracteristic @@ -136,7 +137,7 @@ export class RdDStatBlockParser { } // If creature we need to setup additionnal fields - switch (actorType) { + switch (type) { case "creature": RdDStatBlockParser.parseCreature(statString, actorData) break @@ -147,14 +148,14 @@ export class RdDStatBlockParser { let items = []; // Get skills from compendium - const competences = await SystemCompendiums.getCompetences(actorType); + const competences = await SystemCompendiums.getCompetences(type); //console.log("Competences : ", competences); for (let comp of competences) { - let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu')); + let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[type], 'giu')); if (compMatch) { comp = comp.toObject() comp.system.niveau = Number(compMatch.value); - if (actorType == "creature" || actorType == "entite") { + if (type == "creature" || type == "entite") { comp.system.carac_value = Number(compMatch.carac); if (compMatch.dommages != undefined) { comp.system.dommages = Number(compMatch.dommages); @@ -163,7 +164,7 @@ export class RdDStatBlockParser { } items.push(comp) } - else if (actorType == "personnage") { + else if (type == "personnage") { comp = comp.toObject() items.push(comp) } @@ -213,82 +214,89 @@ export class RdDStatBlockParser { } } - // Attemp to detect spell - let hautRevant = false - let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros") - sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos")) - sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos")) - sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos")) + + if (type == "personnage") { + // Attemp to detect spell + await RdDStatBlockParser.parseHautReve(statString, items); + + RdDStatBlockParser.parsePersonnage(statString, actorData); + } + + let name = RdDStatBlockParser.extractName(type, statString); + + let newActor = RdDBaseActorReve.create({ name, type: type, system: actorData, items }); + + // DUmp.... + console.log(actorData); + } + + static async parseHautReve(statString, items) { + let hautRevant = false; + let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros"); + sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos")); + sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos")); + sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos")); XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'giu'), function (matchSort, i) { - let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name)) + let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name)); if (sort) { - hautRevant = true + hautRevant = true; sort = sort.toObject(); if (matchSort.bonus && matchSort.bonuscase) { - sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}` + sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`; } items.push(sort); } }); if (hautRevant) { - let tetes = await SystemCompendiums.getWorldOrCompendiumItems("tete", "tetes-de-dragon-pour-tous-personnages") - let donHR = tetes.find(t => Grammar.equalsInsensitive(t.name, "Don de Haut-Rêve")) + const donHR = await RdDItemTete.teteDonDeHautReve(); if (donHR) { items.push(donHR.toObject()); } } - if (actorType == "personnage") { + } - let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu')); - actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin' + static parsePersonnage(statString, actorData) { + let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu')); + actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'; - // Get hour name : heure du XXXXX - let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu')); - actorData.heure = this.getHeureKey(heure?.value || "Vaisseau"); + // Get hour name : heure du XXXXX + let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu')); + actorData.heure = this.getHeureKey(heure?.value || "Vaisseau"); - // Get age - let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu')); - if (age?.value) { - actorData.age = Number(age.value); - } - // Get height - let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu')); - if (taille?.value) { - actorData.taille = taille.value; - } - // Get weight - let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu')); - if (poids?.value) { - actorData.poids = poids.value; - } - // Get cheveux - let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu')); - if (cheveux?.value) { - actorData.cheveux = cheveux.value; - } - // Get yeux - let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu')); - if (yeux?.value) { - actorData.yeux = yeux.value; - } - - // Get beauty - let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu')); - if (beaute?.value) { - actorData.beaute = Number(beaute.value); - } + // Get age + let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu')); + if (age?.value) { + actorData.age = Number(age.value); + } + // Get height + let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu')); + if (taille?.value) { + actorData.taille = taille.value; + } + // Get weight + let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu')); + if (poids?.value) { + actorData.poids = poids.value; + } + // Get cheveux + let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu')); + if (cheveux?.value) { + actorData.cheveux = cheveux.value; + } + // Get yeux + let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu')); + if (yeux?.value) { + actorData.yeux = yeux.value; } - // Name is all string before ', né' - let name = RdDStatBlockParser.extractName(actorType, statString); - - let newActor = RdDBaseActorReve.create({ name: name || "Importé", type: actorType, system: actorData, items: items }); - - // DUmp.... - console.log(actorData); + // Get beauty + let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu')); + if (beaute?.value) { + actorData.beaute = Number(beaute.value); + } } static parseCreature(statString, actorData) { @@ -350,24 +358,17 @@ export class RdDStatBlockParser { static extractName(actorType, statString) { switch (actorType) { - case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString); - case "creature": return RdDStatBlockParser.extractNameCreature(statString); + case "personnage": + // Name is all string before first comma ',' + const namePersonnage = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu')); + if (namePersonnage?.value) { + return Misc.upperFirst(namePersonnage?.value); + } } - return RdDStatBlockParser.extractNameCreature(statString); - } - - static extractNamePersonnage(statString) { - let name = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu')); - if (!name?.value) { - name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu')); - } - return Misc.upperFirst(name?.value || "Importé"); - } - - static extractNameCreature(statString) { const name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu')); return Misc.upperFirst(name?.value || "Importé"); } + } /************************************************************************************/ diff --git a/module/item/tete.js b/module/item/tete.js new file mode 100644 index 00000000..f16598cb --- /dev/null +++ b/module/item/tete.js @@ -0,0 +1,25 @@ +import { Grammar } from "../grammar.js" +import { ITEM_TYPES, RdDItem } from "../item.js" +import { SystemCompendiums } from "../settings/system-compendiums.js" + +const DON_HAUT_REVE = "Don de Haut-Rêve" + +export class RdDItemTete extends RdDItem { + + static get defaultIcon() { + return "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp" + } + + static isDonDeHautReve(tete) { + return tete.type == ITEM_TYPES.tete && Grammar.equalsInsensitive(tete.name, DON_HAUT_REVE) + } + + static async teteDonDeHautReve() { + const tetes = await SystemCompendiums.getItems("tetes-de-dragon-pour-tous-personnages", ITEM_TYPES.tete) + const tete = tetes.find(it => RdDItemTete.isDonDeHautReve(it)) + if (!tete) { + ui.notifications.warn(`Impossible de trouver la tête "${DON_HAUT_REVE}", vérifiez le compendium de têtes pour tous personnages`) + } + return tete + } +} diff --git a/module/rdd-main.js b/module/rdd-main.js index 5b857b87..64f78328 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -70,6 +70,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 { RdDItemSort } from "./item-sort.js" +import { RdDItemTete } from "./item/tete.js" /** * RdD system @@ -97,6 +98,7 @@ export class SystemReveDeDragon { ombre: RdDItemOmbre, poison: RdDItemPoison, queue: RdDItemQueue, + tete: RdDItemTete, rencontre: RdDRencontre, service: RdDItemService, signedraconique: RdDItemSigneDraconique, diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 59bc9809..01dd562e 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -145,8 +145,8 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html', - 'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html', - 'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html', + 'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs', + 'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html', diff --git a/module/settings/system-compendiums.js b/module/settings/system-compendiums.js index 663b3c5a..fba598ff 100644 --- a/module/settings/system-compendiums.js +++ b/module/settings/system-compendiums.js @@ -1,5 +1,6 @@ import { ChatUtility } from "../chat-utility.js"; import { HIDE_DICE, SYSTEM_RDD } from "../constants.js"; +import { Grammar } from "../grammar.js"; import { RdDItem } from "../item.js"; import { Misc } from "../misc.js"; import { RdDDice } from "../rdd-dice.js"; @@ -84,15 +85,14 @@ export class SystemCompendiums extends FormApplication { static async getWorldOrCompendiumItems(itemType, compendium) { let items = game.items.filter(it => it.type == itemType) if (compendium) { - const ids = items.map(it => it.id); - const names = items.map(it => it.name.toLowerCase()); - const compendiumItems = await SystemCompendiums.getItems(compendium); - items = items.concat(compendiumItems - .filter(it => it.type == itemType) + const ids = items.map(it => it.id) + const names = items.map(it => Grammar.toLowerCaseNoAccent(it.name)) + const compendiumItems = await SystemCompendiums.getItems(compendium, itemType) + return items.concat(compendiumItems .filter(it => !ids.includes(it.id)) - .filter(it => !names.includes(it.name.toLowerCase()))); + .filter(it => !names.includes(Grammar.equalsInsensitive(it.name)))) } - return items; + return items } static async loadDocument(document) { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 58bf0955..9e772304 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -129,11 +129,10 @@ <div> {{#if system.attributs.hautrevant.value}} <h3>Haut rêvant</h3> - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs"}} {{else}} <h3>Vous n'avez pas le don de haut-rêve</h3> - <p>Attribuer la Tête de Dragon 'Don de Haut Rêve' pour rendre le personnage Haut-Rêvant.</p> - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}} {{/if}} <br><br> </div> diff --git a/templates/actor/haut-revant.html b/templates/actor/haut-revant.hbs similarity index 99% rename from templates/actor/haut-revant.html rename to templates/actor/haut-revant.hbs index 604fca15..74d59386 100644 --- a/templates/actor/haut-revant.html +++ b/templates/actor/haut-revant.hbs @@ -26,7 +26,7 @@ {{/if}} </span> </li> -{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html"}} +{{> "systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs"}} <hr> {{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html"}} diff --git a/templates/actor/non-haut-revant.hbs b/templates/actor/non-haut-revant.hbs new file mode 100644 index 00000000..c91ed10b --- /dev/null +++ b/templates/actor/non-haut-revant.hbs @@ -0,0 +1,41 @@ +{{#if (not system.attributs.hautrevant.value)}} + <p>Attribuer la Tête de Dragon + {{#if options.isGM}} + <a class="chat-card-button don-de-haut-reve" data-tooltip="Donner le don de haut-rêve">Don de Haut Rêve</a> + {{else}} + 'Don de Haut Rêve' + {{/if}} + pour rendre le personnage Haut-Rêvant.</p> +{{/if}} +<li class="item flexrow"> + <span class="competence-label">Seuil de Rêve :</span> + <span> + {{#if options.isGM}} + <input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/> + {{else}} + {{system.reve.seuil.value}} + {{/if}} + </span> +</li> +<li class="item flexrow" > + <span class="competence-label">Refoulement : </span> + <span> + {{#if options.isGM}} + <input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/> + {{else}} + {{system.reve.refoulement.value}} + {{/if}} + </span> +</li> +{{#if system.reve.reve.thanatosused}} +<li class="item flexrow" > + <span class="competence-label">La prochaine queue est une Ombre</span> + <span> + <img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/> + </span> +</li> +{{/if}} +<hr> +{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}} +{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}} +{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}} diff --git a/templates/actor/non-haut-revant.html b/templates/actor/non-haut-revant.html deleted file mode 100644 index 333cf48a..00000000 --- a/templates/actor/non-haut-revant.html +++ /dev/null @@ -1,34 +0,0 @@ -<ul class="item-list"> - <li class="item flexrow"> - <span class="competence-label">Seuil de Rêve :</span> - <span> - {{#if options.isGM}} - <input class="competence-value seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/> - {{else}} - {{system.reve.seuil.value}} - {{/if}} - </span> - </li> - <li class="item flexrow" > - <span class="competence-label">Refoulement : </span> - <span> - {{#if options.isGM}} - <input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/> - {{else}} - {{system.reve.refoulement.value}} - {{/if}} - </span> - </li> - {{#if system.reve.reve.thanatosused}} - <li class="item flexrow" > - <span class="competence-label">La prochaine queue est une Ombre</span> - <span> - <img class="sheet-competence-img" src="systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp"/> - </span> - </li> - {{/if}} -</ul> -<hr> -{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html"}} -{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html"}} -{{> "systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html"}}